2021-09-09 20:42:29 -04:00

243 lines
7.4 KiB
C#

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<System.Type, GizmoContext> s_DrawFunctions;
internal class Property<T> : VFXGizmo.IProperty<T>
{
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<T> : VFXGizmo.IProperty<T>
{
public bool isEditable
{
get { return false; }
}
public void SetValue(T value)
{
}
public static NullProperty<T> defaultProperty = new NullProperty<T>();
}
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<string, object> m_PropertyCache = new Dictionary<string, object>();
public abstract VFXGizmo.IProperty<T> RegisterProperty<T>(string member);
protected bool m_Indeterminate;
public bool IsIndeterminate()
{
return m_Indeterminate;
}
}
static VFXGizmoUtility()
{
s_DrawFunctions = new Dictionary<System.Type, GizmoContext>();
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<VFXGizmoAttribute>().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;
}
}
}
}