Browse Source

lazygit

feature/modules
Gregory Leeman 7 months ago
parent
commit
cdea98e7a0
  1. 6
      .eslintrc.json
  2. 27
      eslint.config.js
  3. 14
      index.html
  4. 4
      main.js
  5. 139
      package-lock.json
  6. 3
      package.json
  7. 95
      scripts/canvas.js
  8. 90
      scripts/color.js
  9. 16
      scripts/layer.js
  10. 4
      scripts/main.js
  11. 243
      styles/archive.css
  12. 194
      styles/main.css

6
.eslintrc.json

@ -1,6 +0,0 @@
{
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
}
}

27
eslint.config.js

@ -1,8 +1,21 @@
import globals from "globals"; // For ES Module Syntax
import pluginJs from "@eslint/js";
export default [ export default [
{languageOptions: { globals: globals.browser }}, {
pluginJs.configs.recommended, languageOptions: {
]; ecmaVersion: "latest", // Or specify a specific version like 2021, 2020, etc.
sourceType: "module", // "module" for ES modules, "script" for non-modular code
globals: {
// Define global variables that are predefined
browser: true,
node: true,
es6: true,
},
},
rules: {
"no-unused-vars": "off",
"semi": ["error", "always"],
"quotes": ["error", "double"]
}
}
];

14
index.html

@ -6,17 +6,21 @@
<link rel="stylesheet" href="styles/main.css"> <link rel="stylesheet" href="styles/main.css">
</head> </head>
<body> <body>
<div id="menu-bar"></div> <div id="menu-bar" class="bar"></div>
<div id="row"> <div id="row">
<div id="tool-bar"></div> <div id="tool-bar" class="bar"></div>
<div id="studio"> <div id="studio">
<div id="easel"></div> <div id="easel"></div>
</div> </div>
<div id="layer-bar"> <div id="layer-bar" class="bar">
<div id="layer-controllers"></div> <div id="layer-controllers"></div>
</div> </div>
</div> </div>
<div id="color-bar"></div> <div id="color-bar" class="bar"></div>
<script src="scripts/render.js"></script> <script src="scripts/mixbox.js"></script>
<script src="scripts/color.js"></script>
<script src="scripts/canvas.js"></script>
<script src="scripts/layer.js"></script>
<script src="scripts/main.js"></script>
</body> </body>
</html> </html>

4
main.js

