c3 backup

This commit is contained in:
Davide Tantillo 2025-08-12 09:56:27 +02:00
parent 75da4d6be5
commit 93c56d08d0
182 changed files with 6533 additions and 129 deletions

2
.gitignore vendored
View File

@ -142,6 +142,8 @@ spine-cocos2dx/example-v4/cocos2dx.zip
spine-ts/spine-core/dist
spine-ts/spine-canvas/dist
spine-ts/spine-construct3/dist
spine-ts/spine-construct3-lib/dist
spine-ts/spine-webgl/dist
spine-ts/spine-player/dist
spine-ts/spine-webcomponents/dist

View File

@ -204,6 +204,10 @@
<li><a href="/spine-webcomponents/example/dispose.html">Dispose</a></li>
<li><a href="/spine-webcomponents/example/gui.html">GUI</a></li>
</ul>
<li>Construct 3</li>
<ul>
<li><a href="/spine-construct3/dist/addon.json">Serve Addon for development</a></li>
</ul>
</ul>
</div>

View File

@ -11,13 +11,15 @@
"workspaces": [
"spine-core",
"spine-canvas",
"spine-canvaskit",
"spine-construct3",
"spine-construct3-lib",
"spine-phaser-v3",
"spine-phaser-v4",
"spine-player",
"spine-threejs",
"spine-pixi-v7",
"spine-pixi-v8",
"spine-canvaskit",
"spine-webgl",
"spine-webcomponents"
],
@ -25,10 +27,12 @@
"@biomejs/biome": "^2.1.1",
"@types/offscreencanvas": "^2019.7.3",
"alive-server": "^1.3.0",
"chokidar-cli": "^3.0.0",
"concurrently": "^9.2.0",
"copyfiles": "^2.4.1",
"esbuild": "^0.25.6",
"rimraf": "^6.0.1",
"tsc-watch": "^7.1.1",
"typescript": "^5.8.3",
"typescript-formatter": "^7.2.2"
}
@ -646,6 +650,14 @@
"resolved": "spine-canvaskit",
"link": true
},
"node_modules/@esotericsoftware/spine-construct3": {
"resolved": "spine-construct3",
"link": true
},
"node_modules/@esotericsoftware/spine-construct3-lib": {
"resolved": "spine-construct3-lib",
"link": true
},
"node_modules/@esotericsoftware/spine-core": {
"resolved": "spine-core",
"link": true
@ -1068,63 +1080,6 @@
"node": ">=0.10.0"
}
},
"node_modules/alive-server/node_modules/anymatch": {
"version": "3.1.3",
"dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/alive-server/node_modules/binary-extensions": {
"version": "2.3.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/alive-server/node_modules/braces": {
"version": "3.0.3",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/alive-server/node_modules/chokidar": {
"version": "3.6.0",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/alive-server/node_modules/event-stream": {
"version": "4.0.1",
"dev": true,
@ -1139,28 +1094,6 @@
"through": "^2.3.8"
}
},
"node_modules/alive-server/node_modules/fill-range": {
"version": "7.1.1",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/alive-server/node_modules/glob-parent": {
"version": "5.1.2",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/alive-server/node_modules/http-auth": {
"version": "4.2.0",
"dev": true,
@ -1175,41 +1108,11 @@
"node": ">=8"
}
},
"node_modules/alive-server/node_modules/is-binary-path": {
"version": "2.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/alive-server/node_modules/is-number": {
"version": "7.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/alive-server/node_modules/map-stream": {
"version": "0.0.7",
"dev": true,
"license": "MIT"
},
"node_modules/alive-server/node_modules/readdirp": {
"version": "3.6.0",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/alive-server/node_modules/split": {
"version": "1.0.1",
"dev": true,
@ -1230,17 +1133,6 @@
"through": "~2.3.4"
}
},
"node_modules/alive-server/node_modules/to-regex-range": {
"version": "5.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/alive-server/node_modules/uuid": {
"version": "8.3.2",
"dev": true,
@ -1271,6 +1163,20 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/apache-crypt": {
"version": "1.2.6",
"dev": true,
@ -1316,6 +1222,19 @@
"dev": true,
"license": "MIT"
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"dev": true,
@ -1325,6 +1244,19 @@
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"license": "MIT",
@ -1352,6 +1284,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/canvaskit-wasm": {
"version": "0.39.1",
"license": "BSD-3-Clause",
@ -1385,6 +1327,199 @@
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar-cli": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz",
"integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"chokidar": "^3.5.2",
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1",
"yargs": "^13.3.0"
},
"bin": {
"chokidar": "index.js"
},
"engines": {
"node": ">= 8.10.0"
}
},
"node_modules/chokidar-cli/node_modules/ansi-regex": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/chokidar-cli/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/chokidar-cli/node_modules/cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"node_modules/chokidar-cli/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/chokidar-cli/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true,
"license": "MIT"
},
"node_modules/chokidar-cli/node_modules/emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true,
"license": "MIT"
},
"node_modules/chokidar-cli/node_modules/is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/chokidar-cli/node_modules/string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/chokidar-cli/node_modules/strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^4.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/chokidar-cli/node_modules/wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/chokidar-cli/node_modules/y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"dev": true,
"license": "ISC"
},
"node_modules/chokidar-cli/node_modules/yargs": {
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
}
},
"node_modules/chokidar-cli/node_modules/yargs-parser": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"license": "ISC",
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"dev": true,
@ -1483,6 +1618,8 @@
},
"node_modules/copyfiles": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz",
"integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1574,6 +1711,16 @@
"ms": "2.0.0"
}
},
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"dev": true,
@ -1753,6 +1900,22 @@
"node": ">= 0.6"
}
},
"node_modules/event-stream": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
"integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==",
"dev": true,
"license": "MIT",
"dependencies": {
"duplexer": "~0.1.1",
"from": "~0",
"map-stream": "~0.1.0",
"pause-stream": "0.0.11",
"split": "0.3",
"stream-combiner": "~0.0.4",
"through": "~2.3.1"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"license": "MIT",
@ -1774,6 +1937,19 @@
"dev": true,
"license": "MIT"
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/finalhandler": {
"version": "1.1.2",
"dev": true,
@ -1791,6 +1967,19 @@
"node": ">= 0.8"
}
},
"node_modules/find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"license": "MIT",
"dependencies": {
"locate-path": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@ -1919,6 +2108,19 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"license": "MIT",
@ -2010,6 +2212,19 @@
"dev": true,
"license": "ISC"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-docker": {
"version": "2.2.1",
"dev": true,
@ -2051,6 +2266,16 @@
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/isarray": {
"version": "0.0.1",
"dev": true,
@ -2089,11 +2314,39 @@
"license": "MIT",
"peer": true
},
"node_modules/locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"dev": true,
"license": "MIT"
},
"node_modules/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,
"license": "MIT"
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
"dev": true,
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@ -2105,6 +2358,12 @@
"yallist": "^2.1.2"
}
},
"node_modules/map-stream": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
"integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==",
"dev": true
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"license": "MIT",
@ -2208,6 +2467,13 @@
"node": ">= 0.6"
}
},
"node_modules/node-cleanup": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz",
"integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==",
"dev": true,
"license": "MIT"
},
"node_modules/noms": {
"version": "0.0.0",
"dev": true,
@ -2298,6 +2564,45 @@
"node": ">=8"
}
},
"node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-limit": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@ -2323,6 +2628,16 @@
"node": ">= 0.8"
}
},
"node_modules/path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"dev": true,
@ -2394,6 +2709,8 @@
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
@ -2463,6 +2780,22 @@
"node": ">=0.8.0"
}
},
"node_modules/ps-tree": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz",
"integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"event-stream": "=3.3.4"
},
"bin": {
"ps-tree": "bin/ps-tree.js"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@ -2508,6 +2841,19 @@
"string_decoder": "~0.10.x"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"dev": true,
@ -2516,6 +2862,13 @@
"node": ">=0.10.0"
}
},
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true,
"license": "ISC"
},
"node_modules/rimraf": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
@ -2695,6 +3048,13 @@
"dev": true,
"license": "ISC"
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"dev": true,
"license": "ISC"
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"dev": true,
@ -2822,6 +3182,19 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/split": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
"integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==",
"dev": true,
"license": "MIT",
"dependencies": {
"through": "2"
},
"engines": {
"node": "*"
}
},
"node_modules/statuses": {
"version": "1.5.0",
"dev": true,
@ -2830,11 +3203,31 @@
"node": ">= 0.6"
}
},
"node_modules/stream-combiner": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
"integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==",
"dev": true,
"license": "MIT",
"dependencies": {
"duplexer": "~0.1.1"
}
},
"node_modules/string_decoder": {
"version": "0.10.31",
"dev": true,
"license": "MIT"
},
"node_modules/string-argv": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.6.19"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"dev": true,
@ -2949,6 +3342,19 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"dev": true,
@ -2965,6 +3371,28 @@
"tree-kill": "cli.js"
}
},
"node_modules/tsc-watch": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-7.1.1.tgz",
"integrity": "sha512-r6t37Dkk4vK44HwxOe+OzjpE/gDamZAwqXhtcAJD/hPVblcjJK45NxbK0HcDASXG0U4pEnCh640JZbeDVSC6yA==",
"dev": true,
"license": "MIT",
"dependencies": {
"cross-spawn": "^7.0.6",
"node-cleanup": "^2.1.2",
"ps-tree": "^1.2.0",
"string-argv": "^0.3.2"
},
"bin": {
"tsc-watch": "dist/lib/tsc-watch.js"
},
"engines": {
"node": ">=12.12.0"
},
"peerDependencies": {
"typescript": "*"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"dev": true,
@ -3100,6 +3528,13 @@
"node": ">= 8"
}
},
"node_modules/which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
"dev": true,
"license": "ISC"
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"dev": true,
@ -3209,6 +3644,22 @@
"@types/node": "20.14.9"
}
},
"spine-construct3": {
"name": "@esotericsoftware/spine-construct3",
"version": "4.2.82",
"license": "LicenseRef-LICENSE",
"dependencies": {
"@esotericsoftware/spine-construct3-lib": "^4.2.82"
}
},
"spine-construct3-lib": {
"name": "@esotericsoftware/spine-construct3-lib",
"version": "4.2.82",
"license": "LicenseRef-LICENSE",
"dependencies": {
"@esotericsoftware/spine-core": "4.2.82"
}
},
"spine-core": {
"name": "@esotericsoftware/spine-core",
"version": "4.2.82",

View File

@ -8,14 +8,17 @@
],
"scripts": {
"prepublish": "npm run clean && npm run build",
"clean": "npx rimraf spine-core/dist spine-canvas/dist spine-canvaskit/dist spine-webgl/dist spine-phaser-v3/dist spine-phaser-v4/dist spine-player/dist spine-threejs/dist spine-pixi-v7/dist spine-pixi-v8/dist spine-webcomponents/dist",
"build": "npm run clean && npm run build:modules && concurrently 'npm run build:core:iife' 'npm run build:core:esm' 'npm run build:canvas:iife' 'npm run build:canvas:esm' 'npm run build:canvaskit:iife' 'npm run build:canvaskit:esm' 'npm run build:webgl:iife' 'npm run build:webgl:esm' 'npm run build:phaser-v3:iife' 'npm run build:phaser-v4:iife' 'npm run build:phaser-v3:esm' 'npm run build:phaser-v4:esm' 'npm run build:player:iife' 'npm run build:player:esm' 'npm run build:player:css' 'npm run build:threejs:iife' 'npm run build:threejs:esm' 'npm run build:pixi-v7:iife' 'npm run build:pixi-v7:esm' 'npm run build:pixi-v8:iife' 'npm run build:pixi-v8:esm' 'npm run build:webcomponents:iife' 'npm run build:webcomponents:esm'",
"clean": "npx rimraf spine-core/dist spine-canvas/dist spine-canvaskit/dist spine-webgl/dist spine-phaser-v3/dist spine-phaser-v4/dist spine-player/dist spine-threejs/dist spine-pixi-v7/dist spine-pixi-v8/dist spine-webcomponents/dist spine-construct3/dist spine-construct3-lib/dist",
"build": "npm run clean && npm run build:modules && concurrently 'npm run build:core:iife' 'npm run build:core:esm' 'npm run build:canvas:iife' 'npm run build:canvas:esm' 'npm run build:canvaskit:iife' 'npm run build:canvaskit:esm' 'npm run build:webgl:iife' 'npm run build:webgl:esm' 'npm run build:phaser-v3:iife' 'npm run build:phaser-v4:iife' 'npm run build:phaser-v3:esm' 'npm run build:phaser-v4:esm' 'npm run build:player:iife' 'npm run build:player:esm' 'npm run build:player:css' 'npm run build:threejs:iife' 'npm run build:threejs:esm' 'npm run build:pixi-v7:iife' 'npm run build:pixi-v7:esm' 'npm run build:pixi-v8:iife' 'npm run build:pixi-v8:esm' 'npm run build:webcomponents:iife' 'npm run build:webcomponents:esm' 'npm run build:construct3' 'npm run build:construct3-lib'",
"format": "npx -y tsx scripts/format.ts",
"lint": "npx biome lint .",
"postbuild": "npm run minify",
"build:modules": "npx tsc -b -clean && npx tsc -b",
"build:core:iife": "npx esbuild --bundle spine-core/src/index.ts --tsconfig=spine-core/tsconfig.json --sourcemap --outfile=spine-core/dist/iife/spine-core.js --format=iife --global-name=spine",
"build:core:esm": "npx esbuild --bundle spine-core/src/index.ts --tsconfig=spine-core/tsconfig.json --sourcemap --outfile=spine-core/dist/esm/spine-core.mjs --format=esm --global-name=spine",
"build:construct3": "npx tsc --project spine-construct3/tsconfig.json && npm run build:construct3:copy-assets",
"build:construct3:copy-assets": "npx copyfiles -u 2 \"spine-construct3/src/**/*.json\" \"spine-construct3/src/**/*.svg\" spine-construct3/dist/ && cp spine-construct3-lib/dist/iife/spine-construct3-lib.js spine-construct3/dist/c3runtime",
"build:construct3-lib": "node spine-construct3-lib/esbuild.config.js",
"build:canvas:iife": "npx esbuild --bundle spine-canvas/src/index.ts --tsconfig=spine-canvas/tsconfig.json --sourcemap --outfile=spine-canvas/dist/iife/spine-canvas.js --format=iife --global-name=spine",
"build:canvas:esm": "npx esbuild --bundle spine-canvas/src/index.ts --tsconfig=spine-canvas/tsconfig.json --sourcemap --outfile=spine-canvas/dist/esm/spine-canvas.mjs --format=esm --global-name=spine",
"build:canvaskit:iife": "npx esbuild --bundle spine-canvaskit/src/index.ts --tsconfig=spine-canvaskit/tsconfig.json --sourcemap --outfile=spine-canvaskit/dist/iife/spine-canvaskit.js --external:canvaskit-wasm --format=iife --global-name=spine",
@ -38,10 +41,12 @@
"build:webcomponents:iife": "npx esbuild --bundle spine-webcomponents/src/index.ts --tsconfig=spine-webcomponents/tsconfig.json --sourcemap --outfile=spine-webcomponents/dist/iife/spine-webcomponents.js --format=iife --global-name=spine",
"build:webcomponents:esm": "npx esbuild --bundle spine-webcomponents/src/index.ts --tsconfig=spine-webcomponents/tsconfig.json --sourcemap --outfile=spine-webcomponents/dist/esm/spine-webcomponents.mjs --format=esm --global-name=spine",
"minify": "npx esbuild --minify spine-core/dist/iife/spine-core.js --outfile=spine-core/dist/iife/spine-core.min.js && npx esbuild --minify spine-core/dist/esm/spine-core.mjs --outfile=spine-core/dist/esm/spine-core.min.mjs && npx esbuild --minify spine-canvas/dist/iife/spine-canvas.js --outfile=spine-canvas/dist/iife/spine-canvas.min.js && npx esbuild --minify spine-canvas/dist/esm/spine-canvas.mjs --outfile=spine-canvas/dist/esm/spine-canvas.min.mjs && npx esbuild --minify spine-canvaskit/dist/iife/spine-canvaskit.js --outfile=spine-canvaskit/dist/iife/spine-canvaskit.min.js && npx esbuild --minify spine-canvaskit/dist/esm/spine-canvaskit.mjs --outfile=spine-canvaskit/dist/esm/spine-canvaskit.min.mjs && npx esbuild --minify spine-player/dist/iife/spine-player.js --outfile=spine-player/dist/iife/spine-player.min.js && npx esbuild --minify spine-player/dist/esm/spine-player.mjs --outfile=spine-player/dist/esm/spine-player.min.mjs && npx esbuild --minify spine-phaser-v3/dist/iife/spine-phaser-v3.js --outfile=spine-phaser-v3/dist/iife/spine-phaser-v3.min.js && npx esbuild --minify spine-phaser-v3/dist/esm/spine-phaser-v3.mjs --outfile=spine-phaser-v3/dist/esm/spine-phaser-v3.min.mjs && npx esbuild --minify spine-phaser-v4/dist/iife/spine-phaser-v4.js --outfile=spine-phaser-v4/dist/iife/spine-phaser-v4.min.js && npx esbuild --minify spine-phaser-v4/dist/esm/spine-phaser-v4.mjs --outfile=spine-phaser-v4/dist/esm/spine-phaser-v4.min.mjs && npx esbuild --minify spine-webgl/dist/iife/spine-webgl.js --outfile=spine-webgl/dist/iife/spine-webgl.min.js && npx esbuild --minify spine-webgl/dist/esm/spine-webgl.mjs --outfile=spine-webgl/dist/esm/spine-webgl.min.mjs && npx esbuild --minify spine-threejs/dist/iife/spine-threejs.js --outfile=spine-threejs/dist/iife/spine-threejs.min.js && npx esbuild --minify spine-threejs/dist/esm/spine-threejs.mjs --outfile=spine-threejs/dist/esm/spine-threejs.min.mjs && npx esbuild --minify spine-pixi-v7/dist/iife/spine-pixi-v7.js --outfile=spine-pixi-v7/dist/iife/spine-pixi-v7.min.js && npx esbuild --minify spine-pixi-v7/dist/esm/spine-pixi-v7.mjs --outfile=spine-pixi-v7/dist/esm/spine-pixi-v7.min.mjs && npx esbuild --minify spine-pixi-v8/dist/iife/spine-pixi-v8.js --outfile=spine-pixi-v8/dist/iife/spine-pixi-v8.min.js && npx esbuild --minify spine-pixi-v8/dist/esm/spine-pixi-v8.mjs --outfile=spine-pixi-v8/dist/esm/spine-pixi-v8.min.mjs && npx esbuild --minify spine-webcomponents/dist/iife/spine-webcomponents.js --outfile=spine-webcomponents/dist/iife/spine-webcomponents.min.js && npx esbuild --minify spine-webcomponents/dist/esm/spine-webcomponents.mjs --outfile=spine-webcomponents/dist/esm/spine-webcomponents.min.mjs",
"dev": "concurrently \"npx alive-server\" \"npm run dev:canvas\" \"npm run dev:canvaskit\" \"npm run dev:webgl\" \"npm run dev:phaser-v3\" \"npm run dev:phaser-v4\" \"npm run dev:player\" \"npm run dev:threejs\" \"npm run dev:pixi-v7\" \"npm run dev:pixi-v8\" \"npm run dev:webcomponents\" \"npm run dev:modules\"",
"dev": "concurrently \"npx alive-server --cors\" \"npm run dev:canvas\" \"npm run dev:canvaskit\" \"npm run dev:webgl\" \"npm run dev:phaser-v3\" \"npm run dev:phaser-v4\" \"npm run dev:player\" \"npm run dev:threejs\" \"npm run dev:pixi-v7\" \"npm run dev:pixi-v8\" \"npm run dev:webcomponents\" \"npm run dev:modules\" \"npm run dev:construct3\" \"npm run dev:construct3-lib\"",
"dev:modules": "npm run build:modules -- --watch",
"dev:canvas": "concurrently \"npm run build:canvas:iife -- --watch\" \"npm run build:canvas:esm -- --watch\"",
"dev:canvaskit": "concurrently \"npm run build:canvaskit:iife -- --watch\" \"npm run build:canvaskit:esm -- --watch\"",
"dev:construct3": "tsc-watch --project spine-construct3/tsconfig.json --onCompilationComplete \"npm run build:construct3:copy-assets\"",
"dev:construct3-lib": "npm run build:construct3-lib -- --watch",
"dev:webgl": "concurrently \"npm run build:webgl:iife -- --watch\" \"npm run build:webgl:esm -- --watch\"",
"dev:phaser-v3": "concurrently \"npm run build:phaser-v3:iife -- --watch\" \"npm run build:phaser-v3:esm -- --watch\"",
"dev:phaser-v4": "concurrently \"npm run build:phaser-v4:iife -- --watch\" \"npm run build:phaser-v4:esm -- --watch\"",
@ -73,13 +78,15 @@
"workspaces": [
"spine-core",
"spine-canvas",
"spine-canvaskit",
"spine-construct3",
"spine-construct3-lib",
"spine-phaser-v3",
"spine-phaser-v4",
"spine-player",
"spine-threejs",
"spine-pixi-v7",
"spine-pixi-v8",
"spine-canvaskit",
"spine-webgl",
"spine-webcomponents"
],
@ -87,10 +94,12 @@
"@biomejs/biome": "^2.1.1",
"@types/offscreencanvas": "^2019.7.3",
"alive-server": "^1.3.0",
"chokidar-cli": "^3.0.0",
"concurrently": "^9.2.0",
"copyfiles": "^2.4.1",
"esbuild": "^0.25.6",
"rimraf": "^6.0.1",
"tsc-watch": "^7.1.1",
"typescript": "^5.8.3",
"typescript-formatter": "^7.2.2"
}

