mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 17:56:04 +08:00
[phaser] Loading and caching of skeleton data, atlas, textures, creation of skeletons, animation state in game object.
# Conflicts: # spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp # spine-flutter/src/spine_flutter.cpp
This commit is contained in:
parent
e805b6c8bc
commit
9ece84dc85
@ -1256,6 +1256,7 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
|
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case ATTACHMENT_DEFORM: {
|
case ATTACHMENT_DEFORM: {
|
||||||
|
VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
|
||||||
bool weighted = attachment->_bones.size() > 0;
|
bool weighted = attachment->_bones.size() > 0;
|
||||||
Vector<float> &vertices = attachment->_vertices;
|
Vector<float> &vertices = attachment->_vertices;
|
||||||
int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size();
|
int deformLength = weighted ? (int) vertices.size() / 3 * 2 : (int) vertices.size();
|
||||||
|
|||||||
@ -34,42 +34,42 @@
|
|||||||
using namespace spine;
|
using namespace spine;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
String atlasFile("data/spineboy-pma.atlas");
|
String atlasFile("data/spineboy-pma.atlas");
|
||||||
String skeletonFile("data/spineboy-pro.skel");
|
String skeletonFile("data/spineboy-pro.skel");
|
||||||
float scale = 0.6f;
|
float scale = 0.6f;
|
||||||
SFMLTextureLoader textureLoader;
|
SFMLTextureLoader textureLoader;
|
||||||
Atlas *atlas = new Atlas(atlasFile, &textureLoader);
|
Atlas *atlas = new Atlas(atlasFile, &textureLoader);
|
||||||
SkeletonData *skeletonData = nullptr;
|
SkeletonData *skeletonData = nullptr;
|
||||||
if (strncmp(skeletonFile.buffer(), ".skel", skeletonFile.length()) > 0) {
|
if (strncmp(skeletonFile.buffer(), ".skel", skeletonFile.length()) > 0) {
|
||||||
SkeletonBinary binary(atlas);
|
SkeletonBinary binary(atlas);
|
||||||
binary.setScale(scale);
|
binary.setScale(scale);
|
||||||
skeletonData = binary.readSkeletonDataFile(skeletonFile);
|
skeletonData = binary.readSkeletonDataFile(skeletonFile);
|
||||||
} else {
|
} else {
|
||||||
SkeletonJson json(atlas);
|
SkeletonJson json(atlas);
|
||||||
json.setScale(scale);
|
json.setScale(scale);
|
||||||
skeletonData = json.readSkeletonDataFile(skeletonFile);
|
skeletonData = json.readSkeletonDataFile(skeletonFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationStateData stateData(skeletonData);
|
AnimationStateData stateData(skeletonData);
|
||||||
SkeletonDrawable drawable(skeletonData, &stateData);
|
SkeletonDrawable drawable(skeletonData, &stateData);
|
||||||
drawable.skeleton->setPosition(320, 590);
|
drawable.skeleton->setPosition(320, 590);
|
||||||
drawable.state->setAnimation(0, "walk", true);
|
drawable.state->setAnimation(0, "walk", true);
|
||||||
|
|
||||||
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed");
|
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed");
|
||||||
window.setFramerateLimit(60);
|
window.setFramerateLimit(60);
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
sf::Clock deltaClock;
|
sf::Clock deltaClock;
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
while (window.pollEvent(event))
|
while (window.pollEvent(event))
|
||||||
if (event.type == sf::Event::Closed) window.close();
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
|
|
||||||
float delta = deltaClock.getElapsedTime().asSeconds();
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
deltaClock.restart();
|
deltaClock.restart();
|
||||||
drawable.update(delta);
|
drawable.update(delta);
|
||||||
window.clear();
|
window.clear();
|
||||||
window.draw(drawable);
|
window.draw(drawable);
|
||||||
window.display();
|
window.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
2
spine-ts/package-lock.json
generated
2
spine-ts/package-lock.json
generated
@ -8419,7 +8419,9 @@
|
|||||||
"version": "4.2.10",
|
"version": "4.2.10",
|
||||||
"license": "LicenseRef-LICENSE",
|
"license": "LicenseRef-LICENSE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@esotericsoftware/spine-canvas": "^4.2.10",
|
||||||
"@esotericsoftware/spine-core": "^4.2.10",
|
"@esotericsoftware/spine-core": "^4.2.10",
|
||||||
|
"@esotericsoftware/spine-webgl": "^4.2.10",
|
||||||
"phaser": "^3.55.2"
|
"phaser": "^3.55.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -8,7 +8,7 @@ var config = {
|
|||||||
type: Phaser.AUTO,
|
type: Phaser.AUTO,
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
// type: Phaser.CANVAS,
|
type: Phaser.CANVAS,
|
||||||
scene: {
|
scene: {
|
||||||
preload: preload,
|
preload: preload,
|
||||||
create: create,
|
create: create,
|
||||||
@ -23,11 +23,12 @@ var config = {
|
|||||||
var game = new Phaser.Game(config);
|
var game = new Phaser.Game(config);
|
||||||
|
|
||||||
function preload () {
|
function preload () {
|
||||||
this.load.spine("raptor", "assets/raptor-pro.json", "assets/raptor.atlas", true);
|
this.load.spineJson("raptor-data", "assets/raptor-pro.json");
|
||||||
|
this.load.spineAtlas("raptor-atlas", "assets/raptor.atlas");
|
||||||
}
|
}
|
||||||
|
|
||||||
function create () {
|
function create () {
|
||||||
let plugin = this.spine;
|
let plugin = this.spine;
|
||||||
var boy = this.add.spine(400, 600, 'raptor');
|
var boy = this.add.spine(400, 600, 'raptor-data', "raptor-atlas");
|
||||||
this.add.text(10, 10, "Spine", { font: '16px Courier', fill: '#00ff00' });
|
this.add.text(10, 10, "Spine", { font: '16px Courier', fill: '#00ff00' });
|
||||||
}
|
}
|
||||||
@ -31,6 +31,8 @@
|
|||||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@esotericsoftware/spine-core": "^4.2.10",
|
"@esotericsoftware/spine-core": "^4.2.10",
|
||||||
|
"@esotericsoftware/spine-webgl": "^4.2.10",
|
||||||
|
"@esotericsoftware/spine-canvas": "^4.2.10",
|
||||||
"phaser": "^3.55.2"
|
"phaser": "^3.55.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import { SPINE_ATLAS_CACHE_KEY, SPINE_FILE_TYPE, SPINE_LOADER_TYPE } from "./keys";
|
|
||||||
|
|
||||||
export class SpineFile extends Phaser.Loader.MultiFile {
|
|
||||||
constructor(loader: Phaser.Loader.LoaderPlugin, key: string, jsonURL: string, atlasURL: string, premultipliedAlpha: boolean = false, jsonXhrSettings: Phaser.Types.Loader.XHRSettingsObject, atlasXhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
|
||||||
let json = new Phaser.Loader.FileTypes.JSONFile(loader, key, jsonURL, jsonXhrSettings);
|
|
||||||
let atlas = new Phaser.Loader.FileTypes.TextFile(loader, key, atlasURL, atlasXhrSettings);
|
|
||||||
atlas.cache = loader.cacheManager.custom[SPINE_ATLAS_CACHE_KEY];
|
|
||||||
super(loader, SPINE_FILE_TYPE, key, [json, atlas]);
|
|
||||||
}
|
|
||||||
|
|
||||||
addToCache() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +1,12 @@
|
|||||||
import { SPINE_GAME_OBJECT_TYPE } from "./keys";
|
import { SPINE_GAME_OBJECT_TYPE } from "./keys";
|
||||||
import { SpinePlugin } from "./SpinePlugin";
|
import { SpinePlugin } from "./SpinePlugin";
|
||||||
import { ComputedSizeMixin, DepthMixin, FlipMixin, ScrollFactorMixin, TransformMixin, VisibleMixin } from "./mixins";
|
import { ComputedSizeMixin, DepthMixin, FlipMixin, ScrollFactorMixin, TransformMixin, VisibleMixin } from "./mixins";
|
||||||
|
import { AnimationState, AnimationStateData, Skeleton } from "@esotericsoftware/spine-core";
|
||||||
|
|
||||||
class BaseSpineGameObject extends Phaser.GameObjects.GameObject {
|
class BaseSpineGameObject extends Phaser.GameObjects.GameObject {
|
||||||
constructor(scene: Phaser.Scene, type: string) {
|
constructor (scene: Phaser.Scene, type: string) {
|
||||||
super(scene, type);
|
super(scene, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SpineContainer {
|
interface SpineContainer {
|
||||||
@ -13,21 +14,32 @@ interface SpineContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(ScrollFactorMixin(TransformMixin(VisibleMixin(BaseSpineGameObject)))))) {
|
export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(ScrollFactorMixin(TransformMixin(VisibleMixin(BaseSpineGameObject)))))) {
|
||||||
blendMode = -1;
|
blendMode = -1;
|
||||||
|
skeleton: Skeleton | null = null;
|
||||||
|
animationState: AnimationState | null = null;
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene, plugin: SpinePlugin, x: number, y: number, key: string) {
|
constructor (scene: Phaser.Scene, private plugin: SpinePlugin, x: number, y: number, dataKey: string, atlasKey: string) {
|
||||||
super(scene, SPINE_GAME_OBJECT_TYPE);
|
super(scene, SPINE_GAME_OBJECT_TYPE);
|
||||||
this.setPosition(x, y);
|
this.setPosition(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
preUpdate(time: number, delta: number) {
|
setSkeleton (dataKey: string, atlasKey: string) {
|
||||||
}
|
if (dataKey && atlasKey) {
|
||||||
|
this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);
|
||||||
|
this.animationState = new AnimationState(new AnimationStateData(this.skeleton.data));
|
||||||
|
} else {
|
||||||
|
this.skeleton = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderWebGL(renderer: Phaser.Renderer.WebGL.WebGLRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix, container: SpineContainer) {
|
preUpdate (time: number, delta: number) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
renderWebGL (renderer: Phaser.Renderer.WebGL.WebGLRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix, container: SpineContainer) {
|
||||||
|
|
||||||
renderCanvas(renderer: Phaser.Renderer.Canvas.CanvasRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix) {
|
}
|
||||||
|
|
||||||
}
|
renderCanvas (renderer: Phaser.Renderer.Canvas.CanvasRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -28,135 +28,286 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { SPINE_ATLAS_CACHE_KEY, SPINE_CONTAINER_TYPE, SPINE_FILE_TYPE, SPINE_GAME_OBJECT_TYPE, SPINE_TEXTURE_CACHE_KEY } from "./keys";
|
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 { SceneRenderer, SkeletonDebugRenderer, SkeletonRenderer } from "@esotericsoftware/spine-webgl"
|
import { AtlasAttachmentLoader, GLTexture, SceneRenderer, Skeleton, SkeletonData, SkeletonDebugRenderer, SkeletonJson, SkeletonRenderer, TextureAtlas } from "@esotericsoftware/spine-webgl"
|
||||||
import { SpineFile } from "./SpineFile";
|
|
||||||
import { SpineGameObject } from "./SpineGameObject";
|
import { SpineGameObject } from "./SpineGameObject";
|
||||||
|
import { CanvasTexture } from "@esotericsoftware/spine-canvas";
|
||||||
|
|
||||||
export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||||
game: Phaser.Game;
|
game: Phaser.Game;
|
||||||
isWebGL: boolean;
|
isWebGL: boolean;
|
||||||
atlasCache: Phaser.Cache.BaseCache;
|
gl: WebGLRenderingContext | null;
|
||||||
spineTextureCache: Phaser.Cache.BaseCache;
|
textureManager: Phaser.Textures.TextureManager;
|
||||||
jsonCache: Phaser.Cache.BaseCache;
|
phaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer | null;
|
||||||
textures: Phaser.Textures.TextureManager;
|
sceneRenderer: SceneRenderer | null;
|
||||||
gl: WebGLRenderingContext | null;
|
skeletonDataCache: Phaser.Cache.BaseCache;
|
||||||
phaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer | null;
|
atlasCache: Phaser.Cache.BaseCache;
|
||||||
sceneRenderer: SceneRenderer | null;
|
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {
|
constructor (scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {
|
||||||
super(scene, pluginManager, pluginKey);
|
super(scene, pluginManager, pluginKey);
|
||||||
var game = this.game = pluginManager.game;
|
var game = this.game = pluginManager.game;
|
||||||
this.isWebGL = this.game.config.renderType === 2;
|
this.isWebGL = this.game.config.renderType === 2;
|
||||||
this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY);
|
this.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null;
|
||||||
this.spineTextureCache = this.game.cache.addCustom(SPINE_TEXTURE_CACHE_KEY);
|
this.textureManager = this.game.textures;
|
||||||
this.jsonCache = this.game.cache.json;
|
this.phaserRenderer = this.game.renderer;
|
||||||
this.textures = this.game.textures;
|
this.sceneRenderer = null;
|
||||||
this.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null;
|
this.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_DATA_CACHE_KEY);
|
||||||
this.phaserRenderer = this.game.renderer;
|
this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY);
|
||||||
this.sceneRenderer = null;
|
|
||||||
|
|
||||||
if (!this.phaserRenderer) {
|
if (!this.phaserRenderer) {
|
||||||
this.phaserRenderer = {
|
this.phaserRenderer = {
|
||||||
width: game.scale.width,
|
width: game.scale.width,
|
||||||
height: game.scale.height,
|
height: game.scale.height,
|
||||||
preRender: () => { },
|
preRender: () => { },
|
||||||
postRender: () => { },
|
postRender: () => { },
|
||||||
render: () => { },
|
render: () => { },
|
||||||
destroy: () => { }
|
destroy: () => { }
|
||||||
} as unknown as Phaser.Renderer.Canvas.CanvasRenderer;
|
} as unknown as Phaser.Renderer.Canvas.CanvasRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileCallback = function (this: any, key: string,
|
let skeletonJsonFileCallback = function (this: any, key: string,
|
||||||
jsonURL: string,
|
url: string,
|
||||||
atlasURL: string,
|
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||||
premultipliedAlpha: boolean,
|
let file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.json, xhrSettings);
|
||||||
jsonXhrSettings: Phaser.Types.Loader.XHRSettingsObject,
|
this.addFile(file.files);
|
||||||
atlasXhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
return this;
|
||||||
let file = new SpineFile(this as any, key, jsonURL, atlasURL, premultipliedAlpha, jsonXhrSettings, atlasXhrSettings);
|
};
|
||||||
this.addFile(file.files);
|
pluginManager.registerFileType("spineJson", skeletonJsonFileCallback, scene);
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
let self = this;
|
|
||||||
let addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, key: string) {
|
|
||||||
let gameObject = new SpineGameObject(scene, self, x, y, key);
|
|
||||||
this.displayList.add(gameObject);
|
|
||||||
this.updateList.add(gameObject);
|
|
||||||
};
|
|
||||||
|
|
||||||
let makeSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, config: any, addToScene: boolean) {
|
let skeletonBinaryFileCallback = function (this: any, key: string,
|
||||||
let key = config.key ? config.key : null;
|
url: string,
|
||||||
let gameObject = new SpineGameObject(this.scene, self, 0, 0, key);
|
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||||
if (addToScene !== undefined) {
|
let file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.binary, xhrSettings);
|
||||||
config.add = addToScene;
|
this.addFile(file.files);
|
||||||
}
|
return this;
|
||||||
Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config);
|
};
|
||||||
}
|
pluginManager.registerFileType("spineBinary", skeletonBinaryFileCallback, scene);
|
||||||
|
|
||||||
pluginManager.registerFileType(SPINE_FILE_TYPE, fileCallback, scene);
|
|
||||||
pluginManager.registerGameObject(SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
boot() {
|
let atlasFileCallback = function (this: any, key: string,
|
||||||
if (this.isWebGL) {
|
url: string,
|
||||||
// Monkeypatch the Spine setBlendMode functions, or batching is destroyed!
|
premultipliedAlpha: boolean,
|
||||||
let setBlendMode = function (this: any, srcBlend: any, dstBlend: any) {
|
xhrSettings: Phaser.Types.Loader.XHRSettingsObject) {
|
||||||
if (srcBlend !== this.srcBlend || dstBlend !== this.dstBlend) {
|
let file = new SpineAtlasFile(this as any, key, url, premultipliedAlpha, xhrSettings);
|
||||||
let gl = this.context.gl;
|
this.addFile(file.files);
|
||||||
this.srcBlend = srcBlend;
|
return this;
|
||||||
this.dstBlend = dstBlend;
|
};
|
||||||
if (this.isDrawing) {
|
pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene);
|
||||||
this.flush();
|
|
||||||
gl.blendFunc(this.srcBlend, this.dstBlend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var sceneRenderer = this.sceneRenderer;
|
let self = this;
|
||||||
if (!sceneRenderer) {
|
let addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string) {
|
||||||
sceneRenderer = new SceneRenderer((this.phaserRenderer! as Phaser.Renderer.WebGL.WebGLRenderer).canvas, this.gl!, true);
|
let gameObject = new SpineGameObject(scene, self, x, y, dataKey, atlasKey);
|
||||||
sceneRenderer.batcher.setBlendMode = setBlendMode;
|
this.displayList.add(gameObject);
|
||||||
(sceneRenderer as any).shapes.setBlendMode = setBlendMode;
|
this.updateList.add(gameObject);
|
||||||
}
|
return gameObject;
|
||||||
|
};
|
||||||
|
|
||||||
this.sceneRenderer = sceneRenderer;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
var eventEmitter = this.systems.events;
|
boot () {
|
||||||
eventEmitter.once('shutdown', this.shutdown, this);
|
if (this.isWebGL) {
|
||||||
eventEmitter.once('destroy', this.destroy, this);
|
// Monkeypatch the Spine setBlendMode functions, or batching is destroyed!
|
||||||
this.game.events.once('destroy', this.gameDestroy, this);
|
let setBlendMode = function (this: any, srcBlend: any, dstBlend: any) {
|
||||||
}
|
if (srcBlend !== this.srcBlend || dstBlend !== this.dstBlend) {
|
||||||
|
let gl = this.context.gl;
|
||||||
|
this.srcBlend = srcBlend;
|
||||||
|
this.dstBlend = dstBlend;
|
||||||
|
if (this.isDrawing) {
|
||||||
|
this.flush();
|
||||||
|
gl.blendFunc(this.srcBlend, this.dstBlend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onResize() {
|
var sceneRenderer = this.sceneRenderer;
|
||||||
var phaserRenderer = this.phaserRenderer;
|
if (!sceneRenderer) {
|
||||||
var sceneRenderer = this.sceneRenderer;
|
sceneRenderer = new SceneRenderer((this.phaserRenderer! as Phaser.Renderer.WebGL.WebGLRenderer).canvas, this.gl!, true);
|
||||||
|
sceneRenderer.batcher.setBlendMode = setBlendMode;
|
||||||
|
(sceneRenderer as any).shapes.setBlendMode = setBlendMode;
|
||||||
|
}
|
||||||
|
|
||||||
if (phaserRenderer && sceneRenderer) {
|
this.sceneRenderer = sceneRenderer;
|
||||||
var viewportWidth = phaserRenderer.width;
|
}
|
||||||
var viewportHeight = phaserRenderer.height;
|
|
||||||
sceneRenderer.camera.position.x = viewportWidth / 2;
|
|
||||||
sceneRenderer.camera.position.y = viewportHeight / 2;
|
|
||||||
sceneRenderer.camera.setViewport(viewportWidth, viewportHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown() {
|
var eventEmitter = this.systems.events;
|
||||||
this.systems.events.off("shutdown", this.shutdown, this);
|
eventEmitter.once('shutdown', this.shutdown, this);
|
||||||
if (this.isWebGL) {
|
eventEmitter.once('destroy', this.destroy, this);
|
||||||
this.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this);
|
this.game.events.once('destroy', this.gameDestroy, this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
onResize () {
|
||||||
this.shutdown()
|
var phaserRenderer = this.phaserRenderer;
|
||||||
}
|
var sceneRenderer = this.sceneRenderer;
|
||||||
|
|
||||||
gameDestroy() {
|
if (phaserRenderer && sceneRenderer) {
|
||||||
this.pluginManager.removeGameObject(SPINE_GAME_OBJECT_TYPE, true, true);
|
var viewportWidth = phaserRenderer.width;
|
||||||
this.pluginManager.removeGameObject(SPINE_CONTAINER_TYPE, true, true);
|
var viewportHeight = phaserRenderer.height;
|
||||||
if (this.sceneRenderer) this.sceneRenderer.dispose();
|
sceneRenderer.camera.position.x = viewportWidth / 2;
|
||||||
}
|
sceneRenderer.camera.position.y = viewportHeight / 2;
|
||||||
|
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.sceneRenderer) this.sceneRenderer.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 string;
|
||||||
|
atlas = new TextureAtlas(atlasFile);
|
||||||
|
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 SkeletonJson(new AtlasAttachmentLoader(atlas));
|
||||||
|
skeletonData = binary.readSkeletonData(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, 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.addToCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
export * from "./require-shim"
|
export * from "./require-shim"
|
||||||
export * from "./SpinePlugin"
|
export * from "./SpinePlugin"
|
||||||
export * from "./SpineFile"
|
|
||||||
export * from "./mixins"
|
export * from "./mixins"
|
||||||
export * from "@esotericsoftware/spine-core";
|
export * from "@esotericsoftware/spine-core";
|
||||||
export * from "@esotericsoftware/spine-canvas";
|
export * from "@esotericsoftware/spine-canvas";
|
||||||
|
|||||||
@ -1,6 +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_CACHE_KEY = "esotericsoftware.spine.atlas.cache";
|
||||||
export const SPINE_TEXTURE_CACHE_KEY = "esotericsoftware.spine.texture.cache";
|
export const SPINE_ATLAS_TEXTURE_CACHE_KEY = "esotericsoftware.spine.atlas.texture.cache";
|
||||||
export const SPINE_LOADER_TYPE = "spine";
|
export const SPINE_LOADER_TYPE = "spine";
|
||||||
export const SPINE_FILE_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_GAME_OBJECT_TYPE = "spine";
|
||||||
export const SPINE_CONTAINER_TYPE = "spineContainer";
|
export const SPINE_CONTAINER_TYPE = "spineContainer";
|
||||||
|
|||||||
@ -33,41 +33,41 @@ export const Transform = components.Transform;
|
|||||||
export const Visible = components.Visible;
|
export const Visible = components.Visible;
|
||||||
|
|
||||||
export interface Type<
|
export interface Type<
|
||||||
T,
|
T,
|
||||||
P extends any[] = any[]
|
P extends any[] = any[]
|
||||||
> extends Function {
|
> extends Function {
|
||||||
new(...args: P): T;
|
new(...args: P): T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Mixin<GameObjectComponent, GameObjectConstraint extends Phaser.GameObjects.GameObject> = <
|
export type Mixin<GameObjectComponent, GameObjectConstraint extends Phaser.GameObjects.GameObject> = <
|
||||||
GameObjectType extends Type<GameObjectConstraint>
|
GameObjectType extends Type<GameObjectConstraint>
|
||||||
>(
|
>(
|
||||||
BaseGameObject: GameObjectType
|
BaseGameObject: GameObjectType
|
||||||
) => GameObjectType & Type<GameObjectComponent>;
|
) => GameObjectType & Type<GameObjectComponent>;
|
||||||
|
|
||||||
export function createMixin<
|
export function createMixin<
|
||||||
GameObjectComponent,
|
GameObjectComponent,
|
||||||
GameObjectConstraint extends Phaser.GameObjects.GameObject = Phaser.GameObjects.GameObject
|
GameObjectConstraint extends Phaser.GameObjects.GameObject = Phaser.GameObjects.GameObject
|
||||||
>(
|
> (
|
||||||
...component: GameObjectComponent[]
|
...component: GameObjectComponent[]
|
||||||
): Mixin<GameObjectComponent, GameObjectConstraint> {
|
): Mixin<GameObjectComponent, GameObjectConstraint> {
|
||||||
return (BaseGameObject) => {
|
return (BaseGameObject) => {
|
||||||
applyMixins(BaseGameObject, component);
|
applyMixins(BaseGameObject, component);
|
||||||
return BaseGameObject as any;
|
return BaseGameObject as any;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyMixins(derivedCtor: any, constructors: any[]) {
|
function applyMixins (derivedCtor: any, constructors: any[]) {
|
||||||
constructors.forEach((baseCtor) => {
|
constructors.forEach((baseCtor) => {
|
||||||
Object.getOwnPropertyNames(baseCtor.prototype || baseCtor).forEach((name) => {
|
Object.getOwnPropertyNames(baseCtor.prototype || baseCtor).forEach((name) => {
|
||||||
Object.defineProperty(
|
Object.defineProperty(
|
||||||
derivedCtor.prototype,
|
derivedCtor.prototype,
|
||||||
name,
|
name,
|
||||||
Object.getOwnPropertyDescriptor(baseCtor.prototype || baseCtor, name) ||
|
Object.getOwnPropertyDescriptor(baseCtor.prototype || baseCtor, name) ||
|
||||||
Object.create(null)
|
Object.create(null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComputedSizeMixin = Mixin<Phaser.GameObjects.Components.Transform, Phaser.GameObjects.GameObject>;
|
type ComputedSizeMixin = Mixin<Phaser.GameObjects.Components.Transform, Phaser.GameObjects.GameObject>;
|
||||||
|
|||||||
@ -2,10 +2,10 @@ declare global {
|
|||||||
var require: any;
|
var require: any;
|
||||||
}
|
}
|
||||||
if (window.Phaser) {
|
if (window.Phaser) {
|
||||||
let prevRequire = window.require;
|
let prevRequire = window.require;
|
||||||
window.require = (x: string) => {
|
window.require = (x: string) => {
|
||||||
if (prevRequire) return prevRequire(x);
|
if (prevRequire) return prevRequire(x);
|
||||||
else if (x === "Phaser") return window.Phaser;
|
else if (x === "Phaser") return window.Phaser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export {}
|
export { }
|
||||||
Loading…
x
Reference in New Issue
Block a user