Sfoglia il codice sorgente

[Unity] Added SkeletonGhost stuff
SkeletonGhost Shader contributed by Alex Dixon

Fenrisul 10 anni fa
parent
commit
aef9b23a20

+ 5 - 0
spine-unity/Assets/spine-unity/Ghost.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 13193c9d213765f4c85f4c1faa615711
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 5 - 0
spine-unity/Assets/spine-unity/Ghost/Shaders.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: a0cee0de78cef7440ae0b5aac39ae971
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 92 - 0
spine-unity/Assets/spine-unity/Ghost/Shaders/SkeletonGhost.shader

@@ -0,0 +1,92 @@
+//Shader written by Alex Dixon
+Shader "Spine/SkeletonGhost" 
+{
+    Properties 
+    {
+        _Color ("Main Color", Color) = (1,1,1,1)
+        _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
+		_TextureFade ("Texture Fade Out", Range(0,1)) = 0
+    }
+    SubShader 
+    {
+    
+      Tags {"Queue"="Transparent" "IgnoreProjector"="False" "RenderType"="Transparent"}
+      Fog { Mode Off }
+      Blend One OneMinusSrcAlpha
+      ZWrite Off
+	  Cull Off
+      
+        Pass 
+        {
+            Tags {"LightMode" = "Always"}                      // This Pass tag is important or Unity may not give it the correct light information.
+           		CGPROGRAM
+                #pragma vertex vert
+                #pragma fragment frag
+                //#pragma multi_compile_fwdbase                       // This line tells Unity to compile this pass for forward base.
+                
+                #include "UnityCG.cginc"
+                //#include "AutoLight.cginc"
+                    
+               	struct vertex_input
+               	{
+               		float4 vertex : POSITION;
+               		float2 texcoord : TEXCOORD0;
+					float4 color : COLOR;
+
+               	};
+                
+                struct vertex_output
+                {
+                    float4  pos         : SV_POSITION;
+                    float2  uv          : TEXCOORD0;
+
+					float4 color : COLOR;
+                };
+                
+                sampler2D _MainTex;
+                fixed4 _Color;
+				fixed _TextureFade;
+                
+                vertex_output vert (vertex_input v)
+                {
+                    vertex_output o;
+                    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
+                    o.uv = v.texcoord.xy;
+                    o.color = v.color;
+					
+						         
+                    return o;
+                }
+                
+                fixed4 frag(vertex_output i) : COLOR
+                {
+                    fixed4 tex = tex2D(_MainTex, i.uv);
+
+					tex = fixed4(max(_TextureFade, tex.r), max(_TextureFade, tex.g), max(_TextureFade, tex.b), tex.a);
+
+					return tex * ((i.color * _Color) * tex.a);
+
+
+
+					//float finalAlpha = tex.a * i.color.a * _Color.a;
+
+                    /*
+                    TODO:  Add basic lighting stuff in later?
+
+                    fixed4 c;
+					c.rgb = (UNITY_LIGHTMODEL_AMBIENT.rgb * tex.rgb);       // Ambient term. Only do this in Forward Base. It only needs calculating once.
+                    c.rgb += tex.rgb; // Diffuse and specular.
+					//Unity 4: c.rgb = (UNITY_LIGHTMODEL_AMBIENT.rgb * tex.rgb * 2);       // Ambient term. Only do this in Forward Base. It only needs calculating once.
+					//Unity 4: c.rgb += (tex.rgb * _LightColor0.rgb * diff) * (atten * 2); // Diffuse and specular.
+                    c.a = tex.a;  // + _LightColor0.a * atten;
+
+                    return c;
+					*/
+                }
+            ENDCG
+        }
+             
+        
+    }
+    //FallBack "Transparent/Cutout/VertexLit"    // Use VertexLit's shadow caster/receiver passes.
+}

+ 7 - 0
spine-unity/Assets/spine-unity/Ghost/Shaders/SkeletonGhost.shader.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3873d4699ee8a4b4da8fa6b8c229b94d
+ShaderImporter:
+  defaultTextures: []
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 147 - 0
spine-unity/Assets/spine-unity/Ghost/SkeletonGhost.cs

