actionsbuilder.list.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. module ActionsBuilder {
  2. export class ListElement {
  3. public rect: Rect = null;
  4. public text: Text = null;
  5. public name: string = "";
  6. public type: number = Type.TRIGGER;
  7. public element: Element = null;
  8. }
  9. export class List {
  10. public listElement: HTMLElement;
  11. public triggersElement: HTMLElement;
  12. public actionsElement: HTMLElement;
  13. public flowControlsElement: HTMLElement;
  14. public triggersList: Paper;
  15. public actionsList: Paper;
  16. public flowControlsList: Paper;
  17. private _parentContainer: HTMLElement;
  18. private _listElements: Array<ListElement> = new Array<ListElement>();
  19. private _viewer: Viewer;
  20. public static get ELEMENT_HEIGHT(): number {
  21. return 25;
  22. }
  23. /**
  24. * Constructor
  25. */
  26. constructor(viewer: Viewer) {
  27. // Get HTML elements
  28. this.listElement = document.getElementById("ListsElementID");
  29. this.triggersElement = document.getElementById("TriggersListID");
  30. this.actionsElement = document.getElementById("ActionsListID");
  31. this.flowControlsElement = document.getElementById("FlowActionsListID");
  32. this._parentContainer = document.getElementById("ParentContainerID");
  33. // Configure this
  34. this._viewer = viewer;
  35. // Create elements (lists)
  36. this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
  37. this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
  38. this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
  39. // Manage events
  40. window.addEventListener("resize", (event: Event) => {
  41. this.onResize(event);
  42. });
  43. }
  44. /**
  45. * Resize event that resizes the list element dynamically
  46. * @param event: the resize event
  47. */
  48. public onResize(event?: Event): void {
  49. var tools = document.getElementById("ToolsButtonsID");
  50. this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
  51. var listElementWidth = this.listElement.getBoundingClientRect().width;
  52. for (var i = 0; i < this._listElements.length; i++) {
  53. var rect = this._listElements[i].rect;
  54. rect.attr("width", listElementWidth - 40);
  55. }
  56. this.triggersList.setSize(listElementWidth, this.triggersList.height);
  57. this.actionsList.setSize(listElementWidth, this.triggersList.height);
  58. this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
  59. }
  60. public createListsElements(): void {
  61. var excludedTriggers = [6, 9, 10];
  62. var yPosition = 10;
  63. var textColor = Raphael.rgb(61, 72, 76);
  64. var whiteColor = Raphael.rgb(255, 255, 255);
  65. var configureTitle = (listElement: ListElement, rectColor: RaphaelColor) => {
  66. listElement.text.attr("x", 15);
  67. listElement.rect.attr("fill", rectColor);
  68. listElement.text.attr("font-family", "Sinkin Sans Medium");
  69. listElement.text.attr("font-size", "11");
  70. };
  71. // Create triggers
  72. var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", Type.TRIGGER, whiteColor, false);
  73. yPosition += List.ELEMENT_HEIGHT;
  74. configureTitle(triggers, Raphael.rgb(41, 129, 255));
  75. for (var i = 0; i < Elements.TRIGGERS.length; i++) {
  76. var element: any = Elements.TRIGGERS[i];
  77. if (this._viewer.root.type === Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
  78. continue;
  79. }
  80. else if (this._viewer.root.type === Type.SCENE && excludedTriggers.indexOf(i) === -1) {
  81. continue;
  82. }
  83. var trigger = this._createListElement(this.triggersList, yPosition, element.text, Type.TRIGGER, textColor, true, element);
  84. trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
  85. yPosition += List.ELEMENT_HEIGHT;
  86. }
  87. yPosition += List.ELEMENT_HEIGHT;
  88. this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
  89. this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
  90. // Create actions
  91. yPosition = 10;
  92. var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", Type.ACTION, textColor, false);
  93. yPosition += List.ELEMENT_HEIGHT;
  94. configureTitle(actions, Raphael.rgb(255, 220, 42));
  95. for (var i = 0; i < Elements.ACTIONS.length; i++) {
  96. var element: any = Elements.ACTIONS[i];
  97. var action = this._createListElement(this.actionsList, yPosition, element.text, Type.ACTION, textColor, true, element);
  98. action.rect.attr("fill", Raphael.rgb(182, 185, 132));
  99. yPosition += List.ELEMENT_HEIGHT;
  100. }
  101. yPosition += List.ELEMENT_HEIGHT;
  102. this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
  103. this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
  104. // Create flow controls
  105. yPosition = 10;
  106. var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", Type.FLOW_CONTROL, whiteColor, false);
  107. yPosition += List.ELEMENT_HEIGHT;
  108. configureTitle(flowControls, Raphael.rgb(255, 41, 53));
  109. for (var i = 0; i < Elements.FLOW_CONTROLS.length - 1; i++) {
  110. var element: any = Elements.FLOW_CONTROLS[i];
  111. var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, Type.FLOW_CONTROL, textColor, true, element);
  112. flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
  113. yPosition += List.ELEMENT_HEIGHT;
  114. }
  115. yPosition += List.ELEMENT_HEIGHT;
  116. this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
  117. this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
  118. }
  119. /**
  120. * Clears the list of elements and removes the elements
  121. */
  122. public clearLists(): void {
  123. for (var i = 0; i < this._listElements.length; i++) {
  124. this._removeListElement(this._listElements[i]);
  125. }
  126. this._listElements.splice(0, this._listElements.length - 1);
  127. }
  128. /**
  129. * Sets the color theme of the lists
  130. * @param color: the theme color
  131. */
  132. public setColorTheme(color: string): void {
  133. this.triggersList.canvas.style.backgroundColor = color;
  134. this.actionsList.canvas.style.backgroundColor = color;
  135. this.flowControlsList.canvas.style.backgroundColor = color;
  136. }
  137. /**
  138. * Creates a list element
  139. * @param paper: the Raphael.js paper
  140. * @param yPosition: the y position of the element
  141. * @param text: the element text
  142. * @param type: the element type (trigger, action, flow control)
  143. * @param textColor: the text color
  144. * @param drag: if the element should be drag'n'dropped
  145. */
  146. private _createListElement(paper: Paper, yPosition: number, text: string, type: number,
  147. textColor: RaphaelColor, drag: boolean, element?: Element): ListElement
  148. {
  149. var object = new ListElement();
  150. object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
  151. object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
  152. object.text.attr("fill", textColor);
  153. object.text.attr("text-anchor", "start");
  154. object.text.attr("font-size", "12");
  155. object.text.attr("text-anchor", "start");
  156. object.text.attr("font-family", "Sinkin Sans Light");
  157. if (drag) {
  158. this._createListElementAnimation(object);
  159. }
  160. object.type = type;
  161. object.element = element;
  162. this._listElements.push(object);
  163. return object;
  164. }
  165. /**
  166. * Removes a list element
  167. * @param element: the element to remove
  168. */
  169. private _removeListElement(element: ListElement): void {
  170. element.rect.remove();
  171. element.text.remove();
  172. }
  173. /*
  174. * Creates the collapse animation of a list
  175. * @param paper: the list paper
  176. * @param htmlElement: the list div container
  177. * @param element: the list element to click on
  178. * @param expandedHeight: the height when the list is expanded
  179. */
  180. private _createCollapseAnimation(paper: Paper, htmlElement: HTMLElement, element: ListElement, expandedHeight: number): void {
  181. var onClick = (event: MouseEvent) => {
  182. var height = htmlElement.style.height;
  183. if (height === expandedHeight + "px") {
  184. htmlElement.style.height = paper.canvas.style.height = 35 + "px";
  185. }
  186. else {
  187. htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
  188. }
  189. };
  190. element.rect.click(onClick);
  191. }
  192. /*
  193. * Creates the animation of a list element
  194. * @param element: the list element to animate
  195. */
  196. private _createListElementAnimation(element: ListElement): void {
  197. var onMove = (dx: number, dy: number, x: number, y: number) =>
  198. { };
  199. var onStart = (x: number, y: number, event: MouseEvent) => {
  200. this._parentContainer.style.cursor = "copy";
  201. element.rect.animate({
  202. x: -10,
  203. opacity: 0.25
  204. }, 500, ">");
  205. element.text.animate({
  206. x: 10,
  207. opacity: 0.25
  208. }, 500, ">");
  209. };
  210. var onEnd = (event: MouseEvent) => {
  211. this._parentContainer.style.cursor = "default";
  212. element.rect.animate({
  213. x: 10,
  214. opacity: 1.0
  215. }, 500, "<");
  216. element.text.animate({
  217. x: 30,
  218. opacity: 1.0
  219. }, 500, "<");
  220. var dragResult = this._viewer.traverseGraph(null, this._viewer.mousex, this._viewer.mousey, false);
  221. if (dragResult.hit) {
  222. if (element.type === Type.TRIGGER && dragResult.action !== this._viewer.root) {
  223. alert("Triggers can be dragged only on the root node (the mesh)");
  224. return;
  225. }
  226. if (element.type === Type.ACTION && dragResult.action === this._viewer.root) {
  227. alert("Please add a trigger before.");
  228. return;
  229. }
  230. //if (element.type === Type.FLOW_CONTROL && (dragResult.action === this._viewer.root || (dragResult.action.type === Type.FLOW_CONTROL && dragResult.action.parent.hub === null))) {
  231. if (element.type === Type.FLOW_CONTROL && dragResult.action === this._viewer.root) {
  232. return;
  233. }
  234. if (element.type === Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
  235. alert("A condition cannot be handled by a Combine Action.");
  236. return;
  237. }
  238. if ((element.type === Type.FLOW_CONTROL || element.type === Type.ACTION) && dragResult.action.type === Type.TRIGGER && dragResult.action.children.length > 0) {
  239. alert("Triggers can have only one child. Please add another trigger of same type.");
  240. return;
  241. }
  242. if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== Type.TRIGGER && dragResult.action !== this._viewer.root) {
  243. alert("An action can have only one child.");
  244. return;
  245. }
  246. this._viewer.addAction(dragResult.action, element.type, element.element);
  247. this._viewer.update();
  248. }
  249. };
  250. element.rect.drag(onMove, onStart, onEnd);
  251. element.text.drag(onMove, onStart, onEnd);
  252. }
  253. }
  254. }