diff --git a/index.html b/index.html
index 500b3ee..c427b30 100644
--- a/index.html
+++ b/index.html
@@ -27,13 +27,15 @@
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/scripts/core/cursor.js b/scripts/core/cursor.js
index 86ef33a..427010c 100644
--- a/scripts/core/cursor.js
+++ b/scripts/core/cursor.js
@@ -8,7 +8,7 @@ function Cursor()
if(event.ctrltKey === true && event.altKey === true && event.shiftKey === true){ /* */ }
else if(event.shiftKey === true && event.ctrlKey === true){ this.set_mode(ronin.eye); }
else if(event.shiftKey === true && event.altKey === true){ this.set_mode(ronin.surface.active_layer); }
- else if(event.ctrltKey === true && event.altKey === true){ this.set_mode(ronin.eye); }
+ else if(event.ctrltKey === true && event.altKey === true){ this.set_mode(ronin.overlay.compositor); }
else if(event.ctrlKey === true){ this.set_mode(ronin.overlay); }
else if(event.altKey === true){ this.set_mode(ronin.surface); }
else if(event.shiftKey === true){ this.set_mode(ronin.eraser); }
diff --git a/scripts/core/init.js b/scripts/core/init.js
index fc15fed..5516c0a 100644
--- a/scripts/core/init.js
+++ b/scripts/core/init.js
@@ -12,7 +12,7 @@ commander.hint.element = document.getElementById('commander_hint');
document.addEventListener('mousedown', function(e){ ronin.cursor.mouse_down(ronin.position_in_canvas(e));}, false);
document.addEventListener('mousemove', function(e){ ronin.cursor.mouse_move(ronin.position_in_canvas(e));}, false);
document.addEventListener('mouseup', function(e){ ronin.cursor.mouse_up(ronin.position_in_canvas(e));}, false);
-// document.addEventListener('contextmenu', function(ev){ ev.preventDefault(); return false;}, false);
+document.addEventListener('contextmenu', function(ev){ ev.preventDefault(); return false;}, false);
// Keyboard
diff --git a/scripts/core/ronin.js b/scripts/core/ronin.js
index 1d859e2..c70fff5 100644
--- a/scripts/core/ronin.js
+++ b/scripts/core/ronin.js
@@ -12,7 +12,7 @@ function Ronin()
this.brush = new Brush(">");
this.eraser = new Eraser(".");
this.eye = new Eye("*");
- this.filter = new Filter("%");
+ this.render = new Render("%");
this.stroke = new Stroke("_");
this.vector = new Vector("+");
this.help = new Help("?");
@@ -25,7 +25,7 @@ function Ronin()
this.modules[this.filesave.rune] = this.filesave;
this.modules[this.history.rune] = this.history;
this.modules[this.overlay.rune] = this.overlay;
- this.modules[this.filter.rune] = this.filter;
+ this.modules[this.render.rune] = this.render;
this.modules[this.brush.rune] = this.brush;
this.modules[this.eraser.rune] = this.eraser;
this.modules[this.eye.rune] = this.eye;
diff --git a/scripts/modules/filter.balance.js b/scripts/filters/balance.js
similarity index 100%
rename from scripts/modules/filter.balance.js
rename to scripts/filters/balance.js
diff --git a/scripts/modules/filter.chromatic.js b/scripts/filters/chromatic.js
similarity index 100%
rename from scripts/modules/filter.chromatic.js
rename to scripts/filters/chromatic.js
diff --git a/scripts/modules/filter.eval.js b/scripts/filters/eval.js
similarity index 100%
rename from scripts/modules/filter.eval.js
rename to scripts/filters/eval.js
diff --git a/scripts/filters/filter.js b/scripts/filters/filter.js
new file mode 100644
index 0000000..ffafc6e
--- /dev/null
+++ b/scripts/filters/filter.js
@@ -0,0 +1,60 @@
+function Filter()
+{
+ this.name = "Unknown";
+ this.parameters = [];
+
+ this.render = function(p)
+ {
+ console.log("render: Nothing here.");
+ }
+
+ this.preview = function(p)
+ {
+ console.log("render: Nothing here.");
+ }
+
+ this.set_color = function(pixels, color, x, y)
+ {
+ x = Math.max(0,Math.min(x,pixels.width-1));
+ y = Math.max(0,Math.min(y,pixels.height-1));
+ var index = (x+y*pixels.width)*4;
+ pixels.data[index] = color.r;
+ pixels.data[index+1] = color.g;
+ pixels.data[index+2] = color.b;
+ pixels.data[index+3] = color.a;
+ }
+
+ this.get_color = function(pixels,x,y)
+ {
+ x = Math.max(0,Math.min(x,pixels.width-1));
+ y = Math.max(0,Math.min(y,pixels.height-1));
+ var index = (x+y*pixels.width)*4;
+ return {r:pixels.data[index], g:pixels.data[index+1], b:pixels.data[index+2], a:pixels.data[index+3]};
+ }
+
+ this.get_color_bilinear = function(pixels, x, y)
+ {
+ var c1 = this.get_color(pixels, Math.floor(x),Math.floor(y));
+ var c2 = this.get_color(pixels, Math.ceil(x),Math.floor(y));
+ var c3 = this.get_color(pixels, Math.floor(x),Math.ceil(y));
+ var c4 = this.get_color(pixels, Math.ceil(x),Math.ceil(y));
+ return this.lerp_color(this.lerp_color(c1,c2, x%1),this.lerp_color(c3,c4, x%1), y%1);
+ }
+
+ this.lerp_color = function(c1, c2, t)
+ {
+ return {r:c1.r+t*(c2.r-c1.r), g:c1.g+t*(c2.g-c1.g), b:c1.b+t*(c2.b-c1.b), a:c1.a+t*(c2.a-c1.a)};
+ }
+
+ //
+
+ this.context = function()
+ {
+ return ronin.surface.active_layer.context();
+ }
+
+ this.pixels = function()
+ {
+ return this.context().getImageData(0,0,ronin.surface.size.width,ronin.surface.size.height);
+ }
+}
\ No newline at end of file
diff --git a/scripts/modules/filter.offset.js b/scripts/filters/offset.js
similarity index 100%
rename from scripts/modules/filter.offset.js
rename to scripts/filters/offset.js
diff --git a/scripts/modules/filter.saturation.js b/scripts/filters/saturation.js
similarity index 100%
rename from scripts/modules/filter.saturation.js
rename to scripts/filters/saturation.js
diff --git a/scripts/filters/stencil.js b/scripts/filters/stencil.js
new file mode 100644
index 0000000..3def11f
--- /dev/null
+++ b/scripts/filters/stencil.js
@@ -0,0 +1,75 @@
+function Filter_Stencil()
+{
+ Filter.call(this);
+
+ this.render = function()
+ {
+ this.draw();
+ }
+
+ this.preview = function()
+ {
+
+ }
+
+ this.draw = function()
+ {
+ var context = this.context();
+ var w = ronin.surface.size.width;
+ var h = ronin.surface.size.height;
+
+ context.translate(w/2,h/2);
+
+ context.rotate(20*Math.PI/180);
+
+ this.line(-w,0,w,0);
+
+ this.line(w*0.4,-h,w*0.4,h);
+ this.line(-w*0.4,-h,-w*0.4,h);
+
+ this.line(-w,h*0.25,w,h*0.25);
+ this.line(-w,-h*0.25,w,-h*0.25);
+
+ this.line(w*0.1,0,w*0.1,h);
+ this.line(-w*0.1,0,-w*0.1,-h);
+
+ this.circle(w*0.4,-h*0.25,w*0.05,1,1.5);
+ this.circle(-w*0.4,h*0.25,w*0.05,0,0.5);
+
+ context.font = "5px Arial";
+ context.fillStyle = "#000000";
+ context.fillText("GRID",(w*0.4)+10,10);
+
+ context.font = "5px Arial";
+ context.fillStyle = "#000000";
+ context.fillText("GRID",(-w*0.4)-20,-10);
+
+ context.rotate(-20*Math.PI/180);
+ context.translate(-w/2,-h/2);
+ }
+
+ this.line = function(x1,x2,y1,y2)
+ {
+ this.context().beginPath();
+
+ this.context().moveTo(x1,x2);
+ this.context().lineTo(y1,y2);
+
+ this.context().lineCap="round";
+ this.context().lineWidth = 0.5;
+ this.context().strokeStyle = "#000";
+ this.context().stroke();
+ this.context().closePath();
+ }
+
+ this.circle = function(x,y,r,c1,c2)
+ {
+ this.context().beginPath();
+ this.context().arc(x,y,r,c1*Math.PI,c2*Math.PI);
+ this.context().lineCap="round";
+ this.context().lineWidth = 0.5;
+ this.context().strokeStyle = "#000";
+ this.context().stroke();
+ this.context().closePath();
+ }
+}
\ No newline at end of file
diff --git a/scripts/modules/filter.js b/scripts/modules/filter.js
deleted file mode 100644
index 3a9c563..0000000
--- a/scripts/modules/filter.js
+++ /dev/null
@@ -1,73 +0,0 @@
-function Filter(rune)
-{
- Module.call(this,rune);
-
- this.parameters = [Any];
-
- this.active = function(cmd)
- {
- if(cmd.content.length < 1){ return; }
-
- var p = cmd.content;
- var filter_name = p[0];
- p.shift();
-
- switch(filter_name) {
- case "saturation":
- this.filter_saturation(this.pixels(),p);
- break;
- case "chromatic":
- this.filter_chromatic(this.pixels(),p);
- break;
- case "offset":
- this.filter_offset(this.pixels(),p);
- break;
- case "eval":
- this.filter_eval(this.pixels(),p);
- break;
- case "balance":
- this.filter_balance(this.pixels(),p);
- break;
- }
- }
-
- this.passive = function(cmd)
- {
- }
-
- this.set_color = function(pixels, color, x, y){
- x = Math.max(0,Math.min(x,pixels.width-1));
- y = Math.max(0,Math.min(y,pixels.height-1));
- var index = (x+y*pixels.width)*4;
- pixels.data[index] = color.r;
- pixels.data[index+1] = color.g;
- pixels.data[index+2] = color.b;
- pixels.data[index+3] = color.a;
- }
-
- this.get_color = function(pixels,x,y){
- x = Math.max(0,Math.min(x,pixels.width-1));
- y = Math.max(0,Math.min(y,pixels.height-1));
- var index = (x+y*pixels.width)*4;
- return {r:pixels.data[index], g:pixels.data[index+1], b:pixels.data[index+2], a:pixels.data[index+3]};
- }
-
- this.get_color_bilinear = function(pixels, x, y){
- var c1 = this.get_color(pixels, Math.floor(x),Math.floor(y));
- var c2 = this.get_color(pixels, Math.ceil(x),Math.floor(y));
- var c3 = this.get_color(pixels, Math.floor(x),Math.ceil(y));
- var c4 = this.get_color(pixels, Math.ceil(x),Math.ceil(y));
- return this.lerp_color(this.lerp_color(c1,c2, x%1),this.lerp_color(c3,c4, x%1), y%1);
- }
-
- this.lerp_color = function(c1, c2, t){
- return {r:c1.r+t*(c2.r-c1.r), g:c1.g+t*(c2.g-c1.g), b:c1.b+t*(c2.b-c1.b), a:c1.a+t*(c2.a-c1.a)};
- }
-
- //
-
- this.pixels = function()
- {
- return ronin.surface.context().getImageData(0,0,ronin.canvas.element.width,ronin.canvas.element.height);
- }
-}
diff --git a/scripts/modules/render.js b/scripts/modules/render.js
new file mode 100644
index 0000000..4f14120
--- /dev/null
+++ b/scripts/modules/render.js
@@ -0,0 +1,26 @@
+function Render(rune)
+{
+ Module.call(this,rune);
+
+ this.parameters = [Any];
+ this.collection = {};
+
+ this.collection["stencil"] = new Filter_Stencil();
+
+ this.active = function(cmd)
+ {
+ var name = cmd.content[0];
+
+ if(!this.collection[name]){ console.log("Unknown filter:"+name); return; }
+
+ cmd.content.shift();
+
+ return this.collection[name].render(cmd.content);
+ }
+
+ this.passive = function(cmd)
+ {
+
+ }
+
+}