@ -1,7 +1,7 @@
// main.js // main.js
const { app, BrowserWindow } = require('electron'); import { app, BrowserWindow } from 'electron';
const path = require('path'); import path from 'path';
function createWindow() { function createWindow() {
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({

139
package-lock.json

@ -8,9 +8,8 @@
"name": "mixx", "name": "mixx",
"version": "1.0.0", "version": "1.0.0",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.9.0",
"electron": "^31.3.1", "electron": "^31.3.1",
"eslint": "^9.9.0", "eslint": "^9.9.1",
"globals": "^15.9.0", "globals": "^15.9.0",
"nodemon": "^3.1.4" "nodemon": "^3.1.4"
} }
@ -73,9 +72,9 @@
} }
}, },
"node_modules/@eslint/config-array": { "node_modules/@eslint/config-array": {
"version": "0.17.1", "version": "0.18.0",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",
"integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.4", "@eslint/object-schema": "^2.1.4",
@ -122,9 +121,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.9.0", "version": "9.9.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz",
"integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -252,12 +251,12 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.14.15", "version": "20.16.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz",
"integrity": "sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==", "integrity": "sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~6.19.2"
} }
}, },
"node_modules/@types/responselike": { "node_modules/@types/responselike": {
@ -467,27 +466,6 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"node_modules/chalk/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/chalk/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": { "node_modules/chokidar": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@ -512,6 +490,18 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/clone-response": { "node_modules/clone-response": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
@ -665,9 +655,9 @@
"optional": true "optional": true
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "31.3.1", "version": "31.4.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-31.3.1.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz",
"integrity": "sha512-9fiuWlRhBfygtcT+auRd/WdBK/f8LZZcrpx0RjpXhH2DPTP/PfnkC4JB1PW55qCbGbh4wAgkYbf4ExIag8oGCA==", "integrity": "sha512-YTwKoAA+nrJMlI1TTHnIXLYWoQLKnhbkz0qxZcI7Hadcy0UaFMFs9xzwvH2MnrRpVJy7RKo49kVGuvSdRl8zMA==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
@ -743,16 +733,16 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.9.0", "version": "9.9.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz",
"integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==", "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.11.0", "@eslint-community/regexpp": "^4.11.0",
"@eslint/config-array": "^0.17.1", "@eslint/config-array": "^0.18.0",
"@eslint/eslintrc": "^3.1.0", "@eslint/eslintrc": "^3.1.0",
"@eslint/js": "9.9.0", "@eslint/js": "9.9.1",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.3.0", "@humanwhocodes/retry": "^0.3.0",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@ -829,18 +819,6 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint/node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/espree": { "node_modules/espree": {
"version": "10.1.0", "version": "10.1.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
@ -1089,15 +1067,15 @@
} }
}, },
"node_modules/glob-parent": { "node_modules/glob-parent": {
"version": "5.1.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"is-glob": "^4.0.1" "is-glob": "^4.0.3"
}, },
"engines": { "engines": {
"node": ">= 6" "node": ">=10.13.0"
} }
}, },
"node_modules/global-agent": { "node_modules/global-agent": {
@ -1205,12 +1183,12 @@
"dev": true "dev": true
}, },
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "3.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=4" "node": ">=8"
} }
}, },
"node_modules/has-property-descriptors": { "node_modules/has-property-descriptors": {
@ -1553,6 +1531,15 @@
"url": "https://opencollective.com/nodemon" "url": "https://opencollective.com/nodemon"
} }
}, },
"node_modules/nodemon/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/nodemon/node_modules/semver": { "node_modules/nodemon/node_modules/semver": {
"version": "7.6.3", "version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@ -1565,6 +1552,18 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/nodemon/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/normalize-path": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -1995,15 +1994,15 @@
} }
}, },
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"has-flag": "^3.0.0" "has-flag": "^4.0.0"
}, },
"engines": { "engines": {
"node": ">=4" "node": ">=8"
} }
}, },
"node_modules/text-table": { "node_modules/text-table": {
@ -2065,9 +2064,9 @@
"dev": true "dev": true
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "5.26.5", "version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true "dev": true
}, },
"node_modules/universalify": { "node_modules/universalify": {

3
package.json

@ -8,9 +8,8 @@
"start": "nodemon --exec electron ." "start": "nodemon --exec electron ."
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.9.0",
"electron": "^31.3.1", "electron": "^31.3.1",
"eslint": "^9.9.0", "eslint": "^9.9.1",
"globals": "^15.9.0", "globals": "^15.9.0",
"nodemon": "^3.1.4" "nodemon": "^3.1.4"
} }

95
scripts/canvas.js

