diff --git a/README.md b/README.md index 3a081da..6613832 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Ronin is a procedural graphics tool designed to automate simple graphical The library updates is constantly revealing new applications to Ronin, you can see the list of available functions here. Most of our iconography and designs were created with both Ronin and Dotgrid. -Learn more by reading the manual, or have a look at some experiments on twitter. If you need help, visit the Community, follow the [workshop](https://github.com/hundredrabbits/Ronin/blob/master/WORKSHOP.md) or watch the [video tutorial](https://www.youtube.com/watch?v=SgAWGh1s9zg). +Learn more by reading the manual, or have a look at some experiments on twitter. If you need help, visit the Community, follow the [workshop](https://github.com/hundredrabbits/Ronin/blob/master/resources/WORKSHOP.md) or watch the [video tutorial](https://www.youtube.com/watch?v=SgAWGh1s9zg). ```lisp ; clear screen @@ -29,7 +29,7 @@ npm install npm start ``` - + ## Helpers @@ -152,9 +152,9 @@ To save an image in memory, open an image file with Ronin, or drag an image file - `(test name a b)` - `(benchmark fn)` Logs time taken to execute a function. - + - + ## Extras diff --git a/desktop/icon.svg b/desktop/icon.svg index 6c60788..ae2f668 100644 --- a/desktop/icon.svg +++ b/desktop/icon.svg @@ -1,4 +1,6 @@ - + - + + + \ No newline at end of file diff --git a/desktop/package-lock.json b/desktop/package-lock.json index ce75acb..5c622fd 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@electron/get": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.6.0.tgz", - "integrity": "sha512-xuvAzbN9iBApfAMvW0hKUpxHR5wPVbG9RaoSTbpu/WaHISDu0MVfMWYhfeU0X730CpBV0G2RkLgwAs9WDan3GA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.7.2.tgz", + "integrity": "sha512-LSE4LZGMjGS9TloDx0yO44D2UTbaeKRk+QjlhWLiQlikV6J4spgDCjb6z4YIcqmPAwNzlNCnWF4dubytwI+ATA==", "dev": true, "requires": { "debug": "^4.1.1", @@ -17,7 +17,7 @@ "global-tunnel-ng": "^2.7.1", "got": "^9.6.0", "sanitize-filename": "^1.6.2", - "sumchecker": "^3.0.0" + "sumchecker": "^3.0.1" } }, "@sindresorhus/is": { @@ -36,15 +36,15 @@ } }, "@types/node": { - "version": "12.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.5.tgz", - "integrity": "sha512-KEjODidV4XYUlJBF3XdjSH5FWoMCtO0utnhtdLf1AgeuZLOrRbvmU/gaRCVg7ZaQDjVf3l84egiY0mRNe5xE4A==", + "version": "12.12.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.26.tgz", + "integrity": "sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA==", "dev": true }, "asar": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/asar/-/asar-2.0.1.tgz", - "integrity": "sha512-Vo9yTuUtyFahkVMFaI6uMuX6N7k5DWa6a/8+7ov0/f8Lq9TVR0tUjzSzxQSxT1Y+RJIZgnP7BVb6Uhi+9cjxqA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/asar/-/asar-2.0.3.tgz", + "integrity": "sha512-QdHKO+HOYVtE4B/M3up3i4LSJeJgsa2CTVBrjBf9GgLUPGGUFZowcdJ5yE4gOJuRAHNdqB9JFeRfFfaOu5x8Rw==", "dev": true, "requires": { "chromium-pickle-js": "^0.2.0", @@ -75,15 +75,15 @@ "dev": true }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "boolean": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-2.0.3.tgz", - "integrity": "sha512-iHzXeFCXWrpjYE7DToXGCBPGZf0eVISqzL+4sgrOSYEKXnb59WHPFvGTTyCj6zJ/MuuLAxEn8zPkrTHHzlt3IA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.0.tgz", + "integrity": "sha512-OElxJ1lUSinuoUnkpOgLmxp0DC4ytEhODEL6QJU0NpxE/mI4rUSh8h1P1Wkvfi3xQEBcxXR2gBIPNYNuaFcAbQ==", "dev": true, "optional": true }, @@ -220,9 +220,9 @@ } }, "core-js": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.6.tgz", - "integrity": "sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", "dev": true, "optional": true }, @@ -233,18 +233,18 @@ "dev": true }, "cross-zip": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/cross-zip/-/cross-zip-2.1.6.tgz", - "integrity": "sha512-xLIETNkzRcU6jGRzenJyRFxahbtP4628xEKMTI/Ql0Vu8m4h8M7uRLVi7E5OYHuJ6VQPsG4icJumKAFUvfm0+A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cross-zip/-/cross-zip-3.0.0.tgz", + "integrity": "sha512-cm+l8PJ6WiSQmKZ/x8DGvUm2u/3FX2JFs1AFd18gdHaVhP5Lf4oE6Jrj2Jd05JYSioz5x+nIRVp0zBQuzuCRcQ==", "dev": true, "requires": { "rimraf": "^3.0.0" }, "dependencies": { "rimraf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", - "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -283,9 +283,9 @@ } }, "defer-to-connect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.0.tgz", - "integrity": "sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, "define-properties": { @@ -312,9 +312,9 @@ "dev": true }, "electron": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-7.0.1.tgz", - "integrity": "sha512-eMFoZIO0+eOAE9FyNC/f0Vp8l/sJziTMK+axEt2XIpGCagom1IZgUKPGwmHUcftZCX5lNKh+Tv53T0GcNnNTKQ==", + "version": "7.1.11", + "resolved": "https://registry.npmjs.org/electron/-/electron-7.1.11.tgz", + "integrity": "sha512-YDXfnovKY+8iZ5ISQh1kRqYIRKbpOSxGXCx2WVxPFPutEQ7Q/Xzr3h4GePEY25/NXMytMfhKaAZAYjtWUm3r9Q==", "dev": true, "requires": { "@electron/get": "^1.0.1", @@ -323,19 +323,19 @@ } }, "electron-notarize": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-0.1.1.tgz", - "integrity": "sha512-TpKfJcz4LXl5jiGvZTs5fbEx+wUFXV5u8voeG5WCHWfY/cdgdD8lDZIZRqLVOtR3VO+drgJ9aiSHIO9TYn/fKg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-0.2.1.tgz", + "integrity": "sha512-oZ6/NhKeXmEKNROiFmRNfytqu3cxqC95sjooG7kBXQVEUSQkZnbiAhxVh5jXngL881G197pbwpeVPJyM7Ikmxw==", "dev": true, "requires": { "debug": "^4.1.1", - "fs-extra": "^8.0.1" + "fs-extra": "^8.1.0" } }, "electron-osx-sign": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.14.tgz", - "integrity": "sha512-72vtrz9I3dOeFDaNvO5thwIjrimDiXMmYEbN0hEBqnvcSSMOWugjim2wiY9ox3dhuBFUhxp3owmuZCoH3Ij08A==", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.15.tgz", + "integrity": "sha512-1QtPNpjIji9bGZ0VRFwtJUyU1uHi7q3XUAOG0qFsvAUfs5H0T8hbgUfyg3xvPzmF1ruV8T8pQmQ86vNfLrcRiA==", "dev": true, "requires": { "bluebird": "^3.5.0", @@ -370,16 +370,16 @@ } }, "electron-packager": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-14.1.0.tgz", - "integrity": "sha512-4oGtQYYjSA/M4BGOwG0NBqEtThBf7aCV76C2AZsD71eGocYqZNvtvfzeeMnKkc3EW1nPq7iJ4Wge+GXma0kwIA==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-14.2.1.tgz", + "integrity": "sha512-g6y3BVrAOz/iavKD+VMFbehrQcwCWuA3CZvVbmmbQuCfegGA1ytwWn0BNIDDrEdbuz31Fti7mnNHhb5L+3Wq9A==", "dev": true, "requires": { "@electron/get": "^1.6.0", "asar": "^2.0.1", - "cross-zip": "^2.1.5", + "cross-zip": "^3.0.0", "debug": "^4.0.1", - "electron-notarize": "^0.1.1", + "electron-notarize": "^0.2.0", "electron-osx-sign": "^0.4.11", "fs-extra": "^8.1.0", "galactus": "^0.2.1", @@ -392,6 +392,14 @@ "sanitize-filename": "^1.6.0", "semver": "^6.0.0", "yargs-parser": "^16.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "encodeurl": { @@ -526,13 +534,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true, - "optional": true - }, "galactus": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz", @@ -605,9 +606,9 @@ } }, "glob": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", - "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -619,18 +620,18 @@ } }, "global-agent": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.5.tgz", - "integrity": "sha512-pYJjCxxNBzYxo6iNO62JZn8iCFVbvpiM0zE4w/G5hBNIvLjnvzIeCVQPMKc3aK8ju5L7Q8NNI/oBSosU0eeSYw==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.8.tgz", + "integrity": "sha512-VpBe/rhY6Rw2VDOTszAMNambg+4Qv8j0yiTNDYEXXXxkUNGWLHp8A3ztK4YDBbFNcWF4rgsec6/5gPyryya/+A==", "dev": true, "optional": true, "requires": { - "boolean": "^2.0.2", - "core-js": "^3.3.3", + "boolean": "^3.0.0", + "core-js": "^3.6.4", "es6-error": "^4.1.1", - "matcher": "^2.0.0", - "roarr": "^2.14.2", - "semver": "^6.3.0", + "matcher": "^2.1.0", + "roarr": "^2.15.2", + "semver": "^7.1.2", "serialize-error": "^5.0.0" } }, @@ -648,15 +649,13 @@ } }, "globalthis": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.0.tgz", - "integrity": "sha512-vcCAZTJ3r5Qcu5l8/2oyVdoFwxKgfYnMTR2vwWeux/NAVZK3PwcMaWkdUIn4GJbmKuRK7xcvDsLuK+CKcXyodg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", + "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", "dev": true, "optional": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "object-keys": "^1.0.12" + "define-properties": "^1.1.3" } }, "got": { @@ -827,9 +826,9 @@ "dev": true }, "matcher": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.0.0.tgz", - "integrity": "sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.1.0.tgz", + "integrity": "sha512-o+nZr+vtJtgPNklyeUKkkH42OsK8WAfdgaJE2FNxcjLPg+5QbeEoT6vRj8Xq/iv18JlQ9cmKsEu0b94ixWf1YQ==", "dev": true, "optional": true, "requires": { @@ -1089,9 +1088,9 @@ } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -1104,9 +1103,9 @@ } }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -1131,15 +1130,15 @@ } }, "roarr": { - "version": "2.14.3", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.14.3.tgz", - "integrity": "sha512-D4BpKVruUDCJ9DJWcC7T+fx4o10IUYJ7MdmjM4Skx1aqc42CE7LGzPDUAfczibhavNGcnY1IHqJdq16NmiG4rQ==", + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.2.tgz", + "integrity": "sha512-jmaDhK9CO4YbQAV8zzCnq9vjAqeO489MS5ehZ+rXmFiPFFE6B+S9KYO6prjmLJ5A0zY3QxVlQdrIya7E/azz/Q==", "dev": true, "optional": true, "requires": { - "boolean": "^2.0.2", + "boolean": "^3.0.0", "detect-node": "^2.0.4", - "globalthis": "^1.0.0", + "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" @@ -1161,10 +1160,11 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.2.tgz", + "integrity": "sha512-BJs9T/H8sEVHbeigqzIEo57Iu/3DG6c4QoqTfbQB3BPA4zgzAomh/Fk9E7QtjWQ8mx2dgA9YCfSF4y9k9bHNpQ==", + "dev": true, + "optional": true }, "semver-compare": { "version": "1.0.0", @@ -1238,9 +1238,9 @@ "dev": true }, "sumchecker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.0.tgz", - "integrity": "sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, "requires": { "debug": "^4.1.0" @@ -1350,9 +1350,9 @@ "dev": true }, "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", "dev": true }, "yargs-parser": { diff --git a/desktop/package.json b/desktop/package.json index 9d8f23a..d223733 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -3,13 +3,14 @@ "version": "0.1.0", "main": "main.js", "scripts": { - "start": "electron .", + "start": "electron . --disable-gpu", "fix": "standard --fix", "clean": "rm -r ~/Documents/Ronin-darwin-x64/ ; rm -r ~/Documents/Ronin-linux-x64/ ; rm -r ~/Documents/Ronin-win32-x64/ ; echo 'cleaned build location'", "build_osx": "electron-packager . Ronin --platform=darwin --arch=x64 --out ~/Documents/ --overwrite --icon=icon.icns ; echo 'Built for OSX'", "build_linux": "electron-packager . Ronin --platform=linux --arch=x64 --out ~/Documents/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'", "build_win": "electron-packager . Ronin --platform=win32 --arch=x64 --out ~/Documents/ --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 ; npm run add_manual", + "add_manual": "cp ../resources/MANUAL.txt ~/Documents/Ronin-darwin-x64/MANUAL.txt ; cp ../resources/MANUAL.txt ~/Documents/Ronin-linux-x64/MANUAL.txt ; cp ../resources/MANUAL.txt ~/Documents/Ronin-win32-x64/MANUAL.txt", "push_osx": "~/Applications/butler push ~/Documents/Ronin-darwin-x64/ hundredrabbits/ronin:osx-64", "push_linux": "~/Applications/butler push ~/Documents/Ronin-linux-x64/ hundredrabbits/ronin:linux-64", "push_win": "~/Applications/butler push ~/Documents/Ronin-win32-x64/ hundredrabbits/ronin:windows-64", @@ -17,8 +18,8 @@ "push": "npm run build ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run status" }, "devDependencies": { - "electron": "^7.1.5", - "electron-packager": "^14.1.1" + "electron": "^7.1.11", + "electron-packager": "^14.2.1" }, "standard": { "globals": [ diff --git a/desktop/sources/scripts/client.js b/desktop/sources/scripts/client.js index 3da2acd..0975bf2 100644 --- a/desktop/sources/scripts/client.js +++ b/desktop/sources/scripts/client.js @@ -39,8 +39,8 @@ function Client () { window.addEventListener('drop', this.onDrop) this.acels.set('File', 'New', 'CmdOrCtrl+N', () => { this.source.new(); this.surface.clear(); this.commander.clear() }) - this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.download('ronin', 'lisp', this.commander._input.value, 'text/plain') }) - this.acels.set('File', 'Export Image', 'CmdOrCtrl+E', () => { this.source.download('ronin', 'png', this.surface.el.toDataURL('image/png', 1.0), 'image/png') }) + this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.write('ronin', 'lisp', this.commander._input.value, 'text/plain') }) + this.acels.set('File', 'Export Image', 'CmdOrCtrl+E', () => { this.source.write('ronin', 'png', this.surface.el.toDataURL('image/png', 1.0), 'image/png') }) this.acels.set('File', 'Open', 'CmdOrCtrl+O', () => { this.source.open('lisp', this.whenOpen) }) this.acels.add('Edit', 'undo') diff --git a/desktop/sources/scripts/lib/acels.js b/desktop/sources/scripts/lib/acels.js index 40320bc..62f630c 100644 --- a/desktop/sources/scripts/lib/acels.js +++ b/desktop/sources/scripts/lib/acels.js @@ -37,10 +37,10 @@ function Acels (client) { if ((event.ctrlKey || event.metaKey) && event.shiftKey) { return `CmdOrCtrl+Shift+${accelerator}` } - if (event.shiftKey) { + if (event.shiftKey && event.key.toUpperCase() !== event.key) { return `Shift+${accelerator}` } - if (event.altKey) { + if (event.altKey && event.key.length !== 1) { return `Alt+${accelerator}` } if (event.ctrlKey || event.metaKey) { @@ -73,7 +73,7 @@ function Acels (client) { for (const cat in cats) { text += `\n### ${cat}\n\n` for (const item of cats[cat]) { - text += item.accelerator ? `- \`${item.accelerator}\`: ${item.info}\n` : '' + text += item.accelerator ? `- \`${item.accelerator.replace('`', 'tilde')}\`: ${item.name}\n` : '' } } return text.trim() @@ -83,8 +83,9 @@ function Acels (client) { const cats = this.sort() let text = '' for (const cat in cats) { + text += `\n${cat}\n\n` for (const item of cats[cat]) { - text += item.accelerator ? `${cat}: ${item.name} | ${item.accelerator}\n` : '' + text += item.accelerator ? `${item.name.padEnd(25, '.')} ${item.accelerator}\n` : '' } } return text.trim() @@ -105,13 +106,13 @@ function Acels (client) { submenu: [ { label: 'Download Themes', click: () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') } }, { label: 'Open Theme', click: () => { client.theme.open() } }, - { label: 'Reset Theme', click: () => { client.theme.reset() } } + { label: 'Reset Theme', accelerator: 'CmdOrCtrl+Escape', click: () => { client.theme.reset() } } ] }, { label: 'Fullscreen', accelerator: 'CmdOrCtrl+Enter', click: () => { app.toggleFullscreen() } }, { label: 'Hide', accelerator: 'CmdOrCtrl+H', click: () => { app.toggleVisible() } }, { label: 'Toggle Menubar', accelerator: 'Alt+H', click: () => { app.toggleMenubar() } }, - { label: 'Inspect', accelerator: 'CmdOrCtrl+.', click: () => { app.inspect() } }, + { label: 'Inspect', accelerator: 'CmdOrCtrl+Tab', click: () => { app.inspect() } }, { role: 'quit' } ] }) diff --git a/desktop/sources/scripts/lib/source.js b/desktop/sources/scripts/lib/source.js index f651b2e..ba2554c 100644 --- a/desktop/sources/scripts/lib/source.js +++ b/desktop/sources/scripts/lib/source.js @@ -18,14 +18,14 @@ function Source (client) { this.cache = {} } - this.open = (ext, callback) => { + this.open = (ext, callback, store = false) => { console.log('Source', 'Open file..') const input = document.createElement('input') input.type = 'file' input.onchange = (e) => { const file = e.target.files[0] if (file.name.indexOf('.' + ext) < 0) { console.warn('Source', `Skipped ${file.name}`); return } - this.read(file, callback) + this.read(file, callback, store) } input.click() } @@ -37,7 +37,7 @@ function Source (client) { input.setAttribute('multiple', 'multiple') input.onchange = (e) => { for (const file of e.target.files) { - if (file.name.indexOf('.' + ext) < 0) { console.warn('Source', `Skipped ${file.name}`); return } + if (file.name.indexOf('.' + ext) < 0) { console.warn('Source', `Skipped ${file.name}`); continue } this.read(file, this.store) } } @@ -60,11 +60,12 @@ function Source (client) { // I/O - this.read = (file, callback) => { + this.read = (file, callback, store = false) => { const reader = new FileReader() reader.onload = (event) => { const res = event.target.result if (callback) { callback(file, res) } + if (store) { this.store(file, res) } } reader.readAsText(file, 'UTF-8') } diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js index 187ca84..d7f412b 100644 --- a/desktop/sources/scripts/library.js +++ b/desktop/sources/scripts/library.js @@ -1,5 +1,6 @@ 'use strict' +/* global Image */ /* global Image */ function Library (client) { @@ -11,12 +12,9 @@ function Library (client) { return shape || this.rect(0, 0, img.width, img.height) } - this.export = async (name = 'export', type = 'image/png', quality = 1.0) => { // Exports a graphic file with format. - const base64 = client.surface.el.toDataURL(type, quality) - const link = document.createElement('a') - link.setAttribute('href', base64) - link.setAttribute('download', type === 'image/png' ? name + '.png' : name + '.jpg') - link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })) + this.export = async (name = 'ronin', type = 'image/png', quality = 1.0) => { // Exports a graphic file with format. + const ext = type === 'image/png' ? name + '.png' : name + '.jpg' + client.source.write(name, ext, client.surface.el.toDataURL(type, 1.0), type) } // Shapes diff --git a/resources/MANUAL.txt b/resources/MANUAL.txt new file mode 100644 index 0000000..f763f1a --- /dev/null +++ b/resources/MANUAL.txt @@ -0,0 +1,22 @@ +File + +New...................... CmdOrCtrl+N +Save..................... CmdOrCtrl+S +Export Image............. CmdOrCtrl+E +Open..................... CmdOrCtrl+O + +Edit + + +View + +Toggle Guides............ CmdOrCtrl+Shift+H +Toggle Commander......... CmdOrCtrl+K +Expand Commander......... CmdOrCtrl+Shift+K + +Project + +Run...................... CmdOrCtrl+R +Reload Run............... CmdOrCtrl+Shift+R +Re-Indent................ CmdOrCtrl+Shift+I +Clean.................... Escape \ No newline at end of file diff --git a/resources/PRELUDE.md b/resources/PRELUDE.md new file mode 100644 index 0000000..55fc238 --- /dev/null +++ b/resources/PRELUDE.md @@ -0,0 +1,46 @@ +# Prelude + +## Colors + +### Compare two Colors + +Use: `(if (color-eq (255 200 0) (200 255 0)) "yes" "no")`. + +``` +(defn color-eq + (a b) + (and + (eq a:0 b:0) + (eq a:1 b:1) + (eq a:2 b:2))) +``` + +## Pixels + +### Erase all pixels of a specific color + +Use: `(pixels erase-color (255 0 0))`. + +``` +(defn erase-color + (a b) + (a:0 a:1 a:2 + (if + (and + (eq a:0 b:0) + (eq a:1 b:1) + (eq a:2 b:2)) 0 255))) +``` + +### Posterize + +Use: `(pixels posterize 40)`. + +``` +(defn posterize + (a q) + ( + (step a:0 q) + (step a:1 q) + (step a:2 q) a:3)) +``` \ No newline at end of file diff --git a/resources/PREVIEW.jpg b/resources/PREVIEW.jpg new file mode 100644 index 0000000..3878100 Binary files /dev/null and b/resources/PREVIEW.jpg differ diff --git a/resources/PREVIEW2.jpg b/resources/PREVIEW2.jpg new file mode 100644 index 0000000..61e3447 Binary files /dev/null and b/resources/PREVIEW2.jpg differ diff --git a/resources/PREVIEW3.jpg b/resources/PREVIEW3.jpg new file mode 100644 index 0000000..9d87853 Binary files /dev/null and b/resources/PREVIEW3.jpg differ diff --git a/resources/WORKSHOP.md b/resources/WORKSHOP.md new file mode 100644 index 0000000..2f7a5e4 --- /dev/null +++ b/resources/WORKSHOP.md @@ -0,0 +1,261 @@ +# Workshop + + + +This workshop is designed to go over the **most commonly used functions** with [Ronin](https://github.com/hundredrabbits/Ronin). The list of all available functions and their usage is located [here](https://github.com/hundredrabbits/Ronin/#library). You can also follow along our [video tutorial](https://youtu.be/SgAWGh1s9zg). + +- **Part 1**: [Images](#Images) `(import)`, `(crop)`, `(export)` +- **Part 2**: [Draw](#Draw) `(stroke)`, `(fill)`, `(gradient)`, `(clear)` +- **Part 3**: [Filters](#Filters) `(pixels)`, `(saturation)`, `(convolve)`, `(sharpen)` +- **Part 4**: [Events](#Events) `(echo)`, `(on "mouse-down")`, `(on "animate")`, `(on "/a")` + +## Images + +This section will teach the basics of opening, cropping and saving an image file. You can use the `$path` helper to quickly get an image's path into Ronin, by writing `$path` and dragging a file onto the Ronin window. + +### Import + +To import an image onto the current canvas, type the following text, drag an image file onto the Ronin window, trace a shape in the canvas and press `cmd+r`: + +```lisp +(import $path + (guide $rect)) +``` + +The previous code will import an image, and preserve its ratio. Alternatively, you could use a `$line` to stretch the image, or a `$pos` to simply draw the image at its original size. + +```lisp +(import $path + (guide $line)) +``` + +### Crop + +To crop the canvas, type the following text, drag an image file onto the Ronin window press `cmd+r`: + +```lisp +(import $path + (pos 0 0)) +(crop + (rect 50 50 300 300)) +``` + +### Export + +To export the resulting image, type the following text, drag an image file onto the Ronin window, then drag a folder and add the new file's name, and press `cmd+r`: + +```lisp +(import $path) +(export $path) +``` + +For example, a version of that same code with file paths, might look something like the following: + +```lisp +(import "~/Desktop/photo.jpg") +(export "~/Desktop/export.png") +``` + +You could also **generate the export path from the import path**. To import `~/Desktop/photo.jpg`, and automatically generate the export path `~/Desktop/photo-export.jpg`, use this: + +```lisp +(def import-path $path) +(def export-path + (concat + (dirpath import-path) "/" + (filename import-path) "-export.jpg")) +(import import-path) +(export export-path) +``` + +## Draw + +This section will teach you how to draw some basic shapes and colorize them. + +### Stroke + +In Ronin, a shape is either a `(rect)`, a `(line)`, a `(circle)` or a `(pos)`. To draw the outline of any shape, wrap the shape inside of a `(stroke shape width color)` function, like: + +```lisp +(stroke + (rect 100 100 300 200) "red" 10) +``` + +Or, if you would like to trace the shape with your mouse: + +```lisp +(stroke + $rect "red" 10) +``` + +### Fill + +To fill the inside of any shape, wrap it inside of a `(fill shape color)` function, like: + +```lisp +(fill + (rect 100 100 300 200) "orange") +``` + +### Gradient + +To colorize a stroke or a fill, with a gradient, use the `(gradient line colors)` where the colors is a list of colors like `("blue" "red" "yellow")`: + +```lisp +(clear) +(fill + (circle 300 300 200) + (gradient + (line 0 0 500 500) + ("white" "black"))) +``` + +To better understand how the `(line)` affects the coloring of the circle, wrap the `$line` inside a `(guide)`, as follows to preserve the guide interface: + +```lisp +(clear) +(fill + (circle 300 300 200) + (gradient + (guide $line) + ("white" "black"))) +``` + +### Clear + +In the previous example, we used the `(clear)` function, which clears the canvas, but it can also be used to clear only a part of the canvas: + +```lisp +(clear) +(fill + frame "red") +(clear + (rect 100 100 300 300)) +``` + +## Filters + +This section will cover how to manipulate the pixels of an image. + +### Pixels + +First let's open an image, ideally one in color, and change every pixel of a selected area at `(rect 100 100 200 200)`: + +```lisp +(import $path) +(pixels saturation 10 + (rect 100 100 200 200)) +``` + +The `(pixels)` function expects a function that returns 4 values(r,g,b,a), and so you can define a custom filter like: + +``` +(defn invert + (pixel) + ( + (sub 255 pixel:0) + (sub 255 pixel:1) + (sub 255 pixel:2) pixel:3)) +(pixels invert) +``` + +### saturation + +In the previous example, we increased the saturation of a region of the image, to desaturate an entire image, you can simply omit the `(rect)` which will select the entire canvas, and set the pixel filter to `saturation` and the value to `0.5`(50% saturation): + +```lisp +(import $path) +(pixels saturation 0.5) +``` + +### convolve + +Effects which use the surrounding pixels, or convolution matrix, are used with the `(convolve)` function, you can learn more about this family of filters [here](https://en.wikipedia.org/wiki/Kernel_(image_processing)). + +### sharpen + +```lisp +(import $path) +(convolve (sharpen) $rect) +``` + +Custom convolve kernels can also be created like this: + +```lisp +(import $path) +(def (blur) + ( + (-1 -1 -1) + (-1 5 -1) + (-1 -1 -1))) +(convolve (blur)) +``` + + + +## Events + +This section will demonstrate how to use events in Ronin to create interactive scripts. + +### Echo + +You can print some content to the screen in Ronin, by using the `(echo)` function, for example, the following script will write the word `hello` at the bottom left of the interface: + +```lisp +(echo "hello") +``` + +### MouseDown + +Let's use the `(debug)` function to display the position of the mouse cursor in the interface. + +```lisp +(on "mouse-down" echo) +``` + +We can define a function that triggers when the `mouse-down` event is detected, or when you click on the canvas: + +```lisp +; define the function +(defn draw-rect + (e) + (fill e:circle "red")) +; use the function +(on "mouse-move" draw-rect) +``` + +For more examples of functions, see the [examples](https://github.com/hundredrabbits/Ronin/tree/master/examples). + +You can find a more elaborate version of this example [here](https://github.com/hundredrabbits/Ronin/blob/master/examples/events/on-mouse.lisp). + +### Animate + +The `animate` event fires around 30 times per second, and is a perfect tool to create animations. Following the previous example, and the pattern of creating a function and binding it to the event, let's make a function that will use the `(time)` to animate a box: + +```lisp +; define the function +(defn wob-rect + () + ( + (clear) + (def rect-x 300) + (def rect-y (add (mul (sin (time 0.005)) 50) 300)) + (fill + (rect rect-x rect-y 100 100) "red"))) +; use the function +(on "animate" wob-rect) +``` + +You can find a more elaborate version of this example [here](https://github.com/hundredrabbits/Ronin/blob/master/examples/events/on-animate.lisp). + +### OSC + +Other programs can communicate with Ronin via OSC with the previous pattern. For example, if you send OSC data to the port `49162`, at the path `/a`, the event can be used in Ronin to trigger a function: + +```lisp +(on "/a" echo) +``` + +You can find a more elaborate version of this example [here](https://github.com/hundredrabbits/Ronin/blob/master/examples/events/on-osc.lisp). + +I hope this workshop has been enlightening, if you have questions or suggestions, please visit the [community](https://hundredrabbits.itch.io/ronin/community). Enjoy!