This commit is contained in:
Devine Lu Linvega 2018-10-04 11:27:40 +12:00
parent a8628139a0
commit fce187e04c
12 changed files with 1185 additions and 1366 deletions

View File

@ -1,81 +1,72 @@
const {app, BrowserWindow, webFrame, Menu, dialog} = require('electron')
const { app, BrowserWindow, webFrame, Menu, dialog } = require('electron')
const path = require('path')
const url = require('url')
const shell = require('electron').shell
let is_shown = true;
let is_shown = true
app.on('ready', () =>
{
app.on('ready', () => {
app.win = new BrowserWindow({
width: 405,
height: 420,
minWidth: 405,
width: 405,
height: 420,
minWidth: 405,
minHeight: 420,
webPreferences: {zoomFactor: 1.0},
backgroundColor:"#000",
frame:false,
autoHideMenuBar: true,
webPreferences: { zoomFactor: 1.0 },
backgroundColor: '#000',
frame: false,
autoHideMenuBar: true,
icon: __dirname + '/icon.ico'
})
app.win.loadURL(`file://${__dirname}/sources/index.html`);
app.win.loadURL(`file://${__dirname}/sources/index.html`)
// app.inspect();
app.win.on('closed', () => {
win = null
app.quit()
})
app.win.on('hide',function() {
is_shown = false;
app.win.on('hide', function () {
is_shown = false
})
app.win.on('show',function() {
is_shown = true;
app.win.on('show', function () {
is_shown = true
})
app.on('window-all-closed', () =>
{
app.on('window-all-closed', () => {
app.quit()
})
app.on('activate', () => {
if (app.win === null) {
createWindow()
}
else{
app.win.show();
} else {
app.win.show()
}
})
})
app.inspect = function()
{
app.win.toggleDevTools();
app.inspect = function () {
app.win.toggleDevTools()
}
app.toggle_fullscreen = function()
{
app.win.setFullScreen(app.win.isFullScreen() ? false : true);
app.toggle_fullscreen = function () {
app.win.setFullScreen(!app.win.isFullScreen())
}
app.toggle_visible = function()
{
if(process.platform == "win32"){
if(!app.win.isMinimized()){ app.win.minimize(); } else{ app.win.restore(); }
}
else{
if(is_shown && !app.win.isFullScreen()){ app.win.hide(); } else{ app.win.show(); }
app.toggle_visible = function () {
if (process.platform == 'win32') {
if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() }
} else {
if (is_shown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() }
}
}
app.inject_menu = function(menu)
{
try{
Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
app.inject_menu = function (menu) {
try {
Menu.setApplicationMenu(Menu.buildFromTemplate(menu))
} catch (err) {
console.warn('Cannot inject menu.')
}
catch(err){
console.warn("Cannot inject menu.")
}
}
}

View File

@ -1,113 +1,102 @@
'use strict';
'use strict'
function Cursor()
{
this.pos = {x:0,y:0};
this.translation = null;
this.operation = null;
function Cursor () {
this.pos = { x: 0, y: 0 }
this.translation = null
this.operation = null
this.translate = function(from = null,to = null, multi = false)
{
if((from || to) && this.translation == null){ this.translation = {multi:multi}; console.log("Begin translation") }
this.translate = function (from = null, to = null, multi = false) {
if ((from || to) && this.translation == null) { this.translation = { multi: multi }; console.log('Begin translation') }
if(from){ this.translation.from = from; }
if(to){ this.translation.to = to; }
if (from) { this.translation.from = from }
if (to) { this.translation.to = to }
if(!from && !to){
this.translation = null;
if (!from && !to) {
this.translation = null
}
}
this.down = function(e)
{
this.pos = this.pos_from_event(e);
// Translation
if(dotgrid.tool.vertex_at(this.pos)){
this.translate(this.pos,this.pos,e.shiftKey)
}
dotgrid.guide.update();
dotgrid.interface.update();
e.preventDefault();
}
this.last_pos = {x:0,y:0}
this.move = function(e)
{
this.down = function (e) {
this.pos = this.pos_from_event(e)
// Translation
if(this.translation){
this.translate(null,this.pos)
if (dotgrid.tool.vertex_at(this.pos)) {
this.translate(this.pos, this.pos, e.shiftKey)
}
if(this.last_pos.x != this.pos.x || this.last_pos.y != this.pos.y){
dotgrid.guide.update();
}
dotgrid.interface.update();
e.preventDefault();
this.last_pos = this.pos;
dotgrid.guide.update()
dotgrid.interface.update()
e.preventDefault()
}
this.up = function(e)
{
this.last_pos = { x: 0, y: 0 }
this.move = function (e) {
this.pos = this.pos_from_event(e)
if(e.altKey){ dotgrid.tool.remove_segments_at(this.pos); this.translate(); return; }
if(this.translation && !is_equal(this.translation.from,this.translation.to)){
if(this.translation.multi){ dotgrid.tool.translate_multi(this.translation.from,this.translation.to); }
else{ dotgrid.tool.translate(this.translation.from,this.translation.to); }
}
else if(e.target.id == "guide"){
dotgrid.tool.add_vertex({x:this.pos.x,y:this.pos.y});
dotgrid.picker.stop();
// Translation
if (this.translation) {
this.translate(null, this.pos)
}
this.translate();
if (this.last_pos.x != this.pos.x || this.last_pos.y != this.pos.y) {
dotgrid.guide.update()
}
dotgrid.interface.update();
dotgrid.guide.update();
e.preventDefault();
dotgrid.interface.update()
e.preventDefault()
this.last_pos = this.pos
}
this.alt = function(e)
{
this.up = function (e) {
this.pos = this.pos_from_event(e)
dotgrid.tool.remove_segments_at(this.pos);
e.preventDefault();
if (e.altKey) { dotgrid.tool.remove_segments_at(this.pos); this.translate(); return }
setTimeout(() => { dotgrid.tool.clear(); },150);
if (this.translation && !is_equal(this.translation.from, this.translation.to)) {
if (this.translation.multi) { dotgrid.tool.translate_multi(this.translation.from, this.translation.to) } else { dotgrid.tool.translate(this.translation.from, this.translation.to) }
} else if (e.target.id == 'guide') {
dotgrid.tool.add_vertex({ x: this.pos.x, y: this.pos.y })
dotgrid.picker.stop()
}
this.translate()
dotgrid.interface.update()
dotgrid.guide.update()
e.preventDefault()
}
this.alt = function (e) {
this.pos = this.pos_from_event(e)
dotgrid.tool.remove_segments_at(this.pos)
e.preventDefault()
setTimeout(() => { dotgrid.tool.clear() }, 150)
}
// Position Mods
this.pos_from_event = function(e)
{
return this.pos_snap(this.pos_relative({x:e.clientX,y:e.clientY}))
this.pos_from_event = function (e) {
return this.pos_snap(this.pos_relative({ x: e.clientX, y: e.clientY }))
}
this.pos_relative = function(pos)
{
this.pos_relative = function (pos) {
return {
x:pos.x - dotgrid.guide.el.offsetLeft,
y:pos.y - dotgrid.guide.el.offsetTop
};
x: pos.x - dotgrid.guide.el.offsetLeft,
y: pos.y - dotgrid.guide.el.offsetTop
}
}
this.pos_snap = function(pos)
{
const grid = dotgrid.tool.settings.size.width/dotgrid.grid_x;
this.pos_snap = function (pos) {
const grid = dotgrid.tool.settings.size.width / dotgrid.grid_x
return {
x:clamp(step(pos.x,grid),grid,dotgrid.tool.settings.size.width),
y:clamp(step(pos.y,grid),grid,dotgrid.tool.settings.size.height+grid)
};
x: clamp(step(pos.x, grid), grid, dotgrid.tool.settings.size.width),
y: clamp(step(pos.y, grid), grid, dotgrid.tool.settings.size.height + grid)
}
}
function is_equal(a,b){ return a.x == b.x && a.y == b.y; }
}
function is_equal (a, b) { return a.x == b.x && a.y == b.y }
}

View File

@ -1,310 +1,284 @@
'use strict';
'use strict'
function Dotgrid(width,height,grid_x,grid_y,block_x,block_y)
{
this.controller = null;
this.theme = new Theme();
this.interface = new Interface();
this.history = new History();
this.guide = new Guide();
this.renderer = new Renderer();
this.tool = new Tool();
this.picker = new Picker();
this.cursor = new Cursor();
function Dotgrid (width, height, grid_x, grid_y, block_x, block_y) {
this.controller = null
this.theme = new Theme()
this.interface = new Interface()
this.history = new History()
this.guide = new Guide()
this.renderer = new Renderer()
this.tool = new Tool()
this.picker = new Picker()
this.cursor = new Cursor()
this.grid_x = grid_x;
this.grid_y = grid_y;
this.block_x = block_x;
this.block_y = block_y;
this.grid_x = grid_x
this.grid_y = grid_y
this.block_x = block_x
this.block_y = block_y
// ISU
this.install = function(host)
{
host.appendChild(this.guide.el);
this.install = function (host) {
host.appendChild(this.guide.el)
this.interface.install(host);
this.theme.install(host,this.update);
this.interface.install(host)
this.theme.install(host, this.update)
}
this.start = function()
{
this.theme.start();
this.tool.start();
this.guide.start();
this.interface.start();
this.start = function () {
this.theme.start()
this.tool.start()
this.guide.start()
this.interface.start()
document.addEventListener('mousedown', function(e){ dotgrid.cursor.down(e); }, false);
document.addEventListener('mousemove', function(e){ dotgrid.cursor.move(e); }, false);
document.addEventListener('contextmenu', function(e){ dotgrid.cursor.alt(e); }, false);
document.addEventListener('mouseup', function(e){ dotgrid.cursor.up(e);}, false);
document.addEventListener('copy', function(e){ dotgrid.copy(e); }, false);
document.addEventListener('cut', function(e){ dotgrid.cut(e); }, false);
document.addEventListener('paste', function(e){ dotgrid.paste(e); }, false);
window.addEventListener('drop', dotgrid.drag);
document.addEventListener('mousedown', function (e) { dotgrid.cursor.down(e) }, false)
document.addEventListener('mousemove', function (e) { dotgrid.cursor.move(e) }, false)
document.addEventListener('contextmenu', function (e) { dotgrid.cursor.alt(e) }, false)
document.addEventListener('mouseup', function (e) { dotgrid.cursor.up(e) }, false)
document.addEventListener('copy', function (e) { dotgrid.copy(e) }, false)
document.addEventListener('cut', function (e) { dotgrid.cut(e) }, false)
document.addEventListener('paste', function (e) { dotgrid.paste(e) }, false)
window.addEventListener('drop', dotgrid.drag)
this.new();
this.new()
setTimeout(() => { document.body.className += ' ready'; }, 250)
setTimeout(() => { document.body.className += ' ready' }, 250)
}
this.update = function()
{
dotgrid.resize();
dotgrid.interface.update();
dotgrid.guide.update();
this.update = function () {
dotgrid.resize()
dotgrid.interface.update()
dotgrid.guide.update()
}
// File
this.new = function()
{
this.new = function () {
this.set_zoom(1.0)
this.set_size({width:300,height:300})
this.history.push(this.tool.layers);
this.clear();
this.set_size({ width: 300, height: 300 })
this.history.push(this.tool.layers)
this.clear()
}
this.open = function()
{
if(!dialog){ return; }
this.open = function () {
if (!dialog) { return }
const paths = dialog.showOpenDialog({properties: ['openFile'],filters:[{name:"Dotgrid Image",extensions:["dot","grid"]}]});
const paths = dialog.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'Dotgrid Image', extensions: ['dot', 'grid'] }] })
if(!paths){ console.warn("Nothing to load"); return; }
if (!paths) { console.warn('Nothing to load'); return }
fs.readFile(paths[0], 'utf-8', (err, data) => {
if(err){ alert("An error ocurred reading the file :" + err.message); return; }
this.tool.replace(JSON.parse(data.toString().trim()));
this.guide.update();
});
}
this.save = function(content = this.tool.export())
{
if(dotgrid.tool.length() < 1){ console.warn("Nothing to save"); return; }
if(!dialog){ this.save_web(content); return; }
dialog.showSaveDialog({title:"Save to .grid",filters: [{name: "Dotgrid Format", extensions: ["grid", "dot"]}]},(fileName) => {
if (fileName === undefined){ return; }
fileName = fileName.substr(-5,5) != ".grid" ? fileName+".grid" : fileName;
fs.writeFileSync(fileName, content);
dotgrid.guide.update()
});
}
this.save_web = function(content)
{
console.info("Web Save");
const win = window.open("", "Save", `toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top=${screen.height-200},left=${screen.width-640}`);
win.document.body.innerHTML = `<style>body { background:${dotgrid.theme.active.background}; color:${dotgrid.theme.active.f_med}} pre { color:${dotgrid.theme.active.f_high} }</style><p>To save: Copy this into a .grid file.<br />To load: Drag the .grid onto the browser window.</p><pre>${content}</pre>`;
}
this.render = function(content = this.renderer.to_png({width:dotgrid.tool.settings.size.width*2,height:dotgrid.tool.settings.size.height*2}), ready = null, size = null)
{
if(!ready){return; }
if(dotgrid.tool.length() < 1){ console.warn("Nothing to render"); return; }
if(!dialog){ dotgrid.render_web(content); return; }
dialog.showSaveDialog({title:"Save to .png",filters: [{name: "Image Format", extensions: ["png"]}]},(fileName) => {
if (fileName === undefined){ return; }
fileName = fileName.substr(-4,4) != ".png" ? fileName+".png" : fileName;
console.log(`Rendered ${size.width}x${size.height}`)
fs.writeFileSync(fileName, ready);
});
}
this.render_web = function(content,window)
{
// Handled in Renderer
console.info("Web Render");
}
this.export = function(content = this.renderer.to_svg())
{
if(dotgrid.tool.length() < 1){ console.warn("Nothing to export"); return; }
if(!dialog){ this.export_web(content); return; }
dialog.showSaveDialog({title:"Save to .svg",filters: [{name: "Vector Format", extensions: ["svg"]}]},(fileName) => {
if (fileName === undefined){ return; }
fileName = fileName.substr(-4,4) != ".svg" ? fileName+".svg" : fileName;
fs.writeFileSync(fileName, content);
if (err) { alert('An error ocurred reading the file :' + err.message); return }
this.tool.replace(JSON.parse(data.toString().trim()))
this.guide.update()
});
})
}
this.export_web = function(content)
{
console.info("Web Export");
const win = window.open("", "Save", `toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top=${screen.height-200},left=${screen.width-640}`);
win.document.body.innerHTML = `<style>body { background:${dotgrid.theme.active.background}}</style>${dotgrid.renderer.to_svg()}`;
this.save = function (content = this.tool.export()) {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to save'); return }
if (!dialog) { this.save_web(content); return }
dialog.showSaveDialog({ title: 'Save to .grid', filters: [{ name: 'Dotgrid Format', extensions: ['grid', 'dot'] }] }, (fileName) => {
if (fileName === undefined) { return }
fileName = fileName.substr(-5, 5) != '.grid' ? fileName + '.grid' : fileName
fs.writeFileSync(fileName, content)
dotgrid.guide.update()
})
}
this.save_web = function (content) {
console.info('Web Save')
const win = window.open('', 'Save', `toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top=${screen.height - 200},left=${screen.width - 640}`)
win.document.body.innerHTML = `<style>body { background:${dotgrid.theme.active.background}; color:${dotgrid.theme.active.f_med}} pre { color:${dotgrid.theme.active.f_high} }</style><p>To save: Copy this into a .grid file.<br />To load: Drag the .grid onto the browser window.</p><pre>${content}</pre>`
}
this.render = function (content = this.renderer.to_png({ width: dotgrid.tool.settings.size.width * 2, height: dotgrid.tool.settings.size.height * 2 }), ready = null, size = null) {
if (!ready) { return }
if (dotgrid.tool.length() < 1) { console.warn('Nothing to render'); return }
if (!dialog) { dotgrid.render_web(content); return }
dialog.showSaveDialog({ title: 'Save to .png', filters: [{ name: 'Image Format', extensions: ['png'] }] }, (fileName) => {
if (fileName === undefined) { return }
fileName = fileName.substr(-4, 4) != '.png' ? fileName + '.png' : fileName
console.log(`Rendered ${size.width}x${size.height}`)
fs.writeFileSync(fileName, ready)
})
}
this.render_web = function (content, window) {
// Handled in Renderer
console.info('Web Render')
}
this.export = function (content = this.renderer.to_svg()) {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to export'); return }
if (!dialog) { this.export_web(content); return }
dialog.showSaveDialog({ title: 'Save to .svg', filters: [{ name: 'Vector Format', extensions: ['svg'] }] }, (fileName) => {
if (fileName === undefined) { return }
fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName
fs.writeFileSync(fileName, content)
this.guide.update()
})
}
this.export_web = function (content) {
console.info('Web Export')
const win = window.open('', 'Save', `toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top=${screen.height - 200},left=${screen.width - 640}`)
win.document.body.innerHTML = `<style>body { background:${dotgrid.theme.active.background}}</style>${dotgrid.renderer.to_svg()}`
}
// Basics
this.set_size = function(size = {width:300,height:300},ui = true,scale = 1)
{
size = { width:clamp(step(size.width,15),105,1080),height:clamp(step(size.height,15),120,1080)}
this.set_size = function (size = { width: 300, height: 300 }, ui = true, scale = 1) {
size = { width: clamp(step(size.width, 15), 105, 1080), height: clamp(step(size.height, 15), 120, 1080) }
this.tool.settings.size.width = size.width
this.tool.settings.size.height = size.height
try{
const win = require('electron').remote.getCurrentWindow();
win.setSize((size.width+100)*scale,(size.height+100+(ui ? 10 : 0))*scale,true);
try {
const win = require('electron').remote.getCurrentWindow()
win.setSize((size.width + 100) * scale, (size.height + 100 + (ui ? 10 : 0)) * scale, true)
} catch (err) {
console.log('No window')
}
catch(err){
console.log("No window")
}
this.grid_x = size.width/15
this.grid_y = size.height/15
this.grid_width = this.tool.settings.size.width/this.grid_x;
this.grid_height = this.tool.settings.size.height/this.grid_y;
this.grid_x = size.width / 15
this.grid_y = size.height / 15
dotgrid.guide.resize(size);
this.grid_width = this.tool.settings.size.width / this.grid_x
this.grid_height = this.tool.settings.size.height / this.grid_y
this.interface.update();
dotgrid.guide.update();
dotgrid.guide.resize(size)
this.interface.update()
dotgrid.guide.update()
}
this.set_zoom = function(scale)
{
this.set_size({width:this.tool.settings.size.width,height:this.tool.settings.size.height},true,scale)
this.set_zoom = function (scale) {
this.set_size({ width: this.tool.settings.size.width, height: this.tool.settings.size.height }, true, scale)
try{
webFrame.setZoomFactor(scale)
}
catch(err){
console.log("Cannot zoom")
try {
webFrame.setZoomFactor(scale)
} catch (err) {
console.log('Cannot zoom')
}
}
// Draw
this.reset = function()
{
this.tool.clear();
this.update();
this.reset = function () {
this.tool.clear()
this.update()
}
this.clear = function()
{
this.history.clear();
this.tool.reset();
this.reset();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.clear = function () {
this.history.clear()
this.tool.reset()
this.reset()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.resize = function()
{
const size = {width:step(window.innerWidth-90,15),height:step(window.innerHeight-120,15)}
this.resize = function () {
const size = { width: step(window.innerWidth - 90, 15), height: step(window.innerHeight - 120, 15) }
if(size.width == dotgrid.tool.settings.size.width && size.height == dotgrid.tool.settings.size.height){
return;
if (size.width == dotgrid.tool.settings.size.width && size.height == dotgrid.tool.settings.size.height) {
return
}
console.log(`Resized: ${size.width}x${size.height}`)
dotgrid.tool.settings.size.width = size.width
dotgrid.tool.settings.size.height = size.height
dotgrid.grid_x = size.width/15
dotgrid.grid_y = size.height/15
dotgrid.grid_x = size.width / 15
dotgrid.grid_y = size.height / 15
dotgrid.grid_width = dotgrid.tool.settings.size.width/dotgrid.grid_x;
dotgrid.grid_height = dotgrid.tool.settings.size.height/dotgrid.grid_y;
dotgrid.grid_width = dotgrid.tool.settings.size.width / dotgrid.grid_x
dotgrid.grid_height = dotgrid.tool.settings.size.height / dotgrid.grid_y
dotgrid.guide.resize(size);
dotgrid.guide.resize(size)
document.title = `Dotgrid — ${size.width}x${size.height}`
}
this.drag = function(e)
{
e.preventDefault();
e.stopPropagation();
this.drag = function (e) {
e.preventDefault()
e.stopPropagation()
const file = e.dataTransfer.files[0];
const file = e.dataTransfer.files[0]
if(!file || !file.path || file.path.indexOf(".dot") < 0 && file.path.indexOf(".grid") < 0){ console.warn("Dotgrid","Not a dot file"); return; }
if (!file || !file.path || file.path.indexOf('.dot') < 0 && file.path.indexOf('.grid') < 0) { console.warn('Dotgrid', 'Not a dot file'); return }
const reader = new FileReader();
reader.onload = function(e){
dotgrid.tool.replace(JSON.parse(e.target.result.toString().trim()));
dotgrid.guide.update();
};
reader.readAsText(file);
const reader = new FileReader()
reader.onload = function (e) {
dotgrid.tool.replace(JSON.parse(e.target.result.toString().trim()))
dotgrid.guide.update()
}
reader.readAsText(file)
}
this.copy = function(e)
{
dotgrid.guide.update();
this.copy = function (e) {
dotgrid.guide.update()
if(e.target !== this.picker.input){
e.clipboardData.setData('text/source', dotgrid.tool.export(dotgrid.tool.layer()));
e.clipboardData.setData('text/plain', dotgrid.tool.path());
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg());
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg());
e.preventDefault();
if (e.target !== this.picker.input) {
e.clipboardData.setData('text/source', dotgrid.tool.export(dotgrid.tool.layer()))
e.clipboardData.setData('text/plain', dotgrid.tool.path())
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg())
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg())
e.preventDefault()
}
dotgrid.guide.update();
dotgrid.guide.update()
}
this.cut = function(e)
{
dotgrid.guide.update();
this.cut = function (e) {
dotgrid.guide.update()
if(e.target !== this.picker.input){
e.clipboardData.setData('text/plain', dotgrid.tool.export(dotgrid.tool.layer()));
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg());
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg());
dotgrid.tool.layers[dotgrid.tool.index] = [];
e.preventDefault();
if (e.target !== this.picker.input) {
e.clipboardData.setData('text/plain', dotgrid.tool.export(dotgrid.tool.layer()))
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg())
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg())
dotgrid.tool.layers[dotgrid.tool.index] = []
e.preventDefault()
}
dotgrid.guide.update();
dotgrid.guide.update()
}
this.paste = function(e)
{
if(e.target !== this.picker.el){
const data = e.clipboardData.getData("text/source");
this.paste = function (e) {
if (e.target !== this.picker.el) {
const data = e.clipboardData.getData('text/source')
if (is_json(data)) {
data = JSON.parse(data.trim());
dotgrid.tool.import(data);
data = JSON.parse(data.trim())
dotgrid.tool.import(data)
}
e.preventDefault();
e.preventDefault()
}
dotgrid.guide.update();
dotgrid.guide.update()
}
}
window.addEventListener('resize', function(e)
{
dotgrid.update();
}, false);
window.addEventListener('resize', function (e) {
dotgrid.update()
}, false)
window.addEventListener('dragover',function(e)
{
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
window.addEventListener('dragover', function (e) {
e.stopPropagation()
e.preventDefault()
e.dataTransfer.dropEffect = 'copy'
})
String.prototype.capitalize = function()
{
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
String.prototype.capitalize = function () {
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase()
}
function is_json(text){ try{ JSON.parse(text);return true; } catch(error){ return false; }}
function pos_is_equal(a,b){ return a && b && a.x == b.x && a.y == b.y }
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
function step(v,s){ return Math.round(v/s) * s; }
function is_json (text) { try { JSON.parse(text); return true } catch (error) { return false } }
function pos_is_equal (a, b) { return a && b && a.x == b.x && a.y == b.y }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
function step (v, s) { return Math.round(v / s) * s }

View File

@ -1,115 +1,106 @@
'use strict';
'use strict'
function Generator(layer,style)
{
this.layer = layer;
this.style = style;
function Generator (layer, style) {
this.layer = layer
this.style = style
function operate(layer,offset,scale,mirror = 0,angle = 0)
{
function operate (layer, offset, scale, mirror = 0, angle = 0) {
const l = copy(layer)
for(const k1 in l){
const seg = l[k1];
for(const k2 in seg.vertices){
if(mirror == 1){ seg.vertices[k2].x = (dotgrid.tool.settings.size.width) - seg.vertices[k2].x + 15 }
if(mirror == 2){ seg.vertices[k2].y = (dotgrid.tool.settings.size.height) - seg.vertices[k2].y + 30 }
for (const k1 in l) {
const seg = l[k1]
for (const k2 in seg.vertices) {
if (mirror == 1) { seg.vertices[k2].x = (dotgrid.tool.settings.size.width) - seg.vertices[k2].x + 15 }
if (mirror == 2) { seg.vertices[k2].y = (dotgrid.tool.settings.size.height) - seg.vertices[k2].y + 30 }
// Offset
seg.vertices[k2].x += offset.x
seg.vertices[k2].y += offset.y
// Rotate
const center = {x:(dotgrid.tool.settings.size.width/2)+offset.x+(7.5),y:(dotgrid.tool.settings.size.height/2)+offset.y+30}
seg.vertices[k2] = rotate_point(seg.vertices[k2],center,angle)
const center = { x: (dotgrid.tool.settings.size.width / 2) + offset.x + (7.5), y: (dotgrid.tool.settings.size.height / 2) + offset.y + 30 }
seg.vertices[k2] = rotate_point(seg.vertices[k2], center, angle)
// Scale
seg.vertices[k2].x *= scale
seg.vertices[k2].y *= scale
}
}
return l;
return l
}
this.render = function(prev,segment,mirror = 0)
{
const type = segment.type;
const vertices = segment.vertices;
let html = '';
let skip = 0;
this.render = function (prev, segment, mirror = 0) {
const type = segment.type
const vertices = segment.vertices
let html = ''
let skip = 0
for (const id in vertices) {
if (skip > 0) { skip -= 1; continue }
for(const id in vertices){
if(skip > 0){ skip -= 1; continue; }
let vertex = vertices[id]
let next = vertices[parseInt(id)+1]
let after_next = vertices[parseInt(id)+2]
let next = vertices[parseInt(id) + 1]
let after_next = vertices[parseInt(id) + 2]
if(id == 0 && !prev || id == 0 && prev && (prev.x != vertex.x || prev.y != vertex.y)){
html += `M${vertex.x},${vertex.y} `
if (id == 0 && !prev || id == 0 && prev && (prev.x != vertex.x || prev.y != vertex.y)) {
html += `M${vertex.x},${vertex.y} `
}
if(type == "line"){
html += `L${vertex.x},${vertex.y} `;
}
else if(type == "arc_c"){
if (type == 'line') {
html += `L${vertex.x},${vertex.y} `
} else if (type == 'arc_c') {
let clock = mirror > 0 ? '0,0' : '0,1'
html += next ? `A${Math.abs(next.x - vertex.x)},${Math.abs(next.y - vertex.y)} 0 ${clock} ${next.x},${next.y} ` : '';
}
else if(type == "arc_r"){
html += next ? `A${Math.abs(next.x - vertex.x)},${Math.abs(next.y - vertex.y)} 0 ${clock} ${next.x},${next.y} ` : ''
} else if (type == 'arc_r') {
let clock = mirror > 0 ? '0,1' : '0,0'
html += next ? `A${Math.abs(next.x - vertex.x)},${Math.abs(next.y - vertex.y)} 0 ${clock} ${next.x},${next.y} ` : '';
}
else if(type == "bezier"){
html += next && after_next ?`Q${next.x},${next.y} ${after_next.x},${after_next.y} ` : '';
html += next ? `A${Math.abs(next.x - vertex.x)},${Math.abs(next.y - vertex.y)} 0 ${clock} ${next.x},${next.y} ` : ''
} else if (type == 'bezier') {
html += next && after_next ? `Q${next.x},${next.y} ${after_next.x},${after_next.y} ` : ''
skip = 1
}
else{
} else {
console.warn(`unknown type:${type}`)
}
}
if(segment.type == "close"){
html += "Z "
if (segment.type == 'close') {
html += 'Z '
}
return html
}
this.convert = function(layer,mirror,angle)
{
let s = ""
this.convert = function (layer, mirror, angle) {
let s = ''
let prev = null
for(const id in layer){
const seg = layer[id];
s += `${this.render(prev,seg,mirror)}`
prev = seg.vertices ? seg.vertices[seg.vertices.length-1] : null
for (const id in layer) {
const seg = layer[id]
s += `${this.render(prev, seg, mirror)}`
prev = seg.vertices ? seg.vertices[seg.vertices.length - 1] : null
}
return s;
return s
}
this.toString = function(offset = {x:0,y:0}, scale = 1, mirror = this.style && this.style.mirror_style ? this.style.mirror_style : 0)
{
let s = this.convert(operate(this.layer,offset,scale))
this.toString = function (offset = { x: 0, y: 0 }, scale = 1, mirror = this.style && this.style.mirror_style ? this.style.mirror_style : 0) {
let s = this.convert(operate(this.layer, offset, scale))
if(mirror == 1 || mirror == 2){
s += this.convert(operate(this.layer,offset,scale,mirror),mirror)
if (mirror == 1 || mirror == 2) {
s += this.convert(operate(this.layer, offset, scale, mirror), mirror)
}
if(mirror == 3){
s += this.convert(operate(this.layer,offset,scale,mirror,120),mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,240),mirror)
if (mirror == 3) {
s += this.convert(operate(this.layer, offset, scale, mirror, 120), mirror)
s += this.convert(operate(this.layer, offset, scale, mirror, 240), mirror)
}
if(mirror == 4){
s += this.convert(operate(this.layer,offset,scale,mirror,72),mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,144),mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,216),mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,288),mirror)
if (mirror == 4) {
s += this.convert(operate(this.layer, offset, scale, mirror, 72), mirror)
s += this.convert(operate(this.layer, offset, scale, mirror, 144), mirror)
s += this.convert(operate(this.layer, offset, scale, mirror, 216), mirror)
s += this.convert(operate(this.layer, offset, scale, mirror, 288), mirror)
}
return s
}
function copy(data){ return data ? JSON.parse(JSON.stringify(data)) : []; }
function rotate_point(point, origin, angle){ angle = angle * Math.PI / 180.0; return { x: (Math.cos(angle) * (point.x-origin.x) - Math.sin(angle) * (point.y-origin.y) + origin.x).toFixed(1), y: (Math.sin(angle) * (point.x-origin.x) + Math.cos(angle) * (point.y-origin.y) + origin.y).toFixed(1) }; }
}
function copy (data) { return data ? JSON.parse(JSON.stringify(data)) : [] }
function rotate_point (point, origin, angle) { angle = angle * Math.PI / 180.0; return { x: (Math.cos(angle) * (point.x - origin.x) - Math.sin(angle) * (point.y - origin.y) + origin.x).toFixed(1), y: (Math.sin(angle) * (point.x - origin.x) + Math.cos(angle) * (point.y - origin.y) + origin.y).toFixed(1) } }
}

View File

@ -1,281 +1,259 @@
'use strict';
'use strict'
function Guide()
{
this.el = document.createElement("canvas");
this.el.id = "guide";
this.el.width = 640;
this.el.height = 640;
this.el.style.width = "320px";
this.el.style.height = "320px";
this.show_extras = true;
function Guide () {
this.el = document.createElement('canvas')
this.el.id = 'guide'
this.el.width = 640
this.el.height = 640
this.el.style.width = '320px'
this.el.style.height = '320px'
this.show_extras = true
this.scale = 2;
this.scale = 2
this.start = function()
{
this.clear();
this.update();
}
this.update = function(force = false)
{
this.clear();
this.el.getContext('2d').restore();
this.draw_rulers();
if(dotgrid.tool.index == 2){ this.draw_markers() ; this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[2],dotgrid.tool.styles[2]).toString({x:0,y:0},this.scale),dotgrid.tool.styles[2])
if(dotgrid.tool.index == 1){ this.draw_markers() ; this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[1],dotgrid.tool.styles[1]).toString({x:0,y:0},this.scale),dotgrid.tool.styles[1])
if(dotgrid.tool.index == 0){ this.draw_markers(); this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[0],dotgrid.tool.styles[0]).toString({x:0,y:0},this.scale),dotgrid.tool.styles[0])
this.draw_handles()
this.draw_translation();
this.draw_cursor();
this.draw_preview();
}
this.clear = function()
{
this.el.getContext('2d').clearRect(0, 0, this.el.width*this.scale, this.el.height*this.scale);
}
this.toggle = function()
{
this.show_extras = this.show_extras ? false : true;
this.start = function () {
this.clear()
this.update()
}
this.resize = function(size)
{
const offset = 15
this.el.width = (size.width+offset)*this.scale;
this.el.height = (size.height+(offset*2))*this.scale;
this.el.style.width = (size.width+offset)+"px";
this.el.style.height = (size.height+(offset*2))+"px";
this.update = function (force = false) {
this.clear()
this.update();
this.el.getContext('2d').restore()
this.draw_rulers()
if (dotgrid.tool.index == 2) { this.draw_markers(); this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[2], dotgrid.tool.styles[2]).toString({ x: 0, y: 0 }, this.scale), dotgrid.tool.styles[2])
if (dotgrid.tool.index == 1) { this.draw_markers(); this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[1], dotgrid.tool.styles[1]).toString({ x: 0, y: 0 }, this.scale), dotgrid.tool.styles[1])
if (dotgrid.tool.index == 0) { this.draw_markers(); this.draw_vertices() }
this.draw_path(new Generator(dotgrid.tool.layers[0], dotgrid.tool.styles[0]).toString({ x: 0, y: 0 }, this.scale), dotgrid.tool.styles[0])
this.draw_handles()
this.draw_translation()
this.draw_cursor()
this.draw_preview()
}
this.draw_handles = function()
{
if(!this.show_extras){ return; }
this.clear = function () {
this.el.getContext('2d').clearRect(0, 0, this.el.width * this.scale, this.el.height * this.scale)
}
for(const segment_id in dotgrid.tool.layer()){
const segment = dotgrid.tool.layer()[segment_id];
for(const vertex_id in segment.vertices){
const vertex = segment.vertices[vertex_id];
this.draw_handle(vertex);
this.toggle = function () {
this.show_extras = !this.show_extras
this.update()
}
this.resize = function (size) {
const offset = 15
this.el.width = (size.width + offset) * this.scale
this.el.height = (size.height + (offset * 2)) * this.scale
this.el.style.width = (size.width + offset) + 'px'
this.el.style.height = (size.height + (offset * 2)) + 'px'
this.update()
}
this.draw_handles = function () {
if (!this.show_extras) { return }
for (const segment_id in dotgrid.tool.layer()) {
const segment = dotgrid.tool.layer()[segment_id]
for (const vertex_id in segment.vertices) {
const vertex = segment.vertices[vertex_id]
this.draw_handle(vertex)
}
}
}
this.draw_vertices = function()
{
for(const id in dotgrid.tool.vertices){
this.draw_vertex(dotgrid.tool.vertices[id]);
this.draw_vertices = function () {
for (const id in dotgrid.tool.vertices) {
this.draw_vertex(dotgrid.tool.vertices[id])
}
}
this.draw_markers = function()
{
if(!this.show_extras){ return; }
this.draw_markers = function () {
if (!this.show_extras) { return }
const cursor = {x:parseInt(dotgrid.cursor.pos.x/dotgrid.grid_width),y:parseInt(dotgrid.cursor.pos.y/dotgrid.grid_width)}
const cursor = { x: parseInt(dotgrid.cursor.pos.x / dotgrid.grid_width), y: parseInt(dotgrid.cursor.pos.y / dotgrid.grid_width) }
for (let x = dotgrid.grid_x-1; x >= 0; x--) {
for (let x = dotgrid.grid_x - 1; x >= 0; x--) {
for (let y = dotgrid.grid_y; y >= 0; y--) {
let is_step = x % dotgrid.block_x == 0 && y % dotgrid.block_y == 0;
let is_step = x % dotgrid.block_x == 0 && y % dotgrid.block_y == 0
// Color
let color = is_step ? dotgrid.theme.active.b_med : dotgrid.theme.active.b_low;
if((y == 0 || y == dotgrid.grid_y) && cursor.x == x+1){ color = dotgrid.theme.active.b_high; }
else if((x == 0 || x == dotgrid.grid_x-1) && cursor.y == y+1){ color = dotgrid.theme.active.b_high; }
else if(cursor.x == x+1 && cursor.y == y+1){ color = dotgrid.theme.active.b_high; }
let color = is_step ? dotgrid.theme.active.b_med : dotgrid.theme.active.b_low
if ((y == 0 || y == dotgrid.grid_y) && cursor.x == x + 1) { color = dotgrid.theme.active.b_high } else if ((x == 0 || x == dotgrid.grid_x - 1) && cursor.y == y + 1) { color = dotgrid.theme.active.b_high } else if (cursor.x == x + 1 && cursor.y == y + 1) { color = dotgrid.theme.active.b_high }
this.draw_marker({
x:parseInt(x * dotgrid.grid_width) + dotgrid.grid_width,
y:parseInt(y * dotgrid.grid_height) + dotgrid.grid_height
},is_step ? 2.5 : 1.5,color);
x: parseInt(x * dotgrid.grid_width) + dotgrid.grid_width,
y: parseInt(y * dotgrid.grid_height) + dotgrid.grid_height
}, is_step ? 2.5 : 1.5, color)
}
}
}
this.draw_marker = function(pos,radius = 1,color)
{
let ctx = this.el.getContext('2d');
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(pos.x * this.scale, pos.y * this.scale, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
this.draw_marker = function (pos, radius = 1, color) {
let ctx = this.el.getContext('2d')
ctx.beginPath()
ctx.lineWidth = 2
ctx.arc(pos.x * this.scale, pos.y * this.scale, radius, 0, 2 * Math.PI, false)
ctx.fillStyle = color
ctx.fill()
ctx.closePath()
}
this.draw_vertex = function(pos, radius = 5)
{
let ctx = this.el.getContext('2d');
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false);
ctx.fillStyle = dotgrid.theme.active.f_med;
ctx.fill();
ctx.closePath();
this.draw_vertex = function (pos, radius = 5) {
let ctx = this.el.getContext('2d')
ctx.beginPath()
ctx.lineWidth = 2
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false)
ctx.fillStyle = dotgrid.theme.active.f_med
ctx.fill()
ctx.closePath()
}
this.draw_rule = function(from,to)
{
let ctx = this.el.getContext('2d');
this.draw_rule = function (from, to) {
let ctx = this.el.getContext('2d')
ctx.beginPath();
ctx.moveTo(from.x,from.y);
ctx.lineTo(to.x,to.y);
ctx.lineCap="round";
ctx.lineWidth = 3;
ctx.strokeStyle = dotgrid.theme.active.b_low;
ctx.stroke();
ctx.closePath();
ctx.beginPath()
ctx.moveTo(from.x, from.y)
ctx.lineTo(to.x, to.y)
ctx.lineCap = 'round'
ctx.lineWidth = 3
ctx.strokeStyle = dotgrid.theme.active.b_low
ctx.stroke()
ctx.closePath()
}
this.draw_ruler = function(pos)
{
let offset = 15 * this.scale;
this.draw_ruler = function (pos) {
let offset = 15 * this.scale
let top = offset
let bottom = (dotgrid.tool.settings.size.height * this.scale)+offset
let bottom = (dotgrid.tool.settings.size.height * this.scale) + offset
let left = offset
let right = (dotgrid.tool.settings.size.width * this.scale)
// Translation
this.draw_rule({x:pos.x * this.scale,y:top},{x:pos.x * this.scale,y:bottom});
this.draw_rule({x:left,y:pos.y * this.scale},{x:right,y:pos.y * this.scale});
this.draw_rule({ x: pos.x * this.scale, y: top }, { x: pos.x * this.scale, y: bottom })
this.draw_rule({ x: left, y: pos.y * this.scale }, { x: right, y: pos.y * this.scale })
}
this.draw_rulers = function()
{
if(!dotgrid.cursor.translation){ return; }
this.draw_rulers = function () {
if (!dotgrid.cursor.translation) { return }
let ctx = this.el.getContext('2d');
let ctx = this.el.getContext('2d')
this.draw_ruler(dotgrid.cursor.translation.to)
ctx.setLineDash([]);
ctx.restore();
ctx.setLineDash([])
ctx.restore()
}
this.draw_handle = function(pos, radius = 6)
{
let ctx = this.el.getContext('2d');
this.draw_handle = function (pos, radius = 6) {
let ctx = this.el.getContext('2d')
ctx.beginPath();
ctx.lineWidth = 3;
ctx.lineCap="round";
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), radius+3, 0, 2 * Math.PI, false);
ctx.fillStyle = dotgrid.theme.active.f_high;
ctx.fill();
ctx.strokeStyle = dotgrid.theme.active.f_high;
ctx.stroke();
ctx.closePath();
ctx.beginPath()
ctx.lineWidth = 3
ctx.lineCap = 'round'
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), radius + 3, 0, 2 * Math.PI, false)
ctx.fillStyle = dotgrid.theme.active.f_high
ctx.fill()
ctx.strokeStyle = dotgrid.theme.active.f_high
ctx.stroke()
ctx.closePath()
ctx.beginPath();
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false);
ctx.fillStyle = dotgrid.theme.active.f_low;
ctx.fill();
ctx.closePath();
ctx.beginPath()
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false)
ctx.fillStyle = dotgrid.theme.active.f_low
ctx.fill()
ctx.closePath()
ctx.beginPath();
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius-3, 0, 2 * Math.PI, false);
ctx.fillStyle = dotgrid.theme.active.f_high;
ctx.fill();
ctx.closePath();
ctx.beginPath()
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius - 3, 0, 2 * Math.PI, false)
ctx.fillStyle = dotgrid.theme.active.f_high
ctx.fill()
ctx.closePath()
}
this.draw_path = function(path,style)
{
let ctx = this.el.getContext('2d');
let p = new Path2D(path);
this.draw_path = function (path, style) {
let ctx = this.el.getContext('2d')
let p = new Path2D(path)
ctx.strokeStyle = style.color;
ctx.lineWidth = style.thickness * this.scale;
ctx.lineCap = style.strokeLinecap;
ctx.lineJoin = style.strokeLinejoin;
ctx.strokeStyle = style.color
ctx.lineWidth = style.thickness * this.scale
ctx.lineCap = style.strokeLinecap
ctx.lineJoin = style.strokeLinejoin
if(style.fill && style.fill != "none"){
if (style.fill && style.fill != 'none') {
ctx.fillStyle = style.color
ctx.fill(p);
ctx.fill(p)
}
// Dash
if(style.strokeLineDash){ ctx.setLineDash(style.strokeLineDash); }
else{ ctx.setLineDash([]); }
ctx.stroke(p);
if (style.strokeLineDash) { ctx.setLineDash(style.strokeLineDash) } else { ctx.setLineDash([]) }
ctx.stroke(p)
}
this.draw_translation = function()
{
if(!dotgrid.cursor.translation){ return; }
this.draw_translation = function () {
if (!dotgrid.cursor.translation) { return }
let ctx = this.el.getContext('2d');
ctx.beginPath();
ctx.moveTo((dotgrid.cursor.translation.from.x * this.scale),(dotgrid.cursor.translation.from.y * this.scale));
ctx.lineTo((dotgrid.cursor.translation.to.x * this.scale),(dotgrid.cursor.translation.to.y * this.scale));
ctx.lineCap="round";
ctx.lineWidth = 5;
ctx.strokeStyle = dotgrid.theme.active.f_low;
ctx.setLineDash([5,10]);
ctx.stroke();
ctx.closePath();
let ctx = this.el.getContext('2d')
ctx.setLineDash([]);
ctx.restore();
ctx.beginPath()
ctx.moveTo((dotgrid.cursor.translation.from.x * this.scale), (dotgrid.cursor.translation.from.y * this.scale))
ctx.lineTo((dotgrid.cursor.translation.to.x * this.scale), (dotgrid.cursor.translation.to.y * this.scale))
ctx.lineCap = 'round'
ctx.lineWidth = 5
ctx.strokeStyle = dotgrid.theme.active.f_low
ctx.setLineDash([5, 10])
ctx.stroke()
ctx.closePath()
ctx.setLineDash([])
ctx.restore()
}
this.draw_cursor = function(pos = dotgrid.cursor.pos,radius = dotgrid.tool.style().thickness-1)
{
let ctx = this.el.getContext('2d');
this.draw_cursor = function (pos = dotgrid.cursor.pos, radius = dotgrid.tool.style().thickness - 1) {
let ctx = this.el.getContext('2d')
ctx.beginPath();
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), 5, 0, 2 * Math.PI, false);
ctx.strokeStyle = dotgrid.theme.active.background;
ctx.stroke();
ctx.closePath();
ctx.beginPath()
ctx.lineWidth = 3
ctx.lineCap = 'round'
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), 5, 0, 2 * Math.PI, false)
ctx.strokeStyle = dotgrid.theme.active.background
ctx.stroke()
ctx.closePath()
ctx.beginPath();
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), clamp(radius,5,100), 0, 2 * Math.PI, false);
ctx.strokeStyle = dotgrid.theme.active.f_med;
ctx.stroke();
ctx.closePath();
ctx.beginPath()
ctx.lineWidth = 3
ctx.lineCap = 'round'
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), clamp(radius, 5, 100), 0, 2 * Math.PI, false)
ctx.strokeStyle = dotgrid.theme.active.f_med
ctx.stroke()
ctx.closePath()
}
this.draw_preview = function()
{
let ctx = this.el.getContext('2d');
this.draw_preview = function () {
let ctx = this.el.getContext('2d')
let operation = dotgrid.cursor.operation && dotgrid.cursor.operation.cast ? dotgrid.cursor.operation.cast : null
if(!dotgrid.tool.can_cast(operation)){ return; }
if(operation == "close"){ return; }
if (!dotgrid.tool.can_cast(operation)) { return }
if (operation == 'close') { return }
let path = new Generator([{vertices:dotgrid.tool.vertices,type:operation}]).toString({x:0,y:0},2)
let path = new Generator([{ vertices: dotgrid.tool.vertices, type: operation }]).toString({ x: 0, y: 0 }, 2)
let style = {
color:dotgrid.theme.active.f_med,
thickness:2,
strokeLinecap:"round",
strokeLinejoin:"round",
strokeLineDash:[5, 15]
color: dotgrid.theme.active.f_med,
thickness: 2,
strokeLinecap: 'round',
strokeLinejoin: 'round',
strokeLineDash: [5, 15]
}
this.draw_path(path,style)
this.draw_path(path, style)
ctx.setLineDash([]);
ctx.restore();
ctx.setLineDash([])
ctx.restore()
}
function pos_is_equal(a,b){ return a && b && Math.abs(a.x) == Math.abs(b.x) && Math.abs(a.y) == Math.abs(b.y) }
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
function pos_is_equal (a, b) { return a && b && Math.abs(a.x) == Math.abs(b.x) && Math.abs(a.y) == Math.abs(b.y) }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
}

View File

@ -1,55 +1,52 @@
'use strict';
'use strict'
function Interface()
{
this.el = document.createElement("div");
this.el.id = "interface";
function Interface () {
this.el = document.createElement('div')
this.el.id = 'interface'
this.el.appendChild(this.menu_el = document.createElement("div"));
this.menu_el.id = "menu";
this.el.appendChild(this.menu_el = document.createElement('div'))
this.menu_el.id = 'menu'
this.is_visible = true;
this.zoom = false;
this.is_visible = true
this.zoom = false
this.install = function(host)
{
host.appendChild(this.el);
this.install = function (host) {
host.appendChild(this.el)
}
this.start = function(host)
{
let html = ""
this.start = function (host) {
let html = ''
let options = {
cast:{
line: { key:"A",icon:"M60,60 L240,240" },
arc_c: { key:"S",icon:"M60,60 A180,180 0 0,1 240,240" },
arc_r: { key:"D",icon:"M60,60 A180,180 0 0,0 240,240" },
bezier: { key:"F",icon:"M60,60 Q60,150 150,150 Q240,150 240,240" },
close: { key:"Z",icon:"M60,60 A180,180 0 0,1 240,240 M60,60 A180,180 0 0,0 240,240" }
cast: {
line: { key: 'A', icon: 'M60,60 L240,240' },
arc_c: { key: 'S', icon: 'M60,60 A180,180 0 0,1 240,240' },
arc_r: { key: 'D', icon: 'M60,60 A180,180 0 0,0 240,240' },
bezier: { key: 'F', icon: 'M60,60 Q60,150 150,150 Q240,150 240,240' },
close: { key: 'Z', icon: 'M60,60 A180,180 0 0,1 240,240 M60,60 A180,180 0 0,0 240,240' }
},
toggle:{
linecap: { key:"Q",icon:"M60,60 L60,60 L180,180 L240,180 L240,240 L180,240 L180,180" },
linejoin: { key:"W",icon:"M60,60 L120,120 L180,120 M120,180 L180,180 L240,240" },
thickness: { key:"",icon:"M120,90 L120,90 L90,120 L180,210 L210,180 Z M105,105 L105,105 L60,60 M195,195 L195,195 L240,240" },
mirror: { key:"E",icon:"M60,60 L60,60 L120,120 M180,180 L180,180 L240,240 M210,90 L210,90 L180,120 M120,180 L120,180 L90,210" },
fill: { key:"R",icon:"M60,60 L60,150 L150,150 L240,150 L240,240 Z" }
toggle: {
linecap: { key: 'Q', icon: 'M60,60 L60,60 L180,180 L240,180 L240,240 L180,240 L180,180' },
linejoin: { key: 'W', icon: 'M60,60 L120,120 L180,120 M120,180 L180,180 L240,240' },
thickness: { key: '', icon: 'M120,90 L120,90 L90,120 L180,210 L210,180 Z M105,105 L105,105 L60,60 M195,195 L195,195 L240,240' },
mirror: { key: 'E', icon: 'M60,60 L60,60 L120,120 M180,180 L180,180 L240,240 M210,90 L210,90 L180,120 M120,180 L120,180 L90,210' },
fill: { key: 'R', icon: 'M60,60 L60,150 L150,150 L240,150 L240,240 Z' }
},
misc:{
color: { key:"G",icon:"M150,60 A90,90 0 0,1 240,150 A-90,90 0 0,1 150,240 A-90,-90 0 0,1 60,150 A90,-90 0 0,1 150,60"}
misc: {
color: { key: 'G', icon: 'M150,60 A90,90 0 0,1 240,150 A-90,90 0 0,1 150,240 A-90,-90 0 0,1 60,150 A90,-90 0 0,1 150,60' }
},
source:{
open: { key:"c-O", icon:"M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M155,95 A60,60 0 0,1 215,155 A60,60 0 0,1 155,215 A60,60 0 0,1 95,155 A60,60 0 0,1 155,95 "},
render: { key:"c-R", icon:"M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,155 L110,155 L200,155 "},
export: { key:"c-E", icon:"M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,140 L110,140 L200,140 M110,170 L110,170 L200,170"},
save: { key:"c-S", icon:"M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,155 L110,155 L200,155 M110,185 L110,185 L200,185 M110,125 L110,125 L200,125"},
grid: { key:"H", icon:"M65,155 Q155,245 245,155 M65,155 Q155,65 245,155 M155,125 A30,30 0 0,1 185,155 A30,30 0 0,1 155,185 A30,30 0 0,1 125,155 A30,30 0 0,1 155,125 "},
}
source: {
open: { key: 'c-O', icon: 'M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M155,95 A60,60 0 0,1 215,155 A60,60 0 0,1 155,215 A60,60 0 0,1 95,155 A60,60 0 0,1 155,95 ' },
render: { key: 'c-R', icon: 'M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,155 L110,155 L200,155 ' },
export: { key: 'c-E', icon: 'M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,140 L110,140 L200,140 M110,170 L110,170 L200,170' },
save: { key: 'c-S', icon: 'M155,65 A90,90 0 0,1 245,155 A90,90 0 0,1 155,245 A90,90 0 0,1 65,155 A90,90 0 0,1 155,65 M110,155 L110,155 L200,155 M110,185 L110,185 L200,185 M110,125 L110,125 L200,125' },
grid: { key: 'H', icon: 'M65,155 Q155,245 245,155 M65,155 Q155,65 245,155 M155,125 A30,30 0 0,1 185,155 A30,30 0 0,1 155,185 A30,30 0 0,1 125,155 A30,30 0 0,1 155,125 ' }
}
}
for(const type in options){
const tools = options[type];
for(const name in tools){
const tool = tools[name];
for (const type in options) {
const tools = options[type]
for (const name in tools) {
const tool = tools[name]
html += `
<svg
id="option_${name}"
@ -60,99 +57,87 @@ function Interface()
onmouseover="dotgrid.interface.over('${type}','${name}')"
viewBox="0 0 300 300"
class="icon ${type}">
<path id="${name}_path" class="icon_path" d="${tool.icon}"/>${name == "depth" ? `<path class="icon_path inactive" d=""/>` : ""}
<path id="${name}_path" class="icon_path" d="${tool.icon}"/>${name == 'depth' ? `<path class="icon_path inactive" d=""/>` : ''}
<rect ar="${name}" width="300" height="300" opacity="0">
<title>${name.capitalize()}${tool.key ? '('+tool.key+')' : ''}</title>
<title>${name.capitalize()}${tool.key ? '(' + tool.key + ')' : ''}</title>
</rect>
</svg>`
}
}
this.menu_el.innerHTML = html
this.menu_el.appendChild(dotgrid.picker.el)
}
this.over = function(type,name)
{
this.over = function (type, name) {
dotgrid.cursor.operation = {}
dotgrid.cursor.operation[type] = name;
dotgrid.cursor.operation[type] = name
}
this.out = function(type,name)
{
dotgrid.cursor.operation = ""
this.out = function (type, name) {
dotgrid.cursor.operation = ''
}
this.up = function(type,name)
{
if(!dotgrid.tool[type]){ console.warn(`Unknown option(type): ${type}.${name}`,dotgrid.tool); return; }
this.up = function (type, name) {
if (!dotgrid.tool[type]) { console.warn(`Unknown option(type): ${type}.${name}`, dotgrid.tool); return }
this.update(true);
this.update(true)
}
this.down = function(type,name)
{
if(!dotgrid.tool[type]){ console.warn(`Unknown option(type): ${type}.${name}`,dotgrid.tool); return; }
this.down = function (type, name) {
if (!dotgrid.tool[type]) { console.warn(`Unknown option(type): ${type}.${name}`, dotgrid.tool); return }
dotgrid.tool[type](name)
this.update(true);
this.update(true)
}
this.prev_operation = null;
this.prev_operation = null
this.update = function(force = false,id)
{
if(this.prev_operation == dotgrid.cursor.operation && force == false){ return; }
this.update = function (force = false, id) {
if (this.prev_operation == dotgrid.cursor.operation && force == false) { return }
let multi_vertices = null;
let multi_vertices = null
let segments = dotgrid.tool.layer()
const sum_segments = dotgrid.tool.length();
const sum_segments = dotgrid.tool.length()
for(const i in segments){
if(segments[i].vertices.length > 2){ multi_vertices = true; break; }
for (const i in segments) {
if (segments[i].vertices.length > 2) { multi_vertices = true; break }
}
document.getElementById("option_line").className.baseVal = !dotgrid.tool.can_cast("line") ? "icon inactive" : "icon";
document.getElementById("option_arc_c").className.baseVal = !dotgrid.tool.can_cast("arc_c") ? "icon inactive" : "icon";
document.getElementById("option_arc_r").className.baseVal = !dotgrid.tool.can_cast("arc_r") ? "icon inactive" : "icon";
document.getElementById("option_bezier").className.baseVal = !dotgrid.tool.can_cast("bezier") ? "icon inactive" : "icon";
document.getElementById("option_close").className.baseVal = !dotgrid.tool.can_cast("close") ? "icon inactive" : "icon";
document.getElementById("option_thickness").className.baseVal = dotgrid.tool.layer().length < 1 ? "icon inactive" : "icon";
document.getElementById("option_linecap").className.baseVal = dotgrid.tool.layer().length < 1 ? "icon inactive" : "icon";
document.getElementById("option_linejoin").className.baseVal = dotgrid.tool.layer().length < 1 || !multi_vertices ? "icon inactive" : "icon";
document.getElementById("option_mirror").className.baseVal = dotgrid.tool.layer().length < 1 ? "icon inactive" : "icon";
document.getElementById("option_fill").className.baseVal = dotgrid.tool.layer().length < 1 ? "icon inactive" : "icon";
document.getElementById("option_color").children[0].style.fill = dotgrid.tool.style().color;
document.getElementById("option_color").children[0].style.stroke = dotgrid.tool.style().color;
document.getElementById("option_color").className.baseVal = "icon";
document.getElementById('option_line').className.baseVal = !dotgrid.tool.can_cast('line') ? 'icon inactive' : 'icon'
document.getElementById('option_arc_c').className.baseVal = !dotgrid.tool.can_cast('arc_c') ? 'icon inactive' : 'icon'
document.getElementById('option_arc_r').className.baseVal = !dotgrid.tool.can_cast('arc_r') ? 'icon inactive' : 'icon'
document.getElementById('option_bezier').className.baseVal = !dotgrid.tool.can_cast('bezier') ? 'icon inactive' : 'icon'
document.getElementById('option_close').className.baseVal = !dotgrid.tool.can_cast('close') ? 'icon inactive' : 'icon'
document.getElementById('option_thickness').className.baseVal = dotgrid.tool.layer().length < 1 ? 'icon inactive' : 'icon'
document.getElementById('option_linecap').className.baseVal = dotgrid.tool.layer().length < 1 ? 'icon inactive' : 'icon'
document.getElementById('option_linejoin').className.baseVal = dotgrid.tool.layer().length < 1 || !multi_vertices ? 'icon inactive' : 'icon'
document.getElementById('option_mirror').className.baseVal = dotgrid.tool.layer().length < 1 ? 'icon inactive' : 'icon'
document.getElementById('option_fill').className.baseVal = dotgrid.tool.layer().length < 1 ? 'icon inactive' : 'icon'
document.getElementById('option_color').children[0].style.fill = dotgrid.tool.style().color
document.getElementById('option_color').children[0].style.stroke = dotgrid.tool.style().color
document.getElementById('option_color').className.baseVal = 'icon'
// Source
document.getElementById("option_save").className.baseVal = sum_segments < 1 ? "icon inactive source" : "icon source";
document.getElementById("option_export").className.baseVal = sum_segments < 1 ? "icon inactive source" : "icon source";
document.getElementById("option_render").className.baseVal = sum_segments < 1 ? "icon inactive source" : "icon source";
document.getElementById('option_save').className.baseVal = sum_segments < 1 ? 'icon inactive source' : 'icon source'
document.getElementById('option_export').className.baseVal = sum_segments < 1 ? 'icon inactive source' : 'icon source'
document.getElementById('option_render').className.baseVal = sum_segments < 1 ? 'icon inactive source' : 'icon source'
document.getElementById('option_grid').className.baseVal = dotgrid.guide.show_extras ? 'icon inactive source' : 'icon source'
document.getElementById("option_grid").className.baseVal = dotgrid.guide.show_extras ? "icon inactive source" : "icon source";
// Grid
if(dotgrid.guide.show_extras){ document.getElementById("grid_path").setAttribute("d","M65,155 Q155,245 245,155 M65,155 Q155,65 245,155 M155,125 A30,30 0 0,1 185,155 A30,30 0 0,1 155,185 A30,30 0 0,1 125,155 A30,30 0 0,1 155,125 ") }
else{ document.getElementById("grid_path").setAttribute("d","M65,155 Q155,245 245,155 M65,155 ") }
if (dotgrid.guide.show_extras) { document.getElementById('grid_path').setAttribute('d', 'M65,155 Q155,245 245,155 M65,155 Q155,65 245,155 M155,125 A30,30 0 0,1 185,155 A30,30 0 0,1 155,185 A30,30 0 0,1 125,155 A30,30 0 0,1 155,125 ') } else { document.getElementById('grid_path').setAttribute('d', 'M65,155 Q155,245 245,155 M65,155 ') }
// Mirror
if(dotgrid.tool.style().mirror_style == 0){ document.getElementById("mirror_path").setAttribute("d","M60,60 L60,60 L120,120 M180,180 L180,180 L240,240 M210,90 L210,90 L180,120 M120,180 L120,180 L90,210") }
else if(dotgrid.tool.style().mirror_style == 1){ document.getElementById("mirror_path").setAttribute("d","M60,60 L240,240 M180,120 L210,90 M120,180 L90,210") }
else if(dotgrid.tool.style().mirror_style == 2){ document.getElementById("mirror_path").setAttribute("d","M210,90 L210,90 L90,210 M60,60 L60,60 L120,120 M180,180 L180,180 L240,240") }
else if(dotgrid.tool.style().mirror_style == 3){ document.getElementById("mirror_path").setAttribute("d","M60,60 L60,60 L120,120 L120,120 L180,120 M120,150 L120,150 L180,150 M120,180 L120,180 L180,180 L180,180 L240,240 ") }
else if(dotgrid.tool.style().mirror_style == 4){ document.getElementById("mirror_path").setAttribute("d","M120,120 L120,120 L120,120 L180,120 M120,150 L120,150 L180,150 M120,180 L120,180 L180,180 L180,180 L180,180 L240,240 M120,210 L120,210 L180,210 M120,90 L120,90 L180,90 M60,60 L60,60 L120,120 ") }
if (dotgrid.tool.style().mirror_style == 0) { document.getElementById('mirror_path').setAttribute('d', 'M60,60 L60,60 L120,120 M180,180 L180,180 L240,240 M210,90 L210,90 L180,120 M120,180 L120,180 L90,210') } else if (dotgrid.tool.style().mirror_style == 1) { document.getElementById('mirror_path').setAttribute('d', 'M60,60 L240,240 M180,120 L210,90 M120,180 L90,210') } else if (dotgrid.tool.style().mirror_style == 2) { document.getElementById('mirror_path').setAttribute('d', 'M210,90 L210,90 L90,210 M60,60 L60,60 L120,120 M180,180 L180,180 L240,240') } else if (dotgrid.tool.style().mirror_style == 3) { document.getElementById('mirror_path').setAttribute('d', 'M60,60 L60,60 L120,120 L120,120 L180,120 M120,150 L120,150 L180,150 M120,180 L120,180 L180,180 L180,180 L240,240 ') } else if (dotgrid.tool.style().mirror_style == 4) { document.getElementById('mirror_path').setAttribute('d', 'M120,120 L120,120 L120,120 L180,120 M120,150 L120,150 L180,150 M120,180 L120,180 L180,180 L180,180 L180,180 L240,240 M120,210 L120,210 L180,210 M120,90 L120,90 L180,90 M60,60 L60,60 L120,120 ') }
this.prev_operation = dotgrid.cursor.operation;
this.prev_operation = dotgrid.cursor.operation
}
this.toggle = function()
{
this.is_visible = this.is_visible ? false : true;
this.el.className = this.is_visible ? "visible" : "hidden";
this.toggle = function () {
this.is_visible = !this.is_visible
this.el.className = this.is_visible ? 'visible' : 'hidden'
}
}

View File

@ -1,198 +1,185 @@
'use strict';
'use strict'
function Controller()
{
this.menu = {default:{}};
this.mode = "default";
function Controller () {
this.menu = { default: {} }
this.mode = 'default'
this.app = require('electron').remote.app;
this.app = require('electron').remote.app
this.start = function()
{
this.start = function () {
}
this.add = function(mode,cat,label,fn,accelerator)
{
if(!this.menu[mode]){ this.menu[mode] = {}; }
if(!this.menu[mode][cat]){ this.menu[mode][cat] = {}; }
this.menu[mode][cat][label] = {fn:fn,accelerator:accelerator};
console.log(`${mode}/${cat}/${label} <${accelerator}>`);
this.add = function (mode, cat, label, fn, accelerator) {
if (!this.menu[mode]) { this.menu[mode] = {} }
if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
this.menu[mode][cat][label] = { fn: fn, accelerator: accelerator }
console.log(`${mode}/${cat}/${label} <${accelerator}>`)
}
this.add_role = function(mode,cat,label)
{
if(!this.menu[mode]){ this.menu[mode] = {}; }
if(!this.menu[mode][cat]){ this.menu[mode][cat] = {}; }
this.menu[mode][cat][label] = {role:label};
this.add_role = function (mode, cat, label) {
if (!this.menu[mode]) { this.menu[mode] = {} }
if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
this.menu[mode][cat][label] = { role: label }
}
this.set = function(mode = "default")
{
this.mode = mode;
this.commit();
this.set = function (mode = 'default') {
this.mode = mode
this.commit()
}
this.format = function()
{
let f = [];
let m = this.menu[this.mode];
for(const cat in m){
let submenu = [];
for(const name in m[cat]){
let option = m[cat][name];
if(option.role){
submenu.push({role:option.role})
}
else{
submenu.push({label:name,accelerator:option.accelerator,click:option.fn})
this.format = function () {
let f = []
let m = this.menu[this.mode]
for (const cat in m) {
let submenu = []
for (const name in m[cat]) {
let option = m[cat][name]
if (option.role) {
submenu.push({ role: option.role })
} else {
submenu.push({ label: name, accelerator: option.accelerator, click: option.fn })
}
}
f.push({label:cat,submenu:submenu});
f.push({ label: cat, submenu: submenu })
}
return f;
return f
}
this.commit = function()
{
this.app.inject_menu(this.format());
this.commit = function () {
this.app.inject_menu(this.format())
}
this.docs = function()
{
console.log("Generating docs..");
this.docs = function () {
console.log('Generating docs..')
let svg = this.generate_svg(this.format())
let txt = this.documentation(this.format());
let txt = this.documentation(this.format())
dialog.showSaveDialog((fileName) => {
if (fileName === undefined){ return; }
fileName = fileName.substr(-4,4) != ".svg" ? fileName+".svg" : fileName;
fs.writeFile(fileName,svg);
fs.writeFile(fileName.replace(".svg",".md"),txt);
});
if (fileName === undefined) { return }
fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName
fs.writeFile(fileName, svg)
fs.writeFile(fileName.replace('.svg', '.md'), txt)
})
}
this.generate_svg = function(m)
{
let svg_html = "";
this.generate_svg = function (m) {
let svg_html = ''
for(const id in this.layout){
let key = this.layout[id];
let acc = this.accelerator_for_key(key.name,m);
svg_html += `<rect x="${key.x + 1}" y="${key.y + 1}" width="${key.width - 2}" height="${key.height - 2}" rx="4" ry="4" title="${key.name}" stroke="#ccc" fill="none" stroke-width="1"/>`;
svg_html += `<rect x="${key.x + 3}" y="${key.y + 3}" width="${key.width - 6}" height="${key.height - 12}" rx="3" ry="3" title="${key.name}" stroke="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" fill="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" stroke-width="1"/>`;
svg_html += `<text x="${key.x + 10}" y="${key.y + 20}" font-size='11' font-family='Input Mono' stroke-width='0' fill='${acc.basic ? '#fff' : '#000'}'>${key.name.toUpperCase()}</text>`;
svg_html += acc && acc.basic ? `<text x="${key.x + 10}" y="${key.y + 35}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#fff'>${acc.basic}</text>` : '';
svg_html += acc && acc.ctrl ? `<text x="${key.x + 10}" y="${key.y + 45}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#000'>${acc.ctrl}</text>` : '';
for (const id in this.layout) {
let key = this.layout[id]
let acc = this.accelerator_for_key(key.name, m)
svg_html += `<rect x="${key.x + 1}" y="${key.y + 1}" width="${key.width - 2}" height="${key.height - 2}" rx="4" ry="4" title="${key.name}" stroke="#ccc" fill="none" stroke-width="1"/>`
svg_html += `<rect x="${key.x + 3}" y="${key.y + 3}" width="${key.width - 6}" height="${key.height - 12}" rx="3" ry="3" title="${key.name}" stroke="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" fill="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" stroke-width="1"/>`
svg_html += `<text x="${key.x + 10}" y="${key.y + 20}" font-size='11' font-family='Input Mono' stroke-width='0' fill='${acc.basic ? '#fff' : '#000'}'>${key.name.toUpperCase()}</text>`
svg_html += acc && acc.basic ? `<text x="${key.x + 10}" y="${key.y + 35}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#fff'>${acc.basic}</text>` : ''
svg_html += acc && acc.ctrl ? `<text x="${key.x + 10}" y="${key.y + 45}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#000'>${acc.ctrl}</text>` : ''
}
return `<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="900" height="300" version="1.0" style="fill:none;stroke:black;stroke-width:2px;">${svg_html}</svg>`;
return `<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="900" height="300" version="1.0" style="fill:none;stroke:black;stroke-width:2px;">${svg_html}</svg>`
}
this.documentation = function()
{
let txt = "";
this.documentation = function () {
let txt = ''
txt += this.documentation_for_mode("default",this.menu.default);
txt += this.documentation_for_mode('default', this.menu.default)
for(name in this.menu){
if(name == "default"){ continue; }
txt += this.documentation_for_mode(name,this.menu[name]);
for (name in this.menu) {
if (name == 'default') { continue }
txt += this.documentation_for_mode(name, this.menu[name])
}
return txt;
return txt
}
this.documentation_for_mode = function(name,mode)
{
let txt = `## ${name} Mode\n\n`;
this.documentation_for_mode = function (name, mode) {
let txt = `## ${name} Mode\n\n`
for(const id in mode){
if(id == "*"){ continue; }
txt += `### ${id}\n`;
for(const name in mode[id]){
let option = mode[id][name];
txt += `- ${name}: \`${option.accelerator}\`\n`;
for (const id in mode) {
if (id == '*') { continue }
txt += `### ${id}\n`
for (const name in mode[id]) {
let option = mode[id][name]
txt += `- ${name}: \`${option.accelerator}\`\n`
}
txt += "\n"
txt += '\n'
}
return txt+"\n";
return txt + '\n'
}
this.accelerator_for_key = function(key,menu)
{
let acc = {basic:null,ctrl:null}
for(const cat in menu){
let options = menu[cat];
for(const id in options.submenu){
let option = options.submenu[id]; if(option.role){ continue; }
acc.basic = (option.accelerator.toLowerCase() == key.toLowerCase()) ? option.label.toUpperCase().replace("TOGGLE ","").substr(0,8).trim() : acc.basic;
acc.ctrl = (option.accelerator.toLowerCase() == ("CmdOrCtrl+"+key).toLowerCase()) ? option.label.toUpperCase().replace("TOGGLE ","").substr(0,8).trim() : acc.ctrl;
this.accelerator_for_key = function (key, menu) {
let acc = { basic: null, ctrl: null }
for (const cat in menu) {
let options = menu[cat]
for (const id in options.submenu) {
let option = options.submenu[id]; if (option.role) { continue }
acc.basic = (option.accelerator.toLowerCase() == key.toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.basic
acc.ctrl = (option.accelerator.toLowerCase() == ('CmdOrCtrl+' + key).toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.ctrl
}
}
return acc;
return acc
}
this.layout = [
{x:0, y:0, width:60, height:60, name:"esc"},
{x:60, y:0, width:60, height:60, name:"1"},
{x:120, y:0, width:60, height:60, name:"2"},
{x:180, y:0, width:60, height:60, name:"3"},
{x:240, y:0, width:60, height:60, name:"4"},
{x:300, y:0, width:60, height:60, name:"5"},
{x:360, y:0, width:60, height:60, name:"6"},
{x:420, y:0, width:60, height:60, name:"7"},
{x:480, y:0, width:60, height:60, name:"8"},
{x:540, y:0, width:60, height:60, name:"9"},
{x:600, y:0, width:60, height:60, name:"0"},
{x:660, y:0, width:60, height:60, name:"-"},
{x:720, y:0, width:60, height:60, name:"plus"},
{x:780, y:0, width:120, height:60, name:"backspace"},
{x:0, y:60, width:90, height:60, name:"tab"},
{x:90, y:60, width:60, height:60, name:"q"},
{x:150, y:60, width:60, height:60, name:"w"},
{x:210, y:60, width:60, height:60, name:"e"},
{x:270, y:60, width:60, height:60, name:"r"},
{x:330, y:60, width:60, height:60, name:"t"},
{x:390, y:60, width:60, height:60, name:"y"},
{x:450, y:60, width:60, height:60, name:"u"},
{x:510, y:60, width:60, height:60, name:"i"},
{x:570, y:60, width:60, height:60, name:"o"},
{x:630, y:60, width:60, height:60, name:"p"},
{x:690, y:60, width:60, height:60, name:"["},
{x:750, y:60, width:60, height:60, name:"]"},
{x:810, y:60, width:90, height:60, name:"|"},
{x:0, y:120, width:105, height:60, name:"caps"},
{x:105, y:120, width:60, height:60, name:"a"},
{x:165, y:120, width:60, height:60, name:"s"},
{x:225, y:120, width:60, height:60, name:"d"},
{x:285, y:120, width:60, height:60, name:"f"},
{x:345, y:120, width:60, height:60, name:"g"},
{x:405, y:120, width:60, height:60, name:"h"},
{x:465, y:120, width:60, height:60, name:"j"},
{x:525, y:120, width:60, height:60, name:"k"},
{x:585, y:120, width:60, height:60, name:"l"},
{x:645, y:120, width:60, height:60, name:";"},
{x:705, y:120, width:60, height:60, name:"'"},
{x:765, y:120, width:135, height:60, name:"enter"},
{x:0, y:180, width:135, height:60, name:"shift"},
{x:135, y:180, width:60, height:60, name:"z"},
{x:195, y:180, width:60, height:60, name:"x"},
{x:255, y:180, width:60, height:60, name:"c"},
{x:315, y:180, width:60, height:60, name:"v"},
{x:375, y:180, width:60, height:60, name:"b"},
{x:435, y:180, width:60, height:60, name:"n"},
{x:495, y:180, width:60, height:60, name:"m"},
{x:555, y:180, width:60, height:60, name:","},
{x:615, y:180, width:60, height:60, name:"."},
{x:675, y:180, width:60, height:60, name:"/"},
{x:735, y:180, width:165, height:60, name:"capslock"},
{x:0, y:240, width:90, height:60, name:"ctrl"},
{x:90, y:240, width:90, height:60, name:"cmd"},
{x:180, y:240, width:90, height:60, name:"alt"},
{x:270, y:240, width:270, height:60, name:"space"},
{x:810, y:240, width:90, height:60, name:"ctrl"},
{x:720, y:240, width:90, height:60, name:"pn"},
{x:630, y:240, width:90, height:60, name:"fn"},
{x:540, y:240, width:90, height:60, name:"alt"}
];
{ x: 0, y: 0, width: 60, height: 60, name: 'esc' },
{ x: 60, y: 0, width: 60, height: 60, name: '1' },
{ x: 120, y: 0, width: 60, height: 60, name: '2' },
{ x: 180, y: 0, width: 60, height: 60, name: '3' },
{ x: 240, y: 0, width: 60, height: 60, name: '4' },
{ x: 300, y: 0, width: 60, height: 60, name: '5' },
{ x: 360, y: 0, width: 60, height: 60, name: '6' },
{ x: 420, y: 0, width: 60, height: 60, name: '7' },
{ x: 480, y: 0, width: 60, height: 60, name: '8' },
{ x: 540, y: 0, width: 60, height: 60, name: '9' },
{ x: 600, y: 0, width: 60, height: 60, name: '0' },
{ x: 660, y: 0, width: 60, height: 60, name: '-' },
{ x: 720, y: 0, width: 60, height: 60, name: 'plus' },
{ x: 780, y: 0, width: 120, height: 60, name: 'backspace' },
{ x: 0, y: 60, width: 90, height: 60, name: 'tab' },
{ x: 90, y: 60, width: 60, height: 60, name: 'q' },
{ x: 150, y: 60, width: 60, height: 60, name: 'w' },
{ x: 210, y: 60, width: 60, height: 60, name: 'e' },
{ x: 270, y: 60, width: 60, height: 60, name: 'r' },
{ x: 330, y: 60, width: 60, height: 60, name: 't' },
{ x: 390, y: 60, width: 60, height: 60, name: 'y' },
{ x: 450, y: 60, width: 60, height: 60, name: 'u' },
{ x: 510, y: 60, width: 60, height: 60, name: 'i' },
{ x: 570, y: 60, width: 60, height: 60, name: 'o' },
{ x: 630, y: 60, width: 60, height: 60, name: 'p' },
{ x: 690, y: 60, width: 60, height: 60, name: '[' },
{ x: 750, y: 60, width: 60, height: 60, name: ']' },
{ x: 810, y: 60, width: 90, height: 60, name: '|' },
{ x: 0, y: 120, width: 105, height: 60, name: 'caps' },
{ x: 105, y: 120, width: 60, height: 60, name: 'a' },
{ x: 165, y: 120, width: 60, height: 60, name: 's' },
{ x: 225, y: 120, width: 60, height: 60, name: 'd' },
{ x: 285, y: 120, width: 60, height: 60, name: 'f' },
{ x: 345, y: 120, width: 60, height: 60, name: 'g' },
{ x: 405, y: 120, width: 60, height: 60, name: 'h' },
{ x: 465, y: 120, width: 60, height: 60, name: 'j' },
{ x: 525, y: 120, width: 60, height: 60, name: 'k' },
{ x: 585, y: 120, width: 60, height: 60, name: 'l' },
{ x: 645, y: 120, width: 60, height: 60, name: ';' },
{ x: 705, y: 120, width: 60, height: 60, name: "'" },
{ x: 765, y: 120, width: 135, height: 60, name: 'enter' },
{ x: 0, y: 180, width: 135, height: 60, name: 'shift' },
{ x: 135, y: 180, width: 60, height: 60, name: 'z' },
{ x: 195, y: 180, width: 60, height: 60, name: 'x' },
{ x: 255, y: 180, width: 60, height: 60, name: 'c' },
{ x: 315, y: 180, width: 60, height: 60, name: 'v' },
{ x: 375, y: 180, width: 60, height: 60, name: 'b' },
{ x: 435, y: 180, width: 60, height: 60, name: 'n' },
{ x: 495, y: 180, width: 60, height: 60, name: 'm' },
{ x: 555, y: 180, width: 60, height: 60, name: ',' },
{ x: 615, y: 180, width: 60, height: 60, name: '.' },
{ x: 675, y: 180, width: 60, height: 60, name: '/' },
{ x: 735, y: 180, width: 165, height: 60, name: 'capslock' },
{ x: 0, y: 240, width: 90, height: 60, name: 'ctrl' },
{ x: 90, y: 240, width: 90, height: 60, name: 'cmd' },
{ x: 180, y: 240, width: 90, height: 60, name: 'alt' },
{ x: 270, y: 240, width: 270, height: 60, name: 'space' },
{ x: 810, y: 240, width: 90, height: 60, name: 'ctrl' },
{ x: 720, y: 240, width: 90, height: 60, name: 'pn' },
{ x: 630, y: 240, width: 90, height: 60, name: 'fn' },
{ x: 540, y: 240, width: 90, height: 60, name: 'alt' }
]
}
module.exports = new Controller();
module.exports = new Controller()

View File

@ -1,52 +1,45 @@
'use strict';
'use strict'
function History()
{
this.index = 0;
this.a = [];
function History () {
this.index = 0
this.a = []
this.clear = function()
{
this.a = [];
this.index = 0;
this.clear = function () {
this.a = []
this.index = 0
}
this.push = function(data)
{
if(this.index < this.a.length-1){
this.fork();
this.push = function (data) {
if (this.index < this.a.length - 1) {
this.fork()
}
this.index = this.a.length;
this.a = this.a.slice(0,this.index);
this.a.push(copy(data));
this.index = this.a.length
this.a = this.a.slice(0, this.index)
this.a.push(copy(data))
if(this.a.length > 20){
this.a.shift();
if (this.a.length > 20) {
this.a.shift()
}
}
this.fork = function()
{
this.a = this.a.slice(0,this.index+1);
this.fork = function () {
this.a = this.a.slice(0, this.index + 1)
}
this.pop = function()
{
return this.a.pop();
this.pop = function () {
return this.a.pop()
}
this.prev = function()
{
this.index = clamp(this.index-1,0,this.a.length-1);
return copy(this.a[this.index]);
this.prev = function () {
this.index = clamp(this.index - 1, 0, this.a.length - 1)
return copy(this.a[this.index])
}
this.next = function()
{
this.index = clamp(this.index+1,0,this.a.length-1);
return copy(this.a[this.index]);
this.next = function () {
this.index = clamp(this.index + 1, 0, this.a.length - 1)
return copy(this.a[this.index])
}
function copy(data){ return data ? JSON.parse(JSON.stringify(data)) : []; }
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
}
function copy (data) { return data ? JSON.parse(JSON.stringify(data)) : [] }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
}

View File

@ -1,56 +1,50 @@
'use strict';
'use strict'
function Theme(default_theme = {background: "#222", f_high: "#fff", f_med: "#ccc", f_low: "#999", f_inv: "#fff", b_high: "#888", b_med: "#666", b_low: "#444", b_inv: "#000" })
{
const themer = this;
function Theme (default_theme = { background: '#222', f_high: '#fff', f_med: '#ccc', f_low: '#999', f_inv: '#fff', b_high: '#888', b_med: '#666', b_low: '#444', b_inv: '#000' }) {
const themer = this
this.el = document.createElement("style")
this.el = document.createElement('style')
this.el.type = 'text/css'
this.callback;
this.active;
this.callback
this.active
this.collection = {
default: default_theme,
noir: {background: "#222", f_high: "#fff", f_med: "#ccc", f_low: "#999", f_inv: "#fff", b_high: "#888", b_med: "#666", b_low: "#444", b_inv: "#000" },
pale: {background: "#e1e1e1", f_high: "#000", f_med: "#777", f_low: "#fff", f_inv: "#000", b_high: "#eee", b_med: "#999", b_low: "#ccc", b_inv: "#fff" }
noir: { background: '#222', f_high: '#fff', f_med: '#ccc', f_low: '#999', f_inv: '#fff', b_high: '#888', b_med: '#666', b_low: '#444', b_inv: '#000' },
pale: { background: '#e1e1e1', f_high: '#000', f_med: '#777', f_low: '#fff', f_inv: '#000', b_high: '#eee', b_med: '#999', b_low: '#ccc', b_inv: '#fff' }
}
this.install = function(host = document.body,callback)
{
console.log("Theme","Installing..")
this.install = function (host = document.body, callback) {
console.log('Theme', 'Installing..')
host.appendChild(this.el)
this.callback = callback
}
this.start = function()
{
console.log("Theme","Starting..")
const storage = is_json(localStorage.theme) ? JSON.parse(localStorage.theme) : this.collection.default;
this.start = function () {
console.log('Theme', 'Starting..')
const storage = is_json(localStorage.theme) ? JSON.parse(localStorage.theme) : this.collection.default
this.load(!storage.background ? this.collection.default : storage)
}
this.save = function(theme)
{
console.log("Theme","Saving..")
this.active = theme;
localStorage.setItem("theme", JSON.stringify(theme));
this.save = function (theme) {
console.log('Theme', 'Saving..')
this.active = theme
localStorage.setItem('theme', JSON.stringify(theme))
}
this.load = function(theme, fall_back = this.collection.noir)
{
if(!theme || !theme.background){ console.warn("Theme","Not a theme",theme); return; }
this.load = function (theme, fall_back = this.collection.noir) {
if (!theme || !theme.background) { console.warn('Theme', 'Not a theme', theme); return }
this.save(theme);
this.apply(theme);
this.save(theme)
this.apply(theme)
if(this.callback){
this.callback();
if (this.callback) {
this.callback()
}
}
this.apply = function(theme)
{
this.apply = function (theme) {
this.el.innerHTML = `
:root {
--background: ${theme.background};
@ -62,92 +56,80 @@ function Theme(default_theme = {background: "#222", f_high: "#fff", f_med: "#ccc
--b_med: ${theme.b_med};
--b_low: ${theme.b_low};
--b_inv: ${theme.b_inv};
}`;
}`
}
this.parse = function(any)
{
if(any && any.background){ return any; }
else if(any && any.data){ return any.data; }
else if(any && is_json(any)){ return JSON.parse(any); }
else if(any && is_html(any)){ return this.extract(any); }
this.parse = function (any) {
if (any && any.background) { return any } else if (any && any.data) { return any.data } else if (any && is_json(any)) { return JSON.parse(any) } else if (any && is_html(any)) { return this.extract(any) }
return null;
return null
}
this.extract = function(text)
{
const svg = new DOMParser().parseFromString(text,"text/xml")
try{
this.extract = function (text) {
const svg = new DOMParser().parseFromString(text, 'text/xml')
try {
return {
"background": svg.getElementById("background").getAttribute("fill"),
"f_high": svg.getElementById("f_high").getAttribute("fill"),
"f_med": svg.getElementById("f_med").getAttribute("fill"),
"f_low": svg.getElementById("f_low").getAttribute("fill"),
"f_inv": svg.getElementById("f_inv").getAttribute("fill"),
"b_high": svg.getElementById("b_high").getAttribute("fill"),
"b_med": svg.getElementById("b_med").getAttribute("fill"),
"b_low": svg.getElementById("b_low").getAttribute("fill"),
"b_inv": svg.getElementById("b_inv").getAttribute("fill")
};
}
catch(err){
console.warn("Theme","Incomplete SVG Theme", err)
'background': svg.getElementById('background').getAttribute('fill'),
'f_high': svg.getElementById('f_high').getAttribute('fill'),
'f_med': svg.getElementById('f_med').getAttribute('fill'),
'f_low': svg.getElementById('f_low').getAttribute('fill'),
'f_inv': svg.getElementById('f_inv').getAttribute('fill'),
'b_high': svg.getElementById('b_high').getAttribute('fill'),
'b_med': svg.getElementById('b_med').getAttribute('fill'),
'b_low': svg.getElementById('b_low').getAttribute('fill'),
'b_inv': svg.getElementById('b_inv').getAttribute('fill')
}
} catch (err) {
console.warn('Theme', 'Incomplete SVG Theme', err)
}
}
this.reset = function()
{
this.load(this.collection.default);
this.reset = function () {
this.load(this.collection.default)
}
// Defaults
this.pale = function()
{
this.pale = function () {
this.load(this.collection.pale)
}
this.noir = function()
{
this.noir = function () {
this.load(this.collection.noir)
}
this.invert = function()
{
this.invert = function () {
this.load(this.active.background == this.collection.noir.background ? this.collection.pale : this.collection.noir)
}
// Drag
this.drag = function(e)
{
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
this.drag = function (e) {
e.stopPropagation()
e.preventDefault()
e.dataTransfer.dropEffect = 'copy'
}
this.drop = function(e)
{
e.preventDefault();
e.stopPropagation();
this.drop = function (e) {
e.preventDefault()
e.stopPropagation()
const file = e.dataTransfer.files[0];
const file = e.dataTransfer.files[0]
if(!file || !file.name){ console.warn("Theme","Unnamed file."); return; }
if(file.name.indexOf(".thm") < 0 && file.name.indexOf(".svg") < 0){ console.warn("Theme","Skipped, not a theme"); return; }
if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return }
if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return }
const reader = new FileReader();
reader.onload = function(e){
themer.load(themer.parse(e.target.result));
};
reader.readAsText(file);
const reader = new FileReader()
reader.onload = function (e) {
themer.load(themer.parse(e.target.result))
}
reader.readAsText(file)
}
window.addEventListener('dragover',this.drag);
window.addEventListener('drop', this.drop);
window.addEventListener('dragover', this.drag)
window.addEventListener('drop', this.drop)
function is_json(text){ try{ JSON.parse(text); return true; } catch (error){ return false; } }
function is_html(text){ try{ new DOMParser().parseFromString(text,"text/xml"); return true; } catch (error){ return false; } }
}
function is_json (text) { try { JSON.parse(text); return true } catch (error) { return false } }
function is_html (text) { try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } }
}

View File

@ -1,110 +1,100 @@
'use strict';
'use strict'
function Picker()
{
this.memory = "";
this.el = document.createElement("div");
this.el.id = "picker"
this.is_active = false;
this.input = document.createElement("input");
this.input.id = "picker_input"
function Picker () {
this.memory = ''
this.el = document.createElement('div')
this.el.id = 'picker'
this.is_active = false
this.input = document.createElement('input')
this.input.id = 'picker_input'
this.el.appendChild(this.input)
this.start = function()
{
if(this.is_active){ return; }
this.start = function () {
if (this.is_active) { return }
this.is_active = true;
this.is_active = true
this.input.setAttribute("placeholder",`${dotgrid.tool.style().color.replace("#","").trim()}`)
this.input.setAttribute("maxlength",6)
this.input.setAttribute('placeholder', `${dotgrid.tool.style().color.replace('#', '').trim()}`)
this.input.setAttribute('maxlength', 6)
dotgrid.interface.el.className = "picker"
dotgrid.interface.el.className = 'picker'
this.input.focus()
this.input.value = ""
this.input.value = ''
try{ dotgrid.controller.set("picker"); }
catch(err){ }
try { dotgrid.controller.set('picker') } catch (err) { }
}
this.update = function()
{
if(!this.is_active){ return; }
if(!is_color(this.input.value)){ return; }
this.update = function () {
if (!this.is_active) { return }
if (!is_color(this.input.value)) { return }
const hex = `#${this.input.value}`;
const hex = `#${this.input.value}`
document.getElementById("option_color").children[0].style.fill = hex;
document.getElementById("option_color").children[0].style.stroke = hex;
document.getElementById('option_color').children[0].style.fill = hex
document.getElementById('option_color').children[0].style.stroke = hex
}
this.stop = function()
{
if(!this.is_active){ return; }
this.stop = function () {
if (!this.is_active) { return }
this.is_active = false;
dotgrid.interface.el.className = ""
this.is_active = false
dotgrid.interface.el.className = ''
this.input.blur()
this.input.value = ""
this.input.value = ''
try{ dotgrid.controller.set(); }
catch(err){ console.log("No controller"); }
try { dotgrid.controller.set() } catch (err) { console.log('No controller') }
setTimeout(() => { dotgrid.interface.update(true); dotgrid.guide.update(); }, 250)
setTimeout(() => { dotgrid.interface.update(true); dotgrid.guide.update() }, 250)
}
this.validate = function()
{
if(!is_color(this.input.value)){ return; }
this.validate = function () {
if (!is_color(this.input.value)) { return }
const hex = `#${this.input.value}`;
const hex = `#${this.input.value}`
dotgrid.tool.style().color = hex;
dotgrid.tool.style().fill = dotgrid.tool.style().fill != "none" ? hex : "none";
dotgrid.tool.style().color = hex
dotgrid.tool.style().fill = dotgrid.tool.style().fill != 'none' ? hex : 'none'
this.stop();
this.stop()
}
this.listen = function(e,is_down = false)
{
if(is_down && !is_color_char(e.key)){
e.preventDefault();
return;
this.listen = function (e, is_down = false) {
if (is_down && !is_color_char(e.key)) {
e.preventDefault()
return
}
if(e.key == "Enter"){
this.validate();
e.preventDefault();
return;
if (e.key == 'Enter') {
this.validate()
e.preventDefault()
return
}
if(e.key == "Escape"){
this.stop();
e.preventDefault();
return;
if (e.key == 'Escape') {
this.stop()
e.preventDefault()
return
}
this.update();
this.update()
}
function is_color(val)
{
if(val.length != 3 && val.length != 6){
function is_color (val) {
if (val.length != 3 && val.length != 6) {
return false
}
const re = /[0-9A-Fa-f]/g;
const re = /[0-9A-Fa-f]/g
return re.test(val)
}
function is_color_char(val)
{
const re = /[0-9A-Fa-f]/g;
function is_color_char (val) {
const re = /[0-9A-Fa-f]/g
return re.test(val)
}
this.input.onkeydown = function(event){ dotgrid.picker.listen(event,true); }
this.input.onkeyup = function(event){ dotgrid.picker.listen(event); };
}
this.input.onkeydown = function (event) { dotgrid.picker.listen(event, true) }
this.input.onkeyup = function (event) { dotgrid.picker.listen(event) }
}

View File

@ -1,117 +1,111 @@
'use strict';
'use strict'
function Renderer()
{
function Renderer () {
// Create SVG parts
this.svg_el = document.createElementNS("http://www.w3.org/2000/svg", "svg");
this.svg_el.setAttribute("xmlns","http://www.w3.org/2000/svg");
this.svg_el.setAttribute("baseProfile","full");
this.svg_el.setAttribute("version","1.1");
this.svg_el.style.fill = "none";
this.svg_el = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
this.svg_el.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
this.svg_el.setAttribute('baseProfile', 'full')
this.svg_el.setAttribute('version', '1.1')
this.svg_el.style.fill = 'none'
this.layer_1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.layer_2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.layer_3 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.layer_1 = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.layer_2 = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.layer_3 = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.svg_el.appendChild(this.layer_3);
this.svg_el.appendChild(this.layer_2);
this.svg_el.appendChild(this.layer_1);
this.svg_el.appendChild(this.layer_3)
this.svg_el.appendChild(this.layer_2)
this.svg_el.appendChild(this.layer_1)
this.update = function()
{
this.svg_el.setAttribute("width",(dotgrid.tool.settings.size.width-(5))+"px");
this.svg_el.setAttribute("height",(dotgrid.tool.settings.size.height+(10))+"px");
this.svg_el.style.width = (dotgrid.tool.settings.size.width-(5));
this.svg_el.style.height = dotgrid.tool.settings.size.height+(10);
this.svg_el.style.strokeWidth = dotgrid.tool.style().thickness;
this.update = function () {
this.svg_el.setAttribute('width', (dotgrid.tool.settings.size.width - (5)) + 'px')
this.svg_el.setAttribute('height', (dotgrid.tool.settings.size.height + (10)) + 'px')
this.svg_el.style.width = (dotgrid.tool.settings.size.width - (5))
this.svg_el.style.height = dotgrid.tool.settings.size.height + (10)
this.svg_el.style.strokeWidth = dotgrid.tool.style().thickness
let styles = dotgrid.tool.styles
let paths = dotgrid.tool.paths()
this.layer_1.style.strokeWidth = styles[0].thickness;
this.layer_1.style.strokeLinecap = styles[0].strokeLinecap;
this.layer_1.style.strokeLinejoin = styles[0].strokeLinejoin;
this.layer_1.style.stroke = styles[0].color;
this.layer_1.style.fill = styles[0].fill;
this.layer_1.setAttribute("d",paths[0])
this.layer_2.style.strokeWidth = styles[1].thickness;
this.layer_2.style.strokeLinecap = styles[1].strokeLinecap;
this.layer_2.style.strokeLinejoin = styles[1].strokeLinejoin;
this.layer_2.style.stroke = styles[1].color;
this.layer_2.style.fill = styles[1].fill;
this.layer_2.setAttribute("d",paths[1])
this.layer_3.style.strokeWidth = styles[2].thickness;
this.layer_3.style.strokeLinecap = styles[2].strokeLinecap;
this.layer_3.style.strokeLinejoin = styles[2].strokeLinejoin;
this.layer_3.style.stroke = styles[2].color;
this.layer_3.style.fill = styles[2].fill;
this.layer_3.setAttribute("d",paths[2])
this.layer_1.style.strokeWidth = styles[0].thickness
this.layer_1.style.strokeLinecap = styles[0].strokeLinecap
this.layer_1.style.strokeLinejoin = styles[0].strokeLinejoin
this.layer_1.style.stroke = styles[0].color
this.layer_1.style.fill = styles[0].fill
this.layer_1.setAttribute('d', paths[0])
this.layer_2.style.strokeWidth = styles[1].thickness
this.layer_2.style.strokeLinecap = styles[1].strokeLinecap
this.layer_2.style.strokeLinejoin = styles[1].strokeLinejoin
this.layer_2.style.stroke = styles[1].color
this.layer_2.style.fill = styles[1].fill
this.layer_2.setAttribute('d', paths[1])
this.layer_3.style.strokeWidth = styles[2].thickness
this.layer_3.style.strokeLinecap = styles[2].strokeLinecap
this.layer_3.style.strokeLinejoin = styles[2].strokeLinejoin
this.layer_3.style.stroke = styles[2].color
this.layer_3.style.fill = styles[2].fill
this.layer_3.setAttribute('d', paths[2])
}
this.to_png = function(size = dotgrid.tool.settings.size,callback = dotgrid.render)
{
if(!dialog){ return this.to_png_web(size); }
this.to_png = function (size = dotgrid.tool.settings.size, callback = dotgrid.render) {
if (!dialog) { return this.to_png_web(size) }
this.update();
this.update()
let xml = new XMLSerializer().serializeToString(this.svg_el);
let svg64 = btoa(xml);
let b64Start = 'data:image/svg+xml;base64,';
let image64 = b64Start + svg64;
let img = new Image;
let xml = new XMLSerializer().serializeToString(this.svg_el)
let svg64 = btoa(xml)
let b64Start = 'data:image/svg+xml;base64,'
let image64 = b64Start + svg64
let img = new Image()
let canvas = document.createElement("canvas");
let canvas = document.createElement('canvas')
canvas.width = (size.width)*2;
canvas.height = (size.height+30)*2;
canvas.width = (size.width) * 2
canvas.height = (size.height + 30) * 2
let ctx = canvas.getContext('2d');
let ctx = canvas.getContext('2d')
img.onload = function(){
ctx.drawImage(img, 0, 0, (size.width)*2, (size.height+30)*2);
let data = canvas.toDataURL('image/png').replace(/^data:image\/\w+;base64,/, "");
dotgrid.renderer.to_png_ready(callback, new Buffer(data, 'base64'),size)
};
img.src = image64;
img.onload = function () {
ctx.drawImage(img, 0, 0, (size.width) * 2, (size.height + 30) * 2)
let data = canvas.toDataURL('image/png').replace(/^data:image\/\w+;base64,/, '')
dotgrid.renderer.to_png_ready(callback, new Buffer(data, 'base64'), size)
}
img.src = image64
}
this.to_png_ready = function(callback, buffer, size)
{
callback(null,buffer,size)
this.to_png_ready = function (callback, buffer, size) {
callback(null, buffer, size)
}
this.to_png_web = function(size)
{
if(dotgrid.tool.length() < 1){ console.warn('Nothing to render'); return; }
this.update();
this.to_png_web = function (size) {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to render'); return }
this.update()
let xml = new XMLSerializer().serializeToString(this.svg_el);
let svg64 = btoa(xml);
let b64Start = 'data:image/svg+xml;base64,';
let image64 = b64Start + svg64;
let xml = new XMLSerializer().serializeToString(this.svg_el)
let svg64 = btoa(xml)
let b64Start = 'data:image/svg+xml;base64,'
let image64 = b64Start + svg64
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
let win = window.open('about:blank','image from canvas');
let img = new Image;
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = size.width*2;
canvas.height = size.height*2;
let win = window.open('about:blank', 'image from canvas')
let img = new Image()
img.onload = function(){
ctx.drawImage(img, 0, 0, size.width*2, size.height*2);
win.document.write(`<style>body { background:${dotgrid.theme.active.background}}</style><img width='${size.width/2}' height='${size.height/2}' src='${canvas.toDataURL("image/png")}' alt='from canvas'/>`);
};
img.src = image64;
canvas.width = size.width * 2
canvas.height = size.height * 2
img.onload = function () {
ctx.drawImage(img, 0, 0, size.width * 2, size.height * 2)
win.document.write(`<style>body { background:${dotgrid.theme.active.background}}</style><img width='${size.width / 2}' height='${size.height / 2}' src='${canvas.toDataURL('image/png')}' alt='from canvas'/>`)
}
img.src = image64
}
this.to_svg = function()
{
this.update();
this.to_svg = function () {
this.update()
return this.svg_el.outerHTML;
return this.svg_el.outerHTML
}
}
}

View File

@ -1,335 +1,300 @@
'use strict';
'use strict'
function Tool()
{
this.index = 0;
this.settings = { size:{width:300,height:300} }
this.layers = [[],[],[]];
function Tool () {
this.index = 0
this.settings = { size: { width: 300, height: 300 } }
this.layers = [[], [], []]
this.styles = [
{ thickness:10,strokeLinecap:"round",strokeLinejoin:"round",color:"#f00",fill:"none",mirror_style:0 },
{ thickness:10,strokeLinecap:"round",strokeLinejoin:"round",color:"#0f0",fill:"none",mirror_style:0 },
{ thickness:10,strokeLinecap:"round",strokeLinejoin:"round",color:"#00f",fill:"none",mirror_style:0 }
];
this.vertices = [];
this.reqs = { line:2,arc_c:2,arc_r:2,bezier:3,close:0 };
{ thickness: 10, strokeLinecap: 'round', strokeLinejoin: 'round', color: '#f00', fill: 'none', mirror_style: 0 },
{ thickness: 10, strokeLinecap: 'round', strokeLinejoin: 'round', color: '#0f0', fill: 'none', mirror_style: 0 },
{ thickness: 10, strokeLinecap: 'round', strokeLinejoin: 'round', color: '#00f', fill: 'none', mirror_style: 0 }
]
this.vertices = []
this.reqs = { line: 2, arc_c: 2, arc_r: 2, bezier: 3, close: 0 }
this.start = function()
{
this.start = function () {
this.styles[0].color = dotgrid.theme.active.f_high
this.styles[1].color = dotgrid.theme.active.f_med
this.styles[2].color = dotgrid.theme.active.f_low
}
this.reset = function()
{
this.layers = [[],[],[]];
this.vertices = [];
this.index = 0;
this.reset = function () {
this.layers = [[], [], []]
this.vertices = []
this.index = 0
}
this.clear = function()
{
this.vertices = [];
dotgrid.guide.update();
dotgrid.interface.update(true);
this.clear = function () {
this.vertices = []
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.undo = function()
{
this.layers = dotgrid.history.prev();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.undo = function () {
this.layers = dotgrid.history.prev()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.redo = function()
{
this.layers = dotgrid.history.next();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.redo = function () {
this.layers = dotgrid.history.next()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.length = function()
{
this.length = function () {
return this.layers[0].length + this.layers[1].length + this.layers[2].length
}
// I/O
this.export = function(target = {settings:this.settings,layers:this.layers,styles:this.styles})
{
return JSON.stringify(copy(target), null, 2);
this.export = function (target = { settings: this.settings, layers: this.layers, styles: this.styles }) {
return JSON.stringify(copy(target), null, 2)
}
this.import = function(layer)
{
this.import = function (layer) {
this.layers[this.index] = this.layers[this.index].concat(layer)
dotgrid.history.push(this.layers);
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
dotgrid.history.push(this.layers)
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.replace = function(dot)
{
if(!dot.layers || dot.layers.length != 3){ console.warn("Incompatible version"); return; }
if(dot.settings.width && dot.settings.height){
dot.settings.size = {width:dot.settings.width,height:dot.settings.height}
this.replace = function (dot) {
if (!dot.layers || dot.layers.length != 3) { console.warn('Incompatible version'); return }
if (dot.settings.width && dot.settings.height) {
dot.settings.size = { width: dot.settings.width, height: dot.settings.height }
}
if(this.settings && (this.settings.size.width != dot.settings.size.width || this.settings.size.height != dot.settings.size.height)){
dotgrid.set_size({width:dot.settings.size.width,height:dot.settings.size.height})
if (this.settings && (this.settings.size.width != dot.settings.size.width || this.settings.size.height != dot.settings.size.height)) {
dotgrid.set_size({ width: dot.settings.size.width, height: dot.settings.size.height })
}
this.layers = dot.layers;
this.styles = dot.styles;
this.settings = dot.settings;
this.layers = dot.layers
this.styles = dot.styles
this.settings = dot.settings
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
dotgrid.history.push(this.layers);
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
dotgrid.history.push(this.layers)
}
// EDIT
this.remove_segment = function()
{
if(this.vertices.length > 0){ this.clear(); return; }
this.layer().pop();
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.remove_segment = function () {
if (this.vertices.length > 0) { this.clear(); return }
this.layer().pop()
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.remove_segments_at = function(pos)
{
for(const segment_id in this.layer()){
let segment = this.layer()[segment_id];
for(const vertex_id in segment.vertices){
let vertex = segment.vertices[vertex_id];
if(Math.abs(pos.x) == Math.abs(vertex.x) && Math.abs(pos.y) == Math.abs(vertex.y)){
segment.vertices.splice(vertex_id,1)
this.remove_segments_at = function (pos) {
for (const segment_id in this.layer()) {
let segment = this.layer()[segment_id]
for (const vertex_id in segment.vertices) {
let vertex = segment.vertices[vertex_id]
if (Math.abs(pos.x) == Math.abs(vertex.x) && Math.abs(pos.y) == Math.abs(vertex.y)) {
segment.vertices.splice(vertex_id, 1)
}
}
if(segment.vertices.length < 2){
this.layers[this.index].splice(segment_id,1)
if (segment.vertices.length < 2) {
this.layers[this.index].splice(segment_id, 1)
}
}
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
}
this.add_vertex = function(pos)
{
pos = {x:Math.abs(pos.x),y:Math.abs(pos.y)}
this.vertices.push(pos);
dotgrid.interface.update(true);
this.add_vertex = function (pos) {
pos = { x: Math.abs(pos.x), y: Math.abs(pos.y) }
this.vertices.push(pos)
dotgrid.interface.update(true)
}
this.vertex_at = function(pos)
{
for(const segment_id in this.layer()){
let segment = this.layer()[segment_id];
for(const vertex_id in segment.vertices){
let vertex = segment.vertices[vertex_id];
if(vertex.x == Math.abs(pos.x) && vertex.y == Math.abs(pos.y)){
return vertex;
this.vertex_at = function (pos) {
for (const segment_id in this.layer()) {
let segment = this.layer()[segment_id]
for (const vertex_id in segment.vertices) {
let vertex = segment.vertices[vertex_id]
if (vertex.x == Math.abs(pos.x) && vertex.y == Math.abs(pos.y)) {
return vertex
}
}
}
return null;
return null
}
this.cast = function(type)
{
if(!this.layer()){ this.layers[this.index] = []; }
if(!this.can_cast(type)){ console.warn("Cannot cast"); return; }
this.cast = function (type) {
if (!this.layer()) { this.layers[this.index] = [] }
if (!this.can_cast(type)) { console.warn('Cannot cast'); return }
let append_target = this.can_append({type:type,vertices:this.vertices.slice()})
let append_target = this.can_append({ type: type, vertices: this.vertices.slice() })
if(append_target){
if (append_target) {
this.layers[this.index][append_target].vertices = this.layers[this.index][append_target].vertices.concat(this.vertices.slice())
}
else{
this.layer().push({type:type,vertices:this.vertices.slice()})
} else {
this.layer().push({ type: type, vertices: this.vertices.slice() })
}
dotgrid.history.push(this.layers);
dotgrid.history.push(this.layers)
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
console.log(`Casted ${type} -> ${this.layer().length} elements`);
console.log(`Casted ${type} -> ${this.layer().length} elements`)
}
this.i = { linecap:0,linejoin:0,thickness:5 }
this.i = { linecap: 0, linejoin: 0, thickness: 5 }
this.toggle = function(type,mod = 1)
{
if(type == "linecap"){
let a = ["butt","square","round"];
this.i.linecap += mod;
this.style().strokeLinecap = a[this.i.linecap % a.length];
this.toggle = function (type, mod = 1) {
if (type == 'linecap') {
let a = ['butt', 'square', 'round']
this.i.linecap += mod
this.style().strokeLinecap = a[this.i.linecap % a.length]
} else if (type == 'linejoin') {
let a = ['miter', 'round', 'bevel']
this.i.linejoin += mod
this.style().strokeLinejoin = a[this.i.linejoin % a.length]
} else if (type == 'fill') {
this.style().fill = this.style().fill == 'none' ? this.style().color : 'none'
} else if (type == 'thickness') {
this.style().thickness = clamp(this.style().thickness + mod, 1, 100)
} else if (type == 'mirror') {
this.style().mirror_style = this.style().mirror_style > 3 ? 0 : this.style().mirror_style + 1
} else {
console.warn('Unknown', type)
}
else if(type == "linejoin"){
let a = ["miter","round","bevel"];
this.i.linejoin += mod;
this.style().strokeLinejoin = a[this.i.linejoin % a.length];
}
else if(type == "fill"){
this.style().fill = this.style().fill == "none" ? this.style().color : "none";
}
else if(type == "thickness"){
this.style().thickness = clamp(this.style().thickness+mod,1,100);
}
else if(type == "mirror"){
this.style().mirror_style = this.style().mirror_style > 3 ? 0 : this.style().mirror_style+1;
}
else{
console.warn("Unknown",type)
}
dotgrid.interface.update(true);
dotgrid.guide.update();
dotgrid.interface.update(true)
dotgrid.guide.update()
}
this.misc = function(type)
{
dotgrid.picker.start();
this.misc = function (type) {
dotgrid.picker.start()
}
this.source = function(type)
{
if(type == "grid"){ dotgrid.guide.toggle(); }
if(type == "screen"){ app.toggle_fullscreen(); }
this.source = function (type) {
if (type == 'grid') { dotgrid.guide.toggle() }
if (type == 'screen') { app.toggle_fullscreen() }
if(type == "open"){ dotgrid.open(); }
if(type == "save"){ dotgrid.save(); }
if(type == "render"){ dotgrid.render(); }
if(type == "export"){ dotgrid.export(); }
if (type == 'open') { dotgrid.open() }
if (type == 'save') { dotgrid.save() }
if (type == 'render') { dotgrid.render() }
if (type == 'export') { dotgrid.export() }
}
this.can_append = function(content)
{
for(const id in this.layer()){
let stroke = this.layer()[id];
if(stroke.type != content.type){ continue; }
if(!stroke.vertices){ continue; }
if(!stroke.vertices[stroke.vertices.length-1]){ continue; }
if(stroke.vertices[stroke.vertices.length-1].x != content.vertices[0].x){ continue; }
if(stroke.vertices[stroke.vertices.length-1].y != content.vertices[0].y){ continue; }
return id;
this.can_append = function (content) {
for (const id in this.layer()) {
let stroke = this.layer()[id]
if (stroke.type != content.type) { continue }
if (!stroke.vertices) { continue }
if (!stroke.vertices[stroke.vertices.length - 1]) { continue }
if (stroke.vertices[stroke.vertices.length - 1].x != content.vertices[0].x) { continue }
if (stroke.vertices[stroke.vertices.length - 1].y != content.vertices[0].y) { continue }
return id
}
return false;
return false
}
this.can_cast = function(type)
{
if(!type){ return false; }
this.can_cast = function (type) {
if (!type) { return false }
// Cannot cast close twice
if(type == "close"){
let prev = this.layer()[this.layer().length-1];
if(!prev || prev.type == "close"){
return false;
if (type == 'close') {
let prev = this.layer()[this.layer().length - 1]
if (!prev || prev.type == 'close') {
return false
}
}
if(type == "bezier"){
if(this.vertices.length != 3 && this.vertices.length != 5 && this.vertices.length != 7 && this.vertices.length != 9){
return false;
if (type == 'bezier') {
if (this.vertices.length != 3 && this.vertices.length != 5 && this.vertices.length != 7 && this.vertices.length != 9) {
return false
}
}
return this.vertices.length >= this.reqs[type];
return this.vertices.length >= this.reqs[type]
}
this.paths = function()
{
let l1 = new Generator(dotgrid.tool.layers[0],dotgrid.tool.styles[0]).toString({x:-10,y:-10},1)
let l2 = new Generator(dotgrid.tool.layers[1],dotgrid.tool.styles[1]).toString({x:-10,y:-10},1)
let l3 = new Generator(dotgrid.tool.layers[2],dotgrid.tool.styles[2]).toString({x:-10,y:-10},1)
this.paths = function () {
let l1 = new Generator(dotgrid.tool.layers[0], dotgrid.tool.styles[0]).toString({ x: -10, y: -10 }, 1)
let l2 = new Generator(dotgrid.tool.layers[1], dotgrid.tool.styles[1]).toString({ x: -10, y: -10 }, 1)
let l3 = new Generator(dotgrid.tool.layers[2], dotgrid.tool.styles[2]).toString({ x: -10, y: -10 }, 1)
return [l1,l2,l3]
return [l1, l2, l3]
}
this.path = function()
{
return new Generator(dotgrid.tool.layer(),dotgrid.tool.style()).toString({x:-10,y:-10},1)
this.path = function () {
return new Generator(dotgrid.tool.layer(), dotgrid.tool.style()).toString({ x: -10, y: -10 }, 1)
}
this.translate = function(a,b)
{
for(const segment_id in this.layer()){
let segment = this.layer()[segment_id];
for(const vertex_id in segment.vertices){
let vertex = segment.vertices[vertex_id];
if(vertex.x == Math.abs(a.x) && vertex.y == Math.abs(a.y)){
segment.vertices[vertex_id] = {x:Math.abs(b.x),y:Math.abs(b.y)};
this.translate = function (a, b) {
for (const segment_id in this.layer()) {
let segment = this.layer()[segment_id]
for (const vertex_id in segment.vertices) {
let vertex = segment.vertices[vertex_id]
if (vertex.x == Math.abs(a.x) && vertex.y == Math.abs(a.y)) {
segment.vertices[vertex_id] = { x: Math.abs(b.x), y: Math.abs(b.y) }
}
}
}
dotgrid.history.push(this.layers);
this.clear();
dotgrid.guide.update();
dotgrid.history.push(this.layers)
this.clear()
dotgrid.guide.update()
}
this.translate_multi = function(a,b)
{
let offset = {x:a.x - b.x,y:a.y - b.y}
this.translate_multi = function (a, b) {
let offset = { x: a.x - b.x, y: a.y - b.y }
for(const segment_id in this.layer()){
let segment = this.layer()[segment_id];
for(const vertex_id in segment.vertices){
let vertex = segment.vertices[vertex_id];
segment.vertices[vertex_id] = {x:vertex.x-offset.x,y:vertex.y-offset.y};
for (const segment_id in this.layer()) {
let segment = this.layer()[segment_id]
for (const vertex_id in segment.vertices) {
let vertex = segment.vertices[vertex_id]
segment.vertices[vertex_id] = { x: vertex.x - offset.x, y: vertex.y - offset.y }
}
}
dotgrid.history.push(this.layers);
this.clear();
dotgrid.guide.update();
dotgrid.history.push(this.layers)
this.clear()
dotgrid.guide.update()
}
// Style
this.style = function()
{
if(!this.styles[this.index]){
this.styles[this.index] = [];
this.style = function () {
if (!this.styles[this.index]) {
this.styles[this.index] = []
}
return this.styles[this.index];
return this.styles[this.index]
}
// Layers
this.layer = function()
{
if(!this.layers[this.index]){
this.layers[this.index] = [];
this.layer = function () {
if (!this.layers[this.index]) {
this.layers[this.index] = []
}
return this.layers[this.index];
return this.layers[this.index]
}
this.select_layer = function(id)
{
this.index = clamp(id,0,2);
this.clear();
dotgrid.guide.update();
dotgrid.interface.update(true);
this.select_layer = function (id) {
this.index = clamp(id, 0, 2)
this.clear()
dotgrid.guide.update()
dotgrid.interface.update(true)
console.log(`layer:${this.index}`)
}
this.select_next_layer = function()
{
this.select_next_layer = function () {
this.index = this.index >= 2 ? 0 : this.index++
this.select_layer(this.index);
this.select_layer(this.index)
}
this.select_prev_layer = function()
{
this.select_prev_layer = function () {
this.index = this.index >= 0 ? 2 : this.index--
this.select_layer(this.index);
this.select_layer(this.index)
}
function copy(data){ return data ? JSON.parse(JSON.stringify(data)) : []; }
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
function copy (data) { return data ? JSON.parse(JSON.stringify(data)) : [] }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
}