[ts] Port of 139fd84 and 20d5ee6: Add support to skeletons exported with per-skin atlases.

This commit is contained in:
Davide Tantillo 2025-10-15 09:15:11 +02:00
parent d6ff1bddd2
commit 9ae1af6622
3 changed files with 33 additions and 29 deletions

View File

@ -27,16 +27,16 @@
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { AttachmentLoader } from "./attachments/AttachmentLoader.js";
import type { AttachmentLoader } from "./attachments/AttachmentLoader.js";
import { BoundingBoxAttachment } from "./attachments/BoundingBoxAttachment.js";
import { ClippingAttachment } from "./attachments/ClippingAttachment.js";
import { MeshAttachment } from "./attachments/MeshAttachment.js";
import { PathAttachment } from "./attachments/PathAttachment.js";
import { PointAttachment } from "./attachments/PointAttachment.js";
import { RegionAttachment } from "./attachments/RegionAttachment.js";
import { Skin } from "./Skin.js";
import { TextureAtlas } from "./TextureAtlas.js";
import { Sequence } from "./attachments/Sequence.js"
import type { Sequence } from "./attachments/Sequence.js"
import type { Skin } from "./Skin.js";
import type { TextureAtlas } from "./TextureAtlas.js";
/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link TextureAtlas}.
*
@ -44,40 +44,44 @@ import { Sequence } from "./attachments/Sequence.js"
* Spine Runtimes Guide. */
export class AtlasAttachmentLoader implements AttachmentLoader {
atlas: TextureAtlas;
allowMissingRegions: boolean;
constructor (atlas: TextureAtlas) {
constructor (atlas: TextureAtlas, allowMissingRegions = false) {
this.atlas = atlas;
this.allowMissingRegions = allowMissingRegions;
}
loadSequence (name: string, basePath: string, sequence: Sequence) {
let regions = sequence.regions;
const regions = sequence.regions;
for (let i = 0, n = regions.length; i < n; i++) {
let path = sequence.getPath(basePath, i);
let region = this.atlas.findRegion(path);
if (region == null) throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")");
regions[i] = region;
const path = sequence.getPath(basePath, i);
regions[i] = this.atlas.findRegion(path);
if (regions[i] == null && !this.allowMissingRegions)
throw new Error(`Region not found in atlas: ${path} (sequence: ${name})`);
}
}
newRegionAttachment (skin: Skin, name: string, path: string, sequence: Sequence): RegionAttachment {
let attachment = new RegionAttachment(name, path);
const attachment = new RegionAttachment(name, path);
if (sequence != null) {
this.loadSequence(name, path, sequence);
} else {
let region = this.atlas.findRegion(path);
if (!region) throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
const region = this.atlas.findRegion(path);
if (region == null && !this.allowMissingRegions)
throw new Error(`Region not found in atlas: ${path} (region attachment: ${name})`);
attachment.region = region;
}
return attachment;
}
newMeshAttachment (skin: Skin, name: string, path: string, sequence: Sequence): MeshAttachment {
let attachment = new MeshAttachment(name, path);
const attachment = new MeshAttachment(name, path);
if (sequence != null) {
this.loadSequence(name, path, sequence);
} else {
let region = this.atlas.findRegion(path);
if (!region) throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
const region = this.atlas.findRegion(path);
if (region == null && !this.allowMissingRegions)
throw new Error(`Region not found in atlas: ${path} (mesh attachment: ${name})`);
attachment.region = region;
}
return attachment;

View File

@ -27,8 +27,8 @@
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, RGBA2Timeline, RGB2Timeline, AlphaTimeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline, SequenceTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline, BoneTimeline2, SliderTimeline, SliderMixTimeline } from "./Animation.js";
import { VertexAttachment, Attachment } from "./attachments/Attachment.js";
import { AlphaTimeline, Animation, AttachmentTimeline, BoneTimeline2, CurveTimeline, CurveTimeline1, DeformTimeline, DrawOrderTimeline, EventTimeline, IkConstraintTimeline, InheritTimeline, PathConstraintMixTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintMixTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintWindTimeline, RGB2Timeline, RGBA2Timeline, RGBATimeline, RGBTimeline, RotateTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, SequenceTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, SliderMixTimeline, SliderTimeline, Timeline, TransformConstraintTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline } from "./Animation.js";
import { Attachment, VertexAttachment } from "./attachments/Attachment.js";
import { AttachmentLoader } from "./attachments/AttachmentLoader.js";
import { HasTextureRegion } from "./attachments/HasTextureRegion.js";
import { MeshAttachment } from "./attachments/MeshAttachment.js";
@ -488,7 +488,7 @@ export class SkeletonBinary {
region.height = height * scale;
Color.rgba8888ToColor(region.color, color);
region.sequence = sequence;
if (sequence == null) region.updateRegion();
if (region.region != null) region.updateRegion();
return region;
}
case AttachmentType.BoundingBox: {
@ -529,7 +529,7 @@ export class SkeletonBinary {
mesh.worldVerticesLength = vertices.length;
mesh.triangles = triangles;
mesh.regionUVs = uvs;
if (sequence == null) mesh.updateRegion();
if (mesh.region != null) mesh.updateRegion();
mesh.hullLength = hullLength << 1;
mesh.sequence = sequence;
if (nonessential) {

View File

@ -27,17 +27,17 @@
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { TextureRegion } from "../Texture.js";
import { HasTextureRegion } from "./HasTextureRegion.js";
import type { SlotPose } from "src/SlotPose.js";
import type { TextureRegion } from "../Texture.js";
import { Utils } from "../Utils.js";
import { SlotPose } from "src/SlotPose.js";
import type { HasTextureRegion } from "./HasTextureRegion.js";
export class Sequence {
private static _nextID = 0;
id = Sequence.nextID();
regions: TextureRegion[];
regions: Array<TextureRegion | null>;
start = 0;
digits = 0;
/** The index of the region to show for the setup pose. */
@ -48,7 +48,7 @@ export class Sequence {
}
copy (): Sequence {
let copy = new Sequence(this.regions.length);
const copy = new Sequence(this.regions.length);
Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);
copy.start = this.start;
copy.digits = this.digits;
@ -58,10 +58,10 @@ export class Sequence {
apply (slot: SlotPose, attachment: HasTextureRegion) {
let index = slot.sequenceIndex;
if (index == -1) index = this.setupIndex;
if (index === -1) index = this.setupIndex;
if (index >= this.regions.length) index = this.regions.length - 1;
let region = this.regions[index];
if (attachment.region != region) {
const region = this.regions[index];
if (attachment.region !== region) {
attachment.region = region;
attachment.updateRegion();
}
@ -69,7 +69,7 @@ export class Sequence {
getPath (basePath: string, index: number): string {
let result = basePath;
let frame = (this.start + index).toString();
const frame = (this.start + index).toString();
for (let i = this.digits - frame.length; i > 0; i--)
result += "0";
result += frame;