Add component button

This commit is contained in:
max 2024-11-13 21:11:50 +01:00
parent 87ee6df46f
commit cf6cd080c6
2 changed files with 57 additions and 25 deletions

View File

@ -33,6 +33,36 @@ private void DrawEntityComponents(Entity entity)
{ {
World.ComponentTypeEnumerator componentTypes = World.Debug_GetAllComponentTypes(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<Type> 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<World, Entity> componentSetter))
{
componentSetter.Invoke(World, entity);
}
}
}
ImGui.EndPopup();
}
ImGui.Dummy(new Vector2(16, 16));
ImGui.Text("ComponentInspectorByType"); ImGui.Text("ComponentInspectorByType");
foreach (Type componentType in componentTypes) foreach (Type componentType in componentTypes)
{ {
@ -40,6 +70,11 @@ private void DrawEntityComponents(Entity entity)
{ {
componentInspector(World, entity); componentInspector(World, entity);
} }
else if (ComponentHelper.GetComponentByType.TryGetValue(componentType, out Func<World, Entity, ValueType> componentGetter))
{
ValueType component = componentGetter.Invoke(World, entity);
ImGui.Text(component.ToString());
}
else else
{ {
ImGui.Text(componentType.Name); ImGui.Text(componentType.Name);
@ -47,32 +82,18 @@ private void DrawEntityComponents(Entity entity)
ImGui.Separator(); ImGui.Separator();
} }
ImGui.Dummy(new Vector2(16, 16));
ImGui.Text("GetComponentByType");
foreach (Type componentType in componentTypes)
{
if (!ComponentHelper.GetComponentByType.TryGetValue(componentType, out Func<World, Entity, ValueType> componentGetter)) continue;
ValueType component = componentGetter.Invoke(World, entity);
ImGui.Text(component.ToString());
ImGui.Separator();
}
ImGui.Dummy(new Vector2(16, 16)); ImGui.Dummy(new Vector2(16, 16));
ImGui.Text("Reflection"); // ImGui.Text("Reflection");
// TODO: explore something without reflection. // foreach (Type component in componentTypes)
// Maybe generate some look up dictionary<type, Action<world, entity>> for 'custom editors'. // {
// Look into serializing of entities and components. // System.Reflection.MethodInfo getMethodInfo = typeof(World).GetMethod("Get");
foreach (Type component in componentTypes) // System.Reflection.MethodInfo getComponentMethod = getMethodInfo.MakeGenericMethod(component);
{ // object result = getComponentMethod.Invoke(World, [entity]);
System.Reflection.MethodInfo getMethodInfo = typeof(World).GetMethod("Get"); //
System.Reflection.MethodInfo getComponentMethod = getMethodInfo.MakeGenericMethod(component); // // process here
object result = getComponentMethod.Invoke(World, [entity]); // ImGui.Text(result.ToString());
// }
// process here
ImGui.Text(result.ToString());
}
} }
} }
} }

View File

@ -7,18 +7,29 @@ namespace Nerfed.Runtime.Serialization;
public static class ComponentHelper public static class ComponentHelper
{ {
// Auto generate this.
public static readonly Dictionary<Type, Func<World, Entity, ValueType>> GetComponentByType = new() public static readonly Dictionary<Type, Func<World, Entity, ValueType>> GetComponentByType = new()
{ {
{ typeof(LocalTransform), (world, entity) => world.Get<LocalTransform>(entity) }, { typeof(LocalTransform), (world, entity) => world.Get<LocalTransform>(entity) },
{ typeof(Root), (world, entity) => world.Get<Root>(entity) }, { typeof(Root), (world, entity) => world.Get<Root>(entity) },
}; };
// Auto generate this.
public static readonly Dictionary<Type, Action<World, Entity, ValueType>> SetComponentByType = new() public static readonly Dictionary<Type, Action<World, Entity, ValueType>> SetComponentByType = new()
{ {
{ typeof(LocalTransform), (world, entity, component) => world.Set(entity, (LocalTransform)component) }, { typeof(LocalTransform), (world, entity, component) => world.Set(entity, (LocalTransform)component) },
{ typeof(Root), (world, entity, component) => world.Set(entity, (Root)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<Type, Action<World, Entity>> 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<Type, Action<World, Entity>> ComponentInspectorByType = new() public static readonly Dictionary<Type, Action<World, Entity>> ComponentInspectorByType = new()
{ {
{ {
@ -31,7 +42,7 @@ public static class ComponentHelper
ImGui.BeginGroup(); ImGui.BeginGroup();
ImGui.Text($"{nameof(LocalTransform)}"); 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("Rotation", ref eulerAngles);
isDirty |= ImGui.DragFloat3("Scale", ref scale); isDirty |= ImGui.DragFloat3("Scale", ref scale);
ImGui.EndGroup(); ImGui.EndGroup();