@ -1,28 +1,25 @@
import { Color } from './color.js'; /* global makeColor */
function disableImageSmoothing({ctx}) { function disableImageSmoothing({ctx}) {
ctx.imageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false;
if (ctx.imageSmoothingEnabled !== false) { if (ctx.imageSmoothingEnabled !== false) {
ctx.mozImageSmoothingEnabled = false; ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
} }
}; };
class Canvas extends HTMLCanvasElement { // {{{ function makeCanvas({height, width}) {
constructor({height=600, width=800}) { const canvas = document.createElement("canvas");
super(); canvas.ctx = this.getContext("2d");
this.ctx = this.getContext('2d'); canvas.temp = document.createElement("canvas");
this.temp = document.createElement('canvas'); canvas.temp.ctx = this.temp.getContext("2d");
this.temp.ctx = this.temp.getContext('2d'); canvas.resize({height, width});
this.resize({height, width});
}
getData() { canvas.getData = function() {
return this.ctx.getImageData(0, 0, this.width, this.height).data; return this.ctx.getImageData(0, 0, this.width, this.height).data;
} };
fromDataUrl({dataUrl}) { canvas.fromDataUrl = function({dataUrl}) {
const image = new Image(); const image = new Image();
image.src = dataUrl; image.src = dataUrl;
image.onload = () => { image.onload = () => {
@ -34,54 +31,49 @@ class Canvas extends HTMLCanvasElement { // {{{
disableImageSmoothing(this.ctx); disableImageSmoothing(this.ctx);
}; };
return this; return this;
} };
setHeight({height}) { canvas.setHeight = function({height}) {
this.height = height; this.height = height;
this.style.height = `${height}px`; this.style.height = `${height}px`;
disableImageSmoothing(this.ctx); disableImageSmoothing(this.ctx);
return this; return this;
} };
setWidth({width}) { canvas.setWidth = function({width}) {
this.width = width; this.width = width;
this.style.width = `${width}px`; this.style.width = `${width}px`;
disableImageSmoothing(this.ctx); disableImageSmoothing(this.ctx);
return this; return this;
} };
resize({height, width}) { canvas.resize = function({height, width}) {
this.height = height; this.height = height;
this.width = width; this.width = width;
this.style.height = `${height}px`; this.style.height = `${height}px`;
this.style.width = `${width}px`; this.style.width = `${width}px`;
disableImageSmoothing(this.ctx); disableImageSmoothing(this.ctx);
return this; return this;
} };
clear() { canvas.clear = function() {
this.ctx.clearRect(0, 0, this.width, this.height); this.ctx.clearRect(0, 0, this.width, this.height);
return this; return this;
} };
fill({color}) { canvas.fill = function({color}) {
this.ctx.fillStyle = color.toRgbaString(); this.ctx.fillStyle = color.toRgbaString();
this.ctx.fillRect(0, 0, this.width, this.height); this.ctx.fillRect(0, 0, this.width, this.height);
return this; return this;
} };
getColorAtPixel({x, y}) { canvas.getColorAtPixel = function({x, y}) {
const data = this.getData(); const data = this.getData();
const index = (y * this.width + x) * 4; const index = (y * this.width + x) * 4;
return new Color().fromRgbaArray({ return makeColor({r: data[index], g: data[index + 1], b: data[index + 2], a: data[index + 3]});
r: data[index], };
g: data[index + 1],
b: data[index + 2],
a: data[index + 3]
});
}
setColorAtPixel({x, y, color}) { canvas.setColorAtPixel = function({x, y, color}) {
const data = this.getData(); const data = this.getData();
const index = (y * this.width + x) * 4; const index = (y * this.width + x) * 4;
const rgbaArray = color.toRgbaArray(); const rgbaArray = color.toRgbaArray();
@ -90,9 +82,9 @@ class Canvas extends HTMLCanvasElement { // {{{
data[index + 2] = rgbaArray[2]; // blue data[index + 2] = rgbaArray[2]; // blue
data[index + 3] = rgbaArray[3]; // alpha data[index + 3] = rgbaArray[3]; // alpha
return this; return this;
} };
drawLineWithPixels({x1, y1, x2, y2, color}) { canvas.drawLineWithPixels = function({x1, y1, x2, y2, color}) {
const dx = Math.abs(x2 - x1); const dx = Math.abs(x2 - x1);
const dy = Math.abs(y2 - y1); const dy = Math.abs(y2 - y1);
const sx = x1 < x2 ? 1 : -1; const sx = x1 < x2 ? 1 : -1;
@ -106,9 +98,9 @@ class Canvas extends HTMLCanvasElement { // {{{
if (e2 < dx) { err += dx; y1 += sy; } if (e2 < dx) { err += dx; y1 += sy; }
} }
return this; return this;
} };
drawEmptyRectangle({x, y, width, height, color}) { canvas.drawEmptyRectangle = function({x, y, width, height, color}) {
this.ctx.fillStyle = color.toRgbaString(); this.ctx.fillStyle = color.toRgbaString();
for (let x1 = x; x1 < x + width; x1++) { for (let x1 = x; x1 < x + width; x1++) {
this.setPixel(x1, y, color.toRgbaArray()); this.setPixel(x1, y, color.toRgbaArray());
@ -123,18 +115,18 @@ class Canvas extends HTMLCanvasElement { // {{{
this.setPixel(x + width, y1, color.toRgbaString()); this.setPixel(x + width, y1, color.toRgbaString());
} }
return this; return this;
} };
drawRectangle({x, y, width, height, color}) { canvas.drawRectangle = function({x, y, width, height, color}) {
for (let x1 = x; x1 < x + width; x1++) { for (let x1 = x; x1 < x + width; x1++) {
for (let y1 = y; y1 < y + height; y1++) { for (let y1 = y; y1 < y + height; y1++) {
this.setPixel(x1, y1, color.toRgbaString()); this.setPixel(x1, y1, color.toRgbaString());
} }
} }
return this; return this;
} };
drawEmptyCircle({x, y, diameter, color}) { canvas.drawEmptyCircle = function({x, y, diameter, color}) {
const radius = Math.floor(diameter / 2); const radius = Math.floor(diameter / 2);
for (let y1 = -radius; y1 <= radius; y1++) { for (let y1 = -radius; y1 <= radius; y1++) {
for (let x1 = -radius; x1 <= radius; x1++) { for (let x1 = -radius; x1 <= radius; x1++) {
@ -144,9 +136,9 @@ class Canvas extends HTMLCanvasElement { // {{{
} }
} }
return this; return this;
} };
drawCircle({x, y, diameter, color}) { canvas.drawCircle = function({x, y, diameter, color}) {
if (diameter === 1) { if (diameter === 1) {
this.drawPixel(x, y, color.toRgbaString()); this.drawPixel(x, y, color.toRgbaString());
} }
@ -161,9 +153,9 @@ class Canvas extends HTMLCanvasElement { // {{{
} }
} }
return this; return this;
} };
drawLineWithCircles({x1, y1, x2, y2, diameter, color}) { canvas.drawLineWithCircles = function({x1, y1, x2, y2, diameter, color}) {
const dx = x2 - x1; const dx = x2 - x1;
const dy = y2 - y1; const dy = y2 - y1;
const distance = Math.sqrt(dx * dx + dy * dy); const distance = Math.sqrt(dx * dx + dy * dy);
@ -174,9 +166,9 @@ class Canvas extends HTMLCanvasElement { // {{{
this.drawCircle(x, y, diameter, color.toRgbaString()); this.drawCircle(x, y, diameter, color.toRgbaString());
} }
return this; return this;
} };
floodFill({x, y, color}) { canvas.floodFill = function({x, y, color}) {
const targetColor = this.getColorAtPixel(x, y); const targetColor = this.getColorAtPixel(x, y);
const fillColor = color; const fillColor = color;
@ -196,10 +188,9 @@ class Canvas extends HTMLCanvasElement { // {{{
} }
} }
return this; return this;
} };
} return canvas;
// }}} }
export { Canvas, };