View File

@ -0,0 +1,26 @@
Spine Runtimes License Agreement
Last updated April 5, 2025. Replaces all prior versions.
Copyright (c) 2013-2025, Esoteric Software LLC
Integration of the Spine Runtimes into software or otherwise creating
derivative works of the Spine Runtimes is permitted under the terms and
conditions of Section 2 of the Spine Editor License Agreement:
http://esotericsoftware.com/spine-editor-license
Otherwise, it is permitted to integrate the Spine Runtimes into software
or otherwise create derivative works of the Spine Runtimes (collectively,
"Products"), provided that each user of the Products must obtain their own
Spine Editor license and redistribution of the Products in any form must
include this license and copyright notice.
THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,3 @@
# spine-ts THREE.JS
Please see the top-level [README.md](../README.md) for more information.

View File

@ -0,0 +1,52 @@
// build.js
import * as fs from 'node:fs';
import * as esbuild from 'esbuild';
// Plugin to append string after build
const appendStringPlugin = {
name: 'append-string',
setup(build) {
build.onEnd((result) => {
if (result.errors.length === 0) {
const outputFile = 'spine-construct3-lib/dist/iife/spine-construct3-lib.js';
try {
const content = fs.readFileSync(outputFile, 'utf8');
const appendString = 'if(!globalThis.spine)globalThis.spine=spine';
// Only append if not already present
if (!content.includes(appendString)) {
fs.writeFileSync(outputFile, `${content}\n${appendString}`);
console.log('✓ Appended spine global assignment');
}
} catch (err) {
console.error('Error appending string:', err);
}
}
});
}
};
// Check if watch mode is requested
const isWatch = process.argv.includes('--watch');
// Build configuration
const buildOptions = {
entryPoints: ['spine-construct3-lib/src/index.ts'],
bundle: true,
outfile: 'spine-construct3-lib/dist/iife/spine-construct3-lib.js',
tsconfig: 'spine-construct3-lib/tsconfig.json',
sourcemap: true,
format: 'iife',
globalName: 'spine',
plugins: [appendStringPlugin],
};
if (isWatch) {
const ctx = await esbuild.context(buildOptions);
await ctx.watch();
console.log('👀 Watching for changes...');
} else {
await esbuild.build(buildOptions);
console.log('✅ Build complete');
}

View File

@ -0,0 +1,36 @@
{
"name": "@esotericsoftware/spine-construct3-lib",
"version": "4.2.82",
"description": "The official Spine Runtimes for the web.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
"files": [
"dist/**/*",
"README.md",
"LICENSE"
],
"scripts": {},
"repository": {
"type": "git",
"url": "git+https://github.com/esotericsoftware/spine-runtimes.git"
},
"keywords": [
"gamedev",
"animations",
"2d",
"spine",
"game-dev",
"runtimes",
"skeletal"
],
"author": "Esoteric Software LLC",
"license": "LicenseRef-LICENSE",
"bugs": {
"url": "https://github.com/esotericsoftware/spine-runtimes/issues"
},
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
"dependencies": {
"@esotericsoftware/spine-core": "4.2.82"
}
}

View File

@ -0,0 +1,150 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { AtlasAttachmentLoader, SkeletonBinary, SkeletonJson, TextureAtlas } from "@esotericsoftware/spine-core";
import { C3Texture, C3TextureEditor } from "./C3Texture";
export class AssetLoader {
constructor (private type: "editor" | "runtime") {
}
public async loadSkeletonEditor (path: string, textureAtlas: TextureAtlas, instance: SDK.IWorldInstance) {
const projectFile = instance.GetProject().GetProjectFileByName(path);
if (!projectFile) return null;
const blob = projectFile.GetBlob();
const atlasLoader = new AtlasAttachmentLoader(textureAtlas);
const isBinary = path.endsWith(".skel");
if (isBinary) {
const skeletonFile = await blob.arrayBuffer();
const skeletonLoader = new SkeletonBinary(atlasLoader);
skeletonLoader.scale = 1;
return skeletonLoader.readSkeletonData(skeletonFile);
}
const skeletonFile = await blob.text();
const skeletonLoader = new SkeletonJson(atlasLoader);
skeletonLoader.scale = 1;
return skeletonLoader.readSkeletonData(skeletonFile);
}
public async loadAtlasEditor (path: string, instance: SDK.IWorldInstance, renderer: SDK.Gfx.IWebGLRenderer) {
const projectFile = instance.GetProject().GetProjectFileByName(path);
if (!projectFile) return null;
const blob = projectFile.GetBlob();
const content = await blob.text();
const textureAtlas = new TextureAtlas(content);
await Promise.all(textureAtlas.pages.map(async page => {
const texture = await this.loadSpineTextureEditor(page.name, page.pma, instance);
if (texture) {
const spineTexture = new C3TextureEditor(texture, renderer);
page.setTexture(spineTexture);
}
return texture;
}));
return textureAtlas;
}
public async loadSpineTextureEditor (pageName: string, pma = false, instance: SDK.IWorldInstance) {
const projectFile = instance.GetProject().GetProjectFileByName(pageName);
if (!projectFile) {
throw new Error(`An error occured while loading the texture: ${pageName}`);
}
const content = projectFile.GetBlob();
return this.createImageBitmapFromBlob(content, pma);
}
public async loadSkeletonRuntime (path: string, textureAtlas: TextureAtlas, scale = 1, instance: IRuntime) {
const fullPath = await instance.assets.getProjectFileUrl(path);
if (!fullPath) return null;
const content = await instance.assets.fetchArrayBuffer(fullPath);
if (!content) return null;
const atlasLoader = new AtlasAttachmentLoader(textureAtlas);
const isBinary = path.endsWith(".skel");
if (isBinary) {
const skeletonLoader = new SkeletonBinary(atlasLoader);
skeletonLoader.scale = scale;
return skeletonLoader.readSkeletonData(content);
}
const skeletonLoader = new SkeletonJson(atlasLoader);
skeletonLoader.scale = scale;
return skeletonLoader.readSkeletonData(content);
}
public async loadAtlasRuntime (path: string, instance: IRuntime, renderer: IRenderer) {
const fullPath = await instance.assets.getProjectFileUrl(path);
if (!fullPath) return null;
const content = await instance.assets.fetchText(fullPath);
if (!content) return null;
const textureAtlas = new TextureAtlas(content);
await Promise.all(textureAtlas.pages.map(async page => {
const texture = await this.loadSpineTextureRuntime(page.name, page.pma, instance);
if (texture) {
const spineTexture = new C3Texture(texture, renderer);
page.setTexture(spineTexture);
}
return texture;
}));
return textureAtlas;
}
public async loadSpineTextureRuntime (pageName: string, pma = false, instance: IRuntime) {
const fullPath = await instance.assets.getProjectFileUrl(pageName);
if (!fullPath) return null;
const content = await instance.assets.fetchBlob(fullPath);
if (!content) return null;
return this.createImageBitmapFromBlob(content, pma);
}
private async createImageBitmapFromBlob (blob: Blob, pma: boolean): Promise<ImageBitmap | null> {
try {
return createImageBitmap(blob, { premultiplyAlpha: pma ? "none" : "premultiply" });
} catch (e) {
console.error("Failed to create ImageBitmap from blob:", e);
return null;
}
}
}

View File

@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { BlendMode, Texture, type TextureFilter, type TextureWrap } from "@esotericsoftware/spine-core";
export class C3TextureEditor extends Texture {
texture: SDK.Gfx.IWebGLTexture;
renderer: SDK.Gfx.IWebGLRenderer;
constructor (image: HTMLImageElement | ImageBitmap, renderer: SDK.Gfx.IWebGLRenderer) {
super(image);
this.renderer = renderer;
this.texture = renderer.CreateDynamicTexture(image.width, image.height);
this.renderer.UpdateTexture(image, this.texture);
}
setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
}
setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
}
dispose () {
this.renderer.DeleteTexture(this.texture);
}
}
export class C3Texture extends Texture {
texture: ITexture;
renderer: IRenderer;
constructor (image: HTMLImageElement | ImageBitmap, renderer: IRenderer) {
super(image);
this.renderer = renderer;
this.texture = renderer.createDynamicTexture(image.width, image.height);
this.renderer.updateTexture(image, this.texture);
}
setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
}
setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
}
dispose () {
this.renderer.deleteTexture(this.texture);
}
}
export const BlendingModeSpineToC3: Record<BlendMode, BlendModeParameter> = {
[BlendMode.Normal]: "normal",
[BlendMode.Additive]: "additive",
[BlendMode.Multiply]: "normal",
[BlendMode.Screen]: "normal",
}

View File

@ -0,0 +1,133 @@
import { AnimationState, Physics, Skeleton, SkeletonClipping, Skin } from "@esotericsoftware/spine-core";
interface Rectangle {
x: number;
y: number;
width: number;
height: number;
}
interface GameObject {
skeleton?: Skeleton,
state?: AnimationState,
}
export interface SpineBoundsProvider {
/** Returns the bounding box for the skeleton, in skeleton space. */
calculateBounds (gameObject: GameObject): Rectangle;
}
export class AABBRectangleBoundsProvider implements SpineBoundsProvider {
constructor (
private x: number,
private y: number,
private width: number,
private height: number,
) { }
calculateBounds () {
return { x: this.x, y: this.y, width: this.width, height: this.height };
}
}
export class SetupPoseBoundsProvider implements SpineBoundsProvider {
/**
* @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
*/
constructor (private clipping = false) { }
calculateBounds (gameObject: GameObject) {
if (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };
// Make a copy of animation state and skeleton as this might be called while
// the skeleton in the GameObject has already been heavily modified. We can not
// reconstruct that state.
const skeleton = new Skeleton(gameObject.skeleton.data);
skeleton.setupPose();
skeleton.updateWorldTransform(Physics.update);
const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined);
return bounds.width === Number.NEGATIVE_INFINITY
? { x: 0, y: 0, width: 0, height: 0 }
: bounds;
}
}
export class SkinsAndAnimationBoundsProvider implements SpineBoundsProvider {
/**
* @param animation The animation to use for calculating the bounds. If null, the setup pose is used.
* @param skins The skins to use for calculating the bounds. If empty, the default skin is used.
* @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.
* @param clipping If true, clipping attachments are used to compute the bounds. False, by default.
*/
constructor (
private animation?: string,
private skins: string[] = [],
private timeStep: number = 0.05,
private clipping = false,
) { }
calculateBounds (gameObject: GameObject): {
x: number;
y: number;
width: number;
height: number;
} {
if (!gameObject.skeleton || !gameObject.state)
return { x: 0, y: 0, width: 0, height: 0 };
// Make a copy of animation state and skeleton as this might be called while
// the skeleton in the GameObject has already been heavily modified. We can not
// reconstruct that state.
const animationState = new AnimationState(gameObject.state.data);
const skeleton = new Skeleton(gameObject.skeleton.data);
const clipper = this.clipping ? new SkeletonClipping() : undefined;
const data = skeleton.data;
if (this.skins.length > 0) {
const customSkin = new Skin("custom-skin");
for (const skinName of this.skins) {
const skin = data.findSkin(skinName);
if (skin == null) continue;
customSkin.addSkin(skin);
}
skeleton.setSkin(customSkin);
}
skeleton.setupPose();
const animation = this.animation != null ? data.findAnimation(this.animation!) : null;
if (animation == null) {
skeleton.updateWorldTransform(Physics.update);
const bounds = skeleton.getBoundsRect(clipper);
return bounds.width === Number.NEGATIVE_INFINITY
? { x: 0, y: 0, width: 0, height: 0 }
: bounds;
} else {
let minX = Number.POSITIVE_INFINITY,
minY = Number.POSITIVE_INFINITY,
maxX = Number.NEGATIVE_INFINITY,
maxY = Number.NEGATIVE_INFINITY;
animationState.clearTracks();
animationState.setAnimation(0, animation, false);
const steps = Math.max(animation.duration / this.timeStep, 1.0);
for (let i = 0; i < steps; i++) {
const delta = i > 0 ? this.timeStep : 0;
animationState.update(delta);
animationState.apply(skeleton);
skeleton.update(delta);
skeleton.updateWorldTransform(Physics.update);
const bounds = skeleton.getBoundsRect(clipper);
minX = Math.min(minX, bounds.x);
minY = Math.min(minY, bounds.y);
maxX = Math.max(maxX, bounds.x + bounds.width);
maxY = Math.max(maxY, bounds.y + bounds.height);
}
const bounds = {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
};
return bounds.width === Number.NEGATIVE_INFINITY
? { x: 0, y: 0, width: 0, height: 0 }
: bounds;
}
}
}

