From b89a7ee8b956c96a1dcee995ea840feddc5d4b27 Mon Sep 17 00:00:00 2001 From: Pierre Frisch Date: Thu, 22 Dec 2011 07:25:50 -0800 Subject: First commit of Ninja to ninja-internal Signed-off-by: Valerio Virgillito --- js/tools/modifier-tool-base.js | 1007 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1007 insertions(+) create mode 100644 js/tools/modifier-tool-base.js (limited to 'js/tools/modifier-tool-base.js') diff --git a/js/tools/modifier-tool-base.js b/js/tools/modifier-tool-base.js new file mode 100644 index 00000000..f78e99c8 --- /dev/null +++ b/js/tools/modifier-tool-base.js @@ -0,0 +1,1007 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +var Montage = require("montage/core/core").Montage, + DrawingTool = require("js/tools/drawing-tool").DrawingTool, + snapManager = require("js/helper-classes/3D/snap-manager").SnapManager, + viewUtils = require("js/helper-classes/3D/view-utils").ViewUtils, + vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils, + drawUtils = require("js/helper-classes/3D/draw-utils").DrawUtils, + Properties3D = ("js/models/properties-3d").Properties3D; + +exports.ModifierToolBase = Montage.create(DrawingTool, { + + //------------------------------------------------------------------------- + // Drawing Mode Info + drawingFeedback: { value: { mode: "Draw3D", type: "rectangle" } }, + + //------------------------------------------------------------------------- + // Snapping-specific properties + _canSnap: { value: true }, + _dragPlane: { value: null }, + _snapParam: { value: null }, + _snapIndex: { value: -1 }, + _useQuadPt: { value: false }, + + // we set snapping capabilities depending on the tool. + // The following variables are set in a tool's initializeSnapping method called on mouse down. + _snapToElements: { value: true }, + _snapToGrid: { value: true }, + + _clickedObject : {value : null }, + clickedObject: + { + get: function () { + return this._clickedObject; + }, + set: function (value) { + if(value === this.application.ninja.currentDocument.documentRoot) + { + this._clickedObject = this._target; + } + else + { + this._clickedObject = value; + } + + if(value) + { + this._startMat = viewUtils.getMatrixFromElement(this._clickedObject); + } + else + { + this._startMat = null; + } + } + }, + + _getObjectBeingTracked : + { + value: function(hitRec) + { + var elt = hitRec.getElt(); + if(elt === this.application.ninja.currentDocument.documentRoot) + { + elt = this._target; + } + + return elt; + } + }, + + drawWithoutSnapping: + { + value: function(event) + { + // override in subclasses + } + }, + + initializeSnapping: + { + value: function(event) + { + this._mouseDownHitRec = null; + this._mouseUpHitRec = null; + + snapManager.clearAvoidList(); + snapManager.clearDragPlane(); + + // the translate tool does snap align to the bounds of the object only. + // turn off snap align to the cursor. This needs to be re-enabled in the mouse up method + snapManager.enableSnapAlign( false ); + + // snap to element and snap to grid are conditionally enabled based + // on the snap results of the mouse down. enable everything for the first snap + this._snapToElements = snapManager.elementSnapEnabledAppLevel(); + this._snapToGrid = snapManager.gridSnapEnabledAppLevel(); + + this._dragPlane = null; + var do3DSnap = true; + +// if(this._handleMode === null) +// { +// if(!this._activateOriginHandle) +// { +// this.doSelection(event); + + snapManager.enableElementSnap ( true ); +// snapManager.enableGridSnap ( true ); +// } +// } +// else +// { +// this._matL = this._handles[this._handleMode]._matL.slice(0); +// this._planeEq = this._handles[this._handleMode]._planeEq.slice(0); +// this._dirVecL = this._handles[this._handleMode]._dirVecL.slice(0); +// this.m_startPoint = MathUtils.getLocalPoint(event.layerX, event.layerY, this._planeEq, this._matL); +// if(!this.m_startPoint) +// { +// this.m_startPoint = [this.m_xStart, this.m_yStart]; +// } +// } + + + if(this._targets) + { + var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, + new WebKitPoint(event.pageX, event.pageY)); + // do the snap before setting up the avoid list to allow + // a snap on the mouse down + var hitRec = snapManager.snap(point.x, point.y, do3DSnap); + + // we don't want to snap to selected objects during the drag + var len = this._targets.length; + for(var i=0; i 0) + hitRec = alignArray[0]; + } + } + + if (hitRec) + { + if (mouseIsDown && this._clickedObject) + { + // make the hit record working plane relative + this._snapIndex = hitRec.getSnapBoundaryIndex(); + this._useQuadPt = hitRec.getUseQuadPoint(); + var wp = this._dragPlane ? this._dragPlane : workingPlane; + hitRec = hitRec.convertToWorkingPlane( wp ); + + // update the target + this._mouseUpHitRec = hitRec; + } + } + } + }, + + doDraw: { + value: function(event) + { + this.application.ninja.stage.clearDrawingCanvas(); + + if(this._canSnap) + { + this.updateUsingSnappingData(event); + } + else + { + this.updateWithoutSnappingData(event); + } + } + }, + + endDraw: { + value: function (event) { + this.application.ninja.stage.clearDrawingCanvas(); + + this.downPoint.x = null; + this.downPoint.y = null; +// this.isDrawing = false; + + if(this._canSnap) + { + this.cleanupSnap(); + } + } + }, + + cleanupSnap: { + value: function() { + this.mouseDownHitRec = null; + this.mouseUpHitRec = null; + + this._dragPlane = null; + this._useQuadPt = false; + + snapManager.clearAvoidList(); + snapManager.clearDragPlane(); + + // restore the snap settings + snapManager.enableSnapAlign( snapManager.snapAlignEnabledAppLevel() ); + snapManager.enableElementSnap( snapManager.elementSnapEnabledAppLevel() ); + snapManager.enableGridSnap( snapManager.gridSnapEnabledAppLevel() ); + } + }, + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Info for tool's handles + _activateOriginHandle: { value: false }, + _startOriginArray : {value : null }, + _origin: { value: null }, + _delta: { value: null }, + _startPoint: { value: [0, 0] }, + _matL : { value: Matrix.I(4) }, + _planeEq: { value: null }, + _dirVecL: { value: null }, + + // override in subclasses + _initializeToolHandles: { + value: function() { + if(!this._handles) + { + } + else + { + } + } + }, + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Info about objects being modified by the tool + // mode === 0 => x/y translation, mode === 1 => z translation + _mode : {value : 0 }, + _mouseSpeed: { value: 1 }, + + _target: { value: null }, + target: + { + get: function () { + return this._target; + }, + set: function (value) { + this._target = value; + if (value === null) + { + return; + } + + if (this._target.elementModel && this._target.elementModel.props3D) + { + // do nothing + } + else + { + console.warn("no props3D model"); +// if(!this._target.elementModel) +// { +// +// } +// var p3d = Montage.create(Properties3D).init(el); +// +// this._target.elementModel = Montage.create(ElementModel, { +// type: { value: tag}, +// selection: { value: selection}, +// controller: { value: ControllerFactory.getController(controller)}, +// props3D: { value: p3d} +// }); +// this._target.props3D = Object.create(Properties3D, {}); +// this._target.props3D.Init(this._target); + } + } + }, + + _startMat: { value: Matrix.I(4) }, + + _targets: { value: null }, + targets: + { + get: function () { + return this._targets; + }, + set: function (value) { + this._target = value; + if (value === null) + { + return; + } + } + }, + + _undoArray: { value: [] }, + + _initProps3D: + { + value: function(elt) + { + if (elt.elementModel && elt.elementModel.props3D) + { + // do nothing + } + else + { + console.warn("no props3D model"); +// elt.props3D = Object.create(Properties3D, {}); +// elt.props3D.Init(elt); + } + } + }, + + _updateTargets: { + value: function(addToUndoStack) { + // override in subclasses + } + }, + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Routines to run when tool is selected/deselected + Configure: { + value: function(wasSelected) { + if(wasSelected) { + this.eventManager.addEventListener("selectionChange", this, true); + this.application.ninja.stage._iframeContainer.addEventListener("scroll", this, false); + this._initializeToolHandles(); + this.captureSelectionDrawn(null); + this.eventManager.addEventListener( "toolOptionsChange", this, false); + this.eventManager.addEventListener( "toolDoubleClick", this, false); + NJevent("enableStageMove"); + } else { + this.eventManager.removeEventListener("selectionChange", this, true); + this.application.ninja.stage._iframeContainer.removeEventListener("scroll", this, false); + this._targets = null; + + // Clean up + NJevent("disableStageMove"); + + // clear the drag plane + snapManager.clearDragPlane(); + + // restore the snap settings + snapManager.enableSnapAlign( snapManager.snapAlignEnabledAppLevel() ); + snapManager.enableElementSnap( snapManager.elementSnapEnabledAppLevel() ); + snapManager.enableGridSnap( snapManager.gridSnapEnabledAppLevel() ); + this.eventManager.removeEventListener( "toolOptionsChange", this, false); + this.eventManager.removeEventListener( "toolDoubleClick", this, false); + } + } + }, + + captureSelectionChange: { + value: function(event){ + this.eventManager.addEventListener("selectionDrawn", this, true); + } + }, + + captureSelectionDrawn: { + value: function(event){ + this._targets = null; + + var len = this.application.ninja.selectedElements.length; + if(len) + { + if(len === 1) + { + this.target = this.application.ninja.selectedElements[0]._element; + drawUtils.addElement(this.target); + } + else + { + this.target = this.application.ninja.currentDocument.documentRoot; + } + this._updateTargets(); + } + else + { + this.target = null; + } + this.DrawHandles(); + + if(event) + { + this.eventManager.removeEventListener("selectionDrawn", this, true); + } + } + }, + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // User interaction routines + HandleLeftButtonDown: { + value: function(event) { + + var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, + new WebKitPoint(event.pageX, event.pageY)); + this.downPoint.x = point.x; + this.downPoint.y = point.y; + + if(this._handleMode === null) + { + // TODO - Special casing the double-click workflow for reseting tool handle's center for now. + if(!this._activateOriginHandle) + { + this.application.ninja.stage.drawNow = true; + this.doSelection(event); + } + } + + this.startDraw(event); + } + }, + + HandleMouseMove: { + value: function(event) { + if(this._escape) { + this._escape = false; + this.isDrawing = true; + } + + if(this.isDrawing) { + this._hasDraw = true; // Flag for position of element + this.doDraw(event); + } else { + this._showFeedbackOnMouseMove(event); +// if(this._canSnap) +// { +// this.doSnap(event); +// } + } + + this.DrawHandles(this._delta); + if(this._canSnap && this._isDrawing) + { + snapManager.drawLastHit(); + } + } + }, + + HandleLeftButtonUp: { + value: function(event) { + var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, + new WebKitPoint(event.pageX, event.pageY)); + + this.isDrawing = false; + this.application.ninja.stage.showSelectionBounds = true; + if(this._escape) { + this._escape = false; + return; + } + + if(this._hasDraw) + { + if(this._activateOriginHandle) + { + this._setTransformOrigin(true); + } + else if ( ((this.downPoint.x - point.x) !== 0) || + ((this.downPoint.y - point.y) !== 0) ) + { + this._updateTargets(true); + } + + this.endDraw(event); + this._hasDraw = false; + } + if(this._handleMode !== null) + { + this._handleMode = null; + this._delta = null; + this.DrawHandles(); + } + } + }, + + handleToolDoubleClick: { + value: function(event) { + if(!this._target) + { + return; + } + + this.Reset(); + } + }, + + Reset : { + value: function () { + // override in sub-classes + } + }, + + handleToolOptionsChange: { + value: function(event) { + this._handleToolOptionsChange(event); + } + }, + + _handleToolOptionsChange : { + value: function (event) { + // override in sub-classes + } + }, + + /** + * This function is for specifying custom feedback routine + * upon mouse over. + * For example, the drawing tools will add a glow when mousing + * over existing canvas elements to signal to the user that + * the drawing operation will act on the targeted canvas. + */ + _showFeedbackOnMouseMove : { + value: function (event) { + if(this._target && this._handles) + { + var len = this._handles.length; + var i = 0, + toolHandle, + c, + point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, + new WebKitPoint(event.pageX, event.pageY)); + for (i=0; i