diff --git a/.gitignore b/.gitignore index ce4c70cb1..0669d7ecb 100644 --- a/.gitignore +++ b/.gitignore @@ -47,11 +47,14 @@ spine-csharp/src/Attachments/*.cs.meta spine-monogame/example/bin spine-monogame/example/obj +spine-monogame/example/Content/bin/ +spine-monogame/example/Content/obj/ spine-xna/bin spine-xna/obj spine-xna/example/bin spine-xna/example/obj +spine-xna/example-content/obj/ spine-unity/Assets/spine-csharp* !spine-unity/Assets/spine-csharp/Place spine-csharp src here.* diff --git a/CHANGELOG.md b/CHANGELOG.md index c1d0c7907..c8dcb3e08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,17 +106,12 @@ * `SkeletonAnimator` now has autoreset set to true by default. Old prefabs and scene values will have been serialized to whatever value it was previously. This change only applies to new instances of SkeletonAnimator. * Warnings and conditionals checking for specific Unity 5.2-and-below incompatibility have been removed. -## XNA +## XNA/MonoGame * Added support for clipping * Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` * Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code. * Added support for any `Effect` to be used by `SkeletonRenderer` - ## MonoGame - * Added support for clipping - * Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer` - * - ## Java * **Breaking changes** * `Skeleton.getBounds` takes a scratch array as input so it doesn't have to allocate a new array on each invocation itself. Reduces GC activity. diff --git a/spine-monogame/example/Content/Content.mgcb b/spine-monogame/example/Content/Content.mgcb index ddc4c3679..e4de620d4 100644 --- a/spine-monogame/example/Content/Content.mgcb +++ b/spine-monogame/example/Content/Content.mgcb @@ -13,3 +13,9 @@ #---------------------------------- Content ---------------------------------# +#begin SpineEffect.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:SpineEffect.fx + diff --git a/spine-monogame/example/Content/SpineEffect.fx b/spine-monogame/example/Content/SpineEffect.fx new file mode 100644 index 000000000..49d09ec0e --- /dev/null +++ b/spine-monogame/example/Content/SpineEffect.fx @@ -0,0 +1,67 @@ +#if OPENGL + #define SV_POSITION POSITION + #define VS_SHADERMODEL vs_3_0 + #define PS_SHADERMODEL ps_3_0 +#else + #define VS_SHADERMODEL vs_4_0_level_9_1 + #define PS_SHADERMODEL ps_4_0_level_9_1 +#endif + +float4x4 World; +float4x4 View; +float4x4 Projection; + +sampler TextureSampler : register(s0); + +// TODO: add effect parameters here. + +struct VertexShaderInput +{ + float4 Position : POSITION0; + float4 Color : COLOR0; + float4 TextureCoordinate : TEXCOORD0; + float4 Color2 : COLOR1; +}; + +struct VertexShaderOutput +{ + float4 Position : POSITION0; + float4 Color : COLOR0; + float4 TextureCoordinate : TEXCOORD0; + float4 Color2 : COLOR1; +}; + +VertexShaderOutput VertexShaderFunction(VertexShaderInput input) +{ + VertexShaderOutput output; + + float4 worldPosition = mul(input.Position, World); + float4 viewPosition = mul(worldPosition, View); + output.Position = mul(viewPosition, Projection); + output.TextureCoordinate = input.TextureCoordinate; + output.Color = input.Color; + output.Color2 = input.Color2; + + return output; +} + +float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 +{ + float4 texColor = tex2D(TextureSampler, input.TextureCoordinate); + float alpha = texColor.a * input.Color.a; + float4 output; + output.a = alpha; + output.rgb = (1.0 - texColor.rgb) * input.Color2.rgb * alpha + texColor.rgb * input.Color.rgb; + + return output; +} + + +technique BasicColorDrawing +{ + pass P0 + { + VertexShader = compile VS_SHADERMODEL VertexShaderFunction(); + PixelShader = compile PS_SHADERMODEL PixelShaderFunction(); + } +}; \ No newline at end of file diff --git a/spine-monogame/example/ExampleGame.cs b/spine-monogame/example/ExampleGame.cs index 4773279bd..2280aaff6 100644 --- a/spine-monogame/example/ExampleGame.cs +++ b/spine-monogame/example/ExampleGame.cs @@ -42,7 +42,7 @@ using Spine; namespace Spine { public class Example : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; - SkeletonMeshRenderer skeletonRenderer; + SkeletonRenderer skeletonRenderer; Skeleton skeleton; Slot headSlot; AnimationState state; @@ -65,15 +65,22 @@ namespace Spine { base.Initialize(); } - protected override void LoadContent () { - skeletonRenderer = new SkeletonMeshRenderer(GraphicsDevice); + protected override void LoadContent() { + // Two color tint effect, comment line 76 to disable + var spineEffect = Content.Load("Content\\SpineEffect"); + spineEffect.Parameters["World"].SetValue(Matrix.Identity); + spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up)); + + skeletonRenderer = new SkeletonRenderer(GraphicsDevice); skeletonRenderer.PremultipliedAlpha = true; + skeletonRenderer.Effect = spineEffect; // String name = "spineboy"; // String name = "goblins-mesh"; // String name = "raptor"; // String name = "tank"; - String name = "coin"; + // String name = "coin"; + String name = "TwoColorTest"; bool binaryData = true; Atlas atlas = new Atlas(assetsFolder + name + ".atlas", new XnaTextureLoader(GraphicsDevice)); @@ -81,7 +88,8 @@ namespace Spine { float scale = 1; if (name == "spineboy") scale = 0.6f; if (name == "raptor") scale = 0.5f; - if (name == "tank") scale = 0.3f; + if (name == "tank") scale = 0.3f; + if (name == "TwoColorTest") scale = 0.5f; SkeletonData skeletonData; if (binaryData) { @@ -124,12 +132,15 @@ namespace Spine { } else if (name == "tank") { state.SetAnimation(0, "drive", true); + } + else if (name == "TwoColorTest") { + state.SetAnimation(0, "animation", true); } else { state.SetAnimation(0, "walk", true); } skeleton.X = 400 + (name == "tank" ? 300: 0); - skeleton.Y = 580; + skeleton.Y = 580 + (name == "TwoColorTest" ? -300 : 0); skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); @@ -148,6 +159,12 @@ namespace Spine { state.Update(gameTime.ElapsedGameTime.Milliseconds / 1000f); state.Apply(skeleton); skeleton.UpdateWorldTransform(); + if (skeletonRenderer.Effect is BasicEffect) { + ((BasicEffect)skeletonRenderer.Effect).Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0); + } + else { + skeletonRenderer.Effect.Parameters["Projection"].SetValue(Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0)); + } skeletonRenderer.Begin(); skeletonRenderer.Draw(skeleton); skeletonRenderer.End(); diff --git a/spine-monogame/example/spine-monogame-example.csproj b/spine-monogame/example/spine-monogame-example.csproj index a80190aca..5638d957d 100644 --- a/spine-monogame/example/spine-monogame-example.csproj +++ b/spine-monogame/example/spine-monogame-example.csproj @@ -45,14 +45,8 @@ spine-xna\MeshBatcher.cs - - spine-xna\RegionBatcher.cs - - - spine-xna\SkeletonMeshRenderer.cs - - - spine-xna\SkeletonRegionRenderer.cs + + spine-xna\SkeletonRenderer.cs spine-xna\Util.cs @@ -76,7 +70,9 @@ - + + Always + x86\SDL2.dll PreserveNewest diff --git a/spine-xna/example/data/TwoColorTest.skel b/spine-xna/example/data/TwoColorTest.skel new file mode 100644 index 000000000..9c060fb20 Binary files /dev/null and b/spine-xna/example/data/TwoColorTest.skel differ diff --git a/spine-xna/example/src/ExampleGame.cs b/spine-xna/example/src/ExampleGame.cs index 94a4cc4d3..ab5280585 100644 --- a/spine-xna/example/src/ExampleGame.cs +++ b/spine-xna/example/src/ExampleGame.cs @@ -70,6 +70,7 @@ namespace Spine { } protected override void LoadContent () { + // Two color tint effect, comment line 80 to disable var spineEffect = Content.Load("spine-xna-example-content\\SpineEffect"); spineEffect.Parameters["World"].SetValue(Matrix.Identity); spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up)); diff --git a/spine-xna/src/SkeletonRenderer.cs b/spine-xna/src/SkeletonRenderer.cs index bf29c7897..8f105dec1 100644 --- a/spine-xna/src/SkeletonRenderer.cs +++ b/spine-xna/src/SkeletonRenderer.cs @@ -78,9 +78,7 @@ namespace Spine { defaultBlendState = premultipliedAlpha ? BlendState.AlphaBlend : BlendState.NonPremultiplied; device.RasterizerState = rasterizerState; - device.BlendState = defaultBlendState; - - if (effect is BasicEffect) ((BasicEffect)effect).Projection = Matrix.CreateOrthographicOffCenter(0, device.Viewport.Width, device.Viewport.Height, 0, 1, 0); + device.BlendState = defaultBlendState; } public void End () {