@@ -0,0 +1,147 @@
+/*****************************************************************************
+ * SkeletonGhost created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+[RequireComponent(typeof(SkeletonRenderer))]
+public class SkeletonGhost : MonoBehaviour {
+	public bool ghostingEnabled = true;
+	public float spawnRate = 0.05f;
+	public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00);
+	[Tooltip("Remember to set color alpha to 0 if Additive is true")]
+	public bool additive = true;
+	public int maximumGhosts = 10;
+	public float fadeSpeed = 10;
+	public Shader ghostShader;
+	[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
+	[Range(0, 1)]
+	public float textureFade = 1;
+
+	float nextSpawnTime;
+	SkeletonGhostRenderer[] pool;
+	int poolIndex = 0;
+	SkeletonRenderer skeletonRenderer;
+	MeshRenderer meshRenderer;
+	MeshFilter meshFilter;
+
+
+	Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
+
+	void Start () {
+		if (ghostShader == null)
+			ghostShader = Shader.Find("Spine/SkeletonGhost");
+
+		skeletonRenderer = GetComponent<SkeletonRenderer>();
+		meshFilter = GetComponent<MeshFilter>();
+		meshRenderer = GetComponent<MeshRenderer>();
+		nextSpawnTime = Time.time + spawnRate;
+		pool = new SkeletonGhostRenderer[maximumGhosts];
+		for (int i = 0; i < maximumGhosts; i++) {
+			GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
+			pool[i] = go.GetComponent<SkeletonGhostRenderer>();
+			go.SetActive(false);
+			go.hideFlags = HideFlags.HideInHierarchy;
+		}
+
+		if (skeletonRenderer is SkeletonAnimation)
+			((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
+
+	}
+
+	//SkeletonAnimation
+	/*
+	 *	Int Value:		0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
+	 *	Float Value:	Values greater than 0 set the spawnRate equal the float value
+	 *	String Value:	Pass RGBA hex color values in to set the color property.  IE:   "A0FF8BFF"
+	 */
+	void OnEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {
+		if (e.Data.Name == "Ghosting") {
+			ghostingEnabled = e.Int > 0;
+			if (e.Float > 0)
+				spawnRate = e.Float;
+			if (e.String != null) {
+				this.color = HexToColor(e.String);
+			}
+		}
+	}
+
+	//SkeletonAnimator
+	//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled.  Be sure not to set anything other than the Int param in Spine or String will take priority.
+	void Ghosting (float val) {
+		ghostingEnabled = val > 0;
+	}
+
+	void Update () {
+		if (!ghostingEnabled)
+			return;
+
+		if (Time.time >= nextSpawnTime) {
+			GameObject go = pool[poolIndex].gameObject;
+
+			Material[] materials = meshRenderer.sharedMaterials;
+			for (int i = 0; i < materials.Length; i++) {
+				var originalMat = materials[i];
+				Material ghostMat;
+				if (!materialTable.ContainsKey(originalMat)) {
+					ghostMat = new Material(originalMat);
+					ghostMat.shader = ghostShader;
+					ghostMat.color = Color.white;
+					if (ghostMat.HasProperty("_TextureFade"))
+						ghostMat.SetFloat("_TextureFade", textureFade);
+					materialTable.Add(originalMat, ghostMat);
+				} else {
+					ghostMat = materialTable[originalMat];
+				}
+
+				materials[i] = ghostMat;
+			}
+
+			pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingOrder - 1);
+			go.transform.parent = transform;
+
+			go.transform.localPosition = Vector3.zero;
+			go.transform.localRotation = Quaternion.identity;
+			go.transform.localScale = Vector3.one;
+
+			go.transform.parent = null;
+
+			poolIndex++;
+
+			if (poolIndex == pool.Length)
+				poolIndex = 0;
+
+			nextSpawnTime = Time.time + spawnRate;
+		}
+	}
+
+	void OnDestroy () {
+		for (int i = 0; i < maximumGhosts; i++) {
+			if (pool[i] != null)
+				pool[i].Cleanup();
+		}
+
+		foreach (var mat in materialTable.Values)
+			Destroy(mat);
+	}
+
+
+	//based on UnifyWiki  http://wiki.unity3d.com/index.php?title=HexConverter
+	static Color32 HexToColor (string hex) {
+		if (hex.Length < 6)
+			return Color.magenta;
+
+		hex = hex.Replace("#", "");
+		byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
+		byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
+		byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
+		byte a = 0xFF;
+		if (hex.Length == 8)
+			a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
+
+		return new Color32(r, g, b, a);
+	}
+}

