This commit is contained in:
badlogic 2022-10-31 13:21:44 +01:00
commit 4babd19eee
16 changed files with 164 additions and 44 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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);

View File

@ -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<SpineSkin> 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);
}

View File

@ -64,6 +64,7 @@ private:
spine::Skeleton *skeleton;
SpineSprite *sprite;
spine::Vector<float> bounds_vertex_buffer;
Ref<SpineSkin> last_skin;
public:
SpineSkeleton();

View File

@ -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;
}

View File

@ -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<FString> &Skins);

View File

@ -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 () {

View File

@ -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 () {

View File

@ -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),

View File

@ -8,7 +8,7 @@ TextureImporter:
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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"
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c02377d9afbb50e49ab27049e59fb5f8
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant: