diff options
author | Pushkar Joshi | 2012-04-10 14:18:02 -0700 |
---|---|---|
committer | Pushkar Joshi | 2012-04-10 14:18:02 -0700 |
commit | 7fed1940bb4f3a333cef92fd51787a29e6dd787b (patch) | |
tree | b7d5298604e8e1d323c51b2729f1f98daea31e6a /js/tools | |
parent | dae3041e6b8269da3d593a44c09e2288bb434a02 (diff) | |
download | ninja-7fed1940bb4f3a333cef92fd51787a29e6dd787b.tar.gz |
compute and store local coordinates for all anchor points and their control handles separately, AND more hit testing with local coordinates
Diffstat (limited to 'js/tools')
-rwxr-xr-x | js/tools/PenTool.js | 76 |
1 files changed, 37 insertions, 39 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 6c016cab..cd15b36b 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -57,7 +57,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
57 | _isPickedEndPointInSelectPathMode: {value: false, writable: true}, | 57 | _isPickedEndPointInSelectPathMode: {value: false, writable: true}, |
58 | 58 | ||
59 | //when the user wants to place a selected anchor point on top of another point, this is the target where the point will be placed | 59 | //when the user wants to place a selected anchor point on top of another point, this is the target where the point will be placed |
60 | _snapTarget: { value: null, writable: true }, | 60 | _snapTargetIndex: { value: -1, writable: true }, |
61 | 61 | ||
62 | //whether or not we're using webgl for drawing | 62 | //whether or not we're using webgl for drawing |
63 | _useWebGL: {value: false, writable: false }, | 63 | _useWebGL: {value: false, writable: false }, |
@@ -210,7 +210,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
210 | //setting the selection mode to NONE will effectively add a new anchor point at the click location and also give us snapping | 210 | //setting the selection mode to NONE will effectively add a new anchor point at the click location and also give us snapping |
211 | whichPoint = this._selectedSubpath.SEL_NONE; | 211 | whichPoint = this._selectedSubpath.SEL_NONE; |
212 | //set the snap target in case the mouse move handler doesn't get called | 212 | //set the snap target in case the mouse move handler doesn't get called |
213 | this._snapTarget = this._selectedSubpath.getAnchor(0); | 213 | this._snapTargetIndex = 0; |
214 | } | 214 | } |
215 | } | 215 | } |
216 | //check if the clicked location is close to prev and next of the selected anchor point..if so select that anchor, set mode to PREV or NEXT and do nothing else | 216 | //check if the clicked location is close to prev and next of the selected anchor point..if so select that anchor, set mode to PREV or NEXT and do nothing else |
@@ -240,7 +240,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
240 | this._penCanvas = null; | 240 | this._penCanvas = null; |
241 | this._penPlaneMat = null; | 241 | this._penPlaneMat = null; |
242 | this._dragPlane = null; | 242 | this._dragPlane = null; |
243 | this._snapTarget = null; | 243 | this._snapTargetIndex = -1; |
244 | this._selectedSubpath = new SubPath(); | 244 | this._selectedSubpath = new SubPath(); |
245 | this._isNewPath = true; | 245 | this._isNewPath = true; |
246 | } | 246 | } |
@@ -355,7 +355,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
355 | } | 355 | } |
356 | 356 | ||
357 | //snapping...check if the new location of the anchor point is close to another anchor point | 357 | //snapping...check if the new location of the anchor point is close to another anchor point |
358 | this._snapTarget = null; | 358 | this._snapTargetIndex = -1; |
359 | var numAnchors = this._selectedSubpath.getNumAnchors(); | 359 | var numAnchors = this._selectedSubpath.getNumAnchors(); |
360 | for (var i = 0; i < numAnchors; i++) { | 360 | for (var i = 0; i < numAnchors; i++) { |
361 | //check if the selected anchor is close to any other anchors | 361 | //check if the selected anchor is close to any other anchors |
@@ -365,7 +365,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
365 | var distSq = currAnchor.getDistanceSq(selX, selY, selZ); | 365 | var distSq = currAnchor.getDistanceSq(selX, selY, selZ); |
366 | if (distSq < this._PICK_POINT_RADIUS * this._PICK_POINT_RADIUS) { | 366 | if (distSq < this._PICK_POINT_RADIUS * this._PICK_POINT_RADIUS) { |
367 | //set the snap target to the location of the first close-enough anchor | 367 | //set the snap target to the location of the first close-enough anchor |
368 | this._snapTarget = currAnchor; | 368 | this._snapTargetIndex = i; |
369 | break; | 369 | break; |
370 | } | 370 | } |
371 | } | 371 | } |
@@ -413,7 +413,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
413 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; | 413 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; |
414 | } else { | 414 | } else { |
415 | //detect if the current mouse position will hit the path (such that clicking here will insert a new anchor) | 415 | //detect if the current mouse position will hit the path (such that clicking here will insert a new anchor) |
416 | var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5); | 416 | var pathHitTestData = this._selectedSubpath.pathSamplesLocalHitTest(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS*0.5); |
417 | if (pathHitTestData[0]!==-1){ | 417 | if (pathHitTestData[0]!==-1){ |
418 | //change the cursor | 418 | //change the cursor |
419 | var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; | 419 | var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; |
@@ -543,11 +543,6 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
543 | h = Math.round(h); | 543 | h = Math.round(h); |
544 | ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; | 544 | ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; |
545 | ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; | 545 | ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; |
546 | |||
547 | //var bboxMid = this._selectedSubpath.getLocalBBoxMidInStageWorld(); | ||
548 | //left = Math.round(bboxMid[0] - 0.5 * w); | ||
549 | //top = Math.round(bboxMid[1] - 0.5 * h); | ||
550 | |||
551 | ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); | 546 | ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); |
552 | ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); | 547 | ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); |
553 | 548 | ||
@@ -590,9 +585,10 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
590 | } | 585 | } |
591 | 586 | ||
592 | //snapping...if there was a snapTarget and a selected anchor, move the anchor to the snap target | 587 | //snapping...if there was a snapTarget and a selected anchor, move the anchor to the snap target |
593 | if (this._snapTarget !== null && this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex() !== -1) { | 588 | if (this._snapTargetIndex !== -1 && this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex() !== -1) { |
594 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); | 589 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); |
595 | selAnchor.setPos(this._snapTarget.getPosX(), this._snapTarget.getPosY(), this._snapTarget.getPosZ()); | 590 | var snapAnchor = this._selectedSubpath.getAnchor(this._snapTargetIndex); |
591 | selAnchor.setPos(snapAnchor.getPosX(), snapAnchor.getPosY(), snapAnchor.getPosZ()); | ||
596 | this._selectedSubpath.makeDirty(); | 592 | this._selectedSubpath.makeDirty(); |
597 | 593 | ||
598 | //if the first or last anchor point were snapped for an open path, check if the first and last anchor point are at the same position | 594 | //if the first or last anchor point were snapped for an open path, check if the first and last anchor point are at the same position |
@@ -600,7 +596,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
600 | var lastAnchorIndex = this._selectedSubpath.getNumAnchors() - 1; | 596 | var lastAnchorIndex = this._selectedSubpath.getNumAnchors() - 1; |
601 | var firstAnchor = this._selectedSubpath.getAnchor(0); | 597 | var firstAnchor = this._selectedSubpath.getAnchor(0); |
602 | var lastAnchor = this._selectedSubpath.getAnchor(lastAnchorIndex); | 598 | var lastAnchor = this._selectedSubpath.getAnchor(lastAnchorIndex); |
603 | if ((this._selectedSubpath.getSelectedAnchorIndex() === 0 && this._snapTarget === lastAnchor) || (this._selectedSubpath.getSelectedAnchorIndex() === lastAnchorIndex && this._snapTarget === firstAnchor)) { | 599 | if ((this._selectedSubpath.getSelectedAnchorIndex() === 0 && this._snapTargetIndex === lastAnchorIndex) || (this._selectedSubpath.getSelectedAnchorIndex() === lastAnchorIndex && this._snapTargetIndex === 0)) { |
604 | this._selectedSubpath.setIsClosed(true); | 600 | this._selectedSubpath.setIsClosed(true); |
605 | //set the prev of the first anchor to the be prev of the last anchor | 601 | //set the prev of the first anchor to the be prev of the last anchor |
606 | firstAnchor.setPrevPos(lastAnchor.getPrevX(), lastAnchor.getPrevY(), lastAnchor.getPrevZ()); | 602 | firstAnchor.setPrevPos(lastAnchor.getPrevX(), lastAnchor.getPrevY(), lastAnchor.getPrevZ()); |
@@ -616,7 +612,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
616 | } | 612 | } |
617 | } | 613 | } |
618 | } | 614 | } |
619 | this._snapTarget = null; | 615 | this._snapTargetIndex = -1; |
620 | 616 | ||
621 | var drawData = this.getDrawingData(); | 617 | var drawData = this.getDrawingData(); |
622 | if (drawData) { | 618 | if (drawData) { |
@@ -699,7 +695,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
699 | //close the current subpath and reset the pen tool | 695 | //close the current subpath and reset the pen tool |
700 | this._penCanvas = null; | 696 | this._penCanvas = null; |
701 | this._penPlaneMat = null; | 697 | this._penPlaneMat = null; |
702 | this._snapTarget = null; | 698 | this._snapTargetIndex = -1; |
703 | this._selectedSubpath = null; | 699 | this._selectedSubpath = null; |
704 | this.application.ninja.stage.clearDrawingCanvas(); | 700 | this.application.ninja.stage.clearDrawingCanvas(); |
705 | } | 701 | } |
@@ -954,17 +950,21 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
954 | throw ("null drawing context in Pentool::DrawSelectedSubpathAnchors"); | 950 | throw ("null drawing context in Pentool::DrawSelectedSubpathAnchors"); |
955 | ctx.save(); | 951 | ctx.save(); |
956 | 952 | ||
957 | var widthAdjustment = -snapManager.getStageWidth()*0.5; | ||
958 | var heightAdjustment = -snapManager.getStageHeight()*0.5; | ||
959 | |||
960 | var drawingCanvas = subpath.getCanvas(); | 953 | var drawingCanvas = subpath.getCanvas(); |
961 | if (!drawingCanvas){ | 954 | if (!drawingCanvas){ |
962 | drawingCanvas = ViewUtils.getStageElement(); | 955 | drawingCanvas = ViewUtils.getStageElement(); |
963 | } | 956 | } |
964 | var localToGlobalMat = ViewUtils.getLocalToGlobalMatrix(drawingCanvas); | 957 | var localToGlobalMat = ViewUtils.getLocalToGlobalMatrix(drawingCanvas); |
958 | |||
959 | /* | ||
960 | var widthAdjustment = -snapManager.getStageWidth()*0.5; | ||
961 | var heightAdjustment = -snapManager.getStageHeight()*0.5; | ||
965 | var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(drawingCanvas, true, false); | 962 | var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(drawingCanvas, true, false); |
966 | var stageWorldToLocalMat = glmat4.inverse(localToStageWorldMat, []); | 963 | var stageWorldToLocalMat = glmat4.inverse(localToStageWorldMat, []); |
964 | */ | ||
967 | 965 | ||
966 | //build the local coord. for each anchor point (appropriate dirty bit checked in function) | ||
967 | subpath.buildAnchorLocalCoord(); | ||
968 | 968 | ||
969 | //display circles and squares near all control points | 969 | //display circles and squares near all control points |
970 | ctx.fillStyle = "#FFFFFF"; | 970 | ctx.fillStyle = "#FFFFFF"; |
@@ -975,11 +975,14 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
975 | var px=0,py=0; | 975 | var px=0,py=0; |
976 | var localCoord = null; | 976 | var localCoord = null; |
977 | var sp=[0,0,0]; | 977 | var sp=[0,0,0]; |
978 | var currAnchor = null; | 978 | var currAnchor = null, currAnchorLocalCoord=null; |
979 | for (var i = 0; i < numAnchors; i++) { | 979 | for (var i = 0; i < numAnchors; i++) { |
980 | currAnchor = subpath.getAnchor(i); | 980 | |
981 | localCoord = MathUtils.transformAndDivideHomogeneousPoint([currAnchor.getPosX()+widthAdjustment, currAnchor.getPosY()+heightAdjustment, currAnchor.getPosZ()], stageWorldToLocalMat); //convert from stage world to local coord | 981 | //currAnchor = subpath.getAnchor(i); |
982 | sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); //convert from local coord to global (screen) coord | 982 | //localCoord = MathUtils.transformAndDivideHomogeneousPoint([currAnchor.getPosX()+widthAdjustment, currAnchor.getPosY()+heightAdjustment, currAnchor.getPosZ()], stageWorldToLocalMat); //convert from stage world to local coord |
983 | //sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); //convert from local coord to global (screen) coord | ||
984 | currAnchorLocalCoord = subpath.getAnchorLocalCoord(i); | ||
985 | sp = MathUtils.transformAndDivideHomogeneousPoint(currAnchorLocalCoord[1],localToGlobalMat); //convert from local coord to global (screen) coord | ||
983 | px = sp[0]; py=sp[1]; | 986 | px = sp[0]; py=sp[1]; |
984 | 987 | ||
985 | ctx.beginPath(); | 988 | ctx.beginPath(); |
@@ -995,9 +998,8 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
995 | //display the hovered over anchor point | 998 | //display the hovered over anchor point |
996 | ctx.lineWidth = 2; | 999 | ctx.lineWidth = 2; |
997 | if (this._hoveredAnchorIndex>=0 && this._hoveredAnchorIndex<numAnchors) { | 1000 | if (this._hoveredAnchorIndex>=0 && this._hoveredAnchorIndex<numAnchors) { |
998 | currAnchor = subpath.getAnchor(this._hoveredAnchorIndex); | 1001 | currAnchorLocalCoord = subpath.getAnchorLocalCoord(this._hoveredAnchorIndex); |
999 | localCoord = MathUtils.transformAndDivideHomogeneousPoint([currAnchor.getPosX()+widthAdjustment, currAnchor.getPosY()+heightAdjustment, currAnchor.getPosZ()], stageWorldToLocalMat); //convert from stage world to local coord | 1002 | sp = MathUtils.transformAndDivideHomogeneousPoint(currAnchorLocalCoord[1],localToGlobalMat); //convert from local coord to global (screen) coord |
1000 | sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); | ||
1001 | px = sp[0]; py=sp[1]; | 1003 | px = sp[0]; py=sp[1]; |
1002 | 1004 | ||
1003 | ctx.beginPath(); | 1005 | ctx.beginPath(); |
@@ -1022,17 +1024,14 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
1022 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); | 1024 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); |
1023 | var whichPoint = this._selectedSubpath.getSelectedMode(); //which of the selected handles to highlight | 1025 | var whichPoint = this._selectedSubpath.getSelectedMode(); //which of the selected handles to highlight |
1024 | 1026 | ||
1025 | //compute the screen (global) coord. of the selected anchor | 1027 | currAnchorLocalCoord = subpath.getAnchorLocalCoord(this._selectedSubpath.getSelectedAnchorIndex()); |
1026 | localCoord = MathUtils.transformAndDivideHomogeneousPoint([selAnchor.getPosX()+widthAdjustment, selAnchor.getPosY()+heightAdjustment, selAnchor.getPosZ()], stageWorldToLocalMat); //convert from stage world to local coord | 1028 | sp = MathUtils.transformAndDivideHomogeneousPoint(currAnchorLocalCoord[1],localToGlobalMat); //convert from local coord to global (screen) coord |
1027 | sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); | ||
1028 | var posX = sp[0]; var posY=sp[1]; | 1029 | var posX = sp[0]; var posY=sp[1]; |
1029 | 1030 | ||
1030 | //compute the screen (global) coord. of the selected anchor prev and next points | 1031 | sp = MathUtils.transformAndDivideHomogeneousPoint(currAnchorLocalCoord[0],l |