aboutsummaryrefslogtreecommitdiff
path: root/js/tools/PenTool.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-xjs/tools/PenTool.js1256
1 files changed, 779 insertions, 477 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 7fc8dd95..8ecc9f79 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -14,12 +14,10 @@ var ElementMediator = require("js/mediators/element-mediator").ElementMediator;
14var TagTool = require("js/tools/TagTool").TagTool; 14var TagTool = require("js/tools/TagTool").TagTool;
15var ElementController = require("js/controllers/elements/element-controller").ElementController; 15var ElementController = require("js/controllers/elements/element-controller").ElementController;
16var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; 16var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager;
17 17var ViewUtils = require("js/helper-classes/3D/view-utils").ViewUtils;
18var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; 18var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint;
19var SubPath = require("js/lib/geom/sub-path").SubPath; 19var SubPath = require("js/lib/geom/sub-path").SubPath;
20 20
21//todo remove this global var
22var g_DoPenToolMouseMove = true;
23 21
24exports.PenTool = Montage.create(ShapeTool, { 22exports.PenTool = Montage.create(ShapeTool, {
25 23
@@ -35,14 +33,11 @@ exports.PenTool = Montage.create(ShapeTool, {
35 _parentNode: { enumerable: false, value: null, writable: true }, 33 _parentNode: { enumerable: false, value: null, writable: true },
36 _toolsPropertiesContainer: { enumerable: false, value: null, writable: true }, 34 _toolsPropertiesContainer: { enumerable: false, value: null, writable: true },
37 35
38 // Need to keep track of current mouse position for KEY modifiers event which do not have mouse coordinates 36 //set this to true if you want to keep making subpaths after closing current subpath (debugging only)
39 _currentX: { value: 0, writable: true }, 37 _makeMultipleSubpaths: { value: true, writable: true },
40 _currentY: { value: 0, writable: true },
41
42 //the subpaths are what is displayed on the screen currently, with _selectedSubpath being the active one currently being edited
43 _selectedSubpath: { value: null, writable: true },
44 _makeMultipleSubpaths: { value: true, writable: true }, //set this to true if you want to keep making subpaths after closing current subpath
45 38
39 //set this to false if you don't want the mouse move handler being called when the mouse is not down (debugging only)
40 _trackMouseMoveWhenUp: {value: true, writable: false},
46 41
47 //whether the user has held down the Alt key 42 //whether the user has held down the Alt key
48 _isAltDown: { value: false, writable: true }, 43 _isAltDown: { value: false, writable: true },
@@ -50,29 +45,37 @@ exports.PenTool = Montage.create(ShapeTool, {
50 //whether the user has held down the Esc key 45 //whether the user has held down the Esc key
51 _isEscapeDown: {value: false, writable: true }, 46 _isEscapeDown: {value: false, writable: true },
52 47
53 //whether we have just started a new path (set true in mousedown, and set false in mouse up 48 //whether we have just started a new path (may set true in mousedown, and always set false in mouse up
49 //todo this seems to be unnecessary
54 _isNewPath: {value: false, writable: true}, 50 _isNewPath: {value: false, writable: true},
55 51
56 //whether we have clicked one of the endpoints after entering the pen tool in ENTRY_SELECT_PATH edit mode 52 //whether we have clicked one of the endpoints after entering the pen tool in ENTRY_SELECT_PATH edit mode
57 _isPickedEndPointInSelectPathMode: {value: false, writable: true}, 53 _isPickedEndPointInSelectPathMode: {value: false, writable: true},
58 54
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 55 //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 }, 56 _snapTargetIndex: { value: -1, writable: true },
57
58 //index of the anchor point that the user has hovered over
59 _hoveredAnchorIndex: {value: -1, writable: true},
61 60
62 //whether or not we're using webgl for drawing 61 //whether or not we're using webgl for drawing (set to false until we have webgl-ready stroke and fill regions)
63 _useWebGL: {value: false, writable: false }, 62 _useWebGL: {value: false, writable: false },
64 63
65 //the canvas created by the pen tool...this is grown or shrunk with the path (if the canvas was not already provided) 64 //the _selectedSubpath is the active subpath currently being edited
66 _penCanvas: { value: null, writable: true }, 65 _selectedSubpath: { value: null, writable: true },
67 66
68 //the plane matrix for the first click...so the entire path is on the same plane 67 //the canvas for the selected subpath...this is grown or shrunk by the pen tool with the subpath (if the canvas was not already provided)
69 _penPlaneMat: { value: null, writable: true }, 68 _selectedSubpathCanvas: { value: null, writable: true },
70 69
71 //index of the anchor point that the user has hovered over 70 //the plane matrix for the first click...so the entire path is on the same plane
72 _hoveredAnchorIndex: {value: -1, writable: true}, 71 // todo this might be unnecessary as we can get this from element mediator (but that may be slow)
72 _selectedSubpathPlaneMat: { value: null, writable: true },
73 73
74 //constants used for picking points --- NOTE: these should be user-settable parameters 74 //the center of the subpath center in stageworld space
75 _PICK_POINT_RADIUS: { value: 10, writable: false }, 75 _selectedSubpathCanvasCenter: {value: null, writable: true},
76
77 //constants used for picking points --- todo: these should be user-settable parameters
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 },
@@ -86,34 +89,49 @@ exports.PenTool = Montage.create(ShapeTool, {
86 EDIT_PREV_NEXT: { value: 8, writable: false }, 89 EDIT_PREV_NEXT: { value: 8, writable: false },
87 _editMode: { value: this.EDIT_NONE, writable: true }, 90 _editMode: { value: this.EDIT_NONE, writable: true },
88 91
89 //constants used for selection modes on entry to pen tool (mutually exclusive) 92 //constants used for selection modes on entry to pen tool (mutually exclusive i.e. cannot be OR-ed)
90 ENTRY_SELECT_NONE: { value: 0, writable: false}, 93 ENTRY_SELECT_NONE: { value: 0, writable: false},
91 ENTRY_SELECT_CANVAS: { value: 1, writable: false}, 94 ENTRY_SELECT_CANVAS: { value: 1, writable: false},
92 ENTRY_SELECT_PATH: { value: 2, writable: false}, 95 ENTRY_SELECT_PATH: { value: 2, writable: false},
93 _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true}, 96 _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true},
94
95 97
98 //constants used for limiting size of the subpath canvas
99 _MAX_CANVAS_DIMENSION: {value: 3000, writable: false},
96 100
97 _getUnsnappedPosition: { 101 /*
98 value: function(x,y){ 102 // get the stage world position corresponding to the (x,y) mouse event position by querying the snap manager
103 // but temporarily turning off all snapping
104 _getMouseEventPosition : {
105 value: function(x,y, getStageWorld, doSnap){
99 var elemSnap = snapManager.elementSnapEnabled(); 106 var elemSnap = snapManager.elementSnapEnabled();
100 var gridSnap = snapManager.gridSnapEnabled(); 107 var gridSnap = snapManager.gridSnapEnabled();
101 var alignSnap = snapManager.snapAlignEnabled(); 108 var alignSnap = snapManager.snapAlignEnabled();
102 109
103 snapManager.enableElementSnap(false); 110 if (!doSnap){
104 snapManager.enableGridSnap(false); 111 snapManager.enableElementSnap(false);
105 snapManager.enableSnapAlign(false); 112 snapManager.enableGridSnap(false);
113 snapManager.enableSnapAlign(false);
114 }
106 115
107 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); 116 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y));
108 var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); 117 var pos;
118 if (getStageWorld){
119 pos = (snapManager.snap(point.x, point.y, false)).calculateStageWorldPoint();
120 } else {
121 pos = (snapManager.snap(point.x, point.y, false)).getScreenPoint();
122 }
123 var dragPlane = snapManager.getDragPlane();
109 124
110 snapManager.enableElementSnap(elemSnap); 125 if (!doSnap){
111 snapManager.enableGridSnap(gridSnap); 126 snapManager.enableElementSnap(elemSnap);
112 snapManager.enableSnapAlign(alignSnap); 127 snapManager.enableGridSnap(gridSnap);
128 snapManager.enableSnapAlign(alignSnap);
129 }
113 130
114 return unsnappedpos; 131 return [pos, dragPlane];
115 } 132 }
116 }, 133 },
134 */
117 135
118 ShowToolProperties: { 136 ShowToolProperties: {
119 value: function () { 137 value: function () {
@@ -126,6 +144,61 @@ exports.PenTool = Montage.create(ShapeTool, {
126 144
127 }, 145 },
128 146
147 //use the snap manager to build a hit record corresponding to the screen X, Y position
148 // will use the plane of the selected path as the working plane if available, else use stage
149 getHitRecord:{
150 value: function(x,y, doSnap){
151 var elemSnap = snapManager.elementSnapEnabled();
152 var gridSnap = snapManager.gridSnapEnabled();
153 var alignSnap = snapManager.snapAlignEnabled();
154
155 if (!doSnap){
156 snapManager.enableElementSnap(false);
157 snapManager.enableGridSnap(false);
158 snapManager.enableSnapAlign(false);
159 }
160
161 if (this._selectedSubpathCanvas){
162 var drawingCanvas = this._selectedSubpathCanvas;
163 var contentPlane = ViewUtils.getUnprojectedElementPlane(drawingCanvas);
164 snapManager.pushWorkingPlane(contentPlane);
165
166 }
167 var tmpPoint = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y));
168 var hitRec = snapManager.snap(tmpPoint.x, tmpPoint.y, false);
169 if (this._selectedSubpathCanvas){
170 snapManager.popWorkingPlane();
171 }
172
173 if (!doSnap){
174 snapManager.enableElementSnap(elemSnap);
175 snapManager.enableGridSnap(gridSnap);
176 snapManager.enableSnapAlign(alignSnap);
177 }
178 return hitRec;
179 }
180 },
181
182 // **********************************************************************************************************
183 // Mouse down handler
184 // IF the selected subpath is null, it means we're going to start a new subpath
185 // Create a new subpath
186 // Compute the mouse position in stage world space (lying on stage or selected subpath canvas)
187 // IF selected subpath does not have a canvas yet,
188 // IF this is the first anchor point of the selected subpath
189 // Store the plane mat and drag plane of this hit record (will be used for creating a canvas)
190 // Add the mouse position (in stage world space) as an anchor point
191 // ELSE (we may add to the selected subpath)
192 // Compute the mouse position in local (selected subpath canvas) space
193 // IF we hit the path:
194 // Either select an anchor or insert an anchor and select it
195 // (also set proper flags when select endpoint of open path in ENTRY_SELECT_PATH mode)
196 // ELSE
197 // If selected subpath is closed (and we're not in ENTRY_SELECT_PATH mode)
198 // Create a new subpath
199 // Add the mouse position (in selected subpath's local space) as an anchor point (call global to local)
200 // Draw the selected subpath anchors and the selected subpath itself in the stage's context
201 // **********************************************************************************************************
129 HandleLeftButtonDown: 202 HandleLeftButtonDown:
130 { 203 {
131 value: function (event) { 204 value: function (event) {
@@ -134,69 +207,151 @@ exports.PenTool = Montage.create(ShapeTool, {
134 //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) 207 //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2)
135 return; 208 return;
136 } 209 }
210
211 //set the drawing flags (see the drawing-tool.js base class)
137 if (thi