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_Indeterminate = false; m_PropertyCache.Clear(); InternalPrepare(); return true; } protected abstract void InternalPrepare(); public const string separator = "."; public abstract object value { get; } public abstract VFXCoordinateSpace space { get; } public virtual bool spaceLocalByDefault { get { return false; } } protected Dictionary m_PropertyCache = new Dictionary(); public abstract VFXGizmo.IProperty RegisterProperty(string member); protected bool m_Indeterminate; public bool IsIndeterminate() { return m_Indeterminate; } } 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) { return s_DrawFunctions.ContainsKey(type); } static Type GetGizmoType(Type type) { if (type.IsAbstract) return null; Type baseType = type.BaseType; while (baseType != null) { if (baseType.IsGenericType && !baseType.IsGenericTypeDefinition && baseType.GetGenericTypeDefinition() == typeof(VFXGizmo<>)) { return baseType.GetGenericArguments()[0]; } baseType = baseType.BaseType; } return null; } 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 bool NeedsComponent(Context context) { GizmoContext gizmo; if (s_DrawFunctions.TryGetValue(context.portType, out gizmo)) { gizmo.gizmo.currentSpace = context.space; gizmo.gizmo.spaceLocalByDefault = context.spaceLocalByDefault; return gizmo.gizmo.needsComponent; } return false; } 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; gizmo.spaceLocalByDefault = context.spaceLocalByDefault; 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.spaceLocalByDefault = context.spaceLocalByDefault; gizmo.CallDrawGizmo(context.value); gizmo.component = null; } } } }