mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
[haxe] Support for HaxeFlixel (#2764)
* [haxe] Flixel support * [haxe][flixel] WIP fix alpha and color tinting not working on meshes. * [haxe][flixel] Added most of examples - Color/alpha is broken on flixel for meshes. * [haxe][flixel] Flixel color bug example * [haxe][flixel] Add same example of starling to Flixel. * [haxe][flixel] Fix rotation for clipped attachments. * [haxe][flixel] Minor modifications to avoid warning on flixel 6.0.0. * [haxe] Updated readme. * [haxe][flixel] Remove unused assets. * [haxe] Removed useless flipX/flipY on core Skeleton.hx.
This commit is contained in:
parent
01a847b7f7
commit
7f2e4c1df7
@ -23,12 +23,17 @@ spine-haxe works with data exported from Spine 4.2.xx.
|
||||
spine-haxe supports all Spine features except premultiplied alpha atlases and two color tinting.
|
||||
|
||||
## Setup
|
||||
The core module of spine-haxe has zero dependencies. The rendering implementation through Starling has two dependencies: openfl and starling.
|
||||
The spine-haxe runtime is composed of a core module, that is a Haxe implementation of the renderer-agnostic Spine Runtimes core APIs, and the following specific renderer implementations:
|
||||
- [Starling](https://lib.haxe.org/p/starling/)
|
||||
- [HaxeFlixel](https://lib.haxe.org/p/flixel/) (minimum supported version 5.9.0)
|
||||
|
||||
The core module of spine-haxe has zero dependencies. The rendering implementation depends on: openfl, starling, and flixel.
|
||||
To use spine-haxe you have first to install all the necessary dependencies:
|
||||
|
||||
```
|
||||
haxelib install openfl
|
||||
haxelib install starling
|
||||
haxelib install flixel
|
||||
```
|
||||
|
||||
Once you have installed the dependencies, you can [download the latest version of spine-haxe](https://esotericsoftware.com/files/spine-haxe/4.2/spine-haxe-latest.zip) and install it:
|
||||
@ -60,6 +65,7 @@ To setup the development environment install the following:
|
||||
haxelib install openfl
|
||||
haxelib run openfl setup
|
||||
haxelib install starling
|
||||
haxelib install flixel
|
||||
```
|
||||
3. Clone the `spine-runtimes` repository, and use `haxelib` to setup a dev library:
|
||||
```
|
||||
|
||||
@ -27,24 +27,145 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.geom.Rectangle;
|
||||
package;
|
||||
|
||||
import flixelExamples.FlixelState;
|
||||
import starlingExamples.BasicExample;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import starling.core.Starling;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
|
||||
import openfl.display.Sprite;
|
||||
import openfl.text.TextField;
|
||||
import openfl.text.TextFormat;
|
||||
import openfl.events.MouseEvent;
|
||||
|
||||
import openfl.geom.Rectangle;
|
||||
import starling.events.Event;
|
||||
|
||||
class Main extends Sprite {
|
||||
private var background:Sprite;
|
||||
private var flixelButton:Sprite;
|
||||
private var starlingButton:Sprite;
|
||||
private var uiContainer:Sprite;
|
||||
|
||||
private static inline var ratio = 4;
|
||||
private static inline var STAGE_WIDTH:Int = 100 * ratio;
|
||||
private static inline var STAGE_HEIGHT:Int = 200 * ratio;
|
||||
private static inline var BUTTON_WIDTH:Int = 80 * ratio;
|
||||
private static inline var BUTTON_HEIGHT:Int = 40 * ratio;
|
||||
private static inline var BUTTON_SPACING:Int = 20 * ratio;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
}
|
||||
|
||||
private function onAddedToStage(e:Event):Void {
|
||||
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
createUI();
|
||||
centerUI();
|
||||
stage.addEventListener(Event.RESIZE, onResize);
|
||||
}
|
||||
|
||||
private function createUI():Void {
|
||||
uiContainer = new Sprite();
|
||||
addChild(uiContainer);
|
||||
|
||||
background = new Sprite();
|
||||
background.graphics.beginFill(0xA2A2A2);
|
||||
background.graphics.drawRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
background.graphics.endFill();
|
||||
uiContainer.addChild(background);
|
||||
|
||||
flixelButton = createButton("Flixel", 0xFF0000);
|
||||
uiContainer.addChild(flixelButton);
|
||||
|
||||
starlingButton = createButton("Starling", 0x00FF00);
|
||||
uiContainer.addChild(starlingButton);
|
||||
|
||||
positionButtons();
|
||||
|
||||
flixelButton.addEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.addEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
}
|
||||
|
||||
private function createButton(label:String, color:Int):Sprite {
|
||||
var button = new Sprite();
|
||||
var g = button.graphics;
|
||||
|
||||
g.beginFill(color);
|
||||
g.drawRoundRect(0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, 10, 10);
|
||||
g.endFill();
|
||||
|
||||
// Add button text
|
||||
var tf = new TextField();
|
||||
var format = new TextFormat("_sans", 14 * ratio, 0x000000, true, null, null, null, null, "center");
|
||||
tf.defaultTextFormat = format;
|
||||
tf.text = label;
|
||||
tf.width = BUTTON_WIDTH;
|
||||
tf.height = BUTTON_HEIGHT;
|
||||
tf.mouseEnabled = false;
|
||||
tf.selectable = false;
|
||||
|
||||
tf.y = (BUTTON_HEIGHT - tf.textHeight) / 2;
|
||||
|
||||
button.addChild(tf);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private function positionButtons():Void {
|
||||
var totalHeight = (BUTTON_HEIGHT * 2) + BUTTON_SPACING;
|
||||
var startY = (STAGE_HEIGHT - totalHeight) / 2;
|
||||
|
||||
flixelButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
flixelButton.y = startY + BUTTON_HEIGHT + BUTTON_SPACING;
|
||||
|
||||
starlingButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
starlingButton.y = startY;
|
||||
}
|
||||
|
||||
private function centerUI():Void {
|
||||
uiContainer.x = (stage.stageWidth - STAGE_WIDTH) / 2;
|
||||
uiContainer.y = (stage.stageHeight - STAGE_HEIGHT) / 2;
|
||||
}
|
||||
|
||||
private function onResize(e:Event):Void {
|
||||
centerUI();
|
||||
}
|
||||
|
||||
private function onFlixelClick(e:MouseEvent):Void {
|
||||
trace("Launching Flixel game");
|
||||
destroyUI();
|
||||
addChild(new FlxGame(640, 480, FlixelState));
|
||||
FlxG.autoPause = false;
|
||||
}
|
||||
|
||||
private function destroyUI():Void {
|
||||
flixelButton.removeEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.removeEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
stage.removeEventListener(Event.RESIZE, onResize);
|
||||
|
||||
removeChild(uiContainer);
|
||||
|
||||
background = null;
|
||||
flixelButton = null;
|
||||
starlingButton = null;
|
||||
uiContainer = null;
|
||||
}
|
||||
|
||||
private var starlingSingleton:Starling;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
private function onStarlingClick(e:MouseEvent):Void {
|
||||
trace("Launching Starling game");
|
||||
starlingSingleton = new Starling(starling.display.Sprite, stage, new Rectangle(0, 0, 800, 600));
|
||||
starlingSingleton.supportHighResolutions = true;
|
||||
starlingSingleton.addEventListener(Event.ROOT_CREATED, onStarlingRootCreated);
|
||||
}
|
||||
}
|
||||
|
||||
private function onStarlingRootCreated(event:Event):Void {
|
||||
destroyUI();
|
||||
starlingSingleton.removeEventListener(Event.ROOT_CREATED, onStarlingRootCreated);
|
||||
starlingSingleton.start();
|
||||
Starling.current.stage.color = 0x000000;
|
||||
|
||||
45
spine-haxe/example/src/MainFlixel.hx
Normal file
45
spine-haxe/example/src/MainFlixel.hx
Normal file
@ -0,0 +1,45 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package;
|
||||
|
||||
import flixelExamples.FlixelState;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
import openfl.display.Sprite;
|
||||
|
||||
class MainFlixel extends Sprite
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
addChild(new FlxGame(640, 480, FlixelState));
|
||||
FlxG.autoPause = false;
|
||||
}
|
||||
}
|
||||
57
spine-haxe/example/src/MainStarling.hx
Normal file
57
spine-haxe/example/src/MainStarling.hx
Normal file
@ -0,0 +1,57 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package;
|
||||
|
||||
import starlingExamples.BasicExample;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.geom.Rectangle;
|
||||
import starling.core.Starling;
|
||||
import starling.events.Event;
|
||||
|
||||
class MainStarling extends Sprite {
|
||||
private var starlingSingleton:Starling;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
starlingSingleton = new Starling(starling.display.Sprite, stage, new Rectangle(0, 0, 800, 600));
|
||||
starlingSingleton.supportHighResolutions = true;
|
||||
starlingSingleton.addEventListener(Event.ROOT_CREATED, onStarlingRootCreated);
|
||||
}
|
||||
|
||||
private function onStarlingRootCreated(event:Event):Void {
|
||||
starlingSingleton.removeEventListener(Event.ROOT_CREATED, onStarlingRootCreated);
|
||||
starlingSingleton.start();
|
||||
Starling.current.stage.color = 0x000000;
|
||||
|
||||
SceneManager.getInstance().switchScene(new BasicExample());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.text.FlxText;
|
||||
import spine.Skin;
|
||||
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 AnimationBoundExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
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);
|
||||
|
||||
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, .2);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSpriteClipping = new SkeletonSprite(data, animationStateData);
|
||||
var animationClipping = skeletonSpriteClipping.state.setAnimationByName(0, "portal", true).animation;
|
||||
skeletonSpriteClipping.update(0);
|
||||
skeletonSpriteClipping.setBoundingBox(animationClipping, true);
|
||||
skeletonSpriteClipping.screenCenter();
|
||||
skeletonSpriteClipping.x = FlxG.width / 4 - skeletonSpriteClipping.width / 2;
|
||||
add(skeletonSpriteClipping);
|
||||
var textClipping = new FlxText();
|
||||
textClipping.text = "Animation bound with clipping";
|
||||
textClipping.size = 12;
|
||||
textClipping.x = skeletonSpriteClipping.x + skeletonSpriteClipping.width / 2 - textClipping.width / 2;
|
||||
textClipping.y = skeletonSpriteClipping.y + skeletonSpriteClipping.height + 20;
|
||||
textClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
||||
add(textClipping);
|
||||
|
||||
var skeletonSpriteNoClipping = new SkeletonSprite(data, animationStateData);
|
||||
var animationClipping = skeletonSpriteNoClipping.state.setAnimationByName(0, "portal", true).animation;
|
||||
skeletonSpriteNoClipping.update(0);
|
||||
skeletonSpriteNoClipping.setBoundingBox(animationClipping, false);
|
||||
skeletonSpriteNoClipping.screenCenter();
|
||||
skeletonSpriteNoClipping.x = FlxG.width / 4 * 3 - skeletonSpriteClipping.width / 2 - 50;
|
||||
add(skeletonSpriteNoClipping);
|
||||
var textNoClipping = new FlxText();
|
||||
textNoClipping.text = "Animation bound without clipping";
|
||||
textNoClipping.size = 12;
|
||||
textNoClipping.x = skeletonSpriteNoClipping.x + skeletonSpriteNoClipping.width / 2 - textNoClipping.width / 2;
|
||||
textNoClipping.y = skeletonSpriteNoClipping.y + skeletonSpriteNoClipping.height + 20;
|
||||
textNoClipping.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
||||
add(textNoClipping);
|
||||
|
||||
var textInstruction = new FlxText();
|
||||
textInstruction.text = "Red rectangle is the animation bound";
|
||||
textInstruction.size = 12;
|
||||
textInstruction.screenCenter();
|
||||
textInstruction.y = textNoClipping.y + 40;
|
||||
textInstruction.setBorderStyle(FlxTextBorderStyle.OUTLINE, FlxColor.RED, 2);
|
||||
add(textInstruction);
|
||||
|
||||
FlxG.debugger.drawDebug = true;
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
87
spine-haxe/example/src/flixelExamples/BasicExample.hx
Normal file
87
spine-haxe/example/src/flixelExamples/BasicExample.hx
Normal file
@ -0,0 +1,87 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
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 BasicExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new SequenceExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/raptor.atlas"), new FlixelTextureLoader("assets/raptor-pro.atlas"));
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/raptor-pro.skel") : Assets.getText("assets/raptor-pro.json"), atlas, .25);
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
var animation = skeletonSprite.state.setAnimationByName(0, "walk", true).animation;
|
||||
skeletonSprite.setBoundingBox(animation);
|
||||
skeletonSprite.screenCenter();
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
|
||||
trace("loaded");
|
||||
}
|
||||
|
||||
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([DOWN])) {
|
||||
skeletonSprite.y += 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([UP])) {
|
||||
skeletonSprite.y -= 15;
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.text.FlxText;
|
||||
import flixel.math.FlxPoint;
|
||||
import spine.Skin;
|
||||
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 CelestialCircusExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new SnowglobeExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/celestial-circus.atlas"), new FlixelTextureLoader("assets/celestial-circus.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/celestial-circus-pro.skel") : Assets.getText("assets/celestial-circus-pro.json"), atlas, .15);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
37
spine-haxe/example/src/flixelExamples/CloudPotExample.hx
Normal file
37
spine-haxe/example/src/flixelExamples/CloudPotExample.hx
Normal file
@ -0,0 +1,37 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 CloudPotExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new AnimationBoundExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/cloud-pot.atlas"), new FlixelTextureLoader("assets/cloud-pot.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/cloud-pot.skel") : Assets.getText("assets/cloud-pot.json"), atlas, .25);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||
skeletonSprite.screenCenter();
|
||||
skeletonSprite.state.setAnimationByName(0, "playing-in-the-rain", true);
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
108
spine-haxe/example/src/flixelExamples/ControlBonesExample.hx
Normal file
108
spine-haxe/example/src/flixelExamples/ControlBonesExample.hx
Normal file
@ -0,0 +1,108 @@
|
||||
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<FlxSprite> = [];
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
77
spine-haxe/example/src/flixelExamples/EventsExample.hx
Normal file
77
spine-haxe/example/src/flixelExamples/EventsExample.hx
Normal file
@ -0,0 +1,77 @@
|
||||
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 {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
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<FlxText>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
195
spine-haxe/example/src/flixelExamples/FlixelState.hx
Normal file
195
spine-haxe/example/src/flixelExamples/FlixelState.hx
Normal file
@ -0,0 +1,195 @@
|
||||
package flixelExamples;
|
||||
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import spine.animation.AnimationStateData;
|
||||
import openfl.Assets;
|
||||
import spine.atlas.TextureAtlas;
|
||||
import spine.SkeletonData;
|
||||
import spine.flixel.SkeletonSprite;
|
||||
import spine.flixel.FlixelTextureLoader;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxState;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class FlixelState extends FlxState
|
||||
{
|
||||
var spineSprite:SkeletonSprite;
|
||||
var sprite:FlxSprite;
|
||||
var sprite2:FlxSprite;
|
||||
var myText:FlxText;
|
||||
var group:FlxSpriteGroup;
|
||||
var justSetWalking = false;
|
||||
|
||||
var jumping = false;
|
||||
|
||||
var scale = 4;
|
||||
var speed:Float;
|
||||
|
||||
override public function create():Void
|
||||
{
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
// setting speed of spineboy (450 is the speed to not let him slide)
|
||||
speed = 450 / scale;
|
||||
|
||||
// creating a group
|
||||
group = new FlxSpriteGroup();
|
||||
group.setPosition(50, 50);
|
||||
add(group);
|
||||
|
||||
// creating the sprite to check overlapping
|
||||
sprite = new FlxSprite();
|
||||
sprite.loadGraphic(FlxGraphic.fromRectangle(150, 100, 0xff8d008d));
|
||||
group.add(sprite);
|
||||
|
||||
// creating the text to display overlapping state
|
||||
myText = new FlxText(0, 25, 150, "", 16);
|
||||
myText.alignment = CENTER;
|
||||
group.add(myText);
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new BasicExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
// creating a sprite for the floor
|
||||
var floor = new FlxSprite();
|
||||
floor.loadGraphic(FlxGraphic.fromRectangle(FlxG.width, FlxG.height - 100, 0xff822f02));
|
||||
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);
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
spineSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
|
||||
// positioning spineboy
|
||||
spineSprite.setPosition(.5 * FlxG.width, .5 * FlxG.height);
|
||||
|
||||
// setting mix times
|
||||
animationStateData.defaultMix = 0.5;
|
||||
animationStateData.setMixByName("idle", "walk", 0.1);
|
||||
animationStateData.setMixByName("walk", "idle", 0.1);
|
||||
animationStateData.setMixByName("idle", "idle-turn", 0.05);
|
||||
animationStateData.setMixByName("idle-turn", "idle", 0.05);
|
||||
animationStateData.setMixByName("idle-turn", "walk", 0.3);
|
||||
animationStateData.setMixByName("idle", "jump", 0);
|
||||
animationStateData.setMixByName("jump", "idle", 0.05);
|
||||
animationStateData.setMixByName("jump", "walk", 0.05);
|
||||
animationStateData.setMixByName("walk", "jump", 0.05);
|
||||
|
||||
// setting idle animation
|
||||
spineSprite.state.setAnimationByName(0, "idle", true);
|
||||
|
||||
// setting y offset function to move object body while jumping
|
||||
var hip = spineSprite.skeleton.findBone("hip");
|
||||
var initialY = 0.;
|
||||
var initialOffsetY = 0.;
|
||||
spineSprite.state.onStart.add(entry -> {
|
||||
if (entry.animation.name == "jump") {
|
||||
initialY = spineSprite.y;
|
||||
initialOffsetY = spineSprite.offsetY;
|
||||
}
|
||||
});
|
||||
spineSprite.state.onComplete.add(entry -> {
|
||||
if (entry.animation.name == "jump") {
|
||||
jumping = false;
|
||||
spineSprite.y = initialY;
|
||||
spineSprite.offsetY = initialOffsetY;
|
||||
}
|
||||
});
|
||||
var diff = .0;
|
||||
spineSprite.afterUpdateWorldTransforms = spineSprite -> {
|
||||
if (jumping) {
|
||||
diff -= hip.y;
|
||||
spineSprite.offsetY -= diff;
|
||||
spineSprite.y += diff;
|
||||
}
|
||||
diff = hip.y;
|
||||
}
|
||||
|
||||
// adding spineboy to the stage
|
||||
add(spineSprite);
|
||||
|
||||
// FlxG.debugger.visible = !FlxG.debugger.visible;
|
||||
// debug ui
|
||||
// FlxG.debugger.visible = true;
|
||||
// FlxG.debugger.drawDebug = true;
|
||||
// FlxG.log.redirectTraces = true;
|
||||
|
||||
// FlxG.debugger.track(spineSprite);
|
||||
// FlxG.watch.add(spineSprite, "width");
|
||||
// FlxG.watch.add(spineSprite, "offsetY");
|
||||
// FlxG.watch.add(spineSprite, "y");
|
||||
// FlxG.watch.add(this, "jumping");
|
||||
super.create();
|
||||
}
|
||||
|
||||
var justSetIdle = true;
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
if (FlxG.overlap(spineSprite, group)) {
|
||||
myText.text = "Overlapping";
|
||||
} else {
|
||||
myText.text = "Non overlapping";
|
||||
}
|
||||
|
||||
if (!jumping && FlxG.keys.anyJustPressed([SPACE])) {
|
||||
spineSprite.state.setAnimationByName(0, "jump", false);
|
||||
jumping = true;
|
||||
justSetIdle = false;
|
||||
justSetWalking = false;
|
||||
}
|
||||
|
||||
if (FlxG.keys.anyJustPressed([J])) {
|
||||
// spineSprite.antialiasing = !spineSprite.antialiasing;
|
||||
FlxG.debugger.visible = !FlxG.debugger.visible;
|
||||
}
|
||||
|
||||
if (FlxG.keys.anyPressed([RIGHT, LEFT])) {
|
||||
justSetIdle = false;
|
||||
var flipped = false;
|
||||
var deltaX;
|
||||
if (FlxG.keys.anyPressed([RIGHT])) {
|
||||
if (spineSprite.flipX == true) flipped = true;
|
||||
spineSprite.flipX = false;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([LEFT])) {
|
||||
if (spineSprite.flipX == false) flipped = true;
|
||||
spineSprite.flipX = true;
|
||||
}
|
||||
|
||||
deltaX = (spineSprite.flipX == false ? 1 : -1) * speed * elapsed;
|
||||
spineSprite.x += deltaX;
|
||||
|
||||
if (!jumping && !justSetWalking) {
|
||||
justSetWalking = true;
|
||||
if (flipped) {
|
||||
spineSprite.state.setAnimationByName(0, "idle-turn", false);
|
||||
spineSprite.state.addAnimationByName(0, "walk", true, 0);
|
||||
} else {
|
||||
spineSprite.state.setAnimationByName(0, "walk", true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!jumping && !justSetIdle) {
|
||||
justSetWalking = false;
|
||||
justSetIdle = true;
|
||||
spineSprite.state.setAnimationByName(0, "idle", true);
|
||||
}
|
||||
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
55
spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx
Normal file
55
spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx
Normal file
@ -0,0 +1,55 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 MixAndMatchExample extends FlxState {
|
||||
var loadBinary = false;
|
||||
// var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new TankExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
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;
|
||||
|
||||
skeletonSprite.state.update(0);
|
||||
var animation = skeletonSprite.state.setAnimationByName(0, "dance", true).animation;
|
||||
skeletonSprite.setBoundingBox(animation);
|
||||
skeletonSprite.screenCenter();
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
}
|
||||
38
spine-haxe/example/src/flixelExamples/SackExample.hx
Normal file
38
spine-haxe/example/src/flixelExamples/SackExample.hx
Normal file
@ -0,0 +1,38 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 SackExample extends FlxState {
|
||||
var loadBinary = false;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new CelestialCircusExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/sack.atlas"), new FlixelTextureLoader("assets/sack.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/sack-pro.skel") : Assets.getText("assets/sack-pro.json"), atlas, .25);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||
skeletonSprite.screenCenter();
|
||||
skeletonSprite.x -= 100;
|
||||
skeletonSprite.state.setAnimationByName(0, "cape-follow-example", true);
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
39
spine-haxe/example/src/flixelExamples/SequenceExample.hx
Normal file
39
spine-haxe/example/src/flixelExamples/SequenceExample.hx
Normal file
@ -0,0 +1,39 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
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 SequenceExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new MixAndMatchExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/dragon.atlas"), new FlixelTextureLoader("assets/dragon.atlas"));
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/dragon-ess.skel") : Assets.getText("assets/dragon-.json"), atlas, .5);
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
|
||||
var animation = skeletonSprite.state.setAnimationByName(0, "flying", true).animation;
|
||||
skeletonSprite.setBoundingBox(animation);
|
||||
skeletonSprite.screenCenter();
|
||||
add(skeletonSprite);
|
||||
super.create();
|
||||
}
|
||||
|
||||
}
|
||||
37
spine-haxe/example/src/flixelExamples/SnowglobeExample.hx
Normal file
37
spine-haxe/example/src/flixelExamples/SnowglobeExample.hx
Normal file
@ -0,0 +1,37 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 SnowglobeExample extends FlxState {
|
||||
var loadBinary = false;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new CloudPotExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/snowglobe.atlas"), new FlixelTextureLoader("assets/snowglobe.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/snowglobe-pro.skel") : Assets.getText("assets/snowglobe-pro.json"), atlas, .125);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||
skeletonSprite.screenCenter();
|
||||
skeletonSprite.state.setAnimationByName(0, "shake", true);
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
38
spine-haxe/example/src/flixelExamples/TankExample.hx
Normal file
38
spine-haxe/example/src/flixelExamples/TankExample.hx
Normal file
@ -0,0 +1,38 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 TankExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new VineExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/tank.atlas"), new FlixelTextureLoader("assets/tank.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/tank-pro.skel") : Assets.getText("assets/tank-pro.json"), atlas, .125);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||
var animation = skeletonSprite.state.setAnimationByName(0, "drive", true).animation;
|
||||
skeletonSprite.setBoundingBox(animation);
|
||||
skeletonSprite.screenCenter();
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
38
spine-haxe/example/src/flixelExamples/VineExample.hx
Normal file
38
spine-haxe/example/src/flixelExamples/VineExample.hx
Normal file
@ -0,0 +1,38 @@
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
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 VineExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new SackExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/vine.atlas"), new FlixelTextureLoader("assets/vine.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/vine-pro.skel") : Assets.getText("assets/vine-pro.json"), atlas, .4);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(data, animationStateData);
|
||||
var animation = skeletonSprite.state.setAnimationByName(0, "grow", true).animation;
|
||||
skeletonSprite.setBoundingBox(animation);
|
||||
skeletonSprite.screenCenter();
|
||||
add(skeletonSprite);
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -56,17 +58,17 @@ class AnimationBoundExample extends Scene {
|
||||
|
||||
skeletonSpriteClipping = new SkeletonSprite(skeletondata, animationStateDataClipping);
|
||||
skeletonSpriteClipping.skeleton.updateWorldTransform(Physics.update);
|
||||
|
||||
|
||||
skeletonSpriteClipping.scale = scale;
|
||||
skeletonSpriteClipping.x = Starling.current.stage.stageWidth / 3 * 2;
|
||||
skeletonSpriteClipping.y = Starling.current.stage.stageHeight / 2;
|
||||
|
||||
|
||||
var animationClipping = skeletonSpriteClipping.state.setAnimationByName(0, "portal", true).animation;
|
||||
var animationBoundClipping = skeletonSpriteClipping.getAnimationBounds(animationClipping, true);
|
||||
var quad:Quad = new Quad(animationBoundClipping.width * scale, animationBoundClipping.height * scale, 0xc70000);
|
||||
quad.x = skeletonSpriteClipping.x + animationBoundClipping.x * scale;
|
||||
quad.y = skeletonSpriteClipping.y + animationBoundClipping.y * scale;
|
||||
|
||||
|
||||
var animationStateDataNoClipping = new AnimationStateData(skeletondata);
|
||||
animationStateDataNoClipping.defaultMix = 0.25;
|
||||
skeletonSpriteNoClipping = new SkeletonSprite(skeletondata, animationStateDataNoClipping);
|
||||
@ -83,7 +85,7 @@ class AnimationBoundExample extends Scene {
|
||||
|
||||
addChild(quad);
|
||||
addChild(quadNoClipping);
|
||||
addChild(skeletonSpriteClipping);
|
||||
addChild(skeletonSpriteClipping);
|
||||
addChild(skeletonSpriteNoClipping);
|
||||
addText("Animation bound without clipping", 75, 350);
|
||||
addText("Animation bound with clipping", 370, 350);
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,8 +27,10 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import spine.BlendMode;
|
||||
import Scene.SceneManager;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -27,8 +27,10 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import spine.BlendMode;
|
||||
import Scene.SceneManager;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -56,11 +58,11 @@ class CloudPotExample extends Scene {
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
var bounds = skeletonSprite.skeleton.getBounds();
|
||||
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.2;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight / 2;
|
||||
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "playing-in-the-rain", true);
|
||||
|
||||
addChild(skeletonSprite);
|
||||
@ -27,8 +27,10 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import openfl.geom.Point;
|
||||
import Scene.SceneManager;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -42,7 +44,7 @@ import starling.display.Canvas;
|
||||
|
||||
class ControlBonesExample extends Scene {
|
||||
var loadBinary = true;
|
||||
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
private var movement = new openfl.geom.Point();
|
||||
private var controlBones = [];
|
||||
@ -133,7 +135,7 @@ class ControlBonesExample extends Scene {
|
||||
skeletonSprite.skeleton.y += movement.y / skeletonSprite.scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (touchBackground) {
|
||||
var sceneTouch = e.getTouch(this);
|
||||
if (sceneTouch != null && sceneTouch.phase == TouchPhase.ENDED) {
|
||||
@ -27,8 +27,10 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import spine.animation.TrackEntry;
|
||||
import Scene.SceneManager;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,8 +27,10 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import spine.Skin;
|
||||
import Scene.SceneManager;
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -53,11 +55,11 @@ class SackExample extends Scene {
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.2;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight/ 2;
|
||||
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "cape-follow-example", true);
|
||||
|
||||
addChild(skeletonSprite);
|
||||
@ -27,6 +27,8 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
import starling.display.Quad;
|
||||
import starling.text.TextField;
|
||||
import starling.core.Starling;
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -55,11 +57,11 @@ class SnowglobeExample extends Scene {
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
var bounds = skeletonSprite.skeleton.getBounds();
|
||||
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.15;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight/ 1.5;
|
||||
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "shake", true);
|
||||
|
||||
addChild(skeletonSprite);
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationStateData;
|
||||
@ -27,7 +27,9 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import Scene.SceneManager;
|
||||
package starlingExamples;
|
||||
|
||||
import starlingExamples.Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
@ -3,10 +3,13 @@
|
||||
|
||||
<meta title="spine-haxe-example" package="spine" version="4.2.0" company="Esoteric Software" />
|
||||
<app main="Main" path="export" file="SpineHaxeExample" />
|
||||
<!-- <app main="MainStarling" path="export" file="SpineHaxeExample" /> -->
|
||||
<!-- <app main="MainFlixel" path="export" file="SpineHaxeExample" /> -->
|
||||
<window allow-high-dpi="true" />
|
||||
|
||||
<haxelib name="openfl" />
|
||||
<haxelib name="starling" />
|
||||
<haxelib name="flixel" />
|
||||
<haxelib name="spine-haxe" />
|
||||
|
||||
<source path="example/src" />
|
||||
|
||||
72
spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx
Normal file
72
spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx
Normal file
@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.flixel;
|
||||
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.FlxG;
|
||||
import spine.atlas.TextureAtlasPage;
|
||||
import spine.atlas.TextureAtlasRegion;
|
||||
import spine.atlas.TextureLoader;
|
||||
import spine.flixel.SpineTexture;
|
||||
|
||||
class FlixelTextureLoader implements TextureLoader
|
||||
{
|
||||
private var basePath:String;
|
||||
|
||||
public function new(prefix:String) {
|
||||
basePath = "";
|
||||
var slashIndex = prefix.lastIndexOf("/");
|
||||
if (slashIndex != -1) {
|
||||
basePath = prefix.substring(0, slashIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public function loadPage(page:TextureAtlasPage, path:String):Void
|
||||
{
|
||||
var bitmapData = openfl.utils.Assets.getBitmapData(basePath + "/" + path);
|
||||
if (bitmapData == null) {
|
||||
throw new SpineException("Could not load atlas page texture " + basePath + "/" + path);
|
||||
}
|
||||
var texture:FlxGraphic = SpineTexture.from(bitmapData);
|
||||
// TODO: reset this value to true when destroy skeleton
|
||||
// this is needed for sequence, otherwise the previous texture would be detroyed
|
||||
texture.destroyOnNoUse = false;
|
||||
page.texture = texture;
|
||||
}
|
||||
|
||||
public function loadRegion(region:TextureAtlasRegion):Void {
|
||||
region.texture = region.page.texture;
|
||||
}
|
||||
|
||||
public function unloadPage(page:TextureAtlasPage):Void
|
||||
{
|
||||
FlxG.bitmap.remove(cast page.texture);
|
||||
}
|
||||
}
|
||||
40
spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx
Normal file
40
spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx
Normal file
@ -0,0 +1,40 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.flixel;
|
||||
|
||||
import flixel.FlxStrip;
|
||||
|
||||
// this class is just to make the implementation coherent with the starling implementation
|
||||
class SkeletonMesh extends FlxStrip {
|
||||
public function new(/*texture:FlxGraphicAsset*/) {
|
||||
super();
|
||||
// graphic = texture;
|
||||
}
|
||||
}
|
||||
382
spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx
Normal file
382
spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx
Normal file
@ -0,0 +1,382 @@
|
||||
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;
|
||||
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.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxStrip;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.Vector;
|
||||
import openfl.display.BlendMode;
|
||||
import spine.Bone;
|
||||
import spine.Skeleton;
|
||||
import spine.SkeletonData;
|
||||
import spine.Slot;
|
||||
import spine.animation.AnimationState;
|
||||
import spine.animation.AnimationStateData;
|
||||
import spine.atlas.TextureAtlasRegion;
|
||||
import spine.attachments.MeshAttachment;
|
||||
import spine.attachments.RegionAttachment;
|
||||
import spine.attachments.ClippingAttachment;
|
||||
import spine.flixel.SkeletonMesh;
|
||||
|
||||
class SkeletonSprite extends FlxObject
|
||||
{
|
||||
public var skeleton(default, null):Skeleton;
|
||||
public var state(default, null):AnimationState;
|
||||
public var stateData(default, null):AnimationStateData;
|
||||
public var beforeUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
|
||||
public var afterUpdateWorldTransforms: SkeletonSprite -> Void = function(_) {};
|
||||
public static var clipper(default, never):SkeletonClipping = new SkeletonClipping();
|
||||
|
||||
public var offsetX = .0;
|
||||
public var offsetY = .0;
|
||||
public var alpha = 1.; // TODO: clamp
|
||||
public var color:FlxColor = 0xffffff;
|
||||
public var flipX(default, set):Bool = false;
|
||||
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<Float> = new Array<Float>();
|
||||
var _quadTriangles:Array<Int>;
|
||||
var _meshes(default, null):Array<SkeletonMesh> = new Array<SkeletonMesh>();
|
||||
|
||||
private var _tempMatrix = new FlxMatrix();
|
||||
private var _tempPoint = new Point();
|
||||
|
||||
private static var QUAD_INDICES:Array<Int> = [0, 1, 2, 2, 3, 0];
|
||||
public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null)
|
||||
{
|
||||
super(0, 0);
|
||||
Bone.yDown = true;
|
||||
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);
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
width = bounds.width;
|
||||
height = bounds.height;
|
||||
offsetX = -bounds.x;
|
||||
offsetY = -bounds.y;
|
||||
}
|
||||
}
|
||||
|
||||
public function getAnimationBounds(animation:Animation, clip:Bool = true): lime.math.Rectangle {
|
||||
var clipper = clip ? SkeletonSprite.clipper : null;
|
||||
skeleton.setToSetupPose();
|
||||
|
||||
var steps = 100, time = 0.;
|
||||
var stepTime = animation.duration != 0 ? animation.duration / steps : 0;
|
||||
var minX = 100000000., maxX = -100000000., minY = 100000000., maxY = -100000000.;
|
||||
|
||||
var bounds = new lime.math.Rectangle();
|
||||
for (i in 0...steps) {
|
||||
animation.apply(skeleton, time , time, false, [], 1, MixBlend.setup, MixDirection.mixIn);
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
bounds = skeleton.getBounds(clipper);
|
||||
|
||||
if (!Math.isNaN(bounds.x) && !Math.isNaN(bounds.y) && !Math.isNaN(bounds.width) && !Math.isNaN(bounds.height)) {
|
||||
minX = Math.min(bounds.x, minX);
|
||||
minY = Math.min(bounds.y, minY);
|
||||
maxX = Math.max(bounds.right, maxX);
|
||||
maxY = Math.max(bounds.bottom, maxY);
|
||||
} else
|
||||
trace("ERROR");
|
||||
|
||||
time += stepTime;
|
||||
}
|
||||
bounds.x = minX;
|
||||
bounds.y = minY;
|
||||
bounds.width = maxX - minX;
|
||||
bounds.height = maxY - minY;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
override public function destroy():Void
|
||||
{
|
||||
skeleton = null;
|
||||
state = null;
|
||||
stateData = 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 (FlxG.debugger.drawDebug) drawDebug();
|
||||
#end
|
||||
}
|
||||
|
||||
function renderMeshes():Void {
|
||||
var clipper:SkeletonClipping = SkeletonSprite.clipper;
|
||||
var drawOrder:Array<Slot> = skeleton.drawOrder;
|
||||
var attachmentColor:spine.Color;
|
||||
var mesh:SkeletonMesh = null;
|
||||
var numVertices:Int;
|
||||
var numFloats:Int;
|
||||
var triangles:Array<Int> = null;
|
||||
var uvs:Array<Float>;
|
||||
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) {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
var worldVertices:Array<Float> = _tempVertices;
|
||||
if (Std.isOfType(slot.attachment, RegionAttachment)) {
|
||||
var region:RegionAttachment = cast(slot.attachment, RegionAttachment);
|
||||
numVertices = 4;
|
||||
numFloats = clippedVertexSize << 2;
|
||||
if (numFloats > worldVertices.length) {
|
||||
worldVertices.resize(numFloats);
|
||||
}
|
||||
region.computeWorldVertices(slot, worldVertices, 0, clippedVertexSize);
|
||||
|
||||
mesh = getFlixelMeshFromRendererAttachment(region);
|
||||
mesh.graphic = region.region.texture;
|
||||
triangles = QUAD_INDICES;
|
||||
uvs = region.uvs;
|
||||
attachmentColor = region.color;
|
||||
} else if (Std.isOfType(slot.attachment, MeshAttachment)) {
|
||||
var meshAttachment:MeshAttachment = cast(slot.attachment, MeshAttachment);
|
||||
numVertices = meshAttachment.worldVerticesLength >> 1;
|
||||
numFloats = numVertices * clippedVertexSize; // 8 for now because I'm excluding clipping
|
||||
if (numFloats > worldVertices.length) {
|
||||
worldVertices.resize(numFloats);
|
||||
}
|
||||
meshAttachment.computeWorldVertices(slot, 0, meshAttachment.worldVerticesLength, worldVertices, 0, clippedVertexSize);
|
||||
|
||||
mesh = getFlixelMeshFromRendererAttachment(meshAttachment);
|
||||
mesh.graphic = meshAttachment.region.texture;
|
||||
triangles = meshAttachment.triangles;
|
||||
uvs = meshAttachment.uvs;
|
||||
attachmentColor = meshAttachment.color;
|
||||
} else if (Std.isOfType(slot.attachment, ClippingAttachment)) {
|
||||
var clip:ClippingAttachment = cast(slot.attachment, ClippingAttachment);
|
||||
clipper.clipStart(slot, clip);
|
||||
continue;
|
||||
} else {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesh != null) {
|
||||
|
||||
// cannot use directly mesh.color.setRGBFloat otherwise the setter won't be called and transfor color not set
|
||||
mesh.color = FlxColor.fromRGBFloat(
|
||||
skeleton.color.r * slot.color.r * attachmentColor.r * color.redFloat,
|
||||
skeleton.color.g * slot.color.g * attachmentColor.g * color.greenFloat,
|
||||
skeleton.color.b * slot.color.b * attachmentColor.b * color.blueFloat,
|
||||
1
|
||||
);
|
||||
mesh.alpha = skeleton.color.a * slot.color.a * attachmentColor.a * alpha;
|
||||
|
||||
if (clipper.isClipping()) {
|
||||
clipper.clipTriangles(worldVertices, triangles, triangles.length, uvs);
|
||||
|
||||
mesh.indices = Vector.ofArray(clipper.clippedTriangles);
|
||||
mesh.uvtData = Vector.ofArray(clipper.clippedUvs);
|
||||
|
||||
if (angle == 0) {
|
||||
mesh.vertices = Vector.ofArray(clipper.clippedVertices);
|
||||
mesh.x = x + offsetX;
|
||||
mesh.y = y + offsetY;
|
||||
} else {
|
||||
var i = 0;
|
||||
mesh.vertices.length = clipper.clippedVertices.length;
|
||||
while (i < mesh.vertices.length) {
|
||||
_tempPoint.setTo(clipper.clippedVertices[i], clipper.clippedVertices[i + 1]);
|
||||
_tempPoint = _tempMatrix.transformPoint(_tempPoint);
|
||||
mesh.vertices[i] = _tempPoint.x;
|
||||
mesh.vertices[i + 1] = _tempPoint.y;
|
||||
i+=2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var v = 0;
|
||||
var n = numFloats;
|
||||
var i = 0;
|
||||
mesh.vertices.length = numVertices;
|
||||
while (v < n) {
|
||||
if (angle == 0) {
|
||||
mesh.vertices[i] = worldVertices[v];
|
||||
mesh.vertices[i + 1] = worldVertices[v + 1];
|
||||
} else {
|
||||
_tempPoint.setTo(worldVertices[v], worldVertices[v + 1]);
|
||||
_tempPoint = _tempMatrix.transformPoint(_tempPoint);
|
||||
mesh.vertices[i] = _tempPoint.x;
|
||||
mesh.vertices[i + 1] = _tempPoint.y;
|
||||
}
|
||||
v += 8;
|
||||
i += 2;
|
||||
}
|
||||
if (angle == 0) {
|
||||
mesh.x = x + offsetX;
|
||||
mesh.y = y + offsetY;
|
||||
}
|
||||
mesh.indices = Vector.ofArray(triangles);
|
||||
mesh.uvtData = Vector.ofArray(uvs);
|
||||
}
|
||||
|
||||
mesh.antialiasing = antialiasing;
|
||||
mesh.blend = SpineTexture.toFlixelBlending(slot.data.blendMode);
|
||||
// x/y position works for mesh, but angle does not work.
|
||||
// if the transformation matrix is moved into the FlxStrip draw and used there
|
||||
// we can just put vertices without doing any transformation
|
||||
// mesh.x = x + offsetX;
|
||||
// mesh.y = y + offsetY;
|
||||
// mesh.angle = angle;
|
||||
mesh.draw();
|
||||
}
|
||||
|
||||
clipper.clipEndWithSlot(slot);
|
||||
}
|
||||
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<Float>):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<Float>):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<Float>, 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();
|
||||
region.rendererObject = skeletonMesh;
|
||||
skeletonMesh.exists = false;
|
||||
_meshes.push(skeletonMesh);
|
||||
}
|
||||
return region.rendererObject;
|
||||
}
|
||||
|
||||
function set_flipX(value:Bool):Bool
|
||||
{
|
||||
if (value != flipX) skeleton.scaleX = -skeleton.scaleX;
|
||||
return flipX = value;
|
||||
}
|
||||
|
||||
function set_flipY(value:Bool):Bool
|
||||
{
|
||||
if (value != flipY) skeleton.scaleY = -skeleton.scaleY;
|
||||
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 = {
|
||||
var rendererObject:Dynamic;
|
||||
var region:TextureRegion;
|
||||
}
|
||||
30
spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx
Normal file
30
spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx
Normal file
@ -0,0 +1,30 @@
|
||||
package spine.flixel;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import openfl.display.BlendMode;
|
||||
|
||||
class SpineTexture extends FlxGraphic
|
||||
{
|
||||
public static function from(bitmapData: openfl.display.BitmapData): FlxGraphic {
|
||||
return FlxG.bitmap.add(bitmapData);
|
||||
}
|
||||
|
||||
public static function toFlixelBlending (blend: spine.BlendMode): BlendMode {
|
||||
switch (blend) {
|
||||
case spine.BlendMode.normal:
|
||||
return BlendMode.NORMAL;
|
||||
|
||||
case spine.BlendMode.additive:
|
||||
return BlendMode.ADD;
|
||||
|
||||
case spine.BlendMode.multiply:
|
||||
return BlendMode.MULTIPLY;
|
||||
|
||||
case spine.BlendMode.screen:
|
||||
return BlendMode.SCREEN;
|
||||
}
|
||||
return BlendMode.NORMAL;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user