aboutsummaryrefslogtreecommitdiff
path: root/js/tools/PenTool.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/tools/PenTool.js')
-rwxr-xr-xjs/tools/PenTool.js553
1 files changed, 323 insertions, 230 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js
index 4a16a491..61a254ea 100755
--- a/js/tools/PenTool.js
+++ b/js/tools/PenTool.js
@@ -14,7 +14,7 @@ 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
@@ -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 },
@@ -106,6 +109,7 @@ exports.PenTool = Montage.create(ShapeTool, {
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));
108 var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); 111 var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false));
112 this._dragPlane = snapManager.getDragPlane();
109 113
110 snapManager.enableElementSnap(elemSnap); 114 snapManager.enableElementSnap(elemSnap);
111 snapManager.enableGridSnap(gridSnap); 115 snapManager.enableGridSnap(gridSnap);
@@ -214,6 +218,7 @@ exports.PenTool = Montage.create(ShapeTool, {
214 if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { 218 if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) {
215 this._penCanvas = null; 219 this._penCanvas = null;
216 this._penPlaneMat = null; 220 this._penPlaneMat = null;
221 this._dragPlane = null;
217 this._snapTarget = null; 222 this._snapTarget = null;
218 this._selectedSubpath = new SubPath(); 223 this._selectedSubpath = new SubPath();
219 this._isNewPath = true; 224 this._isNewPath = true;
@@ -278,8 +283,15 @@ exports.PenTool = Montage.create(ShapeTool, {
278 this.application.ninja.stage.clearDrawingCanvas(); 283 this.application.ninja.stage.clearDrawingCanvas();
279 this._hoveredAnchorIndex = -1; 284 this._hoveredAnchorIndex = -1;
280 285
281 //set the cursor to be the default cursor 286 //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"; 287 if (this._selectedSubpath && this._selectedSubpath.getNumAnchors()>0){
288 this.application.ninja.stage.drawingCanvas.style.cursor = //"auto";
289 "url('images/cursors/penCursors/Pen_.png') 5 1, default";
290 }
291 else {
292 this.application.ninja.stage.drawingCanvas.style.cursor = //"auto";
293 "url('images/cursors/penCursors/Pen_newPath.png') 5 1, default";
294 }
283 295
284 if (this._isDrawing) { 296 if (this._isDrawing) {
285 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); 297 var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY));
@@ -339,6 +351,10 @@ exports.PenTool = Montage.create(ShapeTool, {
339 351
340 //make the subpath dirty so it will get re-drawn 352 //make the subpath dirty so it will get re-drawn
341 this._selectedSubpath.makeDirty(); 353 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){
342 this.DrawSubpathSVG(this._selectedSubpath); 358 this.DrawSubpathSVG(this._selectedSubpath);
343 } 359 }
344 360
@@ -348,15 +364,27 @@ exports.PenTool = Montage.create(ShapeTool, {
348 364
349 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); 365 var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY);
350 if (currMousePos && this._selectedSubpath ){ 366 if (currMousePos && this._selectedSubpath ){
351 var selAnchor = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); 367 var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS);
352 if (selAnchor >=0) { 368 if (selAnchorRetCode[0] >=0) {
353 this._hoveredAnchorIndex = selAnchor; 369 this._hoveredAnchorIndex = selAnchorRetCode[0];
370 var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1;
371 var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 5 1, default";
372 if (this._selectedSubpath.getIsClosed()===false){
373 if (this._entryEditMode === this.ENTRY_SELECT_PATH && !this._isPickedEndPointInSelectPathMode && (this._hoveredAnchorIndex===0 || this._hoveredAnchorIndex===lastAnchorIndex)){
374 //if we're in SELECT_PATH mode, have not yet clicked on the end anchors, AND we hovered over one of the end anchors
375 cursor = "url('images/cursors/penCursors/Pen_append.png') 5 1, default";
376 } else if ( this._selectedSubpath.getSelectedAnchorIndex()===lastAnchorIndex && this._hoveredAnchorIndex===0) {
377 //if we've selected the last anchor and hover over the first anchor
378 cursor = "url('images/cursors/penCursors/Pen_closePath.png') 5 1, default";
379 }
380 } //if path is not closed
381 this.application.ninja.stage.drawingCanvas.style.cursor = cursor;
354 } else { 382 } else {
355 //detect if the current mouse position will hit the path 383 //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); 384 var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5);
357 if (pathHitTestData[0]!==-1){ 385 if (pathHitTestData[0]!==-1){
358 //change the cursor 386 //change the cursor
359 var cursor = "url('images/cursors/penAdd.png') 10 10,default"; 387 var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default";
360 this.application.ninja.stage.drawingCanvas.style.cursor = cursor; 388 this.application.ninja.stage.drawingCanvas.style.cursor = cursor;
361 } 389 }
362 } 390 }
@@ -374,22 +402,7 @@ exports.PenTool = Montage.create(ShapeTool, {
374 TranslateSelectedSubpathPerPenCanvas:{ 402 TranslateSelectedSubpathPerPenCanvas:{
375 value: function() { 403 value: function() {
376 if (this._penCanvas!==null) { 404 if (this._penCanvas!==null) {
377 //obtain the 2D translation of the canvas due to the Selection tool...assuming this is called in Configure 405 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 } 406 }
394 } 407 }
395 }, 408 },
@@ -397,22 +410,143 @@ exports.PenTool = Montage.create(ShapeTool, {
397 ShowSelectedSubpath:{ 410 ShowSelectedSubpath:{
398 value: function() { 411 value: function() {
399 if (this._selectedSubpath){ 412 if (this._selectedSubpath){
413 if (!this._selectedSubpath.getPlaneMatrix()) {
414 this._selectedSubpath.setPlaneMatrix(this._penPlaneMat);
415 var planeMatInv = glmat4.inverse( this._penPlaneMat, [] );
416 this._selectedSubpath.setPlaneMatrixInverse(planeMatInv);
417 this._selectedSubpath.setDragPlane(this._dragPlane);
418 }
419
400 this._selectedSubpath.createSamples(); //dirty bit is checked here 420 this._selectedSubpath.createSamples(); //dirty bit is checked here
401 var bboxMin = this._selectedSubpath.getBBoxMin(); 421 this._selectedSubpath.buildLocalCoord(); //local dirty bit is checked here
402 var bboxMax = this._selectedSubpath.getBBoxMax(); 422
423 //build the width and height of this canvas by looking at local coordinates (X and Y needed only)
424 var bboxMin = this._selectedSubpath.getLocalBBoxMin();
425 var bboxMax = this._selectedSubpath.getLocalBBoxMax();
403 var bboxWidth = bboxMax[0] - bboxMin[0]; 426 var bboxWidth = bboxMax[0] - bboxMin[0];
404 var bboxHeight = bboxMax[1] - bboxMin[1]; 427 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 428
407 this._selectedSubpath.setCanvasX(bboxMid[0]); 429 //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]); 430 bboxMin = this._selectedSubpath.getBBoxMin();
431 bboxMax = this._selectedSubpath.getBBoxMax();
432 var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])];
409 433
410 //call render shape with the bbox width and height 434 //call render shape with the bbox width and height
411 this.RenderShape(bboxWidth, bboxHeight, this._penPlaneMat, bboxMid, this._penCanvas); 435 this.RenderShape(bboxWidth, bboxHeight, bboxMid, this._penPlaneMat, this._penCanvas);
412 } 436 }
413 } 437 }
414 }, 438 },
415 439
440 RenderShape: {
441 value: function (w, h, midPt, planeMat, canvas) {
442 if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) {
443 return;
444 }
445
446 var left = Math.round(midPt[0] - 0.5 * w);
447 var top = Math.round(midPt[1] - 0.5 * h);
448 this._selectedSubpath.setPlaneCenter(midPt);
449 this._selectedSubpath.setCanvasLeft(left);
450 this._selectedSubpath.setCanvasTop(top);
451
452 if (!canvas) {
453 var newCanvas = null;
454 newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true);
455 var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas);
456 ElementMediator.addElements(newCanvas, elementModel.data, false);
457
458 // create all the GL stuff
459 var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial);
460 //store a reference to this newly created canvas
461 this._penCanvas = newCanvas;
462
463 var subpath = this._selectedSubpath; //new GLSubpath();
464 subpath.setWorld(world);
465 subpath.setCanvas(newCanvas);
466
467 world.addObject(subpath);
468 world.render();
469 //TODO this will not work if there are multiple shapes in the same canvas
470 newCanvas.elementModel.shapeModel.GLGeomObj = subpath;
471