diff options
author | Pushkar Joshi | 2012-04-03 10:14:49 -0700 |
---|---|---|
committer | Pushkar Joshi | 2012-04-03 10:14:49 -0700 |
commit | c838f85d28acbf2fe208a4358aef9cac73b65fbc (patch) | |
tree | be38feb3d6d54d39426504ee504a386377c1483a /js | |
parent | 878743cbbb75f2fc84855ca27779597b67ab1a95 (diff) | |
download | ninja-c838f85d28acbf2fe208a4358aef9cac73b65fbc.tar.gz |
First attempt at preventing the drifting of the canvas due to floating point roundoff errors when constantly changing stroke width
Diffstat (limited to 'js')
-rwxr-xr-x | js/lib/geom/sub-path.js | 27 | ||||
-rwxr-xr-x | js/tools/PenTool.js | 231 |
2 files changed, 133 insertions, 125 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index 19a1da3b..4ded360c 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js | |||
@@ -866,6 +866,27 @@ GLSubpath.prototype.getStrokeWidth = function () { | |||
866 | return this._strokeWidth; | 866 | return this._strokeWidth; |
867 | }; | 867 | }; |
868 | 868 | ||
869 | GLSubpath.prototype.translateSubpathPerCanvas = function(elemMediator){ | ||
870 | //check if the canvas was translated | ||
871 | var penCanvasLeft = parseInt(elemMediator.getProperty(this._canvas, "left"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "left")); | ||
872 | var penCanvasTop = parseInt(elemMediator.getProperty(this._canvas, "top"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "top")); | ||
873 | var penCanvasWidth = parseInt(elemMediator.getProperty(this._canvas, "width"));//this._penCanvas.width; | ||
874 | var penCanvasHeight = parseInt(elemMediator.getProperty(this._canvas, "height"));//this._penCanvas.height; | ||
875 | var penCanvasOldX = penCanvasLeft + 0.5 * penCanvasWidth; | ||
876 | var penCanvasOldY = penCanvasTop + 0.5 * penCanvasHeight; | ||
877 | |||
878 | var translateCanvasX = penCanvasOldX - this._canvasX; | ||
879 | var translateCanvasY = penCanvasOldY - this._canvasY; | ||
880 | |||
881 | //update the canvasX and canvasY parameters for this subpath and also translate the subpath points (since they're stored in stage world space) | ||
882 | if (Math.abs(translateCanvasX)>=1 || Math.abs(translateCanvasY)>=1){ | ||
883 | this.setCanvasX(translateCanvasX + this._canvasX); | ||
884 | this.setCanvasY(translateCanvasY + this._canvasY); | ||
885 | this.translateAnchors(translateCanvasX, translateCanvasY, 0); | ||
886 | } | ||
887 | this._dirty=true; | ||
888 | }; | ||
889 | |||
869 | GLSubpath.prototype.setStrokeWidth = function (w) { | 890 | GLSubpath.prototype.setStrokeWidth = function (w) { |
870 | var diffStrokeWidth = w-Math.floor(this._strokeWidth);//if positive, then stroke width grew, else shrunk | 891 | var diffStrokeWidth = w-Math.floor(this._strokeWidth);//if positive, then stroke width grew, else shrunk |
871 | if (diffStrokeWidth === 0) | 892 | if (diffStrokeWidth === 0) |
@@ -874,11 +895,14 @@ GLSubpath.prototype.setStrokeWidth = function (w) { | |||
874 | this._strokeWidth = w; | 895 | this._strokeWidth = w; |
875 | this._dirty=true; | 896 | this._dirty=true; |
876 | 897 | ||
898 | var ElementMediator = require("js/mediators/element-mediator").ElementMediator; | ||
899 | this.translateSubpathPerCanvas(ElementMediator); | ||
900 | |||
877 | // **** adjust the left, top, width, and height to adjust for the change in stroke width **** | 901 | // **** adjust the left, top, width, and height to adjust for the change in stroke width **** |
878 | this.createSamples(); //dirty bit is checked here | 902 | this.createSamples(); //dirty bit is checked here |
879 | this.buildLocalCoord(); //local dirty bit is checked here | 903 | this.buildLocalCoord(); //local dirty bit is checked here |
880 | 904 | ||
881 | //build the width and height of this canvas by looking at local coordinates (X and Y needed only) | 905 | //build the width and height of this canvas by looking at local coordinates |
882 | var bboxMin = this.getLocalBBoxMin(); | 906 | var bboxMin = this.getLocalBBoxMin(); |
883 | var bboxMax = this.getLocalBBoxMax(); | 907 | var bboxMax = this.getLocalBBoxMax(); |
884 | var bboxWidth = bboxMax[0] - bboxMin[0]; | 908 | var bboxWidth = bboxMax[0] - bboxMin[0]; |
@@ -892,7 +916,6 @@ GLSubpath.prototype.setStrokeWidth = function (w) { | |||
892 | var top = Math.round(bboxMid[1] - 0.5 * bboxHeight); | 916 | var top = Math.round(bboxMid[1] - 0.5 * bboxHeight); |
893 | 917 | ||
894 | var canvasArray=[this._canvas]; | 918 | var canvasArray=[this._canvas]; |
895 | var ElementMediator = require("js/mediators/element-mediator").ElementMediator; | ||
896 | ElementMediator.setProperty(canvasArray, "width", [bboxWidth+"px"], "Changing", "penTool");//canvas.width = w; | 919 | ElementMediator.setProperty(canvasArray, "width", [bboxWidth+"px"], "Changing", "penTool");//canvas.width = w; |
897 | ElementMediator.setProperty(canvasArray, "height", [bboxHeight+"px"], "Changing", "penTool");//canvas.height = h; | 920 | ElementMediator.setProperty(canvasArray, "height", [bboxHeight+"px"], "Changing", "penTool");//canvas.height = h; |
898 | ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); | 921 | ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); |
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, { | |||
393 | TranslateSelectedSubpathPerPenCanvas:{ | 393 | TranslateSelectedSubpathPerPenCanvas:{ |
394 | value: function() { | 394 | value: function() { |
395 | if (this._penCanvas!==null) { | 395 | if (this._penCanvas!==null) { |
396 | //obtain the 2D translation of the canvas due to the Selection tool...assuming this is called in Configure | 396 | this._selectedSubpath.translateSubpathPerCanvas(ElementMediator); |
397 | var penCanvasLeft = parseInt(ElementMediator.getProperty(this._penCanvas, "left"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "left")); | ||
398 | var penCanvasTop = parseInt(ElementMediator.getProperty(this._penCanvas, "top"));//parseFloat(DocumentControllerModule.DocumentController.GetElementStyle(this._penCanvas, "top")); | ||
399 | var penCanvasWidth = parseInt(ElementMediator.getProperty(this._penCanvas, "width"));//this._penCanvas.width; | ||
400 | var penCanvasHeight = parseInt(ElementMediator.getProperty(this._penCanvas, "height"));//this._penCanvas.height; | ||
401 | var penCanvasOldX = penCanvasLeft + 0.5 * penCanvasWidth; | ||
402 | var penCanvasOldY = penCanvasTop + 0.5 * penCanvasHeight; | ||
403 | |||
404 | var translateCanvasX = penCanvasOldX - this._selectedSubpath.getCanvasX(); | ||
405 | var translateCanvasY = penCanvasOldY - this._selectedSubpath.getCanvasY(); | ||
406 | |||
407 | //update the canvasX and canvasY parameters for this subpath and also translate the subpath points (since they're stored in stage world space) | ||
408 | this._selectedSubpath.setCanvasX(translateCanvasX + this._selectedSubpath.getCanvasX()); | ||
409 | this._selectedSubpath.setCanvasY(translateCanvasY + this._selectedSubpath.getCanvasY()); | ||
410 | this._selectedSubpath.translateAnchors(translateCanvasX, translateCanvasY, 0); | ||
411 | this._selectedSubpath.createSamples(); //updates the bounding box | ||
412 | } | 397 | } |
413 | } | 398 | } |
414 | }, | 399 | }, |
@@ -444,6 +429,113 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
444 | } | 429 | } |
445 | }, | 430 | }, |
446 | 431 | ||
432 | RenderShape: { | ||
433 | value: function (w, h, midPt, planeMat, canvas) { | ||
434 | if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | var left = Math.round(midPt[0] - 0.5 * w); | ||
439 | var top = Math.round(midPt[1] - 0.5 * h); | ||
440 | |||
441 | if (!canvas) { | ||
442 | var newCanvas = null; | ||
443 | newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); | ||
444 | var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas); | ||
445 | ElementMediator.addElement(newCanvas, elementModel.data, true); | ||
446 | |||
447 | // create all the GL stuff | ||
448 | var world = this.getGLWorld(newCanvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, newCanvas, this._useWebGL);//fillMaterial, strokeMaterial); | ||
449 | //store a reference to this newly created canvas | ||
450 | this._penCanvas = newCanvas; | ||
451 | |||
452 | var subpath = this._selectedSubpath; //new GLSubpath(); | ||
453 | subpath.setWorld(world); | ||
454 | subpath.setCanvas(newCanvas); | ||
455 | |||
456 | world.addObject(subpath); | ||
457 | world.render(); | ||
458 | //TODO this will not work if there are multiple shapes in the same canvas | ||
459 | newCanvas.elementModel.shapeModel.GLGeomObj = subpath; | ||
460 | newCanvas.elementModel.shapeModel.shapeCount++; | ||
461 | if(newCanvas.elementModel.shapeModel.shapeCount === 1) | ||
462 | { | ||
463 | newCanvas.elementModel.selection = "Subpath"; | ||
464 | newCanvas.elementModel.pi = "SubpathPi"; | ||
465 | newCanvas.elementModel.shapeModel.strokeSize = this.options.strokeSize.value + " " + this.options.strokeSize.units; | ||
466 | var strokeColor = subpath.getStrokeColor(); | ||
467 | newCanvas.elementModel.shapeModel.stroke = strokeColor; | ||
468 | if(strokeColor) { | ||
469 | newCanvas.elementModel.shapeModel.border = this.application.ninja.colorController.colorToolbar.stroke; | ||
470 | } | ||
471 | newCanvas.elementModel.shapeModel.strokeMaterial = subpath.getStrokeMaterial(); | ||
472 | |||
473 | newCanvas.elementModel.shapeModel.GLGeomObj = subpath; | ||
474 | newCanvas.elementModel.shapeModel.useWebGl = this.options.use3D; | ||
475 | } | ||
476 | else | ||
477 | { | ||
478 | // TODO - update the shape's info only. shapeModel will likely need an array of shapes. | ||
479 | } | ||
480 | |||
481 | //if(newCanvas.elementModel.isShape) | ||
482 | if (true) | ||
483 | { | ||
484 | this.application.ninja.selectionController.selectElement(newCanvas); | ||
485 | } | ||
486 | } //if (!canvas) { | ||
487 | else { | ||
488 | |||
489 | var world = null; | ||
490 | if (canvas.elementModel.shapeModel && canvas.elementModel.shapeModel.GLWorld) { | ||
491 | world = canvas.elementModel.shapeModel.GLWorld; | ||
492 | } else { | ||
493 | world = this.getGLWorld(canvas, this._useWebGL);//this.options.use3D);//this.CreateGLWorld(planeMat, midPt, canvas, this._useWebGL);//fillMaterial, strokeMaterial); | ||
494 | } | ||
495 | |||
496 | if (this._entryEditMode !== this.ENTRY_SELECT_CANVAS){ | ||
497 | //update the left and top of the canvas element | ||
498 | var canvasArray=[canvas]; | ||
499 | w= Math.round(w); | ||
500 | h = Math.round(h); | ||
501 | ElementMediator.setProperty(canvasArray, "width", [w+"px"], "Changing", "penTool");//canvas.width = w; | ||
502 | ElementMediator.setProperty(canvasArray, "height", [h+"px"], "Changing", "penTool");//canvas.height = h; | ||
503 | |||
504 | //var bboxMid = this._selectedSubpath.getLocalBBoxMidInStageWorld(); | ||
505 | //left = Math.round(bboxMid[0] - 0.5 * w); | ||
506 | //top = Math.round(bboxMid[1] - 0.5 * h); | ||
507 | |||
508 | ElementMediator.setProperty(canvasArray, "left", [left+"px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "left", parseInt(left) + "px"); | ||
509 | ElementMediator.setProperty(canvasArray, "top", [top + "px"],"Changing", "penTool");//DocumentControllerModule.DocumentController.SetElementStyle(canvas, "top", parseInt(top) + "px"); | ||
510 | |||
511 | //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) | ||
512 | world.setViewportFromCanvas(canvas); | ||
513 | if (this._useWebGL){ | ||
514 | var cam = world.renderer.cameraManager().getActiveCamera(); | ||
515 | cam.setPerspective(world.getFOV(), world.getAspect(), world.getZNear(), world.getZFar()); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | var subpath = this._selectedSubpath; | ||
520 | |||
521 | subpath.setDrawingTool(this); | ||
522 | subpath.setWorld(world); | ||
523 | |||
524 | world.addIfNewObject(subpath); | ||
525 | world.render(); | ||
526 | |||
527 | //TODO this will not work if there are multiple shapes in the same canvas | ||
528 | canvas.elementModel.shapeModel.GLGeomObj = subpath; | ||
529 | |||
530 | //if(newCanvas.elementModel.isShape) | ||
531 | if (true) | ||
532 | { | ||
533 | this.application.ninja.selectionController.selectElement(canvas); | ||
534 | } | ||
535 | } //else of if (!canvas) { | ||
536 | } //value: function (w, h, planeMat, midPt, canvas) { | ||
537 | }, //RenderShape: { | ||
538 | |||
447 | HandleLeftButtonUp: { | 539 | HandleLeftButtonUp: { |
448 | value: function (event) { | 540 | value: function (event) { |
449 | if (this._isAltDown) { | 541 | if (this._isAltDown) { |
@@ -603,113 +695,6 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
603 | } | 695 | } |
604 | }, | 696 | }, |
605 | 697 | ||
606 | RenderShape: { | ||
607 | value: function (w, h, midPt, planeMat, canvas) { | ||
608 | if ((Math.floor(w) === 0) || (Math.floor(h) === 0)) { | ||
609 | return; | ||
610 | } | ||
611 | |||
612 | var left = Math.round(midPt[0] - 0.5 * w); | ||
613 | var top = Math.round(midPt[1] - 0.5 * h); | ||
614 | |||
615 | if (!canvas) { | ||
616 | var newCanvas = null; | ||
617 | newCanvas = NJUtils.makeNJElement("canvas", "Subpath", "shape", {"data-RDGE-id": NJUtils.generateRandom()}, true); | ||
618 | var elementModel = TagTool.makeElement(parseInt(w), parseInt(h), planeMat, midPt, newCanvas); | ||