From 3fd098981077e40841c013a8ac305036d08a215b Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 27 Mar 2012 15:40:37 -0700 Subject: added cursors to the pen tool UI AND change cursor when the user hovers over an anchor point or handles of thte selected anchor --- js/tools/PenTool.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 779b7f16..39a1b15a 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -348,16 +348,17 @@ exports.PenTool = Montage.create(ShapeTool, { var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); if (currMousePos && this._selectedSubpath ){ - var selAnchor = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); - if (selAnchor >=0) { - this._hoveredAnchorIndex = selAnchor; + var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); + if (selAnchorRetCode[0] >=0) { + this._hoveredAnchorIndex = selAnchorRetCode[0]; + var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 0 0, default"; + this.application.ninja.stage.drawingCanvas.style.cursor = cursor; } else { //detect if the current mouse position will hit the path var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); if (pathHitTestData[0]!==-1){ //change the cursor - var cursor = "url('images/cursors/penAdd.png') 10 10,default"; - this.application.ninja.stage.drawingCanvas.style.cursor = cursor; + } } } -- cgit v1.2.3 From f0433bb5dfc0e4cd759efd398f84e9cb7ca548b0 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Wed, 28 Mar 2012 14:14:34 -0700 Subject: change cursors for pen tool realtime feedback....still need to position the cursors correctly over the exact mouse position AND reduce the radius (distance threshold) for picking paths --- js/tools/PenTool.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 39a1b15a..57da4698 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -72,7 +72,7 @@ exports.PenTool = Montage.create(ShapeTool, { _hoveredAnchorIndex: {value: -1, writable: true}, //constants used for picking points --- NOTE: these should be user-settable parameters - _PICK_POINT_RADIUS: { value: 10, writable: false }, + _PICK_POINT_RADIUS: { value: 4, writable: false }, _DISPLAY_ANCHOR_RADIUS: { value: 5, writable: false }, _DISPLAY_SELECTED_ANCHOR_RADIUS: { value: 10, writable: false }, _DISPLAY_SELECTED_ANCHOR_PREV_RADIUS: { value: 2, writable: false }, @@ -279,7 +279,8 @@ exports.PenTool = Montage.create(ShapeTool, { this._hoveredAnchorIndex = -1; //set the cursor to be the default cursor - this.application.ninja.stage.drawingCanvas.style.cursor = "auto"; + this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; + "url('images/cursors/penCursors/Pen_newPath.png') 0 0, default"; if (this._isDrawing) { var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); @@ -351,14 +352,25 @@ exports.PenTool = Montage.create(ShapeTool, { var selAnchorRetCode = this._selectedSubpath.pickAnchor(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); if (selAnchorRetCode[0] >=0) { this._hoveredAnchorIndex = selAnchorRetCode[0]; + var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1; var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 0 0, default"; + if (this._selectedSubpath.getIsClosed()===false){ + if (this._entryEditMode === this.ENTRY_SELECT_PATH && !this._isPickedEndPointInSelectPathMode && (this._hoveredAnchorIndex===0 || this._hoveredAnchorIndex===lastAnchorIndex)){ + //if we're in SELECT_PATH mode, have not yet clicked on the end anchors, AND we hovered over one of the end anchors + cursor = "url('images/cursors/penCursors/Pen_append.png') 0 0, default"; + } else if ( this._selectedSubpath.getSelectedAnchorIndex()===lastAnchorIndex && this._hoveredAnchorIndex===0) { + //if we've selected the last anchor and hover over the first anchor + cursor = "url('images/cursors/penCursors/Pen_closePath.png') 0 0, default"; + } + } //if path is not closed this.application.ninja.stage.drawingCanvas.style.cursor = cursor; } else { - //detect if the current mouse position will hit the path - var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS); + //detect if the current mouse position will hit the path (such that clicking here will insert a new anchor) + var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5); if (pathHitTestData[0]!==-1){ //change the cursor - + var cursor = "url('images/cursors/penCursors/Pen_plus.png') 0 0, default"; + this.application.ninja.stage.drawingCanvas.style.cursor = cursor; } } } -- cgit v1.2.3 From defde265799bb8d6826bb368f04168612e7feb5a Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Wed, 28 Mar 2012 15:29:57 -0700 Subject: adjust the position for the pen tool feedback cursor AND fix a bug where everything selected gets deleted (even if we have a selected subpath) --- js/tools/PenTool.js | 98 +++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 45 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 57da4698..31dadb80 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -278,9 +278,15 @@ exports.PenTool = Montage.create(ShapeTool, { this.application.ninja.stage.clearDrawingCanvas(); this._hoveredAnchorIndex = -1; - //set the cursor to be the default cursor - this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; - "url('images/cursors/penCursors/Pen_newPath.png') 0 0, default"; + //set the cursor to be the default cursor (depending on whether the selected subpath has any points yet) + if (this._selectedSubpath && this._selectedSubpath.getNumAnchors()>0){ + this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; + "url('images/cursors/penCursors/Pen_.png') 5 1, default"; + } + else { + this.application.ninja.stage.drawingCanvas.style.cursor = //"auto"; + "url('images/cursors/penCursors/Pen_newPath.png') 5 1, default"; + } if (this._isDrawing) { var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(event.pageX, event.pageY)); @@ -353,14 +359,14 @@ exports.PenTool = Montage.create(ShapeTool, { if (selAnchorRetCode[0] >=0) { this._hoveredAnchorIndex = selAnchorRetCode[0]; var lastAnchorIndex = this._selectedSubpath.getNumAnchors()-1; - var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 0 0, default"; + var cursor = "url('images/cursors/penCursors/Pen_anchorSelect.png') 5 1, default"; if (this._selectedSubpath.getIsClosed()===false){ if (this._entryEditMode === this.ENTRY_SELECT_PATH && !this._isPickedEndPointInSelectPathMode && (this._hoveredAnchorIndex===0 || this._hoveredAnchorIndex===lastAnchorIndex)){ //if we're in SELECT_PATH mode, have not yet clicked on the end anchors, AND we hovered over one of the end anchors - cursor = "url('images/cursors/penCursors/Pen_append.png') 0 0, default"; + cursor = "url('images/cursors/penCursors/Pen_append.png') 5 1, default"; } else if ( this._selectedSubpath.getSelectedAnchorIndex()===lastAnchorIndex && this._hoveredAnchorIndex===0) { //if we've selected the last anchor and hover over the first anchor - cursor = "url('images/cursors/penCursors/Pen_closePath.png') 0 0, default"; + cursor = "url('images/cursors/penCursors/Pen_closePath.png') 5 1, default"; } } //if path is not closed this.application.ninja.stage.drawingCanvas.style.cursor = cursor; @@ -369,7 +375,7 @@ exports.PenTool = Montage.create(ShapeTool, { var pathHitTestData = this._selectedSubpath.pathHitTest(currMousePos[0], currMousePos[1], currMousePos[2], this._PICK_POINT_RADIUS*0.5); if (pathHitTestData[0]!==-1){ //change the cursor - var cursor = "url('images/cursors/penCursors/Pen_plus.png') 0 0, default"; + var cursor = "url('images/cursors/penCursors/Pen_plus.png') 5 1, default"; this.application.ninja.stage.drawingCanvas.style.cursor = cursor; } } @@ -638,7 +644,8 @@ exports.PenTool = Montage.create(ShapeTool, { // TODO - update the shape's info only. shapeModel will likely need an array of shapes. } - if(newCanvas.elementModel.isShape) + //if(newCanvas.elementModel.isShape) + if (true) { this.application.ninja.selectionController.selectElement(newCanvas); } @@ -681,6 +688,12 @@ exports.PenTool = Montage.create(ShapeTool, { //TODO this will not work if there are multiple shapes in the same canvas canvas.elementModel.shapeModel.GLGeomObj = subpath; + + //if(newCanvas.elementModel.isShape) + if (true) + { + this.application.ninja.selectionController.selectElement(canvas); + } } //else of if (!canvas) { } //value: function (w, h, planeMat, midPt, canvas) { }, //RenderShape: { @@ -1047,37 +1060,32 @@ exports.PenTool = Montage.create(ShapeTool, { handleDelete:{ value: function(event){ - var len = this.application.ninja.selectedElements.length; - if (len===0) { - //clear the selected subpath...the only new additions to this function w.r.t. ToolBase - if (this._selectedSubpath){ - if (this._selectedSubpath.getSelectedAnchorIndex()>=0){ - this._hoveredAnchorIndex=-1; - this._selectedSubpath.removeAnchor(this._selectedSubpath.getSelectedAnchorIndex()); - this._selectedSubpath.createSamples(); - //clear the canvas - this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); - this.DrawSubpathAnchors(this._selectedSubpath); - this.ShowSelectedSubpath(); - } - else { - this._selectedSubpath.clearAllAnchors(); //perhaps unnecessary - this._selectedSubpath = null; - //clear the canvas - this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); - - //undo/redo...go through ElementController and NJEvent - var els = []; - ElementController.removeElement(this._penCanvas); - els.push(this._penCanvas); - NJevent( "deleteSelection", els ); - this._penCanvas = null; - } + //clear the selected subpath...the only new additions to this function w.r.t. ToolBase + if (this._selectedSubpath){ + if (this._selectedSubpath.getSelectedAnchorIndex()>=0){ + this._hoveredAnchorIndex=-1; + this._selectedSubpath.removeAnchor(this._selectedSubpath.getSelectedAnchorIndex()); + this._selectedSubpath.createSamples(); + //clear the canvas + this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); + this.DrawSubpathAnchors(this._selectedSubpath); + this.ShowSelectedSubpath(); } - //do nothing if there was no selected subpath and if there was no selection + else { + this._selectedSubpath.clearAllAnchors(); //perhaps unnecessary + this._selectedSubpath = null; + //clear the canvas + this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); + + //undo/redo...go through ElementController and NJEvent + var els = []; + ElementController.removeElement(this._penCanvas); + els.push(this._penCanvas); + NJevent( "deleteSelection", els ); + this._penCanvas = null; + } } else { - //undo/redo...go through ElementMediator (see ElementMediator.handleDeleting() from where the much of this function is copied) //clear the canvas this.application.ninja.stage.clearDrawingCanvas();//stageManagerModule.stageManager.clearDrawingCanvas(); @@ -1090,15 +1098,15 @@ exports.PenTool = Montage.create(ShapeTool, { } NJevent( "deleteSelection", els ); - //clear out the selected path if it exists - if (this._selectedSubpath) { - this._selectedSubpath.clearAllAnchors(); - this._selectedSubpath = null; - if (this._entryEditMode === this.ENTRY_SELECT_PATH){ - this._entryEditMode = this.ENTRY_SELECT_NONE; - } - this._penCanvas = null; - } + //clear out the selected path if it exists + if (this._selectedSubpath) { + this._selectedSubpath.clearAllAnchors(); + this._selectedSubpath = null; + if (this._entryEditMode === this.ENTRY_SELECT_PATH){ + this._entryEditMode = this.ENTRY_SELECT_NONE; + } + this._penCanvas = null; + } } //redraw the stage to update it this.application.ninja.stage.draw(); -- cgit v1.2.3 From 878743cbbb75f2fc84855ca27779597b67ab1a95 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Mon, 2 Apr 2012 15:25:00 -0700 Subject: render the pen path with local coordinates, but use stage world coordinates to position the canvas on which the path is rendered AND add data-montage- to the ids in the pen and brush reels AND fix a bug with pen stroke transparency not working --- js/tools/PenTool.js | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 31dadb80..98423113 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -416,18 +416,30 @@ exports.PenTool = Montage.create(ShapeTool, { ShowSelectedSubpath:{ value: function() { if (this._selectedSubpath){ + this._selectedSubpath.setPlaneMatrix(this._penPlaneMat); + var planeMatInv = glmat4.inverse( this._penPlaneMat, [] ); + this._selectedSubpath.setPlaneMatrixInverse(planeMatInv); + this._selectedSubpath.createSamples(); //dirty bit is checked here - var bboxMin = this._selectedSubpath.getBBoxMin(); - var bboxMax = this._selectedSubpath.getBBoxMax(); + this._selectedSubpath.buildLocalCoord(); //local dirty bit is checked here + + //build the width and height of this canvas by looking at local coordinates (X and Y needed only) + var bboxMin = this._selectedSubpath.getLocalBBoxMin(); + var bboxMax = this._selectedSubpath.getLocalBBoxMax(); var bboxWidth = bboxMax[0] - bboxMin[0]; var bboxHeight = bboxMax[1] - bboxMin[1]; + + //build the 3D position of the plane center of this canvas by looking at midpoint of the bounding box in stage world coords + bboxMin = this._selectedSubpath.getBBoxMin(); + bboxMax = this._selectedSubpath.getBBoxMax(); var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; + this._selectedSubpath.setPlaneCenter(bboxMid); this._selectedSubpath.setCanvasX(bboxMid[0]); this._selectedSubpath.setCanvasY(bboxMid[1]); //call render shape with the bbox width and height - this.RenderShape(bboxWidth, bboxHeight, this._penPlaneMat, bboxMid, this._penCanvas); + this.RenderShape(bboxWidth, bboxHeight, bboxMid, this._penPlaneMat, this._penCanvas); } } }, @@ -592,7 +604,7 @@ exports.PenTool = Montage.create(ShapeTool, { }, RenderShape: { - value: function (w, h, planeMat, midPt, canvas) { + value: function (w, h, midPt, planeMat, canvas) { if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { return; } @@ -614,10 +626,6 @@ exports.PenTool = Montage.create(ShapeTool, { var subpath = this._selectedSubpath; //new GLSubpath(); subpath.setWorld(world); subpath.setCanvas(newCanvas); - subpath.setPlaneMatrix(planeMat); - var planeMatInv = glmat4.inverse( planeMat, [] ); - subpath.setPlaneMatrixInverse(planeMatInv); - subpath.setPlaneCenter(midPt); world.addObject(subpath); world.render(); @@ -662,11 +670,19 @@ exports.PenTool = Montage.create(ShapeTool, { if (this._entryEditMode !== this.ENTRY_SELECT_CANVAS){ //update the left and top of the canvas element var canvasArray=[canvas]; - ElementMediator.setProperty(canvasArray, "left", [parseInt(left)+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); - ElementMediator.setProperty(canvasArray, "top", [parseInt(top) + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); + w= Math.round(w); + h = Math.round(h); ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; - //update the viewport and projection to reflect the new canvas width and height + + //var bboxMid = this._selectedSubpath.getLocalBBoxMidInStageWorld(); + //left = Math.round(bboxMid[0] - 0.5 * w); + //top = Math.round(bboxMid[1] - 0.5 * h); + + ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); + ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); + + //update the viewport and projection to reflect the new canvas width and height (todo might be unnecessary since we don't use RDGE for now) world.setViewportFromCanvas(canvas); if (this._useWebGL){ var cam = world.renderer.cameraManager().getActiveCamera(); @@ -677,10 +693,6 @@ exports.PenTool = Montage.create(ShapeTool, { var subpath = this._selectedSubpath; subpath.setDrawingTool(this); - subpath.setPlaneMatrix(planeMat); - var planeMatInv = glmat4.inverse( planeMat, [] ); - subpath.setPlaneMatrixInverse(planeMatInv); - subpath.setPlaneCenter(midPt); subpath.setWorld(world); world.addIfNewObject(subpath); @@ -829,6 +841,7 @@ exports.PenTool = Montage.create(ShapeTool, { ctx.strokeStyle = "green"; //if (subpath.getStrokeColor()) // ctx.strokeStyle = MathUtils.colorToHex( subpath.getStrokeColor() ); + ctx.beginPath(); var p0x = subpath.getAnchor(0).getPosX()+ horizontalOffset; var p0y = subpath.getAnchor(0).getPosY()+ verticalOffset; @@ -881,7 +894,6 @@ exports.PenTool = Montage.create(ShapeTool, { ctx.strokeStyle = "green"; var anchorDelta = 2; var selAnchorDelta = 4; - for (var i = 0; i < numAnchors; i++) { var px = subpath.getAnchor(i).getPosX(); var py = subpath.getAnchor(i).getPosY(); -- cgit v1.2.3 From c838f85d28acbf2fe208a4358aef9cac73b65fbc Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 3 Apr 2012 10:14:49 -0700 Subject: First attempt at preventing the drifting of the canvas due to floating point roundoff errors when constantly changing stroke width --- js/tools/PenTool.js | 231 ++++++++++++++++++++++++---------------------------- 1 file changed, 108 insertions(+), 123 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 98423113..0dbefd16 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -393,22 +393,7 @@ exports.PenTool = Montage.create(ShapeTool, { TranslateSelectedSubpathPerPenCanvas:{ value: function() { if (this._penCanvas!==null) { - //obtain the 2D translation of the canvas due to the Selection tool...assuming this is called in Configure - var penCanvasLeft = parseInt(ElementMediator.getProperty(this._penCanvas, "left"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "left")); - var penCanvasTop = parseInt(ElementMediator.getProperty(this._penCanvas, "top"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "top")); - var penCanvasWidth = parseInt(ElementMediator.getProperty(this._penCanvas, "width"));//this._penCanvas.width; - var penCanvasHeight = parseInt(ElementMediator.getProperty(this._penCanvas, "height"));//this._penCanvas.height; - var penCanvasOldX = penCanvasLeft + 0.5 * penCanvasWidth; - var penCanvasOldY = penCanvasTop + 0.5 * penCanvasHeight; - - var translateCanvasX = penCanvasOldX - this._selectedSubpath.getCanvasX(); - var translateCanvasY = penCanvasOldY - this._selectedSubpath.getCanvasY(); - - //update the canvasX and canvasY parameters for this subpath and also translate the subpath points (since they're stored in stage world space) - this._selectedSubpath.setCanvasX(translateCanvasX + this._selectedSubpath.getCanvasX()); - this._selectedSubpath.setCanvasY(translateCanvasY + this._selectedSubpath.getCanvasY()); - this._selectedSubpath.translateAnchors(translateCanvasX, translateCanvasY, 0); - this._selectedSubpath.createSamples(); //updates the bounding box + this._selectedSubpath.translateSubpathPerCanvas(ElementMediator); } } }, @@ -444,6 +429,113 @@ exports.PenTool = Montage.create(ShapeTool, { } }, + RenderShape: { + value: function (w, h, midPt, planeMat, canvas) { + if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { + return; + } + + var left = Math.round(midPt[0] - 0.5 * w); + var top = Math.round(midPt[1] - 0.5 * h); + + if (!canvas) { + var newCanvas = null; + newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); + var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas); + ElementMediator.addElement(newCanvas, elementModel.data, true); + + // create all the GL stuff + var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial); + //store a reference to this newly created canvas + this._penCanvas = newCanvas; + + var subpath = this._selectedSubpath; //new GLSubpath(); + subpath.setWorld(world); + subpath.setCanvas(newCanvas); + + world.addObject(subpath); + world.render(); + //TODO this will not work if there are multiple shapes in the same canvas + newCanvas.elementModel.shapeModel.GLGeomObj = subpath; + newCanvas.elementModel.shapeModel.shapeCount++; + if(newCanvas.elementModel.shapeModel.shapeCount === 1) + { + newCanvas.elementModel.selection = "Subpath"; + newCanvas.elementModel.pi = "SubpathPi"; + newCanvas.elementModel.shapeModel.strokeSize = this.options.strokeSize.value + " " + this.options.strokeSize.units; + var strokeColor = subpath.getStrokeColor(); + newCanvas.elementModel.shapeModel.stroke = strokeColor; + if(strokeColor) { + newCanvas.elementModel.shapeModel.border = this.application.ninja.colorController.colorToolbar.stroke; + } + newCanvas.elementModel.shapeModel.strokeMaterial = subpath.getStrokeMaterial(); + + newCanvas.elementModel.shapeModel.GLGeomObj = subpath; + newCanvas.elementModel.shapeModel.useWebGl = this.options.use3D; + } + else + { + // TODO - update the shape's info only. shapeModel will likely need an array of shapes. + } + + //if(newCanvas.elementModel.isShape) + if (true) + { + this.application.ninja.selectionController.selectElement(newCanvas); + } + } //if (!canvas) { + else { + + var world = null; + if (canvas.elementModel.shapeModel && canvas.elementModel.shapeModel.GLWorld) { + world = canvas.elementModel.shapeModel.GLWorld; + } else { + world = this.getGLWorld(canvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, canvas, this._useWebGL);//fillMaterial, strokeMaterial); + } + + if (this._entryEditMode !== this.ENTRY_SELECT_CANVAS){ + //update the left and top of the canvas element + var canvasArray=[canvas]; + w= Math.round(w); + h = Math.round(h); + ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; + ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; + + //var bboxMid = this._selectedSubpath.getLocalBBoxMidInStageWorld(); + //left = Math.round(bboxMid[0] - 0.5 * w); + //top = Math.round(bboxMid[1] - 0.5 * h); + + ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); + ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); + + //update the viewport and projection to reflect the new canvas width and height (todo might be unnecessary since we don't use RDGE for now) + world.setViewportFromCanvas(canvas); + if (this._useWebGL){ + var cam = world.renderer.cameraManager().getActiveCamera(); + cam.setPerspective(world.getFOV(), world.getAspect(), world.getZNear(), world.getZFar()); + } + } + + var subpath = this._selectedSubpath; + + subpath.setDrawingTool(this); + subpath.setWorld(world); + + world.addIfNewObject(subpath); + world.render(); + + //TODO this will not work if there are multiple shapes in the same canvas + canvas.elementModel.shapeModel.GLGeomObj = subpath; + + //if(newCanvas.elementModel.isShape) + if (true) + { + this.application.ninja.selectionController.selectElement(canvas); + } + } //else of if (!canvas) { + } //value: function (w, h, planeMat, midPt, canvas) { + }, //RenderShape: { + HandleLeftButtonUp: { value: function (event) { if (this._isAltDown) { @@ -603,113 +695,6 @@ exports.PenTool = Montage.create(ShapeTool, { } }, - RenderShape: { - value: function (w, h, midPt, planeMat, canvas) { - if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { - return; - } - - var left = Math.round(midPt[0] - 0.5 * w); - var top = Math.round(midPt[1] - 0.5 * h); - - if (!canvas) { - var newCanvas = null; - newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); - var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas); - ElementMediator.addElement(newCanvas, elementModel.data, true); - - // create all the GL stuff - var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial); - //store a reference to this newly created canvas - this._penCanvas = newCanvas; - - var subpath = this._selectedSubpath; //new GLSubpath(); - subpath.setWorld(world); - subpath.setCanvas(newCanvas); - - world.addObject(subpath); - world.render(); - //TODO this will not work if there are multiple shapes in the same canvas - newCanvas.elementModel.shapeModel.GLGeomObj = subpath; - newCanvas.elementModel.shapeModel.shapeCount++; - if(newCanvas.elementModel.shapeModel.shapeCount === 1) - { - newCanvas.elementModel.selection = "Subpath"; - newCanvas.elementModel.pi = "SubpathPi"; - newCanvas.elementModel.shapeModel.strokeSize = this.options.strokeSize.value + " " + this.options.strokeSize.units; - var strokeColor = subpath.getStrokeColor(); - newCanvas.elementModel.shapeModel.stroke = strokeColor; - if(strokeColor) { - newCanvas.elementModel.shapeModel.border = this.application.ninja.colorController.colorToolbar.stroke; - } - newCanvas.elementModel.shapeModel.strokeMaterial = subpath.getStrokeMaterial(); - - newCanvas.elementModel.shapeModel.GLGeomObj = subpath; - newCanvas.elementModel.shapeModel.useWebGl = this.options.use3D; - } - else - { - // TODO - update the shape's info only. shapeModel will likely need an array of shapes. - } - - //if(newCanvas.elementModel.isShape) - if (true) - { - this.application.ninja.selectionController.selectElement(newCanvas); - } - } //if (!canvas) { - else { - - var world = null; - if (canvas.elementModel.shapeModel && canvas.elementModel.shapeModel.GLWorld) { - world = canvas.elementModel.shapeModel.GLWorld; - } else { - world = this.getGLWorld(canvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, canvas, this._useWebGL);//fillMaterial, strokeMaterial); - } - - if (this._entryEditMode !== this.ENTRY_SELECT_CANVAS){ - //update the left and top of the canvas element - var canvasArray=[canvas]; - w= Math.round(w); - h = Math.round(h); - ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; - ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; - - //var bboxMid = this._selectedSubpath.getLocalBBoxMidInStageWorld(); - //left = Math.round(bboxMid[0] - 0.5 * w); - //top = Math.round(bboxMid[1] - 0.5 * h); - - ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); - ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); - - //update the viewport and projection to reflect the new canvas width and height (todo might be unnecessary since we don't use RDGE for now) - world.setViewportFromCanvas(canvas); - if (this._useWebGL){ - var cam = world.renderer.cameraManager().getActiveCamera(); - cam.setPerspective(world.getFOV(), world.getAspect(), world.getZNear(), world.getZFar()); - } - } - - var subpath = this._selectedSubpath; - - subpath.setDrawingTool(this); - subpath.setWorld(world); - - world.addIfNewObject(subpath); - world.render(); - - //TODO this will not work if there are multiple shapes in the same canvas - canvas.elementModel.shapeModel.GLGeomObj = subpath; - - //if(newCanvas.elementModel.isShape) - if (true) - { - this.application.ninja.selectionController.selectElement(canvas); - } - } //else of if (!canvas) { - } //value: function (w, h, planeMat, midPt, canvas) { - }, //RenderShape: { - BuildSecondCtrlPoint:{ value: function(p0, p2, p3) { var baselineOrig = VecUtils.vecSubtract(3, p3, p0); -- cgit v1.2.3 From 06970d710f7172ee5ab736ef082c7703c61bfd0c Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 3 Apr 2012 11:13:07 -0700 Subject: track the canvas top left position instead of the center position to figure out when to translate the subpath per canvas translation...this one seems to not drift (no floating point issues uncovered so far) --- js/tools/PenTool.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 0dbefd16..91b7606e 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -419,10 +419,6 @@ exports.PenTool = Montage.create(ShapeTool, { bboxMax = this._selectedSubpath.getBBoxMax(); var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; - this._selectedSubpath.setPlaneCenter(bboxMid); - this._selectedSubpath.setCanvasX(bboxMid[0]); - this._selectedSubpath.setCanvasY(bboxMid[1]); - //call render shape with the bbox width and height this.RenderShape(bboxWidth, bboxHeight, bboxMid, this._penPlaneMat, this._penCanvas); } @@ -437,6 +433,9 @@ exports.PenTool = Montage.create(ShapeTool, { var left = Math.round(midPt[0] - 0.5 * w); var top = Math.round(midPt[1] - 0.5 * h); + this._selectedSubpath.setPlaneCenter(midPt); + this._selectedSubpath.setCanvasLeft(left); + this._selectedSubpath.setCanvasTop(top); if (!canvas) { var newCanvas = null; -- cgit v1.2.3 From 79fb912bdaa22b8107bbddc93d1779820af80cf9 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 3 Apr 2012 14:50:34 -0700 Subject: working File I/O for pen tool created paths and some minor bug fixes (correctly setting the canvas for brush stroke file I/O, correct plane matrix for file I/O) --- js/tools/PenTool.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'js/tools') diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 91b7606e..2eae6adc 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -68,6 +68,9 @@ exports.PenTool = Montage.create(ShapeTool, { //the plane matrix for the first click...so the entire path is on the same plane _penPlaneMat: { value: null, writable: true }, + //the plane equation (in stage world space) for the current path being drawn + _dragPlane: {value: null, writable: true}, + //index of the anchor point that the user has hovered over _hoveredAnchorIndex: {value: -1, writable: true}, @@ -105,7 +108,9 @@ exports.PenTool = Montage.create(ShapeTool, { snapManager.enableSnapAlign(false); var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); + //todo fix this function to allow us to get the correct location (in 3D) for the mouse position var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); + this._dragPlane = snapManager.getDragPlane(); snapManager.enableElementSnap(elemSnap); snapManager.enableGridSnap(gridSnap); @@ -214,6 +219,7 @@ exports.PenTool = Montage.create(ShapeTool, { if (this._selectedSubpath.getIsClosed() && this._makeMultipleSubpaths) { this._penCanvas = null; this._penPlaneMat = null; + this._dragPlane = null; this._snapTarget = null; this._selectedSubpath = new SubPath(); this._isNewPath = true; @@ -404,7 +410,8 @@ exports.PenTool = Montage.create(ShapeTool, { this._selectedSubpath.setPlaneMatrix(this._penPlaneMat); var planeMatInv = glmat4.inverse( this._penPlaneMat, [] ); this._selectedSubpath.setPlaneMatrixInverse(planeMatInv); - + this._selectedSubpath.setDragPlane(this._dragPlane); + this._selectedSubpath.createSamples(); //dirty bit is checked here this._selectedSubpath.buildLocalCoord(); //local dirty bit is checked here -- cgit v1.2.3 From f4eccf3e7cb76a14a3546a646575162dbd831538 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Wed, 4 Apr 2012 15:52:41 -0700 Subject: draw the path overlay (and anchor points) taking into account the transformation applied to the element canvas and the stage canvas. Still quite buggy. --- js/tools/BrushTool.js | 1 - js/tools/PenTool.js | 82 +++++++++++++++++++++++++++++++++---------- js/tools/drawing-tool-base.js | 2 ++ 3 files changed, 65 insertions(+), 20 deletions(-) (limited to 'js/tools') diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index f7f0e4bf..78d1e7e6 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js @@ -134,7 +134,6 @@ exports.BrushTool = Montage.create(ShapeTool, { snapManager.enableSnapAlign(false); var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); - //todo fix this function to allow us to get the correct location (in 3D) for the mouse position var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); this._draggingPlane = snapManager.getDragPlane(); diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 2eae6adc..f1c79153 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js @@ -14,7 +14,7 @@ var ElementMediator = require("js/mediators/element-mediator").ElementMediator; var TagTool = require("js/tools/TagTool").TagTool; var ElementController = require("js/controllers/elements/element-controller").ElementController; var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; - +var ViewUtils = require("js/helper-classes/3D/view-utils").ViewUtils; var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; var SubPath = require("js/lib/geom/sub-path").SubPath; @@ -108,7 +108,6 @@ exports.PenTool = Montage.create(ShapeTool, { snapManager.enableSnapAlign(false); var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); - //todo fix this function to allow us to get the correct location (in 3D) for the mouse position var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); this._dragPlane = snapManager.getDragPlane(); @@ -830,14 +829,12 @@ exports.PenTool = Montage.create(ShapeTool, { //display the subpath as a sequence of cubic beziers ctx.lineWidth = 1;//TODO replace hardcoded stroke width with some programmatically set value (should not be same as stroke width) ctx.strokeStyle = "green"; - //if (subpath.getStrokeColor()) - // ctx.strokeStyle = MathUtils.colorToHex( subpath.getStrokeColor() ); - + var i=0; ctx.beginPath(); var p0x = subpath.getAnchor(0).getPosX()+ horizontalOffset; var p0y = subpath.getAnchor(0).getPosY()+ verticalOffset; ctx.moveTo(p0x, p0y); - for (var i = 1; i < numAnchors; i++) { + for (i = 1; i < numAnchors; i++) { var p1x = subpath.getAnchor(i - 1).getNextX()+ horizontalOffset; var p1y = subpath.getAnchor(i - 1).getNextY()+ verticalOffset; var p2x = subpath.getAnchor(i).getPrevX()+ horizontalOffset; @@ -858,6 +855,34 @@ exports.PenTool = Montage.create(ShapeTool, { } ctx.stroke(); + + //draw the stage world points by projecting them to screen space + //get the screen coords of this anchor from its stage world coord + ctx.beginPath(); + ctx.strokeStyle = "red"; + var localToGlobalMat = ViewUtils.getLocalToGlobalMatrix(subpath.getCanvas()); + var currentLTWH = subpath.computeLeftTopWidthHeight(); + var deltaX = currentLTWH[0] - parseInt(ElementMediator.getProperty(subpath.getCanvas(), "left")); + var deltaY = currentLTWH[1] - parseInt(ElementMediator.getProperty(subpath.getCanvas(), "top")); + + var localCoord = subpath.getAnchorLocalCoord(0); + var sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); + //add the difference between the current left and top and the canvas left and top + sp[0]+=deltaX; sp[1]+=deltaY; + + ctx.moveTo(sp[0],sp[1]); + for (i = 1; i < numAnchors; i++) { + localCoord = subpath.getAnchorLocalCoord(i); + sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); + //add the difference between the current left and top and the canvas left and top + sp[0]+=deltaX; sp[1]+=deltaY; + ctx.lineTo(sp[0],sp[1]); + } + if (subpath.getIsClosed()){ + ctx.closePath(); + } + ctx.stroke(); + ctx.restore(); } //function (subpath) }, //DrawSubpathSVG @@ -879,37 +904,56 @@ exports.PenTool = Montage.create(ShapeTool, { var horizontalOffset = this.application.ninja.stage.userContentLeft;//stageManagerModule.stageManager.userContentLeft; var verticalOffset = this.application.ninja.stage.userContentTop;//stageManagerModule.stageManager.userContentTop; - //display circles and squares near all control points + var localToGlobalMat = ViewUtils.getLocalToGlobalMatrix(subpath.getCanvas()); + + var currentLTWH = subpath.computeLeftTopWidthHeight(); + var deltaX = currentLTWH[0] - parseInt(ElementMediator.getProperty(subpath.getCanvas(), "left")); + var deltaY = currentLTWH[1] - parseInt(ElementMediator.getProperty(subpath.getCanvas(), "top")); + + //display circles and squares near all control points ctx.fillStyle = "#FFFFFF"; ctx.lineWidth = 1; ctx.strokeStyle = "green"; var anchorDelta = 2; var selAnchorDelta = 4; for (var i = 0; i < numAnchors; i++) { - var px = subpath.getAnchor(i).getPosX(); - var py = subpath.getAnchor(i).getPosY(); + var px = subpath.getAnchor(i).getPosX()+horizontalOffset; + var py = subpath.getAnchor(i).getPosY()+verticalOffset; + var localCoord = subpath.getAnchorLocalCoord(i); + if (localCoord) { + var sp = MathUtils.transformAndDivideHomogeneousPoint(localCoord,localToGlobalMat); + px = sp[0]; py=sp[1]; + sp[0]+=deltaX; sp[1]+=deltaY; + } ctx.beginPath(); //ctx.arc(px + horizontalOffset, py + verticalOffset, this._DISPLAY_ANCHOR_RADIUS, 0, 2 * Math.PI, false); - ctx.moveTo(px-anchorDelta+horizontalOffset, py-anchorDelta+verticalOffset); - ctx.lineTo(px+anchorDelta+horizontalOffset, py-anchorDelta+verticalOffset); - ctx.lineTo(px+anchorDelta+horizontalOffset, py+anchorDelta+verticalOffset); - ctx.lineTo(px-anchorDelta+horizontalOffset, py+anchorDelta+verticalOffset); + ctx.moveTo(px-anchorDelta, py-anchorDelta); + ctx.lineTo(px+anchorDelta, py-anchorDelta); + ctx.lineTo(px+anchorDelta, py+anchorDelta); + ctx.lineTo(px-anchorDelta, py+anchorDelta); ctx.closePath(); ctx.fill(); ctx.stroke(); + } //display the hovered over anchor point ctx.lineWidth = 2; if (this._hoveredAnchorIndex>=0 && this._hoveredAnchorIndex=0 && this._hoveredAnchorIndex