aboutsummaryrefslogtreecommitdiff
path: root/js/tools/PenTool.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-xjs/tools/PenTool.js362
1 files changed, 193 insertions, 169 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 779b7f16..2eae6adc 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -68,11 +68,14 @@ exports.PenTool = Montage.create(ShapeTool, {
68 //the plane matrix for the first click...so the entire path is on the same plane 68 //the plane matrix for the first click...so the entire path is on the same plane
69 _penPlaneMat: { value: null, writable: true }, 69 _penPlaneMat: { value: null, writable: true },
70 70
71 //the plane equation (in stage world space) for the current path being drawn
72 _dragPlane: {value: null, writable: true},
73
71 //index of the anchor point that the user has hovered over 74 //index of the anchor point that the user has hovered over
72 _hoveredAnchorIndex: {value: -1, writable: true}, 75 _hoveredAnchorIndex: {value: -1, writable: true},
73 76
74 //constants used for picking points --- NOTE: these should be user-settable parameters 77 //constants used for picking points --- NOTE: these should be user-settable parameters
75 _PICK_POINT_RADIUS: { value: 10, writable: false }, 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 },
@@ -105,7 +108,9 @@ exports.PenTool = Montage.create(ShapeTool, {
105 snapManager.enableSnapAlign(false); 108 snapManager.enableSnapAlign(false);
106 109
107 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); 110 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y));
111 //todo fix this function to allow us to get the correct location (in 3D) for the mouse position
108 var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); 112 var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false));
113 this._dragPlane = snapManager.getDragPlane();
109 114
110 snapManager.enableElementSnap(elemSnap); 115 snapManager.enableElementSnap(elemSnap);
111 snapManager.enableGridSnap(gridSnap); 116 snapManager.enableGridSnap(gridSnap);
@@ -214,6 +219,7 @@ exports.PenTool = Montage.create(ShapeTool, {
214 if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { 219 if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) {
215 this._penCanvas = null; 220 this._penCanvas = null;
216 this._penPlaneMat = null; 221 this._penPlaneMat = null;
222 this._dragPlane = null;
217 this._snapTarget = null; 223 this._snapTarget = null;
218 this._selectedSubpath = new SubPath(); 224 this._selectedSubpath = new SubPath();
219 this._isNewPath = true; 225 this._isNewPath = true;
@@ -278,8 +284,15 @@ exports.PenTool = Montage.create(ShapeTool, {
278 this.application.ninja.stage.clearDrawingCanvas(); 284 this.application.ninja.stage.clearDrawingCanvas();
279 this._hoveredAnchorIndex = -1; 285 this._hoveredAnchorIndex = -1;
280 286
281 //set the cursor to be the default cursor 287 //set the cursor to be the default cursor (depending on whether the selected subpath has any points yet)
282 this.application.ninja.stage.drawingCanvas.style.cursor = "auto"; 288 if (this._selectedSubpath && this._selectedSubpath.getNumAnchors()>0){
289 this.application.ninja.stage.drawingCanvas.style.cursor = //"auto";
290 "url('images/cursors/penCursors/Pen_.png') 5 1, default";
291 }
292 else {
293 this.application.ninja.stage.drawingCanvas.style.cursor = //"auto";
294 "url('images/cursors/penCursors/Pen_newPath.png') 5 1, default";
295 }
283 296
284 if (this._isDrawing) { 297 if (this._isDrawing) {
285 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); 298 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY));
@@ -348,15 +361,27 @@ exports.PenTool = Montage.create(ShapeTool, {
348 361
349 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); 362 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY);
350 if (currMousePos && this._selectedSubpath ){ 363 if (currMousePos && this._selectedSubpath ){
351 var selAnchor = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); 364 var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS);
352 if (selAnchor >=0) { 365 if (selAnchorRetCode[0] >=0) {
353 this._hoveredAnchorIndex = selAnchor; 366 this._hoveredAnchorIndex = selAnchorRetCode[0];
367 var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1;
368 var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 5 1, default";
369 if (this._selectedSubpath.getIsClosed()===false){
370 if (this._entryEditMode === this.ENTRY_SELECT_PATH && !this._isPickedEndPointInSelectPathMode && (this._hoveredAnchorIndex===0 || this._hoveredAnchorIndex===lastAnchorIndex)){
371 //if we're in SELECT_PATH mode, have not yet clicked on the end anchors, AND we hovered over one of the end anchors
372 cursor = "url('images/cursors/penCursors/Pen_append.png') 5 1, default";
373 } else if ( this._selectedSubpath.getSelectedAnchorIndex()===lastAnchorIndex && this._hoveredAnchorIndex===0) {
374 //if we've selected the last anchor and hover over the first anchor
375 cursor = "url('images/cursors/penCursors/Pen_closePath.png') 5 1, default";
376 }
377 } //if path is not closed
378 this.application.ninja.stage.drawingCanvas.style.cursor = cursor;
354 } else { 379 } else {
355 //detect if the current mouse position will hit the path 380 //detect if the current mouse position will hit the path (such that clicking here will insert a new anchor)
356 var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); 381 var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5);
357 if (pathHitTestData[0]!==-1){ 382 if (pathHitTestData[0]!==-1){
358 //change the cursor 383 //change the cursor
359 var cursor = "url('images/cursors/penAdd.png') 10 10,default"; 384 var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default";
360 this.application.ninja.stage.drawingCanvas.style.cursor = cursor; 385 this.application.ninja.stage.drawingCanvas.style.cursor = cursor;
361 } 386 }
362 } 387 }
@@ -374,22 +399,7 @@ exports.PenTool = Montage.create(ShapeTool, {
374 TranslateSelectedSubpathPerPenCanvas:{ 399 TranslateSelectedSubpathPerPenCanvas:{
375 value: function() { 400 value: function() {
376 if (this._penCanvas!==null) { 401 if (this._penCanvas!==null) {
377 //obtain the 2D translation of the canvas due to the Selection tool...assuming this is called in Configure 402 this._selectedSubpath.translateSubpathPerCanvas(ElementMediator);
378 var penCanvasLeft = parseInt(ElementMediator.getProperty(this._penCanvas, "left"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "left"));
379 var penCanvasTop = parseInt(ElementMediator.getProperty(this._penCanvas, "top"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "top"));
380 var penCanvasWidth = parseInt(ElementMediator.getProperty(this._penCanvas, "width"));//this._penCanvas.width;
381 var penCanvasHeight = parseInt(ElementMediator.getProperty(this._penCanvas, "height"));//this._penCanvas.height;
382 var penCanvasOldX = penCanvasLeft + 0.5 * penCanvasWidth;
383 var penCanvasOldY = penCanvasTop + 0.5 * penCanvasHeight;
384
385 var translateCanvasX = penCanvasOldX - this._selectedSubpath.getCanvasX();
386 var translateCanvasY = penCanvasOldY - this._selectedSubpath.getCanvasY();
387
388 //update the canvasX and canvasY parameters for this subpath and also translate the subpath points (since they're stored in stage world space)
389 this._selectedSubpath.setCanvasX(translateCanvasX + this._selectedSubpath.getCanvasX());
390 this._selectedSubpath.setCanvasY(translateCanvasY + this._selectedSubpath.getCanvasY());
391 this._selectedSubpath.translateAnchors(translateCanvasX, translateCanvasY, 0);
392 this._selectedSubpath.createSamples(); //updates the bounding box
393 } 403 }
394 } 404 }
395 }, 405 },
@@ -397,22 +407,141 @@ exports.PenTool = Montage.create(ShapeTool, {
397 ShowSelectedSubpath:{ 407 ShowSelectedSubpath:{
398 value: function() { 408 value: function() {
399 if (this._selectedSubpath){ 409 if (this._selectedSubpath){
410 this._selectedSubpath.setPlaneMatrix(this._penPlaneMat);
411 var planeMatInv = glmat4.inverse( this._penPlaneMat, [] );
412 this._selectedSubpath.setPlaneMatrixInverse(planeMatInv);
413 this._selectedSubpath.setDragPlane(this._dragPlane);
414
400 this._selectedSubpath.createSamples(); //dirty bit is checked here 415 this._selectedSubpath.createSamples(); //dirty bit is checked here
401 var bboxMin = this._selectedSubpath.getBBoxMin(); 416 this._selectedSubpath.buildLocalCoord(); //local dirty bit is checked here
402 var bboxMax = this._selectedSubpath.getBBoxMax(); 417
418 //build the width and height of this canvas by looking at local coordinates (X and Y needed only)
419 var bboxMin = this._selectedSubpath.getLocalBBoxMin();
420 var bboxMax = this._selectedSubpath.getLocalBBoxMax();
403 var bboxWidth = bboxMax[0] - bboxMin[0]; 421 var bboxWidth = bboxMax[0] - bboxMin[0];
404 var bboxHeight = bboxMax[1] - bboxMin[1]; 422 var bboxHeight = bboxMax[1] - bboxMin[1];
405 var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])];
406 423
407 this._selectedSubpath.setCanvasX(bboxMid[0]); 424 //build the 3D position of the plane center of this canvas by looking at midpoint of the bounding box in stage world coords
408 this._selectedSubpath.setCanvasY(bboxMid[1]); 425 bboxMin = this._selectedSubpath.getBBoxMin();
426 bboxMax = this._selectedSubpath.getBBoxMax();
427 var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])];
409 428
410 //call render shape with the bbox width and height 429 //call render shape with the bbox width and height
411 this.RenderShape(bboxWidth, bboxHeight, this._penPlaneMat, bboxMid, this._penCanvas); 430 this.RenderShape(bboxWidth, bboxHeight, bboxMid, this._penPlaneMat, this._penCanvas);
412 } 431 }
413 } 432 }
414 }, 433 },
415 434
435 RenderShape: {
436 value: function (w, h, midPt, planeMat, canvas) {
437 if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) {
438 return;
439 }
440
441 var left = Math.round(midPt[0] - 0.5 * w);
442 var top = Math.round(midPt[1] - 0.5 * h);
443 this._selectedSubpath.setPlaneCenter(midPt);
444 this._selectedSubpath.setCanvasLeft(left);
445 this._selectedSubpath.setCanvasTop(top);
446
447 if (!canvas) {
448 var newCanvas = null;
449 newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true);
450 var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas);
451 ElementMediator.addElement(newCanvas, elementModel.data, true);
452
453 // create all the GL stuff
454 var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial);
455 //store a reference to this newly created canvas
456 this._penCanvas = newCanvas;
457
458 var subpath = this._selectedSubpath; //new GLSubpath();
459 subpath.setWorld(world);
460 subpath.setCanvas(newCanvas);
461
462 world.addObject(subpath);
463 world.render();
464 //TODO this will not work if there are multiple shapes in the same canvas
465 newCanvas.elementModel.shapeModel.GLGeomObj = subpath;
466 newCanvas.elementModel.shapeModel.shapeCount++;
467 if(newCanvas.elementModel.shapeModel.shapeCount === 1)
468 {
469 newCanvas.elementModel.selection = "Subpath";
470 newCanvas.elementModel.pi = "SubpathPi";
471 newCanvas.elementModel.shapeModel.strokeSize = this.options.strokeSize.value + " " + this.options.strokeSize.units;
472 var strokeColor = subpath.getStrokeColor();
473 newCanvas.elementModel.shapeModel.stroke = strokeColor;
474 if(strokeColor) {
475 newCanvas.elementModel.shapeModel.border = this.application.ninja.colorController.colorToolbar.stroke;
476 }
477 newCanvas.elementModel.shapeModel.strokeMaterial = subpath.getStrokeMaterial();
478
479 newCanvas.elementModel.shapeModel.GLGeomObj = subpath;
480 newCanvas.elementModel.shapeModel.useWebGl = this.options.use3D;
481 }
482 else
483 {
484 // TODO - update the shape's info only. shapeModel will likely need an array of shapes.
485 }
486
487 //if(newCanvas.elementModel.isShape)
488 if (true)
489 {
490 this.application.ninja.selectionController.selectElement(newCanvas);
<