90
scripts/color.js

@ -1,76 +1,76 @@
import mixbox from './mixbox.js'; /* exported makeColor */
class Color { function makeColor({r=0, g=0, b=0, a=255}) {
constructor() { const color = {};
this.r = 0;
this.g = 0; color.r = r;
this.b = 0; color.g = g;
this.a = 0; color.b = b;
} color.a = a;
fromRgbaArray({rgbaArray}) { color.fromRgbaArray = function({rgbaArray}) {
this.r = rgbaArray[0]; color.r = rgbaArray[0];
this.g = rgbaArray[1]; color.g = rgbaArray[1];
this.b = rgbaArray[2]; color.b = rgbaArray[2];
this.a = rgbaArray[3]; color.a = rgbaArray[3];
return color;
} }
toRgbaArray() { color.toRgbaArray = function() {
return [this.r, this.g, this.b, this.a]; return [color.r, color.g, color.b, color.a];
} }
fromRgbaString({rgbaString}) { color.fromRgbaString = function({rgbaString}) {
this.r = rgbaString.split(',')[0].split('(')[1]; color.r = rgbaString.split(',')[0].split('(')[1];
this.g = rgbaString.split(',')[1]; color.g = rgbaString.split(',')[1];
this.b = rgbaString.split(',')[2]; color.b = rgbaString.split(',')[2];
this.a = rgbaString.split(',')[3].split(')')[0]; color.a = rgbaString.split(',')[3].split(')')[0];
return color;
} }
toRgbaString() { color.toRgbaString = function() {
return `rgba(${this.r},${this.g},${this.b},${this.a})`; return `rgba(${color.r},${color.g},${color.b},${color.a})`;
} }
fromRgbString(rgbString) { color.fromRgbString = function(rgbString) {
this.r = rgbString.split(',')[0].split('(')[1]; color.r = rgbString.split(',')[0].split('(')[1];
this.g = rgbString.split(',')[1]; color.g = rgbString.split(',')[1];
this.b = rgbString.split(',')[2].split(')')[0]; color.b = rgbString.split(',')[2].split(')')[0];
this.a = 255; color.a = 255;
return color;
} }
toRgbString() { color.toRgbString = function() {
return `rgb(${this.r},${this.g},${this.b})`; return `rgb(${color.r},${color.g},${color.b})`;
} }
matchRgbArray({rgbArray, tolereance = 2}) { color.matchRgbArray = function({rgbArray, tolerance = 2}) {
const color1RgbArray = this.toRgbArray(); const color1RgbArray = color.toRgbArray();
cosnt color2RgbArray = rgbArray; const color2RgbArray = rgbArray;
return return Math.abs(color1RgbArray[0] - color2RgbArray[0]) <= tolerance &&
Math.abs(color1RgbArray[0] - color2RgbArray[0]) <= tolerance &&
Math.abs(color1RgbArray[1] - color2RgbArray[1]) <= tolerance && Math.abs(color1RgbArray[1] - color2RgbArray[1]) <= tolerance &&
Math.abs(color1RgbArray[2] - color2RgbArray[2]) <= tolerance; Math.abs(color1RgbArray[2] - color2RgbArray[2]) <= tolerance;
} }
matchColor({color}) { color.matchColor = function({color}) {
return this.matchRgbArray({rgbArray: color.toRgbArray()}); return color.matchRgbArray({rgbArray: color.toRgbArray()});
} }
mixxRgbArray({rgbArray, t}) { color.mixxRgbArray = function({rgbArray, t}) {
const color1RgbArray = this.toRgbArray(); const color1RgbArray = color.toRgbArray();
const color2RgbArray = rgbArray; const color2RgbArray = rgbArray;
var color3RgbArray; var color3RgbArray;
if (this.matchRgbArray({rgbArray: color2RgbArray})) { if (color.matchRgbArray({rgbArray: color2RgbArray})) {
color3RgbArray = color2RgbArray; color3RgbArray = color2RgbArray;
} else { } else {
color3RgbArray = mixbox.lerp(color2, color2, t); color3RgbArray = mixbox.lerp(color1RgbArray, color2RgbArray, t);
} }
this.fromRgbArray(color3RgbArray); return color.fromRgbArray(color3RgbArray);
return this;
} }
mixxColor({color, t}) { color.mixxColor = function({color, t}) {
this.mixxRgbArray({rgbArray: color.toRgbArray(), t}); color.mixxRgbArray({rgbArray: color.toRgbArray(), t});
} }
} }
export { Color, };