View File

@ -0,0 +1,4 @@
export * from "@esotericsoftware/spine-core";
export * from './AssetLoader.js';
export * from './C3Texture.js';
export * from './SpineBoundsProvider.js';

View File

@ -0,0 +1,18 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": "./src",
"outDir": "./dist",
"paths": {
"@esotericsoftware/spine-core": ["../spine-core/src"]
}
},
"include": ["**/*.ts", "../spine-construct3/ts-defs/**/*.d.ts"],
"exclude": ["dist/**/*.d.ts", "example/**/*.ts"],
"references": [
{
"path": "../spine-core"
}
]
}

View File

@ -0,0 +1,249 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://construct.net/sdk/schema/plugin.addon.schema.json",
"title": "Plugin aces.json",
"description": "Plugin JSON file that describes the available actions, conditions and expressions.",
"type": "object",
"properties": {
"$schema": { "type": "string" }
},
"additionalProperties": {
"description": "ACE definitions for a specific category.",
"type": "object",
"properties": {
"conditions": {
"description": "Condition definitions for this category.",
"type": "array",
"items": {
"description": "Condition definition",
"type": "object",
"properties": {
"id": {
"description": "A string specifying a unique ID for the condition.",
"type": "string"
},
"c2id": {
"description": "If you are porting a Construct 2 addon to Construct 3, put the corresponding numerical ID that the Construct 2 addon used here. This allows Construct 3 to import Construct 2 projects using your addon.",
"type": "number"
},
"scriptName": {
"description": "The name of the function in the runtime script for this condition.",
"type": "string"
},
"isDeprecated": {
"description": "Set to true to deprecate the condition. This hides it in the editor, but allows existing projects to continue using it.",
"type": "boolean"
},
"highlight": {
"description": "Set to true to highlight the condition in the picker dialog.",
"type": "boolean"
},
"isTrigger": {
"description": "Specifies a trigger condition. This appears with an arrow in the event sheet. Instead of being evaluated every tick, triggers only run when they are explicity triggered by a runtime call.",
"type": "boolean"
},
"isFakeTrigger": {
"description": "Specifies a fake trigger. This appears identical to a trigger in the event sheet, but is actually evaluated every tick. This is useful for conditions which are true for a single tick, such as for APIs which must poll a value every tick.",
"type": "boolean"
},
"isStatic": {
"description": "Normally, the condition runtime method is executed once per picked instance. If the condition is marked static, the runtime method is executed once only, on the object type class. This means the runtime method must also implement the instance picking entirely itself, including respecting negation and OR blocks.",
"type": "boolean"
},
"isLooping": {
"description": "Display an icon in the event sheet to indicate the condition loops. This should only be used with conditions which implement re-triggering.",
"type": "boolean"
},
"isInvertible": {
"description": "Allow the condition to be inverted in the event sheet. Set to false to disable invert.",
"type": "boolean"
},
"isCompatibleWithTriggers": {
"description": "Allow the condition to be used in the same branch as a trigger. Set to false if the condition does not make sense when used in a trigger, such as the Trigger once condition.",
"type": "boolean"
},
"params": {
"description": "Array of parameters for this condition.",
"type": "array",
"items": { "$ref": "#/$defs/acParameter" }
}
},
"required": ["id", "scriptName"],
"additionalProperties": false
}
},
"actions": {
"description": "Action definitions for this category.",
"type": "array",
"items": {
"description": "Action definition",
"type": "object",
"properties": {
"id": {
"description": "A string specifying a unique ID for the action.",
"type": "string"
},
"c2id": {
"description": "If you are porting a Construct 2 addon to Construct 3, put the corresponding numerical ID that the Construct 2 addon used here. This allows Construct 3 to import Construct 2 projects using your addon.",
"type": "number"
},
"scriptName": {
"description": "The name of the function in the runtime script for this action.",
"type": "string"
},
"isDeprecated": {
"description": "Set to true to deprecate the action. This hides it in the editor, but allows existing projects to continue using it.",
"type": "boolean"
},
"highlight": {
"description": "Set to true to highlight the action in the picker dialog.",
"type": "boolean"
},
"isAsync": {
"description": "Set to true to mark the action as asynchronous. Make the action method an async function, and the system 'Wait for previous actions to complete' action will be able to wait for the action as well.",
"type": "boolean"
},
"params": {
"description": "Array of parameters for this action.",
"type": "array",
"items": { "$ref": "#/$defs/acParameter" }
}
},
"required": ["id", "scriptName"],
"additionalProperties": false
}
},
"expressions": {
"description": "Expression definitions for this category.",
"type": "array",
"items": {
"description": "Expression definition",
"type": "object",
"properties": {
"id": {
"description": "A string specifying a unique ID for the expression.",
"type": "string"
},
"c2id": {
"description": "If you are porting a Construct 2 addon to Construct 3, put the corresponding numerical ID that the Construct 2 addon used here. This allows Construct 3 to import Construct 2 projects using your addon.",
"type": "number"
},
"expressionName": {
"description": "The name typed in by the user for this expression, which is also used as the name of the function in the runtime script.",
"type": "string"
},
"isDeprecated": {
"description": "Set to true to deprecate the expression. This hides it in the editor, but allows existing projects to continue using it.",
"type": "boolean"
},
"highlight": {
"description": "Set to true to highlight the expression in the picker dialog.",
"type": "boolean"
},
"returnType": {
"description": "The type of value returned by the expression.",
"enum": ["number", "string", "any"]
},
"isVariadicParameters": {
"description": "If true, Construct will allow the user to enter any number of parameters beyond those defined. In other words the parameters (if any) listed in \"params\" are required, but this flag enables adding further \"any\" type parameters beyond the end.",
"type": "boolean"
},
"params": {
"description": "Array of parameters for this action.",
"type": "array",
"items": { "$ref": "#/$defs/expParameter" }
}
},
"required": ["id", "expressionName"],
"additionalProperties": false
}
}
}
},
"$defs": {
"acParameter": {
"description": "A parameter for a condition or action.",
"type": "object",
"properties": {
"id": {
"description": "A string with a unique identifier for this parameter.",
"type": "string"
},
"c2id": {
"description": "In some circumstances, it is necessary to specify which Construct 2 parameter ID a parameter corresponds to. However normally it can be inferred by the parameter index.",
"type": "number"
},
"type": {
"description": "The parameter type.",
"enum": ["number", "string", "any", "boolean", "combo", "combo-grouped", "cmp", "object", "objectname", "layer", "layout", "keyb", "instancevar", "instancevarbool", "eventvar", "eventvarbool", "animation", "objinstancevar", "projectfile"]
},
"initialValue": {
"description": "A string which is used as the initial expression for expression-based parameters. Note this is still a string for \"number\" type parameters. It can contain any valid expression for the parameter, such as \"1 + 1\". For \"boolean\" parameters, use a string of either \"true\" or \"false\". For \"combo\" parameters, this is the initial item ID.",
"type": "string"
},
"items": {
"description": "Only valid with the \"combo\" type. Set to an array of item IDs available in the dropdown list.",
"type": "array",
"items": { "type": "string" },
"minItems": 1
},
"itemGroups": {
"description": "Only valid with the \"combo-grouped\" type. Set to an array of item groups available in the dropdown list.",
"type": "array",
"items": {
"description": "A combo item group.",
"type": "object",
"properties": {
"id": {
"description": "The combo item group ID.",
"type": "string"
},
"items": {
"description": "Array of item IDs available in this item group.",
"type": "array",
"items": { "type": "string" },
"minItems": 1
}
}
},
"minItems": 1
},
"filter": {
"description": "Only valid with the \"projectfile\" type. Set to a string of a file extension e.g. \".txt\" to filter the project file list by.",
"type": "string"
},
"allowedPluginIds": {
"description": "Optional and only valid with the \"object\" type. Set to an array of plugin IDs allowed to be shown by the object picker. For example, use [\"Sprite\"] to only allow the object parameter to select a Sprite.",
"type": "array",
"items": { "type": "string" },
"minItems": 1
},
"autocompleteId": {
"description": "Optional and only valid with the \"string\" type. Set to a globally unique ID and string constants with the same ID will offer autocomplete in the editor. Useful for tag parameters.",
"type": "string"
}
},
"required": ["id", "type"]
},
"expParameter": {
"description": "A parameter for an expression.",
"type": "object",
"properties": {
"id": {
"description": "A string with a unique identifier for this parameter.",
"type": "string"
},
"c2id": {
"description": "In some circumstances, it is necessary to specify which Construct 2 parameter ID a parameter corresponds to. However normally it can be inferred by the parameter index.",
"type": "number"
},
"type": {
"description": "The parameter type.",
"enum": ["number", "string", "any"]
}
},
"required": ["id", "type"]
}
}
}

View File

@ -0,0 +1,36 @@
{
"name": "@esotericsoftware/spine-construct3",
"version": "4.2.82",
"description": "The official Spine Runtimes for Construct3",
"main": "dist/plugin.js",
"types": "dist/plugin.d.ts",
"type": "module",
"files": [
"dist/**/*",
"README.md",
"LICENSE"
],
"scripts": {},
"repository": {
"type": "git",
"url": "git+https://github.com/esotericsoftware/spine-runtimes.git"
},
"keywords": [
"gamedev",
"animations",
"2d",
"spine",
"game-dev",
"runtimes",
"skeletal"
],
"author": "Esoteric Software LLC",
"license": "LicenseRef-LICENSE",
"bugs": {
"url": "https://github.com/esotericsoftware/spine-runtimes/issues"
},
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
"dependencies": {
"@esotericsoftware/spine-construct3-lib": "^4.2.82"
}
}

View File

@ -0,0 +1,73 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://construct.net/sdk/schema/plugin.addon.schema.json",
"title": "Plugin addon.json",
"description": "Main JSON file that describes metadata about a plugin.",
"type": "object",
"properties": {
"is-c3-addon": {
"description": "This is used by Construct to identify valid addons.",
"const": true
},
"sdk-version": {
"description": "The version of the Addon SDK used for this addon.",
"enum": [1, 2]
},
"type": {
"description": "Indicates the addon type. For the plugin schema, this must be \"plugin\".",
"const": "plugin"
},
"name": {
"description": "The displayed name of the addon, in English. This can be changed after release.",
"type": "string"
},
"id": {
"description": "The unique ID of the addon. This must not be used by any other addon ever published for Construct, and must never change after you first publish your addon. It is recommended to use a vendor-specific prefix, e.g. MyCompany_MyAddon.",
"type": "string"
},
"version": {
"description": "A string specifying the addon version in four parts (major, minor, patch, revision).",
"type": "string"
},
"min-construct-version": {
"description": "The minimum Construct version required to use this addon, e.g. \"r400\"",
"type": "string"
},
"supports-worker-mode": {
"description": "Whether the addon supports running in worker mode, where the Construct runtime is hosted in a Web Worker. Defaults to true; if set to false the presence of the addon in a project will block the runtime from using worker mode.",
"type": "boolean"
},
"author": {
"description": "A string identifying the author of the addon.",
"type": "string"
},
"website": {
"description": "A string of a URL to the author's website. It is recommended to provide updates to the addon at this URL if any become available. The website should use HTTPS.",
"type": "string",
"format": "uri"
},
"documentation": {
"description": "A string of a URL to the online documentation for the addon. It is important to provide documentation for your addon to be useful to users.",
"type": "string",
"format": "uri"
},
"description": {
"description": "A string of a brief description of what the addon does, displayed when prompting the user to install the addon.",
"type": "string"
},
"editor-scripts": {
"description": "An array of script files in the addon package to load in the editor.",
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
},
"file-list": {
"description": "A list of all files used by the addon. Required for Developer Mode addons to work.",
"type": "array",
"items": { "type": "string" }
}
},
"required": ["is-c3-addon", "type", "name", "id", "version", "author", "website", "documentation", "description", "editor-scripts"]
}

View File

@ -0,0 +1,208 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://construct.net/sdk/schema/plugin.lang.schema.json",
"title": "Plugin language file JSON",
"description": "The language file with strings for a plugin.",
"type": "object",
"properties": {
"languageTag": {
"description": "An IETF language tag defining the translation language, e.g. \"en-US\".",
"type": "string"
},
"fileDescription": {
"description": "Optional description for this file (as a comment only).",
"type": "string"
},
"text": {
"type": "object",
"properties": {
"plugins": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"name": {
"description": "The display name of the plugin.",
"type": "string"
},
"description": {
"description": "The description of the plugin.",
"type": "string"
},
"help-url": {
"description": "A URL for documentation or support.",
"type": "string",
"format": "uri"
},
"properties": {
"description": "Language strings for plugin properties.",
"type": "object",
"additionalProperties": {
"description": "Language strings for a plugin property by its ID.",
"type": "object",
"properties": {
"name": {
"description": "Name of this plugin property.",
"type": "string"
},
"desc": {
"description": "Description of this plugin property.",
"type": "string"
},
"items": {
"$ref": "#/$defs/comboItems"
},
"itemGroups": {
"$ref": "#/$defs/comboItemGroups"
},
"link-text": {
"description": "Link text for a \"link\" type property.",
"type": "string"
}
},
"required": ["name", "desc"],
"additionalProperties": false
}
},
"aceCategories": {
"description": "Language strings for action/condition/expression categories.",
"type": "object",
"additionalProperties": {
"description": "Language string for an action/condition/expression category.",
"type": "string"
}
},
"conditions": {
"type": "object",
"additionalProperties": { "$ref": "#/$defs/acEntry" }
},
"actions": {
"type": "object",
"additionalProperties": { "$ref": "#/$defs/acEntry" }
},
"expressions": {
"type": "object",
"additionalProperties": { "$ref": "#/$defs/expEntry" }
}
},
"required": ["name", "description", "help-url"]
},
"minProperties": 1,
"maxProperties": 1
}
},
"required": ["plugins"],
"additionalProperties": false
}
},
"required": ["languageTag", "text"],
"$defs": {
"acEntry": {
"description": "Language strings for conditions or actions by their ID.",
"type": "object",
"properties": {
"list-name": {
"description": "The name that appears in the condition/action picker dialog.",
"type": "string"
},
"display-text": {
"description": "The text that appears in the event sheet. You can use simple BBCode tags like [b] and [i], and use {0}, {1} etc. as parameter placeholders.",
"type": "string"
},
"description": {
"description": "A description of the action or condition, which appears as a tip at the top of the condition/action picker dialog.",
"type": "string"
},
"params": {
"description": "Language strings for parameters of a condition or action.",
"type": "object",
"additionalProperties": {
"description": "Language strings for a parameter of a condition or action by the parameter ID.",
"type": "object",
"properties": {
"name": {
"description": "Language string for a parameter name.",
"type": "string"
},
"desc": {
"description": "Language string for a parameter description.",
"type": "string"
},
"items": {
"$ref": "#/$defs/comboItems"
}
},
"required": ["name", "desc"],
"additionalProperties": false
}
}
},
"required": ["list-name", "display-text", "description"],
"additionalProperties": false
},
"expEntry": {
"description": "Language strings for expressions by their ID.",
"type": "object",
"properties": {
"description": {
"description": "A description of the action or condition, which appears as a tip at the top of the condition/action picker dialog.",
"type": "string"
},
"translated-name": {
"description": "The translated name of the expression, which must be a valid expression identifier (e.g. no quotes/apostrophes or other characters with special meaning in expressions). Note for en-US this must match the expression name."
},
"params": {
"description": "Language strings for parameters of an expression.",
"type": "object",
"additionalProperties": {
"description": "Language strings for a parameter of an expression by the parameter ID.",
"type": "object",
"properties": {
"name": {
"description": "Language string for a parameter name.",
"type": "string"
},
"desc": {
"description": "Language string for a parameter description.",
"type": "string"
}
},
"required": ["name", "desc"],
"additionalProperties": false
}
}
},
"required": ["description", "translated-name"],
"additionalProperties": false
},
"comboItems": {
"description": "Items for a combo property, parameter or group.",
"type": "object",
"minProperties": 1,
"additionalProperties": {
"description": "Language string for a combo item, with the item ID as the key.",
"type": "string"
}
},
"comboItemGroups": {
"description": "Items for a combo-grouped parameter.",
"type": "object",
"minProperties": 1,
"additionalProperties": {
"description": "Language string for a combo item group.",
"type": "object",
"properties": {
"name": {
"description": "Name of this combo item group.",
"type": "string"
},
"items": {
"$ref": "#/$defs/comboItems"
}
},
"required": ["name", "items"]
}
}
}
}

