diff --git a/README.md b/README.md
index 7bb8ee9..1045a83 100644
--- a/README.md
+++ b/README.md
@@ -3,18 +3,22 @@ Ronin is a simple open-source graphic design tool.
+## Cursor
+- `$` replace with **Pos**.
+- `$+shift` replace with **Rect**.
+
## Modules
## brush
Missing documentation.
+### Methods
+
### Settings
- `size`, default 4
- `color`, default #000
- `opacity`, default 1
-### Methods
-
### Ports
- `speed->` **(0/50)** The cursor speed.
- `distance->` **(0/9999)** The cursor distance.
@@ -26,26 +30,28 @@ Missing documentation.
Manager for the canvas size
+### Methods
+- `resize:WxH` Resize canvas to size.
+- `rescale:0.5` Rescale canvas to float.
+- `crop:X,Y|WxH` Crop canvas to rect.
+- `clear:` Erase entire canvas
+- `fill:#f00` Fill entire canvas with color
+
### Settings
- `width`, default 930
- `height`, default 540
-### Methods
-- `resize:`, no details.
-- `rescale:`, no details.
-- `crop:`, no details.
-
### Ports
## line
Drawing lines. Tween expects something in the `$&$>>$&$` format.
-### Settings
-
### Methods
-- `tween:`, no details.
-- `stroke:`, no details.
+- `stroke:x1,y1&x2,y2` Stroke positions.
+- `tween:tween:$&$>>$&$ step->thickness` Stroke lines between strokes.
+
+### Settings
### Ports
- `step->` **(0/100)** The tween line index..
@@ -55,43 +61,43 @@ Drawing lines. Tween expects something in the `$&$>>$&$` format.
File import/export tools.
+### Methods
+- `load:browser` Press enter to open the file browser.
+- `draw:X,Y|WxH` Draw the loaded image pixels.
+- `save:name` Export canvas.
+
### Settings
- `anchor`, default [object Object]
-### Methods
-- `import:`, no details.
-- `load:`, no details.
-- `save:`, no details.
-
### Ports
## path
Trace lines and to draw shapes.
+### Methods
+- `stroke:x,y&`
+- `fill:x,y&`
+
### Settings
- `thickness`, default 30
- `color`, default black
- `cap`, default square
-### Methods
-- `stroke:`, no details.
-- `fill:`, no details.
-
### Ports
## magnet
Cursor magnetisation settings, changes are reflected on the grid layer.
+### Methods
+- `lock:undefined` undefined
+- `unlock:undefined` undefined
+
### Settings
- `size`, default 0
- `step`, default 4
-### Methods
-- `lock:`, no details.
-- `unlock:`, no details.
-
### Ports
diff --git a/TODO.md b/TODO.md
index 9c9cdb2..5157316 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,25 +1,31 @@
## TODOs
### Commander
-- Parse multicommand with `;`
+
+### Module
+- Move preview into method.
### Path
- Origin marker
-- Export SVG value
### IO
- Import `.rin` files
- Export `.rin` file
+- Negative positions
### Type
- Implement
+### Transform
+- Implement
+
### Docs
- Add shortcuts
- Write tutorial
### Brush
- Finish Port draft
+- Color picker
### Line
- Preview support
\ No newline at end of file
diff --git a/main.js b/main.js
index c869ae3..2b47d9a 100644
--- a/main.js
+++ b/main.js
@@ -56,7 +56,7 @@ app.on('ready', () =>
is_shown = true;
})
// Open the DevTools.
- win.webContents.openDevTools()
+ // win.webContents.openDevTools()
})
app.on('window-all-closed', () =>
diff --git a/sources/index.html b/sources/index.html
index 4d89bad..f1933b2 100644
--- a/sources/index.html
+++ b/sources/index.html
@@ -8,6 +8,7 @@
+
diff --git a/sources/scripts/core/commander.js b/sources/scripts/core/commander.js
index 0156e5e..4a9a8d9 100644
--- a/sources/scripts/core/commander.js
+++ b/sources/scripts/core/commander.js
@@ -14,8 +14,10 @@ function Commander()
this.validate = function(q = ronin.commander.query())
{
+ console.info(q.string)
if(!ronin.modules[q.module]){ console.log("Unknown module",q.module); return; }
if(q.raw.indexOf("$") > -1){ console.log("Variables present"); return; }
+ if(q.raw.indexOf(";") > -1){ this.validate_multi(q); return; }
// Update settings
for(setting_id in q.settings){
@@ -38,6 +40,32 @@ function Commander()
ronin.guide.update();
}
+ this.queue = [];
+
+ this.validate_multi = function(q)
+ {
+ var queue = [];
+ var queries = q.string.split(";");
+
+ for(id in queries){
+ var q = new Query(queries[id].trim());
+ queue.push(q);
+ }
+ this.queue = queue;
+ this.run_queue();
+ }
+
+ this.run_queue = function()
+ {
+ if(ronin.commander.queue.length == 0){ return; }
+
+ ronin.commander.validate(ronin.commander.queue[0]);
+
+ ronin.commander.queue = ronin.commander.queue.splice(1,ronin.commander.queue.length-1)
+
+ setTimeout(ronin.commander.run_queue,250);
+ }
+
this.update = function()
{
var q = ronin.commander.query();
diff --git a/sources/scripts/core/docs.js b/sources/scripts/core/docs.js
index 0417b38..656949d 100644
--- a/sources/scripts/core/docs.js
+++ b/sources/scripts/core/docs.js
@@ -5,16 +5,24 @@ function Docs()
var html = "";
html += this.print_intro();
+ html += "## Cursor\n";
+ html += "- `$` replace with **Pos**.\n";
+ html += "- `$+shift` replace with **Rect**.\n\n";
+
html += "## Modules\n";
html += this.print_modules(ronin.modules);
-
html += this.print_license();
- dialog.showSaveDialog((fileName) => {
- if (fileName === undefined){ return; }
- fs.writeFile(fileName, html, (err) => {
- if(err){ alert("An error ocurred creating the file "+ err.message); return; }
- });
+ // dialog.showSaveDialog((fileName) => {
+ // if (fileName === undefined){ return; }
+ // console.log(fileName)
+ // fs.writeFile(fileName, html, (err) => {
+ // if(err){ alert("An error ocurred creating the file "+ err.message); return; }
+ // });
+ // });
+
+ fs.writeFile("/Users/VillaMoirai/Github/HundredRabbits/Ronin/README.md", html, (err) => {
+ if(err){ alert("An error ocurred creating the file "+ err.message); return; }
});
return html;
@@ -36,13 +44,24 @@ function Docs()
var module = modules[module_name];
html += "## "+module_name+"\n\n";
html += module.docs+"\n\n";
- html += this.print_settings(module.settings)+"\n";
html += this.print_methods(module.methods)+"\n";
+ html += this.print_settings(module.settings)+"\n";
html += this.print_ports(module.ports)+"\n";
}
return html+"\n";
}
+ this.print_methods = function(methods)
+ {
+ var html = "### Methods\n";
+
+ for(method_name in methods){
+ var method = methods[method_name];
+ html += "- `"+method_name+":"+method.params+"` "+method.info+"\n";
+ }
+ return html;
+ }
+
this.print_settings = function(settings)
{
var html = "### Settings\n";
@@ -54,16 +73,6 @@ function Docs()
return html;
}
- this.print_methods = function(methods)
- {
- var html = "### Methods\n";
-
- for(method_name in methods){
- var method_val = methods[method_name];
- html += "- `"+method_name+":`, no details.\n";
- }
- return html;
- }
this.print_ports = function(ports)
{
diff --git a/sources/scripts/core/method.js b/sources/scripts/core/method.js
index e2598a6..af85f5b 100644
--- a/sources/scripts/core/method.js
+++ b/sources/scripts/core/method.js
@@ -1,10 +1,9 @@
-function Method(name,params,info = "Missing documentation")
+function Method(name,params,info = "Missing documentation",f)
{
this.name = name;
this.params = params;
this.info = info;
-
- this.run = null;
+ this.run = f;
this.hint = function()
{
@@ -13,6 +12,6 @@ function Method(name,params,info = "Missing documentation")
this.docs = function()
{
- return "["+this.params+"] "+this.info+"";
+ return ""+this.params+" "+this.info+"";
}
}
\ No newline at end of file
diff --git a/sources/scripts/core/query.js b/sources/scripts/core/query.js
index bfcf5aa..92062bb 100644
--- a/sources/scripts/core/query.js
+++ b/sources/scripts/core/query.js
@@ -1,5 +1,6 @@
function Query(query_str = "")
{
+ this.string = query_str;
this.module = query_str.split(" ")[0];
var parts = query_str.split(" ").splice(1);
this.raw = parts.join(" ");
diff --git a/sources/scripts/modules/filter.js b/sources/scripts/modules/filter.js
new file mode 100644
index 0000000..767e64e
--- /dev/null
+++ b/sources/scripts/modules/filter.js
@@ -0,0 +1,18 @@
+function Filter()
+{
+ Module.call(this,"filter","Pixel filter");
+
+ this.methods.balance = new Method("balance","#ff0033","Filter color balance.",function(q){
+ var color = {r:1,g:0,b:0.5};
+ var originalData = ronin.render.context().getImageData(0, 0, ronin.frame.settings.width*2, ronin.frame.settings.height*2);
+ var data = originalData.data;
+
+ for(var i = 0; i < data.length; i += 4) {
+ data[i] = data[i] * (color.r + 0.5);
+ data[i + 1] = data[i + 1] * (color.g + 0.5);
+ data[i + 2] = data[i + 2] * (color.b + 0.5);
+ }
+
+ ronin.preview.context().putImageData(originalData, 0, 0);
+ });
+}
\ No newline at end of file
diff --git a/sources/scripts/modules/frame.js b/sources/scripts/modules/frame.js
index 313912a..33cd173 100644
--- a/sources/scripts/modules/frame.js
+++ b/sources/scripts/modules/frame.js
@@ -4,24 +4,14 @@ function Frame()
this.settings = {width:400,height:400};
- this.methods = {};
-
- this.methods.resize = new Method("resize","WxH");
-
- this.methods.resize.run = function(q)
- {
+ this.methods.resize = new Method("resize","WxH","Resize canvas to size.",function(q){
var data = ronin.render.select(0,0,ronin.frame.settings.width,ronin.frame.settings.height);
-
ronin.render.clear();
ronin.frame.resize_to(q);
ronin.render.context().putImageData(data, 0, 0);
- }
+ });
- this.methods.rescale = new Method("rescale","X,Y|WxH");
-
- this.methods.rescale.run = function(p)
- {
- // Create a canvas copy
+ this.methods.rescale = new Method("rescale","0.5","Rescale canvas to float.",function(p){
var copy_canvas = document.createElement("canvas");
copy_canvas.width = ronin.frame.settings.width * 2;
copy_canvas.height = ronin.frame.settings.height * 2;
@@ -30,33 +20,25 @@ function Frame()
var new_size = {width:ronin.frame.settings.width * p,height:ronin.frame.settings.height * p};
- // Paste
ronin.render.clear();
ronin.frame.resize_to(new_size);
ronin.render.context().drawImage(copy_ctx.canvas,0,0,new_size.width * 2,new_size.height * 2);
- }
+ });
- this.methods.crop = new Method("crop","X,Y|WxH");
- this.methods.crop.run = function(p)
- {
+ this.methods.crop = new Method("crop","X,Y|WxH","Crop canvas to rect.",function(p){
var data = ronin.render.select(p.x,p.y,p.width,p.height);
-
ronin.render.clear();
ronin.frame.resize_to(p);
ronin.render.context().putImageData(data, 0, 0);
- }
+ });
- this.methods.clear = new Method("clear","X,Y|WxH");
- this.methods.clear.run = function(q)
- {
- ronin.render.fill("blue");
- }
+ this.methods.clear = new Method("clear","","Erase entire canvas",function(q){
+ ronin.render.clear();
+ });
- this.methods.fill = new Method("fill","X,Y|WxH");
- this.methods.fill.run = function(q)
- {
+ this.methods.fill = new Method("fill","#f00","Fill entire canvas with color",function(q){
ronin.render.fill(q);
- }
+ });
this.resize_to = function(size)
{
diff --git a/sources/scripts/modules/io.js b/sources/scripts/modules/io.js
index 344f97e..f551024 100644
--- a/sources/scripts/modules/io.js
+++ b/sources/scripts/modules/io.js
@@ -1,17 +1,10 @@
function IO()
{
Module.call(this,"io","File import/export tools.");
-
- this.settings = {anchor:{x:0,y:0,width:200,height:200}};
-
- this.methods = {};
this.image = null;
- this.methods.load = new Method("load","browser","Press enter to open the file browser.");
-
- this.methods.load.run = function(q)
- {
+ this.methods.load = new Method("load","browser","Press enter to open the file browser.",function(q){
var filepath = dialog.showOpenDialog({properties: ['openFile']});
if(!filepath){ console.log("Nothing to load"); return; }
@@ -25,38 +18,17 @@ function IO()
ronin.commander.inject("io draw:20,20|100x100");
}
});
- }
+ });
- this.methods.draw = new Method("draw","X,Y|WxH","Draw the loaded image pixels.");
-
- this.methods.draw.run = function(q)
- {
+ this.methods.draw = new Method("draw","X,Y|WxH","Draw the loaded image pixels.",function(q){
if(!ronin.io.image){ return; }
ronin.io.draw_image(ronin.render.context(),ronin.io.image,ronin.commander.query().methods.draw);
ronin.io.image = null;
ronin.preview.clear();
- }
+ });
- this.methods.save = new Method("save","name");
-
- this.methods.save.run = function(q)
- {
- // TODO
- ronin.io.render();
- }
-
- this.preview = function(q)
- {
- ronin.preview.clear();
-
- if(ronin.commander.query().methods.draw && this.image){
- this.draw_image(ronin.preview.context(),this.image,ronin.commander.query().methods.draw);
- }
- }
-
- this.render = function()
- {
+ this.methods.save = new Method("save","name","Export canvas.",function(q){
var fs = require('fs');
var data = ronin.render.to_base64('jpg').replace(/^data:image\/\w+;base64,/, "");
var buf = new Buffer(data, 'base64');
@@ -65,54 +37,14 @@ function IO()
if (fileName === undefined){ return; }
fs.writeFile(fileName+'.jpg', buf);
});
- }
+ });
- this.drag_over = function(e)
+ this.preview = function(q)
{
- e.stopPropagation();
- e.preventDefault();
- e.dataTransfer.dropEffect = 'copy';
- }
+ ronin.preview.clear();
- this.drop = function(e)
- {
- e.stopPropagation();
- e.preventDefault();
- var files = e.dataTransfer.files;
- var file = files[0];
-
- if (!file.type.match(/image.*/)) { console.log("Not image"); return false; }
-
- var reader = new FileReader();
-
- reader.onload = function(event)
- {
- ronin.io.inject(event.target.result);
- }
- reader.readAsDataURL(file);
- }
-
- this.inject = function(data_url)
- {
- var img = new Image();
- img.src = data_url;
-
- var width = parseInt(img.naturalWidth * 0.5);
- var height = parseInt(img.naturalHeight * 0.5);
-
- // if(height > 700){
- // width *= 0.5;
- // height *= 0.5;
- // }
- // if(height > 1400){
- // width *= 0.25;
- // height *= 0.25;
- // }
-
- ronin.frame.methods.resize({width:parseInt(width),height:parseInt(height)})
-
- img.onload = function() {
- ronin.render.context().drawImage(img, 0,0,width * 2,height * 2);
+ if(ronin.commander.query().methods.draw && this.image){
+ this.draw_image(ronin.preview.context(),this.image,ronin.commander.query().methods.draw);
}
}
diff --git a/sources/scripts/modules/line.js b/sources/scripts/modules/line.js
index 15a32be..6bef715 100644
--- a/sources/scripts/modules/line.js
+++ b/sources/scripts/modules/line.js
@@ -2,14 +2,14 @@ function Line()
{
Module.call(this,"line","Drawing lines. Tween expects something in the `$&$>>$&$` format.");
- this.methods = {};
-
- this.ports = {};
this.ports.step = new Port(this,"step",false,true,0,100,"The tween line index.");
this.ports.thickness = new Port(this,"thickness",true,true,1,100,"The tween line thickness.");
- this.methods.tween = function(q) // line tween:$&$>>$&$ step->thickness
- {
+ this.methods.stroke = new Method("stroke","x1,y1&x2,y2","Stroke positions.",function(q){
+ ronin.line.stroke_multi(q)
+ })
+
+ this.methods.tween = new Method("tween","tween:$&$>>$&$ step->thickness","Stroke lines between strokes.",function(q){
var from = q.from;
var to = q.to;
@@ -20,12 +20,7 @@ function Line()
ronin.line.stroke_multi(new_positions);
ronin.line.ports.step.write(ronin.line.ports.step.value+1);
}
- }
-
- this.methods.stroke = function(q)
- {
- ronin.line.stroke_multi(q)
- }
+ })
this.preview = function(q)
{
diff --git a/sources/scripts/modules/magnet.js b/sources/scripts/modules/magnet.js
index f7b1631..424d72b 100644
--- a/sources/scripts/modules/magnet.js
+++ b/sources/scripts/modules/magnet.js
@@ -4,21 +4,17 @@ function Magnet()
this.settings = {size:0,step:4};
- this.methods.lock = function(q)
- {
+ this.methods.lock = new Method("lock","10x10","Magnetize cursor",function(q){
var size = parseInt(q);
- ronin.magnet.settings.size = size;
-
if(size < 5){ this.unlock(); return; }
-
+ ronin.magnet.settings.size = size;
ronin.grid.draw(size,ronin.magnet.settings.step);
- }
+ })
- this.methods.unlock = function(q)
- {
+ this.methods.unlock = new Method("unlock","","Release cursor",function(q){
ronin.magnet.settings.size = 0;
ronin.grid.clear();
- }
+ })
this.filter = function(pos)
{
diff --git a/sources/scripts/modules/path.js b/sources/scripts/modules/path.js
index d18bb4a..3f5af1a 100644
--- a/sources/scripts/modules/path.js
+++ b/sources/scripts/modules/path.js
@@ -4,9 +4,7 @@ function Path()
this.settings = {thickness:30,color:"black",cap:"square"};
- this.methods.stroke = new Method("stroke","x,y&");
- this.methods.stroke.run = function(q)
- {
+ this.methods.stroke = new Method("stroke","x,y&","",function(q){
ronin.preview.clear();
var path = ronin.path.create_path(q);
@@ -19,11 +17,9 @@ function Path()
ctx.strokeStyle = "black";
ctx.stroke(new Path2D(path));
ctx.closePath();
- }
+ });
- this.methods.fill = new Method("fill","x,y&");
- this.methods.fill.run = function(q)
- {
+ this.methods.fill = new Method("fill","x,y&","",function(q){
ronin.preview.clear();
var path = ronin.path.create_path(q);
@@ -36,7 +32,7 @@ function Path()
ctx.fillStyle = "black";
ctx.fill(new Path2D(path));
ctx.closePath();
- }
+ });
this.preview = function(q)
{
diff --git a/sources/scripts/ronin.js b/sources/scripts/ronin.js
index 4608c2b..a4fbbe7 100644
--- a/sources/scripts/ronin.js
+++ b/sources/scripts/ronin.js
@@ -20,6 +20,7 @@ function Ronin()
this.line = new Line();
this.path = new Path();
this.magnet = new Magnet();
+ this.filter = new Filter();
this.layers = {
grid : this.grid,
@@ -35,7 +36,8 @@ function Ronin()
line : this.line,
io : this.io,
path : this.path,
- magnet : this.magnet
+ magnet : this.magnet,
+ filter : this.filter
};
this.install = function()
@@ -74,11 +76,5 @@ function Ronin()
this.cursor.update();
this.preview.update();
this.commander.update();
-
- // this.commander.input_el.value = "io import:~/Desktop/test.png anchor=$";
- // this.commander.input_el.value = "path stroke:$+";
-
- // this.commander.input_el.value = "magnet lock:";
- // this.commander.inject("line tween:$&$&$>>$&$&$ step->thickness");
}
}
\ No newline at end of file