Improved load/save

This commit is contained in:
neauoire
2019-11-03 20:44:31 -05:00
parent 7ceef4a5eb
commit 7a618f6925
12 changed files with 109 additions and 281 deletions

View File

@@ -2,15 +2,14 @@
function Cursor (dotgrid) {
this.pos = { x: 0, y: 0 }
this.lastPos = { x: 0, y: 0 }
this.translation = null
this.operation = null
this.translate = function (from = null, to = null, multi = false, copy = false, layer = false) {
if ((from || to) && this.translation === null) { this.translation = { multi: multi, copy: copy, layer: layer } }
if (from) { this.translation.from = from }
if (to) { this.translation.to = to }
if (!from && !to) {
this.translation = null
}
@@ -18,49 +17,36 @@ function Cursor (dotgrid) {
this.down = function (e) {
this.pos = this.atEvent(e)
// Translation
if (dotgrid.tool.vertexAt(this.pos)) {
this.translate(this.pos, this.pos, e.shiftKey, e.ctrlKey || e.metaKey, e.altKey)
}
dotgrid.renderer.update()
dotgrid.interface.update()
e.preventDefault()
}
this.last_pos = { x: 0, y: 0 }
this.move = function (e) {
this.pos = this.atEvent(e)
// Translation
if (this.translation) {
this.translate(null, this.pos)
}
if (this.last_pos.x !== this.pos.x || this.last_pos.y !== this.pos.y) {
if (this.lastPos.x !== this.pos.x || this.lastPos.y !== this.pos.y) {
dotgrid.renderer.update()
}
dotgrid.interface.update()
this.lastPos = this.pos
e.preventDefault()
this.last_pos = this.pos
}
this.up = function (e) {
this.pos = this.atEvent(e)
if (this.translation && !isEqual(this.translation.from, this.translation.to)) {
if (this.translation.layer === true) { dotgrid.tool.translateLayer(this.translation.from, this.translation.to) } else if (this.translation.copy) { dotgrid.tool.translateCopy(this.translation.from, this.translation.to) } else if (this.translation.multi) { dotgrid.tool.translateMulti(this.translation.from, this.translation.to) } else { dotgrid.tool.translate(this.translation.from, this.translation.to) }
} else if (e.target.id === 'guide') {
dotgrid.tool.addVertex({ x: this.pos.x, y: this.pos.y })
dotgrid.picker.stop()
}
this.translate()
dotgrid.interface.update()
dotgrid.renderer.update()
e.preventDefault()
@@ -68,15 +54,13 @@ function Cursor (dotgrid) {
this.alt = function (e) {
this.pos = this.atEvent(e)
dotgrid.tool.removeSegmentsAt(this.pos)
e.preventDefault()
setTimeout(() => { dotgrid.tool.clear() }, 150)
setTimeout(() => {
dotgrid.tool.clear()
}, 150)
}
// Position Mods
this.atEvent = function (e) {
return this.snapPos(this.relativePos({ x: e.clientX, y: e.clientY }))
}

View File

@@ -12,12 +12,9 @@
/* global Picker */
/* global Cursor */
/* global webFrame */
/* global FileReader */
function Dotgrid () {
// ISU
this.install = function (host) {
console.info('Dotgrid', 'Installing..')
@@ -35,7 +32,6 @@ function Dotgrid () {
host.appendChild(this.renderer.el)
// Add events
document.addEventListener('mousedown', (e) => { this.cursor.down(e) }, false)
document.addEventListener('mousemove', (e) => { this.cursor.move(e) }, false)
document.addEventListener('contextmenu', (e) => { this.cursor.alt(e) }, false)
@@ -45,11 +41,12 @@ function Dotgrid () {
document.addEventListener('paste', (e) => { this.paste(e) }, false)
window.addEventListener('resize', (e) => { this.onResize() }, false)
window.addEventListener('dragover', (e) => { e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'copy' })
window.addEventListener('drop', this.drag)
window.addEventListener('drop', this.onDrop)
this.acels.set('File', 'New', 'CmdOrCtrl+N', () => { this.source.new() })
this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.save('export.grid', this.tool.export(), 'text/plain') })
this.acels.set('File', 'Export Vector', 'CmdOrCtrl+E', () => { this.source.download('export.svg', this.manager.toString(), 'image/svg+xml') })
this.acels.set('File', 'Export Image', 'CmdOrCtrl+Shift+E', () => { this.manager.toPNG(this.tool.settings.size, (dataUrl) => { this.source.download('export.png', dataUrl, 'image/png') }) })
this.acels.set('File', 'Open', 'CmdOrCtrl+O', () => { this.source.open('grid', this.whenOpen) })
this.acels.set('File', 'Revert', 'CmdOrCtrl+W', () => { this.source.revert() })
this.acels.set('History', 'Undo', 'CmdOrCtrl+Z', () => { this.history.undo() })
@@ -91,7 +88,7 @@ function Dotgrid () {
}
this.start = () => {
console.log('Ronin', 'Starting..')
console.log('Dotgrid', 'Starting..')
console.info(`${this.acels}`)
this.theme.start()
@@ -124,25 +121,8 @@ function Dotgrid () {
this.update()
}
// Methods
this.modZoom = function (mod = 0, set = false) {
try {
const { webFrame } = require('electron')
const currentZoomFactor = webFrame.getZoomFactor()
webFrame.setZoomFactor(set ? mod : currentZoomFactor + mod)
console.log(window.devicePixelRatio)
} catch (err) {
console.log('Cannot zoom')
}
}
this.setZoom = function (scale) {
try {
webFrame.setZoomFactor(scale)
} catch (err) {
console.log('Cannot zoom')
}
this.whenOpen = (data) => {
this.tool.replace(JSON.parse(data))
}
// Resize Tools
@@ -229,6 +209,16 @@ function Dotgrid () {
reader.readAsText(file)
}
this.onDrop = (e) => {
e.preventDefault()
e.stopPropagation()
const file = e.dataTransfer.files[0]
if (file.name.indexOf('.grid') > -1) {
this.source.load(e.dataTransfer.files[0], this.whenOpen)
}
}
this.copy = function (e) {
this.renderer.update()
@@ -270,15 +260,8 @@ function Dotgrid () {
this.renderer.update()
}
function sizeOffset (a, b) { return { width: a.width - b.width, height: a.height - b.height } }
function printSize (size) { return `${size.width}x${size.height}` }
function isJson (text) { try { JSON.parse(text); return true } catch (error) { return false } }
function step (v, s) { return Math.round(v / s) * s }
}
String.prototype.capitalize = function () {
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase()
}
function sizeOffset (a, b) { return { width: a.width - b.width, height: a.height - b.height } }
function printSize (size) { return `${size.width}x${size.height}` }
function isJson (text) { try { JSON.parse(text); return true } catch (error) { return false } }
function isEqual (a, b) { return a && b && a.x === b.x && a.y === b.y }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
function step (v, s) { return Math.round(v / s) * s }

View File

@@ -1,5 +1,7 @@
'use strict'
/* global dotgrid */
function Generator (layer, style) {
this.layer = layer
this.style = style
@@ -12,15 +14,12 @@ function Generator (layer, style) {
for (const k2 in seg.vertices) {
if (mirror === 1 || mirror === 3) { seg.vertices[k2].x = (dotgrid.tool.settings.size.width) - seg.vertices[k2].x }
if (mirror === 2 || mirror === 3) { seg.vertices[k2].y = (dotgrid.tool.settings.size.height) - seg.vertices[k2].y }
// Offset
seg.vertices[k2].x += offset.x
seg.vertices[k2].y += offset.y
// Rotate
const center = { x: (dotgrid.tool.settings.size.width / 2) + offset.x + (7.5), y: (dotgrid.tool.settings.size.height / 2) + offset.y + 30 }
seg.vertices[k2] = rotatePoint(seg.vertices[k2], center, angle)
// Scale
seg.vertices[k2].x *= scale
seg.vertices[k2].y *= scale
@@ -42,7 +41,9 @@ function Generator (layer, style) {
const next = vertices[parseInt(id) + 1]
const afterNext = vertices[parseInt(id) + 2]
if (parseInt(id) === 0 && !prev || parseInt(id) === 0 && prev && (prev.x !== vertex.x || prev.y !== vertex.y)) {
if (parseInt(id) === 0 && !prev) {
html += `M${vertex.x},${vertex.y} `
} else if (parseInt(id) === 0 && prev && (prev.x !== vertex.x || prev.y !== vertex.y)) {
html += `M${vertex.x},${vertex.y} `
}

View File

@@ -50,7 +50,7 @@ function Interface (dotgrid) {
html += `
<svg
id="option_${name}"
title="${name.capitalize()}"
title="${capitalize(name)}"
onmouseout="dotgrid.interface.out('${type}','${name}')"
onmouseup="dotgrid.interface.up('${type}','${name}')"
onmousedown="dotgrid.interface.down('${type}','${name}', event)"
@@ -59,7 +59,7 @@ function Interface (dotgrid) {
class="icon ${type}">
<path id="${name}_path" class="icon_path" d="${tool.icon}"/>${name === 'depth' ? '<path class="icon_path inactive" d=""/>' : ''}
<rect ar="${name}" width="300" height="300" opacity="0">
<title>${name.capitalize()}${tool.key ? '(' + tool.key + ')' : ''}</title>
<title>${capitalize(name)}${tool.key ? '(' + tool.key + ')' : ''}</title>
</rect>
</svg>`
}
@@ -152,4 +152,8 @@ function Interface (dotgrid) {
e.preventDefault()
}
}
function capitalize (str) {
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
}
}

View File

@@ -1,6 +1,9 @@
'use strict'
// Manages the SVG file
/* global XMLSerializer */
/* global btoa */
/* global Image */
/* global Blob */
function Manager (dotgrid) {
// Create SVG parts
@@ -28,15 +31,9 @@ function Manager (dotgrid) {
const paths = dotgrid.tool.paths()
for (const id in this.layers) {
let style = styles[id]
let path = paths[id]
const style = styles[id]
const path = paths[id]
const layer = this.layers[id]
// Easter Egg
if (dotgrid.tool.settings.crest === true) {
style = styles[0]
path = paths[0]
layer.setAttribute('transform', `rotate(${parseInt(id) * 120} ${(dotgrid.tool.settings.size.width / 2) + 7.5} ${(dotgrid.tool.settings.size.height / 2) + 7.5})`)
}
layer.style.strokeWidth = style.thickness
layer.style.strokeLinecap = style.strokeLinecap
@@ -67,7 +64,7 @@ function Manager (dotgrid) {
canvas.height = (size.height) * 2
img.onload = function () {
canvas.getContext('2d').drawImage(img, 0, 0, (size.width) * 2, (size.height) * 2)
callback(canvas.toDataURL('image/png'), 'export.png')
callback(canvas.toDataURL('image/png'))
}
img.src = image64
}

View File

@@ -73,6 +73,7 @@ function Picker (dotgrid) {
}
this.onKeyDown = (e) => {
e.stopPropagation()
if (e.key === 'Enter') {
this.validate()
e.preventDefault()
@@ -81,9 +82,7 @@ function Picker (dotgrid) {
if (e.key === 'Escape') {
this.stop()
e.preventDefault()
return
}
e.stopPropagation()
}
this.onKeyUp = (e) => {

View File

@@ -1,5 +1,9 @@
'use strict'
/* global Image */
/* global Path2D */
/* global Generator */
function Renderer (dotgrid) {
this.el = document.createElement('canvas')
this.el.id = 'guide'
@@ -68,14 +72,14 @@ function Renderer (dotgrid) {
this.drawMirror = function () {
if (!this.showExtras) { return }
if (dotgrid.tool.style().mirror_style === 0 && dotgrid.tool.settings.crest === false) { return }
if (dotgrid.tool.style().mirror_style === 0) { return }
const middle = { x: dotgrid.tool.settings.size.width, y: dotgrid.tool.settings.size.height }
if (dotgrid.tool.style().mirror_style === 1 || dotgrid.tool.style().mirror_style === 3 || dotgrid.tool.settings.crest === true) {
if (dotgrid.tool.style().mirror_style === 1 || dotgrid.tool.style().mirror_style === 3) {
this.drawRule({ x: middle.x, y: 15 * this.scale }, { x: middle.x, y: (dotgrid.tool.settings.size.height) * this.scale })
}
if (dotgrid.tool.style().mirror_style === 2 || dotgrid.tool.style().mirror_style === 3 || dotgrid.tool.settings.crest === true) {
if (dotgrid.tool.style().mirror_style === 2 || dotgrid.tool.style().mirror_style === 3) {
this.drawRule({ x: 15 * this.scale, y: middle.y }, { x: (dotgrid.tool.settings.size.width) * this.scale, y: middle.y })
}
}
@@ -101,7 +105,6 @@ function Renderer (dotgrid) {
this.drawGrid = function () {
if (!this.showExtras) { return }
const cursor = { x: parseInt(dotgrid.cursor.pos.x / 15), y: parseInt(dotgrid.cursor.pos.y / 15) }
const markers = { w: parseInt(dotgrid.tool.settings.size.width / 15), h: parseInt(dotgrid.tool.settings.size.height / 15) }
for (let x = markers.w - 1; x >= 0; x--) {
@@ -267,6 +270,5 @@ function Renderer (dotgrid) {
function printSize (size) { return `${size.width}x${size.height}` }
function sizeOffset (a, b) { return { width: a.width - b.width, height: a.height - b.height } }
function isEqual (a, b) { return a && b && Math.abs(a.x) === Math.abs(b.x) && Math.abs(a.y) === Math.abs(b.y) }
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
}

View File

@@ -1,72 +0,0 @@
'use strict'
function Source (dotgrid) {
this.path = null
this.new = function () {
dotgrid.setZoom(1.0)
dotgrid.history.push(dotgrid.tool.layers)
dotgrid.clear()
this.path = null
}
this.open = function () {
if (!dialog) { return }
const paths = dialog.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'Dotgrid Image', extensions: ['dot', 'grid'] }] })
if (!paths) { console.warn('Nothing to load'); return }
fs.readFile(paths[0], 'utf-8', (err, data) => {
if (err) { alert('An error ocurred reading the file :' + err.message); return }
this.load(paths[0], data)
})
}
this.load = function (path, data) {
if (!path || isJson(data) === false) { return }
const parsed = JSON.parse(`${data}`)
dotgrid.tool.replace(parsed)
this.path = path
}
this.save = function () {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to save'); return }
if (this.canWrite() === true) {
this.write(this.path, dotgrid.tool.export())
} else {
dotgrid.manager.toGRID(grab)
}
}
this.canWrite = function () {
return fs && fs.existsSync(this.path)
}
this.write = function (path, data) {
console.log('Source', 'Writing ' + path)
fs.writeFile(path, data, (err) => {
if (err) { alert('An error ocurred updating the file' + err.message); console.warn(err) }
})
}
this.export = function () {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to export'); return }
dotgrid.manager.toSVG(grab)
}
this.render = function () {
if (dotgrid.tool.length() < 1) { console.warn('Nothing to render'); return }
dotgrid.manager.toPNG({ width: dotgrid.tool.settings.size.width * 2, height: dotgrid.tool.settings.size.height * 2 }, grab)
}
function grab (base64, name) {
const link = document.createElement('a')
link.setAttribute('href', base64)
link.setAttribute('download', name)
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }))
}
function isJson (text) { try { JSON.parse(text); return true } catch (error) { return false } }
}

View File

@@ -1,8 +1,10 @@
'use strict'
/* global Generator */
function Tool (dotgrid) {
this.index = 0
this.settings = { size: { width: 600, height: 300 }, crest: false }
this.settings = { size: { width: 600, height: 300 } }
this.layers = [[], [], []]
this.styles = [
{ thickness: 10, strokeLinecap: 'round', strokeLinejoin: 'round', color: '#f00', fill: 'none', mirror_style: 0, transform: 'rotate(45)' },
@@ -23,7 +25,6 @@ function Tool (dotgrid) {
}
this.reset = function () {
this.settings.crest = false
this.styles[0].mirror_style = 0
this.styles[1].mirror_style = 0
this.styles[2].mirror_style = 0
@@ -119,7 +120,6 @@ function Tool (dotgrid) {
}
this.selectSegmentAt = function (pos, source = this.layer()) {
const target_segment = null
for (const segmentId in source) {
const segment = source[segmentId]
for (const vertexId in segment.vertices) {
@@ -152,9 +152,9 @@ function Tool (dotgrid) {
}
this.addSegment = function (type, vertices, index = this.index) {
const append_target = this.canAppend({ type: type, vertices: vertices }, index)
if (append_target) {
this.layer(index)[append_target].vertices = this.layer(index)[append_target].vertices.concat(vertices)
const appendTarget = this.canAppend({ type: type, vertices: vertices }, index)
if (appendTarget) {
this.layer(index)[appendTarget].vertices = this.layer(index)[appendTarget].vertices.concat(vertices)
} else {
this.layer(index).push({ type: type, vertices: vertices })
}
@@ -199,24 +199,16 @@ function Tool (dotgrid) {
dotgrid.renderer.update()
}
this.toggleCrest = function () {
this.settings.crest = this.settings.crest !== true
dotgrid.interface.update(true)
dotgrid.renderer.update()
}
this.misc = function (type) {
dotgrid.picker.start()
}
this.source = function (type) {
if (type === 'grid') { dotgrid.renderer.toggle() }
if (type === 'screen') { app.toggleFullscreen() }
if (type === 'open') { dotgrid.source.open() }
if (type === 'save') { dotgrid.source.save() }
if (type === 'render') { dotgrid.source.render() }
if (type === 'export') { dotgrid.source.export() }
if (type === 'open') { dotgrid.source.open('grid', dotgrid.whenOpen) }
if (type === 'save') { dotgrid.source.save('export.grid', dotgrid.tool.export(), 'text/plain') }
if (type === 'export') { dotgrid.source.download('export.svg', dotgrid.manager.toString(), 'image/svg+xml') }
if (type === 'render') { dotgrid.manager.toPNG(dotgrid.tool.settings.size, (dataUrl) => { dotgrid.source.download('export.png', dataUrl, 'image/png') }) }
}
this.canAppend = function (content, index = this.index) {
@@ -353,9 +345,6 @@ function Tool (dotgrid) {
this.selectLayer = function (id) {
this.index = clamp(id, 0, 2)
if (this.index !== 0) { this.settings.crest = false }
this.clear()
dotgrid.renderer.update()
dotgrid.interface.update(true)