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 path = require('path')
const url = require('url') const url = require('url')
const shell = require('electron').shell const shell = require('electron').shell
let is_shown = true; let is_shown = true
app.on('ready', () => app.on('ready', () => {
{
app.win = new BrowserWindow({ app.win = new BrowserWindow({
width: 405, width: 405,
height: 420, height: 420,
minWidth: 405, minWidth: 405,
minHeight: 420, minHeight: 420,
webPreferences: {zoomFactor: 1.0}, webPreferences: { zoomFactor: 1.0 },
backgroundColor:"#000", backgroundColor: '#000',
frame:false, frame: false,
autoHideMenuBar: true, autoHideMenuBar: true,
icon: __dirname + '/icon.ico' icon: __dirname + '/icon.ico'
}) })
app.win.loadURL(`file://${__dirname}/sources/index.html`); app.win.loadURL(`file://${__dirname}/sources/index.html`)
// app.inspect(); // app.inspect();
app.win.on('closed', () => { app.win.on('closed', () => {
win = null win = null
app.quit() app.quit()
}) })
app.win.on('hide',function() { app.win.on('hide', function () {
is_shown = false; is_shown = false
}) })
app.win.on('show',function() { app.win.on('show', function () {
is_shown = true; is_shown = true
}) })
app.on('window-all-closed', () => app.on('window-all-closed', () => {
{
app.quit() app.quit()
}) })
app.on('activate', () => { app.on('activate', () => {
if (app.win === null) { if (app.win === null) {
createWindow() createWindow()
} } else {
else{ app.win.show()
app.win.show();
} }
}) })
}) })
app.inspect = function() app.inspect = function () {
{ app.win.toggleDevTools()
app.win.toggleDevTools();
} }
app.toggle_fullscreen = function() app.toggle_fullscreen = function () {
{ app.win.setFullScreen(!app.win.isFullScreen())
app.win.setFullScreen(app.win.isFullScreen() ? false : true);
} }
app.toggle_visible = function() app.toggle_visible = function () {
{ if (process.platform == 'win32') {
if(process.platform == "win32"){ if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() }
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() }
else{
if(is_shown && !app.win.isFullScreen()){ app.win.hide(); } else{ app.win.show(); }
} }
} }
app.inject_menu = function(menu) app.inject_menu = function (menu) {
{ try {
try{ Menu.setApplicationMenu(Menu.buildFromTemplate(menu))
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() function Cursor () {
{ this.pos = { x: 0, y: 0 }
this.pos = {x:0,y:0}; this.translation = null
this.translation = null; this.operation = null
this.operation = null;
this.translate = function(from = null,to = null, multi = false) 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 || to) && this.translation == null){ this.translation = {multi:multi}; console.log("Begin translation") }
if(from){ this.translation.from = from; } if (from) { this.translation.from = from }
if(to){ this.translation.to = to; } if (to) { this.translation.to = to }
if(!from && !to){ if (!from && !to) {
this.translation = null; this.translation = null
} }
} }
this.down = function(e) 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.pos = this.pos_from_event(e) this.pos = this.pos_from_event(e)
// Translation // Translation
if(this.translation){ if (dotgrid.tool.vertex_at(this.pos)) {
this.translate(null,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.guide.update(); dotgrid.interface.update()
} e.preventDefault()
dotgrid.interface.update();
e.preventDefault();
this.last_pos = this.pos;
} }
this.up = function(e) this.last_pos = { x: 0, y: 0 }
{
this.move = function (e) {
this.pos = this.pos_from_event(e) this.pos = this.pos_from_event(e)
if(e.altKey){ dotgrid.tool.remove_segments_at(this.pos); this.translate(); return; } // Translation
if (this.translation) {
if(this.translation && !is_equal(this.translation.from,this.translation.to)){ this.translate(null, this.pos)
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(); if (this.last_pos.x != this.pos.x || this.last_pos.y != this.pos.y) {
dotgrid.guide.update()
}
dotgrid.interface.update(); dotgrid.interface.update()
dotgrid.guide.update(); e.preventDefault()
e.preventDefault();
this.last_pos = this.pos
} }
this.alt = function(e) this.up = function (e) {
{
this.pos = this.pos_from_event(e) this.pos = this.pos_from_event(e)
dotgrid.tool.remove_segments_at(this.pos); if (e.altKey) { dotgrid.tool.remove_segments_at(this.pos); this.translate(); return }
e.preventDefault();
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 // Position Mods
this.pos_from_event = function(e) this.pos_from_event = function (e) {
{ return this.pos_snap(this.pos_relative({ x: e.clientX, y: e.clientY }))
return this.pos_snap(this.pos_relative({x:e.clientX,y:e.clientY}))
} }
this.pos_relative = function(pos) this.pos_relative = function (pos) {
{
return { return {
x:pos.x - dotgrid.guide.el.offsetLeft, x: pos.x - dotgrid.guide.el.offsetLeft,
y:pos.y - dotgrid.guide.el.offsetTop y: pos.y - dotgrid.guide.el.offsetTop
}; }
} }
this.pos_snap = function(pos) this.pos_snap = function (pos) {
{ const grid = dotgrid.tool.settings.size.width / dotgrid.grid_x
const grid = dotgrid.tool.settings.size.width/dotgrid.grid_x;
return { return {
x:clamp(step(pos.x,grid),grid,dotgrid.tool.settings.size.width), 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) 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) function Dotgrid (width, height, grid_x, grid_y, block_x, block_y) {
{ this.controller = null
this.controller = null; this.theme = new Theme()
this.theme = new Theme(); this.interface = new Interface()
this.interface = new Interface(); this.history = new History()
this.history = new History(); this.guide = new Guide()
this.guide = new Guide(); this.renderer = new Renderer()
this.renderer = new Renderer(); this.tool = new Tool()
this.tool = new Tool(); this.picker = new Picker()
this.picker = new Picker(); this.cursor = new Cursor()
this.cursor = new Cursor();
this.grid_x = grid_x; this.grid_x = grid_x
this.grid_y = grid_y; this.grid_y = grid_y
this.block_x = block_x; this.block_x = block_x
this.block_y = block_y; this.block_y = block_y
// ISU // ISU
this.install = function(host) this.install = function (host) {
{ host.appendChild(this.guide.el)
host.appendChild(this.guide.el);
this.interface.install(host); this.interface.install(host)
this.theme.install(host,this.update); this.theme.install(host, this.update)
} }
this.start = function() this.start = function () {
{ this.theme.start()
this.theme.start(); this.tool.start()
this.tool.start(); this.guide.start()
this.guide.start(); this.interface.start()
this.interface.start();
document.addEventListener('mousedown', function(e){ dotgrid.cursor.down(e); }, false); document.addEventListener('mousedown', function (e) { dotgrid.cursor.down(e) }, false)
document.addEventListener('mousemove', function(e){ dotgrid.cursor.move(e); }, false); document.addEventListener('mousemove', function (e) { dotgrid.cursor.move(e) }, false)
document.addEventListener('contextmenu', function(e){ dotgrid.cursor.alt(e); }, false); document.addEventListener('contextmenu', function (e) { dotgrid.cursor.alt(e) }, false)
document.addEventListener('mouseup', function(e){ dotgrid.cursor.up(e);}, false); document.addEventListener('mouseup', function (e) { dotgrid.cursor.up(e) }, false)
document.addEventListener('copy', function(e){ dotgrid.copy(e); }, false); document.addEventListener('copy', function (e) { dotgrid.copy(e) }, false)
document.addEventListener('cut', function(e){ dotgrid.cut(e); }, false); document.addEventListener('cut', function (e) { dotgrid.cut(e) }, false)
document.addEventListener('paste', function(e){ dotgrid.paste(e); }, false); document.addEventListener('paste', function (e) { dotgrid.paste(e) }, false)
window.addEventListener('drop', dotgrid.drag); window.addEventListener('drop', dotgrid.drag)
this.new(); this.new()
setTimeout(() => { document.body.className += ' ready'; }, 250) setTimeout(() => { document.body.className += ' ready' }, 250)
} }
this.update = function() this.update = function () {
{ dotgrid.resize()
dotgrid.resize(); dotgrid.interface.update()
dotgrid.interface.update(); dotgrid.guide.update()
dotgrid.guide.update();
} }
// File // File
this.new = function() this.new = function () {
{
this.set_zoom(1.0) this.set_zoom(1.0)
this.set_size({width:300,height:300}) this.set_size({ width: 300, height: 300 })
this.history.push(this.tool.layers); this.history.push(this.tool.layers)
this.clear(); this.clear()
} }
this.open = function() this.open = function () {
{ if (!dialog) { return }
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) => { fs.readFile(paths[0], 'utf-8', (err, data) => {
if(err){ alert("An error ocurred reading the file :" + err.message); return; } if (err) { alert('An error ocurred reading the file :' + err.message); return }
this.tool.replace(JSON.parse(data.toString().trim())); 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);
this.guide.update() this.guide.update()
}); })
} }
this.export_web = function(content) this.save = function (content = this.tool.export()) {
{ if (dotgrid.tool.length() < 1) { console.warn('Nothing to save'); return }
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}`); if (!dialog) { this.save_web(content); return }
win.document.body.innerHTML = `<style>body { background:${dotgrid.theme.active.background}}</style>${dotgrid.renderer.to_svg()}`;
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 // Basics
this.set_size = function(size = {width:300,height:300},ui = true,scale = 1) 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) }
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.width = size.width
this.tool.settings.size.height = size.height this.tool.settings.size.height = size.height
try{ try {
const win = require('electron').remote.getCurrentWindow(); const win = require('electron').remote.getCurrentWindow()
win.setSize((size.width+100)*scale,(size.height+100+(ui ? 10 : 0))*scale,true); 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_x = size.width / 15
this.grid_height = this.tool.settings.size.height/this.grid_y; 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.resize(size)
dotgrid.guide.update();
this.interface.update()
dotgrid.guide.update()
} }
this.set_zoom = function(scale) this.set_zoom = function (scale) {
{ this.set_size({ width: this.tool.settings.size.width, height: this.tool.settings.size.height }, true, scale)
this.set_size({width:this.tool.settings.size.width,height:this.tool.settings.size.height},true,scale)
try{ try {
webFrame.setZoomFactor(scale) webFrame.setZoomFactor(scale)
} } catch (err) {
catch(err){ console.log('Cannot zoom')
console.log("Cannot zoom")
} }
} }
// Draw // Draw
this.reset = function() this.reset = function () {
{ this.tool.clear()
this.tool.clear(); this.update()
this.update();
} }
this.clear = function() this.clear = function () {
{ this.history.clear()
this.history.clear(); this.tool.reset()
this.tool.reset(); this.reset()
this.reset(); dotgrid.guide.update()
dotgrid.guide.update(); dotgrid.interface.update(true)
dotgrid.interface.update(true);
} }
this.resize = function() this.resize = function () {
{ const size = { width: step(window.innerWidth - 90, 15), height: step(window.innerHeight - 120, 15) }
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){ if (size.width == dotgrid.tool.settings.size.width && size.height == dotgrid.tool.settings.size.height) {
return; return
} }
console.log(`Resized: ${size.width}x${size.height}`) console.log(`Resized: ${size.width}x${size.height}`)
dotgrid.tool.settings.size.width = size.width dotgrid.tool.settings.size.width = size.width
dotgrid.tool.settings.size.height = size.height dotgrid.tool.settings.size.height = size.height
dotgrid.grid_x = size.width/15 dotgrid.grid_x = size.width / 15
dotgrid.grid_y = size.height/15 dotgrid.grid_y = size.height / 15
dotgrid.grid_width = dotgrid.tool.settings.size.width/dotgrid.grid_x; dotgrid.grid_width = dotgrid.tool.settings.size.width / dotgrid.grid_x
dotgrid.grid_height = dotgrid.tool.settings.size.height/dotgrid.grid_y; 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}` document.title = `Dotgrid — ${size.width}x${size.height}`
} }
this.drag = function(e) this.drag = function (e) {
{ e.preventDefault()
e.preventDefault(); e.stopPropagation()
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(); const reader = new FileReader()
reader.onload = function(e){ reader.onload = function (e) {
dotgrid.tool.replace(JSON.parse(e.target.result.toString().trim())); dotgrid.tool.replace(JSON.parse(e.target.result.toString().trim()))
dotgrid.guide.update(); dotgrid.guide.update()
}; }
reader.readAsText(file); reader.readAsText(file)
} }
this.copy = function(e) this.copy = function (e) {
{ dotgrid.guide.update()
dotgrid.guide.update();
if(e.target !== this.picker.input){ if (e.target !== this.picker.input) {
e.clipboardData.setData('text/source', dotgrid.tool.export(dotgrid.tool.layer())); e.clipboardData.setData('text/source', dotgrid.tool.export(dotgrid.tool.layer()))
e.clipboardData.setData('text/plain', dotgrid.tool.path()); e.clipboardData.setData('text/plain', dotgrid.tool.path())
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg()); e.clipboardData.setData('text/html', dotgrid.renderer.to_svg())
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg()); e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg())
e.preventDefault(); e.preventDefault()
} }
dotgrid.guide.update(); dotgrid.guide.update()
} }
this.cut = function(e) this.cut = function (e) {
{ dotgrid.guide.update()
dotgrid.guide.update();
if(e.target !== this.picker.input){ if (e.target !== this.picker.input) {
e.clipboardData.setData('text/plain', dotgrid.tool.export(dotgrid.tool.layer())); e.clipboardData.setData('text/plain', dotgrid.tool.export(dotgrid.tool.layer()))
e.clipboardData.setData('text/html', dotgrid.renderer.to_svg()); e.clipboardData.setData('text/html', dotgrid.renderer.to_svg())
e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg()); e.clipboardData.setData('text/svg+xml', dotgrid.renderer.to_svg())
dotgrid.tool.layers[dotgrid.tool.index] = []; dotgrid.tool.layers[dotgrid.tool.index] = []
e.preventDefault(); e.preventDefault()
} }
dotgrid.guide.update(); dotgrid.guide.update()
} }
this.paste = function(e) this.paste = function (e) {
{ if (e.target !== this.picker.el) {
if(e.target !== this.picker.el){ const data = e.clipboardData.getData('text/source')
const data = e.clipboardData.getData("text/source");
if (is_json(data)) { if (is_json(data)) {
data = JSON.parse(data.trim()); data = JSON.parse(data.trim())
dotgrid.tool.import(data); dotgrid.tool.import(data)
} }
e.preventDefault(); e.preventDefault()
} }
dotgrid.guide.update(); dotgrid.guide.update()
} }
} }
window.addEventListener('resize', function(e) window.addEventListener('resize', function (e) {
{ dotgrid.update()
dotgrid.update(); }, false)
}, false);
window.addEventListener('dragover',function(e) window.addEventListener('dragover', function (e) {
{ e.stopPropagation()
e.stopPropagation(); e.preventDefault()
e.preventDefault(); e.dataTransfer.dropEffect = 'copy'
e.dataTransfer.dropEffect = 'copy'; })
});
String.prototype.capitalize = function() String.prototype.capitalize = function () {
{ return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase()
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
} }
function is_json(text){ try{ JSON.parse(text);return true; } catch(error){ return false; }} 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 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 clamp (v, min, max) { return v < min ? min : v > max ? max : v }
function step(v,s){ return Math.round(v/s) * s; } function step (v, s) { return Math.round(v / s) * s }

