mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
[haxe][flixel] SkeletonSprite extends FlxTypedGroup<FlxObject> rather than FlxObject.
Replace direct bounds calculation with BoundsProvider interface for better performance and correctness. This makes it easier to get the correct bounds. BREAKING CHANGES: - SkeletonSprite extends FlxTypedGroup<FlxObject> rather than FlxObject. This was necessary because the FlxObject bounding/hitbox is always connected to its position and size and cannot be offset. - Removed getAnimationBounds() method. Replace it with the appropriate BoundsProvider implementation based on your use case, or create your own. - Removed setBoundingBox(). Use BoundsProvider features. - hitTest() now uses the assigned BoundsProvider instead of direct calculation. For accurate hit testing, use CurrentPoseBoundsProvider and call calculateBounds() each frame or on click. New features: - Uses BoundsProvider as starling. - SkeletonSprite constructor now accepts a third optional parameter for BoundsProvider. SetupPoseBoundsProvider is used by default. - Added calculateBounds() to recalculate bounds on demand.
This commit is contained in:
parent
196df9c386
commit
5990697d6e
5
spine-haxe/example/assets/quad.atlas
Normal file
5
spine-haxe/example/assets/quad.atlas
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
quad.png
|
||||||
|
size:100,100
|
||||||
|
filter:Linear,Linear
|
||||||
|
image
|
||||||
|
bounds:0,0,100,100
|
||||||
44
spine-haxe/example/assets/quad.json
Normal file
44
spine-haxe/example/assets/quad.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"bones": [
|
||||||
|
{ "name": "root" },
|
||||||
|
{
|
||||||
|
"name": "pivot",
|
||||||
|
"parent": "root",
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"rotation": 0,
|
||||||
|
"x": 20,
|
||||||
|
"y": -20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pivot2",
|
||||||
|
"parent": "pivot",
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"rotation": 0,
|
||||||
|
"x": 20,
|
||||||
|
"y": -20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "replaceMe",
|
||||||
|
"parent": "pivot2",
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"rotation": 0,
|
||||||
|
"x": 20,
|
||||||
|
"y": -20
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"slots": [
|
||||||
|
{ "name": "replaceMe", "bone": "replaceMe", "attachment": "image" }
|
||||||
|
],
|
||||||
|
"skins": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"attachments": {
|
||||||
|
"replaceMe": { "image": { "width": 100, "height": 100 } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"animations": { "animation": {} }
|
||||||
|
}
|
||||||
BIN
spine-haxe/example/assets/quad.png
Normal file
BIN
spine-haxe/example/assets/quad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@ -57,8 +57,7 @@ class BasicExample extends FlxState {
|
|||||||
animationStateData.defaultMix = 0.25;
|
animationStateData.defaultMix = 0.25;
|
||||||
|
|
||||||
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "walk", true).animation;
|
// skeletonSprite.state.setAnimationByName(0, "walk", true);
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
package flixelExamples;
|
package flixelExamples;
|
||||||
|
|
||||||
|
import spine.boundsprovider.SkinsAndAnimationBoundsProvider;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.text.FlxText;
|
import flixel.text.FlxText;
|
||||||
import spine.Skin;
|
import spine.Skin;
|
||||||
@ -42,7 +43,7 @@ import spine.SkeletonData;
|
|||||||
import spine.animation.AnimationStateData;
|
import spine.animation.AnimationStateData;
|
||||||
import spine.atlas.TextureAtlas;
|
import spine.atlas.TextureAtlas;
|
||||||
|
|
||||||
class AnimationBoundExample extends FlxState {
|
class BoundsProviderExample extends FlxState {
|
||||||
var loadBinary = true;
|
var loadBinary = true;
|
||||||
|
|
||||||
override public function create():Void {
|
override public function create():Void {
|
||||||
@ -60,38 +61,34 @@ class AnimationBoundExample extends FlxState {
|
|||||||
var animationStateData = new AnimationStateData(data);
|
var animationStateData = new AnimationStateData(data);
|
||||||
animationStateData.defaultMix = 0.25;
|
animationStateData.defaultMix = 0.25;
|
||||||
|
|
||||||
var skeletonSpriteClipping = new SkeletonSprite(data, animationStateData);
|
var skeletonSpriteClipping = new SkeletonSprite(data, animationStateData, new SkinsAndAnimationBoundsProvider("portal", null, null, true));
|
||||||
var animationClipping = skeletonSpriteClipping.state.setAnimationByName(0, "portal", true).animation;
|
skeletonSpriteClipping.state.setAnimationByName(0, "portal", true);
|
||||||
skeletonSpriteClipping.update(0);
|
|
||||||
skeletonSpriteClipping.setBoundingBox(animationClipping, true);
|
|
||||||
skeletonSpriteClipping.screenCenter();
|
skeletonSpriteClipping.screenCenter();
|
||||||
skeletonSpriteClipping.x = FlxG.width / 4 - skeletonSpriteClipping.width / 2;
|
skeletonSpriteClipping.x = FlxG.width / 4;
|
||||||
add(skeletonSpriteClipping);
|
add(skeletonSpriteClipping);
|
||||||
var textClipping = new FlxText();
|
var textClipping = new FlxText();
|
||||||
textClipping.text = "Animation bound with clipping";
|
textClipping.text = "Bounds with clipping";
|
||||||
textClipping.size = 12;
|
textClipping.size = 12;
|
||||||
textClipping.x = skeletonSpriteClipping.x + skeletonSpriteClipping.width / 2 - textClipping.width / 2;
|
textClipping.x = skeletonSpriteClipping.boundsX + skeletonSpriteClipping.width / 2 - textClipping.width / 2;
|
||||||
textClipping.y = skeletonSpriteClipping.y + skeletonSpriteClipping.height + 20;
|
textClipping.y = skeletonSpriteClipping.boundsY + skeletonSpriteClipping.height + 20;
|
||||||
textClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
textClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
||||||
add(textClipping);
|
add(textClipping);
|
||||||
|
|
||||||
var skeletonSpriteNoClipping = new SkeletonSprite(data, animationStateData);
|
var skeletonSpriteNoClipping = new SkeletonSprite(data, animationStateData, new SkinsAndAnimationBoundsProvider("portal"));
|
||||||
var animationClipping = skeletonSpriteNoClipping.state.setAnimationByName(0, "portal", true).animation;
|
skeletonSpriteNoClipping.state.setAnimationByName(0, "portal", true);
|
||||||
skeletonSpriteNoClipping.update(0);
|
|
||||||
skeletonSpriteNoClipping.setBoundingBox(animationClipping, false);
|
|
||||||
skeletonSpriteNoClipping.screenCenter();
|
skeletonSpriteNoClipping.screenCenter();
|
||||||
skeletonSpriteNoClipping.x = FlxG.width / 4 * 3 - skeletonSpriteClipping.width / 2 - 50;
|
skeletonSpriteNoClipping.x = FlxG.width / 4 * 3;
|
||||||
add(skeletonSpriteNoClipping);
|
add(skeletonSpriteNoClipping);
|
||||||
var textNoClipping = new FlxText();
|
var textNoClipping = new FlxText();
|
||||||
textNoClipping.text = "Animation bound without clipping";
|
textNoClipping.text = "Bounds without clipping";
|
||||||
textNoClipping.size = 12;
|
textNoClipping.size = 12;
|
||||||
textNoClipping.x = skeletonSpriteNoClipping.x + skeletonSpriteNoClipping.width / 2 - textNoClipping.width / 2;
|
textNoClipping.x = skeletonSpriteNoClipping.boundsX + skeletonSpriteNoClipping.width / 2 - textNoClipping.width / 2;
|
||||||
textNoClipping.y = skeletonSpriteNoClipping.y + skeletonSpriteNoClipping.height + 20;
|
textNoClipping.y = skeletonSpriteNoClipping.boundsY + skeletonSpriteNoClipping.height + 20;
|
||||||
textNoClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
textNoClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
||||||
add(textNoClipping);
|
add(textNoClipping);
|
||||||
|
|
||||||
var textInstruction = new FlxText();
|
var textInstruction = new FlxText();
|
||||||
textInstruction.text = "Red rectangle is the animation bound";
|
textInstruction.text = "Red rectangle is the Spine provider bounds";
|
||||||
textInstruction.size = 12;
|
textInstruction.size = 12;
|
||||||
textInstruction.screenCenter();
|
textInstruction.screenCenter();
|
||||||
textInstruction.y = textNoClipping.y + 40;
|
textInstruction.y = textNoClipping.y + 40;
|
||||||
@ -46,7 +46,7 @@ class CloudPotExample extends FlxState {
|
|||||||
override public function create():Void {
|
override public function create():Void {
|
||||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||||
|
|
||||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new AnimationBoundExample()));
|
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new BoundsProviderExample()));
|
||||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||||
add(button);
|
add(button);
|
||||||
|
|
||||||
|
|||||||
@ -65,8 +65,7 @@ class ControlBonesExample extends FlxState {
|
|||||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||||
skeletonSprite.scaleX = .5;
|
skeletonSprite.scaleX = .5;
|
||||||
skeletonSprite.scaleY = .5;
|
skeletonSprite.scaleY = .5;
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "idle", true).animation;
|
skeletonSprite.state.setAnimationByName(0, "idle", true);
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|
||||||
@ -77,6 +76,8 @@ class ControlBonesExample extends FlxState {
|
|||||||
"front-leg-ik-target",
|
"front-leg-ik-target",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// we need to update, to ensure scale is applied before getting bone values
|
||||||
|
skeletonSprite.update(0);
|
||||||
var radius = 6;
|
var radius = 6;
|
||||||
for (boneName in controlBoneNames) {
|
for (boneName in controlBoneNames) {
|
||||||
var bone = skeletonSprite.skeleton.findBone(boneName);
|
var bone = skeletonSprite.skeleton.findBone(boneName);
|
||||||
@ -84,7 +85,7 @@ class ControlBonesExample extends FlxState {
|
|||||||
skeletonSprite.skeletonToHaxeWorldCoordinates(point);
|
skeletonSprite.skeletonToHaxeWorldCoordinates(point);
|
||||||
var control = new FlxSprite();
|
var control = new FlxSprite();
|
||||||
control.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true);
|
control.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true);
|
||||||
FlxSpriteUtil.drawCircle(control, radius, radius, radius, 0xffff00ff);
|
FlxSpriteUtil.drawCircle(control, -1, -1, -1, 0xffff00ff);
|
||||||
control.setPosition(point[0] - radius, point[1] - radius);
|
control.setPosition(point[0] - radius, point[1] - radius);
|
||||||
controlBones.push(bone);
|
controlBones.push(bone);
|
||||||
controls.push(control);
|
controls.push(control);
|
||||||
|
|||||||
@ -68,9 +68,6 @@ class EventsExample extends FlxState {
|
|||||||
skeletonSprite.state.setAnimationByName(0, "walk", true);
|
skeletonSprite.state.setAnimationByName(0, "walk", true);
|
||||||
|
|
||||||
var trackEntry = skeletonSprite.state.addAnimationByName(0, "run", true, 3);
|
var trackEntry = skeletonSprite.state.addAnimationByName(0, "run", true, 3);
|
||||||
skeletonSprite.setBoundingBox(trackEntry.animation);
|
|
||||||
|
|
||||||
skeletonSprite.setBoundingBox();
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
skeletonSprite.skeleton.setupPoseBones();
|
skeletonSprite.skeleton.setupPoseBones();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|||||||
@ -30,6 +30,11 @@
|
|||||||
package flixelExamples;
|
package flixelExamples;
|
||||||
|
|
||||||
import flixel.ui.FlxButton;
|
import flixel.ui.FlxButton;
|
||||||
|
import flixel.math.FlxPoint;
|
||||||
|
import flixel.util.FlxColor;
|
||||||
|
import flixel.util.FlxSpriteUtil;
|
||||||
|
import spine.boundsprovider.SetupPoseBoundsProvider;
|
||||||
|
import spine.boundsprovider.SkinsAndAnimationBoundsProvider;
|
||||||
import flixel.group.FlxSpriteGroup;
|
import flixel.group.FlxSpriteGroup;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.FlxGraphic;
|
import flixel.graphics.FlxGraphic;
|
||||||
@ -56,6 +61,11 @@ class FlixelState extends FlxState {
|
|||||||
var scale = 4;
|
var scale = 4;
|
||||||
var speed:Float;
|
var speed:Float;
|
||||||
|
|
||||||
|
var skeletonOrigin:FlxSprite;
|
||||||
|
var gameObjectOrigin:FlxSprite;
|
||||||
|
var radius = 3;
|
||||||
|
var rootPoint = [.0, .0];
|
||||||
|
|
||||||
override public function create():Void {
|
override public function create():Void {
|
||||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||||
|
|
||||||
@ -97,12 +107,37 @@ class FlixelState extends FlxState {
|
|||||||
|
|
||||||
// loading spineboy
|
// loading spineboy
|
||||||
var atlas = new TextureAtlas(Assets.getText("assets/spineboy.atlas"), new FlixelTextureLoader("assets/spineboy.atlas"));
|
var atlas = new TextureAtlas(Assets.getText("assets/spineboy.atlas"), new FlixelTextureLoader("assets/spineboy.atlas"));
|
||||||
var skeletondata = SkeletonData.from(Assets.getText("assets/spineboy-pro.json"), atlas, 1 / scale);
|
var skeletondata = SkeletonData.from(Assets.getText("assets/spineboy-pro.json"), atlas, 1);
|
||||||
|
|
||||||
|
// var atlas = new TextureAtlas(Assets.getText("assets/quad.atlas"), new FlixelTextureLoader("assets/quad.atlas"));
|
||||||
|
// var skeletondata = SkeletonData.from(Assets.getText("assets/quad.json"), atlas, 2);
|
||||||
|
|
||||||
var animationStateData = new AnimationStateData(skeletondata);
|
var animationStateData = new AnimationStateData(skeletondata);
|
||||||
spineSprite = new SkeletonSprite(skeletondata, animationStateData);
|
// spineSprite = new SkeletonSprite(skeletondata, animationStateData, new SetupPoseBoundsProvider());
|
||||||
|
|
||||||
|
spineSprite = new SkeletonSprite(skeletondata, animationStateData, new SkinsAndAnimationBoundsProvider("walk"));
|
||||||
|
|
||||||
|
spineSprite.scale = new FlxPoint(1 / scale, 1 / scale);
|
||||||
|
|
||||||
// positioning spineboy
|
// positioning spineboy
|
||||||
spineSprite.setPosition(.5 * FlxG.width, .5 * FlxG.height);
|
spineSprite.screenCenter();
|
||||||
|
spineSprite.y += spineSprite.height / 2;
|
||||||
|
|
||||||
|
var control3 = new FlxSprite();
|
||||||
|
control3.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true);
|
||||||
|
FlxSpriteUtil.drawCircle(control3, radius, radius, radius, 0xff5500ff);
|
||||||
|
add(control3);
|
||||||
|
control3.setPosition(FlxG.width / 2, FlxG.height / 2);
|
||||||
|
|
||||||
|
skeletonOrigin = new FlxSprite();
|
||||||
|
skeletonOrigin.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true);
|
||||||
|
FlxSpriteUtil.drawCircle(skeletonOrigin, radius, radius, radius, 0xff5500ff);
|
||||||
|
add(skeletonOrigin);
|
||||||
|
|
||||||
|
gameObjectOrigin = new FlxSprite();
|
||||||
|
gameObjectOrigin.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true);
|
||||||
|
FlxSpriteUtil.drawCircle(gameObjectOrigin, radius, radius, radius, 0xffff9100);
|
||||||
|
add(gameObjectOrigin);
|
||||||
|
|
||||||
// setting mix times
|
// setting mix times
|
||||||
animationStateData.defaultMix = 0.5;
|
animationStateData.defaultMix = 0.5;
|
||||||
@ -119,7 +154,7 @@ class FlixelState extends FlxState {
|
|||||||
// setting idle animation
|
// setting idle animation
|
||||||
spineSprite.state.setAnimationByName(0, "idle", true);
|
spineSprite.state.setAnimationByName(0, "idle", true);
|
||||||
|
|
||||||
// setting y offset function to move object body while jumping
|
// // setting y offset function to move object body while jumping
|
||||||
var hip = spineSprite.skeleton.findBone("hip");
|
var hip = spineSprite.skeleton.findBone("hip");
|
||||||
var initialY = 0.;
|
var initialY = 0.;
|
||||||
var initialOffsetY = 0.;
|
var initialOffsetY = 0.;
|
||||||
@ -137,13 +172,19 @@ class FlixelState extends FlxState {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
var diff = .0;
|
var diff = .0;
|
||||||
|
var tmpPoint = [.0, .0];
|
||||||
spineSprite.afterUpdateWorldTransforms = spineSprite -> {
|
spineSprite.afterUpdateWorldTransforms = spineSprite -> {
|
||||||
if (jumping) {
|
if (jumping) {
|
||||||
diff -= hip.pose.y;
|
tmpPoint[1] = hip.applied.worldY;
|
||||||
spineSprite.offsetY -= diff;
|
spineSprite.skeletonToHaxeWorldCoordinates(tmpPoint);
|
||||||
spineSprite.y += diff;
|
diff -= (tmpPoint[1]);
|
||||||
|
spineSprite.offsetY += diff;
|
||||||
|
spineSprite.y -= diff;
|
||||||
}
|
}
|
||||||
diff = hip.pose.y;
|
|
||||||
|
tmpPoint[1] = hip.applied.worldY;
|
||||||
|
spineSprite.skeletonToHaxeWorldCoordinates(tmpPoint);
|
||||||
|
diff = tmpPoint[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// adding spineboy to the stage
|
// adding spineboy to the stage
|
||||||
@ -152,7 +193,7 @@ class FlixelState extends FlxState {
|
|||||||
// FlxG.debugger.visible = !FlxG.debugger.visible;
|
// FlxG.debugger.visible = !FlxG.debugger.visible;
|
||||||
// debug ui
|
// debug ui
|
||||||
// FlxG.debugger.visible = true;
|
// FlxG.debugger.visible = true;
|
||||||
// FlxG.debugger.drawDebug = true;
|
FlxG.debugger.drawDebug = true;
|
||||||
// FlxG.log.redirectTraces = true;
|
// FlxG.log.redirectTraces = true;
|
||||||
|
|
||||||
// FlxG.debugger.track(spineSprite);
|
// FlxG.debugger.track(spineSprite);
|
||||||
@ -160,12 +201,14 @@ class FlixelState extends FlxState {
|
|||||||
// FlxG.watch.add(spineSprite, "offsetY");
|
// FlxG.watch.add(spineSprite, "offsetY");
|
||||||
// FlxG.watch.add(spineSprite, "y");
|
// FlxG.watch.add(spineSprite, "y");
|
||||||
// FlxG.watch.add(this, "jumping");
|
// FlxG.watch.add(this, "jumping");
|
||||||
|
|
||||||
super.create();
|
super.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
var justSetIdle = true;
|
var justSetIdle = true;
|
||||||
|
|
||||||
override public function update(elapsed:Float):Void {
|
override public function update(elapsed:Float):Void {
|
||||||
|
// spineSprite.calculateBounds();
|
||||||
if (FlxG.overlap(spineSprite, group)) {
|
if (FlxG.overlap(spineSprite, group)) {
|
||||||
myText.text = "Overlapping";
|
myText.text = "Overlapping";
|
||||||
} else {
|
} else {
|
||||||
@ -184,6 +227,17 @@ class FlixelState extends FlxState {
|
|||||||
FlxG.debugger.visible = !FlxG.debugger.visible;
|
FlxG.debugger.visible = !FlxG.debugger.visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FlxG.keys.anyPressed([UP, DOWN])) {
|
||||||
|
if (FlxG.keys.anyPressed([UP])) {
|
||||||
|
if (spineSprite.flipY == true)
|
||||||
|
spineSprite.flipY = false;
|
||||||
|
}
|
||||||
|
if (FlxG.keys.anyPressed([DOWN])) {
|
||||||
|
if (spineSprite.flipY == false)
|
||||||
|
spineSprite.flipY = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FlxG.keys.anyPressed([RIGHT, LEFT])) {
|
if (FlxG.keys.anyPressed([RIGHT, LEFT])) {
|
||||||
justSetIdle = false;
|
justSetIdle = false;
|
||||||
var flipped = false;
|
var flipped = false;
|
||||||
@ -217,6 +271,13 @@ class FlixelState extends FlxState {
|
|||||||
spineSprite.state.setAnimationByName(0, "idle", true);
|
spineSprite.state.setAnimationByName(0, "idle", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rootBone = spineSprite.skeleton.findBone("root");
|
||||||
|
rootPoint[0] = rootBone.applied.worldX;
|
||||||
|
rootPoint[1] = rootBone.applied.worldY;
|
||||||
|
spineSprite.skeletonToHaxeWorldCoordinates(rootPoint);
|
||||||
|
skeletonOrigin.setPosition(rootPoint[0] - radius, rootPoint[1] - radius);
|
||||||
|
gameObjectOrigin.setPosition(spineSprite.x - radius, spineSprite.y - radius);
|
||||||
|
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
package flixelExamples;
|
package flixelExamples;
|
||||||
|
|
||||||
|
import spine.boundsprovider.SkinsAndAnimationBoundsProvider;
|
||||||
import spine.Skin;
|
import spine.Skin;
|
||||||
import flixel.ui.FlxButton;
|
import flixel.ui.FlxButton;
|
||||||
import flixel.FlxG;
|
import flixel.FlxG;
|
||||||
@ -59,7 +60,7 @@ class MixAndMatchExample extends FlxState {
|
|||||||
var animationStateData = new AnimationStateData(data);
|
var animationStateData = new AnimationStateData(data);
|
||||||
animationStateData.defaultMix = 0.25;
|
animationStateData.defaultMix = 0.25;
|
||||||
|
|
||||||
skeletonSprite = new SkeletonSprite(data, animationStateData);
|
skeletonSprite = new SkeletonSprite(data, animationStateData, new SkinsAndAnimationBoundsProvider("dance", ["full-skins/boy"]));
|
||||||
var customSkin = new Skin("custom");
|
var customSkin = new Skin("custom");
|
||||||
var skinBase = data.findSkin("skin-base");
|
var skinBase = data.findSkin("skin-base");
|
||||||
customSkin.addSkin(skinBase);
|
customSkin.addSkin(skinBase);
|
||||||
@ -74,8 +75,7 @@ class MixAndMatchExample extends FlxState {
|
|||||||
skeletonSprite.skeleton.skin = customSkin;
|
skeletonSprite.skeleton.skin = customSkin;
|
||||||
|
|
||||||
skeletonSprite.state.update(0);
|
skeletonSprite.state.update(0);
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "dance", true).animation;
|
skeletonSprite.state.setAnimationByName(0, "dance", true);
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,6 @@ class SequenceExample extends FlxState {
|
|||||||
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||||
|
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "flying", true).animation;
|
var animation = skeletonSprite.state.setAnimationByName(0, "flying", true).animation;
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
super.create();
|
super.create();
|
||||||
|
|||||||
@ -57,7 +57,6 @@ class TankExample extends FlxState {
|
|||||||
|
|
||||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "drive", true).animation;
|
var animation = skeletonSprite.state.setAnimationByName(0, "drive", true).animation;
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|
||||||
|
|||||||
@ -57,7 +57,6 @@ class VineExample extends FlxState {
|
|||||||
|
|
||||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||||
var animation = skeletonSprite.state.setAnimationByName(0, "grow", true).animation;
|
var animation = skeletonSprite.state.setAnimationByName(0, "grow", true).animation;
|
||||||
skeletonSprite.setBoundingBox(animation);
|
|
||||||
skeletonSprite.screenCenter();
|
skeletonSprite.screenCenter();
|
||||||
add(skeletonSprite);
|
add(skeletonSprite);
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
<project>
|
<project>
|
||||||
|
|
||||||
<meta title="spine-haxe-example" package="spine" version="4.2.0" company="Esoteric Software" />
|
<meta title="spine-haxe-example" package="spine" version="4.2.0" company="Esoteric Software" />
|
||||||
<app main="Main" path="export" file="SpineHaxeExample" />
|
<!-- <app main="Main" path="export" file="SpineHaxeExample" /> -->
|
||||||
<!-- <app main="MainStarling" path="export" file="SpineHaxeExample" /> -->
|
<!-- <app main="MainStarling" path="export" file="SpineHaxeExample" /> -->
|
||||||
<!-- <app main="MainFlixel" path="export" file="SpineHaxeExample" /> -->
|
<app main="MainFlixel" path="export" file="SpineHaxeExample" />
|
||||||
<window allow-high-dpi="true" />
|
<window allow-high-dpi="true" />
|
||||||
|
|
||||||
<haxelib name="openfl" />
|
<haxelib name="openfl" />
|
||||||
|
|||||||
@ -45,8 +45,8 @@ class SetupPoseBoundsProvider extends BoundsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function calculateBounds(gameObject:BoundsGameObject, out:BoundsRectangle):BoundsRectangle {
|
public function calculateBounds(gameObject:BoundsGameObject, out:BoundsRectangle):BoundsRectangle {
|
||||||
var skeleton = gameObject.skeleton;
|
var prevSkeleton = gameObject.skeleton;
|
||||||
if (skeleton == null) {
|
if (prevSkeleton == null) {
|
||||||
zeroRectangle(out);
|
zeroRectangle(out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,9 @@ class SetupPoseBoundsProvider extends BoundsProvider {
|
|||||||
// Make a copy of skeleton as this might be called while
|
// Make a copy of skeleton as this might be called while
|
||||||
// the skeleton in the GameObject has already been heavily modified. We can not
|
// the skeleton in the GameObject has already been heavily modified. We can not
|
||||||
// reconstruct that state.
|
// reconstruct that state.
|
||||||
var skeleton = new Skeleton(skeleton.data);
|
var skeleton = new Skeleton(prevSkeleton.data);
|
||||||
|
skeleton.scaleX = prevSkeleton.scaleX;
|
||||||
|
skeleton.scaleY = prevSkeleton.scaleY * Bone.yDir;
|
||||||
skeleton.setupPose();
|
skeleton.setupPose();
|
||||||
skeleton.updateWorldTransform(Physics.update);
|
skeleton.updateWorldTransform(Physics.update);
|
||||||
var newBounds = skeleton.getBounds(clipping ? new SkeletonClipping() : null);
|
var newBounds = skeleton.getBounds(clipping ? new SkeletonClipping() : null);
|
||||||
|
|||||||
@ -56,9 +56,9 @@ class SkinsAndAnimationBoundsProvider extends BoundsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function calculateBounds(gameObject:BoundsGameObject, out:BoundsRectangle):BoundsRectangle {
|
public function calculateBounds(gameObject:BoundsGameObject, out:BoundsRectangle):BoundsRectangle {
|
||||||
var skeleton = gameObject.skeleton;
|
var prevSkeleton = gameObject.skeleton;
|
||||||
var state = gameObject.state;
|
var state = gameObject.state;
|
||||||
if (skeleton == null || state == null) {
|
if (prevSkeleton == null || state == null) {
|
||||||
zeroRectangle(out);
|
zeroRectangle(out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -67,7 +67,9 @@ class SkinsAndAnimationBoundsProvider extends BoundsProvider {
|
|||||||
// the skeleton in the GameObject has already been heavily modified. We can not
|
// the skeleton in the GameObject has already been heavily modified. We can not
|
||||||
// reconstruct that state.
|
// reconstruct that state.
|
||||||
var animationState = new AnimationState(state.data);
|
var animationState = new AnimationState(state.data);
|
||||||
var skeleton = new Skeleton(skeleton.data);
|
var skeleton = new Skeleton(prevSkeleton.data);
|
||||||
|
skeleton.scaleX = prevSkeleton.scaleX;
|
||||||
|
skeleton.scaleY = prevSkeleton.scaleY * Bone.yDir;
|
||||||
var clipper = clipping ? new SkeletonClipping() : null;
|
var clipper = clipping ? new SkeletonClipping() : null;
|
||||||
var data = skeleton.data;
|
var data = skeleton.data;
|
||||||
if (skins.length > 0) {
|
if (skins.length > 0) {
|
||||||
|
|||||||
@ -29,42 +29,35 @@
|
|||||||
|
|
||||||
package spine.flixel;
|
package spine.flixel;
|
||||||
|
|
||||||
|
import flixel.util.FlxDirectionFlags;
|
||||||
|
import flixel.math.FlxRect;
|
||||||
|
import flixel.FlxCamera;
|
||||||
|
import flixel.FlxBasic;
|
||||||
|
import flixel.util.FlxAxes;
|
||||||
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||||
|
import spine.boundsprovider.SetupPoseBoundsProvider;
|
||||||
|
import spine.boundsprovider.BoundsProvider;
|
||||||
import openfl.geom.Point;
|
import openfl.geom.Point;
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
import flixel.math.FlxMatrix;
|
import flixel.math.FlxMatrix;
|
||||||
import spine.animation.MixDirection;
|
|
||||||
import spine.animation.MixBlend;
|
|
||||||
import spine.animation.Animation;
|
|
||||||
import spine.TextureRegion;
|
import spine.TextureRegion;
|
||||||
import haxe.extern.EitherType;
|
|
||||||
import spine.attachments.Attachment;
|
|
||||||
import flixel.util.typeLimit.OneOfTwo;
|
|
||||||
import flixel.FlxCamera;
|
|
||||||
import flixel.math.FlxRect;
|
|
||||||
import flixel.FlxG;
|
import flixel.FlxG;
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxSprite;
|
|
||||||
import flixel.FlxStrip;
|
|
||||||
import flixel.group.FlxSpriteGroup;
|
|
||||||
import flixel.graphics.FlxGraphic;
|
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import openfl.Vector;
|
import openfl.Vector;
|
||||||
import openfl.display.BlendMode;
|
|
||||||
import spine.Bone;
|
import spine.Bone;
|
||||||
import spine.Rectangle;
|
|
||||||
import spine.Skeleton;
|
import spine.Skeleton;
|
||||||
import spine.SkeletonData;
|
import spine.SkeletonData;
|
||||||
import spine.Slot;
|
import spine.Slot;
|
||||||
import spine.animation.AnimationState;
|
import spine.animation.AnimationState;
|
||||||
import spine.animation.AnimationStateData;
|
import spine.animation.AnimationStateData;
|
||||||
import spine.atlas.TextureAtlasRegion;
|
|
||||||
import spine.attachments.MeshAttachment;
|
import spine.attachments.MeshAttachment;
|
||||||
import spine.attachments.RegionAttachment;
|
import spine.attachments.RegionAttachment;
|
||||||
import spine.attachments.ClippingAttachment;
|
import spine.attachments.ClippingAttachment;
|
||||||
import spine.flixel.SkeletonMesh;
|
import spine.flixel.SkeletonMesh;
|
||||||
|
|
||||||
/** A FlxObject that draws a skeleton. The animation state and skeleton must be updated each frame. */
|
/** A FlxObject that draws a skeleton. The animation state and skeleton must be updated each frame. */
|
||||||
class SkeletonSprite extends FlxObject {
|
class SkeletonSprite extends FlxTypedGroup<FlxObject> {
|
||||||
public var skeleton(default, null):Skeleton;
|
public var skeleton(default, null):Skeleton;
|
||||||
public var state(default, null):AnimationState;
|
public var state(default, null):AnimationState;
|
||||||
public var stateData(default, null):AnimationStateData;
|
public var stateData(default, null):AnimationStateData;
|
||||||
@ -81,6 +74,18 @@ class SkeletonSprite extends FlxObject {
|
|||||||
public var flipY(default, set):Bool = false;
|
public var flipY(default, set):Bool = false;
|
||||||
public var antialiasing:Bool = true;
|
public var antialiasing:Bool = true;
|
||||||
|
|
||||||
|
public var boundsProvider:BoundsProvider;
|
||||||
|
|
||||||
|
public var angle(default, set) = 0.;
|
||||||
|
public var x(default, set) = 0.;
|
||||||
|
public var y(default, set) = 0.;
|
||||||
|
public var width(get, set):Float;
|
||||||
|
public var height(get, set):Float;
|
||||||
|
public var boundsX(get, never):Float;
|
||||||
|
public var boundsY(get, never):Float;
|
||||||
|
|
||||||
|
@:isVar
|
||||||
|
public var scale(never, set):FlxPoint;
|
||||||
@:isVar
|
@:isVar
|
||||||
public var scaleX(get, set):Float = 1;
|
public var scaleX(get, set):Float = 1;
|
||||||
@:isVar
|
@:isVar
|
||||||
@ -92,103 +97,50 @@ class SkeletonSprite extends FlxObject {
|
|||||||
|
|
||||||
private var _tempMatrix = new FlxMatrix();
|
private var _tempMatrix = new FlxMatrix();
|
||||||
private var _tempPoint = new Point();
|
private var _tempPoint = new Point();
|
||||||
|
private var _tempPointFlip = [.0, .0];
|
||||||
|
private var __bounds = new openfl.geom.Rectangle();
|
||||||
|
private var __objectBounds = new FlxObject();
|
||||||
|
|
||||||
private static var QUAD_INDICES:Array<Int> = [0, 1, 2, 2, 3, 0];
|
private static var QUAD_INDICES:Array<Int> = [0, 1, 2, 2, 3, 0];
|
||||||
|
|
||||||
/** Creates an uninitialized SkeletonSprite. The renderer, skeleton, and animation state must be set before use. */
|
/** Creates an uninitialized SkeletonSprite. The renderer, skeleton, and animation state must be set before use. */
|
||||||
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null) {
|
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null, ?boundsProvider:BoundsProvider) {
|
||||||
super(0, 0);
|
super(1);
|
||||||
Bone.yDown = true;
|
Bone.yDown = true;
|
||||||
skeleton = new Skeleton(skeletonData);
|
skeleton = new Skeleton(skeletonData);
|
||||||
skeleton.updateWorldTransform(Physics.update);
|
skeleton.updateWorldTransform(Physics.update);
|
||||||
state = new AnimationState(animationStateData != null ? animationStateData : new AnimationStateData(skeletonData));
|
state = new AnimationState(animationStateData != null ? animationStateData : new AnimationStateData(skeletonData));
|
||||||
setBoundingBox();
|
// setBoundingBox();
|
||||||
|
this.boundsProvider = boundsProvider ?? new SetupPoseBoundsProvider();
|
||||||
|
this.calculateBounds();
|
||||||
|
add(__objectBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBoundingBox(?animation:Animation, ?clip:Bool = true) {
|
// TODO: this changes the scale
|
||||||
var bounds = animation == null ? skeleton.getBounds() : getAnimationBounds(animation, clip);
|
// public function setSize(width:Float, height:Float):Void {
|
||||||
if (bounds.width > 0 && bounds.height > 0) {
|
// this.width = width;
|
||||||
width = bounds.width;
|
// this.height = height;
|
||||||
height = bounds.height;
|
// }
|
||||||
offsetX = -bounds.x;
|
// ============================================================
|
||||||
offsetY = -bounds.y;
|
// DEBUG METHODS (if FLX_DEBUG)
|
||||||
}
|
// ============================================================
|
||||||
}
|
|
||||||
|
|
||||||
public function getAnimationBounds(animation:Animation, clip:Bool = true):Rectangle {
|
|
||||||
var clipper = clip ? SkeletonSprite.clipper : null;
|
|
||||||
skeleton.setupPose();
|
|
||||||
|
|
||||||
var steps = 100, time = 0.;
|
|
||||||
var stepTime = animation.duration != 0 ? animation.duration / steps : 0;
|
|
||||||
var minX = 100000000.,
|
|
||||||
maxX = -100000000.,
|
|
||||||
minY = 100000000.,
|
|
||||||
maxY = -100000000.;
|
|
||||||
|
|
||||||
for (i in 0...steps) {
|
|
||||||
animation.apply(skeleton, time, time, false, [], 1, MixBlend.setup, MixDirection.mixIn, false);
|
|
||||||
skeleton.updateWorldTransform(Physics.update);
|
|
||||||
var boundsSkel = skeleton.getBounds(clipper);
|
|
||||||
|
|
||||||
if (!Math.isNaN(boundsSkel.x) && !Math.isNaN(boundsSkel.y) && !Math.isNaN(boundsSkel.width) && !Math.isNaN(boundsSkel.height)) {
|
|
||||||
minX = Math.min(boundsSkel.x, minX);
|
|
||||||
minY = Math.min(boundsSkel.y, minY);
|
|
||||||
maxX = Math.max(boundsSkel.x + boundsSkel.width, maxX);
|
|
||||||
maxY = Math.max(boundsSkel.y + boundsSkel.height, maxY);
|
|
||||||
} else
|
|
||||||
throw new SpineException("Animation bounds are invalid: " + animation.name);
|
|
||||||
|
|
||||||
time += stepTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
var bounds = new Rectangle();
|
|
||||||
bounds.x = minX;
|
|
||||||
bounds.y = minY;
|
|
||||||
bounds.width = maxX - minX;
|
|
||||||
bounds.height = maxY - minY;
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function destroy():Void {
|
|
||||||
state.clearListeners();
|
|
||||||
state = null;
|
|
||||||
skeleton = null;
|
|
||||||
|
|
||||||
_tempVertices = null;
|
|
||||||
_quadTriangles = null;
|
|
||||||
_tempMatrix = null;
|
|
||||||
_tempPoint = null;
|
|
||||||
|
|
||||||
if (_meshes != null) {
|
|
||||||
for (mesh in _meshes)
|
|
||||||
mesh.destroy();
|
|
||||||
_meshes = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function update(elapsed:Float):Void {
|
|
||||||
super.update(elapsed);
|
|
||||||
state.update(elapsed);
|
|
||||||
state.apply(skeleton);
|
|
||||||
this.beforeUpdateWorldTransforms(this);
|
|
||||||
skeleton.update(elapsed);
|
|
||||||
skeleton.updateWorldTransform(Physics.update);
|
|
||||||
this.afterUpdateWorldTransforms(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function draw():Void {
|
|
||||||
if (alpha == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
renderMeshes();
|
|
||||||
|
|
||||||
#if FLX_DEBUG
|
#if FLX_DEBUG
|
||||||
if (FlxG.debugger.drawDebug)
|
public function drawDebug():Void {
|
||||||
drawDebug();
|
__objectBounds.drawDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function drawDebugOnCamera(camera:FlxCamera):Void {
|
||||||
|
__objectBounds.drawDebugOnCamera(camera);
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// SKELETON SPRITE METHODS
|
||||||
|
// ============================================================
|
||||||
|
public function calculateBounds() {
|
||||||
|
this.boundsProvider.calculateBounds(this, __bounds);
|
||||||
|
__objectBounds.setPosition(x + __bounds.x, y + __bounds.y);
|
||||||
|
__objectBounds.setSize(__bounds.width, __bounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMeshes():Void {
|
function renderMeshes():Void {
|
||||||
@ -320,7 +272,7 @@ class SkeletonSprite extends FlxObject {
|
|||||||
private function getTransformMatrix():FlxMatrix {
|
private function getTransformMatrix():FlxMatrix {
|
||||||
_tempMatrix.identity();
|
_tempMatrix.identity();
|
||||||
// scale is connected to the skeleton scale - no need to rescale
|
// scale is connected to the skeleton scale - no need to rescale
|
||||||
_tempMatrix.scale(1, 1);
|
// _tempMatrix.scale(1, 1);
|
||||||
_tempMatrix.rotate(angle * Math.PI / 180);
|
_tempMatrix.rotate(angle * Math.PI / 180);
|
||||||
_tempMatrix.translate(x + offsetX, y + offsetY);
|
_tempMatrix.translate(x + offsetX, y + offsetY);
|
||||||
return _tempMatrix;
|
return _tempMatrix;
|
||||||
@ -375,18 +327,24 @@ class SkeletonSprite extends FlxObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function set_flipX(value:Bool):Bool {
|
function set_flipX(value:Bool):Bool {
|
||||||
if (value != flipX)
|
if (value != flipX) {
|
||||||
skeleton.scaleX = -skeleton.scaleX;
|
skeleton.scaleX = -skeleton.scaleX;
|
||||||
|
this.calculateBounds();
|
||||||
|
}
|
||||||
return flipX = value;
|
return flipX = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_flipY(value:Bool):Bool {
|
function set_flipY(value:Bool):Bool {
|
||||||
if (value != flipY)
|
if (value != flipY) {
|
||||||
skeleton.scaleY = -skeleton.scaleY;
|
skeleton.scaleY = -skeleton.scaleY * Bone.yDir;
|
||||||
|
this.calculateBounds();
|
||||||
|
}
|
||||||
return flipY = value;
|
return flipY = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_scale(value:FlxPoint):FlxPoint {
|
function set_scale(value:FlxPoint):FlxPoint {
|
||||||
|
scaleX = value.x;
|
||||||
|
scaleY = value.y;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,15 +353,199 @@ class SkeletonSprite extends FlxObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function set_scaleX(value:Float):Float {
|
function set_scaleX(value:Float):Float {
|
||||||
return skeleton.scaleX = value;
|
skeleton.scaleX = value;
|
||||||
|
this.calculateBounds();
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_scaleY():Float {
|
function get_scaleY():Float {
|
||||||
return skeleton.scaleY;
|
return skeleton.scaleY * Bone.yDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_scaleY(value:Float):Float {
|
function set_scaleY(value:Float):Float {
|
||||||
return skeleton.scaleY = value;
|
skeleton.scaleY = value;
|
||||||
|
this.calculateBounds();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_angle(value:Float):Float {
|
||||||
|
__objectBounds.angle = value;
|
||||||
|
return angle = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_x(value:Float):Float {
|
||||||
|
__objectBounds.x = __bounds.x + value;
|
||||||
|
return x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_y(value:Float):Float {
|
||||||
|
__objectBounds.y = __bounds.y + value;
|
||||||
|
return y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_height():Float {
|
||||||
|
return __bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_width():Float {
|
||||||
|
return __bounds.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_width(value:Float):Float {
|
||||||
|
var scale = value / __bounds.width;
|
||||||
|
scaleX *= scale;
|
||||||
|
return __bounds.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_height(value:Float):Float {
|
||||||
|
var scale = value / __bounds.height;
|
||||||
|
scaleY *= scale;
|
||||||
|
return __bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_boundsX():Float {
|
||||||
|
return __objectBounds.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_boundsY():Float {
|
||||||
|
return __objectBounds.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// OVERRIDE METHODS FROM FlxBasic
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
override public function update(elapsed:Float):Void {
|
||||||
|
super.update(elapsed);
|
||||||
|
state.update(elapsed);
|
||||||
|
state.apply(skeleton);
|
||||||
|
this.beforeUpdateWorldTransforms(this);
|
||||||
|
skeleton.update(elapsed);
|
||||||
|
skeleton.updateWorldTransform(Physics.update);
|
||||||
|
this.afterUpdateWorldTransforms(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function draw():Void {
|
||||||
|
if (alpha == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
renderMeshes();
|
||||||
|
|
||||||
|
#if FLX_DEBUG
|
||||||
|
if (FlxG.debugger.drawDebug)
|
||||||
|
__objectBounds.drawDebug();
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function destroy():Void {
|
||||||
|
state.clearListeners();
|
||||||
|
state = null;
|
||||||
|
skeleton = null;
|
||||||
|
|
||||||
|
_tempVertices = null;
|
||||||
|
_quadTriangles = null;
|
||||||
|
_tempMatrix = null;
|
||||||
|
_tempPoint = null;
|
||||||
|
|
||||||
|
if (_meshes != null) {
|
||||||
|
for (mesh in _meshes)
|
||||||
|
mesh.destroy();
|
||||||
|
_meshes = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// OVERLAP/COLLISION METHODS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public function overlaps(objectOrGroup:FlxBasic, inScreenSpace:Bool = false, ?camera:FlxCamera):Bool {
|
||||||
|
return __objectBounds.overlaps(objectOrGroup, inScreenSpace, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function overlapsAt(x:Float, y:Float, objectOrGroup:FlxBasic, inScreenSpace = false, ?camera:FlxCamera):Bool {
|
||||||
|
return __objectBounds.overlapsAt(x, y, objectOrGroup, inScreenSpace, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function overlapsPoint(point:FlxPoint, inScreenSpace = false, ?camera:FlxCamera):Bool {
|
||||||
|
return __objectBounds.overlapsPoint(point, inScreenSpace, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// BOUNDS/POSITION METHODS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public function inWorldBounds():Bool {
|
||||||
|
return __objectBounds.inWorldBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint {
|
||||||
|
return __objectBounds.getScreenPosition(result, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPosition(?result:FlxPoint):FlxPoint {
|
||||||
|
return __objectBounds.getPosition(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMidpoint(?point:FlxPoint):FlxPoint {
|
||||||
|
return __objectBounds.getMidpoint(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHitbox(?rect:FlxRect):FlxRect {
|
||||||
|
return __objectBounds.getHitbox(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRotatedBounds(?newRect:FlxRect):FlxRect {
|
||||||
|
return __objectBounds.getRotatedBounds(newRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// STATE METHODS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public function reset(x:Float, y:Float):Void {
|
||||||
|
__objectBounds.reset(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isOnScreen(?camera:FlxCamera):Bool {
|
||||||
|
return __objectBounds.isOnScreen(camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isPixelPerfectRender(?camera:FlxCamera):Bool {
|
||||||
|
return __objectBounds.isPixelPerfectRender(camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isTouching(direction:FlxDirectionFlags):Bool {
|
||||||
|
return __objectBounds.isTouching(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function justTouched(direction:FlxDirectionFlags):Bool {
|
||||||
|
return __objectBounds.justTouched(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// UTILITY METHODS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public inline function screenCenter(axes:FlxAxes = XY):SkeletonSprite {
|
||||||
|
if (axes.x)
|
||||||
|
x = (FlxG.width - __bounds.width) / 2 - __bounds.x;
|
||||||
|
|
||||||
|
if (axes.y)
|
||||||
|
y = (FlxG.height - __bounds.height) / 2 - __bounds.y;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPosition(x = 0.0, y = 0.0):Void {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSize(width:Float, height:Float):Void {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,9 +46,13 @@
|
|||||||
|
|
||||||
// Create the spine display object
|
// Create the spine display object
|
||||||
const stretchyman = spine.Spine.from({skeleton: "stretchymanData", atlas: "stretchymanAtlas",
|
const stretchyman = spine.Spine.from({skeleton: "stretchymanData", atlas: "stretchymanAtlas",
|
||||||
scale: 0.75,
|
scale: 1,
|
||||||
|
// scale: 0.75,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
stretchyman.skeleton.scaleX = .5;
|
||||||
|
stretchyman.skeleton.scaleY = 1;
|
||||||
|
|
||||||
// Set the default mix time to use when transitioning
|
// Set the default mix time to use when transitioning
|
||||||
// from one animation to the next.
|
// from one animation to the next.
|
||||||
stretchyman.state.data.defaultMix = 0.2;
|
stretchyman.state.data.defaultMix = 0.2;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user