diff options
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-x | js/tools/PenTool.js | 553 |
1 files changed, 323 insertions, 230 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 4a16a491..61a254ea 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -14,7 +14,7 @@ var ElementMediator = require("js/mediators/element-mediator").ElementMediator; | |||
14 | var TagTool = require("js/tools/TagTool").TagTool; | 14 | var TagTool = require("js/tools/TagTool").TagTool; |
15 | var ElementController = require("js/controllers/elements/element-controller").ElementController; | 15 | var ElementController = require("js/controllers/elements/element-controller").ElementController; |
16 | var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; | 16 | var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; |
17 | 17 | var ViewUtils = require("js/helper-classes/3D/view-utils").ViewUtils; | |
18 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; | 18 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; |
19 | var SubPath = require("js/lib/geom/sub-path").SubPath; | 19 | var SubPath = require("js/lib/geom/sub-path").SubPath; |
20 | 20 | ||
@@ -68,11 +68,14 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
68 | //the plane matrix for the first click...so the entire path is on the same plane | 68 | //the plane matrix for the first click...so the entire path is on the same plane |
69 | _penPlaneMat: { value: null, writable: true }, | 69 | _penPlaneMat: { value: null, writable: true }, |
70 | 70 | ||
71 | //the plane equation (in stage world space) for the current path being drawn | ||
72 | _dragPlane: {value: null, writable: true}, | ||
73 | |||
71 | //index of the anchor point that the user has hovered over | 74 | //index of the anchor point that the user has hovered over |
72 | _hoveredAnchorIndex: {value: -1, writable: true}, | 75 | _hoveredAnchorIndex: {value: -1, writable: true}, |
73 | 76 | ||
74 | //constants used for picking points --- NOTE: these should be user-settable parameters | 77 | //constants used for picking points --- NOTE: these should be user-settable parameters |
75 | _PICK_POINT_RADIUS: { value: 10, writable: false }, | 78 | _PICK_POINT_RADIUS: { value: 4, writable: false }, |
76 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, | 79 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, |
77 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, | 80 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, |
78 | _DISPLAY_SELECTED_ANCHOR_PREV_RADIUS: { value: 2, writable: false }, | 81 | _DISPLAY_SELECTED_ANCHOR_PREV_RADIUS: { value: 2, writable: false }, |
@@ -106,6 +109,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
106 | 109 | ||
107 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); | 110 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); |
108 | var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); | 111 | var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); |
112 | this._dragPlane = snapManager.getDragPlane(); | ||
109 | 113 | ||
110 | snapManager.enableElementSnap(elemSnap); | 114 | snapManager.enableElementSnap(elemSnap); |
111 | snapManager.enableGridSnap(gridSnap); | 115 | snapManager.enableGridSnap(gridSnap); |
@@ -214,6 +218,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
214 | if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { | 218 | if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { |
215 | this._penCanvas = null; | 219 | this._penCanvas = null; |
216 | this._penPlaneMat = null; | 220 | this._penPlaneMat = null; |
221 | this._dragPlane = null; | ||
217 | this._snapTarget = null; | 222 | this._snapTarget = null; |
218 | this._selectedSubpath = new SubPath(); | 223 | this._selectedSubpath = new SubPath(); |
219 | this._isNewPath = true; | 224 | this._isNewPath = true; |
@@ -278,8 +283,15 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
278 | this.application.ninja.stage.clearDrawingCanvas(); | 283 | this.application.ninja.stage.clearDrawingCanvas(); |
279 | this._hoveredAnchorIndex = -1; | 284 | this._hoveredAnchorIndex = -1; |
280 | 285 | ||
281 | //set the cursor to be the default cursor | 286 | //set the cursor to be the default cursor (depending on whether the selected subpath has any points yet) |
282 | this.application.ninja.stage.drawingCanvas.style.cursor = "auto"; | 287 | if (this._selectedSubpath && this._selectedSubpath.getNumAnchors()>0){ |
288 | this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; | ||
289 | "url('images/cursors/penCursors/Pen_.png') 5 1, default"; | ||
290 | } | ||
291 | else { | ||
292 | this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; | ||
293 | "url('images/cursors/penCursors/Pen_newPath.png') 5 1, default"; | ||
294 | } | ||
283 | 295 | ||
284 | if (this._isDrawing) { | 296 | if (this._isDrawing) { |
285 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); | 297 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); |
@@ -339,6 +351,10 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
339 | 351 | ||
340 | //make the subpath dirty so it will get re-drawn | 352 | //make the subpath dirty so it will get re-drawn |
341 | this._selectedSubpath.makeDirty(); | 353 | this._selectedSubpath.makeDirty(); |
354 | //this.DrawSubpathSVG(this._selectedSubpath); | ||
355 | } | ||
356 | //todo temp code only...remove this and uncomment the DrawSubpathSVG above | ||
357 | if (this._selectedSubpath){ | ||
342 | this.DrawSubpathSVG(this._selectedSubpath); | 358 | this.DrawSubpathSVG(this._selectedSubpath); |
343 | } | 359 | } |
344 | 360 | ||
@@ -348,15 +364,27 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
348 | 364 | ||
349 | var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); | 365 | var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); |
350 | if (currMousePos && this._selectedSubpath ){ | 366 | if (currMousePos && this._selectedSubpath ){ |
351 | var selAnchor = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); | 367 | var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); |
352 | if (selAnchor >=0) { | 368 | if (selAnchorRetCode[0] >=0) { |
353 | this._hoveredAnchorIndex = selAnchor; | 369 | this._hoveredAnchorIndex = selAnchorRetCode[0]; |
370 | var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1; | ||
371 | var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 5 1, default"; | ||
372 | if (this._selectedSubpath.getIsClosed()===false){ | ||
373 | if (this._entryEditMode === this.ENTRY_SELECT_PATH && !this._isPickedEndPointInSelectPathMode && (this._hoveredAnchorIndex===0 || this._hoveredAnchorIndex===lastAnchorIndex)){ | ||
374 | //if we're in SELECT_PATH mode, have not yet clicked on the end anchors, AND we hovered over one of the end anchors | ||
375 | cursor = "url('images/cursors/penCursors/Pen_append.png') 5 1, default"; | ||
376 | } else if ( this._selectedSubpath.getSelectedAnchorIndex()===lastAnchorIndex && this._hoveredAnchorIndex===0) { | ||
377 | //if we've selected the last anchor and hover over the first anchor | ||
378 | cursor = "url('images/cursors/penCursors/Pen_closePath.png') 5 1, default"; | ||
379 | } | ||
380 | } //if path is not closed | ||
381 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; | ||
354 | } else { | 382 | } else { |
355 | //detect if the current mouse position will hit the path | 383 | //detect if the current mouse position will hit the path (such that clicking here will insert a new anchor) |
356 | var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); | 384 | var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5); |
357 | if (pathHitTestData[0]!==-1){ | 385 | if (pathHitTestData[0]!==-1){ |
358 | //change the cursor | 386 | //change the cursor |
359 | var cursor = "url('images/cursors/penAdd.png') 10 10,default"; | 387 | var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; |
360 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; | 388 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; |
361 | } | 389 | } |
362 | } | 390 | } |
@@ -374,22 +402,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
374 | TranslateSelectedSubpathPerPenCanvas:{ | 402 | TranslateSelectedSubpathPerPenCanvas:{ |
375 | value: function() { | 403 | value: function() { |
376 | if (this._penCanvas!==null) { | 404 | if (this._penCanvas!==null) { |
377 | //obtain the 2D translation of the canvas due to the Selection tool...assuming this is called in Configure | 405 | this._selectedSubpath.translateSubpathPerCanvas(ElementMediator); |
378 | var penCanvasLeft = parseInt(ElementMediator.getProperty(this._penCanvas, "left"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "left")); | ||
379 | var penCanvasTop = parseInt(ElementMediator.getProperty(this._penCanvas, "top"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "top")); | ||
380 | var penCanvasWidth = parseInt(ElementMediator.getProperty(this._penCanvas, "width"));//this._penCanvas.width; | ||
381 | var penCanvasHeight = parseInt(ElementMediator.getProperty(this._penCanvas, "height"));//this._penCanvas.height; | ||
382 | var penCanvasOldX = penCanvasLeft + 0.5 * penCanvasWidth; | ||
383 | var penCanvasOldY = penCanvasTop + 0.5 * penCanvasHeight; | ||
384 | |||
385 | var translateCanvasX = penCanvasOldX - this._selectedSubpath.getCanvasX(); | ||
386 | var translateCanvasY = penCanvasOldY - this._selectedSubpath.getCanvasY(); | ||
387 | |||
388 | //update the canvasX and canvasY parameters for this subpath and also translate the subpath points (since they're stored in stage world space) | ||
389 | this._selectedSubpath.setCanvasX(translateCanvasX + this._selectedSubpath.getCanvasX()); | ||
390 | this._selectedSubpath.setCanvasY(translateCanvasY + this._selectedSubpath.getCanvasY()); | ||
391 | this._selectedSubpath.translateAnchors(translateCanvasX, translateCanvasY, 0); | ||
392 | this._selectedSubpath.createSamples(); //updates the bounding box | ||
393 | } | 406 | } |
394 | } | 407 | } |
395 | }, | 408 | }, |
@@ -397,22 +410,143 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
397 | ShowSelectedSubpath:{ | 410 | ShowSelectedSubpath:{ |
398 | value: function() { | 411 | value: function() { |
399 | if (this._selectedSubpath){ | 412 | if (this._selectedSubpath){ |
413 | if (!this._selectedSubpath.getPlaneMatrix()) { | ||
414 | this._selectedSubpath.setPlaneMatrix(this._penPlaneMat); | ||
415 | var planeMatInv = glmat4.inverse( this._penPlaneMat, [] ); | ||
416 | this._selectedSubpath.setPlaneMatrixInverse(planeMatInv); | ||
417 | this._selectedSubpath.setDragPlane(this._dragPlane); | ||
418 | } | ||
419 | |||
400 | this._selectedSubpath.createSamples(); //dirty bit is checked here | 420 | this._selectedSubpath.createSamples(); //dirty bit is checked here |
401 | var bboxMin = this._selectedSubpath.getBBoxMin(); | 421 | this._selectedSubpath.buildLocalCoord(); //local dirty bit is checked here |
402 | var bboxMax = this._selectedSubpath.getBBoxMax(); | 422 | |
423 | //build the width and height of this canvas by looking at local coordinates (X and Y needed only) | ||
424 | var bboxMin = this._selectedSubpath.getLocalBBoxMin(); | ||
425 | var bboxMax = this._selectedSubpath.getLocalBBoxMax(); | ||
403 | var bboxWidth = bboxMax[0] - bboxMin[0]; | 426 | var bboxWidth = bboxMax[0] - bboxMin[0]; |
404 | var bboxHeight = bboxMax[1] - bboxMin[1]; | 427 | var bboxHeight = bboxMax[1] - bboxMin[1]; |
405 | var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; | ||
406 | 428 | ||
407 | this._selectedSubpath.setCanvasX(bboxMid[0]); | 429 | //build the 3D position of the plane center of this canvas by looking at midpoint of the bounding box in stage world coords |
408 | this._selectedSubpath.setCanvasY(bboxMid[1]); | 430 | bboxMin = this._selectedSubpath.getBBoxMin(); |
431 | bboxMax = this._selectedSubpath.getBBoxMax(); | ||
432 | var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; | ||
409 | 433 | ||
410 | //call render shape with the bbox width and height | 434 | //call render shape with the bbox width and height |
411 | this.RenderShape(bboxWidth, bboxHeight, this._penPlaneMat, bboxMid, this._penCanvas); | 435 | this.RenderShape(bboxWidth, bboxHeight, bboxMid, this._penPlaneMat, this._penCanvas); |
412 | } | 436 | } |
413 | } | 437 | } |
414 | }, | 438 | }, |
415 | 439 | ||
440 | RenderShape: { | ||
441 | value: function (w, h, midPt, planeMat, canvas) { | ||
442 | if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | var left = Math.round(midPt[0] - 0.5 * w); | ||
447 | var top = Math.round(midPt[1] - 0.5 * h); | ||
448 | this._selectedSubpath.setPlaneCenter(midPt); | ||
449 | this._selectedSubpath.setCanvasLeft(left); | ||
450 | this._selectedSubpath.setCanvasTop(top); | ||
451 | |||
452 | if (!canvas) { | ||
453 | var newCanvas = null; | ||
454 | newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); | ||
455 | var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas); | ||
456 | ElementMediator.addElements(newCanvas, elementModel.data, false); | ||
457 | |||
458 | // create all the GL stuff | ||
459 | var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial); | ||
460 | //store a reference to this newly created canvas | ||
461 | this._penCanvas = newCanvas; | ||
462 | |||
463 | var subpath = this._selectedSubpath; //new GLSubpath(); | ||
464 | subpath.setWorld(world); | ||
465 | subpath.setCanvas(newCanvas); | ||
466 | |||
467 | world.addObject(subpath); | ||
468 | world.render(); | ||
469 | //TODO this will not work if there are multiple shapes in the same canvas | ||
470 | newCanvas.elementModel.shapeModel.GLGeomObj = subpath; | ||
471 |