mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
Merge branch '4.2' into 4.3-beta
This commit is contained in:
commit
073f4d3ec4
@ -204,18 +204,16 @@ namespace Spine {
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
|
||||
if (to.nextTrackLast != -1) { // The from entry was applied at least once.
|
||||
bool discard = to.mixTime == 0 && from.mixTime == 0; // Discard the from entry when neither have advanced yet.
|
||||
if (to.mixTime >= to.mixDuration || discard) {
|
||||
// Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0 || discard) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
queue.End(from);
|
||||
}
|
||||
return finished;
|
||||
// The from entry was applied at least once and the mix is complete.
|
||||
if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) {
|
||||
// Mixing is complete for all entries before the from entry or the mix is instantaneous.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
queue.End(from);
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
from.trackTime += delta * from.timeScale;
|
||||
|
||||
@ -1287,7 +1287,7 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimizePositive ? result : ((result >> 1) ^ -(result & 1));
|
||||
return optimizePositive ? result : ((int)((uint)result >> 1) ^ -(result & 1));
|
||||
}
|
||||
|
||||
public string ReadString () {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "com.esotericsoftware.spine.spine-csharp",
|
||||
"displayName": "spine-csharp Runtime",
|
||||
"description": "This plugin provides the spine-csharp core runtime.",
|
||||
"version": "4.2.34",
|
||||
"version": "4.2.36",
|
||||
"unity": "2018.3",
|
||||
"author": {
|
||||
"name": "Esoteric Software",
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
"cpp"
|
||||
],
|
||||
"description": "The official Spine Runtime for Haxe",
|
||||
"version": "4.2.5",
|
||||
"releasenote": "Update to 4.2.5",
|
||||
"version": "4.2.6",
|
||||
"releasenote": "Update to 4.2.6",
|
||||
"contributors": [
|
||||
"esotericsoftware"
|
||||
],
|
||||
|
||||
@ -148,18 +148,16 @@ class AnimationState {
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
|
||||
if (to.nextTrackLast != -1) { // The from entry was applied at least once.
|
||||
var discard:Bool = to.mixTime == 0 && from.mixTime == 0; // Discard the from entry when neither have advanced yet.
|
||||
if (to.mixTime >= to.mixDuration || discard) {
|
||||
// Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0 || discard) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
queue.end(from);
|
||||
}
|
||||
return finished;
|
||||
// The from entry was applied at least once and the mix is complete.
|
||||
if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) {
|
||||
// Mixing is complete for all entries before the from entry or the mix is instantaneous.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
queue.end(from);
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
from.trackTime += delta * from.timeScale;
|
||||
|
||||
@ -116,9 +116,9 @@ class SkeletonSprite extends FlxObject
|
||||
|
||||
override public function destroy():Void
|
||||
{
|
||||
skeleton = null;
|
||||
state.clearListeners();
|
||||
state = null;
|
||||
stateData = null;
|
||||
skeleton = null;
|
||||
|
||||
_tempVertices = null;
|
||||
_quadTriangles = null;
|
||||
|
||||
@ -416,4 +416,13 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
|
||||
bone.worldToLocal(point);
|
||||
}
|
||||
}
|
||||
|
||||
override public function dispose():Void {
|
||||
if (_state != null) {
|
||||
_state.clearListeners();
|
||||
_state = null;
|
||||
}
|
||||
if (_skeleton != null) _skeleton = null;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +151,9 @@
|
||||
<li>
|
||||
<a href="/spine-phaser/example/physics4.html">Physics IV</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/spine-phaser/example/inline-loading.html">Inline loading</a>
|
||||
</li>
|
||||
</ul>
|
||||
<li>Player</li>
|
||||
<ul>
|
||||
|
||||
@ -138,18 +138,16 @@ export class AnimationState {
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
|
||||
if (to.nextTrackLast != -1) { // The from entry was applied at least once.
|
||||
const discard = to.mixTime == 0 && from.mixTime == 0; // Discard the from entry when neither have advanced yet.
|
||||
if (to.mixTime >= to.mixDuration || discard) {
|
||||
// Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0 || discard) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
this.queue.end(from);
|
||||
}
|
||||
return finished;
|
||||
// The from entry was applied at least once and the mix is complete.
|
||||
if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) {
|
||||
// Mixing is complete for all entries before the from entry or the mix is instantaneous.
|
||||
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
||||
to.mixingFrom = from.mixingFrom;
|
||||
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
|
||||
to.interruptAlpha = from.interruptAlpha;
|
||||
this.queue.end(from);
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
from.trackTime += delta * from.timeScale;
|
||||
|
||||
173
spine-ts/spine-phaser/example/inline-loading.html
Normal file
173
spine-ts/spine-phaser/example/inline-loading.html
Normal file
@ -0,0 +1,173 @@
|
||||
<!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.60.0/dist/phaser.js"></script>
|
||||
<script src="../dist/iife/spine-phaser.js"></script>
|
||||
<link rel="stylesheet" href="../../index.css" />
|
||||
<title>Spine Phaser Example</title>
|
||||
</head>
|
||||
|
||||
<body class="p-4 flex flex-col items-center">
|
||||
<h1>Inline loading example</h1>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
|
||||
const png0 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAF0lEQVR4XmNgGAWDGPwHAnSxUTAKaAYAuNkD/UsHnp0AAAAASUVORK5CYII=";
|
||||
const png1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGklEQVR4XmNgGAWDGPyHAnRxogHFBoyCEQUAsVwP8T2BZi4AAAAASUVORK5CYII=";
|
||||
const atlasString =
|
||||
`spine.png
|
||||
size:16,16
|
||||
filter:Linear,Linear
|
||||
pma:true
|
||||
pixel1
|
||||
bounds:6,6,1,1
|
||||
|
||||
spine_2.png
|
||||
size:16,16
|
||||
filter:Linear,Linear
|
||||
pma:true
|
||||
pixel2
|
||||
bounds:6,6,2,2
|
||||
`
|
||||
|
||||
const skeletonJson = {
|
||||
"skeleton": {
|
||||
"hash": "Xgvriu12nCE",
|
||||
"spine": "0.0.00",
|
||||
"x": -150,
|
||||
"y": -50,
|
||||
"width": 300,
|
||||
"height": 100,
|
||||
"images": "./images/",
|
||||
"audio": "./audio"
|
||||
},
|
||||
"bones": [
|
||||
{ "name": "root", "scaleX": 50, "scaleY": 50 }
|
||||
],
|
||||
"slots": [
|
||||
{ "name": "1", "bone": "root", "attachment": "pixel1" },
|
||||
{ "name": "2", "bone": "root", "attachment": "pixel2" }
|
||||
],
|
||||
"skins": [
|
||||
{
|
||||
"name": "default",
|
||||
"attachments": {
|
||||
"1": {
|
||||
"pixel1": { "x": 1, "width": 1, "height": 1 }
|
||||
},
|
||||
"2": {
|
||||
"pixel2": { "x": -1, "width": 2, "height": 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"animations": {
|
||||
"animation": {
|
||||
"slots": {
|
||||
"1": {
|
||||
"rgba": [
|
||||
{ "color": "3f00ffff" },
|
||||
{ "time": 0.3333, "color": "ffffffff" },
|
||||
{ "time": 0.6667, "color": "3f00ffff" }
|
||||
]
|
||||
},
|
||||
"2": {
|
||||
"rgba": [
|
||||
{ "color": "ff0000ff" },
|
||||
{ "time": 0.3333, "color": "ffffffff" },
|
||||
{ "time": 0.6667, "color": "ff0000ff" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BasicExample extends Phaser.Scene {
|
||||
|
||||
atlasKey = "spineboy-atlas";
|
||||
|
||||
async preload() {
|
||||
// manually add the text atlas to the game cache
|
||||
this.game.cache.text.add(this.atlasKey, { data: atlasString, premultipliedAlpha: true });
|
||||
|
||||
// manually add the json skeleton to the game cache
|
||||
this.game.cache.json.add("spineboy-data", skeletonJson);
|
||||
}
|
||||
|
||||
async create() {
|
||||
|
||||
// associate the base64 encoded pngs to their name in the text atlas
|
||||
const texturesMap = {
|
||||
"spine.png": png0,
|
||||
"spine_2.png": png1,
|
||||
}
|
||||
|
||||
const loadedTexturePromises = [];
|
||||
const textureCallbackList = [];
|
||||
const textureCallback = (resolve, combinedKey) => key => {
|
||||
if (combinedKey === key) resolve()
|
||||
}
|
||||
|
||||
// loop over the pngs to load
|
||||
Object.entries(texturesMap).forEach(([keyTexture, value]) => {
|
||||
|
||||
// the cache key that spine plugin will search
|
||||
const combinedKey = `${this.atlasKey}!${keyTexture}`;
|
||||
|
||||
// addBase64 is async and we should wait for the ADD event before starting the game
|
||||
this.textures.addBase64(combinedKey, value);
|
||||
const promise = new Promise((resolve) => {
|
||||
const cb = textureCallback(resolve, combinedKey);
|
||||
textureCallbackList.push(cb);
|
||||
this.textures.on(Phaser.Textures.Events.ADD, cb);
|
||||
});
|
||||
|
||||
// collecting all promises waiting for the ADD event
|
||||
loadedTexturePromises.push(promise);
|
||||
})
|
||||
|
||||
// wait for all pngs to be decoded and loaded
|
||||
await Promise.all(loadedTexturePromises);
|
||||
|
||||
// unregister the listener to the textures since we're done at listenting at texture events
|
||||
textureCallbackList.forEach(cb => this.textures.off(Phaser.Textures.Events.ADD, cb));
|
||||
|
||||
// now all assets are loaded, create the game object as usual
|
||||
const spineboy = this.add.spine(
|
||||
400,
|
||||
300,
|
||||
"spineboy-data",
|
||||
"spineboy-atlas"
|
||||
);
|
||||
spineboy.setInteractive();
|
||||
spineboy.displayWidth = 200;
|
||||
spineboy.displayHeight = (spineboy.height / spineboy.width) * 200;
|
||||
this.input.enableDebug(spineboy, 0xff00ff);
|
||||
spineboy.animationState.setAnimation(0, "animation", true);
|
||||
}
|
||||
}
|
||||
|
||||
new Phaser.Game({
|
||||
type: Phaser.AUTO,
|
||||
width: 800,
|
||||
height: 600,
|
||||
type: Phaser.WEBGL,
|
||||
scene: [BasicExample],
|
||||
plugins: {
|
||||
scene: [
|
||||
{
|
||||
key: "spine.SpinePlugin",
|
||||
plugin: spine.SpinePlugin,
|
||||
mapping: "spine",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user