7
spine-ts/spine-construct3/spine.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
import type * as Spine from '@esotericsoftware/spine-construct3-lib';
declare global {
namespace globalThis {
var spine: typeof Spine;
}
}

View File

@ -0,0 +1,85 @@
{
"$schema": "../aces.schema.json",
"custom": {
"conditions": [
{
"id": "on-skeleton-loaded",
"scriptName": "OnSkeletonLoaded",
"isTrigger": true
},
{
"id": "on-animation-event",
"scriptName": "OnAnimationEvent",
"isTrigger": true,
"params": [
{
"id": "event",
"type": "string",
"initial-value": "complete"
},
{
"id": "track",
"type": "number",
"initial-value": 0
},
{
"id": "animation",
"type": "string"
}
]
}
],
"actions": [
{
"id": "do-alert",
"scriptName": "Alert",
"highlight": true
},
{
"id": "set-skin",
"scriptName": "SetSkin",
"highlight": false,
"params": [
{
"id": "skin-name",
"type": "string"
}
]
},
{
"id": "set-animation",
"scriptName": "SetAnimation",
"highlight": false,
"params": [
{
"id": "track",
"type": "number"
},
{
"id": "animation",
"type": "string"
},
{
"id": "loop",
"type": "boolean"
}
]
}
],
"expressions": [
{
"id": "double",
"expressionName": "Double",
"highlight": true,
"returnType": "number",
"params": [
{
"id": "number",
"type": "number"
}
]
}
]
}
}

View File

@ -0,0 +1,38 @@
{
"$schema": "./plugin.addon.schema.json",
"is-c3-addon": true,
"sdk-version": 2,
"min-construct-version": "r401",
"type": "plugin",
"name": "My Spine plugin",
"id": "EsotericSoftware_SpineConstruct3",
"version": "1.0.0.1",
"author": "Esoteric Software",
"website": "https://www.esotericsoftware.com",
"documentation": "https://www.esotericsoftware.com",
"description": "Example custom drawing Construct 3 plugin.",
"editor-scripts": [
"plugin.js",
"type.js",
"instance.js",
"c3runtime/spine-construct3-lib.js"
],
"file-list": [
"c3runtime/main.js",
"c3runtime/plugin.js",
"c3runtime/type.js",
"c3runtime/instance.js",
"c3runtime/conditions.js",
"c3runtime/actions.js",
"c3runtime/expressions.js",
"lang/en-US.json",
"aces.json",
"addon.json",
"icon.svg",
"plugin.js",
"c3runtime/spine-construct3-lib.js",
"type.js",
"instance.js"
]
}

View File

@ -0,0 +1,20 @@
import type { SDKInstanceClass } from "./instance.ts";
const C3 = globalThis.C3;
C3.Plugins.EsotericSoftware_SpineConstruct3.Acts =
{
Alert (this: SDKInstanceClass) {
alert("Test property = " + this._getTestProperty());
},
SetSkin (this: SDKInstanceClass, skinList: string) {
this.setSkin(skinList.split(","));
},
SetAnimation (this: SDKInstanceClass, track: number, animation: string, loop = false) {
this.setAnimation(track, animation, loop);
}
};

View File

@ -0,0 +1,19 @@
import type { SDKInstanceClass } from "./instance.ts";
const C3 = globalThis.C3;
C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds =
{
OnSkeletonLoaded (this: SDKInstanceClass) {
return true;
},
OnAnimationEvent (this: SDKInstanceClass, event: string, track: number, animation: string) {
console.log(this.triggeredEventName === event
&& this.triggeredEventTrack === track
&& this.triggeredEventAnimation === animation);
return this.triggeredEventName === event
&& this.triggeredEventTrack === track
&& this.triggeredEventAnimation === animation;
},
};

View File

@ -0,0 +1,13 @@
import type { SDKInstanceClass } from "./instance.ts";
const C3 = globalThis.C3;
C3.Plugins.EsotericSoftware_SpineConstruct3.Exps =
{
Double(this: SDKInstanceClass, num: number)
{
return num * 2;
}
};

View File

@ -0,0 +1,289 @@
import { AnimationEventType, AnimationStateListener, BlendingModeSpineToC3, EventType, TrackEntry, type AnimationState, type AssetLoader, type Event, type Skeleton, type SkeletonRendererCore, type SpineBoundsProvider, type TextureAtlas } from "@esotericsoftware/spine-construct3-lib";
const C3 = globalThis.C3;
const spine = globalThis.spine;
spine.Skeleton.yDown = true;
class DrawingInstance extends globalThis.ISDKWorldInstanceBase {
atlasProp = "";
skelProp = "";
skinProp: string[] = [];
animationProp?: string;
textureAtlas?: TextureAtlas;
renderer?: IRenderer;
atlasLoaded = false;
atlasLoading = false;
skeletonLoaded = false;
skeletonLoading = false;
skeleton?: Skeleton;
state?: AnimationState;
private ratio: number;
private assetLoader: AssetLoader;
private skeletonRenderer: SkeletonRendererCore;
private spineBoundsProvider: SpineBoundsProvider;
private _spineBounds?: {
x: number;
y: number;
width: number;
height: number;
};
constructor () {
super();
const properties = this._getInitProperties();
if (properties) {
this.atlasProp = properties[0] as string;
this.skelProp = properties[1] as string;
const skinProp = properties[2] as string;
this.skinProp = skinProp === "" ? [] : skinProp.split(",");
this.animationProp = properties[3] as string;
console.log(properties);
}
this.assetLoader = new spine.AssetLoader("runtime");
this.skeletonRenderer = new spine.SkeletonRendererCore();
if (this.animationProp || (this.skinProp && this.skinProp.length > 0)) {
this.spineBoundsProvider = new spine.SkinsAndAnimationBoundsProvider(this.animationProp, this.skinProp);
} else {
this.spineBoundsProvider = new spine.SetupPoseBoundsProvider();
}
this.ratio = this.width / this.height;
this._setTicking(true);
}
_tick (): void {
const { renderer } = this;
if (!renderer) return;
if (!this.atlasLoaded) {
this._loadAtlas();
return;
}
if (!this.skeletonLoaded) {
this.loadSkeleton();
return;
}
this.x++;
this.x--;
this.update(this.dt);
}
private async loadSkeleton () {
if (this.skeletonLoading) return;
if (!this.atlasLoaded) return;
this.skeletonLoading = true;
const propValue = this.skelProp;
if (this.atlasLoaded && this.textureAtlas) {
const skeletonData = await this.assetLoader.loadSkeletonRuntime(propValue, this.textureAtlas, 0.25, this.plugin.runtime);
if (!skeletonData) return;
this.skeleton = new spine.Skeleton(skeletonData);
const animationStateData = new spine.AnimationStateData(skeletonData);
this.state = new spine.AnimationState(animationStateData);
if (this.animationProp) {
this.setAnimation(0, this.animationProp, true);
}
this._setSkin();
this.update(0);
this._spineBounds = this.spineBoundsProvider.calculateBounds(this);
// Initially, width and height are values set on C3 Editor side that allows to determine the right scale
this.skeleton.scaleX = this.width / this._spineBounds.width;
this.skeleton.scaleY = this.height / this._spineBounds.height;
this.setSize(this._spineBounds.width * this.skeleton.scaleX, this._spineBounds.height * -this.skeleton.scaleY);
this.setOrigin(-this._spineBounds.x * this.skeleton.scaleX / this.width, this._spineBounds.y * this.skeleton.scaleY / this.height);
this.skeletonLoaded = true;
this._trigger(C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds.OnSkeletonLoaded);
}
}
public triggeredEventTrack = -1;
public triggeredEventAnimation = "";
public triggeredEventName = "";
public triggeredEventData?: Event;
private triggetAnimationEvent (eventName: string, track: number, animation: string, event?: Event) {
this.triggeredEventTrack = track;
this.triggeredEventAnimation = animation;
this.triggeredEventName = eventName;
this.triggeredEventData = event;
this._trigger(C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds.OnAnimationEvent);
}
public setAnimation (track: number, animation: string, loop = false) {
const trackEntry = this.state?.setAnimation(track, animation, loop);
if (!trackEntry) return;
trackEntry.listener = {
start: () => {
this.triggetAnimationEvent("start", track, animation);
},
dispose: () => {
this.triggetAnimationEvent("dispose", track, animation);
},
event: (_, event) => {
this.triggetAnimationEvent("event", track, animation, event);
},
interrupt: () => {
this.triggetAnimationEvent("interrupt", track, animation);
},
end: () => {
this.triggetAnimationEvent("end", track, animation);
},
complete: () => {
this.triggetAnimationEvent("complete", track, animation);
},
}
}
public setSkin (skins: string[]) {
this.skinProp = skins;
this._setSkin();
}
private _setSkin () {
const { skeleton } = this;
if (!skeleton) return;
const skins = this.skinProp;
if (skins.length === 0) {
skeleton.skin = null;
} else if (skins.length === 1) {
const skinName = skins[0];
const skin = skeleton.data.findSkin(skinName);
if (!skin) {
// TODO: signal error
return;
}
skeleton.setSkin(skins[0]);
} else {
const customSkin = new spine.Skin(skins.join(","));
for (const s of skins) {
const skin = skeleton.data.findSkin(s)
if (!skin) {
// TODO: signal error
return;
}
customSkin.addSkin(skin);
}
skeleton.setSkin(customSkin);
}
skeleton.setupPose();
this.update(0);
}
private update (delta: number) {
const { state, skeleton } = this;
if (!skeleton || !state) return;
state.update(delta);
skeleton.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform(spine.Physics.update);
}
private async _loadAtlas () {
if (this.atlasLoading || !this.renderer) return;
this.atlasLoading = true;
const textureAtlas = await this.assetLoader.loadAtlasRuntime(this.atlasProp, this.plugin.runtime, this.renderer);
if (!textureAtlas) return;
this.textureAtlas = textureAtlas;
this.atlasLoaded = true;
}
_release () {
super._release();
}
private tempVertices = new Float32Array(4096);
private tempColors = new Float32Array(4096);
_draw (renderer: IRenderer) {
this.renderer ||= renderer;
if (!this.isVisible) return;
if (!this.isOnScreen) return;
if (!this.skeleton) return;
let command = this.skeletonRenderer.render(this.skeleton);
const inv255 = 1 / 255;
while (command) {
const { numVertices, positions, uvs, colors, indices, numIndices, blendMode } = command;
const vertices = this.tempVertices;
const c3colors = this.tempColors;
for (let i = 0; i < numVertices; i++) {
const srcIndex = i * 2;
const dstIndex = i * 3;
vertices[dstIndex] = positions[srcIndex] + this.x;
vertices[dstIndex + 1] = positions[srcIndex + 1] + this.y;
vertices[dstIndex + 2] = 0;
// there's something wrong with the hand after adding the colors on spineboy portal animation
const color = colors[i];
const colorDst = i * 4;
c3colors[colorDst] = (color >>> 16 & 0xFF) * inv255;
c3colors[colorDst + 1] = (color >>> 8 & 0xFF) * inv255;
c3colors[colorDst + 2] = (color & 0xFF) * inv255;
c3colors[colorDst + 3] = (color >>> 24 & 0xFF) * inv255 * this.opacity;
}
renderer.setTexture(command.texture.texture);
renderer.setBlendMode(spine.BlendingModeSpineToC3[blendMode]);
renderer.drawMesh(
vertices.subarray(0, numVertices * 3),
uvs.subarray(0, numVertices * 2),
indices.subarray(0, numIndices),
c3colors.subarray(0, numVertices * 4),
);
command = command.next;
}
}
_saveToJson () {
return {
// data to be saved for savegames
};
}
_loadFromJson (o: JSONValue) {
// load state for savegames
}
_setTestProperty (n: number) {
// this._testProperty = n;
}
_getTestProperty () {
// return this._testProperty;
}
};
C3.Plugins.EsotericSoftware_SpineConstruct3.Instance = DrawingInstance;
export type { DrawingInstance as SDKInstanceClass };

View File

@ -0,0 +1,6 @@
import "./plugin.js";
import "./type.js";
import "./instance.js";
import "./conditions.js";
import "./actions.js";
import "./expressions.js";

View File

@ -0,0 +1,13 @@
const C3 = globalThis.C3;
C3.Plugins.EsotericSoftware_SpineConstruct3 = class DrawingPlugin extends globalThis.ISDKPluginBase
{
constructor()
{
super();
}
};
// Necessary for TypeScript to treat this file as a module
export {}

View File

