diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..b49351dd1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +node_modules +3rdparty +app/data/typedefs \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 879db276a..a3c6afbb4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,11 +1,12 @@ { + "root": true, "env": { "browser": true, "commonjs": true, "es6": true, "node": true }, - "plugins": ["pug"], + "plugins": ["pug", "@typescript-eslint"], "globals": { "alertify": true, "dragonBones": true, @@ -16,11 +17,17 @@ "riot": true, "soundbox": true }, + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2018 }, - "extends": "eslint:recommended", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], "rules": { + "@typescript-eslint/no-var-requires": "off", "accessor-pairs": "error", "array-bracket-spacing": ["error", "never"], "array-callback-return": "error", diff --git a/app/data/ct.release/camera.js b/app/data/ct.release/camera.js index 490cd63af..32343368b 100644 --- a/app/data/ct.release/camera.js +++ b/app/data/ct.release/camera.js @@ -57,6 +57,7 @@ * @property {number} shakeMax The maximum possible value for the `shake` property * to protect players from losing their monitor, in `shake` units. Default is 10. */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars class Camera extends PIXI.DisplayObject { constructor(x, y, w, h) { super(); diff --git a/app/data/i18n/English.json b/app/data/i18n/English.json index 171f05f9b..ee629b8e7 100644 --- a/app/data/i18n/English.json +++ b/app/data/i18n/English.json @@ -126,9 +126,11 @@ "forgetProject": "Forget this project", "browse": "Browse", "latest": "Latest projects", + "examples": "Examples", "unableToWriteToFolders": "Ct.js could not find an appropriate place for projects! Make sure you store ct.js app inside a folder you have access to write to.", "twitter": "Twitter channel", - "discord": "Discord community" + "discord": "Discord community", + "createOrBrowseJunction": "or" }, "licensepanel": { "ctjslicense": "Ct.js License (MIT)" diff --git a/package-lock.json b/package-lock.json index 4c32417ee..89bcbb3a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -142,10 +142,23 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" + }, "@types/node": { - "version": "14.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz", - "integrity": "sha512-jVFzDV6NTbrLMxm4xDSIW/gKnk8rQLF9wAzLWIOg+5nU6ACrIMndeBdXci0FGtqJbP9tQvm6V39eshc96TO2wQ==" + "version": "14.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", + "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==" + }, + "@types/nw.js": { + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/@types/nw.js/-/nw.js-0.13.10.tgz", + "integrity": "sha512-VQ37i4jBL0fU+LJr5z23okMeSLntJvGK4havz87l3Zetr8Aa/sWqoLZVAIpch5WofbaDjWeM7zIwl3n3mEjUJw==", + "requires": { + "@types/node": "*" + } }, "@types/unist": { "version": "2.0.3", @@ -153,6 +166,172 @@ "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.1.tgz", + "integrity": "sha512-O+8Utz8pb4OmcA+Nfi5THQnQpHSD2sDUNw9AxNHpuYOo326HZTtG8gsfT+EAYuVrFNaLyNb2QnUNkmTRDskuRA==", + "requires": { + "@typescript-eslint/experimental-utils": "4.4.1", + "@typescript-eslint/scope-manager": "4.4.1", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.1.tgz", + "integrity": "sha512-Nt4EVlb1mqExW9cWhpV6pd1a3DkUbX9DeyYsdoeziKOpIJ04S2KMVDO+SEidsXRH/XHDpbzXykKcMTLdTXH6cQ==", + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.4.1", + "@typescript-eslint/types": "4.4.1", + "@typescript-eslint/typescript-estree": "4.4.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.4.1.tgz", + "integrity": "sha512-S0fuX5lDku28Au9REYUsV+hdJpW/rNW0gWlc4SXzF/kdrRaAVX9YCxKpziH7djeWT/HFAjLZcnY7NJD8xTeUEg==", + "requires": { + "@typescript-eslint/scope-manager": "4.4.1", + "@typescript-eslint/types": "4.4.1", + "@typescript-eslint/typescript-estree": "4.4.1", + "debug": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.4.1.tgz", + "integrity": "sha512-2oD/ZqD4Gj41UdFeWZxegH3cVEEH/Z6Bhr/XvwTtGv66737XkR4C9IqEkebCuqArqBJQSj4AgNHHiN1okzD/wQ==", + "requires": { + "@typescript-eslint/types": "4.4.1", + "@typescript-eslint/visitor-keys": "4.4.1" + } + }, + "@typescript-eslint/types": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.4.1.tgz", + "integrity": "sha512-KNDfH2bCyax5db+KKIZT4rfA8rEk5N0EJ8P0T5AJjo5xrV26UAzaiqoJCxeaibqc0c/IvZxp7v2g3difn2Pn3w==" + }, + "@typescript-eslint/typescript-estree": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.1.tgz", + "integrity": "sha512-wP/V7ScKzgSdtcY1a0pZYBoCxrCstLrgRQ2O9MmCUZDtmgxCO/TCqOTGRVwpP4/2hVfqMz/Vw1ZYrG8cVxvN3g==", + "requires": { + "@typescript-eslint/types": "4.4.1", + "@typescript-eslint/visitor-keys": "4.4.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.1.tgz", + "integrity": "sha512-H2JMWhLaJNeaylSnMSQFEhT/S/FsJbebQALmoJxMPMxLtlVAMy2uJP/Z543n9IizhjRayLSqoInehCeNW9rWcw==", + "requires": { + "@typescript-eslint/types": "4.4.1", + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + } + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -9780,6 +9959,14 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "requires": { + "tslib": "^1.8.1" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/package.json b/package.json index ed1ffba23..8801706d8 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,10 @@ }, "license": "MIT", "dependencies": { - "@types/node": "^14.11.5", + "@types/node": "^14.11.8", + "@types/nw.js": "^0.13.10", + "@typescript-eslint/eslint-plugin": "^4.4.1", + "@typescript-eslint/parser": "^4.4.1", "filemode": "^3.0.0", "fs-extra": "^9.0.1", "globby": "^11.0.1", diff --git a/src/examples/DungeonCrawler_tutorial/img/r42846504b06f.png b/src/examples/DungeonCrawler_tutorial/img/r42846504b06f.png index e2323efc9..8ba1929fc 100644 Binary files a/src/examples/DungeonCrawler_tutorial/img/r42846504b06f.png and b/src/examples/DungeonCrawler_tutorial/img/r42846504b06f.png differ diff --git a/src/examples/DungeonCrawler_tutorial/img/splash.png b/src/examples/DungeonCrawler_tutorial/img/splash.png index d3016fa11..8ba1929fc 100644 Binary files a/src/examples/DungeonCrawler_tutorial/img/splash.png and b/src/examples/DungeonCrawler_tutorial/img/splash.png differ diff --git a/src/examples/JettyCat.ict b/src/examples/JettyCat.ict index 2524962a0..b8830b15b 100644 --- a/src/examples/JettyCat.ict +++ b/src/examples/JettyCat.ict @@ -1,4 +1,4 @@ -ctjsVersion: 1.3.0 +ctjsVersion: 1.4.2 notes: /* empty */ libs: place: @@ -942,14 +942,17 @@ rooms: uid: 8f93611e-6e95-49c4-8e2b-4cc067be2924 tx: 0.65 ty: 0.65 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: c51bc37f-69c9-4eec-8c2b-332dab64a25a thumbnail: 332dab64a25a gridX: 64 gridY: 64 - lastmod: 1585703848844 + lastmod: 1602729483658 + extends: {} - name: MainMenu oncreate: '' onstep: '' @@ -971,17 +974,21 @@ rooms: - x: 540 'y': 384 uid: 6cd7876a-4918-47a7-8100-75f0375986ef + exts: {} - x: 540 'y': 960 uid: 25ac0f9b-57ff-461d-8eb7-a9ce800b9c71 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 8677472b-4549-48b5-a5a8-a891fb029f6b thumbnail: a891fb029f6b gridX: 108 gridY: 64 - lastmod: 1584496269570 + lastmod: 1602729490329 + extends: {} - name: UI_InGame oncreate: '' onstep: '' @@ -996,15 +1003,19 @@ rooms: uid: d4c02f18-93d0-4ad4-8e5b-62fb9a0f0af9 tx: 0.75 ty: 0.75 + exts: {} - x: 960 'y': 128 uid: 6a532c9b-7e32-4070-b72b-86012306c7fb + exts: {} - x: 512 'y': 960 uid: ba73f80b-0995-40b6-94d5-3e82712b5ecf + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: dd0ac376-10c7-4619-9593-9c2c4e48f46a thumbnail: 9c2c4e48f46a gridX: 64 @@ -1031,12 +1042,15 @@ rooms: - x: 540 'y': 1088 uid: 43938432-cf0b-416d-91e9-8bc9a1f8abcf + exts: {} - x: 540 'y': 576 uid: ee7454ca-ba35-4d79-9b78-83e763fd81f5 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 78d3dac5-253d-4792-a85d-7d775aefe864 thumbnail: 7d775aefe864 gridX: 540 @@ -1063,15 +1077,19 @@ rooms: - x: 540 'y': 384 uid: 92049024-c0ef-41ae-8512-851ce20cad3a + exts: {} - x: 540 'y': 1344 uid: 25ac0f9b-57ff-461d-8eb7-a9ce800b9c71 + exts: {} - x: 540 'y': 832 uid: 8748598b-4494-433f-9f18-fbe985c2a583 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 158a085c-c48c-4b57-8e64-e38a4cd0cc21 thumbnail: e38a4cd0cc21 gridX: 540 @@ -1252,14 +1270,6 @@ emitterTandems: previewTexture: 4e0a0e06-81ea-4cd2-8f3d-569a8ad3e947 starting: 0 settings: - minifyhtmlcss: false - minifyjs: false - fps: 60 - version: - - 1 - - 0 - - 0 - versionPostfix: '' export: windows64: true windows32: true @@ -1271,9 +1281,22 @@ settings: icon: eb24c2bc-a36c-4118-b33e-a7348c00e5bb accent: '#446adb' invertPreloaderScheme: true - title: JettyCat - site: 'https://ctjs.rocks/' - author: ComigoGames + rendering: + maxFPS: 60 + pixelatedrender: false + highDensity: true + usePixiLegacy: true + desktopMode: maximized + authoring: + title: JettyCat + author: ComigoGames + site: 'https://ctjs.rocks/' + version: + - 1 + - 0 + - 0 + versionPostfix: '' + fps: 30 scripts: [] fonts: [] startroom: 8677472b-4549-48b5-a5a8-a891fb029f6b diff --git a/src/examples/JettyCat/img/r332dab64a25a.png b/src/examples/JettyCat/img/r332dab64a25a.png index 0c26364bb..2e811ccda 100644 Binary files a/src/examples/JettyCat/img/r332dab64a25a.png and b/src/examples/JettyCat/img/r332dab64a25a.png differ diff --git a/src/examples/JettyCat/img/ra891fb029f6b.png b/src/examples/JettyCat/img/ra891fb029f6b.png index eb3e4538a..90eba4c72 100644 Binary files a/src/examples/JettyCat/img/ra891fb029f6b.png and b/src/examples/JettyCat/img/ra891fb029f6b.png differ diff --git a/src/examples/JettyCat/img/splash.png b/src/examples/JettyCat/img/splash.png index 6e33e64bb..90eba4c72 100644 Binary files a/src/examples/JettyCat/img/splash.png and b/src/examples/JettyCat/img/splash.png differ diff --git a/src/examples/MoveBlocks.ict b/src/examples/MoveBlocks.ict index 6897bb792..02bd70a8f 100644 --- a/src/examples/MoveBlocks.ict +++ b/src/examples/MoveBlocks.ict @@ -978,7 +978,7 @@ rooms: gridX: 64 gridY: 64 backgroundColor: '#461212' - lastmod: 1602214362314 + lastmod: 1602729638788 - name: PuzzleBlocks_Simple oncreate: '' onstep: '' diff --git a/src/examples/MoveBlocks/img/r62f14320e2c3.png b/src/examples/MoveBlocks/img/r62f14320e2c3.png index d7e78f3d4..339de67ce 100644 Binary files a/src/examples/MoveBlocks/img/r62f14320e2c3.png and b/src/examples/MoveBlocks/img/r62f14320e2c3.png differ diff --git a/src/examples/MoveBlocks/img/rb1dbec7a36a6.png b/src/examples/MoveBlocks/img/rb1dbec7a36a6.png index d7e78f3d4..8ffdfd4c4 100644 Binary files a/src/examples/MoveBlocks/img/rb1dbec7a36a6.png and b/src/examples/MoveBlocks/img/rb1dbec7a36a6.png differ diff --git a/src/examples/MoveBlocks/img/splash.png b/src/examples/MoveBlocks/img/splash.png index d7e78f3d4..339de67ce 100644 Binary files a/src/examples/MoveBlocks/img/splash.png and b/src/examples/MoveBlocks/img/splash.png differ diff --git a/src/examples/Platformer_tutorial/img/r1c4d6e821597.png b/src/examples/Platformer_tutorial/img/r1c4d6e821597.png index 1fab1ccc9..28b72de8f 100644 Binary files a/src/examples/Platformer_tutorial/img/r1c4d6e821597.png and b/src/examples/Platformer_tutorial/img/r1c4d6e821597.png differ diff --git a/src/examples/Platformer_tutorial/img/r9de251b14d06.png b/src/examples/Platformer_tutorial/img/r9de251b14d06.png index 1f5a4b951..70b583853 100644 Binary files a/src/examples/Platformer_tutorial/img/r9de251b14d06.png and b/src/examples/Platformer_tutorial/img/r9de251b14d06.png differ diff --git a/src/examples/Platformer_tutorial/img/splash.png b/src/examples/Platformer_tutorial/img/splash.png index 15f701497..70b583853 100644 Binary files a/src/examples/Platformer_tutorial/img/splash.png and b/src/examples/Platformer_tutorial/img/splash.png differ diff --git a/src/examples/SpaceShooter_tutorial/img/r1.png b/src/examples/SpaceShooter_tutorial/img/r1.png index 677ba70e7..cb8fa0b00 100644 Binary files a/src/examples/SpaceShooter_tutorial/img/r1.png and b/src/examples/SpaceShooter_tutorial/img/r1.png differ diff --git a/src/examples/SpaceShooter_tutorial/img/splash.png b/src/examples/SpaceShooter_tutorial/img/splash.png index 677ba70e7..cb8fa0b00 100644 Binary files a/src/examples/SpaceShooter_tutorial/img/splash.png and b/src/examples/SpaceShooter_tutorial/img/splash.png differ diff --git a/src/examples/catformer/img/r1.png b/src/examples/catformer/img/r1.png index d38b8ec01..03e864f66 100644 Binary files a/src/examples/catformer/img/r1.png and b/src/examples/catformer/img/r1.png differ diff --git a/src/examples/catformer/img/splash.png b/src/examples/catformer/img/splash.png index d38b8ec01..03e864f66 100644 Binary files a/src/examples/catformer/img/splash.png and b/src/examples/catformer/img/splash.png differ diff --git a/src/examples/catsteroids.ict b/src/examples/catsteroids.ict index 67d3fd50d..be5ca27e1 100644 --- a/src/examples/catsteroids.ict +++ b/src/examples/catsteroids.ict @@ -1371,7 +1371,7 @@ rooms: extends: movementY: 0.5 uid: 2e5bf702-9eac-4fef-8282-07d2dd0a9bac - lastmod: 1588761914721 + lastmod: 1602729541705 grid: 50 thumbnail: 1 gridX: 50 @@ -1379,10 +1379,13 @@ rooms: tiles: - depth: -10 tiles: [] + extends: {} copies: - x: 950 'y': 850 uid: 1fab434d-0976-4b65-8390-d013695aba8c + exts: {} + extends: {} - name: MainMenu oncreate: >- ct.sound.spawn('Music_MainMenu', { @@ -1426,20 +1429,24 @@ rooms: movementX: -0.5 uid: 6c75cdb8-cfb4-4dcc-887a-f76ae98b5499 grid: 64 - lastmod: 1588677352152 + lastmod: 1602729545401 thumbnail: 2 gridX: 64 gridY: 64 tiles: - depth: -10 tiles: [] + extends: {} copies: - x: 960 'y': 704 uid: 972bb4d9-7cfc-4dbe-bc30-883562271057 + exts: {} - x: 960 'y': 320 uid: 319c6995-59f3-4267-a1de-cf58f77614d3 + exts: {} + extends: {} - name: RetryScreen oncreate: >- this.score = Number(localStorage.score); @@ -1495,13 +1502,16 @@ rooms: tiles: - depth: -10 tiles: [] + extends: {} copies: - x: 960 'y': 832 uid: 73759c16-fba4-4134-b048-e53aa4d2f34b + exts: {} - x: 960 'y': 192 uid: a6d37145-b35c-42d2-95c6-765069857ada + exts: {} - name: Controls_Layer oncreate: '' onstep: '' @@ -1514,12 +1524,15 @@ rooms: - x: 1722 'y': 898 uid: b334b5ec-69b4-4c0d-bd50-709cf9bfa60d + exts: {} - x: 210 'y': 872 uid: c78818a4-c20e-46b9-8a39-9fbb5a83eabe + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 459c3f03-a31e-465a-a3fd-23d3934bc7d0 thumbnail: 23d3934bc7d0 gridX: 64 @@ -1592,7 +1605,7 @@ rooms: extends: movementY: 0.5 uid: 0716a171-8c7a-4112-bae8-85703255320d - lastmod: 1588676886528 + lastmod: 1602729535763 grid: 50 thumbnail: 85703255320d gridX: 50 @@ -1600,34 +1613,45 @@ rooms: tiles: - depth: -10 tiles: [] + extends: {} copies: - x: 950 'y': 850 uid: 1fab434d-0976-4b65-8390-d013695aba8c + exts: {} - x: 950 'y': -300 uid: 1ef4f56c-b0cc-497b-bd3f-e06eb1c2308d + exts: {} - x: 550 'y': 400 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 750 'y': 400 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 650 'y': 550 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 650 'y': 250 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 450 'y': 250 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 350 'y': 400 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} - x: 450 'y': 550 uid: bc01cee1-1b8b-4418-aeb9-a7c5eac2cd51 + exts: {} + extends: {} - name: UI_Layer oncreate: '' onstep: '' @@ -1640,9 +1664,11 @@ rooms: - x: 960 'y': 1080 uid: 1011221c-4f7b-45e7-b45a-ce886851d32c + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 3123a227-4b15-4b4e-83cd-bb45e24b4389 thumbnail: bb45e24b4389 gridX: 64 @@ -1721,27 +1747,18 @@ rooms: tiles: - depth: -10 tiles: [] + extends: {} copies: - x: 960 'y': 256 uid: ffbec9fc-299c-4aea-a4f1-1c4b27859fb6 + exts: {} soundtick: 9 roomtick: 3 typetick: 19 styletick: 2 starting: 0 settings: - minifyhtmlcss: true - minifyjs: false - title: Catsteroids - author: CoMiGo Games - site: 'http://comigogames.ru/' - fps: 30 - version: - - 0 - - 0 - - 0 - versionPostfix: '' export: windows64: true windows32: true @@ -1749,12 +1766,26 @@ settings: linux32: true mac64: true debug: false - pixelatedrender: false branding: icon: e1452137-8cfa-4eec-b54a-0f2660326b48 accent: '#446adb' invertPreloaderScheme: true - highDensity: true + rendering: + maxFPS: 60 + pixelatedrender: false + highDensity: true + usePixiLegacy: true + desktopMode: maximized + authoring: + title: Catsteroids + author: CoMiGo Games + site: 'http://comigogames.ru/' + version: + - 0 + - 0 + - 0 + versionPostfix: '' + fps: 30 palette: - '#FFFFFF' - '#10102E' @@ -1817,7 +1848,7 @@ scripts: }); }); }; -ctjsVersion: 1.3.0 +ctjsVersion: 1.4.2 fonts: [] skeletons: [] actions: diff --git a/src/examples/catsteroids/img/r1.png b/src/examples/catsteroids/img/r1.png index d09d0e366..4b4a8f60d 100644 Binary files a/src/examples/catsteroids/img/r1.png and b/src/examples/catsteroids/img/r1.png differ diff --git a/src/examples/catsteroids/img/r2.png b/src/examples/catsteroids/img/r2.png index 6ff711edf..c981211e5 100644 Binary files a/src/examples/catsteroids/img/r2.png and b/src/examples/catsteroids/img/r2.png differ diff --git a/src/examples/catsteroids/img/r85703255320d.png b/src/examples/catsteroids/img/r85703255320d.png index 7a1792bbf..1a075dc6c 100644 Binary files a/src/examples/catsteroids/img/r85703255320d.png and b/src/examples/catsteroids/img/r85703255320d.png differ diff --git a/src/examples/catsteroids/img/splash.png b/src/examples/catsteroids/img/splash.png index f97f0ded8..c981211e5 100644 Binary files a/src/examples/catsteroids/img/splash.png and b/src/examples/catsteroids/img/splash.png differ diff --git a/src/examples/yarn.ict b/src/examples/yarn.ict index 92ca2f057..da6868169 100644 --- a/src/examples/yarn.ict +++ b/src/examples/yarn.ict @@ -1,4 +1,4 @@ -ctjsVersion: 1.3.0 +ctjsVersion: 1.4.2 notes: >- There is a number of interesting places to start learning the demo: @@ -375,14 +375,18 @@ rooms: uid: 9e7aec96-1ad3-4679-a248-01180284e78e tx: 0.75 ty: 0.75 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: d21d2804-d690-4c65-9657-7a1486b7f1d9 thumbnail: 7a1486b7f1d9 gridX: 64 gridY: 64 - lastmod: 1570007451105 + lastmod: 1602729464201 + extends: {} + backgroundColor: '#FFFFFF' - name: Micro oncreate: |- var latestBlurb; // we will need it to accurately position text lines @@ -415,14 +419,18 @@ rooms: uid: 9e7aec96-1ad3-4679-a248-01180284e78e tx: 0.75 ty: 0.75 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: cb9565fc-6666-4f0c-bc6c-b49f813ea9ce thumbnail: b49f813ea9ce gridX: 64 gridY: 64 - lastmod: 1570007519025 + lastmod: 1602729449081 + extends: {} + backgroundColor: '#FFFFFF' - name: Stop oncreate: |- var latestBlurb; // we will need it to accurately position text lines @@ -455,14 +463,18 @@ rooms: uid: 9e7aec96-1ad3-4679-a248-01180284e78e tx: 0.75 ty: 0.75 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 95f73a99-6402-4848-81a7-d96488130d15 thumbnail: d96488130d15 gridX: 64 gridY: 64 - lastmod: 1570013323128 + lastmod: 1602729455043 + extends: {} + backgroundColor: '#FFFFFF' - name: Wait oncreate: |- var latestBlurb; // we will need it to accurately position text lines @@ -495,25 +507,21 @@ rooms: uid: 9e7aec96-1ad3-4679-a248-01180284e78e tx: 0.75 ty: 0.75 + exts: {} tiles: - depth: -10 tiles: [] + extends: {} uid: 48b25b49-58b8-44ee-b4c5-cc6b9ea24c38 thumbnail: cc6b9ea24c38 gridX: 64 gridY: 64 - lastmod: 1570056924685 + lastmod: 1602729461377 + extends: {} + backgroundColor: '#FFFFFF' actions: [] starting: 0 settings: - minifyhtmlcss: false - minifyjs: false - fps: 30 - version: - - 0 - - 0 - - 0 - versionPostfix: '' export: linux: true windows: true @@ -522,7 +530,22 @@ settings: icon: -1 accent: '#446adb' invertPreloaderScheme: true - desktopMode: maximized + rendering: + maxFPS: 60 + pixelatedrender: false + highDensity: true + usePixiLegacy: true + desktopMode: maximized + authoring: + title: ! '' + author: ! '' + site: ! '' + version: + - 0 + - 0 + - 0 + versionPostfix: '' + fps: 30 scripts: - name: storyEngine code: |- @@ -642,3 +665,4 @@ scripts: fonts: [] startroom: d21d2804-d690-4c65-9657-7a1486b7f1d9 emitterTandems: [] +palette: [] diff --git a/src/examples/yarn/img/r7a1486b7f1d9.png b/src/examples/yarn/img/r7a1486b7f1d9.png index d6513cef2..5949a1f9d 100644 Binary files a/src/examples/yarn/img/r7a1486b7f1d9.png and b/src/examples/yarn/img/r7a1486b7f1d9.png differ diff --git a/src/examples/yarn/img/rb49f813ea9ce.png b/src/examples/yarn/img/rb49f813ea9ce.png index d6513cef2..969cdc513 100644 Binary files a/src/examples/yarn/img/rb49f813ea9ce.png and b/src/examples/yarn/img/rb49f813ea9ce.png differ diff --git a/src/examples/yarn/img/rcc6b9ea24c38.png b/src/examples/yarn/img/rcc6b9ea24c38.png index 9b3409daf..969cdc513 100644 Binary files a/src/examples/yarn/img/rcc6b9ea24c38.png and b/src/examples/yarn/img/rcc6b9ea24c38.png differ diff --git a/src/examples/yarn/img/rd96488130d15.png b/src/examples/yarn/img/rd96488130d15.png index 9b3409daf..969cdc513 100644 Binary files a/src/examples/yarn/img/rd96488130d15.png and b/src/examples/yarn/img/rd96488130d15.png differ diff --git a/src/examples/yarn/img/splash.png b/src/examples/yarn/img/splash.png index 9b3409daf..5949a1f9d 100644 Binary files a/src/examples/yarn/img/splash.png and b/src/examples/yarn/img/splash.png differ diff --git a/src/node_requires/imageUtils.ts b/src/node_requires/imageUtils.ts new file mode 100644 index 000000000..b60de059c --- /dev/null +++ b/src/node_requires/imageUtils.ts @@ -0,0 +1,109 @@ +type GenericImage = HTMLImageElement | HTMLCanvasElement; + +/** + * Creates a new image of a given size with a source image proportionally filling the whole canvas. + */ +const imageCover = function (image: GenericImage, w: number, h: number): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + const cx = canvas.getContext('2d'); + cx.clearRect(0, 0, w, h); + const k = Math.max(w / image.width, h / image.height); + if ((global as any).currentProject.settings.rendering.pixelatedrender) { + cx.imageSmoothingEnabled = false; + } + cx.drawImage( + image, + (w - image.width * k) / 2, (h - image.height * k) / 2, + image.width * k, image.height * k + ); + return canvas; +}; +/** + * Creates a new image of a given size . + * If the source image exceeds the rectangle, it is scaled down proportionately. + * If the source image is smaller and image smoothing is disabled, scales the image + * by integer multipliers. + * Otherwise, draws the image as is, centered in the middle of a canvas. + */ +const imageContain = function (image: GenericImage, w: number, h: number): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + const cx = canvas.getContext('2d'); + cx.clearRect(0, 0, w, h); + let k; + if (w / image.width > h / image.height) { + k = w / image.width; + } else { + k = h / image.height; + } + if (k > 1) { + if ((global as any).currentProject.settings.rendering.pixelatedrender) { + k = Math.floor(k); + cx.imageSmoothingEnabled = false; + } else { + k = 1; + } + } + cx.drawImage( + image, + (w - image.width * k) / 2, (h - image.height * k) / 2, + image.width * k, image.height * k + ); + return canvas; +}; +/** + * Returns a new canvas with an image-like object drawn into it. + */ +const toCanvas = function (image: GenericImage): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + canvas.width = image.width; + canvas.height = image.height; + const cx = canvas.getContext('2d'); + cx.clearRect(0, 0, canvas.width, canvas.height); + cx.drawImage(image, 0, 0); + return canvas; +}; +/** + * Crops an input image, returning a new canvas element. + */ +const crop = function ( + image: GenericImage, + x: number, + y: number, + w: number, + h: number +): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + const cx = canvas.getContext('2d'); + cx.clearRect(0, 0, w, h); + cx.drawImage( + image, + x, y, w, h, + 0, 0, w, h + ); + return canvas; +}; +/** + * Converts a canvas into a node.js buffer (PNG data). + */ +const toBuffer = function (image: GenericImage): Buffer { + if (!(image instanceof HTMLCanvasElement)) { + image = toCanvas(image); + } + const base64 = image.toDataURL().replace(/^data:image\/\w+;base64,/, ''); + const buffer = Buffer.from(base64, 'base64'); + return buffer; +}; + +module.exports = { + imageCover, + imageContain, + toCanvas, + toBuffer, + crop +}; diff --git a/src/node_requires/resources/projects/index.js b/src/node_requires/resources/projects/index.js deleted file mode 100644 index 7f82278fb..000000000 --- a/src/node_requires/resources/projects/index.js +++ /dev/null @@ -1,27 +0,0 @@ -const defaultProject = require('./defaultProject'); - -/** - * @returns {Promise} A promise that resolves into the absolute path - * to the projects' directory - */ -const getDefaultProjectDir = function () { - const {getProjectsDir} = require('./../../platformUtils'); - return getProjectsDir(); -}; - -const getExamplesDir = function () { - const path = require('path'); - try { - require('gulp'); - // Most likely, we are in a dev environment - return path.join(nw.App.startPath, 'src/examples'); - } catch (e) { - return path.join(nw.App.startPath, 'examples'); - } -}; - -module.exports = { - defaultProject, - getDefaultProjectDir, - getExamplesDir -}; diff --git a/src/node_requires/resources/projects/index.ts b/src/node_requires/resources/projects/index.ts new file mode 100644 index 000000000..f352d24dc --- /dev/null +++ b/src/node_requires/resources/projects/index.ts @@ -0,0 +1,65 @@ +const defaultProject = require('./defaultProject'); + +/** + * @returns {Promise} A promise that resolves into the absolute path + * to the projects' directory + */ +const getDefaultProjectDir = function (): Promise { + const {getProjectsDir} = require('./../../platformUtils'); + return getProjectsDir(); +}; + +const getExamplesDir = function (): string { + const path = require('path'); + try { + require('gulp'); + // Most likely, we are in a dev environment + return path.join((nw.App as any).startPath, 'src/examples'); + } catch (e) { + return path.join((nw.App as any).startPath, 'examples'); + } +}; + +/** + * Returns a path that does not end with `.ict` + * @param {string} projPath + * @returns {string} + */ +const getProjectDir = function (projPath: string): string { + return projPath.replace(/\.ict$/, ''); +}; + +/** + * Returns a path to the project's thumbnail. + * @param {string} projPath + * @param {boolean} [fs] Whether to return a filesystem path (true) or a URL (false; default). + */ +const getProjectThumbnail = function (projPath: string, fs?: boolean) { + const path = require('path'); + projPath = getProjectDir(projPath); + if (fs) { + return path.join(projPath, 'img', 'splash.png'); + } + return `file://${projPath.replace(/\\/g, '/')}/img/splash.png`; +}; + +/** + * Returns a path that ends with `.ict` file + * @param {string} projPath + * @returns {string} + */ +const getProjectIct = function (projPath: string): string { + if (!(/\.ict$/.test(projPath))) { + return projPath + '.ict'; + } + return projPath; +}; + +module.exports = { + defaultProject, + getDefaultProjectDir, + getProjectThumbnail, + getProjectIct, + getProjectDir, + getExamplesDir +}; diff --git a/src/node_requires/resources/textures/index.js b/src/node_requires/resources/textures/index.js index 75dda8421..a8ef7bf74 100644 --- a/src/node_requires/resources/textures/index.js +++ b/src/node_requires/resources/textures/index.js @@ -174,41 +174,18 @@ const textureGenPreview = async function textureGenPreview(texture, destination, if (typeof texture === 'string') { texture = getTextureFromId(texture); } + const {imageContain, toBuffer, crop} = require('../../imageUtils'); const source = await getDOMImage(texture); - - const c = document.createElement('canvas'); - c.x = c.getContext('2d'); - c.width = c.height = size; - c.x.clearRect(0, 0, size, size); - - const x = texture.offx, - y = texture.offy, - w = texture.width, - h = texture.height; - - let k; - if (w > h) { - k = size / w; - } else { - k = size / h; - } - if (k > 1) { - if (global.currentProject.settings.rendering.pixelatedrender) { - k = Math.floor(k); - c.x.imageSmoothingEnabled = false; - } else { - k = 1; - } - } - c.x.drawImage( + const frame = crop( source, - x, y, w, h, - (size - w * k) / 2, (size - h * k) / 2, - w * k, h * k + texture.offx, + texture.offy, + texture.width, + texture.height ); - const thumbnailBase64 = c.toDataURL().replace(/^data:image\/\w+;base64,/, ''); - const buf = Buffer.from(thumbnailBase64, 'base64'); + const c = imageContain(frame, size, size); + const buf = toBuffer(c); const fs = require('fs-extra'); await fs.writeFile(destination, buf); return destination; diff --git a/src/riotTags/project-selector.tag b/src/riotTags/project-selector.tag index af99c0a59..838a58007 100644 --- a/src/riotTags/project-selector.tag +++ b/src/riotTags/project-selector.tag @@ -1,55 +1,74 @@ project-selector - #bg.stretch.middle - #intro.panel.middleinner - div.flexrow - .c4.np - .c8.npt.npb - h2 {voc.latest} - div.flexrow - .c4.npl.npt.project-selector-aPreview.center - img(src="{projectSplash}") - .c8.npr.npt.npl.flexfix - ul.menu.flexfix-body - li( - each="{project in lastProjects}" title="{requirePath.basename(project,'.json')}" - onclick="{updatePreview(project)}" - ondblclick="{loadRecentProject}" - ) - .toright(onclick="{forgetProject}" title="{voc.forgetProject}") + #bg.stretch.flexcol + .spacer + #intro.panel.flexfix.nogrow + ul.nav.tabs.flexfix-header.nb + li(class="{active: tab === 'projects'}" onclick="{changeTab('projects')}") + span {voc.latest} + li(class="{active: tab === 'examples'}" onclick="{changeTab('examples')}") + span {voc.examples} + .flexfix-body.pad(show="{tab === 'projects'}") + .flexrow + h2.nmt {voc.latest} + label.file.nm.nogrow + button.inline.nml.nmr(onclick="{openProjectFind}") + svg.feather + use(xlink:href="data/icons.svg#folder") + span {voc.browse} + .clear + ul.Cards.largeicons.nmb + li.aCard( + each="{project in latestProjects}" + onclick="{loadRecentProject}" + title="{project}" + ) + img(src="{getProjectThumbnail(project)}") + span {getProjectName(project)} + .aCard-Actions(onclick="{forgetProject}" title="{voc.forgetProject}") + button.tiny svg.feather use(xlink:href="data/icons.svg#x") - span {project} - label.file.flexfix-footer.nmb - button.wide.inline.nml.nmr(onclick="{openProjectFind}") + .flexfix-body.pad(show="{tab === 'examples'}") + .flexrow + h2.nmt {voc.examples} + label.file.nm.nogrow + button.inline.nml.nmr(onclick="{openProjectFind}") svg.feather use(xlink:href="data/icons.svg#folder") span {voc.browse} - #newProject.inset.flexrow.flexmiddle - .c4.npl.npt.npb - h3.nm.right {voc.newProject.text} - .c5.np - input( - type='text' - placeholder='{voc.newProject.input}' - pattern='[a-zA-Z_0-9]\\{1,\\}' - ref="projectname" - ).wide - .c3.npr.npt.npb - button.nm.wide.inline(onclick="{openProjectFolder}") {voc.newProject.button} - .aVersionNumber - a(href="https://discord.gg/CggbPkb" title="{voc.discord}" onclick="{openExternal('https://discord.gg/CggbPkb')}") - svg.icon - use(xlink:href="data/icons.svg#discord") - a(href="https://twitter.com/ctjsrocks" title="{voc.twitter}" onclick="{openExternal('https://twitter.com/ctjsrocks')}") - svg.icon - use(xlink:href="data/icons.svg#twitter") - .inlineblock v{ctjsVersion}. - | - | - // as itch releases are always in sync with the fetched version number, let's route users to itch.io page - a.inlineblock(if="{newVersion}" href="https://comigo.itch.io/ct#download" onclick="{openExternal}") - | {newVersion} - img(src="data/img/partycarrot.gif" if="{newVersion}").aPartyCarrot + .clear + ul.Cards.largeicons.nmb + li.aCard( + each="{project in exampleProjects}" + onclick="{loadRecentProject}" + title="{project}" + ) + img(src="{getProjectThumbnail(project)}") + span {getProjectName(project)} + #newProject.inset.flexfix-footer.flexrow + h3.nm.inline {voc.newProject.text} + input( + type='text' + placeholder='{voc.newProject.input}' + pattern='[a-zA-Z_0-9]\\{1,\\}' + ref="projectname" + ) + button.nm.inline(onclick="{openProjectFolder}") {voc.newProject.button} + .spacer + .aVersionNumber.nogrow + a(href="https://discord.gg/CggbPkb" title="{voc.discord}" onclick="{openExternal('https://discord.gg/CggbPkb')}") + svg.icon + use(xlink:href="data/icons.svg#discord") + a(href="https://twitter.com/ctjsrocks" title="{voc.twitter}" onclick="{openExternal('https://twitter.com/ctjsrocks')}") + svg.icon + use(xlink:href="data/icons.svg#twitter") + .inlineblock v{ctjsVersion}. + | + | + // as itch releases are always in sync with the fetched version number, let's route users to itch.io page + a.inlineblock(if="{newVersion}" href="https://comigo.itch.io/ct#download" onclick="{openExternal}") + | {newVersion} + img(src="data/img/partycarrot.gif" if="{newVersion}").aPartyCarrot script. const fs = require('fs-extra'), path = require('path'); @@ -57,6 +76,13 @@ project-selector this.requirePath = path; this.namespace = 'intro'; this.mixin(window.riotVoc); + + this.tab = 'projects'; + this.changeTab = tab => () => { + this.tab = tab; + }; + this.getProjectName = project => path.basename(project, path.extname(project)); + this.visible = true; var hideProjectSelector = () => { this.visible = false; @@ -73,11 +99,43 @@ project-selector // Loads recently opened projects if (('lastProjects' in localStorage) && (localStorage.lastProjects !== '')) { - this.lastProjects = localStorage.lastProjects.split(';'); + this.latestProjects = localStorage.lastProjects.split(';'); + let removedNonexistent = false; + Promise.all(this.latestProjects.map(proj => fs.pathExists(proj) + .then(exists => { + if (!exists) { + this.latestProjects.splice(this.latestProjects.indexOf(proj), 1); + removedNonexistent = true; + } + }) + .catch(err => { + alertify.log(`Got a strange error while trying to access ${proj}. See the console for more details.`); + console.error(err); + }))) + .then(() => { + if (removedNonexistent) { + alertify.log('Removed some projects from the list, as they no longer exist.'); + localStorage.lastProjects = this.latestProjects.join(';'); + } + this.update(); + }); } else { - this.lastProjects = []; + this.latestProjects = []; } + const projects = require('./data/node_requires/resources/projects'); + this.exampleProjects = []; + // Loads examples + fs.readdir(projects.getExamplesDir(), { + withFileTypes: true + }) + .then(entries => entries.filter(entry => entry.isFile() && (/\.ict$/i).test(entry.name))) + .then(entries => entries.map(entry => path.join(projects.getExamplesDir(), entry.name))) + .then(projects => { + this.exampleProjects = projects; + this.update(); + }); + this.getProjectThumbnail = projects.getProjectThumbnail; /** * Update a splash image of a selected project */ @@ -127,8 +185,8 @@ project-selector */ this.forgetProject = e => { const {project} = e.item; - this.lastProjects.splice(this.lastProjects.indexOf(project), 1); - localStorage.lastProjects = this.lastProjects.join(';'); + this.latestProjects.splice(this.latestProjects.indexOf(project), 1); + localStorage.lastProjects = this.latestProjects.join(';'); e.stopPropagation(); }; diff --git a/src/riotTags/rooms/room-editor.tag b/src/riotTags/rooms/room-editor.tag index 8929c4a71..107e8a233 100644 --- a/src/riotTags/rooms/room-editor.tag +++ b/src/riotTags/rooms/room-editor.tag @@ -708,43 +708,20 @@ room-editor.panel.view * Генерирует миниатюру комнаты */ this.roomGenSplash = function roomGenSplash() { + const {imageCover, toBuffer} = require('./data/node_requires/imageUtils'); return new Promise((accept, decline) => { - var c = document.createElement('canvas'), - w, h, k; - c.x = c.getContext('2d'); - c.width = 340; - c.height = 256; - c.x.clearRect(0, 0, c.width, c.height); - w = this.refs.canvas.width; - h = this.refs.canvas.height; - if (w / c.width > h / c.height) { - k = c.width / w; - } else { - k = c.height / h; - } - if (k > 1) { - k = 1; - } - c.x.drawImage( - this.refs.canvas, - 0, 0, this.refs.canvas.width, this.refs.canvas.height, - (c.width - this.refs.canvas.width * k) / 2, - (c.height - this.refs.canvas.height * k) / 2, - this.refs.canvas.width * k, - this.refs.canvas.height * k - ); - var splashBase64 = c.toDataURL().replace(/^data:image\/\w+;base64,/, ''); - var buf = new Buffer(splashBase64, 'base64'); - var nam = global.projdir + '/img/r' + this.room.thumbnail + '.png'; - fs.writeFile(nam, buf, function roomGenSplashCallback(err) { + const c = imageCover(this.refs.canvas, 340, 256); + const buf = toBuffer(c); + const roomSplashName = global.projdir + '/img/r' + this.room.thumbnail + '.png'; + fs.writeFile(roomSplashName, buf, err => { if (err) { decline(err); } else { - accept(nam); + accept(roomSplashName); } }); - var nam2 = global.projdir + '/img/splash.png'; - fs.writeFile(nam2, buf, function projGenSplashCallback(err) { + const projSplashName = global.projdir + '/img/splash.png'; + fs.writeFile(projSplashName, buf, err => { if (err) { decline(err); } diff --git a/src/riotTags/rooms/rooms-panel.tag b/src/riotTags/rooms/rooms-panel.tag index 219edebf9..ef0c96186 100644 --- a/src/riotTags/rooms/rooms-panel.tag +++ b/src/riotTags/rooms/rooms-panel.tag @@ -22,7 +22,7 @@ rooms-panel.panel.view svg.feather use(xlink:href="data/icons.svg#plus") span {voc.create} - ul.cards.rooms.flexfix-body(class="{list: localStorage.roomsLayout === 'list'}") + ul.pad.cards.largeicons.flexfix-body(class="{list: localStorage.roomsLayout === 'list'}") li( each="{room in (searchResults? searchResults : rooms)}" class="{starting: global.currentProject.startroom === room.uid}" diff --git a/src/riotTags/shared/texture-input.tag b/src/riotTags/shared/texture-input.tag index f868eb6fc..f30b80087 100644 --- a/src/riotTags/shared/texture-input.tag +++ b/src/riotTags/shared/texture-input.tag @@ -26,7 +26,7 @@ texture-input(class="{large: opts.large} {opts.class}") img(src="{getTexturePreview(val || -1, true)}") div(if="{val === -1}") {vocGlob.select} div(if="{val !== -1}") {getTextureFromId(val).name} - button.square(if="{val !== -1 && opts.large}" title="{voc.jumpToTexture}" onclick="{openTexture}") + button.tiny(if="{val !== -1 && opts.large}" title="{voc.jumpToTexture}" onclick="{openTexture}") svg.feather use(xlink:href="data/icons.svg#external-link") texture-selector( diff --git a/src/styl/buildingBlocks.styl b/src/styl/buildingBlocks.styl index 5eb2dcd78..d0793171c 100644 --- a/src/styl/buildingBlocks.styl +++ b/src/styl/buildingBlocks.styl @@ -19,8 +19,6 @@ border 1px solid borderBright border-radius br position relative - &.pad - padding 1rem .modal position fixed @@ -144,14 +142,14 @@ // resource cards -.cards +.cards, .Cards list-style none padding 0 display grid grid-template-columns repeat(auto-fill, minmax(17em, 1fr)) grid-gap 0.3em flex-grow 0 - li + li, .aCard background background padding 0.8em margin 0 @@ -225,6 +223,32 @@ &:last-child border-bottom-left-radius br border-bottom-right-radius br + &.largeicons + grid-template-columns repeat(auto-fill, minmax(15em, 1fr)) + li + text-align center + position relative + img + float none + max-width 13.5em + max-height 10em + margin 0 + width auto + height auto + span + font-family consolas, monospace + width 12.5em + text-overflow ellipsis + white-space nowrap + overflow hidden +.aCard-Actions + position absolute + top 0.5rem + right 0.5rem + opacity 0 + {trans} + .aCard:hover &, .aCard:focus & + opacity 1 sounds-panel, rooms-panel .cards li img:hover background none diff --git a/src/styl/hvost.styl b/src/styl/hvost.styl index f16476735..2bbecb6f5 100644 --- a/src/styl/hvost.styl +++ b/src/styl/hvost.styl @@ -156,6 +156,10 @@ for key, val in shortNames .n{key}, .no{val} {val} 0 !important +.pad + padding 1rem + box-sizing border-box + .column padding 1rem box-sizing border-box diff --git a/src/styl/inputs.styl b/src/styl/inputs.styl index 1c128306b..36bdde99e 100644 --- a/src/styl/inputs.styl +++ b/src/styl/inputs.styl @@ -92,6 +92,18 @@ input[type="reset"], &.inline padding 0.2em 0.8em display inline-block + &.tiny + margin 0 + padding 0.35rem + width auto + font-size 0.5rem + display inline-block + line-height 1 + svg + width 1rem + height 1rem + & + button.tiny + margin-left 0.25rem &.vertical padding 1em 0 &.square diff --git a/src/styl/tags/project-selector.styl b/src/styl/tags/project-selector.styl index 910c6b359..8eb3c2cb5 100644 --- a/src/styl/tags/project-selector.styl +++ b/src/styl/tags/project-selector.styl @@ -10,23 +10,18 @@ project-selector label.file margin 1em 0 .panel - width 48rem + width 50rem max-width 95% + max-height calc(100% - 10rem) margin 0 auto 2rem - padding 1rem background background - flex-flow column nowrap z-index 35 {shadamb} + h2 + align-self flex-end .inset - margin 0 -1rem -1rem + margin 0 border-radius 0 0 br br - .menu - max-height 15rem - li - direction rtl - svg - margin-left 1rem .aVersionNumber position absolute bottom 0 @@ -52,14 +47,14 @@ project-selector max-width 100% max-height 20em -#recent - height 15em - span - overflow hidden - white-space nowrap - width 100% - display block - text-overflow ellipsis +#newProject + align-items center + justify-content center + h3, button, input + flex 0 0 auto + input + margin 0 1rem + width 16rem #bg background url('../data/img/bg.png') background-size cover @@ -70,6 +65,4 @@ project-selector text-align initial #id - width 14.75em -#newproj - margin-right 0 + width 14.75em \ No newline at end of file diff --git a/src/styl/tags/rooms/rooms-panel.styl b/src/styl/tags/rooms/rooms-panel.styl index 82cb6d1f2..31e57644e 100644 --- a/src/styl/tags/rooms/rooms-panel.styl +++ b/src/styl/tags/rooms/rooms-panel.styl @@ -3,32 +3,16 @@ rooms-panel padding 1em overflow-x hidden -.cards.rooms - li - text-align center - position relative - img - float none - max-width 13.5em - max-height 10em - margin 0 0 0.5em - width auto - height auto - span - font-family consolas, monospace - width 15em - text-overflow ellipsis - white-space nowrap - overflow hidden - .starting svg - position absolute - right 0.5em - top 0.5em - color warning - &.list + .cards .starting svg - position static - margin 0 0.5rem - order 5 - img - width auto + position absolute + right 0.5em + top 0.5em + color warning + &.list + .starting svg + position static + margin 0 0.5rem + order 5 + img + width auto diff --git a/src/styl/tags/shared/texture-input.styl b/src/styl/tags/shared/texture-input.styl index 2b3e19fbe..7bf218a21 100644 --- a/src/styl/tags/shared/texture-input.styl +++ b/src/styl/tags/shared/texture-input.styl @@ -29,15 +29,9 @@ texture-input position relative display inline-block & > button - margin 0 position absolute right 0.5rem top 0.5rem - width auto - font-size 0.5rem - svg - width 1rem - height 1rem img max-width 128px max-height 128px \ No newline at end of file