From 233d3a9657db66fa05956b6b9d204e677d1c449e Mon Sep 17 00:00:00 2001 From: mob-sakai Date: Sat, 23 Feb 2019 16:40:57 +0900 Subject: [PATCH] close #42; Support changing material property by AnimationClip --- .../Scripts/Editor/UIParticleEditor.cs | 108 ++++++++++++++++++ .../UIParticle/Scripts/UIParticle.cs | 81 ++++++++++++- .../UIParticle/Shaders/UIAdditive.shader | 2 +- 3 files changed, 186 insertions(+), 5 deletions(-) diff --git a/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs b/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs index ab30d1c..cddc0d4 100644 --- a/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs +++ b/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs @@ -39,6 +39,7 @@ protected override void OnEnable () _spTrailParticle = serializedObject.FindProperty ("m_TrailParticle"); _spScale = serializedObject.FindProperty ("m_Scale"); _spIgnoreParent = serializedObject.FindProperty ("m_IgnoreParent"); + _spAnimatableProperties = serializedObject.FindProperty ("m_AnimatableProperties"); if (!s_Material) { @@ -86,6 +87,9 @@ public override void OnInspectorGUI () EditorGUILayout.PropertyField (_spScale); EditorGUI.EndDisabledGroup (); + // AnimatableProperties + AnimatedProperty.DrawAnimatableProperties (_spAnimatableProperties, current.material); + current.GetComponentsInChildren (true, s_ParticleSystems); if (s_ParticleSystems.Any (x => x.GetComponent () == null)) { @@ -107,6 +111,109 @@ public override void OnInspectorGUI () serializedObject.ApplyModifiedProperties (); } + class AnimatedProperty + { + static readonly List s_ActiveNames = new List (); + static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder (); + + public string name; + public ShaderUtil.ShaderPropertyType type; + + static string CollectActiveNames (SerializedProperty sp, List result) + { + result.Clear (); + for (int i = 0; i < sp.arraySize; i++) + { + result.Add (sp.GetArrayElementAtIndex (i).FindPropertyRelative ("name").stringValue); + } + + s_Sb.Length = 0; + if (result.Count == 0) + { + s_Sb.Append ("Nothing"); + } + else + { + result.Aggregate (s_Sb, (a, b) => s_Sb.AppendFormat ("{0}, ", b)); + s_Sb.Length -= 2; + } + + return s_Sb.ToString (); + } + + public static void DrawAnimatableProperties (SerializedProperty sp, Material mat) + { + if (!mat || !mat.shader) + return; + bool isClicked = false; + using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth(false))) + { + var r = EditorGUI.PrefixLabel (EditorGUILayout.GetControlRect (true), new GUIContent(sp.displayName, sp.tooltip)); + isClicked = GUI.Button (r, CollectActiveNames (sp, s_ActiveNames), EditorStyles.popup); + } + + if(isClicked) + { + GenericMenu gm = new GenericMenu (); + gm.AddItem (new GUIContent ("Nothing"), s_ActiveNames.Count == 0, () => + { + sp.ClearArray (); + sp.serializedObject.ApplyModifiedProperties (); + }); + + + for (int i = 0; i < sp.arraySize; i++) + { + var p = sp.GetArrayElementAtIndex (i); + var name = p.FindPropertyRelative ("name").stringValue; + var type = (ShaderUtil.ShaderPropertyType)p.FindPropertyRelative ("type").intValue; + AddMenu (gm, sp, new AnimatedProperty () { name = name, type = type }, false); + } + + for (int i = 0; i < ShaderUtil.GetPropertyCount (mat.shader); i++) + { + var pName = ShaderUtil.GetPropertyName (mat.shader, i); + var type = ShaderUtil.GetPropertyType (mat.shader, i); + AddMenu (gm, sp, new AnimatedProperty () { name = pName, type = type }, true); + + if (type == ShaderUtil.ShaderPropertyType.TexEnv) + { + AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_ST", type = ShaderUtil.ShaderPropertyType.Vector }, true); + AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_HDR", type = ShaderUtil.ShaderPropertyType.Vector }, true); + AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_TexelSize", type = ShaderUtil.ShaderPropertyType.Vector }, true); + } + + } + + gm.ShowAsContext (); + } + } + + public static void AddMenu (GenericMenu menu, SerializedProperty sp, AnimatedProperty property, bool add) + { + if (add && s_ActiveNames.Contains (property.name)) + return; + + menu.AddItem (new GUIContent (string.Format ("{0} ({1})", property.name, property.type)), s_ActiveNames.Contains (property.name), () => + { + var index = s_ActiveNames.IndexOf (property.name); + if (0 <= index) + { + sp.DeleteArrayElementAtIndex (index); + } + else + { + sp.InsertArrayElementAtIndex (sp.arraySize); + var p = sp.GetArrayElementAtIndex (sp.arraySize - 1); + p.FindPropertyRelative ("name").stringValue = property.name; + p.FindPropertyRelative ("type").intValue = (int)property.type; + } + sp.serializedObject.ApplyModifiedProperties (); + }); + } + } + + //################################ // Private Members. //################################ @@ -114,6 +221,7 @@ public override void OnInspectorGUI () SerializedProperty _spTrailParticle; SerializedProperty _spScale; SerializedProperty _spIgnoreParent; + SerializedProperty _spAnimatableProperties; UIParticle [] _particles; ArcHandle _arcHandle = new ArcHandle (); BoxBoundsHandle _boxBoundsHandle = new BoxBoundsHandle (); diff --git a/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs b/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs index 3b906fe..437dee9 100755 --- a/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs +++ b/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs @@ -35,6 +35,28 @@ public class UIParticle : MaskableGraphic [Tooltip ("Ignore parent scale")] [SerializeField] bool m_IgnoreParent = false; + [Tooltip ("Animatable material properties. AnimationでParticleSystemのマテリアルプロパティを変更する場合、有効にしてください。")] + [SerializeField] AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0]; + + static MaterialPropertyBlock s_Mpb; + + [System.Serializable] + public class AnimatableProperty + { + public enum ShaderPropertyType + { + Color, + Vector, + Float, + Range, + TexEnv, + }; + + public string name; + public ShaderPropertyType type; + } + + //################################ // Public/Protected Members. @@ -57,9 +79,7 @@ public override Texture mainTexture if (!tex && _renderer) { Profiler.BeginSample ("Check material"); - var mat = m_IsTrail - ? _renderer.trailMaterial - : _renderer.sharedMaterial; + var mat = material; if (mat && mat.HasProperty (s_IdMainTex)) { tex = mat.mainTexture; @@ -70,6 +90,35 @@ public override Texture mainTexture } } + public override Material material + { + get + { + return _renderer + ? m_IsTrail + ? _renderer.trailMaterial + : _renderer.sharedMaterial + : null; + } + + set + { + if (!_renderer) + { + } + else if (m_IsTrail && _renderer.trailMaterial != value) + { + _renderer.trailMaterial = value; + SetMaterialDirty (); + } + else if (!m_IsTrail && _renderer.sharedMaterial != value) + { + _renderer.sharedMaterial = value; + SetMaterialDirty (); + } + } + } + /// /// Particle effect scale. /// @@ -117,7 +166,15 @@ public bool isRoot /// Configured Material. public override Material GetModifiedMaterial (Material baseMaterial) { - return base.GetModifiedMaterial (_renderer ? _renderer.sharedMaterial : baseMaterial); + Material mat = null; + if (!_renderer) + mat = baseMaterial; + else if (m_AnimatableProperties.Length == 0) + mat = _renderer.sharedMaterial; + else + mat = new Material (material); + + return base.GetModifiedMaterial (mat); } /// @@ -129,6 +186,7 @@ protected override void OnEnable () if (s_ActiveParticles.Count == 0) { Canvas.willRenderCanvases += UpdateMeshes; + s_Mpb = new MaterialPropertyBlock (); } s_ActiveParticles.Add (this); @@ -369,6 +427,21 @@ void UpdateMesh () Profiler.BeginSample ("Set mesh and texture to CanvasRenderer"); canvasRenderer.SetMesh (_mesh); canvasRenderer.SetTexture (mainTexture); + + // Copy the value from MaterialPropertyBlock to CanvasRenderer (#41) + if (Application.isPlaying && 0 < m_AnimatableProperties.Length) + { + _renderer.GetPropertyBlock (s_Mpb); + for (int i = 0; i < canvasRenderer.materialCount; i++) + { + var mat = canvasRenderer.GetMaterial (i); + foreach (var ap in m_AnimatableProperties) + { + mat.SetVector (ap.name, s_Mpb.GetVector (ap.name)); + } + } + } + Profiler.EndSample (); } } diff --git a/Assets/Coffee/UIExtensions/UIParticle/Shaders/UIAdditive.shader b/Assets/Coffee/UIExtensions/UIParticle/Shaders/UIAdditive.shader index 45b5c34..69797b8 100644 --- a/Assets/Coffee/UIExtensions/UIParticle/Shaders/UIAdditive.shader +++ b/Assets/Coffee/UIExtensions/UIParticle/Shaders/UIAdditive.shader @@ -77,7 +77,7 @@ v2f OUT; OUT.worldPosition = IN.vertex; OUT.vertex = UnityObjectToClipPos(IN.vertex); - OUT.texcoord = IN.texcoord; + OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex); #ifdef UNITY_HALF_TEXEL_OFFSET OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1); #endif