diff options
-rwxr-xr-x | js/lib/geom/sub-path.js | 21 | ||||
-rwxr-xr-x | js/tools/PenTool.js | 76 |
2 files changed, 58 insertions, 39 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index 62937461..7e11bb33 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js | |||
@@ -413,19 +413,21 @@ GLSubpath.prototype._checkIntersectionWithSamples = function(startIndex, endInde | |||
413 | //will assume that the BBox test is performed outside this function | 413 | //will assume that the BBox test is performed outside this function |
414 | if (endIndex<startIndex){ | 414 | if (endIndex<startIndex){ |
415 | //go from startIndex to the end of the samples | 415 | //go from startIndex to the end of the samples |
416 | endIndex = this._Samples.length; | 416 | endIndex = this._Samples.length-1; |
417 | } | 417 | } |
418 | for (var i=startIndex; i<endIndex-1; i++){ | 418 | var retParam = null; |
419 | for (var i=startIndex; i<endIndex; i++){ | ||
419 | var seg0 = this._Samples[i].slice(0); | 420 | var seg0 = this._Samples[i].slice(0); |
420 | var j=i+1; | 421 | var j=i+1; |
421 | var seg1 = this._Samples[j].slice(0); | 422 | var seg1 = this._Samples[j].slice(0); |
422 | var distToSegment = MathUtils.distPointToSegment(point, seg0, seg1); | 423 | var distToSegment = MathUtils.distPointToSegment(point, seg0, seg1); |
423 | if (distToSegment<=radius){ | 424 | if (distToSegment<=radius){ |
424 | var paramDistance = MathUtils.paramPointProjectionOnSegment(point, seg0, seg1); //TODO Optimize! this function was called in distPointToSegment above | 425 | var paramDistance = MathUtils.paramPointProjectionOnSegment(point, seg0, seg1); //TODO Optimize! this function was called in distPointToSegment above |
425 | return this._sampleParam[i] + (this._sampleParam[j] - this._sampleParam[i])*paramDistance; | 426 | retParam = this._sampleParam[i] + (this._sampleParam[j] - this._sampleParam[i])*paramDistance; |
427 | break; | ||
426 | } | 428 | } |
427 | } | 429 | } |
428 | return null; | 430 | return retParam; |
429 | }; | 431 | }; |
430 | 432 | ||
431 | GLSubpath.prototype._checkIntersection = function(controlPts, beginParam, endParam, point, radius) { | 433 | GLSubpath.prototype._checkIntersection = function(controlPts, beginParam, endParam, point, radius) { |
@@ -589,6 +591,10 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius, testOnly) | |||
589 | selAnchorIndex = anchorAndRetCode[0]; | 591 | selAnchorIndex = anchorAndRetCode[0]; |
590 | retCode = anchorAndRetCode[1]; | 592 | retCode = anchorAndRetCode[1]; |
591 | 593 | ||
594 | if (retCode!== this.SEL_NONE){ | ||
595 | retCode = retCode | this.SEL_PATH; //ensure that path is also selected if anything else is selected | ||
596 | } | ||
597 | |||
592 | //if the location is not close any of the anchors, check if it is close to the curve itself | 598 | //if the location is not close any of the anchors, check if it is close to the curve itself |
593 | if (selAnchorIndex===-1) { | 599 | if (selAnchorIndex===-1) { |
594 | //first check if the input location is within the bounding box | 600 | //first check if the input location is within the bounding box |
@@ -603,9 +609,11 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius, testOnly) | |||
603 | [this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()]]; | 609 | [this._Anchors[nextIndex].getPosX(),this._Anchors[nextIndex].getPosY(),this._Anchors[nextIndex].getPosZ()]]; |
604 | var point = [pickX, pickY, pickZ]; | 610 | var point = [pickX, pickY, pickZ]; |
605 | if (this._isWithinGivenBoundingBox(point, controlPoints, radius)) { | 611 | if (this._isWithinGivenBoundingBox(point, controlPoints, radius)) { |
612 | //var intersectParam = this._checkIntersection(controlPoints, 0.0, 1.0, point, radius); | ||
606 | var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius); | 613 | var intersectParam = this._checkIntersectionWithSamples(this._anchorSampleIndex[i], this._anchorSampleIndex[nextIndex], point, radius); |
607 | if (intersectParam){ | 614 | if (intersectParam!==null){ |
608 | selAnchorIndex=i; | 615 | selAnchorIndex=i; |
616 | retCode = retCode | this.SEL_PATH; | ||
609 | retParam = intersectParam-i; //make the retParam go from 0 to 1 | 617 | retParam = intersectParam-i; //make the retParam go from 0 to 1 |
610 | break; | 618 | break; |
611 | } | 619 | } |
@@ -614,9 +622,6 @@ GLSubpath.prototype.pickPath = function (pickX, pickY, pickZ, radius, testOnly) | |||
614 | }//if is within bbox | 622 | }//if is within bbox |
615 | } | 623 | } |
616 | 624 | ||
617 | if (retCode!== this.SEL_NONE) | ||
618 | retCode = retCode | this.SEL_PATH; //ensure that path is also selected if anything else is selected | ||
619 | |||
620 | if (!testOnly){ | 625 | if (!testOnly){ |
621 | this._selectMode = retCode; | 626 | this._selectMode = retCode; |
622 | this._selectedAnchorIndex = selAnchorIndex; | 627 | this._selectedAnchorIndex = selAnchorIndex; |
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 50fd97d7..0661c3ea 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -282,6 +282,13 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
282 | // Compute the mouse position in local (selected subpath canvas) space | 282 | // Compute the mouse position in local (selected subpath canvas) space |
283 | var globalPos = hitRec.getScreenPoint(); | 283 | var globalPos = hitRec.getScreenPoint(); |
284 | var localMousePos = ViewUtils.globalToLocal(globalPos, this._selectedSubpathCanvas); | 284 | var localMousePos = ViewUtils.globalToLocal(globalPos, this._selectedSubpathCanvas); |
285 | /* | ||
286 | CHECK IF THIS IS CORRECT | ||
287 | ViewUtils.pushViewportObj | ||
288 | var temp ViewUtils.screenToView(localMousePos[0], localMousePos[1], 0) should return a point in view space of canvas | ||
289 | ViewUtils.popViewportObj | ||
290 | MathUtils.transformPoint(temp, this._selectedSubpathPlaneMat) | ||
291 | */ | ||
285 | 292 | ||
286 | //now perform the hit testing | 293 | //now perform the hit testing |
287 | var prevSelectedAnchorIndex = this._selectedSubpath.getSelectedAnchorIndex(); | 294 | var prevSelectedAnchorIndex = this._selectedSubpath.getSelectedAnchorIndex(); |
@@ -312,8 +319,13 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
312 | //if we have selected the first anchor point, and previously had selected the last anchor point, close the path | 319 | //if we have selected the first anchor point, and previously had selected the last anchor point, close the path |
313 | var numAnchors = this._selectedSubpath.getNumAnchors(); | 320 | var numAnchors = this._selectedSubpath.getNumAnchors(); |
314 | if (numAnchors>1 && !this._selectedSubpath.getIsClosed() && this._selectedSubpath.getSelectedAnchorIndex()===0 && prevSelectedAnchorIndex === numAnchors-1){ | 321 | if (numAnchors>1 && !this._selectedSubpath.getIsClosed() && this._selectedSubpath.getSelectedAnchorIndex()===0 && prevSelectedAnchorIndex === numAnchors-1){ |
315 | //setting the selection mode to NONE will effectively add a new anchor point at the click location and also give us snapping | 322 | //insert an anchor temporarily that will get removed in the mouse up handler |
316 | whichPoint = this._selectedSubpath.SEL_NONE; | 323 | this._selectedSubpath.addAnchor(new AnchorPoint()); |
324 | var newAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); | ||
325 | newAnchor.setPos(localMousePos[0], localMousePos[1], localMousePos[2]); | ||
326 | newAnchor.setPrevPos(localMousePos[0], localMousePos[1], localMousePos[2]); | ||
327 | newAnchor.setNextPos(localMousePos[0], localMousePos[1], localMousePos[2]); | ||
328 | |||
317 | //set the snap target in case the mouse move handler doesn't get called | 329 | //set the snap target in case the mouse move handler doesn't get called |
318 | this._snapTargetIndex = 0; | 330 | this._snapTargetIndex = 0; |
319 | } | 331 | } |
@@ -489,7 +501,6 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
489 | var globalMousePos = hitRec.getScreenPoint(); | 501 | var globalMousePos = hitRec.getScreenPoint(); |
490 | var localMousePos = ViewUtils.globalToLocal(globalMousePos, drawingCanvas); | 502 | var localMousePos = ViewUtils.globalToLocal(globalMousePos, drawingCanvas); |
491 | 503 | ||
492 | |||
493 | //var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS, false); | 504 | //var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS, false); |
494 | //var selAnchorRetCode = this._selectedSubpath.pickAnchor(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS); | 505 | //var selAnchorRetCode = this._selectedSubpath.pickAnchor(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS); |
495 | var selAnchorAndParamAndCode = this._selectedSubpath.pickPath(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS, true); | 506 | var selAnchorAndParamAndCode = this._selectedSubpath.pickPath(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS, true); |
@@ -513,7 +524,6 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
513 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; | 524 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; |
514 | } else if (selAnchorAndParamAndCode[2] & this._selectedSubpath.SEL_PATH) { | 525 | } else if (selAnchorAndParamAndCode[2] & this._selectedSubpath.SEL_PATH) { |
515 | //change the cursor | 526 | //change the cursor |
516 | STOPPED HERE...why is this case not being hit? | ||
517 | var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; | 527 | var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; |
518 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; | 528 | this.application.ninja.stage.drawingCanvas.style.cursor = cursor; |
519 | } | 529 | } |
@@ -723,20 +733,28 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
723 | value: function(){ | 733 | value: function(){ |
724 | var i=0,d=0; | 734 | var i=0,d=0; |
725 | var currAnchor = null; | 735 | var currAnchor = null; |
726 | var localPos = [[0,0,0],[0,0,0],[0,0,0]]; | 736 | var xAdjustment = snapManager.getStageWidth()*0.5; |
727 | //if there is already is a subpath canvas, it means the anchor points are in local space | 737 | var yAdjustment = snapManager.getStageHeight()*0.5; |
738 | var localPos = [[0,0,0,0],[0,0,0,0],[0,0,0,0]]; | ||
739 | //if there already is a subpath canvas, it means the anchor points are in local space | ||
728 | // so convert them to stage world space | 740 | // so convert them to stage world space |
729 | var numAnchors = this._selectedSubpath.getNumAnchors(); | 741 | var numAnchors = this._selectedSubpath.getNumAnchors(); |
730 | if (this._selectedSubpathCanvas) { | 742 | if (this._selectedSubpathCanvas) { |
731 | var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, true, true); | 743 | //this transformation will take the path points from local space to stage world space |
744 | // *without* taking into account the transformation applied to this canvas | ||
745 | // (this is because we use the center of the bbox to find a place for the canvas) | ||
746 | var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, true, false); | ||
732 | for (i=0;i<numAnchors;i++){ | 747 | for (i=0;i<numAnchors;i++){ |
733 | //convert this anchor from local to stage world | 748 | //convert this anchor from local to stage world |
734 | var currAnchor = this._selectedSubpath.getAnchor(i); | 749 | var currAnchor = this._selectedSubpath.getAnchor(i); |
735 | localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ()]; | 750 | localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ(),1]; |
736 | localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ()]; | 751 | localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ(),1]; |
737 | localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ()]; | 752 | localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ(),1]; |
738 | for (d=0;d<3;d++) { | 753 | for (d=0;d<3;d++) { |
739 | localPos[d] = MathUtils.transformAndDivideHomogeneousPoint(localPos[d], localToStageWorldMat); | 754 | localPos[d] = MathUtils.transformAndDivideHomogeneousPoint(localPos[d], localToStageWorldMat); |
755 | //add half the stage width and height to the X and Y coord. | ||
756 | localPos[d][0]+= xAdjustment; | ||
757 | localPos[d][1]+= yAdjustment; | ||
740 | } | 758 | } |
741 | currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]); | 759 | currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]); |
742 | currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]); | 760 | currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]); |
@@ -751,28 +769,21 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
751 | var bboxMax = this._selectedSubpath.getBBoxMax(); | 769 | var bboxMax = this._selectedSubpath.getBBoxMax(); |
752 | 770 | ||
753 | //check if the last point added made this canvas is now bigger than the max canvas size | 771 | //check if the last point added made this canvas is now bigger than the max canvas size |
754 | var needToRemoveLastPoint = false; | ||
755 | for (d=0;d<3;d++){ | 772 | for (d=0;d<3;d++){ |
756 | if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){ | 773 | if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){ |
757 | needToRemoveLastPoint = true; | 774 | console.log("PEN: Warning! Ignoring last added point because canvas size too large"); |
775 | this._selectedSubpath.removeAnchor(numAnchors-1); | ||
776 | numAnchors--; | ||
777 | //recompute the bbox of this subpath | ||
778 | this._selectedSubpath.createSamples(true); | ||
779 | bboxMin = this._selectedSubpath.getBBoxMin(); | ||
780 | bboxMax = this._selectedSubpath.getBBoxMax(); | ||
781 | break; | ||
758 | } | 782 | } |
759 | } | 783 | } |
760 | if (needToRemoveLastPoint){ | 784 | |
761 | console.log("PEN: Warning! Ignoring last added point because canvas size too large") | ||
762 | this._selectedSubpath.removeAnchor(numAnchors-1); | ||
763 | numAnchors--; | ||
764 | //recompute the bbox of this subpath | ||
765 | this._selectedSubpath.createSamples(true); | ||
766 | bboxMin = this._selectedSubpath.getBBoxMin(); | ||
767 | bboxMax = this._selectedSubpath.getBBoxMax(); | ||
768 | } | ||
769 | 785 | ||
770 | this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); | 786 | this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); |
771 | if (this._selectedSubpathCanvas) { | ||
772 | //if the canvas does not yet exist, the stage world point already have this stage dimension offset below | ||
773 | this._selectedSubpathCanvasCenter[0]+= snapManager.getStageWidth()*0.5; | ||
774 | this._selectedSubpathCanvasCenter[1]+= snapManager.getStageHeight()*0.5; | ||
775 | } | ||
776 | 787 | ||
777 | //update the plane matrix of this subpath by querying the element mediator | 788 | //update the plane matrix of this subpath by querying the element mediator |
778 | if (this._selectedSubpathCanvas) { | 789 | if (this._selectedSubpathCanvas) { |
@@ -784,9 +795,9 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
784 | for (i=0;i<numAnchors;i++){ | 795 | for (i=0;i<numAnchors;i++){ |
785 |