diff options
Diffstat (limited to 'js/tools')
-rwxr-xr-x | js/tools/PenTool.js | 160 |
1 files changed, 115 insertions, 45 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 7749d525..ddc8bc04 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -66,14 +66,14 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
66 | _penPlaneMat: { value: null, writable: true }, | 66 | _penPlaneMat: { value: null, writable: true }, |
67 | 67 | ||
68 | //index of the anchor point that the user has hovered over | 68 | //index of the anchor point that the user has hovered over |
69 | _hoveredAnchorIndex: {value: null, writable: true}, | 69 | _hoveredAnchorIndex: {value: -1, writable: true}, |
70 | 70 | ||
71 | //constants used for picking points --- NOTE: these should be user-settable parameters | 71 | //constants used for picking points --- NOTE: these should be user-settable parameters |
72 | _PICK_POINT_RADIUS: { value: 10, writable: false }, | 72 | _PICK_POINT_RADIUS: { value: 10, writable: false }, |
73 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, | 73 | _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, |
74 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, | 74 | _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, |
75 | _DISPLAY_SELECTED_ANCHOR_PREV_RADIUS: { value: 5, writable: false }, | 75 | _DISPLAY_SELECTED_ANCHOR_PREV_RADIUS: { value: 2, writable: false }, |
76 | _DISPLAY_SELECTED_ANCHOR_NEXT_RADIUS: { value: 5, writable: false }, | 76 | _DISPLAY_SELECTED_ANCHOR_NEXT_RADIUS: { value: 2, writable: false }, |
77 | 77 | ||
78 | //constants used for editing modes (can be OR-ed) | 78 | //constants used for editing modes (can be OR-ed) |
79 | EDIT_NONE: { value: 0, writable: false }, | 79 | EDIT_NONE: { value: 0, writable: false }, |
@@ -760,9 +760,7 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
760 | var verticalOffset = this.application.ninja.stage.userContentTop; | 760 | var verticalOffset = this.application.ninja.stage.userContentTop; |
761 | //display the subpath as a sequence of cubic beziers | 761 | //display the subpath as a sequence of cubic beziers |
762 | ctx.lineWidth = 1;//TODO replace hardcoded stroke width with some programmatically set value (should not be same as stroke width) | 762 | ctx.lineWidth = 1;//TODO replace hardcoded stroke width with some programmatically set value (should not be same as stroke width) |
763 | if (ctx.lineWidth == subpath.getStrokeWidth()) | 763 | ctx.strokeStyle = "green"; |
764 | ctx.lineWidth = 3; | ||
765 | ctx.strokeStyle = "black"; | ||
766 | //if (subpath.getStrokeColor()) | 764 | //if (subpath.getStrokeColor()) |
767 | // ctx.strokeStyle = MathUtils.colorToHex( subpath.getStrokeColor() ); | 765 | // ctx.strokeStyle = MathUtils.colorToHex( subpath.getStrokeColor() ); |
768 | ctx.beginPath(); | 766 | ctx.beginPath(); |
@@ -812,34 +810,53 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
812 | var verticalOffset = this.application.ninja.stage.userContentTop;//stageManagerModule.stageManager.userContentTop; | 810 | var verticalOffset = this.application.ninja.stage.userContentTop;//stageManagerModule.stageManager.userContentTop; |
813 | 811 | ||
814 | //display circles and squares near all control points | 812 | //display circles and squares near all control points |
815 | ctx.fillStyle = "#FF4444"; | 813 | ctx.fillStyle = "#FFFFFF"; |
816 | ctx.lineWidth = 2; | 814 | ctx.lineWidth = 1; |
817 | ctx.strokeStyle = "black"; | 815 | ctx.strokeStyle = "green"; |
816 | var anchorDelta = 2; | ||
817 | var selAnchorDelta = 4; | ||
818 | |||
818 | for (var i = 0; i < numAnchors; i++) { | 819 | for (var i = 0; i < numAnchors; i++) { |
819 | var px = subpath.getAnchor(i).getPosX(); | 820 | var px = subpath.getAnchor(i).getPosX(); |
820 | var py = subpath.getAnchor(i).getPosY(); | 821 | var py = subpath.getAnchor(i).getPosY(); |
821 | ctx.beginPath(); | 822 | ctx.beginPath(); |
822 | ctx.arc(px + horizontalOffset, py + verticalOffset, this._DISPLAY_ANCHOR_RADIUS, 0, 2 * Math.PI, false); | 823 | //ctx.arc(px + horizontalOffset, py + verticalOffset, this._DISPLAY_ANCHOR_RADIUS, 0, 2 * Math.PI, false); |
824 | ctx.moveTo(px-anchorDelta+horizontalOffset, py-anchorDelta+verticalOffset); | ||
825 | ctx.lineTo(px+anchorDelta+horizontalOffset, py-anchorDelta+verticalOffset); | ||
826 | ctx.lineTo(px+anchorDelta+horizontalOffset, py+anchorDelta+verticalOffset); | ||
827 | ctx.lineTo(px-anchorDelta+horizontalOffset, py+anchorDelta+verticalOffset); | ||
828 | ctx.closePath(); | ||
823 | ctx.fill(); | 829 | ctx.fill(); |
824 | ctx.stroke(); | 830 | ctx.stroke(); |
825 | } | 831 | } |
826 | 832 | ||
827 | //display the hovered over anchor point | 833 | //display the hovered over anchor point |
828 | ctx.lineWidth = 2; | 834 | ctx.lineWidth = 2; |
829 | ctx.strokeStyle = "black"; | 835 | if (this._hoveredAnchorIndex>=0 && this._hoveredAnchorIndex<numAnchors) { |
830 | if (this._hoveredAnchorIndex && this._hoveredAnchorIndex>=0 && this._hoveredAnchorIndex<numAnchors) { | ||
831 | var px = subpath.getAnchor(this._hoveredAnchorIndex).getPosX(); | 836 | var px = subpath.getAnchor(this._hoveredAnchorIndex).getPosX(); |
832 | var py = subpath.getAnchor(this._hoveredAnchorIndex).getPosY(); | 837 | var py = subpath.getAnchor(this._hoveredAnchorIndex).getPosY(); |
833 | ctx.beginPath(); | 838 | ctx.beginPath(); |
834 | ctx.arc(px + horizontalOffset, py + verticalOffset, this._DISPLAY_ANCHOR_RADIUS*1.5, 0, 2 * Math.PI, false); | 839 | //ctx.arc(px + horizontalOffset, py + verticalOffset, this._DISPLAY_ANCHOR_RADIUS*1.5, 0, 2 * Math.PI, false); |
840 | ctx.moveTo(px-selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
841 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
842 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
843 | ctx.lineTo(px-selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
844 | ctx.closePath(); | ||
835 | ctx.stroke(); | 845 | ctx.stroke(); |
836 | } | 846 | } |
837 | 847 | ||
848 | |||
838 | //display selected anchor and its prev. and next points | 849 | //display selected anchor and its prev. and next points |
839 | if (this._selectedSubpath && subpath === this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex()!== -1) { | 850 | if (this._selectedSubpath && subpath === this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex()!== -1) { |
840 | ctx.lineWidth = 2; | 851 | ctx.lineWidth = 1; |
841 | ctx.strokeStyle = "black"; | 852 | var defFill = "#FFFFFF"; |
853 | var defStroke = "green"; | ||
854 | var selHandleFill = "#000000" | ||
855 | |||
856 | ctx.strokeStyle = defStroke; | ||
857 | ctx.fillStyle = defFill; | ||
842 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); | 858 | var selAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); |
859 | var whichPoint = this._selectedSubpath.getSelectedMode(); //which of the selected handles to highlight | ||
843 | 860 | ||
844 | //line from prev to anchor | 861 | //line from prev to anchor |
845 | ctx.beginPath(); | 862 | ctx.beginPath(); |
@@ -848,10 +865,16 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
848 | ctx.stroke(); | 865 | ctx.stroke(); |
849 | 866 | ||
850 | //selected anchor prev | 867 | //selected anchor prev |
851 | ctx.fillStyle = "#AAAAAA"; | ||
852 | ctx.beginPath(); | 868 | ctx.beginPath(); |
853 | ctx.arc(selAnchor.getPrevX() + horizontalOffset, selAnchor.getPrevY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_PREV_RADIUS, 0, 2 * Math.PI, false); | 869 | ctx.arc(selAnchor.getPrevX() + horizontalOffset, selAnchor.getPrevY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_PREV_RADIUS, 0, 2 * Math.PI, false); |
854 | ctx.fill(); | 870 | ctx.closePath(); |
871 | if (whichPoint & this._selectedSubpath.SEL_PREV){ | ||
872 | ctx.fillStyle = selHandleFill; | ||
873 | ctx.fill(); | ||
874 | ctx.fillStyle = defFill; | ||
875 | }else { | ||
876 | ctx.fill(); | ||
877 | } | ||
855 | ctx.stroke(); | 878 | ctx.stroke(); |
856 | 879 | ||
857 | //line from next to anchor | 880 | //line from next to anchor |
@@ -861,16 +884,27 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
861 | ctx.stroke(); | 884 | ctx.stroke(); |
862 | 885 | ||
863 | //selected anchor next | 886 | //selected anchor next |
864 | ctx.fillStyle = "#666666"; | ||
865 | ctx.beginPath(); | 887 | ctx.beginPath(); |
866 | ctx.arc(selAnchor.getNextX() + horizontalOffset, selAnchor.getNextY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_NEXT_RADIUS, 0, 2 * Math.PI, false); | 888 | ctx.arc(selAnchor.getNextX() + horizontalOffset, selAnchor.getNextY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_NEXT_RADIUS, 0, 2 * Math.PI, false); |
867 | ctx.fill(); | 889 | if (whichPoint & this._selectedSubpath.SEL_NEXT){ |
890 | ctx.fillStyle = selHandleFill; | ||
891 | ctx.fill(); | ||
892 | ctx.fillStyle = defFill; | ||
893 | }else { | ||
894 | ctx.fill(); | ||
895 | } | ||
868 | ctx.stroke(); | 896 | ctx.stroke(); |
869 | 897 | ||
870 | //selected anchor point | 898 | //selected anchor point |
871 | ctx.fillStyle = "#8ED6FF"; | 899 | var px = selAnchor.getPosX(); |
900 | var py = selAnchor.getPosY(); | ||
872 | ctx.beginPath(); | 901 | ctx.beginPath(); |
873 | ctx.arc(selAnchor.getPosX() + horizontalOffset, selAnchor.getPosY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_RADIUS, 0, 2 * Math.PI, false); | 902 | //ctx.arc(selAnchor.getPosX() + horizontalOffset, selAnchor.getPosY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_RADIUS, 0, 2 * Math.PI, false); |
903 | ctx.moveTo(px-selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
904 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
905 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
906 | ctx.lineTo(px-selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
907 | ctx.closePath(); | ||
874 | ctx.fill(); | 908 | ctx.fill(); |
875 | ctx.stroke(); | 909 | ctx.stroke(); |
876 | 910 | ||
@@ -879,7 +913,12 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
879 | ctx.lineWidth = 2; | 913 | ctx.lineWidth = 2; |
880 | ctx.strokeStyle = "red"; | 914 | ctx.strokeStyle = "red"; |
881 | ctx.beginPath(); | 915 | ctx.beginPath(); |
882 | ctx.arc(this._snapTarget.getPosX() + horizontalOffset, this._snapTarget.getPosY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_RADIUS * 2, 0, 2 * Math.PI, false); | 916 | //ctx.arc(this._snapTarget.getPosX() + horizontalOffset, this._snapTarget.getPosY() + verticalOffset, this._DISPLAY_SELECTED_ANCHOR_RADIUS * 2, 0, 2 * Math.PI, false); |
917 | ctx.moveTo(px-selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
918 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py-selAnchorDelta+verticalOffset); | ||
919 | ctx.lineTo(px+selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
920 | ctx.lineTo(px-selAnchorDelta+horizontalOffset, py+selAnchorDelta+verticalOffset); | ||
921 | ctx.closePath(); | ||
883 | ctx.stroke(); | 922 | ctx.stroke(); |
884 | } | 923 | } |
885 | } //if this._selectedSubpath && subpath === this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex()!== -1 | 924 | } //if this._selectedSubpath && subpath === this._selectedSubpath && this._selectedSubpath.getSelectedAnchorIndex()!== -1 |
@@ -955,33 +994,64 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
955 | 994 | ||
956 | handleDelete:{ | 995 | handleDelete:{ |
957 | value: function(event){ | 996 | value: function(event){ |
958 | //clear the selected subpath...the only new additions to this function w.r.t. ToolBase | 997 | var len = this.application.ninja.selectedElements.length; |
959 | if (this._selectedSubpath){ | 998 | if (len===0) { |
960 | if (this._selectedSubpath.getSelectedAnchorIndex()>=0){ | 999 | //clear the selected subpath...the only new additions to this function w.r.t. ToolBase |
961 | this._hoveredAnchorIndex=-1; | 1000 | if (this._selectedSubpath){ |
962 | this._selectedSubpath.removeAnchor(this._selectedSubpath.getSelectedAnchorIndex()); | 1001 | if (this._selectedSubpath.getSelectedAnchorIndex()>=0){ |
963 | this._selectedSubpath.createSamples(); | 1002 | this._hoveredAnchorIndex=-1; |
964 | //clear the canvas | 1003 | this._selectedSubpath.removeAnchor(this._selectedSubpath.getSelectedAnchorIndex()); |
965 | this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); | 1004 | this._selectedSubpath.createSamples(); |
966 | this.DrawSubpathAnchors(this._selectedSubpath); | 1005 | //clear the canvas |
967 | this.ShowSelectedSubpath(); | 1006 | this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); |
1007 | this.DrawSubpathAnchors(this._selectedSubpath); | ||
1008 | this.ShowSelectedSubpath(); | ||
1009 | } | ||
1010 | else { | ||
1011 | this._selectedSubpath.clearAllAnchors(); //perhaps unnecessary | ||
1012 | this._selectedSubpath = null; | ||
1013 | //clear the canvas | ||
1014 | this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); | ||
1015 | |||
1016 | //undo/redo...go through ElementController and NJEvent | ||
1017 | var els = []; | ||
1018 | ElementController.removeElement(this._penCanvas); | ||
1019 | els.push(this._penCanvas); | ||
1020 | NJevent( "deleteSelection", els ); | ||
1021 | this._penCanvas = null; | ||
1022 | } | ||
1023 | } | ||
1024 | //do nothing if there was no selected subpath and if there was no selection | ||
1025 | } | ||
1026 | else { | ||
1027 | |||
1028 | //undo/redo...go through ElementMediator (see ElementMediator.handleDeleting() from where the much of this function is copied) | ||
1029 | //clear the canvas | ||
1030 | this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawi |