diff options
Diffstat (limited to 'js/helper-classes/3D/snap-manager.js')
-rwxr-xr-x | js/helper-classes/3D/snap-manager.js | 179 |
1 files changed, 90 insertions, 89 deletions
diff --git a/js/helper-classes/3D/snap-manager.js b/js/helper-classes/3D/snap-manager.js index 6766ac7f..069c6022 100755 --- a/js/helper-classes/3D/snap-manager.js +++ b/js/helper-classes/3D/snap-manager.js | |||
@@ -21,7 +21,6 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
21 | /////////////////////////////////////////////////////////////////////// | 21 | /////////////////////////////////////////////////////////////////////// |
22 | // Instance variables | 22 | // Instance variables |
23 | /////////////////////////////////////////////////////////////////////// | 23 | /////////////////////////////////////////////////////////////////////// |
24 | currentStage: { value: null, writable: true }, | ||
25 | drawingCanvas: { value: null, writable: true}, | 24 | drawingCanvas: { value: null, writable: true}, |
26 | 25 | ||
27 | // we keep a stack of working planes to facilitate working on other planes temporarily | 26 | // we keep a stack of working planes to facilitate working on other planes temporarily |
@@ -84,14 +83,14 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
84 | popWorkingPlane : { value: function () { workingPlane = this._workingPlaneStack.pop(); return workingPlane; }}, | 83 | popWorkingPlane : { value: function () { workingPlane = this._workingPlaneStack.pop(); return workingPlane; }}, |
85 | 84 | ||
86 | getStageWidth : { value: function () { | 85 | getStageWidth : { value: function () { |
87 | return parseInt(this.currentStage.offsetWidth); | 86 | return parseInt(this.application.ninja.currentDocument.model.documentRoot.offsetWidth); |
88 | }}, | 87 | }}, |
89 | 88 | ||
90 | getStageHeight : { value: function () { | 89 | getStageHeight : { value: function () { |
91 | return parseInt(this.currentStage.offsetHeight); | 90 | return parseInt(this.application.ninja.currentDocument.model.documentRoot.offsetHeight); |
92 | }}, | 91 | }}, |
93 | 92 | ||
94 | getStage : { value: function() { return this.currentStage; }}, | 93 | getStage : { value: function() { return this.application.ninja.currentDocument.model.documentRoot; }}, |
95 | 94 | ||
96 | getGridVertexHitRad : { value: function() { return this._gridVertexHitRad; }}, | 95 | getGridVertexHitRad : { value: function() { return this._gridVertexHitRad; }}, |
97 | getGridEdgeHitRad : { value: function() { return this._gridEdgeHitRad; }}, | 96 | getGridEdgeHitRad : { value: function() { return this._gridEdgeHitRad; }}, |
@@ -130,10 +129,10 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
130 | 129 | ||
131 | bindSnap: { | 130 | bindSnap: { |
132 | value: function() { | 131 | value: function() { |
133 | this.addEventListener("change@appModel.snap", this.toggleSnap, false); | 132 | this.addPropertyChangeListener("appModel.snap", this.toggleSnap, false); |
134 | this.addEventListener("change@appModel.snapGrid", this.toggleSnapGrid, false); | 133 | this.addPropertyChangeListener("appModel.snapGrid", this.toggleSnapGrid, false); |
135 | this.addEventListener("change@appModel.snapObjects", this.toggleSnapObjects, false); | 134 | this.addPropertyChangeListener("appModel.snapObjects", this.toggleSnapObjects, false); |
136 | this.addEventListener("change@appModel.snapAlign", this.toggleSnapAlign, false); | 135 | this.addPropertyChangeListener("appModel.snapAlign", this.toggleSnapAlign, false); |
137 | } | 136 | } |
138 | }, | 137 | }, |
139 | 138 | ||
@@ -185,12 +184,6 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
185 | } | 184 | } |
186 | }, | 185 | }, |
187 | 186 | ||
188 | setCurrentStage: { | ||
189 | value: function(stage) { | ||
190 | this.currentStage = stage; | ||
191 | } | ||
192 | }, | ||
193 | |||
194 | snap : { | 187 | snap : { |
195 | value: function (xScreen, yScreen, snap3D, quadPt) | 188 | value: function (xScreen, yScreen, snap3D, quadPt) |
196 | { | 189 | { |
@@ -230,64 +223,22 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
230 | else | 223 | else |
231 | parentPt = [xScreen, yScreen, 0.0]; | 224 | parentPt = [xScreen, yScreen, 0.0]; |
232 | 225 | ||
233 | var eyePt = []; | 226 | if (!snap3D && this._hasDragPlane) |
234 | var vec = viewUtils.parentToChildVec(parentPt, stage, eyePt); | 227 | this.activateDragPlane(); |
235 | if (vec) | 228 | |
236 | { | 229 | var hitRec = this.snapToStage( parentPt, quadPt ); |
237 | // activate the drag working plane | 230 | |
238 | if (!snap3D && this.hasDragPlane()) | 231 | // try snapping to the 3D grid, or to the stage boundaries if the grid is not displayed |
239 | this.activateDragPlane(); | 232 | if (this.gridSnapEnabled()) |
240 | 233 | this.snapToGrid( hitRec ); | |
241 | // project to the working plane | 234 | |
242 | var currentWorkingPlane = workingPlane.slice(0); | 235 | // save the hit record |
243 | var wp = currentWorkingPlane.slice(0); | 236 | hitRecArray.push( hitRec ); |
244 | var mat = viewUtils.getMatrixFromElement(stage); | 237 | |
245 | wp = MathUtils.transformPlane(wp, mat); | 238 | // restore the original working plane |
246 | var projPt = MathUtils.vecIntersectPlane(eyePt, vec, wp); | 239 | if (!snap3D && this.hasDragPlane()) |
247 | if (projPt) | 240 | this.deactivateDragPlane(); |
248 | { | 241 | |
249 | // the local point gets stored in the coordinate space of the plane | ||
250 | var wpMat = drawUtils.getPlaneToWorldMatrix(currentWorkingPlane, MathUtils.getPointOnPlane(currentWorkingPlane)); | ||
251 | projPt[3] = 1.0; | ||
252 | //var planeToViewMat = mat.multiply(wpMat); | ||
253 | var planeToViewMat = glmat4.multiply(mat, wpMat, []); | ||
254 | //var viewToPlaneMat = planeToViewMat.inverse(); | ||
255 | var viewToPlaneMat = glmat4.inverse( planeToViewMat, [] ); | ||
256 | var planePt = projPt.slice(0); | ||
257 | planePt[3] = 1.0; | ||
258 | //planePt = viewToPlaneMat.multiply(planePt); | ||
259 | planePt = glmat4.multiplyVec3( viewToPlaneMat, planePt ); | ||
260 | |||
261 | // get the screen position of the projected point | ||
262 | viewUtils.setViewportObj(stage); | ||
263 | var offset = viewUtils.getElementOffset(stage); | ||
264 | offset[2] = 0; | ||
265 | var scrPt = viewUtils.viewToScreen(projPt); | ||
266 | //scrPt = scrPt.add(offset); | ||
267 | scrPt = vecUtils.vecAdd(3, scrPt, offset); | ||
268 | |||
269 | // create the hit record | ||
270 | var hitRec = Object.create(HitRecord);//new HitRecord(); | ||
271 | hitRec.setLocalPoint(planePt); | ||
272 | hitRec.setPlaneMatrix( wpMat ); | ||
273 | hitRec.setScreenPoint(scrPt); | ||
274 | hitRec.setPlane(currentWorkingPlane); | ||
275 | hitRec.setType( hitRec.SNAP_TYPE_STAGE ); | ||
276 | hitRec.setElt( stage ); | ||
277 | if (quadPt) hitRec.setUseQuadPoint( true ); | ||
278 | |||
279 | // try snapping to the 3D grid, or to the stage boundaries if the grid is not displayed | ||
280 | if (this.gridSnapEnabled()) | ||
281 | this.snapToGrid( hitRec ); | ||
282 | |||
283 | // save the hit record | ||
284 | hitRecArray.push( hitRec ); | ||
285 | |||
286 | // restore the original working plane | ||
287 | if (!snap3D && this.hasDragPlane()) | ||
288 | this.deactivateDragPlane(); | ||
289 | } | ||
290 | } | ||
291 | } //if (hitRecArray.length == 0) | 242 | } //if (hitRecArray.length == 0) |
292 | 243 | ||
293 | var rtnHit; | 244 | var rtnHit; |
@@ -312,6 +263,62 @@ var SnapManager = exports.SnapManager = Montage.create(Component, { | |||
312 | } | 263 | } |
313 | }, | 264 | }, |
314 | 265 | ||
266 | snapToStage: | ||
267 | { | ||
268 | value: function( scrPt, quadPt ) | ||
269 | { | ||
270 | var stage = this.getStage(); | ||
271 | var l2g = viewUtils.getLocalToGlobalMatrix( stage ); | ||
272 | var g2l = glmat4.inverse( l2g, [] ); | ||
273 | |||
274 | var pt0 = scrPt.slice(), pt1 = scrPt.slice(); | ||
275 | pt0[2] = 0.0; pt1[2] = 10; | ||
276 | |||
277 | var localPt0 = MathUtils.transformAndDivideHomogeneousPoint( pt0, g2l ), | ||
278 | localPt1 = MathUtils.transformAndDivideHomogeneousPoint( pt1, g2l ); | ||
279 | |||
280 | var stageWorldPt0 = viewUtils.localToStageWorld( localPt0, stage ), | ||
281 | stageWorldPt1 = viewUtils.localToStageWorld( localPt1, stage ); | ||
282 | var vec = vecUtils.vecSubtract( 3, stageWorldPt1, stageWorldPt0 ); | ||
283 | |||
284 | var ptOnWorkingPlane = MathUtils.vecIntersectPlane(stageWorldPt0, vec, workingPlane); | ||
285 | |||
286 | var wpMat = drawUtils.getPlaneToWorldMatrix(workingPlane, MathUtils.getPointOnPlane(workingPlane)), | ||
287 | wpMatInv = glmat4.inverse( wpMat, [] ); | ||
288 | var localPt = MathUtils.transformPoint( ptOnWorkingPlane, wpMatInv ); | ||
289 | |||
290 | // create the hit record | ||
291 | var hitRec = Object.create(HitRecord); | ||
292 | hitRec.setLocalPoint( localPt ); | ||
293 | hitRec.setPlaneMatrix( wpMat ); | ||
294 | hitRec.setScreenPoint(scrPt); | ||
295 | hitRec.setPlane(workingPlane); | ||
296 | hitRec.setType( hitRec.SNAP_TYPE_STAGE ); | ||
297 | hitRec.setElt( stage ); | ||
298 | if (quadPt) hitRec.setUseQuadPoint( true ); | ||
299 | |||
300 | // DEBUG CODE | ||
301 | // check that the point is on the working plane | ||
302 | var tmpStageWorldPt = hitRec.calculateStageWorldPoint(); | ||
303 | var err = vecUtils.vecDot(3, tmpStageWorldPt, workingPlane) + workingPlane[3]; | ||
304 | if (MathUtils.fpSign(err) !== 0) | ||
305 | console.log( "snapToStage (function) not on working plane: " + err ); | ||
306 | ////////////////////////////////////////////////////////////////////// | ||
307 | |||
308 | var calculatedScreenPt = hitRec.calculateScreenPoint(); | ||
309 | hitRec.setScreenPoint(calculatedScreenPt); | ||
310 | |||
311 | // DEBUG CODE | ||
312 | // check that the point is on the working plane | ||
313 | var err2 = vecUtils.vecDist(2, calculatedScreenPt, scrPt ); | ||
314 | if (MathUtils.fpSign(err2) !== 0) | ||
315 | console.log( "snapToStage (function) error in screen point: " + err2 ); | ||
316 | ////////////////////////////////////////////////////////////////////// | ||
317 | |||
318 | return hitRec; | ||
319 | } | ||
320 | }, | ||
321 | |||
315 | snapToGrid : { | 322 | snapToGrid : { |
316 | value: function( hitRec ) | 323 | value: function( hitRec ) |
317 | { | 324 |