From d29eb5fa99a515859b8547e04b816d93e5647a62 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 8 Oct 2025 17:49:21 +0200 Subject: [PATCH] [haxe][starling] SkeletonSprite scale is connected to skeleton scale. --- .../flixelExamples/CelestialCircusExample.hx | 1 - .../src/flixelExamples/CloudPotExample.hx | 1 - .../example/src/flixelExamples/SackExample.hx | 1 - .../src/flixelExamples/SnowglobeExample.hx | 1 - .../example/src/flixelExamples/TankExample.hx | 1 - .../example/src/flixelExamples/VineExample.hx | 1 - .../src/starlingExamples/BasicExample.hx | 10 ++- .../CelestialCircusExample.hx | 5 +- .../src/starlingExamples/CloudPotExample.hx | 1 - .../starlingExamples/ControlBonesExample.hx | 3 +- .../src/starlingExamples/EventsExample.hx | 1 - .../starlingExamples/MixAndMatchExample.hx | 5 +- .../src/starlingExamples/SequenceExample.hx | 2 +- .../src/starlingExamples/SnowglobeExample.hx | 1 - .../src/starlingExamples/TankExample.hx | 2 +- .../example/src/starlingExamples/Test.hx | 79 ------------------- .../src/starlingExamples/VineExample.hx | 2 +- spine-haxe/project.xml | 4 +- .../spine/starling/SkeletonSprite.hx | 34 +++++++- 19 files changed, 48 insertions(+), 107 deletions(-) delete mode 100644 spine-haxe/example/src/starlingExamples/Test.hx diff --git a/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx index c9eb219ef..cf84381c6 100644 --- a/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx +++ b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx @@ -31,7 +31,6 @@ package flixelExamples; import flixel.text.FlxText; import flixel.math.FlxPoint; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/flixelExamples/CloudPotExample.hx b/spine-haxe/example/src/flixelExamples/CloudPotExample.hx index ce8343672..e78652945 100644 --- a/spine-haxe/example/src/flixelExamples/CloudPotExample.hx +++ b/spine-haxe/example/src/flixelExamples/CloudPotExample.hx @@ -29,7 +29,6 @@ package flixelExamples; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/flixelExamples/SackExample.hx b/spine-haxe/example/src/flixelExamples/SackExample.hx index d4b8be6b1..3cfff81a6 100644 --- a/spine-haxe/example/src/flixelExamples/SackExample.hx +++ b/spine-haxe/example/src/flixelExamples/SackExample.hx @@ -29,7 +29,6 @@ package flixelExamples; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx b/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx index 4bde6bdaf..671be57e4 100644 --- a/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx +++ b/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx @@ -29,7 +29,6 @@ package flixelExamples; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/flixelExamples/TankExample.hx b/spine-haxe/example/src/flixelExamples/TankExample.hx index 447e4a6c1..7f97c086e 100644 --- a/spine-haxe/example/src/flixelExamples/TankExample.hx +++ b/spine-haxe/example/src/flixelExamples/TankExample.hx @@ -29,7 +29,6 @@ package flixelExamples; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/flixelExamples/VineExample.hx b/spine-haxe/example/src/flixelExamples/VineExample.hx index 9f8d632aa..04ec49156 100644 --- a/spine-haxe/example/src/flixelExamples/VineExample.hx +++ b/spine-haxe/example/src/flixelExamples/VineExample.hx @@ -29,7 +29,6 @@ package flixelExamples; -import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; import spine.flixel.SkeletonSprite; diff --git a/spine-haxe/example/src/starlingExamples/BasicExample.hx b/spine-haxe/example/src/starlingExamples/BasicExample.hx index 538fb3bde..4bfea7624 100644 --- a/spine-haxe/example/src/starlingExamples/BasicExample.hx +++ b/spine-haxe/example/src/starlingExamples/BasicExample.hx @@ -29,6 +29,7 @@ package starlingExamples; +import spine.boundsprovider.SkinsAndAnimationBoundsProvider; import starlingExamples.Scene.SceneManager; import openfl.utils.Assets; import spine.SkeletonData; @@ -49,11 +50,12 @@ class BasicExample extends Scene { var animationStateData = new AnimationStateData(skeletondata); animationStateData.defaultMix = 0.25; - var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); - var bounds = skeletonSprite.skeleton.getBounds(); - skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width * 0.5; + var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData, new SkinsAndAnimationBoundsProvider("walk")); + var bounds = skeletonSprite.bounds; + skeletonSprite.scale = Starling.current.stage.stageWidth * .8 / bounds.width; + skeletonSprite.x = Starling.current.stage.stageWidth / 2; - skeletonSprite.y = Starling.current.stage.stageHeight * 0.9; + skeletonSprite.y = Starling.current.stage.stageHeight * 0.95; skeletonSprite.state.setAnimationByName(0, "walk", true); diff --git a/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx b/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx index 5e7b24187..3cc863448 100644 --- a/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx +++ b/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx @@ -29,7 +29,6 @@ package starlingExamples; -import spine.BlendMode; import starlingExamples.Scene.SceneManager; import openfl.utils.Assets; import spine.SkeletonData; @@ -60,8 +59,6 @@ class CelestialCircusExample extends Scene { skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); skeletonSprite.skeleton.updateWorldTransform(Physics.update); - var bounds = skeletonSprite.skeleton.getBounds(); - skeletonSprite.scale = 0.2; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight / 1.5; @@ -84,7 +81,7 @@ class CelestialCircusExample extends Scene { skeletonTouch.getMovement(this, movement); skeletonSprite.x += movement.x; skeletonSprite.y += movement.y; - skeletonSprite.skeleton.physicsTranslate(movement.x / skeletonSprite.scale, movement.y / skeletonSprite.scale,); + skeletonSprite.skeleton.physicsTranslate(movement.x, movement.y); } } else { var sceneTouch = e.getTouch(this); diff --git a/spine-haxe/example/src/starlingExamples/CloudPotExample.hx b/spine-haxe/example/src/starlingExamples/CloudPotExample.hx index 26166afea..1fd992a8a 100644 --- a/spine-haxe/example/src/starlingExamples/CloudPotExample.hx +++ b/spine-haxe/example/src/starlingExamples/CloudPotExample.hx @@ -55,7 +55,6 @@ class CloudPotExample extends Scene { var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); skeletonSprite.skeleton.updateWorldTransform(Physics.update); - var bounds = skeletonSprite.skeleton.getBounds(); skeletonSprite.scale = 0.2; skeletonSprite.x = Starling.current.stage.stageWidth / 2; diff --git a/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx b/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx index 26a95ae32..c0417dd4b 100644 --- a/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx +++ b/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx @@ -59,7 +59,7 @@ class ControlBonesExample extends Scene { skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); - var bounds = skeletonSprite.skeleton.getBounds(); + var bounds = skeletonSprite.bounds; skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width * 0.25; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight * 0.9; @@ -79,6 +79,7 @@ class ControlBonesExample extends Scene { "front-leg-ik-target", ]; + skeletonSprite.advanceTime(0); for (boneName in controlBoneNames) { var bone = skeletonSprite.skeleton.findBone(boneName); var point = [bone.applied.worldX, bone.applied.worldY]; diff --git a/spine-haxe/example/src/starlingExamples/EventsExample.hx b/spine-haxe/example/src/starlingExamples/EventsExample.hx index ee62155b3..f6ff89f83 100644 --- a/spine-haxe/example/src/starlingExamples/EventsExample.hx +++ b/spine-haxe/example/src/starlingExamples/EventsExample.hx @@ -29,7 +29,6 @@ package starlingExamples; -import spine.animation.TrackEntry; import starlingExamples.Scene.SceneManager; import openfl.utils.Assets; import spine.SkeletonData; diff --git a/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx b/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx index 749fc4c66..12297e610 100644 --- a/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx +++ b/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx @@ -29,6 +29,7 @@ package starlingExamples; +import spine.boundsprovider.SkinsAndAnimationBoundsProvider; import spine.Skin; import starlingExamples.Scene.SceneManager; import openfl.utils.Assets; @@ -50,7 +51,7 @@ class MixAndMatchExample extends Scene { var animationStateData = new AnimationStateData(data); animationStateData.defaultMix = 0.25; - var skeletonSprite = new SkeletonSprite(data, animationStateData); + var skeletonSprite = new SkeletonSprite(data, animationStateData, new SkinsAndAnimationBoundsProvider("dance", ["full-skins/boy"])); var customSkin = new Skin("custom"); var skinBase = data.findSkin("skin-base"); customSkin.addSkin(skinBase); @@ -64,7 +65,7 @@ class MixAndMatchExample extends Scene { customSkin.addSkin(data.findSkin("accessories/hat-red-yellow")); skeletonSprite.skeleton.skin = customSkin; - var bounds = skeletonSprite.skeleton.getBounds(); + var bounds = skeletonSprite.bounds; skeletonSprite.scale = Starling.current.stage.stageHeight / bounds.height * 0.5; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight * 0.9; diff --git a/spine-haxe/example/src/starlingExamples/SequenceExample.hx b/spine-haxe/example/src/starlingExamples/SequenceExample.hx index 2aa64d57e..d1707eec4 100644 --- a/spine-haxe/example/src/starlingExamples/SequenceExample.hx +++ b/spine-haxe/example/src/starlingExamples/SequenceExample.hx @@ -50,7 +50,7 @@ class SequenceExample extends Scene { animationStateData.defaultMix = 0.25; var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); - var bounds = skeletonSprite.skeleton.getBounds(); + var bounds = skeletonSprite.bounds; skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width * 0.5; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight * 0.5; diff --git a/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx b/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx index 47bd3fccb..87790b6c1 100644 --- a/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx +++ b/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx @@ -55,7 +55,6 @@ class SnowglobeExample extends Scene { var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); skeletonSprite.skeleton.updateWorldTransform(Physics.update); - var bounds = skeletonSprite.skeleton.getBounds(); skeletonSprite.scale = 0.15; skeletonSprite.x = Starling.current.stage.stageWidth / 2; diff --git a/spine-haxe/example/src/starlingExamples/TankExample.hx b/spine-haxe/example/src/starlingExamples/TankExample.hx index 708c51de2..2e18cbf19 100644 --- a/spine-haxe/example/src/starlingExamples/TankExample.hx +++ b/spine-haxe/example/src/starlingExamples/TankExample.hx @@ -51,7 +51,7 @@ class TankExample extends Scene { animationStateData.defaultMix = 0.25; var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); - var bounds = skeletonSprite.skeleton.getBounds(); + var bounds = skeletonSprite.bounds; skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight * 0.5; diff --git a/spine-haxe/example/src/starlingExamples/Test.hx b/spine-haxe/example/src/starlingExamples/Test.hx deleted file mode 100644 index 5a5e91a88..000000000 --- a/spine-haxe/example/src/starlingExamples/Test.hx +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated April 5, 2025. Replaces all prior versions. - * - * Copyright (c) 2013-2025, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -package starlingExamples; - -import starlingExamples.Scene.SceneManager; -import openfl.utils.Assets; -import spine.SkeletonData; -import spine.animation.AnimationStateData; -import spine.atlas.TextureAtlas; -import spine.starling.SkeletonSprite; -import spine.starling.StarlingTextureLoader; -import starling.core.Starling; -import starling.events.TouchEvent; -import starling.events.TouchPhase; - -class Test extends Scene { - var loadBinary = true; - - public function load():Void { - background.color = 0xaaaaaaff; - - var atlas = new TextureAtlas(Assets.getText("assets/avatar.spine_atlas"), new StarlingTextureLoader("assets/avatar.spine_atlas")); - var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/avatar.skel") : Assets.getText("assets/avatar.json"), atlas); - var animationStateData = new AnimationStateData(skeletondata); - animationStateData.defaultMix = 0.25; - - var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); - var bounds = skeletonSprite.skeleton.getBounds(); - skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width * 0.2; - skeletonSprite.x = Starling.current.stage.stageWidth / 2; - skeletonSprite.y = Starling.current.stage.stageHeight * 0.9; - - for (i in 0...skeletondata.animations.length) { - skeletonSprite.state.addAnimation(0, skeletondata.animations[i], false, 0); - } - - addChild(skeletonSprite); - juggler.add(skeletonSprite); - - addText("Click anywhere for next scene"); - - addEventListener(TouchEvent.TOUCH, onTouch); - } - - public function onTouch(e:TouchEvent) { - var touch = e.getTouch(this); - trace(touch); - if (touch != null && touch.phase == TouchPhase.ENDED) { - SceneManager.getInstance().switchScene(new SequenceExample()); - } - } -} diff --git a/spine-haxe/example/src/starlingExamples/VineExample.hx b/spine-haxe/example/src/starlingExamples/VineExample.hx index dd4ff1a6b..caa697367 100644 --- a/spine-haxe/example/src/starlingExamples/VineExample.hx +++ b/spine-haxe/example/src/starlingExamples/VineExample.hx @@ -53,7 +53,7 @@ class VineExample extends Scene { var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); skeletonSprite.skeleton.updateWorldTransform(Physics.none); - var bounds = skeletonSprite.skeleton.getBounds(); + var bounds = skeletonSprite.bounds; skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width / 10; skeletonSprite.x = Starling.current.stage.stageWidth / 2; skeletonSprite.y = Starling.current.stage.stageHeight * 0.5; diff --git a/spine-haxe/project.xml b/spine-haxe/project.xml index d3fe1547e..6b4423862 100644 --- a/spine-haxe/project.xml +++ b/spine-haxe/project.xml @@ -2,9 +2,9 @@ - + - + diff --git a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx index 09473a119..41cb2ea73 100644 --- a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx +++ b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx @@ -36,7 +36,6 @@ import openfl.geom.Matrix; import openfl.geom.Point; import openfl.geom.Rectangle as OpenFlRectangle; import spine.Bone; -import spine.Rectangle; import spine.Skeleton; import spine.SkeletonClipping; import spine.SkeletonData; @@ -264,12 +263,12 @@ class SkeletonSprite extends DisplayObject implements IAnimatable { _boundsPoint[0] = __bounds.x; _boundsPoint[1] = __bounds.y; skeletonToHaxeWorldCoordinates(_boundsPoint); - out.setTo(_boundsPoint[0], _boundsPoint[1], __bounds.width * scaleX, __bounds.height * scaleX); + out.setTo(_boundsPoint[0], _boundsPoint[1], __bounds.width, __bounds.height); } else { getTransformationMatrix(targetSpace, _tempMatrix); out.setTo(__bounds.x, __bounds.y, __bounds.width, __bounds.height); MatrixUtil.transformCoords(_tempMatrix, out.x, out.y, _tempPoint); - out.setTo(_tempPoint.x, _tempPoint.y, out.width * scaleX, out.height * scaleY); + out.setTo(_tempPoint.x, _tempPoint.y, out.width, out.height); } return out; @@ -286,6 +285,35 @@ class SkeletonSprite extends DisplayObject implements IAnimatable { return _smoothing; } + override function get_scaleX():Float { + return skeleton.scaleX; + } + + override function set_scaleX(value:Float):Float { + skeleton.scaleX = value; + calculateBounds(); + return skeleton.scaleX; + } + + override function get_scaleY():Float { + return skeleton.scaleY * Bone.yDir; + } + + override function set_scaleY(value:Float):Float { + skeleton.scaleY = value; + calculateBounds(); + return value; + } + + override function get_scale():Float { + return skeleton.scaleX; + } + + override function set_scale(value:Float):Float { + scaleY = value; + return scaleX = value; + } + public function advanceTime(time:Float):Void { state.update(time); state.apply(skeleton);