From 7f2a3fe0139bb8e0d96aa82ebe500addefcaa40f Mon Sep 17 00:00:00 2001 From: ljurow <50641800+ljurow@users.noreply.github.com> Date: Tue, 18 Feb 2025 01:42:26 -0700 Subject: [PATCH 01/24] [ts][threejs] Skin.attachAll() null check (#2755) --- spine-haxe/spine-haxe/spine/Skin.hx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spine-haxe/spine-haxe/spine/Skin.hx b/spine-haxe/spine-haxe/spine/Skin.hx index 769cdddac..56e9da5aa 100644 --- a/spine-haxe/spine-haxe/spine/Skin.hx +++ b/spine-haxe/spine-haxe/spine/Skin.hx @@ -228,13 +228,15 @@ class Skin { var slotAttachment:Attachment = slot.attachment; if (slotAttachment != null && slotIndex < oldSkin.attachments.length) { var dictionary:StringMap = oldSkin.attachments[slotIndex]; - for (name in dictionary.keys()) { - var skinAttachment:Attachment = dictionary.get(name); - if (slotAttachment == skinAttachment) { - var attachment:Attachment = getAttachment(slotIndex, name); - if (attachment != null) - slot.attachment = attachment; - break; + if (null != dictionary) { + for (name in dictionary.keys()) { + var skinAttachment:Attachment = dictionary.get(name); + if (slotAttachment == skinAttachment) { + var attachment:Attachment = getAttachment(slotIndex, name); + if (attachment != null) + slot.attachment = attachment; + break; + } } } } From d11564b1568d9c7d97268f8b59803da4db31d10c Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Tue, 18 Feb 2025 09:57:44 +0100 Subject: [PATCH 02/24] [haxe] Release 4.2.4 --- spine-haxe/haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-haxe/haxelib.json b/spine-haxe/haxelib.json index 78328344e..b875c3f85 100644 --- a/spine-haxe/haxelib.json +++ b/spine-haxe/haxelib.json @@ -17,8 +17,8 @@ "cpp" ], "description": "The official Spine Runtime for Haxe", - "version": "4.2.3", - "releasenote": "Update to 4.2.3", + "version": "4.2.4", + "releasenote": "Update to 4.2.4", "contributors": [ "esotericsoftware" ], From da1ab4929116792d232ad32e8437268f77422666 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Thu, 20 Feb 2025 12:56:12 +0100 Subject: [PATCH 03/24] [ts][pixi-v8] Fix currentClippingSlot not reset. Close #2757. --- spine-ts/spine-pixi-v8/src/Spine.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spine-ts/spine-pixi-v8/src/Spine.ts b/spine-ts/spine-pixi-v8/src/Spine.ts index 6870300ce..75afa9b56 100644 --- a/spine-ts/spine-pixi-v8/src/Spine.ts +++ b/spine-ts/spine-pixi-v8/src/Spine.ts @@ -560,6 +560,7 @@ export class Spine extends ViewContainer { this.spineAttachmentsDirty ||= spineAttachmentsDirty; } + private currentClippingSlot: SlotsToClipping | undefined; private updateAndSetPixiMask (slot: Slot, last: boolean) { // assign/create the currentClippingSlot const attachment = slot.attachment; @@ -614,10 +615,10 @@ export class Spine extends ViewContainer { clippingSlotToPixiMask.mask = undefined; } } + this.currentClippingSlot = undefined; } } - private currentClippingSlot: SlotsToClipping | undefined; private transformAttachments () { const currentDrawOrder = this.skeleton.drawOrder; From 9f819b387207e5a5dac409eb69d0618acaed81e0 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Thu, 20 Feb 2025 12:58:57 +0100 Subject: [PATCH 04/24] [ts] Release 4.2.74 --- spine-ts/package-lock.json | 42 +++++++++++++-------------- spine-ts/package.json | 2 +- spine-ts/spine-canvas/package.json | 4 +-- spine-ts/spine-canvaskit/package.json | 4 +-- spine-ts/spine-core/package.json | 2 +- spine-ts/spine-phaser/package.json | 8 ++--- spine-ts/spine-pixi-v7/package.json | 4 +-- spine-ts/spine-pixi-v8/package.json | 4 +-- spine-ts/spine-player/package.json | 4 +-- spine-ts/spine-threejs/package.json | 4 +-- spine-ts/spine-webgl/package.json | 4 +-- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/spine-ts/package-lock.json b/spine-ts/package-lock.json index 19d1544cf..872d9f76d 100644 --- a/spine-ts/package-lock.json +++ b/spine-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.73", + "version": "4.2.74", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@esotericsoftware/spine-ts", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "workspaces": [ "spine-core", @@ -3142,18 +3142,18 @@ }, "spine-canvas": { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" } }, "spine-canvaskit": { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73", + "@esotericsoftware/spine-core": "4.2.74", "canvaskit-wasm": "0.39.1" }, "devDependencies": { @@ -3163,17 +3163,17 @@ }, "spine-core": { "name": "@esotericsoftware/spine-core", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE" }, "spine-phaser": { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-canvas": "4.2.73", - "@esotericsoftware/spine-core": "4.2.73", - "@esotericsoftware/spine-webgl": "4.2.73" + "@esotericsoftware/spine-canvas": "4.2.74", + "@esotericsoftware/spine-core": "4.2.74", + "@esotericsoftware/spine-webgl": "4.2.74" }, "peerDependencies": { "phaser": "^3.60.0" @@ -3181,10 +3181,10 @@ }, "spine-pixi-v7": { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "peerDependencies": { "@pixi/assets": "^7.2.4", @@ -3198,10 +3198,10 @@ }, "spine-pixi-v8": { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "peerDependencies": { "pixi.js": "^8.4.0" @@ -3209,18 +3209,18 @@ }, "spine-player": { "name": "@esotericsoftware/spine-player", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.73" + "@esotericsoftware/spine-webgl": "4.2.74" } }, "spine-threejs": { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "devDependencies": { "@types/three": "0.162.0" @@ -3231,10 +3231,10 @@ }, "spine-webgl": { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.73", + "version": "4.2.74", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" } } } diff --git a/spine-ts/package.json b/spine-ts/package.json index 7f4f29287..5ff4ca358 100644 --- a/spine-ts/package.json +++ b/spine-ts/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "type": "module", "files": [ diff --git a/spine-ts/spine-canvas/package.json b/spine-ts/spine-canvas/package.json index 31705eb0f..e33be56df 100644 --- a/spine-ts/spine-canvas/package.json +++ b/spine-ts/spine-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" } } \ No newline at end of file diff --git a/spine-ts/spine-canvaskit/package.json b/spine-ts/spine-canvaskit/package.json index d492ba5ad..41a7989c9 100644 --- a/spine-ts/spine-canvaskit/package.json +++ b/spine-ts/spine-canvaskit/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for CanvasKit for NodeJS", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73", + "@esotericsoftware/spine-core": "4.2.74", "canvaskit-wasm": "0.39.1" }, "devDependencies": { diff --git a/spine-ts/spine-core/package.json b/spine-ts/spine-core/package.json index d15c5a0f9..e5cb93613 100644 --- a/spine-ts/spine-core/package.json +++ b/spine-ts/spine-core/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-core", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/spine-ts/spine-phaser/package.json b/spine-ts/spine-phaser/package.json index 62ca2fac8..d2ac4b355 100644 --- a/spine-ts/spine-phaser/package.json +++ b/spine-ts/spine-phaser/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the Phaser.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,9 +31,9 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73", - "@esotericsoftware/spine-webgl": "4.2.73", - "@esotericsoftware/spine-canvas": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74", + "@esotericsoftware/spine-webgl": "4.2.74", + "@esotericsoftware/spine-canvas": "4.2.74" }, "peerDependencies": { "phaser": "^3.60.0" diff --git a/spine-ts/spine-pixi-v7/package.json b/spine-ts/spine-pixi-v7/package.json index 46b52111a..44aa2e8c2 100644 --- a/spine-ts/spine-pixi-v7/package.json +++ b/spine-ts/spine-pixi-v7/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web PixiJS v7.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "peerDependencies": { "@pixi/core": "^7.2.4", diff --git a/spine-ts/spine-pixi-v8/package.json b/spine-ts/spine-pixi-v8/package.json index 26cf3d06c..cc9e4ff76 100644 --- a/spine-ts/spine-pixi-v8/package.json +++ b/spine-ts/spine-pixi-v8/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for PixiJS v8.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "peerDependencies": { "pixi.js": "^8.4.0" diff --git a/spine-ts/spine-player/package.json b/spine-ts/spine-player/package.json index 01d39db82..7b9424d5c 100644 --- a/spine-ts/spine-player/package.json +++ b/spine-ts/spine-player/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-player", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.73" + "@esotericsoftware/spine-webgl": "4.2.74" } } \ No newline at end of file diff --git a/spine-ts/spine-threejs/package.json b/spine-ts/spine-threejs/package.json index a415ff4d7..0a8759e3c 100644 --- a/spine-ts/spine-threejs/package.json +++ b/spine-ts/spine-threejs/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" }, "devDependencies": { "@types/three": "0.162.0" diff --git a/spine-ts/spine-webgl/package.json b/spine-ts/spine-webgl/package.json index 8f000285c..5b916a8a4 100644 --- a/spine-ts/spine-webgl/package.json +++ b/spine-ts/spine-webgl/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.73", + "version": "4.2.74", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.73" + "@esotericsoftware/spine-core": "4.2.74" } } \ No newline at end of file From 219348e7f48fc6a4f6a6bd260c648a43cdc60ffd Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Thu, 20 Feb 2025 15:42:54 +0100 Subject: [PATCH 05/24] [ts][threejs] Fixed dark tint shader. --- spine-ts/spine-threejs/src/MeshBatcher.ts | 2 +- spine-ts/spine-threejs/src/SkeletonMesh.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-ts/spine-threejs/src/MeshBatcher.ts b/spine-ts/spine-threejs/src/MeshBatcher.ts index 36307f97c..1e72634f9 100644 --- a/spine-ts/spine-threejs/src/MeshBatcher.ts +++ b/spine-ts/spine-threejs/src/MeshBatcher.ts @@ -309,7 +309,7 @@ const spineOnBeforeCompile = (shader: THREE.WebGLProgramParametersWithUniforms) #ifdef USE_SPINE_DARK_TINT #ifdef USE_COLOR_ALPHA diffuseColor.a *= vColor.a; - diffuseColor.rgb *= (1.0 - diffuseColor.rgb) * v_dark.rgb + diffuseColor.rgb * vColor.rgb; + diffuseColor.rgb = (diffuseColor.a - diffuseColor.rgb) * v_dark.rgb + diffuseColor.rgb * vColor.rgb; #endif #else #ifdef USE_COLOR_ALPHA diff --git a/spine-ts/spine-threejs/src/SkeletonMesh.ts b/spine-ts/spine-threejs/src/SkeletonMesh.ts index 1d335ec8d..797af709e 100644 --- a/spine-ts/spine-threejs/src/SkeletonMesh.ts +++ b/spine-ts/spine-threejs/src/SkeletonMesh.ts @@ -294,7 +294,7 @@ export class SkeletonMesh extends THREE.Object3D { let darkColor = this.tempDarkColor; if (!slot.darkColor) - darkColor.set(1, 1, 1, 0); + darkColor.set(0, 0, 0, 1); else { darkColor.r = slot.darkColor.r * alpha; darkColor.g = slot.darkColor.g * alpha; From 01a847b7f706e9789d3bc82656b679e4d061ae78 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 20 Feb 2025 19:30:17 +0100 Subject: [PATCH 06/24] [unity] Fixed outline shaders semi transparent gap around skeleton. All outline shaders now provide a `Fill` parameter. Closes #2758. --- CHANGELOG.md | 1 + .../Editor/Shaders/SpineShaderWithOutlineGUI.cs | 5 +++++ .../BlendModes/Spine-Skeleton-PMA-Additive.shader | 1 + .../BlendModes/Spine-Skeleton-PMA-Multiply.shader | 1 + .../Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader | 1 + .../Shaders/CGIncludes/Spine-Outline-Common.cginc | 9 +++++++-- .../Spine-Skeleton-PMA-Additive-Outline.shader | 1 + .../Spine-Skeleton-PMA-Multiply-Outline.shader | 1 + .../BlendModes/Spine-Skeleton-PMA-Screen-Outline.shader | 1 + .../SkeletonGraphic/Spine-SkeletonGraphic-Outline.shader | 1 + .../Spine-SkeletonGraphic-TintBlack-Outline.shader | 1 + .../Shaders/Outline/Spine-Skeleton-Fill-Outline.shader | 1 + .../Shaders/Outline/Spine-Skeleton-Lit-Outline.shader | 1 + .../Outline/Spine-Skeleton-Lit-ZWrite-Outline.shader | 1 + .../Shaders/Outline/Spine-Skeleton-Outline.shader | 2 ++ .../Outline/Spine-Skeleton-OutlineOnly-ZWrite.shader | 2 ++ .../Shaders/Outline/Spine-Skeleton-Tint-Outline.shader | 1 + .../Outline/Spine-Skeleton-TintBlack-Outline.shader | 1 + .../Spine-Special-Skeleton-Grayscale-Outline.shader | 1 + .../Outline/Sprite/SpritesPixelLit-Outline.shader | 1 + .../Shaders/Outline/Sprite/SpritesUnlit-Outline.shader | 1 + .../Outline/Sprite/SpritesVertexLit-Outline.shader | 1 + .../Spine-SkeletonGraphic-Additive.shader | 1 + .../SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader | 1 + .../Spine-SkeletonGraphic-Grayscale.shader | 1 + .../Spine-SkeletonGraphic-Multiply.shader | 1 + .../SkeletonGraphic/Spine-SkeletonGraphic-Screen.shader | 1 + .../Shaders/SkeletonGraphic/Spine-SkeletonGraphic.shader | 1 + .../Spine-SkeletonGraphic-TintBlack-Additive.shader | 1 + .../Spine-SkeletonGraphic-TintBlack-Multiply.shader | 1 + .../Spine-SkeletonGraphic-TintBlack-Screen.shader | 1 + .../TintBlack/Spine-SkeletonGraphic-TintBlack.shader | 1 + .../spine-unity/Shaders/Spine-Skeleton-Fill.shader | 1 + .../spine-unity/Shaders/Spine-Skeleton-Lit-ZWrite.shader | 1 + .../spine-unity/Shaders/Spine-Skeleton-Lit.shader | 1 + .../spine-unity/Shaders/Spine-Skeleton-Tint.shader | 1 + .../spine-unity/Shaders/Spine-Skeleton-TintBlack.shader | 1 + .../Runtime/spine-unity/Shaders/Spine-Skeleton.shader | 1 + .../Shaders/Spine-Special-Skeleton-Grayscale.shader | 1 + .../spine-unity/Shaders/Sprite/SpritesPixelLit.shader | 1 + .../spine-unity/Shaders/Sprite/SpritesUnlit.shader | 1 + .../spine-unity/Shaders/Sprite/SpritesVertexLit.shader | 1 + spine-unity/Assets/Spine/package.json | 2 +- .../Outline/Spine-Skeleton-OutlineOnly-URP.shader | 2 ++ .../Outline/Spine-Skeleton-OutlineOnly-ZWrite-URP.shader | 2 ++ .../com.esotericsoftware.spine.urp-shaders/package.json | 2 +- 46 files changed, 60 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d695cea..f57f3cbfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -169,6 +169,7 @@ - SkeletonMecanim: Added `Scene Preview` option to preview an Animation Clip for e.g. easier event placement. When enabled, the Animation Clip selected in the Animation window is previewed in the Scene and Game views. Lock the `SkeletonMecanim` Inspector window, open the Animation window and select the Animation Clip. Then in the Animation window scrub through the timeline to see the current animation frame previewed. - `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex. - `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel. + - All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour. - **Breaking changes** diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineShaderWithOutlineGUI.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineShaderWithOutlineGUI.cs index effb6d9ef..9d4c6d367 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineShaderWithOutlineGUI.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineShaderWithOutlineGUI.cs @@ -41,6 +41,7 @@ public class SpineShaderWithOutlineGUI : ShaderGUI { MaterialProperty _OutlineWidth = null; MaterialProperty _UseScreenSpaceOutlineWidth = null; MaterialProperty _OutlineColor = null; + MaterialProperty _Fill = null; MaterialProperty _OutlineReferenceTexWidth = null; MaterialProperty _ThresholdEnd = null; MaterialProperty _OutlineSmoothness = null; @@ -54,6 +55,7 @@ public class SpineShaderWithOutlineGUI : ShaderGUI { static GUIContent _OutlineWidthText = new GUIContent("Outline Width", ""); static GUIContent _UseScreenSpaceOutlineWidthText = new GUIContent("Width in Screen Space", "Enable to keep the outline width constant in screen space instead of texture space. Requires more expensive computations."); static GUIContent _OutlineColorText = new GUIContent("Outline Color", ""); + static GUIContent _FillText = new GUIContent("Fill", "Enable to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton."); static GUIContent _OutlineReferenceTexWidthText = new GUIContent("Reference Texture Width", ""); static GUIContent _ThresholdEndText = new GUIContent("Outline Threshold", ""); static GUIContent _OutlineSmoothnessText = new GUIContent("Outline Smoothness", ""); @@ -92,6 +94,7 @@ public class SpineShaderWithOutlineGUI : ShaderGUI { _UseScreenSpaceOutlineWidth = FindProperty("_UseScreenSpaceOutlineWidth", props, false); _OutlineReferenceTexWidth = FindProperty("_OutlineReferenceTexWidth", props, false); _OutlineColor = FindProperty("_OutlineColor", props, false); + _Fill = FindProperty("_Fill", props, false); _ThresholdEnd = FindProperty("_ThresholdEnd", props, false); _OutlineSmoothness = FindProperty("_OutlineSmoothness", props, false); _Use8Neighbourhood = FindProperty("_Use8Neighbourhood", props, false); @@ -157,6 +160,8 @@ public class SpineShaderWithOutlineGUI : ShaderGUI { if (_UseScreenSpaceOutlineWidth != null) _materialEditor.ShaderProperty(_UseScreenSpaceOutlineWidth, _UseScreenSpaceOutlineWidthText); _materialEditor.ShaderProperty(_OutlineColor, _OutlineColorText); + if (_Fill != null) + _materialEditor.ShaderProperty(_Fill, _FillText); _showAdvancedOutlineSettings = EditorGUILayout.Foldout(_showAdvancedOutlineSettings, _OutlineAdvancedText); if (_showAdvancedOutlineSettings) { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader index 7da343e05..a9cb2cbc3 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader @@ -18,6 +18,7 @@ Shader "Spine/Blend Modes/Skeleton PMA Additive" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader index 0454ffcfb..574facd0d 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader @@ -18,6 +18,7 @@ Shader "Spine/Blend Modes/Skeleton PMA Multiply" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader index b39c9cf7e..53298c69c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader @@ -18,6 +18,7 @@ Shader "Spine/Blend Modes/Skeleton PMA Screen" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc index ae3763848..f82ce6e09 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc @@ -46,8 +46,13 @@ float4 computeOutlinePixel(sampler2D mainTexture, float2 mainTextureTexelSize, float average = (pixelTop + pixelBottom + pixelLeft + pixelRight) * vertexColorAlpha / numSamples; #endif float thresholdStart = ThresholdEnd * (1.0 - OutlineSmoothness); - float outlineAlpha = saturate(saturate((average - thresholdStart) / (ThresholdEnd - thresholdStart)) - pixelCenter); - outlineAlpha = pixelCenter > OutlineOpaqueAlpha ? 0 : outlineAlpha; + float outlineAlpha = saturate((average - thresholdStart) / (ThresholdEnd - thresholdStart)); +#if !_OUTLINE_FILL_INSIDE + outlineAlpha = saturate(outlineAlpha - pixelCenter); + outlineAlpha = pixelCenter > OutlineOpaqueAlpha ? 0.0 : outlineAlpha; +#else + outlineAlpha = pixelCenter > OutlineOpaqueAlpha ? 1.0 : outlineAlpha; +#endif return lerp(texColor, OutlineColor, outlineAlpha); } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Additive-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Additive-Outline.shader index 56a176967..d4cb13fc3 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Additive-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Additive-Outline.shader @@ -13,6 +13,7 @@ Shader "Spine/Outline/Blend Modes/Skeleton PMA Additive" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Multiply-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Multiply-Outline.shader index c008d45a1..9c1fd3ed5 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Multiply-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Multiply-Outline.shader @@ -13,6 +13,7 @@ Shader "Spine/Outline/Blend Modes/Skeleton PMA Multiply" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Screen-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Screen-Outline.shader index cdd7bd7ca..07b8edcee 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Screen-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/BlendModes/Spine-Skeleton-PMA-Screen-Outline.shader @@ -13,6 +13,7 @@ Shader "Spine/Outline/Blend Modes/Skeleton PMA Screen" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-Outline.shader index b899d9d03..6ef6cb083 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-Outline.shader @@ -23,6 +23,7 @@ Shader "Spine/Outline/SkeletonGraphic" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack-Outline.shader index 51647cb3f..3ab6749de 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack-Outline.shader @@ -25,6 +25,7 @@ Shader "Spine/Outline/SkeletonGraphic Tint Black" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Fill-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Fill-Outline.shader index 0c00f2368..1c3da7f93 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Fill-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Fill-Outline.shader @@ -14,6 +14,7 @@ Shader "Spine/Outline/Skeleton Fill" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-Outline.shader index 358b6b79a..ccdc0a8be 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-Outline.shader @@ -13,6 +13,7 @@ Shader "Spine/Outline/Skeleton Lit" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-ZWrite-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-ZWrite-Outline.shader index 055c6fa71..195fe8c75 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-ZWrite-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Lit-ZWrite-Outline.shader @@ -14,6 +14,7 @@ Shader "Spine/Outline/Skeleton Lit ZWrite" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Outline.shader index ab5e01914..4e6aed0b8 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Outline.shader @@ -12,6 +12,7 @@ Shader "Spine/Outline/Skeleton" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 @@ -42,6 +43,7 @@ Shader "Spine/Outline/Skeleton" { #pragma fragment fragOutline #pragma shader_feature _ _USE8NEIGHBOURHOOD_ON #pragma shader_feature _ _USE_SCREENSPACE_OUTLINE_WIDTH + #pragma shader_feature _ _OUTLINE_FILL_INSIDE #include "CGIncludes/Spine-Outline-Pass.cginc" ENDCG } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite.shader index 16743f185..e1f7c0390 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite.shader @@ -11,6 +11,7 @@ Shader "Spine/Outline/OutlineOnly-ZWrite" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 @@ -56,6 +57,7 @@ Shader "Spine/Outline/OutlineOnly-ZWrite" { #pragma fragment fragOutline #pragma shader_feature _ _USE8NEIGHBOURHOOD_ON #pragma shader_feature _ _USE_SCREENSPACE_OUTLINE_WIDTH + #pragma shader_feature _ _OUTLINE_FILL_INSIDE #include "CGIncludes/Spine-Outline-Pass.cginc" ENDCG } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Tint-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Tint-Outline.shader index c9d179a30..c0a87690a 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Tint-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-Tint-Outline.shader @@ -14,6 +14,7 @@ Shader "Spine/Outline/Skeleton Tint" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-TintBlack-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-TintBlack-Outline.shader index 7b608ac9e..7edad607e 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-TintBlack-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Skeleton-TintBlack-Outline.shader @@ -14,6 +14,7 @@ Shader "Spine/Outline/Skeleton Tint Black" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Special-Skeleton-Grayscale-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Special-Skeleton-Grayscale-Outline.shader index eaf9ca60a..de6c1c901 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Special-Skeleton-Grayscale-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Spine-Special-Skeleton-Grayscale-Outline.shader @@ -13,6 +13,7 @@ Shader "Spine/Outline/Special/Skeleton Grayscale" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesPixelLit-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesPixelLit-Outline.shader index ce6a98166..91c172e17 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesPixelLit-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesPixelLit-Outline.shader @@ -50,6 +50,7 @@ Shader "Spine/Outline/Sprite/Pixel Lit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesUnlit-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesUnlit-Outline.shader index 64a6805cb..28a73a100 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesUnlit-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesUnlit-Outline.shader @@ -33,6 +33,7 @@ Shader "Spine/Outline/Sprite/Unlit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesVertexLit-Outline.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesVertexLit-Outline.shader index 7ca7fdf5d..2ff861430 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesVertexLit-Outline.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Outline/Sprite/SpritesVertexLit-Outline.shader @@ -51,6 +51,7 @@ Shader "Spine/Outline/Sprite/Vertex Lit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Additive.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Additive.shader index a90833f3c..6d0862f07 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Additive.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Additive.shader @@ -23,6 +23,7 @@ Shader "Spine/SkeletonGraphic Additive" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader index 53078f062..dbc3dc3a9 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader @@ -23,6 +23,7 @@ Shader "Spine/SkeletonGraphic Fill" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Grayscale.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Grayscale.shader index dc8cfe0d2..6499e4f7c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Grayscale.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Grayscale.shader @@ -21,6 +21,7 @@ Shader "Spine/SkeletonGraphic Grayscale" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Multiply.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Multiply.shader index 4e6fde069..5ebecc1ee 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Multiply.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Multiply.shader @@ -23,6 +23,7 @@ Shader "Spine/SkeletonGraphic Multiply" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Screen.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Screen.shader index b25c69c8d..e7953b944 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Screen.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Screen.shader @@ -23,6 +23,7 @@ Shader "Spine/SkeletonGraphic Screen" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic.shader index 82a377d26..0932e5e34 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic.shader @@ -23,6 +23,7 @@ Shader "Spine/SkeletonGraphic" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Additive.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Additive.shader index 3bd624f81..b569b7663 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Additive.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Additive.shader @@ -24,6 +24,7 @@ Shader "Spine/SkeletonGraphic Tint Black Additive" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Multiply.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Multiply.shader index 61987b1b9..a5285776b 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Multiply.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Multiply.shader @@ -24,6 +24,7 @@ Shader "Spine/SkeletonGraphic Tint Black Multiply" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Screen.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Screen.shader index c1a4c2518..56e0ed5a0 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Screen.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack-Screen.shader @@ -24,6 +24,7 @@ Shader "Spine/SkeletonGraphic Tint Black Screen" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack.shader index 6babb5895..678ac9a38 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/TintBlack/Spine-SkeletonGraphic-TintBlack.shader @@ -24,6 +24,7 @@ Shader "Spine/SkeletonGraphic Tint Black" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Fill.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Fill.shader index a7669c8e0..af7ba9c49 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Fill.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Fill.shader @@ -16,6 +16,7 @@ Shader "Spine/Skeleton Fill" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit-ZWrite.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit-ZWrite.shader index b0c57acd0..2f33d2f2a 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit-ZWrite.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit-ZWrite.shader @@ -17,6 +17,7 @@ Shader "Spine/Skeleton Lit ZWrite" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit.shader index f3d10ee03..f01806f93 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Lit.shader @@ -16,6 +16,7 @@ Shader "Spine/Skeleton Lit" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Tint.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Tint.shader index 56feb518e..424dcf6da 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Tint.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-Tint.shader @@ -19,6 +19,7 @@ Shader "Spine/Skeleton Tint" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader index 4fbbbbba2..32883491c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader @@ -21,6 +21,7 @@ Shader "Spine/Skeleton Tint Black" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader index 304de737e..708a50a01 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader @@ -10,6 +10,7 @@ Shader "Spine/Skeleton" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Special-Skeleton-Grayscale.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Special-Skeleton-Grayscale.shader index 367808693..a2f361880 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Special-Skeleton-Grayscale.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Special-Skeleton-Grayscale.shader @@ -15,6 +15,7 @@ Shader "Spine/Special/Skeleton Grayscale" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader index 1dbe6efae..8910d40c6 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader @@ -52,6 +52,7 @@ Shader "Spine/Sprite/Pixel Lit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader index 7549dd85e..124586ea1 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader @@ -34,6 +34,7 @@ Shader "Spine/Sprite/Unlit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader index cd15a4e4e..45e8f7a81 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader @@ -53,6 +53,7 @@ Shader "Spine/Sprite/Vertex Lit" [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 diff --git a/spine-unity/Assets/Spine/package.json b/spine-unity/Assets/Spine/package.json index ac683c326..6ee911457 100644 --- a/spine-unity/Assets/Spine/package.json +++ b/spine-unity/Assets/Spine/package.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.spine-unity", "displayName": "spine-unity Runtime", "description": "This plugin provides the spine-unity runtime core.", - "version": "4.2.98", + "version": "4.2.99", "unity": "2018.3", "author": { "name": "Esoteric Software", diff --git a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-URP.shader b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-URP.shader index 482cb890f..b3cf2acbe 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-URP.shader +++ b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-URP.shader @@ -8,6 +8,7 @@ Shader "Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 @@ -46,6 +47,7 @@ Shader "Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly" { #pragma fragment fragOutline #pragma shader_feature _ _USE8NEIGHBOURHOOD_ON #pragma shader_feature _ _USE_SCREENSPACE_OUTLINE_WIDTH + #pragma shader_feature _ _OUTLINE_FILL_INSIDE #define USE_URP #define fixed4 half4 diff --git a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite-URP.shader b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite-URP.shader index 7c1c03b6b..55375ff65 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite-URP.shader +++ b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Outline/Spine-Skeleton-OutlineOnly-ZWrite-URP.shader @@ -9,6 +9,7 @@ Shader "Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly ZWrite" { [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 [HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0 [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0 [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024 [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25 [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0 @@ -50,6 +51,7 @@ Shader "Universal Render Pipeline/Spine/Outline/Skeleton-OutlineOnly ZWrite" { #pragma fragment fragOutline #pragma shader_feature _ _USE8NEIGHBOURHOOD_ON #pragma shader_feature _ _USE_SCREENSPACE_OUTLINE_WIDTH + #pragma shader_feature _ _OUTLINE_FILL_INSIDE #define USE_URP #define fixed4 half4 diff --git a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json index e11e59022..4724b1a95 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json +++ b/spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.urp-shaders", "displayName": "Spine Universal RP Shaders", "description": "This plugin provides universal render pipeline (URP) shaders for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.2.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", - "version": "4.2.41", + "version": "4.2.42", "unity": "2019.3", "author": { "name": "Esoteric Software", From 7f2e4c1df7458345bc5aebbb098105c0687773f8 Mon Sep 17 00:00:00 2001 From: Davide <7047501+davidetan@users.noreply.github.com> Date: Mon, 24 Feb 2025 10:44:05 +0100 Subject: [PATCH 07/24] [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. --- spine-haxe/README.md | 8 +- spine-haxe/example/src/Main.hx | 137 ++++++- spine-haxe/example/src/MainFlixel.hx | 45 +++ spine-haxe/example/src/MainStarling.hx | 57 +++ .../flixelExamples/AnimationBoundExample.hx | 77 ++++ .../src/flixelExamples/BasicExample.hx | 87 ++++ .../flixelExamples/CelestialCircusExample.hx | 75 ++++ .../src/flixelExamples/CloudPotExample.hx | 37 ++ .../src/flixelExamples/ControlBonesExample.hx | 108 +++++ .../src/flixelExamples/EventsExample.hx | 77 ++++ .../example/src/flixelExamples/FlixelState.hx | 195 +++++++++ .../src/flixelExamples/MixAndMatchExample.hx | 55 +++ .../example/src/flixelExamples/SackExample.hx | 38 ++ .../src/flixelExamples/SequenceExample.hx | 39 ++ .../src/flixelExamples/SnowglobeExample.hx | 37 ++ .../example/src/flixelExamples/TankExample.hx | 38 ++ .../example/src/flixelExamples/VineExample.hx | 38 ++ .../AnimationBoundExample.hx | 12 +- .../{ => starlingExamples}/BasicExample.hx | 4 +- .../CelestialCircusExample.hx | 4 +- .../{ => starlingExamples}/CloudPotExample.hx | 8 +- .../ControlBonesExample.hx | 8 +- .../{ => starlingExamples}/EventsExample.hx | 4 +- .../MixAndMatchExample.hx | 4 +- .../src/{ => starlingExamples}/SackExample.hx | 8 +- .../src/{ => starlingExamples}/Scene.hx | 2 + .../{ => starlingExamples}/SequenceExample.hx | 4 +- .../SnowglobeExample.hx | 8 +- .../src/{ => starlingExamples}/TankExample.hx | 4 +- .../src/{ => starlingExamples}/Test.hx | 4 +- .../src/{ => starlingExamples}/VineExample.hx | 4 +- spine-haxe/project.xml | 3 + .../spine/flixel/FlixelTextureLoader.hx | 72 ++++ .../spine-haxe/spine/flixel/SkeletonMesh.hx | 40 ++ .../spine-haxe/spine/flixel/SkeletonSprite.hx | 382 ++++++++++++++++++ .../spine-haxe/spine/flixel/SpineTexture.hx | 30 ++ 36 files changed, 1719 insertions(+), 34 deletions(-) create mode 100644 spine-haxe/example/src/MainFlixel.hx create mode 100644 spine-haxe/example/src/MainStarling.hx create mode 100644 spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/BasicExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/CloudPotExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/ControlBonesExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/EventsExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/FlixelState.hx create mode 100644 spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/SackExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/SequenceExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/SnowglobeExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/TankExample.hx create mode 100644 spine-haxe/example/src/flixelExamples/VineExample.hx rename spine-haxe/example/src/{ => starlingExamples}/AnimationBoundExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/BasicExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/CelestialCircusExample.hx (98%) rename spine-haxe/example/src/{ => starlingExamples}/CloudPotExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/ControlBonesExample.hx (98%) rename spine-haxe/example/src/{ => starlingExamples}/EventsExample.hx (98%) rename spine-haxe/example/src/{ => starlingExamples}/MixAndMatchExample.hx (98%) rename spine-haxe/example/src/{ => starlingExamples}/SackExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/Scene.hx (99%) rename spine-haxe/example/src/{ => starlingExamples}/SequenceExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/SnowglobeExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/TankExample.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/Test.hx (97%) rename spine-haxe/example/src/{ => starlingExamples}/VineExample.hx (97%) create mode 100644 spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx create mode 100644 spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx create mode 100644 spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx create mode 100644 spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx diff --git a/spine-haxe/README.md b/spine-haxe/README.md index 5050b84dc..d63875ff6 100644 --- a/spine-haxe/README.md +++ b/spine-haxe/README.md @@ -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: ``` diff --git a/spine-haxe/example/src/Main.hx b/spine-haxe/example/src/Main.hx index 63712f6ab..72fa2cc40 100644 --- a/spine-haxe/example/src/Main.hx +++ b/spine-haxe/example/src/Main.hx @@ -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; diff --git a/spine-haxe/example/src/MainFlixel.hx b/spine-haxe/example/src/MainFlixel.hx new file mode 100644 index 000000000..4c7334041 --- /dev/null +++ b/spine-haxe/example/src/MainFlixel.hx @@ -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; + } +} diff --git a/spine-haxe/example/src/MainStarling.hx b/spine-haxe/example/src/MainStarling.hx new file mode 100644 index 000000000..f5dfb3636 --- /dev/null +++ b/spine-haxe/example/src/MainStarling.hx @@ -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()); + } +} diff --git a/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx b/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx new file mode 100644 index 000000000..fd15d54ad --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/AnimationBoundExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/flixelExamples/BasicExample.hx b/spine-haxe/example/src/flixelExamples/BasicExample.hx new file mode 100644 index 000000000..86b53b9f9 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/BasicExample.hx @@ -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); + } + +} diff --git a/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx new file mode 100644 index 000000000..5896ec541 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/CelestialCircusExample.hx @@ -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; + } + + } +} diff --git a/spine-haxe/example/src/flixelExamples/CloudPotExample.hx b/spine-haxe/example/src/flixelExamples/CloudPotExample.hx new file mode 100644 index 000000000..7a701cd84 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/CloudPotExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx b/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx new file mode 100644 index 000000000..75b4cadf2 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/ControlBonesExample.hx @@ -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 = []; + 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; + } + } +} diff --git a/spine-haxe/example/src/flixelExamples/EventsExample.hx b/spine-haxe/example/src/flixelExamples/EventsExample.hx new file mode 100644 index 000000000..505902e26 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/EventsExample.hx @@ -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(); + private var logsNumber = 0; + private var yOffset = 12; + private function log(text:String) { + var length = logs.length; + var newLog = new FlxText(250, 30, text); + newLog.x = 50; + newLog.y = 20 + yOffset * logsNumber++; + newLog.color = 0xffffffff; + textContainer.add(newLog); + if (logs.length < 35) { + logs.push(newLog); + } else { + logs.shift().destroy(); + logs.push(newLog); + textContainer.y -= yOffset; + } + } +} diff --git a/spine-haxe/example/src/flixelExamples/FlixelState.hx b/spine-haxe/example/src/flixelExamples/FlixelState.hx new file mode 100644 index 000000000..110f9b713 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/FlixelState.hx @@ -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); + } +} \ No newline at end of file diff --git a/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx b/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx new file mode 100644 index 000000000..f179f137a --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/MixAndMatchExample.hx @@ -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(); + } + +} diff --git a/spine-haxe/example/src/flixelExamples/SackExample.hx b/spine-haxe/example/src/flixelExamples/SackExample.hx new file mode 100644 index 000000000..beb8a965c --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/SackExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/flixelExamples/SequenceExample.hx b/spine-haxe/example/src/flixelExamples/SequenceExample.hx new file mode 100644 index 000000000..219a82086 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/SequenceExample.hx @@ -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(); + } + +} diff --git a/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx b/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx new file mode 100644 index 000000000..40b7343e0 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/SnowglobeExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/flixelExamples/TankExample.hx b/spine-haxe/example/src/flixelExamples/TankExample.hx new file mode 100644 index 000000000..42a7563b2 --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/TankExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/flixelExamples/VineExample.hx b/spine-haxe/example/src/flixelExamples/VineExample.hx new file mode 100644 index 000000000..97d60bbfb --- /dev/null +++ b/spine-haxe/example/src/flixelExamples/VineExample.hx @@ -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(); + } +} diff --git a/spine-haxe/example/src/AnimationBoundExample.hx b/spine-haxe/example/src/starlingExamples/AnimationBoundExample.hx similarity index 97% rename from spine-haxe/example/src/AnimationBoundExample.hx rename to spine-haxe/example/src/starlingExamples/AnimationBoundExample.hx index 3a32c3975..3ef52b735 100644 --- a/spine-haxe/example/src/AnimationBoundExample.hx +++ b/spine-haxe/example/src/starlingExamples/AnimationBoundExample.hx @@ -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); diff --git a/spine-haxe/example/src/BasicExample.hx b/spine-haxe/example/src/starlingExamples/BasicExample.hx similarity index 97% rename from spine-haxe/example/src/BasicExample.hx rename to spine-haxe/example/src/starlingExamples/BasicExample.hx index 67f53856e..4fbc298d7 100644 --- a/spine-haxe/example/src/BasicExample.hx +++ b/spine-haxe/example/src/starlingExamples/BasicExample.hx @@ -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; diff --git a/spine-haxe/example/src/CelestialCircusExample.hx b/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx similarity index 98% rename from spine-haxe/example/src/CelestialCircusExample.hx rename to spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx index ece50e7fd..33a82dbbc 100644 --- a/spine-haxe/example/src/CelestialCircusExample.hx +++ b/spine-haxe/example/src/starlingExamples/CelestialCircusExample.hx @@ -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; diff --git a/spine-haxe/example/src/CloudPotExample.hx b/spine-haxe/example/src/starlingExamples/CloudPotExample.hx similarity index 97% rename from spine-haxe/example/src/CloudPotExample.hx rename to spine-haxe/example/src/starlingExamples/CloudPotExample.hx index 3aa77c7c4..6c6bc3bf4 100644 --- a/spine-haxe/example/src/CloudPotExample.hx +++ b/spine-haxe/example/src/starlingExamples/CloudPotExample.hx @@ -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); diff --git a/spine-haxe/example/src/ControlBonesExample.hx b/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx similarity index 98% rename from spine-haxe/example/src/ControlBonesExample.hx rename to spine-haxe/example/src/starlingExamples/ControlBonesExample.hx index 3ab20fca8..e171fe2ee 100644 --- a/spine-haxe/example/src/ControlBonesExample.hx +++ b/spine-haxe/example/src/starlingExamples/ControlBonesExample.hx @@ -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) { diff --git a/spine-haxe/example/src/EventsExample.hx b/spine-haxe/example/src/starlingExamples/EventsExample.hx similarity index 98% rename from spine-haxe/example/src/EventsExample.hx rename to spine-haxe/example/src/starlingExamples/EventsExample.hx index eb4e85a30..203f5cd6f 100644 --- a/spine-haxe/example/src/EventsExample.hx +++ b/spine-haxe/example/src/starlingExamples/EventsExample.hx @@ -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; diff --git a/spine-haxe/example/src/MixAndMatchExample.hx b/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx similarity index 98% rename from spine-haxe/example/src/MixAndMatchExample.hx rename to spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx index 198bead50..089ab4c09 100644 --- a/spine-haxe/example/src/MixAndMatchExample.hx +++ b/spine-haxe/example/src/starlingExamples/MixAndMatchExample.hx @@ -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; diff --git a/spine-haxe/example/src/SackExample.hx b/spine-haxe/example/src/starlingExamples/SackExample.hx similarity index 97% rename from spine-haxe/example/src/SackExample.hx rename to spine-haxe/example/src/starlingExamples/SackExample.hx index 00c4daa6b..110b9be5e 100644 --- a/spine-haxe/example/src/SackExample.hx +++ b/spine-haxe/example/src/starlingExamples/SackExample.hx @@ -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); diff --git a/spine-haxe/example/src/Scene.hx b/spine-haxe/example/src/starlingExamples/Scene.hx similarity index 99% rename from spine-haxe/example/src/Scene.hx rename to spine-haxe/example/src/starlingExamples/Scene.hx index 801f8667f..e6f356abc 100644 --- a/spine-haxe/example/src/Scene.hx +++ b/spine-haxe/example/src/starlingExamples/Scene.hx @@ -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; diff --git a/spine-haxe/example/src/SequenceExample.hx b/spine-haxe/example/src/starlingExamples/SequenceExample.hx similarity index 97% rename from spine-haxe/example/src/SequenceExample.hx rename to spine-haxe/example/src/starlingExamples/SequenceExample.hx index 3eb20360b..f37c134fe 100644 --- a/spine-haxe/example/src/SequenceExample.hx +++ b/spine-haxe/example/src/starlingExamples/SequenceExample.hx @@ -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; diff --git a/spine-haxe/example/src/SnowglobeExample.hx b/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx similarity index 97% rename from spine-haxe/example/src/SnowglobeExample.hx rename to spine-haxe/example/src/starlingExamples/SnowglobeExample.hx index f579c8f3f..1a7cc8369 100644 --- a/spine-haxe/example/src/SnowglobeExample.hx +++ b/spine-haxe/example/src/starlingExamples/SnowglobeExample.hx @@ -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); diff --git a/spine-haxe/example/src/TankExample.hx b/spine-haxe/example/src/starlingExamples/TankExample.hx similarity index 97% rename from spine-haxe/example/src/TankExample.hx rename to spine-haxe/example/src/starlingExamples/TankExample.hx index 52e6f39ff..aa8b35885 100644 --- a/spine-haxe/example/src/TankExample.hx +++ b/spine-haxe/example/src/starlingExamples/TankExample.hx @@ -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; diff --git a/spine-haxe/example/src/Test.hx b/spine-haxe/example/src/starlingExamples/Test.hx similarity index 97% rename from spine-haxe/example/src/Test.hx rename to spine-haxe/example/src/starlingExamples/Test.hx index 4edbc69b0..59e0eb713 100644 --- a/spine-haxe/example/src/Test.hx +++ b/spine-haxe/example/src/starlingExamples/Test.hx @@ -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; diff --git a/spine-haxe/example/src/VineExample.hx b/spine-haxe/example/src/starlingExamples/VineExample.hx similarity index 97% rename from spine-haxe/example/src/VineExample.hx rename to spine-haxe/example/src/starlingExamples/VineExample.hx index 6b174086a..5a317261c 100644 --- a/spine-haxe/example/src/VineExample.hx +++ b/spine-haxe/example/src/starlingExamples/VineExample.hx @@ -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; diff --git a/spine-haxe/project.xml b/spine-haxe/project.xml index 85f1a9d4b..6b4423862 100644 --- a/spine-haxe/project.xml +++ b/spine-haxe/project.xml @@ -3,10 +3,13 @@ + + + diff --git a/spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx b/spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx new file mode 100644 index 000000000..b672b1b14 --- /dev/null +++ b/spine-haxe/spine-haxe/spine/flixel/FlixelTextureLoader.hx @@ -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); + } +} \ No newline at end of file diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx new file mode 100644 index 000000000..92052745f --- /dev/null +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonMesh.hx @@ -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; + } +} diff --git a/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx new file mode 100644 index 000000000..be750d193 --- /dev/null +++ b/spine-haxe/spine-haxe/spine/flixel/SkeletonSprite.hx @@ -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 = new Array(); + var _quadTriangles:Array; + var _meshes(default, null):Array = new Array(); + + private var _tempMatrix = new FlxMatrix(); + private var _tempPoint = new Point(); + + private static var QUAD_INDICES:Array = [0, 1, 2, 2, 3, 0]; + public function new(skeletonData:SkeletonData, animationStateData:AnimationStateData = null) + { + 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 = skeleton.drawOrder; + var attachmentColor:spine.Color; + var mesh:SkeletonMesh = null; + var numVertices:Int; + var numFloats:Int; + var triangles:Array = null; + var uvs:Array; + var twoColorTint:Bool = false; + var vertexSize:Int = twoColorTint ? 12 : 8; + _tempMatrix = getTransformMatrix(); + for (slot in drawOrder) { + var clippedVertexSize:Int = clipper.isClipping() ? 2 : vertexSize; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + + var worldVertices:Array = _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):Void { + var transform = getTransformMatrix(); + var a = transform.a, + b = transform.b, + c = transform.c, + d = transform.d, + tx = transform.tx, + ty = transform.ty; + var x = point[0]; + var y = point[1]; + point[0] = x * a + y * c + tx; + point[1] = x * b + y * d + ty; + } + + public function haxeWorldCoordinatesToSkeleton(point:Array):Void { + var transform = getTransformMatrix().invert(); + var a = transform.a, + b = transform.b, + c = transform.c, + d = transform.d, + tx = transform.tx, + ty = transform.ty; + var x = point[0]; + var y = point[1]; + point[0] = x * a + y * c + tx; + point[1] = x * b + y * d + ty; + } + + public function haxeWorldCoordinatesToBone(point:Array, bone: Bone):Void { + this.haxeWorldCoordinatesToSkeleton(point); + if (bone.parent != null) { + bone.parent.worldToLocal(point); + } else { + bone.worldToLocal(point); + } + } + + private function getFlixelMeshFromRendererAttachment(region: RenderedAttachment) { + if (region.rendererObject == null) { + var skeletonMesh = new SkeletonMesh(); + 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; +} \ No newline at end of file diff --git a/spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx b/spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx new file mode 100644 index 000000000..c1d807024 --- /dev/null +++ b/spine-haxe/spine-haxe/spine/flixel/SpineTexture.hx @@ -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; + } + +} From a0721dbf4bb56e0d3de5c4201875f8efea596e7d Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 24 Feb 2025 20:22:23 +0100 Subject: [PATCH 08/24] [unity] Added `RenderExistingMeshGraphic` sample component similar to `RenderExistingMesh`. --- CHANGELOG.md | 5 + .../RenderExistingMeshGraphic.cs | 214 ++++++++++++++++++ .../RenderExistingMeshGraphic.cs.meta | 2 + .../Assets/Spine Examples/package.json | 2 +- 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs create mode 100644 spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index f57f3cbfa..40be0079d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -170,6 +170,11 @@ - `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex. - `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel. - All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour. + - Added example component `RenderExistingMeshGraphic` (similar to `RenderExistingMesh`) to render a `SkeletonGraphic` mesh again with different materials. This might be required by e.g. URP and SkeletonGraphic outline shaders skipping additional render passes. To add a second outline variant of your SkeletonGraphic: + 1. Add a GameObject at the same hierarchy level as the reference SkeletonGraphic and move it before the reference SkeletonGraphic to render behind. + 2. Add a `RenderExistingMeshGraphic` component. + 3. In the `RenderExistingMeshGraphic` component Inspector at `Reference Skeleton Graphic` assign the original `SkeletonGraphic` object. + 4. At `Replacement Material` assign e.g. the included _SkeletonGraphicDefaultOutline_ material to replace all materials with this material. Alternatively, if `Multiple CanvasRenderers` is enabled at the reference SkeletonGraphic, you can add entries to the `Replacement Materials` list and at each entry assign the original SkeletonGraphic material (e.g. _SkeletonGraphicDefault_) to be replaced and the respective `Replacement Material` (e.g. _SkeletonGraphicDefaultOutline_). - **Breaking changes** diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs new file mode 100644 index 000000000..eace21c00 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs @@ -0,0 +1,214 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "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. + *****************************************************************************/ + +#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER +#define NEW_PREFAB_SYSTEM +#endif + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace Spine.Unity.Examples { + using MaterialReplacement = RenderExistingMesh.MaterialReplacement; + +#if NEW_PREFAB_SYSTEM + [ExecuteAlways] +#else + [ExecuteInEditMode] +#endif + public class RenderExistingMeshGraphic : MonoBehaviour { + public SkeletonGraphic referenceSkeletonGraphic; + public Material replacementMaterial; + + public MaterialReplacement[] replacementMaterials = new MaterialReplacement[0]; + + SkeletonSubmeshGraphic ownGraphic; + public List ownSubmeshGraphics; + +#if UNITY_EDITOR + private void Reset () { + Awake(); + LateUpdate(); + } +#endif + + void Awake () { + // subscribe to OnMeshAndMaterialsUpdated + if (referenceSkeletonGraphic) { + referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback; + referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback; + } + + ownGraphic = this.GetComponent(); + if (referenceSkeletonGraphic) { + if (referenceSkeletonGraphic.allowMultipleCanvasRenderers) + EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count); + else + SetupSubmeshGraphic(); + } + } + + protected void OnDisable () { + if (referenceSkeletonGraphic) { + referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback; + } + } + + protected void OnEnable () { +#if UNITY_EDITOR + // handle disabled scene reload + if (Application.isPlaying) { + Awake(); + return; + } +#endif + if (referenceSkeletonGraphic) { + referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback; + referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback; + } + } + + void SetupSubmeshGraphic () { + if (ownGraphic == null) + ownGraphic = this.gameObject.AddComponent(); + + ownGraphic.maskable = referenceSkeletonGraphic.maskable; + ownGraphic.canvasRenderer.cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh; + ownGraphic.canvasRenderer.SetMaterial(replacementMaterial, referenceSkeletonGraphic.mainTexture); + } + + protected void EnsureCanvasRendererCount (int targetCount) { + if (ownSubmeshGraphics == null) + ownSubmeshGraphics = new List(); + + bool cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh; + Vector2 pivot = referenceSkeletonGraphic.rectTransform.pivot; + + int currentCount = ownSubmeshGraphics.Count; + for (int i = currentCount; i < targetCount; ++i) { + GameObject go = new GameObject(string.Format("Renderer{0}", i), typeof(RectTransform)); + go.transform.SetParent(this.transform, false); + go.transform.localPosition = Vector3.zero; + CanvasRenderer canvasRenderer = go.AddComponent(); + canvasRenderer.cullTransparentMesh = cullTransparentMesh; + SkeletonSubmeshGraphic submeshGraphic = go.AddComponent(); + ownSubmeshGraphics.Add(submeshGraphic); + submeshGraphic.maskable = referenceSkeletonGraphic.maskable; + submeshGraphic.raycastTarget = false; + submeshGraphic.rectTransform.pivot = pivot; + submeshGraphic.rectTransform.anchorMin = Vector2.zero; + submeshGraphic.rectTransform.anchorMax = Vector2.one; + submeshGraphic.rectTransform.sizeDelta = Vector2.zero; + } + } + + protected void UpdateCanvasRenderers () { + Mesh[] referenceMeshes = referenceSkeletonGraphic.MeshesMultipleCanvasRenderers.Items; + Material[] referenceMaterials = referenceSkeletonGraphic.MaterialsMultipleCanvasRenderers.Items; + Texture[] referenceTextures = referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Items; + + int end = Math.Min(ownSubmeshGraphics.Count, referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Count); + + for (int i = 0; i < end; i++) { + SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i]; + CanvasRenderer reference = referenceSkeletonGraphic.canvasRenderers[i]; + + if (reference.gameObject.activeInHierarchy) { + Material usedMaterial = replacementMaterial != null ? + replacementMaterial : GetReplacementMaterialFor(referenceMaterials[i]); + if (usedMaterial == null) + usedMaterial = referenceMaterials[i]; + usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial); + submeshGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceTextures[i]); + submeshGraphic.canvasRenderer.SetMesh(referenceMeshes[i]); + submeshGraphic.gameObject.SetActive(true); + } else { + submeshGraphic.canvasRenderer.Clear(); + submeshGraphic.gameObject.SetActive(false); + } + } + } + + protected void DisableCanvasRenderers () { + for (int i = 0; i < ownSubmeshGraphics.Count; i++) { + SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i]; + submeshGraphic.canvasRenderer.Clear(); + submeshGraphic.gameObject.SetActive(false); + } + } + + protected Material GetReplacementMaterialFor (Material originalMaterial) { + for (int i = 0; i < replacementMaterials.Length; ++i) { + MaterialReplacement entry = replacementMaterials[i]; + if (entry.originalMaterial != null && entry.originalMaterial.shader == originalMaterial.shader) + return entry.replacementMaterial; + } + return null; + } + +#if UNITY_EDITOR + void LateUpdate () { + if (!Application.isPlaying) { + UpdateMesh(); + } + } +#endif + + void UpdateOnCallback (SkeletonGraphic g) { + UpdateMesh(); + } + + void UpdateMesh () { + if (!referenceSkeletonGraphic) return; + + if (referenceSkeletonGraphic.allowMultipleCanvasRenderers) { + EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count); + UpdateCanvasRenderers(); + if (ownGraphic) + ownGraphic.canvasRenderer.Clear(); + } else { + if (ownGraphic == null) + ownGraphic = this.gameObject.AddComponent(); + + DisableCanvasRenderers(); + + Material referenceMaterial = referenceSkeletonGraphic.materialForRendering; + Material usedMaterial = replacementMaterial != null ? replacementMaterial : GetReplacementMaterialFor(referenceMaterial); + if (usedMaterial == null) + usedMaterial = referenceMaterial; + usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial); + ownGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceSkeletonGraphic.mainTexture); + Mesh mesh = referenceSkeletonGraphic.GetLastMesh(); + ownGraphic.canvasRenderer.SetMesh(mesh); + } + } + } +} diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta new file mode 100644 index 000000000..ca0fdd068 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ff6ce4ce6b9336a479c6bf5af81fa80a \ No newline at end of file diff --git a/spine-unity/Assets/Spine Examples/package.json b/spine-unity/Assets/Spine Examples/package.json index 9f15b3a28..5c19a8500 100644 --- a/spine-unity/Assets/Spine Examples/package.json +++ b/spine-unity/Assets/Spine Examples/package.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.spine-unity-examples", "displayName": "spine-unity Runtime Examples", "description": "This plugin provides example scenes and scripts for the spine-unity runtime.", - "version": "4.2.37", + "version": "4.2.38", "unity": "2018.3", "author": { "name": "Esoteric Software", From 5ef9772e7ad4fe3bf2a4b066be317d4183470e65 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 24 Feb 2025 20:36:48 +0100 Subject: [PATCH 09/24] [unity] Fixed a compile error on old Unity versions of previous commit a0721db. --- .../Sample Components/RenderExistingMeshGraphic.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs index eace21c00..518419c03 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs @@ -31,6 +31,10 @@ #define NEW_PREFAB_SYSTEM #endif +#if UNITY_2018_2_OR_NEWER +#define HAS_CULL_TRANSPARENT_MESH +#endif + using System; using System.Collections.Generic; using UnityEngine; @@ -101,7 +105,9 @@ namespace Spine.Unity.Examples { ownGraphic = this.gameObject.AddComponent(); ownGraphic.maskable = referenceSkeletonGraphic.maskable; +#if HAS_CULL_TRANSPARENT_MESH ownGraphic.canvasRenderer.cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh; +#endif ownGraphic.canvasRenderer.SetMaterial(replacementMaterial, referenceSkeletonGraphic.mainTexture); } @@ -109,7 +115,9 @@ namespace Spine.Unity.Examples { if (ownSubmeshGraphics == null) ownSubmeshGraphics = new List(); +#if HAS_CULL_TRANSPARENT_MESH bool cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh; +#endif Vector2 pivot = referenceSkeletonGraphic.rectTransform.pivot; int currentCount = ownSubmeshGraphics.Count; @@ -118,7 +126,9 @@ namespace Spine.Unity.Examples { go.transform.SetParent(this.transform, false); go.transform.localPosition = Vector3.zero; CanvasRenderer canvasRenderer = go.AddComponent(); +#if HAS_CULL_TRANSPARENT_MESH canvasRenderer.cullTransparentMesh = cullTransparentMesh; +#endif SkeletonSubmeshGraphic submeshGraphic = go.AddComponent(); ownSubmeshGraphics.Add(submeshGraphic); submeshGraphic.maskable = referenceSkeletonGraphic.maskable; From 5d23a7df1916695dd238621b957d9f572cb5a8c1 Mon Sep 17 00:00:00 2001 From: Ferdy's Lab <31539630+ferdyferdy9@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:23:19 +0700 Subject: [PATCH 10/24] fix godot crash when Visible Collision Shapes is enabled (#2761) --- spine-godot/spine_godot/SpineSprite.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index 7427f7199..0f3688d30 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -1216,8 +1216,9 @@ void SpineSprite::draw() { } #if TOOLS_ENABLED - - float editor_scale = EditorInterface::get_singleton()->get_editor_scale(); + float editor_scale = 1.0; + if (Engine::get_singleton()->is_editor_hint()) editor_scale = EditorInterface::get_singleton()->get_editor_scale(); + float inverse_zoom = 1 / get_viewport()->get_global_canvas_transform().get_scale().x * editor_scale; Vector hover_text_lines; if (hovered_slot) { From caf7700e2cf1ec1ecf7b56ba5ae78f6d79b7a0ed Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Wed, 26 Feb 2025 17:26:10 +0900 Subject: [PATCH 11/24] [iOS] Refactor error and data access (#2733) * implement safe bounded data Access and cancellation supporting URLSession downloadTask * declare specific SpineError type declaring conformance to Error on String is discouraged, and Creating own Error type is recommended * use explicit Error initializing rather than casing syntax (apply requested change) --- spine-ios/Sources/Spine/BoundsProvider.swift | 2 +- .../SkeletonDrawableWrapper+CGImage.swift | 4 +- .../Spine/SkeletonDrawableWrapper.swift | 8 +- .../Spine/Spine.Generated+Extensions.swift | 136 +++++++++++------- 4 files changed, 95 insertions(+), 55 deletions(-) diff --git a/spine-ios/Sources/Spine/BoundsProvider.swift b/spine-ios/Sources/Spine/BoundsProvider.swift index 99130336d..e2b3ca56a 100644 --- a/spine-ios/Sources/Spine/BoundsProvider.swift +++ b/spine-ios/Sources/Spine/BoundsProvider.swift @@ -59,7 +59,7 @@ public final class SkinAndAnimationBounds: NSObject, BoundsProvider { /// the bounding box of the skeleton. If no skins are given, the default skin is used. /// The `stepTime`, given in seconds, defines at what interval the bounds should be sampled /// across the entire animation. - public init(animation: String? = nil, skins: [String]? = nil, let stepTime: TimeInterval = 0.1) { + public init(animation: String? = nil, skins: [String]? = nil, stepTime: TimeInterval = 0.1) { self.animation = animation if let skins, !skins.isEmpty { self.skins = skins diff --git a/spine-ios/Sources/Spine/Extensions/SkeletonDrawableWrapper+CGImage.swift b/spine-ios/Sources/Spine/Extensions/SkeletonDrawableWrapper+CGImage.swift index 9a48e4770..ac0e6437b 100644 --- a/spine-ios/Sources/Spine/Extensions/SkeletonDrawableWrapper+CGImage.swift +++ b/spine-ios/Sources/Spine/Extensions/SkeletonDrawableWrapper+CGImage.swift @@ -27,7 +27,7 @@ public extension SkeletonDrawableWrapper { spineView.delegate?.draw(in: spineView) guard let texture = spineView.currentDrawable?.texture else { - throw "Could not read texture." + throw SpineError("Could not read texture.") } let width = texture.width let height = texture.height @@ -47,7 +47,7 @@ public extension SkeletonDrawableWrapper { let colorSpace = CGColorSpaceCreateDeviceRGB() guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: rowBytes, space: colorSpace, bitmapInfo: bitmapInfo.rawValue), let cgImage = context.makeImage() else { - throw "Could not create image." + throw SpineError("Could not create image.") } return cgImage } diff --git a/spine-ios/Sources/Spine/SkeletonDrawableWrapper.swift b/spine-ios/Sources/Spine/SkeletonDrawableWrapper.swift index b87e5dd06..b5c28dbc2 100644 --- a/spine-ios/Sources/Spine/SkeletonDrawableWrapper.swift +++ b/spine-ios/Sources/Spine/SkeletonDrawableWrapper.swift @@ -94,22 +94,22 @@ public final class SkeletonDrawableWrapper: NSObject { self.skeletonData = skeletonData guard let nativeSkeletonDrawable = spine_skeleton_drawable_create(skeletonData.wrappee) else { - throw "Could not load native skeleton drawable" + throw SpineError("Could not load native skeleton drawable") } skeletonDrawable = SkeletonDrawable(nativeSkeletonDrawable) guard let nativeSkeleton = spine_skeleton_drawable_get_skeleton(skeletonDrawable.wrappee) else { - throw "Could not load native skeleton" + throw SpineError("Could not load native skeleton") } skeleton = Skeleton(nativeSkeleton) guard let nativeAnimationStateData = spine_skeleton_drawable_get_animation_state_data(skeletonDrawable.wrappee) else { - throw "Could not load native animation state data" + throw SpineError("Could not load native animation state data") } animationStateData = AnimationStateData(nativeAnimationStateData) guard let nativeAnimationState = spine_skeleton_drawable_get_animation_state(skeletonDrawable.wrappee) else { - throw "Could not load native animation state" + throw SpineError("Could not load native animation state") } animationState = AnimationState(nativeAnimationState) animationStateWrapper = AnimationStateWrapper( diff --git a/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift b/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift index 64b222673..5f616d2c5 100644 --- a/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift +++ b/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift @@ -57,18 +57,19 @@ public extension Atlas { } private static func fromData(data: Data, loadFile: (_ name: String) async throws -> Data) async throws -> (Atlas, [UIImage]) { - guard let atlasData = String(data: data, encoding: .utf8) as? NSString else { - throw "Couldn't read atlas bytes as utf8 string" + guard let atlasData = String(data: data, encoding: .utf8) else { + throw SpineError("Couldn't read atlas bytes as utf8 string") } - let atlasDataNative = UnsafeMutablePointer(mutating: atlasData.utf8String) - guard let atlas = spine_atlas_load(atlasDataNative) else { - throw "Couldn't load atlas data" + let atlas = try atlasData.utf8CString.withUnsafeBufferPointer { + guard let atlas = spine_atlas_load($0.baseAddress) else { + throw SpineError("Couldn't load atlas data") + } + return atlas } - if let error = spine_atlas_get_error(atlas) { let message = String(cString: error) spine_atlas_dispose(atlas) - throw "Couldn't load atlas: \(message)" + throw SpineError("Couldn't load atlas: \(message)") } var atlasPages = [UIImage]() @@ -130,26 +131,31 @@ public extension SkeletonData { /// /// Throws an `Error` in case the skeleton data could not be loaded. static func fromData(atlas: Atlas, data: Data) throws -> SkeletonData { - let binaryNative = try data.withUnsafeBytes { unsafeBytes in - guard let bytes = unsafeBytes.bindMemory(to: UInt8.self).baseAddress else { - throw "Couldn't read atlas binary" + let result = try data.withUnsafeBytes{ + try $0.withMemoryRebound(to: UInt8.self) { buffer in + guard let ptr = buffer.baseAddress else { + throw SpineError("Couldn't read atlas binary") + } + return spine_skeleton_data_load_binary( + atlas.wrappee, + ptr, + Int32(buffer.count) + ) } - return (data: bytes, length: Int32(unsafeBytes.count)) } - let result = spine_skeleton_data_load_binary( - atlas.wrappee, - binaryNative.data, - binaryNative.length - ) + guard let result else { + throw SpineError("Couldn't load skeleton data") + } + defer { + spine_skeleton_data_result_dispose(result) + } if let error = spine_skeleton_data_result_get_error(result) { let message = String(cString: error) - spine_skeleton_data_result_dispose(result) - throw "Couldn't load skeleton data: \(message)" + throw SpineError("Couldn't load skeleton data: \(message)") } guard let data = spine_skeleton_data_result_get_data(result) else { - throw "Couldn't load skeleton data from result" + throw SpineError("Couldn't load skeleton data from result") } - spine_skeleton_data_result_dispose(result) return SkeletonData(data) } @@ -158,26 +164,31 @@ public extension SkeletonData { /// /// Throws an `Error` in case the atlas could not be loaded. static func fromJson(atlas: Atlas, json: String) throws -> SkeletonData { - let jsonNative = UnsafeMutablePointer(mutating: (json as NSString).utf8String) - guard let result = spine_skeleton_data_load_json(atlas.wrappee, jsonNative) else { - throw "Couldn't load skeleton data json" + let result = try json.utf8CString.withUnsafeBufferPointer { buffer in + guard + let basePtr = buffer.baseAddress, + let result = spine_skeleton_data_load_json(atlas.wrappee, basePtr) else { + throw SpineError("Couldn't load skeleton data json") + } + return result + } + defer { + spine_skeleton_data_result_dispose(result) } if let error = spine_skeleton_data_result_get_error(result) { let message = String(cString: error) - spine_skeleton_data_result_dispose(result) - throw "Couldn't load skeleton data: \(message)" + throw SpineError("Couldn't load skeleton data: \(message)") } guard let data = spine_skeleton_data_result_get_data(result) else { - throw "Couldn't load skeleton data from result" + throw SpineError("Couldn't load skeleton data from result") } - spine_skeleton_data_result_dispose(result) return SkeletonData(data) } private static func fromData(atlas: Atlas, data: Data, isJson: Bool) throws -> SkeletonData { if isJson { guard let json = String(data: data, encoding: .utf8) else { - throw "Couldn't read skeleton data json string" + throw SpineError("Couldn't read skeleton data json string") } return try fromJson(atlas: atlas, json: json) } else { @@ -271,12 +282,12 @@ internal enum FileSource { case .bundle(let fileName, let bundle): let components = fileName.split(separator: ".") guard components.count > 1, let ext = components.last else { - throw "Provide both file name and file extension" + throw SpineError("Provide both file name and file extension") } let name = components.dropLast(1).joined(separator: ".") guard let fileUrl = bundle.url(forResource: name, withExtension: String(ext)) else { - throw "Could not load file with name \(name) from bundle" + throw SpineError("Could not load file with name \(name) from bundle") } return try Data(contentsOf: fileUrl, options: []) case .file(let fileUrl): @@ -289,34 +300,63 @@ internal enum FileSource { } return try Data(contentsOf: temp, options: []) } else { - return try await withCheckedThrowingContinuation { continuation in - let task = URLSession.shared.downloadTask(with: url) { temp, response, error in - if let error { - continuation.resume(throwing: error) - } else { - guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { - continuation.resume(throwing: URLError(.badServerResponse)) - return - } - guard let temp else { - continuation.resume(throwing: "Could not download file.") - return - } - do { - continuation.resume(returning: try Data(contentsOf: temp, options: [])) - } catch { + let lock = NSRecursiveLock() + nonisolated(unsafe) + var isCancelled = false + nonisolated(unsafe) + var taskHolder:URLSessionDownloadTask? = nil + return try await withTaskCancellationHandler { + try await withCheckedThrowingContinuation { continuation in + let task = URLSession.shared.downloadTask(with: url) { temp, response, error in + if let error { continuation.resume(throwing: error) + } else { + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + continuation.resume(throwing: URLError(.badServerResponse)) + return + } + guard let temp else { + continuation.resume(throwing: SpineError("Could not download file.")) + return + } + do { + continuation.resume(returning: try Data(contentsOf: temp, options: [])) + } catch { + continuation.resume(throwing: error) + } } } + task.resume() + let shouldCancel = lock.withLock { + if !isCancelled { + taskHolder = task + } + return isCancelled + } + if shouldCancel { + task.cancel() + } } - task.resume() + } onCancel: { + lock.withLock { + isCancelled = true + let value = taskHolder + taskHolder = nil + return value + }?.cancel() } } } } } -extension String: Error { +public struct SpineError: Error, CustomStringConvertible { + + public let description: String + + internal init(_ description: String) { + self.description = description + } } From c879d7a01c496f69d3331e5bf36106b6671637d7 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 25 Feb 2025 10:25:54 +0100 Subject: [PATCH 12/24] [c] Closes #2765, dispose skeleton data after debug output. --- spine-c/spine-c/src/spine/SkeletonBinary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index 28a4b9fd3..a151c48eb 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -1341,9 +1341,9 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const } else { if (!string_starts_with(skeletonData->version, SPINE_VERSION_STRING)) { FREE(input); - spSkeletonData_dispose(skeletonData); char errorMsg[255]; snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->version, SPINE_VERSION_STRING); + spSkeletonData_dispose(skeletonData); _spSkeletonBinary_setError(self, errorMsg, NULL); return NULL; } From 15cac5f9fcd8558c1e53139d461e3d31b2130ad2 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 26 Feb 2025 13:36:10 +0100 Subject: [PATCH 13/24] [godot] Closes #2747, rewrote the way we sync on-disk asset changes --- .../spine_godot/SpineAtlasResource.cpp | 2 - .../spine_godot/SpineSkeletonDataResource.cpp | 149 ++++++++++++++---- .../spine_godot/SpineSkeletonDataResource.h | 8 + .../spine_godot/SpineSkeletonFileResource.cpp | 1 - .../spine_godot_extension.dev.gdextension | 18 --- 5 files changed, 124 insertions(+), 54 deletions(-) delete mode 100644 spine-godot/spine_godot_extension.dev.gdextension diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp index 0e59817ae..9ae73db0b 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.cpp +++ b/spine-godot/spine_godot/SpineAtlasResource.cpp @@ -217,8 +217,6 @@ void SpineAtlasResource::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_maps"), "", "get_normal_maps"); - - ADD_SIGNAL(MethodInfo("skeleton_atlas_changed")); } SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), texture_loader(nullptr), normal_map_prefix("n") { diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index 73e594db3..7637e41c0 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -32,10 +32,26 @@ #ifdef SPINE_GODOT_EXTENSION #include +#include +#include #else +#if VERSION_MAJOR > 3 +#include "core/config/engine.h" +#include "editor/editor_interface.h" +#else +#include "core/engine.h" +#endif #include #endif +#ifdef TOOLS_ENABLED +#ifdef SPINE_GODOT_EXTENSION +#include +#else +#include "editor/editor_file_system.h" +#endif +#endif + void SpineAnimationMix::_bind_methods() { ClassDB::bind_method(D_METHOD("set_from", "from"), &SpineAnimationMix::set_from); @@ -175,16 +191,115 @@ void SpineSkeletonDataResource::_bind_methods() { #endif ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animation_mixes"), "set_animation_mixes", "get_animation_mixes"); + +#ifdef TOOLS_ENABLED +#if VERSION_MAJOR > 3 + ClassDB::bind_method(D_METHOD("_on_resources_reimported", "resources"), + &SpineSkeletonDataResource::_on_resources_reimported); +#else + ClassDB::bind_method(D_METHOD("_on_resources_reimported", "resources"), + &SpineSkeletonDataResource::_on_resources_reimported); +#endif +#endif +} + +EditorFileSystem *get_editor_file_system() { +#ifdef SPINE_GODOT_EXTENSION + EditorInterface *editor_interface = EditorInterface::get_singleton(); + if (editor_interface) { + return editor_interface->get_resource_filesystem(); + } + return nullptr; +#else + return EditorFileSystem::get_singleton(); +#endif } SpineSkeletonDataResource::SpineSkeletonDataResource() - : default_mix(0), skeleton_data(nullptr), animation_state_data(nullptr) {} + : default_mix(0), skeleton_data(nullptr), animation_state_data(nullptr) { + +#ifdef TOOLS_ENABLED +#if VERSION_MAJOR > 3 + if (Engine::get_singleton()->is_editor_hint()) { + EditorFileSystem *efs = get_editor_file_system(); + if (efs) { + efs->connect("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported)); + } + } +#else + if (Engine::get_singleton()->is_editor_hint()) { + EditorFileSystem *efs = EditorFileSystem::get_singleton(); + if (efs) { + efs->connect("resources_reimported", this, "_on_resources_reimported"); + } + } +#endif +#endif +} SpineSkeletonDataResource::~SpineSkeletonDataResource() { +#ifdef TOOLS_ENABLED +#if VERSION_MAJOR > 3 + if (Engine::get_singleton()->is_editor_hint()) { + EditorFileSystem *efs = get_editor_file_system(); + if (efs && efs->is_connected("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported))) { + efs->disconnect("resources_reimported", callable_mp(this, &SpineSkeletonDataResource::_on_resources_reimported)); + } + } +#else + if (Engine::get_singleton()->is_editor_hint()) { + EditorFileSystem *efs = EditorFileSystem::get_singleton(); + if (efs && efs->is_connected("resources_reimported", this, "_on_resources_reimported")) { + efs->disconnect("resources_reimported", this, "_on_resources_reimported"); + } + } +#endif +#endif + delete skeleton_data; delete animation_state_data; } +#ifdef TOOLS_ENABLED +#if VERSION_MAJOR > 3 +void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray &resources) { + for (int i = 0; i < resources.size(); i++) { + if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) { + print_line("Atlas resource was reimported: " + resources[i]); + #ifdef SPINE_GODOT_EXTENSION + atlas_res = ResourceLoader::get_singleton()->load(resources[i], "SpineAtlasResource", ResourceLoader::CACHE_MODE_IGNORE); + #else + atlas_res = ResourceLoader::load(resources[i], "SpineAtlasResource", ResourceFormatLoader::CACHE_MODE_IGNORE); + #endif + update_skeleton_data(); + } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) { + print_line("Skeleton file resource was reimported: " + resources[i]); + #ifdef SPINE_GODOT_EXTENSION + skeleton_file_res = ResourceLoader::get_singleton()->load(resources[i], "SpineSkeletonFileResource", ResourceLoader::CACHE_MODE_IGNORE); + #else + skeleton_file_res = ResourceLoader::load(resources[i], "SpineSkeletonFileResource", ResourceFormatLoader::CACHE_MODE_IGNORE); + #endif + update_skeleton_data(); + } + } +} +#else +void SpineSkeletonDataResource::_on_resources_reimported(const PoolStringArray &resources) { + for (int i = 0; i < resources.size(); i++) { + if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) { + print_line("Atlas resource was reimported: " + resources[i]); + atlas_res = ResourceLoader::load(resources[i]); + update_skeleton_data(); + } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) { + print_line("Skeleton file resource was reimported: " + resources[i]); + skeleton_file_res = ResourceLoader::load(resources[i]); + update_skeleton_data(); + } + } +} +#endif +#endif + void SpineSkeletonDataResource::update_skeleton_data() { if (skeleton_data) { delete skeleton_data; @@ -249,22 +364,6 @@ bool SpineSkeletonDataResource::is_skeleton_data_loaded() const { void SpineSkeletonDataResource::set_atlas_res( const Ref &atlas) { atlas_res = atlas; - if (atlas_res.is_valid()) { -#if VERSION_MAJOR > 3 - if (!atlas_res->is_connected( - SNAME("skeleton_atlas_changed"), - callable_mp(this, - &SpineSkeletonDataResource::update_skeleton_data))) - atlas_res->connect( - SNAME("skeleton_atlas_changed"), - callable_mp(this, &SpineSkeletonDataResource::update_skeleton_data)); -#else - if (!atlas_res->is_connected(SNAME("skeleton_atlas_changed"), this, - SNAME("update_skeleton_data"))) - atlas_res->connect(SNAME("skeleton_atlas_changed"), this, - SNAME("update_skeleton_data")); -#endif - } update_skeleton_data(); } @@ -275,22 +374,6 @@ Ref SpineSkeletonDataResource::get_atlas_res() { void SpineSkeletonDataResource::set_skeleton_file_res( const Ref &skeleton_file) { skeleton_file_res = skeleton_file; - if (skeleton_file_res.is_valid()) { -#if VERSION_MAJOR > 3 - if (!skeleton_file_res->is_connected( - SNAME("skeleton_file_changed"), - callable_mp(this, - &SpineSkeletonDataResource::update_skeleton_data))) - skeleton_file_res->connect( - SNAME("skeleton_file_changed"), - callable_mp(this, &SpineSkeletonDataResource::update_skeleton_data)); -#else - if (!skeleton_file_res->is_connected(SNAME("skeleton_file_changed"), this, - SNAME("update_skeleton_data"))) - skeleton_file_res->connect(SNAME("skeleton_file_changed"), this, - SNAME("update_skeleton_data")); -#endif - } update_skeleton_data(); } diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h index 28f542fd0..77838d9ca 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.h +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.h @@ -209,4 +209,12 @@ public: float get_reference_scale() const; void set_reference_scale(float reference_scale); + +#ifdef TOOLS_ENABLED +#if VERSION_MAJOR > 3 +void _on_resources_reimported(const PackedStringArray &resources); +#else +void _on_resources_reimported(const PoolStringArray &resources); +#endif +#endif }; diff --git a/spine-godot/spine_godot/SpineSkeletonFileResource.cpp b/spine-godot/spine_godot/SpineSkeletonFileResource.cpp index 93d13fba2..b5404fc59 100644 --- a/spine-godot/spine_godot/SpineSkeletonFileResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonFileResource.cpp @@ -95,7 +95,6 @@ static char *readString(BinaryInput *input) { void SpineSkeletonFileResource::_bind_methods() { ClassDB::bind_method(D_METHOD("load_from_file", "path"), &SpineSkeletonFileResource::load_from_file); - ADD_SIGNAL(MethodInfo("skeleton_file_changed")); } static bool checkVersion(const char *version) { diff --git a/spine-godot/spine_godot_extension.dev.gdextension b/spine-godot/spine_godot_extension.dev.gdextension deleted file mode 100644 index d4d2d8495..000000000 --- a/spine-godot/spine_godot_extension.dev.gdextension +++ /dev/null @@ -1,18 +0,0 @@ -[configuration] - -entry_symbol = "spine_godot_library_init" -compatibility_minimum = "4.1" - -[libraries] - -macos.editor = "res://bin/macos/macos.framework/libspine_godot.macos.dev.editor" -macos.debug = "res://bin/macos/macos.framework/libspine_godot.macos.dev.template_debug" -macos.release = "res://bin/macos/macos.framework/libspine_godot.macos.template_release" - -windows.editor.x86_64 = "res://bin/windows/libspine_godot.windows.editor.dev.x86_64.dll" -windows.debug.x86_64 = "res://bin/windows/libspine_godot.windows.template_debug.dev.x86_64.dll" -windows.release.x86_64 = "res://bin/windows/libspine_godot.windows.template_release.dev.x86_64.dll" - -linux.editor.x86_64 = "res://bin/linux/libspine_godot.linux.editor.dev.x86_64.so" -linux.debug.x86_64 = "res://bin/linux/libspine_godot.linux.template_debug.dev.x86_64.so" -linux.release.x86_64 = "res://bin/linux/libspine_godot.linux.template_release.dev.x86_64.so" \ No newline at end of file From 42fea00bb09a11053be91aa01f4b7f9cf2a0bd44 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 26 Feb 2025 13:39:58 +0100 Subject: [PATCH 14/24] Formatting --- .../spine_godot/SpineSkeletonDataResource.cpp | 12 ++++++------ spine-godot/spine_godot/SpineSkeletonDataResource.h | 4 ++-- spine-godot/spine_godot/SpineSprite.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index 7637e41c0..61fc9481b 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -266,19 +266,19 @@ void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray for (int i = 0; i < resources.size(); i++) { if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) { print_line("Atlas resource was reimported: " + resources[i]); - #ifdef SPINE_GODOT_EXTENSION +#ifdef SPINE_GODOT_EXTENSION atlas_res = ResourceLoader::get_singleton()->load(resources[i], "SpineAtlasResource", ResourceLoader::CACHE_MODE_IGNORE); - #else +#else atlas_res = ResourceLoader::load(resources[i], "SpineAtlasResource", ResourceFormatLoader::CACHE_MODE_IGNORE); - #endif +#endif update_skeleton_data(); } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) { print_line("Skeleton file resource was reimported: " + resources[i]); - #ifdef SPINE_GODOT_EXTENSION +#ifdef SPINE_GODOT_EXTENSION skeleton_file_res = ResourceLoader::get_singleton()->load(resources[i], "SpineSkeletonFileResource", ResourceLoader::CACHE_MODE_IGNORE); - #else +#else skeleton_file_res = ResourceLoader::load(resources[i], "SpineSkeletonFileResource", ResourceFormatLoader::CACHE_MODE_IGNORE); - #endif +#endif update_skeleton_data(); } } diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h index 77838d9ca..d0cbc9365 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.h +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.h @@ -212,9 +212,9 @@ public: #ifdef TOOLS_ENABLED #if VERSION_MAJOR > 3 -void _on_resources_reimported(const PackedStringArray &resources); + void _on_resources_reimported(const PackedStringArray &resources); #else -void _on_resources_reimported(const PoolStringArray &resources); + void _on_resources_reimported(const PoolStringArray &resources); #endif #endif }; diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index 0f3688d30..ecf844c9a 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -1218,7 +1218,7 @@ void SpineSprite::draw() { #if TOOLS_ENABLED float editor_scale = 1.0; if (Engine::get_singleton()->is_editor_hint()) editor_scale = EditorInterface::get_singleton()->get_editor_scale(); - + float inverse_zoom = 1 / get_viewport()->get_global_canvas_transform().get_scale().x * editor_scale; Vector hover_text_lines; if (hovered_slot) { From e0c4cfffeccca5c5a400fe2fd774fb2d8b93b4f4 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 26 Feb 2025 14:14:09 +0100 Subject: [PATCH 15/24] [godot] Disable editor FS access in template builds. --- spine-godot/spine_godot/SpineSkeletonDataResource.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index 61fc9481b..20c32d6d6 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -203,6 +203,7 @@ void SpineSkeletonDataResource::_bind_methods() { #endif } +#ifdef TOOLS_ENABLED EditorFileSystem *get_editor_file_system() { #ifdef SPINE_GODOT_EXTENSION EditorInterface *editor_interface = EditorInterface::get_singleton(); @@ -214,6 +215,7 @@ EditorFileSystem *get_editor_file_system() { return EditorFileSystem::get_singleton(); #endif } +#endif SpineSkeletonDataResource::SpineSkeletonDataResource() : default_mix(0), skeleton_data(nullptr), animation_state_data(nullptr) { From 268d0e8f61dfaf6b379c1889cec5d2d78e20f290 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 26 Feb 2025 14:15:24 +0100 Subject: [PATCH 16/24] [godot] Remove print_lines. --- spine-godot/spine_godot/SpineSkeletonDataResource.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index 20c32d6d6..d65575a4f 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -267,7 +267,6 @@ SpineSkeletonDataResource::~SpineSkeletonDataResource() { void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray &resources) { for (int i = 0; i < resources.size(); i++) { if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) { - print_line("Atlas resource was reimported: " + resources[i]); #ifdef SPINE_GODOT_EXTENSION atlas_res = ResourceLoader::get_singleton()->load(resources[i], "SpineAtlasResource", ResourceLoader::CACHE_MODE_IGNORE); #else @@ -275,7 +274,6 @@ void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray #endif update_skeleton_data(); } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) { - print_line("Skeleton file resource was reimported: " + resources[i]); #ifdef SPINE_GODOT_EXTENSION skeleton_file_res = ResourceLoader::get_singleton()->load(resources[i], "SpineSkeletonFileResource", ResourceLoader::CACHE_MODE_IGNORE); #else @@ -289,11 +287,9 @@ void SpineSkeletonDataResource::_on_resources_reimported(const PackedStringArray void SpineSkeletonDataResource::_on_resources_reimported(const PoolStringArray &resources) { for (int i = 0; i < resources.size(); i++) { if (atlas_res.is_valid() && atlas_res->get_path() == resources[i]) { - print_line("Atlas resource was reimported: " + resources[i]); atlas_res = ResourceLoader::load(resources[i]); update_skeleton_data(); } else if (skeleton_file_res.is_valid() && skeleton_file_res->get_path() == resources[i]) { - print_line("Skeleton file resource was reimported: " + resources[i]); skeleton_file_res = ResourceLoader::load(resources[i]); update_skeleton_data(); } From 0cb6f960f993e144682521f518f2226234e0835f Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Tue, 4 Mar 2025 10:10:35 +0100 Subject: [PATCH 17/24] [haxe] Release 4.2.5 --- spine-haxe/haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-haxe/haxelib.json b/spine-haxe/haxelib.json index b875c3f85..7f698369e 100644 --- a/spine-haxe/haxelib.json +++ b/spine-haxe/haxelib.json @@ -17,8 +17,8 @@ "cpp" ], "description": "The official Spine Runtime for Haxe", - "version": "4.2.4", - "releasenote": "Update to 4.2.4", + "version": "4.2.5", + "releasenote": "Update to 4.2.5", "contributors": [ "esotericsoftware" ], From b4a563b7ce70c024b949f96d89a714c95dba88cf Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Tue, 4 Mar 2025 12:50:37 -0400 Subject: [PATCH 18/24] Typo in error message. --- spine-ts/spine-player/src/Player.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-ts/spine-player/src/Player.ts b/spine-ts/spine-player/src/Player.ts index 2ae8273ea..3fcc764b1 100644 --- a/spine-ts/spine-player/src/Player.ts +++ b/spine-ts/spine-player/src/Player.ts @@ -347,7 +347,7 @@ export class SpinePlayer implements Disposable { this.sceneRenderer = new SceneRenderer(this.canvas, this.context, true); if (config.showLoading) this.loadingScreen = new LoadingScreen(this.sceneRenderer); } catch (e) { - this.showError("Sorry, your browser does not support WebG, or you have disabled WebGL in your browser settings.\nPlease use the latest version of Firefox, Chrome, Edge, or Safari.", e as any); + this.showError("Sorry, your browser does not support WebGL, or you have disabled WebGL in your browser settings.\nPlease use the latest version of Firefox, Chrome, Edge, or Safari.", e as any); return null; } From 0f8a707b48068892e16703e100e0ddeb9cc2917c Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 5 Mar 2025 12:31:10 +0100 Subject: [PATCH 19/24] [ts][phaser] Fix add/make not clearing and rebinding the WebGL pipeline. --- spine-ts/spine-phaser/src/SpinePlugin.ts | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/spine-ts/spine-phaser/src/SpinePlugin.ts b/spine-ts/spine-phaser/src/SpinePlugin.ts index ba8b91419..8c3b4fe4b 100644 --- a/spine-ts/spine-phaser/src/SpinePlugin.ts +++ b/spine-ts/spine-phaser/src/SpinePlugin.ts @@ -122,22 +122,42 @@ export class SpinePlugin extends Phaser.Plugins.ScenePlugin { }; pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene); - let self = this; let addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider) { - let gameObject = new SpineGameObject(this.scene, self, x, y, dataKey, atlasKey, boundsProvider); + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + + const spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider); this.displayList.add(gameObject); this.updateList.add(gameObject); + + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return gameObject; }; let makeSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, config: SpineGameObjectConfig, addToScene: boolean = false) { + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + let x = config.x ? config.x : 0; let y = config.y ? config.y : 0; let boundsProvider = config.boundsProvider ? config.boundsProvider : undefined; - let gameObject = new SpineGameObject(this.scene, self, x, y, config.dataKey, config.atlasKey, boundsProvider); + + const spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider); if (addToScene !== undefined) { config.add = addToScene; } + + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config); } pluginManager.registerGameObject((window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject); From 9ecbee794b01838afcb3942f106e417320f25392 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 5 Mar 2025 12:37:46 +0100 Subject: [PATCH 20/24] [ts] Release 4.2.75 --- spine-ts/package-lock.json | 42 +++++++++++++-------------- spine-ts/package.json | 2 +- spine-ts/spine-canvas/package.json | 4 +-- spine-ts/spine-canvaskit/package.json | 4 +-- spine-ts/spine-core/package.json | 2 +- spine-ts/spine-phaser/package.json | 8 ++--- spine-ts/spine-pixi-v7/package.json | 4 +-- spine-ts/spine-pixi-v8/package.json | 4 +-- spine-ts/spine-player/package.json | 4 +-- spine-ts/spine-threejs/package.json | 4 +-- spine-ts/spine-webgl/package.json | 4 +-- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/spine-ts/package-lock.json b/spine-ts/package-lock.json index 872d9f76d..386244691 100644 --- a/spine-ts/package-lock.json +++ b/spine-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.74", + "version": "4.2.75", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@esotericsoftware/spine-ts", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "workspaces": [ "spine-core", @@ -3142,18 +3142,18 @@ }, "spine-canvas": { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" } }, "spine-canvaskit": { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74", + "@esotericsoftware/spine-core": "4.2.75", "canvaskit-wasm": "0.39.1" }, "devDependencies": { @@ -3163,17 +3163,17 @@ }, "spine-core": { "name": "@esotericsoftware/spine-core", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE" }, "spine-phaser": { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-canvas": "4.2.74", - "@esotericsoftware/spine-core": "4.2.74", - "@esotericsoftware/spine-webgl": "4.2.74" + "@esotericsoftware/spine-canvas": "4.2.75", + "@esotericsoftware/spine-core": "4.2.75", + "@esotericsoftware/spine-webgl": "4.2.75" }, "peerDependencies": { "phaser": "^3.60.0" @@ -3181,10 +3181,10 @@ }, "spine-pixi-v7": { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "peerDependencies": { "@pixi/assets": "^7.2.4", @@ -3198,10 +3198,10 @@ }, "spine-pixi-v8": { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "peerDependencies": { "pixi.js": "^8.4.0" @@ -3209,18 +3209,18 @@ }, "spine-player": { "name": "@esotericsoftware/spine-player", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.74" + "@esotericsoftware/spine-webgl": "4.2.75" } }, "spine-threejs": { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "devDependencies": { "@types/three": "0.162.0" @@ -3231,10 +3231,10 @@ }, "spine-webgl": { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.74", + "version": "4.2.75", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" } } } diff --git a/spine-ts/package.json b/spine-ts/package.json index 5ff4ca358..39683c3f8 100644 --- a/spine-ts/package.json +++ b/spine-ts/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "type": "module", "files": [ diff --git a/spine-ts/spine-canvas/package.json b/spine-ts/spine-canvas/package.json index e33be56df..dfbe82e5e 100644 --- a/spine-ts/spine-canvas/package.json +++ b/spine-ts/spine-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" } } \ No newline at end of file diff --git a/spine-ts/spine-canvaskit/package.json b/spine-ts/spine-canvaskit/package.json index 41a7989c9..88c71b4e2 100644 --- a/spine-ts/spine-canvaskit/package.json +++ b/spine-ts/spine-canvaskit/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for CanvasKit for NodeJS", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74", + "@esotericsoftware/spine-core": "4.2.75", "canvaskit-wasm": "0.39.1" }, "devDependencies": { diff --git a/spine-ts/spine-core/package.json b/spine-ts/spine-core/package.json index e5cb93613..2b335e7ef 100644 --- a/spine-ts/spine-core/package.json +++ b/spine-ts/spine-core/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-core", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/spine-ts/spine-phaser/package.json b/spine-ts/spine-phaser/package.json index d2ac4b355..a897e85c6 100644 --- a/spine-ts/spine-phaser/package.json +++ b/spine-ts/spine-phaser/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the Phaser.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,9 +31,9 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74", - "@esotericsoftware/spine-webgl": "4.2.74", - "@esotericsoftware/spine-canvas": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75", + "@esotericsoftware/spine-webgl": "4.2.75", + "@esotericsoftware/spine-canvas": "4.2.75" }, "peerDependencies": { "phaser": "^3.60.0" diff --git a/spine-ts/spine-pixi-v7/package.json b/spine-ts/spine-pixi-v7/package.json index 44aa2e8c2..3fb4b74d1 100644 --- a/spine-ts/spine-pixi-v7/package.json +++ b/spine-ts/spine-pixi-v7/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web PixiJS v7.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "peerDependencies": { "@pixi/core": "^7.2.4", diff --git a/spine-ts/spine-pixi-v8/package.json b/spine-ts/spine-pixi-v8/package.json index cc9e4ff76..adbd73ac1 100644 --- a/spine-ts/spine-pixi-v8/package.json +++ b/spine-ts/spine-pixi-v8/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for PixiJS v8.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "peerDependencies": { "pixi.js": "^8.4.0" diff --git a/spine-ts/spine-player/package.json b/spine-ts/spine-player/package.json index 7b9424d5c..92df1e98a 100644 --- a/spine-ts/spine-player/package.json +++ b/spine-ts/spine-player/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-player", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.74" + "@esotericsoftware/spine-webgl": "4.2.75" } } \ No newline at end of file diff --git a/spine-ts/spine-threejs/package.json b/spine-ts/spine-threejs/package.json index 0a8759e3c..c0a9f93bb 100644 --- a/spine-ts/spine-threejs/package.json +++ b/spine-ts/spine-threejs/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" }, "devDependencies": { "@types/three": "0.162.0" diff --git a/spine-ts/spine-webgl/package.json b/spine-ts/spine-webgl/package.json index 5b916a8a4..4c54f5779 100644 --- a/spine-ts/spine-webgl/package.json +++ b/spine-ts/spine-webgl/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.74", + "version": "4.2.75", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.74" + "@esotericsoftware/spine-core": "4.2.75" } } \ No newline at end of file From 56823c5ca57446143c233207dcfbf0b544f0c992 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sat, 8 Mar 2025 11:39:19 -0400 Subject: [PATCH 21/24] Use timekeeper delta. --- spine-ts/spine-webgl/tests/test-binary.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-ts/spine-webgl/tests/test-binary.html b/spine-ts/spine-webgl/tests/test-binary.html index 3c9088004..a4b721611 100644 --- a/spine-ts/spine-webgl/tests/test-binary.html +++ b/spine-ts/spine-webgl/tests/test-binary.html @@ -98,7 +98,7 @@ function render() { var start = Date.now() timeKeeper.update(); - var delta = 0.016; // timeKeeper.delta; + var delta = timeKeeper.delta; for (var i = 0; i < skeletons.length; i++) { var state = skeletons[i].state; From 67488d7c9586fd9518a6f60e09f08e84698fb500 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 12 Mar 2025 10:36:48 +0100 Subject: [PATCH 22/24] [ts][phaser] Fix wrong type definition. --- spine-ts/spine-phaser/src/mixins.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-ts/spine-phaser/src/mixins.ts b/spine-ts/spine-phaser/src/mixins.ts index 83c2dc0d1..7f12789b0 100644 --- a/spine-ts/spine-phaser/src/mixins.ts +++ b/spine-ts/spine-phaser/src/mixins.ts @@ -59,7 +59,7 @@ export function createMixin< }; } -type ComputedSizeMixin = Mixin; +type ComputedSizeMixin = Mixin; export const ComputedSizeMixin: ComputedSizeMixin = createMixin(ComputedSize); type DepthMixin = Mixin; From 18d30af5a9cd2429a16e003b85dc844a8f6f2ea9 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 12 Mar 2025 10:40:45 +0100 Subject: [PATCH 23/24] [ts] Release 4.2.76 --- spine-ts/package-lock.json | 42 +++++++++++++-------------- spine-ts/package.json | 2 +- spine-ts/spine-canvas/package.json | 4 +-- spine-ts/spine-canvaskit/package.json | 4 +-- spine-ts/spine-core/package.json | 2 +- spine-ts/spine-phaser/package.json | 8 ++--- spine-ts/spine-pixi-v7/package.json | 4 +-- spine-ts/spine-pixi-v8/package.json | 4 +-- spine-ts/spine-player/package.json | 4 +-- spine-ts/spine-threejs/package.json | 4 +-- spine-ts/spine-webgl/package.json | 4 +-- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/spine-ts/package-lock.json b/spine-ts/package-lock.json index 386244691..8c5586c0f 100644 --- a/spine-ts/package-lock.json +++ b/spine-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.75", + "version": "4.2.76", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@esotericsoftware/spine-ts", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "workspaces": [ "spine-core", @@ -3142,18 +3142,18 @@ }, "spine-canvas": { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" } }, "spine-canvaskit": { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75", + "@esotericsoftware/spine-core": "4.2.76", "canvaskit-wasm": "0.39.1" }, "devDependencies": { @@ -3163,17 +3163,17 @@ }, "spine-core": { "name": "@esotericsoftware/spine-core", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE" }, "spine-phaser": { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-canvas": "4.2.75", - "@esotericsoftware/spine-core": "4.2.75", - "@esotericsoftware/spine-webgl": "4.2.75" + "@esotericsoftware/spine-canvas": "4.2.76", + "@esotericsoftware/spine-core": "4.2.76", + "@esotericsoftware/spine-webgl": "4.2.76" }, "peerDependencies": { "phaser": "^3.60.0" @@ -3181,10 +3181,10 @@ }, "spine-pixi-v7": { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "peerDependencies": { "@pixi/assets": "^7.2.4", @@ -3198,10 +3198,10 @@ }, "spine-pixi-v8": { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "peerDependencies": { "pixi.js": "^8.4.0" @@ -3209,18 +3209,18 @@ }, "spine-player": { "name": "@esotericsoftware/spine-player", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.75" + "@esotericsoftware/spine-webgl": "4.2.76" } }, "spine-threejs": { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "devDependencies": { "@types/three": "0.162.0" @@ -3231,10 +3231,10 @@ }, "spine-webgl": { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.75", + "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" } } } diff --git a/spine-ts/package.json b/spine-ts/package.json index 39683c3f8..cb4110e51 100644 --- a/spine-ts/package.json +++ b/spine-ts/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-ts", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "type": "module", "files": [ diff --git a/spine-ts/spine-canvas/package.json b/spine-ts/spine-canvas/package.json index dfbe82e5e..3d35b5b42 100644 --- a/spine-ts/spine-canvas/package.json +++ b/spine-ts/spine-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvas", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" } } \ No newline at end of file diff --git a/spine-ts/spine-canvaskit/package.json b/spine-ts/spine-canvaskit/package.json index 88c71b4e2..4b1a0ec39 100644 --- a/spine-ts/spine-canvaskit/package.json +++ b/spine-ts/spine-canvaskit/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-canvaskit", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for CanvasKit for NodeJS", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75", + "@esotericsoftware/spine-core": "4.2.76", "canvaskit-wasm": "0.39.1" }, "devDependencies": { diff --git a/spine-ts/spine-core/package.json b/spine-ts/spine-core/package.json index 2b335e7ef..3aebf72ff 100644 --- a/spine-ts/spine-core/package.json +++ b/spine-ts/spine-core/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-core", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/spine-ts/spine-phaser/package.json b/spine-ts/spine-phaser/package.json index a897e85c6..ebf943c3d 100644 --- a/spine-ts/spine-phaser/package.json +++ b/spine-ts/spine-phaser/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-phaser", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the Phaser.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,9 +31,9 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75", - "@esotericsoftware/spine-webgl": "4.2.75", - "@esotericsoftware/spine-canvas": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76", + "@esotericsoftware/spine-webgl": "4.2.76", + "@esotericsoftware/spine-canvas": "4.2.76" }, "peerDependencies": { "phaser": "^3.60.0" diff --git a/spine-ts/spine-pixi-v7/package.json b/spine-ts/spine-pixi-v7/package.json index 3fb4b74d1..d4d207fc8 100644 --- a/spine-ts/spine-pixi-v7/package.json +++ b/spine-ts/spine-pixi-v7/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v7", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web PixiJS v7.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "peerDependencies": { "@pixi/core": "^7.2.4", diff --git a/spine-ts/spine-pixi-v8/package.json b/spine-ts/spine-pixi-v8/package.json index adbd73ac1..3741121b8 100644 --- a/spine-ts/spine-pixi-v8/package.json +++ b/spine-ts/spine-pixi-v8/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-pixi-v8", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for PixiJS v8.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "peerDependencies": { "pixi.js": "^8.4.0" diff --git a/spine-ts/spine-player/package.json b/spine-ts/spine-player/package.json index 92df1e98a..a807e042a 100644 --- a/spine-ts/spine-player/package.json +++ b/spine-ts/spine-player/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-player", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-webgl": "4.2.75" + "@esotericsoftware/spine-webgl": "4.2.76" } } \ No newline at end of file diff --git a/spine-ts/spine-threejs/package.json b/spine-ts/spine-threejs/package.json index c0a9f93bb..f471562f3 100644 --- a/spine-ts/spine-threejs/package.json +++ b/spine-ts/spine-threejs/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-threejs", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" }, "devDependencies": { "@types/three": "0.162.0" diff --git a/spine-ts/spine-webgl/package.json b/spine-ts/spine-webgl/package.json index 4c54f5779..aab54bda4 100644 --- a/spine-ts/spine-webgl/package.json +++ b/spine-ts/spine-webgl/package.json @@ -1,6 +1,6 @@ { "name": "@esotericsoftware/spine-webgl", - "version": "4.2.75", + "version": "4.2.76", "description": "The official Spine Runtimes for the web.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,6 +31,6 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { - "@esotericsoftware/spine-core": "4.2.75" + "@esotericsoftware/spine-core": "4.2.76" } } \ No newline at end of file From f1e0f0f728758a9b5b93ae99e96db8f50c18b083 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Thu, 13 Mar 2025 12:45:38 -0400 Subject: [PATCH 24/24] Fixed animation not being mixed out in some cases. Repro, with any animation playing: state.setAnimation(0, "shoot", true).setMixDuration(0.2f); state.apply(skeleton); Reverts 8d058fb4f4479a041fce1ff3379ba794856c9a3c. We can't know when it's safe to discard a queued animation. Users should avoid queuing animations they don't actually want. Prefer `to.nextTrackLast != -1` for "was applied", as `to.mixTime > 0` is user writable and not quite the same. --- .../spine/AnimationState.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index 9cf287ffb..a9290ed94 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -180,18 +180,16 @@ public class AnimationState { from.animationLast = from.nextAnimationLast; from.trackLast = from.nextTrackLast; - if (to.nextTrackLast != -1) { // The from entry was applied at least once. - boolean discard = to.mixTime == 0 && from.mixTime == 0; // Discard the from entry when neither have advanced yet. - if (to.mixTime >= to.mixDuration || discard) { - // Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded. - if (from.totalAlpha == 0 || to.mixDuration == 0 || discard) { - to.mixingFrom = from.mixingFrom; - if (from.mixingFrom != null) from.mixingFrom.mixingTo = to; - to.interruptAlpha = from.interruptAlpha; - queue.end(from); - } - return finished; + // The from entry was applied at least once and the mix is complete. + if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) { + // Mixing is complete for all entries before the from entry or the mix is instantaneous. + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + queue.end(from); } + return finished; } from.trackTime += delta * from.timeScale;