Move List elements via Drag and Drop

This commit is contained in:
Simon Lübeß
2023-11-22 19:28:02 +01:00
parent 872a400966
commit 0257b93c7b
2 changed files with 113 additions and 46 deletions
+83 -9
View File
@@ -36,6 +36,8 @@ internal class EntityEditor
public static void ShowDefaultEntityEditor(UUID entityId, Type entityType) public static void ShowDefaultEntityEditor(UUID entityId, Type entityType)
{ {
// TODO: Call custom editors here!
ScriptGlue.Entity_GetScriptInstance(entityId, out object instance); ScriptGlue.Entity_GetScriptInstance(entityId, out object instance);
ShowEditor(entityType, instance); ShowEditor(entityType, instance);
@@ -69,16 +71,17 @@ internal class EntityEditor
RangeAttribute range = GetAttribute<RangeAttribute>(attributes); RangeAttribute range = GetAttribute<RangeAttribute>(attributes);
// Get Min and Max Values from Type T
T min = ReadStaticField<T>("MinValue"); T min = ReadStaticField<T>("MinValue");
T max = ReadStaticField<T>("MaxValue"); T max = ReadStaticField<T>("MaxValue");
float speed = 1.0f; float dragSpeed = 1.0f;
// RangeAttribute takes precedence over Minimum- and Maximum-Attribute // RangeAttribute takes precedence over Minimum- and Maximum-Attribute
if (range != null) if (range != null)
{ {
min = ChangeTypeSafe(range.Min); min = ChangeTypeSafe(range.Min);
max = ChangeTypeSafe(range.Max); max = ChangeTypeSafe(range.Max);
speed = range.Speed; dragSpeed = range.Speed;
} }
else else
{ {
@@ -112,7 +115,7 @@ internal class EntityEditor
} }
else else
{ {
if (ImGui.DragScalar(fieldName, dataType, (IntPtr)(&value), speed, (IntPtr)(&min), (IntPtr)(&max))) if (ImGui.DragScalar(fieldName, dataType, (IntPtr)(&value), dragSpeed, (IntPtr)(&min), (IntPtr)(&max)))
{ {
newValue = value; newValue = value;
} }
@@ -134,6 +137,7 @@ internal class EntityEditor
{ {
char value = (char)reference; char value = (char)reference;
// TODO: Allow entering chars like '\0', '\n', etc...
if (ImGui.InputText(fieldName, (IntPtr)(&value), 2)) if (ImGui.InputText(fieldName, (IntPtr)(&value), 2))
newValue = value; newValue = value;
} }
@@ -359,6 +363,12 @@ internal class EntityEditor
} }
} }
struct ListPayload
{
public IList List;
public int Element;
}
private static object ShowListEditor(Type fieldType, object list, string fieldName) private static object ShowListEditor(Type fieldType, object list, string fieldName)
{ {
object newList = DidNotChange; object newList = DidNotChange;
@@ -389,33 +399,97 @@ internal class EntityEditor
myList.Add(newElement); myList.Add(newElement);
} }
ImGui.SetTooltip("Add a new Element at the end of the list."); ImGuiExtension.AttachTooltip("Add a new Element at the end of the list.");
ImGui.SameLine(ImGui.GetWindowContentRegionMax().X - removeButtonWidth); ImGui.SameLine(ImGui.GetWindowContentRegionMax().X - removeButtonWidth);
ImGui.BeginDisabled(myList == null); ImGui.BeginDisabled(myList == null || myList.Count == 0);
if (ImGui.SmallButton("-")) if (ImGui.SmallButton("-"))
{ {
myList!.RemoveAt(myList.Count - 1); myList!.RemoveAt(myList.Count - 1);
} }
ImGuiExtension.AttachTooltip("Remove the last Element from the list.");
ImGui.EndDisabled(); ImGui.EndDisabled();
ImGui.SetTooltip("Remove the last Element from the list.");
if (listOpen) if (listOpen && myList != null)
{ {
for (int i = 0; i < myList?.Count; i++) void DropTarget(int insertIndex, string tooltip)
{
if (ImGui.BeginDragDropTarget())
{
ImGui.SetTooltip(tooltip);
var payloadPtr = ImGui.AcceptDragDropPayload("SCRIPT_EDITOR_LIST_ELEMENT");
unsafe
{
if (payloadPtr.NativePtr != null)
{
ListPayload payload = *(ListPayload*)(payloadPtr.Data);
// Make sure the index is still correct
if (payload.Element < myList.Count)
{
object item = myList[payload.Element];
myList.RemoveAt(payload.Element);
if (payload.Element >= insertIndex)
myList.Insert(insertIndex, item);
else
// If the original index is before the insert index, the insert index will be moved after removing the element
// thus we have to subtract one.
myList.Insert(insertIndex - 1, item);
}
}
}
ImGui.EndDragDropTarget();
}
}
// Drop at index 0
ImGui.Separator();
DropTarget(0, "Drop before Element 0.");
for (int i = 0; i < myList.Count; i++)
{ {
object element = myList[i]; object element = myList[i];
object newValue = ShowFieldEditor(element, element.GetType(), $"Element {i}"); // A Bullet point to grab the element
ImGui.Bullet();
if (ImGui.BeginDragDropSource(ImGuiDragDropFlags.SourceAllowNullID))
{
unsafe
{
ListPayload payload = new() { List = myList, Element = i };
ImGui.SetDragDropPayload("SCRIPT_EDITOR_LIST_ELEMENT", (IntPtr)(&payload), (uint)sizeof(ListPayload));
}
ImGui.SetTooltip($"Move Element {i}");
ImGui.EndDragDropSource();
}
DropTarget(i, $"Drop before Element {i}.");
ImGui.SameLine();
object newValue = ShowFieldEditor(element, element.GetType(), $"Element {i}");
if (newValue != DidNotChange) if (newValue != DidNotChange)
{ {
myList[i] = newValue; myList[i] = newValue;
} }
// Drop after current element
ImGui.Separator();
DropTarget(i + 1, $"Drop after Element {i}.");
} }
ImGui.TreePop(); ImGui.TreePop();
+30 -37
View File
@@ -34,43 +34,36 @@ public static class ImGuiDataTypeExtension
} }
} }
//namespace ImGuiNET; public static class ImGuiExtension
{
/// <summary>
/// A helper function to attach a tooltip to the previous item. It automatically checks IsItemHovered before showing a tooltip with the given text.
/// </summary>
/// <param name="tooltip">The text to be displayed in the tooltip.</param>
public static void AttachTooltip(string tooltip)
{
if (!ImGui.IsItemHovered())
return;
//public static unsafe partial class ImGui ImGui.BeginTooltip();
//{
// [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] ImGui.TextUnformatted(tooltip);
// private static extern unsafe bool ImGui_EditFloat2(byte* label, ref float2 value, float2 resetValues, float dragSpeed, float columnWidth, float2 minValue, float2 maxValue, bool2 componentEnabled);
ImGui.EndTooltip();
}
/// <summary>
/// A helper function to attach a tooltip to the previous item. It automatically checks IsItemHovered before showing a tooltip with the given content.
/// </summary>
/// <param name="tooltipContent">A method that will be called to show the content of the tooltip.</param>
public static void AttachTooltip(Action tooltipContent)
{
if (!ImGui.IsItemHovered())
return;
// public static bool EditFloat2(string label, ref float2 value, float2 resetValues = default, float dragSpeed = 0.1f, ImGui.BeginTooltip();
// float columnWidth = 100f, float2 minValue = default, float2 maxValue = default)
// {
// byte* native_label;
// int label_byteCount = 0;
// if (label != null)
// {
// label_byteCount = Encoding.UTF8.GetByteCount(label);
// if (label_byteCount > Util.StackAllocationSizeLimit)
// {
// native_label = Util.Allocate(label_byteCount + 1);
// }
// else
// {
// byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1];
// native_label = native_label_stackBytes;
// }
// int native_label_offset = Util.GetUtf8(label, native_label, label_byteCount);
// native_label[native_label_offset] = 0;
// }
// else { native_label = null; }
// return ImGui_EditFloat2(native_label, ref value, resetValues, dragSpeed, columnWidth, minValue, maxValue, true); tooltipContent();
// }
ImGui.EndTooltip();
// public static bool EditFloat2(string label, ref float2 value, float2 resetValues, float dragSpeed, }
// float columnWidth, float2 minValue, float2 maxValue, bool2 componentEnabled) }
// {
// return ImGui_EditFloat2(label, ref value, resetValues, dragSpeed, columnWidth, minValue, maxValue, true);
// }
// //ImGui_EditFloat2(char8* label, ref float2 value, float2 resetValues = .Zero, float dragSpeed = 0.1f, float columnWidth = 100f, float2 minValue = .Zero, float2 maxValue = .Zero, bool2 componentEnabled = true)
//}