From b8f3a8b8aed3f4a040f472850264a3cf2c3a8efc Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 19 Dec 2023 15:09:48 +0100 Subject: [PATCH] [ts] Fix SkeletonJson physics constraints and timelines parsing. --- spine-flutter/src/spine_flutter.cpp | 6 +- spine-ts/spine-core/src/SkeletonJson.ts | 96 ++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 3f2e42e77..d6441abea 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -733,9 +733,9 @@ spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable draw Slot &slot = *skeleton->getDrawOrder()[i]; Attachment *attachment = slot.getAttachment(); if (!attachment) { - clipper.clipEnd(slot); - continue; - } + clipper.clipEnd(slot); + continue; + } // Early out if the slot color is 0 or the bone is not active if (slot.getColor().a == 0 || !slot.getBone().isActive()) { diff --git a/spine-ts/spine-core/src/SkeletonJson.ts b/spine-ts/spine-core/src/SkeletonJson.ts index 555b3e3df..a82818e18 100644 --- a/spine-ts/spine-core/src/SkeletonJson.ts +++ b/spine-ts/spine-core/src/SkeletonJson.ts @@ -27,7 +27,7 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Animation, Timeline, AttachmentTimeline, RGBATimeline, RGBTimeline, AlphaTimeline, RGBA2Timeline, RGB2Timeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline } from "./Animation.js"; +import { Animation, Timeline, AttachmentTimeline, RGBATimeline, RGBTimeline, AlphaTimeline, RGBA2Timeline, RGB2Timeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline } from "./Animation.js"; import { VertexAttachment, Attachment } from "./attachments/Attachment.js"; import { AttachmentLoader } from "./attachments/AttachmentLoader.js"; import { MeshAttachment } from "./attachments/MeshAttachment.js"; @@ -44,6 +44,7 @@ import { Utils, Color, NumberArrayLike } from "./Utils.js"; import { Sequence, SequenceMode } from "./attachments/Sequence.js"; import { SequenceTimeline } from "./Animation.js"; import { HasTextureRegion } from "./attachments/HasTextureRegion.js"; +import { PhysicsConstraintData } from "./PhysicsConstraintData.js"; /** Loads skeleton data in the Spine JSON format. * @@ -234,6 +235,44 @@ export class SkeletonJson { } } + if (root.physics) { + // Physics constraints. + for (let i = 0; i < root.physics.length; i++) { + const constraintMap = root.physics[i]; + const data = new PhysicsConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + + const boneName = constraintMap.bone; + const bone = skeletonData.findBone(boneName); + if (bone == null) throw new Error("Physics bone not found: " + boneName); + data.bone = bone; + + data.x = getValue(constraintMap, "x", 0); + data.y = getValue(constraintMap, "y", 0); + data.rotate = getValue(constraintMap, "rotate", 0); + data.scaleX = getValue(constraintMap, "scaleX", 0); + data.shearX = getValue(constraintMap, "shearX", 0); + data.step = 1 / getValue(constraintMap, "fps", 60); + data.inertia = getValue(constraintMap, "inertia", 1); + data.strength = getValue(constraintMap, "strength", 100); + data.damping = getValue(constraintMap, "damping", 1); + data.massInverse = 1 / getValue(constraintMap, "mass", 1); + data.wind = getValue(constraintMap, "wind", 0); + data.gravity = getValue(constraintMap, "gravity", 0); + data.mix = getValue(constraintMap, "mix", 1); + data.inertiaGlobal = getValue(constraintMap, "inertiaGlobal", false); + data.strengthGlobal = getValue(constraintMap, "strengthGlobal", false); + data.dampingGlobal = getValue(constraintMap, "dampingGlobal", false); + data.massGlobal = getValue(constraintMap, "massGlobal", false); + data.windGlobal = getValue(constraintMap, "windGlobal", false); + data.gravityGlobal = getValue(constraintMap, "gravityGlobal", false); + data.mixGlobal = getValue(constraintMap, "mixGlobal", false); + + skeletonData.physicsConstraints.push(data); + } + } + // Skins. if (root.skins) { for (let i = 0; i < root.skins.length; i++) { @@ -276,6 +315,15 @@ export class SkeletonJson { } } + if (skinMap.physics) { + for (let ii = 0; ii < skinMap.physics.length; ii++) { + let constraintName = skinMap.physics[ii]; + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (let slotName in skinMap.attachments) { let slot = skeletonData.findSlot(slotName); if (!slot) throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); @@ -838,6 +886,52 @@ export class SkeletonJson { } } + // Physics constraint timelines. + if (map.physics) { + for (let constraintName in map.physics) { + let constraintMap = map.physics[constraintName]; + let constraintIndex = -1; + if (constraintName.length > 0) { + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) throw new Error("Physics constraint not found: " + constraintName); + constraintIndex = skeletonData.physicsConstraints.indexOf(constraint); + } + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) continue; + + let frames = timelineMap.length; + if (timelineName == "reset") { + const timeline = new PhysicsConstraintResetTimeline(timelineMap.size, constraintIndex); + for (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++) + timeline.setFrame(frame, getValue(keyMap, "time", 0)); + timelines.push(timeline); + continue; + } + + let timeline; + if (timelineName == "inertia") + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex); + else if (timelineName == "strength") + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex); + else if (timelineName == "damping") + timeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex); + else if (timelineName == "mass") + timeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex); + else if (timelineName == "wind") + timeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex); + else if (timelineName == "gravity") + timeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex); + else if (timelineName == "mix") // + timeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex); + else + continue; + timelines.push(readTimeline1(timelineMap, timeline, 0, 1)); + } + } + } + // Attachment timelines. if (map.attachments) { for (let attachmentsName in map.attachments) {