From fc13ef1e806116bb7ece5bb06604fa4f5714a6ed Mon Sep 17 00:00:00 2001 From: Nivesh Rajbhandari Date: Thu, 19 Jul 2012 10:55:22 -0700 Subject: Squashed commit of the following: commit 0285afe3d4bd458a51f11241f13ea6ffdb0283ed Merge: 2f9f5e3 16d06ba Author: Nivesh Rajbhandari Date: Thu Jul 19 10:54:25 2012 -0700 Merge branch 'refs/heads/ninja-mqg734-master' into StageToolDrawingOptimizations commit 2f9f5e369eb96f6c81b5e4bcbe09b418825e2864 Author: Nivesh Rajbhandari Date: Wed Jul 18 17:15:19 2012 -0700 Fixed selection bounds not drawing in nested tags. Signed-off-by: Nivesh Rajbhandari commit b0a3507f9d27579ad511c69314a09136d7f7c6a0 Author: Nivesh Rajbhandari Date: Wed Jul 18 11:07:44 2012 -0700 Layout info needs to redraw if stage is updated. Signed-off-by: Nivesh Rajbhandari commit 63c5e0bf52c33706ba597cb69f7794e287bd0f06 Author: Nivesh Rajbhandari Date: Tue Jul 17 15:40:54 2012 -0700 Per feedback from QE, we are still going to draw tool feedback on each mouse move so the selection bounds are not out of sync with the elements. Signed-off-by: Nivesh Rajbhandari commit 0599a742092b985c4002977e501e3b457173f1d9 Author: Nivesh Rajbhandari Date: Tue Jul 17 15:28:25 2012 -0700 Fixed grid not drawing correctly when switching documents and when adding/removing elements. Signed-off-by: Nivesh Rajbhandari commit fd9410606ee6358910d65b2cb5f71812fd44a7c4 Author: Nivesh Rajbhandari Date: Tue Jul 17 11:36:09 2012 -0700 Updated drawing feedback to handle matrix 2d values entered via CSS Panel. Signed-off-by: Nivesh Rajbhandari commit 559c16c7ac8c9f40b94a011a6f932d4f97df66a7 Author: Nivesh Rajbhandari Date: Mon Jul 16 17:14:28 2012 -0700 IKNinja-751 - Selection boundary doesn't follow the transform applied in the CSS Panel. Signed-off-by: Nivesh Rajbhandari commit e2da5340159db5cd6f75bf6c9b7eb9cbf959e5cd Merge: 7cc5de3 5146f22 Author: Nivesh Rajbhandari Date: Mon Jul 16 15:36:28 2012 -0700 Merge branch 'refs/heads/ninja-mqg734-master' into StageToolDrawingOptimizations commit 7cc5de39e41b4220f53c91b15b0cf0ed53e0b0f6 Author: Nivesh Rajbhandari Date: Mon Jul 16 14:52:06 2012 -0700 Check if ownerDocument.defaultValue is null. Signed-off-by: Nivesh Rajbhandari commit 5ae97995a28a4b06fb7f8703eb8090ea16d88acd Merge: d17974d 0ede302 Author: Nivesh Rajbhandari Date: Mon Jul 16 09:27:22 2012 -0700 Merge branch 'refs/heads/ninja-mqg734-master' into StageToolDrawingOptimizations commit d17974d77273bb635311cb6466f4427cf4d9e5d4 Author: Nivesh Rajbhandari Date: Mon Jul 16 08:45:05 2012 -0700 Pass in selectedElements array directly to drawUtils when drawing selection bounds instead of creating a duplicate array. Signed-off-by: Nivesh Rajbhandari commit 0b1ea3144cb3e2c1d272f60da32423d0604ace3b Author: Nivesh Rajbhandari Date: Fri Jul 13 14:03:40 2012 -0700 Fixed line tool not drawing the width and height info. Signed-off-by: Nivesh Rajbhandari commit b9c70e8d9ae324aa21fa5490edc71d8503bcefbc Author: Nivesh Rajbhandari Date: Fri Jul 13 12:42:25 2012 -0700 Used cached offsetWidth and offsetHeight. Signed-off-by: Nivesh Rajbhandari commit 9e17ac7124745ba745014efe149b31dee4fe658f Author: Nivesh Rajbhandari Date: Thu Jul 12 16:25:41 2012 -0700 Converting tabs to spaces … again! Signed-off-by: Nivesh Rajbhandari commit 351726c951bb73c28f0e15ea1ab32e85cc735688 Author: Nivesh Rajbhandari Date: Thu Jul 12 16:14:31 2012 -0700 Tabs should be 4 spaces. Signed-off-by: Nivesh Rajbhandari commit 250c419aa2dbcb10f012817ee7039aca77cb2518 Merge: 3f8d61a 2880e1d Author: Nivesh Rajbhandari Date: Thu Jul 12 16:08:31 2012 -0700 Merge branch 'refs/heads/ninja-mqg734-master' into StageToolDrawingOptimizations commit 3f8d61a676da3992947ed9a2ed0e449780fcfbe0 Author: Nivesh Rajbhandari Date: Thu Jul 12 15:53:44 2012 -0700 Rotate tool was not working immediately after switching selection and selection bounds were not drawing after resizing canvases. Signed-off-by: Nivesh Rajbhandari commit e2e1f81e3b6917e1032e1b99b79c266937f3bb25 Author: Nivesh Rajbhandari Date: Thu Jul 12 12:15:59 2012 -0700 Single draw cycle for stage updates and tool drawings. Signed-off-by: Nivesh Rajbhandari commit 95a90b4c95ee3163c97bea317144366674e49ade Author: Nivesh Rajbhandari Date: Mon Jun 18 11:46:38 2012 -0700 Single draw cycle for the stage and layout. Signed-off-by: Nivesh Rajbhandari commit 21966b1515d80d2161a14e5a19bc66f3f49a92ce Author: Nivesh Rajbhandari Date: Fri Jun 15 13:33:14 2012 -0700 Cache element offsets, including offsetParent. Signed-off-by: Nivesh Rajbhandari commit 80c563c8ba06149691c6c1e754dd9a5e43bc7d4b Author: Nivesh Rajbhandari Date: Mon Jul 9 17:30:00 2012 -0700 Open materials editor popup next to PI button. Signed-off-by: Nivesh Rajbhandari Signed-off-by: Nivesh Rajbhandari --- js/controllers/styles-controller.js | 51 +- js/helper-classes/3D/draw-utils.js | 658 +++++++++++---------- js/helper-classes/3D/snap-manager.js | 4 +- js/helper-classes/3D/view-utils.js | 99 +++- .../materials-library-panel.js | 14 +- js/panels/Splitter.js | 2 + js/panels/css-panel/styles-view-delegate.js | 3 +- js/stage/layout.js | 58 +- js/stage/stage.reel/stage.js | 288 +++++---- js/tools/Rotate3DToolBase.js | 1 - js/tools/SelectionTool.js | 2 - js/tools/Translate3DToolBase.js | 1 - js/tools/modifier-tool-base.js | 3 - 13 files changed, 644 insertions(+), 540 deletions(-) (limited to 'js') diff --git a/js/controllers/styles-controller.js b/js/controllers/styles-controller.js index 89a389a4..b0db1b6a 100755 --- a/js/controllers/styles-controller.js +++ b/js/controllers/styles-controller.js @@ -1292,33 +1292,68 @@ var stylesController = exports.StylesController = Montage.create(Component, { ///// Get Matrix From Element ///// Returns the matrix from an element's -webkit-transform - //// TODO - This routine should eventually check for other transform styles, i.e., rotateX, translateZ, etc. getMatrixFromElement : { value: function(element, isStage) { isStage = false; var xformStr = this.getElementStyle(element, "-webkit-transform", true, isStage), - mat; + mat, + index1, + index2, + substr, + numArray, + nNums, + i; if (xformStr) { - var index1 = xformStr.indexOf( "matrix3d("); + // Check for 3d matrix + index1 = xformStr.indexOf( "matrix3d("); + // If style does not contain 'matrix3d', try computed matrix/matrix3d from rotateY, translateZ, etc. + if((index1 === -1) && element.ownerDocument.defaultView) { + xformStr = element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue("-webkit-transform"); + index1 = xformStr.indexOf( "matrix3d("); + } if (index1 >= 0) { index1 += 9; // do not include 'matrix3d(' - var index2 = xformStr.indexOf( ")", index1 ); + index2 = xformStr.indexOf( ")", index1 ); if (index2 >= 0) { - var substr = xformStr.substr( index1, (index2-index1)); + substr = xformStr.substr( index1, (index2-index1)); if (substr && (substr.length > 0)) { - var numArray = substr.split(','); - var nNums = numArray.length; + numArray = substr.split(','); + nNums = numArray.length; if (nNums == 16) { // gl-matrix wants row order mat = numArray; - for (var i=0; i<16; i++) { + for (i=0; i<16; i++) { mat[i] = Number( mat[i] ); } } } } + } else { + // Check for 2d matrix + index1 = xformStr.indexOf( "matrix("); + if (index1 >= 0) { + index1 += 7; // do not include 'matrix(' + index2 = xformStr.indexOf( ")", index1 ); + if (index2 >= 0) { + substr = xformStr.substr( index1, (index2-index1)); + if (substr && (substr.length > 0)) { + numArray = substr.split(','); + nNums = numArray.length; + if (nNums === 6) { + // gl-matrix wants row order + mat = Matrix.I(4); + mat[0] = Number(numArray[0]); + mat[1] = Number(numArray[1]); + mat[4] = Number(numArray[2]); + mat[5] = Number(numArray[3]); + mat[12] = Number(numArray[4]); + mat[13] = Number(numArray[5]); + } + } + } + } } } return mat; diff --git a/js/helper-classes/3D/draw-utils.js b/js/helper-classes/3D/draw-utils.js index 869de213..b59bbf39 100755 --- a/js/helper-classes/3D/draw-utils.js +++ b/js/helper-classes/3D/draw-utils.js @@ -42,7 +42,6 @@ var StageLine = require("js/helper-classes/3D/StageLine").StageLine; var DrawUtils = exports.DrawUtils = Montage.create(Component, { - /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// @@ -97,7 +96,7 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { _selectionCtr : {value: null, writable: true }, // Properties that require element planes to be updated - _updatePlaneProps : {value: ["matrix", "left", "top", "width", "height"], writable: false }, + _updatePlaneProps : {value: ["matrix", "left", "top", "width", "height", "border", "border-width", "border-style", "-webkit-transform"], writable: false }, _recalculateScrollOffsets : { value: false }, /////////////////////////////////////////////////////////////////////// @@ -106,33 +105,33 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { setDrawingSurfaceElement : { value: function( s ) { this._drawingSurfaceElt = s; if (s) this._drawingContext = s.getContext("2d"); }}, getDrawingSurfaceElement : { value: function() { return this._drawingSurfaceElt; }}, - getDrawingContext : { value: function() { return this._drawingContext; }}, + getDrawingContext : { value: function() { return this._drawingContext; }}, setSourceSpaceElement : { value: function(ss) { this._sourceSpaceElt = ss; }}, getSourceSpaceElement : { value: function() { return this._sourceSpaceElt; }}, getWorkingPlane : { value: function() { return this._workingPlane; }}, - setWorkingPlane : { value: function (wp) { this._workingPlane = wp; }}, + setWorkingPlane : { value: function (wp) { this._workingPlane = wp; }}, - getGridHorizontalSpacing : { value: function() { return this._gridHorizontalSpacing; }}, + getGridHorizontalSpacing : { value: function() { return this._gridHorizontalSpacing; }}, getGridVerticalSpacing : { value: function() { return this._gridVerticalSpacing; }}, getGridHorizontalLineCount : { value: function() { return this._gridHorizontalLineCount; }}, - getGridVerticalLineCount : { value: function() { return this._gridVerticalLineCount; }}, - getGridOrigin : { value: function() { return this._gridOrigin.slice(0); }}, + getGridVerticalLineCount : { value: function() { return this._gridVerticalLineCount; }}, + getGridOrigin : { value: function() { return this._gridOrigin.slice(0); }}, - isDrawingGrid : { value: function() { return this.drawXY || this.drawYZ || this.drawXZ; }}, - isDrawingElementNormal : { value: function() { return this.drawElementN }}, + isDrawingGrid : { value: function() { return this.drawXY || this.drawYZ || this.drawXZ; }}, + isDrawingElementNormal : { value: function() { return this.drawElementN }}, - getLineColor : { value: function() { return this._lineColor; }}, - setLineColor : { value: function( color ) { this._lineColor = color; }}, + getLineColor : { value: function() { return this._lineColor; }}, + setLineColor : { value: function( color ) { this._lineColor = color; }}, - getLineWidth : { value: function() { return this._drawingContext.lineWidth; }}, - setLineWidth : { value: function( w ) { this._drawingContext.lineWidth = w; }}, + getLineWidth : { value: function() { return this._drawingContext.lineWidth; }}, + setLineWidth : { value: function( w ) { this._drawingContext.lineWidth = w; }}, initialize: { value: function() { - this._gridOrigin = [0,0]; // 2D plane space point + this._gridOrigin = [0,0]; // 2D plane space point this.eventManager.addEventListener("elementAdded", this, false); this.eventManager.addEventListener("elementsRemoved", this, false); @@ -212,7 +211,12 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { this.addElement(elements); } - this.drawWorkingPlane(); + // Redraw stage only once after all addition is completed + var stage = this.application.ninja.stage; + stage.drawLayout = true; + stage.updatePlanes = true; + stage.draw3DInfo = true; + stage.needsDrawSelection = true; } }, @@ -229,7 +233,12 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { this.removeElement(elements); } - this.drawWorkingPlane(); + // Redraw stage only once after all deletion is completed + var stage = this.application.ninja.stage; + stage.drawLayout = true; + stage.updatePlanes = true; + stage.draw3DInfo = true; + stage.needsDrawSelection = true; } }, @@ -310,9 +319,20 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { plane, changed = false, elt, + eltModel, adjustStagePadding = !isChanging || (event.detail.data.prop !== "matrix"); for(var i=0; i < len; i++) { elt = els[i]; + eltModel = elt.elementModel; + eltModel.setProperty("offsetCache", false); + + if(eltModel.selection !== "body") { + if(isChanging) { + eltModel.props3D.matrix3d = null; + } else { + eltModel.props3D.init(elt, false); + } + } plane = elt.elementModel.props3D.elementPlane; if(plane) { plane.init(); @@ -353,8 +373,10 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { } if(!changed) { - this.drawWorkingPlane(); - this.draw3DCompass(); + // If we didn't already set userPaddingTop or userPaddingLeft, force stage to redraw + //this.snapManager._isCacheInvalid = true; +// stage.draw3DInfo = true; + stage.needsDraw = true; } // TODO - Remove this once all stage drawing is consolidated into a single draw cycle @@ -680,81 +702,82 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { { this.application.ninja.stage.clearGridCanvas(); this.drawStageOutline(); - if (!this.isDrawingGrid()) return; - - var saveContext = this.getDrawingSurfaceElement(); - this.setDrawingSurfaceElement(this.application.ninja.stage.gridCanvas); + if (this.isDrawingGrid()) { + var saveContext = this.getDrawingSurfaceElement(); + this.setDrawingSurfaceElement(this.application.ninja.stage.gridCanvas); - // 3 coordinate axes for the plane - var zAxis = [this._workingPlane[0], this._workingPlane[1], this._workingPlane[2]]; + // 3 coordinate axes for the plane + var zAxis = [this._workingPlane[0], this._workingPlane[1], this._workingPlane[2]]; - // get a point that lies on the plane - var ptOnPlane = MathUtils.getPointOnPlane(this._workingPlane); + // get a point that lies on the plane + var ptOnPlane = MathUtils.getPointOnPlane(this._workingPlane); - // define the grid parameters - var width = this.snapManager.getStageWidth(), - height = this.snapManager.getStageHeight(), - nLines = 10; + // define the grid parameters + var width = this.snapManager.getStageWidth(), + height = this.snapManager.getStageHeight(), + nLines = 10; - // get a matrix from working plane space to the world - var mat = this.getPlaneToWorldMatrix(zAxis, ptOnPlane); - var tMat = Matrix.Translation( [0.5*width, 0.5*height, 0] ); - //mat = tMat.multiply(mat); - glmat4.multiply( tMat, mat, mat); + // get a matrix from working plane space to the world + var mat = this.getPlaneToWorldMatrix(zAxis, ptOnPlane); + var tMat = Matrix.Translation( [0.5*width, 0.5*height, 0] ); + //mat = tMat.multiply(mat); + glmat4.multiply( tMat, mat, mat); - // the positioning of the grid may depend on the view direction. - var stage = this.snapManager.getStage(); - var viewMat = this.viewUtils.getMatrixFromElement(stage); - var viewDir = [viewMat[8], viewMat[9], viewMat[10]]; + // the positioning of the grid may depend on the view direction. + var stage = this.snapManager.getStage(); + var viewMat = this.viewUtils.getMatrixFromElement(stage); + var viewDir = [viewMat[8], viewMat[9], viewMat[10]]; - var dx, dy, delta, pt0, pt1; - dx = this._gridVerticalSpacing; - dy = this._gridHorizontalSpacing; - nLines = Math.floor(width / dx) + 1; - if (MathUtils.fpCmp(dx*nLines,width) == 0) nLines--; + var dx, dy, delta, pt0, pt1; + dx = this._gridVerticalSpacing; + dy = this._gridHorizontalSpacing; + nLines = Math.floor(width / dx) + 1; + if (MathUtils.fpCmp(dx*nLines,width) == 0) nLines--; - var saveColor = this._lineColor; - var saveLineWidth = this._drawingContext.lineWidth; + var saveColor = this._lineColor; + var saveLineWidth = this._drawingContext.lineWidth; - // reset the line cache - this._gridLineArray = new Array(); + // reset the line cache + this._gridLineArray = new Array(); - if (this.drawXY) this._lineColor = "red"; - if (this.drawYZ) this._lineColor = "green"; - if (this.drawXZ) this._lineColor = "blue"; - this._drawingContext.lineWidth = 0.25; + if (this.drawXY) this._lineColor = "red"; + if (this.drawYZ) this._lineColor = "green"; + if (this.drawXZ) this._lineColor = "blue"; + this._drawingContext.lineWidth = 0.25; - // get the two endpoints of the first line with constant X - pt0 = [-width / 2.0, height / 2.0, 0]; - pt1 = [-width / 2.0, -height / 2.0, 0]; - delta = [dx, 0, 0]; + // get the two endpoints of the first line with constant X + pt0 = [-width / 2.0, height / 2.0, 0]; + pt1 = [-width / 2.0, -height / 2.0, 0]; + delta = [dx, 0, 0]; - this._gridVerticalLineCount = nLines; - this._gridOrigin = pt1.slice(0); + this._gridVerticalLineCount = nLines; + this._gridOrigin = pt1.slice(0); - // draw the lines with constant X - this.drawGridLines(pt0, pt1, delta, mat, nLines); + // draw the lines with constant X + this.drawGridLines(pt0, pt1, delta, mat, nLines); - // get the two endpoints of the first line with constant Y - pt0 = [-width / 2.0, -height / 2.0, 0]; - pt1 = [width / 2.0, -height / 2.0, 0]; + // get the two endpoints of the first line with constant Y + pt0 = [-width / 2.0, -height / 2.0, 0]; + pt1 = [width / 2.0, -height / 2.0, 0]; - delta = [0, dy, 0]; - nLines = Math.floor(height / dy) + 1; - if (MathUtils.fpCmp(dy*nLines,height) == 0) nLines--; + delta = [0, dy, 0]; + nLines = Math.floor(height / dy) + 1; + if (MathUtils.fpCmp(dy*nLines,height) == 0) nLines--; - this._gridHorizontalLineCount = nLines; + this._gridHorizontalLineCount = nLines; - // draw the lines with constant Y - this.drawGridLines(pt0, pt1, delta, mat, nLines); + // draw the lines with constant Y + this.drawGridLines(pt0, pt1, delta, mat, nLines); - this._lineColor = saveColor; - this._drawingContext.lineWidth = saveLineWidth; + this._lineColor = saveColor; + this._drawingContext.lineWidth = saveLineWidth; - // draw the lines - this.redrawGridLines(); + // draw the lines + this.redrawGridLines(); - this.setDrawingSurfaceElement(saveContext); + this.setDrawingSurfaceElement(saveContext); + } + this.draw3DCompass(); } }, @@ -830,7 +853,7 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { var obj = this._stateArray.pop(); this._lineColor = obj._lineColor; this._drawingContext.lineWidth = obj._lineWidth; - this._drawingContext.strokeStyle = obj._lineColor; + this._drawingContext.strokeStyle = obj._lineColor; } }, @@ -859,8 +882,47 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { } }, + /** + * Draws selection highlight and reg. point for a given element + */ + drawElementBoundingBox: { + value: function(elt, context, stageInfo) { + this.viewUtils.pushViewportObj( elt ); + var bounds3D = this.viewUtils.getElementViewBounds3D( elt ); + + var tmpMat = this.viewUtils.getLocalToGlobalMatrix( elt ); + for (var j=0; j<4; j++) { + var localPt = bounds3D[j]; + var tmpPt = this.viewUtils.localToGlobal2(localPt, tmpMat); + + if(stageInfo) { + tmpPt = vecUtils.vecScale(3, tmpPt, stageInfo.zoomFactor); + tmpPt[0] += stageInfo.scrollLeft; + tmpPt[1] += stageInfo.scrollTop; + } + bounds3D[j] = tmpPt; + } + this.viewUtils.popViewportObj(); + + // draw it + context.beginPath(); + context.moveTo( bounds3D[3][0] + 0.5 , bounds3D[3][1] - 0.5 ); + + // This more granular approach lets us specify different gaps for the selection around the element + context.lineTo( bounds3D[0][0] - 0.5 , bounds3D[0][1] - 0.5 ); + context.lineTo( bounds3D[1][0] - 0.5 , bounds3D[1][1] + 0.5 ); + context.lineTo( bounds3D[2][0] + 0.5 , bounds3D[2][1] + 0.5 ); + context.lineTo( bounds3D[3][0] + 0.5 , bounds3D[3][1] + 0.5 ); + + context.closePath(); + context.stroke(); + + return bounds3D; + } + }, + drawSelectionBounds : { - value: function( eltArray ) { + value: function(eltArray, drawSelectionCube) { this._selectionCtr = null; var len = eltArray.length, i, @@ -870,50 +932,40 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { pt, tmpPt, ssMat, - elt; - + ssMatInv, + elt, + dir, + ctr, + stageInfo, + stageComponent = this.application.ninja.stage, + context; + if (len === 0) return; - var context = this._drawingContext; - if (!context) return; - + context = stageComponent.context; + if(!context) return; // TODO - Get values from app settings context.strokeStyle = "#46a1ff"; - context.lineWidth = 2; + context.lineWidth = 1; + + // for drawing, we need scrollLeft, scrollTop, and zoom factor from the stage + var zoomFactor = stageComponent.zoomFactor; + if(zoomFactor !== 1) { + stageInfo = {zoomFactor: zoomFactor, scrollLeft: stageComponent._scrollLeft*(zoomFactor - 1), scrollTop: stageComponent._scrollTop*(zoomFactor - 1)}; + } // handle the single element case // TODO - Currently, the stage draws its own selection bounds for single selection case if (len === 1) { - // single selection case - //console.log( "single selection" ); - +// console.log( "single selection" ); elt = eltArray[0]; + bounds3D = this.drawElementBoundingBox(elt, context, stageInfo); + this._selectionCtr = [0,0,0]; + dir = vecUtils.vecSubtract(2, bounds3D[1], bounds3D[3]); + ctr = vecUtils.vecNormalize(2, dir, vecUtils.vecDist(2, bounds3D[1], bounds3D[3])/2); - this.viewUtils.pushViewportObj( elt ); - - // get the element bounds in world space - bounds3D = this.viewUtils.getElementViewBounds3D( elt ); - for (j=0; j<4; j++) { - bounds3D[j] = this.viewUtils.localToGlobal( bounds3D[j], elt ); - } - - // draw it - context.beginPath(); - //VV - context.strokeStyle = "#46a1ff"; - context.lineWidth = 2.0; - - context.moveTo( bounds3D[3][0] , bounds3D[3][1] ); - for (var v=0; v<4; v++) { - context.lineTo( bounds3D[v][0] , bounds3D[v][1] ); - } - context.closePath(); - context.stroke(); - - this._selectionCtr = MathUtils.getCenterFromBounds(3, bounds3D); -// console.log("selection center, single elt case - ", this._selectionCtr); - - this.viewUtils.popViewportObj(); + this._selectionCtr[0] += ctr[0] - this.application.ninja.stage.userContentLeft; + this._selectionCtr[1] += ctr[1] - this.application.ninja.stage.userContentTop; } else { @@ -952,7 +1004,7 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { if (MathUtils.fpCmp(dot, 1) != 0) flat = false; } -// console.log( "drawSelectionBounds, flat: " + flat ); +// console.log( "drawSelectionBounds, flat: " + flat ); // if all the elements share the same plane, draw the 2D rectangle if (flat) @@ -963,228 +1015,226 @@ var DrawUtils = exports.DrawUtils = Montage.create(Component, { { elt = eltArray[i]; - // get the element bounds in 'plane' space - bounds = this.viewUtils.getElementViewBounds3D( elt ); - ssMat = this.viewUtils.getLocalToGlobalMatrix( elt ); - for (j=0; j<4; j++) - { - var localPt = bounds[j]; - tmpPt = this.viewUtils.localToGlobal2(localPt, ssMat); - pt = tmpPt; + bounds = this.drawElementBoundingBox(elt, context, stageInfo); - if (!rect) + if(drawSelectionCube) { + for (j=0; j<4; j++) { - rect = Object.create(Rectangle, {}); - rect.setToPoint( pt ) - } - else - { - rect.unionPoint( pt ); + pt = bounds[j]; + if (!rect) + { + rect = Object.create(Rectangle, {}); + rect.setToPoint( pt ) + } + else + { + rect.unionPoint( pt ); + } } } } - // draw the rectangle - context.beginPath(); + if(rect) { + context.lineWidth = 2; + // draw the multi-selection rectangle + context.beginPath(); - pt = MathUtils.makeDimension3(rect.getPoint(3)); + pt = MathUtils.makeDimension3(rect.getPoint(3)); - bounds3D = [[0,0], [0,0], [0,0], [0,0]]; - this._selectionCtr = pt.slice(0); + bounds3D = [[0,0], [0,0], [0,0], [0,0]]; + this._selectionCtr = pt.slice(0); - context.moveTo( pt[0], pt[1] ); - for (i=0; i<4; i++) - { - pt = rect.getPoint(i); - context.lineTo( pt[0], pt[1] ); - bounds3D[i] = pt.slice(0); - } - context.closePath(); - context.stroke(); + context.moveTo( pt[0], pt[1] ); + for (i=0; i<4; i++) { + pt = rect.getPoint(i); + context.lineTo( pt[0], pt[1] ); + bounds3D[i] = pt.slice(0); + } + context.closePath(); + context.stroke(); - var dir = vecUtils.vecSubtract(2, bounds3D[1], bounds3D[3]); - var ctr = vecUtils.vecNormalize(2, dir, vecUtils.vecDist(2, bounds3D[1], bounds3D[3])/2); + dir = vecUtils.vecSubtract(2, bounds3D[1], bounds3D[3]); + ctr = vecUtils.vecNormalize(2, dir, vecUtils.vecDist(2, bounds3D[1], bounds3D[3])/2); - this._selectionCtr[0] += ctr[0] - this.application.ninja.stage.userContentLeft; - this._selectionCtr[1] += ctr[1] - this.application.ninja.stage.userContentTop; + this._selectionCtr[0] += ctr[0] - this.application.ninja.stage.userContentLeft; + this._selectionCtr[1] += ctr[1] - this.application.ninja.stage.userContentTop; + } } else { - var minPt, maxPt; - - // we set the root to "the world". - var saveRoot = this.viewUtils.getRootElement(); - this.viewUtils.setRootElement( this.viewUtils.getStageElement() ); - ssMat = this.viewUtils.getLocalToGlobalMatrix( this._sourceSpaceElt ); - - for (i=0; i maxPt[0]) maxPt[0] = x; - - if (y < minPt[1]) minPt[1] = y; - if (y > maxPt[1]) maxPt[1] = y; - - if (z < minPt[2]) minPt[2] = z; - if (z > maxPt[2]) maxPt[2] = z; + if(drawSelectionCube) { + var minPt, maxPt, x, y, z, + saveRoot = this.viewUtils.getRootElement(); + + // we set the root to "the world". + this.viewUtils.setRootElement( this.viewUtils.getStageElement() ); + ssMat = this.viewUtils.getLocalToGlobalMatrix( this._sourceSpaceElt ); // stageToGlobal + ssMatInv = glmat4.inverse(ssMat, []); // globalToStageWorld + this.viewUtils.setRootElement( saveRoot ); + + for (i=0; i maxPt[0]) maxPt[0] = x; + + if (y < minPt[1]) minPt[1] = y; + if (y > maxPt[1]) maxPt[1] = y; + + if (z < minPt[2]) minPt[2] = z; + if (z > maxPt[2]) maxPt[2] = z; + } } } - } - // restore the root ID - this.viewUtils.setRootElement (saveRoot ); - - context.beginPath(); - - var x0 = minPt[0], y0 = minPt[1], z0 = minPt[2], - x1 = maxPt[0], y1 = maxPt[1], z1 = maxPt[2]; - - this._selectionCtr = [x0, y0, z0]; - this._selectionCtr[0] += (x1-x0)/2; - this._selectionCtr[1] += (y1-y0)/2; - this._selectionCtr[2] += (z1-z0)/2; - - // get the 8 corners of the parallelpiped in world space - var wc = new Array(); // wc == world cube - wc.push( this.viewUtils.localToGlobal2( [x0,y0,z1], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x0,y1,z1], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x1,y1,z1], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x1,y0,z1], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x0,y0,z0], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x0,y1,z0], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x1,y1,z0], ssMat ) ); - wc.push( this.viewUtils.localToGlobal2( [x1,y0,z0], ssMat ) ); - - // determine the signs of the normals of the faces relative to the view direction. - var front = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[2],wc[1]), vecUtils.vecSubtract(3,wc[0],wc[1]))[2] ), - right = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[6],wc[2]), vecUtils.vecSubtract(3,wc[3],wc[2]))[2] ), - back = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[5],wc[6]), vecUtils.vecSubtract(3,wc[7],wc[6]))[2] ), - left = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[1],wc[5]), vecUtils.vecSubtract(3,wc[4],wc[5]))[2] ), - top = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[3],wc[0]), vecUtils.vecSubtract(3,wc[4],wc[0]))[2] ), - bottom = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[5],wc[1]), vecUtils.vecSubtract(3,wc[2],wc[1]))[2] ); - - // draw the side faces - var p; - - //context.strokeStyle = ((front > 0) || (right > 0)) ? dark : light; context.beginPath(); - if ((front > 0) || (right > 0)) { context.beginPath(); - p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + var x0 = minPt[0], y0 = minPt[1], z0 = minPt[2], + x1 = maxPt[0], y1 = maxPt[1], z1 = maxPt[2]; + + var stageWorldCtr = [ 0.5*(x0 + x1), 0.5*(y0 + y1), 0.5*(z0 + z1) ]; + this._selectionCtr = MathUtils.transformAndDivideHomogeneousPoint( stageWorldCtr, ssMat ); + + // get the 8 corners of the parallelpiped in world space + var wc = new Array(); // wc == world cube + wc.push( this.viewUtils.localToGlobal2( [x0,y0,z1], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x0,y1,z1], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x1,y1,z1], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x1,y0,z1], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x0,y0,z0], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x0,y1,z0], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x1,y1,z0], ssMat ) ); + wc.push( this.viewUtils.localToGlobal2( [x1,y0,z0], ssMat ) ); + + // determine the signs of the normals of the faces relative to the view direction. + var front = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[2],wc[1]), vecUtils.vecSubtract(3,wc[0],wc[1]))[2] ), + right = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[6],wc[2]), vecUtils.vecSubtract(3,wc[3],wc[2]))[2] ), + back = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[5],wc[6]), vecUtils.vecSubtract(3,wc[7],wc[6]))[2] ), + left = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[1],wc[5]), vecUtils.vecSubtract(3,wc[4],wc[5]))[2] ), + top = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[3],wc[0]), vecUtils.vecSubtract(3,wc[4],wc[0]))[2] ), + bottom = -MathUtils.fpSign( vecUtils.vecCross(3, vecUtils.vecSubtract(3,wc[5],wc[1]), vecUtils.vecSubtract(3,wc[2],wc[1]))[2] ); + + // draw the side faces + var p; + + //context.strokeStyle = ((front > 0) || (right > 0)) ? dark : light; context.beginPath(); + if ((front > 0) || (right > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((right > 0) || (back > 0)) ? dark : light; context.beginPath(); - if ((right > 0) || (back > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((right > 0) || (back > 0)) ? dark : light; context.beginPath(); + if ((right > 0) || (back > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((back > 0) || (left > 0)) ? dark : light; context.beginPath(); - if ((back > 0) || (left > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((back > 0) || (left > 0)) ? dark : light; context.beginPath(); + if ((back > 0) || (left > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((left > 0) || (front > 0)) ? dark : light; context.beginPath(); - if ((left > 0) || (front > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((left > 0) || (front > 0)) ? dark : light; context.beginPath(); + if ((left > 0) || (front > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - // draw the top and bottom faces - //context.strokeStyle = ((front > 0) || (top > 0)) ? dark : light; context.beginPath(); - if ((front > 0) || (top > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + // draw the top and bottom faces + //context.strokeStyle = ((front > 0) || (top > 0)) ? dark : light; context.beginPath(); + if ((front > 0) || (top > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((top > 0) || (back > 0)) ? dark : light; context.beginPath(); - if ((top > 0) || (back > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((top > 0) || (back > 0)) ? dark : light; context.beginPath(); + if ((top > 0) || (back > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((back > 0) || (bottom > 0)) ? dark : light; context.beginPath(); - if ((back > 0) || (bottom > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((back > 0) || (bottom > 0)) ? dark : light; context.beginPath(); + if ((back > 0) || (bottom > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((bottom > 0) || (front > 0)) ? dark : light; context.beginPath(); - if ((bottom > 0) || (front > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((bottom > 0) || (front > 0)) ? dark : light; context.beginPath(); + if ((bottom > 0) || (front > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - // and the remaining lines - varying Z - if ((top > 0) || (right > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + // and the remaining lines - varying Z + if ((top > 0) || (right > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x1, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((right > 0) || (bottom > 0)) ? dark : light; context.beginPath(); - if ((right > 0) || (bottom > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((right > 0) || (bottom > 0)) ? dark : light; context.beginPath(); + if ((right > 0) || (bottom > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x1, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x1, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((bottom > 0) || (left > 0)) ? dark : light; context.beginPath(); - if ((bottom > 0) || (left > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); - } + //context.strokeStyle = ((bottom > 0) || (left > 0)) ? dark : light; context.beginPath(); + if ((bottom > 0) || (left > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y1, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x0, y1, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } - //context.strokeStyle = ((left > 0) || (top > 0)) ? dark : light; context.beginPath(); - if ((left > 0) || (top > 0)) { - context.beginPath(); - p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); - p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); - context.closePath(); context.stroke(); + //context.strokeStyle = ((left > 0) || (top > 0)) ? dark : light; context.beginPath(); + if ((left > 0) || (top > 0)) { + context.beginPath(); + p = this.viewUtils.localToGlobal2( [x0, y0, z0], ssMat ); context.moveTo( p[0], p[1] ); + p = this.viewUtils.localToGlobal2( [x0, y0, z1], ssMat ); context.lineTo( p[0], p[1] ); + context.closePath(); context.stroke(); + } + } else { + for (i=0; i