+ 13 - 0
spine-unity/Assets/spine-unity/Ghost/SkeletonGhost.cs.meta

@@ -0,0 +1,13 @@
+fileFormatVersion: 2
+guid: 02f2fa991881c6d419500ccc40ad443f
+timeCreated: 1431858330
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences:
+  - ghostShader: {fileID: 4800000, guid: 3873d4699ee8a4b4da8fa6b8c229b94d, type: 3}
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 109 - 0
spine-unity/Assets/spine-unity/Ghost/SkeletonGhostRenderer.cs

@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * SkeletonGhostRenderer created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+
+public class SkeletonGhostRenderer : MonoBehaviour {
+
+	public float fadeSpeed = 10;
+
+	Color32[] colors;
+	Color32 black = new Color32(0, 0, 0, 0);
+	MeshFilter meshFilter;
+	MeshRenderer meshRenderer;
+
+	void Awake () {
+		meshRenderer = gameObject.AddComponent<MeshRenderer>();
+		meshFilter = gameObject.AddComponent<MeshFilter>();
+	}
+
+	public void Initialize (Mesh mesh, Material[] materials, Color32 color, bool additive, float speed, int sortingOrder) {
+		StopAllCoroutines();
+
+		gameObject.SetActive(true);
+		
+
+		meshRenderer.sharedMaterials = materials;
+		meshRenderer.sortingOrder = sortingOrder;
+
+		meshFilter.sharedMesh = (Mesh)Instantiate(mesh);
+
+		colors = meshFilter.sharedMesh.colors32;
+
+		if ((color.a + color.r + color.g + color.b) > 0) {
+			for (int i = 0; i < colors.Length; i++) {
+				colors[i] = color;
+			}
+		}
+
+		fadeSpeed = speed;
+
+		if (additive)
+			StartCoroutine(FadeAdditive());
+		else
+			StartCoroutine(Fade());
+	}
+
+	IEnumerator Fade () {
+		Color32 c;
+		for (int t = 0; t < 500; t++) {
+
+			bool breakout = true;
+			for (int i = 0; i < colors.Length; i++) {
+				c = colors[i];
+				if (c.a > 0)
+					breakout = false;
+
+				colors[i] = Color32.Lerp(c, black, Time.deltaTime * fadeSpeed);
+			}
+
+			meshFilter.sharedMesh.colors32 = colors;
+
+			if (breakout)
+				break;
+			yield return null;
+		}
+
+		Destroy(meshFilter.sharedMesh);
+
+		gameObject.SetActive(false);
+	}
+
+	IEnumerator FadeAdditive () {
+		Color32 c;
+		Color32 black = this.black;
+
+		for (int t = 0; t < 500; t++) {
+
+			bool breakout = true;
+			for (int i = 0; i < colors.Length; i++) {
+				c = colors[i];
+				black.a = c.a;
+				if (c.r > 0 || c.g > 0 || c.b > 0)
+				breakout = false;
+
+				colors[i] = Color32.Lerp(c, black, Time.deltaTime * fadeSpeed);
+			}
+
+			meshFilter.sharedMesh.colors32 = colors;
+
+			if (breakout)
+				break;
+			yield return null;
+		}
+
+		Destroy(meshFilter.sharedMesh);
+
+		gameObject.SetActive(false);
+	}
+
+	public void Cleanup () {
+		if (meshFilter != null && meshFilter.sharedMesh != null)
+			Destroy(meshFilter.sharedMesh);
+
+		Destroy(gameObject);
+	}
+}

+ 10 - 0
spine-unity/Assets/spine-unity/Ghost/SkeletonGhostRenderer.cs.meta

@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 58e3a9b80754b7545a1dff4d8475b51f
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: