[ts][webcomponents] skin accepts a list of skins.

This commit is contained in:
Davide Tantillo 2025-05-20 15:35:31 +02:00
parent 23b288edc8
commit 2b5f3751ad
2 changed files with 22 additions and 9 deletions

View File

@ -370,7 +370,7 @@
atlas="/assets/vine-pma.atlas" atlas="/assets/vine-pma.atlas"
skeleton="/assets/vine-pro.skel" skeleton="/assets/vine-pro.skel"
animation="grow" animation="grow"
mode="origin" fit="origin"
scale=".5" scale=".5"
y-axis="-.5" y-axis="-.5"
></spine-skeleton> ></spine-skeleton>
@ -385,7 +385,7 @@
atlas="/assets/vine-pma.atlas" atlas="/assets/vine-pma.atlas"
skeleton="/assets/vine-pro.skel" skeleton="/assets/vine-pro.skel"
animation="grow" animation="grow"
mode="origin" fit="origin"
scale=".5" scale=".5"
y-axis="-.5" y-axis="-.5"
></spine-skeleton> ></spine-skeleton>
@ -1422,6 +1422,8 @@ function toggleSpinner(element) {
<div class="split-left" style="width: 80%; box-sizing: border-box; min-height: 0;"> <div class="split-left" style="width: 80%; box-sizing: border-box; min-height: 0;">
It's very easy to display your different skins and animations. Simply create a table and use the <code>skin</code> and <code>animation</code> attributes. It's very easy to display your different skins and animations. Simply create a table and use the <code>skin</code> and <code>animation</code> attributes.
<br>
<code>skin</code> accepts an comma separated list of skin names. The skins will be combined in a new one, from the first to the last. If multiple skins set the same slot, the latest in the list will be used.
</div> </div>
<div class="skin-grid"> <div class="skin-grid">

View File

@ -49,6 +49,7 @@ import {
RegionAttachment, RegionAttachment,
MeshAttachment, MeshAttachment,
Bone, Bone,
Skin,
} from "@esotericsoftware/spine-webgl"; } from "@esotericsoftware/spine-webgl";
import { AttributeTypes, castValue, isBase64, Rectangle } from "./wcUtils.js"; import { AttributeTypes, castValue, isBase64, Rectangle } from "./wcUtils.js";
import { SpineWebComponentOverlay } from "./SpineWebComponentOverlay.js"; import { SpineWebComponentOverlay } from "./SpineWebComponentOverlay.js";
@ -76,7 +77,7 @@ interface WidgetAttributes {
animation?: string animation?: string
animations?: AnimationsInfo animations?: AnimationsInfo
defaultMix?: number defaultMix?: number
skin?: string skin?: string[]
fit: FitType fit: FitType
xAxis: number xAxis: number
yAxis: number yAxis: number
@ -219,14 +220,14 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable
* Optional: The name of the skin to be set * Optional: The name of the skin to be set
* Connected to `skin` attribute. * Connected to `skin` attribute.
*/ */
public get skin (): string | undefined { public get skin (): string[] | undefined {
return this._skin; return this._skin;
} }
public set skin (value: string | undefined) { public set skin (value: string[] | undefined) {
this._skin = value; this._skin = value;
this.initWidget(); this.initWidget();
} }
private _skin?: string private _skin?: string[]
/** /**
* Specify the way the skeleton is sized within the element automatically changing its `scaleX` and `scaleY`. * Specify the way the skeleton is sized within the element automatically changing its `scaleX` and `scaleY`.
@ -695,7 +696,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable
animations: { propertyName: "animations", type: "animationsInfo", defaultValue: undefined }, animations: { propertyName: "animations", type: "animationsInfo", defaultValue: undefined },
"animation-bounds": { propertyName: "animationsBound", type: "array-string", defaultValue: undefined }, "animation-bounds": { propertyName: "animationsBound", type: "array-string", defaultValue: undefined },
"default-mix": { propertyName: "defaultMix", type: "number", defaultValue: 0 }, "default-mix": { propertyName: "defaultMix", type: "number", defaultValue: 0 },
skin: { propertyName: "skin", type: "string" }, skin: { propertyName: "skin", type: "array-string" },
width: { propertyName: "width", type: "number", defaultValue: -1 }, width: { propertyName: "width", type: "number", defaultValue: -1 },
height: { propertyName: "height", type: "number", defaultValue: -1 }, height: { propertyName: "height", type: "number", defaultValue: -1 },
isdraggable: { propertyName: "isDraggable", type: "boolean" }, isdraggable: { propertyName: "isDraggable", type: "boolean" },
@ -997,18 +998,28 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable
// skeleton.scaleX = this.dprScale; // skeleton.scaleX = this.dprScale;
// skeleton.scaleY = this.dprScale; // skeleton.scaleY = this.dprScale;
this.loading = false;
// the bounds are calculated the first time, if no custom bound is provided // the bounds are calculated the first time, if no custom bound is provided
this.initWidget(this.bounds.width <= 0 || this.bounds.height <= 0); this.initWidget(this.bounds.width <= 0 || this.bounds.height <= 0);
this.loading = false;
return this; return this;
} }
private initWidget (forceRecalculate = false) { private initWidget (forceRecalculate = false) {
if (this.loading) return;
const { skeleton, state, animation, animations: animationsInfo, skin, defaultMix } = this; const { skeleton, state, animation, animations: animationsInfo, skin, defaultMix } = this;
if (skin) { if (skin) {
skeleton?.setSkinByName(skin); if (skin.length === 1) {
skeleton?.setSkinByName(skin[0]);
} else {
const customSkin = new Skin("custom");
for (const s of skin) customSkin.addSkin(skeleton?.data.findSkin(s) as Skin);
skeleton?.setSkin(customSkin);
}
skeleton?.setSlotsToSetupPose(); skeleton?.setSlotsToSetupPose();
} }