diff --git a/spine-godot/SConstruct b/spine-godot/SConstruct index bce6589fb..d57f5aa9e 100644 --- a/spine-godot/SConstruct +++ b/spine-godot/SConstruct @@ -70,6 +70,11 @@ env = SConscript("godot-cpp/SConstruct", {"env": env, "customs": customs}) env.Append(CPPDEFINES=["SPINE_GODOT_EXTENSION"]) env.Append(CPPPATH=["spine_godot", "spine_godot/spine-cpp/include"]) +# Set iOS minimum deployment target +if env["platform"] == "ios": + env.Append(CCFLAGS=["-miphoneos-version-min=12.0"]) + env.Append(LINKFLAGS=["-miphoneos-version-min=12.0"]) + # sources = Glob("spine_godot/*.cpp") + Glob("spine_godot/spine-cpp/src/spine/*.cpp") sources = Glob("spine_godot/spine-cpp/src/spine/*.cpp") sources.append("spine_godot/GodotSpineExtension.cpp") diff --git a/spine-haxe/spine-haxe/spine/BinaryInput.hx b/spine-haxe/spine-haxe/spine/BinaryInput.hx index c7fb7a8d9..218d5dc78 100644 --- a/spine-haxe/spine-haxe/spine/BinaryInput.hx +++ b/spine-haxe/spine-haxe/spine/BinaryInput.hx @@ -32,6 +32,9 @@ package spine; import haxe.io.FPHelper; import haxe.io.Bytes; +/** + * Input for reading skeleton data. + */ class BinaryInput { private var bytes:Bytes; private var index:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/BlendMode.hx b/spine-haxe/spine-haxe/spine/BlendMode.hx index 9d3692b24..1e230da35 100644 --- a/spine-haxe/spine-haxe/spine/BlendMode.hx +++ b/spine-haxe/spine-haxe/spine/BlendMode.hx @@ -29,6 +29,7 @@ package spine; +/** Determines how images are blended with existing pixels when drawn. */ class BlendMode { public static var normal(default, never):BlendMode = new BlendMode(0, "normal"); public static var additive(default, never):BlendMode = new BlendMode(1, "additive"); diff --git a/spine-haxe/spine-haxe/spine/Bone.hx b/spine-haxe/spine-haxe/spine/Bone.hx index 508d21876..47c691f7f 100644 --- a/spine-haxe/spine-haxe/spine/Bone.hx +++ b/spine-haxe/spine-haxe/spine/Bone.hx @@ -29,6 +29,11 @@ package spine; +/** Stores a bone's current pose. + * + * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a + * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a + * constraint or application code modifies the world transform after it was computed from the local transform. */ class Bone implements Updatable { static public var yDown:Bool = false; @@ -37,55 +42,80 @@ class Bone implements Updatable { private var _parent:Bone; private var _children:Array = new Array(); + /** The local x translation. */ public var x:Float = 0; + /** The local y translation. */ public var y:Float = 0; + /** The local rotation in degrees, counter clockwise. */ public var rotation:Float = 0; + /** The local scaleX. */ public var scaleX:Float = 0; + /** The local scaleY. */ public var scaleY:Float = 0; + /** The local shearX. */ public var shearX:Float = 0; + /** The local shearY. */ public var shearY:Float = 0; + /** The applied local x translation. */ public var ax:Float = 0; + /** The applied local y translation. */ public var ay:Float = 0; + /** The applied local rotation in degrees, counter clockwise. */ public var arotation:Float = 0; + /** The applied local scaleX. */ public var ascaleX:Float = 0; + /** The applied local scaleY. */ public var ascaleY:Float = 0; + /** The applied local shearX. */ public var ashearX:Float = 0; + /** The applied local shearY. */ public var ashearY:Float = 0; + /** Part of the world transform matrix for the X axis. If changed, updateAppliedTransform() should be called. */ public var a:Float = 0; + /** Part of the world transform matrix for the Y axis. If changed, updateAppliedTransform() should be called. */ public var b:Float = 0; + /** Part of the world transform matrix for the X axis. If changed, updateAppliedTransform() should be called. */ public var c:Float = 0; + /** Part of the world transform matrix for the Y axis. If changed, updateAppliedTransform() should be called. */ public var d:Float = 0; + /** The world X position. If changed, updateAppliedTransform() should be called. */ public var worldX:Float = 0; + /** The world Y position. If changed, updateAppliedTransform() should be called. */ public var worldY:Float = 0; + /** Determines how parent world transforms affect this bone. */ public var inherit:Inherit = Inherit.normal; public var sorted:Bool = false; public var active:Bool = false; + /** The bone's setup pose data. */ public var data(get, never):BoneData; private function get_data():BoneData { return _data; } + /** The skeleton this bone belongs to. */ public var skeleton(get, never):Skeleton; private function get_skeleton():Skeleton { return _skeleton; } + /** The parent bone, or null if this is the root bone. */ public var parent(get, never):Bone; private function get_parent():Bone { return _parent; } + /** The immediate children of this bone. */ public var children(get, never):Array; private function get_children():Array { return _children; } - /** @param parent May be null. */ + /** Copy constructor. Does not copy the children bones. */ public function new(data:BoneData, skeleton:Skeleton, parent:Bone) { if (data == null) throw new SpineException("data cannot be null."); @@ -101,17 +131,23 @@ class Bone implements Updatable { return active; } - /** Same as updateWorldTransform(). This method exists for Bone to implement Updatable. */ + /** Computes the world transform using the parent bone and this bone's local applied transform. */ public function update(physics:Physics):Void { updateWorldTransformWith(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY); } - /** Computes the world SRT using the parent bone and this bone's local SRT. */ + /** Computes the world transform using the parent bone and this bone's local transform. + * + * See updateWorldTransformWith(). */ public function updateWorldTransform():Void { updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY); } - /** Computes the world SRT using the parent bone and the specified local SRT. */ + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + * + * @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide + */ public function updateWorldTransformWith(x:Float, y:Float, rotation:Float, scaleX:Float, scaleY:Float, shearX:Float, shearY:Float):Void { ax = x; ay = y; @@ -234,6 +270,7 @@ class Bone implements Updatable { d *= sy; } + /** Sets this bone's local transform to the setup pose. */ public function setToSetupPose():Void { x = data.x; y = data.y; @@ -245,10 +282,14 @@ class Bone implements Updatable { inherit = data.inherit; } - /** Computes the individual applied transform values from the world transform. This can be useful to perform processing using - * the applied transform after the world transform has been modified directly (eg, by a constraint). - *

- * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */ + /** Computes the applied transform values from the world transform. + * + * If the world transform is modified (by a constraint, rotateWorld(), etc) then this method should be called so + * the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply another + * constraint). + * + * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after + * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ public function updateAppliedTransform():Void { var parent:Bone = parent; if (parent == null) { @@ -329,42 +370,49 @@ class Bone implements Updatable { } } + /** The world rotation for the X axis, calculated using a and c. */ public var worldRotationX(get, never):Float; private function get_worldRotationX():Float { return Math.atan2(c, a) * MathUtils.radDeg; } + /** The world rotation for the Y axis, calculated using b and d. */ public var worldRotationY(get, never):Float; private function get_worldRotationY():Float { return Math.atan2(d, b) * MathUtils.radDeg; } + /** The magnitude (always positive) of the world scale X, calculated using a and c. */ public var worldScaleX(get, never):Float; private function get_worldScaleX():Float { return Math.sqrt(a * a + c * c); } + /** The magnitude (always positive) of the world scale Y, calculated using b and d. */ public var worldScaleY(get, never):Float; private function get_worldScaleY():Float { return Math.sqrt(b * b + d * d); } - private function worldToParent(world: Array):Array { + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + public function worldToParent(world: Array):Array { if (world == null) throw new SpineException("world cannot be null."); return parent == null ? world : parent.worldToLocal(world); } - private function parentToWorld(world: Array):Array { + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + public function parentToWorld(world: Array):Array { if (world == null) throw new SpineException("world cannot be null."); return parent == null ? world : parent.localToWorld(world); } + /** Transforms a point from world coordinates to the bone's local coordinates. */ public function worldToLocal(world:Array):Array { var a:Float = a, b:Float = b, c:Float = c, d:Float = d; var invDet:Float = 1 / (a * d - b * c); @@ -374,6 +422,7 @@ class Bone implements Updatable { return world; } + /** Transforms a point from the bone's local coordinates to world coordinates. */ public function localToWorld(local:Array):Array { var localX:Float = local[0], localY:Float = local[1]; local[0] = localX * a + localY * b + worldX; @@ -381,12 +430,14 @@ class Bone implements Updatable { return local; } + /** Transforms a world rotation to a local rotation. */ public function worldToLocalRotation(worldRotation:Float):Float { var sin:Float = MathUtils.sinDeg(worldRotation), cos:Float = MathUtils.cosDeg(worldRotation); return Math.atan2(a * sin - c * cos, d * cos - b * sin) * MathUtils.radDeg + rotation - shearX; } + /** Transforms a local rotation to a world rotation. */ public function localToWorldRotation(localRotation:Float):Float { localRotation -= rotation - shearX; var sin:Float = MathUtils.sinDeg(localRotation), @@ -394,6 +445,10 @@ class Bone implements Updatable { return Math.atan2(cos * c + sin * d, cos * a + sin * b) * MathUtils.radDeg; } + /** Rotates the world transform the specified amount. + * + * After changes are made to the world transform, updateAppliedTransform() should be called and + * update() will need to be called on any child bones, recursively. */ public function rotateWorld(degrees:Float):Void { degrees *= MathUtils.degRad; var sin:Float = Math.sin(degrees), cos:Float = Math.cos(degrees); diff --git a/spine-haxe/spine-haxe/spine/BoneData.hx b/spine-haxe/spine-haxe/spine/BoneData.hx index 079e0eb39..b22a03bf0 100644 --- a/spine-haxe/spine-haxe/spine/BoneData.hx +++ b/spine-haxe/spine-haxe/spine/BoneData.hx @@ -29,26 +29,43 @@ package spine; +/** Stores the setup pose for a spine.Bone. */ class BoneData { private var _index:Int; private var _name:String; private var _parent:BoneData; + /** The bone's length. */ public var length:Float = 0; + /** The local x translation. */ public var x:Float = 0; + /** The local y translation. */ public var y:Float = 0; + /** The local rotation in degrees, counter clockwise. */ public var rotation:Float = 0; + /** The local scaleX. */ public var scaleX:Float = 1; + /** The local scaleY. */ public var scaleY:Float = 1; + /** The local shearX. */ public var shearX:Float = 0; + /** The local shearY. */ public var shearY:Float = 0; + /** Determines how parent world transforms affect this bone. */ public var inherit:Inherit = Inherit.normal; + /** When true, spine.Skeleton.updateWorldTransform() only updates this bone if the spine.Skeleton.getSkin() contains + * this bone. + * @see spine.Skin.getBones() */ public var skinRequired:Bool = false; + /** The color of the bone as it was in Spine, or a default color if nonessential data was not exported. Bones are not usually + * rendered at runtime. */ public var color:Color = new Color(0, 0, 0, 0); + /** The bone icon as it was in Spine, or null if nonessential data was not exported. */ public var icon:String; + /** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ public var visible:Bool = false; - /** @param parent May be null. */ + /** Copy constructor. */ public function new(index:Int, name:String, parent:BoneData) { if (index < 0) throw new SpineException("index must be >= 0"); @@ -59,15 +76,17 @@ class BoneData { _parent = parent; } + /** The index of the bone in spine.Skeleton.getBones(). */ public var index(get, never):Int; private function get_index():Int { return _index; } + /** The name of the bone, which is unique across all bones in the skeleton. */ public var name(get, never):String; - function get_name():String { + private function get_name():String { return _name; } diff --git a/spine-haxe/spine-haxe/spine/Color.hx b/spine-haxe/spine-haxe/spine/Color.hx index 6c39bdd66..da8b11f8f 100644 --- a/spine-haxe/spine-haxe/spine/Color.hx +++ b/spine-haxe/spine-haxe/spine/Color.hx @@ -29,6 +29,7 @@ package spine; +/** A color class, storing the r, g, b and alpha components as floats in the range [0,1]. */ class Color { public static var WHITE:Color = new Color(1, 1, 1, 1); public static var RED:Color = new Color(1, 0, 0, 1); diff --git a/spine-haxe/spine-haxe/spine/ConstraintData.hx b/spine-haxe/spine-haxe/spine/ConstraintData.hx index 294b30e7f..8206b3459 100644 --- a/spine-haxe/spine-haxe/spine/ConstraintData.hx +++ b/spine-haxe/spine-haxe/spine/ConstraintData.hx @@ -29,9 +29,16 @@ package spine; +/** The base class for all constraint datas. */ class ConstraintData { + /** The constraint's name, which is unique across all constraints in the skeleton of the same type. */ public var name:String; + /** The ordinal of this constraint for the order a skeleton's constraints will be applied by + * spine.Skeleton.updateWorldTransform(). */ public var order:Int = 0; + /** When true, spine.Skeleton.updateWorldTransform() only updates this constraint if the spine.Skeleton.getSkin() + * contains this constraint. + * @see spine.Skin.getConstraints() */ public var skinRequired:Bool = false; function new(name:String, order:Int, skinRequired:Bool) { diff --git a/spine-haxe/spine-haxe/spine/Event.hx b/spine-haxe/spine-haxe/spine/Event.hx index d55cdccc2..a45ec0ee8 100644 --- a/spine-haxe/spine-haxe/spine/Event.hx +++ b/spine-haxe/spine-haxe/spine/Event.hx @@ -29,9 +29,17 @@ package spine; +/** Stores the current pose values for an Event. + * + * @see spine.Timeline + * @see spine.Timeline.apply() + * @see spine.AnimationStateListener.event() + * @see https://esotericsoftware.com/spine-events Events in the Spine User Guide + */ class Event { private var _data:EventData; + /** The animation time this event was keyed. */ public var time:Float = 0; public var intValue:Int = 0; public var floatValue:Float = 0; @@ -46,6 +54,7 @@ class Event { _data = data; } + /** The event's setup pose data. */ public var data(get, never):EventData; private function get_data():EventData { diff --git a/spine-haxe/spine-haxe/spine/EventData.hx b/spine-haxe/spine-haxe/spine/EventData.hx index dacbd372f..1117cd492 100644 --- a/spine-haxe/spine-haxe/spine/EventData.hx +++ b/spine-haxe/spine-haxe/spine/EventData.hx @@ -29,6 +29,11 @@ package spine; +/** Stores the setup pose values for an spine.Event. + * + * + * @see https://esotericsoftware.com/spine-events Events in the Spine User Guide + */ class EventData { private var _name:String; @@ -45,6 +50,7 @@ class EventData { _name = name; } + /** The name of the event, which is unique across all events in the skeleton. */ public var name(get, never):String; private function get_name():String { diff --git a/spine-haxe/spine-haxe/spine/HasTextureRegion.hx b/spine-haxe/spine-haxe/spine/HasTextureRegion.hx index 59ec5aeb8..cb289d14e 100644 --- a/spine-haxe/spine-haxe/spine/HasTextureRegion.hx +++ b/spine-haxe/spine-haxe/spine/HasTextureRegion.hx @@ -30,9 +30,15 @@ package spine; interface HasTextureRegion { + /** The name used to find the region. */ public var path:String; + /** Sets the region used to draw the attachment. After setting the region or if the region's properties are changed, + * updateRegion() must be called. */ public var region:TextureRegion; + /** The color to tint the attachment. */ public var color:Color; public var sequence:Sequence; + /** Updates any values the attachment calculates using the region. Must be called after setting the + * region or if the region's properties are changed. */ public function updateRegion():Void; } diff --git a/spine-haxe/spine-haxe/spine/IkConstraint.hx b/spine-haxe/spine-haxe/spine/IkConstraint.hx index 4a68f3eb2..f92f7dc31 100644 --- a/spine-haxe/spine-haxe/spine/IkConstraint.hx +++ b/spine-haxe/spine-haxe/spine/IkConstraint.hx @@ -29,18 +29,36 @@ package spine; +/** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of + * the last bone is as close to the target bone as possible. + * + * @see https://esotericsoftware.com/spine-ik-constraints IK constraints in the Spine User Guide */ class IkConstraint implements Updatable { private var _data:IkConstraintData; + /** The bones that will be modified by this IK constraint. */ public var bones:Array; + /** The bone that is the IK target. */ public var target:Bone; + /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ public var bendDirection:Int = 0; + /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ public var compress:Bool = false; + /** When true and the target is out of range, the parent bone is scaled to reach it. + * + * For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if getSoftness() is + * > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ public var stretch:Bool = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. + * + * For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */ public var mix:Float = 0; + /** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones + * will not straighten completely until the target is this far out of range. */ public var softness:Float = 0; public var active:Bool = false; + /** Copy constructor. */ public function new(data:IkConstraintData, skeleton:Skeleton) { if (data == null) throw new SpineException("data cannot be null."); @@ -74,6 +92,7 @@ class IkConstraint implements Updatable { stretch = data.stretch; } + /** Applies the constraint to the constrained bones. */ public function update(physics:Physics):Void { if (mix == 0) return; @@ -85,6 +104,7 @@ class IkConstraint implements Updatable { } } + /** The IK constraint's setup pose data. */ public var data(get, never):IkConstraintData; private function get_data():IkConstraintData { @@ -92,11 +112,10 @@ class IkConstraint implements Updatable { } public function toString():String { - return _data.name != null ? _data.name : "IkContstraint?"; + return _data.name != null ? _data.name : "IkConstraint?"; } - /** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world - * coordinate system. */ + /** Applies 1 bone IK. The target is specified in the world coordinate system. */ static public function apply1(bone:Bone, targetX:Float, targetY:Float, compress:Bool, stretch:Bool, uniform:Bool, alpha:Float):Void { var p:Bone = bone.parent; var pa:Float = p.a, pb:Float = p.b, pc:Float = p.c, pd:Float = p.d; @@ -164,9 +183,8 @@ class IkConstraint implements Updatable { bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); } - /** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The - * target is specified in the world coordinate system. - * @param child Any descendant bone of the parent. */ + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ static public function apply2(parent:Bone, child:Bone, targetX:Float, targetY:Float, bendDir:Int, stretch:Bool, uniform:Bool, softness:Float, alpha:Float):Void { if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal) return; diff --git a/spine-haxe/spine-haxe/spine/IkConstraintData.hx b/spine-haxe/spine-haxe/spine/IkConstraintData.hx index bf6bd3631..66500381e 100644 --- a/spine-haxe/spine-haxe/spine/IkConstraintData.hx +++ b/spine-haxe/spine-haxe/spine/IkConstraintData.hx @@ -29,14 +29,31 @@ package spine; +/** Stores the setup pose for a spine.IkConstraint. + * + * @see https://esotericsoftware.com/spine-ik-constraints IK constraints in the Spine User Guide */ class IkConstraintData extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ public var bones:Array = new Array(); + /** The bone that is the IK target. */ public var target:BoneData; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. + * + * For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */ public var mix:Float = 0; + /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ public var bendDirection:Int = 0; + /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ public var compress:Bool = false; + /** When true and the target is out of range, the parent bone is scaled to reach it. + * + * For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if softness is + * > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ public var stretch:Bool = false; + /** When true and compress or stretch is used, the bone is scaled on both the X and Y axes. */ public var uniform:Bool = false; + /** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones + * will not straighten completely until the target is this far out of range. */ public var softness:Float = 0; public function new(name:String) { diff --git a/spine-haxe/spine-haxe/spine/Inherit.hx b/spine-haxe/spine-haxe/spine/Inherit.hx index 3485cd3dd..90654c914 100644 --- a/spine-haxe/spine-haxe/spine/Inherit.hx +++ b/spine-haxe/spine-haxe/spine/Inherit.hx @@ -29,6 +29,7 @@ package spine; +/** Determines how a bone inherits world transforms from parent bones. */ class Inherit { public static var normal(default, never):Inherit = new Inherit(0, "normal"); public static var onlyTranslation(default, never):Inherit = new Inherit(1, "onlyTranslation"); diff --git a/spine-haxe/spine-haxe/spine/MathUtils.hx b/spine-haxe/spine-haxe/spine/MathUtils.hx index 0dfaf0826..bb116337f 100644 --- a/spine-haxe/spine-haxe/spine/MathUtils.hx +++ b/spine-haxe/spine-haxe/spine/MathUtils.hx @@ -29,6 +29,9 @@ package spine; +/** + * Various math utility functions. + */ class MathUtils { static public var PI:Float = Math.PI; static public var PI2:Float = Math.PI * 2; @@ -36,18 +39,41 @@ class MathUtils { static public var radDeg:Float = 180 / Math.PI; static public var degRad:Float = Math.PI / 180; + /** + * Returns the cosine in degrees. + * @param degrees The angle in degrees. + * @return The cosine. + */ static public function cosDeg(degrees:Float):Float { return Math.cos(degrees * degRad); } + /** + * Returns the sine in degrees. + * @param degrees The angle in degrees. + * @return The sine. + */ static public function sinDeg(degrees:Float):Float { return Math.sin(degrees * degRad); } + /** + * Returns the arc tangent in degrees. + * @param y The y-coordinate. + * @param x The x-coordinate. + * @return The arc tangent in degrees. + */ static public function atan2Deg (y:Float, x:Float):Float { - return Math.atan2(y, x) * MathUtils.degRad; + return Math.atan2(y, x) * MathUtils.radDeg; } + /** + * Clamps a value between a minimum and maximum value. + * @param value The value to clamp. + * @param min The minimum value. + * @param max The maximum value. + * @return The clamped value. + */ static public function clamp(value:Float, min:Float, max:Float):Float { if (value < min) return min; @@ -56,14 +82,32 @@ class MathUtils { return value; } + /** + * Returns the signum function of the value. + * @param value The value. + * @return -1 if the value is negative, 1 if the value is positive, 0 if the value is zero. + */ static public function signum(value:Float):Float { return value > 0 ? 1 : value < 0 ? -1 : 0; } + /** + * Returns a random number between the specified minimum and maximum values using a triangular distribution. + * @param min The minimum value. + * @param max The maximum value. + * @return A random number using a triangular distribution. + */ static public function randomTriangular(min:Float, max:Float):Float { return randomTriangularWith(min, max, (min + max) * 0.5); } + /** + * Returns a random number between the specified minimum and maximum values using a triangular distribution. + * @param min The minimum value. + * @param max The maximum value. + * @param mode The mode of the triangular distribution. + * @return A random number using a triangular distribution. + */ static public function randomTriangularWith(min:Float, max:Float, mode:Float):Float { var u:Float = Math.random(); var d:Float = max - min; diff --git a/spine-haxe/spine-haxe/spine/PathConstraint.hx b/spine-haxe/spine-haxe/spine/PathConstraint.hx index abf62fd3e..58e700717 100644 --- a/spine-haxe/spine-haxe/spine/PathConstraint.hx +++ b/spine-haxe/spine-haxe/spine/PathConstraint.hx @@ -31,6 +31,10 @@ package spine; import spine.attachments.PathAttachment; +/** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the + * constrained bones so they follow a PathAttachment. + * + * @see https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide */ class PathConstraint implements Updatable { private static inline var NONE:Int = -1; private static inline var BEFORE:Int = -2; @@ -40,11 +44,17 @@ class PathConstraint implements Updatable { private var _data:PathConstraintData; private var _bones:Array; + /** The slot whose path attachment will be used to constrained the bones. */ public var target:Slot; + /** The position along the path. */ public var position:Float = 0; + /** The spacing between bones. */ public var spacing:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ public var mixRotate:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ public var mixX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ public var mixY:Float = 0; private var _spaces(default, never):Array = new Array(); @@ -89,6 +99,7 @@ class PathConstraint implements Updatable { mixY = data.mixY; } + /** Applies the constraint to the constrained bones. */ public function update(physics:Physics):Void { var attachment:PathAttachment = cast(target.attachment, PathAttachment); if (attachment == null) @@ -585,12 +596,14 @@ class PathConstraint implements Updatable { } } + /** The bones that will be modified by this path constraint. */ public var bones(get, never):Array; private function get_bones():Array { return _bones; } + /** The path constraint's setup pose data. */ public var data(get, never):PathConstraintData; private function get_data():PathConstraintData { diff --git a/spine-haxe/spine-haxe/spine/PathConstraintData.hx b/spine-haxe/spine-haxe/spine/PathConstraintData.hx index b123ce24d..333efcfa5 100644 --- a/spine-haxe/spine-haxe/spine/PathConstraintData.hx +++ b/spine-haxe/spine-haxe/spine/PathConstraintData.hx @@ -29,24 +29,39 @@ package spine; +/** Stores the setup pose for a spine.PathConstraint. + * + * @see https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide */ class PathConstraintData extends ConstraintData { + /** The bones that will be modified by this path constraint. */ private var _bones:Array = new Array(); + /** The slot whose path attachment will be used to constrain the bones. */ public var target:SlotData; + /** The mode for positioning the first bone on the path. */ public var positionMode:PositionMode = PositionMode.fixed; + /** The mode for positioning the bones after the first bone on the path. */ public var spacingMode:SpacingMode = SpacingMode.fixed; + /** The mode for adjusting the rotation of the bones. */ public var rotateMode:RotateMode = RotateMode.chain; + /** An offset added to the constrained bone rotation. */ public var offsetRotation:Float = 0; + /** The position along the path. */ public var position:Float = 0; + /** The spacing between bones. */ public var spacing:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ public var mixRotate:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ public var mixX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ public var mixY:Float = 0; public function new(name:String) { super(name, 0, false); } + /** The bones that will be modified by this path constraint. */ public var bones(get, never):Array; private function get_bones():Array { diff --git a/spine-haxe/spine-haxe/spine/Physics.hx b/spine-haxe/spine-haxe/spine/Physics.hx index 76c156152..b179b0ae8 100644 --- a/spine-haxe/spine-haxe/spine/Physics.hx +++ b/spine-haxe/spine-haxe/spine/Physics.hx @@ -29,10 +29,15 @@ package spine; +/** Determines how physics and other non-deterministic updates are applied. */ class Physics { + /** Physics are not updated or applied. */ public static var none(default, never):Physics = new Physics("none"); + /** Physics are reset to the current pose. */ public static var reset(default, never):Physics = new Physics("reset"); + /** Physics are updated and the pose from physics is applied. */ public static var update(default, never):Physics = new Physics("update"); + /** Physics are not updated but the pose from physics is applied. */ public static var pose(default, never):Physics = new Physics("pose"); public static var values:Array = [none, reset, update, pose]; diff --git a/spine-haxe/spine-haxe/spine/PhysicsConstraint.hx b/spine-haxe/spine-haxe/spine/PhysicsConstraint.hx index f8d6ebcba..789418a8e 100644 --- a/spine-haxe/spine-haxe/spine/PhysicsConstraint.hx +++ b/spine-haxe/spine-haxe/spine/PhysicsConstraint.hx @@ -29,6 +29,11 @@ package spine; +/** Stores the current pose for a physics constraint. A physics constraint applies physics to bones. + * + * + * @see https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide + */ class PhysicsConstraint implements Updatable { private var _data:PhysicsConstraintData; private var _bone:Bone = null; @@ -39,6 +44,7 @@ class PhysicsConstraint implements Updatable { public var massInverse:Float = 0; public var wind:Float = 0; public var gravity:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ public var mix:Float = 0; private var _reset:Bool = true; @@ -108,6 +114,7 @@ class PhysicsConstraint implements Updatable { return active; } + /** Applies the constraint to the constrained bones. */ public function update(physics:Physics):Void { var mix:Float = this.mix; if (mix == 0) return; @@ -291,6 +298,8 @@ class PhysicsConstraint implements Updatable { bone.updateAppliedTransform(); } + /** Translates the physics constraint so next update(Physics) forces are applied as if the bone moved an additional + * amount in world space. */ public function translate (x:Float, y:Float):Void { ux -= x; uy -= y; @@ -298,12 +307,15 @@ class PhysicsConstraint implements Updatable { cy -= y; } + /** Rotates the physics constraint so next update(Physics) forces are applied as if the bone rotated around the + * specified point in world space. */ public function rotate (x:Float, y:Float, degrees:Float):Void { var r:Float = degrees * MathUtils.degRad, cos:Float = Math.cos(r), sin:Float = Math.sin(r); var dx:Float = cx - x, dy:Float = cy - y; translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); } + /** The bone constrained by this physics constraint. */ public var bone(get, never):Bone; private function get_bone():Bone { @@ -312,6 +324,7 @@ class PhysicsConstraint implements Updatable { else return _bone; } + /** The physics constraint's setup pose data. */ public var data(get, never):PhysicsConstraintData; private function get_data():PhysicsConstraintData { diff --git a/spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx b/spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx index 16f1aab5d..55c2d2232 100644 --- a/spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx +++ b/spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx @@ -29,7 +29,11 @@ package spine; +/** Stores the setup pose for a PhysicsConstraint. + * + * @see https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide */ class PhysicsConstraintData extends ConstraintData { + /** The bone constrained by this physics constraint. */ public var bone:BoneData; public var x:Float = 0; public var y:Float = 0; @@ -44,6 +48,7 @@ class PhysicsConstraintData extends ConstraintData { public var massInverse:Float = 0; public var wind:Float = 0; public var gravity:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ public var mix:Float = 0; public var inertiaGlobal:Bool = false; public var strengthGlobal:Bool = false; diff --git a/spine-haxe/spine-haxe/spine/Pool.hx b/spine-haxe/spine-haxe/spine/Pool.hx index 81fe45e9d..351155f6a 100644 --- a/spine-haxe/spine-haxe/spine/Pool.hx +++ b/spine-haxe/spine-haxe/spine/Pool.hx @@ -44,6 +44,11 @@ typedef Function = haxe.Constraints.Function; this.instantiator = instantiator; } + /** + * This pool keeps a reference to the obtained instance, so it should be returned to the pool via Pool.free(), + * Pool.freeAll() or clear() to avoid leaking memory. + * @return The obtained instance from the pool or a new instance if the pool is empty. + */ public function obtain():T { return this.items.length > 0 ? this.items.pop() : this.instantiator(); } diff --git a/spine-haxe/spine-haxe/spine/Poolable.hx b/spine-haxe/spine-haxe/spine/Poolable.hx index b7e5730ad..e087bc5a1 100644 --- a/spine-haxe/spine-haxe/spine/Poolable.hx +++ b/spine-haxe/spine-haxe/spine/Poolable.hx @@ -29,6 +29,12 @@ package spine; +/** + * Objects implementing this interface can be reset to prepare them for reuse by an object pool. + */ interface Poolable { + /** + * Resets this object to prepare it for reuse by an object pool. + */ function reset():Void; } diff --git a/spine-haxe/spine-haxe/spine/PositionMode.hx b/spine-haxe/spine-haxe/spine/PositionMode.hx index b45030ab2..4206cbbc3 100644 --- a/spine-haxe/spine-haxe/spine/PositionMode.hx +++ b/spine-haxe/spine-haxe/spine/PositionMode.hx @@ -29,6 +29,11 @@ package spine; +/** + * Controls how the first bone is positioned along the path. + * + * @see https://esotericsoftware.com/spine-path-constraints#Position-mode Position mode in the Spine User Guide + */ class PositionMode { public static var fixed(default, never):PositionMode = new PositionMode("fixed"); public static var percent(default, never):PositionMode = new PositionMode("percent"); diff --git a/spine-haxe/spine-haxe/spine/RotateMode.hx b/spine-haxe/spine-haxe/spine/RotateMode.hx index bb620a4fa..6bc2aae42 100644 --- a/spine-haxe/spine-haxe/spine/RotateMode.hx +++ b/spine-haxe/spine-haxe/spine/RotateMode.hx @@ -29,9 +29,14 @@ package spine; +/** Controls how bones are rotated, translated, and scaled to match the path. + * + * @see https://esotericsoftware.com/spine-path-constraints#Rotate-mode Rotate mode in the Spine User Guide */ class RotateMode { public static var tangent(default, never):RotateMode = new RotateMode("tangent"); public static var chain(default, never):RotateMode = new RotateMode("chain"); + /** When chain scale, constrained bones should all have the same parent. That way when the path constraint scales a bone, it + * doesn't affect other constrained bones. */ public static var chainScale(default, never):RotateMode = new RotateMode("chainScale"); public static var values(default, never):Array = [tangent, chain, chainScale]; diff --git a/spine-haxe/spine-haxe/spine/Sequence.hx b/spine-haxe/spine-haxe/spine/Sequence.hx index 35f8ea5ae..4646c16a4 100644 --- a/spine-haxe/spine-haxe/spine/Sequence.hx +++ b/spine-haxe/spine-haxe/spine/Sequence.hx @@ -29,9 +29,11 @@ package spine; +/** A sequence for an attachment with multiple texture regions, which can be used for animation. */ class Sequence { private static var _nextID = 0; + /** Returns a unique ID for this attachment. */ public var id = _nextID++; public var regions:Array; public var start = 0; @@ -45,6 +47,7 @@ class Sequence { this.regions.resize(count); } + /** Copy constructor. */ public function copy():Sequence { var copy = new Sequence(this.regions.length); for (i in 0...this.regions.length) { diff --git a/spine-haxe/spine-haxe/spine/SequenceMode.hx b/spine-haxe/spine-haxe/spine/SequenceMode.hx index 6a8960a81..8ea02336d 100644 --- a/spine-haxe/spine-haxe/spine/SequenceMode.hx +++ b/spine-haxe/spine-haxe/spine/SequenceMode.hx @@ -29,6 +29,9 @@ package spine; +/** + * Defines how a Sequence is played. + */ class SequenceMode { public static var hold(default, never):SequenceMode = new SequenceMode("hold", 0); public static var once(default, never):SequenceMode = new SequenceMode("once", 1); diff --git a/spine-haxe/spine-haxe/spine/Skeleton.hx b/spine-haxe/spine-haxe/spine/Skeleton.hx index 07a06e505..2f543143d 100644 --- a/spine-haxe/spine-haxe/spine/Skeleton.hx +++ b/spine-haxe/spine-haxe/spine/Skeleton.hx @@ -37,33 +37,61 @@ import spine.attachments.MeshAttachment; import spine.attachments.PathAttachment; import spine.attachments.RegionAttachment; +/** Stores the current pose for a skeleton. + * + * @see https://esotericsoftware.com/spine-runtime-architecture#Instance-objects Instance objects in the Spine Runtimes Guide + */ class Skeleton { private static var quadTriangles:Array = [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; + /** The skeleton's slots. */ public var slots:Array; // 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; + /** The skeleton's IK constraints. */ public var ikConstraints:Array; + /** The skeleton's transform constraints. */ public var transformConstraints:Array; + /** The skeleton's path constraints. */ public var pathConstraints:Array; + /** The skeleton's physics constraints. */ public var physicsConstraints:Array; private var _updateCache:Array = new Array(); private var _skin:Skin; + /** 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. */ public var scaleX:Float = 1; + /** Scales the entire skeleton on the Y axis. + * + * 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; } + /** Sets the skeleton X position, which is added to the root bone worldX position. + * + * 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(). */ public var time:Float = 0; + /** Creates a new skeleton with the specified skeleton data. */ public function new(data:SkeletonData) { if (data == null) { throw new SpineException("data cannot be null."); @@ -115,8 +143,8 @@ class Skeleton { updateCache(); } - /** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are - * added or removed. */ + /** Caches information about bones and constraints. Must be called if the Skeleton.skin is modified or if bones, + * constraints, or weighted path attachments are added or removed. */ public function updateCache():Void { _updateCache.resize(0); @@ -350,7 +378,10 @@ class Skeleton { } } - /** Updates the world transform for each bone and applies constraints. */ + /** Updates the world transform for each bone and applies all constraints. + * + * @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"); for (bone in bones) { @@ -368,6 +399,11 @@ class Skeleton { } } + /** Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies + * all constraints. + * + * @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide + */ public function updateWorldTransformWith(physics:Physics, parent:Bone):Void { // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. var rootBone:Bone = rootBone; @@ -396,7 +432,7 @@ class Skeleton { } } - /** Sets the bones, constraints, and slots to their setup pose values. */ + /** Sets the bones, constraints, slots, and draw order to their setup pose values. */ public function setToSetupPose():Void { setBonesToSetupPose(); setSlotsToSetupPose(); @@ -411,6 +447,7 @@ class Skeleton { for (constraint in this.physicsConstraints) constraint.setToSetupPose(); } + /** Sets the slots and draw order to their setup pose values. */ public function setSlotsToSetupPose():Void { var i:Int = 0; for (slot in slots) { @@ -419,18 +456,21 @@ class Skeleton { } } + /** The skeleton's setup pose data. */ public var data(get, never):SkeletonData; private function get_data():SkeletonData { return _data; } + /** The list of bones and constraints, sorted in the order they should be updated, as computed by Skeleton.updateCache(). */ public var getUpdateCache(get, never):Array; private function get_getUpdateCache():Array { return _updateCache; } + /** Returns the root bone, or null if the skeleton has no bones. */ public var rootBone(get, never):Bone; private function get_rootBone():Bone { @@ -439,7 +479,8 @@ class Skeleton { return bones[0]; } - /** @return May be null. */ + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * repeatedly. */ public function findBone(boneName:String):Bone { if (boneName == null) { throw new SpineException("boneName cannot be null."); @@ -465,7 +506,8 @@ class Skeleton { return -1; } - /** @return May be null. */ + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. */ public function findSlot(slotName:String):Slot { if (slotName == null) { throw new SpineException("slotName cannot be null."); @@ -477,8 +519,12 @@ class Skeleton { return null; } + /** The skeleton's current skin. */ public var skinName(get, set):String; + /** Sets a skin by name. + * + * See Skeleton.skin. */ private function set_skinName(skinName:String):String { var skin:Skin = data.findSkin(skinName); if (skin == null) @@ -492,16 +538,23 @@ class Skeleton { return _skin == null ? null : _skin.name; } + /** The skeleton's current skin. */ public var skin(get, set):Skin; private function get_skin():Skin { return _skin; } - /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. - * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was - * no old skin, each slot's setup mode attachment is attached from the new skin. - * @param newSkin May be null. */ + /** Sets the skin used to look up attachments before looking in the spine.SkeletonData default skin. If the + * skin is changed, Skeleton.updateCache() is called. + * + * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no + * old skin, each slot's setup mode attachment is attached from the new skin. + * + * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + * Skeleton.setSlotsToSetupPose(). Also, often spine.AnimationState.apply() is called before the next time the + * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new + * skin. */ private function set_skin(newSkin:Skin):Skin { if (newSkin == _skin) return null; @@ -526,12 +579,19 @@ class Skeleton { return _skin; } - /** @return May be null. */ + /** Finds an attachment by looking in the Skeleton.skin and spine.SkeletonData defaultSkin using the slot name and attachment + * name. + * + * See Skeleton.getAttachmentForSlotIndex(). */ public function getAttachmentForSlotName(slotName:String, attachmentName:String):Attachment { return getAttachmentForSlotIndex(data.findSlot(slotName).index, attachmentName); } - /** @return May be null. */ + /** Finds an attachment by looking in the Skeleton.skin and spine.SkeletonData defaultSkin using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * @see https://esotericsoftware.com/spine-runtime-skins Runtime skins in the Spine Runtimes Guide + */ public function getAttachmentForSlotIndex(slotIndex:Int, attachmentName:String):Attachment { if (attachmentName == null) throw new SpineException("attachmentName cannot be null."); @@ -545,7 +605,9 @@ class Skeleton { return null; } - /** @param attachmentName May be null. */ + /** A convenience method to set an attachment by finding the slot with Skeleton.findSlot(), finding the attachment with + * Skeleton.getAttachmentForSlotIndex(), then setting the slot's spine.Slot attachment. + * @param attachmentName May be null to clear the slot's attachment. */ public function setAttachment(slotName:String, attachmentName:String):Void { if (slotName == null) throw new SpineException("slotName cannot be null."); @@ -567,7 +629,8 @@ class Skeleton { throw new SpineException("Slot not found: " + slotName); } - /** @return May be null. */ + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. */ public function findIkConstraint(constraintName:String):IkConstraint { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -578,7 +641,8 @@ class Skeleton { return null; } - /** @return May be null. */ + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it repeatedly. */ public function findTransformConstraint(constraintName:String):TransformConstraint { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -589,7 +653,8 @@ class Skeleton { return null; } - /** @return May be null. */ + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. */ public function findPathConstraint(constraintName:String):PathConstraint { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -600,7 +665,8 @@ class Skeleton { return null; } - /** @return May be null. */ + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this + * method than to call it repeatedly. */ public function findPhysicsConstraint(constraintName:String):PhysicsConstraint { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -618,6 +684,8 @@ class Skeleton { private var _tempVertices = new Array(); private var _bounds = new Rectangle(); + /** 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 { var minX:Float = Math.POSITIVE_INFINITY; var minY:Float = Math.POSITIVE_INFINITY; @@ -674,15 +742,18 @@ class Skeleton { return _bounds; } + /** Increments the skeleton's Skeleton.time. */ public function update (delta:Float):Void { time += delta; } + /** Calls spine.PhysicsConstraint.translate() for each physics constraint. */ 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 { for (physicsConstraint in physicsConstraints) physicsConstraint.rotate(x, y, degrees); diff --git a/spine-haxe/spine-haxe/spine/SkeletonBinary.hx b/spine-haxe/spine-haxe/spine/SkeletonBinary.hx index 74e88d7e7..00489902e 100644 --- a/spine-haxe/spine-haxe/spine/SkeletonBinary.hx +++ b/spine-haxe/spine-haxe/spine/SkeletonBinary.hx @@ -82,6 +82,12 @@ import spine.attachments.PointAttachment; import spine.attachments.RegionAttachment; import spine.attachments.VertexAttachment; +/** + * Loads skeleton data in the Spine binary format. + * + * @see https://esotericsoftware.com/spine-binary-format Spine binary format + * @see https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data JSON and binary data in the Spine Runtimes Guide + */ class SkeletonBinary { public var attachmentLoader:AttachmentLoader; public var scale:Float = 1; diff --git a/spine-haxe/spine-haxe/spine/SkeletonClipping.hx b/spine-haxe/spine-haxe/spine/SkeletonClipping.hx index 1c8734e11..dc259c923 100644 --- a/spine-haxe/spine-haxe/spine/SkeletonClipping.hx +++ b/spine-haxe/spine-haxe/spine/SkeletonClipping.hx @@ -274,8 +274,10 @@ class SkeletonClipping { } } - /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping - * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + /** + * Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. + */ public function clip(x1:Float, y1:Float, x2:Float, y2:Float, x3:Float, y3:Float, clippingArea:Array, output:Array):Bool { var originalOutput:Array = output; var clipped:Bool = false; diff --git a/spine-haxe/spine-haxe/spine/SkeletonData.hx b/spine-haxe/spine-haxe/spine/SkeletonData.hx index 94d95868d..f92ebe4a2 100644 --- a/spine-haxe/spine-haxe/spine/SkeletonData.hx +++ b/spine-haxe/spine-haxe/spine/SkeletonData.hx @@ -35,29 +35,58 @@ import spine.animation.Animation; import spine.atlas.TextureAtlas; import spine.attachments.AtlasAttachmentLoader; +/** Stores the setup pose and all of the stateless data for a skeleton. + * + * + * @see https://esotericsoftware.com/spine-runtime-architecture#Data-objects Data objects in the Spine Runtimes + * Guide. */ class SkeletonData { - /** May be null. */ + /** The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been + * set. */ public var name:String; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ public var bones:Array = new Array(); // Ordered parents first. + /** The skeleton's slots in the setup pose draw order. */ public var slots:Array = new Array(); // Setup pose draw order. + /** All skins, including the default skin. */ public var skins:Array = new Array(); + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See Skeleton#getAttachment(int, String). */ public var defaultSkin:Skin; + /** The skeleton's events. */ public var events:Array = new Array(); + /** The skeleton's animations. */ public var animations:Array = new Array(); + /** The skeleton's IK constraints. */ public var ikConstraints:Array = new Array(); + /** The skeleton's transform constraints. */ public var transformConstraints:Array = new Array(); + /** The skeleton's path constraints. */ public var pathConstraints:Array = new Array(); + /** The skeleton's physics constraints. */ public var physicsConstraints:Array = new Array(); + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ public var x:Float = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ public var y:Float = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ public var width:Float = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ public var height:Float = 0; + /** Baseline scale factor for applying physics and other effects based on distance to non-scalable properties, such as angle or + * scale. Default is 100. */ public var referenceScale:Float = 100; + /** The Spine version used to export the skeleton data, or null. */ public var version:String; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. */ public var hash:String; + /** The dopesheet FPS in Spine, or zero if nonessential data was not exported. */ public var fps:Float = 0; + /** The path to the images directory as defined in Spine, or null if nonessential data was not exported. */ public var imagesPath:String; + /** The path to the audio directory as defined in Spine, or null if nonessential data was not exported. */ public var audioPath:String; public static function from(data:Dynamic, atlas:TextureAtlas, scale:Float = 1.0):SkeletonData { @@ -78,7 +107,10 @@ class SkeletonData { // --- Bones. - /** @return May be null. */ + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @param boneName The name of the bone to find. + * @return May be null. */ public function findBone(boneName:String):BoneData { if (boneName == null) throw new SpineException("boneName cannot be null."); @@ -90,7 +122,9 @@ class SkeletonData { return null; } - /** @return -1 if the bone was not found. */ + /** Finds the index of a bone by comparing each bone's name. + * @param boneName The name of the bone to find. + * @return -1 if the bone was not found. */ public function findBoneIndex(boneName:String):Int { if (boneName == null) throw new SpineException("boneName cannot be null."); @@ -103,7 +137,10 @@ class SkeletonData { // --- Slots. - /** @return May be null. */ + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @param slotName The name of the slot to find. + * @return May be null. */ public function findSlot(slotName:String):SlotData { if (slotName == null) throw new SpineException("slotName cannot be null."); @@ -117,7 +154,10 @@ class SkeletonData { // --- Skins. - /** @return May be null. */ + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @param skinName The name of the skin to find. + * @return May be null. */ public function findSkin(skinName:String):Skin { if (skinName == null) throw new SpineException("skinName cannot be null."); @@ -130,7 +170,10 @@ class SkeletonData { // --- Events. - /** @return May be null. */ + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @param eventName The name of the event to find. + * @return May be null. */ public function findEvent(eventName:String):EventData { if (eventName == null) throw new SpineException("eventName cannot be null."); @@ -143,7 +186,10 @@ class SkeletonData { // --- Animations. - /** @return May be null. */ + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @param animationName The name of the animation to find. + * @return May be null. */ public function findAnimation(animationName:String):Animation { if (animationName == null) throw new SpineException("animationName cannot be null."); @@ -156,7 +202,10 @@ class SkeletonData { // --- IK constraints. - /** @return May be null. */ + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @param constraintName The name of the IK constraint to find. + * @return May be null. */ public function findIkConstraint(constraintName:String):IkConstraintData { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -169,7 +218,10 @@ class SkeletonData { // --- Transform constraints. - /** @return May be null. */ + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it multiple times. + * @param constraintName The name of the transform constraint to find. + * @return May be null. */ public function findTransformConstraint(constraintName:String):TransformConstraintData { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -180,7 +232,9 @@ class SkeletonData { return null; } - /** @return -1 if the transform constraint was not found. */ + /** Finds the index of a transform constraint by comparing each transform constraint's name. + * @param transformConstraintName The name of the transform constraint to find. + * @return -1 if the transform constraint was not found. */ public function findTransformConstraintIndex(transformConstraintName:String):Int { if (transformConstraintName == null) throw new SpineException("transformConstraintName cannot be null."); @@ -193,7 +247,10 @@ class SkeletonData { // --- Path constraints. - /** @return May be null. */ + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @param constraintName The name of the path constraint to find. + * @return May be null. */ public function findPathConstraint(constraintName:String):PathConstraintData { if (constraintName == null) throw new SpineException("constraintName cannot be null."); @@ -205,7 +262,9 @@ class SkeletonData { return null; } - /** @return -1 if the path constraint was not found. */ + /** Finds the index of a path constraint by comparing each path constraint's name. + * @param pathConstraintName The name of the path constraint to find. + * @return -1 if the path constraint was not found. */ public function findPathConstraintIndex(pathConstraintName:String):Int { if (pathConstraintName == null) throw new SpineException("pathConstraintName cannot be null."); @@ -218,10 +277,13 @@ class SkeletonData { // --- Physics constraints. - /** @return May be null. */ + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this + * method than to call it multiple times. + * @param constraintName The name of the physics constraint to find. + * @return May be null. */ public function findPhysicsConstraint(constraintName:String):PhysicsConstraintData { if (constraintName == null) - throw new SpineException("physicsConstraintName cannot be null."); + throw new SpineException("constraintName cannot be null."); for (i in 0...physicsConstraints.length) { var constraint:PhysicsConstraintData = physicsConstraints[i]; if (constraint.name == constraintName) @@ -230,7 +292,9 @@ class SkeletonData { return null; } - /** @return -1 if the path constraint was not found. */ + /** Finds the index of a physics constraint by comparing each physics constraint's name. + * @param constraintName The name of the physics constraint to find. + * @return -1 if the physics constraint was not found. */ public function findPhysicsConstraintIndex(constraintName:String):Int { if (constraintName == null) throw new SpineException("constraintName cannot be null."); diff --git a/spine-haxe/spine-haxe/spine/Skin.hx b/spine-haxe/spine-haxe/spine/Skin.hx index 9941aeb22..d04f31729 100644 --- a/spine-haxe/spine-haxe/spine/Skin.hx +++ b/spine-haxe/spine-haxe/spine/Skin.hx @@ -33,7 +33,10 @@ import haxe.ds.StringMap; import spine.attachments.Attachment; import spine.attachments.MeshAttachment; -/** Stores attachments by slot index and attachment name. */ +/** Stores attachments by slot index and attachment name. + * + * See spine.SkeletonData.defaultSkin, spine.Skeleton.skin, and + * Runtime skins at https://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. */ class Skin { private var _name:String; private var _attachments:Array> = new Array>(); @@ -47,6 +50,7 @@ class Skin { _name = name; } + /** Adds an attachment to the skin for the specified slot index and name. */ public function setAttachment(slotIndex:Int, name:String, attachment:Attachment):Void { if (attachment == null) throw new SpineException("attachment cannot be null."); @@ -57,6 +61,7 @@ class Skin { _attachments[slotIndex].set(name, attachment); } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ public function addSkin(skin:Skin):Void { var contained:Bool = false; for (i in 0...skin.bones.length) { @@ -92,6 +97,8 @@ class Skin { } } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ public function copySkin(skin:Skin):Void { var contained:Bool = false; var attachment:SkinEntry; @@ -138,6 +145,7 @@ class Skin { } } + /** Returns the attachment for the specified slot index and name, or null. */ public function getAttachment(slotIndex:Int, name:String):Attachment { if (slotIndex >= _attachments.length) return null; @@ -145,12 +153,14 @@ class Skin { return dictionary != null ? dictionary.get(name) : null; } + /** Removes the attachment in the skin for the specified slot index and name, if any. */ public function removeAttachment(slotIndex:Int, name:String):Void { var dictionary:StringMap = _attachments[slotIndex]; if (dictionary != null) dictionary.remove(name); } + /** Returns all attachments in this skin. */ public function getAttachments():Array { var entries:Array = new Array(); for (slotIndex in 0..._attachments.length) { @@ -166,6 +176,7 @@ class Skin { return entries; } + /** Returns all attachments in this skin for the specified slot index. */ public function getAttachmentsForSlot(slotIndex:Int):Array { var entries:Array = new Array(); var attachments:StringMap = _attachments[slotIndex]; @@ -179,6 +190,7 @@ class Skin { return entries; } + /** Clears all attachments, bones, and constraints. */ public function clear():Void { _attachments.resize(0); _bones.resize(0); @@ -203,12 +215,14 @@ class Skin { return _constraints; } + /** The skin's name, which is unique across all skins in the skeleton. */ public var name(get, never):String; private function get_name():String { return _name; } + /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ public var color(get, never):Color; private function get_color():Color { diff --git a/spine-haxe/spine-haxe/spine/SkinEntry.hx b/spine-haxe/spine-haxe/spine/SkinEntry.hx index 2e63e2e41..e32083104 100644 --- a/spine-haxe/spine-haxe/spine/SkinEntry.hx +++ b/spine-haxe/spine-haxe/spine/SkinEntry.hx @@ -31,8 +31,10 @@ package spine; import spine.attachments.Attachment; +/** Stores an entry in the skin consisting of the slot index and the attachment name. */ class SkinEntry { public var slotIndex:Int = 0; + /** The name the attachment is associated with, equivalent to the skin placeholder name in the Spine editor. */ public var name:String; public var attachment:Attachment; diff --git a/spine-haxe/spine-haxe/spine/Slot.hx b/spine-haxe/spine-haxe/spine/Slot.hx index a0624b0e0..3f4e0eee5 100644 --- a/spine-haxe/spine-haxe/spine/Slot.hx +++ b/spine-haxe/spine-haxe/spine/Slot.hx @@ -32,20 +32,34 @@ package spine; import spine.attachments.Attachment; import spine.attachments.VertexAttachment; +/** Stores a slot's current pose. Slots organize attachments for Skeleton.drawOrder purposes and provide a place to store + * state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared + * across multiple skeletons. */ class Slot { private var _data:SlotData; private var _bone:Bone; + /** The color used to tint the slot's attachment. If darkColor is set, this is used as the light color for two + * color tinting. */ public var color:Color; + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ public var darkColor:Color; private var _attachment:Attachment; + /** The index of the texture region to display when the slot's attachment has a spine.attachments.Sequence. -1 represents the + * Sequence.getSetupIndex(). */ public var sequenceIndex = -1; public var attachmentState:Int = 0; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * @see spine.attachments.VertexAttachment.computeWorldVertices() + * @see spine.animation.DeformTimeline */ public var deform:Array = new Array(); + /** Copy constructor. */ public function new(data:SlotData, bone:Bone) { if (data == null) throw new SpineException("data cannot be null."); @@ -58,34 +72,37 @@ class Slot { setToSetupPose(); } + /** The slot's setup pose data. */ public var data(get, never):SlotData; private function get_data():SlotData { return _data; } + /** The bone this slot belongs to. */ public var bone(get, never):Bone; private function get_bone():Bone { return _bone; } + /** The skeleton this slot belongs to. */ public var skeleton(get, never):Skeleton; private function get_skeleton():Skeleton { return _bone.skeleton; } - /** @return May be null. */ + /** The current attachment for the slot, or null if the slot has no attachment. */ public var attachment(get, set):Attachment; private function get_attachment():Attachment { return _attachment; } - /** Sets the slot's attachment and, if the attachment changed, resets {@link #attachmentTime} and clears the {@link #deform}. - * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getDeformAttachment()} as the specified attachment. - * @param attachment May be null. */ + /** Sets the slot's attachment and, if the attachment changed, resets sequenceIndex and clears the deform. + * The deform is not cleared if the old attachment has the same spine.attachments.VertexAttachment.timelineAttachment as the + * specified attachment. */ public function set_attachment(attachmentNew:Attachment):Attachment { if (attachment == attachmentNew) return attachmentNew; @@ -99,6 +116,7 @@ class Slot { return attachmentNew; } + /** Sets this slot to the setup pose. */ public function setToSetupPose():Void { color.setFromColor(data.color); if (darkColor != null) diff --git a/spine-haxe/spine-haxe/spine/SlotData.hx b/spine-haxe/spine-haxe/spine/SlotData.hx index 64dd62241..d968564bd 100644 --- a/spine-haxe/spine-haxe/spine/SlotData.hx +++ b/spine-haxe/spine-haxe/spine/SlotData.hx @@ -29,15 +29,23 @@ package spine; +/** Stores the setup pose for a spine.Slot. */ class SlotData { private var _index:Int; private var _name:String; private var _boneData:BoneData; + /** The color used to tint the slot's attachment. If SlotData.darkColor is set, this is used as the light color for two + * color tinting. */ public var color:Color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ public var darkColor:Color = null; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ public var attachmentName:String; + /** The blend mode for drawing the slot's attachment. */ public var blendMode:BlendMode = BlendMode.normal; + /** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ public var visible:Bool = true; public function new(index:Int, name:String, boneData:BoneData) { @@ -52,18 +60,21 @@ class SlotData { _boneData = boneData; } + /** The index of the slot in spine.Skeleton.getSlots(). */ public var index(get, never):Int; private function get_index():Int { return _index; } + /** The name of the slot, which is unique across all slots in the skeleton. */ public var name(get, never):String; private function get_name():String { return _name; } + /** The bone this slot belongs to. */ public var boneData(get, never):BoneData; private function get_boneData():BoneData { diff --git a/spine-haxe/spine-haxe/spine/SpacingMode.hx b/spine-haxe/spine-haxe/spine/SpacingMode.hx index a4f420a44..0a0d6df02 100644 --- a/spine-haxe/spine-haxe/spine/SpacingMode.hx +++ b/spine-haxe/spine-haxe/spine/SpacingMode.hx @@ -29,6 +29,9 @@ package spine; +/** Controls how bones after the first bone are positioned along the path. + * + * @see https://esotericsoftware.com/spine-path-constraints#Spacing-mode Spacing mode in the Spine User Guide */ class SpacingMode { public static var length(default, never):SpacingMode = new SpacingMode("length"); public static var fixed(default, never):SpacingMode = new SpacingMode("fixed"); diff --git a/spine-haxe/spine-haxe/spine/TransformConstraint.hx b/spine-haxe/spine-haxe/spine/TransformConstraint.hx index c563fa639..c8c3edaa0 100644 --- a/spine-haxe/spine-haxe/spine/TransformConstraint.hx +++ b/spine-haxe/spine-haxe/spine/TransformConstraint.hx @@ -29,22 +29,34 @@ package spine; +/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained + * bones to match that of the target bone. + * + * @see https://esotericsoftware.com/spine-transform-constraints Transform constraints in the Spine User Guide */ class TransformConstraint implements Updatable { private var _data:TransformConstraintData; private var _bones:Array; + /** The target bone whose world transform will be copied to the constrained bones. */ public var target:Bone; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ public var mixRotate:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ public var mixX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ public var mixY:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ public var mixScaleX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */ public var mixScaleY:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */ public var mixShearY:Float = 0; private var _temp:Array = new Array(); public var active:Bool = false; + /** Copy constructor. */ public function new(data:TransformConstraintData, skeleton:Skeleton) { if (data == null) throw new SpineException("data cannot be null."); @@ -80,6 +92,7 @@ class TransformConstraint implements Updatable { mixShearY = data.mixShearY; } + /** Applies the constraint to the constrained bones. */ public function update(physics:Physics):Void { if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return; @@ -271,12 +284,14 @@ class TransformConstraint implements Updatable { } } + /** The transform constraint's setup pose data. */ public var data(get, never):TransformConstraintData; private function get_data():TransformConstraintData { return _data; } + /** The bones that will be modified by this transform constraint. */ public var bones(get, never):Array; private function get_bones():Array { diff --git a/spine-haxe/spine-haxe/spine/TransformConstraintData.hx b/spine-haxe/spine-haxe/spine/TransformConstraintData.hx index 2ab023349..48d61addf 100644 --- a/spine-haxe/spine-haxe/spine/TransformConstraintData.hx +++ b/spine-haxe/spine-haxe/spine/TransformConstraintData.hx @@ -29,21 +29,40 @@ package spine; +/** + * Stores the setup pose for a spine.TransformConstraint. + * + * + * @see https://esotericsoftware.com/spine-transform-constraints Transform constraints in the Spine User Guide + */ class TransformConstraintData extends ConstraintData { private var _bones:Array = new Array(); + /** The target bone whose world transform will be copied to the constrained bones. */ public var target:BoneData; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ public var mixRotate:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ public var mixX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ public var mixY:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ public var mixScaleX:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */ public var mixScaleY:Float = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */ public var mixShearY:Float = 0; + /** An offset added to the constrained bone rotation. */ public var offsetRotation:Float = 0; + /** An offset added to the constrained bone X translation. */ public var offsetX:Float = 0; + /** An offset added to the constrained bone Y translation. */ public var offsetY:Float = 0; + /** An offset added to the constrained bone scaleX. */ public var offsetScaleX:Float = 0; + /** An offset added to the constrained bone scaleY. */ public var offsetScaleY:Float = 0; + /** An offset added to the constrained bone shearY. */ public var offsetShearY:Float = 0; public var relative:Bool = false; public var local:Bool = false; @@ -52,6 +71,9 @@ class TransformConstraintData extends ConstraintData { super(name, 0, false); } + /** + * The bones that will be modified by this transform constraint. + */ public var bones(get, never):Array; private function get_bones():Array { diff --git a/spine-haxe/spine-haxe/spine/Triangulator.hx b/spine-haxe/spine-haxe/spine/Triangulator.hx index bdb659395..5e31f4e75 100644 --- a/spine-haxe/spine-haxe/spine/Triangulator.hx +++ b/spine-haxe/spine-haxe/spine/Triangulator.hx @@ -44,6 +44,11 @@ class Triangulator { public function new() {} + /** + * Triangulates a convex or concave polygon. + * @param vertices List of polygon vertices in x,y order. + * @return Indices of triangle vertices in clockwise order. + */ public function triangulate(vertices:Array):Array { var vertexCount:Int = vertices.length >> 1; @@ -129,6 +134,12 @@ class Triangulator { return triangles; } + /** + * Decomposes a polygon into convex polygons. + * @param vertices List of polygon vertices in x,y order. + * @param triangles Indices of triangle vertices in clockwise order. + * @return List of convex polygons. + */ public function decompose(vertices:Array, triangles:Array):Array> { for (i in 0...convexPolygons.length) { this.polygonPool.free(convexPolygons[i]); diff --git a/spine-haxe/spine-haxe/spine/Updatable.hx b/spine-haxe/spine-haxe/spine/Updatable.hx index 227a79aba..c33a7ea0e 100644 --- a/spine-haxe/spine-haxe/spine/Updatable.hx +++ b/spine-haxe/spine-haxe/spine/Updatable.hx @@ -29,8 +29,17 @@ package spine; +/** The interface for items updated by spine.Skeleton.updateWorldTransform(). */ interface Updatable { + /** @param physics Determines how physics and other non-deterministic updates are applied. */ function update(physics:Physics):Void; + /** Returns false when this item won't be updated by + * spine.Skeleton.updateWorldTransform() because a skin is required and the + * active skin does not contain this item. + * @see spine.Skin.getBones() + * @see spine.Skin.getConstraints() + * @see spine.BoneData.getSkinRequired() + * @see spine.ConstraintData.getSkinRequired() */ function isActive():Bool; } diff --git a/spine-haxe/spine-haxe/spine/animation/AlphaTimeline.hx b/spine-haxe/spine-haxe/spine/animation/AlphaTimeline.hx index 9a51497f0..699a487fc 100644 --- a/spine-haxe/spine-haxe/spine/animation/AlphaTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/AlphaTimeline.hx @@ -33,6 +33,7 @@ import spine.Event; import spine.Skeleton; import spine.Slot; +/** Changes the alpha for a slot's spine.Slot.color. */ class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { private static inline var ENTRIES:Int = 4; private static inline var R:Float = 1; diff --git a/spine-haxe/spine-haxe/spine/animation/Animation.hx b/spine-haxe/spine-haxe/spine/animation/Animation.hx index 98fcc0919..0d43f9a5d 100644 --- a/spine-haxe/spine-haxe/spine/animation/Animation.hx +++ b/spine-haxe/spine-haxe/spine/animation/Animation.hx @@ -33,11 +33,14 @@ import haxe.ds.StringMap; import spine.Event; import spine.Skeleton; +/** Stores a list of timelines to animate a skeleton's pose over time. */ class Animation { private var _name:String; private var _timelines:Array; private var _timelineIds:StringMap = new StringMap(); + /** The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is + * used to know when it has completed and when it should loop back to the start. */ public var duration:Float = 0; public function new(name:String, timelines:Array, duration:Float) { @@ -61,6 +64,7 @@ class Animation { } } + /** Returns true if this animation contains a timeline with any of the specified property IDs. */ public function hasTimeline(ids:Array):Bool { for (id in ids) { if (_timelineIds.exists(id)) @@ -69,7 +73,26 @@ class Animation { return false; } - /** Poses the skeleton at the specified time for this animation. */ + /** Applies the animation's timelines to the specified skeleton. + * + * See Timeline.apply(). + * @param skeleton The skeleton the animation is being applied to. This provides access to the bones, slots, and other skeleton + * components the timelines may change. + * @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at specific times rather + * than every frame. Pass -1 the first time an animation is applied to ensure frame 0 is triggered. + * @param time The time in seconds the skeleton is being posed for. Most timelines find the frame before and the frame after + * this time and interpolate between the frame values. If beyond the duration and loop is + * true then the animation will repeat, else the last frame will be applied. + * @param loop If true, the animation repeats after the duration. + * @param events If any events are fired, they are added to this list. Can be null to ignore fired events or if no timelines + * fire events. + * @param alpha 0 applies the current or setup values (depending on blend). 1 applies the timeline values. Between + * 0 and 1 applies values between the current or setup values and the timeline values. By adjusting + * alpha over time, an animation can be mixed in or out. alpha can also be useful to apply + * animations on top of each other (layering). + * @param blend Controls how mixing is applied when alpha < 1. + * @param direction Indicates whether the timelines are mixing in or out. Used by timelines which perform instant transitions, + * such as DrawOrderTimeline or AttachmentTimeline. */ public function apply(skeleton:Skeleton, lastTime:Float, time:Float, loop:Bool, events:Array, alpha:Float, blend:MixBlend, direction:MixDirection):Void { if (skeleton == null) @@ -86,6 +109,7 @@ class Animation { } } + /** The animation's name, which is unique across all animations in the skeleton. */ public var name(get, never):String; private function get_name():String { @@ -96,6 +120,7 @@ class Animation { return _name; } + /** If the returned array or the timelines it contains are modified, setTimelines() must be called. */ public var timelines(get, never):Array; private function get_timelines():Array { diff --git a/spine-haxe/spine-haxe/spine/animation/AnimationState.hx b/spine-haxe/spine-haxe/spine/animation/AnimationState.hx index 9e89555df..b37757450 100644 --- a/spine-haxe/spine-haxe/spine/animation/AnimationState.hx +++ b/spine-haxe/spine-haxe/spine/animation/AnimationState.hx @@ -35,11 +35,52 @@ import spine.Event; import spine.Pool; import spine.Skeleton; +/** + * Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies + * multiple animations on top of each other (layering). + * + * @see https://esotericsoftware.com/spine-applying-animations/ Applying Animations in the Spine Runtimes Guide + */ class AnimationState { + /** + * 1) A previously applied timeline has set this property. + * Result: Mix from the current pose to the timeline pose. + */ public static inline var SUBSEQUENT:Int = 0; + /** + * 1) This is the first timeline to set this property. + * 2) The next track entry applied after this one does not have a timeline to set this property. + * Result: Mix from the setup pose to the timeline pose. + */ public static inline var FIRST:Int = 1; + /** + * 1) A previously applied timeline has set this property. + * 2) The next track entry to be applied does have a timeline to set this property. + * 3) The next track entry after that one does not have a timeline to set this property. + * Result: Mix from the current pose to the timeline pose, but do not mix out. This avoids "dipping" when crossfading + * animations that key the same property. A subsequent timeline will set this property using a mix. + */ public static inline var HOLD_SUBSEQUENT:Int = 2; + /** + * 1) This is the first timeline to set this property. + * 2) The next track entry to be applied does have a timeline to set this property. + * 3) The next track entry after that one does not have a timeline to set this property. + * Result: Mix from the setup pose to the timeline pose, but do not mix out. This avoids "dipping" when crossfading animations + * that key the same property. A subsequent timeline will set this property using a mix. + */ public static inline var HOLD_FIRST:Int = 3; + /** + * 1) This is the first timeline to set this property. + * 2) The next track entry to be applied does have a timeline to set this property. + * 3) The next track entry after that one does have a timeline to set this property. + * 4) timelineHoldMix stores the first subsequent track entry that does not have a timeline to set this property. + * Result: The same as HOLD except the mix percentage from the timelineHoldMix track entry is used. This handles when more than + * 2 track entries in a row have a timeline that sets the same property. + * Eg, A -> B -> C -> D where A, B, and C have a timeline setting same property, but D does not. When A is applied, to avoid + * "dipping" A is not mixed out, however D (the first entry that doesn't set the property) mixing in is used to mix out A + * (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap to the mixed + * out position. + */ public static inline var HOLD_MIX:Int = 4; public static inline var SETUP:Int = 1; public static inline var CURRENT:Int = 2; @@ -67,6 +108,9 @@ class AnimationState { private var unkeyedState:Int = 0; + /** + * Creates an uninitialized AnimationState. The animation state data must be set before use. + */ public function new(data:AnimationStateData) { if (data == null) throw new SpineException("data can not be null"); @@ -77,6 +121,9 @@ class AnimationState { }); } + /** + * Increments each track entry spine.animation.TrackEntry.getTrackTime(), setting queued animations as current if needed. + */ public function update(delta:Float):Void { delta *= timeScale; for (i in 0...tracks.length) { @@ -138,6 +185,9 @@ class AnimationState { queue.drain(); } + /** + * Returns true when all mixing from entries are complete. + */ private function updateMixingFrom(to:TrackEntry, delta:Float):Bool { var from:TrackEntry = to.mixingFrom; if (from == null) @@ -165,6 +215,11 @@ class AnimationState { return false; } + /** + * Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple + * skeletons to pose them identically. + * @return True if any animations were applied. + */ public function apply(skeleton:Skeleton):Bool { if (skeleton == null) throw new SpineException("skeleton cannot be null."); @@ -350,6 +405,12 @@ class AnimationState { return mix; } + /** + * Applies the attachment timeline and sets spine.Slot.attachmentState. + * @param attachments False when: 1) the attachment timeline is mixing out, 2) mix < attachmentThreshold, and 3) the timeline + * is not the last timeline to set the slot's attachment. In that case the timeline is applied only so subsequent + * timelines see any deform. + */ public function applyAttachmentTimeline(timeline:AttachmentTimeline, skeleton:Skeleton, time:Float, blend:MixBlend, attachments:Bool) { var slot = skeleton.slots[timeline.slotIndex]; if (!slot.bone.active) @@ -366,6 +427,10 @@ class AnimationState { slot.attachmentState = this.unkeyedState + SETUP; } + /** + * Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest + * the first time the mixing was applied. + */ public function applyRotateTimeline(timeline:RotateTimeline, skeleton:Skeleton, time:Float, alpha:Float, blend:MixBlend, timelinesRotation:Array, i:Int, firstFrame:Bool) { if (firstFrame) @@ -481,6 +546,12 @@ class AnimationState { } } + /** + * Removes all animations from all tracks, leaving skeletons in their current pose. + * + * It may be desired to use spine.animation.AnimationState.setEmptyAnimations() to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. + */ public function clearTracks():Void { var oldTrainDisabled:Bool = queue.drainDisabled; queue.drainDisabled = true; @@ -492,6 +563,12 @@ class AnimationState { queue.drain(); } + /** + * Removes all animations from the track, leaving skeletons in their current pose. + * + * It may be desired to use spine.animation.AnimationState.setEmptyAnimation() to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. + */ public function clearTrack(trackIndex:Int):Void { if (trackIndex >= tracks.length) return; @@ -540,6 +617,11 @@ class AnimationState { queue.start(current); } + /** + * Sets an animation by name. + * + * See spine.animation.AnimationState.setAnimation(). + */ public function setAnimationByName(trackIndex:Int, animationName:String, loop:Bool):TrackEntry { var animation:Animation = data.skeletonData.findAnimation(animationName); if (animation == null) @@ -547,6 +629,14 @@ class AnimationState { return setAnimation(trackIndex, animation, loop); } + /** + * Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never + * applied to a skeleton, it is replaced (not mixed from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case spine.animation.TrackEntry.getTrackEnd() determines when the track is cleared. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the spine.animation.AnimationStateListener.dispose() event occurs. + */ public function setAnimation(trackIndex:Int, animation:Animation, loop:Bool):TrackEntry { if (animation == null) throw new SpineException("animation cannot be null."); @@ -571,6 +661,11 @@ class AnimationState { return entry; } + /** + * Queues an animation by name. + * + * See spine.animation.AnimationState.addAnimation(). + */ public function addAnimationByName(trackIndex:Int, animationName:String, loop:Bool, delay:Float):TrackEntry { var animation:Animation = data.skeletonData.findAnimation(animationName); if (animation == null) @@ -578,6 +673,16 @@ class AnimationState { return addAnimation(trackIndex, animation, loop, delay); } + /** + * Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is + * equivalent to calling spine.animation.AnimationState.setAnimation(). + * @param delay If > 0, sets spine.animation.TrackEntry.getDelay(). If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration (from the spine.animation.AnimationStateData) plus the specified delay (ie the mix + * ends at (delay = 0) or before (delay < 0) the previous track entry duration). If the + * previous entry is looping, its next loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the spine.animation.AnimationStateListener.dispose() event occurs. + */ public function addAnimation(trackIndex:Int, animation:Animation, loop:Bool, delay:Float):TrackEntry { if (animation == null) throw new SpineException("animation cannot be null."); @@ -605,6 +710,23 @@ class AnimationState { return entry; } + /** + * Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * spine.animation.TrackEntry.getMixDuration(). An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either spine.animation.AnimationState.setEmptyAnimation(), + * spine.animation.AnimationState.setEmptyAnimations(), or spine.animation.AnimationState.addEmptyAnimation(). Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still mixes out over one frame. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * spine.animation.AnimationState.addAnimation() with the desired delay (an empty animation has a duration of 0) and on + * the returned track entry, set the spine.animation.TrackEntry.setMixDuration(). Mixing from an empty animation causes the new + * animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value + * from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new + * animation. + */ public function setEmptyAnimation(trackIndex:Int, mixDuration:Float):TrackEntry { var entry:TrackEntry = setAnimation(trackIndex, emptyAnimation, false); entry.mixDuration = mixDuration; @@ -612,6 +734,19 @@ class AnimationState { return entry; } + /** + * Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * spine.animation.TrackEntry.getMixDuration(). If the track is empty, it is equivalent to calling + * spine.animation.AnimationState.setEmptyAnimation(). + * + * See spine.animation.AnimationState.setEmptyAnimation(). + * @param delay If > 0, sets spine.animation.TrackEntry.getDelay(). If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration plus the specified delay (ie the mix ends at (delay = 0) or + * before (delay < 0) the previous track entry duration). If the previous entry is looping, its next + * loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the spine.animation.AnimationStateListener.dispose() event occurs. + */ public function addEmptyAnimation(trackIndex:Int, mixDuration:Float, delay:Float):TrackEntry { var entry:TrackEntry = addAnimation(trackIndex, emptyAnimation, false, delay); if (delay <= 0) entry.delay = Math.max(entry.delay + entry.mixDuration - mixDuration, 0); @@ -620,6 +755,10 @@ class AnimationState { return entry; } + /** + * Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix + * duration. + */ public function setEmptyAnimations(mixDuration:Float):Void { var oldDrainDisabled:Bool = queue.drainDisabled; queue.drainDisabled = true; @@ -675,7 +814,9 @@ class AnimationState { return entry; } - /** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */ + /** + * Removes the spine.animation.TrackEntry.getNext() next entry and all entries after it for the specified entry. + */ public function clearNext(entry:TrackEntry):Void { var next:TrackEntry = entry.next; while (next != null) { @@ -757,6 +898,9 @@ class AnimationState { } } + /** + * Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. + */ public function getCurrent(trackIndex:Int):TrackEntry { if (trackIndex >= tracks.length) return null; @@ -769,6 +913,9 @@ class AnimationState { return onComplete.listeners.length > 0 || onEnd.listeners.length > 0; } + /** + * Removes all listeners added with spine.animation.AnimationState.addListener(). + */ public function clearListeners():Void { onStart.listeners.resize(0); onInterrupt.listeners.resize(0); @@ -778,6 +925,11 @@ class AnimationState { onEvent.listeners.resize(0); } + /** + * Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * spine.animation.AnimationStateListener when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. + */ public function clearListenerNotifications():Void { queue.clear(); } diff --git a/spine-haxe/spine-haxe/spine/animation/AnimationStateData.hx b/spine-haxe/spine-haxe/spine/animation/AnimationStateData.hx index db089dd5a..72934e7dc 100644 --- a/spine-haxe/spine-haxe/spine/animation/AnimationStateData.hx +++ b/spine-haxe/spine-haxe/spine/animation/AnimationStateData.hx @@ -32,22 +32,28 @@ package spine.animation; import haxe.ds.StringMap; import spine.SkeletonData; +/** Stores mix (crossfade) durations to be applied when spine.animation.AnimationState animations are changed. */ class AnimationStateData { private var _skeletonData:SkeletonData; private var animationToMixTime:StringMap = new StringMap(); + /** The mix duration to use when no mix duration has been defined between two animations. */ public var defaultMix:Float = 0; public function new(skeletonData:SkeletonData) { _skeletonData = skeletonData; } + /** The SkeletonData to look up animations when they are specified by name. */ public var skeletonData(get, never):SkeletonData; private function get_skeletonData():SkeletonData { return _skeletonData; } + /** Sets a mix duration by animation name. + * + * See AnimationStateData.setMix(). */ public function setMixByName(fromName:String, toName:String, duration:Float):Void { var from:Animation = _skeletonData.findAnimation(fromName); if (from == null) @@ -58,6 +64,9 @@ class AnimationStateData { setMix(from, to, duration); } + /** Sets the mix duration when changing from the specified animation to the other. + * + * See spine.animation.TrackEntry.mixDuration. */ public function setMix(from:Animation, to:Animation, duration:Float):Void { if (from == null) throw new SpineException("from cannot be null."); @@ -66,6 +75,8 @@ class AnimationStateData { animationToMixTime.set(from.name + ":" + to.name, duration); } + /** Returns the mix duration to use when changing from the specified animation to the other, or the AnimationStateData.defaultMix if + * no mix duration has been set. */ public function getMix(from:Animation, to:Animation):Float { if (animationToMixTime.exists(from.name + ":" + to.name)) return animationToMixTime.get(from.name + ":" + to.name); diff --git a/spine-haxe/spine-haxe/spine/animation/AttachmentTimeline.hx b/spine-haxe/spine-haxe/spine/animation/AttachmentTimeline.hx index f8bfc5d68..dd5642f07 100644 --- a/spine-haxe/spine-haxe/spine/animation/AttachmentTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/AttachmentTimeline.hx @@ -33,10 +33,11 @@ import spine.Event; import spine.Skeleton; import spine.Slot; +/** Changes a slot's spine.Slot.attachment. */ class AttachmentTimeline extends Timeline implements SlotTimeline { public var slotIndex:Int = 0; - /** The attachment name for each key frame. May contain null values to clear the attachment. */ + /** The attachment name for each frame. May contain null values to clear the attachment. */ public var attachmentNames:Array; public function new(frameCount:Int, slotIndex:Int) { @@ -54,7 +55,9 @@ class AttachmentTimeline extends Timeline implements SlotTimeline { return slotIndex; } - /** Sets the time in seconds and the attachment name for the specified key frame. */ + /** Sets the time and attachment name for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, attachmentName:String):Void { frames[frame] = time; attachmentNames[frame] = attachmentName; diff --git a/spine-haxe/spine-haxe/spine/animation/BoneTimeline.hx b/spine-haxe/spine-haxe/spine/animation/BoneTimeline.hx index a2e59ba6f..7c6380012 100644 --- a/spine-haxe/spine-haxe/spine/animation/BoneTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/BoneTimeline.hx @@ -29,6 +29,8 @@ package spine.animation; +/** An interface for timelines which change the property of a bone. */ interface BoneTimeline { + /** The index of the bone in spine.Skeleton.getBones() that will be changed when this timeline is applied. */ function getBoneIndex():Int; } diff --git a/spine-haxe/spine-haxe/spine/animation/CurveTimeline.hx b/spine-haxe/spine-haxe/spine/animation/CurveTimeline.hx index ac78c008e..54885d104 100644 --- a/spine-haxe/spine-haxe/spine/animation/CurveTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/CurveTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Base class for frames that use an interpolation bezier curve. */ +/** The base class for timelines that interpolate between frame values using stepped, linear, or a Bezier curve. */ class CurveTimeline extends Timeline { private static inline var LINEAR:Int = 0; private static inline var STEPPED:Int = 1; @@ -38,6 +38,8 @@ class CurveTimeline extends Timeline { private var curves:Array; // type, x, y, ... + /** @param bezierCount The maximum number of Bezier curves. See CurveTimeline.shrink(). + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ public function new(frameCount:Int, bezierCount:Int, propertyIds:Array) { super(frameCount, propertyIds); curves = new Array(); @@ -45,15 +47,19 @@ class CurveTimeline extends Timeline { curves[frameCount - 1] = STEPPED; } + /** Sets the specified frame to linear interpolation. + * @param frame Between 0 and frameCount - 1, inclusive. */ public function setLinear(frame:Int):Void { curves[frame] = LINEAR; } + /** Sets the specified frame to stepped interpolation. + * @param frame Between 0 and frameCount - 1, inclusive. */ public function setStepped(frame:Int):Void { curves[frame] = STEPPED; } - /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger + /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger * than the actual number of Bezier curves. */ public function shrink(bezierCount:Int):Void { var size:Int = getFrameCount() + bezierCount * BEZIER_SIZE; @@ -62,10 +68,10 @@ class CurveTimeline extends Timeline { /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than * one curve per frame. - * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified * in the constructor), inclusive. - * @param frame Between 0 and frameCount - 1, inclusive. - * @param value The index of the value for this frame that this curve is used for. + * @param frame Between 0 and frameCount - 1, inclusive. + * @param value The index of the value for the frame this curve is used for. * @param time1 The time for the first key. * @param value1 The value for the first key. * @param cx1 The time for the first Bezier handle. @@ -103,9 +109,9 @@ class CurveTimeline extends Timeline { } /** Returns the Bezier interpolated value for the specified time. - * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time. - * @param valueOffset The offset from frameIndex to the value this curve is used for. - * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ + * @param frameIndex The index into Timeline.getFrames() for the values of the frame before time. + * @param valueOffset The offset from frameIndex to the value this curve is used for. + * @param i The index of the Bezier segments. See CurveTimeline.getCurveType(). */ public function getBezierValue(time:Float, frameIndex:Int, valueOffset:Int, i:Int):Float { var x:Float, y:Float; if (curves[i] > time) { diff --git a/spine-haxe/spine-haxe/spine/animation/CurveTimeline1.hx b/spine-haxe/spine-haxe/spine/animation/CurveTimeline1.hx index d09b846b4..a79a1c4dc 100644 --- a/spine-haxe/spine-haxe/spine/animation/CurveTimeline1.hx +++ b/spine-haxe/spine-haxe/spine/animation/CurveTimeline1.hx @@ -29,12 +29,13 @@ package spine.animation; -/** The base class for a {@link CurveTimeline} that sets one property. */ +/** The base class for a spine.animation.CurveTimeline that sets one property. */ class CurveTimeline1 extends CurveTimeline { private static inline var ENTRIES:Int = 2; private static inline var VALUE:Int = 1; - /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(Int)}. + /** @param frameCount The number of frames in the timeline. + * @param bezierCount The maximum number of Bezier curves. See spine.animation.CurveTimeline.shrink(). * @param propertyIds Unique identifiers for the properties the timeline modifies. */ public function new(frameCount:Int, bezierCount:Int, propertyIds:Array) { super(frameCount, bezierCount, propertyIds); @@ -44,8 +45,8 @@ class CurveTimeline1 extends CurveTimeline { return ENTRIES; } - /** Sets the time and values for the specified frame. - * @param frame Between 0 and frameCount, inclusive. + /** Sets the time and value for the specified frame. + * @param frame Between 0 and frameCount, inclusive. * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, value1:Float):Void { frame <<= 1; diff --git a/spine-haxe/spine-haxe/spine/animation/CurveTimeline2.hx b/spine-haxe/spine-haxe/spine/animation/CurveTimeline2.hx index d9d8efd04..fafbdcce1 100644 --- a/spine-haxe/spine-haxe/spine/animation/CurveTimeline2.hx +++ b/spine-haxe/spine-haxe/spine/animation/CurveTimeline2.hx @@ -29,14 +29,15 @@ package spine.animation; -/** The base class for a {@link CurveTimeline} which sets two properties. */ +/** The base class for a spine.animation.CurveTimeline which sets two properties. */ class CurveTimeline2 extends CurveTimeline { private static inline var ENTRIES:Int = 3; private static inline var VALUE1:Int = 1; private static inline var VALUE2:Int = 2; - /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(Int)}. - * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + /** @param frameCount The number of frames in the timeline. + * @param bezierCount The maximum number of Bezier curves. See spine.animation.CurveTimeline.shrink(). + * @param propertyIds Array of unique identifiers for the properties the timeline modifies. */ public function new(frameCount:Int, bezierCount:Int, propertyIds:Array) { super(frameCount, bezierCount, propertyIds); } @@ -46,7 +47,7 @@ class CurveTimeline2 extends CurveTimeline { } /** Sets the time and values for the specified frame. - * @param frame Between 0 and frameCount, inclusive. + * @param frame Between 0 and frameCount, inclusive. * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, value1:Float, value2:Float):Void { frame *= ENTRIES; diff --git a/spine-haxe/spine-haxe/spine/animation/DeformTimeline.hx b/spine-haxe/spine-haxe/spine/animation/DeformTimeline.hx index 8917cca2c..0f2706bba 100644 --- a/spine-haxe/spine-haxe/spine/animation/DeformTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/DeformTimeline.hx @@ -36,13 +36,16 @@ import spine.Event; import spine.Skeleton; import spine.Slot; +/** Changes a slot's spine.Slot.deform to deform a spine.attachments.VertexAttachment. */ class DeformTimeline extends CurveTimeline implements SlotTimeline { public var slotIndex:Int = 0; - /** The attachment that will be deformed. */ + /** The attachment that will be deformed. + * + * @see spine.attachments.VertexAttachment.getTimelineAttachment() */ public var attachment:VertexAttachment; - /** The vertices for each key frame. */ + /** The vertices for each frame. */ public var vertices:Array>; public function new(frameCount:Int, bezierCount:Int, slotIndex:Int, attachment:VertexAttachment) { @@ -61,14 +64,25 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline { return slotIndex; } - /** Sets the time in seconds and the vertices for the specified key frame. - * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + /** Sets the time and vertices for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. + * @param verticesOrDeform Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ public function setFrame(frame:Int, time:Float, verticesOrDeform:Array):Void { frames[frame] = time; vertices[frame] = verticesOrDeform; } - /** @param value1 Ignored (0 is used for a deform timeline). + /** @param bezier The bezier index. + * @param frame The frame index. + * @param value Ignored (0 is used for a deform timeline). + * @param time1 The first time. + * @param value1 Ignored (0 is used for a deform timeline). + * @param cx1 The first control point x. + * @param cy1 The first control point y. + * @param cx2 The second control point x. + * @param cy2 The second control point y. + * @param time2 The second time. * @param value2 Ignored (1 is used for a deform timeline). */ public override function setBezier(bezier:Int, frame:Int, value:Float, time1:Float, value1:Float, cx1:Float, cy1:Float, cx2:Float, cy2:Float, time2:Float, value2:Float):Void { @@ -98,6 +112,8 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline { } } + /** Returns the interpolated percentage for the specified time. + * @param frame The frame before time. */ private function getCurvePercent(time:Float, frame:Int):Float { var i:Int = Std.int(curves[frame]); var x:Float; diff --git a/spine-haxe/spine-haxe/spine/animation/DrawOrderTimeline.hx b/spine-haxe/spine-haxe/spine/animation/DrawOrderTimeline.hx index 34b3df08d..c312fb1ea 100644 --- a/spine-haxe/spine-haxe/spine/animation/DrawOrderTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/DrawOrderTimeline.hx @@ -33,7 +33,9 @@ import spine.Event; import spine.Skeleton; import spine.Slot; +/** Changes a skeleton's Skeleton#drawOrder. */ class DrawOrderTimeline extends Timeline { + /** The draw order for each frame. See setFrame(). */ public var drawOrders:Array>; public function new(frameCount:Int) { @@ -48,7 +50,10 @@ class DrawOrderTimeline extends Timeline { return frames.length; } - /** Sets the time and value of the specified keyframe. */ + /** Sets the time and draw order for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. + * @param drawOrder For each slot in spine.Skeleton.slots, the index of the slot in the new draw order. May be null to use setup pose draw order. */ public function setFrame(frame:Int, time:Float, drawOrder:Array):Void { frames[frame] = time; drawOrders[frame] = drawOrder; diff --git a/spine-haxe/spine-haxe/spine/animation/EventQueue.hx b/spine-haxe/spine-haxe/spine/animation/EventQueue.hx index 10fcb710d..3c48e644a 100644 --- a/spine-haxe/spine-haxe/spine/animation/EventQueue.hx +++ b/spine-haxe/spine-haxe/spine/animation/EventQueue.hx @@ -31,6 +31,9 @@ package spine.animation; import spine.Event; +/** + * Stores events raised by AnimationState and allows them to be processed later. + */ class EventQueue { private var objects:Array; private var animationState:AnimationState; diff --git a/spine-haxe/spine-haxe/spine/animation/EventTimeline.hx b/spine-haxe/spine-haxe/spine/animation/EventTimeline.hx index ee1c88411..7fe8f1a75 100644 --- a/spine-haxe/spine-haxe/spine/animation/EventTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/EventTimeline.hx @@ -33,7 +33,9 @@ import spine.animation.Timeline; import spine.Event; import spine.Skeleton; +/** Fires an spine.Event when specific animation times are reached. */ class EventTimeline extends Timeline { + /** The event for each frame. */ public var events:Array; public function new(frameCount:Int) { @@ -46,13 +48,14 @@ class EventTimeline extends Timeline { return frames.length; } - /** Sets the time in seconds and the event for the specified key frame. */ + /** Sets the time and event for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ public function setFrame(frame:Int, event:Event):Void { frames[frame] = event.time; events[frame] = event; } - /** Fires events for frames > `lastTime` and <= `time`. */ + /** Fires events for frames > lastTime and <= time. */ public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array, alpha:Float, blend:MixBlend, direction:MixDirection):Void { if (events == null) diff --git a/spine-haxe/spine-haxe/spine/animation/IkConstraintTimeline.hx b/spine-haxe/spine-haxe/spine/animation/IkConstraintTimeline.hx index b61585d9d..037c224d2 100644 --- a/spine-haxe/spine-haxe/spine/animation/IkConstraintTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/IkConstraintTimeline.hx @@ -33,6 +33,8 @@ import spine.Event; import spine.IkConstraint; import spine.Skeleton; +/** Changes an IK constraint's spine.IkConstraint.mix, spine.IkConstraint.softness, + * spine.IkConstraint.bendDirection, spine.IkConstraint.stretch, and spine.IkConstraint.compress. */ class IkConstraintTimeline extends CurveTimeline { private static inline var ENTRIES:Int = 6; private static inline var MIX:Int = 1; @@ -41,7 +43,8 @@ class IkConstraintTimeline extends CurveTimeline { private static inline var COMPRESS:Int = 4; private static inline var STRETCH:Int = 5; - /** The index of the IK constraint in {@link Skeleton#ikConstraints} when this timeline is applied. */ + /** The index of the IK constraint in spine.Skeleton.ikConstraints that will be changed when this timeline is + * applied. */ public var constraintIndex:Int = 0; public function new(frameCount:Int, bezierCount:Int, ikConstraintIndex:Int) { @@ -53,7 +56,10 @@ class IkConstraintTimeline extends CurveTimeline { return ENTRIES; } - /** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */ + /** Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. + * @param bendDirection 1 or -1. */ public function setFrame(frame:Int, time:Float, mix:Float, softness:Float, bendDirection:Int, compress:Bool, stretch:Bool):Void { frame *= ENTRIES; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx b/spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx index a64a10ba4..087ba5156 100644 --- a/spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's spine.Bone.inherit. */ class InheritTimeline extends Timeline implements BoneTimeline { public static inline var ENTRIES:Int = 2; private static inline var INHERIT:Int = 1; @@ -52,6 +53,9 @@ class InheritTimeline extends Timeline implements BoneTimeline { return boneIndex; } + /** Sets the transform mode for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, inherit: Inherit):Void { frame *= ENTRIES; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/Listeners.hx b/spine-haxe/spine-haxe/spine/animation/Listeners.hx index 185379b76..b86e057b3 100644 --- a/spine-haxe/spine-haxe/spine/animation/Listeners.hx +++ b/spine-haxe/spine-haxe/spine/animation/Listeners.hx @@ -29,6 +29,9 @@ package spine.animation; +/** + * Manages a collection of listeners for TrackEntry events. + */ class Listeners { private var _listeners:ArrayVoid>; @@ -42,6 +45,8 @@ class Listeners { _listeners = new ArrayVoid>(); } + /** Invoked when this entry has been set as the current entry. spine.animation.Listeners.end(TrackEntry) will occur when this entry will no + * longer be applied. */ public function invoke(entry:TrackEntry) { for (listener in _listeners) { listener(entry); @@ -65,6 +70,9 @@ class Listeners { } } +/** + * Manages a collection of event listeners for TrackEntry events. + */ class EventListeners { private var _listeners:ArrayEvent->Void>; @@ -78,6 +86,11 @@ class EventListeners { _listeners = new ArrayEvent->Void>(); } + /** Invoked when this entry's animation triggers an event. This may occur during mixing (after + * interrupt(TrackEntry)), see spine.animation.TrackEntry.eventThreshold. + * + * Because this event is triggered at the end of spine.animation.AnimationState.apply(Skeleton), any animations set in response to + * the event won't be applied until the next time the AnimationState is applied. */ public function invoke(entry:TrackEntry, event:Event) { for (listener in _listeners) { listener(entry, event); diff --git a/spine-haxe/spine-haxe/spine/animation/MixBlend.hx b/spine-haxe/spine-haxe/spine/animation/MixBlend.hx index 839e209dd..7f6c1761c 100644 --- a/spine-haxe/spine-haxe/spine/animation/MixBlend.hx +++ b/spine-haxe/spine-haxe/spine/animation/MixBlend.hx @@ -29,6 +29,10 @@ package spine.animation; +/** Controls how timeline values are mixed with setup pose values or current pose values when a timeline is applied with + * alpha < 1. + * + * @see spine.animation.Timeline.apply() */ class MixBlend { public var ordinal:Int = 0; @@ -36,8 +40,25 @@ class MixBlend { this.ordinal = ordinal; } + /** Transitions from the setup value to the timeline value (the current value is not used). Before the first frame, the + * setup value is set. */ public static var setup(default, never):MixBlend = new MixBlend(0); + /** Transitions from the current value to the timeline value. Before the first frame, transitions from the current value to + * the setup value. Timelines which perform instant transitions, such as spine.animation.DrawOrderTimeline or + * spine.animation.AttachmentTimeline, use the setup value before the first frame. + * + * first is intended for the first animations applied, not for animations layered on top of those. */ public static var first(default, never):MixBlend = new MixBlend(1); + /** Transitions from the current value to the timeline value. No change is made before the first frame (the current value is + * kept until the first frame). + * + * replace is intended for animations layered on top of others, not for the first animations applied. */ public static var replace(default, never):MixBlend = new MixBlend(2); + /** Transitions from the current value to the current value plus the timeline value. No change is made before the first + * frame (the current value is kept until the first frame). + * + * add is intended for animations layered on top of others, not for the first animations applied. Properties + * set by additive animations must be set manually or by another animation before applying the additive animations, else the + * property values will increase each time the additive animations are applied. */ public static var add(default, never):MixBlend = new MixBlend(3); } diff --git a/spine-haxe/spine-haxe/spine/animation/MixDirection.hx b/spine-haxe/spine-haxe/spine/animation/MixDirection.hx index 55c95422c..6d827b27f 100644 --- a/spine-haxe/spine-haxe/spine/animation/MixDirection.hx +++ b/spine-haxe/spine-haxe/spine/animation/MixDirection.hx @@ -29,6 +29,11 @@ package spine.animation; +/** Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose value) or + * mixing in toward 1 (the timeline's value). Some timelines use this to decide how values are applied. + * + * @see spine.animation.Timeline.apply() + */ class MixDirection { public var ordinal:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/PathConstraintMixTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PathConstraintMixTimeline.hx index f3bb47318..b53f86c6e 100644 --- a/spine-haxe/spine-haxe/spine/animation/PathConstraintMixTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PathConstraintMixTimeline.hx @@ -33,13 +33,16 @@ import spine.Event; import spine.PathConstraint; import spine.Skeleton; +/** Changes a path constraint's PathConstraint.mixRotate, PathConstraint.mixX, and + * PathConstraint.mixY. */ class PathConstraintMixTimeline extends CurveTimeline { private static inline var ENTRIES:Int = 4; private static inline var ROTATE:Int = 1; private static inline var X:Int = 2; private static inline var Y:Int = 3; - /** The index of the path constraint in {@link Skeleton#getPathConstraints()} when this timeline is applied. */ + /** The index of the path constraint in spine.Skeleton.pathConstraints that will be changed when this timeline is + * applied. */ public var constraintIndex:Int = 0; public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) { @@ -51,6 +54,9 @@ class PathConstraintMixTimeline extends CurveTimeline { return ENTRIES; } + /** Sets the time and color for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, mixRotate:Float, mixX:Float, mixY:Float):Void { frame <<= 2; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/PathConstraintPositionTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PathConstraintPositionTimeline.hx index c77e56650..ae22dab44 100644 --- a/spine-haxe/spine-haxe/spine/animation/PathConstraintPositionTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PathConstraintPositionTimeline.hx @@ -33,8 +33,10 @@ import spine.Event; import spine.PathConstraint; import spine.Skeleton; +/** Changes a path constraint's spine.PathConstraint.position. */ class PathConstraintPositionTimeline extends CurveTimeline1 { - /** The index of the path constraint in {@link Skeleton#pathConstraints} when this timeline is applied. */ + /** The index of the path constraint in spine.Skeleton.pathConstraints that will be changed when this timeline is + * applied. */ public var constraintIndex:Int = 0; public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) { diff --git a/spine-haxe/spine-haxe/spine/animation/PathConstraintSpacingTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PathConstraintSpacingTimeline.hx index 1a7b20d48..faddac0aa 100644 --- a/spine-haxe/spine-haxe/spine/animation/PathConstraintSpacingTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PathConstraintSpacingTimeline.hx @@ -33,8 +33,10 @@ import spine.Event; import spine.PathConstraint; import spine.Skeleton; +/** Changes a path constraint's PathConstraint#spacing. */ class PathConstraintSpacingTimeline extends CurveTimeline1 { - /** The index of the path constraint in {@link Skeleton#pathConstraints} when this timeline is applied. */ + /** The index of the path constraint in Skeleton#pathConstraints that will be changed when this timeline is + * applied. */ public var constraintIndex:Int = 0; public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) { diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintDampingTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintDampingTimeline.hx index 42bda84af..a4dcbee3f 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintDampingTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintDampingTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.damping. */ class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintGravityTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintGravityTimeline.hx index 3bcbe2e6e..5ecf42076 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintGravityTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintGravityTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.gravity. */ class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintInertiaTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintInertiaTimeline.hx index 2410aa9e5..45d490081 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintInertiaTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintInertiaTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.inertia. */ class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMassTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMassTimeline.hx index 9fd0bdc50..abc1e695e 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMassTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMassTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */ +/** Changes a physics constraint's spine.PhysicsConstraint.massInverse. The timeline values are not inverted. */ class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMixTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMixTimeline.hx index 6526d59af..9c080a03c 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMixTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintMixTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.mix. */ class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintResetTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintResetTimeline.hx index 63a3e887f..f6679531d 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintResetTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintResetTimeline.hx @@ -33,11 +33,13 @@ import spine.animation.Timeline; import spine.Event; import spine.Skeleton; +/** Resets a physics constraint when specific animation times are reached. */ class PhysicsConstraintResetTimeline extends Timeline { - /** The index of the physics constraint in {@link Skeleton#physicsConstraints} that will be reset when this timeline is - * applied, or -1 if all physics constraints in the skeleton will be reset. */ + /** The index of the physics constraint in Skeleton#physicsConstraints that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ public var constraintIndex:Int = 0; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ public function new(frameCount:Int, physicsConstraintIndex:Int) { propertyIds = [Std.string(Property.physicsConstraintReset)]; super(frameCount, propertyIds); @@ -48,7 +50,8 @@ class PhysicsConstraintResetTimeline extends Timeline { return frames.length; } - /** Sets the time in seconds and the event for the specified key frame. */ + /** Sets the time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ public function setFrame(frame:Int, time:Float):Void { frames[frame] = time; } diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintStrengthTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintStrengthTimeline.hx index 5343026c2..08092c48f 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintStrengthTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintStrengthTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.strength. */ class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintTimeline.hx index e2244e0bc..5bf15d4fb 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintTimeline.hx @@ -33,13 +33,15 @@ import spine.Event; import spine.PathConstraint; import spine.Skeleton; -/** The base class for most {@link PhysicsConstraint} timelines. */ +/** The base class for most spine.PhysicsConstraint timelines. */ abstract class PhysicsConstraintTimeline extends CurveTimeline1 { - /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline + /** The index of the physics constraint in Skeleton.physicsConstraints that will be changed when this timeline * is applied, or -1 if all physics constraints in the skeleton will be changed. */ public var constraintIndex:Int = 0; - /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + /** + * @param physicsConstraintIndex -1 for all physics constraints in the skeleton. + */ public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int, property:Int) { super(frameCount, bezierCount, [property + "|" + physicsConstraintIndex]); constraintIndex = physicsConstraintIndex; diff --git a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintWindTimeline.hx b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintWindTimeline.hx index d57072778..aed4b21b5 100644 --- a/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintWindTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/PhysicsConstraintWindTimeline.hx @@ -29,7 +29,7 @@ package spine.animation; -/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ +/** Changes a physics constraint's spine.PhysicsConstraint.wind. */ class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline { public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); diff --git a/spine-haxe/spine-haxe/spine/animation/Property.hx b/spine-haxe/spine-haxe/spine/animation/Property.hx index 46c292727..743600ff8 100644 --- a/spine-haxe/spine-haxe/spine/animation/Property.hx +++ b/spine-haxe/spine-haxe/spine/animation/Property.hx @@ -29,6 +29,9 @@ package spine.animation; +/** + * Constants for animation property types. + */ class Property { public static inline var rotate:Int = 0; public static inline var x:Int = 1; diff --git a/spine-haxe/spine-haxe/spine/animation/RGB2Timeline.hx b/spine-haxe/spine-haxe/spine/animation/RGB2Timeline.hx index 2c3f78770..eadbff7b1 100644 --- a/spine-haxe/spine-haxe/spine/animation/RGB2Timeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/RGB2Timeline.hx @@ -29,6 +29,7 @@ package spine.animation; +/** Changes the RGB for a slot's spine.Slot.color and spine.Slot.darkColor for two color tinting. */ class RGB2Timeline extends CurveTimeline implements SlotTimeline { private static inline var ENTRIES:Int = 7; private static inline var R:Int = 1; @@ -49,11 +50,15 @@ class RGB2Timeline extends CurveTimeline implements SlotTimeline { return ENTRIES; } + /** The index of the slot in spine.Skeleton.slots that will be changed when this timeline is applied. The + * spine.Slot.darkColor must not be null. */ public function getSlotIndex():Int { return slotIndex; } - /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + /** Sets the time, light color, and dark color for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, r:Float, g:Float, b:Float, r2:Float, g2:Float, b2:Float):Void { frame *= ENTRIES; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/RGBA2Timeline.hx b/spine-haxe/spine-haxe/spine/animation/RGBA2Timeline.hx index c9607c2c7..1e45b2f63 100644 --- a/spine-haxe/spine-haxe/spine/animation/RGBA2Timeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/RGBA2Timeline.hx @@ -29,6 +29,7 @@ package spine.animation; +/** Changes a slot's spine.Slot.getColor() and spine.Slot.getDarkColor() for two color tinting. */ class RGBA2Timeline extends CurveTimeline implements SlotTimeline { private static inline var ENTRIES:Int = 8; private static inline var R:Int = 1; @@ -54,11 +55,15 @@ class RGBA2Timeline extends CurveTimeline implements SlotTimeline { return ENTRIES; } + /** The index of the slot in spine.Skeleton.getSlots() that will be changed when this timeline is applied. The + * spine.Slot.getDarkColor() must not be null. */ public function getSlotIndex():Int { return slotIndex; } - /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + /** Sets the time, light color, and dark color for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, r:Float, g:Float, b:Float, a:Float, r2:Float, g2:Float, b2:Float):Void { frame <<= 3; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/RGBATimeline.hx b/spine-haxe/spine-haxe/spine/animation/RGBATimeline.hx index 2652d8a80..8e7a751d5 100644 --- a/spine-haxe/spine-haxe/spine/animation/RGBATimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/RGBATimeline.hx @@ -29,6 +29,7 @@ package spine.animation; +/** Changes a slot's spine.Slot.color. */ class RGBATimeline extends CurveTimeline implements SlotTimeline { private static inline var ENTRIES:Int = 5; private static inline var R:Int = 1; @@ -51,7 +52,9 @@ class RGBATimeline extends CurveTimeline implements SlotTimeline { return slotIndex; } - /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + /** Sets the time and color for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, r:Float, g:Float, b:Float, a:Float):Void { frame *= ENTRIES; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/RGBTimeline.hx b/spine-haxe/spine-haxe/spine/animation/RGBTimeline.hx index be389462c..885b3f768 100644 --- a/spine-haxe/spine-haxe/spine/animation/RGBTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/RGBTimeline.hx @@ -29,6 +29,7 @@ package spine.animation; +/** Changes the RGB for a slot's spine.Slot.color. */ class RGBTimeline extends CurveTimeline implements SlotTimeline { private static inline var ENTRIES:Int = 4; private static inline var R:Int = 1; @@ -50,7 +51,9 @@ class RGBTimeline extends CurveTimeline implements SlotTimeline { return slotIndex; } - /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + /** Sets the time and color for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, r:Float, g:Float, b:Float):Void { frame <<= 2; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/RotateTimeline.hx b/spine-haxe/spine-haxe/spine/animation/RotateTimeline.hx index 2299c00c4..9d47c7a2b 100644 --- a/spine-haxe/spine-haxe/spine/animation/RotateTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/RotateTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local rotation. */ class RotateTimeline extends CurveTimeline1 implements BoneTimeline { public var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/ScaleTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ScaleTimeline.hx index 9b409889b..5aaaf6022 100644 --- a/spine-haxe/spine-haxe/spine/animation/ScaleTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ScaleTimeline.hx @@ -34,6 +34,7 @@ import spine.Event; import spine.MathUtils; import spine.Skeleton; +/** Changes a bone's local spine.Bone.scaleX and spine.Bone.scaleY. */ class ScaleTimeline extends CurveTimeline2 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/ScaleXTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ScaleXTimeline.hx index 331946e5b..4c7c06357 100644 --- a/spine-haxe/spine-haxe/spine/animation/ScaleXTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ScaleXTimeline.hx @@ -34,6 +34,7 @@ import spine.Event; import spine.MathUtils; import spine.Skeleton; +/** Changes a bone's local spine.Bone.scaleX. */ class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/ScaleYTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ScaleYTimeline.hx index 696711793..d1ea7abe5 100644 --- a/spine-haxe/spine-haxe/spine/animation/ScaleYTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ScaleYTimeline.hx @@ -34,6 +34,7 @@ import spine.Event; import spine.MathUtils; import spine.Skeleton; +/** Changes a bone's local spine.Bone.scaleY. */ class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx b/spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx index 3e445378a..fa0ebd320 100644 --- a/spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/SequenceTimeline.hx @@ -32,6 +32,7 @@ package spine.animation; import spine.attachments.VertexAttachment; import spine.attachments.Attachment; +/** Changes a slot's Slot#getSequenceIndex() for an attachment's Sequence. */ class SequenceTimeline extends Timeline implements SlotTimeline { static var ENTRIES = 3; static var MODE = 1; @@ -61,7 +62,7 @@ class SequenceTimeline extends Timeline implements SlotTimeline { } /** Sets the time, mode, index, and frame time for the specified frame. - * @param frame Between 0 and frameCount, inclusive. + * @param frame Between 0 and frameCount, inclusive. * @param time Seconds between frames. */ public function setFrame(frame:Int, time:Float, mode:SequenceMode, index:Int, delay:Float) { frame *= SequenceTimeline.ENTRIES; diff --git a/spine-haxe/spine-haxe/spine/animation/ShearTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ShearTimeline.hx index 24b7ce7c7..ad39f8043 100644 --- a/spine-haxe/spine-haxe/spine/animation/ShearTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ShearTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local spine.Bone.shearX and spine.Bone.shearY. */ class ShearTimeline extends CurveTimeline2 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/ShearXTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ShearXTimeline.hx index dcaa0c767..aeb8ac9de 100644 --- a/spine-haxe/spine-haxe/spine/animation/ShearXTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ShearXTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local spine.Bone.shearX. */ class ShearXTimeline extends CurveTimeline1 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/ShearYTimeline.hx b/spine-haxe/spine-haxe/spine/animation/ShearYTimeline.hx index be337b238..ccf6e3400 100644 --- a/spine-haxe/spine-haxe/spine/animation/ShearYTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/ShearYTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local Bone.shearY. */ class ShearYTimeline extends CurveTimeline1 implements BoneTimeline { private var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/SlotTimeline.hx b/spine-haxe/spine-haxe/spine/animation/SlotTimeline.hx index 110a500b5..c98cdca26 100644 --- a/spine-haxe/spine-haxe/spine/animation/SlotTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/SlotTimeline.hx @@ -29,6 +29,8 @@ package spine.animation; +/** An interface for timelines which change the property of a slot. */ interface SlotTimeline { + /** The index of the slot in spine.Skeleton.getSlots() that will be changed when this timeline is applied. */ function getSlotIndex():Int; } diff --git a/spine-haxe/spine-haxe/spine/animation/Timeline.hx b/spine-haxe/spine-haxe/spine/animation/Timeline.hx index ebb187319..46eb76ed9 100644 --- a/spine-haxe/spine-haxe/spine/animation/Timeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/Timeline.hx @@ -32,32 +32,65 @@ package spine.animation; import spine.Event; import spine.Skeleton; +/** The base class for all timelines. */ class Timeline { + /** Uniquely encodes both the type of this timeline and the skeleton properties that it affects. */ public var propertyIds:Array; + /** The time in seconds and any other values for each frame. */ public var frames:Array; + /** + * @param propertyIds Unique identifiers for the properties the timeline modifies. + */ public function new(frameCount:Int, propertyIds:Array) { this.propertyIds = propertyIds; frames = new Array(); frames.resize(frameCount * getFrameEntries()); } + /** The number of entries stored per frame. */ public function getFrameEntries():Int { return 1; } + /** The number of frames for this timeline. */ public function getFrameCount():Int { return Std.int(frames.length / getFrameEntries()); } + /** Returns the duration of this timeline in seconds. */ public function getDuration():Float { return frames[frames.length - getFrameEntries()]; } + /** Applies this timeline to the skeleton. + * @param skeleton The skeleton to which the timeline is being applied. This provides access to the bones, slots, and other + * skeleton components that the timeline may change. + * @param lastTime The last time in seconds this timeline was applied. Timelines such as spine.animation.EventTimeline trigger only + * at specific times rather than every frame. In that case, the timeline triggers everything between + * lastTime (exclusive) and time (inclusive). Pass -1 the first time an animation is + * applied to ensure frame 0 is triggered. + * @param time The time in seconds that the skeleton is being posed for. Most timelines find the frame before and the frame + * after this time and interpolate between the frame values. If beyond the last frame, the last frame will be + * applied. + * @param events If any events are fired, they are added to this list. Can be null to ignore fired events or if the timeline + * does not fire events. + * @param alpha 0 applies the current or setup value (depending on blend). 1 applies the timeline value. + * Between 0 and 1 applies a value between the current or setup value and the timeline value. By adjusting + * alpha over time, an animation can be mixed in or out. alpha can also be useful to + * apply animations on top of each other (layering). + * @param blend Controls how mixing is applied when alpha < 1. + * @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions, + * such as spine.animation.DrawOrderTimeline or spine.animation.AttachmentTimeline, and others such as spine.animation.ScaleTimeline. + */ public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array, alpha:Float, blend:MixBlend, direction:MixDirection):Void { throw new SpineException("Timeline implementations must override apply()"); } + /** Linear search using a stride of 1. + * @param time Must be >= the first value in frames. + * @return The index of the first value <= time. + */ public static function search1(frames:Array, time:Float):Int { var n:Int = frames.length; for (i in 1...n) { @@ -67,6 +100,10 @@ class Timeline { return n - 1; } + /** Linear search using the specified stride. + * @param time Must be >= the first value in frames. + * @return The index of the first value <= time. + */ public static function search(values:Array, time:Float, step:Int):Int { var n:Int = values.length; var i:Int = step; diff --git a/spine-haxe/spine-haxe/spine/animation/TrackEntry.hx b/spine-haxe/spine-haxe/spine/animation/TrackEntry.hx index 0c45cd287..26d8fec74 100644 --- a/spine-haxe/spine-haxe/spine/animation/TrackEntry.hx +++ b/spine-haxe/spine-haxe/spine/animation/TrackEntry.hx @@ -32,11 +32,24 @@ package spine.animation; import spine.animation.Listeners.EventListeners; import spine.Poolable; +/** Stores settings and other state for the playback of an animation on an spine.animation.AnimationState track. + * + * References to a track entry must not be kept after the AnimationStateListener.dispose(TrackEntry) event occurs. */ class TrackEntry implements Poolable { + /** The animation to apply for this track entry. */ public var animation:Animation; + /** The animation queued to start after this animation, or null if there is none. next makes up a doubly linked + * list. + * + * See spine.animation.AnimationState.clearNext(TrackEntry) to truncate the list. */ public var next:TrackEntry; + /** The animation queued to play before this animation, or null. previous makes up a doubly linked list. */ public var previous:TrackEntry; + /** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + * mixing is currently occurring. When mixing from multiple animations, mixingFrom makes up a linked list. */ public var mixingFrom:TrackEntry; + /** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is + * currently occurring. When mixing to multiple animations, mixingTo makes up a linked list. */ public var mixingTo:TrackEntry; public var onStart:Listeners = new Listeners(); public var onInterrupt:Listeners = new Listeners(); @@ -44,46 +57,142 @@ class TrackEntry implements Poolable { public var onDispose:Listeners = new Listeners(); public var onComplete:Listeners = new Listeners(); public var onEvent:EventListeners = new EventListeners(); + /** The index of the track where this track entry is either current or queued. + * + * See spine.animation.AnimationState.getCurrent(int). */ public var trackIndex:Int = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ public var loop:Bool = false; + /** If true, the animation will be applied in reverse. Events are not fired when an animation is applied in reverse. */ public var reverse:Bool = false; + /** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + * of being mixed out. + * + * When mixing between animations that key the same property, if a lower track also keys that property then the value will + * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + * while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation + * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + * keys the property, only when a higher track also keys the property. + * + * Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the + * previous animation. */ public var holdPrevious:Bool = false; + /** When the mix percentage (TrackEntry.getMixTime() / TrackEntry.getMixDuration()) is less than the + * eventThreshold, event timelines are applied while this animation is being mixed out. Defaults to 0, so event + * timelines are not applied while this animation is being mixed out. */ public var eventThreshold:Float = 0; + /** When the mix percentage (TrackEntry.getMixTime() / TrackEntry.getMixDuration()) is less than the + * mixAttachmentThreshold, attachment timelines are applied while this animation is being mixed out. Defaults + * to 0, so attachment timelines are not applied while this animation is being mixed out. */ public var mixAttachmentThreshold:Float = 0; + /** When TrackEntry.getAlpha() is greater than alphaAttachmentThreshold, attachment timelines are applied. + * Defaults to 0, so attachment timelines are always applied. */ public var alphaAttachmentThreshold:Float = 0; + /** When the mix percentage (TrackEntry.getMixTime() / TrackEntry.getMixDuration()) is less than the + * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to + * 0, so draw order timelines are not applied while this animation is being mixed out. */ public var mixDrawOrderThreshold:Float = 0; + /** Seconds when this animation starts, both initially and after looping. Defaults to 0. + * + * When changing the animationStart time, it often makes sense to set TrackEntry.getAnimationLast() to the same + * value to prevent timeline keys before the start time from triggering. */ public var animationStart:Float = 0; + /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + * loop back to TrackEntry.getAnimationStart() at this time. Defaults to the animation spine.animation.Animation.duration. */ public var animationEnd:Float = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + * animation is applied, event timelines will fire all events between the animationLast time (exclusive) and + * animationTime (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation + * is applied. */ public var animationLast:Float = 0; public var nextAnimationLast:Float = 0; /** Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry, - * delay postpones incrementing the {@link #getTrackTime()}. When this track entry is queued, - * delay is the time from the start of the previous animation to when this track entry will become the current - * track entry (ie when the previous track entry {@link TrackEntry#getTrackTime()} >= this track entry's - * delay). - *

- * {@link #getTimeScale()} affects the delay. - *

- * When passing delay <= 0 to {@link AnimationState#addAnimation(int, Animation, boolean, float)} this - * delay is set using a mix duration from {@link AnimationStateData}. To change the {@link #getMixDuration()} - * afterward, use {@link #setMixDuration(float, float)} so this delay is adjusted. */ + * delay postpones incrementing the TrackEntry.getTrackTime(). When this track entry is queued, + * delay is the time from the start of the previous animation to when this track entry will become the current + * track entry (ie when the previous track entry TrackEntry.getTrackTime() >= this track entry's + * delay). + * + * TrackEntry.getTimeScale() affects the delay. + * + * When passing delay <= 0 to spine.animation.AnimationState.addAnimation(int, Animation, boolean, float) this + * delay is set using a mix duration from spine.animation.AnimationStateData. To change the TrackEntry.getMixDuration() + * afterward, use TrackEntry.setMixDuration(float, float) so this delay is adjusted. */ public var delay(default, set):Float = 0; + /** Current time in seconds this track entry has been the current track entry. The track time determines + * TrackEntry.getAnimationTime(). The track time can be set to start the animation at a time other than 0, without affecting + * looping. */ public var trackTime:Float = 0; public var trackLast:Float = 0; public var nextTrackLast:Float = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * It may be desired to use spine.animation.AnimationState.addEmptyAnimation(int, float, float) rather than have the animation + * abruptly cease being applied. */ public var trackEnd:Float = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * Values < 0 are not supported. To play an animation in reverse, use TrackEntry.getReverse(). + * + * TrackEntry.getMixTime() is not affected by track entry time scale, so TrackEntry.getMixDuration() may need to be adjusted to + * match the animation speed. + * + * When using spine.animation.AnimationState.addAnimation(int, Animation, boolean, float) with a delay <= 0, the + * TrackEntry.getDelay() is set using the mix duration from the spine.animation.AnimationStateData, assuming time scale to be 1. If + * the time scale is not 1, the delay may need to be adjusted. + * + * See AnimationState spine.animation.AnimationState.getTimeScale() for affecting all animations. */ public var timeScale:Float = 0; + /** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults + * to 1, which overwrites the skeleton's current pose with this animation. + * + * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to + * use alpha on track 0 if the skeleton pose is from the last frame render. */ public var alpha:Float = 0; + /** Seconds from 0 to the TrackEntry.getMixDuration() when mixing from the previous animation to this animation. May be + * slightly more than mixDuration when the mix is complete. */ public var mixTime:Float = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData + * spine.animation.AnimationStateData.getMix(Animation, Animation) based on the animation before this animation (if any). + * + * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the + * properties it was animating. A mix duration of 0 can be set at any time to end the mix on the next + * spine.animation.AnimationState.update(float) update. + * + * The mixDuration can be set manually rather than use the value from + * spine.animation.AnimationStateData.getMix(Animation, Animation). In that case, the mixDuration can be set for a new + * track entry only before spine.animation.AnimationState.update(float) is first called. + * + * When using spine.animation.AnimationState.addAnimation(int, Animation, boolean, float) with a delay <= 0, the + * TrackEntry.getDelay() is set using the mix duration from the spine.animation.AnimationStateData. If mixDuration is set + * afterward, the delay may need to be adjusted. For example: + * entry.delay = entry.previous.getTrackComplete() - entry.mixDuration; + * Alternatively, TrackEntry.setMixDuration(float, float) can be used to recompute the delay: + * entry.setMixDuration(0.25f, 0); */ public var mixDuration:Float = 0; public var interruptAlpha:Float = 0; public var totalAlpha:Float = 0; + /** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to spine.animation.MixBlend.replace. + * + * Track entries on track 0 ignore this setting and always use spine.animation.MixBlend.first. + * + * The mixBlend can be set for a new track entry only before spine.animation.AnimationState.apply(Skeleton) is first + * called. */ public var mixBlend:MixBlend = MixBlend.replace; public var timelineMode:Array = new Array(); public var timelineHoldMix:Array = new Array(); public var timelinesRotation:Array = new Array(); + /** If true, mixing rotation between tracks always uses the shortest rotation direction. If the rotation is animated, the + * shortest rotation direction may change during the mix. + * + * If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest + * of the mix. Defaults to false. */ public var shortestRotation = false; function set_delay(delay:Float):Float { @@ -93,6 +202,12 @@ class TrackEntry implements Poolable { public function new() {} + /** Uses TrackEntry.getTrackTime() to compute the animationTime. When the trackTime is 0, the + * animationTime is equal to the animationStart time. + * + * The animationTime is between TrackEntry.getAnimationStart() and TrackEntry.getAnimationEnd(), except if this + * track entry is non-looping and TrackEntry.getAnimationEnd() is >= to the animation spine.animation.Animation.duration, then + * animationTime continues to increase past TrackEntry.getAnimationEnd(). */ public function getAnimationTime():Float { if (loop) { var duration:Float = animationEnd - animationStart; @@ -103,9 +218,9 @@ class TrackEntry implements Poolable { return Math.min(trackTime + animationStart, animationEnd); } - /** If this track entry is non-looping, the track time in seconds when {@link #getAnimationEnd()} is reached, or the current - * {@link #getTrackTime()} if it has already been reached. If this track entry is looping, the track time when this - * animation will reach its next {@link #getAnimationEnd()} (the next loop completion). */ + /** If this track entry is non-looping, the track time in seconds when TrackEntry.getAnimationEnd() is reached, or the current + * TrackEntry.getTrackTime() if it has already been reached. If this track entry is looping, the track time when this + * animation will reach its next TrackEntry.getAnimationEnd() (the next loop completion). */ public function getTrackComplete():Float { var duration:Float = animationEnd - animationStart; if (duration != 0) { @@ -118,14 +233,14 @@ class TrackEntry implements Poolable { } /** Returns true if this track entry has been applied at least once. - *

- * See {@link AnimationState#apply(Skeleton)}. */ + * + * See spine.animation.AnimationState.apply(Skeleton). */ public function wasApplied() { return nextTrackLast != -1; } - /** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next - * {@link AnimationState#update(float)}. */ + /** Returns true if there is a TrackEntry.getNext() track entry and it will become the current track entry during the next + * spine.animation.AnimationState.update(float). */ public function isNextReady():Bool { return next != null && nextTrackLast - next.delay >= 0; } @@ -147,10 +262,22 @@ class TrackEntry implements Poolable { timelinesRotation.resize(0); } + /** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + * long way around when using TrackEntry.getAlpha() and starting animations on other tracks. + * + * Mixing with spine.animation.MixBlend.replace involves finding a rotation between two others, which has two possible solutions: + * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long + * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the + * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */ public function resetRotationDirection():Void { timelinesRotation.resize(0); } + /** Sets both TrackEntry.getMixDuration() and TrackEntry.getDelay(). + * @param mixDuration If > 0, sets TrackEntry.getDelay(). If <= 0, the delay set is the duration of the previous track + * entry minus the specified mix duration plus the specified delay (ie the mix ends at + * (delay = 0) or before (delay < 0) the previous track entry duration). If the previous + * entry is looping, its next loop completion is used instead of its duration. */ public function setMixDurationWithDelay(mixDuration:Float):Float { this.mixDuration = mixDuration; if (delay <= 0) { diff --git a/spine-haxe/spine-haxe/spine/animation/TransformConstraintTimeline.hx b/spine-haxe/spine-haxe/spine/animation/TransformConstraintTimeline.hx index 1727e9141..4c2893a8b 100644 --- a/spine-haxe/spine-haxe/spine/animation/TransformConstraintTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/TransformConstraintTimeline.hx @@ -34,6 +34,9 @@ import spine.Skeleton; import spine.TransformConstraint; import spine.TransformConstraintData; +/** Changes a transform constraint's spine.TransformConstraint.mixRotate, spine.TransformConstraint.mixX, + * spine.TransformConstraint.mixY, spine.TransformConstraint.mixScaleX, + * spine.TransformConstraint.mixScaleY, and spine.TransformConstraint.mixShearY. */ class TransformConstraintTimeline extends CurveTimeline { static public inline var ENTRIES:Int = 7; private static inline var ROTATE:Int = 1; @@ -43,7 +46,8 @@ class TransformConstraintTimeline extends CurveTimeline { private static inline var SCALEY:Int = 5; private static inline var SHEARY:Int = 6; - /** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */ + /** The index of the transform constraint in spine.Skeleton.transformConstraints that will be changed when this + * timeline is applied. */ public var constraintIndex:Int = 0; public function new(frameCount:Int, bezierCount:Int, transformConstraintIndex:Int) { @@ -55,7 +59,9 @@ class TransformConstraintTimeline extends CurveTimeline { return ENTRIES; } - /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */ + /** Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ public function setFrame(frame:Int, time:Float, mixRotate:Float, mixX:Float, mixY:Float, mixScaleX:Float, mixScaleY:Float, mixShearY:Float):Void { frame *= ENTRIES; frames[frame] = time; diff --git a/spine-haxe/spine-haxe/spine/animation/TranslateTimeline.hx b/spine-haxe/spine-haxe/spine/animation/TranslateTimeline.hx index 8fa040470..e49dbaaa0 100644 --- a/spine-haxe/spine-haxe/spine/animation/TranslateTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/TranslateTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local spine.Bone.x and spine.Bone.y. */ class TranslateTimeline extends CurveTimeline2 implements BoneTimeline { public var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/TranslateXTimeline.hx b/spine-haxe/spine-haxe/spine/animation/TranslateXTimeline.hx index 46a94f218..d09afac27 100644 --- a/spine-haxe/spine-haxe/spine/animation/TranslateXTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/TranslateXTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local spine.Bone.x. */ class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline { public var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/animation/TranslateYTimeline.hx b/spine-haxe/spine-haxe/spine/animation/TranslateYTimeline.hx index 0339c48cf..d2ee9e757 100644 --- a/spine-haxe/spine-haxe/spine/animation/TranslateYTimeline.hx +++ b/spine-haxe/spine-haxe/spine/animation/TranslateYTimeline.hx @@ -33,6 +33,7 @@ import spine.Bone; import spine.Event; import spine.Skeleton; +/** Changes a bone's local y translation. */ class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline { public var boneIndex:Int = 0; diff --git a/spine-haxe/spine-haxe/spine/atlas/TextureLoader.hx b/spine-haxe/spine-haxe/spine/atlas/TextureLoader.hx index c819a2ba6..04fd792bb 100644 --- a/spine-haxe/spine-haxe/spine/atlas/TextureLoader.hx +++ b/spine-haxe/spine-haxe/spine/atlas/TextureLoader.hx @@ -29,10 +29,18 @@ package spine.atlas; +/** The interface which can be implemented to customize loading images for texture atlas pages and regions. */ interface TextureLoader { + /** Loads a texture atlas page. + * @param page The page to load. + * @param path The path to the page image. */ function loadPage(page:TextureAtlasPage, path:String):Void; + /** Loads a texture atlas region. + * @param region The region to load. */ function loadRegion(region:TextureAtlasRegion):Void; + /** Unloads a texture atlas page. + * @param page The page to unload. */ function unloadPage(page:TextureAtlasPage):Void; } diff --git a/spine-haxe/spine-haxe/spine/attachments/AtlasAttachmentLoader.hx b/spine-haxe/spine-haxe/spine/attachments/AtlasAttachmentLoader.hx index 7f5899ef9..b9e7a7e04 100644 --- a/spine-haxe/spine-haxe/spine/attachments/AtlasAttachmentLoader.hx +++ b/spine-haxe/spine-haxe/spine/attachments/AtlasAttachmentLoader.hx @@ -32,6 +32,11 @@ package spine.attachments; import spine.atlas.TextureAtlas; import spine.Skin; +/** + * The interface which can be implemented to customize creating and populating attachments. + * + * @see https://esotericsoftware.com/spine-loading-skeleton-data#AttachmentLoader Loading skeleton data in the Spine Runtimes Guide + */ class AtlasAttachmentLoader implements AttachmentLoader { private var atlas:TextureAtlas; @@ -53,6 +58,9 @@ class AtlasAttachmentLoader implements AttachmentLoader { } } + /** + * @return May be null to not load the attachment. + */ public function newRegionAttachment(skin:Skin, name:String, path:String, sequence:Sequence):RegionAttachment { var attachment = new RegionAttachment(name, path); if (sequence != null) { @@ -66,6 +74,9 @@ class AtlasAttachmentLoader implements AttachmentLoader { return attachment; } + /** + * @return May be null to not load the attachment. In that case null should also be returned for child meshes. + */ public function newMeshAttachment(skin:Skin, name:String, path:String, sequence:Sequence):MeshAttachment { var attachment = new MeshAttachment(name, path); if (sequence != null) { @@ -79,18 +90,30 @@ class AtlasAttachmentLoader implements AttachmentLoader { return attachment; } + /** + * @return May be null to not load the attachment. + */ public function newBoundingBoxAttachment(skin:Skin, name:String):BoundingBoxAttachment { return new BoundingBoxAttachment(name); } + /** + * @return May be null to not load the attachment. + */ public function newPathAttachment(skin:Skin, name:String):PathAttachment { return new PathAttachment(name); } + /** + * @return May be null to not load the attachment. + */ public function newPointAttachment(skin:Skin, name:String):PointAttachment { return new PointAttachment(name); } + /** + * @return May be null to not load the attachment. + */ public function newClippingAttachment(skin:Skin, name:String):ClippingAttachment { return new ClippingAttachment(name); } diff --git a/spine-haxe/spine-haxe/spine/attachments/Attachment.hx b/spine-haxe/spine-haxe/spine/attachments/Attachment.hx index b2de17a4f..81e3a7665 100644 --- a/spine-haxe/spine-haxe/spine/attachments/Attachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/Attachment.hx @@ -29,6 +29,7 @@ package spine.attachments; +/** The base class for all attachments. */ class Attachment { private var _name:String; @@ -39,6 +40,7 @@ class Attachment { _name = name; } + /** The attachment's name. */ public var name(get, never):String; private function get_name():String { @@ -49,6 +51,7 @@ class Attachment { return name; } + /** Returns a copy of the attachment. */ public function copy():Attachment { throw new SpineException("Not implemented"); } diff --git a/spine-haxe/spine-haxe/spine/attachments/AttachmentLoader.hx b/spine-haxe/spine-haxe/spine/attachments/AttachmentLoader.hx index 35c8fc324..147e124bb 100644 --- a/spine-haxe/spine-haxe/spine/attachments/AttachmentLoader.hx +++ b/spine-haxe/spine-haxe/spine/attachments/AttachmentLoader.hx @@ -31,22 +31,26 @@ package spine.attachments; import spine.Skin; +/** The interface which can be implemented to customize creating and populating attachments. + * + * @see https://esotericsoftware.com/spine-loading-skeleton-data#AttachmentLoader Loading skeleton data in the Spine Runtimes Guide + */ interface AttachmentLoader { - /** @return May be null to not load an attachment. */ + /** @return May be null to not load the attachment. */ function newRegionAttachment(skin:Skin, name:String, path:String, sequence:Sequence):RegionAttachment; - /** @return May be null to not load an attachment. */ + /** @return May be null to not load the attachment. In that case null should also be returned for child meshes. */ function newMeshAttachment(skin:Skin, name:String, path:String, sequence:Sequence):MeshAttachment; - /** @return May be null to not load an attachment. */ + /** @return May be null to not load the attachment. */ function newBoundingBoxAttachment(skin:Skin, name:String):BoundingBoxAttachment; - /** @return May be null to not load an attachment */ + /** @return May be null to not load the attachment. */ function newPathAttachment(skin:Skin, name:String):PathAttachment; - /** @return May be null to not load an attachment */ + /** @return May be null to not load the attachment. */ function newPointAttachment(skin:Skin, name:String):PointAttachment; - /** @return May be null to not load an attachment */ + /** @return May be null to not load the attachment. */ function newClippingAttachment(skin:Skin, name:String):ClippingAttachment; } diff --git a/spine-haxe/spine-haxe/spine/attachments/AttachmentType.hx b/spine-haxe/spine-haxe/spine/attachments/AttachmentType.hx index 4e56b3fad..52ca24857 100644 --- a/spine-haxe/spine-haxe/spine/attachments/AttachmentType.hx +++ b/spine-haxe/spine-haxe/spine/attachments/AttachmentType.hx @@ -29,6 +29,9 @@ package spine.attachments; +/** + * The type of attachment. + */ class AttachmentType { public static var region(default, never):AttachmentType = new AttachmentType(0, "region"); public static var boundingbox(default, never):AttachmentType = new AttachmentType(1, "boundingbox"); diff --git a/spine-haxe/spine-haxe/spine/attachments/BoundingBoxAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/BoundingBoxAttachment.hx index 0cd3f0c80..e799a6b4b 100644 --- a/spine-haxe/spine-haxe/spine/attachments/BoundingBoxAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/BoundingBoxAttachment.hx @@ -31,7 +31,15 @@ package spine.attachments; import spine.Color; +/** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle + * effects, and more. + * + * @see SkeletonBounds + * @see https://esotericsoftware.com/spine-bounding-boxes Bounding Boxes in the Spine User Guide + */ class BoundingBoxAttachment extends VertexAttachment { + /** The color of the bounding box as it was in Spine, or a default color if nonessential data was not exported. Bounding boxes + * are not usually rendered at runtime. */ public var color:Color = new Color(0, 0, 0, 0); public function new(name:String) { diff --git a/spine-haxe/spine-haxe/spine/attachments/ClippingAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/ClippingAttachment.hx index d161a1b13..c2ff9604f 100644 --- a/spine-haxe/spine-haxe/spine/attachments/ClippingAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/ClippingAttachment.hx @@ -32,8 +32,13 @@ package spine.attachments; import spine.Color; import spine.SlotData; +/** An attachment with vertices that make up a polygon used for clipping the rendering of other attachments. */ class ClippingAttachment extends VertexAttachment { + /** Clipping is performed between the clipping attachment's slot and the end slot. If null clipping is done until the end of + * the skeleton's rendering. */ public var endSlot:SlotData; + /** The color of the clipping attachment as it was in Spine, or a default color if nonessential data was not exported. Clipping + * attachments are not usually rendered at runtime. */ public var color:Color = new Color(0.2275, 0.2275, 0.2275, 1); public function new(name:String) { diff --git a/spine-haxe/spine-haxe/spine/attachments/MeshAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/MeshAttachment.hx index 6f23a201c..d5ac32222 100644 --- a/spine-haxe/spine-haxe/spine/attachments/MeshAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/MeshAttachment.hx @@ -33,27 +33,46 @@ import spine.Color; import spine.atlas.TextureAtlasRegion; import spine.atlas.TextureAtlasPage; +/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not + * supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh. + * + * @see https://esotericsoftware.com/spine-meshes Mesh attachments in the Spine User Guide */ class MeshAttachment extends VertexAttachment implements HasTextureRegion { public var region:TextureRegion; public var path:String; + /** The UV pair for each vertex, normalized within the texture region. */ public var regionUVs = new Array(); + /** The UV pair for each vertex, normalized within the entire texture. + * See #updateRegion(). */ public var uvs = new Array(); + /** Triplets of vertex indices which describe the mesh's triangulation. */ public var triangles = new Array(); public var color:Color = new Color(1, 1, 1, 1); + /** The width of the mesh's image, or zero if nonessential data was not exported. */ public var width:Float = 0; + /** The height of the mesh's image, or zero if nonessential data was not exported. */ public var height:Float = 0; + /** The number of entries at the beginning of #vertices that make up the mesh hull. */ public var hullLength:Int = 0; + /** Vertex index pairs describing edges for controlling triangulation, or null if nonessential data was not exported. Mesh + * triangles will never cross edges. Triangulation is not performed at runtime. */ public var edges = new Array(); public var rendererObject:Dynamic; public var sequence:Sequence; + /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the #bones, #vertices, + * #regionUVs, #triangles, #hullLength, #edges, #width, and #height with the + * parent mesh, but may have a different #name or #path (and therefore a different texture). */ private var _parentMesh:MeshAttachment; + /** Copy constructor. Use newLinkedMesh() if the other mesh is a linked mesh. */ public function new(name:String, path:String) { super(name); this.path = path; } + /** Calculates uvs using the regionUVs and region. Must be called if the region, the region's properties, or + * the regionUVs are changed. */ public function updateRegion():Void { if (region == null) { throw new SpineException("Region not set."); @@ -174,12 +193,14 @@ class MeshAttachment extends VertexAttachment implements HasTextureRegion { return copy; } + /** If the attachment has a sequence, the region may be changed. */ public override function computeWorldVertices(slot:Slot, start:Int, count:Int, worldVertices:Array, offset:Int, stride:Int):Void { if (sequence != null) sequence.apply(slot, this); super.computeWorldVertices(slot, start, count, worldVertices, offset, stride); } + /** Returns a new mesh with the parentMesh set to this mesh's parent mesh, if any, else to this mesh. */ public function newLinkedMesh():MeshAttachment { var copy:MeshAttachment = new MeshAttachment(name, path); copy.rendererObject = rendererObject; diff --git a/spine-haxe/spine-haxe/spine/attachments/PathAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/PathAttachment.hx index 5a5d43020..1843d4ccb 100644 --- a/spine-haxe/spine-haxe/spine/attachments/PathAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/PathAttachment.hx @@ -31,10 +31,21 @@ package spine.attachments; import spine.Color; +/** An attachment whose vertices make up a composite Bezier curve. + * + * @see PathConstraint + * @see https://esotericsoftware.com/spine-paths Paths in the Spine User Guide + */ class PathAttachment extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ public var lengths:Array; + /** If true, the start and end knots are connected. */ public var closed:Bool = false; + /** If true, additional calculations are performed to make computing positions along the path more accurate and movement along + * the path have a constant speed. */ public var constantSpeed:Bool = false; + /** The color of the path as it was in Spine, or a default color if nonessential data was not exported. Paths are not usually + * rendered at runtime. */ public var color:Color = new Color(0, 0, 0, 0); public function new(name:String) { diff --git a/spine-haxe/spine-haxe/spine/attachments/PointAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/PointAttachment.hx index daaa7ffad..6cf369690 100644 --- a/spine-haxe/spine-haxe/spine/attachments/PointAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/PointAttachment.hx @@ -33,12 +33,20 @@ import spine.Bone; import spine.Color; import spine.MathUtils; +/** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + * used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + * skin. + * + * @see https://esotericsoftware.com/spine-points Point Attachments in the Spine User Guide */ class PointAttachment extends VertexAttachment { public var x:Float = 0; public var y:Float = 0; public var rotation:Float = 0; + /** The color of the point attachment as it was in Spine, or a default color if nonessential data was not exported. Point + * attachments are not usually rendered at runtime. */ public var color:Color = new Color(0.38, 0.94, 0, 1); + /** Copy constructor. */ public function new(name:String) { super(name); } diff --git a/spine-haxe/spine-haxe/spine/attachments/RegionAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/RegionAttachment.hx index 2deb2b2a9..b4a8d9c44 100644 --- a/spine-haxe/spine-haxe/spine/attachments/RegionAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/RegionAttachment.hx @@ -31,6 +31,10 @@ package spine.attachments; import spine.Color; +/** An attachment that displays a textured quadrilateral. + * + * @see https://esotericsoftware.com/spine-regions Region attachments in the Spine User Guide + */ class RegionAttachment extends Attachment implements HasTextureRegion { public static inline var BLX:Int = 0; public static inline var BLY:Int = 1; @@ -41,12 +45,19 @@ class RegionAttachment extends Attachment implements HasTextureRegion { public static inline var BRX:Int = 6; public static inline var BRY:Int = 7; + /** The local x translation. */ public var x:Float = 0; + /** The local y translation. */ public var y:Float = 0; + /** The local scaleX. */ public var scaleX:Float = 1; + /** The local scaleY. */ public var scaleY:Float = 1; + /** The local rotation. */ public var rotation:Float = 0; + /** The width of the region attachment in Spine. */ public var width:Float = 0; + /** The height of the region attachment in Spine. */ public var height:Float = 0; public var color:Color = new Color(1, 1, 1, 1); public var path:String; @@ -54,15 +65,24 @@ class RegionAttachment extends Attachment implements HasTextureRegion { public var region:TextureRegion; public var sequence:Sequence; + /** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex. + * + * See RegionAttachment.updateRegion(). */ private var offsets:Array = new Array(); public var uvs:Array = new Array(); + /** + * @param name The attachment name. + * @param path The path used to find the region for the attachment. + */ public function new(name:String, path:String) { super(name); this.path = path; } + /** Calculates the RegionAttachment.offsets and RegionAttachment.uvs using the region and the attachment's transform. Must be called if the + * region, the region's properties, or the transform are changed. */ public function updateRegion():Void { if (region == null) { throw new SpineException("Region not set."); @@ -126,6 +146,13 @@ class RegionAttachment extends Attachment implements HasTextureRegion { } } + /** Transforms the attachment's four vertices to world coordinates. If the attachment has a RegionAttachment.sequence, the region may + * be changed. + * + * @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide + * @param worldVertices The output world vertices. Must have a length >= offset + 8. + * @param offset The worldVertices index to begin writing values. + * @param stride The number of worldVertices entries between the value pairs written. */ public function computeWorldVertices(slot:Slot, worldVertices:Array, offset:Int, stride:Int):Void { if (sequence != null) sequence.apply(slot, this); diff --git a/spine-haxe/spine-haxe/spine/attachments/VertexAttachment.hx b/spine-haxe/spine-haxe/spine/attachments/VertexAttachment.hx index b22654c76..d4e5a8601 100644 --- a/spine-haxe/spine-haxe/spine/attachments/VertexAttachment.hx +++ b/spine-haxe/spine-haxe/spine/attachments/VertexAttachment.hx @@ -33,13 +33,26 @@ import spine.Bone; import spine.Skeleton; import spine.Slot; +/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's + * spine.Slot.deform. */ class VertexAttachment extends Attachment { private static var nextID:Int = 0; + /** The bones which affect the vertices. The array entries are, for each vertex, the number of bones affecting + * the vertex followed by that many bone indices, which is the index of the bone in spine.Skeleton.bones. Will be null + * if this attachment has no weights. */ public var bones:Array; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting + * each vertex. */ public var vertices = new Array(); + /** The maximum number of world vertex values that can be output by + * computeWorldVertices() using the `count` parameter. */ public var worldVerticesLength:Int = 0; + /** Returns a unique ID for this attachment. */ public var id:Int = nextID++; + /** Timelines for the timeline attachment are also applied to this attachment. + * May be null if no attachment-specific timelines should be applied. */ public var timelineAttachment:VertexAttachment; public function new(name:String) { @@ -47,13 +60,12 @@ class VertexAttachment extends Attachment { timelineAttachment = this; } - /** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is + /** Transforms the attachment's local vertices to world coordinates. If the slot's spine.Slot.deform is * not empty, it is used to deform the vertices. * - * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine - * Runtimes Guide. - * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y. - * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`. + * @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide + * @param start The index of the first vertices value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= worldVerticesLength - `start`. * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * * `stride` / 2. * @param offset The `worldVertices` index to begin writing values. @@ -149,6 +161,7 @@ class VertexAttachment extends Attachment { } } + /** Copy this attachment's data to another attachment. */ public function copyTo(attachment:VertexAttachment):Void { if (bones != null) { attachment.bones = bones.copy(); diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx index 6c11901cd..fffd5be30 100644 --- a/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx @@ -31,8 +31,9 @@ package spine.flixel; import flixel.FlxStrip; -// this class is just to make the implementation coherent with the starling implementation +/** A FlxStrip that draws a skeleton. This class is just to make the implementation coherent with the starling implementation. */ class SkeletonMesh extends FlxStrip { + /** Creates an uninitialized SkeletonMesh. */ public function new(/*texture:FlxGraphicAsset*/) { super(); // graphic = texture; diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx index 729697c81..1730b2c29 100644 --- a/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx @@ -62,6 +62,7 @@ import spine.attachments.RegionAttachment; 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 { public var skeleton(default, null):Skeleton; @@ -92,6 +93,7 @@ class SkeletonSprite extends FlxObject private var _tempPoint = new Point(); private static var QUAD_INDICES:Array = [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) { super(0, 0); diff --git a/spine-haxe/spine-haxe/spine/starling/SkeletonMesh.hx b/spine-haxe/spine-haxe/spine/starling/SkeletonMesh.hx index 605e6b1e3..95d03777b 100644 --- a/spine-haxe/spine-haxe/spine/starling/SkeletonMesh.hx +++ b/spine-haxe/spine-haxe/spine/starling/SkeletonMesh.hx @@ -35,7 +35,9 @@ import starling.rendering.VertexData; import starling.styles.MeshStyle; import starling.textures.Texture; +/** A Starling Mesh that draws a skeleton. */ class SkeletonMesh extends Mesh { + /** Creates a SkeletonMesh with the specified texture and optional vertex, index data and style. */ public function new(texture:Texture, vertexData:VertexData = null, indexData:IndexData = null, style:MeshStyle = null) { super(vertexData == null ? new VertexData() : vertexData, indexData == null ? new IndexData() : indexData, style); this.texture = texture; diff --git a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx index 1b2f714de..8a60d8534 100644 --- a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx +++ b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx @@ -57,6 +57,7 @@ import starling.utils.Color; import starling.utils.MatrixUtil; import starling.utils.Max; +/** A starling display object that draws a skeleton. */ class SkeletonSprite extends DisplayObject implements IAnimatable { static private var _tempPoint:Point = new Point(); static private var _tempMatrix:Matrix = new Matrix(); @@ -78,6 +79,7 @@ class SkeletonSprite extends DisplayObject implements IAnimatable { 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) { super(); Bone.yDown = true; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java index a07833667..2fb9fb78a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java @@ -98,7 +98,7 @@ public class Event { return time; } - /** The events's setup pose data. */ + /** The event's setup pose data. */ public EventData getData () { return data; } diff --git a/spine-monogame/spine-monogame/src/SkeletonRenderer.cs b/spine-monogame/spine-monogame/src/SkeletonRenderer.cs index 0882f0603..8698813d3 100644 --- a/spine-monogame/spine-monogame/src/SkeletonRenderer.cs +++ b/spine-monogame/spine-monogame/src/SkeletonRenderer.cs @@ -132,6 +132,7 @@ namespace Spine { float attachmentColorR, attachmentColorG, attachmentColorB, attachmentColorA; object textureObject = null; int verticesCount = 0; + float[] vertices = this.vertices; int indicesCount = 0; int[] indices = null; float[] uvs = null; @@ -150,7 +151,7 @@ namespace Spine { MeshAttachment mesh = (MeshAttachment)attachment; attachmentColorR = mesh.R; attachmentColorG = mesh.G; attachmentColorB = mesh.B; attachmentColorA = mesh.A; int vertexCount = mesh.WorldVerticesLength; - if (vertices.Length < vertexCount) vertices = new float[vertexCount]; + if (vertices.Length < vertexCount) this.vertices = vertices = new float[vertexCount]; verticesCount = vertexCount >> 1; mesh.ComputeWorldVertices(slot, vertices); indicesCount = mesh.Triangles.Length; @@ -210,10 +211,9 @@ namespace Spine { darkColor.A = premultipliedAlpha ? (byte)255 : (byte)0; // clip - float[] usedVertices = vertices; if (clipper.IsClipping) { - clipper.ClipTriangles(usedVertices, indices, indicesCount, uvs); - usedVertices = clipper.ClippedVertices.Items; + clipper.ClipTriangles(vertices, indices, indicesCount, uvs); + vertices = clipper.ClippedVertices.Items; verticesCount = clipper.ClippedVertices.Count >> 1; indices = clipper.ClippedTriangles.Items; indicesCount = clipper.ClippedTriangles.Count; @@ -240,8 +240,8 @@ namespace Spine { for (int ii = 0, v = 0, nn = verticesCount << 1; v < nn; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Color2 = darkColor; - itemVertices[ii].Position.X = usedVertices[v]; - itemVertices[ii].Position.Y = usedVertices[v + 1]; + itemVertices[ii].Position.X = vertices[v]; + itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = attachmentZOffset; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; diff --git a/spine-ts/index.html b/spine-ts/index.html index 430632b05..c625f53e8 100644 --- a/spine-ts/index.html +++ b/spine-ts/index.html @@ -200,6 +200,7 @@

  • App
  • Login
  • Game
  • +
  • Dispose
  • GUI
  • diff --git a/spine-ts/spine-phaser-v3/LICENSE b/spine-ts/spine-phaser-v3/LICENSE index 4501a611f..d03d3caed 100644 --- a/spine-ts/spine-phaser-v3/LICENSE +++ b/spine-ts/spine-phaser-v3/LICENSE @@ -1,7 +1,7 @@ Spine Runtimes License Agreement -Last updated May 1, 2019. Replaces all prior versions. +Last updated April 5, 2025. Replaces all prior versions. -Copyright (c) 2013-2019, Esoteric Software LLC +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 @@ -14,13 +14,13 @@ or otherwise create derivative works of the Spine Runtimes (collectively, Spine Editor license and redistribution of the Products in any form must include this license and copyright notice. -THIS SOFTWARE IS 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 THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +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. diff --git a/spine-ts/spine-phaser-v3/src/SpineGameObject.ts b/spine-ts/spine-phaser-v3/src/SpineGameObject.ts index 45495a964..f5fa9a204 100644 --- a/spine-ts/spine-phaser-v3/src/SpineGameObject.ts +++ b/spine-ts/spine-phaser-v3/src/SpineGameObject.ts @@ -1,16 +1,16 @@ /****************************************************************************** * Spine Runtimes License Agreement - * Last updated July 28, 2023. Replaces all prior versions. + * Last updated April 5, 2025. Replaces all prior versions. * - * Copyright (c) 2013-2023, Esoteric Software LLC + * 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, + * 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. @@ -23,8 +23,8 @@ * (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. + * (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. *****************************************************************************/ import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; diff --git a/spine-ts/spine-phaser-v3/src/keys.ts b/spine-ts/spine-phaser-v3/src/keys.ts index f8d01d223..c040c7802 100644 --- a/spine-ts/spine-phaser-v3/src/keys.ts +++ b/spine-ts/spine-phaser-v3/src/keys.ts @@ -1,16 +1,16 @@ /****************************************************************************** * Spine Runtimes License Agreement - * Last updated July 28, 2023. Replaces all prior versions. + * Last updated April 5, 2025. Replaces all prior versions. * - * Copyright (c) 2013-2023, Esoteric Software LLC + * 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, + * 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. @@ -23,8 +23,8 @@ * (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. + * (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. *****************************************************************************/ export const SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache"; diff --git a/spine-ts/spine-phaser-v3/src/require-shim.ts b/spine-ts/spine-phaser-v3/src/require-shim.ts index 74db2197f..8644aa40b 100644 --- a/spine-ts/spine-phaser-v3/src/require-shim.ts +++ b/spine-ts/spine-phaser-v3/src/require-shim.ts @@ -1,16 +1,16 @@ /****************************************************************************** * Spine Runtimes License Agreement - * Last updated July 28, 2023. Replaces all prior versions. + * Last updated April 5, 2025. Replaces all prior versions. * - * Copyright (c) 2013-2023, Esoteric Software LLC + * 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, + * 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. @@ -23,8 +23,8 @@ * (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. + * (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. *****************************************************************************/ if (typeof window !== 'undefined' && window.Phaser) { diff --git a/spine-ts/spine-phaser-v4/src/SpinePlugin.ts b/spine-ts/spine-phaser-v4/src/SpinePlugin.ts index 39dc6b514..5841f685e 100644 --- a/spine-ts/spine-phaser-v4/src/SpinePlugin.ts +++ b/spine-ts/spine-phaser-v4/src/SpinePlugin.ts @@ -1,16 +1,16 @@ /****************************************************************************** * Spine Runtimes License Agreement - * Last updated July 28, 2023. Replaces all prior versions. + * Last updated April 5, 2025. Replaces all prior versions. * - * Copyright (c) 2013-2023, Esoteric Software LLC + * 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, + * 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. @@ -23,8 +23,8 @@ * (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. + * (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. *****************************************************************************/ import * as Phaser from "phaser"; diff --git a/spine-ts/spine-pixi-v8/src/index.ts b/spine-ts/spine-pixi-v8/src/index.ts index 6882f62e6..921bab630 100644 --- a/spine-ts/spine-pixi-v8/src/index.ts +++ b/spine-ts/spine-pixi-v8/src/index.ts @@ -1,3 +1,32 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated September 24, 2021. Replaces all prior versions. + * + * Copyright (c) 2013-2021, 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. + *****************************************************************************/ + import './require-shim.js'; // Side effects add require pixi.js to global scope import './assets/atlasLoader.js'; // Side effects install the loaders into pixi import './assets/skeletonLoader.js'; // Side effects install the loaders into pixi diff --git a/spine-ts/spine-webcomponents/LICENSE b/spine-ts/spine-webcomponents/LICENSE index 4501a611f..d03d3caed 100644 --- a/spine-ts/spine-webcomponents/LICENSE +++ b/spine-ts/spine-webcomponents/LICENSE @@ -1,7 +1,7 @@ Spine Runtimes License Agreement -Last updated May 1, 2019. Replaces all prior versions. +Last updated April 5, 2025. Replaces all prior versions. -Copyright (c) 2013-2019, Esoteric Software LLC +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 @@ -14,13 +14,13 @@ or otherwise create derivative works of the Spine Runtimes (collectively, Spine Editor license and redistribution of the Products in any form must include this license and copyright notice. -THIS SOFTWARE IS 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 THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +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. diff --git a/spine-ts/spine-webcomponents/example/app.html b/spine-ts/spine-webcomponents/example/app.html index 6589edc11..72bac282c 100644 --- a/spine-ts/spine-webcomponents/example/app.html +++ b/spine-ts/spine-webcomponents/example/app.html @@ -112,7 +112,7 @@ border: none; background: #007bff; color: white; - cursor: pointer; + pointer: pointer; border-radius: 3px; margin: 1px 0; } @@ -151,7 +151,7 @@ border: none; background: #dc3545; color: white; - cursor: pointer; + pointer: pointer; } .btn.next { @@ -175,7 +175,7 @@ align-items: center; border: 3px solid transparent; transition: border-color 0.3s ease-in-out; - cursor: pointer; + pointer: pointer; background: white; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); } @@ -210,7 +210,7 @@ skeleton="/assets/food/list-search.json" animation="animation" - isinteractive + interactive > @@ -381,7 +381,7 @@ skeleton="/assets/food/meal-ready-pro.json" animation="base" - isinteractive + interactive > @@ -411,7 +411,7 @@ (async () => { /* SECTION 1 */ - const widget1 = await spine.getSpineWidget("list").whenReady; + const widget1 = await spine.getSkeleton("list").whenReady; const setInteractionSectionOne = (itemName, trackNumber) => { const divName = `${itemName}Div`; @@ -450,7 +450,7 @@ const itemSlot = widget1.skeleton.findSlot(`bubble-base-${itemName.charAt(0)}`); let onItem = false; - widget1.addCursorSlotEventCallback(itemSlot, (slot, event) => { + widget1.addPointerSlotEventCallback(itemSlot, (slot, event) => { if (event === "enter") { widget1.state.setAnimation(0, `focus-${itemName}`, true); @@ -501,7 +501,7 @@ /* SECTION 2 */ const btnNext2 = document.getElementById("btn-next-2"); - const widget2 = await spine.getSpineWidget("pan").whenReady; + const widget2 = await spine.getSkeleton("pan").whenReady; const foodPiece1 = widget2.skeleton.findSlot(`food-piece-1`); const foodPiece2 = widget2.skeleton.findSlot(`food-piece-2`); const foodPiece3 = widget2.skeleton.findSlot(`food-piece-3`); @@ -561,7 +561,7 @@ /* SECTION 2 */ /* SECTION 3 */ - const widget3 = await spine.getSpineWidget("delivery").whenReady; + const widget3 = await spine.getSkeleton("delivery").whenReady; const btnNext3 = document.getElementById("btn-next-3"); const box = widget3.skeleton.findSlot("box"); @@ -610,10 +610,10 @@ /* SECTION 4 */ - const widget4 = await spine.getSpineWidget("ready").whenReady; + const widget4 = await spine.getSkeleton("ready").whenReady; const slot4Bread = widget4.skeleton.findSlot("salad"); - widget4.addCursorSlotEventCallback(slot4Bread, (slot, event) => { + widget4.addPointerSlotEventCallback(slot4Bread, (slot, event) => { if (event === "enter") { widget4.state.setAnimation(1, "bread-opening", false); @@ -627,7 +627,7 @@ }); const slot4Bottle = widget4.skeleton.findSlot("bottle-base"); - widget4.addCursorSlotEventCallback(slot4Bottle, (slot, event) => { + widget4.addPointerSlotEventCallback(slot4Bottle, (slot, event) => { if (event === "enter") { widget4.state.setAnimation(2, "bottle-opening", false); @@ -641,7 +641,7 @@ }); const slot4Fries = widget4.skeleton.findSlot("fries-case-back"); - widget4.addCursorSlotEventCallback(slot4Fries, (slot, event) => { + widget4.addPointerSlotEventCallback(slot4Fries, (slot, event) => { if (event === "enter") { widget4.state.setAnimation(3, "fries", true); diff --git a/spine-ts/spine-webcomponents/example/dispose.html b/spine-ts/spine-webcomponents/example/dispose.html new file mode 100644 index 000000000..0266d5a6e --- /dev/null +++ b/spine-ts/spine-webcomponents/example/dispose.html @@ -0,0 +1,170 @@ + + + + + + Webcomponent GUI + + + + +
    +

    Dispose example

    + + If you remove a widget from the DOM, it won't be disposed because you might want to append it to another node. + If you want to actually dispose of a widget, call dispose() on it. + dispose() is safe and won't release resources if they're still used by other widgets. + +
    + If you want to dispose of everything, call dispose() on the overlay. + +

    + The following example allows you to create and dispose of widgets using the same assets. + Below, you can see the number of references to each asset. + A red message will appear when an asset is actually disposed. + The number of skeleton references is at minimum 1 because there's a skeleton on the bottom of the page the use the same skeleton file. +

    + + + +

    + + +

    + +
    + + +
      +
    • + Created widgets: 0 +
    • +
    • + Skeleton references: 1 +
    • +
    • + Atlas references: 0 DISPOSED +
    • +
    • + Texture references: 0 DISPOSED +
    • +
    + + + +
    + + + + + \ No newline at end of file diff --git a/spine-ts/spine-webcomponents/example/game.html b/spine-ts/spine-webcomponents/example/game.html index 3ea5272fb..b3bbaa946 100644 --- a/spine-ts/spine-webcomponents/example/game.html +++ b/spine-ts/spine-webcomponents/example/game.html @@ -42,7 +42,7 @@ atlas="/assets/windmill-pma.atlas" skeleton="/assets/windmill-ess.json" animation="animation" - isinteractive + interactive > { - const spineboy = spine.getSpineWidget("spineboy-game"); - const windmill = spine.getSpineWidget("windmill-game"); + const spineboy = spine.getSkeleton("spineboy-game"); + const windmill = spine.getSkeleton("windmill-game"); await Promise.all([spineboy.whenReady, windmill.whenReady]); spineboy.state.setAnimation(2, "aim", true); spineboy.skeleton.slots.forEach(slot => { if (slot.data.name === "gun") { - spineboy.addCursorSlotEventCallback(slot, (slot,event) => { + spineboy.addPointerSlotEventCallback(slot, (slot,event) => { if (event === "down") { spineboy.state.setAnimation(1, "shoot", false); } @@ -110,7 +110,7 @@ } if (slot.data.name === "torso") { - spineboy.addCursorSlotEventCallback(slot, (slot,event) => { + spineboy.addPointerSlotEventCallback(slot, (slot,event) => { if (event === "down") { spineboy.state.setAnimation(0, "jump", false).mixDuration = 0.2; spineboy.state.addAnimation(0, "walk", true).mixDuration = 0.2; @@ -119,7 +119,7 @@ } if (slot.data.name === "head") { - spineboy.addCursorSlotEventCallback(slot, (slot,event) => { + spineboy.addPointerSlotEventCallback(slot, (slot,event) => { if (event === "down") { spineboy.state.setAnimation(1, "run", true).mixDuration = 0.2; } else { @@ -158,7 +158,7 @@ flowers.push(slot); - windmill.addCursorSlotEventCallback(slot, (slot, event) => { + windmill.addPointerSlotEventCallback(slot, (slot, event) => { if (ammo === 0) return; if (event !== "down") return; diff --git a/spine-ts/spine-webcomponents/example/gui.html b/spine-ts/spine-webcomponents/example/gui.html index f7bec3d2f..97a19b31c 100644 --- a/spine-ts/spine-webcomponents/example/gui.html +++ b/spine-ts/spine-webcomponents/example/gui.html @@ -57,7 +57,7 @@ @@ -1006,7 +1006,7 @@ async function updateCelesteAnimations() { @@ -1025,7 +1025,7 @@ async function updateCelesteAnimations() { > ... (async () => { - const widget = await spine.getSpineWidget("sack-debug").whenReady; + const widget = await spine.getSkeleton("sack-debug").whenReady; widget.skeleton.getRootBone().x += 50; })();` ); @@ -1046,235 +1046,6 @@ async function updateCelesteAnimations() { ///////////////////// --> -
    - -
    - If you remove a widget from the DOM, it won't be disposed because you might want to append it to another node. - If you want to actually dispose of a widget, call dispose() on it. - dispose() is safe and won't release resources if they're still used by other widgets. - -
    - If you want to dispose of everything, call dispose() on the overlay. - -

    - The following example allows you to create and dispose of widgets using the same assets. - Below, you can see the number of references to each asset. - A red message will appear when an asset is actually disposed. - If the number of skeleton references is higher than expected, it's because other widgets on the page are still using it. -

    -

    - - -

    - Widgets: ? -
    - Skeleton references: ? -
    - Atlas references: ? DISPOSED -
    - Texture references: ? DISPOSED -
    - -
    -
    -
    - - - -
    -
    
    -                
    -            
    -
    - -
    - - - - -
    @@ -1334,27 +1105,25 @@ function removeDiv() { atlas="/assets/spineboy-pma.atlas" skeleton="/assets/spineboy-pro.skel" animation="walk" - no-spinner + spinner >
    - A loading spinner is shown while assets are loading. Click the button below to simulate a 2-second loading delay: + If you want to show loading spinner while assets are loading, set the spinner attribute. Click the button below to simulate a 2-second loading delay:



    - If you don't want to show the loading spinner, set no-spinner. -
    Click the button below to toggle the spinner.

    - +
    @@ -1379,14 +1148,14 @@ function removeDiv() { atlas="/assets/spineboy-pma.atlas" skeleton="/assets/spineboy-pro.skel" animation="walk" - no-spinner + spinner > ... -const widget = spine.getSpineWidget("widget-loading"); +const widget = spine.getSkeleton("widget-loading"); async function reloadWidget(element) { element.disabled = true; await widget.whenReady; @@ -1398,8 +1167,8 @@ async function reloadWidget(element) { }, 1000) } function toggleSpinner(element) { - widget.noSpinner = !widget.noSpinner; - element.value = widget.noSpinner ? "Spinner ON" : "Spinner OFF"; + widget.spinner = !widget.spinner; + element.value = widget.spinner ? "Spinner ON" : "Spinner OFF"; }`) @@ -1928,7 +1697,7 @@ function toggleSpinner(element) { Create two arrays, one for the skins and the other for the animations, and loop through them.

    - spine.createSpineWidget allows you to create a Spine widget. + spine.createSkeleton allows you to create a Spine widget.

    By default, assets are loaded immediately. You can delay this by setting manual-start="false". @@ -1954,7 +1723,7 @@ function toggleSpinner(element) { grid.appendChild(gridElement); // create the widget - const widgetSection = spine.createSpineWidget({ + const widgetSection = spine.createSkeleton({ atlasPath: "/assets/chibi-stickers-pma.atlas", skeletonPath: "/assets/chibi-stickers.json", animation, @@ -2002,7 +1771,7 @@ skins.forEach((skin, i) => { grid.appendChild(gridElement); // create the widget - const widgetSection = spine.createSpineWidget({ + const widgetSection = spine.createSkeleton({ atlasPath: "/assets/chibi-stickers-pma.atlas", skeletonPath: "/assets/chibi-stickers.json", animation, @@ -2077,7 +1846,7 @@ skins.forEach((skin, i) => { @@ -2898,21 +2667,21 @@ tank.beforeUpdateWorldTransforms = (delta, skeleton, state) => {
    - If you need to determine the cursor position in the overlay world, you might find useful the following properties. + If you need to determine the pointer position in the overlay world, you might find useful the following properties.
    For spine-skeleton:
      -
    • cursorWorldX and cursorWorldY are the x and y of the cursor relative to the skeleton root (spine world).
    • +
    • pointerWorldX and pointerWorldY are the x and y of the pointer relative to the skeleton root (spine world).
    • worldX and worldY are the x and y of the root relative to the canvas/webgl context origin (spine world).
    For spine-overlay:
      -
    • cursorCanvasX and cursorCanvasY are the x and y of the cursor relative to the canvas top-left corner (screen world).
    • -
    • cursorWorldX and cursorWorldY are the x and y of the cursor relative to the canvas/webgl context origin (spine world).
    • +
    • pointerCanvasX and pointerCanvasY are the x and y of the pointer relative to the canvas top-left corner (screen world).
    • +
    • pointerWorldX and pointerWorldY are the x and y of the pointer relative to the canvas/webgl context origin (spine world).
    - You can use these properties to interact with your widget. See the following examples where the owl eyes will follow the cursor, even if you drag the owls to another position. + You can use these properties to interact with your widget. See the following examples where the owl eyes will follow the pointer, even if you drag the owls to another position. Exaggerate the movement by deselecting the checkbox below.
    @@ -2970,7 +2739,7 @@ function createCircleOfDivs(numDivs = 8) { atlas="/assets/owl-pma.atlas" skeleton="/assets/owl-pro.json" animation="idle" - isdraggable + drag > \`; @@ -3002,8 +2771,8 @@ checkbox.addEventListener('change', () => limitOwl = checkbox.checked); const updateControl = (widget, controlBone, mouseX, mouseY, tempVector) => { controlBone.parent.worldToLocal(tempVector.set( - widget.cursorWorldX, - widget.cursorWorldY, + widget.pointerWorldX, + widget.pointerWorldY, )); let x = tempVector.x; @@ -3062,7 +2831,7 @@ function createCircleOfDivs(numDivs = 8) { atlas="/assets/owl-pma.atlas" skeleton="/assets/owl-pro.json" animation="idle" - isdraggable + drag > `; @@ -3094,8 +2863,8 @@ checkbox.addEventListener('change', () => limitOwl = checkbox.checked); const updateControl = (widget, controlBone, mouseX, mouseY, tempVector) => { controlBone.parent.worldToLocal(tempVector.set( - widget.cursorWorldX, - widget.cursorWorldY, + widget.pointerWorldX, + widget.pointerWorldY, )); let x = tempVector.x; @@ -3131,14 +2900,14 @@ const updateControl = (widget, controlBone, mouseX, mouseY, tempVector) => {
    - You can attach callbacks to your widget to react to pointer interactions. Just make it isinteractive. + You can attach callbacks to your widget to react to pointer interactions. Just make it interactive.

    You can attach a callback for interactions with the widget's bounds or with slots. The available events are down, up, enter, leave, move, and drag.

    - In the following example, if the cursor enters the bounds, the jump animation is set, while the wave animation is set when the cursor leaves. + In the following example, if the pointer enters the bounds, the jump animation is set, while the wave animation is set when the pointer leaves.
    If you click on the head-base slot (the face), you can change the normal and dark tint with the colors selected in the two following selectors. @@ -3159,7 +2928,7 @@ const updateControl = (widget, controlBone, mouseX, mouseY, tempVector) => { skeleton="/assets/chibi-stickers.json" skin="mario" animation="emotes/wave" - isinteractive + interactive style="width: 150px; height: 150px;" > @@ -3169,7 +2938,7 @@ const updateControl = (widget, controlBone, mouseX, mouseY, tempVector) => { skeleton="/assets/chibi-stickers.json" skin="nate" animation="emotes/wave" - isinteractive + interactive style="width: 150px; height: 150px;" > @@ -3181,9 +2950,9 @@ const colorPicker = document.getElementById("color-picker"); const darkPicker = document.getElementById("dark-picker"); [0, 1].forEach(async (i) => { - const widget = await spine.getSpineWidget(`interactive${i}`).whenReady; + const widget = await spine.getSkeleton(`interactive${i}`).whenReady; - widget.cursorEventCallback = (event) => { + widget.pointerEventCallback = (event) => { if (event === "enter") widget.state.setAnimation(0, "emotes/hooray", true).mixDuration = .15; if (event === "leave") widget.state.setAnimation(0, "emotes/wave", true).mixDuration = .25; } @@ -3191,7 +2960,7 @@ const darkPicker = document.getElementById("dark-picker"); const tempColor = new spine.Color(); const slot = widget.skeleton.findSlot("head-base"); slot.darkColor = new spine.Color(0, 0, 0, 1); - widget.addCursorSlotEventCallback(slot, (slot, event) => { + widget.addPointerSlotEventCallback(slot, (slot, event) => { if (event === "down") { slot.darkColor.setFromColor(spine.Color.fromString(darkPicker.value, tempColor)); slot.color.setFromColor(spine.Color.fromString(colorPicker.value, tempColor)); @@ -3209,7 +2978,7 @@ const darkPicker = document.getElementById("dark-picker"); skeleton="/assets/chibi-stickers.json", skin="mario" animation="emotes/wave" - isinteractive + interactive style="width: 150px; height: 150px;" > @@ -3219,14 +2988,14 @@ const darkPicker = document.getElementById("dark-picker"); skeleton="/assets/chibi-stickers.json", skin="nate" animation="emotes/wave" - isinteractive + interactive style="width: 150px; height: 150px;" > [0, 1].forEach(async (i) => { - const widget = await spine.getSpineWidget(\`interactive\${i}\`).whenReady; + const widget = await spine.getSkeleton(\`interactive\${i}\`).whenReady; - widget.cursorEventCallback = (event) => { + widget.pointerEventCallback = (event) => { if (event === "enter") widget.state.setAnimation(0, "emotes/hooray", true).mixDuration = .15; if (event === "leave") widget.state.setAnimation(0, "emotes/wave", true).mixDuration = .25; } @@ -3234,7 +3003,7 @@ const darkPicker = document.getElementById("dark-picker"); const tempColor = new spine.Color(); const slot = widget.skeleton.findSlot("head-base"); slot.darkColor = new spine.Color(0, 0, 0, 1); - widget.addCursorSlotEventCallback(slot, (slot, event) => { + widget.addPointerSlotEventCallback(slot, (slot, event) => { if (event === "down") { slot.darkColor.setFromColor(spine.Color.fromString(darkPicker.value, tempColor)); slot.color.setFromColor(spine.Color.fromString(colorPicker.value, tempColor)); @@ -3300,7 +3069,7 @@ const darkPicker = document.getElementById("dark-picker"); @@ -3391,6 +3160,7 @@ const darkPicker = document.getElementById("dark-picker"); atlas="/assets/cloud-pot-pma.atlas" skeleton="/assets/cloud-pot.skel" animation="playing-in-the-rain" + drag > @@ -3401,11 +3171,11 @@ const darkPicker = document.getElementById("dark-picker"); ... (async () => { - const widget = await spine.getSpineWidget("potty2").whenReady; - widget.followSlot("rain/rain-color", spine.getSpineWidget("potty2-1"), { followVisibility: false, hideAttachment: true }); - widget.followSlot("rain/rain-white", spine.getSpineWidget("potty2-2"), { followVisibility: false, hideAttachment: true }); - widget.followSlot("rain/rain-blue", spine.getSpineWidget("potty2-3"), { followVisibility: false, hideAttachment: true }); - widget.followSlot("rain/rain-green", spine.getSpineWidget("potty2-4"), { followVisibility: false, hideAttachment: true }); + const widget = await spine.getSkeleton("potty2").whenReady; + widget.followSlot("rain/rain-color", spine.getSkeleton("potty2-1"), { followVisibility: false, hideAttachment: true }); + widget.followSlot("rain/rain-white", spine.getSkeleton("potty2-2"), { followVisibility: false, hideAttachment: true }); + widget.followSlot("rain/rain-blue", spine.getSkeleton("potty2-3"), { followVisibility: false, hideAttachment: true }); + widget.followSlot("rain/rain-green", spine.getSkeleton("potty2-4"), { followVisibility: false, hideAttachment: true }); })();`);
    @@ -3478,7 +3248,7 @@ const darkPicker = document.getElementById("dark-picker"); resizeHandle.style.right = "0"; resizeHandle.style.position = "absolute"; resizeHandle.style["background-color"] = "#007bff"; - resizeHandle.style["cursor"] = "se-resize"; + resizeHandle.style["pointer"] = "se-resize"; element.style["position"] = "relative"; element.style["touch-action"] = "none"; diff --git a/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts b/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts index 8ef026d50..07ca453ed 100644 --- a/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts +++ b/spine-ts/spine-webcomponents/src/SpineWebComponentOverlay.ts @@ -153,11 +153,13 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr private disposed = false; private loaded = false; + private running = false; + private visible = true; /** * appendedToBody is assegned in the connectedCallback. - * When true, the overlay will have the size of the element container in contrast to the default behaviour where the - * overlay has always the size of the screen. + * When false, the overlay will have the size of the element container in contrast to the default behaviour where the + * overlay has always the size of the viewport. * This is necessary when the overlay is inserted into a container that scroll in a different way with respect to the page. * Otherwise the following problems might occur: * 1) For containers appendedToBody, the widget will be slightly slower to scroll than the html behind. The effect is more evident for lower refresh rate display. @@ -223,7 +225,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr } connectedCallback (): void { - this.appendedToBody = this.parentElement !== document.body; + this.appendedToBody = this.parentElement === document.body; let overlayId = this.getAttribute('overlay-id'); if (!overlayId) { @@ -266,49 +268,42 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr } }, { rootMargin: "30px 20px 30px 20px" }); - // resize observer is supported by all major browsers today chrome started to support it in version 64 (early 2018) - // we cannot use window.resize event since it does not fire when body resizes, but not the window - // Alternatively, we can store the body size, check the current body size in the loop (like the translateCanvas), and - // if they differs call the resizeCallback. I already tested it, and it works. ResizeObserver should be more efficient. - if (this.appendedToBody) { - // if the element is appendedToBody, the user does not disable translate tweak, and the parent did not have already a transform, add the tweak + // if the element is not appendedToBody, the user does not disable translate tweak, and the parent did not have already a transform, add the tweak + if (!this.appendedToBody) { if (this.hasCssTweakOff()) { this.hasParentTransform = false; } else { this.parentElement!.style.transform = `translateZ(0)`; } - this.resizeObserver = new ResizeObserver(this.resizedCallback); - this.resizeObserver.observe(this.parentElement!); } else { - window.addEventListener("resize", this.resizedCallback) + window.addEventListener("resize", this.windowResizeCallback); } + this.resizeObserver = new ResizeObserver(() => this.resizedCallback()); + this.resizeObserver.observe(this.parentElement!); for (const widget of this.widgets) { this.intersectionObserver?.observe(widget.getHostElement()); } this.input = this.setupDragUtility(); + document.addEventListener('visibilitychange', this.visibilityChangeCallback); + this.startRenderingLoop(); } - private hasCssTweakOff () { - return this.noAutoParentTransform && getComputedStyle(this.parentElement!).transform === "none"; - } - - private running = false; disconnectedCallback (): void { const id = this.getAttribute('overlay-id'); if (id) SpineWebComponentOverlay.OVERLAY_LIST.delete(id); // window.removeEventListener("scroll", this.scrolledCallback); window.removeEventListener("load", this.loadedCallback); - window.removeEventListener("resize", this.resizedCallback); + window.removeEventListener("resize", this.windowResizeCallback); + document.removeEventListener('visibilitychange', this.visibilityChangeCallback); window.screen.orientation.removeEventListener('change', this.orientationChangedCallback); this.intersectionObserver?.disconnect(); this.resizeObserver?.disconnect(); this.input?.dispose(); } - static attributesDescription: Record = { "overlay-id": { propertyName: "overlayId", type: "string" }, "no-auto-parent-transform": { propertyName: "noAutoParentTransform", type: "boolean" }, @@ -329,8 +324,19 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr return; } - private resizedCallback = () => { - this.updateCanvasSize(); + private visibilityChangeCallback = () => { + if (document.hidden) { + this.visible = false; + } else { + this.visible = true; + this.startRenderingLoop(); + } + } + + private windowResizeCallback = () => this.resizedCallback(true); + + private resizedCallback = (onlyDiv = false) => { + this.updateCanvasSize(onlyDiv); } private orientationChangedCallback = () => { @@ -354,6 +360,10 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr } } + private hasCssTweakOff () { + return this.noAutoParentTransform && getComputedStyle(this.parentElement!).transform === "none"; + } + /** * Remove the overlay from the DOM, dispose all the contained widgets, and dispose the renderer. */ @@ -474,7 +484,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let ref: DOMRect; let offsetLeftForOevrlay = 0; let offsetTopForOverlay = 0; - if (this.appendedToBody) { + if (!this.appendedToBody) { ref = this.parentElement!.getBoundingClientRect(); const computedStyle = getComputedStyle(this.parentElement!); offsetLeftForOevrlay = ref.left + parseFloat(computedStyle.borderLeftWidth); @@ -483,7 +493,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const tempVector = new Vector3(); for (const widget of this.widgets) { - const { skeleton, pma, bounds, debug, offsetX, offsetY, dragX, dragY, fit, noSpinner, loading, clip, isDraggable } = widget; + const { skeleton, pma, bounds, debug, offsetX, offsetY, dragX, dragY, fit, spinner, loading, clip, drag } = widget; if (widget.isOffScreenAndWasMoved()) continue; const elementRef = widget.getHostElement(); @@ -492,7 +502,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr divBounds.x = divBounds.left + this.overflowLeftSize; divBounds.y = divBounds.top + this.overflowTopSize; - if (this.appendedToBody) { + if (!this.appendedToBody) { divBounds.x -= offsetLeftForOevrlay; divBounds.y -= offsetTopForOverlay; } @@ -516,7 +526,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr if (clip) startScissor(divBounds); if (loading) { - if (!noSpinner) { + if (spinner) { if (!widget.loadingScreen) widget.loadingScreen = new LoadingScreen(renderer); widget.loadingScreen!.drawInCoordinates(divOriginX, divOriginY); } @@ -611,7 +621,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let { x: ax, y: ay, width: aw, height: ah } = bounds; // show bounds and its center - if (isDraggable) { + if (drag) { renderer.rect(true, ax * skeleton.scaleX + worldOffsetX, ay * skeleton.scaleY + worldOffsetY, @@ -662,7 +672,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let x = this.tempFollowBoneVector.x - this.overflowLeftSize; let y = this.tempFollowBoneVector.y - this.overflowTopSize; - if (!this.appendedToBody) { + if (this.appendedToBody) { x += window.scrollX; y += window.scrollY; } @@ -685,7 +695,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr } const loop = () => { - if (this.disposed || !this.isConnected) { + if (this.disposed || !this.isConnected || !this.visible) { this.running = false; return; }; @@ -708,36 +718,36 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr const transparentRed = new Color(1, 0, 0, .3); } - public cursorCanvasX = 1; - public cursorCanvasY = 1; - public cursorWorldX = 1; - public cursorWorldY = 1; + public pointerCanvasX = 1; + public pointerCanvasY = 1; + public pointerWorldX = 1; + public pointerWorldY = 1; private tempVector = new Vector3(); - private updateCursor (input: Point) { - this.cursorCanvasX = input.x - window.scrollX; - this.cursorCanvasY = input.y - window.scrollY; + private updatePointer (input: Point) { + this.pointerCanvasX = input.x - window.scrollX; + this.pointerCanvasY = input.y - window.scrollY; - if (this.appendedToBody) { + if (!this.appendedToBody) { const ref = this.parentElement!.getBoundingClientRect(); - this.cursorCanvasX -= ref.left; - this.cursorCanvasY -= ref.top; + this.pointerCanvasX -= ref.left; + this.pointerCanvasY -= ref.top; } let tempVector = this.tempVector; - tempVector.set(this.cursorCanvasX, this.cursorCanvasY, 0); + tempVector.set(this.pointerCanvasX, this.pointerCanvasY, 0); this.renderer.camera.screenToWorld(tempVector, this.canvas.clientWidth, this.canvas.clientHeight); if (Number.isNaN(tempVector.x) || Number.isNaN(tempVector.y)) return; - this.cursorWorldX = tempVector.x; - this.cursorWorldY = tempVector.y; + this.pointerWorldX = tempVector.x; + this.pointerWorldY = tempVector.y; } - private updateWidgetCursor (widget: SpineWebComponentSkeleton): boolean { + private updateWidgetPointer (widget: SpineWebComponentSkeleton): boolean { if (widget.worldX === Infinity) return false; - widget.cursorWorldX = this.cursorWorldX - widget.worldX; - widget.cursorWorldY = this.cursorWorldY - widget.worldY; + widget.pointerWorldX = this.pointerWorldX - widget.worldX; + widget.pointerWorldY = this.pointerWorldY - widget.worldY; return true; } @@ -757,29 +767,29 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let lastX = 0; let lastY = 0; inputManager.addListener({ - // moved is used to pass cursor position wrt to canvas and widget position and currently is EXPERIMENTAL + // moved is used to pass pointer position wrt to canvas and widget position and currently is EXPERIMENTAL moved: (x, y, ev) => { const input = getInput(ev); - this.updateCursor(input); + this.updatePointer(input); for (const widget of this.widgets) { - if (!this.updateWidgetCursor(widget) || !widget.onScreen) continue; + if (!this.updateWidgetPointer(widget) || !widget.onScreen) continue; - widget.cursorEventUpdate("move", ev); + widget.pointerEventUpdate("move", ev); } }, down: (x, y, ev) => { const input = getInput(ev); - this.updateCursor(input); + this.updatePointer(input); for (const widget of this.widgets) { - if (!this.updateWidgetCursor(widget) || widget.isOffScreenAndWasMoved()) continue; + if (!this.updateWidgetPointer(widget) || widget.isOffScreenAndWasMoved()) continue; - widget.cursorEventUpdate("down", ev); + widget.pointerEventUpdate("down", ev); - if ((widget.isInteractive && widget.cursorInsideBounds) || (!widget.isInteractive && widget.isCursorInsideBounds())) { - if (!widget.isDraggable) continue; + if ((widget.interactive && widget.pointerInsideBounds) || (!widget.interactive && widget.isPointerInsideBounds())) { + if (!widget.drag) continue; widget.dragging = true; ev?.preventDefault(); @@ -795,12 +805,12 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let dragX = input.x - lastX; let dragY = input.y - lastY; - this.updateCursor(input); + this.updatePointer(input); for (const widget of this.widgets) { - if (!this.updateWidgetCursor(widget) || widget.isOffScreenAndWasMoved()) continue; + if (!this.updateWidgetPointer(widget) || widget.isOffScreenAndWasMoved()) continue; - widget.cursorEventUpdate("drag", ev); + widget.pointerEventUpdate("drag", ev); if (!widget.dragging) continue; @@ -818,8 +828,8 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr for (const widget of this.widgets) { widget.dragging = false; - if (widget.cursorInsideBounds) { - widget.cursorEventUpdate("up", ev); + if (widget.pointerInsideBounds) { + widget.pointerEventUpdate("up", ev); } } } @@ -832,11 +842,11 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr * Resize/scroll utilities */ - private updateCanvasSize () { + private updateCanvasSize (onlyDiv = false) { const { width, height } = this.getViewportSize(); // if the target width/height changes, resize the canvas. - if (this.lastCanvasBaseWidth !== width || this.lastCanvasBaseHeight !== height) { + if (!onlyDiv && this.lastCanvasBaseWidth !== width || this.lastCanvasBaseHeight !== height) { this.lastCanvasBaseWidth = width; this.lastCanvasBaseHeight = height; this.overflowLeftSize = this.overflowLeft * width; @@ -857,14 +867,13 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // this.div!.style.width = 0 + "px"; // this.div!.style.height = 0 + "px"; this.div!.style.display = "none"; - if (!this.appendedToBody) { + if (this.appendedToBody) { const { width, height } = this.getPageSize(); this.div!.style.width = width + "px"; this.div!.style.height = height + "px"; } else { if (this.hasCssTweakOff()) { - // this case lags if scrolls or position fixed - // users should never use tweak off, unless the parent container has already a transform + // this case lags if scrolls or position fixed. Users should never use tweak off this.div!.style.width = this.parentElement!.clientWidth + "px"; this.div!.style.height = this.parentElement!.clientHeight + "px"; this.canvas.style.transform = `translate(${-this.overflowLeftSize}px,${-this.overflowTopSize}px)`; @@ -890,7 +899,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // this means that during zoom it might occurs that the div would be resized // rounded 1px more making a scrollbar appear private getPageSize () { - return document.body.getBoundingClientRect(); + return document.documentElement.getBoundingClientRect(); } private lastViewportWidth = 0; @@ -904,7 +913,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr // determine the target viewport width and height. // The target width/height won't change if the viewport shrink to avoid useless re render (especially re render bursts on mobile) private getViewportSize (): { width: number, height: number } { - if (this.appendedToBody) { + if (!this.appendedToBody) { return { width: this.parentElement!.clientWidth, height: this.parentElement!.clientHeight, @@ -970,7 +979,7 @@ export class SpineWebComponentOverlay extends HTMLElement implements OverlayAttr let scrollPositionX = -this.overflowLeftSize; let scrollPositionY = -this.overflowTopSize; - if (!this.appendedToBody) { + if (this.appendedToBody) { scrollPositionX += window.scrollX; scrollPositionY += window.scrollY; } else { diff --git a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts index 34d17dba0..4ca7af168 100644 --- a/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts +++ b/spine-ts/spine-webcomponents/src/SpineWebComponentSkeleton.ts @@ -64,8 +64,8 @@ export type AnimationsInfo = Record }>; export type AnimationsType = { animationName: string | "#EMPTY#", loop?: boolean, delay?: number, mixDuration?: number }; -export type CursorEventType = "down" | "up" | "enter" | "leave" | "move" | "drag"; -export type CursorEventTypesInput = Exclude; +export type PointerEventType = "down" | "up" | "enter" | "leave" | "move" | "drag"; +export type PointerEventTypesInput = Exclude; // The properties that map to widget attributes interface WidgetAttributes { @@ -95,8 +95,8 @@ interface WidgetAttributes { autoCalculateBounds: boolean width: number height: number - isDraggable: boolean - isInteractive: boolean + drag: boolean + interactive: boolean debug: boolean identifier: string manualStart: boolean @@ -104,7 +104,7 @@ interface WidgetAttributes { pages?: Array clip: boolean offScreenUpdateBehaviour: OffScreenUpdateBehaviourType - noSpinner: boolean + spinner: boolean } // The methods user can override to have custom behaviour @@ -393,9 +393,9 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable /** * If true, the widget is draggable - * Connected to `isdraggable` attribute. + * Connected to `drag` attribute. */ - public isDraggable = false; + public drag = false; /** * The x of the root relative to the canvas/webgl context center in spine world coordinates. @@ -410,49 +410,49 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable public worldY = Infinity; /** - * The x coordinate of the cursor relative to the cursor relative to the skeleton root in spine world coordinates. + * The x coordinate of the pointer relative to the pointer relative to the skeleton root in spine world coordinates. * This is an experimental property and might be removed in the future. */ - public cursorWorldX = 1; + public pointerWorldX = 1; /** - * The x coordinate of the cursor relative to the cursor relative to the skeleton root in spine world coordinates. + * The x coordinate of the pointer relative to the pointer relative to the skeleton root in spine world coordinates. * This is an experimental property and might be removed in the future. */ - public cursorWorldY = 1; + public pointerWorldY = 1; /** * If true, the widget is interactive - * Connected to `isinteractive` attribute. + * Connected to `interactive` attribute. * This is an experimental property and might be removed in the future. */ - public isInteractive = false; + public interactive = false; /** - * If the widget is interactive, this method is invoked with a {@link CursorEventType} when the cursor + * If the widget is interactive, this method is invoked with a {@link PointerEventType} when the pointer * performs actions within the widget bounds (for example, it enter or leaves the bounds). * By default, the function does nothing. * This is an experimental property and might be removed in the future. */ - public cursorEventCallback = (event: CursorEventType, originalEvent?: UIEvent) => { } + public pointerEventCallback = (event: PointerEventType, originalEvent?: UIEvent) => { } // TODO: probably it makes sense to associate a single callback to a groups of slots to avoid the same callback to be called for each slot of the group /** * This methods allows to associate to a Slot a callback. For these slots, if the widget is interactive, - * when the cursor performs actions within the slot's attachment the associated callback is invoked with - * a {@link CursorEventType} (for example, it enter or leaves the slot's attachment bounds). + * when the pointer performs actions within the slot's attachment the associated callback is invoked with + * a {@link PointerEventType} (for example, it enter or leaves the slot's attachment bounds). * This is an experimental property and might be removed in the future. */ - public addCursorSlotEventCallback (slot: number | string | Slot, slotFunction: (slot: Slot, event: CursorEventType) => void) { - this.cursorSlotEventCallbacks.set(this.getSlotFromRef(slot), { slotFunction, inside: false }); + public addPointerSlotEventCallback (slot: number | string | Slot, slotFunction: (slot: Slot, event: PointerEventType) => void) { + this.pointerSlotEventCallbacks.set(this.getSlotFromRef(slot), { slotFunction, inside: false }); } /** - * Remove callbacks added through {@link addCursorSlotEventCallback}. + * Remove callbacks added through {@link addPointerSlotEventCallback}. * @param slot: the slot reference to which remove the associated callback */ - public removeCursorSlotEventCallbacks (slot: number | string | Slot) { - this.cursorSlotEventCallbacks.delete(this.getSlotFromRef(slot)); + public removePointerSlotEventCallbacks (slot: number | string | Slot) { + this.pointerSlotEventCallbacks.delete(this.getSlotFromRef(slot)); } private getSlotFromRef (slotRef: number | string | Slot): Slot { @@ -475,7 +475,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable public debug = false; /** - * An identifier to obtain this widget using the {@link getSpineWidget} function. + * An identifier to obtain this widget using the {@link getSkeleton} function. * This is useful when you need to interact with the widget using js. * Connected to `identifier` attribute. */ @@ -531,10 +531,10 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable public offScreenUpdateBehaviour: OffScreenUpdateBehaviourType = "pause"; /** - * If false (default), a Spine loading spinner is shown during asset loading - * Connected to `no-spinner` attribute. + * If true, a Spine loading spinner is shown during asset loading. Default to false. + * Connected to `spinner` attribute. */ - public noSpinner = false; + public spinner = false; /** * Replace the default state and skeleton update logic for this widget. @@ -599,7 +599,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable /** * The {@link LoadingScreenWidget} of this widget. * This is instantiated only if it is really necessary. - * For example, if {@link noSpinner} is `false`, this property value is null + * For example, if {@link spinner} is `false`, this property value is null */ public loadingScreen: LoadingScreen | null = null; @@ -699,8 +699,8 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable skin: { propertyName: "skin", type: "array-string" }, width: { propertyName: "width", type: "number", defaultValue: -1 }, height: { propertyName: "height", type: "number", defaultValue: -1 }, - isdraggable: { propertyName: "isDraggable", type: "boolean" }, - isinteractive: { propertyName: "isInteractive", type: "boolean" }, + drag: { propertyName: "drag", type: "boolean" }, + interactive: { propertyName: "interactive", type: "boolean" }, "x-axis": { propertyName: "xAxis", type: "number" }, "y-axis": { propertyName: "yAxis", type: "number" }, "offset-x": { propertyName: "offsetX", type: "number" }, @@ -718,7 +718,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable debug: { propertyName: "debug", type: "boolean" }, "manual-start": { propertyName: "manualStart", type: "boolean" }, "start-when-visible": { propertyName: "startWhenVisible", type: "boolean" }, - "no-spinner": { propertyName: "noSpinner", type: "boolean" }, + "spinner": { propertyName: "spinner", type: "boolean" }, clip: { propertyName: "clip", type: "boolean" }, pages: { propertyName: "pages", type: "array-number" }, fit: { propertyName: "fit", type: "fitType", defaultValue: "contain" }, @@ -1094,44 +1094,44 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable /** * @internal */ - public cursorInsideBounds = false; + public pointerInsideBounds = false; private verticesTemp = Utils.newFloatArray(2 * 1024); /** * @internal */ - public cursorSlotEventCallbacks: Map void, + public pointerSlotEventCallbacks: Map void, inside: boolean, }> = new Map(); /** * @internal */ - public cursorEventUpdate (type: CursorEventTypesInput, originalEvent?: UIEvent) { - if (!this.isInteractive) return; + public pointerEventUpdate (type: PointerEventTypesInput, originalEvent?: UIEvent) { + if (!this.interactive) return; this.checkBoundsInteraction(type, originalEvent); this.checkSlotInteraction(type, originalEvent); } - private checkBoundsInteraction (type: CursorEventTypesInput, originalEvent?: UIEvent) { - if (this.isCursorInsideBounds()) { + private checkBoundsInteraction (type: PointerEventTypesInput, originalEvent?: UIEvent) { + if (this.isPointerInsideBounds()) { - if (!this.cursorInsideBounds) { - this.cursorEventCallback("enter", originalEvent); + if (!this.pointerInsideBounds) { + this.pointerEventCallback("enter", originalEvent); } - this.cursorInsideBounds = true; + this.pointerInsideBounds = true; - this.cursorEventCallback(type, originalEvent); + this.pointerEventCallback(type, originalEvent); } else { - if (this.cursorInsideBounds) { - this.cursorEventCallback("leave", originalEvent); + if (this.pointerInsideBounds) { + this.pointerEventCallback("leave", originalEvent); } - this.cursorInsideBounds = false; + this.pointerInsideBounds = false; } } @@ -1139,11 +1139,11 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable /** * @internal */ - public isCursorInsideBounds (): boolean { + public isPointerInsideBounds (): boolean { if (this.isOffScreenAndWasMoved() || !this.skeleton) return false; - const x = this.cursorWorldX / this.skeleton.scaleX; - const y = this.cursorWorldY / this.skeleton.scaleY; + const x = this.pointerWorldX / this.skeleton.scaleX; + const y = this.pointerWorldY / this.skeleton.scaleY; return ( x >= this.bounds.x && @@ -1153,8 +1153,8 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable ); } - private checkSlotInteraction (type: CursorEventTypesInput, originalEvent?: UIEvent) { - for (let [slot, interactionState] of this.cursorSlotEventCallbacks) { + private checkSlotInteraction (type: PointerEventTypesInput, originalEvent?: UIEvent) { + for (let [slot, interactionState] of this.pointerSlotEventCallbacks) { if (!slot.bone.active) continue; let attachment = slot.getAttachment(); @@ -1176,7 +1176,7 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable } // here we have only "move" and "drag" events - if (this.isPointInPolygon(vertices, hullLength, [this.cursorWorldX, this.cursorWorldY])) { + if (this.isPointInPolygon(vertices, hullLength, [this.pointerWorldX, this.pointerWorldY])) { if (!inside) { interactionState.inside = true; @@ -1325,11 +1325,21 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable customElements.define("spine-skeleton", SpineWebComponentSkeleton); -export function getSpineWidget (identifier: string): SpineWebComponentSkeleton { +/** + * Return the first {@link SpineWebComponentSkeleton} with the given {@link SpineWebComponentSkeleton.identifier} + * @param identifier The {@link SpineWebComponentSkeleton.identifier} to search on the DOM + * @returns A skeleton web component instance with the given identifier + */ +export function getSkeleton (identifier: string): SpineWebComponentSkeleton { return document.querySelector(`spine-skeleton[identifier=${identifier}]`) as SpineWebComponentSkeleton; } -export function createSpineWidget (parameters: WidgetAttributes): SpineWebComponentSkeleton { +/** + * Create a {@link SpineWebComponentSkeleton} with the given {@link WidgetAttributes}. + * @param parameters The options to pass to the {@link SpineWebComponentSkeleton} + * @returns The skeleton web component instance created + */ +export function createSkeleton (parameters: WidgetAttributes): SpineWebComponentSkeleton { const widget = document.createElement("spine-skeleton") as SpineWebComponentSkeleton; Object.entries(SpineWebComponentSkeleton.attributesDescription).forEach(entry => {