diff --git a/spine-haxe/README.md b/spine-haxe/README.md index 7601fe34b..e96237c40 100644 --- a/spine-haxe/README.md +++ b/spine-haxe/README.md @@ -51,4 +51,4 @@ As an IDE, we recommend [Visual Studio Code](https://code.visualstudio.com/) wit The extensions provide IDE features like auto-completion, debugging, and build support. -To debug the HTML5 build, set the Lime target in the status bar at the bottom of VS Code to `HTML5 / Debug`. Next, press `CTRL+SHIFT+B` (`CMD+SHIFT+B` on macOS) to build the project. Run the `lime` run configuration by pressing `F5`. This will start a webserver at `http://localhost:3000`. Finally, start the `web` run configuration. If you modify code, rebuild and restart the `web` configuration. +To debug a build, set the corresponding Lime target in the status bar at the bottom of VS Code to e.g. `HTML5 / Debug`. Run the `lime` run configuration by pressing `F5`. diff --git a/spine-haxe/example/src/BasicExample.hx b/spine-haxe/example/src/BasicExample.hx index 6e29895fc..b330f09b3 100644 --- a/spine-haxe/example/src/BasicExample.hx +++ b/spine-haxe/example/src/BasicExample.hx @@ -1,9 +1,10 @@ -import openfl.geom.Rectangle; import spine.SkeletonData; import spine.animation.AnimationStateData; import spine.atlas.TextureAtlas; import spine.starling.SkeletonSprite; import starling.core.Starling; +import starling.events.TouchEvent; +import starling.events.TouchPhase; class BasicExample extends Scene { var loadBinary = true; @@ -24,5 +25,14 @@ class BasicExample extends Scene { addChild(skeletonSprite); juggler.add(skeletonSprite); + + addEventListener(TouchEvent.TOUCH, onTouch); + } + + public function onTouch(e:TouchEvent) { + var touch = e.getTouch(this); + if (touch != null && touch.phase == TouchPhase.ENDED) { + trace("Mouse clicked"); + } } } diff --git a/spine-haxe/example/src/Main.hx b/spine-haxe/example/src/Main.hx index 96995bfb2..1c0617cb9 100644 --- a/spine-haxe/example/src/Main.hx +++ b/spine-haxe/example/src/Main.hx @@ -22,6 +22,6 @@ class Main extends Sprite { starlingSingleton.start(); Starling.current.stage.color = 0x000000; - SceneManager.getInstance().switchScene(new BasicExample()); + SceneManager.getInstance().switchScene(new SequenceExample()); } } diff --git a/spine-haxe/example/src/Scene.hx b/spine-haxe/example/src/Scene.hx index 64b7cf4f0..399091ddf 100644 --- a/spine-haxe/example/src/Scene.hx +++ b/spine-haxe/example/src/Scene.hx @@ -1,3 +1,5 @@ +import starling.utils.Color; +import starling.display.Quad; import starling.core.Starling; import starling.display.Sprite; diff --git a/spine-haxe/example/src/SequenceExample.hx b/spine-haxe/example/src/SequenceExample.hx new file mode 100644 index 000000000..64bc9d17a --- /dev/null +++ b/spine-haxe/example/src/SequenceExample.hx @@ -0,0 +1,42 @@ +import spine.SkeletonData; +import spine.animation.AnimationStateData; +import spine.atlas.TextureAtlas; +import spine.starling.SkeletonSprite; +import starling.core.Starling; +import starling.events.TouchEvent; +import starling.events.TouchPhase; + +class SequenceExample extends Scene { + var loadBinary = false; + + public function load():Void { + var atlas = TextureAtlas.fromAssets("assets/dragon.atlas"); + var skeletondata = SkeletonData.fromAssets("assets/dragon-ess" + (loadBinary ? ".skel" : ".json"), atlas); + var animationStateData = new AnimationStateData(skeletondata); + animationStateData.defaultMix = 0.25; + + var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData); + var bounds = skeletonSprite.skeleton.getBounds(); + skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width * 0.5; + skeletonSprite.x = Starling.current.stage.stageWidth / 2; + skeletonSprite.y = Starling.current.stage.stageHeight * 0.9; + + FIXME + sequences + are + broken + skeletonSprite.state.setAnimationByName(0, "flying", true); + + addChild(skeletonSprite); + juggler.add(skeletonSprite); + + addEventListener(TouchEvent.TOUCH, onTouch); + } + + public function onTouch(e:TouchEvent) { + var touch = e.getTouch(this); + if (touch != null && touch.phase == TouchPhase.ENDED) { + trace("Mouse clicked"); + } + } +} diff --git a/spine-haxe/spine-haxe/spine/SkeletonJson.hx b/spine-haxe/spine-haxe/spine/SkeletonJson.hx index 873d72dbd..6b33758a7 100644 --- a/spine-haxe/spine-haxe/spine/SkeletonJson.hx +++ b/spine-haxe/spine-haxe/spine/SkeletonJson.hx @@ -929,7 +929,7 @@ class SkeletonJson { throw new SpineException("Slot not found: " + slotMapName); for (attachmentMapName in slotMap) { var attachmentMap = slotMap[attachmentMapName]; - var attachment:VertexAttachment = cast(skin.getAttachment(slotIndex, attachmentMapName), VertexAttachment); + var attachment:Attachment = skin.getAttachment(slotIndex, attachmentMapName); if (attachment == null) throw new SpineException("Timeline attachment not found: " + attachmentMapName); @@ -940,11 +940,12 @@ class SkeletonJson { continue; if (timelineMapName == "deform") { - var weighted:Bool = attachment.bones != null; - var vertices:Vector = attachment.vertices; + var vertexAttachment = cast(attachment, VertexAttachment); + var weighted:Bool = vertexAttachment.bones != null; + var vertices:Vector = vertexAttachment.vertices; var deformLength:Int = weighted ? Std.int(vertices.length / 3 * 2) : vertices.length; - var deformTimeline:DeformTimeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + var deformTimeline:DeformTimeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, vertexAttachment); time = getFloat(keyMap, "time"); frame = 0; bezier = 0; diff --git a/spine-haxe/spine-haxe/spine/atlas/TextureAtlas.hx b/spine-haxe/spine-haxe/spine/atlas/TextureAtlas.hx index b965a90de..ef39fa2e2 100644 --- a/spine-haxe/spine-haxe/spine/atlas/TextureAtlas.hx +++ b/spine-haxe/spine-haxe/spine/atlas/TextureAtlas.hx @@ -19,7 +19,7 @@ class TextureAtlas { } var textureLoader = new AssetsTextureLoader(basePath); - return new TextureAtlas(Assets.getText("assets/raptor.atlas"), textureLoader); + return new TextureAtlas(Assets.getText(path), textureLoader); } /** @param object A String or ByteArray. */ diff --git a/spine-ts/spine-webgl/src/LoadingScreen.ts b/spine-ts/spine-webgl/src/LoadingScreen.ts index 19c3eb1f5..27d9af894 100644 --- a/spine-ts/spine-webgl/src/LoadingScreen.ts +++ b/spine-ts/spine-webgl/src/LoadingScreen.ts @@ -27,7 +27,7 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Color, Disposable, TimeKeeper } from "@esotericsoftware/spine-core"; +import { BlendMode, Color, Disposable, TimeKeeper } from "@esotericsoftware/spine-core"; import { GLTexture } from "./GLTexture"; import { ResizeMode, SceneRenderer } from "./SceneRenderer"; @@ -88,7 +88,7 @@ export class LoadingScreen implements Disposable { renderer.resize(ResizeMode.Expand); renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); - renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + renderer.batcher.setBlendMode(BlendMode.Normal, true); if (complete) { this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); diff --git a/spine-ts/spine-webgl/src/PolygonBatcher.ts b/spine-ts/spine-webgl/src/PolygonBatcher.ts index 3ce608348..2cbb36f4a 100644 --- a/spine-ts/spine-webgl/src/PolygonBatcher.ts +++ b/spine-ts/spine-webgl/src/PolygonBatcher.ts @@ -27,12 +27,19 @@ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -import { Disposable } from "@esotericsoftware/spine-core"; +import { BlendMode, Disposable } from "@esotericsoftware/spine-core"; import { GLTexture } from "./GLTexture"; import { Mesh, Position2Attribute, ColorAttribute, TexCoordAttribute, Color2Attribute } from "./Mesh"; import { Shader } from "./Shader"; import { ManagedWebGLRenderingContext } from "./WebGL"; +const GL_ONE = 1; +const GL_ONE_MINUS_SRC_COLOR = 0x0301; +const GL_SRC_ALPHA = 0x0302; +const GL_ONE_MINUS_SRC_ALPHA = 0x0303; +const GL_ONE_MINUS_DST_ALPHA = 0x0305; +const GL_DST_COLOR = 0x0306; + export class PolygonBatcher implements Disposable { public static disableCulling = false; @@ -47,8 +54,7 @@ export class PolygonBatcher implements Disposable { private indicesLength = 0; private srcColorBlend: number; private srcAlphaBlend: number; - private dstColorBlend: number; - private dstAlphaBlend: number; + private dstBlend: number; private cullWasEnabled = false; constructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true, maxVertices: number = 10920) { @@ -61,8 +67,7 @@ export class PolygonBatcher implements Disposable { let gl = this.context.gl; this.srcColorBlend = gl.SRC_ALPHA; this.srcAlphaBlend = gl.ONE; - this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA; - this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; } begin (shader: Shader) { @@ -74,7 +79,7 @@ export class PolygonBatcher implements Disposable { let gl = this.context.gl; gl.enable(gl.BLEND); - gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); if (PolygonBatcher.disableCulling) { this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE); @@ -82,17 +87,28 @@ export class PolygonBatcher implements Disposable { } } - setBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstColorBlend: number, dstAlphaBlend: number) { - if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstColorBlend == dstColorBlend && this.dstAlphaBlend == dstAlphaBlend) return; + private static blendModesGL: {srcRgb: number, srcRgbPma: number, dstRgb: number, srcAlpha: number}[] = [ + {srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + {srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE }, + {srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE}, + {srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE } + ] + + setBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean) { + const blendModeGL = PolygonBatcher.blendModesGL[blendMode]; + const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb; + const srcAlphaBlend = blendModeGL.srcAlpha; + const dstBlend = blendModeGL.dstRgb; + + if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return; this.srcColorBlend = srcColorBlend; this.srcAlphaBlend = srcAlphaBlend; - this.dstColorBlend = dstColorBlend; - this.dstAlphaBlend = dstAlphaBlend; + this.dstBlend = dstBlend; if (this.isDrawing) { this.flush(); - let gl = this.context.gl; - gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend); } + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); } draw (texture: GLTexture, vertices: ArrayLike, indices: Array) { diff --git a/spine-ts/spine-webgl/src/ShapeRenderer.ts b/spine-ts/spine-webgl/src/ShapeRenderer.ts index 240e86320..1bb7c066e 100644 --- a/spine-ts/spine-webgl/src/ShapeRenderer.ts +++ b/spine-ts/spine-webgl/src/ShapeRenderer.ts @@ -43,8 +43,7 @@ export class ShapeRenderer implements Disposable { private tmp = new Vector2(); private srcColorBlend: number; private srcAlphaBlend: number; - private dstColorBlend: number; - private dstAlphaBlend: number; + private dstBlend: number; constructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, maxVertices: number = 10920) { if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); @@ -53,8 +52,7 @@ export class ShapeRenderer implements Disposable { let gl = this.context.gl; this.srcColorBlend = gl.SRC_ALPHA; this.srcAlphaBlend = gl.ONE; - this.dstColorBlend = gl.ONE_MINUS_SRC_ALPHA; - this.dstAlphaBlend = gl.ONE_MINUS_SRC_ALPHA; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; } begin (shader: Shader) { @@ -65,18 +63,17 @@ export class ShapeRenderer implements Disposable { let gl = this.context.gl; gl.enable(gl.BLEND); - gl.blendFuncSeparate(this.srcColorBlend, this.dstColorBlend, this.srcAlphaBlend, this.dstAlphaBlend); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); } - setBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstColorBlend: number, dstAlphaBlend: number) { + setBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstBlend: number) { this.srcColorBlend = srcColorBlend; this.srcAlphaBlend = srcAlphaBlend; - this.dstColorBlend = dstColorBlend; - this.dstAlphaBlend = dstAlphaBlend; + this.dstBlend = dstBlend; if (this.isDrawing) { this.flush(); let gl = this.context.gl; - gl.blendFuncSeparate(srcColorBlend, dstColorBlend, srcAlphaBlend, dstAlphaBlend); + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); } } diff --git a/spine-ts/spine-webgl/src/SkeletonDebugRenderer.ts b/spine-ts/spine-webgl/src/SkeletonDebugRenderer.ts index 7273b6d2b..ed71b5c7a 100644 --- a/spine-ts/spine-webgl/src/SkeletonDebugRenderer.ts +++ b/spine-ts/spine-webgl/src/SkeletonDebugRenderer.ts @@ -67,7 +67,7 @@ export class SkeletonDebugRenderer implements Disposable { let skeletonY = skeleton.y; let gl = this.context.gl; let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; - shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); let bones = skeleton.bones; if (this.drawBones) { diff --git a/spine-ts/spine-webgl/src/SkeletonRenderer.ts b/spine-ts/spine-webgl/src/SkeletonRenderer.ts index 9c77897be..034fac2c8 100644 --- a/spine-ts/spine-webgl/src/SkeletonRenderer.ts +++ b/spine-ts/spine-webgl/src/SkeletonRenderer.ts @@ -30,7 +30,7 @@ import { NumberArrayLike, Color, SkeletonClipping, Vector2, Utils, Skeleton, BlendMode, RegionAttachment, TextureAtlasRegion, MeshAttachment, ClippingAttachment } from "@esotericsoftware/spine-core"; import { GLTexture } from "./GLTexture"; import { PolygonBatcher } from "./PolygonBatcher"; -import { ManagedWebGLRenderingContext, WebGLBlendModeConverter } from "./WebGL"; +import { ManagedWebGLRenderingContext } from "./WebGL"; class Renderable { @@ -68,11 +68,6 @@ export class SkeletonRenderer { let twoColorTint = this.twoColorTint; let blendMode: BlendMode | null = null; - let tempPos = this.temp; - let tempUv = this.temp2; - let tempLight = this.temp3; - let tempDark = this.temp4; - let renderable: Renderable = this.renderable; let uvs: NumberArrayLike; let triangles: Array; @@ -166,11 +161,7 @@ export class SkeletonRenderer { let slotBlendMode = slot.data.blendMode; if (slotBlendMode != blendMode) { blendMode = slotBlendMode; - batcher.setBlendMode( - WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha), - WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode, premultipliedAlpha), - WebGLBlendModeConverter.getDestColorGLBlendMode(blendMode), - WebGLBlendModeConverter.getDestAlphaGLBlendMode(blendMode, premultipliedAlpha)); + batcher.setBlendMode(blendMode, premultipliedAlpha); } if (clipper.isClipping()) { diff --git a/spine-ts/spine-webgl/src/WebGL.ts b/spine-ts/spine-webgl/src/WebGL.ts index ad7326808..f90009487 100644 --- a/spine-ts/spine-webgl/src/WebGL.ts +++ b/spine-ts/spine-webgl/src/WebGL.ts @@ -62,63 +62,3 @@ export class ManagedWebGLRenderingContext { if (index > -1) this.restorables.splice(index, 1); } } - -const ONE = 1; -const ONE_MINUS_SRC_COLOR = 0x0301; -const SRC_ALPHA = 0x0302; -const ONE_MINUS_SRC_ALPHA = 0x0303; -const ONE_MINUS_DST_ALPHA = 0x0305; -const DST_COLOR = 0x0306; - -export class WebGLBlendModeConverter { - - static getDestGLBlendMode (blendMode: BlendMode) { - switch (blendMode) { - case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Additive: return ONE; - case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Screen: return ONE_MINUS_SRC_ALPHA; - default: throw new Error("Unknown blend mode: " + blendMode); - } - } - - static getDestColorGLBlendMode (blendMode: BlendMode) { - switch (blendMode) { - case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Additive: return ONE; - case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Screen: return ONE_MINUS_SRC_COLOR; - default: throw new Error("Unknown blend mode: " + blendMode); - } - } - - static getDestAlphaGLBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean = false) { - switch (blendMode) { - case BlendMode.Normal: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Additive: return premultipliedAlpha ? ONE_MINUS_SRC_ALPHA : ONE; - case BlendMode.Multiply: return ONE_MINUS_SRC_ALPHA; - case BlendMode.Screen: return ONE_MINUS_SRC_ALPHA; - default: throw new Error("Unknown blend mode: " + blendMode); - } - } - - static getSourceColorGLBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean = false) { - switch (blendMode) { - case BlendMode.Normal: return premultipliedAlpha ? ONE : SRC_ALPHA; - case BlendMode.Additive: return premultipliedAlpha ? ONE : SRC_ALPHA; - case BlendMode.Multiply: return DST_COLOR; - case BlendMode.Screen: return premultipliedAlpha ? ONE : SRC_ALPHA; - default: throw new Error("Unknown blend mode: " + blendMode); - } - } - - static getSourceAlphaGLBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean = false) { - switch (blendMode) { - case BlendMode.Normal: return premultipliedAlpha ? SRC_ALPHA : ONE; - case BlendMode.Additive: return premultipliedAlpha ? SRC_ALPHA : ONE; - case BlendMode.Multiply: return ONE; - case BlendMode.Screen: return ONE; - default: throw new Error("Unknown blend mode: " + blendMode); - } - } -}