@ -0,0 +1,49 @@
import type { SDKInstanceClass } from "./instance.ts";
const C3 = globalThis.C3;
C3.Plugins.EsotericSoftware_SpineConstruct3.Type = class DrawingType extends globalThis.ISDKObjectTypeBase<SDKInstanceClass>
{
constructor()
{
super();
}
// async _loadTextures(renderer: IRenderer)
// {
// return renderer.loadTextureForImageInfo(this.getImageInfo(), {
// sampling: this.runtime.sampling
// });
// }
// async _loadTextures(renderer: IRenderer)
// {
// return renderer.loadTextureForImageInfo(this.getImageInfo(), {
// sampling: this.runtime.sampling
// });
// }
// getImageInfo(): IImageInfo
// {
// return {
// width: 1,
// height: 1,
// getSize(): Vec2Arr { return [1, 1]; },
// getTexture(renderer: IRenderer): ITexture | null { return null; },
// getTexRect(): DOMRect { return new DOMRect(0, 0, 1, 1); }
// };
// }
// _onCreate()
// {
// this.runtime.assets.loadImageAsset(this.getImageInfo());
// }
// _releaseTextures(renderer: IRenderer)
// {
// renderer.releaseTextureForImageInfo(this.getImageInfo());
// }
};

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="1700.79004px" height="1700.79004px" viewBox="499 379 690 690"
enable-background="new 0 0 1700.79004 1700.79004" xml:space="preserve">
<g id="bg">
<g>
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#D2E1F0" d="M850.39453,860.66992
c-50.35645,0-94.3252-27.35645-117.85254-68.02051l-80.03027,46.2041c-4.6543,2.68945-6.13086,8.71875-3.24805,13.25586
C691.50098,918.5957,765.7959,962.7168,850.39453,962.7168c88.12598,0,165.07129-47.875,206.24316-119.03613l-80.48633-46.46973
c-4.31445-2.49023-9.80273-1.20508-12.57129,2.93555C939.1748,836.64063,897.59082,860.66992,850.39453,860.66992
L850.39453,860.66992z M1136.7207,559.2959c4.61426-2.66309,6.11035-8.61914,3.3125-13.15137
c-59.91504-97.03027-167.22461-161.69434-289.63867-161.69434c-125.89355,0-235.81348,68.39258-294.63379,170.0498
l80.37695,46.40625c4.39844,2.53906,10.00195,1.14941,12.71094-3.14551
c42.16406-66.85156,116.66992-111.26367,201.5459-111.26367c88.12598,0,165.07129,47.87598,206.24316,119.03613
L1136.7207,559.2959z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#96AAB9" d="M850.39453,962.7168
c-84.59863,0-158.89355-44.12109-201.13086-110.60742c-2.87695-4.53027-1.40039-10.57031,3.24805-13.25586l80.03027-46.2041
c-11.58105-20.0166-18.20996-43.25488-18.20996-68.04199c0-74.78516,60.55762-136.0625,136.0625-136.0625
c47.19629,0,88.78027,24.0293,113.18555,60.52246c2.76465,4.13379,8.26367,5.42188,12.57129,2.93555l80.48633-46.46973
c-41.17188-71.16016-118.11719-119.03613-206.24316-119.03613c-84.87598,0-159.38184,44.41211-201.5459,111.26367
c-2.70605,4.29102-8.31836,5.68164-12.71094,3.14551L555.76074,554.5c-28.95215,50.04004-45.52344,108.13965-45.52344,170.10742
c0,186.96484,151.39453,340.1582,340.15723,340.1582c122.41406,0,229.72363-64.66406,289.63867-161.69531
c2.7959-4.52734,1.29492-10.49023-3.3125-13.15234l-80.08301-46.2373
C1015.46582,914.8418,938.52051,962.7168,850.39453,962.7168z"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#00E1C8" d="M1137.18457,761.19141v-73.16797l-63.36523,36.58398
L1137.18457,761.19141L1137.18457,761.19141z M1026.5752,708.24219l120.05859-69.31641
c12.56836-7.25586,28.3457,1.85254,28.3457,16.36621v138.63086c0,14.5127-15.77734,23.62207-28.3457,16.36621
l-120.05859-69.31641C1014.02734,733.72754,1014.02734,715.4873,1026.5752,708.24219z"/>
</g>
</g>
<g id="logo">
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,383 @@
// / <reference types="editor/sdk" />
import type { AnimationState, AssetLoader, Skeleton, SkeletonRendererCore, SpineBoundsProvider, TextureAtlas } from "@esotericsoftware/spine-construct3-lib";
const SDK = globalThis.SDK;
const PLUGIN_CLASS = SDK.Plugins.EsotericSoftware_SpineConstruct3;
let spine: typeof globalThis.spine;
type SpineBoundsProviderType = "setup" | "animation-skin" | "AABB";
class MyDrawingInstance extends SDK.IWorldInstanceBase {
private layoutView?: SDK.UI.ILayoutView;
private renderer?: SDK.Gfx.IWebGLRenderer;
private currentSkelName = "";
private currentAtlasName = "";
private textureAtlas?: TextureAtlas;
skeleton?: Skeleton;
state?: AnimationState;
skins: string[] = [];
currentSkinString?: string;
animation?: string;
private assetLoader: AssetLoader;
private skeletonRenderer: SkeletonRendererCore;
private offsetX = 0;
private offsetY = 0;
private offsetWidth = 0;
private offsetHeight = 0;
private positioningBounds = false;
private spineBoundsProviderType: SpineBoundsProviderType = "setup";
private spineBoundsProvider?: SpineBoundsProvider;
private _spineBounds?: {
x: number;
y: number;
width: number;
height: number;
};
constructor (sdkType: SDK.ITypeBase, inst: SDK.IWorldInstance) {
super(sdkType, inst);
if (!spine) spine = globalThis.spine;
spine.Skeleton.yDown = true;
this.assetLoader = new spine.AssetLoader("editor");
this.skeletonRenderer = new spine.SkeletonRendererCore();
}
Release () {
}
OnCreate () {
console.log("OnCreate");
}
OnPlacedInLayout () {
this.OnMakeOriginalSize();
}
private tempVertices = new Float32Array(4096);
Draw (iRenderer: SDK.Gfx.IWebGLRenderer, iDrawParams: SDK.Gfx.IDrawParams) {
console.log("DRAW");
this.layoutView ||= iDrawParams.GetLayoutView();
this.renderer ||= iRenderer;
this.loadAtlas();
this.loadSkeleton();
if (this.skeleton) {
this.setSkin();
let x = this.overallOffsetX;
let y = this.overallOffsetY;
let width = this.offsetWidth;
let height = this.offsetHeight;
if (!this.positioningBounds) {
x += this._inst.GetX();
y += this._inst.GetY();
width = this._inst.GetWidth();
height = this._inst.GetHeight();
} else {
// x += this._inst.GetX();
// y += this._inst.GetY();
// width += this._inst.GetWidth();
// height += this._inst.GetHeight();
}
const rx = width / this._spineBounds!.width;
console.log(width, this._spineBounds!.width, rx);
const ry = height / this._spineBounds!.height;
this.skeleton.scaleX = rx;
this.skeleton.scaleY = ry;
this.update(0);
let command = this.skeletonRenderer.render(this.skeleton);
while (command) {
const { numVertices, positions, uvs, indices, numIndices } = command;
const vertices = this.tempVertices;
for (let i = 0; i < numVertices; i++) {
const srcIndex = i * 2;
const dstIndex = i * 3;
vertices[dstIndex] = positions[srcIndex] + x;
vertices[dstIndex + 1] = positions[srcIndex + 1] + y;
vertices[dstIndex + 2] = 0;
}
iRenderer.SetAlphaBlend();
iRenderer.SetTexture(command.texture.texture);
iRenderer.DrawMesh(
vertices.subarray(0, numVertices * 3),
uvs.subarray(0, numVertices * 2),
indices.subarray(0, numIndices),
);
command = command.next;
}
// iRenderer.SetAlphaBlend();
// iRenderer.SetColorFillMode();
// iRenderer.SetColorRgba(0.25, 0, 0, 0.25);
// iRenderer.LineRect(this._inst.GetX(), this._inst.GetY(), this._inst.GetWidth(), this._inst.GetHeight());
} else {
// render placeholder
iRenderer.SetAlphaBlend();
iRenderer.SetColorFillMode();
if (this.HadTextureError())
iRenderer.SetColorRgba(0.25, 0, 0, 0.25);
else
iRenderer.SetColorRgba(0, 0, 0.1, 0.1);
iRenderer.Quad(this._inst.GetQuad());
}
}
private overallOffsetX = 0;
private overallOffsetY = 0;
private overallScaleX = 1
async OnPropertyChanged (id: string, value: EditorPropertyValueType) {
console.log("Prop change - Name: " + id + " - Value: " + value);
switch (id) {
case PLUGIN_CLASS.PROP_ATLAS:
this.layoutView?.Refresh();
break;
case PLUGIN_CLASS.PROP_SKELETON:
this.layoutView?.Refresh();
break;
case PLUGIN_CLASS.PROP_SKIN:
this.layoutView?.Refresh();
break;
case PLUGIN_CLASS.PROP_ANIMATION:
this.layoutView?.Refresh();
break;
case PLUGIN_CLASS.PROP_BOUNDS_PROVIDER:
this.setC3Bounds(true);
this.layoutView?.Refresh();
break;
case PLUGIN_CLASS.PROP_BOUNDS_PROVIDER_MOVE:
value = value as boolean
if (value) {
this.overallOffsetX += this._inst.GetX();
this.overallOffsetY += this._inst.GetY();
this.offsetX = this._inst.GetX();
this.offsetY = this._inst.GetY();
this.offsetWidth = this._inst.GetWidth();
this.offsetHeight = this._inst.GetHeight();
} else {
const w = this.offsetWidth;
this.overallOffsetX -= this._inst.GetX();
this.overallOffsetY -= this._inst.GetY();
this.offsetX -= this._inst.GetX();
this.offsetY -= this._inst.GetY();
this.offsetWidth -= this._inst.GetWidth();
this.offsetHeight -= this._inst.GetHeight();
console.log("OFFSETS");
console.log(this.offsetX);
console.log(this.offsetY);
console.log(this.overallOffsetX);
console.log(this.overallOffsetY);
console.log("OFFSETS");
this.spineBoundsProvider = new spine.AABBRectangleBoundsProvider(
this._spineBounds!.x - this.offsetX,
this._spineBounds!.y - this.offsetY,
this._spineBounds!.width - this.offsetWidth,
this._spineBounds!.height - this.offsetHeight,
);
this._spineBounds = this.spineBoundsProvider.calculateBounds(this);
const { x, y, width, height } = this._spineBounds;
console.log(this._inst.GetX(), this._inst.GetY());
console.log(x, y, width, height, (-x) / width, (-y) / height);
// this._inst.SetSize(width, height);
// this._inst.SetOrigin(-x / width, -y / height);
}
this.positioningBounds = value;
break;
}
console.log("Prop change end");
}
private setSkin () {
const { skeleton } = this;
if (!skeleton) return;
const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKIN) as string;
if (this.currentSkinString === propValue) return;
this.currentSkinString = propValue;
const skins = propValue === "" ? [] : propValue.split(",");
this.skins = skins;
if (skins.length === 1) {
const skinName = skins[0];
const skin = skeleton.data.findSkin(skinName);
if (!skin) {
// TODO: signal error
return;
}
skeleton.setSkin(skins[0]);
} else if (skins.length > 1) {
const customSkin = new spine.Skin(propValue);
for (const s of skins) {
const skin = skeleton.data.findSkin(s)
if (!skin) {
// TODO: signal error
return;
}
customSkin.addSkin(skin);
}
skeleton.setSkin(customSkin);
}
skeleton.setupPose();
this.update(0);
this.setC3Bounds();
}
private async loadSkeleton () {
const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKELETON) as string;
const projectFile = this._inst.GetProject().GetProjectFileByName(propValue);
if (projectFile && this.textureAtlas) {
if (this.currentSkelName === propValue) return;
this.currentSkelName = propValue;
const skeletonData = await this.assetLoader.loadSkeletonEditor(propValue, this.textureAtlas, this._inst);
if (!skeletonData) return;
this.skeleton = new spine.Skeleton(skeletonData);
const animationStateData = new spine.AnimationStateData(skeletonData);
this.state = new spine.AnimationState(animationStateData);
this.update(0);
this.setSkin();
this.setC3Bounds(true);
console.log("SKELETON LOADED");
}
}
private setC3Bounds (init = false) {
const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_PROVIDER) as SpineBoundsProviderType;
console.log(propValue);
if (propValue === "animation-skin") {
const { skins, animation } = this;
if ((skins && skins.length > 0) || animation) {
this.spineBoundsProvider = new spine.SkinsAndAnimationBoundsProvider(animation, skins);
} else {
throw new Error("One among skin and animation needs to have a value to set this bounds provider.");
}
} else if (propValue === "setup") {
this.spineBoundsProvider = new spine.SetupPoseBoundsProvider();
} else {
this.spineBoundsProvider = new spine.AABBRectangleBoundsProvider(0, 0, 100, 100);
}
this._spineBounds = this.spineBoundsProvider.calculateBounds(this);
const { x, y, width, height } = this._spineBounds;
if (width <= 0 || height <= 0 || !init) return;
this._inst.SetSize(width, height);
this._inst.SetOrigin(-x / width, -y / height);
}
private update (delta: number) {
const { state, skeleton } = this;
if (!skeleton || !state) return;
state.update(delta);
skeleton.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform(spine.Physics.update);
}
private async loadAtlas () {
if (!this.renderer) return;
const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_ATLAS) as string;
if (this.currentAtlasName === propValue) return;
this.currentAtlasName = propValue;
const textureAtlas = await this.assetLoader.loadAtlasEditor(propValue, this._inst, this.renderer);
if (!textureAtlas) return;
this.textureAtlas = textureAtlas;
this.layoutView?.Refresh();
}
GetTexture () {
const image = this.GetObjectType().GetImage();
return super.GetTexture(image);
}
IsOriginalSizeKnown () {
return true;
}
GetOriginalWidth () {
if (!this._spineBounds) return 100;
return this._spineBounds.width;
}
GetOriginalHeight () {
if (!this._spineBounds) return 100;
return this._spineBounds.height;
}
OnMakeOriginalSize () {
if (!this._spineBounds)
this._inst.SetSize(100, 100);
else
this._inst.SetSize(this._spineBounds.width, this._spineBounds.height);
}
HasDoubleTapHandler () {
return false;
}
OnDoubleTap () { }
LoadC2Property (name: string, valueString: string) {
return false; // not handled
}
};
PLUGIN_CLASS.Instance = MyDrawingInstance;
export type { MyDrawingInstance as SDKEditorInstanceClass };

View File

