From a2f82a2fbf67d7c425f553f3787366de6c57eeda Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Fri, 19 Jul 2024 17:59:03 +0200 Subject: [PATCH] [haxe][flixel] Add same example of starling to Flixel. --- spine-haxe/example/src/Main.hx | 5 +- .../flixelExamples/AnimationBoundExample.hx | 5 +- .../example/src/flixelExamples/BugExample.hx | 69 ----------- .../flixelExamples/CelestialCircusExample.hx | 40 ++++++- .../src/flixelExamples/ControlBonesExample.hx | 106 +++++++++++++++++ .../src/flixelExamples/EventsExample.hx | 75 ++++++++++++ .../example/src/flixelExamples/FlixelState.hx | 11 +- .../src/flixelExamples/MixAndMatchExample.hx | 54 +++------ spine-haxe/project.xml | 4 +- .../spine-haxe/spine/flixel/SkeletonMesh.hx | 3 - .../spine-haxe/spine/flixel/SkeletonSprite.hx | 108 ++++++++++++++++-- 11 files changed, 349 insertions(+), 131 deletions(-) delete mode 100644 spine-haxe/example/src/flixelExamples/BugExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/ControlBonesExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/EventsExample.hx diff --git a/spine-haxe/example/src/Main.hx b/spine-haxe/example/src/Main.hx index b38282244..c044f63c9 100644 --- a/spine-haxe/example/src/Main.hx +++ b/spine-haxe/example/src/Main.hx @@ -29,8 +29,9 @@ package; -import starlingExample.BasicExample; -import starlingExample.Scene.SceneManager; +import flixelExamples.FlixelState; +import starlingExamples.BasicExample; +import starlingExamples.Scene.SceneManager; import starling.core.Starling; import flixel.FlxG; import flixel.FlxGame; diff --git a/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx b/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx index f8be8878f..5742a4a3c 100644 --- a/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx +++ b/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx @@ -18,7 +18,10 @@ class AnimationBoundExample extends FlxState { var loadBinary = true; override public function create():Void { - var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(new CloudPotExample())); + var button = new FlxButton(0, 0, "Next scene", () -> { + FlxG.debugger.drawDebug = false; + FlxG.switchState(new ControlBonesExample()); + }); button.setPosition(FlxG.width * .75, FlxG.height / 10); add(button); diff --git a/spine-haxe/example/src/flixelExamples/BugExample.hx b/spine-haxe/example/src/flixelExamples/BugExample.hx deleted file mode 100644 index 622fc0729..000000000 --- a/spine-haxe/example/src/flixelExamples/BugExample.hx +++ /dev/null @@ -1,69 +0,0 @@ -package flixelExamples; - - -import openfl.Vector; -import flixel.graphics.FlxGraphic; -import flixel.FlxStrip; -import flixel.ui.FlxButton; -import flixel.FlxG; -import flixel.FlxState; -import openfl.utils.Assets; - -class BugExample extends FlxState { - var loadBinary = true; - - var head:FlxStrip = new FlxStrip(); - var pom:FlxStrip = new FlxStrip(); - var patch:FlxStrip = new FlxStrip(); - - override public function create():Void { - var bitmapData = openfl.utils.Assets.getBitmapData("assets/mix-and-match.png"); - var texture:FlxGraphic = FlxG.bitmap.add(bitmapData); - head.graphic = texture; - pom.graphic = texture; - patch.graphic = texture; - head.vertices = Vector.ofArray([ - 0., 0., 100., 0., 100., 100., 0., 100. - ]); - head.indices = Vector.ofArray([ - 0,1,2,2,3,0 - ]); - head.uvtData = Vector.ofArray([ - 0.115234375,0.279296875,0.115234375,0.13671875,0.2080078125,0.13671875,0.2080078125,0.279296875 - ]); - - patch.vertices = Vector.ofArray([ - -0.3972883003879213,-241.54102616829798,-24.347906632760896,-219.4804656912936,-50.850584500165084,-218.65483854163446,-55.32463497690269,-250.2884010498572,-3.2456740232505874,-256.12600556888134 - ]); - patch.indices = Vector.ofArray([ - 3,4,0,1,2,3,0,1,3 - ]); - patch.uvtData = Vector.ofArray([ - 0.14951038412982598,0.00390625,0.1689453125,0.06543703563511372,0.1689453125,0.1328125,0.12890625,0.1328125,0.12890625,0.00390625 - ]); - - pom.vertices = Vector.ofArray([ - 100., 100., 200., 100., 200., 200., 100., 200. - ]); - pom.indices = Vector.ofArray([ - 0,1,2,2,3,0 - ]); - pom.uvtData = Vector.ofArray([ - 0.40625,0.330078125,0.40625,0.24609375,0.453125,0.24609375,0.453125,0.330078125 - ]); - - patch.color = -9306137; - - head.screenCenter(); - patch.screenCenter(); - pom.screenCenter(); - patch.y +=100; - add(head); - add(pom); - - // add(patch); // <--- uncomment this, and head and pom will disappear - - camera.zoom = 1; - super.create(); - } -} diff --git a/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx index ac1a8a3f2..bbc989b61 100644 --- a/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx +++ b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx @@ -1,6 +1,8 @@ package flixelExamples; +import flixel.text.FlxText; +import flixel.math.FlxPoint; import spine.Skin; import flixel.ui.FlxButton; import flixel.FlxG; @@ -15,6 +17,7 @@ import spine.atlas.TextureAtlas; class CelestialCircusExample extends FlxState { var loadBinary = true; + var skeletonSprite:SkeletonSprite; override public function create():Void { var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(new SnowglobeExample())); button.setPosition(FlxG.width * .75, FlxG.height / 10); @@ -25,11 +28,46 @@ class CelestialCircusExample extends FlxState { var animationStateData = new AnimationStateData(data); animationStateData.defaultMix = 0.25; - var skeletonSprite = new SkeletonSprite(data, animationStateData); + skeletonSprite = new SkeletonSprite(data, animationStateData); skeletonSprite.screenCenter(); skeletonSprite.state.setAnimationByName(0, "eyeblink-long", true); add(skeletonSprite); + add(new FlxText(50, 50, 200, "Drag Celeste to move her around", 16)); + super.create(); } + + var mousePosition = FlxPoint.get(); + var dragging:Bool = false; + var lastX:Float = 0; + var lastY:Float = 0; + override public function update(elapsed:Float):Void + { + super.update(elapsed); + + mousePosition = FlxG.mouse.getPosition(); + + if (FlxG.mouse.justPressed && skeletonSprite.overlapsPoint(mousePosition)) + { + dragging = true; + lastX = mousePosition.x; + lastY = mousePosition.y; + } + + if (FlxG.mouse.justReleased) dragging = false; + + if (dragging) + { + skeletonSprite.x += mousePosition.x - lastX; + skeletonSprite.y += mousePosition.y - lastY; + skeletonSprite.skeleton.physicsTranslate( + mousePosition.x - lastX, + mousePosition.y - lastY, + ); + lastX = mousePosition.x; + lastY = mousePosition.y; + } + + } } diff --git a/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx b/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx new file mode 100644 index 000000000..fc215b6aa --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx @@ -0,0 +1,106 @@ +package flixelExamples; + + +import flixel.util.FlxSave; +import flixel.math.FlxPoint; +import flixel.util.FlxColor; +import flixel.util.FlxSpriteUtil; +import flixel.FlxSprite; +import flixel.ui.FlxButton; +import flixel.FlxG; +import spine.flixel.SkeletonSprite; +import spine.flixel.FlixelTextureLoader; +import flixel.FlxState; +import openfl.utils.Assets; +import spine.SkeletonData; +import spine.animation.AnimationStateData; +import spine.atlas.TextureAtlas; + +class ControlBonesExample extends FlxState { + var loadBinary = true; + + private var controlBones = []; + private var controls:Array = []; + override public function create():Void { + var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(new EventsExample())); + button.setPosition(FlxG.width * .75, FlxG.height / 10); + add(button); + + var atlas = new TextureAtlas(Assets.getText("assets/stretchyman.atlas"), new FlixelTextureLoader("assets/stretchyman.atlas")); + var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/stretchyman-pro.skel") : Assets.getText("assets/stretchyman-pro.json"), atlas); + var animationStateData = new AnimationStateData(data); + animationStateData.defaultMix = 0.25; + + var skeletonSprite = new SkeletonSprite(data, animationStateData); + skeletonSprite.scaleX = .5; + skeletonSprite.scaleY = .5; + var animation = skeletonSprite.state.setAnimationByName(0, "idle", true).animation; + skeletonSprite.setBoundingBox(animation); + skeletonSprite.screenCenter(); + add(skeletonSprite); + + var controlBoneNames = [ + "back-arm-ik-target", + "back-leg-ik-target", + "front-arm-ik-target", + "front-leg-ik-target", + ]; + + var radius = 6; + for (boneName in controlBoneNames) { + var bone = skeletonSprite.skeleton.findBone(boneName); + var point = [bone.worldX, bone.worldY]; + skeletonSprite.skeletonToHaxeWorldCoordinates(point); + var control = new FlxSprite(); + control.makeGraphic(radius * 2, radius * 2, FlxColor.TRANSPARENT, true); + FlxSpriteUtil.drawCircle(control, radius, radius, radius, 0xffff00ff); + control.setPosition(point[0] - radius, point[1] - radius); + controlBones.push(bone); + controls.push(control); + add(control); + } + + var point = [.0, .0]; + skeletonSprite.beforeUpdateWorldTransforms = function (go) { + for (i in 0...controls.length) { + var bone = controlBones[i]; + var control = controls[i]; + point[0] = control.x + radius; + point[1] = control.y + radius; + go.haxeWorldCoordinatesToBone(point, bone); + bone.x = point[0]; + bone.y = point[1]; + } + }; + + super.create(); + } + + var mousePosition = FlxPoint.get(); + var offsetX:Float = 0; + var offsetY:Float = 0; + var sprite:FlxSprite; + override public function update(elapsed:Float):Void + { + super.update(elapsed); + + mousePosition = FlxG.mouse.getPosition(); + + for (control in controls) { + if (FlxG.mouse.justPressed && control.overlapsPoint(mousePosition)) + { + sprite = control; + offsetX = mousePosition.x - sprite.x; + offsetY = mousePosition.y - sprite.y; + } + } + + if (FlxG.mouse.justReleased) sprite = null; + + if (sprite != null) + { + sprite.x = mousePosition.x - offsetX; + sprite.y = mousePosition.y - offsetY; + } + } +} diff --git a/spine-haxe/example/src/flixelExamples/EventsExample.hx b/spine-haxe/example/src/flixelExamples/EventsExample.hx new file mode 100644 index 000000000..b0be4b486 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/EventsExample.hx @@ -0,0 +1,75 @@ +package flixelExamples; + + +import flixel.text.FlxText; +import flixel.ui.FlxButton; +import flixel.FlxG; +import flixel.group.FlxSpriteGroup; +import spine.flixel.SkeletonSprite; +import spine.flixel.FlixelTextureLoader; +import flixel.FlxState; +import openfl.utils.Assets; +import spine.SkeletonData; +import spine.animation.AnimationStateData; +import spine.atlas.TextureAtlas; + +class EventsExample extends FlxState { + var loadBinary = true; + + override public function create():Void { + var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(new FlixelState())); + button.setPosition(FlxG.width * .75, FlxG.height / 10); + add(button); + + var atlas = new TextureAtlas(Assets.getText("assets/spineboy.atlas"), new FlixelTextureLoader("assets/spineboy.atlas")); + var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/spineboy-pro.skel") : Assets.getText("assets/spineboy-pro.json"), atlas, .25); + var animationStateData = new AnimationStateData(data); + animationStateData.defaultMix = 0.25; + + var skeletonSprite = new SkeletonSprite(data, animationStateData); + + // add callback to the AnimationState + skeletonSprite.state.onStart.add(entry -> log('Started animation ${entry.animation.name}')); + skeletonSprite.state.onInterrupt.add(entry -> log('Interrupted animation ${entry.animation.name}')); + skeletonSprite.state.onEnd.add(entry -> log('Ended animation ${entry.animation.name}')); + skeletonSprite.state.onDispose.add(entry -> log('Disposed animation ${entry.animation.name}')); + skeletonSprite.state.onComplete.add(entry -> log('Completed animation ${entry.animation.name}')); + + skeletonSprite.state.setAnimationByName(0, "walk", true); + + var trackEntry = skeletonSprite.state.addAnimationByName(0, "run", true, 3); + skeletonSprite.setBoundingBox(trackEntry.animation); + + skeletonSprite.setBoundingBox(); + skeletonSprite.screenCenter(); + skeletonSprite.skeleton.setBonesToSetupPose(); + add(skeletonSprite); + + trackEntry.onEvent.add( + (entry, event) -> log('Custom event for ${entry.animation.name}: ${event.data.name}')); + + + add(textContainer); + super.create(); + } + + private var textContainer = new FlxSpriteGroup(); + private var logs = new Array(); + private var logsNumber = 0; + private var yOffset = 12; + private function log(text:String) { + var length = logs.length; + var newLog = new FlxText(250, 30, text); + newLog.x = 50; + newLog.y = 20 + yOffset * logsNumber++; + newLog.color = 0xffffffff; + textContainer.add(newLog); + if (logs.length < 35) { + logs.push(newLog); + } else { + logs.shift().destroy(); + logs.push(newLog); + textContainer.y -= yOffset; + } + } +} diff --git a/spine-haxe/example/src/flixelExamples/FlixelState.hx b/spine-haxe/example/src/flixelExamples/FlixelState.hx index 2ae77dfbe..56c719a88 100644 --- a/spine-haxe/example/src/flixelExamples/FlixelState.hx +++ b/spine-haxe/example/src/flixelExamples/FlixelState.hx @@ -30,7 +30,8 @@ class FlixelState extends FlxState override public function create():Void { - // FlxG.switchState(new AnimationBoundExample()); + // FlxG.switchState(new EventsExample()); + // FlxG.switchState(new ControlBonesExample()); // FlxG.switchState(new MixAndMatchExample()); // FlxG.switchState(new SequenceExample()); // FlxG.switchState(new BasicExample()); @@ -65,6 +66,14 @@ class FlixelState extends FlxState floor.y = FlxG.height - 100; add(floor); + // instructions + var groupInstructions = new FlxSpriteGroup(); + groupInstructions.setPosition(50, 405); + groupInstructions.add(new FlxText(0, 0, 200, "Left/Right - Move", 16)); + groupInstructions.add(new FlxText(0, 25, 150, "Space - Jump", 16)); + groupInstructions.add(new FlxText(200, 25, 400, "Click the button for the next example", 16)); + add(groupInstructions); + // loading spineboy 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); diff --git a/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx b/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx index f9c34a1bf..6878d057b 100644 --- a/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx +++ b/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx @@ -22,58 +22,32 @@ class MixAndMatchExample extends FlxState { button.setPosition(FlxG.width * .75, FlxG.height / 10); add(button); - // var atlas = new TextureAtlas(Assets.getText("assets/export/skeleton.atlas"), new FlixelTextureLoader("assets/export/skeleton.atlas")); - // var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/export/skeleton.skel") : Assets.getText("assets/export/skeleton.json"), atlas, .5); - var atlas = new TextureAtlas(Assets.getText("assets/mix-and-match.atlas"), new FlixelTextureLoader("assets/mix-and-match.atlas")); var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/mix-and-match-pro.skel") : Assets.getText("assets/mix-and-match-pro.json"), atlas, .5); var animationStateData = new AnimationStateData(data); animationStateData.defaultMix = 0.25; skeletonSprite = new SkeletonSprite(data, animationStateData); - // var customSkin = new Skin("custom"); - // var skinBase = data.findSkin("skin-base"); - // customSkin.addSkin(skinBase); - // customSkin.addSkin(data.findSkin("nose/short")); - // customSkin.addSkin(data.findSkin("eyelids/girly")); - // customSkin.addSkin(data.findSkin("eyes/violet")); - // customSkin.addSkin(data.findSkin("hair/brown")); - // customSkin.addSkin(data.findSkin("clothes/hoodie-orange")); - // customSkin.addSkin(data.findSkin("legs/pants-jeans")); - // customSkin.addSkin(data.findSkin("accessories/bag")); - // customSkin.addSkin(data.findSkin("accessories/hat-red-yellow")); - // skeletonSprite.skeleton.skin = customSkin; + var customSkin = new Skin("custom"); + var skinBase = data.findSkin("skin-base"); + customSkin.addSkin(skinBase); + customSkin.addSkin(data.findSkin("nose/short")); + customSkin.addSkin(data.findSkin("eyelids/girly")); + customSkin.addSkin(data.findSkin("eyes/violet")); + customSkin.addSkin(data.findSkin("hair/brown")); + customSkin.addSkin(data.findSkin("clothes/hoodie-orange")); + customSkin.addSkin(data.findSkin("legs/pants-jeans")); + customSkin.addSkin(data.findSkin("accessories/bag")); + customSkin.addSkin(data.findSkin("accessories/hat-red-yellow")); + skeletonSprite.skeleton.skin = customSkin; - skeletonSprite.skeleton.skinName = "full-skins/girl"; skeletonSprite.state.update(0); - skeletonSprite.setBoundingBox(); + var animation = skeletonSprite.state.setAnimationByName(0, "dance", true).animation; + skeletonSprite.setBoundingBox(animation); skeletonSprite.screenCenter(); - // skeletonSprite.state.setAnimationByName(0, "dance", true); add(skeletonSprite); - // FlxG.debugger.visible = !FlxG.debugger.visible; - // FlxG.debugger.track(skeletonSprite); - // FlxG.debugger.track(camera); - // FlxG.debugger.drawDebug = true; super.create(); } - override public function update(elapsed:Float):Void - { - if (FlxG.keys.anyPressed([RIGHT])) { - skeletonSprite.x += 15; - } - if (FlxG.keys.anyPressed([LEFT])) { - skeletonSprite.x -= 15; - } - if (FlxG.keys.anyPressed([UP])) { - skeletonSprite.y -= 15; - } - if (FlxG.keys.anyPressed([DOWN])) { - skeletonSprite.y += 15; - } - - super.update(elapsed); - } - } diff --git a/spine-haxe/project.xml b/spine-haxe/project.xml index b483b9fe9..a4a5b01b8 100644 --- a/spine-haxe/project.xml +++ b/spine-haxe/project.xml @@ -2,9 +2,9 @@ - + - + diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx index a6a6c62ee..eacd34245 100644 --- a/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx @@ -29,7 +29,6 @@ package spine.flixel; -import flixel.system.FlxAssets.FlxGraphicAsset; import flixel.FlxStrip; class SkeletonMesh extends FlxStrip { @@ -37,6 +36,4 @@ class SkeletonMesh extends FlxStrip { super(); // graphic = texture; } - - } diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx index c7de9b65b..8dd1f67ff 100644 --- a/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx @@ -1,5 +1,8 @@ package spine.flixel; +import openfl.geom.Point; +import flixel.math.FlxPoint; +import flixel.math.FlxMatrix; import spine.animation.MixDirection; import spine.animation.MixBlend; import spine.animation.Animation; @@ -47,9 +50,18 @@ class SkeletonSprite extends FlxObject public var flipY(default, set):Bool = false; public var antialiasing:Bool = true; + @:isVar + public var scaleX(get, set):Float = 1; + @:isVar + public var scaleY(get, set):Float = 1; + var _tempVertices:Array = new Array(); var _quadTriangles:Array; var _meshes(default, null):Array = new Array(); + + private var _tempMatrix = new FlxMatrix(); + private var _tempPoint = new Point(); + private static var QUAD_INDICES:Array = [0, 1, 2, 2, 3, 0]; public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null) { @@ -58,13 +70,11 @@ class SkeletonSprite extends FlxObject skeleton = new Skeleton(skeletonData); skeleton.updateWorldTransform(Physics.update); state = new AnimationState(animationStateData != null ? animationStateData : new AnimationStateData(skeletonData)); - setBoundingBox(); } public function setBoundingBox(?animation:Animation, ?clip:Bool = true) { var bounds = animation == null ? skeleton.getBounds() : getAnimationBounds(animation, clip); - trace(bounds); if (bounds.width > 0 && bounds.height > 0) { width = bounds.width; height = bounds.height; @@ -112,6 +122,8 @@ class SkeletonSprite extends FlxObject _tempVertices = null; _quadTriangles = null; + _tempMatrix = null; + _tempPoint = null; if (_meshes != null) { for (mesh in _meshes) mesh.destroy(); @@ -154,6 +166,7 @@ class SkeletonSprite extends FlxObject var uvs:Array; var twoColorTint:Bool = false; var vertexSize:Int = twoColorTint ? 12 : 8; + _tempMatrix = getTransformMatrix(); for (slot in drawOrder) { var clippedVertexSize:Int = clipper.isClipping() ? 2 : vertexSize; if (!slot.bone.active) { @@ -202,16 +215,13 @@ class SkeletonSprite extends FlxObject if (mesh != null) { // cannot use directly mesh.color.setRGBFloat otherwise the setter won't be called and transfor color not set - var _tmpColor:Int; - _tmpColor = FlxColor.fromRGBFloat( + mesh.color = FlxColor.fromRGBFloat( skeleton.color.r * slot.color.r * attachmentColor.r * color.redFloat, skeleton.color.g * slot.color.g * attachmentColor.g * color.greenFloat, skeleton.color.b * slot.color.b * attachmentColor.b * color.blueFloat, 1 ); - // mesh color and alpha are bugged - // mesh.color = _tmpColor; - // mesh.alpha = skeleton.color.a * slot.color.a * attachmentColor.a * alpha; + mesh.alpha = skeleton.color.a * slot.color.a * attachmentColor.a * alpha; if (clipper.isClipping()) { clipper.clipTriangles(worldVertices, triangles, triangles.length, uvs); @@ -224,8 +234,15 @@ class SkeletonSprite extends FlxObject var i = 0; mesh.vertices.length = numVertices; while (v < n) { - mesh.vertices[i] = worldVertices[v]; - mesh.vertices[i + 1] = worldVertices[v + 1]; + // if (angle != 0) { + _tempPoint.setTo(worldVertices[v], worldVertices[v + 1]); + _tempPoint = _tempMatrix.transformPoint(_tempPoint); + mesh.vertices[i] = _tempPoint.x; + mesh.vertices[i + 1] = _tempPoint.y; + // } else { + // mesh.vertices[i] = worldVertices[v]; + // mesh.vertices[i + 1] = worldVertices[v + 1]; + // } v += 8; i += 2; } @@ -235,9 +252,9 @@ class SkeletonSprite extends FlxObject mesh.antialiasing = antialiasing; mesh.blend = SpineTexture.toFlixelBlending(slot.data.blendMode); - mesh.x = x + offsetX; - mesh.y = y + offsetY; - // mesh._cameras = _cameras; + // mesh.x = x + offsetX; + // mesh.y = y + offsetY; + mesh.angle = angle; mesh.draw(); } @@ -246,6 +263,52 @@ class SkeletonSprite extends FlxObject clipper.clipEnd(); } + private function getTransformMatrix():FlxMatrix { + _tempMatrix.identity(); + // scale is connected to the skeleton scale - no need to rescale + _tempMatrix.scale(1, 1); + _tempMatrix.rotate(angle * Math.PI / 180); + _tempMatrix.translate(x + offsetX, y + offsetY); + return _tempMatrix; + } + + public function skeletonToHaxeWorldCoordinates(point:Array):Void { + var transform = getTransformMatrix(); + var a = transform.a, + b = transform.b, + c = transform.c, + d = transform.d, + tx = transform.tx, + ty = transform.ty; + var x = point[0]; + var y = point[1]; + point[0] = x * a + y * c + tx; + point[1] = x * b + y * d + ty; + } + + public function haxeWorldCoordinatesToSkeleton(point:Array):Void { + var transform = getTransformMatrix().invert(); + var a = transform.a, + b = transform.b, + c = transform.c, + d = transform.d, + tx = transform.tx, + ty = transform.ty; + var x = point[0]; + var y = point[1]; + point[0] = x * a + y * c + tx; + point[1] = x * b + y * d + ty; + } + + public function haxeWorldCoordinatesToBone(point:Array, bone: Bone):Void { + this.haxeWorldCoordinatesToSkeleton(point); + if (bone.parent != null) { + bone.parent.worldToLocal(point); + } else { + bone.worldToLocal(point); + } + } + private function getFlixelMeshFromRendererAttachment(region: RenderedAttachment) { if (region.rendererObject == null) { var skeletonMesh = new SkeletonMesh(); @@ -269,6 +332,27 @@ class SkeletonSprite extends FlxObject skeleton.flipY = value; return flipY = value; } + + function set_scale(value:FlxPoint):FlxPoint { + return value; + } + + function get_scaleX():Float { + return skeleton.scaleX; + } + + function set_scaleX(value:Float):Float { + return skeleton.scaleX = value; + } + + function get_scaleY():Float { + return skeleton.scaleY; + } + + function set_scaleY(value:Float):Float { + return skeleton.scaleY = value; + } + } typedef RenderedAttachment = {