diff --git a/spine-ts/spine-construct3/src/aces.json b/spine-ts/spine-construct3/src/aces.json index 305ba03a4..b160a007c 100644 --- a/spine-ts/spine-construct3/src/aces.json +++ b/spine-ts/spine-construct3/src/aces.json @@ -135,6 +135,21 @@ "type": "number" } ] + }, + { + "id": "set-attachment", + "scriptName": "SetAttachment", + "highlight": false, + "params": [ + { + "id": "slot-name", + "type": "string" + }, + { + "id": "attachment-name", + "type": "string" + } + ] } ], "expressions": [ @@ -149,6 +164,18 @@ "type": "number" } ] + }, + { + "id": "slot-attachment", + "expressionName": "SlotAttachment", + "highlight": false, + "returnType": "string", + "params": [ + { + "id": "slot-name", + "type": "string" + } + ] } ] } diff --git a/spine-ts/spine-construct3/src/c3runtime/actions.ts b/spine-ts/spine-construct3/src/c3runtime/actions.ts index 0a36b66ac..18a314fa9 100644 --- a/spine-ts/spine-construct3/src/c3runtime/actions.ts +++ b/spine-ts/spine-construct3/src/c3runtime/actions.ts @@ -35,6 +35,10 @@ C3.Plugins.EsotericSoftware_SpineConstruct3.Acts = SetEmptyAnimation (this: SDKInstanceClass, track: number, mixDuration: number) { this.setEmptyAnimation(track, mixDuration); + }, + + SetAttachment (this: SDKInstanceClass, slotName: string, attachmentName: string) { + this.setAttachment(slotName, attachmentName === "" ? null : attachmentName); } }; diff --git a/spine-ts/spine-construct3/src/c3runtime/expressions.ts b/spine-ts/spine-construct3/src/c3runtime/expressions.ts index 9b3caabee..11e8c1ca5 100644 --- a/spine-ts/spine-construct3/src/c3runtime/expressions.ts +++ b/spine-ts/spine-construct3/src/c3runtime/expressions.ts @@ -7,6 +7,13 @@ C3.Plugins.EsotericSoftware_SpineConstruct3.Exps = { Double (this: SDKInstanceClass, num: number) { return num * 2; + }, + SlotAttachment (this: SDKInstanceClass, slotName: string) { + if (!this.skeleton) return ""; + const slot = this.skeleton.findSlot(slotName); + if (!slot) return ""; + const attachment = slot.pose.getAttachment(); + return attachment ? attachment.name : ""; } }; diff --git a/spine-ts/spine-construct3/src/c3runtime/instance.ts b/spine-ts/spine-construct3/src/c3runtime/instance.ts index 3e2dc8ade..37ee6f3e2 100644 --- a/spine-ts/spine-construct3/src/c3runtime/instance.ts +++ b/spine-ts/spine-construct3/src/c3runtime/instance.ts @@ -179,6 +179,10 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase { this.state?.setEmptyAnimation(track, mixDuration); } + public setAttachment (slotName: string, attachmentName: string | null) { + this.skeleton?.setAttachment(slotName, attachmentName); + } + private _setSkin () { const { skeleton } = this; if (!skeleton) return; diff --git a/spine-ts/spine-construct3/src/lang/en-US.json b/spine-ts/spine-construct3/src/lang/en-US.json index 4d96de10f..5c276c08d 100644 --- a/spine-ts/spine-construct3/src/lang/en-US.json +++ b/spine-ts/spine-construct3/src/lang/en-US.json @@ -209,6 +209,21 @@ "desc": "Duration in seconds to mix from the current animation to empty" } } + }, + "set-attachment": { + "list-name": "Set attachment", + "display-text": "Set slot {0} attachment to {1}", + "description": "Change the attachment on a specific slot", + "params": { + "slot-name": { + "name": "Slot name", + "desc": "Name of the slot" + }, + "attachment-name": { + "name": "Attachment name", + "desc": "Name of the attachment to set" + } + } } }, "expressions": { @@ -221,6 +236,16 @@ "desc": "The number to double." } } + }, + "slot-attachment": { + "description": "Get the name of the attachment on a slot. Returns empty string if no attachment.", + "translated-name": "SlotAttachment", + "params": { + "slot-name": { + "name": "Slot name", + "desc": "Name of the slot" + } + } } } } diff --git a/spine-ts/spine-construct3/src/lang/zh-CN.json b/spine-ts/spine-construct3/src/lang/zh-CN.json index 6738a4f1d..599660a85 100644 --- a/spine-ts/spine-construct3/src/lang/zh-CN.json +++ b/spine-ts/spine-construct3/src/lang/zh-CN.json @@ -211,6 +211,21 @@ } } }, + "set-attachment": { + "list-name": "设置附件", + "display-text": "将插槽{0}的附件设置为{1}", + "description": "更改特定插槽上的附件", + "params": { + "slot-name": { + "name": "插槽名称", + "desc": "插槽的名称" + }, + "attachment-name": { + "name": "附件名称", + "desc": "要设置的附件名称" + } + } + }, "expressions": { "double": { "description": "将数字翻倍。", @@ -221,6 +236,16 @@ "desc": "要翻倍的数字。" } } + }, + "slot-attachment": { + "description": "获取插槽上的附件名称。如果没有附件则返回空字符串。", + "translated-name": "SlotAttachment", + "params": { + "slot-name": { + "name": "插槽名称", + "desc": "插槽的名称" + } + } } } } diff --git a/spine-ts/spine-core/src/Skeleton.ts b/spine-ts/spine-core/src/Skeleton.ts index 0ba5c4167..02acbd9d7 100644 --- a/spine-ts/spine-core/src/Skeleton.ts +++ b/spine-ts/spine-core/src/Skeleton.ts @@ -407,7 +407,7 @@ export class Skeleton { /** A convenience method to set an attachment by finding the slot with {@link findSlot()}, finding the attachment with * {@link getAttachment()}, then setting the slot's {@link Slot.attachment}. * @param attachmentName May be null to clear the slot's attachment. */ - setAttachment (slotName: string, attachmentName: string) { + setAttachment (slotName: string, attachmentName: string | null) { if (!slotName) throw new Error("slotName cannot be null."); const slot = this.findSlot(slotName); if (!slot) throw new Error(`Slot not found: ${slotName}`);