diff --git a/Nerfed.Editor/Systems/EditorInspectorWindow.cs b/Nerfed.Editor/Systems/EditorInspectorWindow.cs index 5451031..ffcca33 100644 --- a/Nerfed.Editor/Systems/EditorInspectorWindow.cs +++ b/Nerfed.Editor/Systems/EditorInspectorWindow.cs @@ -33,6 +33,36 @@ private void DrawEntityComponents(Entity entity) { World.ComponentTypeEnumerator componentTypes = World.Debug_GetAllComponentTypes(entity); + // Add button of all types that we can add. Also filter out types we already have. + List componentTypesToAdd = ComponentHelper.AddComponentByType.Keys.ToList(); + foreach (Type componentType in componentTypes) + { + componentTypesToAdd.Remove(componentType); + } + + const string popupId = "AddComponentPopup"; + if (ImGui.Button("Add Component")) + { + ImGui.OpenPopup(popupId); + } + + if (ImGui.BeginPopup(popupId)) + { + foreach (Type componentType in componentTypesToAdd) + { + if (ImGui.Selectable(componentType.Name)) + { + if (ComponentHelper.AddComponentByType.TryGetValue(componentType, out Action componentSetter)) + { + componentSetter.Invoke(World, entity); + } + } + } + ImGui.EndPopup(); + } + + ImGui.Dummy(new Vector2(16, 16)); + ImGui.Text("ComponentInspectorByType"); foreach (Type componentType in componentTypes) { @@ -40,6 +70,11 @@ private void DrawEntityComponents(Entity entity) { componentInspector(World, entity); } + else if (ComponentHelper.GetComponentByType.TryGetValue(componentType, out Func componentGetter)) + { + ValueType component = componentGetter.Invoke(World, entity); + ImGui.Text(component.ToString()); + } else { ImGui.Text(componentType.Name); @@ -47,32 +82,18 @@ private void DrawEntityComponents(Entity entity) ImGui.Separator(); } - ImGui.Dummy(new Vector2(16, 16)); - - ImGui.Text("GetComponentByType"); - foreach (Type componentType in componentTypes) - { - if (!ComponentHelper.GetComponentByType.TryGetValue(componentType, out Func componentGetter)) continue; - ValueType component = componentGetter.Invoke(World, entity); - ImGui.Text(component.ToString()); - ImGui.Separator(); - } - ImGui.Dummy(new Vector2(16, 16)); - ImGui.Text("Reflection"); - // TODO: explore something without reflection. - // Maybe generate some look up dictionary> for 'custom editors'. - // Look into serializing of entities and components. - foreach (Type component in componentTypes) - { - System.Reflection.MethodInfo getMethodInfo = typeof(World).GetMethod("Get"); - System.Reflection.MethodInfo getComponentMethod = getMethodInfo.MakeGenericMethod(component); - object result = getComponentMethod.Invoke(World, [entity]); - - // process here - ImGui.Text(result.ToString()); - } + // ImGui.Text("Reflection"); + // foreach (Type component in componentTypes) + // { + // System.Reflection.MethodInfo getMethodInfo = typeof(World).GetMethod("Get"); + // System.Reflection.MethodInfo getComponentMethod = getMethodInfo.MakeGenericMethod(component); + // object result = getComponentMethod.Invoke(World, [entity]); + // + // // process here + // ImGui.Text(result.ToString()); + // } } } } diff --git a/Nerfed.Runtime/Serialization/ComponentHelper.cs b/Nerfed.Runtime/Serialization/ComponentHelper.cs index c6349f7..12398ca 100644 --- a/Nerfed.Runtime/Serialization/ComponentHelper.cs +++ b/Nerfed.Runtime/Serialization/ComponentHelper.cs @@ -7,18 +7,29 @@ namespace Nerfed.Runtime.Serialization; public static class ComponentHelper { + // Auto generate this. public static readonly Dictionary> GetComponentByType = new() { { typeof(LocalTransform), (world, entity) => world.Get(entity) }, { typeof(Root), (world, entity) => world.Get(entity) }, }; + // Auto generate this. public static readonly Dictionary> SetComponentByType = new() { { typeof(LocalTransform), (world, entity, component) => world.Set(entity, (LocalTransform)component) }, { typeof(Root), (world, entity, component) => world.Set(entity, (Root)component) }, }; + + // Auto generate this, but it should only contain user assignable components (so something like 'root' should be excluded). + // Maybe use an attribute for this. + public static readonly Dictionary> AddComponentByType = new() + { + { typeof(LocalTransform), (world, entity) => world.Set(entity, LocalTransform.Identity) }, + }; + // Auto generate this, but also keep the option for 'custom inspectors'. + // Maybe via attribute? public static readonly Dictionary> ComponentInspectorByType = new() { { @@ -31,7 +42,7 @@ public static class ComponentHelper ImGui.BeginGroup(); ImGui.Text($"{nameof(LocalTransform)}"); - isDirty |= ImGui.DragFloat3("Position", ref position, 0.2f, float.MinValue, float.MaxValue, "%f0 m"); // TODO: right format. + isDirty |= ImGui.DragFloat3("Position", ref position, 0.2f, float.MinValue, float.MaxValue /*, "%f0 m" */); // TODO: right format. isDirty |= ImGui.DragFloat3("Rotation", ref eulerAngles); isDirty |= ImGui.DragFloat3("Scale", ref scale); ImGui.EndGroup();