mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-14 02:58:44 +08:00
Merge branch '4.1' into 4.2-beta
# Conflicts: # .gitignore # spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp # spine-ts/package-lock.json # spine-ts/package.json
This commit is contained in:
commit
68a9096049
1
.gitignore
vendored
1
.gitignore
vendored
@ -185,3 +185,4 @@ spine-flutter/src/spine-cpp
|
||||
|
||||
spine-godot/.clang-format
|
||||
|
||||
spine-ts/spine-phaser/dist
|
||||
|
||||
@ -357,6 +357,29 @@ cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-player/example/
|
||||
cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-player/example/assets/"
|
||||
cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-player/example/assets/"
|
||||
|
||||
rm "$ROOT/spine-ts/spine-phaser/example/assets/"*
|
||||
cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../raptor/export/raptor-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../raptor/export/raptor-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
|
||||
cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
|
||||
cp -f ../coin/export/coin-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../coin/export/coin-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../coin/export/coin-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
|
||||
cp -f ../stretchyman/export/stretchyman-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../stretchyman/export/stretchyman-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../stretchyman/export/stretchyman-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../stretchyman/export/stretchyman-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
|
||||
cp -f ../mix-and-match/export/mix-and-match-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../mix-and-match/export/mix-and-match-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
cp -f ../mix-and-match/export/mix-and-match-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
|
||||
|
||||
echo "spine-monogame"
|
||||
rm "$ROOT/spine-monogame/spine-monogame-example/data/"*
|
||||
cp -f ../coin/export/coin-pro.json "$ROOT/spine-monogame/spine-monogame-example/data/"
|
||||
|
||||
@ -34,42 +34,42 @@
|
||||
using namespace spine;
|
||||
|
||||
int main(void) {
|
||||
String atlasFile("data/spineboy-pma.atlas");
|
||||
String skeletonFile("data/spineboy-pro.skel");
|
||||
float scale = 0.6f;
|
||||
SFMLTextureLoader textureLoader;
|
||||
Atlas *atlas = new Atlas(atlasFile, &textureLoader);
|
||||
SkeletonData *skeletonData = nullptr;
|
||||
if (strncmp(skeletonFile.buffer(), ".skel", skeletonFile.length()) > 0) {
|
||||
SkeletonBinary binary(atlas);
|
||||
binary.setScale(scale);
|
||||
skeletonData = binary.readSkeletonDataFile(skeletonFile);
|
||||
} else {
|
||||
SkeletonJson json(atlas);
|
||||
json.setScale(scale);
|
||||
skeletonData = json.readSkeletonDataFile(skeletonFile);
|
||||
}
|
||||
String atlasFile("data/spineboy-pma.atlas");
|
||||
String skeletonFile("data/spineboy-pro.skel");
|
||||
float scale = 0.6f;
|
||||
SFMLTextureLoader textureLoader;
|
||||
Atlas *atlas = new Atlas(atlasFile, &textureLoader);
|
||||
SkeletonData *skeletonData = nullptr;
|
||||
if (strncmp(skeletonFile.buffer(), ".skel", skeletonFile.length()) > 0) {
|
||||
SkeletonBinary binary(atlas);
|
||||
binary.setScale(scale);
|
||||
skeletonData = binary.readSkeletonDataFile(skeletonFile);
|
||||
} else {
|
||||
SkeletonJson json(atlas);
|
||||
json.setScale(scale);
|
||||
skeletonData = json.readSkeletonDataFile(skeletonFile);
|
||||
}
|
||||
|
||||
AnimationStateData stateData(skeletonData);
|
||||
SkeletonDrawable drawable(skeletonData, &stateData);
|
||||
drawable.skeleton->setPosition(320, 590);
|
||||
drawable.state->setAnimation(0, "walk", true);
|
||||
AnimationStateData stateData(skeletonData);
|
||||
SkeletonDrawable drawable(skeletonData, &stateData);
|
||||
drawable.skeleton->setPosition(320, 590);
|
||||
drawable.state->setAnimation(0, "walk", true);
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed");
|
||||
window.setFramerateLimit(60);
|
||||
sf::Event event;
|
||||
sf::Clock deltaClock;
|
||||
while (window.isOpen()) {
|
||||
while (window.pollEvent(event))
|
||||
if (event.type == sf::Event::Closed) window.close();
|
||||
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed");
|
||||
window.setFramerateLimit(60);
|
||||
sf::Event event;
|
||||
sf::Clock deltaClock;
|
||||
while (window.isOpen()) {
|
||||
while (window.pollEvent(event))
|
||||
if (event.type == sf::Event::Closed) window.close();
|
||||
|
||||
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||
deltaClock.restart();
|
||||
drawable.update(delta);
|
||||
window.clear();
|
||||
window.draw(drawable);
|
||||
window.display();
|
||||
}
|
||||
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||
deltaClock.restart();
|
||||
drawable.update(delta);
|
||||
window.clear();
|
||||
window.draw(drawable);
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
8
spine-ts/.vscode/launch.json
vendored
8
spine-ts/.vscode/launch.json
vendored
@ -31,6 +31,14 @@
|
||||
"name": "threejs-example",
|
||||
"url": "http://localhost:8080/spine-threejs/example/index.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "phaser-example",
|
||||
"url": "http://localhost:8080/spine-phaser/example/index.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
@ -16,6 +16,10 @@
|
||||
<li><a href="/spine-canvas/example">Example</a></li>
|
||||
<li><a href="/spine-canvas/example/mouse-click.html">Mouse click</a></li>
|
||||
</ul>
|
||||
<li>Phaser</li>
|
||||
<ul>
|
||||
<li><a href="/spine-phaser/example/index.html">Example</a></li>
|
||||
</ul>
|
||||
<li>Player</li>
|
||||
<ul>
|
||||
<li><a href="/spine-player/example/example.html">Example</a></li>
|
||||
|
||||
@ -7,20 +7,22 @@
|
||||
],
|
||||
"scripts": {
|
||||
"prepublish": "npm run clean && npm run build",
|
||||
"clean": "npx rimraf spine-core/dist spine-canvas/dist spine-webgl/dist spine-player/dist spine-threejs/dist",
|
||||
"build": "npm run clean && npm run build:modules && concurrently \"npm run build:core\" \"npm run build:canvas\" \"npm run build:webgl\" \"npm run build:player\" \"npm run build:threejs\"",
|
||||
"clean": "npx rimraf spine-core/dist spine-canvas/dist spine-webgl/dist spine-phaser/dist spine-player/dist spine-threejs/dist",
|
||||
"build": "npm run clean && npm run build:modules && concurrently \"npm run build:core\" \"npm run build:canvas\" \"npm run build:webgl\" \"npm run build:phaser\" \"npm run build:player\" \"npm run build:threejs\"",
|
||||
"postbuild": "npm run minify",
|
||||
"build:modules": "npx tsc -b -clean && npx tsc -b",
|
||||
"build:core": "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:canvas": "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:webgl": "npx esbuild --bundle spine-webgl/src/index.ts --tsconfig=spine-webgl/tsconfig.json --sourcemap --outfile=spine-webgl/dist/iife/spine-webgl.js --format=iife --global-name=spine",
|
||||
"build:player": "npx copyfiles -f spine-player/css/spine-player.css spine-player/dist/ && npx npx esbuild --bundle spine-player/src/index.ts --tsconfig=spine-player/tsconfig.json --sourcemap --outfile=spine-player/dist/iife/spine-player.js --format=iife --global-name=spine",
|
||||
"build:phaser": "npx esbuild --bundle spine-phaser/src/index.ts --tsconfig=spine-phaser/tsconfig.json --sourcemap --outfile=spine-phaser/dist/iife/spine-phaser.js --external:Phaser --alias:phaser=Phaser --format=iife --global-name=spine",
|
||||
"build:threejs": "npx esbuild --bundle spine-threejs/src/index.ts --tsconfig=spine-threejs/tsconfig.json --sourcemap --outfile=spine-threejs/dist/iife/spine-threejs.js --external:three --format=iife --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-canvas/dist/iife/spine-canvas.js --outfile=spine-canvas/dist/iife/spine-canvas.min.js && npx esbuild --minify spine-player/dist/iife/spine-player.js --outfile=spine-player/dist/iife/spine-player.min.js && npx esbuild --minify spine-webgl/dist/iife/spine-webgl.js --outfile=spine-webgl/dist/iife/spine-webgl.min.js && npx esbuild --minify spine-threejs/dist/iife/spine-threejs.js --outfile=spine-threejs/dist/iife/spine-threejs.min.js",
|
||||
"dev": "concurrently \"npx live-server --no-browser\" \"npm run dev:modules\" \"npm run dev:canvas\" \"npm run dev:webgl\" \"npm run dev:player\" \"npm run dev:threejs\"",
|
||||
"minify": "npx esbuild --minify spine-core/dist/iife/spine-core.js --outfile=spine-core/dist/iife/spine-core.min.js && npx esbuild --minify spine-canvas/dist/iife/spine-canvas.js --outfile=spine-canvas/dist/iife/spine-canvas.min.js && npx esbuild --minify spine-player/dist/iife/spine-player.js --outfile=spine-player/dist/iife/spine-player.min.js && npx esbuild --minify spine-phaser/dist/iife/spine-phaser.js --outfile=spine-phaser/dist/iife/spine-phaser.min.js && npx esbuild --minify spine-webgl/dist/iife/spine-webgl.js --outfile=spine-webgl/dist/iife/spine-webgl.min.js && npx esbuild --minify spine-threejs/dist/iife/spine-threejs.js --outfile=spine-threejs/dist/iife/spine-threejs.min.js",
|
||||
"dev": "concurrently \"npx live-server --no-browser\" \"npm run dev:canvas\" \"npm run dev:webgl\" \"npm run dev:phaser\" \"npm run dev:player\" \"npm run dev:threejs\"",
|
||||
"dev:modules": "npm run build:modules -- --watch",
|
||||
"dev:canvas": "npm run build:canvas -- --watch",
|
||||
"dev:webgl": "npm run build:webgl -- --watch",
|
||||
"dev:phaser": "npm run build:phaser -- --watch",
|
||||
"dev:player": "npm run build:player -- --watch",
|
||||
"dev:threejs": "npm run build:threejs -- --watch"
|
||||
},
|
||||
@ -46,18 +48,18 @@
|
||||
"workspaces": [
|
||||
"spine-core",
|
||||
"spine-canvas",
|
||||
"spine-phaser",
|
||||
"spine-player",
|
||||
"spine-threejs",
|
||||
"spine-webgl"
|
||||
],
|
||||
"devDependencies": {
|
||||
"concurrently": "^6.2.1",
|
||||
"@types/offscreencanvas": "^2019.6.4",
|
||||
"concurrently": "^7.6.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"esbuild": "^0.12.22",
|
||||
"live-server": "^1.2.1",
|
||||
"npx": "^10.2.2",
|
||||
"esbuild": "^0.16.4",
|
||||
"live-server": "^1.2.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^4.9.3",
|
||||
"@types/offscreencanvas": "^2019.6.4"
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ set -e
|
||||
|
||||
if [ ! "$#" -eq 2 ]; then
|
||||
echo "Usage: ./publish.sh <last-version> <new-version>"
|
||||
exit
|
||||
exit
|
||||
else
|
||||
lastVersion=${1%/}
|
||||
newVersion=${2%/}
|
||||
@ -14,6 +14,7 @@ fi
|
||||
sed -i '' "s/$lastVersion/$newVersion/" package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-canvas/package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-core/package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-phaser/package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-player/package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-threejs/package.json
|
||||
sed -i '' "s/$lastVersion/$newVersion/" spine-webgl/package.json
|
||||
|
||||
@ -45,6 +45,8 @@ import { Color, Utils, MathUtils, Vector2, NumberArrayLike } from "./Utils";
|
||||
*
|
||||
* See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine Runtimes Guide. */
|
||||
export class Skeleton {
|
||||
static yDown = false;;
|
||||
|
||||
/** The skeleton's setup pose data. */
|
||||
data: SkeletonData;
|
||||
|
||||
@ -81,7 +83,15 @@ export class Skeleton {
|
||||
|
||||
/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale
|
||||
* inheritance. */
|
||||
scaleY = 1;
|
||||
private _scaleY = 1;
|
||||
|
||||
public get scaleY() {
|
||||
return Skeleton.yDown ? -this._scaleY : this._scaleY;
|
||||
}
|
||||
|
||||
public set scaleY(scaleY: number) {
|
||||
this._scaleY = scaleY;
|
||||
}
|
||||
|
||||
/** Sets the skeleton X position, which is added to the root bone worldX position. */
|
||||
x = 0;
|
||||
|
||||
26
spine-ts/spine-phaser/LICENSE
Normal file
26
spine-ts/spine-phaser/LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
Spine Runtimes License Agreement
|
||||
Last updated May 1, 2019. Replaces all prior versions.
|
||||
|
||||
Copyright (c) 2013-2019, 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.
|
||||
|
||||
THIS SOFTWARE IS 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 THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
3
spine-ts/spine-phaser/README.md
Normal file
3
spine-ts/spine-phaser/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# spine-ts Phaser
|
||||
|
||||
Please see https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-ts/README.md for more information.
|
||||
59
spine-ts/spine-phaser/example/arcade-physics-test.html
Normal file
59
spine-ts/spine-phaser/example/arcade-physics-test.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Arcade Physics example</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
physics: {
|
||||
default: 'arcade',
|
||||
arcade: {
|
||||
debug: true,
|
||||
gravity: { y: 200 }
|
||||
}
|
||||
},
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("coin-data", "assets/coin-pro.skel");
|
||||
this.load.spineAtlas("coin-atlas", "assets/coin-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
let coin = this.add.spine(400, 200, 'coin-data', "coin-atlas");
|
||||
coin.animationState.setAnimation(0, "animation", true);
|
||||
coin.setScale(0.3);
|
||||
coin.setSize(280, 280);
|
||||
|
||||
this.physics.add.existing(coin);
|
||||
|
||||
coin.body.setOffset(0, 50);
|
||||
coin.body.setVelocity(100, 200);
|
||||
coin.body.setBounce(1, 1);
|
||||
coin.body.setCollideWorldBounds(true);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
19
spine-ts/spine-phaser/example/assets/coin-pma.atlas
Normal file
19
spine-ts/spine-phaser/example/assets/coin-pma.atlas
Normal file
@ -0,0 +1,19 @@
|
||||
coin-pma.png
|
||||
size: 1024, 1024
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
coin-front-logo
|
||||
bounds: 2, 570, 305, 302
|
||||
coin-front-shine-logo
|
||||
bounds: 2, 286, 282, 282
|
||||
coin-front-shine-spineboy
|
||||
bounds: 305, 283, 282, 282
|
||||
coin-front-spineboy
|
||||
bounds: 309, 567, 305, 302
|
||||
rotate: 90
|
||||
coin-side-round
|
||||
bounds: 2, 2, 144, 282
|
||||
coin-side-straight
|
||||
bounds: 286, 286, 17, 282
|
||||
shine
|
||||
bounds: 148, 39, 72, 245
|
||||
BIN
spine-ts/spine-phaser/example/assets/coin-pma.png
Normal file
BIN
spine-ts/spine-phaser/example/assets/coin-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
spine-ts/spine-phaser/example/assets/coin-pro.skel
Normal file
BIN
spine-ts/spine-phaser/example/assets/coin-pro.skel
Normal file
Binary file not shown.
363
spine-ts/spine-phaser/example/assets/mix-and-match-pma.atlas
Normal file
363
spine-ts/spine-phaser/example/assets/mix-and-match-pma.atlas
Normal file
@ -0,0 +1,363 @@
|
||||
mix-and-match-pma.png
|
||||
size: 1024, 512
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
base-head
|
||||
bounds: 587, 2, 95, 73
|
||||
boy/arm-front
|
||||
bounds: 558, 271, 36, 115
|
||||
boy/backpack
|
||||
bounds: 235, 109, 119, 153
|
||||
boy/backpack-pocket
|
||||
bounds: 328, 73, 34, 62
|
||||
rotate: 90
|
||||
boy/backpack-strap-front
|
||||
bounds: 665, 79, 38, 88
|
||||
boy/backpack-up
|
||||
bounds: 395, 364, 21, 70
|
||||
rotate: 90
|
||||
boy/body
|
||||
bounds: 251, 264, 97, 132
|
||||
rotate: 90
|
||||
boy/boot-ribbon-front
|
||||
bounds: 648, 131, 9, 11
|
||||
boy/collar
|
||||
bounds: 744, 4, 73, 29
|
||||
rotate: 90
|
||||
boy/ear
|
||||
bounds: 383, 109, 19, 23
|
||||
rotate: 90
|
||||
boy/eye-back-low-eyelid
|
||||
bounds: 739, 284, 17, 6
|
||||
rotate: 90
|
||||
boy/eye-back-pupil
|
||||
bounds: 832, 443, 8, 9
|
||||
rotate: 90
|
||||
boy/eye-back-up-eyelid
|
||||
bounds: 558, 264, 23, 5
|
||||
boy/eye-back-up-eyelid-back
|
||||
bounds: 802, 491, 19, 10
|
||||
rotate: 90
|
||||
boy/eye-front-low-eyelid
|
||||
bounds: 386, 363, 22, 7
|
||||
rotate: 90
|
||||
boy/eye-front-pupil
|
||||
bounds: 816, 389, 9, 9
|
||||
boy/eye-front-up-eyelid
|
||||
bounds: 160, 71, 31, 6
|
||||
rotate: 90
|
||||
boy/eye-front-up-eyelid-back
|
||||
bounds: 801, 434, 26, 9
|
||||
rotate: 90
|
||||
boy/eye-iris-back
|
||||
bounds: 618, 264, 17, 17
|
||||
boy/eye-iris-front
|
||||
bounds: 727, 264, 18, 18
|
||||
boy/eye-white-back
|
||||
bounds: 580, 131, 20, 12
|
||||
boy/eye-white-front
|
||||
bounds: 510, 130, 27, 13
|
||||
boy/eyebrow-back
|
||||
bounds: 751, 88, 20, 11
|
||||
rotate: 90
|
||||
boy/eyebrow-front
|
||||
bounds: 483, 130, 25, 11
|
||||
boy/hair-back
|
||||
bounds: 494, 388, 122, 81
|
||||
rotate: 90
|
||||
boy/hair-bangs
|
||||
bounds: 667, 284, 70, 37
|
||||
boy/hair-side
|
||||
bounds: 789, 374, 25, 43
|
||||
boy/hand-backfingers
|
||||
bounds: 467, 364, 19, 21
|
||||
boy/hand-front-fingers
|
||||
bounds: 488, 364, 19, 21
|
||||
boy/hat
|
||||
bounds: 615, 417, 93, 56
|
||||
rotate: 90
|
||||
boy/leg-front
|
||||
bounds: 138, 104, 31, 158
|
||||
boy/mouth-close
|
||||
bounds: 551, 365, 21, 5
|
||||
rotate: 90
|
||||
girl-blue-cape/mouth-close
|
||||
bounds: 551, 365, 21, 5
|
||||
rotate: 90
|
||||
girl-spring-dress/mouth-close
|
||||
bounds: 551, 365, 21, 5
|
||||
rotate: 90
|
||||
girl/mouth-close
|
||||
bounds: 551, 365, 21, 5
|
||||
rotate: 90
|
||||
boy/mouth-smile
|
||||
bounds: 705, 79, 29, 7
|
||||
boy/nose
|
||||
bounds: 836, 473, 17, 10
|
||||
rotate: 90
|
||||
boy/pompom
|
||||
bounds: 747, 273, 48, 43
|
||||
rotate: 90
|
||||
boy/zip
|
||||
bounds: 648, 144, 14, 23
|
||||
girl-blue-cape/back-eyebrow
|
||||
bounds: 602, 131, 18, 12
|
||||
girl-blue-cape/body-dress
|
||||
bounds: 2, 264, 109, 246
|
||||
girl-blue-cape/body-ribbon
|
||||
bounds: 615, 283, 50, 38
|
||||
girl-blue-cape/cape-back
|
||||
bounds: 2, 69, 134, 193
|
||||
girl-blue-cape/cape-back-up
|
||||
bounds: 386, 387, 123, 106
|
||||
rotate: 90
|
||||
girl-blue-cape/cape-ribbon
|
||||
bounds: 675, 264, 50, 18
|
||||
girl-blue-cape/cape-shoulder-back
|
||||
bounds: 751, 110, 49, 59
|
||||
girl-blue-cape/cape-shoulder-front
|
||||
bounds: 113, 264, 62, 76
|
||||
rotate: 90
|
||||
girl-blue-cape/cape-up-front
|
||||
bounds: 399, 264, 98, 117
|
||||
rotate: 90
|
||||
girl-blue-cape/ear
|
||||
bounds: 775, 2, 19, 23
|
||||
girl-spring-dress/ear
|
||||
bounds: 775, 2, 19, 23
|
||||
girl/ear
|
||||
bounds: 775, 2, 19, 23
|
||||
girl-blue-cape/eye-back-low-eyelid
|
||||
bounds: 802, 463, 17, 6
|
||||
girl-spring-dress/eye-back-low-eyelid
|
||||
bounds: 802, 463, 17, 6
|
||||
girl/eye-back-low-eyelid
|
||||
bounds: 802, 463, 17, 6
|
||||
girl-blue-cape/eye-back-pupil
|
||||
bounds: 816, 367, 8, 9
|
||||
girl-spring-dress/eye-back-pupil
|
||||
bounds: 816, 367, 8, 9
|
||||
girl/eye-back-pupil
|
||||
bounds: 816, 367, 8, 9
|
||||
girl-blue-cape/eye-back-up-eyelid
|
||||
bounds: 554, 131, 24, 12
|
||||
girl-spring-dress/eye-back-up-eyelid
|
||||
bounds: 554, 131, 24, 12
|
||||
girl/eye-back-up-eyelid
|
||||
bounds: 554, 131, 24, 12
|
||||
girl-blue-cape/eye-back-up-eyelid-back
|
||||
bounds: 832, 453, 17, 11
|
||||
rotate: 90
|
||||
girl-spring-dress/eye-back-up-eyelid-back
|
||||
bounds: 832, 453, 17, 11
|
||||
rotate: 90
|
||||
girl/eye-back-up-eyelid-back
|
||||
bounds: 832, 453, 17, 11
|
||||
rotate: 90
|
||||
girl-blue-cape/eye-front-low-eyelid
|
||||
bounds: 739, 303, 18, 6
|
||||
rotate: 90
|
||||
girl-spring-dress/eye-front-low-eyelid
|
||||
bounds: 739, 303, 18, 6
|
||||
rotate: 90
|
||||
girl/eye-front-low-eyelid
|
||||
bounds: 739, 303, 18, 6
|
||||
rotate: 90
|
||||
girl-blue-cape/eye-front-pupil
|
||||
bounds: 816, 378, 9, 9
|
||||
girl-spring-dress/eye-front-pupil
|
||||
bounds: 816, 378, 9, 9
|
||||
girl/eye-front-pupil
|
||||
bounds: 816, 378, 9, 9
|
||||
girl-blue-cape/eye-front-up-eyelid
|
||||
bounds: 392, 77, 30, 14
|
||||
rotate: 90
|
||||
girl-spring-dress/eye-front-up-eyelid
|
||||
bounds: 392, 77, 30, 14
|
||||
rotate: 90
|
||||
girl/eye-front-up-eyelid
|
||||
bounds: 392, 77, 30, 14
|
||||
rotate: 90
|
||||
girl-blue-cape/eye-front-up-eyelid-back
|
||||
bounds: 455, 130, 26, 11
|
||||
girl-spring-dress/eye-front-up-eyelid-back
|
||||
bounds: 455, 130, 26, 11
|
||||
girl/eye-front-up-eyelid-back
|
||||
bounds: 455, 130, 26, 11
|
||||
girl-blue-cape/eye-iris-back
|
||||
bounds: 637, 264, 17, 17
|
||||
girl-blue-cape/eye-iris-front
|
||||
bounds: 802, 471, 18, 18
|
||||
girl-blue-cape/eye-white-back
|
||||
bounds: 596, 264, 20, 16
|
||||
girl-spring-dress/eye-white-back
|
||||
bounds: 596, 264, 20, 16
|
||||
girl-blue-cape/eye-white-front
|
||||
bounds: 796, 5, 20, 16
|
||||
rotate: 90
|
||||
girl-spring-dress/eye-white-front
|
||||
bounds: 796, 5, 20, 16
|
||||
rotate: 90
|
||||
girl/eye-white-front
|
||||
bounds: 796, 5, 20, 16
|
||||
rotate: 90
|
||||
girl-blue-cape/front-eyebrow
|
||||
bounds: 608, 149, 18, 12
|
||||
rotate: 90
|
||||
girl-blue-cape/hair-back
|
||||
bounds: 508, 145, 117, 98
|
||||
rotate: 90
|
||||
girl-blue-cape/hair-bangs
|
||||
bounds: 673, 419, 91, 40
|
||||
rotate: 90
|
||||
girl-blue-cape/hair-head-side-back
|
||||
bounds: 196, 331, 30, 52
|
||||
rotate: 90
|
||||
girl-blue-cape/hair-head-side-front
|
||||
bounds: 738, 323, 41, 42
|
||||
girl-blue-cape/hair-side
|
||||
bounds: 473, 3, 36, 71
|
||||
girl-blue-cape/hand-front-fingers
|
||||
bounds: 509, 365, 19, 21
|
||||
girl-spring-dress/hand-front-fingers
|
||||
bounds: 509, 365, 19, 21
|
||||
girl-blue-cape/leg-front
|
||||
bounds: 168, 72, 30, 158
|
||||
rotate: 90
|
||||
girl-blue-cape/mouth-smile
|
||||
bounds: 736, 79, 29, 7
|
||||
girl-spring-dress/mouth-smile
|
||||
bounds: 736, 79, 29, 7
|
||||
girl/mouth-smile
|
||||
bounds: 736, 79, 29, 7
|
||||
girl-blue-cape/nose
|
||||
bounds: 747, 264, 11, 7
|
||||
girl-spring-dress/nose
|
||||
bounds: 747, 264, 11, 7
|
||||
girl/nose
|
||||
bounds: 747, 264, 11, 7
|
||||
girl-blue-cape/sleeve-back
|
||||
bounds: 767, 79, 42, 29
|
||||
girl-blue-cape/sleeve-front
|
||||
bounds: 408, 76, 52, 119
|
||||
rotate: 90
|
||||
girl-spring-dress/arm-front
|
||||
bounds: 596, 282, 17, 111
|
||||
girl-spring-dress/back-eyebrow
|
||||
bounds: 801, 420, 18, 12
|
||||
girl-spring-dress/body-up
|
||||
bounds: 179, 4, 64, 66
|
||||
girl-spring-dress/cloak-down
|
||||
bounds: 775, 27, 50, 50
|
||||
girl-spring-dress/cloak-up
|
||||
bounds: 360, 7, 64, 58
|
||||
rotate: 90
|
||||
girl-spring-dress/eye-iris-back
|
||||
bounds: 656, 264, 17, 17
|
||||
girl-spring-dress/eye-iris-front
|
||||
bounds: 814, 492, 18, 18
|
||||
girl-spring-dress/front-eyebrow
|
||||
bounds: 822, 472, 18, 12
|
||||
rotate: 90
|
||||
girl-spring-dress/hair-back
|
||||
bounds: 196, 363, 147, 93
|
||||
rotate: 90
|
||||
girl-spring-dress/hair-bangs
|
||||
bounds: 696, 326, 91, 40
|
||||
rotate: 90
|
||||
girl-spring-dress/hair-head-side-back
|
||||
bounds: 529, 76, 30, 52
|
||||
girl-spring-dress/hair-head-side-front
|
||||
bounds: 781, 323, 41, 42
|
||||
girl-spring-dress/hair-side
|
||||
bounds: 511, 3, 36, 71
|
||||
girl-spring-dress/leg-front
|
||||
bounds: 171, 104, 30, 158
|
||||
girl-spring-dress/neck
|
||||
bounds: 138, 70, 20, 32
|
||||
girl-spring-dress/shoulder-ribbon
|
||||
bounds: 622, 131, 36, 24
|
||||
rotate: 90
|
||||
girl-spring-dress/skirt
|
||||
bounds: 113, 328, 182, 81
|
||||
rotate: 90
|
||||
girl-spring-dress/underskirt
|
||||
bounds: 2, 2, 175, 65
|
||||
girl/arm-front
|
||||
bounds: 577, 395, 36, 115
|
||||
girl/back-eyebrow
|
||||
bounds: 834, 492, 18, 12
|
||||
rotate: 90
|
||||
girl/bag-base
|
||||
bounds: 191, 264, 62, 58
|
||||
rotate: 90
|
||||
girl/bag-strap-front
|
||||
bounds: 385, 265, 12, 96
|
||||
girl/bag-top
|
||||
bounds: 738, 367, 49, 50
|
||||
girl/body
|
||||
bounds: 356, 130, 97, 132
|
||||
girl/boot-ribbon-front
|
||||
bounds: 539, 130, 13, 13
|
||||
girl/eye-iris-back
|
||||
bounds: 821, 424, 17, 17
|
||||
girl/eye-iris-front
|
||||
bounds: 812, 443, 18, 18
|
||||
girl/eye-white-back
|
||||
bounds: 814, 5, 20, 16
|
||||
rotate: 90
|
||||
girl/front-eyebrow
|
||||
bounds: 816, 400, 18, 12
|
||||
rotate: 90
|
||||
girl/hair-back
|
||||
bounds: 291, 363, 147, 93
|
||||
rotate: 90
|
||||
girl/hair-bangs
|
||||
bounds: 715, 419, 91, 40
|
||||
rotate: 90
|
||||
girl/hair-flap-down-front
|
||||
bounds: 288, 5, 70, 65
|
||||
girl/hair-head-side-back
|
||||
bounds: 561, 77, 30, 52
|
||||
girl/hair-head-side-front
|
||||
bounds: 757, 419, 41, 42
|
||||
rotate: 90
|
||||
girl/hair-patch
|
||||
bounds: 245, 4, 66, 41
|
||||
rotate: 90
|
||||
girl/hair-side
|
||||
bounds: 549, 3, 36, 71
|
||||
girl/hair-strand-back-1
|
||||
bounds: 684, 3, 58, 74
|
||||
girl/hair-strand-back-2
|
||||
bounds: 692, 171, 91, 58
|
||||
rotate: 90
|
||||
girl/hair-strand-back-3
|
||||
bounds: 615, 323, 92, 79
|
||||
rotate: 90
|
||||
girl/hair-strand-front-1
|
||||
bounds: 518, 269, 38, 94
|
||||
girl/hair-strand-front-2
|
||||
bounds: 593, 79, 70, 50
|
||||
girl/hair-strand-front-3
|
||||
bounds: 705, 88, 44, 81
|
||||
girl/hand-front-fingers
|
||||
bounds: 530, 365, 19, 21
|
||||
girl/hat
|
||||
bounds: 608, 169, 93, 82
|
||||
rotate: 90
|
||||
girl/leg-front
|
||||
bounds: 203, 104, 30, 158
|
||||
girl/pompom
|
||||
bounds: 757, 462, 48, 43
|
||||
rotate: 90
|
||||
girl/scarf
|
||||
bounds: 455, 143, 119, 51
|
||||
rotate: 90
|
||||
girl/scarf-back
|
||||
bounds: 420, 2, 72, 51
|
||||
rotate: 90
|
||||
girl/zip
|
||||
bounds: 356, 109, 19, 25
|
||||
rotate: 90
|
||||
BIN
spine-ts/spine-phaser/example/assets/mix-and-match-pma.png
Normal file
BIN
spine-ts/spine-phaser/example/assets/mix-and-match-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 369 KiB |
8001
spine-ts/spine-phaser/example/assets/mix-and-match-pro.json
Normal file
8001
spine-ts/spine-phaser/example/assets/mix-and-match-pro.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
spine-ts/spine-phaser/example/assets/mix-and-match-pro.skel
Normal file
BIN
spine-ts/spine-phaser/example/assets/mix-and-match-pro.skel
Normal file
Binary file not shown.
101
spine-ts/spine-phaser/example/assets/raptor-pma.atlas
Normal file
101
spine-ts/spine-phaser/example/assets/raptor-pma.atlas
Normal file
@ -0,0 +1,101 @@
|
||||
raptor-pma.png
|
||||
size: 1024, 512
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
back-arm
|
||||
bounds: 829, 88, 46, 25
|
||||
rotate: 90
|
||||
back-bracer
|
||||
bounds: 195, 238, 39, 28
|
||||
rotate: 90
|
||||
back-hand
|
||||
bounds: 724, 140, 36, 34
|
||||
rotate: 90
|
||||
back-knee
|
||||
bounds: 760, 131, 49, 67
|
||||
rotate: 90
|
||||
back-thigh
|
||||
bounds: 225, 238, 39, 24
|
||||
rotate: 90
|
||||
eyes-open
|
||||
bounds: 975, 204, 47, 45
|
||||
front-arm
|
||||
bounds: 969, 112, 48, 26
|
||||
front-bracer
|
||||
bounds: 724, 97, 41, 29
|
||||
rotate: 90
|
||||
front-hand
|
||||
bounds: 251, 239, 41, 38
|
||||
front-open-hand
|
||||
bounds: 856, 76, 43, 44
|
||||
rotate: 90
|
||||
front-thigh
|
||||
bounds: 729, 178, 57, 29
|
||||
rotate: 90
|
||||
gun
|
||||
bounds: 894, 251, 107, 103
|
||||
gun-nohand
|
||||
bounds: 764, 241, 105, 102
|
||||
head
|
||||
bounds: 756, 345, 136, 149
|
||||
lower-leg
|
||||
bounds: 475, 237, 73, 98
|
||||
rotate: 90
|
||||
mouth-grind
|
||||
bounds: 975, 172, 47, 30
|
||||
mouth-smile
|
||||
bounds: 975, 140, 47, 30
|
||||
neck
|
||||
bounds: 366, 282, 18, 21
|
||||
raptor-back-arm
|
||||
bounds: 636, 97, 82, 86
|
||||
rotate: 90
|
||||
raptor-body
|
||||
bounds: 2, 2, 632, 233
|
||||
raptor-front-arm
|
||||
bounds: 871, 168, 81, 102
|
||||
rotate: 90
|
||||
raptor-front-leg
|
||||
bounds: 2, 237, 191, 257
|
||||
raptor-hindleg-back
|
||||
bounds: 195, 279, 169, 215
|
||||
raptor-horn
|
||||
bounds: 431, 312, 182, 80
|
||||
rotate: 90
|
||||
raptor-horn-back
|
||||
bounds: 513, 318, 176, 77
|
||||
rotate: 90
|
||||
raptor-jaw
|
||||
bounds: 894, 356, 126, 138
|
||||
raptor-jaw-tooth
|
||||
bounds: 294, 240, 37, 48
|
||||
rotate: 90
|
||||
raptor-mouth-inside
|
||||
bounds: 344, 241, 36, 41
|
||||
rotate: 90
|
||||
raptor-saddle-strap-back
|
||||
bounds: 575, 242, 54, 74
|
||||
raptor-saddle-strap-front
|
||||
bounds: 764, 182, 57, 95
|
||||
rotate: 90
|
||||
raptor-saddle-w-shadow
|
||||
bounds: 592, 323, 162, 171
|
||||
raptor-tail-shadow
|
||||
bounds: 366, 305, 189, 63
|
||||
rotate: 90
|
||||
raptor-tongue
|
||||
bounds: 387, 239, 86, 64
|
||||
stirrup-back
|
||||
bounds: 829, 136, 44, 35
|
||||
rotate: 90
|
||||
stirrup-front
|
||||
bounds: 866, 121, 45, 50
|
||||
rotate: 90
|
||||
stirrup-strap
|
||||
bounds: 918, 120, 49, 46
|
||||
torso
|
||||
bounds: 636, 181, 54, 91
|
||||
rotate: 90
|
||||
visor
|
||||
bounds: 631, 237, 131, 84
|
||||
BIN
spine-ts/spine-phaser/example/assets/raptor-pma.png
Normal file
BIN
spine-ts/spine-phaser/example/assets/raptor-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 KiB |
9161
spine-ts/spine-phaser/example/assets/raptor-pro.json
Normal file
9161
spine-ts/spine-phaser/example/assets/raptor-pro.json
Normal file
File diff suppressed because one or more lines are too long
102
spine-ts/spine-phaser/example/assets/spineboy-pma.atlas
Normal file
102
spine-ts/spine-phaser/example/assets/spineboy-pma.atlas
Normal file
@ -0,0 +1,102 @@
|
||||
spineboy-pma.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
crosshair
|
||||
bounds: 813, 160, 45, 45
|
||||
eye-indifferent
|
||||
bounds: 569, 2, 47, 45
|
||||
eye-surprised
|
||||
bounds: 643, 7, 47, 45
|
||||
rotate: 90
|
||||
front-bracer
|
||||
bounds: 811, 51, 29, 40
|
||||
front-fist-closed
|
||||
bounds: 807, 93, 38, 41
|
||||
front-fist-open
|
||||
bounds: 815, 210, 43, 44
|
||||
front-foot
|
||||
bounds: 706, 64, 63, 35
|
||||
rotate: 90
|
||||
front-shin
|
||||
bounds: 80, 11, 41, 92
|
||||
front-thigh
|
||||
bounds: 754, 12, 23, 56
|
||||
front-upper-arm
|
||||
bounds: 618, 5, 23, 49
|
||||
goggles
|
||||
bounds: 214, 20, 131, 83
|
||||
gun
|
||||
bounds: 347, 14, 105, 102
|
||||
rotate: 90
|
||||
head
|
||||
bounds: 80, 105, 136, 149
|
||||
hoverboard-board
|
||||
bounds: 2, 8, 246, 76
|
||||
rotate: 90
|
||||
hoverboard-thruster
|
||||
bounds: 478, 2, 30, 32
|
||||
hoverglow-small
|
||||
bounds: 218, 117, 137, 38
|
||||
rotate: 90
|
||||
mouth-grind
|
||||
bounds: 775, 80, 47, 30
|
||||
rotate: 90
|
||||
mouth-oooo
|
||||
bounds: 779, 31, 47, 30
|
||||
rotate: 90
|
||||
mouth-smile
|
||||
bounds: 783, 207, 47, 30
|
||||
rotate: 90
|
||||
muzzle-glow
|
||||
bounds: 779, 4, 25, 25
|
||||
muzzle-ring
|
||||
bounds: 451, 14, 25, 105
|
||||
muzzle01
|
||||
bounds: 664, 60, 67, 40
|
||||
rotate: 90
|
||||
muzzle02
|
||||
bounds: 580, 56, 68, 42
|
||||
rotate: 90
|
||||
muzzle03
|
||||
bounds: 478, 36, 83, 53
|
||||
rotate: 90
|
||||
muzzle04
|
||||
bounds: 533, 49, 75, 45
|
||||
rotate: 90
|
||||
muzzle05
|
||||
bounds: 624, 56, 68, 38
|
||||
rotate: 90
|
||||
neck
|
||||
bounds: 806, 8, 18, 21
|
||||
portal-bg
|
||||
bounds: 258, 121, 133, 133
|
||||
portal-flare1
|
||||
bounds: 690, 2, 56, 30
|
||||
rotate: 90
|
||||
portal-flare2
|
||||
bounds: 510, 3, 57, 31
|
||||
portal-flare3
|
||||
bounds: 722, 4, 58, 30
|
||||
rotate: 90
|
||||
portal-shade
|
||||
bounds: 393, 121, 133, 133
|
||||
portal-streaks1
|
||||
bounds: 528, 126, 126, 128
|
||||
portal-streaks2
|
||||
bounds: 656, 129, 125, 125
|
||||
rear-bracer
|
||||
bounds: 826, 13, 28, 36
|
||||
rear-foot
|
||||
bounds: 743, 70, 57, 30
|
||||
rotate: 90
|
||||
rear-shin
|
||||
bounds: 174, 14, 38, 89
|
||||
rear-thigh
|
||||
bounds: 783, 158, 28, 47
|
||||
rear-upper-arm
|
||||
bounds: 783, 136, 20, 44
|
||||
rotate: 90
|
||||
torso
|
||||
bounds: 123, 13, 49, 90
|
||||
BIN
spine-ts/spine-phaser/example/assets/spineboy-pma.png
Normal file
BIN
spine-ts/spine-phaser/example/assets/spineboy-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 KiB |
BIN
spine-ts/spine-phaser/example/assets/spineboy-pro.skel
Normal file
BIN
spine-ts/spine-phaser/example/assets/spineboy-pro.skel
Normal file
Binary file not shown.
16
spine-ts/spine-phaser/example/assets/stretchyman-pma.atlas
Normal file
16
spine-ts/spine-phaser/example/assets/stretchyman-pma.atlas
Normal file
@ -0,0 +1,16 @@
|
||||
stretchyman-pma.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
back-arm
|
||||
bounds: 149, 45, 72, 202
|
||||
back-leg
|
||||
bounds: 312, 4, 100, 318
|
||||
rotate: 90
|
||||
body
|
||||
bounds: 223, 106, 141, 452
|
||||
rotate: 90
|
||||
front-arm
|
||||
bounds: 2, 26, 145, 221
|
||||
head
|
||||
bounds: 223, 2, 87, 102
|
||||
BIN
spine-ts/spine-phaser/example/assets/stretchyman-pma.png
Normal file
BIN
spine-ts/spine-phaser/example/assets/stretchyman-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
2116
spine-ts/spine-phaser/example/assets/stretchyman-pro.json
Normal file
2116
spine-ts/spine-phaser/example/assets/stretchyman-pro.json
Normal file
File diff suppressed because one or more lines are too long
BIN
spine-ts/spine-phaser/example/assets/stretchyman-pro.skel
Normal file
BIN
spine-ts/spine-phaser/example/assets/stretchyman-pro.skel
Normal file
Binary file not shown.
44
spine-ts/spine-phaser/example/basic-example.html
Normal file
44
spine-ts/spine-phaser/example/basic-example.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Basic example</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
let spineboy = this.add.spine(400, 300, 'spineboy-data', "spineboy-atlas");
|
||||
spineboy.scale = 0.5;
|
||||
spineboy.animationState.setAnimation(0, "walk", true);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
63
spine-ts/spine-phaser/example/batching-test.html
Normal file
63
spine-ts/spine-phaser/example/batching-test.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Batching test</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
update: update,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
let debug;
|
||||
|
||||
function preload () {
|
||||
this.load.spineJson("raptor-data", "assets/raptor-pro.json");
|
||||
this.load.spineAtlas("raptor-atlas", "assets/raptor-pma.atlas");
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
let plugin = this.spine;
|
||||
let x = 25;
|
||||
let y = 60;
|
||||
for (let j = 0; j < 10; j++, y+= 600 / 10) {
|
||||
for (let i = 0; i < 20; i++, x += 800 / 20) {
|
||||
let obj = Math.random() > 0.5
|
||||
? this.add.spine(x, y, 'spineboy-data', "spineboy-atlas")
|
||||
: this.add.spine(x, y, 'raptor-data', "raptor-atlas");
|
||||
obj.animationState.setAnimation(0, "walk", true);
|
||||
obj.scale = 0.1;
|
||||
}
|
||||
x = 25;
|
||||
}
|
||||
debug = this.add.text(0, 600 - 40, "FPS: ");
|
||||
}
|
||||
|
||||
function update () {
|
||||
debug.setText("draw calls: " + spine.PolygonBatcher.getAndResetGlobalDrawCalls() + "\ndelta: " + game.loop.delta);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
70
spine-ts/spine-phaser/example/blend-test.html
Normal file
70
spine-ts/spine-phaser/example/blend-test.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Blend test</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
backgroundColor: '#cdcdcd',
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
update: update
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let controls;
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
let obj = this.add.spine(i * 200, 600, 'spineboy-data', 'spineboy-atlas').setScale(0.25);
|
||||
obj.setScale(0.25);
|
||||
obj.animationState.setAnimation(0, "idle", true);
|
||||
obj.animationState.setAnimation(1, "shoot", true);
|
||||
}
|
||||
var cursors = this.input.keyboard.createCursorKeys();
|
||||
|
||||
var controlConfig = {
|
||||
camera: this.cameras.main,
|
||||
left: cursors.left,
|
||||
right: cursors.right,
|
||||
up: cursors.up,
|
||||
down: cursors.down,
|
||||
zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
|
||||
zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
|
||||
acceleration: 0.35,
|
||||
drag: 0.01,
|
||||
maxSpeed: 1.2
|
||||
};
|
||||
|
||||
controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
|
||||
}
|
||||
|
||||
function update (time, delta) {
|
||||
controls.update(delta);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
56
spine-ts/spine-phaser/example/bounds-test.html
Normal file
56
spine-ts/spine-phaser/example/bounds-test.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bounds test</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
update: update,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
let spineboy;
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
spineboy = this.add.spine(400, 300, 'spineboy-data', "spineboy-atlas", new spine.SkinsAndAnimationBoundsProvider("run"));
|
||||
spineboy.scale = 0.4
|
||||
spineboy.setInteractive();
|
||||
this.input.enableDebug(spineboy, 0xff00ff);
|
||||
spineboy.on("pointerdown", () => spineboy.animationState.setAnimation(0, "run", true));
|
||||
}
|
||||
|
||||
let time = 0;
|
||||
function update (t, delta) {
|
||||
time += delta / 1000;
|
||||
let scale = 0.4 + Math.cos(time) * 0.2;
|
||||
spineboy.scale = scale;
|
||||
spineboy.angle++;
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
113
spine-ts/spine-phaser/example/camera-pipeline-test.html
Normal file
113
spine-ts/spine-phaser/example/camera-pipeline-test.html
Normal file
@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Camera pipeline test</h1>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
backgroundColor: '#cdcdcd',
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const fragShader = `
|
||||
#define SHADER_NAME PLASMA_FS
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D uMainSampler;
|
||||
uniform float uTime;
|
||||
uniform vec2 uResolution;
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / uResolution.xy;
|
||||
|
||||
float x = p.x;
|
||||
float y = p.y;
|
||||
float mov0 = x+y+cos(sin(uTime)*2.0)*100.+sin(x/100.)*1000.;
|
||||
float mov1 = y / 0.9 + uTime;
|
||||
float mov2 = x / 0.2;
|
||||
float c1 = abs(sin(mov1+uTime)/2.+mov2/2.-mov1-mov2+uTime);
|
||||
float c2 = abs(sin(c1+sin(mov0/1000.+uTime)+sin(y/40.+uTime)+sin((x+y)/100.)*3.));
|
||||
float c3 = abs(sin(c2+cos(mov1+mov2+c2)+cos(mov2)+sin(x/1000.)));
|
||||
|
||||
vec4 pixel = texture2D(uMainSampler, outTexCoord);
|
||||
|
||||
gl_FragColor = pixel * vec4(c1, c2, c3, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
class PlasmaPostFX extends Phaser.Renderer.WebGL.Pipelines.PostFXPipeline {
|
||||
constructor(game) {
|
||||
super({
|
||||
game,
|
||||
name: 'PlasmaPostFX',
|
||||
fragShader,
|
||||
uniforms: [
|
||||
'uMainSampler',
|
||||
'uTime',
|
||||
'uResolution'
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
onPreRender() {
|
||||
this.set1f('uTime', this.game.loop.time / 1000);
|
||||
}
|
||||
|
||||
onDraw(renderTarget) {
|
||||
this.set2f('uResolution', renderTarget.width, renderTarget.height);
|
||||
|
||||
this.bindAndDraw(renderTarget);
|
||||
}
|
||||
}
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload() {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
this.load.image("img", "assets/raptor-pma.png")
|
||||
}
|
||||
|
||||
function create() {
|
||||
this.renderer.pipelines.addPostPipeline('PlasmaPostFX', PlasmaPostFX);
|
||||
|
||||
// FIXME: Need a dummy sprite so the MultiPipeline sets up state
|
||||
// so rendering the Spine sprite actually works. Unsure what state
|
||||
// is needed.
|
||||
var s = this.add.sprite(0, 0, 'img');
|
||||
|
||||
let spineboy = this.add.spine(400, 300, 'spineboy-data', "spineboy-atlas");
|
||||
spineboy.scale = 0.5;
|
||||
spineboy.animationState.setAnimation(0, "walk", true);
|
||||
|
||||
this.cameras.main.setPostPipeline("PlasmaPostFX");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
71
spine-ts/spine-phaser/example/control-bones-test.html
Normal file
71
spine-ts/spine-phaser/example/control-bones-test.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Control bones</h1>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("stretchyman-data", "assets/stretchyman-pro.skel");
|
||||
this.load.spineAtlas("stretchyman-atlas", "assets/stretchyman-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
let stretchyman = this.add.spine(400, 550, 'stretchyman-data', "stretchyman-atlas");
|
||||
stretchyman.scale = 0.8;
|
||||
stretchyman.skeleton.updateWorldTransform();
|
||||
|
||||
var controlBones = ["back-arm-ik-target", "back-leg-ik-target", "front-arm-ik-target", "front-leg-ik-target"];
|
||||
for (var i = 0; i < controlBones.length; i++)
|
||||
{
|
||||
var bone = stretchyman.skeleton.findBone(controlBones[i]);
|
||||
let point = {x: bone.worldX, y: bone.worldY};
|
||||
stretchyman.skeletonToPhaserWorldCoordinates(point);
|
||||
|
||||
var control = this.add.circle(point.x, point.y, 4, 0xff00ff).setData('bone', bone);
|
||||
|
||||
control.setInteractive();
|
||||
this.input.setDraggable(control);
|
||||
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
|
||||
|
||||
gameObject.x = dragX;
|
||||
gameObject.y = dragY;
|
||||
|
||||
var bone = gameObject.getData('bone');
|
||||
let point = { x: dragX, y: dragY };
|
||||
stretchyman.phaserWorldCoordinatesToBone(point, bone);
|
||||
|
||||
bone.x = point.x;
|
||||
bone.y = point.y;
|
||||
bone.update();
|
||||
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
24
spine-ts/spine-phaser/example/index.html
Normal file
24
spine-ts/spine-phaser/example/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Spine Phaser</h1>
|
||||
<ul>
|
||||
<li><a href="./basic-example.html">Basic example</a></li>
|
||||
<li><a href="./batching-test.html">Batching test</a></li>
|
||||
<li><a href="./multi-scene-test.html">Multi-scene test</a></li>
|
||||
<li><a href="./bounds-test.html">Bounds test</a></li>
|
||||
<li><a href="./visibility-test.html">Visibility test</a></li>
|
||||
<li><a href="./arcade-physics-test.html">Arcade physics example</a></li>
|
||||
<li><a href="./blend-test.html">Blend test</a></li>
|
||||
<li><a href="./camera-pipeline-test.html">Camera pipeline test</a></li>
|
||||
<li><a href="./control-bones-test.html">Control bones</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
65
spine-ts/spine-phaser/example/multi-scene-test.html
Normal file
65
spine-ts/spine-phaser/example/multi-scene-test.html
Normal file
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Multi-scene test</h1>
|
||||
</body>
|
||||
<script>
|
||||
class Scene1 extends Phaser.Scene {
|
||||
constructor () {
|
||||
super({key: "Scene1"})
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
create() {
|
||||
let spineboy = this.add.spine(400, 500, 'spineboy-data', "spineboy-atlas");
|
||||
spineboy.scale = 0.5;
|
||||
spineboy.animationState.setAnimation(0, "walk", true);
|
||||
this.input.once('pointerdown', () => this.scene.start('Scene2'));
|
||||
}
|
||||
}
|
||||
|
||||
class Scene2 extends Phaser.Scene {
|
||||
constructor () {
|
||||
super({key: "Scene2"})
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.spineJson("raptor-data", "assets/raptor-pro.json");
|
||||
this.load.spineAtlas("raptor-atlas", "assets/raptor-pma.atlas");
|
||||
}
|
||||
|
||||
create() {
|
||||
let raptor = this.add.spine(300, 600, 'raptor-data', "raptor-atlas");
|
||||
raptor.scale = 0.5;
|
||||
raptor.animationState.setAnimation(0, "walk", true);
|
||||
this.input.once('pointerdown', () => this.scene.start('Scene1'));
|
||||
}
|
||||
}
|
||||
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: [ Scene1, Scene2 ],
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
let game = new Phaser.Game(config);
|
||||
</script>
|
||||
</html>
|
||||
BIN
spine-ts/spine-phaser/example/nyan.png
Normal file
BIN
spine-ts/spine-phaser/example/nyan.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 563 B |
50
spine-ts/spine-phaser/example/visibility-test.html
Normal file
50
spine-ts/spine-phaser/example/visibility-test.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Basic example</h1>
|
||||
</body>
|
||||
<script>
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: {
|
||||
preload: preload,
|
||||
create: create,
|
||||
},
|
||||
plugins: {
|
||||
scene: [
|
||||
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
||||
|
||||
function preload () {
|
||||
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
|
||||
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
|
||||
}
|
||||
|
||||
function create () {
|
||||
let spineboy = this.add.spine(250, 500, 'spineboy-data', "spineboy-atlas");
|
||||
spineboy.scale = 0.5;
|
||||
spineboy.animationState.setAnimation(0, "walk", true);
|
||||
|
||||
let spineboy2 = this.add.spine(550, 500, 'spineboy-data', "spineboy-atlas");
|
||||
spineboy2.scale = 0.5;
|
||||
spineboy2.animationState.setAnimation(0, "run", true);
|
||||
|
||||
this.input.on('pointerdown', () => spineboy2.visible = !spineboy2.visible);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
38
spine-ts/spine-phaser/package.json
Normal file
38
spine-ts/spine-phaser/package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-phaser",
|
||||
"version": "4.2.10",
|
||||
"description": "The official Spine Runtimes for the Phaser.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"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.10",
|
||||
"@esotericsoftware/spine-webgl": "^4.2.10",
|
||||
"@esotericsoftware/spine-canvas": "^4.2.10",
|
||||
"phaser": "^3.55.2"
|
||||
}
|
||||
}
|
||||
255
spine-ts/spine-phaser/src/SpineGameObject.ts
Normal file
255
spine-ts/spine-phaser/src/SpineGameObject.ts
Normal file
@ -0,0 +1,255 @@
|
||||
import { SPINE_GAME_OBJECT_TYPE } from "./keys";
|
||||
import { SpinePlugin } from "./SpinePlugin";
|
||||
import { ComputedSizeMixin, DepthMixin, FlipMixin, ScrollFactorMixin, TransformMixin, VisibleMixin } from "./mixins";
|
||||
import { AnimationState, AnimationStateData, Bone, MathUtils, Skeleton, Skin, Vector2 } from "@esotericsoftware/spine-core";
|
||||
import { Vector3 } from "@esotericsoftware/spine-webgl";
|
||||
|
||||
class BaseSpineGameObject extends Phaser.GameObjects.GameObject {
|
||||
constructor(scene: Phaser.Scene, type: string) {
|
||||
super(scene, type);
|
||||
}
|
||||
}
|
||||
|
||||
export interface SpineGameObjectBoundsProvider {
|
||||
calculateBounds(gameObject: SpineGameObject): { x: number, y: number, width: number, height: number };
|
||||
}
|
||||
|
||||
export class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider {
|
||||
calculateBounds(gameObject: SpineGameObject) {
|
||||
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.setToSetupPose();
|
||||
skeleton.updateWorldTransform();
|
||||
return skeleton.getBoundsRect();
|
||||
}
|
||||
}
|
||||
|
||||
export class SkinsAndAnimationBoundsProvider implements SpineGameObjectBoundsProvider {
|
||||
constructor(private animation: string, private skins: string[] = [], private timeStep: number = 0.05) {
|
||||
|
||||
}
|
||||
|
||||
calculateBounds(gameObject: SpineGameObject): { x: number; y: number; width: number; height: number; } {
|
||||
if (!gameObject.skeleton || !gameObject.animationState) 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.animationState.data);
|
||||
const skeleton = new Skeleton(gameObject.skeleton.data);
|
||||
const data = skeleton.data;
|
||||
if (this.skins.length > 0) {
|
||||
let 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.setToSetupPose();
|
||||
|
||||
const animation = this.animation != null ? data.findAnimation(this.animation!) : null;
|
||||
if (animation == null) {
|
||||
skeleton.updateWorldTransform();
|
||||
return skeleton.getBoundsRect();
|
||||
} else {
|
||||
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
||||
animationState.clearTracks();
|
||||
animationState.setAnimationWith(0, animation, false);
|
||||
const steps = Math.max(animation.duration / this.timeStep, 1.0);
|
||||
for (let i = 0; i < steps; i++) {
|
||||
animationState.update(i > 0 ? this.timeStep : 0);
|
||||
animationState.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
|
||||
const bounds = skeleton.getBoundsRect();
|
||||
minX = Math.min(minX, bounds.x);
|
||||
minY = Math.min(minY, bounds.y);
|
||||
maxX = Math.max(maxX, minX + bounds.width);
|
||||
maxY = Math.max(maxY, minY + bounds.height);
|
||||
}
|
||||
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(ScrollFactorMixin(TransformMixin(VisibleMixin(BaseSpineGameObject)))))) {
|
||||
blendMode = -1;
|
||||
skeleton: Skeleton | null = null;
|
||||
animationStateData: AnimationStateData | null = null;
|
||||
animationState: AnimationState | null = null;
|
||||
private premultipliedAlpha = false;
|
||||
private _displayOriginX = 0;
|
||||
private _displayOriginY = 0;
|
||||
private _scaleX = 1;
|
||||
private _scaleY = 1;
|
||||
|
||||
constructor(scene: Phaser.Scene, private plugin: SpinePlugin, x: number, y: number, dataKey: string, atlasKey: string, public boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider()) {
|
||||
super(scene, SPINE_GAME_OBJECT_TYPE);
|
||||
this.setPosition(x, y); x
|
||||
this.setSkeleton(dataKey, atlasKey);
|
||||
}
|
||||
|
||||
setSkeleton(dataKey: string, atlasKey: string) {
|
||||
if (dataKey && atlasKey) {
|
||||
this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey);
|
||||
this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);
|
||||
this.animationStateData = new AnimationStateData(this.skeleton.data);
|
||||
this.animationState = new AnimationState(this.animationStateData);
|
||||
this.updateSize();
|
||||
} else {
|
||||
this.skeleton = null;
|
||||
this.animationStateData = null;
|
||||
this.animationState = null;
|
||||
}
|
||||
}
|
||||
|
||||
public get displayOriginX() {
|
||||
return this._displayOriginX;
|
||||
}
|
||||
|
||||
public set displayOriginX(value: number) {
|
||||
this._displayOriginX = value;
|
||||
}
|
||||
|
||||
public get displayOriginY() {
|
||||
return this._displayOriginY;
|
||||
}
|
||||
|
||||
public set displayOriginY(value: number) {
|
||||
this._displayOriginY = value;
|
||||
}
|
||||
|
||||
public get scaleX() {
|
||||
return this._scaleX;
|
||||
}
|
||||
|
||||
public set scaleX(value: number) {
|
||||
this._scaleX = value;
|
||||
this.updateSize();
|
||||
}
|
||||
|
||||
public get scaleY() {
|
||||
return this._scaleY;
|
||||
}
|
||||
|
||||
public set scaleY(value: number) {
|
||||
this._scaleY = value;
|
||||
this.updateSize();
|
||||
}
|
||||
|
||||
updateSize() {
|
||||
if (!this.skeleton) return;
|
||||
let bounds = this.boundsProvider.calculateBounds(this);
|
||||
// For some reason the TS compiler and the ComputedSize mixin don't work well together...
|
||||
let self = this as any;
|
||||
self.width = bounds.width;
|
||||
self.height = bounds.height;
|
||||
this.displayOriginX = -bounds.x;
|
||||
this.displayOriginY = -bounds.y;
|
||||
}
|
||||
|
||||
skeletonToPhaserWorldCoordinates(point: {x: number, y: number}) {
|
||||
let transform = this.getWorldTransformMatrix();
|
||||
let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty;
|
||||
let x = point.x
|
||||
let y = point.y
|
||||
point.x = x * a + y * c + tx;
|
||||
point.y = x * b + y * d + ty;
|
||||
}
|
||||
|
||||
phaserWorldCoordinatesToSkeleton(point: {x: number, y: number}) {
|
||||
let transform = this.getWorldTransformMatrix();
|
||||
transform = transform.invert();
|
||||
let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty;
|
||||
let x = point.x
|
||||
let y = point.y
|
||||
point.x = x * a + y * c + tx;
|
||||
point.y = x * b + y * d + ty;
|
||||
}
|
||||
|
||||
phaserWorldCoordinatesToBone(point: {x: number, y: number}, bone: Bone) {
|
||||
this.phaserWorldCoordinatesToSkeleton(point);
|
||||
if (bone.parent) {
|
||||
bone.parent.worldToLocal(point as Vector2);
|
||||
} else {
|
||||
bone.worldToLocal(point as Vector2);
|
||||
}
|
||||
}
|
||||
|
||||
preUpdate(time: number, delta: number) {
|
||||
if (!this.skeleton || !this.animationState) return;
|
||||
|
||||
this.animationState.update(delta / 1000);
|
||||
this.animationState.apply(this.skeleton);
|
||||
this.skeleton.updateWorldTransform();
|
||||
}
|
||||
|
||||
preDestroy() {
|
||||
this.skeleton = null;
|
||||
this.animationState = null;
|
||||
// FIXME tear down any event emitters
|
||||
}
|
||||
|
||||
willRender(camera: Phaser.Cameras.Scene2D.Camera) {
|
||||
if (!this.visible) return false;
|
||||
|
||||
var GameObjectRenderMask = 0xf;
|
||||
var result = (!this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
renderWebGL(renderer: Phaser.Renderer.WebGL.WebGLRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix) {
|
||||
if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer) return;
|
||||
|
||||
let sceneRenderer = this.plugin.webGLRenderer;
|
||||
if (renderer.newType) {
|
||||
renderer.pipelines.clear();
|
||||
sceneRenderer.begin();
|
||||
}
|
||||
|
||||
camera.addToRenderList(src);
|
||||
let transform = Phaser.GameObjects.GetCalcMatrix(src, camera, parentMatrix).calc;
|
||||
let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty;
|
||||
sceneRenderer.drawSkeleton(this.skeleton, this.premultipliedAlpha, -1, -1, (vertices, numVertices, stride) => {
|
||||
for (let i = 0; i < numVertices; i += stride) {
|
||||
let vx = vertices[i];
|
||||
let vy = vertices[i + 1];
|
||||
vertices[i] = vx * a + vy * c + tx;
|
||||
vertices[i + 1] = vx * b + vy * d + ty;
|
||||
}
|
||||
});
|
||||
|
||||
if (!renderer.nextTypeMatch) {
|
||||
sceneRenderer.end();
|
||||
renderer.pipelines.rebind();
|
||||
}
|
||||
}
|
||||
|
||||
renderCanvas(renderer: Phaser.Renderer.Canvas.CanvasRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix) {
|
||||
if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) return;
|
||||
|
||||
let context = renderer.currentContext;
|
||||
let skeletonRenderer = this.plugin.canvasRenderer;
|
||||
(skeletonRenderer as any).ctx = context;
|
||||
|
||||
camera.addToRenderList(src);
|
||||
let transform = Phaser.GameObjects.GetCalcMatrix(src, camera, parentMatrix).calc;
|
||||
let skeleton = this.skeleton;
|
||||
skeleton.x = transform.tx;
|
||||
skeleton.y = transform.ty;
|
||||
skeleton.scaleX = transform.scaleX;
|
||||
skeleton.scaleY = transform.scaleY;
|
||||
let root = skeleton.getRootBone()!;
|
||||
root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized;
|
||||
this.skeleton.updateWorldTransform();
|
||||
|
||||
context.save();
|
||||
skeletonRenderer.draw(skeleton);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
315
spine-ts/spine-phaser/src/SpinePlugin.ts
Normal file
315
spine-ts/spine-phaser/src/SpinePlugin.ts
Normal file
@ -0,0 +1,315 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, 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 Phaser from "phaser";
|
||||
import { SPINE_ATLAS_CACHE_KEY, SPINE_CONTAINER_TYPE, SPINE_GAME_OBJECT_TYPE, SPINE_ATLAS_TEXTURE_CACHE_KEY, SPINE_SKELETON_DATA_FILE_TYPE, SPINE_ATLAS_FILE_TYPE, SPINE_SKELETON_FILE_CACHE_KEY as SPINE_SKELETON_DATA_CACHE_KEY } from "./keys";
|
||||
import { AtlasAttachmentLoader, Bone, GLTexture, SceneRenderer, Skeleton, SkeletonBinary, SkeletonData, SkeletonJson, TextureAtlas } from "@esotericsoftware/spine-webgl"
|
||||
import { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject";
|
||||
import { CanvasTexture, SkeletonRenderer } from "@esotericsoftware/spine-canvas";
|
||||
|
||||
export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||
game: Phaser.Game;
|
||||
isWebGL: boolean;
|
||||
gl: WebGLRenderingContext | null;
|
||||
textureManager: Phaser.Textures.TextureManager;
|
||||
phaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer | null;
|
||||
webGLRenderer: SceneRenderer | null;
|
||||
canvasRenderer: SkeletonRenderer | null;
|
||||
skeletonDataCache: Phaser.Cache.BaseCache;
|
||||
atlasCache: Phaser.Cache.BaseCache;
|
||||
|
||||
constructor (scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {
|
||||
super(scene, pluginManager, pluginKey);
|
||||
var game = this.game = pluginManager.game;
|
||||
this.isWebGL = this.game.config.renderType === 2;
|
||||
this.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null;
|
||||
this.textureManager = this.game.textures;
|
||||
this.phaserRenderer = this.game.renderer;
|
||||
this.webGLRenderer = null;
|
||||
this.canvasRenderer = null;
|
||||
this.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_DATA_CACHE_KEY);
|
||||
this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY);
|
||||
|
||||
if (!this.phaserRenderer) {
|
||||
this.phaserRenderer = {
|
||||
width: game.scale.width,
|
||||
height: game.scale.height,
|
||||
preRender: () => { },
|
||||
postRender: () => { },
|
||||
render: () => { },
|
||||
destroy: () => { }
|
||||
} as unknown as Phaser.Renderer.Canvas.CanvasRenderer;
|
||||
}
|
||||
|
||||
let skeletonJsonFileCallback = function (this: any, key: string,
|
||||
url: string,
|
||||
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||
let file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.json, xhrSettings);
|
||||
this.addFile(file.files);
|
||||
return this;
|
||||
};
|
||||
pluginManager.registerFileType("spineJson", skeletonJsonFileCallback, scene);
|
||||
|
||||
|
||||
let skeletonBinaryFileCallback = function (this: any, key: string,
|
||||
url: string,
|
||||
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||
let file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.binary, xhrSettings);
|
||||
this.addFile(file.files);
|
||||
return this;
|
||||
};
|
||||
pluginManager.registerFileType("spineBinary", skeletonBinaryFileCallback, scene);
|
||||
|
||||
|
||||
let atlasFileCallback = function (this: any, key: string,
|
||||
url: string,
|
||||
premultipliedAlpha: boolean,
|
||||
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||
let file = new SpineAtlasFile(this as any, key, url, premultipliedAlpha, xhrSettings);
|
||||
this.addFile(file.files);
|
||||
return this;
|
||||
};
|
||||
pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene);
|
||||
|
||||
let self = this;
|
||||
let addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider) {
|
||||
let gameObject = new SpineGameObject(scene, self, x, y, dataKey, atlasKey, boundsProvider);
|
||||
this.displayList.add(gameObject);
|
||||
this.updateList.add(gameObject);
|
||||
return gameObject;
|
||||
};
|
||||
|
||||
let makeSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, config: any, addToScene: boolean) {
|
||||
let dataKey = config.dataKey ? config.dataKey : null;
|
||||
let atlasKey = config.atlasKey ? config.atlasKey : null;
|
||||
let gameObject = new SpineGameObject(this.scene, self, 0, 0, dataKey, atlasKey);
|
||||
if (addToScene !== undefined) {
|
||||
config.add = addToScene;
|
||||
}
|
||||
Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config);
|
||||
}
|
||||
pluginManager.registerGameObject(SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject);
|
||||
}
|
||||
|
||||
boot () {
|
||||
Skeleton.yDown = true;
|
||||
if (this.isWebGL) {
|
||||
if (!this.webGLRenderer) {
|
||||
this.webGLRenderer = new SceneRenderer((this.phaserRenderer! as Phaser.Renderer.WebGL.WebGLRenderer).canvas, this.gl!, true);
|
||||
}
|
||||
this.game.scale.on(Phaser.Scale.Events.RESIZE, this.onResize, this);
|
||||
} else {
|
||||
if (!this.canvasRenderer) {
|
||||
this.canvasRenderer = new SkeletonRenderer(this.scene.sys.context);
|
||||
}
|
||||
}
|
||||
|
||||
var eventEmitter = this.systems.events;
|
||||
eventEmitter.once('shutdown', this.shutdown, this);
|
||||
eventEmitter.once('destroy', this.destroy, this);
|
||||
this.game.events.once('destroy', this.gameDestroy, this);
|
||||
}
|
||||
|
||||
onResize () {
|
||||
var phaserRenderer = this.phaserRenderer;
|
||||
var sceneRenderer = this.webGLRenderer;
|
||||
|
||||
if (phaserRenderer && sceneRenderer) {
|
||||
var viewportWidth = phaserRenderer.width;
|
||||
var viewportHeight = phaserRenderer.height;
|
||||
sceneRenderer.camera.position.x = viewportWidth / 2;
|
||||
sceneRenderer.camera.position.y = viewportHeight / 2;
|
||||
sceneRenderer.camera.up.y = -1;
|
||||
sceneRenderer.camera.direction.z = 1;
|
||||
sceneRenderer.camera.setViewport(viewportWidth, viewportHeight);
|
||||
}
|
||||
}
|
||||
|
||||
shutdown () {
|
||||
this.systems.events.off("shutdown", this.shutdown, this);
|
||||
if (this.isWebGL) {
|
||||
this.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this);
|
||||
}
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.shutdown()
|
||||
}
|
||||
|
||||
gameDestroy () {
|
||||
this.pluginManager.removeGameObject(SPINE_GAME_OBJECT_TYPE, true, true);
|
||||
this.pluginManager.removeGameObject(SPINE_CONTAINER_TYPE, true, true);
|
||||
if (this.webGLRenderer) this.webGLRenderer.dispose();
|
||||
}
|
||||
|
||||
isAtlasPremultiplied(atlasKey: string) {
|
||||
let atlasFile = this.game.cache.text.get(atlasKey);
|
||||
if (!atlasFile) return false;
|
||||
return atlasFile.premultipliedAlpha;
|
||||
}
|
||||
|
||||
createSkeleton (dataKey: string, atlasKey: string) {
|
||||
let atlas: TextureAtlas;
|
||||
if (this.atlasCache.exists(atlasKey)) {
|
||||
atlas = this.atlasCache.get(atlasKey);
|
||||
} else {
|
||||
let atlasFile = this.game.cache.text.get(atlasKey) as { data: string, premultipliedAlpha: boolean };
|
||||
atlas = new TextureAtlas(atlasFile.data);
|
||||
if (this.isWebGL) {
|
||||
let gl = this.gl!;
|
||||
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
||||
for (let atlasPage of atlas.pages) {
|
||||
atlasPage.setTexture(new GLTexture(gl, this.textureManager.get(atlasKey + "!" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap, false));
|
||||
}
|
||||
} else {
|
||||
for (let atlasPage of atlas.pages) {
|
||||
atlasPage.setTexture(new CanvasTexture(this.textureManager.get(atlasKey + "!" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap));
|
||||
}
|
||||
}
|
||||
this.atlasCache.add(atlasKey, atlas);
|
||||
}
|
||||
|
||||
let skeletonData: SkeletonData;
|
||||
if (this.skeletonDataCache.exists(dataKey)) {
|
||||
skeletonData = this.skeletonDataCache.get(dataKey);
|
||||
} else {
|
||||
if (this.game.cache.json.exists(dataKey)) {
|
||||
let jsonFile = this.game.cache.json.get(dataKey) as any;
|
||||
let json = new SkeletonJson(new AtlasAttachmentLoader(atlas));
|
||||
skeletonData = json.readSkeletonData(jsonFile);
|
||||
} else {
|
||||
let binaryFile = this.game.cache.binary.get(dataKey) as ArrayBuffer;
|
||||
let binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas));
|
||||
skeletonData = binary.readSkeletonData(new Uint8Array(binaryFile));
|
||||
}
|
||||
this.skeletonDataCache.add(dataKey, skeletonData);
|
||||
}
|
||||
|
||||
return new Skeleton(skeletonData);
|
||||
}
|
||||
}
|
||||
|
||||
export enum SpineSkeletonDataFileType {
|
||||
json,
|
||||
binary
|
||||
}
|
||||
|
||||
export class SpineSkeletonDataFile extends Phaser.Loader.MultiFile {
|
||||
constructor (loader: Phaser.Loader.LoaderPlugin, key: string, url: string, public fileType: SpineSkeletonDataFileType, xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||
let file = null;
|
||||
let isJson = fileType == SpineSkeletonDataFileType.json;
|
||||
if (isJson) {
|
||||
file = new Phaser.Loader.FileTypes.JSONFile(loader, {
|
||||
key: key,
|
||||
url: url,
|
||||
extension: "json",
|
||||
xhrSettings: xhrSettings,
|
||||
} as Phaser.Types.Loader.FileTypes.JSONFileConfig);
|
||||
} else {
|
||||
file = new Phaser.Loader.FileTypes.BinaryFile(loader, {
|
||||
key: key,
|
||||
url: url,
|
||||
extension: "skel",
|
||||
xhrSettings: xhrSettings,
|
||||
} as Phaser.Types.Loader.FileTypes.BinaryFileConfig);
|
||||
}
|
||||
super(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]);
|
||||
}
|
||||
|
||||
onFileComplete (file: Phaser.Loader.File) {
|
||||
this.pending--;
|
||||
}
|
||||
|
||||
addToCache () {
|
||||
if (this.isReadyToProcess()) this.files[0].addToCache();
|
||||
}
|
||||
}
|
||||
|
||||
export class SpineAtlasFile extends Phaser.Loader.MultiFile {
|
||||
constructor (loader: Phaser.Loader.LoaderPlugin, key: string, url: string, public premultipliedAlpha: boolean = true, xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||
super(loader, SPINE_ATLAS_FILE_TYPE, key, [
|
||||
new Phaser.Loader.FileTypes.TextFile(loader, {
|
||||
key: key,
|
||||
url: url,
|
||||
xhrSettings: xhrSettings,
|
||||
extension: "atlas"
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
onFileComplete (file: Phaser.Loader.File) {
|
||||
if (this.files.indexOf(file) != -1) {
|
||||
this.pending--;
|
||||
|
||||
if (file.type == "text") {
|
||||
var lines = file.data.split('\n');
|
||||
let textures = [];
|
||||
textures.push(lines[0]);
|
||||
for (var t = 1; t < lines.length; t++) {
|
||||
var line = lines[t];
|
||||
if (line.trim() === '' && t < lines.length - 1) {
|
||||
line = lines[t + 1];
|
||||
textures.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
let basePath = file.src.match(/^.*\//);
|
||||
for (var i = 0; i < textures.length; i++) {
|
||||
var url = basePath + textures[i];
|
||||
var key = file.key + "!" + textures[i];
|
||||
var image = new Phaser.Loader.FileTypes.ImageFile(this.loader, key, url);
|
||||
|
||||
if (!this.loader.keyExists(image)) {
|
||||
this.addToMultiFile(image);
|
||||
this.loader.addFile(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addToCache () {
|
||||
if (this.isReadyToProcess()) {
|
||||
let textureManager = this.loader.textureManager;
|
||||
for (let file of this.files) {
|
||||
if (file.type == "image") {
|
||||
if (!textureManager.exists(file.key)) {
|
||||
textureManager.addImage(file.key, file.data);
|
||||
}
|
||||
} else {
|
||||
file.data = {
|
||||
data: file.data,
|
||||
premultipliedAlpha: this.premultipliedAlpha || file.data.indexOf("pma: true") >= 0
|
||||
};
|
||||
file.addToCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
spine-ts/spine-phaser/src/index.ts
Normal file
8
spine-ts/spine-phaser/src/index.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export * from "./require-shim"
|
||||
export * from "./SpinePlugin"
|
||||
export * from "./SpineGameObject"
|
||||
export * from "./mixins"
|
||||
export * from "@esotericsoftware/spine-core";
|
||||
export * from "@esotericsoftware/spine-webgl";
|
||||
import { SpinePlugin } from "./SpinePlugin";
|
||||
(window as any).spine = { SpinePlugin: SpinePlugin };
|
||||
8
spine-ts/spine-phaser/src/keys.ts
Normal file
8
spine-ts/spine-phaser/src/keys.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache";
|
||||
export const SPINE_ATLAS_CACHE_KEY = "esotericsoftware.spine.atlas.cache";
|
||||
export const SPINE_ATLAS_TEXTURE_CACHE_KEY = "esotericsoftware.spine.atlas.texture.cache";
|
||||
export const SPINE_LOADER_TYPE = "spine";
|
||||
export const SPINE_SKELETON_DATA_FILE_TYPE = "spineSkeletonData";
|
||||
export const SPINE_ATLAS_FILE_TYPE = "spineAtlasData";
|
||||
export const SPINE_GAME_OBJECT_TYPE = "spine";
|
||||
export const SPINE_CONTAINER_TYPE = "spineContainer";
|
||||
77
spine-ts/spine-phaser/src/mixins.ts
Normal file
77
spine-ts/spine-phaser/src/mixins.ts
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021-present AgogPixel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main
|
||||
|
||||
let components = (Phaser.GameObjects.Components as any);
|
||||
export const ComputedSize = components.ComputedSize;
|
||||
export const Depth = components.Depth;
|
||||
export const Flip = components.Flip;
|
||||
export const ScrollFactor = components.ScrollFactor;
|
||||
export const Transform = components.Transform;
|
||||
export const Visible = components.Visible;
|
||||
|
||||
export interface Type<
|
||||
T,
|
||||
P extends any[] = any[]
|
||||
> extends Function {
|
||||
new(...args: P): T;
|
||||
}
|
||||
|
||||
export type Mixin<GameObjectComponent, GameObjectConstraint extends Phaser.GameObjects.GameObject> = <
|
||||
GameObjectType extends Type<GameObjectConstraint>
|
||||
>(
|
||||
BaseGameObject: GameObjectType
|
||||
) => GameObjectType & Type<GameObjectComponent>;
|
||||
|
||||
export function createMixin<
|
||||
GameObjectComponent,
|
||||
GameObjectConstraint extends Phaser.GameObjects.GameObject = Phaser.GameObjects.GameObject
|
||||
> (
|
||||
...component: GameObjectComponent[]
|
||||
): Mixin<GameObjectComponent, GameObjectConstraint> {
|
||||
return (BaseGameObject) => {
|
||||
(Phaser as any).Class.mixin(BaseGameObject, component);
|
||||
return BaseGameObject as any;
|
||||
};
|
||||
}
|
||||
|
||||
type ComputedSizeMixin = Mixin<Phaser.GameObjects.Components.Transform, Phaser.GameObjects.GameObject>;
|
||||
export const ComputedSizeMixin: ComputedSizeMixin = createMixin<Phaser.GameObjects.Components.ComputedSize>(ComputedSize);
|
||||
|
||||
type DepthMixin = Mixin<Phaser.GameObjects.Components.Depth, Phaser.GameObjects.GameObject>;
|
||||
export const DepthMixin: DepthMixin = createMixin<Phaser.GameObjects.Components.Depth>(Depth);
|
||||
|
||||
type FlipMixin = Mixin<Phaser.GameObjects.Components.Flip, Phaser.GameObjects.GameObject>;
|
||||
export const FlipMixin: FlipMixin = createMixin<Phaser.GameObjects.Components.Flip>(Flip);
|
||||
|
||||
type ScrollFactorMixin = Mixin<Phaser.GameObjects.Components.ScrollFactor, Phaser.GameObjects.GameObject>;
|
||||
export const ScrollFactorMixin: ScrollFactorMixin = createMixin<Phaser.GameObjects.Components.ScrollFactor>(ScrollFactor);
|
||||
|
||||
type TransformMixin = Mixin<Phaser.GameObjects.Components.Transform, Phaser.GameObjects.GameObject>;
|
||||
export const TransformMixin: TransformMixin = createMixin<Phaser.GameObjects.Components.Transform>(Transform);
|
||||
|
||||
type VisibleMixin = Mixin<Phaser.GameObjects.Components.Visible, Phaser.GameObjects.GameObject>;
|
||||
export const VisibleMixin: VisibleMixin = createMixin<Phaser.GameObjects.Components.Visible>(Visible);
|
||||
|
||||
11
spine-ts/spine-phaser/src/require-shim.ts
Normal file
11
spine-ts/spine-phaser/src/require-shim.ts
Normal file
@ -0,0 +1,11 @@
|
||||
declare global {
|
||||
var require: any;
|
||||
}
|
||||
if (window.Phaser) {
|
||||
let prevRequire = window.require;
|
||||
window.require = (x: string) => {
|
||||
if (prevRequire) return prevRequire(x);
|
||||
else if (x === "Phaser") return window.Phaser;
|
||||
}
|
||||
}
|
||||
export { }
|
||||
36
spine-ts/spine-phaser/tsconfig.json
Normal file
36
spine-ts/spine-phaser/tsconfig.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@esotericsoftware/spine-core": [
|
||||
"../spine-core/src"
|
||||
],
|
||||
"@esotericsoftware/spine-canvas": [
|
||||
"../spine-canvas/src"
|
||||
],
|
||||
"@esotericsoftware/spine-webgl": [
|
||||
"../spine-webgl/src"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
],
|
||||
"exclude": [
|
||||
"dist/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../spine-core"
|
||||
},
|
||||
{
|
||||
"path": "../spine-canvas"
|
||||
},
|
||||
{
|
||||
"path": "../spine-webgl"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,3 +1,3 @@
|
||||
export * from './Player';
|
||||
export * from "@esotericsoftware/spine-core";
|
||||
export * from "@esotericsoftware/spine-webgl";
|
||||
export * from "@esotericsoftware/spine-webgl";
|
||||
@ -36,6 +36,7 @@ import { ManagedWebGLRenderingContext } from "./WebGL";
|
||||
export class PolygonBatcher implements Disposable {
|
||||
private context: ManagedWebGLRenderingContext;
|
||||
private drawCalls = 0;
|
||||
private static globalDrawCalls = 0;
|
||||
private isDrawing = false;
|
||||
private mesh: Mesh;
|
||||
private shader: Shader | null = null;
|
||||
@ -120,6 +121,7 @@ export class PolygonBatcher implements Disposable {
|
||||
this.mesh.setVerticesLength(0);
|
||||
this.mesh.setIndicesLength(0);
|
||||
this.drawCalls++;
|
||||
PolygonBatcher.globalDrawCalls++;
|
||||
}
|
||||
|
||||
end () {
|
||||
@ -138,6 +140,12 @@ export class PolygonBatcher implements Disposable {
|
||||
return this.drawCalls;
|
||||
}
|
||||
|
||||
static getAndResetGlobalDrawCalls () {
|
||||
let result = PolygonBatcher.globalDrawCalls;
|
||||
PolygonBatcher.globalDrawCalls = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
dispose () {
|
||||
this.mesh.dispose();
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ import { PolygonBatcher } from "./PolygonBatcher";
|
||||
import { Shader } from "./Shader";
|
||||
import { ShapeRenderer } from "./ShapeRenderer";
|
||||
import { SkeletonDebugRenderer } from "./SkeletonDebugRenderer";
|
||||
import { SkeletonRenderer } from "./SkeletonRenderer";
|
||||
import { SkeletonRenderer, VertexTransformer } from "./SkeletonRenderer";
|
||||
import { ManagedWebGLRenderingContext } from "./WebGL";
|
||||
;
|
||||
|
||||
@ -86,10 +86,10 @@ export class SceneRenderer implements Disposable {
|
||||
this.enableRenderer(this.batcher);
|
||||
}
|
||||
|
||||
drawSkeleton (skeleton: Skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1) {
|
||||
drawSkeleton (skeleton: Skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform: VertexTransformer | null = null) {
|
||||
this.enableRenderer(this.batcher);
|
||||
this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha;
|
||||
this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd);
|
||||
this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform);
|
||||
}
|
||||
|
||||
drawSkeletonDebug (skeleton: Skeleton, premultipliedAlpha = false, ignoredBones?: Array<string>) {
|
||||
|
||||
@ -37,6 +37,8 @@ class Renderable {
|
||||
constructor (public vertices: NumberArrayLike, public numVertices: number, public numFloats: number) { }
|
||||
};
|
||||
|
||||
export type VertexTransformer = (vertices: NumberArrayLike, numVertices: number, stride: number) => void;
|
||||
|
||||
export class SkeletonRenderer {
|
||||
static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
||||
|
||||
@ -60,7 +62,7 @@ export class SkeletonRenderer {
|
||||
this.vertices = Utils.newFloatArray(this.vertexSize * 1024);
|
||||
}
|
||||
|
||||
draw (batcher: PolygonBatcher, skeleton: Skeleton, slotRangeStart: number = -1, slotRangeEnd: number = -1) {
|
||||
draw (batcher: PolygonBatcher, skeleton: Skeleton, slotRangeStart: number = -1, slotRangeEnd: number = -1, transformer: VertexTransformer | null = null) {
|
||||
let clipper = this.clipper;
|
||||
let premultipliedAlpha = this.premultipliedAlpha;
|
||||
let twoColorTint = this.twoColorTint;
|
||||
@ -174,6 +176,7 @@ export class SkeletonRenderer {
|
||||
clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
|
||||
let clippedVertices = new Float32Array(clipper.clippedVertices);
|
||||
let clippedTriangles = clipper.clippedTriangles;
|
||||
if (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize);
|
||||
batcher.draw(texture, clippedVertices, clippedTriangles);
|
||||
} else {
|
||||
let verts = renderable.vertices;
|
||||
@ -201,6 +204,7 @@ export class SkeletonRenderer {
|
||||
}
|
||||
}
|
||||
let view = (renderable.vertices as Float32Array).subarray(0, renderable.numFloats);
|
||||
if (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize);
|
||||
batcher.draw(texture, view, triangles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES2015"
|
||||
"ES2015",
|
||||
"ScriptHost"
|
||||
],
|
||||
"declaration": true,
|
||||
"composite": true,
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
{
|
||||
"path": "./spine-webgl"
|
||||
},
|
||||
{
|
||||
"path": "./spine-phaser"
|
||||
},
|
||||
{
|
||||
"path": "./spine-player"
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user