Merge branch 'master' into convolution
This commit is contained in:
		
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
								
							| @@ -25,6 +25,8 @@ npm start | |||||||
|  |  | ||||||
| ## Library | ## Library | ||||||
|  |  | ||||||
|  | Additional functions can be found in the [includes](https://github.com/hundredrabbits/Ronin/tree/master/desktop/sources/lisp), you can also look at the [examples](https://github.com/hundredrabbits/Ronin/tree/master/examples) to see them in action. | ||||||
|  |  | ||||||
| - `(import path rect)` Imports a graphic file with format. | - `(import path rect)` Imports a graphic file with format. | ||||||
| - `(export path ~format ~quality)` Exports a graphic file with format. | - `(export path ~format ~quality)` Exports a graphic file with format. | ||||||
| - `(open path)` Imports a graphic file and resizes the frame. | - `(open path)` Imports a graphic file and resizes the frame. | ||||||
| @@ -38,6 +40,17 @@ npm start | |||||||
| - `(stroke ~shape)` Strokes a shape. | - `(stroke ~shape)` Strokes a shape. | ||||||
| - `(fill ~rect)` Fills a shape. | - `(fill ~rect)` Fills a shape. | ||||||
| - `(clear ~rect)` Clears a rect. | - `(clear ~rect)` Clears a rect. | ||||||
|  | - `(frame)` Returns a rect of the frame. | ||||||
|  | - `(center)` Returns a position of the center of the frame. | ||||||
|  | - `(resize w h ~fit)` Resizes the canvas to target w and h, returns the rect. | ||||||
|  | - `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect. | ||||||
|  | - `(crop rect)` Crop canvas to rect. | ||||||
|  | - `(clone a b)`  | ||||||
|  | - `(theme variable ~el)`  | ||||||
|  | - `(gradient [x1 y1 x2 y2] ~colors 'black'])`  | ||||||
|  | - `(pixels rect fn q)`  | ||||||
|  | - `(saturation pixel ~q)`  | ||||||
|  | - `(contrast pixel ~q)`  | ||||||
| - `(concat ...items)` Concat multiple strings. | - `(concat ...items)` Concat multiple strings. | ||||||
| - `(add ...args)` Adds values. | - `(add ...args)` Adds values. | ||||||
| - `(sub ...args)` Subtracts values. | - `(sub ...args)` Subtracts values. | ||||||
| @@ -71,17 +84,8 @@ npm start | |||||||
| - `(get item key)` Gets an object's parameter with name. | - `(get item key)` Gets an object's parameter with name. | ||||||
| - `(set item key val)` Sets an object's parameter with name as value. | - `(set item key val)` Sets an object's parameter with name as value. | ||||||
| - `(of h ...keys)` Gets object parameters with names. | - `(of h ...keys)` Gets object parameters with names. | ||||||
| - `(frame)` Returns a rect of the frame. | - `(keys item)` Returns a list of the object's keys | ||||||
| - `(center)` Returns a position of the center of the frame. | - `(values item)` Returns a list of the object's values | ||||||
| - `(resize w h ~fit)` Resizes the canvas to target w and h, returns the rect. |  | ||||||
| - `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect. |  | ||||||
| - `(crop rect)` Crop canvas to rect. |  | ||||||
| - `(clone a b)`  |  | ||||||
| - `(theme variable ~el)`  |  | ||||||
| - `(gradient [x1 y1 x2 y2] ~colors 'black'])`  |  | ||||||
| - `(pixels rect fn q)`  |  | ||||||
| - `(saturation pixel ~q)`  |  | ||||||
| - `(contrast pixel ~q)`  |  | ||||||
| - `(dir ~path)` Returns the content of a directory. | - `(dir ~path)` Returns the content of a directory. | ||||||
| - `(file ~path)` Returns the content of a file. | - `(file ~path)` Returns the content of a file. | ||||||
| - `(dirpath ~path)` Returns the path of a directory. | - `(dirpath ~path)` Returns the path of a directory. | ||||||
| @@ -93,6 +97,7 @@ npm start | |||||||
| - `(js)` Javascript interop. | - `(js)` Javascript interop. | ||||||
| - `(test name a b)`  | - `(test name a b)`  | ||||||
| - `(benchmark fn)` logs time taken to execute a function. | - `(benchmark fn)` logs time taken to execute a function. | ||||||
|  | - `(osc ~address)` returns the last received osc msg on port 12940 | ||||||
|  |  | ||||||
| ## Extras | ## Extras | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| const { app, BrowserWindow, webFrame, Menu } = require('electron') | const { app, BrowserWindow, webFrame, Menu } = require('electron') | ||||||
| const path = require('path') | const path = require('path') | ||||||
| const url = require('url') | const url = require('url') | ||||||
|  | const osc = require('osc') | ||||||
| const shell = require('electron').shell | const shell = require('electron').shell | ||||||
|  |  | ||||||
| let isShown = true | let isShown = true | ||||||
|   | |||||||
							
								
								
									
										1262
									
								
								desktop/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1262
									
								
								desktop/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -4,6 +4,7 @@ | |||||||
