diff options
author | Pushkar Joshi | 2012-04-24 15:40:12 -0700 |
---|---|---|
committer | Pushkar Joshi | 2012-04-24 15:40:12 -0700 |
commit | 4290e20e2b2f4536f4365d02e1cd7a1418bc8ea9 (patch) | |
tree | 4f4c6657125aeabd853717daaff1d1fbfc54fe54 /js | |
parent | e7bbd9b08b4cd87530596b370366d994ca766650 (diff) | |
download | ninja-4290e20e2b2f4536f4365d02e1cd7a1418bc8ea9.tar.gz |
allow the realtime drawing of brush strokes drawn off the standard XY plane by passing in the transformation matrix
Diffstat (limited to 'js')
-rwxr-xr-x | js/lib/geom/brush-stroke.js | 34 | ||||
-rw-r--r-- | js/tools/BrushTool.js | 744 |
2 files changed, 433 insertions, 345 deletions
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index efd21c4a..89ef79fb 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js | |||
@@ -117,7 +117,7 @@ var BrushStroke = function GLBrushStroke() { | |||
117 | }; | 117 | }; |
118 | 118 | ||
119 | this.getPoint = function (index) { | 119 | this.getPoint = function (index) { |
120 | return this._Points[index]; | 120 | return this._Points[index].slice(0); |
121 | }; | 121 | }; |
122 | 122 | ||
123 | this.addPoint = function (pt) { | 123 | this.addPoint = function (pt) { |
@@ -399,7 +399,7 @@ var BrushStroke = function GLBrushStroke() { | |||
399 | 399 | ||
400 | // ***** unproject all the centered points and convert them to 2D (plane space)***** | 400 | // ***** unproject all the centered points and convert them to 2D (plane space)***** |
401 | // (undo the projection step performed by the browser) | 401 | // (undo the projection step performed by the browser) |
402 | localPoint = this._unprojectPt(localPoint, 1400); //todo get the perspective distance from the canvas | 402 | //localPoint = this._unprojectPt(localPoint, 1400); //todo get the perspective distance from the canvas |
403 | localPoint = MathUtils.transformPoint(localPoint, this._planeMatInv); | 403 | localPoint = MathUtils.transformPoint(localPoint, this._planeMatInv); |
404 | 404 | ||
405 | //add to the list of local points | 405 | //add to the list of local points |
@@ -572,13 +572,13 @@ var BrushStroke = function GLBrushStroke() { | |||
572 | ctx.restore(); | 572 | ctx.restore(); |
573 | } //this.render() | 573 | } //this.render() |
574 | 574 | ||
575 | this.drawToContext = function(ctx, origX, origY, drawStageWorldPts){ | 575 | this.drawToContext = function(ctx, deltaX, deltaY, drawStageWorldPts, stageWorldToScreenMat){ |
576 | var points = this._LocalPoints; | 576 | var points = this._LocalPoints; |
577 | if (drawStageWorldPts){ | 577 | if (drawStageWorldPts){ //this is usually true when we're drawing the brush stroke on the stage (no canvas yet) |
578 | points = this._Points; | 578 | points = this._Points; |
579 | } | 579 | } |
580 | var numPoints = points.length; | 580 | var numPoints = points.length; |
581 | 581 | var tempP, p; | |
582 | if (this._strokeUseCalligraphic) { | 582 | if (this._strokeUseCalligraphic) { |
583 | //build the stamp for the brush stroke | 583 | //build the stamp for the brush stroke |
584 | var t=0; | 584 | var t=0; |
@@ -623,9 +623,9 @@ var BrushStroke = function GLBrushStroke() { | |||
623 | //ctx.strokeStyle="rgba("+parseInt(255*currStrokeColor[0])+","+parseInt(255*currStrokeColor[1])+","+parseInt(255*currStrokeColor[2])+","+alphaVal+")"; | 623 | //ctx.strokeStyle="rgba("+parseInt(255*currStrokeColor[0])+","+parseInt(255*currStrokeColor[1])+","+parseInt(255*currStrokeColor[2])+","+alphaVal+")"; |
624 | ctx.translate(disp[0],disp[1]); | 624 | ctx.translate(disp[0],disp[1]); |
625 | ctx.beginPath(); | 625 | ctx.beginPath(); |
626 | ctx.moveTo(points[0][0]-origX, points[0][1]-origY); | 626 | ctx.moveTo(points[0][0]-deltaX, points[0][1]-deltaY); |
627 | for (var i=0;i<numPoints;i++){ | 627 | for (var i=0;i<numPoints;i++){ |
628 | ctx.lineTo(points[i][0]-origX, points[i][1]-origY); | 628 | ctx.lineTo(points[i][0]-deltaX, points[i][1]-deltaY); |
629 | } | 629 | } |
630 | ctx.stroke(); | 630 | ctx.stroke(); |
631 | ctx.restore(); | 631 | ctx.restore(); |
@@ -641,13 +641,27 @@ var BrushStroke = function GLBrushStroke() { | |||
641 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; | 641 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; |
642 | for (var l=0;l<numlayers;l++){ | 642 | for (var l=0;l<numlayers;l++){ |
643 | ctx.beginPath(); | 643 | ctx.beginPath(); |
644 | ctx.moveTo(points[0][0]-origX, points[0][1]-origY); | 644 | if (drawStageWorldPts) { |
645 | tempP = points[0].slice(0); | ||
646 | tempP[0]+=deltaX; tempP[1]+=deltaY; | ||
647 | p = MathUtils.transformAndDivideHomogeneousPoint(tempP, stageWorldToScreenMat); | ||
648 | } else { | ||
649 | p = points[0]; | ||
650 | } | ||
651 | ctx.moveTo(p[0],p[1]); | ||
645 | if (numPoints===1){ | 652 | if (numPoints===1){ |
646 | //display a tiny segment as a single point | 653 | //display a tiny segment as a single point |
647 | ctx.lineTo(points[0][0]-origX, points[0][1]-origY+0.01); | 654 | ctx.lineTo(p[0],p[1]+0.01); |
648 | } | 655 | } |
649 | for (var i=1;i<numPoints;i++){ | 656 | for (var i=1;i<numPoints;i++){ |
650 | ctx.lineTo(points[i][0]-origX, points[i][1]-origY); | 657 | if (drawStageWorldPts) { |
658 | tempP = points[i].slice(0); | ||
659 | tempP[0]+=deltaX; tempP[1]+=deltaY; | ||
660 | p = MathUtils.transformAndDivideHomogeneousPoint(tempP, stageWorldToScreenMat); | ||
661 | } else { | ||
662 | p = points[i]; | ||
663 | } | ||
664 | ctx.lineTo(p[0],p[1]); | ||
651 | } | 665 | } |
652 | ctx.lineWidth=2*l+minStrokeWidth; | 666 | ctx.lineWidth=2*l+minStrokeWidth; |
653 | ctx.stroke(); | 667 | ctx.stroke(); |
diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index 6cd6858c..01350d1c 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js | |||
@@ -13,7 +13,7 @@ var NJUtils = require("js/lib/NJUtils").NJUtils; | |||
13 | var ElementMediator = require("js/mediators/element-mediator").ElementMediator; | 13 | var ElementMediator = require("js/mediators/element-mediator").ElementMediator; |
14 | var TagTool = require("js/tools/TagTool").TagTool; | 14 | var TagTool = require("js/tools/TagTool").TagTool; |
15 | var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; | 15 | var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager; |
16 | 16 | var ViewUtils = require("js/helper-classes/3D/view-utils").ViewUtils; | |
17 | var BrushStroke = require("js/lib/geom/brush-stroke").BrushStroke; | 17 | var BrushStroke = require("js/lib/geom/brush-stroke").BrushStroke; |
18 | 18 | ||
19 | //whether or not we want the mouse move to be handled all the time (not just while drawing) inside the brush tool | 19 | //whether or not we want the mouse move to be handled all the time (not just while drawing) inside the brush tool |
@@ -21,396 +21,470 @@ var g_DoBrushToolMouseMove = true; | |||
21 | 21 | ||
22 | exports.BrushTool = Montage.create(ShapeTool, { | 22 | exports.BrushTool = Montage.create(ShapeTool, { |
23 | hasReel: { value: false }, | 23 | hasReel: { value: false }, |
24 | _toolID: { value: "brushTool" }, | 24 | _toolID: { value: "brushTool" }, |
25 | _imageID: { value: "brushToolImg" }, | 25 | _imageID: { value: "brushToolImg" }, |
26 | _toolImageClass: { value: "brushToolUp" }, | 26 | _toolImageClass: { value: "brushToolUp" }, |
27 | _selectedToolImageClass: { value: "brushToolDown" }, | 27 | _selectedToolImageClass: { value: "brushToolDown" }, |
28 | _toolTipText: { value: "Brush Tool" }, | 28 | _toolTipText: { value: "Brush Tool" }, |
29 | _brushView: { value: null, writable: true }, | 29 | _brushView: { value: null, writable: true }, |
30 | 30 | ||
31 | _selectedToolClass: { value: "brushToolSpecificProperties" }, | 31 | _selectedToolClass: { value: "brushToolSpecificProperties" }, |
32 | _penToolProperties: { enumerable: false, value: null, writable: true }, | 32 | _penToolProperties: { enumerable: false, value: null, writable: true }, |
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 | //config options | 36 | //config options |
37 | _useWebGL: {value: false, writable: false}, | 37 | _useWebGL: {value: false, writable: false}, |
38 | 38 | ||
39 | //view options | 39 | //view options |
40 | _brushStrokeCanvas: {value: null, writable: true}, | 40 | _brushStrokeCanvas: {value: null, writable: true}, |
41 | _brushStrokePlaneMat: {value: null, writable: true}, | 41 | _brushStrokePlaneMat: {value: null, writable: true}, |
42 | _draggingPlane: {value: null, writable: true}, | 42 | _draggingPlane: {value: null, writable: true}, |
43 | 43 | ||
44 | //the current brush stroke | 44 | //the current brush stroke |
45 | _selectedBrushStroke: {value: null, writable: true}, | 45 | _selectedBrushStroke: {value: null, writable: true}, |
46 | 46 | ||
47 | ShowToolProperties: { | 47 | ShowToolProperties: { |
48 | value: function () { | 48 | value: function () { |
49 | this._brushView = PenView.create(); | 49 | this._brushView = PenView.create(); |
50 | this._brushView.element = document.getElementById('topPanelContainer').children[0]; | 50 | this._brushView.element = document.getElementById('topPanelContainer').children[0]; |
51 | this._brushView.needsDraw = true; | 51 | this._brushView.needsDraw = true; |
52 | this._brushView.addEventListener(ToolEvents.TOOL_OPTION_CHANGE, this, false); | 52 | this._brushView.addEventListener(ToolEvents.TOOL_OPTION_CHANGE, this, false); |
53 | } | 53 | } |
54 | }, | 54 | }, |
55 | |||
56 | HandleLeftButtonDown: { | ||
57 | value: function (event) { | ||
58 | //ignore any right or middle clicks | ||
59 | if (event.button !== 0) { | ||
60 | //NOTE: this will work on Webkit only...IE has different codes (left: 1, middle: 4, right: 2) | ||
61 | return; | ||
62 | } | ||
63 | if (this._canDraw) { | ||
64 | this._isDrawing = true; | ||
65 | } | ||
66 | 55 | ||
67 | this.startDraw(event); | ||
68 | this._brushStrokePlaneMat = this.mouseDownHitRec.getPlaneMatrix(); | ||
69 | 56 | ||
70 | //start a new brush stroke | 57 | /* |
71 | if (this._selectedBrushStroke === null){ | 58 | _getUnsnappedPosition: { |
72 | this._selectedBrushStroke = new BrushStroke(); | 59 | value: function(x,y){ |
73 | if (this.application.ninja.colorController.colorToolbar.stroke.webGlColor){ | 60 | var elemSnap = snapManager.elementSnapEnabled(); |
74 | this._selectedBrushStroke.setStrokeColor(this.application.ninja.colorController.colorToolbar.stroke.webGlColor); | 61 | var gridSnap = snapManager.gridSnapEnabled(); |
75 | } | 62 | var alignSnap = snapManager.snapAlignEnabled(); |
76 | if (this.application.ninja.colorController.colorToolbar.fill.webGlColor){ | ||
77 | this._selectedBrushStroke.setSecondStrokeColor(this.application.ninja.colorController.colorToolbar.fill.webGlColor); | ||
78 | } | ||
79 | |||
80 | //add this point to the brush stroke in case the user does a mouse up before doing a mouse move | ||
81 | var currMousePos = this._getUnsnappedPosition(event.pageX, event.pageY); | ||
82 | this._selectedBrushStroke.addPoint(currMousePos); | ||
83 | |||
84 | var strokeSize = 1; | ||
85 | if (this.options.strokeSize) { | ||
86 | strokeSize = ShapesController.GetValueInPixels(this.options.strokeSize.value, this.options.strokeSize.units); | ||
87 | } | ||
88 | this._selectedBrushStroke.setStrokeWidth(strokeSize); | ||
89 | 63 | ||
90 | var strokeHardness = 100; | 64 | snapManager.enableElementSnap(false); |
91 | if (this.options.strokeHardness){ | 65 | snapManager.enableGridSnap(false); |
92 | strokeHardness = this.options.strokeHardness.value; | 66 | snapManager.enableSnapAlign(false); |
93 | } | ||
94 | this._selectedBrushStroke.setStrokeHardness(strokeHardness); | ||
95 | 67 | ||
96 | var doSmoothing = false; | 68 | var point = webkitConvertPointFromPageToNode(this.application.ninja.stage.canvas, new WebKitPoint(x,y)); |
97 | if (this.options.doSmoothing){ | 69 | var unsnappedpos = DrawingToolBase.getHitRecPos(snapManager.snap(point.x, point.y, false)); |
98 | doSmoothing = this.options.doSmoothing; | 70 | this._draggingPlane = snapManager.getDragPlane(); |
99 | } | ||
100 | this._selectedBrushStroke.setDoSmoothing(doSmoothing); | ||
101 | if (doSmoothing){ | ||
102 | this._selectedBrushStroke.setSmoothingAmount(this.options.smoothingAmount.value); | ||
103 | } | ||
104 | |||
105 | var useCalligraphic = false; | ||
106 | if (this.options.useCalligraphic){ | ||
107 | useCalligraphic = this.options.useCalligraphic; | ||
108 | } | ||
109 | if (useCalligraphic) { | ||
110 | this._selectedBrushStroke.setStrokeUseCalligraphic(true); | ||