aboutsummaryrefslogtreecommitdiff
path: root/js/tools/PenTool.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-xjs/tools/PenTool.js357
1 files changed, 274 insertions, 83 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 10eb03c9..0532bdb3 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -33,10 +33,10 @@ exports.PenTool = Montage.create(ShapeTool, {
33 _parentNode: { enumerable: false, value: null, writable: true }, 33 _parentNode: { enumerable: false, value: null, writable: true },
34 _toolsPropertiesContainer: { enumerable: false, value: null, writable: true }, 34 _toolsPropertiesContainer: { enumerable: false, value: null, writable: true },
35 35
36 //set this to true if you want to keep making subpaths after closing current subpath (debugging only) 36 //set this to true if you want to keep making subpaths after closing current subpath (debugging only...should always be true)
37 _makeMultipleSubpaths: { value: true, writable: true }, 37 _makeMultipleSubpaths: { value: true, writable: true },
38 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) 39 //set this to false if you don't want the mouse move handler being called when the mouse is not down (debugging only...should always be true)
40 _trackMouseMoveWhenUp: {value: true, writable: false}, 40 _trackMouseMoveWhenUp: {value: true, writable: false},
41 41
42 //whether the user has held down the Alt key 42 //whether the user has held down the Alt key
@@ -95,6 +95,12 @@ exports.PenTool = Montage.create(ShapeTool, {
95 ENTRY_SELECT_PATH: { value: 2, writable: false}, 95 ENTRY_SELECT_PATH: { value: 2, writable: false},
96 _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true}, 96 _entryEditMode: {value: this.ENTRY_SELECT_NONE, writable: true},
97 97
98 //constants used for determining whether a subtool has been selected (mutually exclusive i.e. cannot be OR-ed)
99 SUBTOOL_NONE: {value: 0, writable: false},
100 SUBTOOL_PENPLUS: {value: 1, writable: false},
101 SUBTOOL_PENMINUS: {value: 2, writable: false},
102 _subtool: {value: this.SUBTOOL_NONE, writable: true},
103
98 //constants used for limiting size of the subpath canvas 104 //constants used for limiting size of the subpath canvas
99 _MAX_CANVAS_DIMENSION: {value: 3000, writable: false}, 105 _MAX_CANVAS_DIMENSION: {value: 3000, writable: false},
100 106
@@ -179,6 +185,71 @@ exports.PenTool = Montage.create(ShapeTool, {
179 } 185 }
180 }, 186 },
181 187
188 _removeSelectedSubpathAndCanvas:{
189 value: function(removeSelectedSubpath){
190 if (removeSelectedSubpath){
191 this._selectedSubpath.clearAllAnchors(); //perhaps unnecessary
192 this._selectedSubpath = null;
193 if (this._subtool === this.SUBTOOL_NONE){
194 if (this._entryEditMode === this.ENTRY_SELECT_PATH){
195 this._entryEditMode = this.ENTRY_SELECT_NONE;
196 }
197 }
198 } else {
199 this._selectedSubpath.setCanvas(null);
200 }
201 //clear the canvas
202 this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas();
203
204 //undo/redo...go through ElementController and NJEvent
205 var els = [];
206 ElementController.removeElement(this._selectedSubpathCanvas);
207 els.push(this._selectedSubpathCanvas);
208 NJevent( "elementsRemoved", els );
209 this._selectedSubpathCanvas = null;
210 }
211 },
212
213 _removeSelectedAnchorPoint:{
214 value: function(){
215 this._hoveredAnchorIndex=-1;
216 this._selectedSubpath.removeAnchor(this._selectedSubpath.getSelectedAnchorIndex());
217 if (this._selectedSubpath.getNumAnchors()===1){
218 //convert the remaining anchor point to stage world coords
219 var xDelta = snapManager.getStageWidth()*0.5;
220 var yDelta = snapManager.getStageHeight()*0.5;
221 var anchor = this._selectedSubpath.getAnchor(0);
222 var swPos = ViewUtils.localToStageWorld([anchor.getPosX(),anchor.getPosY(),anchor.getPosZ()], this._selectedSubpathCanvas);
223 anchor.setPos(swPos[0]+xDelta, swPos[1]+yDelta, swPos[2]);
224 swPos = ViewUtils.localToStageWorld([anchor.getPrevX(),anchor.getPrevY(),anchor.getPrevZ()], this._selectedSubpathCanvas);
225 anchor.setPrevPos(swPos[0]+xDelta, swPos[1]+yDelta, swPos[2]);
226 swPos = ViewUtils.localToStageWorld([anchor.getNextX(),anchor.getNextY(),anchor.getNextZ()], this._selectedSubpathCanvas);
227 anchor.setNextPos(swPos[0]+xDelta, swPos[1]+yDelta, swPos[2]);
228 }
229 //clear the canvas
230 this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas();
231 var removeSelectedSubpath=true;
232 var newNumAnchors = this._selectedSubpath.getNumAnchors();
233 if (newNumAnchors>1) {
234 this._selectedSubpath.createSamples(false);
235 this.PrepareSelectedSubpathForRendering();
236 this.ShowSelectedSubpath();
237 }
238 else {
239 //since we have 0 or 1 anchors, we will remove the selected canvas (as the path does not exist)
240 if (newNumAnchors===0){
241 removeSelectedSubpath = true;
242 } else{
243 removeSelectedSubpath = false; //don't remove the selected subpath if there is still one anchor
244 }
245 this._removeSelectedSubpathAndCanvas(removeSelectedSubpath);
246 }
247 if (!removeSelectedSubpath){
248 this.DrawSubpathAnchors(this._selectedSubpath);
249 }
250 }
251 },
252
182 // ********************************************************************************************************** 253 // **********************************************************************************************************
183 // Mouse down handler 254 // Mouse down handler
184 // IF the selected subpath is null, it means we're going to start a new subpath 255 // IF the selected subpath is null, it means we're going to start a new subpath
@@ -204,7 +275,7 @@ exports.PenTool = Montage.create(ShapeTool, {
204 value: function (event) { 275 value: function (event) {
205 //ignore any right or middle clicks 276 //ignore any right or middle clicks
206 if (event.button !== 0) { 277 if (event.button !== 0) {
207 //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) 278 //todo NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2)
208 return; 279 return;
209 } 280 }
210 281
@@ -220,6 +291,11 @@ exports.PenTool = Montage.create(ShapeTool, {
220 if (this._entryEditMode !== this.ENTRY_SELECT_PATH && this._selectedSubpath && this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { 291 if (this._entryEditMode !== this.ENTRY_SELECT_PATH && this._selectedSubpath && this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) {
221 this._selectedSubpath = null; 292 this._selectedSubpath = null;
222 } 293 }
294
295 if (this._subtool !== this.SUBTOOL_NONE && this._selectedSubpath===null) {
296 //do nothing because the pen plus and pen minus subtools need a selected subpath
297 return;
298 }
223 if (this._selectedSubpath === null) { 299 if (this._selectedSubpath === null) {
224 this._selectedSubpath = new SubPath(); 300 this._selectedSubpath = new SubPath();
225 this._selectedSubpathCanvas = null; 301 this._selectedSubpathCanvas = null;
@@ -255,12 +331,24 @@ exports.PenTool = Montage.create(ShapeTool, {
255 colorArray = [1,1,1,0]; 331 colorArray = [1,1,1,0];
256 } 332 }
257 this._selectedSubpath.setFillColor(colorArray); 333 this._selectedSubpath.setFillColor(colorArray);
258 } 334 } //if the selectedSubpath was null and needed to be constructed
259 335
260 //build the hit record for the current mouse position (on the stage or the plane of the path canvas) 336 //build the hit record for the current mouse position (on the stage or the plane of the path canvas)
261 var hitRec = this.getHitRecord(event.pageX, event.pageY, false); 337 var hitRec = this.getHitRecord(event.pageX, event.pageY, false);
262 338 var globalMousePos=null, localMousePos=null, stageWorldMousePos = null, drawingCanvas=null;
263 if (this._selectedSubpathCanvas === null){ 339 if (!this._selectedSubpathCanvas){
340 drawingCanvas = ViewUtils.getStageElement();
341 stageWorldMousePos = hitRec.calculateStageWorldPoint();
342 stageWorldMousePos[0]+= snapManager.getStageWidth()*0.5;
343 stageWorldMousePos[1]+= snapManager.getStageHeight()*0.5;
344 localMousePos = stageWorldMousePos; //since the subpath points are in stage world space, set the 'localMousePos' to be stage world as well
345 }
346 else {
347 globalMousePos = hitRec.getScreenPoint();
348 localMousePos = ViewUtils.globalToLocal(globalMousePos, this._selectedSubpathCanvas);
349 }
350
351 if (this._selectedSubpathCanvas === null && this._subtool===this.SUBTOOL_NONE){
264 //IF this is the first anchor point of the selected subpath 352 //IF this is the first anchor point of the selected subpath
265 // Store the plane mat and drag plane of this hit record (will be used for creating a canvas) 353 // Store the plane mat and drag plane of this hit record (will be used for creating a canvas)
266 // Add the mouse position (in stage world space) as an anchor point 354 // Add the mouse position (in stage world space) as an anchor point
@@ -269,18 +357,36 @@ exports.PenTool = Montage.create(ShapeTool, {
269 this._selectedSubpathPlaneMat = hitRec.getPlaneMatrix(); 357 this._selectedSubpathPlaneMat = hitRec.getPlaneMatrix();
270 } 358 }
271 359
272 //calculate the stage world position from the hit record 360 //check if the mouse click location is close to the existing anchor
273 var swMousePos = hitRec.calculateStageWorldPoint(); 361 var indexAndCode = this._selectedSubpath.pickAnchor(stageWorldMousePos[0], stageWorldMousePos[1], stageWorldMousePos[2], this._PICK_POINT_RADIUS);
274 swMousePos[0]+= snapManager.getStageWidth()*0.5; swMousePos[1]+= snapManager.getStageHeight()*0.5; 362 if (indexAndCode[0]>=0){
275 363 //the anchor point was hit, so we do not add another anchor
276 this._selectedSubpath.addAnchor(new AnchorPoint()); 364 switch(indexAndCode[1]){
277 var newAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex()); 365 case this._selectedSubpath.SEL_ANCHOR:
278 newAnchor.setPos(swMousePos[0], swMousePos[1], swMousePos[2]); 366 this._editMode = this.EDIT_ANCHOR;
279 newAnchor.setPrevPos(swMousePos[0], swMousePos[1], swMousePos[2]); 367 break;
280 newAnchor.setNextPos(swMousePos[0], swMousePos[1], swMousePos[2]); 368 case this._selectedSubpath.SEL_PREV:
281 //set the mode so that dragging will update the next and previous locations 369 this._editMode = this.EDIT_PREV;
282 this._editMode = this.EDIT_PREV_NEXT; 370 break;
283 } 371 case this._selectedSubpath.SEL_NEXT:
372 this._editMode = this.EDIT_NEXT;
373 break;
374 default:
375 this._editMode = this.EDIT_ANCHOR;
376 console.log("WARNING picked anchor point with incorrect mode");
377 break;
378 }
379
380 } else {
381 this._selectedSubpath.addAnchor(new AnchorPoint());
382 var newAnchor = this._selectedSubpath.getAnchor(this._selectedSubpath.getSelectedAnchorIndex());
383 newAnchor.setPos(stageWorldMousePos[0], stageWorldMousePos[1], stageWorldMousePos[2]);
384 newAnchor.setPrevPos(stageWorldMousePos[0], stageWorldMousePos[1], stageWorldMousePos[2]);
385 newAnchor.setNextPos(stageWorldMousePos[0], stageWorldMousePos[1], stageWorldMousePos[2]);
386 //set the mode so that dragging will update the next and previous locations
387 this._editMode = this.EDIT_PREV_NEXT;
388 }
389 } //if we have not yet created a canvas for this path
284 390
285 //the selected subpath has a canvas, so test within that canvas' space 391 //the selected subpath has a canvas, so test within that canvas' space
286 else 392 else
@@ -295,10 +401,6 @@ exports.PenTool = Montage.create(ShapeTool, {
295 // Create a new subpath 401 // Create a new subpath
296 // Add the mouse position (in selected subpath's local space) as an anchor point (call global to local) 402 // Add the mouse position (in selected subpath's local space) as an anchor point (call global to local)
297 403
298 // Compute the mouse position in local (selected subpath canvas) space
299 var globalPos = hitRec.getScreenPoint();
300 var localMousePos = ViewUtils.globalToLocal(globalPos, this._selectedSubpathCanvas);
301
302 //now perform the hit testing 404 //now perform the hit testing
303 var prevSelectedAnchorIndex = this._selectedSubpath.getSelectedAnchorIndex(); 405 var prevSelectedAnchorIndex = this._selectedSubpath.getSelectedAnchorIndex();
304 var selAnchorAndParamAndCode = this._selectedSubpath.pickPath(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS, false); 406 var selAnchorAndParamAndCode = this._selectedSubpath.pickPath(localMousePos[0], localMousePos[1], localMousePos[2], this._PICK_POINT_RADIUS, false);
@@ -311,6 +413,15 @@ exports.PenTool = Montage.create(ShapeTool, {
311 if (whichPoint !== this._selectedSubpath.SEL_NONE){ 413 if (whichPoint !== this._selectedSubpath.SEL_NONE){
312 //if we hit the anchor point itself 414 //if we hit the anchor point itself