Merge branch 'master' into feature/guru-examples
This commit is contained in:
commit
deb80276f5
@ -1,6 +1,8 @@
|
|||||||
# Ronin
|
# Ronin
|
||||||
|
|
||||||
Ronin is a graphic design tool under development.
|
_All I wanted, was a way of resizing photos._
|
||||||
|
|
||||||
|
Ronin is a LISP repl to create generative graphics currently under development. You can follow the daily progress on [Mastodon](https://merveilles.town/@neauoire/). Until we have documented the library, you can find a list of available functions [here](https://github.com/hundredrabbits/Ronin/blob/master/desktop/sources/scripts/library.js).
|
||||||
|
|
||||||
<img src='https://raw.githubusercontent.com/hundredrabbits/Ronin/master/PREVIEW.jpg' width='600'/>
|
<img src='https://raw.githubusercontent.com/hundredrabbits/Ronin/master/PREVIEW.jpg' width='600'/>
|
||||||
|
|
||||||
|
BIN
desktop/icon.png
BIN
desktop/icon.png
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 5.3 KiB |
@ -12,7 +12,7 @@ app.on('ready', () => {
|
|||||||
width: 780,
|
width: 780,
|
||||||
height: 392,
|
height: 392,
|
||||||
minWidth: 380,
|
minWidth: 380,
|
||||||
minHeight: 380,
|
minHeight: 360,
|
||||||
backgroundColor: '#000',
|
backgroundColor: '#000',
|
||||||
icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
|
icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
|
||||||
resizable: true,
|
resizable: true,
|
||||||
|
1788
desktop/package-lock.json
generated
Normal file
1788
desktop/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,17 +4,17 @@
|
|||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
"clean" : "rm -r ~/Desktop/Ronin-darwin-x64/ ; rm -r ~/Desktop/Ronin-linux-x64/ ; rm -r ~/Desktop/Ronin-win32-x64/ ; echo 'cleaned build location'",
|
"clean": "rm -r ~/Desktop/Ronin-darwin-x64/ ; rm -r ~/Desktop/Ronin-linux-x64/ ; rm -r ~/Desktop/Ronin-win32-x64/ ; echo 'cleaned build location'",
|
||||||
"build_osx" : "electron-packager . Ronin --platform=darwin --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.icns ; echo 'Built for OSX'",
|
"build_osx": "electron-packager . Ronin --platform=darwin --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.icns ; echo 'Built for OSX'",
|
||||||
"build_linux" : "electron-packager . Ronin --platform=linux --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'",
|
"build_linux": "electron-packager . Ronin --platform=linux --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'",
|
||||||
"build_win" : "electron-packager . Ronin --platform=win32 --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for WIN'",
|
"build_win": "electron-packager . Ronin --platform=win32 --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for WIN'",
|
||||||
"build" : "npm run clean ; npm run build_osx ; npm run build_linux ; npm run build_win",
|
"build": "npm run clean ; npm run build_osx ; npm run build_linux ; npm run build_win",
|
||||||
"push_osx" : "~/butler push ~/Desktop/Ronin-darwin-x64/ hundredrabbits/ronin:osx-64",
|
"push_osx": "~/butler push ~/Desktop/Ronin-darwin-x64/ hundredrabbits/ronin:osx-64",
|
||||||
"push_linux" : "~/butler push ~/Desktop/Ronin-linux-x64/ hundredrabbits/ronin:linux-64",
|
"push_linux": "~/butler push ~/Desktop/Ronin-linux-x64/ hundredrabbits/ronin:linux-64",
|
||||||
"push_win" : "~/butler push ~/Desktop/Ronin-win32-x64/ hundredrabbits/ronin:windows-64",
|
"push_win": "~/butler push ~/Desktop/Ronin-win32-x64/ hundredrabbits/ronin:windows-64",
|
||||||
"push_theme" : "~/butler push ~/Github/HundredRabbits/Themes/themes/ hundredrabbits/ronin:themes",
|
"push_theme": "~/butler push ~/Github/HundredRabbits/Themes/themes/ hundredrabbits/ronin:themes",
|
||||||
"push_status" : "~/butler status hundredrabbits/ronin",
|
"push_status": "~/butler status hundredrabbits/ronin",
|
||||||
"push" : "npm run build ; npm run push_theme ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run push_status"
|
"push": "npm run build ; npm run push_theme ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run push_status"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^5.0.6",
|
"electron": "^5.0.6",
|
||||||
|
@ -43,10 +43,10 @@
|
|||||||
ronin.controller.add("default","View","Zoom In",() => { ronin.modZoom(0.25) },"CmdOrCtrl+=")
|
ronin.controller.add("default","View","Zoom In",() => { ronin.modZoom(0.25) },"CmdOrCtrl+=")
|
||||||
ronin.controller.add("default","View","Zoom Out",() => { ronin.modZoom(-0.25) },"CmdOrCtrl+-")
|
ronin.controller.add("default","View","Zoom Out",() => { ronin.modZoom(-0.25) },"CmdOrCtrl+-")
|
||||||
ronin.controller.add("default","View","Zoom Reset",() => { ronin.modZoom(1,true) },"CmdOrCtrl+0")
|
ronin.controller.add("default","View","Zoom Reset",() => { ronin.modZoom(1,true) },"CmdOrCtrl+0")
|
||||||
|
ronin.controller.add("default","View","Toggle Commander",() => { ronin.commander.toggle(); },"CmdOrCtrl+K");
|
||||||
ronin.controller.add("default","Project","Run",() => { ronin.commander.run(); },"CmdOrCtrl+R");
|
ronin.controller.add("default","Project","Run",() => { ronin.commander.run(); },"CmdOrCtrl+R");
|
||||||
ronin.controller.add("default","Project","Reload Run",() => { ronin.source.revert(); ronin.commander.run(); },"CmdOrCtrl+Shift+R");
|
ronin.controller.add("default","Project","Reload Run",() => { ronin.source.revert(); ronin.commander.run(); },"CmdOrCtrl+Shift+R");
|
||||||
ronin.controller.add("default","Project", "Toggle Animation (experimental)",() => { ronin.commander.toggleAnimation(); },"CmdOrCtrl+Shift+T");
|
ronin.controller.add("default","Project", "Animate",() => { ronin.animate(!ronin.always); },"CmdOrCtrl+Shift+T");
|
||||||
ronin.controller.add("default","Commander","Toggle",() => { ronin.commander.toggle(); },"CmdOrCtrl+K");
|
|
||||||
ronin.controller.add("default","Theme","Open Theme",() => { ronin.theme.open() },"CmdOrCtrl+Shift+O")
|
ronin.controller.add("default","Theme","Open Theme",() => { ronin.theme.open() },"CmdOrCtrl+Shift+O")
|
||||||
ronin.controller.add("default","Theme","Reset Theme",() => { ronin.theme.reset() },"CmdOrCtrl+Shift+Backspace")
|
ronin.controller.add("default","Theme","Reset Theme",() => { ronin.theme.reset() },"CmdOrCtrl+Shift+Backspace")
|
||||||
ronin.controller.addSpacer('default', 'Theme', 'Download')
|
ronin.controller.addSpacer('default', 'Theme', 'Download')
|
||||||
|
@ -4,12 +4,13 @@ body { margin:0px; padding:0px; overflow:hidden; font-family:"input_mono_regular
|
|||||||
|
|
||||||
#ronin { height: calc(100vh - 60px); width:calc(100vw - 60px); -webkit-app-region: drag; padding: 30px;overflow: hidden; }
|
#ronin { height: calc(100vh - 60px); width:calc(100vw - 60px); -webkit-app-region: drag; padding: 30px;overflow: hidden; }
|
||||||
#ronin #wrapper { overflow: hidden; position: relative; }
|
#ronin #wrapper { overflow: hidden; position: relative; }
|
||||||
#ronin #wrapper #commander { z-index: 9000; position: relative; width: 300px; height: calc(100vh - 60px); border-right: 1px solid #333; -webkit-app-region: no-drag; padding-right: 30px; transition: margin-left 250ms;}
|
#ronin #wrapper #commander { z-index: 9000;position: relative;width: 310px;height: calc(100vh - 60px);-webkit-app-region: no-drag;padding-right: 30px;transition: margin-left 250ms;}
|
||||||
#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 80px); resize: none; font-size: 12px;line-height: 15px; padding-right: 15px}
|
#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 80px); resize: none; font-size: 12px;line-height: 15px; padding-right: 15px}
|
||||||
#ronin #wrapper #commander div#status { position: absolute; bottom: 0px; }
|
#ronin #wrapper #commander div#status { position: absolute; bottom: 0px; }
|
||||||
#ronin.hidden #wrapper #commander { margin-left:-331px; }
|
#ronin.hidden #wrapper #commander { margin-left:-331px; }
|
||||||
|
|
||||||
#ronin canvas#surface,#ronin canvas#guide { position: absolute; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><circle cx='10' cy='10' r='1' fill='%23555'></circle></svg>"); background-size: 10px 10px; background-position: -4px -4px; width:100%; height:100%; left:340px; transition: left 250ms}
|
#ronin canvas#surface,#ronin canvas#guide { position: absolute; top:0px; -webkit-user-select: none;-webkit-app-region: no-drag; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><circle cx='10' cy='10' r='1' fill='%23555'></circle></svg>"); background-size: 10px 10px; background-position: -4px -4px; width:100%; height:100%; left:340px; transition: left 250ms}
|
||||||
#ronin canvas#guide { background:none; }
|
#ronin canvas#guide { background:none; }
|
||||||
|
#ronin canvas#surface { border-radius: 2px }
|
||||||
|
|
||||||
#ronin.hidden canvas#surface, #ronin.hidden canvas#guide { left:0px; }
|
#ronin.hidden canvas#surface, #ronin.hidden canvas#guide { left:0px; }
|
@ -1,5 +1,5 @@
|
|||||||
body { background:var(--background); }
|
body { background:var(--background); }
|
||||||
#ronin #wrapper { background: var(--background); }
|
#ronin #wrapper { background: var(--background); }
|
||||||
#ronin #wrapper #commander { background:var(--background);border-right-color: var(--f_low) }
|
#ronin #wrapper #commander { background:var(--background); }
|
||||||
#ronin #wrapper #commander textarea { color:var(--f_high); }
|
#ronin #wrapper #commander textarea { color:var(--f_high); }
|
||||||
#ronin #wrapper #commander div#status { color:var(--f_med); }
|
#ronin #wrapper #commander div#status { color:var(--f_med); }
|
@ -4,7 +4,7 @@ function Commander (ronin) {
|
|||||||
this._input = document.createElement('textarea')
|
this._input = document.createElement('textarea')
|
||||||
this._status = document.createElement('div')
|
this._status = document.createElement('div')
|
||||||
this._status.id = 'status'
|
this._status.id = 'status'
|
||||||
this.isAnimated = false
|
this.isVisible = true
|
||||||
|
|
||||||
this.install = function (host) {
|
this.install = function (host) {
|
||||||
this.el.appendChild(this._input)
|
this.el.appendChild(this._input)
|
||||||
@ -23,16 +23,9 @@ function Commander (ronin) {
|
|||||||
|
|
||||||
this.run = (txt = this._input.value) => {
|
this.run = (txt = this._input.value) => {
|
||||||
if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return }
|
if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return }
|
||||||
!this.isAnimated && console.log('========')
|
|
||||||
ronin.surface.maximize()
|
|
||||||
const inter = new Lisp(txt, ronin.library)
|
const inter = new Lisp(txt, ronin.library)
|
||||||
inter.toPixels()
|
inter.toPixels()
|
||||||
this.isAnimated && requestAnimationFrame(() => this.run(txt))
|
ronin.always && requestAnimationFrame(() => this.run(txt))
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleAnimation = () => {
|
|
||||||
this.isAnimated = !this.isAnimated
|
|
||||||
this.run(this._input.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.load = function (txt) {
|
this.load = function (txt) {
|
||||||
@ -106,8 +99,14 @@ function Commander (ronin) {
|
|||||||
this.cache = this._input.value
|
this.cache = this._input.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.canInject = function () {
|
||||||
|
return this._input.value.indexOf('$path') > -1
|
||||||
|
}
|
||||||
|
|
||||||
this.injectPath = function (path) {
|
this.injectPath = function (path) {
|
||||||
this._input.value = this._input.value.replace('($path)', `(path "${path}")`)
|
if (this.canInject()) {
|
||||||
|
this._input.value = this._input.value.replace('$path', `"${path}"`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.commit = function () {
|
this.commit = function () {
|
||||||
@ -145,19 +144,19 @@ function Commander (ronin) {
|
|||||||
// Display
|
// Display
|
||||||
|
|
||||||
this.show = function () {
|
this.show = function () {
|
||||||
if (ronin.el.className !== '') {
|
if (this.isVisible === true) { return }
|
||||||
ronin.el.className = ''
|
ronin.el.className = ''
|
||||||
}
|
this.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hide = function () {
|
this.hide = function () {
|
||||||
if (ronin.el.className !== 'hidden') {
|
if (this.isVisible !== true) { return }
|
||||||
ronin.el.className = 'hidden'
|
ronin.el.className = 'hidden'
|
||||||
}
|
this.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggle = function () {
|
this.toggle = function () {
|
||||||
if (ronin.el.className === 'hidden') {
|
if (this.isVisible !== true) {
|
||||||
this.show()
|
this.show()
|
||||||
} else {
|
} else {
|
||||||
this.hide()
|
this.hide()
|
||||||
|
@ -1,55 +1,42 @@
|
|||||||
function Library (ronin) {
|
function Library (ronin) {
|
||||||
this.open = (path, callback) => {
|
this.open = async (path) => {
|
||||||
ronin.surface.open(path, callback)
|
return ronin.surface.open(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.export = (path, type = 'image/png', quality = 1.0) => {
|
||||||
|
if (!path) { console.warn('Missing export path'); return path }
|
||||||
|
var dataUrl = ronin.surface.el.toDataURL(type, quality)
|
||||||
|
const data = dataUrl.replace(/^data:image\/png;base64,/, '')
|
||||||
|
fs.writeFileSync(path, data, 'base64')
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
this.folder = (path = ronin.source.path) => {
|
this.draw = async (path, rect) => {
|
||||||
const a = []
|
|
||||||
if (path) {
|
|
||||||
const folder = ronin.source.folder(path)
|
|
||||||
if (fs.existsSync(folder)) {
|
|
||||||
return fs.readdirSync(folder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
this.save = (path = ronin.source.folder(), type = 'png', quality = 1.0) => {
|
|
||||||
if (!path) { console.warn('Missing save path'); return path }
|
|
||||||
var fullQuality = ronin.surface.el.toDataURL('image/png', quality)
|
|
||||||
const base64Data = url.replace(/^data:image\/png;base64,/, '')
|
|
||||||
fs.writeFile('image.png', base64Data, 'base64', function (err) {
|
|
||||||
console.warn('error', err)
|
|
||||||
})
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
this.draw = (path, rect, callback) => {
|
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.src = path
|
img.src = path
|
||||||
ronin.surface.draw(img, rect, callback)
|
return ronin.surface.draw(img, rect)
|
||||||
return rect
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resize = (w = 1, h = 1, callback) => {
|
this.resize = async (w = 1, h = 1) => {
|
||||||
const rect = w <= 1 || h <= 1 ? { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h } : { x: 0, y: 0, w, h }
|
const rect = w <= 1 || h <= 1 ? { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h } : { x: 0, y: 0, w, h }
|
||||||
const a = document.createElement('img')
|
const a = document.createElement('img')
|
||||||
const b = document.createElement('img')
|
const b = document.createElement('img')
|
||||||
a.src = ronin.surface.el.toDataURL()
|
a.src = ronin.surface.el.toDataURL()
|
||||||
ronin.surface.resizeImage(a, b)
|
ronin.surface.resizeImage(a, b)
|
||||||
ronin.surface.resize(rect, true)
|
ronin.surface.resize(rect, true)
|
||||||
ronin.surface.draw(b, rect, callback)
|
return ronin.surface.draw(b, rect)
|
||||||
return rect
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.crop = (rect, callback) => {
|
this.crop = async (rect) => {
|
||||||
ronin.surface.crop(rect, callback)
|
return ronin.surface.crop(rect)
|
||||||
return rect
|
}
|
||||||
|
|
||||||
|
this.folder = (path = ronin.source.path) => {
|
||||||
|
return fs.existsSync(path) ? fs.readdirSync(path) : []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.exit = () => {
|
this.exit = () => {
|
||||||
// TODO: Closes Ronin
|
ronin.source.quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logic
|
// Logic
|
||||||
@ -66,7 +53,8 @@ function Library (ronin) {
|
|||||||
return a === b
|
return a === b
|
||||||
}
|
}
|
||||||
|
|
||||||
this.and = (...args) => {
|
this.and = (a, b, ...rest) => {
|
||||||
|
let args = [a, b].concat(rest)
|
||||||
for (let i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
if (!args[i]) {
|
if (!args[i]) {
|
||||||
return args[i]
|
return args[i]
|
||||||
@ -75,7 +63,8 @@ function Library (ronin) {
|
|||||||
return args[args.length - 1]
|
return args[args.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
this.or = (...args) => {
|
this.or = (a, b, ...rest) => {
|
||||||
|
let args = [a, b].concat(rest)
|
||||||
for (let i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
if (args[i]) {
|
if (args[i]) {
|
||||||
return args[i]
|
return args[i]
|
||||||
@ -86,13 +75,22 @@ function Library (ronin) {
|
|||||||
|
|
||||||
// Arrays
|
// Arrays
|
||||||
|
|
||||||
this.map = (fn, arr) => {
|
this.map = async (fn, arr) => {
|
||||||
return arr.map(fn)
|
return Promise.all(arr.map(fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.filter = (fn, arr) => {
|
this._filter = (fn, arr) => {
|
||||||
return arr.filter(fn)
|
return arr.filter(fn)
|
||||||
}
|
}
|
||||||
|
this.filter = (fn, arr) => {
|
||||||
|
const list = Array.from(arr)
|
||||||
|
return Promise.all(list.map((element, index) => fn(element, index, list)))
|
||||||
|
.then(result => {
|
||||||
|
return list.filter((_, index) => {
|
||||||
|
return result[index]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.reduce = (fn, arr, acc = 0) => {
|
this.reduce = (fn, arr, acc = 0) => {
|
||||||
return arr.reduce(fn, acc)
|
return arr.reduce(fn, acc)
|
||||||
@ -169,10 +167,6 @@ function Library (ronin) {
|
|||||||
return this.pos(rect.w / 2, rect.h / 2)
|
return this.pos(rect.w / 2, rect.h / 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.path = (path) => {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scale = (rect, w, h) => {
|
this.scale = (rect, w, h) => {
|
||||||
return { x: rect.x, y: rect.y, w: rect.w * w, h: rect.h * h }
|
return { x: rect.x, y: rect.y, w: rect.w * w, h: rect.h * h }
|
||||||
}
|
}
|
||||||
@ -199,7 +193,16 @@ function Library (ronin) {
|
|||||||
return rect
|
return rect
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
this.get = (item, key) => {
|
||||||
|
return item[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set = (item, key, val) => {
|
||||||
|
item[key] = val
|
||||||
|
return item[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should remove (of) for (get)?
|
||||||
|
|
||||||
this.of = (h, ...keys) => {
|
this.of = (h, ...keys) => {
|
||||||
return keys.reduce((acc, key) => {
|
return keys.reduce((acc, key) => {
|
||||||
@ -298,16 +301,10 @@ function Library (ronin) {
|
|||||||
// Generics
|
// Generics
|
||||||
|
|
||||||
this.echo = (...args) => {
|
this.echo = (...args) => {
|
||||||
const msg = args.reduce((acc, val) => { return acc + val + ' ' }, '')
|
ronin.log(args)
|
||||||
ronin.log(msg)
|
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
this.print = (msg) => {
|
|
||||||
ronin.log(msg)
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
this.str = (...args) => {
|
this.str = (...args) => {
|
||||||
return args.reduce((acc, val) => { return acc + val }, '')
|
return args.reduce((acc, val) => { return acc + val }, '')
|
||||||
}
|
}
|
||||||
@ -327,9 +324,11 @@ function Library (ronin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Livecoding
|
// Livecoding
|
||||||
|
|
||||||
this.time = Date.now
|
this.time = Date.now
|
||||||
|
|
||||||
// javascript interop
|
// javascript interop
|
||||||
this.js = window
|
this.js = window
|
||||||
|
|
||||||
|
// Client
|
||||||
|
this.ronin = ronin
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,10 @@ function Lisp (input, lib) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const special = {
|
const special = {
|
||||||
run: (input, context) => {
|
include: (input, context) => {
|
||||||
const file = fs.readFileSync(
|
const p = input[1].value
|
||||||
path.resolve(input[1].value),
|
if (!fs.existsSync(p)) { console.warn('Source', p); return [] }
|
||||||
{ encoding: 'utf-8' })
|
const file = fs.readFileSync(p, { encoding: 'utf-8' })
|
||||||
|
|
||||||
return interpret(this.parse(file), context)
|
return interpret(this.parse(file), context)
|
||||||
},
|
},
|
||||||
let: function (input, context) {
|
let: function (input, context) {
|
||||||
@ -31,7 +30,6 @@ function Lisp (input, lib) {
|
|||||||
acc.scope[x[0].value] = interpret(x[1], context)
|
acc.scope[x[0].value] = interpret(x[1], context)
|
||||||
return acc
|
return acc
|
||||||
}, new Context({}, context))
|
}, new Context({}, context))
|
||||||
|
|
||||||
return interpret(input[2], letContext)
|
return interpret(input[2], letContext)
|
||||||
},
|
},
|
||||||
def: function (input, context) {
|
def: function (input, context) {
|
||||||
@ -52,7 +50,7 @@ function Lisp (input, lib) {
|
|||||||
// docstring
|
// docstring
|
||||||
console.log(input[2].value)
|
console.log(input[2].value)
|
||||||
}
|
}
|
||||||
context.scope[identifier] = function () {
|
context.scope[identifier] = async function () {
|
||||||
const lambdaArguments = arguments
|
const lambdaArguments = arguments
|
||||||
const lambdaScope = argumentNames.reduce(function (acc, x, i) {
|
const lambdaScope = argumentNames.reduce(function (acc, x, i) {
|
||||||
acc[x.value] = lambdaArguments[i]
|
acc[x.value] = lambdaArguments[i]
|
||||||
@ -62,33 +60,32 @@ function Lisp (input, lib) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
lambda: function (input, context) {
|
lambda: function (input, context) {
|
||||||
return function () {
|
return async function () {
|
||||||
const lambdaArguments = arguments
|
const lambdaArguments = arguments
|
||||||
const lambdaScope = input[1].reduce(function (acc, x, i) {
|
const lambdaScope = input[1].reduce(function (acc, x, i) {
|
||||||
acc[x.value] = lambdaArguments[i]
|
acc[x.value] = lambdaArguments[i]
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
return interpret(input[2], new Context(lambdaScope, context))
|
return interpret(input[2], new Context(lambdaScope, context))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
if: function (input, context) {
|
if: async function (input, context) {
|
||||||
if (interpret(input[1], context)) {
|
if (await interpret(input[1], context)) {
|
||||||
return interpret(input[2], context)
|
return interpret(input[2], context)
|
||||||
}
|
}
|
||||||
return input[3] ? interpret(input[3], context) : []
|
return input[3] ? interpret(input[3], context) : []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const interpretList = function (input, context) {
|
const interpretList = async function (input, context) {
|
||||||
if (input.length > 0 && input[0].value in special) {
|
if (input.length > 0 && input[0].value in special) {
|
||||||
return special[input[0].value](input, context)
|
return special[input[0].value](input, context)
|
||||||
}
|
}
|
||||||
const list = input.map(function (x) { return interpret(x, context) })
|
const list = await Promise.all(input.map(function (x) { return interpret(x, context) }))
|
||||||
return list[0] instanceof Function ? list[0].apply(undefined, list.slice(1)) : list
|
return list[0] instanceof Function ? list[0].apply(undefined, list.slice(1)) : list
|
||||||
}
|
}
|
||||||
|
|
||||||
const interpret = function (input, context) {
|
const interpret = async function (input, context) {
|
||||||
if (!input) { console.warn('error', context.scope); return null }
|
if (!input) { console.warn('error', context.scope); return null }
|
||||||
|
|
||||||
if (context === undefined) {
|
if (context === undefined) {
|
||||||
@ -137,7 +134,7 @@ function Lisp (input, lib) {
|
|||||||
return parenthesize(tokenize(input))
|
return parenthesize(tokenize(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toPixels = function () {
|
this.toPixels = async function () {
|
||||||
return interpret(this.parse(input))
|
return interpret(this.parse(input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ function Ronin () {
|
|||||||
this.surface = new Surface(this)
|
this.surface = new Surface(this)
|
||||||
this.library = new Library(this)
|
this.library = new Library(this)
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
|
||||||
|
this.always = false
|
||||||
|
|
||||||
this.install = function (host = document.body) {
|
this.install = function (host = document.body) {
|
||||||
this._wrapper = document.createElement('div')
|
this._wrapper = document.createElement('div')
|
||||||
this._wrapper.id = 'wrapper'
|
this._wrapper.id = 'wrapper'
|
||||||
@ -40,7 +44,6 @@ function Ronin () {
|
|||||||
this.source.start()
|
this.source.start()
|
||||||
this.commander.start()
|
this.commander.start()
|
||||||
this.surface.start()
|
this.surface.start()
|
||||||
|
|
||||||
console.log('Ronin', 'Started')
|
console.log('Ronin', 'Started')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,15 +51,21 @@ function Ronin () {
|
|||||||
this.theme.reset()
|
this.theme.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log = function (msg) {
|
this.log = function (...msg) {
|
||||||
console.log(msg)
|
console.log(...msg)
|
||||||
this.commander.setStatus(msg)
|
this.commander.setStatus(msg.reduce((acc, val) => { return acc + val + ' ' }, ''))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.load = function (content = this.default()) {
|
this.load = function (content = this.default()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.animate = (b = true) => {
|
||||||
|
if (this.always === b) { return }
|
||||||
|
this.always = b
|
||||||
|
this.commander.run()
|
||||||
|
}
|
||||||
|
|
||||||
// Zoom
|
// Zoom
|
||||||
|
|
||||||
this.modZoom = function (mod = 0, set = false) {
|
this.modZoom = function (mod = 0, set = false) {
|
||||||
@ -92,12 +101,12 @@ function Ronin () {
|
|||||||
const file = e.dataTransfer.files[0]
|
const file = e.dataTransfer.files[0]
|
||||||
if (!file || !file.name) { console.warn('File', 'Not a valid file.'); return }
|
if (!file || !file.name) { console.warn('File', 'Not a valid file.'); return }
|
||||||
const path = file.path ? file.path : file.name
|
const path = file.path ? file.path : file.name
|
||||||
if (path.indexOf('.lisp') > -1) {
|
if (this.commander.canInject()) {
|
||||||
this.source.read(path)
|
|
||||||
this.commander.show()
|
|
||||||
} else if (file.path) {
|
|
||||||
this.commander.injectPath(file.path)
|
this.commander.injectPath(file.path)
|
||||||
this.commander.show()
|
this.commander.show()
|
||||||
|
} else if (path.indexOf('.lisp') > -1) {
|
||||||
|
this.source.read(path)
|
||||||
|
this.commander.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ function Source (ronin) {
|
|||||||
this.new = function () {
|
this.new = function () {
|
||||||
console.log('Source', 'Make a new file..')
|
console.log('Source', 'Make a new file..')
|
||||||
this.path = null
|
this.path = null
|
||||||
|
ronin.surface.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.open = function () {
|
this.open = function () {
|
||||||
|
@ -4,7 +4,6 @@ function Surface (ronin) {
|
|||||||
this._guide = document.createElement('canvas')
|
this._guide = document.createElement('canvas')
|
||||||
this._guide.id = 'guide'
|
this._guide.id = 'guide'
|
||||||
this.ratio = window.devicePixelRatio
|
this.ratio = window.devicePixelRatio
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
this.context = this.el.getContext('2d')
|
this.context = this.el.getContext('2d')
|
||||||
this.guide = this.el.getContext('2d')
|
this.guide = this.el.getContext('2d')
|
||||||
@ -22,11 +21,6 @@ function Surface (ronin) {
|
|||||||
|
|
||||||
this.start = function () {
|
this.start = function () {
|
||||||
this.maximize()
|
this.maximize()
|
||||||
console.log('Surface', `Ratio:${this.ratio}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.update = function () {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shape
|
// Shape
|
||||||
@ -112,28 +106,28 @@ function Surface (ronin) {
|
|||||||
|
|
||||||
// IO
|
// IO
|
||||||
|
|
||||||
this.open = function (path, callback = () => {}) {
|
this.open = function (path) {
|
||||||
const img = new Image()
|
return new Promise(resolve => {
|
||||||
img.src = path
|
const img = new Image()
|
||||||
img.onload = () => {
|
img.src = path
|
||||||
ronin.log(`Open ${img.width}x${img.height}`)
|
img.onload = () => {
|
||||||
const rect = { x: 0, y: 0, w: img.width, h: img.height }
|
ronin.log(`Open ${img.width}x${img.height}`)
|
||||||
this.resize(rect, true)
|
const rect = { x: 0, y: 0, w: img.width, h: img.height }
|
||||||
this.context.drawImage(img, 0, 0, img.width, img.height)
|
this.resize(rect, true)
|
||||||
if (typeof callback === 'function') {
|
this.context.drawImage(img, 0, 0, img.width, img.height)
|
||||||
callback()
|
resolve()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.draw = function (img, rect = this.getFrame(), callback = () => {}) {
|
this.draw = function (img, rect = this.getFrame()) {
|
||||||
img.onload = () => {
|
return new Promise(resolve => {
|
||||||
ronin.log(`Draw ${img.width}x${img.height}`)
|
img.onload = () => {
|
||||||
this.context.drawImage(img, rect.x, rect.y, rect.w, rect.h) // no strect: img.height * (rect.w / img.width)
|
ronin.log(`Draw ${img.width}x${img.height}`)
|
||||||
if (typeof callback === 'function') {
|
this.context.drawImage(img, rect.x, rect.y, rect.w, rect.h) // no strect: img.height * (rect.w / img.width)
|
||||||
callback()
|
resolve()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.crop = function (rect) {
|
this.crop = function (rect) {
|
||||||
@ -156,6 +150,7 @@ function Surface (ronin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.resize = function (size, fit = false) {
|
this.resize = function (size, fit = false) {
|
||||||
|
console.log('Surface', `Resize: ${size.w}x${size.h}`)
|
||||||
this.el.width = size.w
|
this.el.width = size.w
|
||||||
this.el.height = size.h
|
this.el.height = size.h
|
||||||
this.el.style.width = size.w + 'px'
|
this.el.style.width = size.w + 'px'
|
||||||
@ -171,7 +166,7 @@ function Surface (ronin) {
|
|||||||
|
|
||||||
this.fitWindow = function (size) {
|
this.fitWindow = function (size) {
|
||||||
const win = require('electron').remote.getCurrentWindow()
|
const win = require('electron').remote.getCurrentWindow()
|
||||||
const pad = { w: 60, h: 60 }
|
const pad = { w: ronin.commander.isVisible === true ? 400 : 60, h: 60 }
|
||||||
win.setSize(size.w + pad.w, size.h + pad.h, false)
|
win.setSize(size.w + pad.w, size.h + pad.h, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
examples/animate.lisp
Normal file
13
examples/animate.lisp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
; animate
|
||||||
|
|
||||||
|
(
|
||||||
|
(def start (get ronin "animate"))
|
||||||
|
|
||||||
|
(def t (sin (div (time) 100)))
|
||||||
|
|
||||||
|
(def pos (add 200 (mul 30 t)))
|
||||||
|
(defn square (a) (rect a a a a))
|
||||||
|
(stroke (square pos) 1 "red")
|
||||||
|
|
||||||
|
(start)
|
||||||
|
)
|
@ -1,10 +0,0 @@
|
|||||||
; animation
|
|
||||||
; click Project > Toggle Animation
|
|
||||||
|
|
||||||
(
|
|
||||||
(def t (sin (div (time) 100)))
|
|
||||||
|
|
||||||
(def pos (add 200 (mul 30 t)))
|
|
||||||
(defn square (a) (rect a a a a))
|
|
||||||
(stroke (square pos) 1 "red")
|
|
||||||
)
|
|
@ -2,15 +2,6 @@
|
|||||||
|
|
||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
|
(open "../static/crystal.jpg")
|
||||||
; Filter
|
(crop (rect 100 100 400 400))
|
||||||
|
|
||||||
(def filter-action
|
|
||||||
(lambda () (crop (rect 100 100 400 400))))
|
|
||||||
|
|
||||||
; Draw photo
|
|
||||||
|
|
||||||
(open
|
|
||||||
"../../PREVIEW.jpg"
|
|
||||||
filter-action)
|
|
||||||
)
|
)
|
@ -3,7 +3,7 @@
|
|||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
|
|
||||||
; Filter
|
; Glitch
|
||||||
|
|
||||||
(defn glitch
|
(defn glitch
|
||||||
(rec)
|
(rec)
|
||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
(draw
|
(draw
|
||||||
"../static/crystal.jpg"
|
"../static/crystal.jpg"
|
||||||
(rect 0 0 400 400)
|
(rect 0 0 400 400))
|
||||||
(lambda () (glitch 2000)))
|
|
||||||
|
(glitch 500)
|
||||||
)
|
)
|
@ -1,5 +0,0 @@
|
|||||||
; load file
|
|
||||||
|
|
||||||
((clear)
|
|
||||||
(print (folder))
|
|
||||||
)
|
|
@ -1,13 +1,9 @@
|
|||||||
; scale file
|
; scale file
|
||||||
(
|
(
|
||||||
; Filter
|
|
||||||
|
|
||||||
(def filter-action
|
(open "../static/crystal.jpg")
|
||||||
(lambda () (pixels
|
(pixels
|
||||||
(frame)
|
(frame)
|
||||||
saturation
|
saturation
|
||||||
0.5)
|
12)
|
||||||
))
|
|
||||||
|
|
||||||
(open (path "/Users/VillaMoirai/Desktop/clip.jpg") filter-action)
|
|
||||||
)
|
)
|
@ -2,20 +2,11 @@
|
|||||||
|
|
||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
|
|
||||||
; Filter
|
|
||||||
|
|
||||||
(def filter-action
|
|
||||||
(lambda () (pixels
|
|
||||||
(rect 0 0 500 500)
|
|
||||||
saturation
|
|
||||||
0.5)
|
|
||||||
))
|
|
||||||
|
|
||||||
; Draw photo
|
|
||||||
|
|
||||||
(draw
|
(draw
|
||||||
"../../PREVIEW.jpg"
|
"../../PREVIEW.jpg"
|
||||||
(frame)
|
(frame))
|
||||||
filter-action)
|
(pixels
|
||||||
|
(rect 0 0 500 500)
|
||||||
|
saturation
|
||||||
|
0.5)
|
||||||
)
|
)
|
@ -6,15 +6,16 @@
|
|||||||
(defn place
|
(defn place
|
||||||
(rec)
|
(rec)
|
||||||
(if (gt rec 0)
|
(if (gt rec 0)
|
||||||
((draw "../static/crystal.jpg"
|
(
|
||||||
(rect
|
(draw "../static/crystal.jpg"
|
||||||
(random 200)
|
(rect
|
||||||
(random 200)
|
(random 200)
|
||||||
(random 200)
|
(random 200)
|
||||||
(random 200))
|
(random 200)
|
||||||
(lambda () (place (sub rec 1)))
|
(random 200)))
|
||||||
)))
|
(place (sub rec 1))
|
||||||
)
|
))
|
||||||
|
)
|
||||||
|
|
||||||
(place 30)
|
(place 30)
|
||||||
)
|
)
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
|
(def line-color "red")
|
||||||
(defn rec
|
(defn rec
|
||||||
(v)
|
(v)
|
||||||
(if (gt v 0)
|
(if (gt v 0)
|
||||||
((stroke (circle
|
((stroke (circle
|
||||||
(mul 5 v)
|
(mul 5 v)
|
||||||
(mul 5 v)
|
(mul 5 v)
|
||||||
(mul 5 v)) 1 "red")
|
(mul 5 v)) 1 line-color)
|
||||||
(rec (sub v 5))))
|
(rec (sub v 5))))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,15 +2,6 @@
|
|||||||
|
|
||||||
(
|
(
|
||||||
(clear)
|
(clear)
|
||||||
|
(open "../../PREVIEW.jpg")
|
||||||
; Filter
|
(resize 0.5 0.5)
|
||||||
|
|
||||||
(def filter-action
|
|
||||||
(lambda () (resize 0.5 0.5)))
|
|
||||||
|
|
||||||
; Draw photo
|
|
||||||
|
|
||||||
(open
|
|
||||||
"../../PREVIEW.jpg"
|
|
||||||
filter-action)
|
|
||||||
)
|
)
|
@ -1,5 +1,4 @@
|
|||||||
(
|
(
|
||||||
(run "../examples/recursive.lisp")
|
(include "../examples/recursive.lisp")
|
||||||
(echo value)
|
(echo line-color)
|
||||||
(echo (addOne value))
|
|
||||||
)
|
)
|
Loading…
x
Reference in New Issue
Block a user