|   "main": "main.js", |   "main": "main.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "start": "electron .", |     "start": "electron .", | ||||||
|  |     "install": "electron-rebuild", | ||||||
|     "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'", | ||||||
| @@ -16,8 +17,12 @@ | |||||||
|     "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" | ||||||
|   }, |   }, | ||||||
|  |   "dependencies": { | ||||||
|  |     "osc": "^2.3.1" | ||||||
|  |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "electron": "^5.0.6", |     "electron": "^5.0.6", | ||||||
|     "electron-packager": "^13.1.1" |     "electron-packager": "^13.1.1", | ||||||
|  |     "electron-rebuild": "^1.8.5" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
|     <script type="text/javascript" src="scripts/surface.js"></script> |     <script type="text/javascript" src="scripts/surface.js"></script> | ||||||
|     <script type="text/javascript" src="scripts/lisp.js"></script> |     <script type="text/javascript" src="scripts/lisp.js"></script> | ||||||
|     <script type="text/javascript" src="scripts/library.js"></script> |     <script type="text/javascript" src="scripts/library.js"></script> | ||||||
|  |     <script type="text/javascript" src="scripts/osc.js"></script> | ||||||
|  |  | ||||||
|     <link rel="stylesheet" type="text/css" href="links/reset.css"/> |     <link rel="stylesheet" type="text/css" href="links/reset.css"/> | ||||||
|     <link rel="stylesheet" type="text/css" href="links/fonts.css"/> |     <link rel="stylesheet" type="text/css" href="links/fonts.css"/> | ||||||
|     <link rel="stylesheet" type="text/css" href="links/main.css"/> |     <link rel="stylesheet" type="text/css" href="links/main.css"/> | ||||||
| @@ -18,10 +20,10 @@ | |||||||
|   <body> |   <body> | ||||||
|     <script type="text/javascript"> |     <script type="text/javascript"> | ||||||
|       const {dialog,app} = require('electron').remote; |       const {dialog,app} = require('electron').remote; | ||||||
|       const fs = require('fs'); |       const fs = require('fs') | ||||||
|       const app_path = app.getAppPath(); |       const ronin = new Ronin() | ||||||
|       const ronin = new Ronin(); |  | ||||||
|       ronin.controller = new Controller(); |       ronin.controller = new Controller() | ||||||
|       ronin.controller.add("default","*","About",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Dotgrid'); },"CmdOrCtrl+,"); |       ronin.controller.add("default","*","About",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Dotgrid'); },"CmdOrCtrl+,"); | ||||||
|       ronin.controller.add("default","*","Fullscreen",() => { app.toggleFullscreen() },"CmdOrCtrl+Enter"); |       ronin.controller.add("default","*","Fullscreen",() => { app.toggleFullscreen() },"CmdOrCtrl+Enter"); | ||||||
|       ronin.controller.add("default","*","Hide",() => { app.toggleVisible() },"CmdOrCtrl+H"); |       ronin.controller.add("default","*","Hide",() => { app.toggleVisible() },"CmdOrCtrl+H"); | ||||||
| @@ -53,9 +55,10 @@ | |||||||
|       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') | ||||||
|       ronin.controller.add("default","Theme","Download Themes..",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') }) |       ronin.controller.add("default","Theme","Download Themes..",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') }) | ||||||
|       ronin.controller.commit(); |       ronin.controller.commit() | ||||||
|       ronin.install(document.body); |  | ||||||
|       window.addEventListener('load', () => { ronin.start(); }) |       ronin.install(document.body) | ||||||
|  |       window.addEventListener('load', () => { ronin.start() }) | ||||||
|     </script> |     </script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -14,4 +14,4 @@ body { margin:0px; padding:0px; overflow:hidden; font-family:"input_mono_regular | |||||||
| #ronin canvas#guide { background:none; } | #ronin canvas#guide { background:none; } | ||||||
| #ronin canvas#surface { border-radius: 2px } | #ronin canvas#surface { border-radius: 2px } | ||||||
|  |  | ||||||
| #ronin.hidden canvas#surface, #ronin.hidden canvas#guide { left:10px; } | #ronin.hidden canvas#surface, #ronin.hidden canvas#guide { left:0px; } | ||||||
							
								
								
									
										34
									
								
								desktop/sources/lisp/prelude.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								desktop/sources/lisp/prelude.lisp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | ;  | ||||||
|  | (echo "Loading prelude.lisp") | ||||||
|  | ; translate | ||||||
|  | (defn translate  | ||||||
|  |   (r p)  | ||||||
|  |   (clone r  | ||||||
|  |     (rect  | ||||||
|  |       (of p :x)  | ||||||
|  |       (of p :y)  | ||||||
|  |       (of r :w)  | ||||||
|  |       (of r :h)))) | ||||||
|  | ; times | ||||||
|  | (defn times  | ||||||
|  |   (v f)  | ||||||
|  |   ( | ||||||
|  |     (f v)  | ||||||
|  |     (if  | ||||||
|  |       (gt v 1)  | ||||||
|  |       (times  | ||||||
|  |         (sub v 1) f)))) | ||||||
|  | ; convert deg to radians | ||||||
|  | (defn deg-rad  | ||||||
|  |   (deg)  | ||||||
|  |   (mul deg  | ||||||
|  |     (div PI 180))) | ||||||
|  | ; position on a circle from angle | ||||||
|  | (defn circle-pos  | ||||||
|  |   (cx cy r a) {:x  | ||||||
|  |   (add cx  | ||||||
|  |     (mul r  | ||||||
|  |       (cos a))) :y  | ||||||
|  |   (add cy  | ||||||
|  |     (mul r  | ||||||
|  |       (sin a)))}) | ||||||
| @@ -31,11 +31,21 @@ function Commander (ronin) { | |||||||
|     this.hide() |     this.hide() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   this.cache = '' | ||||||
|  |  | ||||||
|   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 } | ||||||
|     const inter = new Lisp(txt, ronin.library) |     this.cache = txt | ||||||
|     inter.toPixels() |     if (ronin.always !== true) { | ||||||
|     ronin.always === true && requestAnimationFrame(() => this.run(txt)) |       ronin.surface.maximize() | ||||||
|  |       ronin.interpreter.run(this.cache) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.loop = () => { | ||||||
|  |     ronin.surface.maximize() | ||||||
|  |     ronin.interpreter.run(this.cache) | ||||||
|  |     ronin.always === true && requestAnimationFrame(() => this.loop()) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.load = function (txt) { |   this.load = function (txt) { | ||||||
| @@ -47,6 +57,10 @@ function Commander (ronin) { | |||||||
|   this.reindent = function () { |   this.reindent = function () { | ||||||
|     let val = this._input.value.replace(/\n/g, '').replace(/ +(?= )/g, '').replace(/\( \(/g, '((').replace(/\) \)/g, '))').trim() |     let val = this._input.value.replace(/\n/g, '').replace(/ +(?= )/g, '').replace(/\( \(/g, '((').replace(/\) \)/g, '))').trim() | ||||||
|     let depth = 0 |     let depth = 0 | ||||||
|  |     if (val.split('(').length !== val.split(')').length) { | ||||||
|  |       ronin.log('Uneven number of parens.') | ||||||
|  |       return | ||||||
|  |     } | ||||||
|     for (let i = 0; i < val.length; i++) { |     for (let i = 0; i < val.length; i++) { | ||||||
|       const c = val.charAt(i) |       const c = val.charAt(i) | ||||||
|       if (c === '(') { depth++ } else if (c === ')') { depth-- } |       if (c === '(') { depth++ } else if (c === ')') { depth-- } | ||||||
| @@ -68,7 +82,7 @@ function Commander (ronin) { | |||||||
|     // Logs |     // Logs | ||||||
|     if (msg && msg !== this._log.textContent) { |     if (msg && msg !== this._log.textContent) { | ||||||
|       this._log.textContent = `${msg}` |       this._log.textContent = `${msg}` | ||||||
|       console.log(msg) |       // console.log(msg) | ||||||
|     } |     } | ||||||
|     // Source |     // Source | ||||||
|     const _source = `${ronin.source} ${this._input.value.split('\n').length} lines` |     const _source = `${ronin.source} ${this._input.value.split('\n').length} lines` | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ function Library (ronin) { | |||||||
|  |  | ||||||
|   this.export = (path, format = 'image/png', quality = 1.0) => { // Exports a graphic file with format. |   this.export = (path, format = 'image/png', quality = 1.0) => { // Exports a graphic file with format. | ||||||
|     if (!path) { console.warn('Missing export path'); return path } |     if (!path) { console.warn('Missing export path'); return path } | ||||||
|     var dataUrl = ronin.surface.el.toDataURL(format, quality) |     const dataUrl = ronin.surface.el.toDataURL(format, quality) | ||||||
|     const data = dataUrl.replace(/^data:image\/png;base64,/, '').replace(/^data:image\/jpeg;base64,/, '') |     const data = dataUrl.replace(/^data:image\/png;base64,/, '').replace(/^data:image\/jpeg;base64,/, '') | ||||||
|     fs.writeFileSync(path, data, 'base64') |     fs.writeFileSync(path, data, 'base64') | ||||||
|     return path |     return path | ||||||
| @@ -31,8 +31,8 @@ function Library (ronin) { | |||||||
|     return { x, y, w, h, t } |     return { x, y, w, h, t } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.circle = (x, y, r, t = 'circle') => { // Returns a circle shape. |   this.circle = (cx, cy, r, t = 'circle') => { // Returns a circle shape. | ||||||
|     return { x, y, r, t } |     return { cx, cy, r, t } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.line = (a, b, t = 'line') => { // Returns a line shape. |   this.line = (a, b, t = 'line') => { // Returns a line shape. | ||||||
| @@ -64,6 +64,83 @@ function Library (ronin) { | |||||||
|     return rect |     return rect | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Frame | ||||||
|  |  | ||||||
|  |   this.frame = () => { // Returns a rect of the frame. | ||||||
|  |     return ronin.surface.getFrame() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.center = () => { // Returns a position of the center of the frame. | ||||||
|  |     const rect = this.frame() | ||||||
|  |     return this.pos(rect.w / 2, rect.h / 2) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.resize = async (w, h, fit = true) => { // Resizes the canvas to target w and h, returns the rect. | ||||||
|  |     const rect = { x: 0, y: 0, w, h } | ||||||
|  |     const a = document.createElement('img') | ||||||
|  |     const b = document.createElement('img') | ||||||
|  |     a.src = ronin.surface.el.toDataURL() | ||||||
|  |     await ronin.surface.resizeImage(a, b) | ||||||
|  |     ronin.surface.resize(rect, fit) | ||||||
|  |     return ronin.surface.draw(b, rect) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.rescale = async (w, h) => { // Rescales the canvas to target ratio of w and h, returns the rect. | ||||||
|  |     const rect = { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h } | ||||||
|  |     const a = document.createElement('img') | ||||||
|  |     const b = document.createElement('img') | ||||||
|  |     a.src = ronin.surface.el.toDataURL() | ||||||
|  |     await ronin.surface.resizeImage(a, b) | ||||||
|  |     ronin.surface.resize(rect, true) | ||||||
|  |     return ronin.surface.draw(b, rect) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.crop = async (rect) => { // Crop canvas to rect. | ||||||
|  |     return ronin.surface.crop(rect) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.clone = (a, b) => { | ||||||
|  |     ronin.surface.clone(a, b) | ||||||
|  |     return [a, b] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.theme = (variable, el = document.documentElement) => { | ||||||
|  |     // ex. (theme "f_main") -> :root { --f_main: "#fff" } | ||||||
|  |     return getComputedStyle(el).getPropertyValue(`--${variable}`) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Gradients | ||||||
|  |  | ||||||
|  |   this.gradient = ([x1, y1, x2, y2], colors = ['white', 'black']) => { | ||||||
|  |     return ronin.surface.linearGradient(x1, y1, x2, y2, colors) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Pixels | ||||||
|  |  | ||||||
|  |   this.pixels = (rect, fn, q) => { | ||||||
|  |     const img = ronin.surface.context.getImageData(0, 0, rect.w, rect.h) | ||||||
|  |     for (let i = 0, loop = img.data.length; i < loop; i += 4) { | ||||||
|  |       const pixel = { r: img.data[i], g: img.data[i + 1], b: img.data[i + 2], a: img.data[i + 3] } | ||||||
|  |       const processed = fn(pixel, q) | ||||||
|  |       img.data[i] = processed[0] | ||||||
|  |       img.data[i + 1] = processed[1] | ||||||
|  |       img.data[i + 2] = processed[2] | ||||||
|  |       img.data[i + 3] = processed[3] | ||||||
|  |     } | ||||||
|  |     ronin.surface.context.putImageData(img, 0, 0) | ||||||
|  |     return rect | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.saturation = (pixel, q = 1) => { | ||||||
|  |     const color = 0.2126 * pixel.r + 0.7152 * pixel.g + 0.0722 * pixel.b | ||||||
|  |     return [(color * (1 - q)) + (pixel.r * q), (color * (1 - q)) + (pixel.g * q), (color * (1 - q)) + (pixel.b * q), pixel.a] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.contrast = (pixel, q = 1) => { | ||||||
|  |     const intercept = 128 * (1 - q) | ||||||
|  |     return [pixel.r * q + intercept, pixel.g * q + intercept, pixel.b * q + intercept, pixel.a] | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Strings |   // Strings | ||||||
|  |  | ||||||
|   this.concat = function (...items) { // Concat multiple strings. |   this.concat = function (...items) { // Concat multiple strings. | ||||||
| @@ -233,78 +310,12 @@ function Library (ronin) { | |||||||
|     }, h) |     }, h) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Frame |   this.keys = (item) => { // Returns a list of the object's keys | ||||||
|  |     return Object.keys(item) | ||||||
|   this.frame = () => { // Returns a rect of the frame. |  | ||||||
|     return ronin.surface.getFrame() |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.center = () => { // Returns a position of the center of the frame. |   this.values = (item) => { // Returns a list of the object's values | ||||||
|     const rect = this.frame() |     return Object.values(item) | ||||||
|     return this.pos(rect.w / 2, rect.h / 2) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.resize = async (w, h, fit = true) => { // Resizes the canvas to target w and h, returns the rect. |  | ||||||
|     const rect = { x: 0, y: 0, w, h } |  | ||||||
|     const a = document.createElement('img') |  | ||||||
|     const b = document.createElement('img') |  | ||||||
|     a.src = ronin.surface.el.toDataURL() |  | ||||||
|     await ronin.surface.resizeImage(a, b) |  | ||||||
|     ronin.surface.resize(rect, fit) |  | ||||||
|     return ronin.surface.draw(b, rect) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.rescale = async (w, h) => { // Rescales the canvas to target ratio of w and h, returns the rect. |  | ||||||
|     const rect = { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h } |  | ||||||
|     const a = document.createElement('img') |  | ||||||
|     const b = document.createElement('img') |  | ||||||
|     a.src = ronin.surface.el.toDataURL() |  | ||||||
|     await ronin.surface.resizeImage(a, b) |  | ||||||
|     ronin.surface.resize(rect, true) |  | ||||||
|     return ronin.surface.draw(b, rect) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.crop = async (rect) => { // Crop canvas to rect. |  | ||||||
|     return ronin.surface.crop(rect) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.clone = (a, b) => { |  | ||||||
|     ronin.surface.clone(a, b) |  | ||||||
|     return [a, b] |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.theme = (variable, el = document.documentElement) => { |  | ||||||
|     // ex. (theme "f_main") -> :root { --f_main: "#fff" } |  | ||||||
|     return getComputedStyle(el).getPropertyValue(`--${variable}`) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Gradients |  | ||||||
|  |  | ||||||
|   this.gradient = ([x1, y1, x2, y2], colors = ['white', 'black']) => { |  | ||||||
|     return ronin.surface.linearGradient(x1, y1, x2, y2, colors) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Pixels |  | ||||||
|  |  | ||||||
|   this.pixels = (rect, fn, q) => { |  | ||||||
|     const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h) |  | ||||||
|     for (let i = 0, loop = img.data.length; i < loop; i += 4) { |  | ||||||
|       const pixel = { r: img.data[i], g: img.data[i + 1], b: img.data[i + 2], a: img.data[i + 3] } |  | ||||||
|       const processed = fn(pixel, q) |  | ||||||
|       img.data.set(processed, i); |  | ||||||
|     } |  | ||||||
|     ronin.surface.context.putImageData(img, rect.x, rect.y) |  | ||||||
|     return rect |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.saturation = (pixel, q = 1) => { |  | ||||||
|     const color = 0.2126 * pixel.r + 0.7152 * pixel.g + 0.0722 * pixel.b * (1 - q) |  | ||||||
|     return [color + (pixel.r * q), color + (pixel.g * q), color + (pixel.b * q), pixel.a] |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this.contrast = (pixel, q = 1) => { |  | ||||||
|     const intercept = 128 * (1 - q) |  | ||||||
|     return [pixel.r * q + intercept, pixel.g * q + intercept, pixel.b * q + intercept, pixel.a] |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Convolve |   // Convolve | ||||||
| @@ -370,6 +381,16 @@ function Library (ronin) { | |||||||
|     return args |     return args | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   this.table = (arg) => { | ||||||
|  |     console.table(arg) | ||||||
|  |     return arg | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.debug = (arg) => { | ||||||
|  |     console.log(arg) | ||||||
|  |     return arg | ||||||
|  |   } | ||||||
|  |  | ||||||
|   this.time = (rate = 1) => { // Returns timestamp in milliseconds. |   this.time = (rate = 1) => { // Returns timestamp in milliseconds. | ||||||
|     return (Date.now() * rate) |     return (Date.now() * rate) | ||||||
|   } |   } | ||||||
| @@ -397,4 +418,10 @@ function Library (ronin) { | |||||||
|     console.log(`time taken: ${Date.now() - start}ms`) |     console.log(`time taken: ${Date.now() - start}ms`) | ||||||
|     return result |     return result | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // IO | ||||||
|  |  | ||||||
|  |   this.osc = (path) => { // Returns the latest osc message at path | ||||||
|  |     return path ? ronin.osc.msg[path] : ronin.osc.msg | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| 'use strict' | 'use strict' | ||||||
|  |  | ||||||
| function Lisp (input, lib) { | function Lisp (lib = {}, includes = []) { | ||||||
|   const path = require('path') |   const path = require('path') | ||||||
|   const fs = require('fs') |   const fs = require('fs') | ||||||
|  |  | ||||||
|   const TYPES = { identifier: 0, number: 1, string: 2, bool: 3 } |   const TYPES = { identifier: 0, number: 1, string: 2, bool: 3 } | ||||||
|  |  | ||||||
|   const Context = function (scope, parent) { |   const Context = function (scope, parent) { | ||||||
|     this.scope = scope |     this.scope = scope | ||||||
|     this.parent = parent |     this.parent = parent | ||||||
|  |  | ||||||
|     this.get = function (identifier) { |     this.get = function (identifier) { | ||||||
|       if (identifier in this.scope) { |       if (identifier in this.scope) { | ||||||
|         return this.scope[identifier] |         return this.scope[identifier] | ||||||
| @@ -20,9 +20,9 @@ function Lisp (input, lib) { | |||||||
|  |  | ||||||
|   const special = { |   const special = { | ||||||
|     include: (input, context) => { |     include: (input, context) => { | ||||||
|       if (!input[1].value || !fs.existsSync(input[1].value)) { console.warn('Source', input[1].value); return [] } |       if (!input[1].value || !fs.existsSync(input[1].value)) { console.warn('Lisp', 'No file: ' + input[1].value); return [] } | ||||||
|       const file = fs.readFileSync(input[1].value, { encoding: 'utf-8' }) |       const file = fs.readFileSync(input[1].value, { encoding: 'utf-8' }) | ||||||
|       return interpret(this.parse(file), context) |       return interpret(this.parse(`(${file})`), context) | ||||||
|     }, |     }, | ||||||
|     let: function (input, context) { |     let: function (input, context) { | ||||||
|       const letContext = input[1].reduce(function (acc, x) { |       const letContext = input[1].reduce(function (acc, x) { | ||||||
| @@ -60,21 +60,32 @@ function Lisp (input, lib) { | |||||||
|         return interpret(input[2], new Context(lambdaScope, context)) |         return interpret(input[2], new Context(lambdaScope, context)) | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     __fn: function (input, context) { |  | ||||||
|       return async function () { |  | ||||||
|         const lambdaArguments = arguments |  | ||||||
|         const lambdaScope = [].reduce(function (acc, x, i) { |  | ||||||
|           acc[x.value] = lambdaArguments[i] |  | ||||||
|           return acc |  | ||||||
|         }, {}) |  | ||||||
|         return interpret(input.slice(1), new Context(lambdaScope, context)) |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     if: async function (input, context) { |     if: async function (input, context) { | ||||||
|       if (await 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) : [] | ||||||
|  |     }, | ||||||
|  |     __fn: function (input, context) { | ||||||
|  |       return async function () { | ||||||
|  |         const lambdaArguments = arguments | ||||||
|  |         const keys = [...new Set(input.slice(2).flat(100).filter(i => | ||||||
|  |           i.type === TYPES.identifier && | ||||||
|  |           i.value[0] === '%' | ||||||
|  |         ).map(x => x.value).sort())] | ||||||
|  |         const lambdaScope = keys.reduce(function (acc, x, i) { | ||||||
|  |           acc[x] = lambdaArguments[i] | ||||||
|  |           return acc | ||||||
|  |         }, {}) | ||||||
|  |         return interpret(input.slice(1), new Context(lambdaScope, context)) | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     __obj: async function (input, context) { | ||||||
|  |       const obj = {} | ||||||
|  |       for (let i = 1; i < input.length; i += 2) { | ||||||
|  |         obj[await interpret(input[i], context)] = await interpret(input[i + 1], context) | ||||||
|  |       } | ||||||
|  |       return obj | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -90,7 +101,7 @@ function Lisp (input, lib) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   const interpret = async function (input, context) { |   const interpret = async function (input, context) { | ||||||
|     if (!input) { console.warn('error', context.scope); return null } |     if (!input) { console.warn('Lisp', 'error', context.scope); return null } | ||||||
|  |  | ||||||
|     if (context === undefined) { |     if (context === undefined) { | ||||||
|       return interpret(input, new Context(lib)) |       return interpret(input, new Context(lib)) | ||||||
| @@ -108,6 +119,8 @@ function Lisp (input, lib) { | |||||||
|       return { type: TYPES.number, value: parseFloat(input) } |       return { type: TYPES.number, value: parseFloat(input) } | ||||||
|     } else if (input[0] === '"' && input.slice(-1) === '"') { |     } else if (input[0] === '"' && input.slice(-1) === '"') { | ||||||
|       return { type: TYPES.string, value: input.slice(1, -1) } |       return { type: TYPES.string, value: input.slice(1, -1) } | ||||||
|  |     } else if (input[0] === ':') { | ||||||
|  |       return { type: TYPES.string, value: input.slice(1) } | ||||||
|     } else if (input === 'true' || input === 'false') { |     } else if (input === 'true' || input === 'false') { | ||||||
|       return { type: TYPES.bool, value: input === 'true' } |       return { type: TYPES.bool, value: input === 'true' } | ||||||
|     } else { |     } else { | ||||||
| @@ -124,10 +137,14 @@ function Lisp (input, lib) { | |||||||
|       input.unshift('__fn') |       input.unshift('__fn') | ||||||
|       list.push(parenthesize(input, [])) |       list.push(parenthesize(input, [])) | ||||||
|       return parenthesize(input, list) |       return parenthesize(input, list) | ||||||
|  |     } else if (token === '{') { | ||||||
|  |       input.unshift('__obj') | ||||||
|  |       list.push(parenthesize(input, [])) | ||||||
|  |       return parenthesize(input, list) | ||||||
|     } else if (token === '(') { |     } else if (token === '(') { | ||||||
|       list.push(parenthesize(input, [])) |       list.push(parenthesize(input, [])) | ||||||
|       return parenthesize(input, list) |       return parenthesize(input, list) | ||||||
|     } else if (token === ')') { |     } else if (token === ')' || token === '}') { | ||||||
|       return list |       return list | ||||||
|     } else { |     } else { | ||||||
|       return parenthesize(input, list.concat(categorize(token))) |       return parenthesize(input, list.concat(categorize(token))) | ||||||
| @@ -135,21 +152,35 @@ function Lisp (input, lib) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   const tokenize = function (input) { |   const tokenize = function (input) { | ||||||
|     const i = input.replace(/^\;.*\n?/gm, '').split('"') |     const i = input.replace(/^\;.*\n?/gm, '').replace('λ', 'lambda ').split('"') | ||||||
|     return i.map(function (x, i) { |     return i.map(function (x, i) { | ||||||
|       return i % 2 === 0 ?  |       return i % 2 === 0 | ||||||
|         x.replace(/\(/g, ' ( ').replace(/\)/g, ' ) ').replace(/' \( /g, ' \'( ') |         ? x.replace(/\(/g, ' ( ') | ||||||
|  |           .replace(/\)/g, ' ) ') | ||||||
|  |           .replace(/' \( /g, ' \'( ') // '() | ||||||
|  |           .replace(/\{/g, ' { ') // {} | ||||||
|  |           .replace(/\}/g, ' } ') // {} | ||||||
|         : x.replace(/ /g, '!whitespace!') |         : x.replace(/ /g, '!whitespace!') | ||||||
|     }) |     }) | ||||||
|     .join('"').trim().split(/\s+/) |       .join('"').trim().split(/\s+/) | ||||||
|     .map(function (x) { return x.replace(/!whitespace!/g, ' ') }) |       .map(function (x) { return x.replace(/!whitespace!/g, ' ') }) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.inc = function () { | ||||||
|  |     return includes.reduce((acc, item) => { | ||||||
|  |       const p = path.join(__dirname, `lisp/${item}.lisp`) | ||||||
|  |       if (!fs.existsSync(p)) { console.warn('Lisp', `Missing include: ${p}`); return acc } | ||||||
|  |       return `${acc}(include "${p}") ` | ||||||
|  |     }, '') | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.parse = function (input) { |   this.parse = function (input) { | ||||||
|     return parenthesize(tokenize(`(${input})`)) |     return parenthesize(tokenize(input)) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.toPixels = async function () { |   this.run = async function (input) { | ||||||
|     return interpret(this.parse(input)) |     return interpret(this.parse(`( | ||||||
|  |       ${this.inc()} | ||||||
|  |       ${input})`)) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								desktop/sources/scripts/osc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								desktop/sources/scripts/osc.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | 'use strict' | ||||||
|  |  | ||||||
|  | function Osc (ronin) { | ||||||
|  |   const osc = require('osc') | ||||||
|  |  | ||||||
|  |   this.msg = {} | ||||||
|  |  | ||||||
|  |   this.start = function () { | ||||||
|  |     const udpPort = new osc.UDPPort({ | ||||||
|  |       localAddress: '0.0.0.0', | ||||||
|  |       localPort: 49162, | ||||||
|  |       metadata: true | ||||||
|  |     }) | ||||||
|  |     udpPort.on('message', this.onMsg) | ||||||
|  |     udpPort.open() | ||||||
|  |     ronin.log('OSC', 'Started.') | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this.onMsg = (msg, timeTag, info) => { | ||||||
|  |     this.msg[msg.address] = msg.args | ||||||
|  |     // ronin.log(`${info.address}:${info.port} > ${msg.args}`, info) | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -11,6 +11,8 @@ function Ronin () { | |||||||
|     b_inv: '#ffb545' |     b_inv: '#ffb545' | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   this.includes = ['prelude'] | ||||||
|  |  | ||||||
|   this.el = document.createElement('div') |   this.el = document.createElement('div') | ||||||
|   this.el.id = 'ronin' |   this.el.id = 'ronin' | ||||||
|  |  | ||||||
| @@ -19,7 +21,8 @@ function Ronin () { | |||||||
|   this.commander = new Commander(this) |   this.commander = new Commander(this) | ||||||
|   this.surface = new Surface(this) |   this.surface = new Surface(this) | ||||||
|   this.library = new Library(this) |   this.library = new Library(this) | ||||||
|  |   this.interpreter = new Lisp(this.library, this.includes) | ||||||
|  |   this.osc = new Osc(this) | ||||||
|   // Parameters |   // Parameters | ||||||
|  |  | ||||||
|   this.always = false |   this.always = false | ||||||
| @@ -43,7 +46,7 @@ function Ronin () { | |||||||
|     this.source.start() |     this.source.start() | ||||||
|     this.commander.start() |     this.commander.start() | ||||||
|     this.surface.start() |     this.surface.start() | ||||||
|     console.log('Ronin', 'Started') |     this.osc.start() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.reset = function () { |   this.reset = function () { | ||||||
| @@ -61,7 +64,7 @@ function Ronin () { | |||||||
|   this.animate = (b = true) => { |   this.animate = (b = true) => { | ||||||
|     if (this.always === b) { return } |     if (this.always === b) { return } | ||||||
|     this.always = b |     this.always = b | ||||||
|     this.commander.run() |     this.commander.loop() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Zoom |   // Zoom | ||||||
|   | |||||||
| @@ -126,12 +126,6 @@ function Source (ronin) { | |||||||
|     return `${str}` |     return `${str}` | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.locate = function (name) { |  | ||||||
|     if (!this.path) { return } |  | ||||||
|     const loc = path.join(this.folder(), name) |  | ||||||
|     return fs.existsSync(loc) ? loc : null |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Etc |   // Etc | ||||||
|  |  | ||||||
|   this.name = function () { |   this.name = function () { | ||||||
|   | |||||||
| @@ -100,7 +100,7 @@ function Surface (ronin) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.traceCircle = function (circle, context) { |   this.traceCircle = function (circle, context) { | ||||||
|     context.arc(circle.x, circle.y, circle.r, 0, 2 * Math.PI) |     context.arc(circle.cx, circle.cy, circle.r, 0, 2 * Math.PI) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.traceText = function (text, context) { |   this.traceText = function (text, context) { | ||||||
| @@ -185,7 +185,7 @@ function Surface (ronin) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.maximize = function () { |   this.maximize = function () { | ||||||
|     this.resize({ x: 0, y: 0, w: (window.innerWidth * this.ratio) - 60, h: (window.innerHeight * this.ratio) - 60, t: 'rect' }) |     this.resize({ x: 0, y: 0, w: ((window.innerWidth - 60) * this.ratio), h: ((window.innerHeight - 60) * this.ratio), t: 'rect' }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this.onResize = function () { |   this.onResize = function () { | ||||||
|   | |||||||
| @@ -1,17 +1,50 @@ | |||||||
| ; animate | ; | ||||||
|  |  | ||||||
| (clear) | (clear) | ||||||
| (def t  | ; | ||||||
|   (sin  | (def seg-count 50) | ||||||
|     (div  | ;  | ||||||
|       (time) 100)))  | (def frame-middle  | ||||||
| (def pos  |   (div  | ||||||
|   (add 200 30  |     (of  | ||||||
|     (mul 30 t)))  |       (frame) :h) 2))  | ||||||
| (defn square  | ;  | ||||||
|   (a)  | (def seg-width  | ||||||
|   (rect a a a a))  |   (div  | ||||||
| (stroke  |     (of  | ||||||
|   (square pos) 1 "red")  |       (frame) :w) seg-count))  | ||||||
| ; set false to stop  | ; | ||||||
| (animate true) | (defn elevation  | ||||||
|  |   (i)  | ||||||
|  |   (add  | ||||||
|  |     (mul  | ||||||
|  |       (sin  | ||||||
|  |         (add  | ||||||
|  |           (time 0.001)  | ||||||
|  |           (div i 5)))  | ||||||
|  |       (div  | ||||||
|  |         (of  | ||||||
|  |           (frame) :h) 5)) frame-middle)) | ||||||
|  | ; | ||||||
|  | (defn draw-dash  | ||||||
|  |   (i)  | ||||||
|  |   ( | ||||||
|  |     (def x  | ||||||
|  |       (mul  | ||||||
|  |         (sub i 1) seg-width))  | ||||||
|  |     (def y  | ||||||
|  |       (elevation i))  | ||||||
|  |     (stroke  | ||||||
|  |       (line  | ||||||
|  |         (pos x  | ||||||
|  |           (elevation  | ||||||
|  |             (sub i 1)))  | ||||||
|  |         (pos  | ||||||
|  |           (add x seg-width)  | ||||||
|  |           (elevation i))) 4  | ||||||
|  |       (gradient  | ||||||
|  |         (50 0  | ||||||
|  |           (of  | ||||||
|  |             (frame) :w) 0)  | ||||||
|  |         ("rgba(255,255,255,0)" "white" "#72dec2" "red"))))) | ||||||
|  | ; | ||||||
|  | (times seg-count draw-dash) | ||||||
| @@ -1,25 +1,26 @@ | |||||||
| (echo (map (lambda (a) (add a 1)) (1 2 3))) | (echo (map '(add %1 1) (1 2 3))) | ||||||
|  |  | ||||||
| (echo (first (1 2 3))) | (echo (first (1 2 3))) | ||||||
| (echo (rest (1 2 3))) | (echo (rest (1 2 3))) | ||||||
|  |  | ||||||
| (echo | (echo | ||||||
|   (filter  |   (filter  | ||||||
|     (lambda (a) (eq 0 (mod a 2)))  |     '(eq 0 (mod %1 2))  | ||||||
|     (1 2 3 4 5)) |     (1 2 3 4 5)) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| (clear)  | (clear)  | ||||||
| (map (lambda (a) | (map | ||||||
|   (stroke (rect (mul a 30) 20 50 50) |   '(stroke (rect (mul a 30) 20 50 50) | ||||||
| 1 "red")) | 1 "red") | ||||||
| (range 0 20 5)) | (range 0 20 5)) | ||||||
|  |  | ||||||
| (map (lambda (a) | (map | ||||||
|   (stroke  |   '(stroke  | ||||||
|     (rect  |     (rect  | ||||||
|       (mul a 10)  |       (mul %1 10)  | ||||||
|       (add 50 (mul (sin a) 40))  |       (add 250 (mul (sin %1) 250))  | ||||||
|       a  |       (mul 4 %1) | ||||||
|       (add 20 (mul (cos a) 50))) 1 "red")) |       (add 20 (mul (cos %1) 50))) 1 "red") | ||||||
|   (range 0 200 5)) |   (range 0 200 5)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,3 +7,7 @@ | |||||||
| ; define a function  | ; define a function  | ||||||
| (defn add-two (a) (add 2 a))  | (defn add-two (a) (add 2 a))  | ||||||
| (echo (add-two 4)) | (echo (add-two 4)) | ||||||
|  |  | ||||||
|  | ; use a lambda | ||||||
|  | (times 5  | ||||||
|  |   (λ (a) (echo (concat "time:" a)))) | ||||||
| @@ -35,14 +35,14 @@ | |||||||
|   (test "range simple" (range 0 4) (0 1 2 3 4)) |   (test "range simple" (range 0 4) (0 1 2 3 4)) | ||||||
|   (test "range with step" (range 0 4 2) (0 2 4)) |   (test "range with step" (range 0 4 2) (0 2 4)) | ||||||
|   (test "range with negative step" (range 0 -4 -1) (0 -1 -2 -3 -4)) |   (test "range with negative step" (range 0 -4 -1) (0 -1 -2 -3 -4)) | ||||||
|   (test "map" (map (lambda (a) (add 1 a)) (1 2 3)) (2 3 4)) |   (test "map" (map (λ (a) (add 1 a)) (1 2 3)) (2 3 4)) | ||||||
|   (test "filter" (filter (lambda (a) (eq 0 (mod a 2))) (2 3 4 5 6)) (2 4 6)) |   (test "filter" (filter (λ (a) (eq 0 (mod a 2))) (2 3 4 5 6)) (2 4 6)) | ||||||
|   (test "reduce" (reduce (lambda (acc val) (add acc val)) (1 2 3) 4) 10) |   (test "reduce" (reduce (λ (acc val) (add acc val)) (1 2 3) 4) 10) | ||||||
|  |  | ||||||
| ; Scope | ; Scope | ||||||
|  |  | ||||||
|   (def aaa 123) |   (def aaa 123) | ||||||
|   (def addOne (lambda (a) (add a 1))) |   (def addOne (λ (a) (add a 1))) | ||||||
|   (test "def - value" aaa 123) |   (test "def - value" aaa 123) | ||||||
|   (test "def - func" (addOne 4) 5) |   (test "def - func" (addOne 4) 5) | ||||||
|   (defn addTwo (a) (add 2 a)) |   (defn addTwo (a) (add 2 a)) | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ | |||||||
|  |  | ||||||
| (defn dejong (r a b c d) | (defn dejong (r a b c d) | ||||||
|   (reduce   |   (reduce   | ||||||
|     (lambda (acc val) |     (λ (acc val) | ||||||
|       (first ( |       (first ( | ||||||
|         (_dejong (first acc) (last acc) a b c d) |         (_dejong (first acc) (last acc) a b c d) | ||||||
|       ))) |       ))) | ||||||
|   | |||||||
| @@ -5,12 +5,11 @@ | |||||||
| (defn glitch  | (defn glitch  | ||||||
|   (rec)  |   (rec)  | ||||||
|   (if (gt rec 1) |   (if (gt rec 1) | ||||||
|   ((clone  |     ( | ||||||
|     (rect (random 400) (random 400) 2 2) |       (translate | ||||||
|     (rect (random 400) (random 400)  |         (rect (random 400) (random 400) (random 10) (random 10)) | ||||||
| (random 10) (random 30))) |         (pos (random 400) (random 400))) | ||||||
|     (glitch (sub rec 1)))) |       (glitch (sub rec 1))))) | ||||||
| ) |  | ||||||
|  |  | ||||||
| (import  | (import  | ||||||
|   "../static/crystal.jpg"  |   "../static/crystal.jpg"  | ||||||
|   | |||||||
| @@ -1,6 +1 @@ | |||||||
| ( | (echo (map '(add %1 2) (4 5 6)) | ||||||
|  |  | ||||||
| (echo (map '(add 1 2) (4 5 6)) |  | ||||||
|  |  | ||||||
| ) |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								examples/objects.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								examples/objects.lisp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | ; objects | ||||||
|  |  | ||||||
|  | (test "symbols" :a "a") | ||||||
|  |  | ||||||
|  | (def ob {:a "fantastic" :b 2}) | ||||||
|  |  | ||||||
|  | ((of (js) :console :log) ob) | ||||||
|  |  | ||||||
|  | (echo (of ob :a)) | ||||||
|  |  | ||||||
|  | (echo (keys ob)) | ||||||
|  | (echo (values ob)) | ||||||
|  |  | ||||||
|  | (set ob :a 4) | ||||||
|  | (echo (of ob :a)) | ||||||
							
								
								
									
										1
									
								
								examples/orca.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/orca.lisp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | (debug (of (osc "/a") :0 :value)) | ||||||
							
								
								
									
										11
									
								
								examples/osc.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/osc.lisp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | (clear) | ||||||
|  | (def x (of (osc "/test") "args" "0" "value")) | ||||||
|  | (def y (of (osc "/test") "args" "1" "value")) | ||||||
|  | (def r (of (osc "/test") "args" "2" "value")) | ||||||
|  |  | ||||||
|  | (fill  | ||||||
|  | (circle x y r) | ||||||
|  | "red") | ||||||
|  | (stroke  | ||||||
|  | (circle x y r) | ||||||
|  | 5 "white") | ||||||
							
								
								
									
										37
									
								
								examples/stars.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								examples/stars.lisp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | ; stars | ||||||
|  | (clear) | ||||||
|  | ; | ||||||
|  | (defn draw-spoke  | ||||||
|  |   (cx cy r a)  | ||||||
|  |   ( | ||||||
|  |     (stroke  | ||||||
|  |       (line  | ||||||
|  |         (pos cx cy)  | ||||||
|  |         (circle-pos cx cy r a)) 2 "white"))) | ||||||
|  | ; | ||||||
|  | (defn draw-star  | ||||||
|  |   (cx cy r c)  | ||||||
|  |   ( | ||||||
|  |     (times c  | ||||||
|  |       (λ  | ||||||
|  |         (i)  | ||||||
|  |         ( | ||||||
|  |           (draw-spoke cx cy r  | ||||||
|  |             (deg-rad  | ||||||
|  |               (mul i  | ||||||
|  |                 (div 360 c))))))))) | ||||||
|  | ; main | ||||||
|  | (times 100  | ||||||
|  |   (λ  | ||||||
|  |     ()  | ||||||
|  |     ( | ||||||
|  |       (draw-star  | ||||||
|  |         (random 100  | ||||||
|  |           (of  | ||||||
|  |             (frame) :w))  | ||||||
|  |         (random 100  | ||||||
|  |           (of  | ||||||
|  |             (frame) :h))  | ||||||
|  |         (random 10 100)  | ||||||
|  |         (floor  | ||||||
|  |           (random 3 32)))))) | ||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| (clear)  | (clear)  | ||||||
| (def col  | (def col  | ||||||
|   (lambda  |   (λ  | ||||||
|     (i)  |     (i)  | ||||||
|     (of  |     (of  | ||||||
|       ( |       ( | ||||||
| @@ -16,7 +16,7 @@ | |||||||
|         (theme "b_inv"))  |         (theme "b_inv"))  | ||||||
|       (mod i 8))))  |       (mod i 8))))  | ||||||
| (def rec  | (def rec  | ||||||
|   (lambda  |   (λ  | ||||||
|     (v i)  |     (v i)  | ||||||
|     (if  |     (if  | ||||||
|       (gt v 0)  |       (gt v 0)  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user