diff options
-rwxr-xr-x | js/helper-classes/RDGE/GLBrushStroke.js | 74 | ||||
-rw-r--r-- | js/tools/BrushTool.js | 12 |
2 files changed, 65 insertions, 21 deletions
diff --git a/js/helper-classes/RDGE/GLBrushStroke.js b/js/helper-classes/RDGE/GLBrushStroke.js index 8fb6ab25..52ac79f5 100755 --- a/js/helper-classes/RDGE/GLBrushStroke.js +++ b/js/helper-classes/RDGE/GLBrushStroke.js | |||
@@ -34,6 +34,9 @@ function GLBrushStroke() { | |||
34 | this._strokeMaterial; | 34 | this._strokeMaterial; |
35 | this._strokeStyle = "Solid"; | 35 | this._strokeStyle = "Solid"; |
36 | 36 | ||
37 | //the wetness of the brush (currently this is multiplied to the square of the stroke width, but todo should be changed | ||
38 | this._WETNESS_FACTOR = 0.010625;//0.0625; | ||
39 | |||
37 | //drawing context | 40 | //drawing context |
38 | this._world = null; | 41 | this._world = null; |
39 | 42 | ||
@@ -69,21 +72,23 @@ function GLBrushStroke() { | |||
69 | this.getPoint = function (index) { return this._Points[index]; } | 72 | this.getPoint = function (index) { return this._Points[index]; } |
70 | this.addPoint = function (pt) | 73 | this.addPoint = function (pt) |
71 | { | 74 | { |
72 | //add the point if it is some epsilon away from the previous point | 75 | //add the point only if it is some epsilon away from the previous point |
73 | var doAddPoint=true; | ||
74 | var numPoints = this._Points.length; | 76 | var numPoints = this._Points.length; |
75 | if (numPoints>0) { | 77 | if (numPoints>0) { |
78 | var threshold = this._WETNESS_FACTOR*this._strokeWidth*this._strokeWidth; | ||
76 | var prevPt = this._Points[numPoints-1]; | 79 | var prevPt = this._Points[numPoints-1]; |
77 | var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; | 80 | var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; |
78 | var diffPtMag = diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]; | 81 | var diffPtMag = diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]; |
79 | if (diffPtMag<16)//TODO hook this up to the variable that measures flow/wetness of the paint brush...a smaller number-> more samples | 82 | if (diffPtMag>threshold){ |
80 | doAddPoint=false; | 83 | this._Points.push(pt); |
81 | } | 84 | this._dirty=true; |
82 | if (doAddPoint) { | 85 | } |
86 | }else{ | ||
83 | this._Points.push(pt); | 87 | this._Points.push(pt); |
84 | this._dirty=true; | 88 | this._dirty=true; |
85 | } | 89 | } |
86 | } | 90 | } |
91 | |||
87 | this.insertPoint = function(pt, index){ this._Points.splice(index, 0, pt); this._dirty=true;} | 92 | this.insertPoint = function(pt, index){ this._Points.splice(index, 0, pt); this._dirty=true;} |
88 | this.isDirty = function(){return this._dirty;} | 93 | this.isDirty = function(){return this._dirty;} |
89 | this.makeDirty = function(){this._dirty=true;} | 94 | this.makeDirty = function(){this._dirty=true;} |
@@ -127,10 +132,39 @@ function GLBrushStroke() { | |||
127 | 132 | ||
128 | this.computeMetaGeometry = function(){ | 133 | this.computeMetaGeometry = function(){ |
129 | if (this._dirty){ | 134 | if (this._dirty){ |
135 | var numPoints = this._Points.length; | ||
136 | |||
137 | //**** add samples to the path if needed...linear interpolation for now | ||
138 | if (numPoints>1) { | ||
139 | var threshold = this._WETNESS_FACTOR*this._strokeWidth*this._strokeWidth; | ||
140 | var prevPt = this._Points[0]; | ||
141 | var prevIndex = 0; | ||
142 | for (var i=1;i<numPoints;i++){ | ||
143 | var pt = this._Points[i]; | ||
144 | var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]]; | ||
145 | var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]); | ||
146 | if (distance>threshold){ | ||
147 | //insert points along the prev. to current point | ||
148 | var numNewPoints = Math.floor(distance/threshold); | ||
149 | for (var j=0;j<numNewPoints;j++){ | ||
150 | var param = (j+1)/(numNewPoints+1); | ||
151 | var newpt = [prevPt[0]+ diff[0]*param, prevPt[1]+ diff[1]*param]; | ||
152 | //insert new point before point i | ||
153 | this._Points.splice(i, 0, [newpt[0], newpt[1], 0]); | ||
154 | i++; | ||
155 | } | ||
156 | this._dirty=true; | ||
157 | } | ||
158 | prevPt=pt; | ||
159 | //update numPoints to match the new length | ||
160 | numPoints = this._Points.length; | ||
161 | } | ||
162 | } | ||
163 | |||
130 | // *** compute the bounding box ********* | 164 | // *** compute the bounding box ********* |
131 | this._BBoxMin = [Infinity, Infinity, Infinity]; | 165 | this._BBoxMin = [Infinity, Infinity, Infinity]; |
132 | this._BBoxMax = [-Infinity, -Infinity, -Infinity]; | 166 | this._BBoxMax = [-Infinity, -Infinity, -Infinity]; |
133 | var numPoints = this._Points.length; | 167 | numPoints = this._Points.length; |
134 | if (numPoints === 0) { | 168 | if (numPoints === 0) { |
135 | this._BBoxMin = [0, 0, 0]; | 169 | this._BBoxMin = [0, 0, 0]; |
136 | this._BBoxMax = [0, 0, 0]; | 170 | this._BBoxMax = [0, 0, 0]; |
@@ -204,6 +238,7 @@ function GLBrushStroke() { | |||
204 | ctx.stroke(); | 238 | ctx.stroke(); |
205 | */ | 239 | */ |
206 | 240 | ||
241 | /* | ||
207 | var isDebug = false; | 242 | var isDebug = false; |
208 | var prevPt = this._Points[0]; | 243 | var prevPt = this._Points[0]; |
209 | var prevX = prevPt[0]-bboxMin[0]; | 244 | var prevX = prevPt[0]-bboxMin[0]; |
@@ -284,9 +319,9 @@ function GLBrushStroke() { | |||
284 | } | 319 | } |
285 | ctx.stroke(); | 320 | ctx.stroke(); |
286 | } | 321 | } |
322 | */ | ||
287 | 323 | ||
288 | 324 | ||
289 | /* | ||
290 | var R2 = this._strokeWidth; | 325 | var R2 = this._strokeWidth; |
291 | var R = R2*0.5; | 326 | var R = R2*0.5; |
292 | var hardness = 0.25; //for a pencil, this is always 1 //TODO get hardness parameter from user interface | 327 | var hardness = 0.25; //for a pencil, this is always 1 //TODO get hardness parameter from user interface |
@@ -294,23 +329,30 @@ function GLBrushStroke() { | |||
294 | if (innerRadius<1) | 329 | if (innerRadius<1) |
295 | innerRadius=1; | 330 | innerRadius=1; |
296 | 331 | ||
332 | var r = ctx.createRadialGradient(0,0,innerRadius, 0,0,R); | ||
333 | //r.addColorStop(0, 'rgba(255,0,0,0.5)'); | ||
334 | var midColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",0.5)"; | ||
335 | r.addColorStop(0, midColor); | ||
336 | //r.addColorStop(0.5, 'rgba(255,0,0,0.5)'); // prevent aggregation of semi-opaque pixels | ||
337 | //r.addColorStop(1, 'rgba(255,0,0,0.0)'); | ||
338 | var endColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",0.0)"; | ||
339 | r.addColorStop(1, endColor); | ||
340 | ctx.fillStyle = r; | ||
341 | |||
297 | for (var i = 0; i < numPoints; i++) { | 342 | for (var i = 0; i < numPoints; i++) { |
298 | var pt = this._Points[i]; | 343 | var pt = this._Points[i]; |
299 | ctx.globalCompositeOperation = 'source-over'; | 344 | ctx.globalCompositeOperation = 'source-over'; |
300 | var x = pt[0]-bboxMin[0]; | 345 | var x = pt[0]-bboxMin[0]; |
301 | var y = pt[1]-bboxMin[1]; | 346 | var y = pt[1]-bboxMin[1]; |
302 | var r = ctx.createRadialGradient(x, y, innerRadius, x, y, R); | 347 | ctx.save(); |
303 | r.addColorStop(0, 'rgba(255,0,0,0.5)'); | 348 | ctx.translate(x,y); |
304 | //r.addColorStop(0.5, 'rgba(255,0,0,0.5)'); // prevent aggregation of semi-opaque pixels | 349 | ctx.arc(0, 0, R, 0, 2 * Math.PI, false); |
305 | r.addColorStop(1, 'rgba(255,0,0,0.0)'); | ||
306 | ctx.fillStyle = r; | ||
307 | //ctx.fillRect(x-R, y-R, R2, R2); | ||
308 | ctx.arc(x, y, R, 0, 2 * Math.PI, false); | ||
309 | ctx.fill(); | 350 | ctx.fill(); |
351 | ctx.restore(); | ||
310 | //ctx.globalCompositeOperation = 'source-in'; | 352 | //ctx.globalCompositeOperation = 'source-in'; |
311 | //ctx.rect(x-R, y-R, R2, R2); | 353 | //ctx.rect(x-R, y-R, R2, R2); |
312 | } | 354 | } |
313 | */ | 355 | |
314 | ctx.restore(); | 356 | ctx.restore(); |
315 | } //render() | 357 | } //render() |
316 | 358 | ||
diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index 9a0ad583..776d914c 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js | |||
@@ -64,6 +64,11 @@ exports.BrushTool = Montage.create(ShapeTool, { | |||
64 | //start a new brush stroke | 64 | //start a new brush stroke |
65 | if (this._selectedBrushStroke === null){ | 65 | if (this._selectedBrushStroke === null){ |
66 | this._selectedBrushStroke = new GLBrushStroke(); | 66 | this._selectedBrushStroke = new GLBrushStroke(); |
67 | if (this.application.ninja.colorController.colorToolbar.stroke.webGlColor){ | ||
68 | this._selectedBrushStroke.setStrokeColor(this.application.ninja.colorController.colorToolbar.stroke.webGlColor); | ||
69 | } | ||
70 | //TODO get these values from the options | ||
71 | this._selectedBrushStroke.setStrokeWidth(20); | ||
67 | } | 72 | } |
68 | NJevent("enableStageMove");//stageManagerModule.stageManager.enableMouseMove(); | 73 | NJevent("enableStageMove");//stageManagerModule.stageManager.enableMouseMove(); |
69 | } //value: function (event) { | 74 | } //value: function (event) { |
@@ -132,10 +137,7 @@ exports.BrushTool = Montage.create(ShapeTool, { | |||
132 | this._isDrawing = false; | 137 | this._isDrawing = false; |
133 | this._hasDraw = false; | 138 | this._hasDraw = false; |
134 | 139 | ||
135 | //TODO get these values from the options | 140 | |
136 | if (this._selectedBrushStroke){ | ||
137 | this._selectedBrushStroke.setStrokeWidth(20); | ||
138 | } | ||
139 | //display the previously drawn stroke in a separate canvas | 141 | //display the previously drawn stroke in a separate canvas |
140 | this.RenderCurrentBrushStroke(); | 142 | this.RenderCurrentBrushStroke(); |
141 | 143 | ||
@@ -150,7 +152,7 @@ exports.BrushTool = Montage.create(ShapeTool, { | |||
150 | //clear the canvas before we draw anything else | 152 | //clear the canvas before we draw anything else |
151 | this.application.ninja.stage.clearDrawingCanvas(); | 153 | this.application.ninja.stage.clearDrawingCanvas(); |
152 | if (this._selectedBrushStroke && this._selectedBrushStroke.getNumPoints()>0){ | 154 | if (this._selectedBrushStroke && this._selectedBrushStroke.getNumPoints()>0){ |
153 | this._selectedBrushStroke.computeMetaGeometry(); | 155 | //this._selectedBrushStroke.computeMetaGeometry(); |
154 | var ctx = this.application.ninja.stage.drawingContext;//stageManagerModule.stageManager.drawingContext; | 156 | var ctx = this.application.ninja.stage.drawingContext;//stageManagerModule.stageManager.drawingContext; |
155 | if (ctx === null) | 157 | if (ctx === null) |
156 | throw ("null drawing context in Brushtool::ShowCurrentBrushStrokeOnStage"); | 158 | throw ("null drawing context in Brushtool::ShowCurrentBrushStrokeOnStage"); |