@ -0,0 +1,132 @@
{
"$schema": "../../plugin.lang.schema.json",
"languageTag": "en-US",
"fileDescription": "Strings for MyDrawingPlugin.",
"text": {
"plugins": {
"esotericsoftware_spineconstruct3": {
"name": "Spine",
"description": "Spine runtime for Construct3.",
"help-url": "https://www.construct.net",
"properties": {
"spine-skeleton-file": {
"name": "Skeleton",
"desc": "Skeleton file"
},
"spine-atlas-file": {
"name": "Atlas",
"desc": "Atlas file"
},
"spine-skeleton-file-blob": {
"name": "Skel Blob",
"desc": "Skel file blob"
},
"spine-animation": {
"name": "animation",
"desc": "animation"
},
"spine-skin": {
"name": "skin",
"desc": "skin"
},
"spine-bounds-provider-group": {
"name": "Bounds provider",
"desc": "Select the desired buound provider and fill the respective properties."
},
"spine-bounds-provider": {
"name": "Bounds provider",
"desc": "The bounds provider to use.",
"items": {
"AABB": "AABB Rectangle",
"setup": "Setup pose bounds",
"animation-skin": "Animation + Skin bounds"
}
},
"spine-bounds-provider-move": {
"name": "Position bounds",
"desc": "Keep the skeleton in a fixed position while adjusting the size and position of the bounds."
}
},
"aceCategories": {
"custom": "Custom"
},
"conditions": {
"on-skeleton-loaded": {
"list-name": "On skeleton loaded",
"display-text": "On skeleton loaded",
"description": "Do something when skeleton is loaded"
},
"on-animation-event": {
"list-name": "On animation event",
"display-text": "On {0} event triggered by animation {2} on track {1} trigger",
"description": "Do something when animation event is triggered",
"params": {
"event": {
"name": "Event name",
"desc": "Event name"
},
"animation": {
"name": "Animation",
"desc": "Animation"
},
"track": {
"name": "Track number",
"desc": "Track number"
}
}
}
},
"actions": {
"do-alert": {
"list-name": "Do alert",
"display-text": "Do alert",
"description": "Do a dummy alert."
},
"set-skin": {
"list-name": "Set skin",
"display-text": "Set skin {0}",
"description": "Set skin",
"params": {
"skin-name": {
"name": "Skins list",
"desc": "A comma separated list of skins to set. Empty string to unset skins."
}
}
},
"set-animation": {
"list-name": "Set animation",
"display-text": "Set animation {1} on track {0} with loop {2}",
"description": "Set animation",
"params": {
"track": {
"name": "track",
"desc": "track"
},
"animation": {
"name": "animations name",
"desc": "animations name"
},
"loop": {
"name": "loop",
"desc": "loop"
}
}
}
},
"expressions": {
"double": {
"description": "Double a number.",
"translated-name": "Double",
"params": {
"number": {
"name": "Number",
"desc": "The number to double."
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,73 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://construct.net/sdk/schema/plugin.addon.schema.json",
"title": "Plugin addon.json",
"description": "Main JSON file that describes metadata about a plugin.",
"type": "object",
"properties": {
"is-c3-addon": {
"description": "This is used by Construct to identify valid addons.",
"const": true
},
"sdk-version": {
"description": "The version of the Addon SDK used for this addon.",
"enum": [1, 2]
},
"type": {
"description": "Indicates the addon type. For the plugin schema, this must be \"plugin\".",
"const": "plugin"
},
"name": {
"description": "The displayed name of the addon, in English. This can be changed after release.",
"type": "string"
},
"id": {
"description": "The unique ID of the addon. This must not be used by any other addon ever published for Construct, and must never change after you first publish your addon. It is recommended to use a vendor-specific prefix, e.g. MyCompany_MyAddon.",
"type": "string"
},
"version": {
"description": "A string specifying the addon version in four parts (major, minor, patch, revision).",
"type": "string"
},
"min-construct-version": {
"description": "The minimum Construct version required to use this addon, e.g. \"r400\"",
"type": "string"
},
"supports-worker-mode": {
"description": "Whether the addon supports running in worker mode, where the Construct runtime is hosted in a Web Worker. Defaults to true; if set to false the presence of the addon in a project will block the runtime from using worker mode.",
"type": "boolean"
},
"author": {
"description": "A string identifying the author of the addon.",
"type": "string"
},
"website": {
"description": "A string of a URL to the author's website. It is recommended to provide updates to the addon at this URL if any become available. The website should use HTTPS.",
"type": "string",
"format": "uri"
},
"documentation": {
"description": "A string of a URL to the online documentation for the addon. It is important to provide documentation for your addon to be useful to users.",
"type": "string",
"format": "uri"
},
"description": {
"description": "A string of a brief description of what the addon does, displayed when prompting the user to install the addon.",
"type": "string"
},
"editor-scripts": {
"description": "An array of script files in the addon package to load in the editor.",
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
},
"file-list": {
"description": "A list of all files used by the addon. Required for Developer Mode addons to work.",
"type": "array",
"items": { "type": "string" }
}
},
"required": ["is-c3-addon", "type", "name", "id", "version", "author", "website", "documentation", "description", "editor-scripts"]
}

View File

@ -0,0 +1,113 @@
import type { SDKEditorInstanceClass } from "./instance.ts";
const SDK = globalThis.SDK;
////////////////////////////////////////////
// The plugin ID is how Construct identifies different kinds of plugins.
// *** NEVER CHANGE THE PLUGIN ID! ***
// If you change the plugin ID after releasing the plugin, Construct will think it is an entirely different
// plugin and assume it is incompatible with the old one, and YOU WILL BREAK ALL EXISTING PROJECTS USING THE PLUGIN.
// Only the plugin name is displayed in the editor, so to rename your plugin change the name but NOT the ID.
// If you want to completely replace a plugin, make it deprecated (it will be hidden but old projects keep working),
// and create an entirely new plugin with a different plugin ID.
const PLUGIN_ID = "EsotericSoftware_SpineConstruct3";
////////////////////////////////////////////
const PLUGIN_CATEGORY = "general";
let app = null;
const PLUGIN_CLASS = class MyDrawingPlugin extends SDK.IPluginBase {
static PROP_ATLAS = "spine-atlas-file";
static PROP_SKELETON = "spine-skeleton-file";
static PROP_SKIN = "spine-skin";
static PROP_ANIMATION = "spine-animation";
static PROP_ERRORS = "spine-errors";
static PROP_RATIO_WIDTH = "spine-restore-ratio-width";
static PROP_RATIO_HEIGHT = "spine-restore-ratio-height";
static PROP_SKELETON_BLOB = "spine-skeleton-file-blob";
static PROP_BOUNDS_PROVIDER_GROUP = "spine-bounds-provider-group";
static PROP_BOUNDS_PROVIDER = "spine-bounds-provider";
static PROP_BOUNDS_PROVIDER_MOVE = "spine-bounds-provider-move";
static TYPE_BOUNDS_SETUP = "setup";
static TYPE_BOUNDS_ANIMATION_SKIN = "animation-skin";
static TYPE_BOUNDS_AABB = "AABB";
constructor () {
super(PLUGIN_ID);
SDK.Lang.PushContext("plugins." + PLUGIN_ID.toLowerCase());
// @ts-ignore
this._info.SetName(globalThis.lang(".name"));
// @ts-ignore
this._info.SetDescription(globalThis.lang(".description"));
this._info.SetCategory(PLUGIN_CATEGORY);
this._info.SetAuthor("Esoteric Software");
// @ts-ignore
this._info.SetHelpUrl(globalThis.lang(".help-url"));
this._info.SetPluginType("world"); // mark as world plugin, which can draw
this._info.SetIsResizable(true); // allow to be resized
this._info.SetIsRotatable(true); // allow to be rotated
this._info.SetHasImage(false);
this._info.SetSupportsEffects(true); // allow effects
this._info.SetMustPreDraw(true);
this._info.SetRuntimeModuleMainScript("c3runtime/main.js");
this._info.AddC3RuntimeScript("c3runtime/spine-construct3-lib.js");
this._info.AddFileDependency({
filename: "c3runtime/spine-construct3-lib.js",
type: "external-runtime-script"
})
SDK.Lang.PushContext(".properties");
this._info.SetProperties([
new SDK.PluginProperty("text", MyDrawingPlugin.PROP_ATLAS, ""),
new SDK.PluginProperty("text", MyDrawingPlugin.PROP_SKELETON, ""),
new SDK.PluginProperty("text", MyDrawingPlugin.PROP_SKIN, ""),
new SDK.PluginProperty("text", MyDrawingPlugin.PROP_ANIMATION, ""),
new SDK.PluginProperty("projectfile", MyDrawingPlugin.PROP_SKELETON_BLOB, ""),
new SDK.PluginProperty("info", MyDrawingPlugin.PROP_ERRORS, {
infoCallback (inst) {
const atlas = inst.GetInstance().GetPropertyValue(MyDrawingPlugin.PROP_ATLAS);
const skeleton = inst.GetInstance().GetPropertyValue(MyDrawingPlugin.PROP_SKELETON);
let error = "";
if (atlas && skeleton) {
error = "You can't set both .skel and .json skeleton file.";
}
if (!atlas && !skeleton) {
error = "Missing skeleton file.";
}
return error;
},
}),
new SDK.PluginProperty("group", MyDrawingPlugin.PROP_BOUNDS_PROVIDER_GROUP),
new SDK.PluginProperty("combo", MyDrawingPlugin.PROP_BOUNDS_PROVIDER, {
initialValue: "setup",
items: [
MyDrawingPlugin.TYPE_BOUNDS_SETUP,
MyDrawingPlugin.TYPE_BOUNDS_ANIMATION_SKIN,
MyDrawingPlugin.TYPE_BOUNDS_AABB
],
}),
new SDK.PluginProperty("check", MyDrawingPlugin.PROP_BOUNDS_PROVIDER_MOVE, false),
]);
SDK.Lang.PopContext(); // .properties
SDK.Lang.PopContext();
}
};
SDK.Plugins.EsotericSoftware_SpineConstruct3 = PLUGIN_CLASS;
PLUGIN_CLASS.Register(PLUGIN_ID, PLUGIN_CLASS);

View File

@ -0,0 +1,13 @@
const SDK = globalThis.SDK;
const PLUGIN_CLASS = SDK.Plugins.EsotericSoftware_SpineConstruct3;
PLUGIN_CLASS.Type = class MyDrawingPluginType extends SDK.ITypeBase {
constructor (sdkPlugin: SDK.IPluginBase, iObjectType: SDK.IObjectType) {
super(sdkPlugin, iObjectType);
}
};
export { }

View File

@ -0,0 +1,23 @@

type SimulateControlType8Direction = "left" | "right" | "up" | "down";
/** Represents the 8 Direction behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/direction | I8DirectionBehaviorInstance documentation } */
declare class I8DirectionBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
stop(): void;
reverse(): void;
simulateControl(ctrl: SimulateControlType8Direction): void;
speed: number;
maxSpeed: number;
acceleration: number;
deceleration: number;
vectorX: number;
vectorY: number;
setVector(x: number, y: number): void;
getVector(): Vec2Arr;
isDefaultControls: boolean;
isIgnoringInput: boolean;
isAllowSliding: boolean;
isEnabled: boolean;
}

View File

@ -0,0 +1,7 @@

/** Represents the Anchor behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/anchor | IAnchorBehaviorInstance documentation } */
declare class IAnchorBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
isEnabled: boolean;
}

View File

@ -0,0 +1,13 @@

/** Represents the Bullet behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/bullet | IBulletBehaviorInstance documentation } */
declare class IBulletBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
speed: number;
acceleration: number;
gravity: number;
angleOfMotion: number;
bounceOffSolids: boolean;
distanceTravelled: number;
isEnabled: boolean;
}

View File

@ -0,0 +1,25 @@

type SimulateControlTypeCar = "left" | "right" | "up" | "down";
/** Represents the Car behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/car | ICarBehaviorInstance documentation } */
declare class ICarBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
stop(): void;
simulateControl(ctrl: SimulateControlTypeCar): void;
speed: number;
maxSpeed: number;
acceleration: number;
deceleration: number;
readonly vectorX: number;
readonly vectorY: number;
getVector(): Vec2Arr;
readonly angleOfMotion: number;
steerSpeed: number;
driftRecover: number;
friction: number;
turnWhileStopped: boolean;
isDefaultControls: boolean;
isIgnoringInput: boolean;
isEnabled: boolean;
}

View File

@ -0,0 +1,20 @@

type DragDropBehaviorAxes = "both" | "horizontal" | "vertical";
interface DragDropBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"dragstart": BehaviorInstanceEvent<InstType, BehInstType>;
"drop": BehaviorInstanceEvent<InstType, BehInstType>;
}
/** Represents the Car behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/drag-drop | IDragDropBehaviorInstance documentation } */
declare class IDragDropBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof DragDropBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: DragDropBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof DragDropBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: DragDropBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
axes: DragDropBehaviorAxes;
drop(): void;
readonly isDragging: boolean;
isEnabled: boolean;
}

View File

@ -0,0 +1,20 @@

interface FadeBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"fadeinend": BehaviorInstanceEvent<InstType, BehInstType>;
"waitend": BehaviorInstanceEvent<InstType, BehInstType>;
"fadeoutend": BehaviorInstanceEvent<InstType, BehInstType>;
}
/** Represents the Fade behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/fade | IFadeBehaviorInstance documentation } */
declare class IFadeBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof FadeBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: FadeBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof FadeBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: FadeBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
startFade(): void;
restartFade(): void;
fadeInTime: number;
waitTime: number;
fadeOutTime: number;
}

View File

@ -0,0 +1,16 @@

interface FlashBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"flashend": BehaviorInstanceEvent<InstType, BehInstType>;
}
/** Represents the Flash behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/flash | IFlashBehaviorInstance documentation } */
declare class IFlashBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof FlashBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: FlashBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof FlashBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: FlashBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
flash(on: number, off: number, dur: number): void;
stop(): void;
readonly isFlashing: boolean;
}

View File

@ -0,0 +1,32 @@

type FollowBehaviorMode = "time" | "distance";
type FollowBehaviorInterpolationType = "step" | "linear" | "angular";
type FollowBehaviorPropertyType = "x" | "y" | "z-elevation" | "width" | "height" | "angle" | "opacity" | "visibility" | "destroyed";
/** Represents the Follow behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/follow | IFollowBehaviorInstance documentation } */
declare class IFollowBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
followInstance: IInstance;
mode: FollowBehaviorMode;
delay: number;
maxDelay: number;
historyRate: number;
clearHistory(): void;
rewindHistory(time: number): void;
setFollowingProperty(prop: FollowBehaviorPropertyType, isEnabled: boolean): void;
isFollowingProperty(prop: FollowBehaviorPropertyType): boolean;
setPropertyInterpolation(prop: FollowBehaviorPropertyType, interp: FollowBehaviorInterpolationType): void;
getPropertyInterpolation(prop: FollowBehaviorPropertyType): FollowBehaviorInterpolationType;
startFollowingCustomProperty(customProp: string, interp: FollowBehaviorInterpolationType): void;
stopFollowingCustomProperty(customProp: string): void;
isFollowingCustomProperty(customProp: string): boolean;
setCustomPropertyValue(customProp: string, value: number|string): void;
getDelayedCustomPropertyValue(customProp: string): number|string;
saveHistoryToJSON(maxDelay?: number): JSONValue;
loadHistoryFromJSON(json: JSONValue): void;
isEnabled: boolean;
}

View File

@ -0,0 +1,7 @@

/** Represents the Jump-thru behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/jump-thru | IJumpthruBehaviorInstance documentation } */
declare class IJumpthruBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
isEnabled: boolean;
}

View File

@ -0,0 +1,16 @@

/** Represents the Line-of-sight behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/line-of-sight | ILOSBehaviorInstance documentation } */
declare class ILOSBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
ray: ILOSBehaviorRay;
range: number;
coneOfView: number;
hasLOStoPosition(x: number, y: number): boolean;
hasLOSBetweenPositions(fromX: number, fromY: number, fromAngle: number, toX: number, toY: number): boolean;
castRay(fromX: number, fromY: number, toX: number, toY: number, useCollisionCells?: boolean): ILOSBehaviorRay;
addObstacle<InstType2 extends IInstance>(objectClass: IObjectClass<InstType2>): void;
clearObstacles(): void;
}

View File

@ -0,0 +1,20 @@

/** Represents the result of casting a ray with the Line-of-sight behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/line-of-sight | ILOSBehaviorInstance documentation } */
declare class ILOSBehaviorRay
{
readonly didCollide: boolean;
readonly hitX: number;
readonly hitY: number;
getHitPosition(): Vec2Arr;
readonly hitDistance: number;
readonly hitUid: number;
getNormalX(length: number): number;
getNormalY(length: number): number;
getNormal(length: number): Vec2Arr;
readonly normalAngle: number;
getReflectionX(length: number): number;
getReflectionY(length: number): number;
getReflection(length: number): Vec2Arr;
readonly reflectionAngle: number;
}

View File

@ -0,0 +1,32 @@

interface MoveToBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"arrived": BehaviorInstanceEvent<InstType, BehInstType>;
"hitsolid": BehaviorInstanceEvent<InstType, BehInstType>;
}
/** Represents the Move To behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/move | IMoveToBehaviorInstance documentation } */
declare class IMoveToBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof MoveToBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: MoveToBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof MoveToBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: MoveToBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
moveToPosition(x: number, y: number, isDirect?: boolean): void;
getTargetX(): number;
getTargetY(): number;
getTargetPosition(): Vec2Arr;
getWaypointCount(): number;
getWaypointX(index: number): number;
getWaypointY(index: number): number;
getWaypoint(index: number): number;
stop(): void;
readonly isMoving: boolean;
speed: number;
maxSpeed: number;
acceleration: number;
deceleration: number;
angleOfMotion: number;
rotateSpeed: number;
isStopOnSolids: boolean;
isEnabled: boolean;
}

View File

@ -0,0 +1,20 @@

/** Represents the Orbit behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/orbit | IOrbitBehaviorInstance documentation } */
declare class IOrbitBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
setTargetPosition(x: number, y: number): void;
getTargetPosition(): Vec2Arr;
pin(inst: IWorldInstance): void;
speed: number;
acceleration: number;
rotation: number;
offsetAngle: number;
primaryRadius: number;
secondaryRadius: number;
isMatchRotation: boolean;
totalRotation: number;
totalAbsoluteRotation: number;
getDistanceToTarget(): number;
isEnabled: boolean;
}

View File

@ -0,0 +1,38 @@

type PathfindingDirectMovementMode = "none" | "to-destination" | "anywhere-along-path";
interface PathfindingBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"arrived": BehaviorInstanceEvent<InstType, BehInstType>;
}
/** Represents the Pathfinding behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/pathfinding | IPathfindingBehaviorInstance documentation } */
declare class IPathfindingBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof PathfindingBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: PathfindingBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof PathfindingBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: PathfindingBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
readonly map: IPathfindingMap;
findPath(x: number, y: number): Promise<boolean>;
calculatePath(fromX: number, fromY: number, toX: number, toY: number): Promise<boolean>;
startMoving(): void;
stop(): void;
maxSpeed: number;
speed: number;
acceleration: number;
deceleration: number;
rotateSpeed: number;
readonly isCalculatingPath: boolean;
readonly isMoving: boolean;
readonly currentNode: number;
getNodeCount(): number;
getNodeXAt(index: number): number;
getNodeYAt(index: number): number;
getNodeAt(index: number): Vec2Arr;
nodes(): Generator<Vec2Arr>;
directMovementMode: PathfindingDirectMovementMode;
isEnabled: boolean;
}

View File

@ -0,0 +1,18 @@

/** Represents a shared pathfinding obstacle map for the Pathfinding behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/pathfinding | IPathfindingBehaviorInstance documentation } */
declare class IPathfindingMap
{
readonly cellSize: number;
readonly cellBorder: number;
readonly widthInCells: number;
readonly heightInCells: number;
isCellObstacle(x: number, y: number): boolean;
moveCost: number;
isDiagonalsEnabled: boolean;
regenerateMap(): Promise<void>;
regenerateRegion(startX: number, startY: number, endX: number, endY: number): Promise<void>;
regenerateObjectRegion<InstanceType extends IInstance>(objectClass: IObjectClass<InstanceType>): Promise<void>;
startPathGroup(baseCost?: number, cellSpread?: number, maxWorkers?: number): void;
endPathGroup(): void;
}

View File

@ -0,0 +1,13 @@

type PhysicsSteppingMode = "fixed" | "variable";
/** Represents global settings with the Physics behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/physics | IPhysicsBehaviorInstance documentation } */
declare class IPhysicsBehavior extends IBehavior_
{
worldGravity: number;
steppingMode: PhysicsSteppingMode;
velocityIterations: number;
positionIterations: number;
setCollisionsEnabled<InstType1 extends IInstance, InstType2 extends IInstance>(objectClassA: IObjectClass<InstType1>, objectClassB: IObjectClass<InstType2>, state: boolean): void;
}

View File

@ -0,0 +1,59 @@

/** Represents the Physics behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/physics | IPhysicsBehaviorInstance documentation } */
declare class IPhysicsBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
readonly behavior: IPhysicsBehavior;
isEnabled: boolean;
angularVelocity: number;
density: number;
friction: number;
elasticity: number;
linearDamping: number;
angularDamping: number;
isImmovable: boolean;
isPreventRotation: boolean;
isBullet: boolean;
readonly mass: number;
/**
* @deprecated Use isAwake (which also has a setter) instead of isSleeping
*/
readonly isSleeping: boolean;
isAwake: boolean;
applyForce(fx: number, fy: number, imgPt?: ImagePointParameter): void;
applyForceTowardPosition(f: number, px: number, py: number, imgPt?: ImagePointParameter): void;
applyForceAtAngle(f: number, a: number, imgPt?: ImagePointParameter): void;
applyImpulse(ix: number, iy: number, imgPt?: ImagePointParameter): void;
applyImpulseTowardPosition(i: number, px: number, py: number, imgPt?: ImagePointParameter): void;
applyImpulseAtAngle(i: number, a: number, imgPt?: ImagePointParameter): void;
applyTorque(m: number): void;
applyTorqueToAngle(m: number, a: number): void;
applyTorqueToPosition(m: number, px: number, py: number): void;
setVelocity(vx: number, vy: number): void;
getVelocityX(): number;
getVelocityY(): number;
getVelocity(): Vec2Arr;
teleport(x: number, y: number): void;
getCenterOfMassX(): number;
getCenterOfMassY(): number;
getCenterOfMass(): Vec2Arr;
getContactCount(): number;
getContactX(): number;
getContactY(): number;
getContact(): Vec2Arr;
createDistanceJoint(imgPt: ImagePointParameter, otherInst: IWorldInstance, otherImgPt: ImagePointParameter, damping: number, freq: number): void;
createRevoluteJoint(imgPt: ImagePointParameter, otherInst: IWorldInstance): void;
createLimitedRevoluteJoint(imgPt: ImagePointParameter, otherInst: IWorldInstance, lower: number, upper: number): void;
createPrismaticJoint(imgPt: ImagePointParameter, otherInst: IWorldInstance, axisAngle: number, enableLimit: boolean, lowerTranslation: number, upperTranslation: number, enableMotor: boolean, motorSpeed: number, maxMotorForce: number): void;
removeAllJoints(): void;
}

View File

@ -0,0 +1,36 @@

