From 3f099d6b876094e292554c9da708ecddf9a19213 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 4 Mar 2026 16:39:25 +0100 Subject: [PATCH] Add setBoundsForSkinAnimation and setBoundsForSetupPose actions. --- spine-ts/spine-construct3/src/aces.json | 22 ++++++++++ .../spine-construct3/src/c3runtime/actions.ts | 8 ++++ .../src/c3runtime/instance.ts | 44 ++++++++++++++++++- spine-ts/spine-construct3/src/lang/en-US.json | 20 +++++++++ spine-ts/spine-construct3/src/lang/zh-CN.json | 20 +++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/spine-ts/spine-construct3/src/aces.json b/spine-ts/spine-construct3/src/aces.json index 1c99d5840..fe91794ac 100644 --- a/spine-ts/spine-construct3/src/aces.json +++ b/spine-ts/spine-construct3/src/aces.json @@ -642,6 +642,28 @@ "initial-value": 200 } ] + }, + { + "id": "set-bounds-for-skin-animation", + "scriptName": "SetBoundsForSkinAnimation", + "highlight": false, + "params": [ + { + "id": "skins", + "type": "string", + "initial-value": "" + }, + { + "id": "animation", + "type": "string", + "initial-value": "" + } + ] + }, + { + "id": "set-bounds-for-setup-pose", + "scriptName": "SetBoundsForSetupPose", + "highlight": false } ], "expressions": [ diff --git a/spine-ts/spine-construct3/src/c3runtime/actions.ts b/spine-ts/spine-construct3/src/c3runtime/actions.ts index dbcf37698..8910215fb 100644 --- a/spine-ts/spine-construct3/src/c3runtime/actions.ts +++ b/spine-ts/spine-construct3/src/c3runtime/actions.ts @@ -182,6 +182,14 @@ C3.Plugins.EsotericSoftware_SpineConstruct3.Acts = SetBounds (this: SDKInstanceClass, x: number, y: number, width: number, height: number) { this.setBounds(x, y, width, height); + }, + + SetBoundsForSkinAnimation (this: SDKInstanceClass, skins: string, animation: string) { + this.setBoundsForSkinAnimation(skins === "" ? [] : skins.split(","), animation); + }, + + SetBoundsForSetupPose (this: SDKInstanceClass) { + this.setBoundsForSetupPose(); } }; diff --git a/spine-ts/spine-construct3/src/c3runtime/instance.ts b/spine-ts/spine-construct3/src/c3runtime/instance.ts index 851fa9134..cc192619e 100644 --- a/spine-ts/spine-construct3/src/c3runtime/instance.ts +++ b/spine-ts/spine-construct3/src/c3runtime/instance.ts @@ -1167,7 +1167,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase { this.spineBounds = { x, y, width, height }; - this.setOrigin(-x / width, y / height); + this.setOrigin(-x / width, 1 + y / height); this.width = width * scaleX * (this.isMirrored ? -1 : 1); this.height = height * scaleY * (this.isFlipped ? -1 : 1); @@ -1181,6 +1181,48 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase { return { ...this.spineBounds }; } + public setBoundsForSkinAnimation (skins: string[], animation: string) { + if (!this.skeleton || !this.state) { + console.warn('[Spine] setBoundsForSkinAnimation: skeleton or state not loaded'); + return; + } + + const boundsProvider = new spine.SkinsAndAnimationBoundsProvider( + animation || undefined, + skins + ); + + const bounds = boundsProvider.calculateBounds(this); + + if (bounds.width <= 0 || bounds.height <= 0) { + console.warn('[Spine] setBoundsForSkinAnimation: calculated bounds have invalid dimensions'); + return; + } + + const yUp = -(bounds.y + bounds.height); + + this.setBounds(bounds.x, yUp, bounds.width, bounds.height); + } + + public setBoundsForSetupPose () { + if (!this.skeleton) { + console.warn('[Spine] setBoundsForSetupPose: skeleton not loaded'); + return; + } + + const boundsProvider = new spine.SetupPoseBoundsProvider(); + const bounds = boundsProvider.calculateBounds(this); + + if (bounds.width <= 0 || bounds.height <= 0) { + console.warn('[Spine] setBoundsForSetupPose: calculated bounds have invalid dimensions'); + return; + } + + const yUp = -(bounds.y + bounds.height); + + this.setBounds(bounds.x, yUp, bounds.width, bounds.height); + } + /**********/ }; diff --git a/spine-ts/spine-construct3/src/lang/en-US.json b/spine-ts/spine-construct3/src/lang/en-US.json index c7eccffc7..cbb920a58 100644 --- a/spine-ts/spine-construct3/src/lang/en-US.json +++ b/spine-ts/spine-construct3/src/lang/en-US.json @@ -744,6 +744,26 @@ "desc": "Height of the bounds in Spine world coordinates" } } + }, + "set-bounds-for-skin-animation": { + "list-name": "Set bounds for skin/animation", + "display-text": "Set bounds for skins {0} and animation {1}", + "description": "Calculate and set bounds based on the specified skins and animation. Uses a separate skeleton to compute the bounding box by stepping through the animation frames. The skeleton's visual size stays the same.", + "params": { + "skins": { + "name": "Skins", + "desc": "Comma-separated list of skin names. Leave empty to use the default skin." + }, + "animation": { + "name": "Animation", + "desc": "Animation name to calculate bounds for. Leave empty to use setup pose." + } + } + }, + "set-bounds-for-setup-pose": { + "list-name": "Set bounds for setup pose", + "display-text": "Set bounds for setup pose", + "description": "Calculate and set bounds based on the skeleton's setup pose. The skeleton's visual size stays the same." } }, "expressions": { diff --git a/spine-ts/spine-construct3/src/lang/zh-CN.json b/spine-ts/spine-construct3/src/lang/zh-CN.json index d0a1cadbd..92953ab31 100644 --- a/spine-ts/spine-construct3/src/lang/zh-CN.json +++ b/spine-ts/spine-construct3/src/lang/zh-CN.json @@ -744,6 +744,26 @@ "desc": "边界在Spine世界坐标中的高度" } } + }, + "set-bounds-for-skin-animation": { + "list-name": "根据皮肤/动画设置边界", + "display-text": "根据皮肤{0}和动画{1}设置边界", + "description": "根据指定的皮肤和动画计算并设置边界。使用独立的骨架通过遍历动画帧来计算边界框。骨架的视觉大小保持不变。", + "params": { + "skins": { + "name": "皮肤", + "desc": "逗号分隔的皮肤名称列表。留空以使用默认皮肤。" + }, + "animation": { + "name": "动画", + "desc": "用于计算边界的动画名称。留空以使用初始姿势。" + } + } + }, + "set-bounds-for-setup-pose": { + "list-name": "根据初始姿势设置边界", + "display-text": "根据初始姿势设置边界", + "description": "根据骨架的初始姿势计算并设置边界。骨架的视觉大小保持不变。" } }, "expressions": {