16
scripts/layer.js

@ -1,7 +1,4 @@
import { Canvas } from './canvas.js'; class Layer {
import { Color } from './color.js';
class Layer { // {{{
constructor({height=600, width=800}) { constructor({height=600, width=800}) {
this.drawCanvas = new Canvas({height, width}); this.drawCanvas = new Canvas({height, width});
this.selectCanvas = new Canvas({height, width}); this.selectCanvas = new Canvas({height, width});
@ -40,9 +37,7 @@ class Layer { // {{{
} }
// }}} class Layers {
class Layers { // {{{
constructor({easelElement, controllersElement, height=600, width=800, backgroundColor=new Color(255, 255, 255)}) { constructor({easelElement, controllersElement, height=600, width=800, backgroundColor=new Color(255, 255, 255)}) {
this.backgroundColor = backgroundColor; this.backgroundColor = backgroundColor;
this.height = height; this.height = height;
@ -55,6 +50,7 @@ class Layers { // {{{
new Layer({height: this.height, width: this.width}) new Layer({height: this.height, width: this.width})
]; ];
this.activeIndex = 1; this.activeIndex = 1;
this.refresh();
} }
@ -156,6 +152,7 @@ class Layers { // {{{
refreshEasel() { refreshEasel() {
this.easelElement.innerHTML = ''; this.easelElement.innerHTML = '';
this.layers.forEach(layer => { this.layers.forEach(layer => {
console.log("test");
this.easelElement.appendChild(layer.drawCanvas); this.easelElement.appendChild(layer.drawCanvas);
this.easelElement.appendChild(layer.selectCanvas); this.easelElement.appendChild(layer.selectCanvas);
}); });
@ -238,13 +235,10 @@ class Layers { // {{{
} }
refresh() { refresh() {
console.log("test");
this.refreshEasel(); this.refreshEasel();
this.refreshControllers(); this.refreshControllers();
this.refreshPreviews(); this.refreshPreviews();
} }
} }
// }}}
export { Layer, Layers };

4
scripts/render.js → scripts/main.js

@ -39,6 +39,8 @@ let isMouseDown = false;
let interval; let interval;
var startTime; var startTime;
document.on
const layers = new Layers({ const layers = new Layers({
easelElement: easelElement, easelElement: easelElement,
controllersElement: layerControllersElement, controllersElement: layerControllersElement,
@ -53,7 +55,7 @@ const tools = new Tools({
tools.addTool({ // brush {{{ tools.addTool({ // brush {{{
name: 'Brush', name: 'Brush',
key: 'b', key: 'b',
iconPath: 'icons/brush.png', iconPath: 'icons/brush.svg',
mouseMove: () => { mouseMove: () => {
const canvas = layers.getActive().selectCanvas; const canvas = layers.getActive().selectCanvas;
canvas canvas

243
styles/archive.css

@ -0,0 +1,243 @@
:root {
--white: #FFFFFF;
--button: #DDE4E7;
--hover: #B3BBBD;
--active: #8F9598;
/* --background: #7E888B; */
--background: #949C9E;
--black: #000000;
}
@font-face {
font-family: 'VT323';
src: url('fonts/VT323-Regular.ttf') format('truetype');
}
div {
box-sizing: border-box;
}
body {
margin: 0;
overflow: hidden;
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
font-family: 'VT323', monospace;
background-color: var(--background);
color: var(--black);
}
#menu-bar,
#info-bar,
#tool-bar,
#layer-bar {
z-index: 2;
}
#menu-bar {
justify-content: space-between;
}
#menu-bar, #info-bar {
padding: 10px;
background-color: var(--button);
display: flex;
flex-direction: row;
gap: 10px;
justify-content: flex-start;
flex-wrap: wrap;
}
#menu-bar {
order: 1;
}
#info-bar {
order: 3;
}
#tool-bar, #layer-bar {
display: flex;
padding: 10px;
padding-top: 0;
padding-bottom: 0;
background-color: var(--button);
gap: 10px;
height: 100%;
flex-direction: column;
justify-content: flex-start;
}
#studio {
flex-grow: 1;
height: 100%;
border: 1px solid;
cursor: crosshair;
}
#easel {
position: absolute;
border: 1px solid;
z-index: -1;
}
.button {
background-color: var(--button);
border: 1px solid;
border-radius: 2px;
cursor: pointer;
display: flex;
text-align: center;
justify-content: center;
}
.button:hover {
background-color: var(--hover);
}
.button.active, .button:active {
background-color: var(--active);
}
.bar-button {
position: relative;
flex-shrink: 0;
width: 30px;
height: 30px;
padding: 5px;
flex-direction: column;
}
.puck {
position: relative;
flex-shrink: 0;
width: 30px;
height: 30px;
border: 1px solid;
border-radius: 2px;
}
.key-hint {
display: block;
height: 13px;
width: 9px;
line-height: 8px;
position: absolute;
top: 2px;
left: 1px;
font-size: 1em;
justify-content: center;
text-align: center;
border-radius: 0 0 5px 0;
text-shadow:
1px 1px 0 #000,
-1px 1px 0 #000,
-1px -1px 0 #000,
1px -1px 0 #000;
color: var(--white);
pointer-events: none;
}
#layer-controllers {
background-color: var(--background);
border: 1px solid;
height: 100%;
}
.layer-controller {
background-color: var(--button);
height: 40px;
width: 90px;
border: 1px solid;
border-radius: 2px;
padding: 2px;
position: relative;
margin: 1px;
display: flex;
flex-direction: row;
gap: 2px;
align-items: center;
justify-content: space-between;
}
.layer-controller.active {
background-color: var(--active);
}
.layer-controller:hover {
background-color: var(--hover);
}
.layer-add-button {
background-color: var(--button);
height: 12px;
width: 100%;
border: 1px solid;
border-radius: 2px;
position: relative;
margin: 1px;
text-align: center;
font-size: .7em;
cursor: pointer;
}
.layer-add-button:hover {
background-color: var(--hover);
}
.top-left {
top: 0;
left: 0;
}
.bottom-right {
bottom: 0;
right: 0;
}
.top-right {
top: 0;
right: 0;
}
.bottom-left {
bottom: 0;
left: 0;
}
.layer-preview {
width: 30px;
height: 30px;
border: 1px solid;
object-fit: contain;
background-color: var(--background);
cursor: pointer;
}
.layer-move-buttons, .layer-merge-buttons {
font-size: .7em;
display: flex;
flex-direction: column;
gap: 2px;
flex-grow: 1;
height: 100%;
}
.layer-delete-button {
font-size: .7em;
flex-grow: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.layer-move-button, .layer-merge-button {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
}

194
styles/main.css

@ -3,7 +3,6 @@
--button: #DDE4E7; --button: #DDE4E7;
--hover: #B3BBBD; --hover: #B3BBBD;
--active: #8F9598; --active: #8F9598;
/* --background: #7E888B; */
--background: #949C9E; --background: #949C9E;
--black: #000000; --black: #000000;
} }
@ -29,52 +28,28 @@ body {
color: var(--black); color: var(--black);
} }
#menu-bar, .bar {
#info-bar,
#tool-bar,
#layer-bar {
z-index: 2; z-index: 2;
}
#menu-bar {
justify-content: space-between;
}
#menu-bar, #info-bar {
padding: 10px;
background-color: var(--button); background-color: var(--button);
display: flex; display: flex;
flex-direction: row;
gap: 10px; gap: 10px;
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} padding: 10px;
#menu-bar {
order: 1;
}
#info-bar {
order: 3;
} }
#row { #row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-grow: 1; flex-grow: 1;
order: 2; }
#menu-bar, #color-bar {
flex-direction: row;
} }
#tool-bar, #layer-bar { #tool-bar, #layer-bar {
display: flex;
padding: 10px;
padding-top: 0;
padding-bottom: 0;
background-color: var(--button);
gap: 10px;
height: 100%;
flex-direction: column; flex-direction: column;
justify-content: flex-start;
} }
#studio { #studio {
@ -96,160 +71,3 @@ canvas {
left: 0; left: 0;
} }
.button {
background-color: var(--button);
border: 1px solid;
border-radius: 2px;
cursor: pointer;
display: flex;
text-align: center;
justify-content: center;
}
.button:hover {
background-color: var(--hover);
}
.button.active, .button:active {
background-color: var(--active);
}
.bar-button {
position: relative;
flex-shrink: 0;
width: 30px;
height: 30px;
padding: 5px;
flex-direction: column;
}
.puck {
position: relative;
flex-shrink: 0;
width: 30px;
height: 30px;
border: 1px solid;
border-radius: 2px;
}
.key-hint {
display: block;
height: 13px;
width: 9px;
line-height: 8px;
position: absolute;
top: 2px;
left: 1px;
font-size: 1em;
justify-content: center;
text-align: center;
border-radius: 0 0 5px 0;
text-shadow:
1px 1px 0 #000,
-1px 1px 0 #000,
-1px -1px 0 #000,
1px -1px 0 #000;
color: var(--white);
pointer-events: none;
}
#layer-controllers {
background-color: var(--background);
border: 1px solid;
height: 100%;
}
.layer-controller {
background-color: var(--button);
height: 40px;
width: 90px;
border: 1px solid;
border-radius: 2px;
padding: 2px;
position: relative;
margin: 1px;
display: flex;
flex-direction: row;
gap: 2px;
align-items: center;
justify-content: space-between;
}
.layer-controller.active {
background-color: var(--active);
}
.layer-controller:hover {
background-color: var(--hover);
}
.layer-add-button {
background-color: var(--button);
height: 12px;
width: 100%;
border: 1px solid;
border-radius: 2px;
position: relative;
margin: 1px;
text-align: center;
font-size: .7em;
cursor: pointer;
}
.layer-add-button:hover {
background-color: var(--hover);
}
.top-left {
top: 0;
left: 0;
}
.bottom-right {
bottom: 0;
right: 0;
}
.top-right {
top: 0;
right: 0;
}
.bottom-left {
bottom: 0;
left: 0;
}
.layer-preview {
width: 30px;
height: 30px;
border: 1px solid;
object-fit: contain;
background-color: var(--background);
cursor: pointer;
}
.layer-move-buttons, .layer-merge-buttons {
font-size: .7em;
display: flex;
flex-direction: column;
gap: 2px;
flex-grow: 1;
height: 100%;
}
.layer-delete-button {
font-size: .7em;
flex-grow: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.layer-move-button, .layer-merge-button {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
}

Loading…
Cancel
Save