diff --git a/dist/Spine-v1.48.0.c3addon b/dist/Spine-v1.48.0.c3addon new file mode 100644 index 0000000..c4a815c Binary files /dev/null and b/dist/Spine-v1.48.0.c3addon differ diff --git a/src/addon.json b/src/addon.json index fd2050b..f246296 100755 --- a/src/addon.json +++ b/src/addon.json @@ -3,7 +3,7 @@ "type": "plugin", "name": "Spine", "id": "Gritsenko_Spine", - "version": "1.47.5", + "version": "1.48.0", "author": "Mikal and Igor Gritsenko", "website": "https://gritsenko.github.io/c3_spine_plugin", "documentation": "https://gritsenko.github.io/c3_spine_plugin", diff --git a/src/c3runtime/actions.js b/src/c3runtime/actions.js index 9ec7852..fb4bc66 100644 --- a/src/c3runtime/actions.js +++ b/src/c3runtime/actions.js @@ -123,8 +123,14 @@ } const skeleton = this.skeletonInfo.skeleton; - - this.customSkins[skinName] = new spine.Skin(skinName); + // If already exists, just clear + if (this.customSkins[skinName]) + { + this.customSkins[skinName].clear(); + } else + { + this.customSkins[skinName] = new spine.Skin(skinName); + } }, AddCustomSkin(skinName,addSkinName) @@ -142,7 +148,7 @@ let addSkin = skeleton.data.findSkin(addSkinName); if (addSkin) { - this.customSkins[skinName].addSkin(skeleton.data.findSkin(addSkinName)); + this.customSkins[skinName].addSkin(addSkin); } else { if (this.debug) console.warn('[Spine] AddCustomSkin, add skin does not exist',skinName,addSkinName, this.uid, this.runtime.GetTickCount()); @@ -164,7 +170,6 @@ this.skinName = skinName const skeleton = this.skeletonInfo.skeleton; - this.customSkins[this.skinName] skeleton.setSkin(this.customSkins[this.skinName]); skeleton.setSlotsToSetupPose(); @@ -214,53 +219,7 @@ ApplySlotColors() { - if (!this.skeletonInfo || !this.skeletonInfo.skeleton) - { - if (this.debug) console.warn('[Spine] ApplySlotColors, no skeleton.', this.uid, this.runtime.GetTickCount()); - return; - } - - const skeleton = this.skeletonInfo.skeleton; - // Set regular colors to slots - let slotName; - for(slotName in this.slotColors) - { - let slot = skeleton.findSlot(slotName); - if (slot === null) - { - console.warn("[Spine] ApplySlotColors, slot not found: ",slotName,this.uid,this.runtime.GetTickCount()); - continue; - } - let color = this.slotColors[slotName]; - slot.color.set( - spineBatcher.getRValue(color), - spineBatcher.getGValue(color), - spineBatcher.getBValue(color), - spineBatcher.getAValue(color)); - } - - // Set dark colors to slots - for(slotName in this.slotDarkColors) - { - let slot = skeleton.findSlot(slotName); - if (slot === null) - { - console.warn("[Spine] ApplySlotColors dark color, slot not found: ",slotName,this.uid,this.runtime.GetTickCount()); - continue; - } - // Set only if dark Color is available, (Tint Black must be applied to the slot in the project.) - if (slot.darkColor) - { - let color = this.slotDarkColors[slotName]; - slot.darkColor.set( - spineBatcher.getRValue(color), - spineBatcher.getGValue(color), - spineBatcher.getBValue(color), - spineBatcher.getAValue(color)); - } - } - - this.SetRenderOnce(1.0, true, this.uid); + this._applySlotColors() }, ResetSlotColors() diff --git a/src/c3runtime/instance.js b/src/c3runtime/instance.js index 126566a..bd4287c 100644 --- a/src/c3runtime/instance.js +++ b/src/c3runtime/instance.js @@ -983,6 +983,119 @@ this.SetRenderOnce(1.0, true, this.uid); } + _addCustomSkinOutfit(skinName, addOutfit, slots, dependentSlots) + { + const spine = globalThis.spine; + if (!this.skeletonInfo || !this.skeletonInfo.skeleton) + { + if (this.debug) console.warn('[Spine] AddCustomSkin, skeleton is not available',skinName,addOutfit, this.uid, this.runtime.GetTickCount()); + return; + } + + const skeleton = this.skeletonInfo.skeleton; + + if (!this.customSkins[skinName]) + { + this.customSkins[skinName] = new spine.Skin(skinName); + } else + { + this.customSkins[skinName].clear(); + } + + slots.forEach( slotName => + { + let addSkinName = slotName+'/'+addOutfit[slotName].skinName; + let addSkin = skeleton.data.findSkin(addSkinName); + if (addSkin) + { + // Skin + this.customSkins[skinName].addSkin(addSkin); + if (dependentSlots[slotName]) + { + let addSkinName = dependentSlots[slotName]+'/'+addOutfit[slotName].skinName; + let addSkin = skeleton.data.findSkin(addSkinName); + this.customSkins[skinName].addSkin(addSkin); + } + // Color + this.slotColors[slotName] = this._swap32(addOutfit[slotName].tintColor); + this.slotDarkColors[slotName] = this._swap32(addOutfit[slotName].tintDarkColor); + const slotRef = skeleton.findSlot(slotName) + spine.Color.rgba8888ToColor(slotRef.color, addOutfit[slotName].tintColor); + spine.Color.rgba8888ToColor(slotRef.darkColor, addOutfit[slotName].tintDarkColor); + // Dependent slots color + if (dependentSlots[slotName]) + { + const slotRef = skeleton.findSlot(dependentSlots[slotName]) + spine.Color.rgba8888ToColor(slotRef.color, addOutfit[slotName].tintColor); + spine.Color.rgba8888ToColor(slotRef.darkColor, addOutfit[slotName].tintDarkColor); + } + } else + { + if (this.debug) console.warn('[Spine] AddCustomSkin, add skin does not exist',skinName,addSkinName, this.uid, this.runtime.GetTickCount()); + } + }) + this.SetRenderOnce(1.0, true, this.uid); + } + + // Unsigned swap for C3 RGBA representation + _swap32(val) { + return (((val & 0xFF) << 24) + | ((val & 0xFF00) << 8) + | ((val >>> 8) & 0xFF00) + | ((val >>> 24) & 0xFF)) >>> 0; + } + + _applySlotColors() + { + if (!this.skeletonInfo || !this.skeletonInfo.skeleton) + { + if (this.debug) console.warn('[Spine] ApplySlotColors, no skeleton.', this.uid, this.runtime.GetTickCount()); + return; + } + + const skeleton = this.skeletonInfo.skeleton; + // Set regular colors to slots + let slotName; + for(slotName in this.slotColors) + { + let slot = skeleton.findSlot(slotName); + if (slot === null) + { + console.warn("[Spine] ApplySlotColors, slot not found: ",slotName,this.uid,this.runtime.GetTickCount()); + continue; + } + let color = this.slotColors[slotName]; + slot.color.set( + spineBatcher.getRValue(color), + spineBatcher.getGValue(color), + spineBatcher.getBValue(color), + spineBatcher.getAValue(color)); + } + + // Set dark colors to slots + for(slotName in this.slotDarkColors) + { + let slot = skeleton.findSlot(slotName); + if (slot === null) + { + console.warn("[Spine] ApplySlotColors dark color, slot not found: ",slotName,this.uid,this.runtime.GetTickCount()); + continue; + } + // Set only if dark Color is available, (Tint Black must be applied to the slot in the project.) + if (slot.darkColor) + { + let color = this.slotDarkColors[slotName]; + slot.darkColor.set( + spineBatcher.getRValue(color), + spineBatcher.getGValue(color), + spineBatcher.getBValue(color), + spineBatcher.getAValue(color)); + console.log('darkColor, slotName', slotName, Number(this.slotDarkColors[slotName]).toString(16), spineBatcher.getRValue(color), spineBatcher.getAValue(color)) + } + } + + this.SetRenderOnce(1.0, true, this.uid); + } }; // Script interface. Use a WeakMap to safely hide the internal implementation details from the @@ -1034,5 +1147,15 @@ map.get(this)._deleteAnimation(trackIndex, mixDuration); } + addCustomSkinOutfit(skinName, addOutfit, slots, dependentSlots) + { + map.get(this)._addCustomSkinOutfit(skinName, addOutfit, slots, dependentSlots); + } + + applySlotColors() + { + map.get(this)._applySlotColors(); + } + }; } \ No newline at end of file diff --git a/src/c3runtime/spine-draw.js b/src/c3runtime/spine-draw.js index 9117833..ae6f752 100644 --- a/src/c3runtime/spine-draw.js +++ b/src/c3runtime/spine-draw.js @@ -343,6 +343,6 @@ class SpineBatch { if (!globalThis.spineBatcher) { - console.log('[Spine] SpineBatcher init, 1.47.5'); + console.log('[Spine] SpineBatcher init, 1.48.0'); globalThis.spineBatcher = new SpineBatch(); } \ No newline at end of file diff --git a/src/plugin.js b/src/plugin.js index 99b55d2..e492b7f 100755 --- a/src/plugin.js +++ b/src/plugin.js @@ -3,7 +3,7 @@ const C3 = self.C3; const PLUGIN_ID = "Gritsenko_Spine"; - const PLUGIN_VERSION = "1.47.5"; + const PLUGIN_VERSION = "1.48.0"; const PLUGIN_CATEGORY = "general"; const PLUGIN_CLASS = SDK.Plugins.Gritsenko_Spine = class SpinePlugin extends SDK.IPluginBase {