diff --git a/spine-ts/index.html b/spine-ts/index.html
index 8ac653b04..2767da1a7 100644
--- a/spine-ts/index.html
+++ b/spine-ts/index.html
@@ -43,6 +43,7 @@
Physics III - (v7)
Physics IV - (v7)
Slot Objects - (v7)
+ Slot Objects (Rotation, scale test) - (v7)
Bounds - (v7)
Bunny Mark - (v7)
diff --git a/spine-ts/spine-pixi-v7/example/slot-objects-scale-rotation.html b/spine-ts/spine-pixi-v7/example/slot-objects-scale-rotation.html
new file mode 100644
index 000000000..21c7ed04f
--- /dev/null
+++ b/spine-ts/spine-pixi-v7/example/slot-objects-scale-rotation.html
@@ -0,0 +1,130 @@
+
+
+
+ spine-pixi
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spine-ts/spine-pixi-v7/src/Spine.ts b/spine-ts/spine-pixi-v7/src/Spine.ts
index eb49e192b..9ec656e93 100644
--- a/spine-ts/spine-pixi-v7/src/Spine.ts
+++ b/spine-ts/spine-pixi-v7/src/Spine.ts
@@ -34,7 +34,6 @@ import {
AtlasAttachmentLoader,
ClippingAttachment,
Color,
- MathUtils,
MeshAttachment,
Physics,
RegionAttachment,
@@ -52,7 +51,7 @@ import { SlotMesh } from "./SlotMesh.js";
import { DarkSlotMesh } from "./DarkSlotMesh.js";
import type { ISpineDebugRenderer, SpineDebugRenderer } from "./SpineDebugRenderer.js";
import { Assets } from "@pixi/assets";
-import { IPointData, Point, Rectangle } from "@pixi/core";
+import { IPointData, Point } from "@pixi/core";
import { Ticker } from "@pixi/core";
import type { IDestroyOptions, DisplayObject } from "@pixi/display";
import { Bounds, Container } from "@pixi/display";
@@ -593,8 +592,24 @@ export class Spine extends Container {
if (slotObject.visible) {
slotObject.position.set(slot.bone.worldX, slot.bone.worldY);
- slotObject.scale.set(slot.bone.getWorldScaleX(), slot.bone.getWorldScaleY());
- slotObject.rotation = slot.bone.getWorldRotationX() * MathUtils.degRad;
+ slotObject.angle = slot.bone.getWorldRotationX();
+
+ let bone: Bone | null = slot.bone;
+ let cumulativeScaleX = 1;
+ let cumulativeScaleY = 1;
+ while (bone) {
+ cumulativeScaleX *= bone.scaleX;
+ cumulativeScaleY *= bone.scaleY;
+ bone = bone.parent;
+ };
+
+ if (cumulativeScaleX < 0) slotObject.angle -= 180;
+
+ slotObject.scale.set(
+ slot.bone.getWorldScaleX() * Math.sign(cumulativeScaleX),
+ slot.bone.getWorldScaleY() * Math.sign(cumulativeScaleY),
+ );
+
slotObject.zIndex = zIndex + 1;
slotObject.alpha = this.skeleton.color.a * slot.color.a;
}
diff --git a/spine-ts/spine-pixi-v8/example/slot-objects-scale-rotation.html b/spine-ts/spine-pixi-v8/example/slot-objects-scale-rotation.html
new file mode 100644
index 000000000..ab0df26d1
--- /dev/null
+++ b/spine-ts/spine-pixi-v8/example/slot-objects-scale-rotation.html
@@ -0,0 +1,126 @@
+
+
+
+ spine-pixi
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spine-ts/spine-pixi-v8/src/Spine.ts b/spine-ts/spine-pixi-v8/src/Spine.ts
index ae18440cf..720647274 100644
--- a/spine-ts/spine-pixi-v8/src/Spine.ts
+++ b/spine-ts/spine-pixi-v8/src/Spine.ts
@@ -33,7 +33,6 @@ import {
Cache,
Container,
ContainerOptions,
- DEG_TO_RAD,
DestroyOptions,
fastCopy,
Graphics,
@@ -785,14 +784,25 @@ export class Spine extends ViewContainer {
container.visible = this.skeleton.drawOrder.includes(slot) && followAttachmentValue;
if (container.visible) {
- const bone = slot.bone;
+ let bone: Bone | null = slot.bone;
container.position.set(bone.worldX, bone.worldY);
+ container.angle = bone.getWorldRotationX();
- container.scale.x = bone.getWorldScaleX();
- container.scale.y = bone.getWorldScaleY();
+ let cumulativeScaleX = 1;
+ let cumulativeScaleY = 1;
+ while (bone) {
+ cumulativeScaleX *= bone.scaleX;
+ cumulativeScaleY *= bone.scaleY;
+ bone = bone.parent;
+ };
- container.rotation = bone.getWorldRotationX() * DEG_TO_RAD;
+ if (cumulativeScaleX < 0) container.angle -= 180;
+
+ container.scale.set(
+ slot.bone.getWorldScaleX() * Math.sign(cumulativeScaleX),
+ slot.bone.getWorldScaleY() * Math.sign(cumulativeScaleY),
+ );
container.alpha = this.skeleton.color.a * slot.color.a;
}