View File

@ -1,115 +1,106 @@
'use strict'; 'use strict'
function Generator(layer,style) function Generator (layer, style) {
{ this.layer = layer
this.layer = layer; this.style = style
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) const l = copy(layer)
for(const k1 in l){ for (const k1 in l) {
const seg = l[k1]; const seg = l[k1]
for(const k2 in seg.vertices){ 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 == 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 } if (mirror == 2) { seg.vertices[k2].y = (dotgrid.tool.settings.size.height) - seg.vertices[k2].y + 30 }
// Offset // Offset
seg.vertices[k2].x += offset.x seg.vertices[k2].x += offset.x
seg.vertices[k2].y += offset.y seg.vertices[k2].y += offset.y
// Rotate // Rotate
const center = {x:(dotgrid.tool.settings.size.width/2)+offset.x+(7.5),y:(dotgrid.tool.settings.size.height/2)+offset.y+30} 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) seg.vertices[k2] = rotate_point(seg.vertices[k2], center, angle)
// Scale // Scale
seg.vertices[k2].x *= scale seg.vertices[k2].x *= scale
seg.vertices[k2].y *= scale seg.vertices[k2].y *= scale
} }
} }
return l; return l
} }
this.render = function(prev,segment,mirror = 0) this.render = function (prev, segment, mirror = 0) {
{ const type = segment.type
const type = segment.type; const vertices = segment.vertices
const vertices = segment.vertices; let html = ''
let html = ''; let skip = 0
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 vertex = vertices[id]
let next = vertices[parseInt(id)+1] let next = vertices[parseInt(id) + 1]
let after_next = vertices[parseInt(id)+2] let after_next = vertices[parseInt(id) + 2]
if(id == 0 && !prev || id == 0 && prev && (prev.x != vertex.x || prev.y != vertex.y)){ if (id == 0 && !prev || id == 0 && prev && (prev.x != vertex.x || prev.y != vertex.y)) {
html += `M${vertex.x},${vertex.y} ` html += `M${vertex.x},${vertex.y} `
} }
if(type == "line"){ if (type == 'line') {
html += `L${vertex.x},${vertex.y} `; html += `L${vertex.x},${vertex.y} `
} } else if (type == 'arc_c') {
else if(type == "arc_c"){
let clock = mirror > 0 ? '0,0' : '0,1' 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} ` : ''; 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') {
else if(type == "arc_r"){
let clock = mirror > 0 ? '0,1' : '0,0' 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} ` : ''; 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') {
else if(type == "bezier"){ html += next && after_next ? `Q${next.x},${next.y} ${after_next.x},${after_next.y} ` : ''
html += next && after_next ?`Q${next.x},${next.y} ${after_next.x},${after_next.y} ` : '';
skip = 1 skip = 1
} } else {
else{
console.warn(`unknown type:${type}`) console.warn(`unknown type:${type}`)
} }
} }
if(segment.type == "close"){ if (segment.type == 'close') {
html += "Z " html += 'Z '
} }
return html return html
} }
this.convert = function(layer,mirror,angle) this.convert = function (layer, mirror, angle) {
{ let s = ''
let s = ""
let prev = null let prev = null
for(const id in layer){ for (const id in layer) {
const seg = layer[id]; const seg = layer[id]
s += `${this.render(prev,seg,mirror)}` s += `${this.render(prev, seg, mirror)}`
prev = seg.vertices ? seg.vertices[seg.vertices.length-1] : null 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) 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))
let s = this.convert(operate(this.layer,offset,scale))
if(mirror == 1 || mirror == 2){ if (mirror == 1 || mirror == 2) {
s += this.convert(operate(this.layer,offset,scale,mirror),mirror) s += this.convert(operate(this.layer, offset, scale, mirror), mirror)
} }
if(mirror == 3){ if (mirror == 3) {
s += this.convert(operate(this.layer,offset,scale,mirror,120),mirror) s += this.convert(operate(this.layer, offset, scale, mirror, 120), mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,240),mirror) s += this.convert(operate(this.layer, offset, scale, mirror, 240), mirror)
} }
if(mirror == 4){ if (mirror == 4) {
s += this.convert(operate(this.layer,offset,scale,mirror,72),mirror) 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, 144), mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,216),mirror) s += this.convert(operate(this.layer, offset, scale, mirror, 216), mirror)
s += this.convert(operate(this.layer,offset,scale,mirror,288),mirror) s += this.convert(operate(this.layer, offset, scale, mirror, 288), mirror)
} }
return s return s
} }
function copy(data){ return data ? JSON.parse(JSON.stringify(data)) : []; } 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 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() function Guide () {
{ this.el = document.createElement('canvas')
this.el = document.createElement("canvas"); this.el.id = 'guide'
this.el.id = "guide"; this.el.width = 640
this.el.width = 640; this.el.height = 640
this.el.height = 640; this.el.style.width = '320px'
this.el.style.width = "320px"; this.el.style.height = '320px'
this.el.style.height = "320px"; this.show_extras = true
this.show_extras = true;
this.scale = 2; this.scale = 2
this.start = function() this.start = function () {
{ this.clear()
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.update() this.update()
} }
this.resize = function(size) this.update = function (force = false) {
{ this.clear()
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.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() this.clear = function () {
{ this.el.getContext('2d').clearRect(0, 0, this.el.width * this.scale, this.el.height * this.scale)
if(!this.show_extras){ return; } }
for(const segment_id in dotgrid.tool.layer()){ this.toggle = function () {
const segment = dotgrid.tool.layer()[segment_id]; this.show_extras = !this.show_extras
for(const vertex_id in segment.vertices){ this.update()
const vertex = segment.vertices[vertex_id]; }
this.draw_handle(vertex);
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() this.draw_vertices = function () {
{ for (const id in dotgrid.tool.vertices) {
for(const id in dotgrid.tool.vertices){ this.draw_vertex(dotgrid.tool.vertices[id])
this.draw_vertex(dotgrid.tool.vertices[id]);
} }
} }
this.draw_markers = function() this.draw_markers = function () {
{ if (!this.show_extras) { return }
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--) { 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 // Color
let color = is_step ? dotgrid.theme.active.b_med : dotgrid.theme.active.b_low; 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; } 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 }
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({ this.draw_marker({
x:parseInt(x * dotgrid.grid_width) + dotgrid.grid_width, x: parseInt(x * dotgrid.grid_width) + dotgrid.grid_width,
y:parseInt(y * dotgrid.grid_height) + dotgrid.grid_height y: parseInt(y * dotgrid.grid_height) + dotgrid.grid_height
},is_step ? 2.5 : 1.5,color); }, is_step ? 2.5 : 1.5, color)
} }
} }
} }
this.draw_marker = function(pos,radius = 1,color) this.draw_marker = function (pos, radius = 1, color) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d'); ctx.beginPath()
ctx.beginPath(); ctx.lineWidth = 2
ctx.lineWidth = 2; ctx.arc(pos.x * this.scale, pos.y * this.scale, radius, 0, 2 * Math.PI, false)
ctx.arc(pos.x * this.scale, pos.y * this.scale, radius, 0, 2 * Math.PI, false); ctx.fillStyle = color
ctx.fillStyle = color; ctx.fill()
ctx.fill(); ctx.closePath()
ctx.closePath();
} }
this.draw_vertex = function(pos, radius = 5) this.draw_vertex = function (pos, radius = 5) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d'); ctx.beginPath()
ctx.beginPath(); ctx.lineWidth = 2
ctx.lineWidth = 2; ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false)
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false); ctx.fillStyle = dotgrid.theme.active.f_med
ctx.fillStyle = dotgrid.theme.active.f_med; ctx.fill()
ctx.fill(); ctx.closePath()
ctx.closePath();
} }
this.draw_rule = function(from,to) this.draw_rule = function (from, to) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d');
ctx.beginPath(); ctx.beginPath()
ctx.moveTo(from.x,from.y); ctx.moveTo(from.x, from.y)
ctx.lineTo(to.x,to.y); ctx.lineTo(to.x, to.y)
ctx.lineCap="round"; ctx.lineCap = 'round'
ctx.lineWidth = 3; ctx.lineWidth = 3
ctx.strokeStyle = dotgrid.theme.active.b_low; ctx.strokeStyle = dotgrid.theme.active.b_low
ctx.stroke(); ctx.stroke()
ctx.closePath(); ctx.closePath()
} }
this.draw_ruler = function(pos) this.draw_ruler = function (pos) {
{ let offset = 15 * this.scale
let offset = 15 * this.scale;
let top = offset 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 left = offset
let right = (dotgrid.tool.settings.size.width * this.scale) let right = (dotgrid.tool.settings.size.width * this.scale)
// Translation // Translation
this.draw_rule({x:pos.x * this.scale,y:top},{x:pos.x * this.scale,y:bottom}); 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: left, y: pos.y * this.scale }, { x: right, y: pos.y * this.scale })
} }
this.draw_rulers = function() this.draw_rulers = function () {
{ if (!dotgrid.cursor.translation) { return }
if(!dotgrid.cursor.translation){ return; }
let ctx = this.el.getContext('2d'); let ctx = this.el.getContext('2d')
this.draw_ruler(dotgrid.cursor.translation.to) this.draw_ruler(dotgrid.cursor.translation.to)
ctx.setLineDash([]); ctx.setLineDash([])
ctx.restore(); ctx.restore()
} }
this.draw_handle = function(pos, radius = 6) this.draw_handle = function (pos, radius = 6) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d');
ctx.beginPath(); ctx.beginPath()
ctx.lineWidth = 3; ctx.lineWidth = 3
ctx.lineCap="round"; 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.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.fillStyle = dotgrid.theme.active.f_high
ctx.fill(); ctx.fill()
ctx.strokeStyle = dotgrid.theme.active.f_high; ctx.strokeStyle = dotgrid.theme.active.f_high
ctx.stroke(); ctx.stroke()
ctx.closePath(); ctx.closePath()
ctx.beginPath(); ctx.beginPath()
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false); ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius, 0, 2 * Math.PI, false)
ctx.fillStyle = dotgrid.theme.active.f_low; ctx.fillStyle = dotgrid.theme.active.f_low
ctx.fill(); ctx.fill()
ctx.closePath(); ctx.closePath()
ctx.beginPath(); ctx.beginPath()
ctx.arc((pos.x * this.scale), (pos.y * this.scale), radius-3, 0, 2 * Math.PI, false); 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.fillStyle = dotgrid.theme.active.f_high
ctx.fill(); ctx.fill()
ctx.closePath(); ctx.closePath()
} }
this.draw_path = function(path,style) this.draw_path = function (path, style) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d'); let p = new Path2D(path)
let p = new Path2D(path);
ctx.strokeStyle = style.color; ctx.strokeStyle = style.color
ctx.lineWidth = style.thickness * this.scale; ctx.lineWidth = style.thickness * this.scale
ctx.lineCap = style.strokeLinecap; ctx.lineCap = style.strokeLinecap
ctx.lineJoin = style.strokeLinejoin; ctx.lineJoin = style.strokeLinejoin
if(style.fill && style.fill != "none"){ if (style.fill && style.fill != 'none') {
ctx.fillStyle = style.color ctx.fillStyle = style.color
ctx.fill(p); ctx.fill(p)
} }
// Dash // Dash
if(style.strokeLineDash){ ctx.setLineDash(style.strokeLineDash); } if (style.strokeLineDash) { ctx.setLineDash(style.strokeLineDash) } else { ctx.setLineDash([]) }
else{ ctx.setLineDash([]); } ctx.stroke(p)
ctx.stroke(p);
} }
this.draw_translation = function() this.draw_translation = function () {
{ if (!dotgrid.cursor.translation) { return }
if(!dotgrid.cursor.translation){ return; }
let ctx = this.el.getContext('2d'); 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();
ctx.setLineDash([]); ctx.beginPath()
ctx.restore(); 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) this.draw_cursor = function (pos = dotgrid.cursor.pos, radius = dotgrid.tool.style().thickness - 1) {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d');
ctx.beginPath(); ctx.beginPath()
ctx.lineWidth = 3; ctx.lineWidth = 3
ctx.lineCap = "round"; ctx.lineCap = 'round'
ctx.arc(Math.abs(pos.x * -this.scale), Math.abs(pos.y * this.scale), 5, 0, 2 * Math.PI, false); 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.strokeStyle = dotgrid.theme.active.background
ctx.stroke(); ctx.stroke()
ctx.closePath(); ctx.closePath()
ctx.beginPath(); ctx.beginPath()
ctx.lineWidth = 3; ctx.lineWidth = 3
ctx.lineCap = "round"; 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.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.strokeStyle = dotgrid.theme.active.f_med
ctx.stroke(); ctx.stroke()
ctx.closePath(); ctx.closePath()
} }
this.draw_preview = function() this.draw_preview = function () {
{ let ctx = this.el.getContext('2d')
let ctx = this.el.getContext('2d');
let operation = dotgrid.cursor.operation && dotgrid.cursor.operation.cast ? dotgrid.cursor.operation.cast : null let operation = dotgrid.cursor.operation && dotgrid.cursor.operation.cast ? dotgrid.cursor.operation.cast : null
if(!dotgrid.tool.can_cast(operation)){ return; } if (!dotgrid.tool.can_cast(operation)) { return }
if(operation == "close"){ 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 = { let style = {
color:dotgrid.theme.active.f_med, color: dotgrid.theme.active.f_med,
thickness:2, thickness: 2,
strokeLinecap:"round", strokeLinecap: 'round',
strokeLinejoin:"round", strokeLinejoin: 'round',
strokeLineDash:[5, 15] strokeLineDash: [5, 15]
} }
this.draw_path(path,style) this.draw_path(path, style)
ctx.setLineDash([]); ctx.setLineDash([])
ctx.restore(); 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 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 clamp (v, min, max) { return v < min ? min : v > max ? max : v }
} }

View File

@ -1,55 +1,52 @@
'use strict'; 'use strict'
function Interface() function Interface () {
{ this.el = document.createElement('div')
this.el = document.createElement("div"); this.el.id = 'interface'
this.el.id = "interface";
this.el.appendChild(this.menu_el = document.createElement("div")); this.el.appendChild(this.menu_el = document.createElement('div'))
this.menu_el.id = "menu"; this.menu_el.id = 'menu'
this.is_visible = true; this.is_visible = true
this.zoom = false; this.zoom = false
this.install = function(host) this.install = function (host) {
{ host.appendChild(this.el)
host.appendChild(this.el);
} }
this.start = function(host) this.start = function (host) {
{ let html = ''
let html = ""
let options = { let options = {
cast:{ cast: {
line: { key:"A",icon:"M60,60 L240,240" }, line: { key: 'A', icon: 'M60,60 L240,240' },
arc_c: { key:"S",icon:"M60,60 A180,180 0 0,1 240,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" }, 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" }, 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" } close: { key: 'Z', icon: 'M60,60 A180,180 0 0,1 240,240 M60,60 A180,180 0 0,0 240,240' }
}, },
toggle:{ toggle: {
linecap: { key:"Q",icon:"M60,60 L60,60 L180,180 L240,180 L240,240 L180,240 L180,180" }, 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" }, 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" }, 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" }, 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" } fill: { key: 'R', icon: 'M60,60 L60,150 L150,150 L240,150 L240,240 Z' }
}, },
misc:{ 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"} 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:{ 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 "}, 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 "}, 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"}, 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"}, 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 "}, 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){ for (const type in options) {
const tools = options[type]; const tools = options[type]
for(const name in tools){ for (const name in tools) {
const tool = tools[name]; const tool = tools[name]
html += ` html += `
<svg <svg
id="option_${name}" id="option_${name}"
@ -60,99 +57,87 @@ function Interface()
onmouseover="dotgrid.interface.over('${type}','${name}')" onmouseover="dotgrid.interface.over('${type}','${name}')"
viewBox="0 0 300 300" viewBox="0 0 300 300"
class="icon ${type}"> 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"> <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> </rect>
</svg>` </svg>`
} }
} }
this.menu_el.innerHTML = html this.menu_el.innerHTML = html
this.menu_el.appendChild(dotgrid.picker.el) this.menu_el.appendChild(dotgrid.picker.el)
} }
this.over = function(type,name) this.over = function (type, name) {
{
dotgrid.cursor.operation = {} dotgrid.cursor.operation = {}
dotgrid.cursor.operation[type] = name; dotgrid.cursor.operation[type] = name
} }
this.out = function(type,name) this.out = function (type, name) {
{ dotgrid.cursor.operation = ''
dotgrid.cursor.operation = ""
} }
this.up = function(type,name) this.up = function (type, name) {
{ if (!dotgrid.tool[type]) { console.warn(`Unknown option(type): ${type}.${name}`, dotgrid.tool); return }
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) this.down = function (type, name) {
{ if (!dotgrid.tool[type]) { console.warn(`Unknown option(type): ${type}.${name}`, dotgrid.tool); return }
if(!dotgrid.tool[type]){ console.warn(`Unknown option(type): ${type}.${name}`,dotgrid.tool); return; }
dotgrid.tool[type](name) dotgrid.tool[type](name)
this.update(true); this.update(true)
} }
this.prev_operation = null; this.prev_operation = null
this.update = function(force = false,id) this.update = function (force = false, id) {
{ if (this.prev_operation == dotgrid.cursor.operation && force == false) { return }
if(this.prev_operation == dotgrid.cursor.operation && force == false){ return; }
let multi_vertices = null; let multi_vertices = null
let segments = dotgrid.tool.layer() let segments = dotgrid.tool.layer()
const sum_segments = dotgrid.tool.length(); const sum_segments = dotgrid.tool.length()
for(const i in segments){ for (const i in segments) {
if(segments[i].vertices.length > 2){ multi_vertices = true; break; } 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_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_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_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_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_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_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_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_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_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_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.fill = dotgrid.tool.style().color
document.getElementById("option_color").children[0].style.stroke = 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_color').className.baseVal = 'icon'
// Source // Source
document.getElementById("option_save").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_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_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 // 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 ") } 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 ') }
else{ document.getElementById("grid_path").setAttribute("d","M65,155 Q155,245 245,155 M65,155 ") }
// Mirror // 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") } 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 ') }
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.toggle = function () {
{ this.is_visible = !this.is_visible
this.is_visible = this.is_visible ? false : true; this.el.className = this.is_visible ? 'visible' : 'hidden'
this.el.className = this.is_visible ? "visible" : "hidden";
} }
} }

View File

@ -1,198 +1,185 @@
'use strict'; 'use strict'
function Controller() function Controller () {
{ this.menu = { default: {} }
this.menu = {default:{}}; this.mode = '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) this.add = function (mode, cat, label, fn, accelerator) {
{ if (!this.menu[mode]) { this.menu[mode] = {} }
if(!this.menu[mode]){ this.menu[mode] = {}; } if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
if(!this.menu[mode][cat]){ this.menu[mode][cat] = {}; } this.menu[mode][cat][label] = { fn: fn, accelerator: accelerator }
this.menu[mode][cat][label] = {fn:fn,accelerator:accelerator}; console.log(`${mode}/${cat}/${label} <${accelerator}>`)
console.log(`${mode}/${cat}/${label} <${accelerator}>`);
} }
this.add_role = function(mode,cat,label) this.add_role = function (mode, cat, label) {
{ if (!this.menu[mode]) { this.menu[mode] = {} }
if(!this.menu[mode]){ this.menu[mode] = {}; } if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
if(!this.menu[mode][cat]){ this.menu[mode][cat] = {}; } this.menu[mode][cat][label] = { role: label }
this.menu[mode][cat][label] = {role:label};
} }
this.set = function(mode = "default") this.set = function (mode = 'default') {
{ this.mode = mode
this.mode = mode; this.commit()
this.commit();
} }
this.format = function() this.format = function () {
{ let f = []
let f = []; let m = this.menu[this.mode]
let m = this.menu[this.mode]; for (const cat in m) {
for(const cat in m){ let submenu = []
let submenu = []; for (const name in m[cat]) {
for(const name in m[cat]){ let option = m[cat][name]
let option = m[cat][name]; if (option.role) {
if(option.role){ submenu.push({ role: option.role })
submenu.push({role:option.role}) } else {
} submenu.push({ label: name, accelerator: option.accelerator, click: option.fn })
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.commit = function () {
{ this.app.inject_menu(this.format())
this.app.inject_menu(this.format());
} }
this.docs = function() this.docs = function () {
{ console.log('Generating docs..')
console.log("Generating docs..");
let svg = this.generate_svg(this.format()) let svg = this.generate_svg(this.format())
let txt = this.documentation(this.format()); let txt = this.documentation(this.format())
dialog.showSaveDialog((fileName) => { dialog.showSaveDialog((fileName) => {
if (fileName === undefined){ return; } if (fileName === undefined) { return }
fileName = fileName.substr(-4,4) != ".svg" ? fileName+".svg" : fileName; fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName
fs.writeFile(fileName,svg); fs.writeFile(fileName, svg)
fs.writeFile(fileName.replace(".svg",".md"),txt); fs.writeFile(fileName.replace('.svg', '.md'), txt)
}); })
} }
this.generate_svg = function(m) this.generate_svg = function (m) {
{ let svg_html = ''
let svg_html = "";
for(const id in this.layout){ for (const id in this.layout) {
let key = this.layout[id]; let key = this.layout[id]
let acc = this.accelerator_for_key(key.name,m); 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 + 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 += `<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 += `<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.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>` : ''; 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() this.documentation = function () {
{ let txt = ''
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){ for (name in this.menu) {
if(name == "default"){ continue; } if (name == 'default') { continue }
txt += this.documentation_for_mode(name,this.menu[name]); txt += this.documentation_for_mode(name, this.menu[name])
} }
return txt; return txt
} }
this.documentation_for_mode = function(name,mode) this.documentation_for_mode = function (name, mode) {
{ let txt = `## ${name} Mode\n\n`
let txt = `## ${name} Mode\n\n`;
for(const id in mode){ for (const id in mode) {
if(id == "*"){ continue; } if (id == '*') { continue }
txt += `### ${id}\n`; txt += `### ${id}\n`
for(const name in mode[id]){ for (const name in mode[id]) {
let option = mode[id][name]; let option = mode[id][name]
txt += `- ${name}: \`${option.accelerator}\`\n`; txt += `- ${name}: \`${option.accelerator}\`\n`
} }
txt += "\n" txt += '\n'
} }
return txt+"\n"; return txt + '\n'
} }
this.accelerator_for_key = function(key,menu) this.accelerator_for_key = function (key, menu) {
{ let acc = { basic: null, ctrl: null }
let acc = {basic:null,ctrl:null} for (const cat in menu) {
for(const cat in menu){ let options = menu[cat]
let options = menu[cat]; for (const id in options.submenu) {
for(const id in options.submenu){ let option = options.submenu[id]; if (option.role) { continue }
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.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
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 = [ this.layout = [
{x:0, y:0, width:60, height:60, name:"esc"}, { x: 0, y: 0, width: 60, height: 60, name: 'esc' },
{x:60, y:0, width:60, height:60, name:"1"}, { x: 60, y: 0, width: 60, height: 60, name: '1' },
{x:120, y:0, width:60, height:60, name:"2"}, { x: 120, y: 0, width: 60, height: 60, name: '2' },
{x:180, y:0, width:60, height:60, name:"3"}, { x: 180, y: 0, width: 60, height: 60, name: '3' },
{x:240, y:0, width:60, height:60, name:"4"}, { x: 240, y: 0, width: 60, height: 60, name: '4' },
{x:300, y:0, width:60, height:60, name:"5"}, { x: 300, y: 0, width: 60, height: 60, name: '5' },
{x:360, y:0, width:60, height:60, name:"6"}, { x: 360, y: 0, width: 60, height: 60, name: '6' },
{x:420, y:0, width:60, height:60, name:"7"}, { x: 420, y: 0, width: 60, height: 60, name: '7' },
{x:480, y:0, width:60, height:60, name:"8"}, { x: 480, y: 0, width: 60, height: 60, name: '8' },
{x:540, y:0, width:60, height:60, name:"9"}, { x: 540, y: 0, width: 60, height: 60, name: '9' },
{x:600, y:0, width:60, height:60, name:"0"}, { x: 600, y: 0, width: 60, height: 60, name: '0' },
{x:660, y:0, width:60, height:60, name:"-"}, { x: 660, y: 0, width: 60, height: 60, name: '-' },
{x:720, y:0, width:60, height:60, name:"plus"}, { x: 720, y: 0, width: 60, height: 60, name: 'plus' },
{x:780, y:0, width:120, height:60, name:"backspace"}, { x: 780, y: 0, width: 120, height: 60, name: 'backspace' },
{x:0, y:60, width:90, height:60, name:"tab"}, { x: 0, y: 60, width: 90, height: 60, name: 'tab' },
{x:90, y:60, width:60, height:60, name:"q"}, { x: 90, y: 60, width: 60, height: 60, name: 'q' },
{x:150, y:60, width:60, height:60, name:"w"}, { x: 150, y: 60, width: 60, height: 60, name: 'w' },
{x:210, y:60, width:60, height:60, name:"e"}, { x: 210, y: 60, width: 60, height: 60, name: 'e' },
{x:270, y:60, width:60, height:60, name:"r"}, { x: 270, y: 60, width: 60, height: 60, name: 'r' },
{x:330, y:60, width:60, height:60, name:"t"}, { x: 330, y: 60, width: 60, height: 60, name: 't' },
{x:390, y:60, width:60, height:60, name:"y"}, { x: 390, y: 60, width: 60, height: 60, name: 'y' },
{x:450, y:60, width:60, height:60, name:"u"}, { x: 450, y: 60, width: 60, height: 60, name: 'u' },
{x:510, y:60, width:60, height:60, name:"i"}, { x: 510, y: 60, width: 60, height: 60, name: 'i' },
{x:570, y:60, width:60, height:60, name:"o"}, { x: 570, y: 60, width: 60, height: 60, name: 'o' },
{x:630, y:60, width:60, height:60, name:"p"}, { x: 630, y: 60, width: 60, height: 60, name: 'p' },
{x:690, y:60, width:60, height:60, name:"["}, { x: 690, y: 60, width: 60, height: 60, name: '[' },
{x:750, 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: 810, y: 60, width: 90, height: 60, name: '|' },
{x:0, y:120, width:105, height:60, name:"caps"}, { x: 0, y: 120, width: 105, height: 60, name: 'caps' },
{x:105, y:120, width:60, height:60, name:"a"}, { x: 105, y: 120, width: 60, height: 60, name: 'a' },
{x:165, y:120, width:60, height:60, name:"s"}, { x: 165, y: 120, width: 60, height: 60, name: 's' },
{x:225, y:120, width:60, height:60, name:"d"}, { x: 225, y: 120, width: 60, height: 60, name: 'd' },
{x:285, y:120, width:60, height:60, name:"f"}, { x: 285, y: 120, width: 60, height: 60, name: 'f' },
{x:345, y:120, width:60, height:60, name:"g"}, { x: 345, y: 120, width: 60, height: 60, name: 'g' },
{x:405, y:120, width:60, height:60, name:"h"}, { x: 405, y: 120, width: 60, height: 60, name: 'h' },
{x:465, y:120, width:60, height:60, name:"j"}, { x: 465, y: 120, width: 60, height: 60, name: 'j' },
{x:525, y:120, width:60, height:60, name:"k"}, { x: 525, y: 120, width: 60, height: 60, name: 'k' },
{x:585, y:120, width:60, height:60, name:"l"}, { x: 585, y: 120, width: 60, height: 60, name: 'l' },
{x:645, y:120, width:60, height:60, name:";"}, { x: 645, y: 120, width: 60, height: 60, name: ';' },
{x:705, 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: 765, y: 120, width: 135, height: 60, name: 'enter' },
{x:0, y:180, width:135, height:60, name:"shift"}, { x: 0, y: 180, width: 135, height: 60, name: 'shift' },
{x:135, y:180, width:60, height:60, name:"z"}, { x: 135, y: 180, width: 60, height: 60, name: 'z' },
{x:195, y:180, width:60, height:60, name:"x"}, { x: 195, y: 180, width: 60, height: 60, name: 'x' },
{x:255, y:180, width:60, height:60, name:"c"}, { x: 255, y: 180, width: 60, height: 60, name: 'c' },
{x:315, y:180, width:60, height:60, name:"v"}, { x: 315, y: 180, width: 60, height: 60, name: 'v' },
{x:375, y:180, width:60, height:60, name:"b"}, { x: 375, y: 180, width: 60, height: 60, name: 'b' },
{x:435, y:180, width:60, height:60, name:"n"}, { x: 435, y: 180, width: 60, height: 60, name: 'n' },
{x:495, y:180, width:60, height:60, name:"m"}, { x: 495, y: 180, width: 60, height: 60, name: 'm' },
{x:555, y:180, width:60, height:60, name:","}, { x: 555, y: 180, width: 60, height: 60, name: ',' },
{x:615, 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: 675, y: 180, width: 60, height: 60, name: '/' },
{x:735, y:180, width:165, height:60, name:"capslock"}, { x: 735, y: 180, width: 165, height: 60, name: 'capslock' },
{x:0, y:240, width:90, height:60, name:"ctrl"}, { x: 0, y: 240, width: 90, height: 60, name: 'ctrl' },
{x:90, y:240, width:90, height:60, name:"cmd"}, { x: 90, y: 240, width: 90, height: 60, name: 'cmd' },
{x:180, y:240, width:90, height:60, name:"alt"}, { x: 180, y: 240, width: 90, height: 60, name: 'alt' },
{x:270, y:240, width:270, height:60, name:"space"}, { x: 270, y: 240, width: 270, height: 60, name: 'space' },
{x:810, y:240, width:90, height:60, name:"ctrl"}, { x: 810, y: 240, width: 90, height: 60, name: 'ctrl' },
{x:720, y:240, width:90, height:60, name:"pn"}, { x: 720, y: 240, width: 90, height: 60, name: 'pn' },
{x:630, y:240, width:90, height:60, name:"fn"}, { x: 630, y: 240, width: 90, height: 60, name: 'fn' },
{x:540, y:240, width:90, height:60, name:"alt"} { 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() function History () {
{ this.index = 0
this.index = 0; this.a = []
this.a = [];
this.clear = function() this.clear = function () {
{ this.a = []
this.a = []; this.index = 0
this.index = 0;
} }
this.push = function(data) this.push = function (data) {
{ if (this.index < this.a.length - 1) {
if(this.index < this.a.length-1){ this.fork()
this.fork();
} }
this.index = this.a.length; this.index = this.a.length
this.a = this.a.slice(0,this.index); this.a = this.a.slice(0, this.index)
this.a.push(copy(data)); this.a.push(copy(data))
if(this.a.length > 20){ if (this.a.length > 20) {
this.a.shift(); this.a.shift()
} }
} }
this.fork = function() this.fork = function () {
{ this.a = this.a.slice(0, this.index + 1)
this.a = this.a.slice(0,this.index+1);
} }
this.pop = function() this.pop = function () {
{ return this.a.pop()
return this.a.pop();
} }
this.prev = function() this.prev = function () {
{ this.index = clamp(this.index - 1, 0, this.a.length - 1)
this.index = clamp(this.index-1,0,this.a.length-1); return copy(this.a[this.index])
return copy(this.a[this.index]);
} }
this.next = function() this.next = function () {
{ this.index = clamp(this.index + 1, 0, this.a.length - 1)
this.index = clamp(this.index+1,0,this.a.length-1); return copy(this.a[this.index])
return copy(this.a[this.index]);
} }
function copy(data){ return data ? JSON.parse(JSON.stringify(data)) : []; } function copy (data) { return data ? JSON.parse(JSON.stringify(data)) : [] }
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; } 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" }) 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
const themer = this;
this.el = document.createElement("style") this.el = document.createElement('style')
this.el.type = 'text/css' this.el.type = 'text/css'
this.callback; this.callback
this.active; this.active
this.collection = { this.collection = {
default: default_theme, 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" }, 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" } 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) this.install = function (host = document.body, callback) {
{ console.log('Theme', 'Installing..')
console.log("Theme","Installing..")
host.appendChild(this.el) host.appendChild(this.el)
this.callback = callback this.callback = callback
} }
this.start = function() this.start = function () {
{ console.log('Theme', 'Starting..')
console.log("Theme","Starting..") const storage = is_json(localStorage.theme) ? JSON.parse(localStorage.theme) : this.collection.default
const storage = is_json(localStorage.theme) ? JSON.parse(localStorage.theme) : this.collection.default;
this.load(!storage.background ? this.collection.default : storage) this.load(!storage.background ? this.collection.default : storage)
} }
this.save = function(theme) this.save = function (theme) {
{ console.log('Theme', 'Saving..')
console.log("Theme","Saving..") this.active = theme
this.active = theme; localStorage.setItem('theme', JSON.stringify(theme))
localStorage.setItem("theme", JSON.stringify(theme));
} }
this.load = function(theme, fall_back = this.collection.noir) this.load = function (theme, fall_back = this.collection.noir) {
{ if (!theme || !theme.background) { console.warn('Theme', 'Not a theme', theme); return }
if(!theme || !theme.background){ console.warn("Theme","Not a theme",theme); return; }
this.save(theme); this.save(theme)
this.apply(theme); this.apply(theme)
if(this.callback){ if (this.callback) {
this.callback(); this.callback()
} }
} }
this.apply = function(theme) this.apply = function (theme) {
{
this.el.innerHTML = ` this.el.innerHTML = `
:root { :root {
--background: ${theme.background}; --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_med: ${theme.b_med};
--b_low: ${theme.b_low}; --b_low: ${theme.b_low};
--b_inv: ${theme.b_inv}; --b_inv: ${theme.b_inv};
}`; }`
} }
this.parse = function(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) }
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) this.extract = function (text) {
{ const svg = new DOMParser().parseFromString(text, 'text/xml')
const svg = new DOMParser().parseFromString(text,"text/xml")
try {
try{
return { return {
"background": svg.getElementById("background").getAttribute("fill"), 'background': svg.getElementById('background').getAttribute('fill'),
"f_high": svg.getElementById("f_high").getAttribute("fill"), 'f_high': svg.getElementById('f_high').getAttribute('fill'),
"f_med": svg.getElementById("f_med").getAttribute("fill"), 'f_med': svg.getElementById('f_med').getAttribute('fill'),
"f_low": svg.getElementById("f_low").getAttribute("fill"), 'f_low': svg.getElementById('f_low').getAttribute('fill'),
"f_inv": svg.getElementById("f_inv").getAttribute("fill"), 'f_inv': svg.getElementById('f_inv').getAttribute('fill'),
"b_high": svg.getElementById("b_high").getAttribute("fill"), 'b_high': svg.getElementById('b_high').getAttribute('fill'),
"b_med": svg.getElementById("b_med").getAttribute("fill"), 'b_med': svg.getElementById('b_med').getAttribute('fill'),
"b_low": svg.getElementById("b_low").getAttribute("fill"), 'b_low': svg.getElementById('b_low').getAttribute('fill'),
"b_inv": svg.getElementById("b_inv").getAttribute("fill") 'b_inv': svg.getElementById('b_inv').getAttribute('fill')
}; }
} } catch (err) {
catch(err){ console.warn('Theme', 'Incomplete SVG Theme', err)
console.warn("Theme","Incomplete SVG Theme", err)
} }
} }
this.reset = function() this.reset = function () {
{ this.load(this.collection.default)
this.load(this.collection.default);
} }
// Defaults // Defaults
this.pale = function() this.pale = function () {
{
this.load(this.collection.pale) this.load(this.collection.pale)
} }
this.noir = function() this.noir = function () {
{
this.load(this.collection.noir) 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) this.load(this.active.background == this.collection.noir.background ? this.collection.pale : this.collection.noir)
} }
// Drag // Drag
this.drag = function(e) this.drag = function (e) {
{ e.stopPropagation()
e.stopPropagation(); e.preventDefault()
e.preventDefault(); e.dataTransfer.dropEffect = 'copy'
e.dataTransfer.dropEffect = 'copy';
} }
this.drop = function(e) this.drop = function (e) {
{ e.preventDefault()
e.preventDefault(); e.stopPropagation()
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 || !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.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return }
const reader = new FileReader(); const reader = new FileReader()
reader.onload = function(e){ reader.onload = function (e) {
themer.load(themer.parse(e.target.result)); themer.load(themer.parse(e.target.result))
}; }
reader.readAsText(file); reader.readAsText(file)
} }
window.addEventListener('dragover',this.drag); window.addEventListener('dragover', this.drag)
window.addEventListener('drop', this.drop); window.addEventListener('drop', this.drop)
function is_json(text){ try{ JSON.parse(text); 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; } } 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() function Picker () {
{ this.memory = ''
this.memory = ""; this.el = document.createElement('div')
this.el = document.createElement("div"); this.el.id = 'picker'
this.el.id = "picker" this.is_active = false
this.is_active = false; this.input = document.createElement('input')
this.input = document.createElement("input"); this.input.id = 'picker_input'
this.input.id = "picker_input"
this.el.appendChild(this.input) this.el.appendChild(this.input)
this.start = function() this.start = function () {
{ if (this.is_active) { return }
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('placeholder', `${dotgrid.tool.style().color.replace('#', '').trim()}`)
this.input.setAttribute("maxlength",6) this.input.setAttribute('maxlength', 6)
dotgrid.interface.el.className = "picker" dotgrid.interface.el.className = 'picker'
this.input.focus() this.input.focus()
this.input.value = "" this.input.value = ''
try{ dotgrid.controller.set("picker"); } try { dotgrid.controller.set('picker') } catch (err) { }
catch(err){ }
} }
this.update = function() this.update = function () {
{ if (!this.is_active) { return }
if(!this.is_active){ return; } if (!is_color(this.input.value)) { 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.fill = hex
document.getElementById("option_color").children[0].style.stroke = hex; document.getElementById('option_color').children[0].style.stroke = hex
} }
this.stop = function() this.stop = function () {
{ if (!this.is_active) { return }
if(!this.is_active){ return; }
this.is_active = false; this.is_active = false
dotgrid.interface.el.className = "" dotgrid.interface.el.className = ''
this.input.blur() this.input.blur()
this.input.value = "" this.input.value = ''
try{ dotgrid.controller.set(); } try { dotgrid.controller.set() } catch (err) { console.log('No controller') }
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() this.validate = function () {
{ if (!is_color(this.input.value)) { return }
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().color = hex
dotgrid.tool.style().fill = dotgrid.tool.style().fill != "none" ? hex : "none"; dotgrid.tool.style().fill = dotgrid.tool.style().fill != 'none' ? hex : 'none'
this.stop(); this.stop()
} }
this.listen = function(e,is_down = false) this.listen = function (e, is_down = false) {
{ if (is_down && !is_color_char(e.key)) {
if(is_down && !is_color_char(e.key)){ e.preventDefault()
e.preventDefault(); return
return;
} }
if(e.key == "Enter"){ if (e.key == 'Enter') {
this.validate(); this.validate()
e.preventDefault(); e.preventDefault()
return; return
} }
if(e.key == "Escape"){ if (e.key == 'Escape') {
this.stop(); this.stop()
e.preventDefault(); e.preventDefault()
return; return
} }
this.update(); this.update()
} }
function is_color(val) function is_color (val) {
{ if (val.length != 3 && val.length != 6) {
if(val.length != 3 && val.length != 6){
return false return false
} }
const re = /[0-9A-Fa-f]/g; const re = /[0-9A-Fa-f]/g
return re.test(val) return re.test(val)
} }
function is_color_char(val) function is_color_char (val) {
{ const re = /[0-9A-Fa-f]/g
const re = /[0-9A-Fa-f]/g;
return re.test(val) return re.test(val)
} }
this.input.onkeydown = function(event){ dotgrid.picker.listen(event,true); } this.input.onkeydown = function (event) { dotgrid.picker.listen(event, true) }
this.input.onkeyup = function(event){ dotgrid.picker.listen(event); }; 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 // Create SVG parts
this.svg_el = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 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('xmlns', 'http://www.w3.org/2000/svg')
this.svg_el.setAttribute("baseProfile","full"); this.svg_el.setAttribute('baseProfile', 'full')
this.svg_el.setAttribute("version","1.1"); this.svg_el.setAttribute('version', '1.1')
this.svg_el.style.fill = "none"; this.svg_el.style.fill = 'none'
this.layer_1 = 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_2 = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.layer_3 = 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_3)
this.svg_el.appendChild(this.layer_2); this.svg_el.appendChild(this.layer_2)
this.svg_el.appendChild(this.layer_1); this.svg_el.appendChild(this.layer_1)
this.update = function() this.update = function () {
{ this.svg_el.setAttribute('width', (dotgrid.tool.settings.size.width - (5)) + 'px')
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.setAttribute("height",(dotgrid.tool.settings.size.height+(10))+"px"); this.svg_el.style.width = (dotgrid.tool.settings.size.width - (5))
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.height = dotgrid.tool.settings.size.height+(10); this.svg_el.style.strokeWidth = dotgrid.tool.style().thickness
this.svg_el.style.strokeWidth = dotgrid.tool.style().thickness;
let styles = dotgrid.tool.styles let styles = dotgrid.tool.styles
let paths = dotgrid.tool.paths() let paths = dotgrid.tool.paths()
this.layer_1.style.strokeWidth = styles[0].thickness; this.layer_1.style.strokeWidth = styles[0].thickness
this.layer_1.style.strokeLinecap = styles[0].strokeLinecap; this.layer_1.style.strokeLinecap = styles[0].strokeLinecap
this.layer_1.style.strokeLinejoin = styles[0].strokeLinejoin; this.layer_1.style.strokeLinejoin = styles[0].strokeLinejoin
this.layer_1.style.stroke = styles[0].color; this.layer_1.style.stroke = styles[0].color
this.layer_1.style.fill = styles[0].fill; this.layer_1.style.fill = styles[0].fill
this.layer_1.setAttribute("d",paths[0]) this.layer_1.setAttribute('d', paths[0])
this.layer_2.style.strokeWidth = styles[1].thickness; this.layer_2.style.strokeWidth = styles[1].thickness
this.layer_2.style.strokeLinecap = styles[1].strokeLinecap; this.layer_2.style.strokeLinecap = styles[1].strokeLinecap
this.layer_2.style.strokeLinejoin = styles[1].strokeLinejoin; this.layer_2.style.strokeLinejoin = styles[1].strokeLinejoin
this.layer_2.style.stroke = styles[1].color; this.layer_2.style.stroke = styles[1].color
this.layer_2.style.fill = styles[1].fill; this.layer_2.style.fill = styles[1].fill
this.layer_2.setAttribute("d",paths[1]) this.layer_2.setAttribute('d', paths[1])
this.layer_3.style.strokeWidth = styles[2].thickness; this.layer_3.style.strokeWidth = styles[2].thickness
this.layer_3.style.strokeLinecap = styles[2].strokeLinecap; this.layer_3.style.strokeLinecap = styles[2].strokeLinecap
this.layer_3.style.strokeLinejoin = styles[2].strokeLinejoin; this.layer_3.style.strokeLinejoin = styles[2].strokeLinejoin
this.layer_3.style.stroke = styles[2].color; this.layer_3.style.stroke = styles[2].color
this.layer_3.style.fill = styles[2].fill; this.layer_3.style.fill = styles[2].fill
this.layer_3.setAttribute("d",paths[2]) this.layer_3.setAttribute('d', paths[2])
} }
this.to_png = function(size = dotgrid.tool.settings.size,callback = dotgrid.render) this.to_png = function (size = dotgrid.tool.settings.size, callback = dotgrid.render) {
{ if (!dialog) { return this.to_png_web(size) }
if(!dialog){ return this.to_png_web(size); }
this.update(); this.update()
let xml = new XMLSerializer().serializeToString(this.svg_el); let xml = new XMLSerializer().serializeToString(this.svg_el)
let svg64 = btoa(xml); let svg64 = btoa(xml)
let b64Start = 'data:image/svg+xml;base64,'; let b64Start = 'data:image/svg+xml;base64,'
let image64 = b64Start + svg64; let image64 = b64Start + svg64
let img = new Image; let img = new Image()
let canvas = document.createElement("canvas"); let canvas = document.createElement('canvas')
canvas.width = (size.width)*2; canvas.width = (size.width) * 2
canvas.height = (size.height+30)*2; canvas.height = (size.height + 30) * 2
let ctx = canvas.getContext('2d'); let ctx = canvas.getContext('2d')
img.onload = function(){ img.onload = function () {
ctx.drawImage(img, 0, 0, (size.width)*2, (size.height+30)*2); ctx.drawImage(img, 0, 0, (size.width) * 2, (size.height + 30) * 2)
let data = canvas.toDataURL('image/png').replace(/^data:image\/\w+;base64,/, ""); let data = canvas.toDataURL('image/png').replace(/^data:image\/\w+;base64,/, '')
dotgrid.renderer.to_png_ready(callback, new Buffer(data, 'base64'),size) dotgrid.renderer.to_png_ready(callback, new Buffer(data, 'base64'), size)
}; }
img.src = image64; img.src = image64
} }
this.to_png_ready = function(callback, buffer, size) this.to_png_ready = function (callback, buffer, size) {
{ callback(null, buffer, size)
callback(null,buffer,size)
} }
this.to_png_web = function(size) this.to_png_web = function (size) {
{ if (dotgrid.tool.length() < 1) { console.warn('Nothing to render'); return }
if(dotgrid.tool.length() < 1){ console.warn('Nothing to render'); return; } this.update()
this.update();
let xml = new XMLSerializer().serializeToString(this.svg_el); let xml = new XMLSerializer().serializeToString(this.svg_el)
let svg64 = btoa(xml); let svg64 = btoa(xml)
let b64Start = 'data:image/svg+xml;base64,'; let b64Start = 'data:image/svg+xml;base64,'
let image64 = b64Start + svg64; let image64 = b64Start + svg64
let canvas = document.createElement("canvas"); let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d'); let ctx = canvas.getContext('2d')
let win = window.open('about:blank','image from canvas');
let img = new Image;
canvas.width = size.width*2; let win = window.open('about:blank', 'image from canvas')
canvas.height = size.height*2; let img = new Image()
img.onload = function(){ canvas.width = size.width * 2
ctx.drawImage(img, 0, 0, size.width*2, size.height*2); canvas.height = 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.onload = function () {
img.src = image64; 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.to_svg = function () {
{ this.update()
this.update();
return this.svg_el.outerHTML; return this.svg_el.outerHTML
} }
} }

View File

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