mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 17:18:44 +08:00
[phaser] Bounds providers.
This commit is contained in:
parent
be6b19afa5
commit
90cd61e505
@ -38,7 +38,7 @@ function preload () {
|
||||
}
|
||||
|
||||
function create () {
|
||||
spineboy = this.add.spine(400, 300, 'spineboy-data', "spineboy-atlas");
|
||||
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);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { SPINE_GAME_OBJECT_TYPE } from "./keys";
|
||||
import { SpinePlugin } from "./SpinePlugin";
|
||||
import { ComputedSizeMixin, DepthMixin, FlipMixin, ScrollFactorMixin, TransformMixin, VisibleMixin } from "./mixins";
|
||||
import { AnimationState, AnimationStateData, MathUtils, Skeleton } from "@esotericsoftware/spine-core";
|
||||
import { AnimationState, AnimationStateData, MathUtils, Skeleton, Skin } from "@esotericsoftware/spine-core";
|
||||
|
||||
class BaseSpineGameObject extends Phaser.GameObjects.GameObject {
|
||||
constructor(scene: Phaser.Scene, type: string) {
|
||||
@ -16,23 +16,66 @@ export interface SpineGameObjectBoundsProvider {
|
||||
export class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider {
|
||||
calculateBounds(gameObject: SpineGameObject) {
|
||||
if (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };
|
||||
gameObject.skeleton.setToSetupPose();
|
||||
gameObject.skeleton.updateWorldTransform();
|
||||
return gameObject.skeleton.getBoundsRect();
|
||||
// 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[] = []) {
|
||||
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) return { x: 0, y: 0, width: 0, height: 0 };
|
||||
// FIXME
|
||||
gameObject.skeleton.setToSetupPose();
|
||||
gameObject.skeleton.updateWorldTransform();
|
||||
return gameObject.skeleton.getBoundsRect();
|
||||
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;
|
||||
let customSkin = new Skin("custom-skin");
|
||||
if (this.skins.length > 0) {
|
||||
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;
|
||||
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
||||
if (animation == null) {
|
||||
skeleton.updateWorldTransform();
|
||||
const bounds = skeleton.getBoundsRect();
|
||||
minX = bounds.x;
|
||||
minY = bounds.y;
|
||||
maxX = minX + bounds.width;
|
||||
maxY = minY + bounds.height;
|
||||
} else {
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +136,7 @@ export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(Scro
|
||||
}
|
||||
|
||||
public get scaleY() {
|
||||
return this._scaleX;
|
||||
return this._scaleY;
|
||||
}
|
||||
|
||||
public set scaleY(value: number) {
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
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 } from "./SpineGameObject";
|
||||
import { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject";
|
||||
import { CanvasTexture, SkeletonRenderer } from "@esotericsoftware/spine-canvas";
|
||||
|
||||
export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||
@ -98,8 +98,8 @@ export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||
pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene);
|
||||
|
||||
let self = this;
|
||||
let addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string) {
|
||||
let gameObject = new SpineGameObject(scene, self, x, y, dataKey, atlasKey);
|
||||
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;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
export * from "./require-shim"
|
||||
export * from "./SpinePlugin"
|
||||
export * from "./SpineGameObject"
|
||||
export * from "./mixins"
|
||||
export * from "@esotericsoftware/spine-core";
|
||||
export * from "@esotericsoftware/spine-webgl";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user