Skip to content

Commit

Permalink
Added Default EngineObject PropertyDrawer
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsakharov committed Apr 4, 2024
1 parent 136f422 commit 3993f8a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 39 deletions.
110 changes: 72 additions & 38 deletions Prowl.Editor/Drawers/PropertyDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Hexa.NET.ImGui;
using Prowl.Editor.ImGUI.Widgets;
using Prowl.Editor.Utilities;
using Prowl.Runtime;
using System.Reflection;
using System.Text;
namespace Prowl.Editor.PropertyDrawers;

public abstract class PropertyDrawer {
Expand All @@ -12,6 +12,33 @@ public abstract class PropertyDrawer {
protected internal abstract bool Draw_Internal(string label, ref object value, float width);


public static void ClearLookUp()
{
_propertyDrawerLookup.Clear();
}

public static void GenerateLookUp()
{
_propertyDrawerLookup.Clear();
foreach (Assembly editorAssembly in EditorApplication.Instance.ExternalAssemblies.Append(typeof(EditorApplication).Assembly))
{
List<Type> derivedTypes = EditorUtils.GetDerivedTypes(typeof(PropertyDrawer<>), editorAssembly);
foreach (Type type in derivedTypes)
{
try
{
PropertyDrawer propertyDrawer = Activator.CreateInstance(type) as PropertyDrawer ?? throw new NullReferenceException();
if (!_propertyDrawerLookup.TryAdd(propertyDrawer.PropertyType, propertyDrawer))
Debug.LogWarning($"Failed to register property drawer for {type.ToString()}");
}
catch
{
Debug.LogWarning($"Failed to register property drawer for {type.ToString()}");
}
}
}
}

public static bool Draw(object container, FieldInfo fieldInfo, float width = -1, string? label = null)
{
if (fieldInfo == null) return false;
Expand All @@ -24,14 +51,17 @@ public static bool Draw(object container, FieldInfo fieldInfo, float width = -1,
EditorGui.HandleBeginImGUIAttributes(imGuiAttributes);
if (width == -1) width = ImGui.GetContentRegionAvail().X;

if (fieldInfo.FieldType.IsAssignableTo(typeof(EngineObject)))
return DrawEngineObjectField(container, label ?? fieldInfo.Name, fieldInfo, ref width);

var value = fieldInfo.GetValue(container);
if (value == null)
{
CreateInstanceButton(label ?? fieldInfo.Name, width);
DrawNullField(label ?? fieldInfo.Name, width);
return false;
}

bool changed = Draw(label ?? fieldInfo.Name, ref value, width);
bool changed = Draw(label ?? fieldInfo.Name, ref value, fieldInfo.FieldType, width);
if (changed) fieldInfo.SetValue(container, value);

EditorGui.HandleEndImGUIAttributes(imGuiAttributes);
Expand All @@ -46,29 +76,18 @@ public static bool Draw(object container, PropertyInfo propertyInfo, float width
var value = propertyInfo.GetValue(container);
if (value == null)
{
CreateInstanceButton(label ?? propertyInfo.Name, width);
DrawNullField(label ?? propertyInfo.Name, width);
return false;
}

bool changed = Draw(label ?? propertyInfo.Name, ref value, width);
bool changed = Draw(label ?? propertyInfo.Name, ref value, propertyInfo.PropertyType, width);
if (changed) propertyInfo.SetValue(container, value);
return changed;
}

private static void CreateInstanceButton(string name, float width)
{
float w = width;
DrawLabel(name, ref w);
ImGui.SetNextItemWidth(width);
ImGui.TextDisabled("null");
ImGui.Columns(1);
}

public static bool Draw(string label, ref object value, float width = -1)
protected static bool Draw(string label, ref object value, Type objType, float width = -1)
{
if (value == null) return false;
if (width == -1) width = ImGui.GetContentRegionAvail().X;
var objType = value.GetType();
bool changed = false;
ImGui.PushID(label);
PropertyDrawer? propertyDrawer;
Expand Down Expand Up @@ -115,33 +134,48 @@ public static bool Draw(string label, ref object value, float width = -1)
ImGui.PopID();
return changed;
}

public static void ClearLookUp() {
_propertyDrawerLookup.Clear();
}

public static void GenerateLookUp()
protected static bool DrawEngineObjectField(object container, string label, FieldInfo field, ref float width)
{
_propertyDrawerLookup.Clear();
foreach (Assembly editorAssembly in EditorApplication.Instance.ExternalAssemblies.Append(typeof(EditorApplication).Assembly))
bool changed = false;
DrawLabel(label, ref width);

EngineObject value = (EngineObject)field.GetValue(container);
if (value == null)
{
List<Type> derivedTypes = EditorUtils.GetDerivedTypes(typeof(PropertyDrawer<>), editorAssembly);
foreach (Type type in derivedTypes)
{
try
{
PropertyDrawer propertyDrawer = Activator.CreateInstance(type) as PropertyDrawer ?? throw new NullReferenceException();
if (!_propertyDrawerLookup.TryAdd(propertyDrawer.PropertyType, propertyDrawer))
Debug.LogWarning($"Failed to register property drawer for {type.ToString()}");
}
catch
{
Debug.LogWarning($"Failed to register property drawer for {type.ToString()}");
}
}
var pos = ImGui.GetCursorPos();
ImGui.TextDisabled("null");
ImGui.SetCursorPos(pos);
ImGui.Selectable("##null", new System.Numerics.Vector2(width, 21));
GUIHelper.ItemRectFilled(0.9f, 0.1f, 0.1f, 0.3f);
}
else
{
ImGui.Selectable(value.Name, new System.Numerics.Vector2(width, 21));
GUIHelper.ItemRectFilled(0.1f, 0.1f, 0.9f, 0.3f);

if (ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(ImGuiMouseButton.Left))
GlobalSelectHandler.Select(value);
}

// Drag and drop support
if (DragnDrop.Drop(out var instance, field.FieldType))
{
field.SetValue(container, instance);
changed = true;
}
ImGui.Columns(1);
return changed;
}

private static void DrawNullField(string name, float width)
{
float w = width;
DrawLabel(name, ref w);
ImGui.SetNextItemWidth(width);
ImGui.TextDisabled("null");
ImGui.Columns(1);
}

protected static void DrawLabel(string label, ref float width)
{
Expand Down
5 changes: 4 additions & 1 deletion Prowl.Editor/Drawers/PropertyDrawerOrderable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Prowl.Editor.PropertyDrawers;

public abstract class PropertyDrawerOrderable<T> : PropertyDrawer<T> where T : class
{
protected abstract Type ElementType(T value);
protected abstract int GetCount(T value);
protected abstract object GetElement(T value, int index);
protected abstract void SetElement(T value, int index, object element);
Expand Down Expand Up @@ -56,7 +57,7 @@ protected override bool Draw(string label, ref T? value, float width)
ImGui.SameLine();
ImGui.Indent(28);

if (PropertyDrawer.Draw($"Element {i}", ref element, width))
if (PropertyDrawer.Draw($"Element {i}", ref element, ElementType(value), width))
{
SetElement(value, i, element);
changed = true;
Expand Down Expand Up @@ -104,6 +105,7 @@ protected override bool Draw(string label, ref T? value, float width)

public class PropertyDrawerArray : PropertyDrawerOrderable<Array>
{
protected override Type ElementType(Array value) => value.GetType().GetElementType();
protected override int GetCount(Array value) => value.Length;
protected override object GetElement(Array value, int index) => value.GetValue(index);
protected override void SetElement(Array value, int index, object element) => value.SetValue(element, index);
Expand All @@ -126,6 +128,7 @@ protected override void AddElement(ref Array value)

public class PropertyDrawerList : PropertyDrawerOrderable<System.Collections.IList>
{
protected override Type ElementType(System.Collections.IList value) => value.GetType().GetGenericArguments()[0];
protected override int GetCount(System.Collections.IList value) => value.Count;
protected override object GetElement(System.Collections.IList value, int index) => value[index];
protected override void SetElement(System.Collections.IList value, int index, object element) => value[index] = element;
Expand Down

0 comments on commit 3993f8a

Please sign in to comment.