actionsbuilder.utils.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. var ActionsBuilder;
  2. (function (ActionsBuilder) {
  3. var Utils = (function () {
  4. /*
  5. * Constructor
  6. * @param viewer: the viewer instance
  7. */
  8. function Utils(viewer) {
  9. // Members
  10. this.copiedStructure = null;
  11. // Configure this
  12. this._viewer = viewer;
  13. }
  14. /*
  15. * Tests the graph and reports errors
  16. */
  17. Utils.prototype.onTestGraph = function () {
  18. var _this = this;
  19. if (this._viewer.root.children.length === 0) {
  20. alert("Please add at least a Trigger and an Action to test the graph");
  21. }
  22. var onTestTarget = function (targetType, target) {
  23. var targetExists = false;
  24. var array = _this._viewer.parameters._getTargetFromType(targetType);
  25. if (array === null) {
  26. return targetExists;
  27. }
  28. for (var i = 0; i < array.length; i++) {
  29. if (array[i] === target) {
  30. targetExists = true;
  31. break;
  32. }
  33. }
  34. return targetExists;
  35. };
  36. var onNodeError = function (action) {
  37. var node = action.node;
  38. node.rect.attr("fill", Raphael.rgb(255, 0, 0));
  39. return false;
  40. };
  41. var onTestAction = function (action) {
  42. console.log("Testing " + action.name);
  43. if (action.combineArray !== null) {
  44. var foundError = false;
  45. for (var i = 0; i < action.combineArray.length; i++) {
  46. if (!onTestAction(action.combineArray[i])) {
  47. foundError = true;
  48. }
  49. }
  50. if (foundError) {
  51. return false;
  52. }
  53. }
  54. else {
  55. // Test properties
  56. var properties = action.properties;
  57. var propertiesResults = action.propertiesResults;
  58. if (properties !== null) {
  59. var object = null;
  60. var propertyPath = null;
  61. for (var i = 0; i < properties.length; i++) {
  62. // Target
  63. if (properties[i].text === "target" || properties[i].text === "parent") {
  64. object = _this._viewer.parameters._getObjectFromType(properties[i].targetType);
  65. var targetExists = onTestTarget(propertiesResults[i].targetType, propertiesResults[i].value);
  66. if (!targetExists) {
  67. return onNodeError(action);
  68. }
  69. }
  70. else if (properties[i].text === "propertyPath") {
  71. var property = propertiesResults[i].value;
  72. var effectiveProperty = object;
  73. var p = property.split(".");
  74. for (var j = 0; j < p.length && effectiveProperty !== undefined; j++) {
  75. effectiveProperty = effectiveProperty[p[j]];
  76. }
  77. if (effectiveProperty === undefined) {
  78. return onNodeError(action);
  79. }
  80. else {
  81. propertyPath = effectiveProperty;
  82. }
  83. }
  84. else if (properties[i].text == "value" && propertyPath != null) {
  85. var value = propertiesResults[i].value;
  86. if (!isNaN(propertyPath)) {
  87. var num = parseFloat(value);
  88. if (isNaN(num) || value === "") {
  89. return onNodeError(action);
  90. }
  91. }
  92. }
  93. }
  94. }
  95. var foundError = false;
  96. for (var i = 0; i < action.children.length; i++) {
  97. if (!onTestAction(action.children[i])) {
  98. foundError = true;
  99. }
  100. }
  101. return !foundError;
  102. }
  103. };
  104. var root = this._viewer.root;
  105. var foundError = false;
  106. for (var i = 0; i < root.children.length; i++) {
  107. var trigger = root.children[i];
  108. var properties = trigger.properties;
  109. // Test properties of trigger (parameter)
  110. if (properties !== null && properties.length > 0) {
  111. // Only one property
  112. var parameter = trigger.propertiesResults[0].value;
  113. if (properties[0].targetType !== null) {
  114. // Intersection trigger
  115. if (!onTestTarget("MeshProperties", parameter)) {
  116. foundError = onNodeError(trigger);
  117. }
  118. }
  119. else {
  120. // Key trigger
  121. if (!parameter.match(/[a-z]/)) {
  122. foundError = onNodeError(trigger);
  123. }
  124. }
  125. }
  126. for (var j = 0; j < trigger.children.length; j++) {
  127. var child = trigger.children[j];
  128. var result = onTestAction(child);
  129. if (!result) {
  130. foundError = true;
  131. }
  132. }
  133. }
  134. if (foundError) {
  135. alert("Found error(s). the red nodes contain the error.");
  136. }
  137. else {
  138. alert("No error found.");
  139. }
  140. };
  141. /*
  142. * Recursively reduce/expand nodes
  143. */
  144. Utils.prototype.onReduceAll = function (forceExpand) {
  145. if (forceExpand === void 0) { forceExpand = false; }
  146. if (this._viewer.selectedNode === null) {
  147. return;
  148. }
  149. var action = this._viewer.selectedNode;
  150. if (action.combineArray !== null) {
  151. for (var i = 0; i < action.combineArray.length; i++) {
  152. this._viewer.selectedNode = action.combineArray[i];
  153. this.onReduce(forceExpand, !forceExpand);
  154. }
  155. }
  156. else {
  157. this.onReduce(forceExpand, !forceExpand);
  158. }
  159. for (var i = 0; i < action.children.length; i++) {
  160. this._viewer.selectedNode = action.children[i];
  161. this.onReduceAll(forceExpand);
  162. }
  163. };
  164. /*
  165. * Reduces the selected node
  166. */
  167. Utils.prototype.onReduce = function (forceExpand, forceReduce) {
  168. if (forceExpand === void 0) { forceExpand = false; }
  169. if (forceReduce === void 0) { forceReduce = false; }
  170. if (this._viewer.selectedNode === null) {
  171. return;
  172. }
  173. var node = this._viewer.selectedNode.node;
  174. node.rect.stop(node.rect.animation);
  175. // Set minimized
  176. if (forceExpand === true) {
  177. node.minimized = false;
  178. }
  179. else if (forceReduce === true) {
  180. node.minimized = true;
  181. }
  182. else {
  183. node.minimized = !node.minimized;
  184. }
  185. // Set size
  186. if (node.minimized) {
  187. node.text.hide();
  188. node.rect.attr("width", ActionsBuilder.Viewer.NODE_MINIMIZED_WIDTH * this._viewer.zoom);
  189. }
  190. else {
  191. node.text.show();
  192. node.rect.attr("width", ActionsBuilder.Viewer.NODE_WIDTH * this._viewer.zoom);
  193. }
  194. };
  195. /*
  196. * Detaches the selected action
  197. */
  198. Utils.prototype.onDetachAction = function (forceDetach, forceAttach) {
  199. var _this = this;
  200. if (forceDetach === void 0) { forceDetach = false; }
  201. if (forceAttach === void 0) { forceAttach = false; }
  202. if (this._viewer.selectedNode === null) {
  203. return;
  204. }
  205. var action = this._viewer.selectedNode;
  206. if (forceDetach === true) {
  207. action.node.detached = true;
  208. }
  209. else if (forceAttach === true) {
  210. action.node.detached = false;
  211. }
  212. else {
  213. action.node.detached = !action.node.detached;
  214. }
  215. var onSetColor = function (root, detached) {
  216. var rootNode = root.node;
  217. rootNode.rect.attr("fill", _this._viewer.getNodeColor(root.type, detached));
  218. if (root.combineArray !== null) {
  219. for (var i = 0; i < root.combineArray.length; i++) {
  220. var combineNode = root.combineArray[i].node;
  221. combineNode.rect.attr("fill", _this._viewer.getNodeColor(root.combineArray[i].type, detached));
  222. }
  223. }
  224. for (var i = 0; i < root.children.length; i++) {
  225. onSetColor(root.children[i], detached);
  226. }
  227. };
  228. onSetColor(action, action.node.detached);
  229. };
  230. /*
  231. * Removes the selected node
  232. */
  233. Utils.prototype.onRemoveNode = function () {
  234. if (this._viewer.selectedNode === null) {
  235. return;
  236. }
  237. var action = this._viewer.selectedNode;
  238. var parent = action.parent;
  239. // If trigger, remove branch
  240. if (action.type === ActionsBuilder.Type.TRIGGER) {
  241. this.onRemoveBranch();
  242. return;
  243. }
  244. // If it is a combine hub
  245. if (action.type === ActionsBuilder.Type.FLOW_CONTROL && parent !== null && parent.combineArray !== null) {
  246. action = parent;
  247. parent = action.parent;
  248. }
  249. // Remove
  250. if (parent !== null && parent.combineArray !== null) {
  251. parent.removeCombinedAction(action);
  252. if (parent.combineArray.length === 0) {
  253. parent.node.text.attr("text", "combine");
  254. }
  255. }
  256. else {
  257. if (action.combineArray !== null) {
  258. action.removeChild(action.hub);
  259. }
  260. action.parent.removeChild(action);
  261. }
  262. if (action.combineArray !== null) {
  263. this._viewer.removeAction(action.hub, false);
  264. }
  265. this._viewer.removeAction(action, false);
  266. // Finish
  267. this._viewer.update();
  268. this._viewer.parameters.clearParameters();
  269. this._viewer.selectedNode = null;
  270. };
  271. /*
  272. * Removes a branch starting from the selected node
  273. */
  274. Utils.prototype.onRemoveBranch = function () {
  275. if (this._viewer.selectedNode === null) {
  276. return;
  277. }
  278. if (this._viewer.selectedNode === this._viewer.root) {
  279. alert("Cannot remove the root node");
  280. return;
  281. }
  282. var action = this._viewer.selectedNode;
  283. var parent = action.parent;
  284. // If combine
  285. if (action.parent !== null && action.parent.combineArray !== null) {
  286. action = parent;
  287. parent = action.parent;
  288. }
  289. // Remove
  290. if (action.combineArray !== null) {
  291. action.removeChild(action.hub);
  292. }
  293. action.parent.removeChild(action);
  294. this._viewer.removeAction(action, true);
  295. // Finish
  296. this._viewer.update();
  297. this._viewer.parameters.clearParameters();
  298. this._viewer.selectedNode = null;
  299. };
  300. /*
  301. * Copies the selected structure
  302. */
  303. Utils.prototype.onCopyStructure = function () {
  304. if (this._viewer.selectedNode === null) {
  305. return;
  306. }
  307. var structure = this.createJSON(this._viewer.selectedNode);
  308. var asText = JSON.stringify(structure);
  309. if (window.clipboardData !== undefined) {
  310. window.clipboardData.setData("text", asText);
  311. }
  312. else {
  313. this.copiedStructure = asText;
  314. }
  315. };
  316. /*
  317. * Pastes the graph structure previously copied
  318. */
  319. Utils.prototype.onPasteStructure = function () {
  320. if (this._viewer.selectedNode === null) {
  321. return;
  322. }
  323. var asText = (window.clipboardData !== undefined) ? window.clipboardData.getData("text") : this.copiedStructure;
  324. var isJson = asText.length > 0 && asText[0] == "{" && asText[asText.length - 1] == "}";
  325. var structure = JSON.parse(asText);
  326. var action = this._viewer.selectedNode;
  327. if (structure.type === ActionsBuilder.Type.TRIGGER && action !== this._viewer.root) {
  328. alert("You can't paste a trigger if the selected node isn't the root object");
  329. return;
  330. }
  331. if (structure.type !== ActionsBuilder.Type.TRIGGER && action === this._viewer.root) {
  332. alert("You can't paste an action or condition if the selected node is the root object");
  333. return;
  334. }
  335. this.loadFromJSON(structure, action);
  336. this._viewer.update();
  337. };
  338. /*
  339. * Loads a graph from JSON
  340. * @pram graph: the graph structure
  341. * @param startAction: the action to start load
  342. */
  343. Utils.prototype.loadFromJSON = function (graph, startAction) {
  344. var _this = this;
  345. // If startNode is null, means it replaces all the graph
  346. // If not, it comes from a copy/paste
  347. if (startAction === null) {
  348. for (var i = 0; i < this._viewer.root.children.length; i++) {
  349. this._viewer.removeAction(this._viewer.root.children[i], true);
  350. }
  351. this._viewer.root.clearChildren();
  352. }
  353. var load = function (root, parent, detached, combine) {
  354. if (parent === null) {
  355. parent = _this._viewer.root;
  356. }
  357. var newAction = null;
  358. if (root.type !== ActionsBuilder.Type.OBJECT && root.type !== ActionsBuilder.Type.SCENE) {
  359. var action = _this._viewer.addAction(parent, root.type, ActionsBuilder.Elements.GetElementFromName(root.name));
  360. for (var i = 0; i < root.properties.length; i++) {
  361. var targetType = root.properties[i].targetType;
  362. if (targetType === undefined) {
  363. targetType = "MeshProperties"; // Default is mesh properties
  364. }
  365. action.propertiesResults[i] = { value: root.properties[i].value, targetType: targetType };
  366. }
  367. var node = action.node;
  368. node.detached = root.detached;
  369. if (detached) {
  370. node.rect.attr("fill", _this._viewer.getNodeColor(action.type, detached));
  371. }
  372. // If combine array
  373. if (root.combine !== undefined) {
  374. for (var i = 0; i < root.combine.length; i++) {
  375. load(root.combine[i], action, detached, true);
  376. }
  377. }
  378. if (!combine) {
  379. parent = parent.children[parent.children.length - 1];
  380. }
  381. }
  382. for (var i = 0; i < root.children.length; i++) {
  383. load(root.children[i], newAction !== null && newAction.combineArray !== null ? newAction.hub : parent, root.detached, false);
  384. }
  385. };
  386. // Finish
  387. load(graph, startAction, false, false);
  388. this._viewer.update();
  389. };
  390. /*
  391. * Creates a JSON object starting from a root action
  392. * @param root: the root action
  393. */
  394. Utils.prototype.createJSON = function (root) {
  395. var action = {
  396. type: root.type,
  397. name: root.name,
  398. detached: root.node.detached,
  399. children: new Array(),
  400. combine: new Array(),
  401. properties: new Array()
  402. };
  403. // Set properties
  404. for (var i = 0; i < root.properties.length; i++) {
  405. action.properties.push({
  406. name: root.properties[i].text,
  407. value: root.propertiesResults[i].value,
  408. targetType: root.propertiesResults[i].targetType
  409. });
  410. }
  411. // If combine
  412. if (root.combineArray !== null) {
  413. for (var i = 0; i < root.combineArray.length; i++) {
  414. var combinedAction = root.combineArray[i];
  415. action.combine.push(this.createJSON(combinedAction));
  416. }
  417. root = root.children[0]; // Hub
  418. }
  419. for (var i = 0; i < root.children.length; i++) {
  420. action.children.push(this.createJSON(root.children[i]));
  421. }
  422. return action;
  423. };
  424. /*
  425. *
  426. */
  427. Utils.prototype.setElementVisible = function (element, visible) {
  428. element.style.display = visible ? "block" : "none";
  429. };
  430. return Utils;
  431. })();
  432. ActionsBuilder.Utils = Utils;
  433. })(ActionsBuilder || (ActionsBuilder = {}));
  434. //# sourceMappingURL=actionsbuilder.utils.js.map