using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.VFX; using System.Linq; using System.Reflection; using Type = System.Type; using Delegate = System.Delegate; namespace UnityEditor.VFX.UI { static class VFXGizmoUtility { static Dictionary s_DrawFunctions; internal class Property : VFXGizmo.IProperty { public Property(IPropertyRMProvider controller, bool editable) { m_Controller = controller; m_Editable = editable; } IPropertyRMProvider m_Controller; bool m_Editable; public bool isEditable { get { return m_Editable; } } public void SetValue(T value) { if (m_Editable) m_Controller.value = value; } } internal class NullProperty : VFXGizmo.IProperty { public bool isEditable { get { return false; } } public void SetValue(T value) { } public static NullProperty defaultProperty = new NullProperty(); } public abstract class Context : VFXGizmo.IContext { public abstract Type portType { get; } bool m_Prepared; public void Unprepare() { m_Prepared = false; } public bool Prepare() { if (m_Prepared) return false; m_Prepared = true; m_Error = GizmoError.None; m_PropertyCache.Clear(); InternalPrepare(); return true; } protected abstract void InternalPrepare(); public const string separator = "."; public abstract object value { get; } public abstract VFXSpace space { get; } protected Dictionary m_PropertyCache = new Dictionary(); public abstract VFXGizmo.IProperty RegisterProperty(string member); protected GizmoError m_Error; public GizmoError GetError() { return m_Error; } public bool IsIndeterminate() { return m_Error != GizmoError.None; } } static VFXGizmoUtility() { s_DrawFunctions = new Dictionary(); foreach (Type type in typeof(VFXGizmoUtility).Assembly.GetTypes()) // TODO put all user assemblies instead { var attributes = type.GetCustomAttributes(false); if (attributes != null) { var gizmoAttribute = attributes.OfType().FirstOrDefault(); if (gizmoAttribute != null) { s_DrawFunctions[gizmoAttribute.type] = new GizmoContext() { gizmo = (VFXGizmo)System.Activator.CreateInstance(type) }; } } } } public static bool HasGizmo(Type type) { if (type == null) return false; return s_DrawFunctions.ContainsKey(type); } public static VFXGizmo CreateGizmoInstance(Context context) { GizmoContext gizmo; if (s_DrawFunctions.TryGetValue(context.portType, out gizmo)) { return (VFXGizmo)System.Activator.CreateInstance(gizmo.gizmo.GetType()); } return null; } struct GizmoContext { public Context lastContext; public VFXGizmo gizmo; } static internal void Draw(Context context, VisualEffect component) { GizmoContext gizmo; if (s_DrawFunctions.TryGetValue(context.portType, out gizmo)) { bool forceRegister = false; if (gizmo.lastContext != context) { forceRegister = true; s_DrawFunctions[context.portType] = new GizmoContext() { gizmo = gizmo.gizmo, lastContext = context }; } Draw(context, component, gizmo.gizmo, forceRegister); } } static internal GizmoError CollectGizmoError(Context context, VisualEffect component) { var error = context.GetError(); GizmoContext gizmo; if (s_DrawFunctions.TryGetValue(context.portType, out gizmo)) { gizmo.gizmo.currentSpace = context.space; gizmo.gizmo.component = component; error |= gizmo.gizmo.error; gizmo.gizmo.component = null; } return error; } static internal Bounds GetGizmoBounds(Context context, VisualEffect component) { GizmoContext gizmo; if (s_DrawFunctions.TryGetValue(context.portType, out gizmo)) { bool forceRegister = false; if (gizmo.lastContext != context) { forceRegister = true; s_DrawFunctions[context.portType] = new GizmoContext() { gizmo = gizmo.gizmo, lastContext = context }; } return GetGizmoBounds(context, component, gizmo.gizmo, forceRegister); } return new Bounds(); } static internal Bounds GetGizmoBounds(Context context, VisualEffect component, VFXGizmo gizmo, bool forceRegister = false) { if (context.Prepare() || forceRegister) { gizmo.RegisterEditableMembers(context); } if (!context.IsIndeterminate()) { gizmo.component = component; gizmo.currentSpace = context.space; Bounds bounds = gizmo.CallGetGizmoBounds(context.value); gizmo.component = null; return bounds; } return new Bounds(); } static internal void Draw(Context context, VisualEffect component, VFXGizmo gizmo, bool forceRegister = false) { if (context.Prepare() || forceRegister) { gizmo.RegisterEditableMembers(context); } if (!context.IsIndeterminate()) { gizmo.component = component; gizmo.currentSpace = context.space; gizmo.currentHashCode = context.GetHashCode(); gizmo.CallDrawGizmo(context.value); gizmo.component = null; } } } }