diff --git a/CHANGELOG.md b/CHANGELOG.md index b8dd85bd0..a3725b597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,9 @@ * Added Spine Preferences setting `Prefabs` - `Optimize Preview Meshes`. When enabled, Spine prefab preview meshes will be removed in a pre-build step to reduce build size. This increases build time as all prefabs in the project will be processed. Defaults to false to not slow down builds substantially every time. * Added Spine Preferences setting `Reload SkeletonData after Play`. When enabled, the shared `SkeletonData` of all skeletons in the active scene is reloaded (from the `.json` or `.skel.bytes` file) after exiting play-mode. You can disable this setting to avoid the reloading delay if you can ensure that there are no (accidental) modifications to the shared `SkeletonData` during play-mode (otherwise it would carry over its effect into subsequent plays). Defaults to `true` (the safe setting), which maintains existing behaviour. * Added `SkeletonAnimationMulti` sample component methods `SetActiveSkeleton(int index)` and getter property `SkeletonAnimations` to more easily apply changes at all SkeletonAnimation instances instead of only the active one. + * PMA textures now have `sRGB (Color Texture)` disabled by default, the preset template `PMATexturePreset.preset` has been adjusted accordingly. As PMA textures are only allowed with Gamma color space, `sRGB (Color Texture)` shall be disabled to prevent border artifacts when mipmaps are enabled. In Gamma color space having this setting disabled has no drawbacks, only benefits. + * `SkeletonRenderTexture` and `SkeletonGraphicRenderTexture` components now support automatic down-scaling when required size on screen exceeds `Max Render Texture Size`. + * Added `Spine/SkeletonGraphic Fill` shader to provide functionality of `Spine/Skeleton Fill` shader for `SkeletonGraphic`. * **Breaking changes** * Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead. diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 55dd1ddab..dfbf8de93 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/spine-c/spine-c/src/spine/Animation.c @@ -2016,7 +2016,7 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float slotAttachment = slot->attachment; if (slotAttachment != self->attachment) { - if (slotAttachment == NULL) return; + if (slotAttachment == NULL) return; switch (slotAttachment->type) { case SP_ATTACHMENT_BOUNDING_BOX: case SP_ATTACHMENT_CLIPPING: diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index c3bdec691..e931e786e 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -174,7 +174,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData); readColor(input, slotData->getColor()); - unsigned char a = readByte(input); + unsigned char a = readByte(input); unsigned char r = readByte(input); unsigned char g = readByte(input); unsigned char b = readByte(input); diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/spine_godot/SpineSkeleton.cpp index 81169289b..1e8564de1 100644 --- a/spine-godot/spine_godot/SpineSkeleton.cpp +++ b/spine-godot/spine_godot/SpineSkeleton.cpp @@ -69,10 +69,11 @@ void SpineSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y); } -SpineSkeleton::SpineSkeleton() : skeleton(nullptr), sprite(nullptr) { +SpineSkeleton::SpineSkeleton() : skeleton(nullptr), sprite(nullptr), last_skin(nullptr) { } SpineSkeleton::~SpineSkeleton() { + if (last_skin.is_valid()) last_skin.unref(); delete skeleton; } @@ -136,6 +137,8 @@ void SpineSkeleton::set_skin_by_name(const String &skin_name) { void SpineSkeleton::set_skin(Ref new_skin) { SPINE_CHECK(skeleton, ) + if (last_skin.is_valid()) last_skin.unref(); + last_skin = new_skin; skeleton->setSkin(new_skin.is_valid() && new_skin->get_spine_object() ? new_skin->get_spine_object() : nullptr); } diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/spine_godot/SpineSkeleton.h index dd9b8afd3..b8677d108 100644 --- a/spine-godot/spine_godot/SpineSkeleton.h +++ b/spine-godot/spine_godot/SpineSkeleton.h @@ -64,6 +64,7 @@ private: spine::Skeleton *skeleton; SpineSprite *sprite; spine::Vector bounds_vertex_buffer; + Ref last_skin; public: SpineSkeleton(); diff --git a/spine-sfml/cpp/example/test.cpp b/spine-sfml/cpp/example/test.cpp index e228d7159..e54d07e02 100644 --- a/spine-sfml/cpp/example/test.cpp +++ b/spine-sfml/cpp/example/test.cpp @@ -38,41 +38,41 @@ using namespace spine; DebugExtension dbgExtension(SpineExtension::getInstance()); void test() { - SFMLTextureLoader textureLoader; - Atlas atlas("data/bomb.atlas", &textureLoader); - SkeletonBinary loader(&atlas); - SkeletonData *skeletonData = loader.readSkeletonDataFile("data/bomb.skel"); + SFMLTextureLoader textureLoader; + Atlas atlas("data/bomb.atlas", &textureLoader); + SkeletonBinary loader(&atlas); + SkeletonData *skeletonData = loader.readSkeletonDataFile("data/bomb.skel"); - SkeletonDrawable drawable(skeletonData); - drawable.setUsePremultipliedAlpha(true); - drawable.skeleton->setPosition(320, 590); - drawable.state->setAnimation(0, "expl", false); - drawable.skeleton->setSkin("mdl"); + SkeletonDrawable drawable(skeletonData); + drawable.setUsePremultipliedAlpha(true); + drawable.skeleton->setPosition(320, 590); + drawable.state->setAnimation(0, "expl", false); + drawable.skeleton->setSkin("mdl"); - sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - Test"); - window.setFramerateLimit(60); - sf::Event event; - sf::Clock deltaClock; - while (window.isOpen()) { - while (window.pollEvent(event)) - if (event.type == sf::Event::Closed) window.close(); + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - Test"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); - float delta = deltaClock.getElapsedTime().asSeconds(); - deltaClock.restart(); + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); - drawable.update(delta); + drawable.update(delta); - window.clear(); - window.draw(drawable); - window.display(); - } + window.clear(); + window.draw(drawable); + window.display(); + } - delete skeletonData; + delete skeletonData; } int main() { - SpineExtension::setInstance(&dbgExtension); - test(); - dbgExtension.reportLeaks(); - return 0; + SpineExtension::setInstance(&dbgExtension); + test(); + dbgExtension.reportLeaks(); + return 0; } \ No newline at end of file diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h index de1294157..e6e92daaf 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h @@ -53,7 +53,10 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine) USpineSkeletonDataAsset *SkeletonData; - spine::Skeleton *GetSkeleton() { CheckState(); return skeleton; }; + spine::Skeleton *GetSkeleton() { + CheckState(); + return skeleton; + }; UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton") void GetSkins(TArray &Skins); diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonGraphicRenderTexture.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonGraphicRenderTexture.cs index 30f2dc2b4..13117d584 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonGraphicRenderTexture.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonGraphicRenderTexture.cs @@ -248,7 +248,8 @@ namespace Spine.Unity.Examples { } Vector2 targetCameraViewportSize = targetCamera.pixelRect.size; - commandBuffer.SetViewport(new Rect(-screenSpaceMin, targetCameraViewportSize)); + Rect viewportRect = new Rect(-screenSpaceMin * downScaleFactor, targetCameraViewportSize * downScaleFactor); + commandBuffer.SetViewport(viewportRect); } protected override void AssignMeshAtRenderer () { diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTexture.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTexture.cs index da4d428b6..369682ca7 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTexture.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTexture.cs @@ -167,7 +167,8 @@ namespace Spine.Unity.Examples { commandBuffer.SetProjectionMatrix(targetCamera.projectionMatrix); commandBuffer.SetViewMatrix(targetCamera.worldToCameraMatrix); Vector2 targetCameraViewportSize = targetCamera.pixelRect.size; - commandBuffer.SetViewport(new Rect(-screenSpaceMin, targetCameraViewportSize)); + Rect viewportRect = new Rect(-screenSpaceMin * downScaleFactor, targetCameraViewportSize * downScaleFactor); + commandBuffer.SetViewport(viewportRect); } protected void RenderToRenderTexture () { diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTextureBase.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTextureBase.cs index 8fb639e4a..7b5ec2ea2 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTextureBase.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonRenderTexture/SkeletonRenderTextureBase.cs @@ -47,8 +47,10 @@ namespace Spine.Unity.Examples { public Camera targetCamera; protected CommandBuffer commandBuffer; - protected Vector2Int requiredRenderTextureSize; + protected Vector2Int screenSize; + protected Vector2Int usedRenderTextureSize; protected Vector2Int allocatedRenderTextureSize; + protected Vector2 downScaleFactor = Vector2.one; protected Vector3 worldCornerNoDistortion0; protected Vector3 worldCornerNoDistortion1; @@ -89,17 +91,22 @@ namespace Spine.Unity.Examples { uvCorner2 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner2); uvCorner3 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner3); - requiredRenderTextureSize = new Vector2Int( - Math.Min(maxRenderTextureSize, Math.Abs((int)screenSpaceMax.x - (int)screenSpaceMin.x)), - Math.Min(maxRenderTextureSize, Math.Abs((int)screenSpaceMax.y - (int)screenSpaceMin.y))); + screenSize = new Vector2Int(Math.Abs((int)screenSpaceMax.x - (int)screenSpaceMin.x), + Math.Abs((int)screenSpaceMax.y - (int)screenSpaceMin.y)); + usedRenderTextureSize = new Vector2Int( + Math.Min(maxRenderTextureSize, screenSize.x), + Math.Min(maxRenderTextureSize, screenSize.y)); + downScaleFactor = new Vector2( + (float)usedRenderTextureSize.x / (float)screenSize.x, + (float)usedRenderTextureSize.y / (float)screenSize.y); PrepareRenderTexture(); } protected void PrepareRenderTexture () { Vector2Int textureSize = new Vector2Int( - Mathf.NextPowerOfTwo(requiredRenderTextureSize.x), - Mathf.NextPowerOfTwo(requiredRenderTextureSize.y)); + Mathf.NextPowerOfTwo(usedRenderTextureSize.x), + Mathf.NextPowerOfTwo(usedRenderTextureSize.y)); if (textureSize != allocatedRenderTextureSize) { if (renderTexture) @@ -135,8 +142,12 @@ namespace Spine.Unity.Examples { }; quadMesh.normals = normals; - float maxU = (float)requiredRenderTextureSize.x / (float)allocatedRenderTextureSize.x; - float maxV = (float)requiredRenderTextureSize.y / (float)allocatedRenderTextureSize.y; + float maxU = (float)usedRenderTextureSize.x / (float)allocatedRenderTextureSize.x; + float maxV = (float)usedRenderTextureSize.y / (float)allocatedRenderTextureSize.y; + if (downScaleFactor.x < 1 || downScaleFactor.y < 1) { + maxU = downScaleFactor.x * (float)screenSize.x / (float)allocatedRenderTextureSize.x; + maxV = downScaleFactor.y * (float)screenSize.y / (float)allocatedRenderTextureSize.y; + } Vector2[] uv = new Vector2[4] { new Vector2(uvCorner0.x * maxU, uvCorner0.y * maxV), new Vector2(uvCorner1.x * maxU, uvCorner1.y * maxV), diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMAPresetTemplate.png.meta b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMAPresetTemplate.png.meta index 8153700c4..c265f09ae 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMAPresetTemplate.png.meta +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMAPresetTemplate.png.meta @@ -8,7 +8,7 @@ TextureImporter: mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 1 + sRGBTexture: 0 linearTexture: 0 fadeOut: 0 borderMipMap: 0 diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset index f5d5a7333..ed43c6efd 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset @@ -26,7 +26,7 @@ Preset: objectReference: {fileID: 0} - target: {fileID: 0} propertyPath: m_sRGBTexture - value: 1 + value: 0 objectReference: {fileID: 0} - target: {fileID: 0} propertyPath: m_LinearTexture diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs index a79e861fd..7145e5f18 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs @@ -884,6 +884,7 @@ namespace Spine.Unity.Editor { return false; } + texImporter.sRGBTexture = false; // as PMA is the default, prevent any border issues that may arise when enabling mipmaps later. texImporter.textureCompression = TextureImporterCompression.Uncompressed; texImporter.alphaSource = TextureImporterAlphaSource.FromInput; texImporter.mipmapEnabled = false; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/CGIncludes/Spine-SkeletonGraphic-NormalPass.cginc b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/CGIncludes/Spine-SkeletonGraphic-NormalPass.cginc index 9b414b743..2b782970a 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/CGIncludes/Spine-SkeletonGraphic-NormalPass.cginc +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/CGIncludes/Spine-SkeletonGraphic-NormalPass.cginc @@ -26,6 +26,11 @@ fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; +#ifdef ENABLE_FILL +float4 _FillColor; +float _FillPhase; +#endif + VertexOutput vert (VertexInput IN) { VertexOutput OUT; @@ -73,6 +78,9 @@ fixed4 frag (VertexOutput IN) : SV_Target clip (color.a - 0.001); #endif + #ifdef ENABLE_FILL + color.rgb = lerp(color.rgb, (_FillColor.rgb * color.a), _FillPhase); // make sure to PMA _FillColor. + #endif return color; } 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 new file mode 100644 index 000000000..7b2074718 --- /dev/null +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader @@ -0,0 +1,78 @@ +Shader "Spine/SkeletonGraphic Fill" +{ + Properties + { + _FillColor("FillColor", Color) = (1,1,1,1) + _FillPhase("FillPhase", Range(0, 1)) = 0 + [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} + [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 + [Toggle(_CANVAS_GROUP_COMPATIBLE)] _CanvasGroupCompatible("CanvasGroup Compatible", Int) = 1 + _Color("Tint", Color) = (1,1,1,1) + + [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 + [HideInInspector] _Stencil("Stencil ID", Float) = 0 + [HideInInspector][Enum(UnityEngine.Rendering.StencilOp)] _StencilOp("Stencil Operation", Float) = 0 + [HideInInspector] _StencilWriteMask("Stencil Write Mask", Float) = 255 + [HideInInspector] _StencilReadMask("Stencil Read Mask", Float) = 255 + + [HideInInspector] _ColorMask("Color Mask", Float) = 15 + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0 + + // Outline properties are drawn via custom editor. + [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0 + [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1) + [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 + [HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1 + [HideInInspector] _OutlineOpaqueAlpha("Opaque Alpha", Range(0,1)) = 1.0 + [HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0 + } + + SubShader + { + Tags + { + "Queue" = "Transparent" + "IgnoreProjector" = "True" + "RenderType" = "Transparent" + "PreviewType" = "Plane" + "CanUseSpriteAtlas" = "True" + } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + Cull Off + Lighting Off + ZWrite Off + ZTest[unity_GUIZTestMode] + Fog { Mode Off } + Blend One OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass + { + Name "Normal" + + CGPROGRAM + #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT + #pragma shader_feature _ _CANVAS_GROUP_COMPATIBLE + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #define ENABLE_FILL + #include "CGIncludes/Spine-SkeletonGraphic-NormalPass.cginc" + ENDCG + } + } + CustomEditor "SpineShaderWithOutlineGUI" +} diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader.meta b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader.meta new file mode 100644 index 000000000..68d15e4d2 --- /dev/null +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-Fill.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c02377d9afbb50e49ab27049e59fb5f8 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: