using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.VFX; namespace UnityEngine.VFX.Utility { /// /// A Behaviour that controls binding between Visual Effect Properties, and other scene values, through the use of VFXBinderBase /// [RequireComponent(typeof(VisualEffect))] [DefaultExecutionOrder(1)] [DisallowMultipleComponent] [ExecuteAlways] public class VFXPropertyBinder : MonoBehaviour { /// /// Whether the bindings should be executed in editor (as preview) /// [SerializeField] protected bool m_ExecuteInEditor = true; /// /// The list of all Bindings attached to the binder, these bindings are managed by the VFXPropertyBinder and should be managed using the AddPropertyBinder, ClearPropertyBinders, RemovePropertyBinder, RemovePropertyBinders, and GetPropertyBinders. /// public List m_Bindings = new List(); /// /// The Visual Effect component attached to the VFXPropertyBinder /// [SerializeField] protected VisualEffect m_VisualEffect; private void OnEnable() { Reload(); } private void OnValidate() { Reload(); } static private void SafeDestroy(Object toDelete) { #if UNITY_EDITOR if (Application.isPlaying) Destroy(toDelete); //Undo.DestroyObjectImmediate is needed only for Reset, which can't be called in play mode else UnityEditor.Undo.DestroyObjectImmediate(toDelete); #else Destroy(toDelete); #endif } #if UNITY_EDITOR List m_BinderToCopyPaste; #endif private void Reload() { m_VisualEffect = GetComponent(); #if UNITY_EDITOR //Handle probable copy/paste component saving list of inappropriate entries. m_BinderToCopyPaste = new List(); foreach (var bindings in m_Bindings) { if (bindings != null && bindings.gameObject != gameObject) m_BinderToCopyPaste.Add(bindings); } if (m_BinderToCopyPaste.Count == 0) m_BinderToCopyPaste = null; #endif m_Bindings = new List(); m_Bindings.AddRange(gameObject.GetComponents()); } private void Reset() { Reload(); ClearPropertyBinders(); } #if UNITY_EDITOR void Update() { if (m_BinderToCopyPaste != null) { //We can't add a component during a OnInvalidate, restore & copy linked binders (from copy/past) here foreach (var copyPaste in m_BinderToCopyPaste) { var type = copyPaste.GetType(); var newComponent = gameObject.AddComponent(type); UnityEditor.EditorUtility.CopySerialized(copyPaste, newComponent); } m_BinderToCopyPaste = null; Reload(); } } #endif void LateUpdate() { if (!m_ExecuteInEditor && Application.isEditor && !Application.isPlaying) return; for (int i = 0; i < m_Bindings.Count; i++) { var binding = m_Bindings[i]; if (binding == null) { Debug.LogWarning(string.Format("Parameter binder at index {0} of GameObject {1} is null or missing", i, gameObject.name)); continue; } else { if (binding.IsValid(m_VisualEffect)) binding.UpdateBinding(m_VisualEffect); } } } /// /// Adds a new PropertyBinder /// /// the Type of Property Binder /// The PropertyBinder newly Created public T AddPropertyBinder() where T : VFXBinderBase { return gameObject.AddComponent(); } /// /// Adds a new PropertyBinder /// /// the Type of Property Binder /// The PropertyBinder newly Created [Obsolete("Use AddPropertyBinder() instead")] public T AddParameterBinder() where T : VFXBinderBase { return AddPropertyBinder(); } /// /// Clears all the Property Binders /// public void ClearPropertyBinders() { var allBinders = GetComponents(); foreach (var binder in allBinders) SafeDestroy(binder); } /// /// Clears all the Property Binders /// [Obsolete("Please use ClearPropertyBinders() instead")] public void ClearParameterBinders() { ClearPropertyBinders(); } /// /// Removes specified Property Binder /// /// The VFXBinderBase to remove public void RemovePropertyBinder(VFXBinderBase binder) { if (binder.gameObject == this.gameObject) SafeDestroy(binder); } /// /// Removes specified Property Binder /// /// The VFXBinderBase to remove [Obsolete("Please use RemovePropertyBinder() instead")] public void RemoveParameterBinder(VFXBinderBase binder) { RemovePropertyBinder(binder); } /// /// Remove all Property Binders of Given Type /// /// Specified VFXBinderBase type public void RemovePropertyBinders() where T : VFXBinderBase { var allBinders = GetComponents(); foreach (var binder in allBinders) if (binder is T) SafeDestroy(binder); } /// /// Remove all Property Binders of Given Type /// /// Specified VFXBinderBase type [Obsolete("Please use RemovePropertyBinders() instead")] public void RemoveParameterBinders() where T : VFXBinderBase { RemovePropertyBinders(); } /// /// Gets all VFXBinderBase of Given Type, attached to this VFXPropertyBinder /// /// Specific VFXBinderBase type /// An IEnumerable of all VFXBinderBase public IEnumerable GetPropertyBinders() where T : VFXBinderBase { foreach (var binding in m_Bindings) { if (binding is T) yield return binding as T; } } /// /// Gets all VFXBinderBase of Given Type, attached to this VFXPropertyBinder /// /// Specific VFXBinderBase type /// An IEnumerable of all VFXBinderBase [Obsolete("Please use GetPropertyBinders() instead")] public IEnumerable GetParameterBinders() where T : VFXBinderBase { return GetPropertyBinders(); } } }