type SimulateControlTypePlatform = "left" | "right" | "jump";
type PlatformCeilingCollisionMode = "stop" | "preserve-momentum";
type PlatformWallSide = "left" | "right";
/** Represents the Platform behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/platform | IPlatformBehaviorInstance documentation } */
declare class IPlatformBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
fallThrough(): void;
resetDoubleJump(d: boolean): void;
simulateControl(ctrl: SimulateControlTypePlatform): void;
speed: number;
maxSpeed: number;
acceleration: number;
deceleration: number;
jumpStrength: number;
maxFallSpeed: number;
gravity: number;
gravityAngle: number;
isDoubleJumpEnabled: boolean;
jumpSustain: number;
ceilingCollisionMode: PlatformCeilingCollisionMode;
isByWall(side: PlatformWallSide): boolean;
readonly isOnFloor: boolean;
readonly isMoving: boolean;
readonly isJumping: boolean;
readonly isFalling: boolean;
vectorX: number;
vectorY: number;
setVector(x: number, y: number): void;
getVector(): Vec2Arr;
isDefaultControls: boolean;
isIgnoringInput: boolean;
isEnabled: boolean;
}

View File

@ -0,0 +1,9 @@

/** Represents the Rotate behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/rotate | IRotateBehaviorInstance documentation } */
declare class IRotateBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
speed: number;
acceleration: number;
isEnabled: boolean;
}

View File

@ -0,0 +1,9 @@

/** Represents the Shadow Caster behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/shadow-caster | IShadowCasterBehaviorInstance documentation } */
declare class IShadowCasterBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
height: number;
tag: string;
isEnabled: boolean;
}

View File

@ -0,0 +1,17 @@

type SineBehaviorMovementType = "horizontal" | "vertical" | "size" | "width" | "height" | "angle" | "opacity" | "value-only" | "forwards-backwards" | "z-elevation";
type SineBehaviorWaveType = "sine" | "triangle" | "sawtooth" | "reverse-sawtooth" | "square";
/** Represents the Sine behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/sine | ISineBehaviorInstance documentation } */
declare class ISineBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
period: number;
magnitude: number;
phase: number;
movement: SineBehaviorMovementType;
wave: SineBehaviorWaveType;
readonly value: number;
updateInitialState(): void;
isEnabled: boolean;
}

View File

@ -0,0 +1,8 @@

/** Represents the Solid behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/solid | ISolidBehaviorInstance documentation } */
declare class ISolidBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
tags: string;
isEnabled: boolean;
}

View File

@ -0,0 +1,26 @@

type SimulateControlTypeTile = "left" | "right" | "up" | "down";
/** Represents the Tile Movement behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/tile-movement | ITileMovementBehaviorInstance documentation } */
declare class ITileMovementBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
isIgnoringInput: boolean;
isEnabled: boolean;
isDefaultControls: boolean;
simulateControl(dir: SimulateControlTypeTile): void;
setSpeed(x: number, y: number): void;
getSpeed(): Vec2Arr;
setGridPosition(x: number, y: number, immediate?: boolean): void;
getGridPosition(): Vec2Arr;
modifyGridDimensions(width: number, height: number, x: number, y: number): void;
isMoving(): boolean;
isMovingDirection(dir: SimulateControlTypeTile): boolean;
canMoveTo(x: number, y: number): boolean;
canMoveDirection(dir: SimulateControlTypeTile, distance: number): boolean;
getTargetPosition(): Vec2Arr;
getGridTargetPosition(): Vec2Arr;
toGridSpace(x: number, y: number): Vec2Arr;
fromGridSpace(x: number, y: number): Vec2Arr;
}

View File

@ -0,0 +1,31 @@

type TimerBehaviorTimerType = "once" | "regular";
declare class TimerBehaviorEvent<InstType = IInstance, BehInstType = ITimerBehaviorInstance<InstType>> extends BehaviorInstanceEvent<InstType, BehInstType>
{
tag: string;
}
interface TimerBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"timer": TimerBehaviorEvent<InstType, BehInstType>;
}
/** Represents the Timer behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/timer | ITimerBehaviorInstance documentation } */
declare class ITimerBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof TimerBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: TimerBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof TimerBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: TimerBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
startTimer(duration: number, name: string, type?: TimerBehaviorTimerType): void;
setTimerPaused(name: string, isPaused: boolean): void;
setAllTimersPaused(isPaused: boolean): void;
stopTimer(name: string): void;
stopAllTimers(): void;
isTimerRunning(name: string): boolean;
isTimerPaused(name: string): boolean;
getCurrentTime(name: string): number;
getTotalTime(name: string): number;
getDuration(name: string): number;
hasFinished(name: string): boolean;
}

View File

@ -0,0 +1,30 @@

type TurretBehaviorTargetMode = "first" | "nearest";
declare class TurretBehaviorEvent<InstType = IInstance, BehInstType = ITurretBehaviorInstance<InstType>> extends BehaviorInstanceEvent<InstType, BehInstType>
{
targetInst: IWorldInstance;
}
interface TurretBehaviorInstanceEventMap<InstType, BehInstType> extends BehaviorInstanceEventMap<InstType, BehInstType> {
"targetacquired": TurretBehaviorEvent<InstType, BehInstType>;
"shoot": TurretBehaviorEvent<InstType, BehInstType>;
}
/** Represents the Turret behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/turret | ITurretBehaviorInstance documentation } */
declare class ITurretBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
addEventListener<K extends keyof TurretBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: TurretBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
removeEventListener<K extends keyof TurretBehaviorInstanceEventMap<InstType, this>>(type: K, listener: (ev: TurretBehaviorInstanceEventMap<InstType, this>[K]) => any): void;
currentTarget: IWorldInstance | null;
range: number;
rateOfFire: number;
isRotateEnabled: boolean;
rotateSpeed: number;
targetMode: TurretBehaviorTargetMode;
isPredictiveAimEnabled: boolean;
projectileSpeed: number;
isEnabled: boolean;
}

View File

@ -0,0 +1,27 @@

type TweenPropertyType = "x" | "y" | "width" | "height" | "angle" | "opacity" | "color" | "z-elevation" | "x-scale" | "y-scale" | "position" | "size" | "scale" | "value";
type TweenEndValueType = number | Vec2Arr | Vec3Arr;
type TweenBuiltInEaseType = "linear" | "in-sine" | "out-sine" | "in-out-sine" | "in-elastic" | "out-elastic" | "in-out-elastic" | "in-back" | "out-back" | "in-out-back" |
"in-bounce" | "out-bounce" | "in-out-bounce" | "in-cubic" | "out-cubic" | "in-out-cubic" | "in-quadratic" | "out-quadratic" | "in-out-quadratic" |
"in-quartic" | "out-quartic" | "in-out-quartic" | "in-quintic" | "out-quintic" | "in-out-quintic" | "in-circular" | "out-circular" | "in-out-circular" |
"in-exponential" | "out-exponential" | "in-out-exponential";
interface StartTweenOpts {
tags?: string | string[];
destroyOnComplete?: boolean;
loop?: boolean;
pingPong?: boolean;
repeatCount?: number;
startValue?: number;
}
/** Represents the Tween behavior.
* @see {@link https://www.construct.net/make-games/manuals/construct-3/scripting/scripting-reference/behavior-interfaces/tween | ITweenBehaviorInstance documentation } */
declare class ITweenBehaviorInstance<InstType> extends IBehaviorInstance<InstType>
{
startTween(prop: TweenPropertyType, endValue: TweenEndValueType, time: number, ease: TweenBuiltInEaseType, opts?: StartTweenOpts): ITweenState;
allTweens(): Generator<ITweenState>;
tweensByTags(tags: string | string[]): Generator<ITweenState>;
isEnabled: boolean;
}

View File

@ -0,0 +1,12 @@
declare namespace SDK {
class IBehaviorBase {
constructor(id: string);
_info: SDK.IBehaviorInfo;
Release(): void;
static Register(id: string, class_: new () => SDK.IBehaviorBase): void;
}
}

View File

@ -0,0 +1,30 @@
type BehaviorInfoCategory = "attributes" | "general" | "movements" | "other";
declare namespace SDK {
class IBehaviorInfo {
SetName(v: string): void;
SetDescription(v: string): void;
SetVersion(v: string): void;
SetCategory(v: BehaviorInfoCategory): void;
SetAuthor(v: string): void;
SetHelpUrl(v: string): void;
SetIcon(url: string, type: string): void;
SetIsOnlyOneAllowed(o: boolean): void;
SetIsDeprecated(d: boolean): void;
SetCanBeBundled(b: boolean): void;
SetProperties(arr: SDK.PluginProperty[]): void;
AddCordovaPluginReference(o: PluginInfoCordovaPluginReference): void;
AddFileDependency(o: PluginInfoFileDependency): void;
AddRemoteScriptDependency(url: string, type?: PluginInfoScriptType): void;
SetRuntimeModuleMainScript(path: string): void;
AddC3RuntimeScript(path: string): void;
SetC3RuntimeScripts(arr: string[]): void;
SetTypeScriptDefinitionFiles(arr: string[]): void;
SetScriptInterfaceNames(o: { instance?: string, behaviorType?: string, behavior?: string }): void;
}
}

View File

@ -0,0 +1,17 @@
declare namespace SDK {
class IBehaviorInstanceBase {
constructor(sdkBehaviorType: SDK.IBehaviorTypeBase, iBehaviorInstance: SDK.IBehaviorInstance);
_sdkBehaviorType: SDK.IBehaviorTypeBase;
_behaviorInstance: SDK.IBehaviorInstance;
GetBehaviorInstance(): SDK.IBehaviorInstance;
GetSdkBehaviorType(): SDK.IBehaviorTypeBase;
Release(): void;
OnCreate(): void;
OnPropertyChanged(id: string, value: EditorPropertyValueType): void;
}
}

View File

@ -0,0 +1,8 @@
declare namespace SDK {
class IBehaviorTypeBase {
constructor(sdkBehavior: SDK.IBehaviorBase, iBehaviorType: SDK.IBehaviorType);
_sdkBehavior: SDK.IBehaviorBase;
_behaviorType: SDK.IBehaviorType;
}
}

View File

@ -0,0 +1,21 @@
declare namespace SDK {
class IInstanceBase {
constructor(sdkType: SDK.ITypeBase, iInstance: SDK.IObjectInstance);
_sdkType: SDK.ITypeBase;
_inst: SDK.IObjectInstance;
Release(): void;
OnCreate(): void;
OnAfterCreate(): void;
OnPropertyChanged(id: string, value: EditorPropertyValueType): void;
OnTimelinePropertyChanged(id: string, value: number | string, detail: { resultMode: "relative" | "absolute" }): void;
OnExitTimelineEditMode(): void;
LoadC2Property(name: string, valueString: string): boolean;
GetObjectType(): SDK.IObjectType;
GetProject(): SDK.IProject;
GetInstance(): SDK.IObjectInstance;
}
}

View File

@ -0,0 +1,14 @@
declare namespace SDK {
class IPluginBase {
constructor(id: string);
_info: SDK.IPluginInfo;
Release(): void;
static Register(id: string, class_: new () => SDK.IPluginBase): void;
}
}

View File

@ -0,0 +1,80 @@
type PluginInfoCategory = "3d" | "data-and-storage" | "html-elements" | "general" | "input" | "media" | "monetisation" | "platform-specific" | "web" | "other";
type PluginInfoPluginType = "object" | "world";
type PluginInfoScriptType = "" | "module";
interface PluginInfoCordovaPluginReference {
id: string,
version?: string,
platform?: "all" | "ios" | "android",
plugin?: SDK.IPluginBase,
variables?: Array<[string, SDK.PluginProperty]>
}
interface PluginInfoCordovaResourceFile {
src: string,
target?: string,
platform?: "all" | "ios" | "android"
}
interface PluginInfoFileDependency {
filename: string,
fileType?: string,
scriptType?: PluginInfoScriptType,
type: "copy-to-output" | "external-dom-script" | "external-runtime-script" | "external-css" | "wrapper-extension",
platform?: "all" | "windows-x86" | "windows-x64" | "windows-arm64" | "xbox-uwp-x64" | "macos-universal" | "linux-x64" | "linux-arm" | "linux-arm64"
}
declare namespace SDK {
class IPluginInfo {
SetName(v: string): void;
SetDescription(v: string): void;
SetVersion(v: string): void;
SetCategory(v: PluginInfoCategory): void;
SetAuthor(v: string): void;
SetHelpUrl(v: string): void;
SetPluginType(v: PluginInfoPluginType): void;
SetIcon(url: string, type: string): void;
SetIsResizable(v: boolean): void;
SetIsRotatable(v: boolean): void;
SetSupportsZElevation(v: boolean): void;
SetHasImage(v: boolean): void;
SetDefaultImageURL(v: string): void;
SetHasAnimations(v: boolean): void;
SetIsTiled(v: boolean): void;
SetIsFont(v: boolean): void;
SetHasTilemap(v: boolean): void;
SetIsDeprecated(v: boolean): void;
SetIsSingleGlobal(v: boolean): void;
SetSupportsEffects(v: boolean): void;
SetMustPreDraw(v: boolean): void;
SetIs3D(v: boolean): void;
SetSupportsColor(v: boolean): void;
SetCanBeBundled(v: boolean): void;
SetSupportsColor(v: boolean): void;
AddCommonPositionACEs(): void;
AddCommonSizeACEs(): void;
AddCommonAngleACEs(): void;
AddCommonAppearanceACEs(): void;
AddCommonZOrderACEs(): void;
AddCommonSceneGraphACEs(): void;
SetProperties(arr: SDK.PluginProperty[]): void;
AddCordovaPluginReference(o: PluginInfoCordovaPluginReference): void;
AddCordovaResourceFile(o: PluginInfoCordovaResourceFile): void;
AddFileDependency(o: PluginInfoFileDependency): void;
AddRemoteScriptDependency(url: string, type?: PluginInfoScriptType): void;
SetGooglePlayServicesEnabled(e: boolean): void;
SetWrapperExportProperties(componentId: string, propertyIds: string[]): void;
SetRuntimeModuleMainScript(path: string): void;
AddC3RuntimeScript(path: string): void;
SetC3RuntimeScripts(arr: string[]): void;
SetDOMSideScripts(arr: string[]): void;
SetTypeScriptDefinitionFiles(arr: string[]): void;
SetScriptInterfaceNames(o: { instance?: string, objectType?: string, plugin?: string }): void;
}
}

View File

@ -0,0 +1,26 @@
type PluginPropertyInitialValueType = number | Vec3Arr | string | boolean;
type PluginPropertyType = "integer" | "float" | "percent" | "text" | "longtext" | "check" | "font" | "combo" | "color" | "object" | "group" | "link" | "info" | "projectfile";
type PluginPropertyCallbackType = "for-each-instance" | "once-for-type";
interface PluginPropertyOptions {
initialValue?: PluginPropertyInitialValueType,
minValue?: number,
maxValue?: number,
items?: string[],
dragSpeedMultiplier?: number,
allowedPluginIds?: string[],
linkCallback?: (p: SDK.IWorldInstanceBase | SDK.ITypeBase) => void,
infoCallback?: (inst: SDK.IInstanceBase) => string,
callbackType?: PluginPropertyCallbackType,
interpolatable?: boolean,
filter?: string
}
declare namespace SDK {
class PluginProperty {
constructor(type: PluginPropertyType, id: string, initialValue_or_options?: PluginPropertyOptions | PluginPropertyInitialValueType);
}
}

View File

@ -0,0 +1,12 @@
declare namespace SDK {
class ITypeBase {
constructor(sdkPlugin: SDK.IPluginBase, iObjectType: SDK.IObjectType);
_sdkPlugin: SDK.IPluginBase;
_objectType: SDK.IObjectType;
GetObjectType(): SDK.IObjectType;
}
}

View File

@ -0,0 +1,23 @@
declare namespace SDK {
class IWorldInstanceBase extends SDK.IInstanceBase {
constructor(sdkType: SDK.ITypeBase, iInstance: SDK.IWorldInstance);
_inst: SDK.IWorldInstance;
Draw(iRenderer: SDK.Gfx.IWebGLRenderer, iDrawParams: SDK.Gfx.IDrawParams): void;
OnPlacedInLayout(): void;
GetTexture(animationFrame: SDK.IAnimationFrame): SDK.Gfx.IWebGLTexture | null;
GetTexRect(): SDK.Rect;
HadTextureError(): boolean;
IsOriginalSizeKnown(): boolean;
GetOriginalWidth(): number;
GetOriginalHeight(): number;
HasDoubleTapHandler(): boolean;
OnDoubleTap(): void;
}
}

View File

@ -0,0 +1,6 @@
declare namespace SDK.Gfx {
class IDrawParams {
GetDt(): number;
GetLayoutView(): SDK.UI.ILayoutView;
}
}

View File

@ -0,0 +1,53 @@
// Note types like TextureCreateOptions are taken from the runtime type
// definitions as they match the same types used by the editor
declare namespace SDK.Gfx {
class IWebGLRenderer {
SetAlphaBlend(): void;
SetColorFillMode(): void;
SetTextureFillMode(): void;
SetSmoothLineFillMode(): void;
SetColor(color: SDK.Color): void;
SetColorRgba(r: number, g: number, b: number, a: number): void;
SetOpacity(opacity: number): void;
ResetColor(): void;
SetCurrentZ(z: number): void;
GetCurrentZ(): number;
Rect(r: SDK.Rect): void;
Rect2(left: number, top: number, right: number, bottom: number): void;
Quad(q: SDK.Quad): void;
Quad2(tlx: number, tly: number, trx: number, try_: number, brx: number, bry: number, blx: number, bly: number): void;
Quad3(q: SDK.Quad, r: SDK.Rect): void;
Quad4(q: SDK.Quad, uv: SDK.Quad): void;
Quad3D(tlx: number, tly: number, tlz: number, trx: number, try_: number, trz: number, brx: number, bry: number, brz: number, blx: number, bly: number, blz: number, r: SDK.Rect): void;
Quad3D2(tlx: number, tly: number, tlz: number, trx: number, try_: number, trz: number, brx: number, bry: number, brz: number, blx: number, bly: number, blz: number, uv: SDK.Quad): void;
DrawMesh(posArr: Float32Array, uvArr: Float32Array, indexArr: Uint16Array): void;
ConvexPoly(pts: number[]): void;
Line(x1: number, y1: number, x2: number, y2: number): void;
TexturedLine(x1: number, y1: number, x2: number, y2: number, u: number, v: number): void;
LineRect(left: number, top: number, right: number, bottom: number): void;
LineRect2(r: SDK.Rect): void;
LineQuad(q: SDK.Quad): void;
PushLineWidth(w: number): void;
PopLineWidth(): void;
PushLineCap(type: RendererLineCapMode): void;
PopLineCap(): void;
SetTexture(tex: SDK.Gfx.IWebGLTexture): void;
CreateDynamicTexture(width: number, height: number, opts?: TextureCreateOptions): SDK.Gfx.IWebGLTexture;
UpdateTexture(data: TextureUpdateDataType, tex: SDK.Gfx.IWebGLTexture, opts?: TextureUpdateOptions): void;
DeleteTexture(tex: SDK.Gfx.IWebGLTexture): void;
CreateRendererText(): SDK.Gfx.IWebGLText;
}
}

View File

@ -0,0 +1,30 @@
// Note types like TextAlignHorizontalMode are taken from the runtime type
// definitions as they match the same types used by the editor
declare namespace SDK.Gfx {
class IWebGLText {
Release(): void;
SetFontName(fontName: string): void;
SetFontSize(fontSize: number): void;
SetLineHeight(h: number): void;
SetBold(b: boolean): void;
SetItalic(i: boolean): void;
SetColor(color: SDK.Color): void;
SetColorRgb(r: number, g: number, b: number): void;
SetHorizontalAlignment(h: TextAlignHorizontalMode): void;
SetVerticalAlignment(v: TextAlignVerticalMode): void;
SetWordWrapMode(mode: TextWordWrapMode): void;
SetText(text: string): void;
SetSize(width: number, height: number, zoomScale: number): void;
GetTexture(): SDK.Gfx.IWebGLTexture | null;
GetTexRect(): SDK.Rect;
SetTextureUpdateCallback(callback: () => void): void;
ReleaseTexture(): void;
GetTextWidth(): number;
GetTextHeight(): number;
}
}

View File

@ -0,0 +1,6 @@
declare namespace SDK.Gfx {
class IWebGLTexture {
GetWidth(): number;
GetHeight(): number;
}
}

View File

@ -0,0 +1,29 @@
declare namespace SDK {
class Color {
constructor(r?: number, g?: number, b?: number, a?: number);
setRgb(r: number, g: number, b: number): void;
setRgba(r: number, g: number, b: number, a: number): void;
copy(c: SDK.Color): void;
copyRgb(c: SDK.Color): void;
clone(): SDK.Color;
setR(r: number): void;
getR(): number;
setG(g: number): void;
getG(): number;
setB(b: number): void;
getB(): number;
setA(a: number): void;
getA(): number;
equals(c: SDK.Color): boolean;
equalsIgnoringAlpha(c: SDK.Color): boolean;
equalsRgb(r: number, b: number, g: number): boolean;
equalsRgba(r: number, b: number, g: number, a: number): boolean;
premultiply(): void;
unpremultiply(): void;
}
}

View File

@ -0,0 +1,9 @@
declare namespace SDK.Lang {
function PushContext(str: string): void;
function PopContext(): void;
function Get(s: string): string;
}
// Global lang() method
declare function lang(s: string): string;

View File

@ -0,0 +1,40 @@
declare namespace SDK {
class Quad {
constructor(tlx?: number, tly?: number, trx?: number, try_?: number, brx?: number, bry?: number, blx?: number, bly?: number);
set(tlx: number, tly: number, trx: number, try_: number, brx: number, bry: number, blx: number, bly: number): void;
setRect(left: number, top: number, right: number, bottom: number): void;
copy(q: SDK.Quad): void;
setTlx(v: number): void;
getTlx(): number;
setTly(v: number): void;
getTly(): number;
setTrx(v: number): void;
getTrx(): number;
setTry(v: number): void;
getTry(): number;
setBrx(v: number): void;
getBrx(): number;
setBry(v: number): void;
getBry(): number;
setBlx(v: number): void;
getBlx(): number;
setBly(v: number): void;
getBly(): number;
midX(): number;
midY(): number;
offset(x: number, y: number): void;
setFromRect(r: SDK.Rect): void;
setFromRotatedRect(r: SDK.Rect, a: number): void;
getBoundingBox(r: SDK.Rect): void;
containsPoint(x: number, y: number): boolean;
intersectsSegment(x1: number, y1: number, x2: number, y2: number): boolean;
intersectsQuad(q: SDK.Quad): boolean;
}
}

View File

@ -0,0 +1,33 @@
declare namespace SDK {
class Rect {
constructor(left?: number, top?: number, right?: number, bottom?: number);
set(left: number, top: number, right: number, bottom: number): void;
copy(r: SDK.Rect): void;
clone(): SDK.Rect;
setLeft(left: number): void;
getLeft(): number;
setTop(top: number): void;
getTop(): number;
setRight(right: number): void;
getRight(): number;
setBottom(bottom: number): void;
getBottom(): number;
width(): number;
height(): number;
midX(): number;
midY(): number;
offset(x: number, y: number): void;
inflate(x: number, y: number): void;
deflate(x: number, y: number): void;
multiply(x: number, y: number): void;
divide(x: number, y: number): void;
clamp(left: number, top: number, right: number, bottom: number): void;
normalize(): void;
intersectsRect(r: SDK.Rect): boolean;
containsPoint(x: number, y: number): boolean;
}
}

View File

@ -0,0 +1,12 @@
declare namespace SDK {
class IZipFile {
PathExists(path: string): boolean;
GetFileList(): string[];
GetFirstEntryWithExtension(ext: string): SDK.IZipFileEntry | null;
GetEntry(path: string): SDK.IZipFileEntry | null;
ReadText(entry: SDK.IZipFileEntry): Promise<string>;
ReadJson(entry: SDK.IZipFileEntry): Promise<JSONValue>;
ReadBlob(entry: SDK.IZipFileEntry): Promise<Blob>;
}
}

View File

@ -0,0 +1,5 @@
declare namespace SDK {
class IZipFileEntry {
}
}

View File

@ -0,0 +1,6 @@
declare namespace SDK {
class ILayer {
GetName(): string;
GetLayout: SDK.ILayout;
}
}

View File

@ -0,0 +1,8 @@
declare namespace SDK {
class ILayout {
GetName(): string;
GetProject(): SDK.IProject;
GetEventSheet(): SDK.IEventSheet;
GetAllLayers(): SDK.ILayer[];
}
}

View File

@ -0,0 +1,26 @@
type EditorProjectFileKind = "general" | "sound" | "music" | "video" | "font" | "icon";
declare namespace SDK {
class IProject {
GetName(): string;
GetSystemType(): SDK.IObjectType;
GetSingleGlobalObjectType(pluginId: string): SDK.IObjectType | null;
CreateObjectType(pluginId: string, name: string): Promise<SDK.IObjectType>;
CreateFamily(name: string, members: SDK.IObjectType[]): SDK.IFamily;
GetObjectTypeByName(name: string): SDK.IObjectType | null;
GetFamilyByName(name: string): SDK.IFamily | null;
GetObjectClassByName(name: string): SDK.IObjectClass | null;
GetObjectClassBySID(sid: number): SDK.IObjectClass | null;
GetInstanceByUID(uid: number): SDK.IObjectInstance | null;
AddOrReplaceProjectFile(blob: Blob, filename: string, kind?: EditorProjectFileKind): void;
GetProjectFileByName(name: string): SDK.IProjectFile | null;
GetProjectFileByExportPath(path: string): SDK.IProjectFile | null;
ShowImportAudioDialog(fileList: Blob[]): void;
EnsureFontLoaded(fontName: string): Promise<void>;
UndoPointChangeObjectInstancesProperty(instances: SDK.IObjectInstance | SDK.IObjectInstance[], propertyId: string): void;
}
}

View File

@ -0,0 +1,7 @@
declare namespace SDK {
class IProjectFile {
GetName(): string;
GetProject(): SDK.IProjectFile;
GetBlob(): Blob;
}
}

View File

@ -0,0 +1,8 @@
type EditorACParameterType = number | string | SDK.IObjectClass;
declare namespace SDK {
class IEventBlock extends IEventParentRow {
AddCondition(iObjectClass: SDK.IObjectClass, iBehaviorType: null, cndId: string, params?: EditorACParameterType[]): void;
AddAction(iObjectClass: SDK.IObjectClass, iBehaviorType: null, actId: string, params?: EditorACParameterType[]): void;
}
}

View File

@ -0,0 +1,5 @@
declare namespace SDK {
class IEventParentRow {
AddEventBlock(): Promise<SDK.IEventBlock>;
}
}

View File

@ -0,0 +1,7 @@
declare namespace SDK {
class IEventSheet {
GetName(): string;
GetProject(): SDK.IProject;
GetRoot(): SDK.IEventParentRow;
}
}

View File

@ -0,0 +1,22 @@
declare namespace SDK {
class IAnimation {
GetName(): string;
GetObjectType(): SDK.IObjectType;
GetFrames(): SDK.IAnimationFrame[];
AddFrame(blob: Blob, width: number, height: number): Promise<SDK.IAnimationFrame>;
SetSpeed(s: number): void;
GetSpeed(): number;
SetLooping(l: boolean): void;
IsLooping(): boolean;
SetPingPong(p: boolean): void;
IsPingPong(): boolean;
SetRepeatCount(r: number): void;
GetRepeatCount(): number;
SetRepeatTo(f: number): void;
GetRepeatTo(): number;
Delete(): void;
}
}

View File

@ -0,0 +1,26 @@
declare namespace SDK {
class IAnimationFrame {
GetObjectType(): SDK.IObjectType;
GetWidth(): number;
GetHeight(): number;
GetCachedWebGLTexture(): SDK.Gfx.IWebGLTexture | null;
GetTexRect(): SDK.Rect;
LoadWebGLTexture(): Promise<SDK.Gfx.IWebGLTexture>;
GetBlob(): Blob;
ReplaceBlobAndDecode(blob: Blob): Promise<void>;
SetDuration(d: number): void;
GetDuration(): number;
SetOriginX(x: number): void;
GetOriginX(): number;
SetOriginY(y: number): void;
GetOriginY(): number;
AddImagePoint(name: string, x: number, y: number): SDK.IImagePoint;
GetImagePoints(): SDK.IImagePoint[];
GetCollisionPoly(): SDK.ICollisionPoly;
Delete(): void;
}
}

View File

@ -0,0 +1,12 @@
declare namespace SDK {
class IBehaviorInstance {
GetProject(): SDK.IProject;
GetPropertyValue(id: string): EditorPropertyValueType;
SetPropertyValue(id: string, value: EditorPropertyValueType): void;
GetObjectInstance(): SDK.IObjectInstance;
GetExternalSdkInstance(): SDK.IBehaviorInstanceBase | null;
}
}

View File

@ -0,0 +1,6 @@
declare namespace SDK {
class IBehaviorType {
GetProject(): SDK.IProject;
GetName(): string;
}
}

View File

@ -0,0 +1,9 @@
declare namespace SDK {
class ICollisionPoly {
Reset(): void;
IsDefault(): boolean;
GetPoints(): number[];
SetPoints(arr: number[]): void;
}
}

View File

@ -0,0 +1,14 @@
type EditorContainerSelectMode = "normal" | "all" | "wrap";
declare namespace SDK {
class IContainer {
IsActive(): boolean;
GetMembers(): SDK.IObjectType[];
RemoveObjectType(iObjectType: SDK.IObjectType): void;
SetSelectMode(mode: EditorContainerSelectMode): void;
GetSelectMode(): EditorContainerSelectMode;
}
}

View File

@ -0,0 +1,6 @@
declare namespace SDK {
class IFamily extends IObjectClass {
GetMembers(): SDK.IObjectType[];
SetMembers(memberS: SDK.IObjectType[]): void;
}
}

View File

@ -0,0 +1,11 @@
declare namespace SDK {
class IImagePoint {
GetAnimationFrame(): SDK.IAnimationFrame;
GetName(): string;
SetName(name: string): void;
SetX(x: number): void;
GetX(): number;
SetY(y: number): void;
GetY(): number;
}
}

View File

@ -0,0 +1,7 @@
declare namespace SDK {
class IObjectClass {
GetProject(): SDK.IProject;
GetName(): string;
Delete(): void;
}
}

View File

@ -0,0 +1,15 @@
declare namespace SDK {
class IObjectInstance {
GetProject(): SDK.IProject;
GetObjectType(): SDK.IObjectType;
GetUID(): number;
SetPropertyValue(id: string, value: EditorPropertyValueType): void;
GetPropertyValue(id: string): EditorPropertyValueType;
GetTimelinePropertyValue(id: string): EditorPropertyValueType;
GetExternalSdkInstance(): SDK.IInstanceBase | null;
}
}

View File

@ -0,0 +1,18 @@
declare namespace SDK {
class IObjectType extends IObjectClass {
GetImage(): SDK.IAnimationFrame;
EditImage(): void;
GetAnimations(): SDK.IAnimation[];
EditAnimations(): void;
AddAnimation(animName: string, frameBlob: Blob, frameWidth: number, frameHeight: number): Promise<SDK.IAnimation>;
CreateWorldInstance(layer: SDK.ILayer): SDK.IWorldInstance;
GetAllInstances(): SDK.IWorldInstance[];
IsInContainer(): boolean;
GetContainer(): SDK.IContainer | null;
CreateContainer(initialObjectTypes: SDK.IObjectType[]): SDK.IContainer;
}
}

View File

@ -0,0 +1,40 @@
declare namespace SDK {
class IWorldInstance extends IObjectInstance {
GetBoundingBox(): SDK.Rect;
GetQuad(): SDK.Quad;
GetColor(): SDK.Color;
SetOpacity(o: number): void;
GetOpacity(): number;
SetX(x: number): void;
GetX(): number;
SetY(y: number): void;
GetY(): number;
SetXY(x: number, y: number): void;
SetZElevation(z: number): void;
GetZElevation(): number;
GetTotalZElevation(): number;
SetWidth(w: number): void;
GetWidth(): number;
SetHeight(h: number): void;
GetHeight(): number;
SetSize(w: number, h: number): void;
SetOriginX(x: number): void;
GetOriginX(): number;
SetOriginY(y: number): void;
GetOriginY(): number;
SetOrigin(x: number, y: number): void;
SetAngle(a: number): void;
GetAngle(): number;
GetLayer(): SDK.ILayer;
GetLayout(): SDK.ILayout;
ApplyBlendMode(iRenderer: SDK.Gfx.IWebGLRenderer): void;
}
}

View File

@ -0,0 +1,11 @@
declare namespace SDK {
let Plugins: any;
let Behaviors: any;
}
type EditorPropertyValueType = number | string | boolean | SDK.Color;
type Vec2Arr = [number, number];
type Vec3Arr = [number, number, number];
type Vec4Arr = [number, number, number, number];

View File

@ -0,0 +1,17 @@
declare namespace SDK.UI {
class ILayoutView {
GetProject(): SDK.IProject;
GetZoomFactor(): number;
LayoutToClientDeviceX(x: number): number;
LayoutToClientDeviceY(y: number): number;
SetDeviceTransform(iRenderer: SDK.Gfx.IWebGLRenderer): void;
SetDefaultTransform(iRenderer: SDK.Gfx.IWebGLRenderer): void;
Refresh(): void;
GetLayout(): SDK.ILayout;
GetActiveLayer(): SDK.ILayer;
}
}

Some files were not shown because too many files have changed in this diff Show More