[haxe] Backport 69279957: Removed lime dependency from Skeleton.hx.

This commit is contained in:
Davide Tantillo 2025-11-28 09:21:40 +01:00
parent f173e85667
commit 0dfaede396
3 changed files with 119 additions and 91 deletions

View File

@ -25,12 +25,11 @@
* 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 spine;
import lime.math.Rectangle;
import haxe.ds.StringMap;
import spine.Rectangle;
import spine.attachments.Attachment;
import spine.attachments.ClippingAttachment;
import spine.attachments.MeshAttachment;
@ -43,20 +42,27 @@ import spine.attachments.RegionAttachment;
*/
class Skeleton {
private static var quadTriangles:Array<Int> = [0, 1, 2, 2, 3, 0];
private var _data:SkeletonData;
/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */
public var bones:Array<Bone>;
/** The skeleton's slots. */
public var slots:Array<Slot>; // Setup pose draw order.
/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */
public var drawOrder:Array<Slot>;
/** The skeleton's IK constraints. */
public var ikConstraints:Array<IkConstraint>;
/** The skeleton's transform constraints. */
public var transformConstraints:Array<TransformConstraint>;
/** The skeleton's path constraints. */
public var pathConstraints:Array<PathConstraint>;
/** The skeleton's physics constraints. */
public var physicsConstraints:Array<PhysicsConstraint>;
@ -65,6 +71,7 @@ class Skeleton {
/** The color to tint all the skeleton's attachments. */
public var color:Color = new Color(1, 1, 1, 1);
/** Scales the entire skeleton on the X axis.
*
* Bones that do not inherit scale are still affected by this property. */
@ -74,6 +81,7 @@ class Skeleton {
*
* Bones that do not inherit scale are still affected by this property. */
public var scaleY(get, default):Float = 1;
function get_scaleY() {
return Bone.yDown ? -scaleY : scaleY;
}
@ -82,10 +90,12 @@ class Skeleton {
*
* Bones that do not inherit translation are still affected by this property. */
public var x:Float = 0;
/** Sets the skeleton Y position, which is added to the root bone worldY position.
*
* Bones that do not inherit translation are still affected by this property. */
public var y:Float = 0;
/** Returns the skeleton's time. This is used for time-based manipulations, such as spine.PhysicsConstraint.
*
* See Skeleton.update(). */
@ -317,7 +327,7 @@ class Skeleton {
}
private function sortPathConstraintAttachment(skin:Skin, slotIndex:Int, slotBone:Bone):Void {
var dict:StringMap<Attachment> = skin.attachments[slotIndex];
var dict = skin.attachments[slotIndex];
if (dict != null) {
for (attachment in dict.keyValueIterator()) {
sortPathConstraintAttachment2(attachment.value, slotBone);
@ -345,10 +355,12 @@ class Skeleton {
}
}
private function sortPhysicsConstraint (constraint: PhysicsConstraint) {
private function sortPhysicsConstraint(constraint:PhysicsConstraint) {
var bone:Bone = constraint.bone;
constraint.active = bone.active && (!constraint.data.skinRequired || (skin != null && contains(skin.constraints, constraint.data)));
if (!constraint.active) return;
constraint.active = bone.active
&& (!constraint.data.skinRequired || (skin != null && contains(skin.constraints, constraint.data)));
if (!constraint.active)
return;
sortBone(bone);
@ -383,7 +395,8 @@ class Skeleton {
* @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide
*/
public function updateWorldTransform(physics:Physics):Void {
if (physics == null) throw new SpineException("physics is undefined");
if (physics == null)
throw new SpineException("physics is undefined");
for (bone in bones) {
bone.ax = bone.x;
bone.ay = bone.y;
@ -440,11 +453,16 @@ class Skeleton {
/** Sets the bones and constraints to their setup pose values. */
public function setBonesToSetupPose():Void {
for (bone in this.bones) bone.setToSetupPose();
for (constraint in this.ikConstraints) constraint.setToSetupPose();
for (constraint in this.transformConstraints) constraint.setToSetupPose();
for (constraint in this.pathConstraints) constraint.setToSetupPose();
for (constraint in this.physicsConstraints) constraint.setToSetupPose();
for (bone in this.bones)
bone.setToSetupPose();
for (constraint in this.ikConstraints)
constraint.setToSetupPose();
for (constraint in this.transformConstraints)
constraint.setToSetupPose();
for (constraint in this.pathConstraints)
constraint.setToSetupPose();
for (constraint in this.physicsConstraints)
constraint.setToSetupPose();
}
/** Sets the slots and draw order to their setup pose values. */
@ -686,7 +704,7 @@ class Skeleton {
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. Optionally applies
* clipping. */
public function getBounds(clipper: SkeletonClipping = null):Rectangle {
public function getBounds(clipper:SkeletonClipping = null):Rectangle {
var minX:Float = Math.POSITIVE_INFINITY;
var minY:Float = Math.POSITIVE_INFINITY;
var maxX:Float = Math.NEGATIVE_INFINITY;
@ -732,9 +750,11 @@ class Skeleton {
ii += 2;
}
}
if (clipper != null) clipper.clipEndWithSlot(slot);
if (clipper != null)
clipper.clipEndWithSlot(slot);
}
if (clipper != null) clipper.clipEnd();
if (clipper != null)
clipper.clipEnd();
_bounds.x = minX;
_bounds.y = minY;
_bounds.width = maxX - minX;
@ -743,18 +763,18 @@ class Skeleton {
}
/** Increments the skeleton's Skeleton.time. */
public function update (delta:Float):Void {
public function update(delta:Float):Void {
time += delta;
}
/** Calls spine.PhysicsConstraint.translate() for each physics constraint. */
public function physicsTranslate (x:Float, y:Float):Void {
public function physicsTranslate(x:Float, y:Float):Void {
for (physicsConstraint in physicsConstraints)
physicsConstraint.translate(x, y);
}
/** Calls spine.PhysicsConstraint.rotate() for each physics constraint. */
public function physicsRotate (x:Float, y:Float, degrees:Float):Void {
public function physicsRotate(x:Float, y:Float, degrees:Float):Void {
for (physicsConstraint in physicsConstraints)
physicsConstraint.rotate(x, y, degrees);
}

View File

@ -25,7 +25,7 @@
* 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 spine.flixel;
@ -63,13 +63,13 @@ import spine.attachments.ClippingAttachment;
import spine.flixel.SkeletonMesh;
/** A FlxObject that draws a skeleton. The animation state and skeleton must be updated each frame. */
class SkeletonSprite extends FlxObject
{
class SkeletonSprite extends FlxObject {
public var skeleton(default, null):Skeleton;
public var state(default, null):AnimationState;
public var stateData(default, null):AnimationStateData;
public var beforeUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
public var afterUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
public var beforeUpdateWorldTransforms:SkeletonSprite->Void = function(_) {};
public var afterUpdateWorldTransforms:SkeletonSprite->Void = function(_) {};
public static var clipper(default, never):SkeletonClipping = new SkeletonClipping();
public var offsetX = .0;
@ -93,9 +93,9 @@ class SkeletonSprite extends FlxObject
private var _tempPoint = new Point();
private static var QUAD_INDICES:Array<Int> = [0, 1, 2, 2, 3, 0];
/** Creates an uninitialized SkeletonSprite. The renderer, skeleton, and animation state must be set before use. */
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null)
{
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null) {
super(0, 0);
Bone.yDown = true;
skeleton = new Skeleton(skeletonData);
@ -114,30 +114,34 @@ class SkeletonSprite extends FlxObject
}
}
public function getAnimationBounds(animation:Animation, clip:Bool = true): lime.math.Rectangle {
public function getAnimationBounds(animation:Animation, clip:Bool = true):Rectangle {
var clipper = clip ? SkeletonSprite.clipper : null;
skeleton.setToSetupPose();
var steps = 100, time = 0.;
var stepTime = animation.duration != 0 ? animation.duration / steps : 0;
var minX = 100000000., maxX = -100000000., minY = 100000000., maxY = -100000000.;
var minX = 100000000.,
maxX = -100000000.,
minY = 100000000.,
maxY = -100000000.;
var bounds = new lime.math.Rectangle();
for (i in 0...steps) {
animation.apply(skeleton, time , time, false, [], 1, MixBlend.setup, MixDirection.mixIn);
animation.apply(skeleton, time, time, false, [], 1, MixBlend.setup, MixDirection.mixIn);
skeleton.updateWorldTransform(Physics.update);
bounds = skeleton.getBounds(clipper);
var boundsSkel = skeleton.getBounds(clipper);
if (!Math.isNaN(bounds.x) && !Math.isNaN(bounds.y) && !Math.isNaN(bounds.width) && !Math.isNaN(bounds.height)) {
minX = Math.min(bounds.x, minX);
minY = Math.min(bounds.y, minY);
maxX = Math.max(bounds.right, maxX);
maxY = Math.max(bounds.bottom, maxY);
if (!Math.isNaN(boundsSkel.x) && !Math.isNaN(boundsSkel.y) && !Math.isNaN(boundsSkel.width) && !Math.isNaN(boundsSkel.height)) {
minX = Math.min(boundsSkel.x, minX);
minY = Math.min(boundsSkel.y, minY);
maxX = Math.max(boundsSkel.x + boundsSkel.width, maxX);
maxY = Math.max(boundsSkel.y + boundsSkel.height, maxY);
} else
trace("ERROR");
throw new SpineException("Animation bounds are invalid: " + animation.name);
time += stepTime;
}
var bounds = new Rectangle();
bounds.x = minX;
bounds.y = minY;
bounds.width = maxX - minX;
@ -145,8 +149,7 @@ class SkeletonSprite extends FlxObject
return bounds;
}
override public function destroy():Void
{
override public function destroy():Void {
state.clearListeners();
state = null;
skeleton = null;
@ -157,15 +160,15 @@ class SkeletonSprite extends FlxObject
_tempPoint = null;
if (_meshes != null) {
for (mesh in _meshes) mesh.destroy();
for (mesh in _meshes)
mesh.destroy();
_meshes = null;
}
super.destroy();
}
override public function update(elapsed:Float):Void
{
override public function update(elapsed:Float):Void {
super.update(elapsed);
state.update(elapsed);
state.apply(skeleton);
@ -175,14 +178,15 @@ class SkeletonSprite extends FlxObject
this.afterUpdateWorldTransforms(this);
}
override public function draw():Void
{
if (alpha == 0) return;
override public function draw():Void {
if (alpha == 0)
return;
renderMeshes();
#if FLX_DEBUG
if (FlxG.debugger.drawDebug) drawDebug();
if (FlxG.debugger.drawDebug)
drawDebug();
#end
}
@ -244,14 +248,10 @@ class SkeletonSprite extends FlxObject
}
if (mesh != null) {
// cannot use directly mesh.color.setRGBFloat otherwise the setter won't be called and transfor color not set
mesh.color = FlxColor.fromRGBFloat(
skeleton.color.r * slot.color.r * attachmentColor.r * color.redFloat,
mesh.color = FlxColor.fromRGBFloat(skeleton.color.r * slot.color.r * attachmentColor.r * color.redFloat,
skeleton.color.g * slot.color.g * attachmentColor.g * color.greenFloat,
skeleton.color.b * slot.color.b * attachmentColor.b * color.blueFloat,
1
);
skeleton.color.b * slot.color.b * attachmentColor.b * color.blueFloat, 1);
mesh.alpha = skeleton.color.a * slot.color.a * attachmentColor.a * alpha;
if (clipper.isClipping()) {
@ -272,7 +272,7 @@ class SkeletonSprite extends FlxObject
_tempPoint = _tempMatrix.transformPoint(_tempPoint);
mesh.vertices[i] = _tempPoint.x;
mesh.vertices[i + 1] = _tempPoint.y;
i+=2;
i += 2;
}
}
} else {
@ -354,7 +354,7 @@ class SkeletonSprite extends FlxObject
point[1] = x * b + y * d + ty;
}
public function haxeWorldCoordinatesToBone(point:Array<Float>, bone: Bone):Void {
public function haxeWorldCoordinatesToBone(point:Array<Float>, bone:Bone):Void {
this.haxeWorldCoordinatesToSkeleton(point);
if (bone.parent != null) {
bone.parent.worldToLocal(point);
@ -363,7 +363,7 @@ class SkeletonSprite extends FlxObject
}
}
private function getFlixelMeshFromRendererAttachment(region: RenderedAttachment) {
private function getFlixelMeshFromRendererAttachment(region:RenderedAttachment) {
if (region.rendererObject == null) {
var skeletonMesh = new SkeletonMesh();
region.rendererObject = skeletonMesh;
@ -373,15 +373,15 @@ class SkeletonSprite extends FlxObject
return region.rendererObject;
}
function set_flipX(value:Bool):Bool
{
if (value != flipX) skeleton.scaleX = -skeleton.scaleX;
function set_flipX(value:Bool):Bool {
if (value != flipX)
skeleton.scaleX = -skeleton.scaleX;
return flipX = value;
}
function set_flipY(value:Bool):Bool
{
if (value != flipY) skeleton.scaleY = -skeleton.scaleY;
function set_flipY(value:Bool):Bool {
if (value != flipY)
skeleton.scaleY = -skeleton.scaleY;
return flipY = value;
}
@ -404,7 +404,6 @@ class SkeletonSprite extends FlxObject
function set_scaleY(value:Float):Float {
return skeleton.scaleY = value;
}
}
typedef RenderedAttachment = {

View File

@ -25,7 +25,7 @@
* 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 spine.starling;
@ -33,7 +33,7 @@ import spine.animation.Animation;
import starling.animation.IAnimatable;
import openfl.geom.Matrix;
import openfl.geom.Point;
import openfl.geom.Rectangle;
import openfl.geom.Rectangle as OpenFlRectangle;
import spine.Bone;
import spine.Skeleton;
import spine.SkeletonClipping;
@ -76,8 +76,8 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
private var tempLight:spine.Color = new spine.Color(0, 0, 0);
private var tempDark:spine.Color = new spine.Color(0, 0, 0);
public var beforeUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
public var afterUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
public var beforeUpdateWorldTransforms:SkeletonSprite->Void = function(_) {};
public var afterUpdateWorldTransforms:SkeletonSprite->Void = function(_) {};
/** Creates an uninitialized SkeletonSprite. The skeleton and animation state must be set before use. */
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null) {
@ -306,9 +306,9 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
return null;
}
override public function getBounds(targetSpace:DisplayObject, resultRect:Rectangle = null):Rectangle {
override public function getBounds(targetSpace:DisplayObject, resultRect:OpenFlRectangle = null):OpenFlRectangle {
if (resultRect == null) {
resultRect = new Rectangle();
resultRect = new OpenFlRectangle();
}
if (targetSpace == this) {
resultRect.setTo(0, 0, 0, 0);
@ -322,31 +322,39 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
return resultRect;
}
public function getAnimationBounds(animation:Animation, clip:Bool = true): Rectangle {
public function getAnimationBounds(animation:Animation, clip:Bool = true):Rectangle {
var clipper = clip ? SkeletonSprite.clipper : null;
_skeleton.setToSetupPose();
var steps = 100, time = 0.;
var stepTime = animation.duration != 0 ? animation.duration / steps : 0;
var minX = 100000000., maxX = -100000000., minY = 100000000., maxY = -100000000.;
var minX = 100000000.,
maxX = -100000000.,
minY = 100000000.,
maxY = -100000000.;
var bound:lime.math.Rectangle;
for (i in 0...steps) {
animation.apply(_skeleton, time , time, false, [], 1, MixBlend.setup, MixDirection.mixIn);
animation.apply(_skeleton, time, time, false, [], 1, MixBlend.setup, MixDirection.mixIn);
_skeleton.updateWorldTransform(Physics.update);
bound = _skeleton.getBounds(clipper);
var boundsSkel = _skeleton.getBounds(clipper);
if (!Math.isNaN(bound.x) && !Math.isNaN(bound.y) && !Math.isNaN(bound.width) && !Math.isNaN(bound.height)) {
minX = Math.min(bound.x, minX);
minY = Math.min(bound.y, minY);
maxX = Math.max(bound.right, maxX);
maxY = Math.max(bound.bottom, maxY);
if (!Math.isNaN(boundsSkel.x) && !Math.isNaN(boundsSkel.y) && !Math.isNaN(boundsSkel.width) && !Math.isNaN(boundsSkel.height)) {
minX = Math.min(boundsSkel.x, minX);
minY = Math.min(boundsSkel.y, minY);
maxX = Math.max(boundsSkel.x + boundsSkel.width, maxX);
maxY = Math.max(boundsSkel.y + boundsSkel.height, maxY);
} else
trace("ERROR");
throw new SpineException("Animation bounds are invalid: " + animation.name);
time += stepTime;
}
return new Rectangle(minX, minY, maxX - minX, maxY - minY);
var bounds = new Rectangle();
bounds.x = minX;
bounds.y = minY;
bounds.width = maxX - minX;
bounds.height = maxY - minY;
return bounds;
}
public var skeleton(get, never):Skeleton;
@ -410,7 +418,7 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
point[1] = x * b + y * d + ty;
}
public function haxeWorldCoordinatesToBone(point:Array<Float>, bone: Bone):Void {
public function haxeWorldCoordinatesToBone(point:Array<Float>, bone:Bone):Void {
this.haxeWorldCoordinatesToSkeleton(point);
if (bone.parent != null) {
bone.parent.worldToLocal(point);
@ -424,7 +432,8 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
_state.clearListeners();
_state = null;
}
if (_skeleton != null) _skeleton = null;
if (_skeleton != null)
_skeleton = null;
dispatchEventWith(starling.events.Event.REMOVE_FROM_JUGGLER);
removeFromParent();