From d6acfe9c93cafb82ab663776756de772f24fc84d Mon Sep 17 00:00:00 2001 From: Ben McGraw Date: Sat, 16 Jul 2022 23:20:23 -0700 Subject: [PATCH 1/2] add support for project-relative paths and json-relative paths to chr json files, superceding whatever garbage there was before --- .babelrc | 4 + .vscode/settings.json | 7 + package-lock.json | 487 ++++- package.json | 331 +-- src/Map.js | 4083 ++++++++++++++++++++---------------- src/js/ui/EntityPalette.js | 1848 ++++++++-------- src/main/BaseSetup.js | 2242 ++++++++++---------- src/main/main.ts | 10 +- webpack.main.config.js | 8 +- 9 files changed, 5012 insertions(+), 4008 deletions(-) create mode 100644 .babelrc create mode 100644 .vscode/settings.json diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..ec07443 --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env"], + "plugins": [["@babel/plugin-transform-runtime"]] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..788514f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "workbench.colorCustomizations": { + "activityBar.background": "#60090E", + "titleBar.activeBackground": "#860C14", + "titleBar.activeForeground": "#FFFBFB" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ca24b52..db603d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -159,6 +159,203 @@ "lodash": "^4.17.13" } }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "dev": true + }, + "@babel/generator": { + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", + "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", + "dev": true, + "requires": { + "@babel/types": "^7.18.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", + "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-function-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", + "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.8.tgz", + "integrity": "sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA==", + "dev": true + }, + "@babel/template": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/traverse": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.8.tgz", + "integrity": "sha512-UNg/AcSySJYR/+mIcJQDCv00T+AqRO7j/ZEJLzpaYtgM48rMg5MnkJgyNqkzo88+p4tfRvZJCEiwwfG6h4jkRg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.7", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.8", + "@babel/types": "^7.18.8", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.8.tgz", + "integrity": "sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "browserslist": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", + "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001366", + "electron-to-chromium": "^1.4.188", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.4" + } + }, + "caniuse-lite": { + "version": "1.0.30001367", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz", + "integrity": "sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.192", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.192.tgz", + "integrity": "sha512-8nCXyIQY9An88NXAp+PuPy5h3/w5ZY7Iu2lag65Q0XREprcat5F8gKhoHsBUnQcFuCRnmevpR8yEBYRU3d2HDw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", + "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "dev": true + }, "@babel/helper-explode-assignable-expression": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", @@ -298,6 +495,18 @@ "@babel/types": "^7.8.3" } }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, "@babel/helper-wrap-function": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", @@ -809,6 +1018,53 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-transform-runtime": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.6.tgz", + "integrity": "sha512-8uRHk9ZmRSnWqUgyae249EJZ94b0yAGLBIqzZzl+0iEdbno55Pmlt/32JZsHwXD9k/uZj18Aqqk35wBX4CBTXA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-polyfill-corejs2": "^0.3.1", + "babel-plugin-polyfill-corejs3": "^0.5.2", + "babel-plugin-polyfill-regenerator": "^0.3.1", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", + "dev": true + }, + "@babel/types": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.8.tgz", + "integrity": "sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", @@ -976,11 +1232,18 @@ } }, "@babel/runtime": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", - "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz", + "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==", "requires": { - "regenerator-runtime": "^0.13.2" + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + } } }, "@babel/runtime-corejs3": { @@ -1322,6 +1585,45 @@ "@types/yargs": "^13.0.0" } }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", @@ -2795,6 +3097,115 @@ "@types/babel__traverse": "^7.0.6" } }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "dependencies": { + "@babel/compat-data": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "dependencies": { + "browserslist": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", + "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001366", + "electron-to-chromium": "^1.4.188", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.4" + } + }, + "caniuse-lite": { + "version": "1.0.30001367", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz", + "integrity": "sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==", + "dev": true + }, + "core-js-compat": { + "version": "3.23.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.4.tgz", + "integrity": "sha512-RkSRPe+JYEoflcsuxJWaiMPhnZoFS51FcIxm53k4KzhISCBTmaGlto9dTIrYuk0hnJc3G6pKufAKepHnBq6B6Q==", + "dev": true, + "requires": { + "browserslist": "^4.21.1", + "semver": "7.0.0" + } + }, + "electron-to-chromium": { + "version": "1.4.192", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.192.tgz", + "integrity": "sha512-8nCXyIQY9An88NXAp+PuPy5h3/w5ZY7Iu2lag65Q0XREprcat5F8gKhoHsBUnQcFuCRnmevpR8yEBYRU3d2HDw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" + } + } + }, "babel-preset-jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", @@ -2809,7 +3220,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -2818,8 +3228,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" } } }, @@ -4860,8 +5269,7 @@ "core-js": { "version": "2.6.11", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" }, "core-js-compat": { "version": "3.6.4", @@ -6536,6 +6944,12 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -8031,8 +8445,7 @@ "version": "2.1.1", "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -8081,8 +8494,7 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", @@ -8095,8 +8507,7 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -8227,8 +8638,7 @@ "version": "2.0.4", "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.8", @@ -8242,7 +8652,6 @@ "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -8269,7 +8678,6 @@ "resolved": false, "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -8290,7 +8698,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "optional": true, "requires": { "minimist": "^1.2.5" } @@ -8389,8 +8796,7 @@ "version": "1.0.1", "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -8404,7 +8810,6 @@ "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -8500,8 +8905,7 @@ "version": "5.1.2", "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -8543,7 +8947,6 @@ "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8565,7 +8968,6 @@ "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -8614,15 +9016,13 @@ "version": "1.0.2", "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "resolved": false, "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "optional": true + "dev": true } } }, @@ -11665,6 +12065,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -13429,6 +13835,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -14211,7 +14623,8 @@ "regenerator-runtime": { "version": "0.13.3", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true }, "regenerator-transform": { "version": "0.14.1", @@ -16894,6 +17307,16 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "update-notifier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.0.0.tgz", diff --git a/package.json b/package.json index 5137780..3f121a8 100644 --- a/package.json +++ b/package.json @@ -1,172 +1,175 @@ { - "name": "Breaditor", - "version": "2.0.1", - "description": "", - "main": "./dist/main.js", - "scripts": { - "build-main": "cross-env NODE_ENV=production webpack --config webpack.main.prod.config.js", - "build-renderer": "cross-env NODE_ENV=production webpack --config webpack.renderer.prod.config.js", - "build": "npm run build-main && npm run build-renderer", - "start-renderer-dev": "webpack-dev-server --config webpack.renderer.dev.config.js", - "start-main-dev": "webpack --config webpack.main.config.js && electron ./dist/main.js", - "start-dev": "cross-env NODE_ENV=test START_HOT=1 npm run start-renderer-dev", - "dev": "npm run start-dev", - "prestart": "npm run build", - "start": "electron .", - "lint": "eslint --ext=jsx,js,tsx,ts src", - "lint-fix": "eslint --fix --ext=jsx,js,tsx,ts src", - "test": "jest --detectOpenHandles", - "watch": "jest --detectOpenHandles --watchAll", - "pretest:e2e": "npm run build", - "test:e2e": "jest --testMatch '**/?(*.)+(e2etest).[tj]s?(x)'", - "test-circle": "npm test && npm run test:e2e", - "pack": "npm run build && electron-builder --dir", - "dist": "npm run build && electron-builder", - "postinstall": "electron-builder install-app-deps" - }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" - } - }, - "lint-staged": { - "{src,test,mocks}/**/*.{json,css,scss,md}": [ - "prettier --config ./.prettierrc --write" - ], - "{src,test,mocks}/**/*.{js,ts,tsx}": [ - "prettier --config ./.prettierrc --write", - "eslint --ext=jsx,js,ts,tsx --fix src" - ] - }, - "jest": { - "transform": { - "^.+\\.(j|t)sx?$": "ts-jest" + "name": "breaditor", + "version": "2.0.2", + "description": "", + "main": "./dist/main.js", + "scripts": { + "build-main": "cross-env NODE_ENV=production webpack --config webpack.main.prod.config.js", + "build-renderer": "cross-env NODE_ENV=production webpack --config webpack.renderer.prod.config.js", + "build": "npm run build-main && npm run build-renderer", + "start-renderer-dev": "webpack-dev-server --config webpack.renderer.dev.config.js", + "start-main-dev": "webpack --config webpack.main.config.js && electron ./dist/main.js", + "start-dev": "cross-env NODE_ENV=test START_HOT=1 npm run start-renderer-dev", + "dev": "npm run start-dev", + "prestart": "npm run build", + "start": "electron .", + "lint": "eslint --ext=jsx,js,tsx,ts src", + "lint-fix": "eslint --fix --ext=jsx,js,tsx,ts src", + "test": "jest --detectOpenHandles", + "watch": "jest --detectOpenHandles --watchAll", + "pretest:e2e": "npm run build", + "test:e2e": "jest --testMatch '**/?(*.)+(e2etest).[tj]s?(x)'", + "test-circle": "npm test && npm run test:e2e", + "pack": "npm run build && electron-builder --dir", + "dist": "npm run build && electron-builder", + "postinstall": "electron-builder install-app-deps" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "{src,test,mocks}/**/*.{json,css,scss,md}": [ + "prettier --config ./.prettierrc --write" + ], + "{src,test,mocks}/**/*.{js,ts,tsx}": [ + "prettier --config ./.prettierrc --write", + "eslint --ext=jsx,js,ts,tsx --fix src" + ] + }, + "jest": { + "transform": { + "^.+\\.(j|t)sx?$": "ts-jest" + }, + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "json", + "node" + ], + "moduleNameMapper": { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/mocks/fileMock.js", + "\\.(s?css|sass)$": "/mocks/styleMock.js" + }, + "setupFiles": [ + "./setup-jest.js" + ] + }, + "build": { + "productName": "Breaditor", + "appId": "com.breadbros.breaditor", + "mac": { + "category": "public.app-category.developer-tools" + }, + "directories": { + "output": "release" + }, + "files": [ + "dist/", + "node_modules/", + "package.json" + ], + "linux": { + "target": "deb" + }, + "win": { + "target": "nsis" + } }, - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "json", - "node" - ], - "moduleNameMapper": { - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/mocks/fileMock.js", - "\\.(s?css|sass)$": "/mocks/styleMock.js" + "repository": { + "type": "git", + "url": "git+ssh://git@github.com:Robinfr/electron-react-typescript.git" }, - "setupFiles": [ - "./setup-jest.js" - ] - }, - "build": { - "productName": "Breaditor", - "appId": "com.breadbros.breaditor", - "mac": { - "category": "public.app-category.developer-tools" + "author": { + "name": "Ben McGraw", + "email": "ben@breadbros.com" }, - "directories": { - "output": "release" + "license": "MIT License", + "bugs": { + "url": "https://github.com/mcgrue/breaditor/issues" }, - "files": [ - "dist/", - "node_modules/", - "package.json" - ], - "linux": { - "target": "deb" + "homepage": "https://breaditor.com", + "devDependencies": { + "@babel/core": "^7.4.5", + "@babel/plugin-proposal-class-properties": "^7.4.4", + "@babel/plugin-transform-runtime": "^7.18.6", + "@babel/polyfill": "^7.4.4", + "@babel/preset-env": "^7.4.5", + "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.3.3", + "@hot-loader/react-dom": "^16.8.6", + "@types/electron-devtools-installer": "^2.2.0", + "@types/jest": "^24.0.13", + "@types/react": "^16.8.18", + "@types/react-dom": "^16.8.4", + "@types/react-redux": "^7.0.9", + "@types/react-test-renderer": "^16.8.1", + "@types/webdriverio": "^4.8.7", + "@types/webpack-env": "^1.13.3", + "@typescript-eslint/eslint-plugin": "^2.4.0", + "@typescript-eslint/parser": "^2.4.0", + "babel-loader": "^8.0.6", + "clean-webpack-plugin": "^3.0.0", + "copy-webpack-plugin": "^6.3.2", + "cross-env": "^5.1.3", + "css-loader": "^2.1.1", + "electron": "^3.1.9", + "electron-builder": "^22.3.2", + "electron-devtools-installer": "^2.2.4", + "eslint": "^6.5.1", + "eslint-config-airbnb": "^18.0.1", + "eslint-config-prettier": "^6.4.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-jsx-a11y": "^6.2.3", + "eslint-plugin-prettier": "^3.1.1", + "eslint-plugin-react": "^7.16.0", + "eslint-plugin-react-hooks": "^1.7.0", + "file-loader": "^3.0.1", + "fork-ts-checker-webpack-plugin": "^1.3.4", + "html-webpack-plugin": "^3.2.0", + "husky": "^4.2.1", + "image-webpack-loader": "^4.6.0", + "jest": "^24.8.0", + "lint-staged": "^10.0.7", + "node-sass": "^4.12.0", + "prettier": "^1.18.2", + "react-hot-loader": "^4.8.8", + "react-test-renderer": "^16.8.6", + "redux-devtools-extension": "^2.13.5", + "sass-loader": "^7.1.0", + "source-map-loader": "^0.2.4", + "spectron": "^5.0.0", + "style-loader": "^0.23.1", + "ts-jest": "^24.0.2", + "typescript": "^3.4.5", + "webpack": "^4.32.2", + "webpack-cli": "^3.3.2", + "webpack-dev-server": "^3.11.2", + "webpack-merge": "^4.2.1" }, - "win": { - "target": "nsis" + "dependencies": { + "@babel/runtime": "^7.18.6", + "@sphinxxxx/color-conversion": "^2.2.2", + "@types/jquery": "^3.5.5", + "@types/react-panelgroup": "^1.0.1", + "@types/source-map-support": "^0.5.3", + "babel-polyfill": "^6.26.0", + "electron-canvas-to-buffer": "^2.0.0", + "fs-jetpack": "^1.3.1", + "jquery": "^3.6.0", + "lodash": "^4.17.20", + "natives": "^1.1.6", + "pngjs": "^6.0.0", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-panelgroup": "^1.0.12", + "react-redux": "^7.0.3", + "redux": "^4.0.1", + "source-map-support": "^0.5.19", + "sprintf-js": "^1.0.3", + "ui-contextmenu": "^1.18.1", + "uuid": "^8.0.0" } - }, - "repository": { - "type": "git", - "url": "git+ssh://git@github.com:Robinfr/electron-react-typescript.git" - }, - "author": { - "name": "Ben McGraw", - "email": "ben@breadbros.com" - }, - "license": "MIT License", - "bugs": { - "url": "https://github.com/mcgrue/breaditor/issues" - }, - "homepage": "https://breaditor.com", - "devDependencies": { - "@babel/core": "^7.4.5", - "@babel/plugin-proposal-class-properties": "^7.4.4", - "@babel/polyfill": "^7.4.4", - "@babel/preset-env": "^7.4.5", - "@babel/preset-react": "^7.0.0", - "@babel/preset-typescript": "^7.3.3", - "@hot-loader/react-dom": "^16.8.6", - "@types/electron-devtools-installer": "^2.2.0", - "@types/jest": "^24.0.13", - "@types/react": "^16.8.18", - "@types/react-dom": "^16.8.4", - "@types/react-redux": "^7.0.9", - "@types/react-test-renderer": "^16.8.1", - "@types/webdriverio": "^4.8.7", - "@types/webpack-env": "^1.13.3", - "@typescript-eslint/eslint-plugin": "^2.4.0", - "@typescript-eslint/parser": "^2.4.0", - "babel-loader": "^8.0.6", - "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.3.2", - "cross-env": "^5.1.3", - "css-loader": "^2.1.1", - "electron": "^3.1.9", - "electron-builder": "^22.3.2", - "electron-devtools-installer": "^2.2.4", - "eslint": "^6.5.1", - "eslint-config-airbnb": "^18.0.1", - "eslint-config-prettier": "^6.4.0", - "eslint-plugin-import": "^2.18.2", - "eslint-plugin-jsx-a11y": "^6.2.3", - "eslint-plugin-prettier": "^3.1.1", - "eslint-plugin-react": "^7.16.0", - "eslint-plugin-react-hooks": "^1.7.0", - "file-loader": "^3.0.1", - "fork-ts-checker-webpack-plugin": "^1.3.4", - "html-webpack-plugin": "^3.2.0", - "husky": "^4.2.1", - "image-webpack-loader": "^4.6.0", - "jest": "^24.8.0", - "lint-staged": "^10.0.7", - "node-sass": "^4.12.0", - "prettier": "^1.18.2", - "react-hot-loader": "^4.8.8", - "react-test-renderer": "^16.8.6", - "redux-devtools-extension": "^2.13.5", - "sass-loader": "^7.1.0", - "source-map-loader": "^0.2.4", - "spectron": "^5.0.0", - "style-loader": "^0.23.1", - "ts-jest": "^24.0.2", - "typescript": "^3.4.5", - "webpack": "^4.32.2", - "webpack-cli": "^3.3.2", - "webpack-dev-server": "^3.11.2", - "webpack-merge": "^4.2.1" - }, - "dependencies": { - "@sphinxxxx/color-conversion": "^2.2.2", - "@types/jquery": "^3.5.5", - "@types/react-panelgroup": "^1.0.1", - "@types/source-map-support": "^0.5.3", - "electron-canvas-to-buffer": "^2.0.0", - "fs-jetpack": "^1.3.1", - "jquery": "^3.6.0", - "lodash": "^4.17.20", - "natives": "^1.1.6", - "pngjs": "^6.0.0", - "react": "^16.8.6", - "react-dom": "^16.8.6", - "react-panelgroup": "^1.0.12", - "react-redux": "^7.0.3", - "redux": "^4.0.1", - "source-map-support": "^0.5.19", - "sprintf-js": "^1.0.3", - "ui-contextmenu": "^1.18.1", - "uuid": "^8.0.0" - } } diff --git a/src/Map.js b/src/Map.js index 75b0f2b..71b603b 100644 --- a/src/Map.js +++ b/src/Map.js @@ -1,18 +1,26 @@ import { MakeUndoRedoStack } from './UndoRedo'; -import { LOG, INFO, WARN} from './Logging'; -import { getObsVisibility, MAGICAL_OBS_LAYER_ID, MAGICAL_ZONE_LAYER_ID , getSelectedLayer } from './js/ui/LayersPalette'; +import { LOG, INFO, WARN } from './Logging'; +import { + getObsVisibility, + MAGICAL_OBS_LAYER_ID, + MAGICAL_ZONE_LAYER_ID, + getSelectedLayer +} from './js/ui/LayersPalette'; import { ShaderProgram } from './ShaderProgram.js'; import { updateRstringInfo, updateInfoDims, updateLocationText, updateZoomText } from './Tools.js'; import { getZoneVisibility, getZoneAlpha } from './js/ui/ZonesPalette'; -import { getNormalEntityVisibility, shouldShowEntitiesForLayer, generate_unique_entity_uuid_for_this_map } from './js/ui/EntityPalette.js'; +import { + getNormalEntityVisibility, + shouldShowEntitiesForLayer, + generate_unique_entity_uuid_for_this_map +} from './js/ui/EntityPalette.js'; import { notify } from './Notification-Pane'; - const path = require('path'); -const {sprintf} = require('sprintf-js'); +const { sprintf } = require('sprintf-js'); -const {$} = window; +const { $ } = window; const ENTITY_PREVIEW_ALPHA = 0.75; const ANIMATE_TILES = true; // TODO hook this up to a toggle in the UI @@ -31,712 +39,744 @@ export const checkerColorB = [1.0, 1.0, 1.0, 1.0]; let lastKnownPath = ''; -export const heal_uuids_for_this_map = (map) => { - const currentEntities = map.mapData.entities; - for (let i = currentEntities.length - 1; i >= 0; i--) { - if( !currentEntities[i].uuid ) { - currentEntities[i].uuid = generate_unique_entity_uuid_for_this_map(map); +export const heal_uuids_for_this_map = map => { + const currentEntities = map.mapData.entities; + for (let i = currentEntities.length - 1; i >= 0; i--) { + if (!currentEntities[i].uuid) { + currentEntities[i].uuid = generate_unique_entity_uuid_for_this_map(map); + } } - } - map.mapData.entities = currentEntities; + map.mapData.entities = currentEntities; }; -export const cleanEntities = (mapData) => { - for (let i = mapData.entities.length - 1; i >= 0; i--) { - if (mapData.entities[i].MAPED_USEDEFAULT) { - delete mapData.entities[i].MAPED_USEDEFAULT; - } +export const cleanEntities = mapData => { + for (let i = mapData.entities.length - 1; i >= 0; i--) { + if (mapData.entities[i].MAPED_USEDEFAULT) { + delete mapData.entities[i].MAPED_USEDEFAULT; + } - if (mapData.entities[i].MAPED_HIGHLIGHTED) { - delete mapData.entities[i].MAPED_HIGHLIGHTED; + if (mapData.entities[i].MAPED_HIGHLIGHTED) { + delete mapData.entities[i].MAPED_HIGHLIGHTED; + } } - } }; const animateAlpha = (t, swag) => { - return Math.sin(t / swag) * 0.3 + 0.5; + return Math.sin(t / swag) * 0.3 + 0.5; }; // Builds an image (well a uint8 array) where each pixel of the image maps to a tile index on the vsp. // A very dark minimap. const buildTileDataTexture = (data, anims) => { - const now = Date.now() / 10; // the delay is in centiseconds - const out = new Uint8Array(data.length * 4); - for (let i = 0; i < data.length; i++) { - let t = data[i]; - - if (anims && anims[t]) { - const anim = anims[t]; - const frameCount = 1 + anim.end - anim.start; - const frame = Math.floor(now / anim.delay) % frameCount; - t = anim.start + frame; - } + const now = Date.now() / 10; // the delay is in centiseconds + const out = new Uint8Array(data.length * 4); + for (let i = 0; i < data.length; i++) { + let t = data[i]; + + if (anims && anims[t]) { + const anim = anims[t]; + const frameCount = 1 + anim.end - anim.start; + const frame = Math.floor(now / anim.delay) % frameCount; + t = anim.start + frame; + } - out[i * 4 + 0] = t % 256; - out[i * 4 + 1] = (t >> 8) % 256; - out[i * 4 + 2] = (t >> 16) % 256; - out[i * 4 + 3] = (t >> 24) % 256; - } - return out; + out[i * 4 + 0] = t % 256; + out[i * 4 + 1] = (t >> 8) % 256; + out[i * 4 + 2] = (t >> 16) % 256; + out[i * 4 + 3] = (t >> 24) % 256; + } + return out; }; let __obsColor = [1, 1, 1, 0.5]; export const setObsColor = (r, g, b, a) => { - __obsColor = [r, g, b, a]; + __obsColor = [r, g, b, a]; }; export const getObsColor = () => { - return __obsColor; + return __obsColor; }; -export const verifyTileData = (mapdatafile) => { - const readyPromise = new Promise(function (resolve, reject) { - resolve(); - }); +export const verifyTileData = mapdatafile => { + const readyPromise = new Promise(function(resolve, reject) { + resolve(); + }); - LOG('No verification done on tile data yet...'); + LOG('No verification done on tile data yet...'); - return readyPromise; + return readyPromise; }; const saveData = (mapFile, mapData) => { - const jetpack = require('fs-jetpack').cwd(__dirname); - jetpack.write(mapFile, mapData); + const jetpack = require('fs-jetpack').cwd(__dirname); + jetpack.write(mapFile, mapData); }; let verifyPromiseResolver = null; let verifyPromiseRejecter = null; -export const verifyMap = (mapfile) => { - const { dialog } = require('electron').remote; - - const readyPromise = new Promise(function (resolve, reject) { - verifyPromiseResolver = resolve; - verifyPromiseRejecter = reject; - }); - - const jetpack = require('fs-jetpack').cwd(__dirname); - const mapData = jetpack.read(mapfile, 'json'); - - let needsDefault = false; - let needsObstructions = false; - - if (typeof mapData.vsp === 'string') { - window.alert( - `Detected old format vsps: '${ mapData.vsp }'.\n\nPlease select a json vsp for the map's default and` + - ` a second one for the obstructions.`); - needsDefault = true; - needsObstructions = true; - } else { - if (!mapData.vsp.default) { - needsDefault = true; - } - - if (!mapData.vsp.obstructions) { - needsObstructions = true; - } - } +export const verifyMap = mapfile => { + const { dialog } = require('electron').remote; - if (typeof mapData.tallentitylayer === 'string') { - const truth = new Set(); - mapData.layers.map((a) => { - truth.add(a.name === mapData.tallentitylayer); + const readyPromise = new Promise(function(resolve, reject) { + verifyPromiseResolver = resolve; + verifyPromiseRejecter = reject; }); - if (!truth.has(true)) { - throw new Error(`looking for mapData.tallentitylayer "${ mapData.tallentitylayer }", but could not find it`); + const jetpack = require('fs-jetpack').cwd(__dirname); + const mapData = jetpack.read(mapfile, 'json'); + + let needsDefault = false; + let needsObstructions = false; + + if (typeof mapData.vsp === 'string') { + window.alert( + `Detected old format vsps: '${mapData.vsp}'.\n\nPlease select a json vsp for the map's default and` + + ` a second one for the obstructions.` + ); + needsDefault = true; + needsObstructions = true; + } else { + if (!mapData.vsp.default) { + needsDefault = true; + } + + if (!mapData.vsp.obstructions) { + needsObstructions = true; + } } - } - - if ($.isNumeric(mapData.tallentitylayer)) { - try { - mapData.tallentitylayer = mapData.layers[mapData.tallentitylayer].name; // convert to name - } catch (e) { - console.error(e); - mapData.tallentitylayer = false; + + if (typeof mapData.tallentitylayer === 'string') { + const truth = new Set(); + mapData.layers.map(a => { + truth.add(a.name === mapData.tallentitylayer); + }); + + if (!truth.has(true)) { + throw new Error( + `looking for mapData.tallentitylayer "${mapData.tallentitylayer}", but could not find it` + ); + } } - } - - if (!mapData.tallentitylayer) { - const stack = mapData.renderstring.split(','); - while (stack.length && !mapData.tallentitylayer) { - const rCode = stack.pop(); - if (!$.isNumeric(rCode)) { - continue; - } - mapData.tallentitylayer = mapData.layers[(parseInt(rCode) - 1)].name; + if ($.isNumeric(mapData.tallentitylayer)) { + try { + mapData.tallentitylayer = mapData.layers[mapData.tallentitylayer].name; // convert to name + } catch (e) { + console.error(e); + mapData.tallentitylayer = false; + } } if (!mapData.tallentitylayer) { - throw new Error('no tallentitylayer, and couldnt default to a valid candidate'); + const stack = mapData.renderstring.split(','); + while (stack.length && !mapData.tallentitylayer) { + const rCode = stack.pop(); + if (!$.isNumeric(rCode)) { + continue; + } + + mapData.tallentitylayer = mapData.layers[parseInt(rCode) - 1].name; + } + + if (!mapData.tallentitylayer) { + throw new Error('no tallentitylayer, and couldnt default to a valid candidate'); + } } - } - INFO(`mapData.tallentitylayer verified as ${ mapData.tallentitylayer}`); + INFO(`mapData.tallentitylayer verified as ${mapData.tallentitylayer}`); - if (typeof mapData.vsp !== 'object') { - mapData.vsp = {}; - } + if (typeof mapData.vsp !== 'object') { + mapData.vsp = {}; + } - let filenames; - let filename; + let filenames; + let filename; - if (needsDefault) { - window.alert('Due to sins (surely on your part) you do not have a default tile vsp set.' + - 'Please select the correct one.'); + if (needsDefault) { + window.alert( + 'Due to sins (surely on your part) you do not have a default tile vsp set.' + + 'Please select the correct one.' + ); - filenames = dialog.showOpenDialog({ - title: 'Choose a default tileset', - filters: [{ name: 'tileset', extensions: ['vsp.json'] }] - }); + filenames = dialog.showOpenDialog({ + title: 'Choose a default tileset', + filters: [{ name: 'tileset', extensions: ['vsp.json'] }] + }); - filename = filenames[0].replace(path.dirname(mapfile) + path.sep, ''); + filename = filenames[0].replace(path.dirname(mapfile) + path.sep, ''); - mapData.vsp.default = filename; - } + mapData.vsp.default = filename; + } - if (needsObstructions) { - window.alert('Please select the obstruction tileset for this map.'); + if (needsObstructions) { + window.alert('Please select the obstruction tileset for this map.'); - filenames = dialog.showOpenDialog({ - title: 'Choose an obstruction tileset', - filters: [{ name: 'tileset', extensions: ['obsvsp.json'] }] - }); + filenames = dialog.showOpenDialog({ + title: 'Choose an obstruction tileset', + filters: [{ name: 'tileset', extensions: ['obsvsp.json'] }] + }); - filename = filenames[0].replace(path.dirname(mapfile) + path.sep, ''); + filename = filenames[0].replace(path.dirname(mapfile) + path.sep, ''); - mapData.vsp.obstructions = filename; - } + mapData.vsp.obstructions = filename; + } - for (let i = mapData.layers.length - 1; i >= 0; i--) { - if (!mapData.layers[i].vsp) { - LOG(`setting layer[${ i }]s vsp to default...`); - mapData.layers[i].vsp = 'default'; + for (let i = mapData.layers.length - 1; i >= 0; i--) { + if (!mapData.layers[i].vsp) { + LOG(`setting layer[${i}]s vsp to default...`); + mapData.layers[i].vsp = 'default'; + } } - } - saveData(mapfile, mapData); + saveData(mapfile, mapData); - verifyPromiseResolver(); + verifyPromiseResolver(); - return readyPromise; + return readyPromise; }; - // todo all of this.mapData should be obfuscated export function Map(mapfile, mapdatafile, updateLocationFunction) { - let i; - INFO('Loading map', mapfile); - - if (typeof mapfile !== typeof mapdatafile) { - throw new Error( - sprintf( - "type mismatch on mapfile and mapdatafile. both must be object or string. got: '%s', '%s'", - typeof mapfile, typeof mapdatafile - ) - ); - } + let i; + INFO('Loading map', mapfile); - this.selfDestruct = () => { - for (let i = this.vspImages.length - 1; i >= 0; i--) { - LOG("deleting vspImages",i,this.vspImages[i]); - delete this.vspImages[i]; + if (typeof mapfile !== typeof mapdatafile) { + throw new Error( + sprintf( + "type mismatch on mapfile and mapdatafile. both must be object or string. got: '%s', '%s'", + typeof mapfile, + typeof mapdatafile + ) + ); } - for ( const key in this.entityTextures ) { - if (this.entityTextures.hasOwnProperty(key)) { - LOG("deleting entityTextures",key,this.entityTextures[key].img); - delete this.entityTextures[key].img; - } - } - }; - - let tallentitylayer_layerref = null; - this.getEntityTallRedrawLayer = () => { - return tallentitylayer_layerref; - }; - - this.setEntityTallRedrawLayerByName = (name) => { - // this.mapData.tallentitylayer_layerref - if (this.layerLookup[name]) { - tallentitylayer_layerref = this.layerLookup[name]; - this.mapData.tallentitylayer = name; - return tallentitylayer_layerref; - } + this.selfDestruct = () => { + for (let i = this.vspImages.length - 1; i >= 0; i--) { + LOG('deleting vspImages', i, this.vspImages[i]); + delete this.vspImages[i]; + } + + for (const key in this.entityTextures) { + if (this.entityTextures.hasOwnProperty(key)) { + LOG('deleting entityTextures', key, this.entityTextures[key].img); + delete this.entityTextures[key].img; + } + } + }; - throw new Error(`Unknown layer name: "${ name }"`); - }; + let tallentitylayer_layerref = null; + this.getEntityTallRedrawLayer = () => { + return tallentitylayer_layerref; + }; - const FILELOAD_MODE = (typeof mapfile === 'string'); + this.setEntityTallRedrawLayerByName = name => { + // this.mapData.tallentitylayer_layerref + if (this.layerLookup[name]) { + tallentitylayer_layerref = this.layerLookup[name]; + this.mapData.tallentitylayer = name; + return tallentitylayer_layerref; + } - this.filenames = {}; + throw new Error(`Unknown layer name: "${name}"`); + }; - if (FILELOAD_MODE) { - this.filenames.mapfile = mapfile; - this.filenames.mapdatafile = mapdatafile; + const FILELOAD_MODE = typeof mapfile === 'string'; - this.dataPath = path.dirname(mapdatafile); - lastKnownPath = this.dataPath; - - // TODO probably need a better concept of project management - this.mapedConfigFile = path.join(this.dataPath, '$$$_MAPED.json'); - } else { - this.dataPath = ''; - - // TODO probably need a better concept of project management - this.mapedConfigFile = path.join(lastKnownPath, '$$$_MAPED.json'); - } + this.filenames = {}; - this.updateLocationFn = updateLocationFunction; + if (FILELOAD_MODE) { + this.filenames.mapfile = mapfile; + this.filenames.mapdatafile = mapdatafile; - this.readyPromise = new Promise(function (resolve, reject) { - - this.promiseResolver = resolve; - this.promiseRejecter = reject; - }.bind(this)); + this.dataPath = path.dirname(mapdatafile); + lastKnownPath = this.dataPath; - if (FILELOAD_MODE) { - const jetpack = require('fs-jetpack').cwd(__dirname); - this.mapData = jetpack.read(mapfile, 'json'); - this.mapPath = mapfile; - } else { - this.mapData = mapfile; - this.mapPath = null; // TODO, I dunno, maybe this is stupid? What do we use this for anyway? - } - - // TODO eventually hide access to map.layers - this.layers = this.mapData.layers; - - this.getLayerByName = (name) => { - for (let i = this.layers.length - 1; i >= 0; i--) { - if (this.layers[i].name === name) { - return this.layers[i]; - } + // TODO probably need a better concept of project management + this.mapedConfigFile = path.join(this.dataPath, '$$$_MAPED.json'); + } else { + this.dataPath = ''; + + // TODO probably need a better concept of project management + this.mapedConfigFile = path.join(lastKnownPath, '$$$_MAPED.json'); } - throw new Error(`Unknown layer by name of "${ name }"`); - }; + this.updateLocationFn = updateLocationFunction; - this.getLayerByRStringCode = (rstringcode) => { - if ($.isNumeric(rstringcode)) { - const i = parseInt(rstringcode); + this.readyPromise = new Promise( + function(resolve, reject) { + this.promiseResolver = resolve; + this.promiseRejecter = reject; + }.bind(this) + ); - if (i > 0 && i <= this.layers.length) { - return this.layers[i - 1]; - } + if (FILELOAD_MODE) { + const jetpack = require('fs-jetpack').cwd(__dirname); + this.mapData = jetpack.read(mapfile, 'json'); + this.mapPath = mapfile; + } else { + this.mapData = mapfile; + this.mapPath = null; // TODO, I dunno, maybe this is stupid? What do we use this for anyway? } - notify(`Cannot get layer ${ rstringcode }, it doesnt exist on this map!\nValid range [1, ${ this.layers.length }]`) - return {name: false}; - }; + // TODO eventually hide access to map.layers + this.layers = this.mapData.layers; - this.getLayerByIdx_DANGEROUS = (idx) => { - if ($.isNumeric(idx)) { - const i = parseInt(idx); + this.getLayerByName = name => { + for (let i = this.layers.length - 1; i >= 0; i--) { + if (this.layers[i].name === name) { + return this.layers[i]; + } + } - if (i >= 0 && i < this.layers.length) { - return this.layers[i]; - } - } + throw new Error(`Unknown layer by name of "${name}"`); + }; - throw new Error(`Invalid layer index "${ idx }". Valid range [0, ${ this.layers.length - 1 }]`); - }; + this.getLayerByRStringCode = rstringcode => { + if ($.isNumeric(rstringcode)) { + const i = parseInt(rstringcode); - const jetpack = require('fs-jetpack').cwd(__dirname); - this.mapedConfigData = jetpack.read(this.mapedConfigFile, 'json'); + if (i > 0 && i <= this.layers.length) { + return this.layers[i - 1]; + } + } - this.checkerColorA = checkerColorA; - this.checkerColorB = checkerColorB; + notify( + `Cannot get layer ${rstringcode}, it doesnt exist on this map!\nValid range [1, ${this.layers.length}]` + ); + return { name: false }; + }; - if(this.mapedConfigData) { - if( this.mapedConfigData.checkerColorA && !this.mapData.isTileSelectorMap ) { - this.checkerColorA = this.mapedConfigData.checkerColorA; - } + this.getLayerByIdx_DANGEROUS = idx => { + if ($.isNumeric(idx)) { + const i = parseInt(idx); - if( this.mapedConfigData.checkerColorB && !this.mapData.isTileSelectorMap ) { - this.checkerColorB = this.mapedConfigData.checkerColorB; - } - } else { - alert(`Failed to read config file expected at ${this.mapedConfigFile}`); - } + if (i >= 0 && i < this.layers.length) { + return this.layers[i]; + } + } - this.filenames.vspfiles = this.mapData.vsp; + throw new Error( + `Invalid layer index "${idx}". Valid range [0, ${this.layers.length - 1}]` + ); + }; - // Initialize an undo/redostack just for this map! - this.UndoRedo = MakeUndoRedoStack(this); + const jetpack = require('fs-jetpack').cwd(__dirname); + this.mapedConfigData = jetpack.read(this.mapedConfigFile, 'json'); - // for "E" layer rendering - this.fakeEntityLayer = { - name: 'Entity Layer (E)', - parallax: { - X: 1, - Y: 1 - }, - vsp: 'default' - }; - - this.updateRstring = (rstring) => { - if (typeof rstring === 'string') { - LOG(`Setting new rstring: '${ rstring }'`); - this.layerRenderOrder = rstring.split(','); - } else if (typeof rstring.length === 'number') { - LOG("Setting new rstring: '"); - this.layerRenderOrder = rstring.map( (r) => `${r}` ); - LOG(this.layerRenderOrder); + this.checkerColorA = checkerColorA; + this.checkerColorB = checkerColorB; + + if (this.mapedConfigData) { + if (this.mapedConfigData.checkerColorA && !this.mapData.isTileSelectorMap) { + this.checkerColorA = this.mapedConfigData.checkerColorA; + } + + if (this.mapedConfigData.checkerColorB && !this.mapData.isTileSelectorMap) { + this.checkerColorB = this.mapedConfigData.checkerColorB; + } } else { - throw new Error('What fresh hell is this. What are you throwing at updateRstring?!'); + alert(`Failed to read config file expected at ${this.mapedConfigFile}`); } - this.mapData.renderstring = this.layerRenderOrder.join(','); + this.filenames.vspfiles = this.mapData.vsp; - updateRstringInfo(this.layerRenderOrder); - }; + // Initialize an undo/redostack just for this map! + this.UndoRedo = MakeUndoRedoStack(this); - this.updateRstring(this.mapData.renderstring); - this.mapSizeInTiles = { - width: 0, - height: 0 - }; + // for "E" layer rendering + this.fakeEntityLayer = { + name: 'Entity Layer (E)', + parallax: { + X: 1, + Y: 1 + }, + vsp: 'default' + }; - // YOU BIG FAT PHONY - this.regenerateLayerLookup = () => { - this.calculateSize(); + this.updateRstring = rstring => { + if (typeof rstring === 'string') { + LOG(`Setting new rstring: '${rstring}'`); + this.layerRenderOrder = rstring.split(','); + } else if (typeof rstring.length === 'number') { + LOG("Setting new rstring: '"); + this.layerRenderOrder = rstring.map(r => `${r}`); + LOG(this.layerRenderOrder); + } else { + throw new Error('What fresh hell is this. What are you throwing at updateRstring?!'); + } - this.layerLookup = {}; - this.layerLookup[this.fakeEntityLayer.name] = this.fakeEntityLayer; + this.mapData.renderstring = this.layerRenderOrder.join(','); - // populate this.layerLookup - for (let i = 0; i < this.mapData.layers.length; i++) { - LOG(i); - LOG(this.mapData.layers[i].name); + updateRstringInfo(this.layerRenderOrder); + }; - const layerName = this.uniqueLayerName(this.mapData.layers[i].name); - this.mapData.layers[i].name = layerName; // clean up the non unique name if necessary - this.layerLookup[layerName] = this.mapData.layers[i]; - } - } - this.regenerateLayerLookup(); + this.updateRstring(this.mapData.renderstring); + this.mapSizeInTiles = { + width: 0, + height: 0 + }; - // TODO: this branch-code is bad - if (!this.mapData.isTileSelectorMap) { - this.setEntityTallRedrawLayerByName(this.mapData.tallentitylayer); - } + // YOU BIG FAT PHONY + this.regenerateLayerLookup = () => { + this.calculateSize(); - this.camera = [0, 0, 1]; + this.layerLookup = {}; + this.layerLookup[this.fakeEntityLayer.name] = this.fakeEntityLayer; - if (FILELOAD_MODE) { - const jetpack = require('fs-jetpack').cwd(__dirname); - this.mapRawTileData = jetpack.read(mapdatafile, 'json'); // zone_data: [{x:x,y:y,z:zIdx}, ...] - } else { - this.mapRawTileData = mapdatafile; - } + // populate this.layerLookup + for (let i = 0; i < this.mapData.layers.length; i++) { + LOG(i); + LOG(this.mapData.layers[i].name); + + const layerName = this.uniqueLayerName(this.mapData.layers[i].name); + this.mapData.layers[i].name = layerName; // clean up the non unique name if necessary + this.layerLookup[layerName] = this.mapData.layers[i]; + } + }; + this.regenerateLayerLookup(); - this.legacyObsData = this.mapRawTileData.legacy_obstruction_data; - this.tileData = this.mapRawTileData.tile_data; + // TODO: this branch-code is bad + if (!this.mapData.isTileSelectorMap) { + this.setEntityTallRedrawLayerByName(this.mapData.tallentitylayer); + } - this.regenerateZoneData = () => { - const tmpZones = this.mapRawTileData.zone_data; - this.zoneData = new Array(this.mapSizeInTiles.width * this.mapSizeInTiles.height); + this.camera = [0, 0, 1]; - $.each(tmpZones, (idx) => { - this.zoneData[getFlatIdx(tmpZones[idx].x, tmpZones[idx].y, this.mapSizeInTiles.width)] = tmpZones[idx].z; - }); - }; + if (FILELOAD_MODE) { + const jetpack = require('fs-jetpack').cwd(__dirname); + this.mapRawTileData = jetpack.read(mapdatafile, 'json'); // zone_data: [{x:x,y:y,z:zIdx}, ...] + } else { + this.mapRawTileData = mapdatafile; + } - this.regenerateZoneData(); + this.legacyObsData = this.mapRawTileData.legacy_obstruction_data; + this.tileData = this.mapRawTileData.tile_data; - this.vspData = {}; + this.regenerateZoneData = () => { + const tmpZones = this.mapRawTileData.zone_data; + this.zoneData = new Array(this.mapSizeInTiles.width * this.mapSizeInTiles.height); + + $.each(tmpZones, idx => { + this.zoneData[getFlatIdx(tmpZones[idx].x, tmpZones[idx].y, this.mapSizeInTiles.width)] = + tmpZones[idx].z; + }); + }; + + this.regenerateZoneData(); + + this.vspData = {}; // if( FILELOAD_MODE ) { - for (const k in this.filenames.vspfiles) { - const tmppath = path.join(this.dataPath, this.filenames.vspfiles[k]); - INFO(`Loading '${ tmppath }'...`); - const jetpack = require('fs-jetpack').cwd(__dirname); - this.vspData[k] = jetpack.read(tmppath, 'json'); - INFO(k, '->', this.vspData[k]); - } + for (const k in this.filenames.vspfiles) { + const tmppath = path.join(this.dataPath, this.filenames.vspfiles[k]); + INFO(`Loading '${tmppath}'...`); + const jetpack = require('fs-jetpack').cwd(__dirname); + this.vspData[k] = jetpack.read(tmppath, 'json'); + INFO(k, '->', this.vspData[k]); + } // / "if this.dataPath" as a sentinel for only doing this to "real" maps. This file is garbage. - if (this.dataPath && this.mapData.vsp.obstructions) { - const tmppath = path.join(this.dataPath, this.mapData.vsp.obstructions); - const jetpack = require('fs-jetpack').cwd(__dirname); - this.obsLayerData = jetpack.read(tmppath, 'json'); - if (!this.obsLayerData) { - debugger; - } - if (!this.obsLayerData.vsp) { - this.obsLayerData.vsp = 'obstructions'; + if (this.dataPath && this.mapData.vsp.obstructions) { + const tmppath = path.join(this.dataPath, this.mapData.vsp.obstructions); + const jetpack = require('fs-jetpack').cwd(__dirname); + this.obsLayerData = jetpack.read(tmppath, 'json'); + if (!this.obsLayerData) { + debugger; + } + if (!this.obsLayerData.vsp) { + this.obsLayerData.vsp = 'obstructions'; + } + INFO(`loaded obsLayerData from ${tmppath}`); } - INFO(`loaded obsLayerData from ${ tmppath}`); - } - // todo: stop being evil - // todo: that probably won't happen. MWAHAHAHAHHA. - this.vspData.zones = $.extend(true, {}, this.vspData.obstructions); - this.vspData.zones.source_image = $('#zones_tileset')[0].src; + // todo: stop being evil + // todo: that probably won't happen. MWAHAHAHAHHA. + this.vspData.zones = $.extend(true, {}, this.vspData.obstructions); + this.vspData.zones.source_image = $('#zones_tileset')[0].src; - this.compactifyZones = () => { - // zone_data: [{x,y,z}, ...] - const tmpZones = []; - const mapWidth = this.mapSizeInTiles.width; + this.compactifyZones = () => { + // zone_data: [{x,y,z}, ...] + const tmpZones = []; + const mapWidth = this.mapSizeInTiles.width; - // walk the in-memory zoneData layer, anything with zone >0, add. - $.each(this.zoneData, (idx) => { - if (this.zoneData[idx] > 0) { - const x = getXfromFlat(idx, mapWidth); - const y = getYfromFlat(idx, mapWidth); + // walk the in-memory zoneData layer, anything with zone >0, add. + $.each(this.zoneData, idx => { + if (this.zoneData[idx] > 0) { + const x = getXfromFlat(idx, mapWidth); + const y = getYfromFlat(idx, mapWidth); - const zone = {x, y, z: this.zoneData[idx]}; + const zone = { x, y, z: this.zoneData[idx] }; - LOG('saving out flatzone', zone); + LOG('saving out flatzone', zone); - tmpZones.push(zone); - } - }); + tmpZones.push(zone); + } + }); - this.mapRawTileData.zone_data = tmpZones; - }; + this.mapRawTileData.zone_data = tmpZones; + }; - this.entitySortFn = (a, b) => { - const entityDataA = this._getEntityData(a); - const entityDataB = this._getEntityData(b); + this.entitySortFn = (a, b) => { + const entityDataA = this._getEntityData(a); + const entityDataB = this._getEntityData(b); - // Entities should Z-sort (within their layers) by the bottom of their hitbox (PY + hitbox.H), not the top. - if (a.location.py && b.location.py) { - return (a.location.py+entityDataA.hitbox[3]) - (b.location.py+entityDataB.hitbox[3]); - } + // Entities should Z-sort (within their layers) by the bottom of their hitbox (PY + hitbox.H), not the top. + if (a.location.py && b.location.py) { + return a.location.py + entityDataA.hitbox[3] - (b.location.py + entityDataB.hitbox[3]); + } - WARN("Entity sorting is being done without px/py or hitbox calculations. WARNING!"); - return a.location.ty - b.location.ty; - } - - this.toLoad = 0; - this.doneLoading = function (name) { - this.toLoad--; - LOG(`done loading ${name}`); - LOG(`${this.toLoad} left...`) - if (this.toLoad === 0) { - this.promiseResolver(this); - } - if(this.toLoad < 0) { - throw new Error("Someone done fucked up") - } - }.bind(this); - - this.vspImages = {}; - this.vspAnimations = {}; - for(const k in this.vspData) { - const vsp = this.vspData[k]; - if (!vsp) { - continue; - } - // TODO probably actually want to fail the load or do something other than - // just silently carry on when the image can't be loaded - this.toLoad++; - this.vspImages[k] = new window.Image(); - this.vspImages[k].onload = this.doneLoading; + WARN('Entity sorting is being done without px/py or hitbox calculations. WARNING!'); + return a.location.ty - b.location.ty; + }; - if (k !== 'zones') { // TODO: a better solution to map-relative assets versus app-relative assets. - // THIS IS SAD AND PATHETIC AND SADTHETIC - this.vspImages[k].src = path.join(this.dataPath, this.vspData[k].source_image); - } else { - this.vspImages[k].src = this.vspData[k].source_image; - } + this.toLoad = 0; + this.doneLoading = function(name) { + this.toLoad--; + LOG(`done loading ${name}`); + LOG(`${this.toLoad} left...`); + if (this.toLoad === 0) { + this.promiseResolver(this); + } + if (this.toLoad < 0) { + throw new Error('Someone done fucked up'); + } + }.bind(this); + + this.vspImages = {}; + this.vspAnimations = {}; + for (const k in this.vspData) { + const vsp = this.vspData[k]; + if (!vsp) { + continue; + } + // TODO probably actually want to fail the load or do something other than + // just silently carry on when the image can't be loaded + this.toLoad++; + this.vspImages[k] = new window.Image(); + this.vspImages[k].onload = this.doneLoading; + + if (k !== 'zones') { + // TODO: a better solution to map-relative assets versus app-relative assets. + // THIS IS SAD AND PATHETIC AND SADTHETIC + this.vspImages[k].src = path.join(this.dataPath, this.vspData[k].source_image); + } else { + this.vspImages[k].src = this.vspData[k].source_image; + } - this.vspAnimations[k] = {}; - if (vsp.animations) { - for (const anim of vsp.animations) { - this.vspAnimations[k][anim.start] = anim; - } + this.vspAnimations[k] = {}; + if (vsp.animations) { + for (const anim of vsp.animations) { + this.vspAnimations[k][anim.start] = anim; + } + } } - } - - this.toLoad++; - this.entityTextures = { - '__default__': { img: new window.Image() } - }; - this.entityTextures.__default__.img.onload = this.doneLoading; - this.entityTextures.__default__.img.src = $('#default_sprite').src; // path.join(window.appPath, 'assets/images/defaultsprite.png'); - - const defaultEntityLayer = this.fakeEntityLayer.name; - - this.resetEntityData = () => { - this.entityData = { - '__default__': { - animations: { - 'Idle Down': [ [ [ 0, 100 ] ], 'Looping' ], - 'Idle Up': [ [ [ 0, 100 ] ], 'Looping' ], - 'Idle Left': [ [ [ 0, 100 ] ], 'Looping' ], - 'Idle Right': [ [ [ 0, 100 ] ], 'Looping' ] - }, - animation: 'Idle Down', - dims: [ 16, 32 ], - hitbox: [ 0, 16, 16, 16 ], - regions: {}, - frames: 1, - image: '__default__', - inner_pad: 0, - outer_pad: 0, - per_row: 1 - } + + this.toLoad++; + this.entityTextures = { + __default__: { img: new window.Image() } + }; + this.entityTextures.__default__.img.onload = this.doneLoading; + this.entityTextures.__default__.img.src = $('#default_sprite').src; // path.join(window.appPath, 'assets/images/defaultsprite.png'); + + const defaultEntityLayer = this.fakeEntityLayer.name; + + this.resetEntityData = () => { + this.entityData = { + __default__: { + animations: { + 'Idle Down': [[[0, 100]], 'Looping'], + 'Idle Up': [[[0, 100]], 'Looping'], + 'Idle Left': [[[0, 100]], 'Looping'], + 'Idle Right': [[[0, 100]], 'Looping'] + }, + animation: 'Idle Down', + dims: [16, 32], + hitbox: [0, 16, 16, 16], + regions: {}, + frames: 1, + image: '__default__', + inner_pad: 0, + outer_pad: 0, + per_row: 1 + } + }; }; - }; - this.resetEntityData(); + this.resetEntityData(); - this.createEntityRenderData = () => { - if (!this.mapData.entities || !this.mapData.entities.length) { - return; - } + this.createEntityRenderData = () => { + if (!this.mapData.entities || !this.mapData.entities.length) { + return; + } - const tilewidth = this.vspData.default.tilesize.width; - const tileheight = this.vspData.default.tilesize.height; + const tilewidth = this.vspData.default.tilesize.width; + const tileheight = this.vspData.default.tilesize.height; - INFO('createEntityRenderData...'); - this.entities = {}; - for (i = 0; i < this.mapData.entities.length; i++) { - const entity = this.mapData.entities[i]; + INFO('createEntityRenderData...'); + this.entities = {}; + for (i = 0; i < this.mapData.entities.length; i++) { + const entity = this.mapData.entities[i]; - entity.location.layer = entity.location.layer || defaultEntityLayer; + entity.location.layer = entity.location.layer || defaultEntityLayer; - entity.location.px = entity.location.px || entity.location.tx * tilewidth; - entity.location.py = entity.location.py || entity.location.ty * tileheight; + entity.location.px = entity.location.px || entity.location.tx * tilewidth; + entity.location.py = entity.location.py || entity.location.ty * tileheight; - this.addEntityWithoutSort(entity, entity.location, false); - } + this.addEntityWithoutSort(entity, entity.location, false); + } - for (const i in this.entities) { - if (this.entities[i]) { - INFO('Sorting entities on layer', i, ', ', this.entities[i].length, 'entities to sort'); - this.entities[i].sort(this.entitySortFn); - } - } - }; - - this.createEntityRenderData(); - - this.renderContainer = null; - - this.selectionMaker = function () { - return { - add (x, y, w, h) { - if (x < this.hull.x || this.hull.x === null) { this.hull.x = x; } - if (y < this.hull.y || this.hull.y === null) { this.hull.y = y; } - if (x + w > this.hull.x + this.hull.w) { this.hull.w = x + w; } - if (y + h > this.hull.y + this.hull.h) { this.hull.h = y + h; } - - let ix = null; - let iy = null; - let i = null; - for (iy = 0; iy < h; iy++) { - for (ix = 0; ix < w; ix++) { - i = getFlatIdx(x + ix, y + iy, this.map.mapSizeInTiles.width); - this.tiles[i] = true; - } - } - - this.recalculateLines(); - }, - remove (x, y, w, h) { - // TODO update hull -- it's much harder to recalc the hull on subtraction - let ix = null; - let iy = null; - let i = null; - for (iy = 0; iy < h; iy++) { - for (ix = 0; ix < w; ix++) { - i = getFlatIdx(x + ix, y + iy, this.map.mapSizeInTiles.width); - this.tiles[i] = false; - } - } - - this.recalculateLines(); - }, - deselect () { - this.hull.x = null; - this.hull.y = null; - this.hull.w = 0; - this.hull.h = 0; - - this.tiles = []; - this.lines = []; - }, - - // "private" - recalculateLines () { - this.lines = []; - - const mapWidth = this.map.mapSizeInTiles.width; - let x = null; - let y = null; - let i = null; - for (y = this.hull.y; y < this.hull.y + this.hull.h; y++) { - for (x = this.hull.x; x < this.hull.x + this.hull.w; x++) { - i = getFlatIdx(x, y, mapWidth); - if (this.tiles[i] !== this.tiles[i - 1]) { this.lines.push(x, y, x, y + 1); } - if (this.tiles[i] !== this.tiles[i - mapWidth]) { this.lines.push(x, y, x + 1, y); } - } - } - - // INFO('Recalculated lines:'); - // INFO(this.hull); - // INFO(this.tiles); - // INFO(this.lines); - }, - - hull: { x: null, y: null, w: 0, h: 0 }, // TODO: it's not w/x at least in mark mode. It's x2,y2 (non-inclusive) - tiles: [], - lines: [] + for (const i in this.entities) { + if (this.entities[i]) { + INFO( + 'Sorting entities on layer', + i, + ', ', + this.entities[i].length, + 'entities to sort' + ); + this.entities[i].sort(this.entitySortFn); + } + } }; - }; - - this.windowOverlayMaker = function() { - return { - map: null, - on: false, - - viewport: { - x: 0, - y: 0, - width: 320, - height: 180 - }, - shade: { - color: [.5,.5,0], - opacity: .5 - } + + this.createEntityRenderData(); + + this.renderContainer = null; + + this.selectionMaker = function() { + return { + add(x, y, w, h) { + if (x < this.hull.x || this.hull.x === null) { + this.hull.x = x; + } + if (y < this.hull.y || this.hull.y === null) { + this.hull.y = y; + } + if (x + w > this.hull.x + this.hull.w) { + this.hull.w = x + w; + } + if (y + h > this.hull.y + this.hull.h) { + this.hull.h = y + h; + } + + let ix = null; + let iy = null; + let i = null; + for (iy = 0; iy < h; iy++) { + for (ix = 0; ix < w; ix++) { + i = getFlatIdx(x + ix, y + iy, this.map.mapSizeInTiles.width); + this.tiles[i] = true; + } + } + + this.recalculateLines(); + }, + remove(x, y, w, h) { + // TODO update hull -- it's much harder to recalc the hull on subtraction + let ix = null; + let iy = null; + let i = null; + for (iy = 0; iy < h; iy++) { + for (ix = 0; ix < w; ix++) { + i = getFlatIdx(x + ix, y + iy, this.map.mapSizeInTiles.width); + this.tiles[i] = false; + } + } + + this.recalculateLines(); + }, + deselect() { + this.hull.x = null; + this.hull.y = null; + this.hull.w = 0; + this.hull.h = 0; + + this.tiles = []; + this.lines = []; + }, + + // "private" + recalculateLines() { + this.lines = []; + + const mapWidth = this.map.mapSizeInTiles.width; + let x = null; + let y = null; + let i = null; + for (y = this.hull.y; y < this.hull.y + this.hull.h; y++) { + for (x = this.hull.x; x < this.hull.x + this.hull.w; x++) { + i = getFlatIdx(x, y, mapWidth); + if (this.tiles[i] !== this.tiles[i - 1]) { + this.lines.push(x, y, x, y + 1); + } + if (this.tiles[i] !== this.tiles[i - mapWidth]) { + this.lines.push(x, y, x + 1, y); + } + } + } + + // INFO('Recalculated lines:'); + // INFO(this.hull); + // INFO(this.tiles); + // INFO(this.lines); + }, + + hull: { x: null, y: null, w: 0, h: 0 }, // TODO: it's not w/x at least in mark mode. It's x2,y2 (non-inclusive) + tiles: [], + lines: [] + }; }; - }; - this.selection = this.selectionMaker(); - this.selection.map = this; + this.windowOverlayMaker = function() { + return { + map: null, + on: false, + + viewport: { + x: 0, + y: 0, + width: 320, + height: 180 + }, + shade: { + color: [0.5, 0.5, 0], + opacity: 0.5 + } + }; + }; - this.windowOverlay = this.windowOverlayMaker(); - this.windowOverlay.map = this; + this.selection = this.selectionMaker(); + this.selection.map = this; - this.visibleHoverTile = this.selectionMaker(); - this.visibleHoverTile.map = this; + this.windowOverlay = this.windowOverlayMaker(); + this.windowOverlay.map = this; - // heal uuids into uuid-less maps - if(has_unset_uuids(this)) { - heal_uuids_for_this_map(this); - notify("Your map lacked entity uuids.\nWe've added them in.\nPlease save before using these uuids."); - } + this.visibleHoverTile = this.selectionMaker(); + this.visibleHoverTile.map = this; - this.doneLoading(); -}; + // heal uuids into uuid-less maps + if (has_unset_uuids(this)) { + heal_uuids_for_this_map(this); + notify( + "Your map lacked entity uuids.\nWe've added them in.\nPlease save before using these uuids." + ); + } + + this.doneLoading(); +} -const has_unset_uuids = (map) => { - for (let i = map.mapData.entities.length - 1; i >= 0; i--) { - if( !map.mapData.entities[i].uuid ) { - return true; +const has_unset_uuids = map => { + for (let i = map.mapData.entities.length - 1; i >= 0; i--) { + if (!map.mapData.entities[i].uuid) { + return true; + } } - } - return false; + return false; }; export const getFlatIdx = (x, y, width) => { - return parseInt(width, 10) * parseInt(y, 10) + parseInt(x, 10); + return parseInt(width, 10) * parseInt(y, 10) + parseInt(x, 10); }; // extracts the first dimension of a flat-indexed 2 dimensionally array given @@ -744,7 +784,7 @@ export const getFlatIdx = (x, y, width) => { // wish to extract the first dimension's value from. // export const getXfromFlat = (idx, numColumns) => { - return idx % numColumns; + return idx % numColumns; }; // extracts the second dimension of a flat-indexed 2 dimensionally array given @@ -752,885 +792,1208 @@ export const getXfromFlat = (idx, numColumns) => { // wish to extract the second dimension's value from. // export const getYfromFlat = (idx, numColumns) => { - const flatval = idx - getXfromFlat(idx, numColumns); - return parseInt(flatval / numColumns, 10); + const flatval = idx - getXfromFlat(idx, numColumns); + return parseInt(flatval / numColumns, 10); }; -Map.prototype = { - sullyDataHealing(entity) { - // TODO this section is full of asset-healing code that's super Sully-specific. Clean it up for general release. - if (!this.entityData[entity.filename]) { - const jetpack = require('fs-jetpack').cwd(__dirname); - const originalDatafile = jetpack.path(this.dataPath, this.mapedConfigData.path_to_chrs, entity.filename); - let datafile = jetpack.path(this.dataPath, this.mapedConfigData.path_to_chrs, entity.filename); - let data = null; - - if (entity.filename.endsWith('chr')) { - if (jetpack.exists(`${datafile }.json`)) { - entity.filename += '.json'; - datafile += '.json'; - } else { - const lastDitch = jetpack.path(this.dataPath, this.mapedConfigData.path_to_chrs, 'chrs', entity.filename); - - if (jetpack.exists(lastDitch)) { - entity.filename = `${'chrs' + '/'}${ entity.filename }.json`; - datafile = `${lastDitch }.json`; - } else { - datafile = null; - } +Map.prototype = { + sullyDataHealing(entity) { + // TODO this section is full of asset-healing code that's super Sully-specific. Clean it up for general release. + if (!this.entityData[entity.filename]) { + const jetpack = require('fs-jetpack').cwd(__dirname); + const originalDatafile = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + entity.filename + ); + let datafile = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + entity.filename + ); + let data = null; + + if (entity.filename.endsWith('chr')) { + if (jetpack.exists(`${datafile}.json`)) { + entity.filename += '.json'; + datafile += '.json'; + } else { + const lastDitch = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + 'chrs', + entity.filename + ); + + if (jetpack.exists(lastDitch)) { + entity.filename = `${'chrs' + '/'}${entity.filename}.json`; + datafile = `${lastDitch}.json`; + } else { + datafile = null; + } + } + } + + if (datafile === null && !entity.filename.endsWith('json')) { + const lastDitch = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + `${entity.filename}.chr.json` + ); + + if (jetpack.exists(lastDitch)) { + entity.filename = jetpack.path(`${entity.filename}.chr.json`); + datafile = lastDitch; + } else { + datafile = null; + } + } + + if (datafile === null && !entity.filename.startsWith('chr')) { + const lastDitch = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + 'chrs', + entity.filename + ); + + if (jetpack.exists(lastDitch)) { + entity.filename = jetpack.path('chrs', entity.filename); + datafile = lastDitch; + } else { + datafile = null; + } + } + + if ( + datafile === null && + !entity.filename.startsWith('chr') && + !entity.filename.endsWith('json') + ) { + const lastDitch = jetpack.path( + this.dataPath, + this.mapedConfigData.path_to_chrs, + 'chrs', + `${entity.filename}.chr.json` + ); + + if (jetpack.exists(lastDitch)) { + entity.filename = jetpack.path('chrs', `${entity.filename}.chr.json`); + datafile = lastDitch; + } else { + datafile = null; + } + } + + try { + // TODO: use aen's loaders in MAPPO and convert binary chrs to images and json files, motherfucker! + data = jetpack.read(datafile, 'json'); + } catch (e) { + window.alert( + `Failure while attempting to parse json for ${datafile}\nReason: \n${e}` + ); + if (entity.filename.endsWith('json')) { + console.error('Couldnt read a json entity file:', entity.filename); + } + console.warn(`Totally couldnt read datafile: '${datafile}'`); + data = null; + } + + if (data) { + this._maybeAddEntityTexture(data, entity, datafile); + } else { + console.warn( + `Could not find '${entity.filename}', using the default. Path: `, + datafile + ); + // debugger; + entity.MAPED_USEDEFAULT = true; + } } - } - - if (datafile === null && !entity.filename.endsWith('json')) { - const lastDitch = jetpack.path( - this.dataPath, this.mapedConfigData.path_to_chrs, `${entity.filename }.chr.json` - ); + }, - if (jetpack.exists(lastDitch)) { - entity.filename = jetpack.path(`${entity.filename }.chr.json`); - datafile = lastDitch; - } else { - datafile = null; - } - } + maybeAddEntityTextureFromFilename(data, filename) { + this._maybeAddEntityTexture(data, false, filename); + }, - if (datafile === null && !entity.filename.startsWith('chr')) { - const lastDitch = jetpack.path( - this.dataPath, this.mapedConfigData.path_to_chrs, 'chrs', entity.filename - ); + maybeAddEntityTexture(data, entity) { + alert('KILL THIS, USE _maybeAddEntityTexture'); + this._maybeAddEntityTexture(data, entity); + }, - if (jetpack.exists(lastDitch)) { - entity.filename = jetpack.path('chrs', entity.filename); - datafile = lastDitch; - } else { - datafile = null; + _maybeAddEntityTexture(data, entity, filename) { + try { + let imageFilename = ''; + const jetpack = require('fs-jetpack').cwd(__dirname); + + const projectBasePath = jetpack.path(this.dataPath, this.mapedConfigData.path_to_chrs); + const jsonDirPath = path.dirname(jetpack.path(filename)); + + if (entity) { + filename = entity.filename; + //debugger; + } + + function _isIllegalPath(path) { + return !(path.indexOf('../') == -1 && path.indexOf('..\\') == -1); + } + + function _isProjectRelative(path) { + return path.startsWith('~/') || path.startsWith('~\\'); + } + + function _isDatafileRelative(path) { + if (_isProjectRelative(path)) { + return false; + } + + let validFilenameStart = str => { + const regexp = new RegExp('^[a-z0-9_-]', 'i'); // TODO: this is almost certainly wrong; different filesystems will have different allowed things. Let's only accept the intersection of win/mac/linux/ps4-5/xbox/switch tho + return regexp.test(str); + }; + + return path.startsWith('./') || path.startsWith('.\\') || validFilenameStart(path); + } + + if (_isIllegalPath(data.image)) { + const msg = `Illegal imagefile path in chr json '${filename}'. field 'image' had value '${data.image}', and we do not allow 'walking up' the dirtree.`; + alert(msg); + throw Error(msg); + } else if (_isProjectRelative(data.image)) { + const tmp = data.image.substr(2); + imageFilename = jetpack.path(projectBasePath, tmp); + } else if (_isDatafileRelative(data.image)) { + imageFilename = jetpack.path(jsonDirPath, data.image); + } else { + const msg = `Illegal imagefile path in chr json '${filename}'. field 'image' had value '${data.image}' is neither project-relative (starts with '~/') nor datafile-relative (is a naked filename or is a path in a subdir from the json file)...`; + + alert(msg); + throw Error(msg); + } + + this.entityData[filename] = data; + + for (const name in data.animations) { + // convert short-hand to useful-hand + if (typeof data.animations[name][0] === 'string') { + const chunks = data.animations[name][0].split(' '); + const t = parseInt(chunks.shift().substring(1), 10); + + data.animations[name][0] = []; + for (let f = 0; f < chunks.length; f++) { + data.animations[name][0].push([parseInt(chunks[f], 10), t]); + } + } + } + + /// TODO: for gods sake put this all under test dammit + /// TODO: this is a bad scheme for storing entity textures. If there's the same filename but different paths, there'll be a colission. Change to full normalized path maybe? + LOG(`this.entityTextures[${data.image}] ${this.entityTextures[data.image]}`); + if (!this.entityTextures[data.image]) { + // TODO maybe make this definable in this.mapedConfigData too? + let imagePath = imageFilename; + + if (!jetpack.inspect(imagePath)) { + imagePath += '.png'; // TODO this is stupid and bad and wrong. + } + if (!jetpack.inspect(imagePath)) { + console.warn( + `Couldnt load image (${data.image}) for entity ({filename}); falling back...` + ); + // this.entityData[filename].image = '__default__'; + if (entity) { + entity.MAPED_USEDEFAULT = false; + } + + return; + } + + INFO(`Adding '${imagePath}' to entityTextures cache...`); + this.toLoad++; + this.entityTextures[data.image] = {}; + this.entityTextures[data.image].img = new window.Image(); + const fn = this.doneLoading; + this.entityTextures[data.image].img.onload = function() { + fn(data.image); + }; + this.entityTextures[data.image].img.src = imagePath; + } + + if (entity) { + entity.MAPED_USEDEFAULT = false; + } + LOG('NOT USING DEFAULT ENTITY FOR ', data.image); + } catch (e) { + debugger; } - } - - if (datafile === null && !entity.filename.startsWith('chr') && !entity.filename.endsWith('json')) { - const lastDitch = jetpack.path( - this.dataPath, this.mapedConfigData.path_to_chrs, 'chrs', `${entity.filename }.chr.json` - ); + }, - if (jetpack.exists(lastDitch)) { - entity.filename = jetpack.path('chrs', `${entity.filename }.chr.json`); - datafile = lastDitch; - } else { - datafile = null; + addEntityWithoutSort(entity, location) { + // TODO we just shouldnt save any "MAPED_" properties in the first place. + // TODO we should have a universal MAPED_CONF type that lives parallel to objects, not in them + if (entity.MAPED_USEDEFAULT) { + delete entity.MAPED_USEDEFAULT; } - } - try { - // TODO: use aen's loaders in MAPPO and convert binary chrs to images and json files, motherfucker! - data = jetpack.read(datafile, 'json'); - } catch (e) { - window.alert(`Failure while attempting to parse json for ${ datafile }\nReason: \n${ e}` ); - if (entity.filename.endsWith('json')) { - console.error('Couldnt read a json entity file:', entity.filename); + if (!this.entities[location.layer]) { + this.entities[location.layer] = []; } - console.warn(`Totally couldnt read datafile: '${ datafile }'`); - data = null; - } - - if (data) { - this.maybeAddEntityTexture(data, entity); - } else { - console.warn(`Could not find '${ entity.filename }', using the default. Path: `, datafile); - // debugger; - entity.MAPED_USEDEFAULT = true; - } - } - }, - - maybeAddEntityTextureFromFilename(data, filename) { - this._maybeAddEntityTexture(data, false, filename); - }, + this.entities[location.layer].push(entity); - maybeAddEntityTexture(data, entity) { - this._maybeAddEntityTexture(data, entity); - }, + this.sullyDataHealing(entity); - _maybeAddEntityTexture(data, entity, filename) { - - if(entity) { - filename = entity.filename; - } - - this.entityData[filename] = data; - - for (const name in data.animations) { - // convert short-hand to useful-hand - if (typeof data.animations[name][0] === 'string') { - const chunks = data.animations[name][0].split(' '); - const t = parseInt(chunks.shift().substring(1), 10); - - data.animations[name][0] = []; - for (let f = 0; f < chunks.length; f++) { - data.animations[name][0].push([parseInt(chunks[f], 10), t]); + if (entity.filename.endsWith('chr')) { + console.warn(`entity ('${entity.filename}') is binary in format. Skipping for now.`); + entity.MAPED_USEDEFAULT = true; + return; } - } - } - const jetpack = require('fs-jetpack').cwd(__dirname); - - LOG(`this.entityTextures[${data.image}] ${ this.entityTextures[data.image]}`) - if (!this.entityTextures[data.image]) { - // TODO maybe make this definable in this.mapedConfigData too? - let imagePath = jetpack.path(this.dataPath, this.mapedConfigData.path_to_chrs, data.image); - if (!jetpack.inspect(imagePath)) { - imagePath += '.png'; // TODO this is stupid and bad and wrong. - } - if (!jetpack.inspect(imagePath)) { - console.warn("Couldn't load image", data.image, 'for entity', filename, '; falling back.'); - // this.entityData[filename].image = '__default__'; - if(entity) { - entity.MAPED_USEDEFAULT = false; + if (!entity.filename.endsWith('chr') && !entity.filename.endsWith('json')) { + console.warn( + `entity ('${entity.filename}') has an unknown format. Skipping for now. (2)` + ); + entity.MAPED_USEDEFAULT = true; + return; } - - return; - } - - INFO(`Adding '${ imagePath }' to entityTextures cache...`); - this.toLoad++; - this.entityTextures[data.image] = {}; - this.entityTextures[data.image].img = new window.Image(); - const fn = this.doneLoading; - this.entityTextures[data.image].img.onload = function() { fn(data.image); } - this.entityTextures[data.image].img.src = imagePath; - } - - if(entity) { - entity.MAPED_USEDEFAULT = false; - } - LOG('NOT USING DEFAULT ENTITY FOR ', data.image); - }, - - addEntityWithoutSort(entity, location) { - // TODO we just shouldnt save any "MAPED_" properties in the first place. - // TODO we should have a universal MAPED_CONF type that lives parallel to objects, not in them - if (entity.MAPED_USEDEFAULT) { - delete entity.MAPED_USEDEFAULT; - } - - if (!this.entities[location.layer]) { - this.entities[location.layer] = []; - } - this.entities[location.layer].push(entity); - - this.sullyDataHealing(entity); - - if (entity.filename.endsWith('chr')) { - console.warn(`entity ('${ entity.filename }') is binary in format. Skipping for now.`); - entity.MAPED_USEDEFAULT = true; - return; - } - - if (!entity.filename.endsWith('chr') && !entity.filename.endsWith('json')) { - console.warn(`entity ('${ entity.filename }') has an unknown format. Skipping for now. (2)`); - entity.MAPED_USEDEFAULT = true; - return; - } - - if (!entity.MAPED_USEDEFAULT) { - if ( - this.entityData[entity.filename].regions && - this.entityData[entity.filename].regions.Tall_Redraw && - !this.getEntityTallRedrawLayer() - ) { - window.alert(`ERROR: Loading tall entity ${ entity.filename } with no tallentitylayer in map!`); - } - - entity.animation = entity.animation || Object.keys(this.entityData[entity.filename].animations)[0]; - } else { - entity.animation = 'Idle Down'; // / m-m-m-magick (__default__ has this) - } - }, - addEntity (filename, location) { - this.addEntityWithoutSort(filename, location); - this.entities[location.layer].sort(this.entitySortFn); - }, - getVSPTileLocation (vsp, idx) { - let x = null; - let y = null; - - y = parseInt(idx / this.vspData[vsp].tiles_per_row); - x = idx - y * this.vspData[vsp].tiles_per_row; - - y *= this.vspData[vsp].tilesize.height; - x *= this.vspData[vsp].tilesize.width; - - return { - x, - y - }; - }, - - getZone (tileX, tileY) { - const idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + if (!entity.MAPED_USEDEFAULT) { + try { + if ( + this.entityData[entity.filename].regions && + this.entityData[entity.filename].regions.Tall_Redraw && + !this.getEntityTallRedrawLayer() + ) { + window.alert( + `ERROR: Loading tall entity ${entity.filename} with no tallentitylayer in map!` + ); + } + + entity.animation = + entity.animation || Object.keys(this.entityData[entity.filename].animations)[0]; + } catch (e) { + debugger; + throw e; + } + } else { + entity.animation = 'Idle Down'; // / m-m-m-magick (__default__ has this) + } + }, + addEntity(filename, location) { + this.addEntityWithoutSort(filename, location); + this.entities[location.layer].sort(this.entitySortFn); + }, - return this.zoneData[idx]; - }, + getVSPTileLocation(vsp, idx) { + let x = null; + let y = null; - setZone (tileX, tileY, zoneIdx) { - const idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + y = parseInt(idx / this.vspData[vsp].tiles_per_row); + x = idx - y * this.vspData[vsp].tiles_per_row; - this.zoneData[idx] = zoneIdx; - }, + y *= this.vspData[vsp].tilesize.height; + x *= this.vspData[vsp].tilesize.width; - getTile (tileX, tileY, layerIdx) { - let idx; + return { + x, + y + }; + }, - if (layerIdx === MAGICAL_OBS_LAYER_ID) { // TODO the obs sentinel is the WORST - idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); - if (this.legacyObsData) { // we are in the main map. - return this.legacyObsData[idx]; - } if (this.tileData && this.tileData.length === 1) { // we are in the obs map - layerIdx = 0; - } else { - throw new Error( - 'Something very strange happened where you were trying to access obs data when there was both no obs ' + - 'tiledata and multiple non-obs tile layers.'); - } - } else if (layerIdx === MAGICAL_ZONE_LAYER_ID) { // TODO the obs sentinel is the WORST - idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + getZone(tileX, tileY) { + const idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); - try { return this.zoneData[idx]; - } catch(ig) { - return 0; - } - } else { // we are on a normal layer - idx = getFlatIdx(tileX, tileY, this.layers[layerIdx].dimensions.X); - } - - return this.tileData[layerIdx][idx]; - }, - - setTile (tileX, tileY, layerIdx, tileIdx) { - let idx; - - // / jesus, right? One day this won't be a thing, he lied to himself. - if( layerIdx !== MAGICAL_OBS_LAYER_ID && layerIdx !== MAGICAL_ZONE_LAYER_ID ) { - if( tileX < 0 || tileY < 0 || tileX >= this.layers[layerIdx].dimensions.X || tileY >= this.layers[layerIdx].dimensions.Y ) { - console.warn(`attempted to set a tile out of layer bounds. (${tileX},${tileY})`); - INFO(`layerIdx: ${ layerIdx}`); - INFO(this.layers[layerIdx].dimensions) - return; - } - - idx = getFlatIdx(tileX, tileY, this.layers[layerIdx].dimensions.X); - - } else { - idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); - } - - - - if (layerIdx === MAGICAL_OBS_LAYER_ID) { // TODO the obs sentinel is the WORST - this.legacyObsData[idx] = tileIdx; - } else if(layerIdx === MAGICAL_ZONE_LAYER_ID) { - - if( !tileIdx ) { - delete this.zoneData[idx] - } else { - this.zoneData[idx] = tileIdx; - } - - } else { - this.tileData[layerIdx][idx] = tileIdx; - } - }, - - ready () { + }, - const key = `map-${ this.mapData.name}`; - const $cont = $('.map-palette'); + setZone(tileX, tileY, zoneIdx) { + const idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); - const setPaletteLocations = function (paletteDict) { - let configVar = null; - let obj = null; + this.zoneData[idx] = zoneIdx; + }, - for (const k in paletteDict) { - // INFO('paletteDict.' + k); - configVar = `${k } settings`; // this should be CONST'd somewhere and referenced in both places - const $pal = $(`.${ k}`); + getTile(tileX, tileY, layerIdx) { + let idx; + + if (layerIdx === MAGICAL_OBS_LAYER_ID) { + // TODO the obs sentinel is the WORST + idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + if (this.legacyObsData) { + // we are in the main map. + return this.legacyObsData[idx]; + } + if (this.tileData && this.tileData.length === 1) { + // we are in the obs map + layerIdx = 0; + } else { + throw new Error( + 'Something very strange happened where you were trying to access obs data when there was both no obs ' + + 'tiledata and multiple non-obs tile layers.' + ); + } + } else if (layerIdx === MAGICAL_ZONE_LAYER_ID) { + // TODO the obs sentinel is the WORST + idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + + try { + return this.zoneData[idx]; + } catch (ig) { + return 0; + } + } else { + // we are on a normal layer + idx = getFlatIdx(tileX, tileY, this.layers[layerIdx].dimensions.X); + } - // INFO('configVar: ' + configVar); - // INFO('$pal: ' + $pal); - // INFO('localStorage[configVar]: ' + localStorage[configVar]); + return this.tileData[layerIdx][idx]; + }, - if (localStorage[configVar] && $pal) { - obj = JSON.parse(localStorage[configVar]); + setTile(tileX, tileY, layerIdx, tileIdx) { + let idx; + + // / jesus, right? One day this won't be a thing, he lied to himself. + if (layerIdx !== MAGICAL_OBS_LAYER_ID && layerIdx !== MAGICAL_ZONE_LAYER_ID) { + if ( + tileX < 0 || + tileY < 0 || + tileX >= this.layers[layerIdx].dimensions.X || + tileY >= this.layers[layerIdx].dimensions.Y + ) { + console.warn(`attempted to set a tile out of layer bounds. (${tileX},${tileY})`); + INFO(`layerIdx: ${layerIdx}`); + INFO(this.layers[layerIdx].dimensions); + return; + } + + idx = getFlatIdx(tileX, tileY, this.layers[layerIdx].dimensions.X); + } else { + idx = getFlatIdx(tileX, tileY, this.mapSizeInTiles.width); + } - if (obj.w) { $pal.width(obj.w); } - if (obj.h) { $pal.height(obj.h); } - if (obj.x) { $pal.css('left', obj.x); } - if (obj.y) { $pal.css('top', obj.y); } - obj.hide ? $pal.hide() : $pal.show(); + if (layerIdx === MAGICAL_OBS_LAYER_ID) { + // TODO the obs sentinel is the WORST + this.legacyObsData[idx] = tileIdx; + } else if (layerIdx === MAGICAL_ZONE_LAYER_ID) { + if (!tileIdx) { + delete this.zoneData[idx]; + } else { + this.zoneData[idx] = tileIdx; + } } else { - INFO('lol, no'); + this.tileData[layerIdx][idx] = tileIdx; } - } - }; + }, - const {localStorage} = window; - - if (`${localStorage[key] }-mapx`) { - if (localStorage[`${key }-width`]) { $cont.width(localStorage[`${key }-width`]); } - if (localStorage[`${key }-height`]) { $cont.height(localStorage[`${key }-height`]); } - if (localStorage[`${key }-top`]) { $cont.css('top', localStorage[`${key }-top`]); } - if (localStorage[`${key }-left`]) { $cont.css('left', localStorage[`${key }-left`]); } - if (localStorage[`${key }-mapx`]) { this.camera[0] = parseInt(localStorage[`${key }-mapx`]); } - if (localStorage[`${key }-mapy`]) { this.camera[1] = parseInt(localStorage[`${key }-mapy`]); } - if (localStorage[`${key }-mapzoom`]) { this.camera[2] = parseInt(localStorage[`${key }-mapzoom`]); } - if( !this.camera[2] ) { - this.camera[2] = 1; - } + ready() { + const key = `map-${this.mapData.name}`; + const $cont = $('.map-palette'); + + const setPaletteLocations = function(paletteDict) { + let configVar = null; + let obj = null; + + for (const k in paletteDict) { + // INFO('paletteDict.' + k); + configVar = `${k} settings`; // this should be CONST'd somewhere and referenced in both places + const $pal = $(`.${k}`); + + // INFO('configVar: ' + configVar); + // INFO('$pal: ' + $pal); + // INFO('localStorage[configVar]: ' + localStorage[configVar]); + + if (localStorage[configVar] && $pal) { + obj = JSON.parse(localStorage[configVar]); + + if (obj.w) { + $pal.width(obj.w); + } + if (obj.h) { + $pal.height(obj.h); + } + if (obj.x) { + $pal.css('left', obj.x); + } + if (obj.y) { + $pal.css('top', obj.y); + } + obj.hide ? $pal.hide() : $pal.show(); + } else { + INFO('lol, no'); + } + } + }; + + const { localStorage } = window; + + if (`${localStorage[key]}-mapx`) { + if (localStorage[`${key}-width`]) { + $cont.width(localStorage[`${key}-width`]); + } + if (localStorage[`${key}-height`]) { + $cont.height(localStorage[`${key}-height`]); + } + if (localStorage[`${key}-top`]) { + $cont.css('top', localStorage[`${key}-top`]); + } + if (localStorage[`${key}-left`]) { + $cont.css('left', localStorage[`${key}-left`]); + } + if (localStorage[`${key}-mapx`]) { + this.camera[0] = parseInt(localStorage[`${key}-mapx`]); + } + if (localStorage[`${key}-mapy`]) { + this.camera[1] = parseInt(localStorage[`${key}-mapy`]); + } + if (localStorage[`${key}-mapzoom`]) { + this.camera[2] = parseInt(localStorage[`${key}-mapzoom`]); + } + if (!this.camera[2]) { + this.camera[2] = 1; + } + + if (localStorage[`${key}-layerspallete`]) { + this.camera[1] = parseInt(localStorage[`${key}-layerspallete`]); + } + + if (localStorage.palettes) { + INFO('palletes found...'); + setPaletteLocations(JSON.parse(localStorage.palettes)); + } else { + console.warn('no palettes registered.'); + } + + updateInfoDims(this); + updateLocationText(this); + updateZoomText(this); + } - if (localStorage[`${key }-layerspallete`]) { this.camera[1] = parseInt(localStorage[`${key }-layerspallete`]); } + return this.readyPromise; + }, - if (localStorage.palettes) { - INFO('palletes found...'); - setPaletteLocations(JSON.parse(localStorage.palettes)); - } else { - console.warn('no palettes registered.'); - } + uniqueLayerName(like) { + if (like && !this.layerLookup[like]) { + return like; + } + if (!like) { + like = 'Layer 0'; + } // will have 1 added to the 0 so unnamed layers will be Layer 1, Layer 2, etc. - updateInfoDims(this); - updateLocationText(this); - updateZoomText(this); - } + let name = ''; + let num = parseInt(like.match(/\d*$/)[0], 10) || 1; // || 1 so that two layers named "Foo" become "Foo" and "Foo 2" + const stem = like.replace(/\d*$/, ''); + num++; - return this.readyPromise; - }, + name = stem + num; - uniqueLayerName (like) { - if (like && !this.layerLookup[like]) { return like; } - if (!like) { like = 'Layer 0'; } // will have 1 added to the 0 so unnamed layers will be Layer 1, Layer 2, etc. + while (this.layerLookup[name]) { + num++; + name = stem + num; + } - let name = ''; - let num = parseInt(like.match(/\d*$/)[0], 10) || 1; // || 1 so that two layers named "Foo" become "Foo" and "Foo 2" - const stem = like.replace(/\d*$/, ''); - num++; + return name; + }, - name = stem + num; + setCanvas($canvas) { + INFO('Setting canvas on map'); + if (this.renderContainer) { + this.cleanUpCallbacks(); + } - while (this.layerLookup[name]) { - num++; - name = stem + num; - } + // set up callbacks + $(window).on('resize', this.resize.bind(this)); + + // set up context + this.renderContainer = $canvas; + this.gl = this.renderContainer[0].getContext('webgl'); // we're targeting Electron not the Internet at large so + // don't worry about failing to get a GL context + this.gl.clearColor(0.5, 0.5, 0.5, 1.0); + + const readShader = shaderPath => { + const jetpack = + process.env.NODE_ENV !== 'production' + ? require('fs-jetpack') + : require('fs-jetpack').cwd(__dirname); + const p = jetpack.path(shaderPath); + const res = jetpack.read(p); + return res; + }; + + this.checkerShader = new ShaderProgram( + this.gl, + readShader('shaders/tilemap-vert.glsl'), + readShader('shaders/check-frag.glsl') + ); + this.tilemapShader = new ShaderProgram( + this.gl, + readShader('shaders/tilemap-vert.glsl'), + readShader('shaders/tilemap-frag.glsl') + ); + this.spriteShader = new ShaderProgram( + this.gl, + readShader('shaders/sprite-vert.glsl'), + readShader('shaders/sprite-frag.glsl') + ); + this.obstructionmapShader = new ShaderProgram( + this.gl, + readShader('shaders/tilemap-vert.glsl'), + readShader('shaders/tilemapObs-frag.glsl') + ); + this.zonemapShader = new ShaderProgram( + this.gl, + readShader('shaders/tilemap-vert.glsl'), + readShader('shaders/tilemap-frag.glsl') + ); + this.selectionShader = new ShaderProgram( + this.gl, + readShader('shaders/selection-vert.glsl'), + readShader('shaders/selection-frag.glsl') + ); + this.screenviewShader = new ShaderProgram( + this.gl, + readShader('shaders/screenview-vert.glsl'), + readShader('shaders/screenview-frag.glsl') + ); + this.layerBorderShader = new ShaderProgram( + this.gl, + readShader('shaders/tilemap-vert.glsl'), + readShader('shaders/layerborder-frag.glsl') + ); + this.entityBoundsShader = new ShaderProgram( + this.gl, + readShader('shaders/sprite-vert.glsl'), + readShader('shaders/entitybounds-frag.glsl') + ); - return name; - }, + this.tileLibraryTextures = {}; + for (const k in this.vspImages) { + if (!this.vspImages[k]) { + return; + } + this.tileLibraryTextures[k] = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.tileLibraryTextures[k]); + this.gl.texParameteri( + this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_S, + this.gl.CLAMP_TO_EDGE + ); + this.gl.texParameteri( + this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_T, + this.gl.CLAMP_TO_EDGE + ); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D( + this.gl.TEXTURE_2D, + 0, + this.gl.RGBA, + this.gl.RGBA, + this.gl.UNSIGNED_BYTE, + this.vspImages[k] + ); + } - setCanvas ($canvas) { - INFO('Setting canvas on map'); - if (this.renderContainer) { this.cleanUpCallbacks(); } + this.tileLayoutTexture = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.tileLayoutTexture); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D( + this.gl.TEXTURE_2D, + 0, + this.gl.RGBA, + this.mapData.layers[0].dimensions.X, + this.mapData.layers[0].dimensions.Y, + 0, + this.gl.RGBA, + this.gl.UNSIGNED_BYTE, + buildTileDataTexture(this.tileData[0]) + ); - // set up callbacks - $(window).on('resize', this.resize.bind(this)); + this.gl.enable(this.gl.BLEND); - // set up context - this.renderContainer = $canvas; - this.gl = this.renderContainer[0].getContext('webgl'); // we're targeting Electron not the Internet at large so - // don't worry about failing to get a GL context - this.gl.clearColor(0.5, 0.5, 0.5, 1.0); + this.vertexbuffer = this.gl.createBuffer(); + this.entityVertexBuffer = this.gl.createBuffer(); + this.selectionVertexBuffer = this.gl.createBuffer(); + this.screenviewVertexBuffer = this.gl.createBuffer(); + this.lineBuf = this.gl.createBuffer(); - const readShader = (shaderPath) => { - const jetpack = process.env.NODE_ENV !== 'production' ? require('fs-jetpack') : require('fs-jetpack').cwd(__dirname); - const p = jetpack.path(shaderPath); - const res = jetpack.read(p); - return res; - }; + this.calculateSize(); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.screenviewVertexBuffer); + this.gl.bufferData( + this.gl.ARRAY_BUFFER, + new Float32Array([-1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0]), + this.gl.STATIC_DRAW + ); - this.checkerShader = new ShaderProgram( - this.gl, readShader('shaders/tilemap-vert.glsl'), readShader('shaders/check-frag.glsl')); - this.tilemapShader = new ShaderProgram( - this.gl, readShader('shaders/tilemap-vert.glsl'), readShader('shaders/tilemap-frag.glsl')); - this.spriteShader = new ShaderProgram( - this.gl, readShader('shaders/sprite-vert.glsl'), readShader('shaders/sprite-frag.glsl')); - this.obstructionmapShader = new ShaderProgram( - this.gl, readShader('shaders/tilemap-vert.glsl'), readShader('shaders/tilemapObs-frag.glsl')); - this.zonemapShader = new ShaderProgram( - this.gl, readShader('shaders/tilemap-vert.glsl'), readShader('shaders/tilemap-frag.glsl')); - this.selectionShader = new ShaderProgram( - this.gl, readShader('shaders/selection-vert.glsl'), readShader('shaders/selection-frag.glsl')); - this.screenviewShader = new ShaderProgram( - this.gl, readShader('shaders/screenview-vert.glsl'), readShader('shaders/screenview-frag.glsl')); - this.layerBorderShader = new ShaderProgram( - this.gl, readShader('shaders/tilemap-vert.glsl'), readShader('shaders/layerborder-frag.glsl')); - this.entityBoundsShader = new ShaderProgram( - this.gl, readShader('shaders/sprite-vert.glsl'), readShader('shaders/entitybounds-frag.glsl')); - - this.tileLibraryTextures = {}; - for (const k in this.vspImages) { - if (!this.vspImages[k]) { return; } - this.tileLibraryTextures[k] = this.gl.createTexture(); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.tileLibraryTextures[k]); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); - this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.vspImages[k]); - } + for (const k in this.entityTextures) { + const texture = this.entityTextures[k]; - this.tileLayoutTexture = this.gl.createTexture(); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.tileLayoutTexture); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); - this.gl.texImage2D( - this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.mapData.layers[0].dimensions.X, this.mapData.layers[0].dimensions.Y, - 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, buildTileDataTexture(this.tileData[0]) - ); + texture.tex = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, texture.tex); + this.gl.texParameteri( + this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_S, + this.gl.CLAMP_TO_EDGE + ); + this.gl.texParameteri( + this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_T, + this.gl.CLAMP_TO_EDGE + ); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D( + this.gl.TEXTURE_2D, + 0, + this.gl.RGBA, + this.gl.RGBA, + this.gl.UNSIGNED_BYTE, + texture.img + ); + } - this.gl.enable(this.gl.BLEND); - - this.vertexbuffer = this.gl.createBuffer(); - this.entityVertexBuffer = this.gl.createBuffer(); - this.selectionVertexBuffer = this.gl.createBuffer(); - this.screenviewVertexBuffer = this.gl.createBuffer(); - this.lineBuf = this.gl.createBuffer(); - - this.calculateSize(); - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.screenviewVertexBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([ - -1.0, -1.0, - 1.0, 1.0, - 1.0, -1.0, - 1.0, 1.0, - -1.0, -1.0, - -1.0, 1.0 - ]), this.gl.STATIC_DRAW); - - for (const k in this.entityTextures) { - const texture = this.entityTextures[k]; - - texture.tex = this.gl.createTexture(); - this.gl.bindTexture(this.gl.TEXTURE_2D, texture.tex); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); - this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, texture.img); - } + // make sure the size is right + this.resize(); - // make sure the size is right - this.resize(); + if (this.onLoad) { + this.onLoad(this); + } + }, - if (this.onLoad) { - this.onLoad(this); - } - }, + calculateSize() { + this.mapSizeInTiles = { + width: 0, + height: 0 + }; + for (let i = 0; i < this.mapData.layers.length; i++) { + if (this.mapData.layers[i].dimensions.X > this.mapSizeInTiles.width) { + this.mapSizeInTiles.width = this.mapData.layers[i].dimensions.X; + } + if (this.mapData.layers[i].dimensions.Y > this.mapSizeInTiles.height) { + this.mapSizeInTiles.height = this.mapData.layers[i].dimensions.Y; + } + } - calculateSize() { - this.mapSizeInTiles = { - width: 0, - height: 0 - }; - for (let i = 0; i < this.mapData.layers.length; i++) { - if (this.mapData.layers[i].dimensions.X > this.mapSizeInTiles.width) { - this.mapSizeInTiles.width = this.mapData.layers[i].dimensions.X; - } - if (this.mapData.layers[i].dimensions.Y > this.mapSizeInTiles.height) { - this.mapSizeInTiles.height = this.mapData.layers[i].dimensions.Y; - } - } + updateInfoDims(this); + + // this could get called before this.gl is created, potentially, so don't blow up + // if that's the case + if (this.gl) { + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexbuffer); + this.gl.bufferData( + this.gl.ARRAY_BUFFER, + new Float32Array([ + 0.0, + 0.0, + this.mapSizeInTiles.width, + 0.0, + 0.0, + -this.mapSizeInTiles.height, + 0.0, + -this.mapSizeInTiles.height, + this.mapSizeInTiles.width, + 0.0, + this.mapSizeInTiles.width, + -this.mapSizeInTiles.height + ]), + this.gl.STATIC_DRAW + ); + } + }, - updateInfoDims(this); - - // this could get called before this.gl is created, potentially, so don't blow up - // if that's the case - if (this.gl) { - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexbuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([ - 0.0, 0.0, - this.mapSizeInTiles.width, 0.0, - 0.0, -this.mapSizeInTiles.height, - 0.0, -this.mapSizeInTiles.height, - this.mapSizeInTiles.width, 0.0, - this.mapSizeInTiles.width, -this.mapSizeInTiles.height - ]), this.gl.STATIC_DRAW); - } - }, + drawEntities(i, map, layer, tallEntities, tick) { + if (!map.entities) { + return; + } - drawEntities (i, map, layer, tallEntities, tick) { - if (!map.entities) { - return; - } + // Layered Entities + if (getNormalEntityVisibility()) { + if ( + map.entities[layer.name] && + map.entities[layer.name].length > 0 && + shouldShowEntitiesForLayer(layer.name) + ) { + const entities = map.entities[layer.name]; + + const showEntityPreview = + getSelectedLayer() && layer === getSelectedLayer().layer && map.entityPreview; + map.spriteShader.use(); + + for (let e = 0; e < entities.length; e++) { + const mask = + !entities[e].MAPED_USEDEFAULT && + map.entityData[entities[e].filename].regions && + map.entityData[entities[e].filename].regions.Tall_Redraw + ? map.entityData[entities[e].filename].regions.Tall_Redraw + : null; + + if ( + showEntityPreview && + map.entityPreview.location.ty < entities[e].location.ty && // TODO this whole check should favor py. + (e === 0 || map.entityPreview.location.ty >= entities[e - 1].location.ty) + ) { + map.renderEntity( + map.entityPreview, + layer, + [1, 1, 1, ENTITY_PREVIEW_ALPHA], + null, + mask, + false + ); + } + if (entities[e].MAPED_HIGHLIGHTED) { + map.renderEntity( + entities[e], + layer, + [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], + null, + mask, + false + ); + } else { + map.renderEntity(entities[e], layer, [1, 1, 1, 1], null, mask, false); + } + if (mask) { + tallEntities.push(entities[e]); + } + } + } else if (map.entityPreview) { + map.renderEntity( + map.entityPreview, + layer, + [1, 1, 1, ENTITY_PREVIEW_ALPHA], + null, + null, + false + ); + } + + if (map.getEntityTallRedrawLayer() === layer) { + for (const e in tallEntities) { + const entity = tallEntities[e]; + + if (entity.MAPED_HIGHLIGHTED) { + map.renderEntity( + entity, + layer, + [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], + map.entityData[entity.filename].regions.Tall_Redraw, + null, + true + ); + } else { + map.renderEntity( + entity, + layer, + [TALLENT_R, TALLENT_G, TALLENT_B, TALLENT_A], + map.entityData[entity.filename].regions.Tall_Redraw, + null, + true + ); + } + } + } + } + }, - // Layered Entities - if (getNormalEntityVisibility()) { - if (map.entities[layer.name] && map.entities[layer.name].length > 0 && shouldShowEntitiesForLayer(layer.name)) { - const entities = map.entities[layer.name]; - - const showEntityPreview = (getSelectedLayer() && layer === getSelectedLayer().layer && map.entityPreview); - map.spriteShader.use(); - - for (let e = 0; e < entities.length; e++) { - const mask = (!entities[e].MAPED_USEDEFAULT && map.entityData[entities[e].filename].regions && - map.entityData[entities[e].filename].regions.Tall_Redraw ? - map.entityData[entities[e].filename].regions.Tall_Redraw : null); - - if (showEntityPreview && - map.entityPreview.location.ty < entities[e].location.ty && // TODO this whole check should favor py. - (e === 0 || map.entityPreview.location.ty >= entities[e - 1].location.ty) - ) { - map.renderEntity(map.entityPreview, layer, [1, 1, 1, ENTITY_PREVIEW_ALPHA], null, mask, false); - } - if (entities[e].MAPED_HIGHLIGHTED) { - map.renderEntity( - entities[e], layer, [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], null, mask, false + maybeRenderZones(gl) { + // ZONES + if (getZoneVisibility() && this.zoneData.length > 1) { + const vsp = 'zones'; // TODO zones layer shouldn't just default like this + const layer = { + parallax: { X: 1, Y: 1 }, + alpha: getZoneAlpha(), + dimensions: { X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.height } + }; + + this.tilemapShader.use(); + + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + gl.uniform4f( + this.tilemapShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + this.vspData[vsp].tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + this.vspData[vsp].tilesize.height, + this.renderContainerDimensions.w / + this.vspData[vsp].tilesize.width / + this.camera[2], + this.renderContainerDimensions.h / + this.vspData[vsp].tilesize.height / + this.camera[2] ); - } else { - map.renderEntity(entities[e], layer, [1, 1, 1, 1], null, mask, false); - } - if (mask) { - tallEntities.push(entities[e]); - } - } - } else if (map.entityPreview) { - map.renderEntity(map.entityPreview, layer, [1, 1, 1, ENTITY_PREVIEW_ALPHA], null, null, false); - } - if (map.getEntityTallRedrawLayer() === layer) { - for (const e in tallEntities) { - const entity = tallEntities[e]; - - if (entity.MAPED_HIGHLIGHTED) { - map.renderEntity( - entity, layer, - [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], - map.entityData[entity.filename].regions.Tall_Redraw, - null, - true + gl.uniform4f( + this.tilemapShader.uniform('u_dimensions'), + layer.dimensions.X, + layer.dimensions.Y, + this.vspData[vsp].tiles_per_row, + this.vspImages[vsp].height / this.vspData[vsp].tilesize.height ); - } else { - map.renderEntity( - entity, layer, - [TALLENT_R, TALLENT_G, TALLENT_B, TALLENT_A], - map.entityData[entity.filename].regions.Tall_Redraw, - null, - true + + gl.uniform1f(this.tilemapShader.uniform('u_opacity'), layer.alpha); + + const u_tileLibrary = this.tilemapShader.uniform('u_tileLibrary'); + gl.uniform1i(u_tileLibrary, 0); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); + + const u_tileLayout = this.tilemapShader.uniform('u_tileLayout'); + gl.uniform1i(u_tileLayout, 1); + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); + gl.texImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + layer.dimensions.X, + layer.dimensions.Y, + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + buildTileDataTexture(this.zoneData) ); - } + + const a_position = this.tilemapShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + + gl.drawArrays(gl.TRIANGLES, 0, 6); } - } - } - }, - - maybeRenderZones (gl) { - // ZONES - if (getZoneVisibility() && this.zoneData.length > 1) { - const vsp = 'zones'; // TODO zones layer shouldn't just default like this - const layer = { - parallax: { X: 1, Y: 1 }, - alpha: getZoneAlpha(), - dimensions: {X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.height} - }; - - this.tilemapShader.use(); - - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - gl.uniform4f(this.tilemapShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / this.vspData[vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / this.vspData[vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] + }, + + maybeRenderObstructions(gl) { + // OBSTRUCTIONS + if (getObsVisibility() && this.legacyObsData) { + const vsp = 'obstructions'; // TODO obstruction layer shouldn't just default like this + const layer = { + parallax: { X: 1, Y: 1 }, + dimensions: { X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.height } + }; + + if (this.mapData.obstructions_layer) { + layer.dimensions = this.mapData.obstructions_layer.dimensions; + } + + // TODO this.mapData.obstructions_layer.offset + + this.obstructionmapShader.use(); + + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + gl.uniform4f( + this.obstructionmapShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + this.vspData[vsp].tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + this.vspData[vsp].tilesize.height, + this.renderContainerDimensions.w / + this.vspData[vsp].tilesize.width / + this.camera[2], + this.renderContainerDimensions.h / + this.vspData[vsp].tilesize.height / + this.camera[2] ); - gl.uniform4f(this.tilemapShader.uniform('u_dimensions'), + gl.uniform4f( + this.obstructionmapShader.uniform('u_dimensions'), layer.dimensions.X, layer.dimensions.Y, this.vspData[vsp].tiles_per_row, this.vspImages[vsp].height / this.vspData[vsp].tilesize.height ); - gl.uniform1f(this.tilemapShader.uniform('u_opacity'), layer.alpha); + gl.uniform4f( + this.obstructionmapShader.uniform('u_color'), + __obsColor[0], + __obsColor[1], + __obsColor[2], + __obsColor[3] + ); - const u_tileLibrary = this.tilemapShader.uniform('u_tileLibrary'); - gl.uniform1i(u_tileLibrary, 0); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); + const u_tileLibrary = this.obstructionmapShader.uniform('u_tileLibrary'); + gl.uniform1i(u_tileLibrary, 0); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); - const u_tileLayout = this.tilemapShader.uniform('u_tileLayout'); - gl.uniform1i(u_tileLayout, 1); - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); - gl.texImage2D( - gl.TEXTURE_2D, 0, gl.RGBA, layer.dimensions.X, layer.dimensions.Y, 0, - gl.RGBA, gl.UNSIGNED_BYTE, buildTileDataTexture(this.zoneData) - ); + const u_tileLayout = this.obstructionmapShader.uniform('u_tileLayout'); + gl.uniform1i(u_tileLayout, 1); + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); - const a_position = this.tilemapShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + gl.texImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + layer.dimensions.X, + layer.dimensions.Y, + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + buildTileDataTexture(this.legacyObsData) + ); - gl.drawArrays(gl.TRIANGLES, 0, 6); - } - }, - - maybeRenderObstructions (gl) { - // OBSTRUCTIONS - if (getObsVisibility() && this.legacyObsData) { - const vsp = 'obstructions'; // TODO obstruction layer shouldn't just default like this - const layer = { - parallax: { X: 1, Y: 1 }, - dimensions: {X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.height} - }; - - if( this.mapData.obstructions_layer ) { - layer.dimensions = this.mapData.obstructions_layer.dimensions; - } + const a_position = this.obstructionmapShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - // TODO this.mapData.obstructions_layer.offset - - this.obstructionmapShader.use(); - - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - gl.uniform4f(this.obstructionmapShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / this.vspData[vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / this.vspData[vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] - ); - - gl.uniform4f(this.obstructionmapShader.uniform('u_dimensions'), - layer.dimensions.X, - layer.dimensions.Y, - this.vspData[vsp].tiles_per_row, - this.vspImages[vsp].height / this.vspData[vsp].tilesize.height - ); - - gl.uniform4f( - this.obstructionmapShader.uniform('u_color'), - __obsColor[0], __obsColor[1], __obsColor[2], __obsColor[3] - ); - - const u_tileLibrary = this.obstructionmapShader.uniform('u_tileLibrary'); - gl.uniform1i(u_tileLibrary, 0); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); - - const u_tileLayout = this.obstructionmapShader.uniform('u_tileLayout'); - gl.uniform1i(u_tileLayout, 1); - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); - - gl.texImage2D( - gl.TEXTURE_2D, 0, gl.RGBA, layer.dimensions.X, layer.dimensions.Y, 0, - gl.RGBA, gl.UNSIGNED_BYTE, buildTileDataTexture(this.legacyObsData) - ); - - const a_position = this.obstructionmapShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - - gl.drawArrays(gl.TRIANGLES, 0, 6); - } - }, - - renderTilesAndEntityLayers (gl, tick) { - const tallEntities = []; - - // render each layer in turn - this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.SRC_ALPHA, this.gl.DST_ALPHA); - const len = this.layerRenderOrder.length; - for (let i = 0; i < len; i++) { - // something about optimization means this runs 2x faster if renderLayer is its own function - // 100% glad that I've avoided javascript so far - this.renderLayer(gl, i, tallEntities, tick); - } - }, + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + }, - renderLayer (gl, i, tallEntities, tick) { - const layerIndex = parseInt(this.layerRenderOrder[i], 10) - 1; - const layer = this.mapData.layers[layerIndex]; + renderTilesAndEntityLayers(gl, tick) { + const tallEntities = []; - if (this.layerRenderOrder[i] === 'E') { - this.drawEntities(i, this, this.fakeEntityLayer, tallEntities, tick); - return; - } - if (isNaN(layerIndex)) { - return; - } + // render each layer in turn + this.gl.blendFuncSeparate( + this.gl.SRC_ALPHA, + this.gl.ONE_MINUS_SRC_ALPHA, + this.gl.SRC_ALPHA, + this.gl.DST_ALPHA + ); + const len = this.layerRenderOrder.length; + for (let i = 0; i < len; i++) { + // something about optimization means this runs 2x faster if renderLayer is its own function + // 100% glad that I've avoided javascript so far + this.renderLayer(gl, i, tallEntities, tick); + } + }, - if (!layer) { - console.warn('sub-tick escape for when youre making a new map. this is dumb and bad.'); - return; - } + renderLayer(gl, i, tallEntities, tick) { + const layerIndex = parseInt(this.layerRenderOrder[i], 10) - 1; + const layer = this.mapData.layers[layerIndex]; - if (layer.MAPED_HIDDEN) { - if (this.getEntityTallRedrawLayer() === layer) { - this.spriteShader.use(); - for (const e in tallEntities) { - const entity = tallEntities[e]; - - if (entity.MAPED_HIGHLIGHTED) { - this.renderEntity( - entity, layer, - [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], - this.entityData[entity.filename].regions.Tall_Redraw, - null, null - ); - } else { - this.renderEntity( - entity, layer, - [TALLENT_R, TALLENT_G, TALLENT_B, TALLENT_A], - this.entityData[entity.filename].regions.Tall_Redraw, - null, null - ); - } + if (this.layerRenderOrder[i] === 'E') { + this.drawEntities(i, this, this.fakeEntityLayer, tallEntities, tick); + return; + } + if (isNaN(layerIndex)) { + return; } - } - - return; - } - const {vsp} = layer; + if (!layer) { + console.warn('sub-tick escape for when youre making a new map. this is dumb and bad.'); + return; + } - this.tilemapShader.use(); + if (layer.MAPED_HIDDEN) { + if (this.getEntityTallRedrawLayer() === layer) { + this.spriteShader.use(); + for (const e in tallEntities) { + const entity = tallEntities[e]; + + if (entity.MAPED_HIGHLIGHTED) { + this.renderEntity( + entity, + layer, + [HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, animateAlpha(tick, 100)], + this.entityData[entity.filename].regions.Tall_Redraw, + null, + null + ); + } else { + this.renderEntity( + entity, + layer, + [TALLENT_R, TALLENT_G, TALLENT_B, TALLENT_A], + this.entityData[entity.filename].regions.Tall_Redraw, + null, + null + ); + } + } + } + + return; + } - const appliedOffset = (layer.offset) ? layer.offset : {X:0, Y:0}; // If layer has an offset, use other, otherwise use default value - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - gl.uniform4f(this.tilemapShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x) / this.vspData[vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y) / this.vspData[vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] - ); + const { vsp } = layer; + + this.tilemapShader.use(); + + const appliedOffset = layer.offset ? layer.offset : { X: 0, Y: 0 }; // If layer has an offset, use other, otherwise use default value + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + gl.uniform4f( + this.tilemapShader.uniform('u_camera'), + Math.floor( + layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x + ) / this.vspData[vsp].tilesize.width, + Math.floor( + layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y + ) / this.vspData[vsp].tilesize.height, + this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], + this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] + ); - gl.uniform4f(this.tilemapShader.uniform('u_dimensions'), - layer.dimensions.X, - layer.dimensions.Y, - this.vspData[vsp].tiles_per_row, - this.vspImages[vsp].height / this.vspData[vsp].tilesize.height - ); + gl.uniform4f( + this.tilemapShader.uniform('u_dimensions'), + layer.dimensions.X, + layer.dimensions.Y, + this.vspData[vsp].tiles_per_row, + this.vspImages[vsp].height / this.vspData[vsp].tilesize.height + ); - gl.uniform1f(this.tilemapShader.uniform('u_opacity'), layer.alpha); - - const u_tileLibrary = this.tilemapShader.uniform('u_tileLibrary'); - gl.uniform1i(u_tileLibrary, 0); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); - - // todo: rename u_tileLayout to something eles? "Dark Minimap?" - const u_tileLayout = this.tilemapShader.uniform('u_tileLayout'); - gl.uniform1i(u_tileLayout, 1); - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); - gl.texImage2D( - gl.TEXTURE_2D, 0, gl.RGBA, layer.dimensions.X, layer.dimensions.Y, 0, - gl.RGBA, gl.UNSIGNED_BYTE, buildTileDataTexture(this.tileData[layerIndex], ANIMATE_TILES ? this.vspAnimations[vsp] : undefined) - ); + gl.uniform1f(this.tilemapShader.uniform('u_opacity'), layer.alpha); + + const u_tileLibrary = this.tilemapShader.uniform('u_tileLibrary'); + gl.uniform1i(u_tileLibrary, 0); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.tileLibraryTextures[vsp]); + + // todo: rename u_tileLayout to something eles? "Dark Minimap?" + const u_tileLayout = this.tilemapShader.uniform('u_tileLayout'); + gl.uniform1i(u_tileLayout, 1); + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this.tileLayoutTexture); + gl.texImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + layer.dimensions.X, + layer.dimensions.Y, + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + buildTileDataTexture( + this.tileData[layerIndex], + ANIMATE_TILES ? this.vspAnimations[vsp] : undefined + ) + ); - const a_position = this.tilemapShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + const a_position = this.tilemapShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + + // draw the tiles! + gl.drawArrays(gl.TRIANGLES, 0, 6); + + // / TODO: extract everything below this this into its own helper function? + this.layerBorderShader.use(); + + const a_positionLayer = this.layerBorderShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); + gl.enableVertexAttribArray(a_positionLayer); + gl.vertexAttribPointer(a_positionLayer, 2, gl.FLOAT, false, 0, 0); + + gl.uniform4f( + this.layerBorderShader.uniform('u_camera'), + Math.floor( + layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x + ) / this.vspData[vsp].tilesize.width, + Math.floor( + layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y + ) / this.vspData[vsp].tilesize.height, + this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], + this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] + ); - // draw the tiles! - gl.drawArrays(gl.TRIANGLES, 0, 6); + gl.uniform4f( + this.layerBorderShader.uniform('u_dimensions'), + layer.dimensions.X, + layer.dimensions.Y, + this.vspData[vsp].tiles_per_row, + this.vspImages[vsp].height / this.vspData[vsp].tilesize.height + ); - // / TODO: extract everything below this this into its own helper function? - this.layerBorderShader.use(); - - const a_positionLayer = this.layerBorderShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); - gl.enableVertexAttribArray(a_positionLayer); - gl.vertexAttribPointer(a_positionLayer, 2, gl.FLOAT, false, 0, 0); - - gl.uniform4f(this.layerBorderShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x) / this.vspData[vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y) / this.vspData[vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] - ); + const r = layer.borderColor ? layer.borderColor.R : 0; + const g = layer.borderColor ? layer.borderColor.G : 0; + const b = layer.borderColor ? layer.borderColor.B : 0; + const a = layer.borderColor ? layer.borderColor.A : 0; - gl.uniform4f(this.layerBorderShader.uniform('u_dimensions'), - layer.dimensions.X, - layer.dimensions.Y, - this.vspData[vsp].tiles_per_row, - this.vspImages[vsp].height / this.vspData[vsp].tilesize.height - ); + gl.uniform4f(this.layerBorderShader.uniform('u_borderColor'), r, g, b, a); - const r = layer.borderColor ? layer.borderColor.R: 0; - const g = layer.borderColor ? layer.borderColor.G: 0; - const b = layer.borderColor ? layer.borderColor.B: 0; - const a = layer.borderColor ? layer.borderColor.A: 0; + gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([ + 0, + 0, + layer.dimensions.X, + 0, + layer.dimensions.X, + 0, + layer.dimensions.X, + -layer.dimensions.Y, + layer.dimensions.X, + -layer.dimensions.Y, + 0, + -layer.dimensions.Y, + 0, + -layer.dimensions.Y, + 0, + 0 + ]), + this.gl.STATIC_DRAW + ); - gl.uniform4f( - this.layerBorderShader.uniform('u_borderColor'), - r,g,b, a - ); + gl.drawArrays(gl.LINES, 0, 8); - gl.bindBuffer( gl.ARRAY_BUFFER, this.lineBuf ); - gl.bufferData( gl.ARRAY_BUFFER, new Float32Array([ - 0, 0, - layer.dimensions.X, 0, - layer.dimensions.X, 0, - layer.dimensions.X, -layer.dimensions.Y, - layer.dimensions.X, -layer.dimensions.Y, - 0, -layer.dimensions.Y, - 0, -layer.dimensions.Y, - 0, 0,]), - this.gl.STATIC_DRAW - ); + this.drawEntities(i, this, layer, tallEntities, tick); + }, - gl.drawArrays( gl.LINES, 0, 8 ); - - this.drawEntities(i, this, layer, tallEntities, tick); - }, - - maybeRenderMarchingAnts (gl, selection) { - const vsp = 'default'; // TODO this is definitely wrong. Definitely if we allow vsp size mixing. - - // MARCHING ANTS - if (selection.lines.length > 0 && typeof vsp !== 'undefined') { - // TODO remove these fake layer shenanegans - // TODO something smells about getSelectedLayer().layer - const layer = getSelectedLayer() ? getSelectedLayer().layer : { - parallax: { X: 1, Y: 1 }, - offset: {X: 0, Y: 0}, - dimensions: {X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.width} - }; - const appliedOffset = (selection.map.mapData.isTileSelectorMap) ? {X:0, Y:0} : layer.offset; // If tileset selector, ignore offset - - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - this.selectionShader.use(); - gl.uniform4f( - this.selectionShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x) / this.vspData[vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y) / this.vspData[vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[vsp].tilesize.height / this.camera[2] - ); - gl.uniform4f( - this.selectionShader.uniform('u_dimensions'), - layer.dimensions.X, - layer.dimensions.Y, - this.vspData[vsp].tiles_per_row, - this.vspImages[vsp].height / this.vspData[vsp].tilesize.height - ); - gl.uniform1i(this.selectionShader.uniform('u_time'), Date.now()); - - const a_position = this.selectionShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.selectionVertexBuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(selection.lines), this.gl.STATIC_DRAW); - - gl.drawArrays(gl.LINES, 0, selection.lines.length / 2); - } - }, + maybeRenderMarchingAnts(gl, selection) { + const vsp = 'default'; // TODO this is definitely wrong. Definitely if we allow vsp size mixing. + + // MARCHING ANTS + if (selection.lines.length > 0 && typeof vsp !== 'undefined') { + // TODO remove these fake layer shenanegans + // TODO something smells about getSelectedLayer().layer + const layer = getSelectedLayer() + ? getSelectedLayer().layer + : { + parallax: { X: 1, Y: 1 }, + offset: { X: 0, Y: 0 }, + dimensions: { X: this.mapSizeInTiles.width, Y: this.mapSizeInTiles.width } + }; + const appliedOffset = selection.map.mapData.isTileSelectorMap + ? { X: 0, Y: 0 } + : layer.offset; // If tileset selector, ignore offset + + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + this.selectionShader.use(); + gl.uniform4f( + this.selectionShader.uniform('u_camera'), + Math.floor( + layer.parallax.X * (this.camera[0] - appliedOffset.X + viewport.x) - viewport.x + ) / this.vspData[vsp].tilesize.width, + Math.floor( + layer.parallax.Y * (this.camera[1] - appliedOffset.Y + viewport.y) - viewport.y + ) / this.vspData[vsp].tilesize.height, + this.renderContainerDimensions.w / + this.vspData[vsp].tilesize.width / + this.camera[2], + this.renderContainerDimensions.h / + this.vspData[vsp].tilesize.height / + this.camera[2] + ); + gl.uniform4f( + this.selectionShader.uniform('u_dimensions'), + layer.dimensions.X, + layer.dimensions.Y, + this.vspData[vsp].tiles_per_row, + this.vspImages[vsp].height / this.vspData[vsp].tilesize.height + ); + gl.uniform1i(this.selectionShader.uniform('u_time'), Date.now()); + + const a_position = this.selectionShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.selectionVertexBuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + this.gl.bufferData( + this.gl.ARRAY_BUFFER, + new Float32Array(selection.lines), + this.gl.STATIC_DRAW + ); - maybeRenderScreenviewOverlay(gl, overlay) { + gl.drawArrays(gl.LINES, 0, selection.lines.length / 2); + } + }, - /* + maybeRenderScreenviewOverlay(gl, overlay) { + /* overlay = { on: boolean, viewport: { @@ -1646,488 +2009,581 @@ Map.prototype = { } */ - if( overlay.on ) { - this.screenviewShader.use(); - - // uniforms... - gl.uniform4f(this.screenviewShader.uniform('u_camera'), - Math.floor(this.camera[0]), - Math.floor(this.camera[1]), - this.renderContainerDimensions.w / this.camera[2], - this.renderContainerDimensions.h / this.camera[2] - ); - gl.uniform4f(this.screenviewShader.uniform('u_viewport'), - Math.floor(overlay.viewport.x), - Math.floor(overlay.viewport.y), - Math.floor(overlay.viewport.width), - Math.floor(overlay.viewport.height) - ); - gl.uniform4f(this.screenviewShader.uniform('u_color'), - overlay.shade.color[0], - overlay.shade.color[1], - overlay.shade.color[2], - overlay.shade.opacity - ); - - const a_position = this.screenviewShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.screenviewVertexBuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - - gl.drawArrays(gl.TRIANGLES, 0, 6); - } - }, + if (overlay.on) { + this.screenviewShader.use(); - render () { - const {gl} = this; - const tick = Date.now(); + // uniforms... + gl.uniform4f( + this.screenviewShader.uniform('u_camera'), + Math.floor(this.camera[0]), + Math.floor(this.camera[1]), + this.renderContainerDimensions.w / this.camera[2], + this.renderContainerDimensions.h / this.camera[2] + ); + gl.uniform4f( + this.screenviewShader.uniform('u_viewport'), + Math.floor(overlay.viewport.x), + Math.floor(overlay.viewport.y), + Math.floor(overlay.viewport.width), + Math.floor(overlay.viewport.height) + ); + gl.uniform4f( + this.screenviewShader.uniform('u_color'), + overlay.shade.color[0], + overlay.shade.color[1], + overlay.shade.color[2], + overlay.shade.opacity + ); - this.renderContainerDimensions = { - w: this.renderContainer.width(), - h: this.renderContainer.height() - }; + const a_position = this.screenviewShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.screenviewVertexBuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - this.renderBackground(gl); + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + }, - this.renderTilesAndEntityLayers(gl, tick); + render() { + const { gl } = this; + const tick = Date.now(); - this.maybeRenderObstructions(gl); + this.renderContainerDimensions = { + w: this.renderContainer.width(), + h: this.renderContainer.height() + }; - this.maybeRenderZones(gl); + this.renderBackground(gl); - this.maybeRenderMarchingAnts(gl, this.selection); + this.renderTilesAndEntityLayers(gl, tick); - this.maybeRenderMarchingAnts(gl, this.visibleHoverTile); + this.maybeRenderObstructions(gl); - this.maybeRenderScreenviewOverlay(gl, this.windowOverlay); + this.maybeRenderZones(gl); - // uncomment these to get frame render times - // const tock = new Date().getTime(); - // LOG((tock-tick) + 'ms to render'); - }, + this.maybeRenderMarchingAnts(gl, this.selection); - renderBackground (gl) { - gl.clear(gl.COLOR_BUFFER_BIT); + this.maybeRenderMarchingAnts(gl, this.visibleHoverTile); - if (window.$$$SCREENSHOT) { - return; - } + this.maybeRenderScreenviewOverlay(gl, this.windowOverlay); - // fill the map part of display with transparent pixels, first + // uncomment these to get frame render times + // const tock = new Date().getTime(); + // LOG((tock-tick) + 'ms to render'); + }, - const layer = this.layers[0]; + renderBackground(gl) { + gl.clear(gl.COLOR_BUFFER_BIT); - this.gl.blendFunc(this.gl.ONE, this.gl.ZERO); + if (window.$$$SCREENSHOT) { + return; + } - this.checkerShader.use(); + // fill the map part of display with transparent pixels, first - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - gl.uniform4f(this.checkerShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / this.vspData[layer.vsp].tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / this.vspData[layer.vsp].tilesize.height, - this.renderContainerDimensions.w / this.vspData[layer.vsp].tilesize.width / this.camera[2], - this.renderContainerDimensions.h / this.vspData[layer.vsp].tilesize.height / this.camera[2] - ); + const layer = this.layers[0]; - gl.uniform4f(this.checkerShader.uniform('u_dimensions'), - layer.dimensions.X, - layer.dimensions.Y, - this.vspData[layer.vsp].tiles_per_row, - this.vspImages[layer.vsp].height / this.vspData[layer.vsp].tilesize.height - ); + this.gl.blendFunc(this.gl.ONE, this.gl.ZERO); - gl.uniform4f(this.checkerShader.uniform('u_colorA'), this.checkerColorA[0], this.checkerColorA[1], this.checkerColorA[2], this.checkerColorA[3] ); - gl.uniform4f(this.checkerShader.uniform('u_colorB'), this.checkerColorB[0], this.checkerColorB[1], this.checkerColorB[2], this.checkerColorB[3]); + this.checkerShader.use(); - const a_position = this.checkerShader.attribute('a_position'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); - gl.enableVertexAttribArray(a_position); - gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + gl.uniform4f( + this.checkerShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + this.vspData[layer.vsp].tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + this.vspData[layer.vsp].tilesize.height, + this.renderContainerDimensions.w / + this.vspData[layer.vsp].tilesize.width / + this.camera[2], + this.renderContainerDimensions.h / + this.vspData[layer.vsp].tilesize.height / + this.camera[2] + ); - gl.drawArrays(gl.TRIANGLES, 0, 6); - }, + gl.uniform4f( + this.checkerShader.uniform('u_dimensions'), + layer.dimensions.X, + layer.dimensions.Y, + this.vspData[layer.vsp].tiles_per_row, + this.vspImages[layer.vsp].height / this.vspData[layer.vsp].tilesize.height + ); - _getEntityData (entity) { - const e = entity.MAPED_USEDEFAULT ? this.entityData.__default__ : this.entityData[entity.filename]; + gl.uniform4f( + this.checkerShader.uniform('u_colorA'), + this.checkerColorA[0], + this.checkerColorA[1], + this.checkerColorA[2], + this.checkerColorA[3] + ); + gl.uniform4f( + this.checkerShader.uniform('u_colorB'), + this.checkerColorB[0], + this.checkerColorB[1], + this.checkerColorB[2], + this.checkerColorB[3] + ); - if (!entity.MAPED_USEDEFAULT && e === this.entityData.__default__) { - debugger; - } + const a_position = this.checkerShader.attribute('a_position'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer); + gl.enableVertexAttribArray(a_position); + gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0); - return e; - }, + gl.drawArrays(gl.TRIANGLES, 0, 6); + }, - _getAnimationSafe(entity, entityData) { - if(entityData.animations[entity.animation]) { - return entityData.animations[entity.animation][0][0][0]; - } + _getEntityData(entity) { + const e = entity.MAPED_USEDEFAULT + ? this.entityData.__default__ + : this.entityData[entity.filename]; - if( Object.keys(entityData.animations).length ) { - return entityData.animations[Object.keys(entityData.animations)[0]][0][0][0]; - } + if (!entity.MAPED_USEDEFAULT && e === this.entityData.__default__) { + debugger; + } - ERROR("Entity didnt have any animations. THAT'S ILLEGAL."); - debugger; - }, + e.___filename = entity.MAPED_USEDEFAULT ? 'DEFAULT' : entity.filename; - renderEntity (entity, layer, tint, clip, mask, isTallRedraw) { - this.spriteShader.use(); + return e; + }, - const {gl} = this; - const {tilesize} = this.vspData[layer.vsp]; + _getAnimationSafe(entity, entityData) { + if (entityData.animations[entity.animation]) { + return entityData.animations[entity.animation][0][0][0]; + } - let layerOffsetTx = 0; - let layerOffsetTy = 0; + if (Object.keys(entityData.animations).length) { + return entityData.animations[Object.keys(entityData.animations)[0]][0][0][0]; + } - if(layer.offset) { - layerOffsetTx = layer.offset.X / tilesize.width; - layerOffsetTy = layer.offset.Y / tilesize.height; - } + ERROR("Entity didnt have any animations. THAT'S ILLEGAL."); + debugger; + }, - const entityData = this._getEntityData(entity); - const entityTexture = this.entityTextures[entityData.image];// || this.entityTextures["__default__"]; - if (!entityTexture) { - alert(`Entity '${ entity.name }' at (${ entity.location.tx },${ entity.location.ty }) with image path \`${ entityData.image }\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.`); - } + renderEntity(entity, layer, tint, clip, mask, isTallRedraw) { + this.spriteShader.use(); - clip = (!clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip); + const { gl } = this; + const { tilesize } = this.vspData[layer.vsp]; - const a_vertices = this.spriteShader.attribute('a_vertices'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.entityVertexBuffer); - gl.enableVertexAttribArray(a_vertices); - gl.vertexAttribPointer(a_vertices, 4, gl.FLOAT, false, 0, 0); + let layerOffsetTx = 0; + let layerOffsetTy = 0; - let tx; - let ty; + if (layer.offset) { + layerOffsetTx = layer.offset.X / tilesize.width; + layerOffsetTy = layer.offset.Y / tilesize.height; + } - // the coordinatespace isn't what you think it is. tx/ty can be fractional here. Time is a flat circle - if (Number.isInteger(entity.location.px) && Number.isInteger(entity.location.py)) { - tx = entity.location.px / tilesize.width; - ty = entity.location.py / tilesize.height; - } else { - tx = entity.location.tx; - ty = entity.location.ty; - } + const entityData = this._getEntityData(entity); + const entityTexture = this.entityTextures[entityData.image]; // || this.entityTextures["__default__"]; + if (!entityTexture) { + alert( + `Entity '${entity.name}' at (TX(${entity.location.tx},${entity.location.ty}) PX(${entity.location.px},${entity.location.py})) with image path \`${entityData.image}\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.` + ); + } - // apply hitbox xform - tx -= (entityData.hitbox[0] / tilesize.width); - ty -= (entityData.hitbox[1] / tilesize.height); - - // apply layer offset xform - tx += layerOffsetTx; - ty += layerOffsetTy; - - const tw = clip[2] / tilesize.width; - const th = clip[3] / tilesize.height; - - let fx = (entityData.outer_pad + clip[0]) / entityTexture.img.width; - let fy = (entityData.outer_pad + clip[1]) / entityTexture.img.height; - const fw = clip[2] / entityTexture.img.width; - const fh = clip[3] / entityTexture.img.height; - - const f = this._getAnimationSafe(entity, entityData); - fx += ((entityData.dims[0] + entityData.inner_pad) / entityTexture.img.width) * (f % entityData.per_row); - fy += ((entityData.dims[1] + entityData.inner_pad) / entityTexture.img.height) * Math.floor(f / entityData.per_row); - - const verts = []; - if (!mask) { - verts.push(tx, -ty, fx, fy); - verts.push(tx + tw, -ty, fx + fw, fy); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tw, -ty - th, fx + fw, fy + fh); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tw, -ty, fx + fw, fy); - } else { - const tm = [ - mask[0] / tilesize.width, - mask[1] / tilesize.height, - mask[2] / tilesize.width, - mask[3] / tilesize.height - ]; - const fm = [ - mask[0] / entityTexture.img.width, - mask[1] / entityTexture.img.height, - mask[2] / entityTexture.img.width, - mask[3] / entityTexture.img.height, - ] - - if (mask[1] > 0) { - verts.push(tx, -ty, fx, fy); - verts.push(tx + tw, -ty, fx + fw, fy); - verts.push(tx, -ty - tm[1], fx, fy + fm[1]); - verts.push(tx + tw, -ty - tm[1], fx + fw, fy + fm[1]); - verts.push(tx, -ty - tm[1], fx, fy + fm[1]); - verts.push(tx + tw, -ty, fx + fw, fy); - } - if (mask[0] > 0) { - verts.push(tx, -ty, fx, fy); - verts.push(tx + tm[0], -ty, fx + fm[0], fy); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tm[0], -ty - th, fx + fm[0], fy + fh); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tm[0], -ty, fx + fm[0], fy); - } - if (mask[0] + mask[2] < entityData.dims[0]) { - verts.push(tx + tm[0] + tm[2], -ty, fx + fm[0] + fm[2], fy); - verts.push(tx + tw, -ty, fx + fw, fy); - verts.push(tx + tm[0] + tm[2], -ty - th, fx + fm[0] + fm[2], fy + fh); - verts.push(tx + tw, -ty - th, fx + fw, fy + fh); - verts.push(tx + tm[0] + tm[2], -ty - th, fx + fm[0] + fm[2], fy + fh); - verts.push(tx + tw, -ty, fx + fw, fy); - } - // assume we at least have the "below the mask" part of the entity to draw - verts.push(tx, -ty - tm[1] - tm[3], fx, fy + fm[1] + fm[3]); - verts.push(tx + tw, -ty - tm[1] - tm[3], fx + fw, fy + fm[1] + fm[3]); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tw, -ty - th, fx + fw, fy + fh); - verts.push(tx, -ty - th, fx, fy + fh); - verts.push(tx + tw, -ty - tm[1] - tm[3], fx + fw, fy + fm[1] + fm[3]); - } - this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(verts), this.gl.STATIC_DRAW); - - const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x:0, y:0 }; - gl.uniform4f( - this.spriteShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / tilesize.height, - this.renderContainerDimensions.w / tilesize.width / this.camera[2], - this.renderContainerDimensions.h / tilesize.height / this.camera[2] - ); + clip = !clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip; - gl.uniform4f(this.spriteShader.uniform('u_tint'), tint[0], tint[1], tint[2], tint[3]); + const a_vertices = this.spriteShader.attribute('a_vertices'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.entityVertexBuffer); + gl.enableVertexAttribArray(a_vertices); + gl.vertexAttribPointer(a_vertices, 4, gl.FLOAT, false, 0, 0); - const u_texture = this.tilemapShader.uniform('u_spriteAtlas'); - gl.uniform1i(u_texture, 0); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, entityTexture.tex); + let tx; + let ty; - gl.drawArrays(gl.TRIANGLES, 0, verts.length / 4); + // the coordinatespace isn't what you think it is. tx/ty can be fractional here. Time is a flat circle + if (Number.isInteger(entity.location.px) && Number.isInteger(entity.location.py)) { + tx = entity.location.px / tilesize.width; + ty = entity.location.py / tilesize.height; + } else { + tx = entity.location.tx; + ty = entity.location.ty; + } - // if A is 0, it's not being drawn anyway. - if( this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING && this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING.A ) { - this.renderEntityBounds(entity, layer, tint, clip, mask, verts, viewport); - } + // apply hitbox xform + tx -= entityData.hitbox[0] / tilesize.width; + ty -= entityData.hitbox[1] / tilesize.height; + + // apply layer offset xform + tx += layerOffsetTx; + ty += layerOffsetTy; + + const tw = clip[2] / tilesize.width; + const th = clip[3] / tilesize.height; + + let fx = (entityData.outer_pad + clip[0]) / entityTexture.img.width; + let fy = (entityData.outer_pad + clip[1]) / entityTexture.img.height; + const fw = clip[2] / entityTexture.img.width; + const fh = clip[3] / entityTexture.img.height; + + const f = this._getAnimationSafe(entity, entityData); + fx += + ((entityData.dims[0] + entityData.inner_pad) / entityTexture.img.width) * + (f % entityData.per_row); + fy += + ((entityData.dims[1] + entityData.inner_pad) / entityTexture.img.height) * + Math.floor(f / entityData.per_row); + + const verts = []; + if (!mask) { + verts.push(tx, -ty, fx, fy); + verts.push(tx + tw, -ty, fx + fw, fy); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tw, -ty - th, fx + fw, fy + fh); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tw, -ty, fx + fw, fy); + } else { + const tm = [ + mask[0] / tilesize.width, + mask[1] / tilesize.height, + mask[2] / tilesize.width, + mask[3] / tilesize.height + ]; + const fm = [ + mask[0] / entityTexture.img.width, + mask[1] / entityTexture.img.height, + mask[2] / entityTexture.img.width, + mask[3] / entityTexture.img.height + ]; + + if (mask[1] > 0) { + verts.push(tx, -ty, fx, fy); + verts.push(tx + tw, -ty, fx + fw, fy); + verts.push(tx, -ty - tm[1], fx, fy + fm[1]); + verts.push(tx + tw, -ty - tm[1], fx + fw, fy + fm[1]); + verts.push(tx, -ty - tm[1], fx, fy + fm[1]); + verts.push(tx + tw, -ty, fx + fw, fy); + } + if (mask[0] > 0) { + verts.push(tx, -ty, fx, fy); + verts.push(tx + tm[0], -ty, fx + fm[0], fy); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tm[0], -ty - th, fx + fm[0], fy + fh); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tm[0], -ty, fx + fm[0], fy); + } + if (mask[0] + mask[2] < entityData.dims[0]) { + verts.push(tx + tm[0] + tm[2], -ty, fx + fm[0] + fm[2], fy); + verts.push(tx + tw, -ty, fx + fw, fy); + verts.push(tx + tm[0] + tm[2], -ty - th, fx + fm[0] + fm[2], fy + fh); + verts.push(tx + tw, -ty - th, fx + fw, fy + fh); + verts.push(tx + tm[0] + tm[2], -ty - th, fx + fm[0] + fm[2], fy + fh); + verts.push(tx + tw, -ty, fx + fw, fy); + } + // assume we at least have the "below the mask" part of the entity to draw + verts.push(tx, -ty - tm[1] - tm[3], fx, fy + fm[1] + fm[3]); + verts.push(tx + tw, -ty - tm[1] - tm[3], fx + fw, fy + fm[1] + fm[3]); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tw, -ty - th, fx + fw, fy + fh); + verts.push(tx, -ty - th, fx, fy + fh); + verts.push(tx + tw, -ty - tm[1] - tm[3], fx + fw, fy + fm[1] + fm[3]); + } + this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(verts), this.gl.STATIC_DRAW); + + const viewport = this.windowOverlay.on ? this.windowOverlay.viewport : { x: 0, y: 0 }; + gl.uniform4f( + this.spriteShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + tilesize.height, + this.renderContainerDimensions.w / tilesize.width / this.camera[2], + this.renderContainerDimensions.h / tilesize.height / this.camera[2] + ); - // if A is 0, it's not being drawn anyway. - if( this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING && this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING.A ) { - this.renderEntityHitBoxBounds(entity, layer, tint, clip, mask, verts, viewport); - } + gl.uniform4f(this.spriteShader.uniform('u_tint'), tint[0], tint[1], tint[2], tint[3]); - // if A is 0, it's not being drawn anyway. - if( isTallRedraw && this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING && this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING.A ) { - this.renderEntityTallRedrawBoundsBounds(entity, layer, tint, clip, mask, verts, viewport); - } - }, + const u_texture = this.tilemapShader.uniform('u_spriteAtlas'); + gl.uniform1i(u_texture, 0); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, entityTexture.tex); - renderEntityTallRedrawBoundsBounds(entity, layer, tint, clip, mask, verts, viewport) { - this.entityBoundsShader.use(); - - const {gl} = this; - const {tilesize} = this.vspData[layer.vsp]; + gl.drawArrays(gl.TRIANGLES, 0, verts.length / 4); - let layerOffsetTx = 0; - let layerOffsetTy = 0; + // if A is 0, it's not being drawn anyway. + if ( + this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING && + this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING.A + ) { + this.renderEntityBounds(entity, layer, tint, clip, mask, verts, viewport); + } - if(layer.offset) { - layerOffsetTx = layer.offset.X / tilesize.width; - layerOffsetTy = layer.offset.Y / tilesize.height; - } + // if A is 0, it's not being drawn anyway. + if ( + this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING && + this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING.A + ) { + this.renderEntityHitBoxBounds(entity, layer, tint, clip, mask, verts, viewport); + } - const entityData = this._getEntityData(entity); - const entityTexture = this.entityTextures[entityData.image];// || this.entityTextures["__default__"]; - if (!entityTexture) { - alert(`Entity '${ entity.name }' at (${ entity.location.tx },${ entity.location.ty }) with image path \`${ entityData.image }\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.`); - } + // if A is 0, it's not being drawn anyway. + if ( + isTallRedraw && + this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING && + this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING.A + ) { + this.renderEntityTallRedrawBoundsBounds( + entity, + layer, + tint, + clip, + mask, + verts, + viewport + ); + } + }, - clip = (!clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip); - - const a_vertices = this.spriteShader.attribute('a_vertices'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); - gl.enableVertexAttribArray(a_vertices); - gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); - - const hitbox_x = entityData.hitbox[0]; // -entityData.hitbox[0] - const hitbox_y = entityData.hitbox[1]; // -entityData.hitbox[1] - const hitbox_w = entityData.hitbox[2]; // -entityData.hitbox[0] - const hitbox_h = entityData.hitbox[3]; // -entityData.hitbox[1] - - let x = entity.location.px / tilesize.width || entity.location.tx; - let y = entity.location.py / tilesize.height || entity.location.ty; - x += layerOffsetTx; - y += layerOffsetTy; - x -= hitbox_x / tilesize.width; - y -= hitbox_y / tilesize.height; - x += clip[0] / tilesize.width; - y += clip[1] / tilesize.height; - - const w = clip[2] / tilesize.width; - const h = clip[3] / tilesize.height; - - gl.bufferData( gl.ARRAY_BUFFER, new Float32Array([ - x, -y, - x+w, -y, - x+w, -y, - x+w, -(y+h), - x+w, -(y+h), - x, -(y+h), - x, -(y+h), - x, -y,]), - this.gl.STATIC_DRAW - ); + renderEntityTallRedrawBoundsBounds(entity, layer, tint, clip, mask, verts, viewport) { + this.entityBoundsShader.use(); - gl.uniform4f( - this.entityBoundsShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / tilesize.height, - this.renderContainerDimensions.w / tilesize.width / this.camera[2], - this.renderContainerDimensions.h / tilesize.height / this.camera[2] - ); + const { gl } = this; + const { tilesize } = this.vspData[layer.vsp]; - const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING; + let layerOffsetTx = 0; + let layerOffsetTy = 0; - gl.uniform4f( - this.entityBoundsShader.uniform('u_entBoundsColor'), - borderColor.R, - borderColor.G, - borderColor.B, - borderColor.A - ); - - gl.drawArrays( gl.LINES, 0, 8 ); - }, + if (layer.offset) { + layerOffsetTx = layer.offset.X / tilesize.width; + layerOffsetTy = layer.offset.Y / tilesize.height; + } - renderEntityBounds(entity, layer, tint, clip, mask, verts, viewport) { - this.entityBoundsShader.use(); - - const {gl} = this; - const {tilesize} = this.vspData[layer.vsp]; + const entityData = this._getEntityData(entity); + const entityTexture = this.entityTextures[entityData.image]; // || this.entityTextures["__default__"]; + if (!entityTexture) { + alert( + `Entity '${entity.name}' at (${entity.location.tx},${entity.location.ty}) with image path \`${entityData.image}\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.` + ); + } - let layerOffsetTx = 0; - let layerOffsetTy = 0; + clip = !clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip; + + const a_vertices = this.spriteShader.attribute('a_vertices'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); + gl.enableVertexAttribArray(a_vertices); + gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); + + const hitbox_x = entityData.hitbox[0]; // -entityData.hitbox[0] + const hitbox_y = entityData.hitbox[1]; // -entityData.hitbox[1] + const hitbox_w = entityData.hitbox[2]; // -entityData.hitbox[0] + const hitbox_h = entityData.hitbox[3]; // -entityData.hitbox[1] + + let x = entity.location.px / tilesize.width || entity.location.tx; + let y = entity.location.py / tilesize.height || entity.location.ty; + x += layerOffsetTx; + y += layerOffsetTy; + x -= hitbox_x / tilesize.width; + y -= hitbox_y / tilesize.height; + x += clip[0] / tilesize.width; + y += clip[1] / tilesize.height; + + const w = clip[2] / tilesize.width; + const h = clip[3] / tilesize.height; + + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([ + x, + -y, + x + w, + -y, + x + w, + -y, + x + w, + -(y + h), + x + w, + -(y + h), + x, + -(y + h), + x, + -(y + h), + x, + -y + ]), + this.gl.STATIC_DRAW + ); - if(layer.offset) { - layerOffsetTx = layer.offset.X / tilesize.width; - layerOffsetTy = layer.offset.Y / tilesize.height; - } + gl.uniform4f( + this.entityBoundsShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + tilesize.height, + this.renderContainerDimensions.w / tilesize.width / this.camera[2], + this.renderContainerDimensions.h / tilesize.height / this.camera[2] + ); - const entityData = this._getEntityData(entity); - const entityTexture = this.entityTextures[entityData.image];// || this.entityTextures["__default__"]; - if (!entityTexture) { - alert(`Entity '${ entity.name }' at (${ entity.location.tx },${ entity.location.ty }) with image path \`${ entityData.image }\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.`); - } + const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING; - clip = (!clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip); - - const a_vertices = this.spriteShader.attribute('a_vertices'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); - gl.enableVertexAttribArray(a_vertices); - gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); - - const hitbox_x = entityData.hitbox[0]; // -entityData.hitbox[0] - const hitbox_y = entityData.hitbox[1]; // -entityData.hitbox[1] - const hitbox_w = entityData.hitbox[2]; // -entityData.hitbox[0] - const hitbox_h = entityData.hitbox[3]; // -entityData.hitbox[1] - - let x = entity.location.px / tilesize.width || entity.location.tx; - let y = entity.location.py / tilesize.height || entity.location.ty; - x -= hitbox_x / tilesize.width;; - y -= hitbox_y / tilesize.height; - x+= layerOffsetTx; - y+= layerOffsetTy; - const w = entityData.dims[0] / tilesize.width; - const h = entityData.dims[1] / tilesize.height; - - gl.bufferData( gl.ARRAY_BUFFER, new Float32Array([ - x, -y, - x+w, -y, - x+w, -y, - x+w, -(y+h), - x+w, -(y+h), - x, -(y+h), - x, -(y+h), - x, -y,]), - this.gl.STATIC_DRAW - ); + gl.uniform4f( + this.entityBoundsShader.uniform('u_entBoundsColor'), + borderColor.R, + borderColor.G, + borderColor.B, + borderColor.A + ); - gl.uniform4f( - this.entityBoundsShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / tilesize.height, - this.renderContainerDimensions.w / tilesize.width / this.camera[2], - this.renderContainerDimensions.h / tilesize.height / this.camera[2] - ); + gl.drawArrays(gl.LINES, 0, 8); + }, - const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING; + renderEntityBounds(entity, layer, tint, clip, mask, verts, viewport) { + this.entityBoundsShader.use(); - gl.uniform4f( - this.entityBoundsShader.uniform('u_entBoundsColor'), - borderColor.R, - borderColor.G, - borderColor.B, - borderColor.A - ); - - gl.drawArrays( gl.LINES, 0, 8 ); - }, + const { gl } = this; + const { tilesize } = this.vspData[layer.vsp]; - renderEntityHitBoxBounds(entity, layer, tint, clip, mask, verts, viewport) { - this.entityBoundsShader.use(); - - const {gl} = this; - const {tilesize} = this.vspData[layer.vsp]; - let layerOffsetTx = 0; - let layerOffsetTy = 0; - - if(layer.offset) { - layerOffsetTx = layer.offset.X / tilesize.width; - layerOffsetTy = layer.offset.Y / tilesize.height; - } - const entityData = this._getEntityData(entity); - const entityTexture = this.entityTextures[entityData.image];// || this.entityTextures["__default__"]; - if (!entityTexture) { - alert(`Entity '${ entity.name }' at (${ entity.location.tx },${ entity.location.ty }) with image path \`${ entityData.image }\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.`); - } + let layerOffsetTx = 0; + let layerOffsetTy = 0; - clip = (!clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip); + if (layer.offset) { + layerOffsetTx = layer.offset.X / tilesize.width; + layerOffsetTy = layer.offset.Y / tilesize.height; + } - const a_vertices = this.spriteShader.attribute('a_vertices'); - gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); - gl.enableVertexAttribArray(a_vertices); - gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); + const entityData = this._getEntityData(entity); + const entityTexture = this.entityTextures[entityData.image]; // || this.entityTextures["__default__"]; + if (!entityTexture) { + alert( + `Entity '${entity.name}' at (${entity.location.tx},${entity.location.ty}) with image path \`${entityData.image}\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.` + ); + } - let x = entity.location.px / tilesize.width || entity.location.tx; - let y = entity.location.py / tilesize.height || entity.location.ty; - x+=layerOffsetTx; - y+=layerOffsetTy; - const w = entityData.hitbox[2] / tilesize.width; - const h = entityData.hitbox[3] / tilesize.height; + clip = !clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip; + + const a_vertices = this.spriteShader.attribute('a_vertices'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); + gl.enableVertexAttribArray(a_vertices); + gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); + + const hitbox_x = entityData.hitbox[0]; // -entityData.hitbox[0] + const hitbox_y = entityData.hitbox[1]; // -entityData.hitbox[1] + const hitbox_w = entityData.hitbox[2]; // -entityData.hitbox[0] + const hitbox_h = entityData.hitbox[3]; // -entityData.hitbox[1] + + let x = entity.location.px / tilesize.width || entity.location.tx; + let y = entity.location.py / tilesize.height || entity.location.ty; + x -= hitbox_x / tilesize.width; + y -= hitbox_y / tilesize.height; + x += layerOffsetTx; + y += layerOffsetTy; + const w = entityData.dims[0] / tilesize.width; + const h = entityData.dims[1] / tilesize.height; + + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([ + x, + -y, + x + w, + -y, + x + w, + -y, + x + w, + -(y + h), + x + w, + -(y + h), + x, + -(y + h), + x, + -(y + h), + x, + -y + ]), + this.gl.STATIC_DRAW + ); - let x1 = x; - let x2 = x+w; + gl.uniform4f( + this.entityBoundsShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + tilesize.height, + this.renderContainerDimensions.w / tilesize.width / this.camera[2], + this.renderContainerDimensions.h / tilesize.height / this.camera[2] + ); - let y1 = y; - let y2 = y+h; + const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING; - if( x2 < x1 ) { - [x1, x2] = [x2, x1]; - } + gl.uniform4f( + this.entityBoundsShader.uniform('u_entBoundsColor'), + borderColor.R, + borderColor.G, + borderColor.B, + borderColor.A + ); - if( y2 < y1 ) { - [y1, y2] = [y2, y1]; - } + gl.drawArrays(gl.LINES, 0, 8); + }, + + renderEntityHitBoxBounds(entity, layer, tint, clip, mask, verts, viewport) { + this.entityBoundsShader.use(); + + const { gl } = this; + const { tilesize } = this.vspData[layer.vsp]; + let layerOffsetTx = 0; + let layerOffsetTy = 0; + + if (layer.offset) { + layerOffsetTx = layer.offset.X / tilesize.width; + layerOffsetTy = layer.offset.Y / tilesize.height; + } + const entityData = this._getEntityData(entity); + const entityTexture = this.entityTextures[entityData.image]; // || this.entityTextures["__default__"]; + if (!entityTexture) { + alert( + `Entity '${entity.name}' at (${entity.location.tx},${entity.location.ty}) with image path \`${entityData.image}\` tried to render without an assigned asset! Make sure the appropriate asset (png?) exists.` + ); + } + + clip = !clip ? [0, 0, entityData.dims[0], entityData.dims[1]] : clip; + + const a_vertices = this.spriteShader.attribute('a_vertices'); + gl.bindBuffer(gl.ARRAY_BUFFER, this.lineBuf); + gl.enableVertexAttribArray(a_vertices); + gl.vertexAttribPointer(a_vertices, 2, gl.FLOAT, false, 0, 0); - const arLines = [ - x, -y, - x+w, -y, - x+w, -y, - x+w, -(y+h), - x+w, -(y+h), - x, -(y+h), - x, -(y+h), - x, -y, - ]; - - /* Playing around with "architectural" shading but I think I need some trig to do it how I thought I could :( + let x = entity.location.px / tilesize.width || entity.location.tx; + let y = entity.location.py / tilesize.height || entity.location.ty; + x += layerOffsetTx; + y += layerOffsetTy; + const w = entityData.hitbox[2] / tilesize.width; + const h = entityData.hitbox[3] / tilesize.height; + + let x1 = x; + let x2 = x + w; + + let y1 = y; + let y2 = y + h; + + if (x2 < x1) { + [x1, x2] = [x2, x1]; + } + + if (y2 < y1) { + [y1, y2] = [y2, y1]; + } + + const arLines = [ + x, + -y, + x + w, + -y, + x + w, + -y, + x + w, + -(y + h), + x + w, + -(y + h), + x, + -(y + h), + x, + -(y + h), + x, + -y + ]; + + /* Playing around with "architectural" shading but I think I need some trig to do it how I thought I could :( let xi = x1; let yi = y1; @@ -2142,54 +2598,55 @@ Map.prototype = { */ - gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(arLines), - this.gl.STATIC_DRAW - ); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arLines), this.gl.STATIC_DRAW); - gl.uniform4f( - this.entityBoundsShader.uniform('u_camera'), - Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / tilesize.width, - Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / tilesize.height, - this.renderContainerDimensions.w / tilesize.width / this.camera[2], - this.renderContainerDimensions.h / tilesize.height / this.camera[2] - ); + gl.uniform4f( + this.entityBoundsShader.uniform('u_camera'), + Math.floor(layer.parallax.X * (this.camera[0] + viewport.x) - viewport.x) / + tilesize.width, + Math.floor(layer.parallax.Y * (this.camera[1] + viewport.y) - viewport.y) / + tilesize.height, + this.renderContainerDimensions.w / tilesize.width / this.camera[2], + this.renderContainerDimensions.h / tilesize.height / this.camera[2] + ); - const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING; + const borderColor = this.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING; - gl.uniform4f( - this.entityBoundsShader.uniform('u_entBoundsColor'), - borderColor.R, - borderColor.G, - borderColor.B, - borderColor.A - ); - - gl.drawArrays( gl.LINES, 0, arLines.length/2 ); - }, - - cleanUpCallbacks () { - this.renderContainer.off(undefined, undefined, this); - }, - - resize () { - if (!this.renderContainer || !this.gl) { return; } - const w = this.renderContainer.width(); - const h = this.renderContainer.height(); - this.renderContainer.attr('width', w); - this.renderContainer.attr('height', h); - this.gl.viewport(0, 0, w, h); - }, - - resetCamera (x,y,z) { - - if(typeof x === 'undefined') { - x = 0; - y = 0; - z = 1; - } + gl.uniform4f( + this.entityBoundsShader.uniform('u_entBoundsColor'), + borderColor.R, + borderColor.G, + borderColor.B, + borderColor.A + ); + + gl.drawArrays(gl.LINES, 0, arLines.length / 2); + }, - this.camera[0] = x; - this.camera[1] = y; - this.camera[2] = z; - } + cleanUpCallbacks() { + this.renderContainer.off(undefined, undefined, this); + }, + + resize() { + if (!this.renderContainer || !this.gl) { + return; + } + const w = this.renderContainer.width(); + const h = this.renderContainer.height(); + this.renderContainer.attr('width', w); + this.renderContainer.attr('height', h); + this.gl.viewport(0, 0, w, h); + }, + + resetCamera(x, y, z) { + if (typeof x === 'undefined') { + x = 0; + y = 0; + z = 1; + } + + this.camera[0] = x; + this.camera[1] = y; + this.camera[2] = z; + } }; diff --git a/src/js/ui/EntityPalette.js b/src/js/ui/EntityPalette.js index 4cb51f4..44701a6 100644 --- a/src/js/ui/EntityPalette.js +++ b/src/js/ui/EntityPalette.js @@ -6,352 +6,357 @@ import { notify } from '../../Notification-Pane'; const { clipboard } = require('electron'); const jetpack = require('fs-jetpack'); -const {$} = window; +const { $ } = window; let _entityLayersExpanded = false; -const getDirFromPath = (path) => { - return path.match(/(.*)[\/\\]/)[1]||''; -} +const getDirFromPath = path => { + return path.match(/(.*)[\/\\]/)[1] || ''; +}; -const get_sully_code_line_for_entity = (e) => { - let tmp = ''; - - if(e.activation_script) { - tmp += `public void ${e.activation_script}( Entity e ) {`; - } else { - tmp += `// no activation script `; - } - - tmp += `//"${e.name}", uuid: "${e.uuid}"\n`; - - if(e.activation_script) { - tmp += `\n}\n\n`; - } - - return tmp; -} +const get_sully_code_line_for_entity = e => { + let tmp = ''; -const maybe_change_script_name = (e) => { - if( !e.activation_script && e.name ) { - let tmp = e.name.toLowerCase(); - tmp = tmp.replace(/\W/g, '_'); - e.activation_script = tmp; - return true; - } + if (e.activation_script) { + tmp += `public void ${e.activation_script}( Entity e ) {`; + } else { + tmp += `// no activation script `; + } - return false; + tmp += `//"${e.name}", uuid: "${e.uuid}"\n`; + + if (e.activation_script) { + tmp += `\n}\n\n`; + } + + return tmp; +}; + +const maybe_change_script_name = e => { + if (!e.activation_script && e.name) { + let tmp = e.name.toLowerCase(); + tmp = tmp.replace(/\W/g, '_'); + e.activation_script = tmp; + return true; + } + + return false; }; const generate_functions_from_names = () => { - let count = 0; + let count = 0; - window.$$$currentMap.mapData.entities.forEach((e) => { - - if( maybe_change_script_name(e) ) { - count++; - } - }); + window.$$$currentMap.mapData.entities.forEach(e => { + if (maybe_change_script_name(e)) { + count++; + } + }); - notify(`Generated ${count} activation scripts from names.`); -} + notify(`Generated ${count} activation scripts from names.`); +}; const copy_useful_entity_data_to_clipboard = () => { - let tmp = ''; + let tmp = ''; - window.$$$currentMap.mapData.entities.forEach((e) => { - tmp += get_sully_code_line_for_entity(e); - }); + window.$$$currentMap.mapData.entities.forEach(e => { + tmp += get_sully_code_line_for_entity(e); + }); - clipboard.writeText(tmp, 'clipboard'); - notify("Copied all entity data to clipboard in Sully format."); + clipboard.writeText(tmp, 'clipboard'); + notify('Copied all entity data to clipboard in Sully format.'); }; -const copy_useful_single_entity_data_to_clipboard = (e) => { - clipboard.writeText(get_sully_code_line_for_entity(e), 'clipboard'); - notify(`Copied entity data for "${e.name}" to clipboard in Sully format.`); +const copy_useful_single_entity_data_to_clipboard = e => { + clipboard.writeText(get_sully_code_line_for_entity(e), 'clipboard'); + notify(`Copied entity data for "${e.name}" to clipboard in Sully format.`); }; const set_animation_dropdown = ($template, animationKeyset, animation) => { - const $entAnim = $template.find('#entity_animation'); - - // repopulate animation select - $entAnim.empty(); - $.each(animationKeyset, (key, value) => { - $entAnim.append( - $('') - .attr('value', value) - .text(value) - ); - }); - - // set value - $entAnim.val(animation); -} + const $entAnim = $template.find('#entity_animation'); + + // repopulate animation select + $entAnim.empty(); + $.each(animationKeyset, (key, value) => { + $entAnim.append( + $('') + .attr('value', value) + .text(value) + ); + }); + + // set value + $entAnim.val(animation); +}; -export const setNormalEntityVisibility = (val) => { - window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE = !!val; +export const setNormalEntityVisibility = val => { + window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE = !!val; }; export const getNormalEntityVisibility = () => { - return window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE; + return window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE; }; -export const setEntityLayersExpanded = (val) => { - _entityLayersExpanded = !!val; +export const setEntityLayersExpanded = val => { + _entityLayersExpanded = !!val; }; export const getEntityLayersExpanded = () => { - return _entityLayersExpanded; + return _entityLayersExpanded; }; -export const shouldShowEntitiesForLayer = (layername) => { - if (!window.$$$currentMap.layerLookup[layername]) { - modal_error(`cannot shouldShowEntitiesForLayer, '${ layername }' is not a layer`); - } +export const shouldShowEntitiesForLayer = layername => { + if (!window.$$$currentMap.layerLookup[layername]) { + modal_error(`cannot shouldShowEntitiesForLayer, '${layername}' is not a layer`); + } - const shouldHide = window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS; + const shouldHide = window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS; - return !shouldHide; + return !shouldHide; }; export const setShowEntitiesForLayer = (layername, isVisible) => { - if (!window.$$$currentMap.layerLookup[layername]) { - modal_error(`cannot setShowEntitiesForLayer, '${ layername }' is not a layer`); - } + if (!window.$$$currentMap.layerLookup[layername]) { + modal_error(`cannot setShowEntitiesForLayer, '${layername}' is not a layer`); + } - window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS = !isVisible; + window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS = !isVisible; - console.log(`ents(${ layername })${ window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS}`); + console.log(`ents(${layername})${window.$$$currentMap.layerLookup[layername].maped_HIDE_ENTS}`); }; let currentEntities = null; // TODO test-only atm. bad. -export const setCurrentEntities = (ce) => { - currentEntities = ce; - return currentEntities; +export const setCurrentEntities = ce => { + currentEntities = ce; + return currentEntities; }; export const getCurrentEntities = () => { - return currentEntities; + return currentEntities; }; -const initEntitiesWidget = (map) => { - currentEntities = map.mapData.entities; +const initEntitiesWidget = map => { + currentEntities = map.mapData.entities; - redraw_palette(); - setupColorStuff(); + redraw_palette(); + setupColorStuff(); - $('.entity-palette').resize(function () { - fixContainerSize(); - }); + $('.entity-palette').resize(function() { + fixContainerSize(); + }); - $('.entity-palette #entity-new').click((evt) => { - new_entity_click(evt); - }); + $('.entity-palette #entity-new').click(evt => { + new_entity_click(evt); + }); + + $('.entity-palette #entity-spreadsheet').click(() => { + window.alert('SPREAD THAT SHEET entity SHEIT'); + }); - $('.entity-palette #entity-spreadsheet').click(() => { - window.alert('SPREAD THAT SHEET entity SHEIT'); - }); - - init(); + init(); }; -const _select_entity_ui_inner = ($node) => { - $('.entity-row').removeClass('highlighted'); - $node.addClass('highlighted'); +const _select_entity_ui_inner = $node => { + $('.entity-row').removeClass('highlighted'); + $node.addClass('highlighted'); }; -const select_entity_from_pallete = (evt) => { - const $it_me = $(evt.target).closest('.entity-row'); - _select_entity_ui_inner($it_me); - return $it_me; +const select_entity_from_pallete = evt => { + const $it_me = $(evt.target).closest('.entity-row'); + _select_entity_ui_inner($it_me); + return $it_me; }; let highlightedEnts = new Set(); -export const addEntityToHighlight = (ent) => { - ent.MAPED_HIGHLIGHTED = true; - highlightedEnts.add(ent); +export const addEntityToHighlight = ent => { + ent.MAPED_HIGHLIGHTED = true; + highlightedEnts.add(ent); }; export const clearAllEntitysFromHighlight = () => { - highlightedEnts.forEach((e) => { - delete e.MAPED_HIGHLIGHTED; - }); + highlightedEnts.forEach(e => { + delete e.MAPED_HIGHLIGHTED; + }); - highlightedEnts = new Set(); + highlightedEnts = new Set(); }; export const getSelectedEntities = () => { - return Array.from(highlightedEnts); -} + return Array.from(highlightedEnts); +}; -export const moveSelectedEntityToTile = (x, y) => { - const entList = getSelectedEntities(); +export const moveSelectedEntityToTile = (x, y) => { + const entList = getSelectedEntities(); - if( entList.length != 1 ) { - alert(`Invald number of entities selected. Need 1, got ${ entList.length}` ); - return; - } + if (entList.length != 1) { + alert(`Invald number of entities selected. Need 1, got ${entList.length}`); + return; + } - const ent = entList[0]; + const ent = entList[0]; - update_entity_location(ent.INDEX, { - tx: x, - ty: y, - px: null, - py: null - }); + update_entity_location(ent.INDEX, { + tx: x, + ty: y, + px: null, + py: null + }); - do_the_no_things(null, redraw_palette); -} + do_the_no_things(null, redraw_palette); +}; -export const moveSelectedEntityToPixel = (px, py) => { - const entList = getSelectedEntities(); +export const moveSelectedEntityToPixel = (px, py) => { + const entList = getSelectedEntities(); - if( entList.length != 1 ) { - alert(`Invald number of entities selected. Need 1, got ${ entList.length}` ); - return; - } + if (entList.length != 1) { + alert(`Invald number of entities selected. Need 1, got ${entList.length}`); + return; + } - const ent = entList[0]; + const ent = entList[0]; - update_entity_location(ent.INDEX, { - tx: null, - ty: null, - px, - py, - }); + update_entity_location(ent.INDEX, { + tx: null, + ty: null, + px, + py + }); - do_the_no_things(null, redraw_palette); -} + do_the_no_things(null, redraw_palette); +}; -export const selectEntityByIndex = (idx) => { - if (!idx) { - idx = 0; - } +export const selectEntityByIndex = idx => { + if (!idx) { + idx = 0; + } - const $it_me = $(`.entity-row[data-index=${ idx }]`); - // _select_entity_ui_inner($it_me); - $it_me.click(); - return $it_me; + const $it_me = $(`.entity-row[data-index=${idx}]`); + // _select_entity_ui_inner($it_me); + $it_me.click(); + return $it_me; }; -const singleclick_handler = (evt) => { - clearAllEntitysFromHighlight(); - - const $ent = select_entity_from_pallete(evt); - const ent = currentEntities[$ent.data('index')]; - ent.INDEX = $ent.data('index'); +const singleclick_handler = evt => { + clearAllEntitysFromHighlight(); - addEntityToHighlight(ent); + const $ent = select_entity_from_pallete(evt); + const ent = currentEntities[$ent.data('index')]; + ent.INDEX = $ent.data('index'); + addEntityToHighlight(ent); - const {hitbox} = window.$$$currentMap.entityData[ent.filename]; - // centerMapOnXY(window.$$$currentMap, ent.location.px - hitbox[0], ent.location.py - hitbox[1], hitbox[2], hitbox[3]); + const { hitbox } = window.$$$currentMap.entityData[ent.filename]; + // centerMapOnXY(window.$$$currentMap, ent.location.px - hitbox[0], ent.location.py - hitbox[1], hitbox[2], hitbox[3]); }; -const doubleclick_handler = (evt) => { - const $it_me = select_entity_from_pallete(evt); - edit_entity_click(evt, $it_me.data('index')); +const doubleclick_handler = evt => { + const $it_me = select_entity_from_pallete(evt); + edit_entity_click(evt, $it_me.data('index')); }; const redraw_palette = () => { - const $list = $('.entity-list'); - $list.html(''); + const $list = $('.entity-list'); + $list.html(''); - $('#entity-number').text(currentEntities.length); + $('#entity-number').text(currentEntities.length); - for (let i = 0; i < currentEntities.length; i++) { - const myBaseData = $$$currentMap.entityData[currentEntities[i].filename]; + for (let i = 0; i < currentEntities.length; i++) { + const myBaseData = $$$currentMap.entityData[currentEntities[i].filename]; - const $tmp = $(`
  • `); - - $tmp.find('.entity-name').text(currentEntities[i].name); + const $tmp = $( + `
  • ` + ); - if(myBaseData && myBaseData.regions && myBaseData.regions.Tall_Redraw) { - $tmp.find('.entity-index').html(`${i } `); - } else { - $tmp.find('.entity-index').text(i); - } + $tmp.find('.entity-name').text(currentEntities[i].name); + + if (myBaseData && myBaseData.regions && myBaseData.regions.Tall_Redraw) { + $tmp.find('.entity-index').html( + `${i} ` + ); + } else { + $tmp.find('.entity-index').text(i); + } - $tmp.click(singleclick_handler); - $tmp.dblclick(doubleclick_handler); + $tmp.click(singleclick_handler); + $tmp.dblclick(doubleclick_handler); - $list.append($tmp); - } + $list.append($tmp); + } - fixContainerSize(); + fixContainerSize(); }; const fixContainerSize = () => { - const palette = $('.entity-palette'); - const container = $('.entity-palette .window-container'); + const palette = $('.entity-palette'); + const container = $('.entity-palette .window-container'); - container.height(palette.height() - 290); + container.height(palette.height() - 290); }; export const init = () => { - $(function() { - $.contextMenu({ - selector: '.entity-palette h3.ui-widget-header', - callback(key, options) { - switch(key) { - default: - console.log(`unknown key: ${ key}`); - return; - case 'generate_functions': - generate_functions_from_names(); - return; - case 'copy_scriptnames': - copy_useful_entity_data_to_clipboard(); - - } - }, - items: { - "copy_scriptnames": {name: "Copy useful entity data to clipboard", icon: "copy"}, - "generate_functions": {name: "Autogenerate activation scripts from name", icon: "gear"}, - }, - }); - - $.contextMenu({ - selector: 'li.entity-row', - callback(key, options) { - - switch(key) { - default: - console.log(`unknown key: ${ key}`); - return; - case 'code': - copy_useful_single_entity_data_to_clipboard(currentEntities[$(this).data('index')]); - return; - case 'clone': - options.$menu.trigger("contextmenu:hide"); - var entity_to_copy = $(this).data('index'); - clone_entity(entity_to_copy); - return; - case 'edit': - $(this).dblclick(); - return; - case 'delete': - var entity_to_delete = $(this).data('index'); - if( confirm(`Are you sure you want to delete entity #${entity_to_delete}?`) ) { - delete_entity(entity_to_delete); + $(function() { + $.contextMenu({ + selector: '.entity-palette h3.ui-widget-header', + callback(key, options) { + switch (key) { + default: + console.log(`unknown key: ${key}`); + return; + case 'generate_functions': + generate_functions_from_names(); + return; + case 'copy_scriptnames': + copy_useful_entity_data_to_clipboard(); + } + }, + items: { + copy_scriptnames: { name: 'Copy useful entity data to clipboard', icon: 'copy' }, + generate_functions: { + name: 'Autogenerate activation scripts from name', + icon: 'gear' + } } - - } - }, - items: { - "edit": {name: "Edit", icon: "edit"}, - "clone": {name: "Clone", icon: "copy"}, - "delete": {name: "Delete", icon: "delete"}, - "code": {name: "Copy useful entity data to clipboard", icon: "copy"}, - } + }); + + $.contextMenu({ + selector: 'li.entity-row', + callback(key, options) { + switch (key) { + default: + console.log(`unknown key: ${key}`); + return; + case 'code': + copy_useful_single_entity_data_to_clipboard( + currentEntities[$(this).data('index')] + ); + return; + case 'clone': + options.$menu.trigger('contextmenu:hide'); + var entity_to_copy = $(this).data('index'); + clone_entity(entity_to_copy); + return; + case 'edit': + $(this).dblclick(); + return; + case 'delete': + var entity_to_delete = $(this).data('index'); + if ( + confirm(`Are you sure you want to delete entity #${entity_to_delete}?`) + ) { + delete_entity(entity_to_delete); + } + } + }, + items: { + edit: { name: 'Edit', icon: 'edit' }, + clone: { name: 'Clone', icon: 'copy' }, + delete: { name: 'Delete', icon: 'delete' }, + code: { name: 'Copy useful entity data to clipboard', icon: 'copy' } + } + }); }); - }); }; const template = ` @@ -380,833 +385,864 @@ let hasDirtyArt = false; let oldData = null; let oldEnt = null; const setup_template = (ent, id) => { - const $template = $(template); - - if (ent) { - $('#modal-dialog').attr('title', `Edit Entity (id: ${ id })`); - } else { - $('#modal-dialog').attr('title', `Add New Entity (id: ${ currentEntities.length })`); - } - - const entityFilenameClickFn = () => { - const absPathToChrs = jetpack.path(window.$$$currentMap.dataPath, window.$$$currentMap.mapedConfigData.path_to_chrs); - const curRelPath = $('#entity_filename').val(); - - const whatDirToOpenFn = (curPath, absPath, prevRelPath) => { - - if( curPath ) { // "edit" mode - const dir = getDirFromPath(curPath); + const $template = $(template); - if(dir.startsWith(absPath)) { - return dir; - } - - return jetpack.path(absPath, dir); - } // "new" mode - if(prevRelPath) { - return jetpack.path(absPath, prevRelPath); - } - return jetpack.path(absPath, curPath); - - ; + if (ent) { + $('#modal-dialog').attr('title', `Edit Entity (id: ${id})`); + } else { + $('#modal-dialog').attr('title', `Add New Entity (id: ${currentEntities.length})`); } - // This "could" have been nested trinaries... but NO. - const whatDirToOpen = whatDirToOpenFn(curRelPath, absPathToChrs, previousEntityRelPath); - previousEntityRelPath = whatDirToOpen; - - const { dialog } = require('electron').remote; - dialog.showOpenDialog({ - title: 'Choose a new entity file', - defaultPath: whatDirToOpen, - filters: [{ name: 'text', extensions: ['json'] }], - openFile: true, - openDirectory: false, - multiSelections: false - }, function(filepath) { - - let path = ''; - - if(!filepath) { - console.log("No filepath to new entity!"); - return; - } + const entityFilenameClickFn = () => { + const absPathToChrs = jetpack.path( + window.$$$currentMap.dataPath, + window.$$$currentMap.mapedConfigData.path_to_chrs + ); + const curRelPath = $('#entity_filename').val(); - path = filepath[0]; + const whatDirToOpenFn = (curPath, absPath, prevRelPath) => { + if (curPath) { + // "edit" mode + const dir = getDirFromPath(curPath); - // if we're an absolute path, reletivize it! - if( filepath[0].indexOf(absPathToChrs) === 0 ) { - path = filepath[0].substring(absPathToChrs.length).replace(/\\/g, '/'); - if( path.indexOf('/') === 0 ) { - path = path.substring(1); - } - } + if (dir.startsWith(absPath)) { + return dir; + } - if( $('#entity_filename').val() !== path ) { - hasDirtyArt = true; - } + return jetpack.path(absPath, dir); + } // "new" mode + if (prevRelPath) { + return jetpack.path(absPath, prevRelPath); + } + return jetpack.path(absPath, curPath); + }; + + // This "could" have been nested trinaries... but NO. + const whatDirToOpen = whatDirToOpenFn(curRelPath, absPathToChrs, previousEntityRelPath); + previousEntityRelPath = whatDirToOpen; + + const { dialog } = require('electron').remote; + dialog.showOpenDialog( + { + title: 'Choose a new entity file', + defaultPath: whatDirToOpen, + filters: [{ name: 'text', extensions: ['json'] }], + openFile: true, + openDirectory: false, + multiSelections: false + }, + function(filepath) { + let path = ''; + + if (!filepath) { + console.log('No filepath to new entity!'); + return; + } + + path = filepath[0]; + + // if we're an absolute path, reletivize it! + if (filepath[0].indexOf(absPathToChrs) === 0) { + path = filepath[0].substring(absPathToChrs.length).replace(/\\/g, '/'); + if (path.indexOf('/') === 0) { + path = path.substring(1); + } + } + + if ($('#entity_filename').val() !== path) { + hasDirtyArt = true; + } + + $('#entity_filename').val(path); + + const anims = get_animations_by_filepath(path); + const animationKeyset = Object.keys(anims); + + if (ent) { + set_animation_dropdown($template, animationKeyset, ent.animation); + } else { + set_animation_dropdown( + $template, + animationKeyset, + animationKeyset.length ? animationKeyset[0] : '' + ); + } + + const data = get_entity_data(path); + previousEntityRelPath = getDirFromPath(path); + + if (ent) { + oldData = get_entity_data(ent.filename); + oldEnt = ent; + window.$$$currentMap.maybeAddEntityTexture(data, ent); + } else { + // TODO: is this used? + window.$$$currentMap.maybeAddEntityTextureFromFilename(data, path); + } + } + ); + }; + $template.find('#entity_filename').click(entityFilenameClickFn); + + const $entFace = $template.find('#entity_facing'); + const faceKeyset = ['Up', 'Down', 'Left', 'Right']; + + // repopulate facing select + $entFace.empty(); + $.each(faceKeyset, (key, value) => { + $entFace.append( + $('') + .attr('value', value) + .text(value) + ); + }); - $('#entity_filename').val(path); + if (ent) { + console.log(`Editing: ${ent.name}`); - const anims = get_animations_by_filepath(path); - const animationKeyset = Object.keys(anims); + $template.find('#entity_name').val(ent.name); + $template.find('#entity_uuid').val(ent.uuid); + $template.find('#entity_filename').val(ent.filename); - if(ent) { - set_animation_dropdown($template, animationKeyset, ent.animation); - } else { - set_animation_dropdown($template, animationKeyset, animationKeyset.length ? animationKeyset[0] : ''); - } + $template.find('#entity_activation_script').val(ent.activation_script); + $template.find('#entity_speed').val(ent.speed); - const data = get_entity_data(path); - previousEntityRelPath = getDirFromPath(path); + $template.find('#entity_location_tx').val(ent.location.tx); + $template.find('#entity_location_ty').val(ent.location.ty); - if(ent) { - oldData = get_entity_data(ent.filename); - oldEnt = ent; - window.$$$currentMap.maybeAddEntityTexture(data, ent); - } else { - window.$$$currentMap.maybeAddEntityTextureFromFilename(data, path); + if (typeof ent.location.px === 'undefined') { + ent.location.px = ent.location.tx * 16; // TODO: should be based on tilesize + ent.location.py = ent.location.ty * 16; // TODO: should be based on tilesize } - } - ); - }; - $template.find('#entity_filename').click(entityFilenameClickFn); - - const $entFace = $template.find('#entity_facing'); - const faceKeyset = ['Up', 'Down', 'Left', 'Right']; - - // repopulate facing select - $entFace.empty(); - $.each(faceKeyset, (key, value) => { - $entFace.append( - $('') - .attr('value', value) - .text(value) - ); - }); - - if (ent) { - console.log(`Editing: ${ ent.name}`); - - $template.find('#entity_name').val(ent.name); - $template.find('#entity_uuid').val(ent.uuid); - $template.find('#entity_filename').val(ent.filename); - - $template.find('#entity_activation_script').val(ent.activation_script); - $template.find('#entity_speed').val(ent.speed); - - $template.find('#entity_location_tx').val(ent.location.tx); - $template.find('#entity_location_ty').val(ent.location.ty); - - if (typeof ent.location.px === 'undefined') { - ent.location.px = ent.location.tx * 16; // TODO: should be based on tilesize - ent.location.py = ent.location.ty * 16; // TODO: should be based on tilesize - } - $template.find('#entity_location_px').val(ent.location.px); - $template.find('#entity_location_py').val(ent.location.py); + $template.find('#entity_location_px').val(ent.location.px); + $template.find('#entity_location_py').val(ent.location.py); + + // http://regex.info/blog/2006-09-15/247 + $template.find('#entity_wander').val( + JSON.stringify(ent.wander) + .replace(/{/g, '{\n') + .replace(/}/g, '\n}') + .replace(/,/g, ',\n') + .replace(/":/g, '": ') + .replace(/^"/gm, '\t"') + ); - // http://regex.info/blog/2006-09-15/247 - $template.find('#entity_wander').val(JSON.stringify(ent.wander).replace(/{/g, '{\n').replace(/}/g, '\n}') - .replace(/,/g, ',\n').replace(/":/g, '": ').replace(/^"/mg, '\t"')); + $template + .find('#entity_pays_attention_to_obstructions') + .prop('checked', ent.pays_attention_to_obstructions); + $template.find('#entity_is_an_obstruction').prop('checked', ent.is_an_obstruction); + $template.find('#entity_autofaces').prop('checked', ent.autofaces); - $template.find('#entity_pays_attention_to_obstructions').prop('checked', ent.pays_attention_to_obstructions); - $template.find('#entity_is_an_obstruction').prop('checked', ent.is_an_obstruction); - $template.find('#entity_autofaces').prop('checked', ent.autofaces); + let entData; + if (window.$$$currentMap.entityData[ent.filename]) { + entData = window.$$$currentMap.entityData[ent.filename]; + } else { + // TODO: load the new entitydata in! + console.warn(`I DO NOT KNOW HOW TO RENDER [${ent.filename}]`); + entData = window.$$$currentMap.entityData.__default__; + } - let entData; - if (window.$$$currentMap.entityData[ent.filename]) { - entData = window.$$$currentMap.entityData[ent.filename]; - } else { - // TODO: load the new entitydata in! - console.warn(`I DO NOT KNOW HOW TO RENDER [${ ent.filename }]`); - entData = window.$$$currentMap.entityData.__default__; + // = window.$$$currentMap.entityData[ent.filename] || window.$$$currentMap.entityData['__default__']; + const animationKeyset = Object.keys(entData.animations); + set_animation_dropdown($template, animationKeyset, ent.animation); + + // set value. + $entFace.val(ent.facing); + + const $entLocLay = $template.find('#entity_location_layer'); + const locLayKeyset = LayersWidget.get_layernames_by_rstring_order(); + $entLocLay.empty(); + $.each(locLayKeyset, (key, value) => { + $entLocLay.append( + $('') + .attr('value', value) + .text(value) + ); + }); + + $entLocLay.val(ent.location.layer); } - // = window.$$$currentMap.entityData[ent.filename] || window.$$$currentMap.entityData['__default__']; - const animationKeyset = Object.keys(entData.animations); - set_animation_dropdown($template, animationKeyset, ent.animation); - - // set value. - $entFace.val(ent.facing); - - const $entLocLay = $template.find('#entity_location_layer'); - const locLayKeyset = LayersWidget.get_layernames_by_rstring_order(); - $entLocLay.empty(); - $.each(locLayKeyset, (key, value) => { - $entLocLay.append( - $('') - .attr('value', value) - .text(value) - ); - }); - - $entLocLay.val(ent.location.layer); - } - - return $template; + return $template; }; const SIMPLE_MATH_REGEX = /([-+]?[0-9]*\.?[0-9]+[\/\+\-\*])+([-+]?[0-9]*\.?[0-9]+)/; function is_simple_math(str) { - return str.match(SIMPLE_MATH_REGEX) !== null; + return str.match(SIMPLE_MATH_REGEX) !== null; } function do_simple_math(str) { - if(is_simple_math(str)) { - return parseInt(eval(str)); // I AM LITERALLY HITLER - } + if (is_simple_math(str)) { + return parseInt(eval(str)); // I AM LITERALLY HITLER + } - return null; + return null; } function _maf(selector) { - if(is_simple_math($(selector).val())) { - $(selector).val(do_simple_math($(selector).val())); - } + if (is_simple_math($(selector).val())) { + $(selector).val(do_simple_math($(selector).val())); + } } function do_simple_math_if_present() { - _maf('#entity_location_px'); - _maf('#entity_location_py'); - _maf('#entity_location_tx'); - _maf('#entity_location_ty'); + _maf('#entity_location_px'); + _maf('#entity_location_py'); + _maf('#entity_location_tx'); + _maf('#entity_location_ty'); } function assert_pixel_versus_tile_in_editing() { + const loc_tx = parseInt($('#entity_location_tx').val()); + const loc_ty = parseInt($('#entity_location_ty').val()); - const loc_tx = parseInt($('#entity_location_tx').val()); - const loc_ty = parseInt($('#entity_location_ty').val()); + const loc_px = parseInt($('#entity_location_px').val()); + const loc_py = parseInt($('#entity_location_py').val()); - const loc_px = parseInt($('#entity_location_px').val()); - const loc_py = parseInt($('#entity_location_py').val()); + let pixels_on = false; + let tiles_on = false; - let pixels_on = false; - let tiles_on = false; + const tiles = $('div.tile_coordinates input'); + const pixels = $('div.pixel_coordinates input'); - const tiles = $('div.tile_coordinates input'); - const pixels = $('div.pixel_coordinates input'); + tiles.css('background-color', '#AAA'); + pixels.css('background-color', '#AAA'); - tiles.css('background-color', '#AAA'); - pixels.css('background-color', '#AAA'); - - if (!loc_px && !loc_py) { - tiles_on = true; - } else if (loc_tx * 16 === loc_px && loc_ty * 16 === loc_py) { // TODO: pi - tiles_on = true; + if (!loc_px && !loc_py) { + tiles_on = true; + } else if (loc_tx * 16 === loc_px && loc_ty * 16 === loc_py) { + // TODO: pi + tiles_on = true; } else { - pixels_on = true; + pixels_on = true; } - if (tiles_on) { - tiles.css('background-color', 'white'); - } + if (tiles_on) { + tiles.css('background-color', 'white'); + } - if (pixels_on) { - pixels.css('background-color', 'white'); - } + if (pixels_on) { + pixels.css('background-color', 'white'); + } } function new_entity_click(evt) { - _entity_click(evt); + _entity_click(evt); } function edit_entity_click(evt, id) { - _entity_click(evt, id); + _entity_click(evt, id); } -export const show_edit_entity_dialog = (id) => { - const evt = { stopPropagation: () => {} }; - _entity_click(evt, id); -} +export const show_edit_entity_dialog = id => { + const evt = { stopPropagation: () => {} }; + _entity_click(evt, id); +}; let dialog; function _entity_click(evt, id) { - evt.stopPropagation(); + evt.stopPropagation(); - const ent = currentEntities[id]; + const ent = currentEntities[id]; - $(() => { - const $template = setup_template(ent, id); + $(() => { + const $template = setup_template(ent, id); - $('#modal-dialog').html(''); - $('#modal-dialog').append($template); + $('#modal-dialog').html(''); + $('#modal-dialog').append($template); + + $('#modal-dialog').show(); + + $('#entity_location_tx').on('change', () => { + $('#entity_location_px').val(''); + $('#entity_location_py').val(''); + }); + $('#entity_location_ty').on('change', () => { + $('#entity_location_px').val(''); + $('#entity_location_py').val(''); + }); + $('#entity_location_px').on('change', () => { + $('#entity_location_tx').val(''); + $('#entity_location_ty').val(''); + }); + $('#entity_location_py').on('change', () => { + $('#entity_location_tx').val(''); + $('#entity_location_ty').val(''); + }); + + assert_pixel_versus_tile_in_editing(); + + dialog = $('#modal-dialog').dialog({ + width: 500, + modal: true, + title: $('#modal-dialog').attr('title'), + buttons: { + Save: () => { + const _id = $.isNumeric(id) && ent ? id : currentEntities.length; + + update_entity(_id); + + hasDirtyArt = false; + }, + Cancel: function() { + if (hasDirtyArt) { + // / put it back! + window.$$$currentMap.maybeAddEntityTexture(oldData, oldEnt); + oldData = null; + oldEnt = null; + hasDirtyArt = false; + } + + dialog.dialog('close'); + } + }, + close() { + $('#modal-dialog').html(''); + } + }); + }); +} - $('#modal-dialog').show(); +export const update_entity = ent_id => { + const entity_name = $('#entity_name').val(); + const entity_filename = $('#entity_filename').val(); // TODO: validate existance + const entity_uuid = $('#entity_uuid').val(); + const entity_activation_script = $('#entity_activation_script').val(); + const entity_speed = parseInt($('#entity_speed').val()); - $('#entity_location_tx').on('change', () => { - $('#entity_location_px').val(''); - $('#entity_location_py').val(''); - }); - $('#entity_location_ty').on('change', () => { - $('#entity_location_px').val(''); - $('#entity_location_py').val(''); - }); - $('#entity_location_px').on('change', () => { - $('#entity_location_tx').val(''); - $('#entity_location_ty').val(''); - }); - $('#entity_location_py').on('change', () => { - $('#entity_location_tx').val(''); - $('#entity_location_ty').val(''); - }); + const entity_pays_attention_to_obstructions = $('#entity_pays_attention_to_obstructions').is( + ':checked' + ); + const entity_is_an_obstruction = $('#entity_is_an_obstruction').is(':checked'); + const entity_autofaces = $('#entity_autofaces').is(':checked'); - assert_pixel_versus_tile_in_editing(); + let entity_wander; - dialog = $('#modal-dialog').dialog({ - width: 500, - modal: true, - title: $('#modal-dialog').attr('title'), - buttons: { - Save: () => { - const _id = ($.isNumeric(id) && ent) ? id : currentEntities.length; + if (ent_id < currentEntities.length) { + entity_wander = currentEntities[ent_id].wander; + } else { + // add + entity_wander = { mode: 'Scripted', delay: 0, initial_movestring: '' }; + } - update_entity(_id); + const entity_animation = $('#entity_animation').val(); + const entity_facing = $('#entity_facing').val(); - hasDirtyArt = false; - }, - 'Cancel': function () { + do_simple_math_if_present(); - if( hasDirtyArt ) { - // / put it back! - window.$$$currentMap.maybeAddEntityTexture(oldData, oldEnt); - oldData = null; - oldEnt = null; - hasDirtyArt = false; - } + let loc_tx = parseInt($('#entity_location_tx').val()); + let loc_ty = parseInt($('#entity_location_ty').val()); - dialog.dialog('close'); - } - }, - close () { - $('#modal-dialog').html(''); - } - }); - }); -} + let loc_px = parseInt($('#entity_location_px').val()); + let loc_py = parseInt($('#entity_location_py').val()); + + console.log('loc_tx, loc_ty, loc_px, loc_py:'); + console.log(loc_tx, loc_ty, loc_px, loc_py); + + const loc_l = $('#entity_location_layer').val(); + + if (!loc_tx && loc_tx !== 0) { + loc_tx = null; + } + + if (!loc_ty && loc_ty !== 0) { + loc_ty = null; + } + + if (!loc_px && loc_px !== 0) { + loc_px = null; + } + + if (!loc_py && loc_py !== 0) { + loc_py = null; + } + + const vals = { + loc_tx, + loc_ty, + loc_px, + loc_py, + loc_l, + entity_animation, + entity_facing, + entity_wander, + entity_name, + entity_uuid, + entity_filename, + entity_activation_script, + entity_speed, + entity_pays_attention_to_obstructions, + entity_is_an_obstruction, + entity_autofaces + }; -export const update_entity = (ent_id) => { - const entity_name = $('#entity_name').val(); - const entity_filename = $('#entity_filename').val(); // TODO: validate existance - const entity_uuid = $('#entity_uuid').val(); - const entity_activation_script = $('#entity_activation_script').val(); - const entity_speed = parseInt($('#entity_speed').val()); - - const entity_pays_attention_to_obstructions = $('#entity_pays_attention_to_obstructions').is(':checked'); - const entity_is_an_obstruction = $('#entity_is_an_obstruction').is(':checked'); - const entity_autofaces = $('#entity_autofaces').is(':checked'); - - let entity_wander; - - if (ent_id < currentEntities.length) { - entity_wander = currentEntities[ent_id].wander; - } else { // add - entity_wander = {mode: 'Scripted', delay: 0, initial_movestring: ''}; - } - - const entity_animation = $('#entity_animation').val(); - const entity_facing = $('#entity_facing').val(); - - do_simple_math_if_present(); - - let loc_tx = parseInt($('#entity_location_tx').val()); - let loc_ty = parseInt($('#entity_location_ty').val()); - - let loc_px = parseInt($('#entity_location_px').val()); - let loc_py = parseInt($('#entity_location_py').val()); - - console.log('loc_tx, loc_ty, loc_px, loc_py:'); - console.log(loc_tx, loc_ty, loc_px, loc_py); - - const loc_l = $('#entity_location_layer').val(); - - if(!loc_tx && loc_tx !== 0) { - loc_tx = null; - } - - if(!loc_ty && loc_ty !== 0) { - loc_ty = null; - } - - if(!loc_px && loc_px !== 0) { - loc_px = null; - } - - if(!loc_py && loc_py !== 0) { - loc_py = null; - } - - const vals = { - loc_tx, - loc_ty, - loc_px, - loc_py, - loc_l, - entity_animation, - entity_facing, - entity_wander, - entity_name, - entity_uuid, - entity_filename, - entity_activation_script, - entity_speed, - entity_pays_attention_to_obstructions, - entity_is_an_obstruction, - entity_autofaces - }; - - if (_update_entity_inner(ent_id, vals)) { - dialog.dialog('close'); - selectEntityByIndex(ent_id); - scrollEntityPalletteToEntity(ent_id); - } + if (_update_entity_inner(ent_id, vals)) { + dialog.dialog('close'); + selectEntityByIndex(ent_id); + scrollEntityPalletteToEntity(ent_id); + } }; export const update_entity_location = (ent_id, valDict) => { - if (!$.isNumeric(ent_id) || ent_id < 0) { - modal_error(`Invalid input: ent_id (${ ent_id }) is invalid.`); - return false; - } + if (!$.isNumeric(ent_id) || ent_id < 0) { + modal_error(`Invalid input: ent_id (${ent_id}) is invalid.`); + return false; + } - window.$$$currentMap.UndoRedo.change_one_entity_location( - ent_id, valDict - ); + window.$$$currentMap.UndoRedo.change_one_entity_location(ent_id, valDict); - do_the_no_things(null, redraw_palette); + do_the_no_things(null, redraw_palette); }; -const get_entity_data = (chr_filepath) => { - const fullpath = jetpack.path(window.$$$currentMap.dataPath, window.$$$currentMap.mapedConfigData.path_to_chrs, chr_filepath); - console.log( `fullpath to entity for animation verificaiton: ${ fullpath}` ); +const get_entity_data = chr_filepath => { + const fullpath = jetpack.path( + window.$$$currentMap.dataPath, + window.$$$currentMap.mapedConfigData.path_to_chrs, + chr_filepath + ); + console.log(`fullpath to entity for animation verificaiton: ${fullpath}`); - const data = jetpack.read(fullpath, 'json'); + const data = jetpack.read(fullpath, 'json'); - return data; -} + return data; +}; -const get_animations_by_filepath = (chr_filepath) => { - const data = get_entity_data(chr_filepath); +const get_animations_by_filepath = chr_filepath => { + const data = get_entity_data(chr_filepath); - if(!data) { - console.error(`Invalid entity filepath: ${ fullpath}`); - return []; - } + if (!data) { + console.error(`Invalid entity filepath: ${fullpath}`); + return []; + } - if( !data.animations ) { - console.error(`Entity has no animations: ${ fullpath}`); - return []; - } + if (!data.animations) { + console.error(`Entity has no animations: ${fullpath}`); + return []; + } - return data.animations; + return data.animations; }; const is_valid_animation = (chr_filepath, animation_name) => { - const animations = get_animations_by_filepath(chr_filepath); + const animations = get_animations_by_filepath(chr_filepath); - console.info(`data.animations[${animation_name}]: ${ animations[animation_name]}`); - return !!animations[animation_name]; + console.info(`data.animations[${animation_name}]: ${animations[animation_name]}`); + return !!animations[animation_name]; }; -const _loc_helper = (valDict) => { - - const loc = {}; +const _loc_helper = valDict => { + const loc = {}; - if( valDict.loc_l ) { - loc.layer = valDict.loc_l; - } + if (valDict.loc_l) { + loc.layer = valDict.loc_l; + } - loc.tx = valDict.loc_tx; - loc.ty = valDict.loc_ty; - loc.px = valDict.loc_px; - loc.py = valDict.loc_py; + loc.tx = valDict.loc_tx; + loc.ty = valDict.loc_ty; + loc.px = valDict.loc_px; + loc.py = valDict.loc_py; - if( typeof loc.tx !== 'number' && typeof loc.px !== 'number') { - loc.tx = 0; - loc.px = 0; - } + if (typeof loc.tx !== 'number' && typeof loc.px !== 'number') { + loc.tx = 0; + loc.px = 0; + } - if( typeof loc.ty !== 'number' && typeof loc.py !== 'number') { - loc.ty = 0; - loc.tx = 0; - } + if (typeof loc.ty !== 'number' && typeof loc.py !== 'number') { + loc.ty = 0; + loc.tx = 0; + } - return loc; + return loc; }; export const _update_entity_inner = (ent_id, valDict) => { - const loc = _loc_helper(valDict); + const loc = _loc_helper(valDict); - let ent = null; + let ent = null; - if (!$.isNumeric(ent_id) || ent_id < 0) { - modal_error(`Invalid input: ent_id (${ ent_id }) is invalid.`); - return false; - } + if (!$.isNumeric(ent_id) || ent_id < 0) { + modal_error(`Invalid input: ent_id (${ent_id}) is invalid.`); + return false; + } - if (!$.isNumeric(valDict.entity_speed)) { - modal_error(`Invalid input: speed not numeric (${ valDict.entity_speed }).`); - return false; - } - - if (!valDict.entity_facing) { - valDict.entity_facing = 'Down'; - } - - // if old_value_dict's null, we should undo to deleting ent_id. - let old_value_dict = null; - - // if old_value_dict's not null, we should restore ent_id's old state. - if( currentEntities[ent_id] ) { - // these two dicts should be kept in sync for undo/redo. Any abstraction patterns that could aid this? - old_value_dict = { - 'name': valDict.entity_name, - 'uuid': valDict.entity_uuid, - 'filename': valDict.entity_filename, - 'facing': valDict.entity_facing, - 'pays_attention_to_obstructions': valDict.entity_pays_attention_to_obstructions, - 'is_an_obstruction': valDict.entity_is_an_obstruction, - 'autofaces': valDict.entity_autofaces, - 'speed': valDict.entity_speed, - 'wander': valDict.entity_wander, - 'activation_script': valDict.entity_activation_script, - 'animation': valDict.entity_animation, - - 'location': loc - }; - } - - ent = { - 'name': valDict.entity_name, - 'uuid': valDict.entity_uuid, - 'filename': valDict.entity_filename, - 'facing': valDict.entity_facing, - 'pays_attention_to_obstructions': valDict.entity_pays_attention_to_obstructions, - 'is_an_obstruction': valDict.entity_is_an_obstruction, - 'autofaces': valDict.entity_autofaces, - 'speed': valDict.entity_speed, - 'wander': valDict.entity_wander, - 'activation_script': valDict.entity_activation_script, - 'animation': valDict.entity_animation, - - 'location': loc - }; - - let old_layer; - let new_layer; - - if (!currentEntities[ent_id]) { - currentEntities[ent_id] = {}; - } - - if( ent.animation != valDict.entity_animation ) { - // todo lookahead in the new file to see if the new animation name is valid. - if( !is_valid_animation(ent.filename, ent.animation) ) { - alert(`${ent.filename } does not have animation ${ ent.animation}` ); - ent.animation = ''; + if (!$.isNumeric(valDict.entity_speed)) { + modal_error(`Invalid input: speed not numeric (${valDict.entity_speed}).`); + return false; + } + + if (!valDict.entity_facing) { + valDict.entity_facing = 'Down'; } - } + // if old_value_dict's null, we should undo to deleting ent_id. + let old_value_dict = null; + + // if old_value_dict's not null, we should restore ent_id's old state. + if (currentEntities[ent_id]) { + // these two dicts should be kept in sync for undo/redo. Any abstraction patterns that could aid this? + old_value_dict = { + name: valDict.entity_name, + uuid: valDict.entity_uuid, + filename: valDict.entity_filename, + facing: valDict.entity_facing, + pays_attention_to_obstructions: valDict.entity_pays_attention_to_obstructions, + is_an_obstruction: valDict.entity_is_an_obstruction, + autofaces: valDict.entity_autofaces, + speed: valDict.entity_speed, + wander: valDict.entity_wander, + activation_script: valDict.entity_activation_script, + animation: valDict.entity_animation, + + location: loc + }; + } + + ent = { + name: valDict.entity_name, + uuid: valDict.entity_uuid, + filename: valDict.entity_filename, + facing: valDict.entity_facing, + pays_attention_to_obstructions: valDict.entity_pays_attention_to_obstructions, + is_an_obstruction: valDict.entity_is_an_obstruction, + autofaces: valDict.entity_autofaces, + speed: valDict.entity_speed, + wander: valDict.entity_wander, + activation_script: valDict.entity_activation_script, + animation: valDict.entity_animation, + + location: loc + }; + + let old_layer; + let new_layer; - let k; - for (k in ent) { - if (ent.hasOwnProperty(k)) { - currentEntities[ent_id][k] = ent[k]; + if (!currentEntities[ent_id]) { + currentEntities[ent_id] = {}; } - } - if (currentEntities[ent_id] && currentEntities[ent_id].location) { - old_layer = currentEntities[ent_id].location.layer; - } else { - old_layer = new_layer; - } + if (ent.animation != valDict.entity_animation) { + // todo lookahead in the new file to see if the new animation name is valid. + if (!is_valid_animation(ent.filename, ent.animation)) { + alert(`${ent.filename} does not have animation ${ent.animation}`); + ent.animation = ''; + } + } - if( !ent.uuid ) { - currentEntities[ent_id].uuid = generate_unique_entity_uuid_for_this_map(); - } + let k; + for (k in ent) { + if (ent.hasOwnProperty(k)) { + currentEntities[ent_id][k] = ent[k]; + } + } + + if (currentEntities[ent_id] && currentEntities[ent_id].location) { + old_layer = currentEntities[ent_id].location.layer; + } else { + old_layer = new_layer; + } - if (old_layer && new_layer && old_layer !== new_layer) { - relocate_entity_for_map_rendering(currentEntities[ent_id].uuid, old_layer, new_layer); - } + if (!ent.uuid) { + currentEntities[ent_id].uuid = generate_unique_entity_uuid_for_this_map(); + } + if (old_layer && new_layer && old_layer !== new_layer) { + relocate_entity_for_map_rendering(currentEntities[ent_id].uuid, old_layer, new_layer); + } - do_the_no_things(currentEntities[ent_id], redraw_palette); // these args seem dumb + do_the_no_things(currentEntities[ent_id], redraw_palette); // these args seem dumb - if( window.$$$currentMap.mapedConfigData.autoSelectEntityAfterEdit ) { - addEntityToHighlight(currentEntities[ent_id]); + if (window.$$$currentMap.mapedConfigData.autoSelectEntityAfterEdit) { + addEntityToHighlight(currentEntities[ent_id]); - if(currentEntities[ent_id].location.layer === "Entity Layer (E)") { - selectEntityLayer(false); + if (currentEntities[ent_id].location.layer === 'Entity Layer (E)') { + selectEntityLayer(false); + } } - } - return true; + return true; }; export const _does_uuid_already_exist = (uuid, map) => { - let curEnts = null; - if(!map) { - curEnts = currentEntities; - } else { - curEnts = map.mapData.entities; - } - - for (let i = curEnts.length - 1; i >= 0; i--) { - if( curEnts[i].uuid && curEnts[i].uuid === uuid ) { - return true; + let curEnts = null; + if (!map) { + curEnts = currentEntities; + } else { + curEnts = map.mapData.entities; } - } - return false; -} + for (let i = curEnts.length - 1; i >= 0; i--) { + if (curEnts[i].uuid && curEnts[i].uuid === uuid) { + return true; + } + } -export const generate_unique_entity_uuid_for_this_map = (map) => { - while(true) { - const uuid = uuidv4(); + return false; +}; + +export const generate_unique_entity_uuid_for_this_map = map => { + while (true) { + const uuid = uuidv4(); + + if (_does_uuid_already_exist(uuid, map)) { + continue; + } - if( _does_uuid_already_exist(uuid, map) ) { - continue; + return uuid; + } +}; + +export const delete_entity = ent_id => { + if (ent_id < 0 || ent_id >= currentEntities.length) { + console.warn( + `Attempted to delete out-of bounds entity: ${ent_id} (out of ${currentEntities.length}). ` + ); + return; } - return uuid; - } + currentEntities.splice(ent_id, 1); + do_the_no_things(null, redraw_palette); // these args seem dumb }; -export const delete_entity = ( ent_id ) => { - if( ent_id < 0 || ent_id >= currentEntities.length ) { - console.warn(`Attempted to delete out-of bounds entity: ${ ent_id } (out of ${currentEntities.length}). `); - return; - } +const clone_entity = ent_index => { + const e = currentEntities[ent_index]; + + const vals = { + entity_name: `Copy of ${e.name}`, + + loc_tx: e.location.tx, + loc_ty: e.location.ty, + loc_px: e.location.px, + loc_py: e.location.py, + loc_l: e.location.layer, + entity_animation: e.animation, + entity_facing: e.facing, + entity_wander: e.wander, + entity_filename: e.filename, + entity_activation_script: e.activation_script, + entity_speed: e.speed, + entity_pays_attention_to_obstructions: e.pays_attention_to_obstructions, + entity_is_an_obstruction: e.is_an_obstruction, + entity_autofaces: e.autofaces + }; - currentEntities.splice(ent_id, 1); - do_the_no_things(null, redraw_palette); // these args seem dumb -} + const new_id = currentEntities.length; -const clone_entity = ( ent_index ) => { - const e = currentEntities[ent_index]; - - const vals = { - entity_name: `Copy of ${e.name}`, - - loc_tx: e.location.tx, - loc_ty: e.location.ty, - loc_px: e.location.px, - loc_py: e.location.py, - loc_l: e.location.layer, - entity_animation: e.animation, - entity_facing: e.facing, - entity_wander: e.wander, - entity_filename: e.filename, - entity_activation_script: e.activation_script, - entity_speed: e.speed, - entity_pays_attention_to_obstructions: e.pays_attention_to_obstructions, - entity_is_an_obstruction: e.is_an_obstruction, - entity_autofaces: e.autofaces - }; - - const new_id = currentEntities.length; - - _update_entity_inner(new_id, vals) - - redraw_palette(); - - selectEntityByIndex(new_id); - scrollEntityPalletteToEntity(new_id); -}; + _update_entity_inner(new_id, vals); + redraw_palette(); + + selectEntityByIndex(new_id); + scrollEntityPalletteToEntity(new_id); +}; // TODO: ent_name should be a uuid // TODO: until then, make sure ent_name is verified unique const relocate_entity_for_map_rendering = (ent_uuid, old_layer, new_layer) => { - let myboy = null; - const ents = window.$$$currentMap.entities; - - for (let i = ents[old_layer].length - 1; i >= 0; i--) { - if(!ents[old_layer][i].uuid) { - alert("You are trying to move an entity without a UUID. Reload the map, save it, reload it, and try again.\n\nCancelling action."); - return; - } + let myboy = null; + const ents = window.$$$currentMap.entities; + + for (let i = ents[old_layer].length - 1; i >= 0; i--) { + if (!ents[old_layer][i].uuid) { + alert( + 'You are trying to move an entity without a UUID. Reload the map, save it, reload it, and try again.\n\nCancelling action.' + ); + return; + } - if (ents[old_layer][i].uuid === ent_uuid) { - if (!ents[new_layer]) { - ents[new_layer] = []; - } + if (ents[old_layer][i].uuid === ent_uuid) { + if (!ents[new_layer]) { + ents[new_layer] = []; + } - myboy = ents[old_layer].splice(i, 1); - ents[new_layer].push(myboy[0]); // remember to unbox. :( + myboy = ents[old_layer].splice(i, 1); + ents[new_layer].push(myboy[0]); // remember to unbox. :( - return; + return; + } } - } - window.alert( - `FAILED TO MOVE entity '${ ent_name }' from layer '${ old_layer - }' to layer '${ new_layer }'. FOR REASONS.` - ); + window.alert( + `FAILED TO MOVE entity '${ent_name}' from layer '${old_layer}' to layer '${new_layer}'. FOR REASONS.` + ); }; -export const scrollEntityPalletteToEntity = (entToFocus) => { - const $container = $('.entity-palette .window-container'); - const $rowToScrollTo = $('.entity-row.highlighted'); - const entIdx = $rowToScrollTo.data('index'); - let msg = ''; +export const scrollEntityPalletteToEntity = entToFocus => { + const $container = $('.entity-palette .window-container'); + const $rowToScrollTo = $('.entity-row.highlighted'); + const entIdx = $rowToScrollTo.data('index'); + let msg = ''; - if (!entToFocus) { - entToFocus = 0; - } + if (!entToFocus) { + entToFocus = 0; + } - if (entIdx !== entToFocus) { - msg = `unexpected entity index, expected ${ entToFocus }, got ${ entIdx}`; - console.log(msg); - throw msg; - } + if (entIdx !== entToFocus) { + msg = `unexpected entity index, expected ${entToFocus}, got ${entIdx}`; + console.log(msg); + throw msg; + } - const loc = parseInt($rowToScrollTo.offset().top - $container.offset().top); + const loc = parseInt($rowToScrollTo.offset().top - $container.offset().top); - $('.entity-palette .window-container').scrollTop(loc); + $('.entity-palette .window-container').scrollTop(loc); }; const setupEntityBoundsDrawing = () => { - if(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX) { - $('#all_entity_bounds_color').val(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX); - } - - let startColor = $('#all_entity_bounds_color').val() ? $('#all_entity_bounds_color').val() : '#00000000'; - - saveAllEntityBoundsColor(startColor); - if(startColor === '#00000000') { - $("#all_entity_bounds_draw_off").hide(); - } else { - startColor = startColor.substr(0,7); - } - - const allEntityBoundsColorpicker = $('#all_entity_bounds_draw_picker').spectrum({ - color: startColor, - showInput: true, - className: "full-spectrum", - showInitial: true, - showSelectionPalette: true, - maxSelectionSize: 10, - preferredFormat: "hex", - change(color) { - const _color = `${color.toHexString() }ff`; - $('#all_entity_bounds_color').val(_color) - allEntityBoundsColorpicker.spectrum("set", color.toHexString()); - if( _color !== '#00000000') { - $("#all_entity_bounds_draw_off").show(); - } - saveAllEntityBoundsColor(_color); + if (window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX) { + $('#all_entity_bounds_color').val( + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX + ); } - }); - $("#all_entity_bounds_draw_off").click( () => { - $("#all_entity_bounds_draw_off").hide(); - allEntityBoundsColorpicker.spectrum("set", "#00000000"); - saveAllEntityBoundsColor("#00000000") - } ); -} + let startColor = $('#all_entity_bounds_color').val() + ? $('#all_entity_bounds_color').val() + : '#00000000'; + + saveAllEntityBoundsColor(startColor); + if (startColor === '#00000000') { + $('#all_entity_bounds_draw_off').hide(); + } else { + startColor = startColor.substr(0, 7); + } + + const allEntityBoundsColorpicker = $('#all_entity_bounds_draw_picker').spectrum({ + color: startColor, + showInput: true, + className: 'full-spectrum', + showInitial: true, + showSelectionPalette: true, + maxSelectionSize: 10, + preferredFormat: 'hex', + change(color) { + const _color = `${color.toHexString()}ff`; + $('#all_entity_bounds_color').val(_color); + allEntityBoundsColorpicker.spectrum('set', color.toHexString()); + if (_color !== '#00000000') { + $('#all_entity_bounds_draw_off').show(); + } + saveAllEntityBoundsColor(_color); + } + }); -const saveAllEntityBoundsColor = (hex) => { - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX = hex; - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING = hexToRgba(hex); + $('#all_entity_bounds_draw_off').click(() => { + $('#all_entity_bounds_draw_off').hide(); + allEntityBoundsColorpicker.spectrum('set', '#00000000'); + saveAllEntityBoundsColor('#00000000'); + }); +}; + +const saveAllEntityBoundsColor = hex => { + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING_HEX = hex; + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_BOUNDS_DRAWING = hexToRgba(hex); }; const setupEntityHitboxDrawing = () => { - if(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX) { - $('#all_entity_hitbox_bounds_color').val(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX); - } - let hitboxStartColor = $('#all_entity_hitbox_bounds_color').val() ? $('#all_entity_hitbox_bounds_color').val() : '#00000000'; - saveAllEntityHitboxBoundsColor(hitboxStartColor); - - if(hitboxStartColor === '#00000000') { - $("#all_entity_hitbox_bounds_draw_off").hide(); - } else { - hitboxStartColor = hitboxStartColor.substr(0,7); - } - - const allEntityHitboxBoundsColorpicker = $('#all_entity_hitbox_bounds_draw_picker').spectrum({ - color: hitboxStartColor, - showInput: true, - className: "full-spectrum", - showInitial: true, - showSelectionPalette: true, - maxSelectionSize: 10, - preferredFormat: "hex", - change(color) { - const _color = `${color.toHexString() }ff`; - $('#all_entity_hitbox_bounds_color').val(_color) - allEntityHitboxBoundsColorpicker.spectrum("set", color.toHexString()); - if( _color !== '#00000000') { - $("#all_entity_hitbox_bounds_draw_off").show(); - } - saveAllEntityHitboxBoundsColor(_color); + if (window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX) { + $('#all_entity_hitbox_bounds_color').val( + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX + ); } - }); + let hitboxStartColor = $('#all_entity_hitbox_bounds_color').val() + ? $('#all_entity_hitbox_bounds_color').val() + : '#00000000'; + saveAllEntityHitboxBoundsColor(hitboxStartColor); - $("#all_entity_hitbox_bounds_draw_off").click( () => { - $("#all_entity_hitbox_bounds_draw_off").hide(); - allEntityHitboxBoundsColorpicker.spectrum("set", "#00000000"); - saveAllEntityHitboxBoundsColor("#00000000") - } ); -} + if (hitboxStartColor === '#00000000') { + $('#all_entity_hitbox_bounds_draw_off').hide(); + } else { + hitboxStartColor = hitboxStartColor.substr(0, 7); + } + + const allEntityHitboxBoundsColorpicker = $('#all_entity_hitbox_bounds_draw_picker').spectrum({ + color: hitboxStartColor, + showInput: true, + className: 'full-spectrum', + showInitial: true, + showSelectionPalette: true, + maxSelectionSize: 10, + preferredFormat: 'hex', + change(color) { + const _color = `${color.toHexString()}ff`; + $('#all_entity_hitbox_bounds_color').val(_color); + allEntityHitboxBoundsColorpicker.spectrum('set', color.toHexString()); + if (_color !== '#00000000') { + $('#all_entity_hitbox_bounds_draw_off').show(); + } + saveAllEntityHitboxBoundsColor(_color); + } + }); + + $('#all_entity_hitbox_bounds_draw_off').click(() => { + $('#all_entity_hitbox_bounds_draw_off').hide(); + allEntityHitboxBoundsColorpicker.spectrum('set', '#00000000'); + saveAllEntityHitboxBoundsColor('#00000000'); + }); +}; -const saveAllEntityHitboxBoundsColor = (hex) => { - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX = hex; - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING = hexToRgba(hex); +const saveAllEntityHitboxBoundsColor = hex => { + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING_HEX = hex; + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_HITBOX_BOUNDS_DRAWING = hexToRgba(hex); }; const setupEntityTallRedrawDrawing = () => { - if(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX) { - $('#all_entity_tallredraw_bounds_color').val(window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX); - } - let tallRedrawStartColor = $('#all_entity_tallredraw_bounds_color').val() ? $('#all_entity_tallredraw_bounds_color').val() : '#00000000'; - saveAllEntityTallRedrawBoundsColor(tallRedrawStartColor); - - if(tallRedrawStartColor === '#00000000') { - $("#all_entity_tallredraw_bounds_draw_off").hide(); - } else { - tallRedrawStartColor = tallRedrawStartColor.substr(0,7); - } - - const allEntityTallRedrawBoundsColorpicker = $('#all_entity_tallredraw_bounds_draw_picker').spectrum({ - color: tallRedrawStartColor, - showInput: true, - className: "full-spectrum", - showInitial: true, - showSelectionPalette: true, - maxSelectionSize: 10, - preferredFormat: "hex", - change(color) { - const _color = `${color.toHexString() }ff`; - $('#all_entity_tallredraw_bounds_color').val(_color) - allEntityTallRedrawBoundsColorpicker.spectrum("set", color.toHexString()); - if( _color !== '#00000000') { - $("#all_entity_tallredraw_bounds_draw_off").show(); - } - saveAllEntityTallRedrawBoundsColor(_color); + if (window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX) { + $('#all_entity_tallredraw_bounds_color').val( + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX + ); } - }); + let tallRedrawStartColor = $('#all_entity_tallredraw_bounds_color').val() + ? $('#all_entity_tallredraw_bounds_color').val() + : '#00000000'; + saveAllEntityTallRedrawBoundsColor(tallRedrawStartColor); - $("#all_entity_tallredraw_bounds_draw_off").click( () => { - $("#all_entity_tallredraw_bounds_draw_off").hide(); - allEntityTallRedrawBoundsColorpicker.spectrum("set", "#00000000"); - saveAllEntityTallRedrawBoundsColor("#00000000") - } ); -} + if (tallRedrawStartColor === '#00000000') { + $('#all_entity_tallredraw_bounds_draw_off').hide(); + } else { + tallRedrawStartColor = tallRedrawStartColor.substr(0, 7); + } + + const allEntityTallRedrawBoundsColorpicker = $( + '#all_entity_tallredraw_bounds_draw_picker' + ).spectrum({ + color: tallRedrawStartColor, + showInput: true, + className: 'full-spectrum', + showInitial: true, + showSelectionPalette: true, + maxSelectionSize: 10, + preferredFormat: 'hex', + change(color) { + const _color = `${color.toHexString()}ff`; + $('#all_entity_tallredraw_bounds_color').val(_color); + allEntityTallRedrawBoundsColorpicker.spectrum('set', color.toHexString()); + if (_color !== '#00000000') { + $('#all_entity_tallredraw_bounds_draw_off').show(); + } + saveAllEntityTallRedrawBoundsColor(_color); + } + }); + + $('#all_entity_tallredraw_bounds_draw_off').click(() => { + $('#all_entity_tallredraw_bounds_draw_off').hide(); + allEntityTallRedrawBoundsColorpicker.spectrum('set', '#00000000'); + saveAllEntityTallRedrawBoundsColor('#00000000'); + }); +}; -const saveAllEntityTallRedrawBoundsColor = (hex) => { - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX = hex; - window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING = hexToRgba(hex); +const saveAllEntityTallRedrawBoundsColor = hex => { + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING_HEX = hex; + window.$$$currentMap.mapData.MAPED_GLOBAL_ENTITY_TALLREDRAW_BOUNDS_DRAWING = hexToRgba(hex); }; const setupColorStuff = () => { - setupEntityBoundsDrawing(); - setupEntityHitboxDrawing(); - setupEntityTallRedrawDrawing(); -} + setupEntityBoundsDrawing(); + setupEntityHitboxDrawing(); + setupEntityTallRedrawDrawing(); +}; export const EntitiesWidget = { - initEntitiesWidget + initEntitiesWidget }; - diff --git a/src/main/BaseSetup.js b/src/main/BaseSetup.js index f742c77..9e80b6d 100644 --- a/src/main/BaseSetup.js +++ b/src/main/BaseSetup.js @@ -1,12 +1,27 @@ -import { LOG, INFO } from '../Logging' +import { LOG, INFO } from '../Logging'; import { TilesetSelectorWidget } from '../js/ui/TilesetSelectorPalette.js'; import { Map, verifyTileData, verifyMap, cleanEntities } from '../Map.js'; import { Palettes } from '../Palettes.js'; -import { LayersWidget, selectNumberedLayer, visibilityFix, getSelectedLayer, MAGICAL_ENT_LAYER_ID, MAGICAL_OBS_LAYER_ID, MAGICAL_ZONE_LAYER_ID } from '../js/ui/LayersPalette.js'; // , selectZoneLayer, selectObstructionLayer, selectNumberedLayer, newLayerOnNewMap +import { + LayersWidget, + selectNumberedLayer, + visibilityFix, + getSelectedLayer, + MAGICAL_ENT_LAYER_ID, + MAGICAL_OBS_LAYER_ID, + MAGICAL_ZONE_LAYER_ID +} from '../js/ui/LayersPalette.js'; // , selectZoneLayer, selectObstructionLayer, selectNumberedLayer, newLayerOnNewMap import { ZonesWidget } from '../js/ui/ZonesPalette.js'; import { EntitiesWidget } from '../js/ui/EntityPalette.js'; import { updateMapAndVSPFileInfo } from '../js/ui/InfoPalette.js'; -import { getCurrentHoverTile, initTools, updateRstringInfo, updateLocationFunction, selectAll, updateInfoDims } from '../Tools.js'; +import { + getCurrentHoverTile, + initTools, + updateRstringInfo, + updateLocationFunction, + selectAll, + updateInfoDims +} from '../Tools.js'; import { cut, copy, paste } from '../js/ui/CutCopyPaste'; import { handleUndo, handleRedo } from '../UndoRedo'; import { setupNotifications, notify } from '../Notification-Pane'; @@ -22,232 +37,238 @@ const path = require('path'); const { dialog } = require('electron').remote; const fs = require('fs'); -const updateScreenview = (map) => { - $('#screenview-indicator-switch').prop('checked', map.windowOverlay.on); - $('#screenview-indicator-x').val(map.windowOverlay.viewport.x); - $('#screenview-indicator-y').val(map.windowOverlay.viewport.y); - $('#screenview-indicator-width').val(map.windowOverlay.viewport.width); - $('#screenview-indicator-height').val(map.windowOverlay.viewport.height); -} +const updateScreenview = map => { + $('#screenview-indicator-switch').prop('checked', map.windowOverlay.on); + $('#screenview-indicator-x').val(map.windowOverlay.viewport.x); + $('#screenview-indicator-y').val(map.windowOverlay.viewport.y); + $('#screenview-indicator-width').val(map.windowOverlay.viewport.width); + $('#screenview-indicator-height').val(map.windowOverlay.viewport.height); +}; // / TODO: why have both $$$_BREDITOR_MOST_RECENT.json and $$$_MAPED.json... 🤔 // / I guess one should be in the appdir to at least point to the project directory... const loadMostRecentFileOption = () => { - // / TODO: is there a reason for requiring these in-block like this, or is it just cargo cult copypasta? - const jp = jetpack.cwd(APPDATA_DIR); - - const appConfigData = jp.read(BREADPATH.getMostRecentFilesJSONPath(), 'json'); - window.$$$_most_recent_options = appConfigData; + // / TODO: is there a reason for requiring these in-block like this, or is it just cargo cult copypasta? + const jp = jetpack.cwd(APPDATA_DIR); - return appConfigData; -} + const appConfigData = jp.read(BREADPATH.getMostRecentFilesJSONPath(), 'json'); + window.$$$_most_recent_options = appConfigData; -const initScreen = (map) => { + return appConfigData; +}; - updateScreenview(map); +const initScreen = map => { + updateScreenview(map); - $('#screenview-indicator-switch').click( () => { - map.windowOverlay.on = $('#screenview-indicator-switch').prop('checked'); - } ); + $('#screenview-indicator-switch').click(() => { + map.windowOverlay.on = $('#screenview-indicator-switch').prop('checked'); + }); - $('#screenview-indicator-x').on('change', (ev) => map.windowOverlay.viewport.x = parseInt($(ev.target).val(), 10)); - $('#screenview-indicator-y').on('change', (ev) => map.windowOverlay.viewport.y = parseInt($(ev.target).val(), 10)); - $('#screenview-indicator-width').on('change', (ev) => map.windowOverlay.viewport.width = parseInt($(ev.target).val(), 10)); - $('#screenview-indicator-height').on('change', (ev) => map.windowOverlay.viewport.height = parseInt($(ev.target).val(), 10)); -} + $('#screenview-indicator-x').on( + 'change', + ev => (map.windowOverlay.viewport.x = parseInt($(ev.target).val(), 10)) + ); + $('#screenview-indicator-y').on( + 'change', + ev => (map.windowOverlay.viewport.y = parseInt($(ev.target).val(), 10)) + ); + $('#screenview-indicator-width').on( + 'change', + ev => (map.windowOverlay.viewport.width = parseInt($(ev.target).val(), 10)) + ); + $('#screenview-indicator-height').on( + 'change', + ev => (map.windowOverlay.viewport.height = parseInt($(ev.target).val(), 10)) + ); +}; -const initInfoWidget = (map) => { - updateMapAndVSPFileInfo(map); +const initInfoWidget = map => { + updateMapAndVSPFileInfo(map); }; function killAllElementListeners($elem) { - // first argument of function: "$._data ()" is: "Element" - not jQuery object - $.each( $._data( $elem, "events" ), function(name) { - LOG(`body had listener: ${ name}`); - $elem.off( name ); // function off() removes an event handler - } ); + // first argument of function: "$._data ()" is: "Element" - not jQuery object + $.each($._data($elem, 'events'), function(name) { + LOG(`body had listener: ${name}`); + $elem.off(name); // function off() removes an event handler + }); } function killAllDocumentListeners(doc) { - // first argument of function: "$._data ()" is: "Element" - not jQuery object - $.each( $._data( $elem, "events" ), function(name) { - LOG(`body had listener: ${ name}`); - $elem.off( name ); // function off() removes an event handler - } ); + // first argument of function: "$._data ()" is: "Element" - not jQuery object + $.each($._data($elem, 'events'), function(name) { + LOG(`body had listener: ${name}`); + $elem.off(name); // function off() removes an event handler + }); } - function setupShiftKeyPressed() { - // TODO this are evil. - window.isShiftKeyPressed = false; - $(document).on('keyup keydown', function(e){ - window.isShiftKeyPressed = e.shiftKey; - }); + // TODO this are evil. + window.isShiftKeyPressed = false; + $(document).on('keyup keydown', function(e) { + window.isShiftKeyPressed = e.shiftKey; + }); } let __setupChording_once = false; // TODO: verify all this cannot be done with accelerators function setupChording() { - if(__setupChording_once) { - return; - } + if (__setupChording_once) { + return; + } - // this is dumb. - __setupChording_once = true; + // this is dumb. + __setupChording_once = true; - $('body').on('keydown', (e) => { - if (!(e.ctrlKey || e.cmdKey)) { // TODO verify this on mac, cmdKey is a guess. - return; - } + $('body').on('keydown', e => { + if (!(e.ctrlKey || e.cmdKey)) { + // TODO verify this on mac, cmdKey is a guess. + return; + } - if (document.activeElement.type && document.activeElement.type === 'text') { - INFO('in a textfield, ignoring the accelerator'); - return; - } + if (document.activeElement.type && document.activeElement.type === 'text') { + INFO('in a textfield, ignoring the accelerator'); + return; + } - // if(e.key === 'c' && ) { - // INFO('on the tools palette, ignoring the spacebar'); - // return; - // } - - // TODO all of these commands should probably be passed in the map on the currently active map palette - // (if there is one) so as to include the tileset map or any future ones - if (e.key === 'c' || e.key === 'C') { - LOG('edit-copy, but the one on the document. SIGH WINDOWS.'); - - if (window.$$$currentMap.selection.tiles && window.$$$currentMap.selection.tiles.length) { - copy(window.$$$currentMap); - } else if ( - window.$$$currentTilsesetSelectorMap && - window.$$$currentTilsesetSelectorMap.selection.tiles && - window.$$$currentTilsesetSelectorMap.selection.tiles.length - ) { - copy(window.$$$currentTilsesetSelectorMap); - } else { - LOG('FALL THROUGH'); - } - - return; - } + // if(e.key === 'c' && ) { + // INFO('on the tools palette, ignoring the spacebar'); + // return; + // } + + // TODO all of these commands should probably be passed in the map on the currently active map palette + // (if there is one) so as to include the tileset map or any future ones + if (e.key === 'c' || e.key === 'C') { + LOG('edit-copy, but the one on the document. SIGH WINDOWS.'); + + if ( + window.$$$currentMap.selection.tiles && + window.$$$currentMap.selection.tiles.length + ) { + copy(window.$$$currentMap); + } else if ( + window.$$$currentTilsesetSelectorMap && + window.$$$currentTilsesetSelectorMap.selection.tiles && + window.$$$currentTilsesetSelectorMap.selection.tiles.length + ) { + copy(window.$$$currentTilsesetSelectorMap); + } else { + LOG('FALL THROUGH'); + } - if ((e.key === 'v' || e.key === 'V')) { - if( e.shiftKey ) { - LOG('super-paste, but the one on the document. SIGH WINDOWS.'); - window.$$$superpaste(); - return; - } - LOG('edit-paste, but the one on the document. SIGH WINDOWS.'); - paste(window.$$$currentMap); - return; - - } + return; + } - if ((e.key === 'x' || e.key === 'X')) { - if(e.shiftKey) { - LOG('super-cut, but the one on the document. SIGH WINDOWS.'); - window.$$$supercut(); - return; - } - LOG('edit-cut, but the one on the document. SIGH WINDOWS.'); - cut(window.$$$currentMap); - return; - - } + if (e.key === 'v' || e.key === 'V') { + if (e.shiftKey) { + LOG('super-paste, but the one on the document. SIGH WINDOWS.'); + window.$$$superpaste(); + return; + } + LOG('edit-paste, but the one on the document. SIGH WINDOWS.'); + paste(window.$$$currentMap); + return; + } - if (e.key === 'a' || e.key === 'A') { - LOG('edit-select-all but the one on the document. SIGH WINDOWS.'); - selectAll(window.$$$currentMap); - - } - }); + if (e.key === 'x' || e.key === 'X') { + if (e.shiftKey) { + LOG('super-cut, but the one on the document. SIGH WINDOWS.'); + window.$$$supercut(); + return; + } + LOG('edit-cut, but the one on the document. SIGH WINDOWS.'); + cut(window.$$$currentMap); + return; + } + + if (e.key === 'a' || e.key === 'A') { + LOG('edit-select-all but the one on the document. SIGH WINDOWS.'); + selectAll(window.$$$currentMap); + } + }); } // TODO: jesus pull this apart and clean it up. -const tick = function (timestamp) { - if (window.$$$currentMap && window.$$$currentMap.render) { - window.$$$currentMap.render(); - TilesetSelectorWidget.renderTilesetSelectorWidget(); - } +const tick = function(timestamp) { + if (window.$$$currentMap && window.$$$currentMap.render) { + window.$$$currentMap.render(); + TilesetSelectorWidget.renderTilesetSelectorWidget(); + } - if (window.$$$SCREENSHOT) { - window.$$$SCREENSHOT(); - window.$$$SCREENSHOT = null; - } + if (window.$$$SCREENSHOT) { + window.$$$SCREENSHOT(); + window.$$$SCREENSHOT = null; + } - window.requestAnimationFrame(tick); + window.requestAnimationFrame(tick); }; - - /** * Setup the rest of the app ;D */ function setupTheRestOfTheApp() { - Palettes.setupPaletteRegistry(); + Palettes.setupPaletteRegistry(); + + if (window.$$$currentMap) { + window.$$$currentMap.selfDestruct(); + } + window.$$$currentMap = null; - if(window.$$$currentMap) { - window.$$$currentMap.selfDestruct(); - } - window.$$$currentMap = null; + if (!window.$$$RAF_INIT) { + window.$$$RAF_INIT = true; + window.requestAnimationFrame(tick); + } - if(!window.$$$RAF_INIT) { - window.$$$RAF_INIT = true; - window.requestAnimationFrame(tick); - } - - $('#btn-tool-undo').click(() => { - handleUndo(); - }); - $('#btn-tool-redo').click(() => { - handleRedo(); - }); + $('#btn-tool-undo').click(() => { + handleUndo(); + }); + $('#btn-tool-redo').click(() => { + handleRedo(); + }); } export function autoloadMostRecentMapIfAvailable() { - const fs = require('fs'); + const fs = require('fs'); - const opts = loadMostRecentFileOption(); + const opts = loadMostRecentFileOption(); - if(opts && opts.abs_path_to_maps && opts.most_recent_map) { - const filepath = path.join(opts.abs_path_to_maps, opts.most_recent_map); + if (opts && opts.abs_path_to_maps && opts.most_recent_map) { + const filepath = path.join(opts.abs_path_to_maps, opts.most_recent_map); - if( fs.existsSync(filepath) ) { - INFO(`${filepath} specified to autoload...`); - loadByFilename(filepath); + if (fs.existsSync(filepath)) { + INFO(`${filepath} specified to autoload...`); + loadByFilename(filepath); + } else { + INFO(`${filepath} specified to autoload... but it wasn't there.`); + } } else { - INFO(`${filepath} specified to autoload... but it wasn't there.`); + INFO('No map specified to autoload.'); } - - } else { - INFO('No map specified to autoload.'); - } } /** -* Necesary to setup a freshly loaded map. -*/ + * Necesary to setup a freshly loaded map. + */ export function setupFreshApp() { + killAllElementListeners($('#body')); + // killAllDocumentListeners(document); - killAllElementListeners($( "#body" )); - // killAllDocumentListeners(document); + setupShiftKeyPressed(); - setupShiftKeyPressed(); + setupChording(); - setupChording(); + setupTheRestOfTheApp(); - setupTheRestOfTheApp(); + setupNotifications(); - setupNotifications(); - - loadPlugins(); + loadPlugins(); } export function setupWindowFunctions() { - - const newMapDialog = () => { - const $template = ` + const newMapDialog = () => { + const $template = `

    Last step: how big (in tiles) do you want the base layer of your new map to be?

    Width
    Height
    @@ -255,71 +276,76 @@ export function setupWindowFunctions() {

    Nothing has yet been altered on your disk. However: pressing "CREATE ALL NEW FILES" will create and/or overwrite any files you've specified during this process.

    `; - const title = 'Step 4: Create new map'; - - $('#modal-dialog').html(''); - $('#modal-dialog').append($template); - $('#modal-dialog').show(); - - window.$$$hide_all_windows(); - - const dialog = $('#modal-dialog').dialog({ - width: 500, - modal: true, - title, - buttons: { - 'Cancel': function () { - $('#modal-dialog').dialog( "close" ); - }, 'CREATE ALL NEW FILES': () => { - const wid = parseInt($('#newmap-width').val(),10); - const hig = parseInt($('#newmap-height').val(),10); - - if(wid>0 && hig>0) { - SaveNewMap(); - } else { - alert("Invalid values. Please try again."); - } - } - } - }); - }; - - - const dialoger = (title, template, buttonMap, noCancel, afterDialogOpenFn) => { - $('#modal-dialog').html(''); - $('#modal-dialog').append(template); - $('#modal-dialog').show(); + const title = 'Step 4: Create new map'; - window.$$$hide_all_windows(); + $('#modal-dialog').html(''); + $('#modal-dialog').append($template); + $('#modal-dialog').show(); + + window.$$$hide_all_windows(); + + const dialog = $('#modal-dialog').dialog({ + width: 500, + modal: true, + title, + buttons: { + Cancel: function() { + $('#modal-dialog').dialog('close'); + }, + 'CREATE ALL NEW FILES': () => { + const wid = parseInt($('#newmap-width').val(), 10); + const hig = parseInt($('#newmap-height').val(), 10); + + if (wid > 0 && hig > 0) { + SaveNewMap(); + } else { + alert('Invalid values. Please try again.'); + } + } + } + }); + }; - if(!noCancel && !buttonMap.cancel && !buttonMap.Cancel) { - buttonMap.Cancel = { - text: "Close", - click: () => { $('#modal-dialog').dialog( "close" ); }, - id: "modal-dialog-close-button", - class: "close-button" - }; - } + const dialoger = (title, template, buttonMap, noCancel, afterDialogOpenFn) => { + $('#modal-dialog').html(''); + $('#modal-dialog').append(template); + $('#modal-dialog').show(); + + window.$$$hide_all_windows(); + + if (!noCancel && !buttonMap.cancel && !buttonMap.Cancel) { + buttonMap.Cancel = { + text: 'Close', + click: () => { + $('#modal-dialog').dialog('close'); + }, + id: 'modal-dialog-close-button', + class: 'close-button' + }; + } - const dialog = $('#modal-dialog').dialog({ - width: 500, - modal: true, - title: title, - buttons: buttonMap - }); + const dialog = $('#modal-dialog').dialog({ + width: 500, + modal: true, + title: title, + buttons: buttonMap + }); - if(afterDialogOpenFn) { - afterDialogOpenFn(); - } - }; + if (afterDialogOpenFn) { + afterDialogOpenFn(); + } + }; - const newVspDialogPreStepCopyOrRef = (existingVspFilename) => { - const relPath = path.relative(path.dirname(window.newMapFilename),path.dirname(existingVspFilename));// + path.basename(existingVspFilename); - let shittyMutex4 = false; + const newVspDialogPreStepCopyOrRef = existingVspFilename => { + const relPath = path.relative( + path.dirname(window.newMapFilename), + path.dirname(existingVspFilename) + ); // + path.basename(existingVspFilename); + let shittyMutex4 = false; - dialoger( - 'Step 2c: Copy it or reference it?', - ` + dialoger( + 'Step 2c: Copy it or reference it?', + `

    You selected:

    ${window.newMapFilename}

    @@ -331,99 +357,104 @@ export function setupWindowFunctions() {

    Copying means changes you make to it will not be refelected in other tilesets that used the original.

    Referencing means if you move your image around, it'll likely break things and you'll need to edit the json file to fix it.

    `, - { - 'Make a new COPY': () => { - if(shittyMutex4) return; - shittyMutex4 = true; - dialog.showSaveDialog( - {filters: [{ name: 'image', extensions: ['png'] }]}, - (filename) => { - shittyMutex4 = false; - if(existingVspFilename == filename) { - alert("You selected to copy over the original image. Please try again and enter a new filename."); - return; - } - - if(filename) { - newVspDialogStepFinal(existingVspFilename, filename); - } - }); - }, - 'Keep the same REFERENCE': () => { - newVspDialogStepFinal(existingVspFilename); - } - } - ) - } - - const errorHandler = (val, sel) => { - const ret = ( Number.isNaN(val) || val <= 0 ); - ret ? $(sel).addClass('error') : $(sel).removeClass('error'); - return !ret; - } + { + 'Make a new COPY': () => { + if (shittyMutex4) return; + shittyMutex4 = true; + dialog.showSaveDialog( + { filters: [{ name: 'image', extensions: ['png'] }] }, + filename => { + shittyMutex4 = false; + if (existingVspFilename == filename) { + alert( + 'You selected to copy over the original image. Please try again and enter a new filename.' + ); + return; + } + + if (filename) { + newVspDialogStepFinal(existingVspFilename, filename); + } + } + ); + }, + 'Keep the same REFERENCE': () => { + newVspDialogStepFinal(existingVspFilename); + } + } + ); + }; - const newVspDialogStepFinal = (existingImageFilename, newImageCopyFilename) => { + const errorHandler = (val, sel) => { + const ret = Number.isNaN(val) || val <= 0; + ret ? $(sel).addClass('error') : $(sel).removeClass('error'); + return !ret; + }; - let w = 256; - let h = 256; + const newVspDialogStepFinal = (existingImageFilename, newImageCopyFilename) => { + let w = 256; + let h = 256; - if(existingImageFilename) { - const data = fs.readFileSync(existingImageFilename); - const png = PNG.sync.read(data); - - if(png) { - w = png.width; - h = png.height; - } - } + if (existingImageFilename) { + const data = fs.readFileSync(existingImageFilename); + const png = PNG.sync.read(data); - const listener = () => { - const vw = parseInt($('#vsp-width').val(),10); - const vh = parseInt($('#vsp-height').val(),10); - const tw = parseInt($('#tile-width').val(),10); - const th = parseInt($('#tile-height').val(),10); - - let valid = true; - valid &= errorHandler(vw,'#vsp-width'); - valid &= errorHandler(vh,'#vsp-height'); - valid &= errorHandler(tw,'#tile-width'); - valid &= errorHandler(th,'#tile-height'); - valid &= errorHandler($("#image-name").val().length,'#image-name'); - valid &= errorHandler($("#vsp-name").val().length,'#vsp-name'); - - if( !valid ) { - $("#tiles-per-row").val("-").removeClass("error"); - $("#tiles-total").val("-").removeClass("error"); - - } else { - const perRow = parseInt(vw/tw, 10); - const perCol = parseInt(vh/th, 10); - - $("#tiles-per-row").val(perRow); - $("#tiles-total").val(perRow*perCol); - - if(perRow <= 0) { - $("#tiles-total").addClass("error"); - } else { - $("#tiles-total").removeClass("error"); + if (png) { + w = png.width; + h = png.height; + } } - if(perRow*perCol <= 0) { - $("#tiles-total").addClass("error"); - } else { - $("#tiles-total").removeClass("error"); - } - } - }; + const listener = () => { + const vw = parseInt($('#vsp-width').val(), 10); + const vh = parseInt($('#vsp-height').val(), 10); + const tw = parseInt($('#tile-width').val(), 10); + const th = parseInt($('#tile-height').val(), 10); + + let valid = true; + valid &= errorHandler(vw, '#vsp-width'); + valid &= errorHandler(vh, '#vsp-height'); + valid &= errorHandler(tw, '#tile-width'); + valid &= errorHandler(th, '#tile-height'); + valid &= errorHandler($('#image-name').val().length, '#image-name'); + valid &= errorHandler($('#vsp-name').val().length, '#vsp-name'); + + if (!valid) { + $('#tiles-per-row') + .val('-') + .removeClass('error'); + $('#tiles-total') + .val('-') + .removeClass('error'); + } else { + const perRow = parseInt(vw / tw, 10); + const perCol = parseInt(vh / th, 10); + + $('#tiles-per-row').val(perRow); + $('#tiles-total').val(perRow * perCol); + + if (perRow <= 0) { + $('#tiles-total').addClass('error'); + } else { + $('#tiles-total').removeClass('error'); + } - const verify = () => { - return $("#modal-dialog input.error").length === 0 && $("#vsp-name").val(); - }; + if (perRow * perCol <= 0) { + $('#tiles-total').addClass('error'); + } else { + $('#tiles-total').removeClass('error'); + } + } + }; + + const verify = () => { + return $('#modal-dialog input.error').length === 0 && $('#vsp-name').val(); + }; - let topPart; - if(existingImageFilename && newImageCopyFilename) { - const imagename = path.basename(existingImageFilename); - topPart = ` + let topPart; + if (existingImageFilename && newImageCopyFilename) { + const imagename = path.basename(existingImageFilename); + topPart = `

    We will create a new tileset definition by copying an existing file:

    ${existingImageFilename}

    To a new copy of that file at:

    @@ -435,8 +466,8 @@ export function setupWindowFunctions() { image height:

    `; - } else if(existingImageFilename === null && newImageCopyFilename === true) { - topPart = ` + } else if (existingImageFilename === null && newImageCopyFilename === true) { + topPart = `

    We will create a new tileset definition by creating a brand new image!

    Note: it's usually optimal to have your width and height be the same number (square) and a power of 2.

    @@ -447,10 +478,9 @@ export function setupWindowFunctions() { image height:

    `; - - } else { - const vspname = path.basename(existingImageFilename); - topPart = ` + } else { + const vspname = path.basename(existingImageFilename); + topPart = `

    We will create a new tileset definition by referencing an existing file:

    ${existingImageFilename}

    ...and storing that as a relative path to the Tileset Definition you are about to save.

    @@ -461,11 +491,11 @@ export function setupWindowFunctions() { image height:

    `; - } + } - dialoger( - 'Step 2d: Define your Tileset', - ` + dialoger( + 'Step 2d: Define your Tileset', + ` ${topPart}

    tile width:
    @@ -475,175 +505,177 @@ export function setupWindowFunctions() { Tileset Definition File:

    `, - { - 'Confirm': () => { - listener(); - if( !verify() ){ - alert('Please fix any errors before continuing.'); - return; - } - - const vw = parseInt($('#vsp-width').val(),10); - const tw = parseInt($('#tile-width').val(),10); - const th = parseInt($('#tile-height').val(),10); - const tpr = parseInt(vw/tw,10); - const imgName = $("#image-name").val(); - const vspName = $("#vsp-name").val(); - - window.newMapData.default_vspfile = vspName; - window.newVspData = { - "tilesize": { - "width": tw, - "height": th + { + Confirm: () => { + listener(); + if (!verify()) { + alert('Please fix any errors before continuing.'); + return; + } + + const vw = parseInt($('#vsp-width').val(), 10); + const tw = parseInt($('#tile-width').val(), 10); + const th = parseInt($('#tile-height').val(), 10); + const tpr = parseInt(vw / tw, 10); + const imgName = $('#image-name').val(); + const vspName = $('#vsp-name').val(); + + window.newMapData.default_vspfile = vspName; + window.newVspData = { + tilesize: { + width: tw, + height: th + }, + tiles_per_row: tpr, + source_image: { + existingImageFilename, + newImageCopyFilename, + imgName, + vspName + } + }; + + obsModeDialog(); + } }, - "tiles_per_row": tpr, - "source_image": { - existingImageFilename, - newImageCopyFilename, - imgName, - vspName + false, + () => { + $('#modal-dialog input').on('keyup', listener); + + let shittyMutex1 = false; + let shittyMutex2 = false; + + $('#choose-vsp').click(() => { + if (shittyMutex1) return; + shittyMutex1 = true; + dialog.showSaveDialog( + { + title: 'Save new tileset definion', + filters: [{ name: 'text', extensions: ['vsp.json'] }] + }, + filename => { + shittyMutex1 = false; + if (filename) { + $('#vsp-name').val(filename); + } + } + ); + }); + + $('#choose-image').click(() => { + if (shittyMutex2) return; + shittyMutex2 = true; + dialog.showSaveDialog( + { + title: 'Save new tileset image', + filters: [{ name: 'img', extensions: ['png'] }] + }, + filename => { + shittyMutex2 = false; + if (filename) { + $('#image-name').val(filename); + } + } + ); + }); } - }; + ); + }; - obsModeDialog(); - }, - }, false, () => { - - $("#modal-dialog input").on("keyup", listener); - - let shittyMutex1 = false; - let shittyMutex2 = false; - - $("#choose-vsp").click( () => { - if(shittyMutex1) return; - shittyMutex1 = true; - dialog.showSaveDialog( + const newVspDialog = () => { + let shittyMutex3 = false; + + dialoger( + 'Step 2b: Tileset Image Asset', + ` +

    Do you want to create a new tileset from an existing image, or a brand new image?
    (Note: currently only png is supported.)

    + `, { - title: 'Save new tileset definion', - filters: [{ name: 'text', extensions: ['vsp.json'] }] - }, - (filename) => { - shittyMutex1 = false; - if( filename ) { - $("#vsp-name").val(filename); - } + 'Existing Image': () => { + if (shittyMutex3) return; + shittyMutex3 = true; + dialog.showOpenDialog( + { + title: 'Choose Tileset Image', + filters: [{ name: 'image', extensions: ['png'] }] + }, + res => { + shittyMutex3 = false; + if (res) { + newVspDialogPreStepCopyOrRef(res[0]); + } + } + ); + }, + 'Generate a New Image': () => { + newVspDialogStepFinal(null, true); + } } - )}); + ); + }; - $("#choose-image").click( () => { - if(shittyMutex2) return; - shittyMutex2 = true; - dialog.showSaveDialog( - { - title: 'Save new tileset image', - filters: [{ name: 'img', extensions: ['png'] }] + const vspModeDialog = () => { + window.$$$hide_all_windows(); + dialoger('Step 2: Default Tileset Options', ``, { + 'Create new tileset': () => { + newVspDialog(); + }, + 'Choose existing tileset': () => { + _chooseExistingDefaultTileVSP(obsModeDialog); }, - (filename) => { - shittyMutex2 = false; - if( filename ) { - $("#image-name").val(filename); - } + 'This map will not have tiles': () => { + alert('Thats insane! (currently unsupported)'); } - )}); - } - ); - }; - - const newVspDialog = () => { - - let shittyMutex3 = false; + }); + }; - dialoger( - 'Step 2b: Tileset Image Asset', - ` -

    Do you want to create a new tileset from an existing image, or a brand new image?
    (Note: currently only png is supported.)

    - `, - { - 'Existing Image': () => { - if(shittyMutex3) return; - shittyMutex3 = true; - dialog.showOpenDialog( + function _chooseExistingDefaultTileVSP(obsModeDialog) { + dialog.showOpenDialog( { - title: 'Choose Tileset Image', - filters: [{ name: 'image', extensions: ['png'] }] + title: 'Choose default VSP', + filters: [{ name: 'text', extensions: ['vsp.json'] }] }, - (res) => { - shittyMutex3 = false; - if(res) { - newVspDialogPreStepCopyOrRef(res[0]); - } - } - ); - }, - 'Generate a New Image': () => { - newVspDialogStepFinal(null, true); - }, - } - ); - }; - - const vspModeDialog = () => { - window.$$$hide_all_windows(); - dialoger( - 'Step 2: Default Tileset Options', - ``, - { - 'Create new tileset': () => { - newVspDialog(); - }, - 'Choose existing tileset': () => { - _chooseExistingDefaultTileVSP(obsModeDialog); - }, - 'This map will not have tiles': () => { - alert('Thats insane! (currently unsupported)'); - }, - } - ); - }; - - function _chooseExistingDefaultTileVSP(obsModeDialog) { - dialog.showOpenDialog( - { - title: 'Choose default VSP', - filters: [{ name: 'text', extensions: ['vsp.json'] }] - }, - (res) => { - if (!res) { - return; - } - window.newMapData.default_vspfile = res[0]; - - window.newVspData = require('fs-jetpack').cwd(__dirname).read(res[0], 'json'); - - obsModeDialog(); - } - ); - } + res => { + if (!res) { + return; + } + window.newMapData.default_vspfile = res[0]; - const newObsTilesetDialog = () => { + window.newVspData = require('fs-jetpack') + .cwd(__dirname) + .read(res[0], 'json'); - const validate = () => { - let valid = true; + obsModeDialog(); + } + ); + } - const rows = parseInt($('#tiles-per-row').val(),10); - const cols = parseInt($('#tiles-per-col').val(),10); + const newObsTilesetDialog = () => { + const validate = () => { + let valid = true; - valid &= errorHandler(rows,'#tiles-per-row'); - valid &= errorHandler(cols,'#tiles-per-col'); - valid &= errorHandler($("#obs-image-name").val().length,'#obs-image-name'); - valid &= errorHandler($("#obs-def-name").val().length,'#obs-def-name'); + const rows = parseInt($('#tiles-per-row').val(), 10); + const cols = parseInt($('#tiles-per-col').val(), 10); - if(rows && cols && rows > 0 && cols > 0 ) { - $("#tiles-total").text( rows*cols ); - $("#image-dims").text( `${window.newVspData.tilesize.width*cols} x ${window.newVspData.tilesize.height*rows} (pixels)` ); - } + valid &= errorHandler(rows, '#tiles-per-row'); + valid &= errorHandler(cols, '#tiles-per-col'); + valid &= errorHandler($('#obs-image-name').val().length, '#obs-image-name'); + valid &= errorHandler($('#obs-def-name').val().length, '#obs-def-name'); - return valid; - }; + if (rows && cols && rows > 0 && cols > 0) { + $('#tiles-total').text(rows * cols); + $('#image-dims').text( + `${window.newVspData.tilesize.width * cols} x ${window.newVspData.tilesize + .height * rows} (pixels)` + ); + } + + return valid; + }; - dialoger( - `Step 3a: Create New Obstruction Tileset`, - ` + dialoger( + `Step 3a: Create New Obstruction Tileset`, + `

    Obstruction tiles must be the same size as your default tilesize.

    tile width:
    @@ -659,113 +691,116 @@ export function setupWindowFunctions() { Obstruction Tileset Definition File:

    `, - { - 'Continue': () => { - if(!validate()) { - alert("Please correct any errors in the form before trying again."); - return; - } - - window.newMapData.obs_vspfile = { - "obs-image-name": $("#obs-image-name").val(), - "obs-def-name": $("#obs-def-name").val(), - rows: parseInt($('#tiles-per-row').val(),10), - cols: parseInt($('#tiles-per-col').val(),10), - }; - newMapDialog(); - } - }, - false, - () => { - $("#modal-dialog input").on("keyup", validate); - - let shittyMutex1 = false; - let shittyMutex2 = false; - - $("#choose-image").click( () => { - if(shittyMutex1) return; - shittyMutex1 = true; - dialog.showSaveDialog( { - title: 'Save new obstruction image data', - filters: [{ name: 'image', extensions: ['png'] }] + Continue: () => { + if (!validate()) { + alert('Please correct any errors in the form before trying again.'); + return; + } + + window.newMapData.obs_vspfile = { + 'obs-image-name': $('#obs-image-name').val(), + 'obs-def-name': $('#obs-def-name').val(), + rows: parseInt($('#tiles-per-row').val(), 10), + cols: parseInt($('#tiles-per-col').val(), 10) + }; + newMapDialog(); + } }, - (filename) => { - shittyMutex1 = false; - if( filename ) { - $("#obs-image-name").val(filename); - } + false, + () => { + $('#modal-dialog input').on('keyup', validate); + + let shittyMutex1 = false; + let shittyMutex2 = false; + + $('#choose-image').click(() => { + if (shittyMutex1) return; + shittyMutex1 = true; + dialog.showSaveDialog( + { + title: 'Save new obstruction image data', + filters: [{ name: 'image', extensions: ['png'] }] + }, + filename => { + shittyMutex1 = false; + if (filename) { + $('#obs-image-name').val(filename); + } + } + ); + }); + + $('#choose-vsp').click(() => { + if (shittyMutex2) return; + shittyMutex2 = true; + dialog.showSaveDialog( + { + title: 'Save new obstruction definition file', + filters: [{ name: 'text', extensions: ['.vsp.json'] }] + }, + filename => { + shittyMutex2 = false; + if (filename) { + $('#obs-def-name').val(filename); + } + } + ); + }); } - )}); + ); + }; - $("#choose-vsp").click( () => { - if(shittyMutex2) return; - shittyMutex2 = true; - dialog.showSaveDialog( + const obsModeDialog = () => { + dialoger( + 'Step 3: Default Obstruction Tileset Options', + `

    Breaditor presently only supports tile-based obstructions based on 1-bit pngs.

    +

    We will be working on adding vector-based obstructions in the future.

    `, { - title: 'Save new obstruction definition file', - filters: [{ name: 'text', extensions: ['.vsp.json'] }] - }, - (filename) => { - shittyMutex2 = false; - if( filename ) { - $("#obs-def-name").val(filename); - } + 'Choose Existing Obstruction Tileset': () => { + _chooseExistingDefaultObsVSP(); + }, + 'Create New Obstruction Tileset': () => { + newObsTilesetDialog(); + } } - )}); + ); + }; - } - ); - }; + window._newStep2_chooseObsVSP = function(res) { + newMapDialog(); + }; - const obsModeDialog = () => { + const _chooseExistingDefaultObsVSP = function(res) { + dialog.showOpenDialog( + { + title: 'Choose Obstruction VSP', + filters: [{ name: 'text', extensions: ['obsvsp.json'] }] + }, + res => { + if (res) { + window.newMapData.obs_vspfile = res[0]; + newMapDialog(); + } + } + ); + }; - dialoger( - 'Step 3: Default Obstruction Tileset Options', - `

    Breaditor presently only supports tile-based obstructions based on 1-bit pngs.

    -

    We will be working on adding vector-based obstructions in the future.

    `, - { - 'Choose Existing Obstruction Tileset': () => { - _chooseExistingDefaultObsVSP(); - }, - 'Create New Obstruction Tileset': () => { - newObsTilesetDialog(); - }, - } - ); - }; - - window._newStep2_chooseObsVSP = function (res) { - newMapDialog(); - }; - - const _chooseExistingDefaultObsVSP = function (res) { - dialog.showOpenDialog({ - title: 'Choose Obstruction VSP', - filters: [{ name: 'text', extensions: ['obsvsp.json'] }] - }, - (res) => { - if(res) { - window.newMapData.obs_vspfile = res[0]; - newMapDialog(); - } - } - ); - }; + window._newStep0_chooseSaveLocation = () => { + dialog.showSaveDialog( + { filters: [{ name: 'text', extensions: ['map.json'] }] }, + filename => { + if (filename) { + const jp = jetpack.cwd(APPDATA_DIR); - window._newStep0_chooseSaveLocation = () => { - dialog.showSaveDialog( - {filters: [{ name: 'text', extensions: ['map.json'] }]}, - (filename) => { - if (filename) { - const jp = jetpack.cwd(APPDATA_DIR); - - const warning = !jp.exists(filename) ? "" : `

    Warning, there is already a map of that name there, and we will overwrite it if you finish this New Map wizard.

    `; + const warning = !jp.exists(filename) + ? '' + : `

    Warning, there is already a map of that name there, and we will overwrite it if you finish this New Map wizard.

    `; - dialoger( - "Step 1: Verify Save Location", + dialoger( + 'Step 1: Verify Save Location', - `

    You want to create a new map file at

    + `

    You want to create a new map file at

    ${filename}

    @@ -773,179 +808,184 @@ export function setupWindowFunctions() { Is that correct?

    ${warning} - `, - { - 'Yes': () => { - window.newMapFilename = filename; - vspModeDialog(); - } - }); - } - } - ); - }; + `, + { + Yes: () => { + window.newMapFilename = filename; + vspModeDialog(); + } + } + ); + } + } + ); + }; - window.$$$new = () => { - window.newMapFilename = ''; - window.newMapData = {}; + window.$$$new = () => { + window.newMapFilename = ''; + window.newMapData = {}; - window._newStep0_chooseSaveLocation(); - }; + window._newStep0_chooseSaveLocation(); + }; - window.$$$save = function (newName, isSaveAs, reloadAfterSave) { - if(window.$$$currentMap.compactifyZones) { - window.$$$currentMap.compactifyZones(); - } - window._save(newName, window.$$$currentMap, isSaveAs || reloadAfterSave); - }; + window.$$$save = function(newName, isSaveAs, reloadAfterSave) { + if (window.$$$currentMap.compactifyZones) { + window.$$$currentMap.compactifyZones(); + } + window._save(newName, window.$$$currentMap, isSaveAs || reloadAfterSave); + }; - window._save = function (newName, map, reloadAfterSave) { - const jp = jetpack.cwd(APPDATA_DIR); + window._save = function(newName, map, reloadAfterSave) { + const jp = jetpack.cwd(APPDATA_DIR); - let mapfile = null; - let datafile = null; - if (typeof newName !== 'undefined') { - mapfile = newName; - datafile = mapfile.replace('.map.json', '.map.data.json'); // todo this is shit. - } else { - mapfile = map.filenames.mapfile; - datafile = map.filenames.mapdatafile; - } + let mapfile = null; + let datafile = null; + if (typeof newName !== 'undefined') { + mapfile = newName; + datafile = mapfile.replace('.map.json', '.map.data.json'); // todo this is shit. + } else { + mapfile = map.filenames.mapfile; + datafile = map.filenames.mapdatafile; + } - const mapData = JSON.parse(JSON.stringify(map.mapData)); - const tileData = JSON.parse(JSON.stringify(map.mapRawTileData)); + const mapData = JSON.parse(JSON.stringify(map.mapData)); + const tileData = JSON.parse(JSON.stringify(map.mapRawTileData)); - cleanEntities(mapData); // TODO this should probably happen not-here? + cleanEntities(mapData); // TODO this should probably happen not-here? - INFO('saving', mapfile); - INFO('saving', datafile); + INFO('saving', mapfile); + INFO('saving', datafile); - jp.write(mapfile, mapData); - jp.write(datafile, tileData); + jp.write(mapfile, mapData); + jp.write(datafile, tileData); - saveMostRecentMapLocation(mapfile); + saveMostRecentMapLocation(mapfile); - notify("Saved map."); + notify('Saved map.'); - if(reloadAfterSave) { - INFO("Reloading map after saveas..."); - window.$$$show_all_windows(); - $('#modal-dialog').dialog( "close" ); + if (reloadAfterSave) { + INFO('Reloading map after saveas...'); + window.$$$show_all_windows(); + $('#modal-dialog').dialog('close'); - const doAfterNewMapCreate = () => { - selectNumberedLayer(1); - visibilityFix(); - window.$$$currentMap.resetCamera(); + const doAfterNewMapCreate = () => { + selectNumberedLayer(1); + visibilityFix(); + window.$$$currentMap.resetCamera(); - window.$$$showPallete('tileset-selector'); - window.$$$showPallete('map'); - window.$$$showPallete('tool'); - window.$$$showPallete('info'); - window.$$$showPallete('layers'); + window.$$$showPallete('tileset-selector'); + window.$$$showPallete('map'); + window.$$$showPallete('tool'); + window.$$$showPallete('info'); + window.$$$showPallete('layers'); - window.$$$hidePallete('zones'); - window.$$$hidePallete('entity'); - window.$$$hidePallete('screenview-indicator'); - - window.$$$collect_all_windows(); - }; + window.$$$hidePallete('zones'); + window.$$$hidePallete('entity'); + window.$$$hidePallete('screenview-indicator'); - loadByFilename(mapfile, doAfterNewMapCreate); - } -}; + window.$$$collect_all_windows(); + }; - window.$$$about_breaditor = () => { - window.alert( - 'Breaditor is a pile of junk made mostly by @bengrue and a little by Shamus Peveril.' + - 'TODO: make this better.' + - 'TODO: add the licenses jeez.' - ); - }; + loadByFilename(mapfile, doAfterNewMapCreate); + } + }; - window.$$$collect_all_windows = () => { - let x = 0; - let y = 0; - let z = 0; + window.$$$about_breaditor = () => { + window.alert( + 'Breaditor is a pile of junk made mostly by @bengrue and a little by Shamus Peveril.' + + 'TODO: make this better.' + + 'TODO: add the licenses jeez.' + ); + }; - window.$$$palette_registry.map((pal) => { - const node_selector = `.${ pal}`; - const $node = $(node_selector); - $node.css('top', `${y }px`); - $node.css('left', `${x }px`); - $node.css('z-index', z); + window.$$$collect_all_windows = () => { + let x = 0; + let y = 0; + let z = 0; - Palettes.correctResizeWidget($node); + window.$$$palette_registry.map(pal => { + const node_selector = `.${pal}`; + const $node = $(node_selector); + $node.css('top', `${y}px`); + $node.css('left', `${x}px`); + $node.css('z-index', z); - x += 30; - y += 30; - z += 2; - }); + Palettes.correctResizeWidget($node); - Palettes.savePalettePositions(); - }; + x += 30; + y += 30; + z += 2; + }); - window.$$$show_all_windows = () => { - window.$$$palette_registry.map((pal) => { - const node_selector = `.${ pal}`; - const $node = $(node_selector); - $node.show(); - }); + Palettes.savePalettePositions(); + }; - Palettes.savePalettePositions(); - }; + window.$$$show_all_windows = () => { + window.$$$palette_registry.map(pal => { + const node_selector = `.${pal}`; + const $node = $(node_selector); + $node.show(); + }); - window.$$$hide_all_windows = () => { - if(!window.$$$palette_registry) return; - window.$$$palette_registry.map((pal) => { - const node_selector = `.${ pal}`; - const $node = $(node_selector); - $node.hide(); - }); - }; + Palettes.savePalettePositions(); + }; - window.$$$load = () => { - const options = { - filters: [{ name: 'text', extensions: ['map.json'] }] + window.$$$hide_all_windows = () => { + if (!window.$$$palette_registry) return; + window.$$$palette_registry.map(pal => { + const node_selector = `.${pal}`; + const $node = $(node_selector); + $node.hide(); + }); }; - if( window.$$$_most_recent_options && window.$$$_most_recent_options.abs_path_to_maps ) { - options.defaultPath = window.$$$_most_recent_options.abs_path_to_maps; - } + window.$$$load = () => { + const options = { + filters: [{ name: 'text', extensions: ['map.json'] }] + }; - dialog.showOpenDialog( options, loadByFilename ); - }; + if (window.$$$_most_recent_options && window.$$$_most_recent_options.abs_path_to_maps) { + options.defaultPath = window.$$$_most_recent_options.abs_path_to_maps; + } - window.$$$superpaste = () => { - const hoverTile = getCurrentHoverTile(); - if (hoverTile === null) { - console.error('attempted to paste when hovertile was null. wtf.'); - return; - } - const map = window.$$$currentMap; - const tX = hoverTile[0]; - const tY = hoverTile[1]; + dialog.showOpenDialog(options, loadByFilename); + }; - superPaste(map, tX, tY); - } + window.$$$superpaste = () => { + const hoverTile = getCurrentHoverTile(); + if (hoverTile === null) { + console.error('attempted to paste when hovertile was null. wtf.'); + return; + } + const map = window.$$$currentMap; + const tX = hoverTile[0]; + const tY = hoverTile[1]; - window.$$$supercut = function() { - const map = window.$$$currentMap; + superPaste(map, tX, tY); + }; - if( getSelectedLayer() === null ) { - alert("Supercut: Please select a layer first."); - return; - } + window.$$$supercut = function() { + const map = window.$$$currentMap; - if (!map.selection.tiles || !map.selection.tiles.length) { - alert("Supercut: Please mark a selection on a layer first (hotkey 'm')."); - return; - } + if (getSelectedLayer() === null) { + alert('Supercut: Please select a layer first.'); + return; + } - const title = 'Supercut Setup'; + if (!map.selection.tiles || !map.selection.tiles.length) { + alert("Supercut: Please mark a selection on a layer first (hotkey 'm')."); + return; + } + + const title = 'Supercut Setup'; - let $template = ` -

    Selection: (${map.selection.hull.x},${map.selection.hull.y}) through (${map.selection.hull.w-1},${map.selection.hull.h-1})

    -

    ${map.selection.hull.w-1-map.selection.hull.x}x${map.selection.hull.h-1-map.selection.hull.y}, ${(map.selection.hull.w-1-map.selection.hull.x)*(map.selection.hull.h-1-map.selection.hull.y)} tiles

    + let $template = ` +

    Selection: (${map.selection.hull.x},${map.selection.hull.y}) through (${map.selection.hull + .w - 1},${map.selection.hull.h - 1})

    +

    ${map.selection.hull.w - 1 - map.selection.hull.x}x${map.selection.hull.h - + 1 - + map.selection.hull.y}, ${(map.selection.hull.w - 1 - map.selection.hull.x) * + (map.selection.hull.h - 1 - map.selection.hull.y)} tiles

    Select layers to supercut from:

    Zones
    @@ -954,170 +994,168 @@ export function setupWindowFunctions() {
    `; - let layer = null; - for (let i = 0; i < map.layers.length; i++) { - layer = map.layers[i]; - $template += ` + let layer = null; + for (let i = 0; i < map.layers.length; i++) { + layer = map.layers[i]; + $template += ` ${layer.name}
    `; - } - - // debugger; - // window.$$$currentMap; - - $('#modal-dialog').html(''); - $('#modal-dialog').append($template); - - $('#modal-dialog').show(); - - const dialog = $('#modal-dialog').dialog({ - width: 500, - modal: true, - title, - buttons: { - 'Cut': () => { - const layers = []; - $(".supercut-layers:checked").each(function() { - const me = $(this); - layers.push($(me[0]).data("layer-id")); - }); - setSuperCutPasteLayers(layers); - superCut(window.$$$currentMap); - $('#modal-dialog').dialog( "close" ); - }, - 'Cancel': function () { - $('#modal-dialog').dialog( "close" ); } - }, - close () { + + // debugger; + // window.$$$currentMap; + $('#modal-dialog').html(''); - } - }); - } + $('#modal-dialog').append($template); + + $('#modal-dialog').show(); + + const dialog = $('#modal-dialog').dialog({ + width: 500, + modal: true, + title, + buttons: { + Cut: () => { + const layers = []; + $('.supercut-layers:checked').each(function() { + const me = $(this); + layers.push($(me[0]).data('layer-id')); + }); + setSuperCutPasteLayers(layers); + superCut(window.$$$currentMap); + $('#modal-dialog').dialog('close'); + }, + Cancel: function() { + $('#modal-dialog').dialog('close'); + } + }, + close() { + $('#modal-dialog').html(''); + } + }); + }; - window.$$$openRecent = function() { - const path = require('path'); - - const maps = window.$$$_most_recent_options.recent_maps; + window.$$$openRecent = function() { + const path = require('path'); - let $template = ''; - for (var i = 0; i < maps.length; i++) { - $template += ` + const maps = window.$$$_most_recent_options.recent_maps; + + let $template = ''; + for (var i = 0; i < maps.length; i++) { + $template += `
    `; - } + } - const title = 'Open recent map'; + const title = 'Open recent map'; - $('#modal-dialog').html(''); - $('#modal-dialog').append($template); + $('#modal-dialog').html(''); + $('#modal-dialog').append($template); - for (var i = 0; i < maps.length; i++) { - const {basePath} = maps[i]; - const file = maps[i].map; + for (var i = 0; i < maps.length; i++) { + const { basePath } = maps[i]; + const file = maps[i].map; - $(`#recent-${i}`).on('click', (evt) => { - $('#modal-dialog').dialog( "close" ); - loadByFilename(path.join(basePath, file)); - }); - } + $(`#recent-${i}`).on('click', evt => { + $('#modal-dialog').dialog('close'); + loadByFilename(path.join(basePath, file)); + }); + } - $('#modal-dialog').show(); + $('#modal-dialog').show(); - const dialog = $('#modal-dialog').dialog({ - width: 500, - modal: true, - title, - buttons: { - 'Cancel': function () { - $('#modal-dialog').dialog( "close" ); - } - }, - close () { - $('#modal-dialog').html(''); - } - }); - } - - window.$$$saveAs = function ( isNewMap ) { - dialog.showSaveDialog( - {filters: [{ name: 'text', extensions: ['map.json'] }]}, - (filename) => { - if (filename) { - window.$$$save(filename, true, isNewMap); - } - } - ); - }; + const dialog = $('#modal-dialog').dialog({ + width: 500, + modal: true, + title, + buttons: { + Cancel: function() { + $('#modal-dialog').dialog('close'); + } + }, + close() { + $('#modal-dialog').html(''); + } + }); + }; - window.$$$hidePallete = (pal) => { - window.$$$toggle_pallete(pal, false, true); - } + window.$$$saveAs = function(isNewMap) { + dialog.showSaveDialog( + { filters: [{ name: 'text', extensions: ['map.json'] }] }, + filename => { + if (filename) { + window.$$$save(filename, true, isNewMap); + } + } + ); + }; - window.$$$showPallete = (pal) => { - window.$$$toggle_pallete(pal, true); - } + window.$$$hidePallete = pal => { + window.$$$toggle_pallete(pal, false, true); + }; - /** You are not ready */ - window.$$$toggle_pallete = (pal, forceShow, forceHide) => { - if (pal.msg) { - pal = pal.msg; - } + window.$$$showPallete = pal => { + window.$$$toggle_pallete(pal, true); + }; - let node_selector = ''; - let node = `${pal }-palette`; + /** You are not ready */ + window.$$$toggle_pallete = (pal, forceShow, forceHide) => { + if (pal.msg) { + pal = pal.msg; + } - if (window.$$$palette_registry.indexOf(node) >= 0) { - node_selector = `.${ node}`; - node = $(node_selector); + let node_selector = ''; + let node = `${pal}-palette`; - if (!node.length) { - throw new Error(`Invalid palette node selector: '${ node_selector }'`); - } - } else { - throw new Error(`Invalid palette name: '${ pal }'`); - } - - if(forceHide) { - node.hide(); + if (window.$$$palette_registry.indexOf(node) >= 0) { + node_selector = `.${node}`; + node = $(node_selector); - Palettes.savePalettePositions(); - return; - } + if (!node.length) { + throw new Error(`Invalid palette node selector: '${node_selector}'`); + } + } else { + throw new Error(`Invalid palette name: '${pal}'`); + } - if(forceShow) { - node.show(); + if (forceHide) { + node.hide(); - if (node_selector === '.layers-palette') { - visibilityFix(); - } + Palettes.savePalettePositions(); + return; + } - Palettes.savePalettePositions(); + if (forceShow) { + node.show(); - return; - } + if (node_selector === '.layers-palette') { + visibilityFix(); + } + Palettes.savePalettePositions(); - if (node.is(':visible')) { - node.hide(); - } else { - node.show(); + return; + } - if (node_selector === '.layers-palette') { - visibilityFix(); - } - } + if (node.is(':visible')) { + node.hide(); + } else { + node.show(); - Palettes.savePalettePositions(); - }; + if (node_selector === '.layers-palette') { + visibilityFix(); + } + } - window.appPath = path.dirname(require('electron').remote.app.getAppPath()); -}; + Palettes.savePalettePositions(); + }; -const SaveNewMap = () => { - const wid = parseInt($('#newmap-width').val(),10); - const hig = parseInt($('#newmap-height').val(),10); + window.appPath = path.dirname(require('electron').remote.app.getAppPath()); +} +const SaveNewMap = () => { + const wid = parseInt($('#newmap-width').val(), 10); + const hig = parseInt($('#newmap-height').val(), 10); debugger; @@ -1126,296 +1164,334 @@ const SaveNewMap = () => { //doMapCreationStuff(wid, hig); //window.$$$saveAs(true); -} +}; export const weNeedToReferenceATilesetImage = () => { - return window.newVspData && window.newVspData.source_image && window.newVspData.source_image.existingImageFilename && !window.newVspData.source_image.newImageCopyFilename;q -} + return ( + window.newVspData && + window.newVspData.source_image && + window.newVspData.source_image.existingImageFilename && + !window.newVspData.source_image.newImageCopyFilename + ); + q; +}; export const weNeedToCopyATilesetImage = () => { - return window.newVspData && window.newVspData.source_image && window.newVspData.source_image.existingImageFilename && window.newVspData.source_image.newImageCopyFilename; -} - -export const weAreReferencingATileset = (testUnsetText) => { - if(!testUnsetText) { - testUnsetText = ""; - } - - return window.newVspData && typeof window.newVspData.source_image == "string" && window.newVspData.source_image != testUnsetText; -} - -export const weAreGoingToMakeAnImageOMG = () => { - const d = window.newVspData; - const si = d.source_image; - return d.tilesize.width > 0 && d.tilesize.height > 0 && d.tiles_per_row > 0 && si.existingImageFilename === null && si.newImageCopyFilename === true && typeof si.imgName == "string" && typeof si.vspName == "string"; -} + return ( + window.newVspData && + window.newVspData.source_image && + window.newVspData.source_image.existingImageFilename && + window.newVspData.source_image.newImageCopyFilename + ); +}; -export const doTilesetCreationStuff = () => { - const i = 4; - debugger; +export const weAreReferencingATileset = testUnsetText => { + if (!testUnsetText) { + testUnsetText = ''; + } - if(weNeedToCopyATilesetImage()) { - const jp = jetpack.cwd(APPDATA_DIR); - jp.copy( - window.newVspData.source_image.existingImageFilename, // from - window.newVspData.source_image.newImageCopyFilename, // to - { overwrite: true } - ); - const fullPathToVSP = window.newVspData.source_image.vspName; - window.newMapData.default_vspfile = path.join( - path.relative( - path.dirname(window.newMapFilename), - path.dirname(window.newVspData.source_image.vspName) - ), - path.basename(window.newVspData.source_image.vspName) - ); - - window.newVspData.source_image = path.join( - path.relative( - path.dirname(fullPathToVSP), - path.dirname(window.newVspData.source_image.newImageCopyFilename) - ), - path.basename(window.newVspData.source_image.newImageCopyFilename) - ); - - jetpack.write(fullPathToVSP, window.newVspData); - - } else if(weNeedToReferenceATilesetImage()) { - const fullPathToVSP = window.newVspData.source_image.vspName; - - window.newMapData.default_vspfile = path.join( - path.relative( - path.dirname(window.newMapFilename), - path.dirname(window.newVspData.source_image.vspName) - ), - path.basename(window.newVspData.source_image.vspName) + return ( + window.newVspData && + typeof window.newVspData.source_image == 'string' && + window.newVspData.source_image != testUnsetText ); +}; - window.newVspData.source_image = path.join( - path.relative( - path.dirname(fullPathToVSP), - path.dirname(window.newVspData.source_image.existingImageFilename) - ), - path.basename(window.newVspData.source_image.existingImageFilename) +export const weAreGoingToMakeAnImageOMG = () => { + const d = window.newVspData; + const si = d.source_image; + return ( + d.tilesize.width > 0 && + d.tilesize.height > 0 && + d.tiles_per_row > 0 && + si.existingImageFilename === null && + si.newImageCopyFilename === true && + typeof si.imgName == 'string' && + typeof si.vspName == 'string' ); +}; - jetpack.write(fullPathToVSP, window.newVspData); - } else if(weAreReferencingATileset()) { - window.newMapData.default_vspfile = path.join( - path.relative( - path.dirname(window.newMapFilename), - path.dirname(window.newMapData.default_vspfile) - ), - path.basename(window.newMapData.default_vspfile) - ); - } else if(weAreGoingToMakeAnImageOMG()) { +export const doTilesetCreationStuff = () => { + const i = 4; + debugger; - } else { - throw "doTilesetCreationStuff for New Map FTUX has apparently fallen through to a state before thought to be impossible! OH NO!"; - } + if (weNeedToCopyATilesetImage()) { + const jp = jetpack.cwd(APPDATA_DIR); + jp.copy( + window.newVspData.source_image.existingImageFilename, // from + window.newVspData.source_image.newImageCopyFilename, // to + { overwrite: true } + ); + const fullPathToVSP = window.newVspData.source_image.vspName; + window.newMapData.default_vspfile = path.join( + path.relative( + path.dirname(window.newMapFilename), + path.dirname(window.newVspData.source_image.vspName) + ), + path.basename(window.newVspData.source_image.vspName) + ); + + window.newVspData.source_image = path.join( + path.relative( + path.dirname(fullPathToVSP), + path.dirname(window.newVspData.source_image.newImageCopyFilename) + ), + path.basename(window.newVspData.source_image.newImageCopyFilename) + ); + + jetpack.write(fullPathToVSP, window.newVspData); + } else if (weNeedToReferenceATilesetImage()) { + const fullPathToVSP = window.newVspData.source_image.vspName; + + window.newMapData.default_vspfile = path.join( + path.relative( + path.dirname(window.newMapFilename), + path.dirname(window.newVspData.source_image.vspName) + ), + path.basename(window.newVspData.source_image.vspName) + ); + + window.newVspData.source_image = path.join( + path.relative( + path.dirname(fullPathToVSP), + path.dirname(window.newVspData.source_image.existingImageFilename) + ), + path.basename(window.newVspData.source_image.existingImageFilename) + ); + + jetpack.write(fullPathToVSP, window.newVspData); + } else if (weAreReferencingATileset()) { + window.newMapData.default_vspfile = path.join( + path.relative( + path.dirname(window.newMapFilename), + path.dirname(window.newMapData.default_vspfile) + ), + path.basename(window.newMapData.default_vspfile) + ); + } else if (weAreGoingToMakeAnImageOMG()) { + } else { + throw 'doTilesetCreationStuff for New Map FTUX has apparently fallen through to a state before thought to be impossible! OH NO!'; + } }; export const doObsCreationStuff = () => { - const i = 4; - debugger; + const i = 4; + debugger; }; export function doMapCreationStuff(wid, hig) { - debugger; - - window.$$$currentMap = { - layers: [] - }; - - // "legacy_obstruction_data" - window.$$$currentMap.layers.length = 1; - window.$$$currentMap.layers[0] = { - "name": "New Layer", - "parallax": { "X": 1, "Y": 1 }, - "dimensions": { "X": wid, "Y": hig }, - "alpha": 1, - "vsp": "default" - }; - - const oneLayerSize = wid * hig; - window.$$$currentMap.zoneData = Array(oneLayerSize); - window.$$$currentMap.legacyObsData = Array.apply(null, Array(oneLayerSize)).map(Number.prototype.valueOf, 0); - const blankLayerData = Array.apply(null, Array(oneLayerSize)).map(Number.prototype.valueOf, 0); - window.$$$currentMap.mapRawTileData = { - tile_data: [blankLayerData], - legacy_obstruction_data: window.$$$currentMap.legacyObsData, - zone_data: [] - }; - - window.$$$currentMap.entities = {}; - window.$$$currentMap.entityData = {}; - window.$$$currentMap.entityTextures = {}; - window.$$$currentMap.mapData = { - "notes": [], - "name": "", - "vsp": { - "default": path.basename(window.newMapData.default_vspfile), - "obstructions": path.basename(window.newMapData.obs_vspfile) - }, - "music": "", - "renderstring": "1,E,R", - "initscript": "start", - "starting_coordinates": [0, 0], - "layers": [{ - "name": "New Layer", - "parallax": { - "X": 1, - "Y": 1 - }, - "dimensions": { - "X": wid, - "Y": hig - }, - "alpha": 1, - "vsp": "default" - }], - "zones": [{ - "name": "NULL_ZONE", - "activation_script": "", - "activation_chance": 0, - "can_by_adjacent_activated": false - }], - "entities": [], - "tallentitylayer": "New Layer", - "MAPED_ENTLAYER_VISIBLE": true, - "MAPED_ZONELAYER_VISIBLE": true, - "MAPED_OBSLAYER_VISIBLE": true - }; + debugger; + + window.$$$currentMap = { + layers: [] + }; + + // "legacy_obstruction_data" + window.$$$currentMap.layers.length = 1; + window.$$$currentMap.layers[0] = { + name: 'New Layer', + parallax: { X: 1, Y: 1 }, + dimensions: { X: wid, Y: hig }, + alpha: 1, + vsp: 'default' + }; + + const oneLayerSize = wid * hig; + window.$$$currentMap.zoneData = Array(oneLayerSize); + window.$$$currentMap.legacyObsData = Array.apply(null, Array(oneLayerSize)).map( + Number.prototype.valueOf, + 0 + ); + const blankLayerData = Array.apply(null, Array(oneLayerSize)).map(Number.prototype.valueOf, 0); + window.$$$currentMap.mapRawTileData = { + tile_data: [blankLayerData], + legacy_obstruction_data: window.$$$currentMap.legacyObsData, + zone_data: [] + }; + + window.$$$currentMap.entities = {}; + window.$$$currentMap.entityData = {}; + window.$$$currentMap.entityTextures = {}; + window.$$$currentMap.mapData = { + notes: [], + name: '', + vsp: { + default: path.basename(window.newMapData.default_vspfile), + obstructions: path.basename(window.newMapData.obs_vspfile) + }, + music: '', + renderstring: '1,E,R', + initscript: 'start', + starting_coordinates: [0, 0], + layers: [ + { + name: 'New Layer', + parallax: { + X: 1, + Y: 1 + }, + dimensions: { + X: wid, + Y: hig + }, + alpha: 1, + vsp: 'default' + } + ], + zones: [ + { + name: 'NULL_ZONE', + activation_script: '', + activation_chance: 0, + can_by_adjacent_activated: false + } + ], + entities: [], + tallentitylayer: 'New Layer', + MAPED_ENTLAYER_VISIBLE: true, + MAPED_ZONELAYER_VISIBLE: true, + MAPED_OBSLAYER_VISIBLE: true + }; } function loadByFilename(fileNames, andThenFn) { - if (fileNames === undefined) { - return; - } + if (fileNames === undefined) { + return; + } - const fileName = Array.isArray(fileNames) ? fileNames[0] : fileNames; - - const dataName = fileName.replace('.map.json', '.map.data.json'); - // const vspName = fileName.replace('.map.json', '.vsp.json'); + const fileName = Array.isArray(fileNames) ? fileNames[0] : fileNames; - saveMostRecentMapLocation(fileName); + const dataName = fileName.replace('.map.json', '.map.data.json'); + // const vspName = fileName.replace('.map.json', '.vsp.json'); - // TODO: verify that all three of these files, you know... exist? - bootstrapMap(fileName, dataName, andThenFn); -}; + saveMostRecentMapLocation(fileName); + + // TODO: verify that all three of these files, you know... exist? + bootstrapMap(fileName, dataName, andThenFn); +} function saveMostRecentMapLocation(filename) { - - const jp = jetpack.cwd(APPDATA_DIR); - const appConfigPath = BREADPATH.getMostRecentFilesJSONPath(); + const jp = jetpack.cwd(APPDATA_DIR); + const appConfigPath = BREADPATH.getMostRecentFilesJSONPath(); - let appConfigData = jp.read(appConfigPath, 'json'); - if( !appConfigData ) { - appConfigData = {}; - } + let appConfigData = jp.read(appConfigPath, 'json'); + if (!appConfigData) { + appConfigData = {}; + } - appConfigData.abs_path_to_maps = path.dirname(filename); - appConfigData.most_recent_map = path.basename(filename); + appConfigData.abs_path_to_maps = path.dirname(filename); + appConfigData.most_recent_map = path.basename(filename); - if(!appConfigData.recent_maps) { - appConfigData.recent_maps = []; - } + if (!appConfigData.recent_maps) { + appConfigData.recent_maps = []; + } - appConfigData.recent_maps.unshift({ - basePath: appConfigData.abs_path_to_maps, - map: appConfigData.most_recent_map - }); + appConfigData.recent_maps.unshift({ + basePath: appConfigData.abs_path_to_maps, + map: appConfigData.most_recent_map + }); - appConfigData.recent_maps = dedupeRecentMaps(appConfigData.recent_maps); + appConfigData.recent_maps = dedupeRecentMaps(appConfigData.recent_maps); - window.$$$_most_recent_options = appConfigData; + window.$$$_most_recent_options = appConfigData; - jp.write(appConfigPath, appConfigData); -}; + jp.write(appConfigPath, appConfigData); +} const MAX_RECENT_MAPS = 10; function dedupeRecentMaps(mapQueue) { - const hitList = {}; - const newQueue = []; - - for (let i = 0; i < mapQueue.length; i++) { - const key = mapQueue[i].basePath + mapQueue[i].map; - if(!hitList[key]) { - newQueue.push(mapQueue[i]); - hitList[key] = true; - } - - if(newQueue.length >= MAX_RECENT_MAPS) { - return newQueue; + const hitList = {}; + const newQueue = []; + + for (let i = 0; i < mapQueue.length; i++) { + const key = mapQueue[i].basePath + mapQueue[i].map; + if (!hitList[key]) { + newQueue.push(mapQueue[i]); + hitList[key] = true; + } + + if (newQueue.length >= MAX_RECENT_MAPS) { + return newQueue; + } } - } - return newQueue; + return newQueue; } export function bootstrapMap(mapFile, tiledataFile, andThen) { - - const errorHandler = (e) => { - console.error(e); - }; - - verifyTileData(tiledataFile) - .then(() => { - LOG('verify map?'); - verifyMap(mapFile) - .then(() => { - LOG('create map?'); - - new Map( - mapFile, tiledataFile, (map) => { updateLocationFunction(map); updateScreenview(map); } - ).ready().then( (m) => { - LOG('Done loading map...'); - const currentMap = m; - m.setCanvas($('.map_canvas')); - - window.$$$currentMap = currentMap; - - for (let i = m.mapData.entities.length - 1; i >= 0; i--) { - if (!m.mapData.entities[i].animation) { - // TODO this is very bad - window.alert(`Theres an entity ${ i } with unset animation; ALERT GRUE wtf`); - // mapData.entities[0].filename - m.mapData.entities[i].animation = 'Idle Down'; // TOD no no no - } - } - - if (typeof window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE === 'undefined') { - window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE = true; - } - - if (typeof window.$$$currentMap.mapData.MAPED_ZONELAYER_VISIBLE === 'undefined') { - window.$$$currentMap.mapData.MAPED_ZONELAYER_VISIBLE = true; - } - - if (typeof window.$$$currentMap.mapData.MAPED_OBSLAYER_VISIBLE === 'undefined') { - window.$$$currentMap.mapData.MAPED_OBSLAYER_VISIBLE = true; - } - - LayersWidget.initLayersWidget(currentMap); - initInfoWidget(currentMap); - initScreen(currentMap); - ZonesWidget.initZonesWidget(currentMap); - EntitiesWidget.initEntitiesWidget(currentMap); - - initTools($('.map_canvas'), window.$$$currentMap); - - updateRstringInfo(); - - // mostly for creating new maps. FOR NOW. - if(andThen) { - andThen(); - } - - // TODO do we need to do this at all? - // window.$$$hide_all_windows(); - }).catch( (e) => {LOG(e); throw e;} ) - }) - }) -}; + const errorHandler = e => { + console.error(e); + }; + verifyTileData(tiledataFile).then(() => { + LOG('verify map?'); + verifyMap(mapFile).then(() => { + LOG('create map?'); + + new Map(mapFile, tiledataFile, map => { + updateLocationFunction(map); + updateScreenview(map); + }) + .ready() + .then(m => { + LOG('Done loading map...'); + const currentMap = m; + m.setCanvas($('.map_canvas')); + + window.$$$currentMap = currentMap; + + for (let i = m.mapData.entities.length - 1; i >= 0; i--) { + if (!m.mapData.entities[i].animation) { + // TODO this is very bad + window.alert( + `Theres an entity ${i} with unset animation; ALERT GRUE wtf` + ); + // mapData.entities[0].filename + m.mapData.entities[i].animation = 'Idle Down'; // TOD no no no + } + } + + if ( + typeof window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE === 'undefined' + ) { + window.$$$currentMap.mapData.MAPED_ENTLAYER_VISIBLE = true; + } + + if ( + typeof window.$$$currentMap.mapData.MAPED_ZONELAYER_VISIBLE === 'undefined' + ) { + window.$$$currentMap.mapData.MAPED_ZONELAYER_VISIBLE = true; + } + + if ( + typeof window.$$$currentMap.mapData.MAPED_OBSLAYER_VISIBLE === 'undefined' + ) { + window.$$$currentMap.mapData.MAPED_OBSLAYER_VISIBLE = true; + } + + LayersWidget.initLayersWidget(currentMap); + initInfoWidget(currentMap); + initScreen(currentMap); + ZonesWidget.initZonesWidget(currentMap); + EntitiesWidget.initEntitiesWidget(currentMap); + + initTools($('.map_canvas'), window.$$$currentMap); + + updateRstringInfo(); + + // mostly for creating new maps. FOR NOW. + if (andThen) { + andThen(); + } + + // TODO do we need to do this at all? + // window.$$$hide_all_windows(); + }) + .catch(e => { + LOG(e); + throw e; + }); + }); + }); +} diff --git a/src/main/main.ts b/src/main/main.ts index d2f5740..954c17b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -11,9 +11,9 @@ import { prodMenuTemplate } from '../menu/prod_menu_template'; let win: BrowserWindow | null; const setApplicationMenu = () => { - const menus:MenuItemConstructorOptions[] = prodMenuTemplate as MenuItemConstructorOptions[]; + const menus: MenuItemConstructorOptions[] = prodMenuTemplate as MenuItemConstructorOptions[]; // if (process.env.NODE_ENV !== 'production') { - menus.push(devMenuTemplate); + menus.push(devMenuTemplate); // } Menu.setApplicationMenu(Menu.buildFromTemplate(menus)); }; @@ -35,8 +35,8 @@ const createWindow = async () => { await installExtensions(); } - win = new BrowserWindow({ - width: 1000, + win = new BrowserWindow({ + width: 1000, height: 600, webPreferences: { webSecurity: false, @@ -129,4 +129,4 @@ app.on('ready', function () { app.on('window-all-closed', function () { app.quit(); }); -*/ \ No newline at end of file +*/ diff --git a/webpack.main.config.js b/webpack.main.config.js index 196ae93..6817e40 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -20,14 +20,12 @@ module.exports = merge.smart(baseConfig, { cacheDirectory: true, babelrc: false, presets: [ - [ - '@babel/preset-env', - { targets: 'maintained node versions' } - ], + ['@babel/preset-env', { targets: 'maintained node versions' }], '@babel/preset-typescript' ], plugins: [ - ['@babel/plugin-proposal-class-properties', { loose: true }] + ['@babel/plugin-proposal-class-properties', { loose: true }], + ['@babel/plugin-transform-runtime'] ] } } From dd19e70ea299a69f98237bf1297ebf8acdf8087f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Jul 2022 01:30:42 +0000 Subject: [PATCH 2/2] Bump terser from 4.8.0 to 4.8.1 Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/commits) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index db603d0..d97ab3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Breaditor", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -8445,7 +8445,8 @@ "version": "2.1.1", "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -8494,7 +8495,8 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -8507,7 +8509,8 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -8638,7 +8641,8 @@ "version": "2.0.4", "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.8", @@ -8652,6 +8656,7 @@ "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -8678,6 +8683,7 @@ "resolved": false, "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -8698,6 +8704,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -8796,7 +8803,8 @@ "version": "1.0.1", "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -8810,6 +8818,7 @@ "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -8905,7 +8914,8 @@ "version": "5.1.2", "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -8947,6 +8957,7 @@ "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8968,6 +8979,7 @@ "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -9016,13 +9028,15 @@ "version": "1.0.2", "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "resolved": false, "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "optional": true } } }, @@ -16676,9 +16690,9 @@ "dev": true }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "requires": { "commander": "^2.20.0",