Several fixes with bounds and errors detection.

This commit is contained in:
Davide Tantillo 2025-11-20 17:31:00 +01:00
parent 5773af096d
commit e27dc43e8f
2 changed files with 38 additions and 30 deletions

View File

@ -90,7 +90,7 @@ export class SkinsAndAnimationBoundsProvider implements SpineBoundsProvider {
} }
skeleton.setupPose(); skeleton.setupPose();
const animation = this.animation != null ? data.findAnimation(this.animation!) : null; const animation = this.animation != null ? data.findAnimation(this.animation) : null;
if (animation == null) { if (animation == null) {
skeleton.updateWorldTransform(Physics.update); skeleton.updateWorldTransform(Physics.update);

View File

@ -32,11 +32,12 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
private positionModePrevX = 0; private positionModePrevX = 0;
private positionModePrevY = 0; private positionModePrevY = 0;
private positionModePrevAngle = 0; private positionModePrevAngle = 0;
private spineBoundsInit = false;
private spineBounds = { private spineBounds = {
x: 0, x: 0,
y: 0, y: 0,
width: 100, width: 200,
height: 100, height: 200,
}; };
// utils for drawing // utils for drawing
@ -59,6 +60,7 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} }
Release () { Release () {
this.textureAtlas?.dispose();
} }
OnCreate () { OnCreate () {
@ -75,6 +77,7 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
this.loadAtlas(); this.loadAtlas();
this.loadSkeleton(); this.loadSkeleton();
this.initBounds();
const { _inst, skeleton } = this; const { _inst, skeleton } = this;
const errorsString = this.getErrorsString(); const errorsString = this.getErrorsString();
@ -203,14 +206,13 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} }
async OnPropertyChanged (id: string, value: EditorPropertyValueType) { async OnPropertyChanged (id: string, value: EditorPropertyValueType) {
console.log(`Prop change - Name: ${id} - Value: ${value}`);
if (id === PLUGIN_CLASS.PROP_ATLAS) { if (id === PLUGIN_CLASS.PROP_ATLAS) {
this.textureAtlasSID = -1; this.textureAtlasSID = -1;
this.textureAtlas?.dispose(); this.textureAtlas?.dispose();
this.textureAtlas = undefined; this.textureAtlas = undefined;
this.skins = []; this.skins = [];
this.skeleton = undefined; this.skeleton = undefined;
this.spineBoundsInit = false;
this.resetBounds(); this.resetBounds();
this.layoutView?.Refresh(); this.layoutView?.Refresh();
return; return;
@ -220,6 +222,7 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
this.errorSkeleton = undefined; this.errorSkeleton = undefined;
this.skeleton = undefined; this.skeleton = undefined;
this.skins = []; this.skins = [];
this.spineBoundsInit = false;
this.resetBounds(); this.resetBounds();
this.layoutView?.Refresh(); this.layoutView?.Refresh();
return; return;
@ -266,12 +269,11 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
this.positioningBounds = value; this.positioningBounds = value;
return return
} }
console.log("Prop change end");
} }
private setAnimation () { private setAnimation () {
this.animation = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_ANIMATION) as string; const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_ANIMATION) as string;
this.animation = propValue === "" ? undefined : propValue;
} }
private setSkin () { private setSkin () {
@ -288,19 +290,13 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} else if (skins.length === 1) { } else if (skins.length === 1) {
const skinName = skins[0]; const skinName = skins[0];
const skin = skeleton.data.findSkin(skinName); const skin = skeleton.data.findSkin(skinName);
if (!skin) { if (!skin) return;
// TODO: signal error
return;
}
skeleton.setSkin(skins[0]); skeleton.setSkin(skins[0]);
} else { } else {
const customSkin = new spine.Skin(propValue); const customSkin = new spine.Skin(propValue);
for (const s of skins) { for (const s of skins) {
const skin = skeleton.data.findSkin(s) const skin = skeleton.data.findSkin(s)
if (!skin) { if (!skin) return;
// TODO: signal error
return;
}
customSkin.addSkin(skin); customSkin.addSkin(skin);
} }
skeleton.setSkin(customSkin); skeleton.setSkin(customSkin);
@ -335,8 +331,6 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
if (!this.renderer || !this.textureAtlas) return; if (!this.renderer || !this.textureAtlas) return;
if (this.skeleton) return; if (this.skeleton) return;
console.log("Loading skeleton");
const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKELETON) as number; const propValue = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKELETON) as number;
const loaderScale = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_LOADER_SCALE) as number; const loaderScale = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_LOADER_SCALE) as number;
const skeletonData = await this.assetLoader.loadSkeletonEditor(propValue, this.textureAtlas, loaderScale, this._inst) const skeletonData = await this.assetLoader.loadSkeletonEditor(propValue, this.textureAtlas, loaderScale, this._inst)
@ -355,11 +349,7 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
this.setAnimation(); this.setAnimation();
this.update(0); this.update(0);
this.setBoundsFromBoundsProvider();
this.initBounds();
this.layoutView?.Refresh(); this.layoutView?.Refresh();
console.log("SKELETON LOADED");
} }
private setBoundsFromBoundsProvider () { private setBoundsFromBoundsProvider () {
@ -387,6 +377,8 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
public resetBounds (keepScale = false) { public resetBounds (keepScale = false) {
if (!this.skeleton || !this.textureAtlas) { if (!this.skeleton || !this.textureAtlas) {
this._inst.SetSize(200, 200); this._inst.SetSize(200, 200);
this.spineBounds.width = 200;
this.spineBounds.height = 200;
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_X, 0); this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_X, 0);
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_Y, 0); this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_Y, 0);
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_ANGLE, 0); this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_ANGLE, 0);
@ -396,7 +388,12 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} }
this.setBoundsFromBoundsProvider(); this.setBoundsFromBoundsProvider();
if (this.getErrorsString()) return; if (this.getErrorsString()) {
this.spineBoundsInit = false;
return;
};
this.spineBoundsInit = true;
const { x, y, width, height } = this.spineBounds; const { x, y, width, height } = this.spineBounds;
this._inst.SetOrigin(-x / width, -y / height); this._inst.SetOrigin(-x / width, -y / height);
@ -416,6 +413,8 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} }
private initBounds () { private initBounds () {
if (this.spineBoundsInit) return;
const offsetX = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_X) as number; const offsetX = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_X) as number;
const offsetY = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_Y) as number; const offsetY = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_Y) as number;
const offsetAngle = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_ANGLE) as number; const offsetAngle = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_OFFSET_ANGLE) as number;
@ -425,13 +424,16 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
const scaleY = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKELETON_SCALE_Y) as number; const scaleY = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKELETON_SCALE_Y) as number;
const scaledBounds = scaleX !== 1 || scaleY !== 1; const scaledBounds = scaleX !== 1 || scaleY !== 1;
if (shiftedBounds || scaledBounds) { if (!shiftedBounds && !scaledBounds) {
this.spineBounds.width = this._inst.GetWidth() / scaleX; this.resetBounds();
this.spineBounds.height = this._inst.GetHeight() / scaleY;
return; return;
} }
this.resetBounds(); this.setBoundsFromBoundsProvider();
this.spineBounds.width = this._inst.GetWidth() / scaleX;
this.spineBounds.height = this._inst.GetHeight() / scaleY;
this.spineBoundsInit = true;
} }
private checkAtlasTexturesValidity () { private checkAtlasTexturesValidity () {
@ -451,16 +453,22 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
} }
private getErrorsString () { private getErrorsString () {
const { skins, animation, spineBounds } = this; const { skins, animation, spineBounds, skeleton } = this;
const errors = []; const errors = [];
const boundsType = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_PROVIDER) as SpineBoundsProviderType; const boundsType = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_BOUNDS_PROVIDER) as SpineBoundsProviderType;
if (boundsType === "animation-skin" && ((!skins || skins.length === 0) && !animation)) if (boundsType === "animation-skin" && (skins.length === 0 && !animation))
errors.push("Animation/Skin bounds provider requires one between skin and animation to be set."); errors.push("Animation/Skin bounds provider requires one between skin and animation to be set.");
if (Boolean(!animation || this.skeleton?.data.findAnimation(animation)) === false) if (Boolean(!animation || skeleton?.data.findAnimation(animation)) === false)
errors.push("Not existing animation"); errors.push("Not existing animation");
if (skins.length > 0) {
const missingSkins = skins.filter(skin => !skeleton?.data.findSkin(skin)).join(", ");
if (missingSkins)
errors.push("Not existing skin(s): ", missingSkins);
}
const { width, height } = spineBounds; const { width, height } = spineBounds;
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
errors.push("A bounds cannot have negative dimensions. This might happen when the setup pose is empty. Try to set a skin and the Animation/Skin bounds provider."); errors.push("A bounds cannot have negative dimensions. This might happen when the setup pose is empty. Try to set a skin and the Animation/Skin bounds provider.");