diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 719a24674..036a021c2 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -2278,7 +2278,7 @@ public class Animation { PhysicsConstraint constraint; if (constraintIndex == -1) { float value = time >= frames[0] ? getCurveValue(time) : 0; - + Object[] constraints = skeleton.physicsConstraints.items; for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) { constraint = (PhysicsConstraint)constraints[i]; diff --git a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java index f1162b6f5..9814baf7b 100644 --- a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java +++ b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java @@ -113,7 +113,7 @@ class SkeletonViewerUI { CheckBox debugPathsCheckbox = new CheckBox("Paths", skin); CheckBox debugPointsCheckbox = new CheckBox("Points", skin); CheckBox debugClippingCheckbox = new CheckBox("Clipping", skin); - + CheckBox pmaCheckbox = new CheckBox("Premultiplied", skin); CheckBox linearCheckbox = new CheckBox("Linear", skin); diff --git a/spine-ts/spine-core/src/Animation.ts b/spine-ts/spine-core/src/Animation.ts index b4c494ab1..bd726ce51 100644 --- a/spine-ts/spine-core/src/Animation.ts +++ b/spine-ts/spine-core/src/Animation.ts @@ -350,20 +350,20 @@ export abstract class CurveTimeline1 extends CurveTimeline { getRelativeValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) { if (time < this.frames[0]) { switch (blend) { - case MixBlend.setup: - return setup; - case MixBlend.first: - return current + (setup - current) * alpha; + case MixBlend.setup: + return setup; + case MixBlend.first: + return current + (setup - current) * alpha; } return current; } let value = this.getCurveValue(time); switch (blend) { - case MixBlend.setup: - return setup + value * alpha; - case MixBlend.first: - case MixBlend.replace: - value += setup - current; + case MixBlend.setup: + return setup + value * alpha; + case MixBlend.first: + case MixBlend.replace: + value += setup - current; } return current + value * alpha; } @@ -371,10 +371,10 @@ export abstract class CurveTimeline1 extends CurveTimeline { getAbsoluteValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) { if (time < this.frames[0]) { switch (blend) { - case MixBlend.setup: - return setup; - case MixBlend.first: - return current + (setup - current) * alpha; + case MixBlend.setup: + return setup; + case MixBlend.first: + return current + (setup - current) * alpha; } return current; } @@ -383,13 +383,13 @@ export abstract class CurveTimeline1 extends CurveTimeline { return current + (value - current) * alpha; } - getAbsoluteValue2 (time: number, alpha: number, blend: MixBlend , current: number, setup: number, value: number) { + getAbsoluteValue2 (time: number, alpha: number, blend: MixBlend, current: number, setup: number, value: number) { if (time < this.frames[0]) { switch (blend) { - case MixBlend.setup: - return setup; - case MixBlend.first: - return current + (setup - current) * alpha; + case MixBlend.setup: + return setup; + case MixBlend.first: + return current + (setup - current) * alpha; } return current; } @@ -401,10 +401,10 @@ export abstract class CurveTimeline1 extends CurveTimeline { const frames = this.frames; if (time < frames[0]) { switch (blend) { - case MixBlend.setup: - return setup; - case MixBlend.first: - return current + (setup - current) * alpha; + case MixBlend.setup: + return setup; + case MixBlend.first: + return current + (setup - current) * alpha; } return current; } @@ -416,22 +416,22 @@ export abstract class CurveTimeline1 extends CurveTimeline { // Mixing out uses sign of setup or current pose, else use sign of key. if (direction == MixDirection.mixOut) { switch (blend) { - case MixBlend.setup: - return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; - case MixBlend.first: - case MixBlend.replace: - return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha; + case MixBlend.setup: + return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; + case MixBlend.first: + case MixBlend.replace: + return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha; } } else { let s = 0; switch (blend) { - case MixBlend.setup: - s = Math.abs(setup) * MathUtils.signum(value); - return s + (value - s) * alpha; - case MixBlend.first: - case MixBlend.replace: - s = Math.abs(current) * MathUtils.signum(value); - return s + (value - s) * alpha; + case MixBlend.setup: + s = Math.abs(setup) * MathUtils.signum(value); + return s + (value - s) * alpha; + case MixBlend.first: + case MixBlend.replace: + s = Math.abs(current) * MathUtils.signum(value); + return s + (value - s) * alpha; } } return current + (value - setup) * alpha; @@ -2024,220 +2024,220 @@ export abstract class PhysicsConstraintTimeline extends CurveTimeline1 { abstract global (constraint: PhysicsConstraintData): boolean; } - /** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */ - export class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); - } - - setup (constraint: PhysicsConstraint): number { - return constraint.data.inertia; - } - - get (constraint: PhysicsConstraint): number { - return constraint.inertia; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.inertia = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.inertiaGlobal; - } +/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */ +export class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); } - /** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */ - export class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); - } - - setup (constraint: PhysicsConstraint): number { - return constraint.data.strength; - } - - get (constraint: PhysicsConstraint): number { - return constraint.strength; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.strength = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.strengthGlobal; - } + setup (constraint: PhysicsConstraint): number { + return constraint.data.inertia; } - /** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */ - export class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); - } - - setup (constraint: PhysicsConstraint): number { - return constraint.data.damping; - } - - get (constraint: PhysicsConstraint): number { - return constraint.damping; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.damping = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.dampingGlobal; - } + get (constraint: PhysicsConstraint): number { + return constraint.inertia; } - /** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */ - export class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); - } - - setup (constraint: PhysicsConstraint): number { - return 1 / constraint.data.massInverse; - } - - get (constraint: PhysicsConstraint): number { - return 1 / constraint.massInverse; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.massInverse = 1 / value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.massGlobal; - } + set (constraint: PhysicsConstraint, value: number): void { + constraint.inertia = value; } - /** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ - export class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); - } + global (constraint: PhysicsConstraintData): boolean { + return constraint.inertiaGlobal; + } +} - setup (constraint: PhysicsConstraint): number { - return constraint.data.wind; - } - - get (constraint: PhysicsConstraint): number { - return constraint.wind; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.wind = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.windGlobal; - } +/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */ +export class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); } - /** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */ - export class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); - } - - setup (constraint: PhysicsConstraint): number { - return constraint.data.gravity; - } - - get (constraint: PhysicsConstraint): number { - return constraint.gravity; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.gravity = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.gravityGlobal; - } + setup (constraint: PhysicsConstraint): number { + return constraint.data.strength; } - /** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */ - export class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline { - constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { - super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); - } - - setup (constraint: PhysicsConstraint): number { - return constraint.data.mix; - } - - get (constraint: PhysicsConstraint): number { - return constraint.mix; - } - - set (constraint: PhysicsConstraint, value: number): void { - constraint.mix = value; - } - - global (constraint: PhysicsConstraintData): boolean { - return constraint.mixGlobal; - } + get (constraint: PhysicsConstraint): number { + return constraint.strength; } - /** Resets a physics constraint when specific animation times are reached. */ - export class PhysicsConstraintResetTimeline extends Timeline { - private static propertyIds: string[] = [Property.physicsConstraintReset.toString()]; + set (constraint: PhysicsConstraint, value: number): void { + constraint.strength = value; + } - /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is - * applied, or -1 if all physics constraints in the skeleton will be reset. */ - constraintIndex: number; + global (constraint: PhysicsConstraintData): boolean { + return constraint.strengthGlobal; + } +} - /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ - constructor (frameCount: number, physicsConstraintIndex: number) { - super(frameCount, PhysicsConstraintResetTimeline.propertyIds); - this.constraintIndex = physicsConstraintIndex; +/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */ +export class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); + } + + setup (constraint: PhysicsConstraint): number { + return constraint.data.damping; + } + + get (constraint: PhysicsConstraint): number { + return constraint.damping; + } + + set (constraint: PhysicsConstraint, value: number): void { + constraint.damping = value; + } + + global (constraint: PhysicsConstraintData): boolean { + return constraint.dampingGlobal; + } +} + +/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */ +export class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); + } + + setup (constraint: PhysicsConstraint): number { + return 1 / constraint.data.massInverse; + } + + get (constraint: PhysicsConstraint): number { + return 1 / constraint.massInverse; + } + + set (constraint: PhysicsConstraint, value: number): void { + constraint.massInverse = 1 / value; + } + + global (constraint: PhysicsConstraintData): boolean { + return constraint.massGlobal; + } +} + +/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ +export class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); + } + + setup (constraint: PhysicsConstraint): number { + return constraint.data.wind; + } + + get (constraint: PhysicsConstraint): number { + return constraint.wind; + } + + set (constraint: PhysicsConstraint, value: number): void { + constraint.wind = value; + } + + global (constraint: PhysicsConstraintData): boolean { + return constraint.windGlobal; + } +} + +/** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */ +export class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); + } + + setup (constraint: PhysicsConstraint): number { + return constraint.data.gravity; + } + + get (constraint: PhysicsConstraint): number { + return constraint.gravity; + } + + set (constraint: PhysicsConstraint, value: number): void { + constraint.gravity = value; + } + + global (constraint: PhysicsConstraintData): boolean { + return constraint.gravityGlobal; + } +} + +/** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */ +export class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline { + constructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); + } + + setup (constraint: PhysicsConstraint): number { + return constraint.data.mix; + } + + get (constraint: PhysicsConstraint): number { + return constraint.mix; + } + + set (constraint: PhysicsConstraint, value: number): void { + constraint.mix = value; + } + + global (constraint: PhysicsConstraintData): boolean { + return constraint.mixGlobal; + } +} + +/** Resets a physics constraint when specific animation times are reached. */ +export class PhysicsConstraintResetTimeline extends Timeline { + private static propertyIds: string[] = [Property.physicsConstraintReset.toString()]; + + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ + constraintIndex: number; + + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor (frameCount: number, physicsConstraintIndex: number) { + super(frameCount, PhysicsConstraintResetTimeline.propertyIds); + this.constraintIndex = physicsConstraintIndex; + } + + getFrameCount () { + return this.frames.length; + } + + /** Sets the time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ + setFrame (frame: number, time: number) { + this.frames[frame] = time; + } + + /** Resets the physics constraint when frames > lastTime and <= time. */ + apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) { + + let constraint: PhysicsConstraint | undefined; + if (this.constraintIndex != -1) { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (!constraint.active) return; } - getFrameCount () { - return this.frames.length; - } + const frames = this.frames; - /** Sets the time for the specified frame. - * @param frame Between 0 and frameCount, inclusive. */ - setFrame (frame: number, time: number) { - this.frames[frame] = time; - } + if (lastTime > time) { // Apply after lastTime for looped animations. + this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame. + return; + if (time < frames[0]) return; - /** Resets the physics constraint when frames > lastTime and <= time. */ - apply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) { - - let constraint: PhysicsConstraint | undefined; - if (this.constraintIndex != -1) { - constraint = skeleton.physicsConstraints[this.constraintIndex]; - if (!constraint.active) return; - } - - const frames = this.frames; - - if (lastTime > time) { // Apply after lastTime for looped animations. - this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction); - lastTime = -1; - } else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame. - return; - if (time < frames[0]) return; - - if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) { - if (constraint != null) - constraint.reset(); - else { - for (const constraint of skeleton.physicsConstraints) { - if (constraint.active) constraint.reset(); - } + if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) { + if (constraint != null) + constraint.reset(); + else { + for (const constraint of skeleton.physicsConstraints) { + if (constraint.active) constraint.reset(); } } } } +} /** Changes a slot's {@link Slot#getSequenceIndex()} for an attachment's {@link Sequence}. */ export class SequenceTimeline extends Timeline implements SlotTimeline { diff --git a/spine-ts/spine-core/src/PhysicsConstraint.ts b/spine-ts/spine-core/src/PhysicsConstraint.ts index 2f6e1d84f..2d10b8ee8 100644 --- a/spine-ts/spine-core/src/PhysicsConstraint.ts +++ b/spine-ts/spine-core/src/PhysicsConstraint.ts @@ -76,7 +76,7 @@ export class PhysicsConstraint implements Updatable { remaining = 0; lastTime = 0; - constructor(data: PhysicsConstraintData, skeleton: Skeleton) { + constructor (data: PhysicsConstraintData, skeleton: Skeleton) { this.data = data; this.skeleton = skeleton; this.bone = skeleton.bones[data.bone.index]; @@ -128,102 +128,102 @@ export class PhysicsConstraint implements Updatable { const l = bone.data.length; switch (physics) { - case Physics.none: - return; - case Physics.reset: - this.reset(); + case Physics.none: + return; + case Physics.reset: + this.reset(); // Fall through. - case Physics.update: - this.remaining += Math.max(this.skeleton.time - this.lastTime, 0); - this.lastTime = this.skeleton.time; + case Physics.update: + this.remaining += Math.max(this.skeleton.time - this.lastTime, 0); + this.lastTime = this.skeleton.time; - const bx = bone.worldX, by = bone.worldY; - if (this._reset) { - this._reset = false; - this.ux = bx; - this.uy = by; - } else { - let remaining = this.remaining, i = this.inertia, step = this.data.step; - if (x || y) { - if (x) { - this.xOffset += (this.ux - bx) * i; - this.ux = bx; - } - if (y) { - this.yOffset += (this.uy - by) * i; - this.uy = by; - } - if (remaining >= step) { - const m = this.massInverse * step, e = this.strength, w = this.wind * 100, g = this.gravity * -100; - const d = Math.pow(this.damping, 60 * step); - do { - if (x) { - this.xVelocity += (w - this.xOffset * e) * m; - this.xOffset += this.xVelocity * step; - this.xVelocity *= d; - } - if (y) { - this.yVelocity += (g - this.yOffset * e) * m; - this.yOffset += this.yVelocity * step; - this.yVelocity *= d; - } - remaining -= step; - } while (remaining >= step); - } - if (x) bone.worldX += this.xOffset * mix * this.data.x; - if (y) bone.worldY += this.yOffset * mix * this.data.y; - } - if (rotateOrShearX || scaleX) { - let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0; - if (rotateOrShearX) { - mr = mix * this.data.rotate; - let dx = this.cx - bone.worldX, dy = this.cy - bone.worldY, r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr; - this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; - r = this.rotateOffset * mr + ca; - c = Math.cos(r); - s = Math.sin(r); - if (scaleX) { - r = l * bone.getWorldScaleX(); - if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + const bx = bone.worldX, by = bone.worldY; + if (this._reset) { + this._reset = false; + this.ux = bx; + this.uy = by; + } else { + let remaining = this.remaining, i = this.inertia, step = this.data.step; + if (x || y) { + if (x) { + this.xOffset += (this.ux - bx) * i; + this.ux = bx; } - } else { - c = Math.cos(ca); - s = Math.sin(ca); - const r = l * bone.getWorldScaleX(); - if (r > 0) this.scaleOffset += ((this.cx - bone.worldX) * c + (this.cy - bone.worldY) * s) * i / r; + if (y) { + this.yOffset += (this.uy - by) * i; + this.uy = by; + } + if (remaining >= step) { + const m = this.massInverse * step, e = this.strength, w = this.wind * 100, g = this.gravity * -100; + const d = Math.pow(this.damping, 60 * step); + do { + if (x) { + this.xVelocity += (w - this.xOffset * e) * m; + this.xOffset += this.xVelocity * step; + this.xVelocity *= d; + } + if (y) { + this.yVelocity += (g - this.yOffset * e) * m; + this.yOffset += this.yVelocity * step; + this.yVelocity *= d; + } + remaining -= step; + } while (remaining >= step); + } + if (x) bone.worldX += this.xOffset * mix * this.data.x; + if (y) bone.worldY += this.yOffset * mix * this.data.y; } - remaining = this.remaining; - if (remaining >= step) { - const m = this.massInverse * step, e = this.strength, w = this.wind, g = this.gravity; - const d = Math.pow(this.damping, 60 * step); - while (true) { - remaining -= step; + if (rotateOrShearX || scaleX) { + let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0; + if (rotateOrShearX) { + mr = mix * this.data.rotate; + let dx = this.cx - bone.worldX, dy = this.cy - bone.worldY, r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr; + this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; + r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); if (scaleX) { - this.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m; - this.scaleOffset += this.scaleVelocity * step; - this.scaleVelocity *= d; + r = l * bone.getWorldScaleX(); + if (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = Math.cos(ca); + s = Math.sin(ca); + const r = l * bone.getWorldScaleX(); + if (r > 0) this.scaleOffset += ((this.cx - bone.worldX) * c + (this.cy - bone.worldY) * s) * i / r; + } + remaining = this.remaining; + if (remaining >= step) { + const m = this.massInverse * step, e = this.strength, w = this.wind, g = this.gravity; + const d = Math.pow(this.damping, 60 * step); + while (true) { + remaining -= step; + if (scaleX) { + this.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m; + this.scaleOffset += this.scaleVelocity * step; + this.scaleVelocity *= d; + } + if (rotateOrShearX) { + this.rotateVelocity += (-0.01 * l * (w * s + g * c) - this.rotateOffset * e) * m; + this.rotateOffset += this.rotateVelocity * step; + this.rotateVelocity *= d; + if (remaining < step) break; + const r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + } else if (remaining < step) // + break; } - if (rotateOrShearX) { - this.rotateVelocity += (-0.01 * l * (w * s + g * c) - this.rotateOffset * e) * m; - this.rotateOffset += this.rotateVelocity * step; - this.rotateVelocity *= d; - if (remaining < step) break; - const r = this.rotateOffset * mr + ca; - c = Math.cos(r); - s = Math.sin(r); - } else if (remaining < step) // - break; } } + this.remaining = remaining; } - this.remaining = remaining; - } - this.cx = bone.worldX; - this.cy = bone.worldY; - break; - case Physics.pose: - if (x) bone.worldX += this.xOffset * mix * this.data.x; - if (y) bone.worldY += this.yOffset * mix * this.data.y; + this.cx = bone.worldX; + this.cy = bone.worldY; + break; + case Physics.pose: + if (x) bone.worldX += this.xOffset * mix * this.data.x; + if (y) bone.worldY += this.yOffset * mix * this.data.y; } if (rotateOrShearX) { diff --git a/spine-ts/spine-core/src/PhysicsConstraintData.ts b/spine-ts/spine-core/src/PhysicsConstraintData.ts index c023388a4..ee590718e 100644 --- a/spine-ts/spine-core/src/PhysicsConstraintData.ts +++ b/spine-ts/spine-core/src/PhysicsConstraintData.ts @@ -34,7 +34,7 @@ import { ConstraintData } from "./ConstraintData.js"; /** Stores the setup pose for a {@link PhysicsConstraint}. *

* See Physics constraints in the Spine User Guide. */ -export class  PhysicsConstraintData extends ConstraintData { +export class PhysicsConstraintData extends ConstraintData { private _bone: BoneData | null = null; /** The bone constrained by this physics constraint. */ public set bone (boneData: BoneData) { this._bone = boneData; } diff --git a/spine-ts/spine-core/src/Utils.ts b/spine-ts/spine-core/src/Utils.ts index e45315143..b8db72837 100644 --- a/spine-ts/spine-core/src/Utils.ts +++ b/spine-ts/spine-core/src/Utils.ts @@ -199,7 +199,7 @@ export class MathUtils { return Math.sin(degrees * MathUtils.degRad); } - static atan2Deg(y: number, x: number) { + static atan2Deg (y: number, x: number) { return Math.atan2(y, x) * MathUtils.degRad; }