aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPushkar Joshi2012-04-09 15:55:10 -0700
committerPushkar Joshi2012-04-09 15:55:10 -0700
commitdae3041e6b8269da3d593a44c09e2288bb434a02 (patch)
tree495fc661a2e90816706a09b8d7d702550bd7fd8c
parent6cce5e9367676f5b452c28dd7d960aa46f4e464c (diff)
downloadninja-dae3041e6b8269da3d593a44c09e2288bb434a02.tar.gz
snapping feedback for pen tool, correct for subpaths that may lie on rotated canvas, and with a rotated view
-rwxr-xr-xjs/helper-classes/3D/vec-utils.js19
-rwxr-xr-xjs/lib/geom/sub-path.js29
-rwxr-xr-xjs/tools/PenTool.js63
3 files changed, 97 insertions, 14 deletions
diff --git a/js/helper-classes/3D/vec-utils.js b/js/helper-classes/3D/vec-utils.js
index 4eacd856..0916c840 100755
--- a/js/helper-classes/3D/vec-utils.js
+++ b/js/helper-classes/3D/vec-utils.js
@@ -113,6 +113,25 @@ var VecUtils = exports.VecUtils = Object.create(Object.prototype,
113 } 113 }
114 }, 114 },
115 115
116 vecDistSq : {
117 value: function( dimen, a, b ) {
118 var sum;
119
120 if ((a.length < dimen) || (b.length < dimen))
121 {
122 throw new Error( "dimension error in VecUtils.vecDistSq" );
123 }
124
125 var sum = 0.0;
126 for (var i=0; i<dimen; i++)
127 {
128 var d = a[i] - b[i];
129 sum += d*d;
130 }
131 return sum;
132 }
133 },
134
116 vecDot : { 135 vecDot : {
117 value: function( dimen, v0, v1 ) { 136 value: function( dimen, v0, v1 ) {
118 if ((v0.length < dimen) || (v1.length < dimen)) 137 if ((v0.length < dimen) || (v1.length < dimen))
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index d784fbc6..33bcfc9a 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -620,7 +620,28 @@ GLSubpath.prototype._isWithinBoundingBox = function(point, ctrlPts, radius) {
620 return true; 620 return true;
621}; 621};
622 622
623GLSubpath.prototype._checkAnchorIntersection = function(pickX, pickY, pickZ, radSq, anchorIndex, minDistance) { 623GLSubpath.prototype._checkAnchorIntersection = function(pickX, pickY, pickZ, radSq, anchorIndex, minDistance, useLocal) {
624 //if we are asked to use the local coordinate and the local coordinate for this anchor exists
625 if (useLocal && this._anchorSampleIndex.length>anchorIndex && this._LocalPoints.length > this._anchorSampleIndex[anchorIndex]) {
626 var localCoord = this._LocalPoints[this._anchorSampleIndex[anchorIndex]]
627 var distSq = VecUtils.vecDistSq(3, [pickX, pickY, pickZ], localCoord);
628 //check the anchor point
629 if (distSq < radSq && distSq<minDistance) {
630 return this.SEL_ANCHOR;
631 }
632 /*
633 //check the prev. and next of the selected anchor point
634 distSq = this._Anchors[anchorIndex].getPrevDistanceSq(pickX, pickY, pickZ);
635 if (distSq<radSq && distSq<minDistance){
636 return this.SEL_PREV;
637 }
638 distSq = this._Anchors[anchorIndex].getNextDistanceSq(pickX, pickY, pickZ);
639 if (distSq<radSq && distSq<minDistance){
640 return this.SEL_NEXT;
641 }*/
642 return this.SEL_NONE;
643 }
644
624 var distSq = this._Anchors[anchorIndex].getDistanceSq(pickX, pickY, pickZ); 645 var distSq = this._Anchors[anchorIndex].getDistanceSq(pickX, pickY, pickZ);
625 //check the anchor point 646 //check the anchor point
626 if (distSq < radSq && distSq<minDistance) { 647 if (distSq < radSq && distSq<minDistance) {
@@ -638,7 +659,7 @@ GLSubpath.prototype._checkAnchorIntersection = function(pickX, pickY, pickZ, rad
638 return this.SEL_NONE; 659 return this.SEL_NONE;
639}; 660};
640 661
641GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) { 662GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius, useLocal) {
642 var numAnchors = this._Anchors.length; 663 var numAnchors = this._Anchors.length;
643 var selAnchorIndex = -1; 664 var selAnchorIndex = -1;
644 var retCode = this.SEL_NONE; 665 var retCode = this.SEL_NONE;
@@ -646,14 +667,14 @@ GLSubpath.prototype.pickAnchor = function (pickX, pickY, pickZ, radius) {
646 var radSq = radius * radius; 667 var radSq = radius * radius;
647 //check if the clicked location is close to the currently selected anchor position 668 //check if the clicked location is close to the currently selected anchor position
648 if (this._selectedAnchorIndex>=0 && this._selectedAnchorIndex<this._Anchors.length){ 669 if (this._selectedAnchorIndex>=0 && this._selectedAnchorIndex<this._Anchors.length){
649 retCode = this._checkAnchorIntersection(pickX, pickY, pickZ, radSq, this._selectedAnchorIndex, minDistance); 670 retCode = this._checkAnchorIntersection(pickX, pickY, pickZ, radSq, this._selectedAnchorIndex, minDistance, useLocal);
650 if (retCode!==this.SEL_NONE){ 671 if (retCode!==this.SEL_NONE){
651 return [this._selectedAnchorIndex, retCode]; 672 return [this._selectedAnchorIndex, retCode];
652 } 673 }
653 } 674 }
654 //now check if the click location is close to any anchor position 675 //now check if the click location is close to any anchor position
655 for (var i = 0; i < numAnchors; i++) { 676 for (var i = 0; i < numAnchors; i++) {
656 retCode = this._checkAnchorIntersection(pickX, pickY, pickZ, radSq, i, minDistance); 677 retCode = this._checkAnchorIntersection(pickX, pickY, pickZ, radSq, i, minDistance, useLocal);
657 if (retCode!==this.SEL_NONE){ 678 if (retCode!==this.SEL_NONE){
658 selAnchorIndex=i; 679 selAnchorIndex=i;
659 break; 680 break;
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 61a254ea..6c016cab 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -119,6 +119,27 @@ exports.PenTool = Montage.create(ShapeTool, {
119 } 119 }
120 }, 120 },
121 121
122 _getUnsnappedScreenPosition: {
123 value: function(x,y){
124 var elemSnap = snapManager.elementSnapEnabled();
125 var gridSnap = snapManager.gridSnapEnabled();
126 var alignSnap = snapManager.snapAlignEnabled();
127
128 snapManager.enableElementSnap(false);
129 snapManager.enableGridSnap(false);
130 snapManager.enableSnapAlign(false);
131
132 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y));
133 var unsnappedpos = (snapManager.snap(point.x, point.y, false)).getScreenPoint();
134 this._dragPlane = snapManager.getDragPlane();
135
136 snapManager.enableElementSnap(elemSnap);
137 snapManager.enableGridSnap(gridSnap);
138 snapManager.enableSnapAlign(alignSnap);
139
140 return unsnappedpos;
141 }
142 },
122 ShowToolProperties: { 143 ShowToolProperties: {
123 value: function () { 144 value: function () {
124 this._penView = PenView.create(); 145 this._penView = PenView.create();
@@ -351,20 +372,31 @@ exports.PenTool = Montage.create(ShapeTool, {
351 372
352 //make the subpath dirty so it will get re-drawn 373 //make the subpath dirty so it will get re-drawn
353 this._selectedSubpath.makeDirty(); 374 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){
358 this.DrawSubpathSVG(this._selectedSubpath); 375 this.DrawSubpathSVG(this._selectedSubpath);
359 } 376 }
360
361 } else { //if mouse is not down: 377 } else { //if mouse is not down:
362 //this.doSnap(event); 378 //this.doSnap(event);
363 //this.DrawHandles(); 379 //this.DrawHandles();
364 380
365 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); 381 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY);
366 if (currMousePos && this._selectedSubpath ){ 382 if (currMousePos && this._selectedSubpath ){
367 var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); 383 /*
384 //convert the mouse pos. to local space of the canvas
385 var widthAdjustment = -snapManager.getStageWidth()*0.5;
386 var heightAdjustment = -snapManager.getStageHeight()*0.5; */
387
388
389 var drawingCanvas = this._selectedSubpath.getCanvas();
390 if (!drawingCanvas){
391 drawingCanvas = ViewUtils.getStageElement();
392 }
393 /*var stageWorldToGlobalMatrix = ViewUtils.getStageWorldToGlobalMatrix();
394 var globalMousePos = MathUtils.transformAndDivideHomogeneousPoint([currMousePos[0]+widthAdjustment, currMousePos[1]+heightAdjustment, currMousePos[2]], stageWorldToGlobalMatrix);*/
395 var globalMousePos = this._getUnsnappedScreenPosition(event.pageX, event.pageY);
396 var localMousePos = ViewUtils.globalToLocal(globalMousePos, drawingCanvas);
397
398 //var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS, false);
399 var selAnchorRetCode = this._selectedSubpath.pickAnchor(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS, true);
368 if (selAnchorRetCode[0] >=0) { 400 if (selAnchorRetCode[0] >=0) {
369 this._hoveredAnchorIndex = selAnchorRetCode[0]; 401 this._hoveredAnchorIndex = selAnchorRetCode[0];
370 var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1; 402 var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1;
@@ -599,12 +631,23 @@ exports.PenTool = Montage.create(ShapeTool, {
599 strokeSize = ShapesController.GetValueInPixels(this.options.strokeSize.value, this.options.strokeSize.units); 631 strokeSize = ShapesController.GetValueInPixels(this.options.strokeSize.value, this.options.strokeSize.units);
600 } 632 }
601 this._selectedSubpath.setStrokeWidth(strokeSize); 633 this._selectedSubpath.setStrokeWidth(strokeSize);
602 if (this.application.ninja.colorController.colorToolbar.stroke.webGlColor){ 634
603 this._selectedSubpath.setStrokeColor(this.application.ninja.colorController.colorToolbar.stroke.webGlColor); 635 var colorArray=[];
636 var color = this.application.ninja.colorController.colorToolbar.stroke.color;
637 if (color){
638 colorArray = [color.r/255, color.g/255, color.b/255, color.a];
639 }else {
640 colorArray = [1,1,1,0];
604 } 641 }
605 if (this.application.ninja.colorController.colorToolbar.fill.webGlColor){ 642 this._selectedSubpath.setStrokeColor(colorArray);
606 this._selectedSubpath.setFillColor(this.application.ninja.colorController.colorToolbar.fill.webGlColor); 643
644 color = this.application.ninja.colorController.colorToolbar.fill.color;
645 if (color){
646 colorArray = [color.r/255, color.g/255, color.b/255, color.a];
647 } else {
648 colorArray = [1,1,1,0];
607 } 649 }
650 this._selectedSubpath.setFillColor(colorArray);
608 } //if this is a new path being rendered 651 } //if this is a new path being rendered
609 652
610 this._selectedSubpath.makeDirty(); 653 this._selectedSubpath.makeDirty();