APIs

Show:
  1. /**
  2. Scene Editor Backbone view
  3. @class SceneEditorView
  4. @constructor
  5. @return {object} instantiated the SceneEditorView
  6. **/
  7. define(['jquery', 'backbone', 'fabric', 'BlockScene', 'BlockRSS', 'ScenesToolbarView', 'BlockFactory', 'contextmenu'], function ($, Backbone, fabric, BlockScene, BlockRSS, ScenesToolbarView, BlockFactory, contextmenu) {
  8.  
  9. BB.SERVICES.SCENE_EDIT_VIEW = 'SceneEditorView';
  10.  
  11. var SceneEditorView = BB.View.extend({
  12.  
  13. /**
  14. Constructor
  15. @method initialize
  16. **/
  17. initialize: function () {
  18. var self = this;
  19. BB.comBroker.setService(BB.SERVICES['SCENE_EDIT_VIEW'], self);
  20. self.m_selectedSceneID = undefined;
  21. self.m_sceneScrollTop = 0;
  22. self.m_sceneScrollLeft = 0;
  23. self.m_objectScaling = 0;
  24. self.m_mouseX = 0;
  25. self.m_mouseY = 0;
  26. self.m_gridMagneticMode = 0;
  27. self.m_rendering = false;
  28. self.m_memento = {};
  29. self.m_canvasMouseState = 0;
  30. self.m_copiesObjects = [];
  31. self.PUSH_TOP = 1;
  32. self.PUSH_BOTTOM = 0;
  33. self.m_blocks = {
  34. blocksPre: [],
  35. blocksPost: {},
  36. blockSelected: undefined
  37. };
  38. self.m_dimensionProps = undefined;
  39. self.m_canvas = undefined;
  40. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  41.  
  42. new ScenesToolbarView({
  43. stackView: self.options.stackView,
  44. el: Elements.SCENE_TOOLBAR
  45. });
  46.  
  47. self.m_canvasScale = 1;
  48. self.SCALE_FACTOR = 1.2;
  49.  
  50. self._listenSceneViewStackSelected();
  51. self._listenSceneSelection();
  52. self._initializeBlockFactory();
  53. self._listenAddBlockWizard();
  54. self._listenZoom();
  55. self._listenToCanvasScroll();
  56. self._listenPushToTop();
  57. self._listenPushToBottom();
  58. self._listenSceneChanged();
  59. self._listenContextMenu();
  60. self._listenSelectNextBlock();
  61. self._listenSceneRemove();
  62. self._listenSceneBlockRemove();
  63. self._listenSceneNew();
  64. self._listenMemento();
  65. self._listenGridMagnet();
  66. self._listenCanvasSelectionsFromToolbar();
  67. self._listenAppResized();
  68. self._listenStackViewSelected();
  69. self._delegateSceneBlockModified();
  70. },
  71.  
  72. /**
  73. Listen to when a new scene is selected via Slider View
  74. @method _listenSceneViewStackSelected
  75. **/
  76. _listenSceneViewStackSelected: function () {
  77. var self = this;
  78. self.listenTo(self.options.stackView, BB.EVENTS.SELECTED_STACK_VIEW, function (e) {
  79. if (e == self) {
  80. log('load new scene');
  81. }
  82. });
  83. },
  84.  
  85. /**
  86. Listen to changes in a new scene selection
  87. @method _listenSceneSelection
  88. **/
  89. _listenSceneSelection: function () {
  90. var self = this;
  91. BB.comBroker.listen(BB.EVENTS.LOAD_SCENE, function (e) {
  92. self.m_selectedSceneID = e.edata;
  93. self._loadScene();
  94. self._sceneCanvasSelected();
  95. BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  96. if (self._mementoInit())
  97. self._mementoAddState();
  98. });
  99. },
  100.  
  101. /**
  102. Init block factory if it hasn't already been loaded
  103. @method _initializeBlockFactory
  104. **/
  105. _initializeBlockFactory: function () {
  106. var self = this;
  107. self.m_blockFactory = BB.comBroker.getService(BB.SERVICES['BLOCK_FACTORY']);
  108. if (self.m_blockFactory && self.m_blockFactory.blocksLoaded()) {
  109. self._initDimensionProps();
  110. return
  111. }
  112.  
  113. BB.comBroker.listenOnce(BB.EVENTS['BLOCKS_LOADED'], function () {
  114. self._initDimensionProps();
  115. });
  116. require(['BlockFactory'], function (BlockFactory) {
  117. self.m_blockFactory = new BlockFactory();
  118. self.m_blockFactory.loadBlockModules();
  119. });
  120. },
  121.  
  122. /**
  123. Init block factory if it hasn't already been loaded
  124. @method _initializeBlockFactory
  125. **/
  126. _initializeBlockFactory: function () {
  127. var self = this;
  128. self.m_blockFactory = BB.comBroker.getService(BB.SERVICES['BLOCK_FACTORY']);
  129.  
  130. if (self.m_blockFactory && self.m_blockFactory.blocksLoaded()) {
  131. self._initDimensionProps();
  132.  
  133. } else {
  134.  
  135. BB.comBroker.listenOnce(BB.EVENTS['BLOCKS_LOADED'], function () {
  136. self._initDimensionProps();
  137. });
  138.  
  139. require(['BlockFactory'], function (BlockFactory) {
  140. self.m_blockFactory = new BlockFactory();
  141. self.m_blockFactory.loadBlockModules();
  142. });
  143. }
  144. },
  145.  
  146. /**
  147. Init the dimension props class
  148. @method _initDimensionProps
  149. **/
  150. _initDimensionProps: function () {
  151. var self = this;
  152. require(['DimensionProps'], function (DimensionProps) {
  153. self.m_dimensionProps = new DimensionProps({
  154. appendTo: Elements.SCENE_BLOCK_PROPS,
  155. showAngle: true,
  156. showLock: true,
  157. hideSpinners: true
  158. });
  159. // self.m_dimensionProps.hideSpinners();
  160. BB.comBroker.setService(BB.SERVICES['DIMENSION_PROPS_LAYOUT'], self.m_dimensionProps);
  161. $(self.m_dimensionProps).on('changed', function (e) {
  162. var block = self.m_canvas.getActiveObject();
  163. if (_.isNull(block))
  164. return;
  165. var props = e.target.getValues();
  166. var block_id = block.getBlockData().blockID;
  167. self._updateBlockCords(block, false, props.x, props.y, props.w, props.h, props.a);
  168. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, [block_id]);
  169. });
  170. self._sceneActive();
  171. })
  172. },
  173.  
  174. /**
  175. Bring the scene into view
  176. @method _sceneActive
  177. **/
  178. _sceneActive: function () {
  179. var self = this;
  180. $('#sceneToolbar').fadeIn();
  181. $(Elements.SCENE_TOOLBAR).fadeTo(500, 1);
  182. },
  183.  
  184. /**
  185. Init a new canvas and listen to even changes on that new canvas
  186. @method _initializeCanvas
  187. @param {Number} w width
  188. @param {Number} h height
  189. **/
  190. _initializeCanvas: function (w, h) {
  191. var self = this;
  192. var canvasID = BB.lib.unhash(Elements.SCENE_CANVAS);
  193. $(Elements.SCENE_CANVAS_CONTAINER).empty();
  194. $(Elements.SCENE_CANVAS_CONTAINER).append('<canvas id="' + canvasID + '" width="' + w + 'px" height="' + h + 'px" />');
  195. self.m_canvas = new fabric.Canvas(canvasID);
  196. self.m_canvas.renderOnAddRemove = false;
  197. $(Elements.SCENE_CANVAS).addClass('basicBorder');
  198.  
  199. self._listenBlockModified();
  200. self._listenCanvasSelections();
  201. self._listenKeyboard();
  202. },
  203.  
  204. /**
  205. Init a new scene and subclass off a standard Block
  206. @method _initializeScene
  207. **/
  208. _initializeScene: function () {
  209. var self = this;
  210. var scene_player_data = pepper.getScenePlayerdata(self.m_selectedSceneID);
  211. self.m_sceneBlock = self.m_blockFactory.createBlock(self.m_selectedSceneID, scene_player_data, BB.CONSTS.PLACEMENT_IS_SCENE);
  212. self.m_sceneBlock.setCanvas(self.m_canvas, self.m_gridMagneticMode);
  213. //_.extend(self.m_canvas, self.m_sceneBlock);
  214. },
  215.  
  216. /**
  217. Announce that block count changed with block array of ids
  218. @method self._updateBlockCount();
  219. **/
  220. _updateBlockCount: function () {
  221. var self = this;
  222. var blocks = [];
  223. if (_.isUndefined(self.m_selectedSceneID)) {
  224. BB.comBroker.fire(BB.EVENTS.SCENE_BLOCK_LIST_UPDATED, this, null, null);
  225. return;
  226. }
  227. // cpu breather
  228. setTimeout(function () {
  229. if (_.isUndefined(self.m_canvas))
  230. return;
  231. var objects = self.m_canvas.getObjects().length;
  232. for (var i = 0; i < objects; i++) {
  233. blocks.push({
  234. id: self.m_canvas.item(i).m_block_id,
  235. name: self.m_canvas.item(i).m_blockName
  236. });
  237. }
  238. BB.comBroker.fire(BB.EVENTS.SCENE_BLOCK_LIST_UPDATED, this, null, blocks);
  239. }, 500);
  240.  
  241. },
  242.  
  243. /**
  244. Load a new scene and dispose of any previous ones
  245. @return {Number} Unique clientId.
  246. **/
  247. _loadScene: function () {
  248. var self = this;
  249. if (_.isUndefined(self.m_selectedSceneID))
  250. return -1;
  251. self._sceneProcessing(true, $.proxy(function () {
  252. self._disposeBlocks();
  253. self.disposeScene();
  254. self._zoomReset();
  255. self.m_property.resetPropertiesView();
  256. var domPlayerData = pepper.getScenePlayerdataDom(self.m_selectedSceneID);
  257. var l = $(domPlayerData).find('Layout').eq(0);
  258. var w = $(l).attr('width');
  259. var h = $(l).attr('height');
  260. self._initializeCanvas(w, h);
  261. self._initializeScene(self.m_selectedSceneID);
  262. self._preRender(domPlayerData);
  263. }), self);
  264.  
  265. },
  266.  
  267. /**
  268. Listen to selection of next block
  269. @method _listenSelectNextDivision
  270. **/
  271. _listenSelectNextBlock: function () {
  272. var self = this;
  273. BB.comBroker.listen(BB.EVENTS['SCENE_SELECT_NEXT'], function () {
  274. if (_.isUndefined(self.m_selectedSceneID))
  275. return;
  276. var viewer = self.m_canvas.getActiveObject();
  277. var viewIndex = self.m_canvas.getObjects().indexOf(viewer);
  278. var totalViews = self.m_canvas.getObjects().length;
  279. var blockID = undefined;
  280. if (viewIndex == totalViews - 1) {
  281. self.m_canvas.setActiveObject(self.m_canvas.item(0));
  282. blockID = self.m_canvas.getActiveObject().getBlockData().blockID;
  283. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, blockID);
  284. } else {
  285. self.m_canvas.setActiveObject(self.m_canvas.item(viewIndex + 1));
  286. blockID = self.m_canvas.getActiveObject().getBlockData().blockID;
  287. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, blockID);
  288. }
  289. });
  290. },
  291.  
  292. /**
  293. Listen to when a user selects to delete a block
  294. @method _listenSceneBlockRemove
  295. **/
  296. _listenSceneBlockRemove: function () {
  297. var self = this;
  298. BB.comBroker.listen(BB.EVENTS.SCENE_ITEM_REMOVE, function () {
  299. self._onContentMenuSelection('remove');
  300. });
  301. },
  302.  
  303. /**
  304. Listen to when a user selects to delete a scene
  305. @method _listenSceneRemove
  306. **/
  307. _listenSceneRemove: function () {
  308. var self = this;
  309. BB.comBroker.listen(BB.EVENTS.SCENE_EDITOR_REMOVE, function (e) {
  310. if (self.m_canvas)
  311. self.m_canvas.setBackgroundColor('#ffffff', function () {
  312. }).renderAll();
  313.  
  314. // remove a scene and notify before so channel instances
  315. // can remove corresponding blocks and after so channelList can refresh UI
  316. var sceneID = pepper.getSceneIdFromPseudoId(e.edata);
  317. BB.comBroker.fire(BB.EVENTS.REMOVING_SCENE, this, null, sceneID);
  318. pepper.removeBlocksWithSceneID(sceneID);
  319. pepper.removeSceneFromBlockCollectionInScenes(sceneID);
  320. pepper.removeSceneFromBlockCollectionsInChannels(sceneID);
  321. pepper.removeScene(sceneID);
  322. BB.comBroker.fire(BB.EVENTS.SCENE_LIST_UPDATED, this, null);
  323. self.disposeScene();
  324. self._zoomReset();
  325. self.m_property.resetPropertiesView();
  326. self.m_selectedSceneID = undefined;
  327. $(Elements.SCENE_CANVAS).removeClass('basicBorder');
  328. self._updateBlockCount();
  329. BB.comBroker.fire(BB.EVENTS.REMOVED_SCENE, this, null, self.m_selected_resource_id);
  330. });
  331. },
  332.  
  333. /**
  334. Listen to keyboard events
  335. @method _listenKeyboard
  336. **/
  337. _listenKeyboard: function () {
  338. var self = this;
  339. if (_.isUndefined(self.m_canvas))
  340. return;
  341. $('canvas').attr('tabindex', '1');
  342. var keyDown = _.debounce(function (e) {
  343. if (self.m_objectScaling)
  344. return;
  345. if (self.m_canvasMouseState)
  346. return;
  347. var block = self.m_canvas.getActiveObject();
  348. if (_.isNull(block))
  349. return;
  350. var dimensionProps = BB.comBroker.getService(BB.SERVICES['DIMENSION_PROPS_LAYOUT']);
  351. var values = dimensionProps.getValues();
  352. var val = e.shiftKey ? 25 : 1;
  353. switch (e.keyCode) {
  354. case 38:
  355. {
  356. values.y = values.y - val;
  357. break;
  358. }
  359. case 40:
  360. {
  361. values.y = values.y + val;
  362. break;
  363. }
  364. case 37:
  365. {
  366. values.x = values.x - val;
  367. break;
  368. }
  369. case 39:
  370. {
  371. values.x = values.x + val;
  372. break;
  373. }
  374. }
  375. dimensionProps.setValues(values, true);
  376. return false;
  377. }, 100);
  378. $('.upper-canvas').keydown(keyDown);
  379. },
  380.  
  381. /**
  382. Listen to user selection of new scene
  383. @method _listenSceneNew
  384. **/
  385. _listenSceneNew: function () {
  386. var self = this;
  387. BB.comBroker.listen(BB.EVENTS.NEW_SCENE_ADD, function (e) {
  388. var player_data = BB.PepperHelper.getBlockBoilerplate('3510').getDefaultPlayerData(BB.CONSTS.PLACEMENT_IS_SCENE);
  389. self.createScene(player_data, false, true, e.edata.mimeType, e.edata.name);
  390. });
  391. },
  392.  
  393. /**
  394. Listen when mouse enters canvas wrapper and announce it
  395. @method _listenMouseEnterCanvas
  396. **/
  397. _listenMouseEnterCanvas: function () {
  398. var self = this;
  399. $(Elements.SCENE_CANVAS_CONTAINER).on("mouseover", function (e) {
  400. BB.comBroker.fire(BB.EVENTS.MOUSE_ENTERS_CANVAS, self, self);
  401. });
  402. },
  403.  
  404. /**
  405. Listen to the event of scene changes which normally comes from a block that modified its data
  406. and re-render all scene content
  407. @method _listenSceneChanged
  408. **/
  409. _listenSceneChanged: function (e) {
  410. var self = this;
  411. BB.comBroker.listen(BB.EVENTS['SCENE_BLOCK_CHANGE'], function (e) {
  412. if (self.m_rendering)
  413. return;
  414. var blockIDs = e.edata;
  415. log('block(s) edited ' + blockIDs);
  416. var domPlayerData = pepper.getScenePlayerdataDom(self.m_selectedSceneID);
  417. self.m_blocks.blockSelected = blockIDs[0];
  418. self._preRender(domPlayerData, blockIDs);
  419. self._mementoAddState();
  420. });
  421. },
  422.  
  423. /**
  424. Listen to any canvas right click
  425. @method _listenContextMenu
  426. **/
  427. _listenContextMenu: function () {
  428. var self = this;
  429. $(Elements.SCENE_CANVAS_CONTAINER).contextmenu({
  430. target: Elements.SCENE_CONTEXT_MENU,
  431. before: function (e, element, target) {
  432. e.preventDefault();
  433. // no canvas
  434. if (_.isUndefined(self.m_canvas)) {
  435. this.closemenu();
  436. return false;
  437. }
  438. // remember right click position for pasting
  439. self.m_mouseX = e.offsetX;
  440. self.m_mouseY = e.offsetY;
  441.  
  442. // group selected
  443. var active = self.m_canvas.getActiveGroup();
  444. if (active) {
  445. $('.blocksOnly', Elements.SCENE_CONTEXT_MENU).show();
  446. return true;
  447. }
  448. // scene selected
  449. var block = self.m_canvas.getActiveObject();
  450. if (_.isNull(block)) {
  451. $('.blocksOnly', Elements.SCENE_CONTEXT_MENU).hide();
  452. return true;
  453. }
  454. // object selected
  455. $('.blocksOnly', Elements.SCENE_CONTEXT_MENU).show();
  456. return true;
  457. },
  458. onItem: function (context, e) {
  459. self._onContentMenuSelection($(e.target).attr('name'))
  460. }
  461. });
  462. },
  463.  
  464. /**
  465. On Scene right click context menu selection command
  466. @method _onContentMenuSelection
  467. @param {String} i_command
  468. **/
  469. _onContentMenuSelection: function (i_command) {
  470. var self = this;
  471. var blocks = [];
  472.  
  473. var contextCmd = function (i_blocks) {
  474. switch (i_command) {
  475. case 'copy':
  476. {
  477. self.m_copiesObjects = [];
  478. _.each(i_blocks, function (selectedObject) {
  479. var blockPlayerData = selectedObject.getBlockData().blockData;
  480. blockPlayerData = pepper.stripPlayersID(blockPlayerData);
  481. self.m_copiesObjects.push(blockPlayerData);
  482. });
  483. break;
  484. }
  485.  
  486. case 'cut':
  487. {
  488. self.m_copiesObjects = [];
  489. _.each(i_blocks, function (selectedObject) {
  490. var blockData = selectedObject.getBlockData();
  491. var blockPlayerData = blockData.blockData;
  492. self._discardSelections();
  493. pepper.removeScenePlayer(self.m_selectedSceneID, blockData.blockID);
  494. self._disposeBlocks(blockData.blockID);
  495. blockPlayerData = pepper.stripPlayersID(blockPlayerData);
  496. self.m_copiesObjects.push(blockPlayerData);
  497. });
  498. self.m_canvas.renderAll();
  499. self._updateBlockCount();
  500. break;
  501. }
  502.  
  503. case 'remove':
  504. {
  505. _.each(i_blocks, function (selectedObject) {
  506. var blockData = selectedObject.getBlockData();
  507. self._discardSelections();
  508. pepper.removeScenePlayer(self.m_selectedSceneID, blockData.blockID);
  509. self._disposeBlocks(blockData.blockID);
  510. });
  511. self.m_canvas.renderAll();
  512. self._updateBlockCount();
  513. break;
  514. }
  515.  
  516. case 'paste':
  517. {
  518. var x, y, blockID, origX, origY, blockIDs = [];
  519. _.each(self.m_copiesObjects, function (domPlayerData, i) {
  520. blockID = pepper.generateSceneId();
  521. $(domPlayerData).attr('id', blockID);
  522. blockIDs.push(blockID);
  523. var layout = $(domPlayerData).find('Layout');
  524. if (i == 0) {
  525. origX = parseInt(layout.attr('x'));
  526. origY = parseInt(layout.attr('y'));
  527. x = self.m_mouseX;
  528. y = self.m_mouseY;
  529. } else {
  530. x = self.m_mouseX + (parseInt(layout.attr('x') - origX));
  531. y = self.m_mouseY + (parseInt(layout.attr('y') - origY));
  532. }
  533. layout.attr('x', x);
  534. layout.attr('y', y);
  535. var player_data = (new XMLSerializer()).serializeToString(domPlayerData);
  536. pepper.appendScenePlayerBlock(self.m_selectedSceneID, player_data);
  537. });
  538. self._discardSelections();
  539. if (self.m_copiesObjects.length == 1) {
  540. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, [blockID]);
  541. } else {
  542. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, blockIDs);
  543. }
  544. self._updateBlockCount();
  545. break;
  546. }
  547. }
  548. };
  549.  
  550. // no canvas
  551. if (_.isUndefined(self.m_canvas)) {
  552. return;
  553. }
  554. // group selected
  555. var group = self.m_canvas.getActiveGroup();
  556. if (group) {
  557. log(i_command + ' on group');
  558. blocks = [];
  559. _.each(group.objects, function (selectedObject) {
  560. blocks.push(selectedObject);
  561. });
  562. contextCmd(blocks);
  563. return;
  564. }
  565. // scene selected
  566. var block = self.m_canvas.getActiveObject();
  567. if (_.isNull(block)) {
  568. log(i_command + ' on scene');
  569. contextCmd(null);
  570. return;
  571. }
  572. // object selected
  573. log(i_command + ' on object');
  574. blocks = [];
  575. blocks.push(block);
  576. contextCmd(blocks);
  577. return true;
  578. },
  579.  
  580. /**
  581. Listen to canvas scrolling
  582. @method _listenToCanvasScroll
  583. **/
  584. _listenToCanvasScroll: function () {
  585. var self = this;
  586. var sceneScrolling = _.debounce(function () {
  587. $(Elements.SCENE_CANVAS_CONTAINER).scroll(function (e) {
  588. self.m_sceneScrollTop = $('#scenesPanel').scrollTop();
  589. self.m_sceneScrollLeft = $('#scenesPanel').scrollLeft();
  590. self.m_canvas.calcOffset();
  591. });
  592. }, 500);
  593. $(Elements.SCENE_CANVAS_CONTAINER).scroll(sceneScrolling);
  594. },
  595.  
  596. /**
  597. Listen to and add new component / resources to scene
  598. @method _listenAddBlockWizard
  599. @param {event} e
  600. **/
  601. _listenAddBlockWizard: function () {
  602. var self = this;
  603. BB.comBroker.listen(BB.EVENTS.ADD_NEW_BLOCK_SCENE, function (e) {
  604. var blockID = pepper.generateSceneId();
  605. var player_data = BB.PepperHelper.getBlockBoilerplate(e.edata.blockCode).getDefaultPlayerData(BB.CONSTS.PLACEMENT_SCENE, e.edata.resourceID);
  606. var domPlayerData = $.parseXML(player_data);
  607. $(domPlayerData).find('Player').attr('id', blockID);
  608. player_data = (new XMLSerializer()).serializeToString(domPlayerData);
  609. pepper.appendScenePlayerBlock(self.m_selectedSceneID, player_data);
  610. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, [blockID]);
  611. });
  612. },
  613.  
  614. /**
  615. Listen to re-order of screen division, putting selected on top
  616. @method _listenPushToTop
  617. **/
  618. _listenPushToTop: function () {
  619. var self = this;
  620. BB.comBroker.listen(BB.EVENTS.SCENE_PUSH_TOP, function () {
  621. if (_.isUndefined(self.m_selectedSceneID))
  622. return;
  623. var block = self.m_canvas.getActiveObject();
  624. if (_.isNull(block)) {
  625. self._discardSelections();
  626. return;
  627. }
  628. self.m_canvas.bringToFront(block);
  629. self._updateZorder(self.PUSH_TOP, block);
  630. self._mementoAddState();
  631. });
  632. },
  633.  
  634. /**
  635. Listen to re-order of screen division, putting selected at bottom
  636. @method _listenPushToBottom
  637. **/
  638. _listenPushToBottom: function () {
  639. var self = this;
  640. BB.comBroker.listen(BB.EVENTS.SCENE_PUSH_BOTTOM, function () {
  641. if (_.isUndefined(self.m_selectedSceneID))
  642. return;
  643. var block = self.m_canvas.getActiveObject();
  644. if (_.isNull(block)) {
  645. self._discardSelections();
  646. return;
  647. }
  648. self.m_canvas.sendToBack(block);
  649. self._updateZorder(self.PUSH_BOTTOM, block);
  650. self._mementoAddState();
  651. });
  652. },
  653.  
  654. /**
  655. Listen grid magnet when dragging objects
  656. @method _listenGridMagnet
  657. **/
  658. _listenGridMagnet: function () {
  659. var self = this;
  660. $(Elements.SCENE_GRID_MAGNET).on('click', function () {
  661. if (self.m_rendering || _.isUndefined(self.m_canvas))
  662. return;
  663. switch (self.m_gridMagneticMode) {
  664. case 0:
  665. {
  666. self.m_gridMagneticMode = 1;
  667. break;
  668. }
  669. case 1:
  670. {
  671. self.m_gridMagneticMode = 2;
  672. break;
  673. }
  674. case 2:
  675. {
  676. self.m_gridMagneticMode = 0;
  677. break;
  678. }
  679. }
  680. self.m_sceneBlock.setCanvas(self.m_canvas, self.m_gridMagneticMode);
  681. });
  682. },
  683.  
  684. /**
  685. @method _sceneProcessing
  686. **/
  687. _sceneProcessing: function (i_status, i_callBack) {
  688. var self = this;
  689. if (i_status) {
  690. $(Elements.SCENE_PROCESSING).css({
  691. width: $('#scenePanelWrap').width(),
  692. height: $('#scenePanelWrap').height()
  693. })
  694. $(Elements.SCENE_PROCESSING).fadeTo('fast', 0.7, i_callBack);
  695. } else {
  696. $(Elements.SCENE_PROCESSING).fadeOut('slow', i_callBack);
  697. }
  698. },
  699.  
  700. /**
  701. Listen to undo and redo
  702. @method _listenMemento
  703. **/
  704. _listenMemento: function () {
  705. var self = this;
  706. BB.comBroker.listen(BB.EVENTS.SCENE_UNDO, function (e) {
  707. if (self.m_rendering)
  708. return;
  709. self.m_blocks.blockSelected = undefined;
  710. self._discardSelections();
  711. self._mementoLoadState('undo');
  712. });
  713. BB.comBroker.listen(BB.EVENTS.SCENE_REDO, function (e) {
  714. if (self.m_rendering)
  715. return;
  716. self.m_blocks.blockSelected = undefined;
  717. self._discardSelections();
  718. self._mementoLoadState('redo');
  719. });
  720. },
  721.  
  722. /**
  723. Init a undo / redo via memento pattern
  724. @method _mementoInit
  725. @return {Boolean} return true if memento created false if one already existed
  726. **/
  727. _mementoInit: function () {
  728. var self = this;
  729. if (_.isUndefined(self.m_memento[self.m_selectedSceneID])) {
  730. self.m_memento[self.m_selectedSceneID] = {
  731. playerData: [],
  732. cursor: -1
  733. };
  734. return true;
  735. }
  736. return false;
  737. },
  738.  
  739. /**
  740. Remember current memento state
  741. @method _mementoAddState
  742. **/
  743. _mementoAddState: function () {
  744. var self = this;
  745. var MAX = 100;
  746. if (_.isUndefined(self.m_selectedSceneID))
  747. return;
  748. self._mementoInit(self.m_selectedSceneID);
  749.  
  750. // maintain memento to stack MAX value
  751. if (self.m_memento[self.m_selectedSceneID].playerData.length > MAX)
  752. self.m_memento[self.m_selectedSceneID].playerData.shift();
  753.  
  754. // if undo / redo was executed, remove ahead mementos
  755. if (self.m_memento[self.m_selectedSceneID].cursor != self.m_memento[self.m_selectedSceneID].playerData.length - 1)
  756. self.m_memento[self.m_selectedSceneID].playerData.splice(self.m_memento[self.m_selectedSceneID].cursor + 1);
  757.  
  758. var player_data = pepper.getScenePlayerdata(self.m_selectedSceneID);
  759. self.m_memento[self.m_selectedSceneID].playerData.push(player_data);
  760. self.m_memento[self.m_selectedSceneID].cursor = self.m_memento[self.m_selectedSceneID].playerData.length - 1;
  761. },
  762.  
  763. /**
  764. Remember current memento state
  765. @method _mementoLoadState
  766. **/
  767. _mementoLoadState: function (i_direction) {
  768. var self = this;
  769. if (_.isUndefined(self.m_selectedSceneID))
  770. return;
  771. self._mementoInit(self.m_selectedSceneID);
  772. if (self.m_memento[self.m_selectedSceneID].playerData.length == 0)
  773. return;
  774.  
  775. switch (i_direction) {
  776. case 'undo':
  777. {
  778. var cursor = self.m_memento[self.m_selectedSceneID].cursor;
  779. if (cursor == 0)
  780. return;
  781. self.m_memento[self.m_selectedSceneID].cursor--;
  782. cursor = self.m_memento[self.m_selectedSceneID].cursor;
  783. break;
  784. }
  785. case 'redo':
  786. {
  787. var cursor = self.m_memento[self.m_selectedSceneID].cursor;
  788. if (cursor == self.m_memento[self.m_selectedSceneID].playerData.length - 1)
  789. return;
  790. self.m_memento[self.m_selectedSceneID].cursor++;
  791. cursor = self.m_memento[self.m_selectedSceneID].cursor;
  792. break;
  793. }
  794. }
  795. var player_data = self.m_memento[self.m_selectedSceneID].playerData[cursor];
  796. pepper.setScenePlayerData(self.m_selectedSceneID, player_data);
  797. self._loadScene();
  798. BB.comBroker.fire(BB.EVENTS.SCENE_LIST_UPDATED, this, null);
  799. },
  800.  
  801. /**
  802. Update the z-order index of an object
  803. @method _updateZorder
  804. @param {String} i_pushDirection
  805. @param {Object} i_block
  806. **/
  807. _updateZorder: function (i_pushDirection, i_block) {
  808. var self = this;
  809. if (_.isUndefined(self.m_selectedSceneID))
  810. return;
  811. var active = self.m_canvas.getActiveGroup();
  812. if (active)
  813. return;
  814. var blockID = i_block.getBlockData().blockID;
  815. var sceneDomPlayerData = pepper.getScenePlayerdataDom(self.m_selectedSceneID);
  816. var domBlockData = $(sceneDomPlayerData).find('[id="' + blockID + '"]');
  817. switch (i_pushDirection) {
  818. case self.PUSH_TOP:
  819. {
  820. $(sceneDomPlayerData).find('Players').append($(domBlockData));
  821. break;
  822. }
  823. case self.PUSH_BOTTOM:
  824. {
  825. $(sceneDomPlayerData).find('Players').prepend($(domBlockData));
  826. break;
  827. }
  828. }
  829. pepper.setScenePlayerData(self.m_selectedSceneID, (new XMLSerializer()).serializeToString(sceneDomPlayerData));
  830. },
  831.  
  832. /**
  833. Pre render creates all of the Fabric blocks that will later get added when we call _render
  834. This allows for smooth (non flickering) rendering since when we are ready to render, the blocks have
  835. already been instantiated and ready to be added to canvas
  836. @method _preRender
  837. @param {Object} i_domPlayerData
  838. @param {Object} [i_blockIDs] optionally render only a single block
  839. **/
  840. _preRender: function (i_domPlayerData, i_blockIDs) {
  841. var self = this;
  842. var zIndex = -1;
  843. self._renderPause();
  844. self.m_blocks.blocksPre = [];
  845. self.m_blocks.blocksPost = {};
  846. log('pre-rendering new blocks');
  847.  
  848. // if rendering specific blocks instead of entire canvas
  849. if (i_blockIDs) {
  850. $(i_domPlayerData).find('Players').children('Player').each(function (i, player) {
  851. zIndex++;
  852. var blockID = $(player).attr('id');
  853. if (_.indexOf(i_blockIDs, blockID) > -1) {
  854. var block = {
  855. blockID: blockID,
  856. blockType: $(player).attr('player'),
  857. zIndex: zIndex,
  858. player_data: (new XMLSerializer()).serializeToString(player)
  859. };
  860. self.m_blocks.blocksPre.push(block);
  861. }
  862. });
  863. } else {
  864. $(i_domPlayerData).find('Players').children('Player').each(function (i, player) {
  865. var block = {
  866. blockID: $(player).attr('id'),
  867. blockType: $(player).attr('player'),
  868. zIndex: -1,
  869. player_data: (new XMLSerializer()).serializeToString(player)
  870.  
  871. };
  872. self.m_blocks.blocksPre.push(block);
  873. });
  874. }
  875. self._createBlock(i_blockIDs);
  876. },
  877.  
  878. /**
  879. Render the pre created blocks (via _preRender) and add all blocks to fabric canvas
  880. @method _render
  881. **/
  882. _render: function (i_blockIDs) {
  883. var self = this;
  884. if (!self.m_canvas)
  885. return;
  886. var nZooms = Math.round(Math.log(1 / self.m_canvasScale) / Math.log(1.2));
  887. var selectedBlockID = self.m_blocks.blockSelected;
  888. var createAll = i_blockIDs[0] == undefined ? true : false; // if to re-render entire canvas
  889.  
  890. if (createAll) {
  891. self._disposeBlocks();
  892. self._zoomReset();
  893. } else {
  894. // if to re-render only changed blocks
  895. for (var i = 0; i < i_blockIDs.length; i++)
  896. self._disposeBlocks(i_blockIDs[i]);
  897. }
  898. _.forEach(self.m_blocks.blocksPost, function (i_block) {
  899. self.m_canvas.add(i_block);
  900. });
  901. if (createAll) {
  902. self._resetAllObjectScale();
  903. self._zoomTo(nZooms);
  904. } else {
  905. // if to re-render only changed blocks
  906. _.forEach(self.m_blocks.blocksPost, function (i_block) {
  907. var zIndex = i_block.getZindex();
  908. if (zIndex > -1)
  909. i_block.moveTo(zIndex);
  910. self.m_canvas.setActiveObject(i_block);
  911. self._zoomToBlock(nZooms, i_block);
  912. self._resetObjectScale(i_block);
  913. });
  914. }
  915. self._scrollTo(self.m_sceneScrollTop, self.m_sceneScrollLeft);
  916. self.m_canvas.renderAll();
  917. self._sceneProcessing(false, function () {
  918. });
  919. self._renderContinue();
  920. if (createAll)
  921. self._updateBlockCount();
  922.  
  923. // select previous selection
  924. if (_.isUndefined(selectedBlockID))
  925. return;
  926. if (createAll) {
  927. for (var i = 0; i < self.m_canvas.getObjects().length; i++) {
  928. if (selectedBlockID == self.m_canvas.item(i).getBlockData().blockID) {
  929. self._blockSelected(self.m_canvas.item(i));
  930. break;
  931. }
  932. }
  933. } else {
  934. var block = self.m_blocks.blocksPost[Object.keys(self.m_blocks.blocksPost)[0]];
  935. self._blockSelected(block);
  936. }
  937. },
  938.  
  939. /**
  940. Prevent rendering of canvas to continue and remove canvas listeners
  941. @method _renderPause
  942. **/
  943. _renderPause: function () {
  944. var self = this;
  945. self.m_rendering = true;
  946. if (_.isUndefined(self.m_canvas))
  947. return;
  948. self.m_canvas.removeListeners();
  949. },
  950.  
  951. /**
  952. Allow rendering of canvas to continue and add canvas listeners
  953. @method _renderContinue
  954. **/
  955. _renderContinue: function () {
  956. var self = this;
  957. self.m_rendering = false;
  958. if (_.isUndefined(self.m_canvas))
  959. return;
  960. self.m_canvas._initEventListeners();
  961. },
  962.  
  963. /**
  964. Create all the blocks that have been pre injected to m_blocks.blocksPre and after each block
  965. is created created the next block; thus creating blocks sequentially due to fabric bug. When no
  966. more blocks are to be created (m_blocks.blocksPre queue is empty) we _render the canvas
  967. @method _createBlock
  968. @param {Array} [i_blockIDs] optional array of block ids to render, or non if we render the entire canvas
  969. **/
  970. _createBlock: function (i_blockIDs) {
  971. var self = this;
  972. var blockData = self.m_blocks.blocksPre.shift();
  973. if (blockData == undefined) {
  974. self._render([i_blockIDs]);
  975. return;
  976. }
  977. var newBlock = self.m_blockFactory.createBlock(blockData.blockID, blockData.player_data, BB.CONSTS.PLACEMENT_SCENE, self.m_selectedSceneID);
  978. newBlock.setZindex(blockData.zIndex);
  979. var blockID = newBlock.getBlockData().blockID;
  980. newBlock.fabricateBlock(self.m_canvasScale, function () {
  981. self.m_blocks.blocksPost[blockID] = newBlock;
  982. self._createBlock(i_blockIDs);
  983. });
  984. },
  985.  
  986. /**
  987. Announce to all that scene was re-rendered but do it via debounce
  988. @method _delegateSceneBlockModified
  989. **/
  990. _delegateSceneBlockModified: function () {
  991. var self = this;
  992. self._sceneBlockModified = _.debounce(function (e) {
  993. BB.comBroker.fire(BB.EVENTS.SCENE_BLOCKS_RENDERED, self, self.m_canvas);
  994. self._mementoAddState();
  995. // self._drawGrid();
  996. }, 200);
  997. },
  998.  
  999. /**
  1000. Anytime the containing StackView is selected, re-render
  1001. removed while we were gone
  1002. @method _listenStackViewSelected
  1003. **/
  1004. _listenStackViewSelected: function () {
  1005. var self = this;
  1006. var appContentFaderView = BB.comBroker.getService(BB.SERVICES['APP_CONTENT_FADER_VIEW']);
  1007. appContentFaderView.on(BB.EVENTS.SELECTED_STACK_VIEW, function (e) {
  1008. if (e == BB.comBroker.getService(BB.SERVICES['SCENES_LOADER_VIEW'])) {
  1009. setTimeout(function () {
  1010. if (_.isUndefined(self.m_canvas))
  1011. return;
  1012. self.m_canvas.calcOffset();
  1013. }, 500);
  1014. }
  1015. });
  1016. },
  1017.  
  1018. /**
  1019. Listen to when the app is resized so we can re-render
  1020. @method _listenAppResized
  1021. **/
  1022. _listenAppResized: function () {
  1023. var self = this;
  1024. BB.comBroker.listen(BB.EVENTS.APP_SIZED, function (e) {
  1025. if (_.isUndefined(self.m_canvas))
  1026. return;
  1027. self.m_canvas.calcOffset();
  1028. });
  1029. },
  1030.  
  1031. /**
  1032. Scene block scales via mouse UI
  1033. @method _sceneBlockScaled
  1034. @param {Event} e
  1035. **/
  1036. _sceneBlockScaled: function (e) {
  1037. var self = this;
  1038. if (self.m_objectScaling)
  1039. return;
  1040. self.m_objectScaling = 1;
  1041. var block = e.target;
  1042. if (_.isUndefined(block))
  1043. return;
  1044. block.on('modified', function () {
  1045. setTimeout(function () {
  1046. block.off('modified');
  1047. var blockID = block.getBlockData().blockID;
  1048. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, [blockID]);
  1049. self.m_objectScaling = 0;
  1050. }, 15);
  1051. });
  1052. },
  1053.  
  1054. /**
  1055. Scene block moving
  1056. @method _sceneBlockMoving
  1057. @param {Object} i_options
  1058. **/
  1059. _sceneBlockMoving: function (i_options) {
  1060. var self = this;
  1061. var grid = 0;
  1062. if (i_options.target.lockMovementX)
  1063. return;
  1064. if (self.m_gridMagneticMode == 0)
  1065. return;
  1066. if (self.m_gridMagneticMode == 1)
  1067. grid = 5;
  1068. if (self.m_gridMagneticMode == 2)
  1069. grid = 10;
  1070. i_options.target.set({
  1071. left: Math.round(i_options.target.left / grid) * grid,
  1072. top: Math.round(i_options.target.top / grid) * grid
  1073. });
  1074. },
  1075.  
  1076. /**
  1077. Listen to changes in scale so we can reset back to non-zoom on any block object
  1078. @method _listenBlockModified
  1079. **/
  1080. _listenBlockModified: function () {
  1081. var self = this;
  1082. self.m_canvas.on({
  1083. //'object:moving': self.m_objectScaleHandler,
  1084. //'object:selected': self.m_objectScaleHandler,
  1085. 'object:modified': self._sceneBlockModified,
  1086. 'object:scaling': $.proxy(self._sceneBlockScaled, self)
  1087. });
  1088. self.m_canvas.on('object:moving', $.proxy(self._sceneBlockMoving, self));
  1089. },
  1090.  
  1091. _drawGrid: function () {
  1092. var self = this;
  1093. self.m_canvas.setBackgroundColor('', self.m_canvas.renderAll.bind(self.m_canvas));
  1094. var context = $(self.m_canvas)[0].getContext("2d");
  1095. var h = 600;
  1096. var w = 700;
  1097. for (var x = 0.5; x < (w + 1); x += 10) {
  1098. context.moveTo(x, 0);
  1099. context.lineTo(x, (h + 1));
  1100. }
  1101. for (var y = 0.5; y < (h + 1); y += 10) {
  1102. context.moveTo(0, y);
  1103. context.lineTo(w, y);
  1104. }
  1105. context.globalAlpha = 0.1;
  1106. context.strokeStyle = "black";
  1107. context.stroke();
  1108. context.globalAlpha = 1;
  1109. },
  1110.  
  1111. /**
  1112. Listen to canvas user selections
  1113. @method _listenCanvasSelections
  1114. **/
  1115. _listenCanvasSelections: function () {
  1116. var self = this;
  1117.  
  1118. //self.m_canvas.on('object:selected', function (e) {
  1119. // var blockID = e.target.m_blockType;
  1120. // BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, blockID);
  1121. //});
  1122.  
  1123. self.m_canvas.on('mouse:down', function (options) {
  1124. self.m_canvasMouseState = 1;
  1125. });
  1126.  
  1127. self.m_canvas.on('mouse:up', function (options) {
  1128. self.m_canvasMouseState = 0;
  1129. var active = self.m_canvas.getActiveObject();
  1130. var group = self.m_canvas.getActiveGroup();
  1131.  
  1132. //options.e.stopImmediatePropagation();
  1133. //options.e.preventDefault();
  1134.  
  1135. //// Group
  1136. if (group) {
  1137. log('group selected');
  1138. var selectedGroup = options.target || group;
  1139. _.each(group.objects, function (selectedObject) {
  1140. var objectPos = {
  1141. x: (selectedGroup.left + (selectedObject.left)),
  1142. y: (selectedGroup.top + (selectedObject.top))
  1143. };
  1144. if (objectPos.x < 0 && objectPos.y < 0) {
  1145. // objectPos.x = objectPos.x * -1;
  1146. // objectPos.y = objectPos.y * -1;
  1147. return;
  1148. }
  1149. var blockID = selectedObject.getBlockData().blockID;
  1150. log('object: ' + selectedObject.m_blockType + ' ' + blockID);
  1151. self._updateBlockCords(selectedObject, true, objectPos.x, objectPos.y, selectedObject.currentWidth, selectedObject.currentHeight, selectedObject.angle);
  1152. // self._updateZorder();
  1153. });
  1154. // self._mementoAddState();
  1155. selectedGroup.hasControls = false;
  1156. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  1157. return;
  1158. }
  1159.  
  1160. //// Object
  1161. if (options.target || active) {
  1162. var block = options.target || active;
  1163. self._blockSelected(block);
  1164. return;
  1165. }
  1166.  
  1167. //// Scene
  1168. self._sceneCanvasSelected();
  1169. log('scene: ' + self.m_selectedSceneID);
  1170. // log('object ' + options.e.clientX + ' ' + options.e.clientY + ' ' + options.target.m_blockType);
  1171.  
  1172. });
  1173. },
  1174.  
  1175. /**
  1176. Select a block object on the canvas
  1177. @method _blockSelected
  1178. @param {Object} i_block
  1179. **/
  1180. _blockSelected: function (i_block) {
  1181. var self = this;
  1182. self.m_canvas.setActiveObject(i_block);
  1183. var blockID = i_block.getBlockData().blockID;
  1184. log('object: ' + i_block.m_blockType + ' ' + blockID);
  1185. self._updateBlockCords(i_block, true, i_block.left, i_block.top, i_block.currentWidth, i_block.currentHeight, i_block.angle);
  1186. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, blockID);
  1187. },
  1188.  
  1189. /**
  1190. Deselect current group and or block selections
  1191. @method _canvasDiscardSelections
  1192. **/
  1193. _discardSelections: function () {
  1194. var self = this;
  1195. if (!self.m_canvas)
  1196. return;
  1197. self.m_canvas.discardActiveGroup();
  1198. self.m_canvas.discardActiveObject();
  1199. },
  1200.  
  1201. /**
  1202. Set the scene (i.e.: Canvas) as the selected block
  1203. @method _sceneCanvasSelected
  1204. **/
  1205. _sceneCanvasSelected: function () {
  1206. var self = this;
  1207. if (_.isUndefined(self.m_selectedSceneID))
  1208. return;
  1209. self._discardSelections();
  1210. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, self.m_selectedSceneID);
  1211. },
  1212.  
  1213. /**
  1214. Listen to scene block / item selection initiated by user selection of toolbar dropdown
  1215. @method _listenCanvasSelectionsFromToolbar
  1216. **/
  1217. _listenCanvasSelectionsFromToolbar: function () {
  1218. var self = this;
  1219. BB.comBroker.listen(BB.EVENTS.SCENE_ITEM_SELECTED, function (e) {
  1220. var blockID = e.edata;
  1221.  
  1222. // Scene selected
  1223. if (blockID == BB.CONSTS.SCENE_CANVAS_SELECTED) {
  1224. self._sceneCanvasSelected();
  1225. return;
  1226. }
  1227.  
  1228. // block selected
  1229. for (var i = 0; i < self.m_canvas.getObjects().length; i++) {
  1230. if (self.m_canvas.item(i).getBlockData().blockID == blockID) {
  1231. self._blockSelected(self.m_canvas.item(i));
  1232. break;
  1233. }
  1234. }
  1235. });
  1236. },
  1237.  
  1238. /**
  1239. Update the coordinates of a block in pepper db, don't allow below w/h MIN_SIZE
  1240. @method _updateBlockCords
  1241. @param {String} blockID
  1242. @param {Boolean} i_calcScale
  1243. @param {Number} x
  1244. @param {Number} y
  1245. @param {Number} w
  1246. @param {Number} h
  1247. **/
  1248. _updateBlockCords: function (i_block, i_calcScale, x, y, w, h, a) {
  1249. var self = this;
  1250.  
  1251. var blockID = i_block.getBlockData().blockID;
  1252. var blockMinWidth = i_block.getBlockData().blockMinWidth;
  1253. var blockMinHeight = i_block.getBlockData().blockMinHeight;
  1254.  
  1255. if (i_calcScale) {
  1256. var sy = 1 / self.m_canvasScale;
  1257. var sx = 1 / self.m_canvasScale;
  1258. h = h * sy;
  1259. w = w * sx;
  1260. x = x * sx;
  1261. y = y * sy;
  1262. }
  1263.  
  1264. if (h < blockMinHeight)
  1265. h = blockMinHeight;
  1266. if (w < blockMinWidth)
  1267. w = blockMinWidth;
  1268.  
  1269. var domPlayerData = pepper.getScenePlayerdataBlock(self.m_selectedSceneID, blockID);
  1270. var layout = $(domPlayerData).find('Layout');
  1271. layout.attr('rotation', parseInt(a));
  1272. layout.attr('x', parseInt(x));
  1273. layout.attr('y', parseInt(y));
  1274. layout.attr('width', parseInt(w));
  1275. layout.attr('height', parseInt(h));
  1276. var player_data = (new XMLSerializer()).serializeToString(domPlayerData);
  1277. pepper.setScenePlayerdataBlock(self.m_selectedSceneID, blockID, player_data);
  1278. },
  1279.  
  1280. /**
  1281. Reset all canvas objects to their scale is set to 1
  1282. @method _resetAllObjectScale
  1283. **/
  1284. _resetAllObjectScale: function () {
  1285. var self = this;
  1286. if (_.isUndefined(self.m_selectedSceneID))
  1287. return;
  1288. _.each(self.m_canvas.getObjects(), function (obj) {
  1289. self._resetObjectScale(obj);
  1290. });
  1291. // self.m_canvas.renderAll();
  1292. },
  1293.  
  1294. /**
  1295. Reset a canvas object so its scale is set to 1
  1296. @method _resetObjectScale
  1297. **/
  1298. _resetObjectScale: function (i_target) {
  1299. var self = this;
  1300. if (_.isNull(i_target))
  1301. return;
  1302. if (i_target.width != i_target.currentWidth || i_target.height != i_target.currentHeight) {
  1303. i_target.width = i_target.currentWidth;
  1304. i_target.height = i_target.currentHeight;
  1305. i_target.scaleX = 1;
  1306. i_target.scaleY = 1;
  1307. }
  1308. },
  1309.  
  1310. /**
  1311. Remove all block instances
  1312. @method _disposeBlocks
  1313. @params {Number} [i_blockID] optional to remove only a single block
  1314. **/
  1315. _disposeBlocks: function (i_blockID) {
  1316. var self = this, i;
  1317. if (_.isUndefined(self.m_canvas))
  1318. return;
  1319. var totalObjects = self.m_canvas.getObjects().length;
  1320. var c = -1;
  1321. for (i = 0; i < totalObjects; i++) {
  1322. c++;
  1323. var block = self.m_canvas.item(c);
  1324. // single block
  1325. if (i_blockID) {
  1326. if (block.getBlockData().blockID == i_blockID) {
  1327. block.selectable = false; // fix fabric scale block bug
  1328. self.m_canvas.remove(block);
  1329. block.deleteBlock();
  1330. break;
  1331. }
  1332. } else {
  1333. // all blocks
  1334. block.selectable = false; // fix fabric scale block bug
  1335. self.m_canvas.remove(block);
  1336. if (block) {
  1337. block.deleteBlock();
  1338. c--;
  1339. }
  1340. }
  1341. }
  1342. if (!i_blockID)
  1343. self.m_canvas.clear();
  1344. },
  1345.  
  1346. _canvasUnselectable: function () {
  1347. var self = this, i;
  1348. if (_.isUndefined(self.m_canvas))
  1349. return;
  1350. self.m_canvas.removeListeners();
  1351. //self.m_canvas.interactive = false;
  1352. // self.m_canvas.selection = false;
  1353. var totalObjects = self.m_canvas.getObjects().length;
  1354. var c = -1;
  1355. for (i = 0; i < totalObjects; i++) {
  1356. c++;
  1357. var block = self.m_canvas.item(c);
  1358. block.selectable = false;
  1359. if (block)
  1360. c--;
  1361. }
  1362. },
  1363.  
  1364. /**
  1365. Listen to all zoom events via wiring the UI
  1366. @method _listenZoom
  1367. **/
  1368. _listenZoom: function () {
  1369. var self = this;
  1370. BB.comBroker.listen(BB.EVENTS.SCENE_ZOOM_IN, function (e) {
  1371. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  1372. self._zoomIn();
  1373. self._discardSelections();
  1374. self._resetAllObjectScale();
  1375. self.m_canvas.renderAll();
  1376. });
  1377. BB.comBroker.listen(BB.EVENTS.SCENE_ZOOM_OUT, function (e) {
  1378. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  1379. self._zoomOut();
  1380. self._discardSelections();
  1381. self._resetAllObjectScale();
  1382. self.m_canvas.renderAll();
  1383. });
  1384. BB.comBroker.listen(BB.EVENTS.SCENE_ZOOM_RESET, function (e) {
  1385. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  1386. self._zoomReset();
  1387. self._resetAllObjectScale();
  1388. self.m_canvas.renderAll();
  1389. });
  1390. },
  1391.  
  1392. /**
  1393. Zoom to scale size
  1394. @method _zoomTo
  1395. @param {Number} nZooms
  1396. **/
  1397. _zoomTo: function (nZooms) {
  1398. var self = this, i;
  1399. if (nZooms > 0) {
  1400. for (i = 0; i < nZooms; i++)
  1401. self._zoomOut();
  1402. } else {
  1403. for (i = 0; i > nZooms; nZooms++)
  1404. self._zoomIn();
  1405. }
  1406. },
  1407.  
  1408. /**
  1409. Zoom to scale size
  1410. @method _zoomTo
  1411. @param {Number} nZooms
  1412. **/
  1413. _zoomToBlock: function (nZooms, block) {
  1414. var self = this, i;
  1415. if (nZooms > 0) {
  1416. for (i = 0; i < nZooms; i++)
  1417. self._zoomOutBlock(block);
  1418. } else {
  1419. for (i = 0; i > nZooms; nZooms++)
  1420. self._zoomInBlock(block);
  1421. }
  1422. },
  1423.  
  1424. /**
  1425. Scroll canvas to set position
  1426. @method _scrollTo
  1427. @param {Number} i_top
  1428. @param {Number} i_left
  1429. **/
  1430. _scrollTo: function (i_top, i_left) {
  1431. var self = this;
  1432. $(Elements.SCENES_PANEL).scrollTop(i_top);
  1433. $(Elements.SCENES_PANEL).scrollLeft(i_left);
  1434. },
  1435.  
  1436. /**
  1437. Zoom scene in
  1438. @method _zoomIn
  1439. **/
  1440. _zoomIn: function () {
  1441. var self = this;
  1442. if (_.isUndefined(self.m_selectedSceneID))
  1443. return;
  1444. self.m_canvasScale = self.m_canvasScale * self.SCALE_FACTOR;
  1445. self.m_canvas.setHeight(self.m_canvas.getHeight() * self.SCALE_FACTOR);
  1446. self.m_canvas.setWidth(self.m_canvas.getWidth() * self.SCALE_FACTOR);
  1447.  
  1448. var objects = self.m_canvas.getObjects();
  1449. for (var i in objects) {
  1450. if (_.isNull(objects[i]))
  1451. return;
  1452. self._zoomInBlock(objects[i]);
  1453. }
  1454. },
  1455.  
  1456. /**
  1457. Zoom scene in
  1458. @method _zoomIn
  1459. **/
  1460. _zoomInBlock: function (i_block) {
  1461. var self = this;
  1462. var scaleX = i_block.scaleX;
  1463. var scaleY = i_block.scaleY;
  1464. var left = i_block.left;
  1465. var top = i_block.top;
  1466. var tempScaleX = scaleX * self.SCALE_FACTOR;
  1467. var tempScaleY = scaleY * self.SCALE_FACTOR;
  1468. var tempLeft = left * self.SCALE_FACTOR;
  1469. var tempTop = top * self.SCALE_FACTOR;
  1470.  
  1471. i_block['canvasScale'] = self.m_canvasScale;
  1472. i_block.scaleX = tempScaleX;
  1473. i_block.scaleY = tempScaleY;
  1474. i_block.left = tempLeft;
  1475. i_block.top = tempTop;
  1476. i_block.setCoords();
  1477.  
  1478. if (i_block.forEachObject != undefined) {
  1479. i_block.forEachObject(function (obj) {
  1480. var scaleX = obj.scaleX;
  1481. var scaleY = obj.scaleY;
  1482. var left = obj.left;
  1483. var top = obj.top;
  1484. var tempScaleX = scaleX * self.SCALE_FACTOR;
  1485. var tempScaleY = scaleY * self.SCALE_FACTOR;
  1486. var tempLeft = left * self.SCALE_FACTOR;
  1487. var tempTop = top * self.SCALE_FACTOR;
  1488. obj['canvasScale'] = self.m_canvasScale;
  1489. obj.scaleX = tempScaleX;
  1490. obj.scaleY = tempScaleY;
  1491. obj.left = tempLeft;
  1492. obj.top = tempTop;
  1493. obj.setCoords();
  1494. });
  1495. }
  1496. },
  1497.  
  1498. /**
  1499. Zoom scene out
  1500. @method _zoomOut
  1501. **/
  1502. _zoomOutBlock: function (i_block) {
  1503. var self = this;
  1504. var scaleX = i_block.scaleX;
  1505. var scaleY = i_block.scaleY;
  1506. var left = i_block.left;
  1507. var top = i_block.top;
  1508. var tempScaleX = scaleX * (1 / self.SCALE_FACTOR);
  1509. var tempScaleY = scaleY * (1 / self.SCALE_FACTOR);
  1510. var tempLeft = left * (1 / self.SCALE_FACTOR);
  1511. var tempTop = top * (1 / self.SCALE_FACTOR);
  1512. i_block['canvasScale'] = self.m_canvasScale;
  1513. i_block.scaleX = tempScaleX;
  1514. i_block.scaleY = tempScaleY;
  1515. i_block.left = tempLeft;
  1516. i_block.top = tempTop;
  1517. i_block.setCoords();
  1518.  
  1519. if (i_block.forEachObject != undefined) {
  1520. i_block.forEachObject(function (obj) {
  1521. var scaleX = obj.scaleX;
  1522. var scaleY = obj.scaleY;
  1523. var left = obj.left;
  1524. var top = obj.top;
  1525. var tempScaleX = scaleX * (1 / self.SCALE_FACTOR);
  1526. var tempScaleY = scaleY * (1 / self.SCALE_FACTOR);
  1527. var tempLeft = left * (1 / self.SCALE_FACTOR);
  1528. var tempTop = top * (1 / self.SCALE_FACTOR);
  1529. obj['canvasScale'] = self.m_canvasScale;
  1530. obj.scaleX = tempScaleX;
  1531. obj.scaleY = tempScaleY;
  1532. obj.left = tempLeft;
  1533. obj.top = tempTop;
  1534. obj.setCoords();
  1535. });
  1536. }
  1537. },
  1538.  
  1539. /**
  1540. Zoom scene out
  1541. @method _zoomOut
  1542. **/
  1543. _zoomOut: function () {
  1544. var self = this;
  1545. if (_.isUndefined(self.m_selectedSceneID))
  1546. return;
  1547. self.m_canvasScale = self.m_canvasScale / self.SCALE_FACTOR;
  1548. self.m_canvas.setHeight(self.m_canvas.getHeight() * (1 / self.SCALE_FACTOR));
  1549. self.m_canvas.setWidth(self.m_canvas.getWidth() * (1 / self.SCALE_FACTOR));
  1550. var objects = self.m_canvas.getObjects();
  1551. for (var i in objects) {
  1552. if (_.isNull(objects[i]))
  1553. return;
  1554. self._zoomOutBlock(objects[i]);
  1555. }
  1556. },
  1557.  
  1558. /**
  1559. Zoom reset back to scale 1
  1560. @method _zoomReset
  1561. **/
  1562. _zoomReset: function () {
  1563. var self = this;
  1564. if (_.isUndefined(self.m_selectedSceneID) || _.isUndefined(self.m_canvas)) {
  1565. self.m_canvasScale = 1;
  1566. return;
  1567. }
  1568. self._discardSelections();
  1569. self.m_canvas.setHeight(self.m_canvas.getHeight() * (1 / self.m_canvasScale));
  1570. self.m_canvas.setWidth(self.m_canvas.getWidth() * (1 / self.m_canvasScale));
  1571. var objects = self.m_canvas.getObjects();
  1572. for (var i in objects) {
  1573. if (_.isNull(objects[i]))
  1574. return;
  1575. var scaleX = objects[i].scaleX;
  1576. var scaleY = objects[i].scaleY;
  1577. var left = objects[i].left;
  1578. var top = objects[i].top;
  1579. var tempScaleX = scaleX * (1 / self.m_canvasScale);
  1580. var tempScaleY = scaleY * (1 / self.m_canvasScale);
  1581. var tempLeft = left * (1 / self.m_canvasScale);
  1582. var tempTop = top * (1 / self.m_canvasScale);
  1583. objects[i].scaleX = tempScaleX;
  1584. objects[i].scaleY = tempScaleY;
  1585. objects[i].left = tempLeft;
  1586. objects[i].top = tempTop;
  1587. objects[i].setCoords();
  1588. objects[i]['canvasScale'] = 1;
  1589.  
  1590. if (objects[i].forEachObject != undefined) {
  1591. objects[i].forEachObject(function (obj) {
  1592. var scaleX = obj.scaleX;
  1593. var scaleY = obj.scaleY;
  1594. var left = obj.left;
  1595. var top = obj.top;
  1596. var tempScaleX = scaleX * (1 / self.m_canvasScale);
  1597. var tempScaleY = scaleY * (1 / self.m_canvasScale);
  1598. var tempLeft = left * (1 / self.m_canvasScale);
  1599. var tempTop = top * (1 / self.m_canvasScale);
  1600. obj.scaleX = tempScaleX;
  1601. obj.scaleY = tempScaleY;
  1602. obj.left = tempLeft;
  1603. obj.top = tempTop;
  1604. obj.setCoords();
  1605. obj['canvasScale'] = 1;
  1606. });
  1607. }
  1608. }
  1609. self.m_canvasScale = 1;
  1610. },
  1611.  
  1612. /**
  1613. Remove a Scene and cleanup after
  1614. @method disposeScene
  1615. **/
  1616. disposeScene: function () {
  1617. var self = this;
  1618. if (_.isUndefined(self.m_canvas))
  1619. return;
  1620. self.m_canvas.off('mouse:up');
  1621. self.m_blocks.blocksPost = {};
  1622. self._disposeBlocks();
  1623. self.m_sceneBlock.deleteBlock();
  1624. self.m_canvas.dispose();
  1625. self.m_canvas = undefined;
  1626. self.m_property.resetPropertiesView();
  1627. },
  1628.  
  1629. /**
  1630. Create a new scene based on player_data and strip injected IDs if arged
  1631. @method createScene
  1632. @param {String} i_scenePlayerData
  1633. @optional {Boolean} i_stripIDs
  1634. @optional {Boolean} i_loadScene
  1635. @optional {String} i_mimeType
  1636. @optional {String} i_name
  1637. **/
  1638. createScene: function (i_scenePlayerData, i_stripIDs, i_loadScene, i_mimeType, i_name) {
  1639. var self = this;
  1640. if (i_stripIDs)
  1641. i_scenePlayerData = pepper.stripPlayersID(i_scenePlayerData);
  1642. self.m_selectedSceneID = pepper.createScene(i_scenePlayerData, i_mimeType, i_name);
  1643. // BB.comBroker.fire(BB.EVENTS.NEW_SCENE_ADDED, this, null, self.m_selectedSceneID);
  1644. if (i_loadScene)
  1645. self._loadScene();
  1646. BB.comBroker.fire(BB.EVENTS.SCENE_LIST_UPDATED, this, null);
  1647. },
  1648.  
  1649. /**
  1650. Get currently selected scene id
  1651. @method getSelectedSceneID
  1652. @return {Number} scene id
  1653. **/
  1654. getSelectedSceneID: function () {
  1655. var self = this;
  1656. return self.m_selectedSceneID;
  1657. }
  1658. });
  1659. return SceneEditorView;
  1660. });