Inspector tests
This commit is contained in:
		@@ -1,6 +1,8 @@
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using ImGuiNET;
 | 
			
		||||
using MoonTools.ECS;
 | 
			
		||||
using Nerfed.Editor.Components;
 | 
			
		||||
using Nerfed.Runtime.Serialization;
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
namespace Nerfed.Editor.Systems
 | 
			
		||||
@@ -29,19 +31,40 @@ namespace Nerfed.Editor.Systems
 | 
			
		||||
 | 
			
		||||
        private void DrawEntityComponents(Entity entity)
 | 
			
		||||
        {
 | 
			
		||||
            World.ComponentTypeEnumerator components = World.Debug_GetAllComponentTypes(entity);
 | 
			
		||||
 | 
			
		||||
            foreach (Type type in components)
 | 
			
		||||
            World.ComponentTypeEnumerator componentTypes = World.Debug_GetAllComponentTypes(entity);
 | 
			
		||||
            
 | 
			
		||||
            ImGui.Text("ComponentInspectorByType");
 | 
			
		||||
            foreach (Type componentType in componentTypes)
 | 
			
		||||
            {
 | 
			
		||||
                ImGui.Text(type.Name);
 | 
			
		||||
                if (ComponentHelper.ComponentInspectorByType.TryGetValue(componentType, out Action<World, Entity> componentInspector))
 | 
			
		||||
                {
 | 
			
		||||
                    componentInspector(World, entity);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui.Text(componentType.Name);
 | 
			
		||||
                }
 | 
			
		||||
                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.Separator();
 | 
			
		||||
 | 
			
		||||
            ImGui.Text("Reflection");
 | 
			
		||||
            // TODO: explore something without reflection.
 | 
			
		||||
            // Maybe generate some look up dictionary<type, Action<world, entity>> for 'custom editors'.
 | 
			
		||||
            // Look into serializing of entities and components.
 | 
			
		||||
            foreach (Type component in components)
 | 
			
		||||
            foreach (Type component in componentTypes)
 | 
			
		||||
            {
 | 
			
		||||
                System.Reflection.MethodInfo getMethodInfo = typeof(World).GetMethod("Get");
 | 
			
		||||
                System.Reflection.MethodInfo getComponentMethod = getMethodInfo.MakeGenericMethod(component);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,6 @@ namespace Nerfed.Runtime.Components
 | 
			
		||||
{
 | 
			
		||||
    public readonly record struct LocalTransform(Vector3 position, Quaternion rotation, Vector3 scale)
 | 
			
		||||
    {
 | 
			
		||||
        public readonly Vector3 position = position;
 | 
			
		||||
        public readonly Quaternion rotation = rotation;
 | 
			
		||||
        public readonly Vector3 scale = scale;
 | 
			
		||||
 | 
			
		||||
        public static readonly LocalTransform Identity = new(Vector3.Zero, Quaternion.Identity, Vector3.One);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								Nerfed.Runtime/Serialization/ComponentHelper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								Nerfed.Runtime/Serialization/ComponentHelper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using ImGuiNET;
 | 
			
		||||
using MoonTools.ECS;
 | 
			
		||||
using Nerfed.Runtime.Components;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Serialization;
 | 
			
		||||
 | 
			
		||||
public static class ComponentHelper
 | 
			
		||||
{
 | 
			
		||||
    public static readonly Dictionary<Type, Func<World, Entity, ValueType>> GetComponentByType = new()
 | 
			
		||||
    {
 | 
			
		||||
        { typeof(LocalTransform), (world, entity) => world.Get<LocalTransform>(entity) },
 | 
			
		||||
        { typeof(Root), (world, entity) => world.Get<Root>(entity) },
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    public static readonly Dictionary<Type, Action<World, Entity, ValueType>> SetComponentByType = new()
 | 
			
		||||
    {
 | 
			
		||||
        { typeof(LocalTransform), (world, entity, component) => world.Set(entity, (LocalTransform)component) },
 | 
			
		||||
        { typeof(Root), (world, entity, component) => world.Set(entity, (Root)component) },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public static readonly Dictionary<Type, Action<World, Entity>> ComponentInspectorByType = new()
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            typeof(LocalTransform), (world, entity) =>
 | 
			
		||||
            {
 | 
			
		||||
                (Vector3 position, Quaternion rotation, Vector3 scale) = world.Get<LocalTransform>(entity);
 | 
			
		||||
                Vector3 eulerAngles = MathEx.ToEulerAngles(rotation);
 | 
			
		||||
                eulerAngles = new Vector3(float.RadiansToDegrees(eulerAngles.X), float.RadiansToDegrees(eulerAngles.Y), float.RadiansToDegrees(eulerAngles.Z));
 | 
			
		||||
                bool isDirty = false;
 | 
			
		||||
                
 | 
			
		||||
                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("Rotation", ref eulerAngles);
 | 
			
		||||
                isDirty |= ImGui.DragFloat3("Scale", ref scale);
 | 
			
		||||
                ImGui.EndGroup();
 | 
			
		||||
 | 
			
		||||
                if (!isDirty)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                eulerAngles = new Vector3(float.DegreesToRadians(eulerAngles.X), float.DegreesToRadians(eulerAngles.Y), float.DegreesToRadians(eulerAngles.Z));
 | 
			
		||||
                world.Set(entity, new LocalTransform(position, MathEx.ToQuaternion(eulerAngles), scale));
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            typeof(Root), (world, entity) =>
 | 
			
		||||
            {
 | 
			
		||||
                ImGui.BeginGroup();
 | 
			
		||||
                ImGui.Text($"{nameof(Root)}");
 | 
			
		||||
                ImGui.EndGroup();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime;
 | 
			
		||||
 | 
			
		||||
public static class MathEx
 | 
			
		||||
@@ -17,4 +19,51 @@ public static class MathEx
 | 
			
		||||
    public static float Remap(float value, float oldMin, float oldMax, float newMin, float newMax) {
 | 
			
		||||
        return (value - oldMin) / (oldMax - oldMin) * (newMax - newMin) + newMin;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
    // https://stackoverflow.com/questions/70462758/c-sharp-how-to-convert-quaternions-to-euler-angles-xyz
 | 
			
		||||
    public static Quaternion ToQuaternion(Vector3 v)
 | 
			
		||||
    {
 | 
			
		||||
        float cy = (float)Math.Cos(v.Z * 0.5);
 | 
			
		||||
        float sy = (float)Math.Sin(v.Z * 0.5);
 | 
			
		||||
        float cp = (float)Math.Cos(v.Y * 0.5);
 | 
			
		||||
        float sp = (float)Math.Sin(v.Y * 0.5);
 | 
			
		||||
        float cr = (float)Math.Cos(v.X * 0.5);
 | 
			
		||||
        float sr = (float)Math.Sin(v.X * 0.5);
 | 
			
		||||
 | 
			
		||||
        return new Quaternion
 | 
			
		||||
        {
 | 
			
		||||
            W = (cr * cp * cy + sr * sp * sy),
 | 
			
		||||
            X = (sr * cp * cy - cr * sp * sy),
 | 
			
		||||
            Y = (cr * sp * cy + sr * cp * sy),
 | 
			
		||||
            Z = (cr * cp * sy - sr * sp * cy),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Vector3 ToEulerAngles(Quaternion q)
 | 
			
		||||
    {
 | 
			
		||||
        Vector3 angles = new();
 | 
			
		||||
 | 
			
		||||
        // roll / x
 | 
			
		||||
        double sinrCosp = 2 * (q.W * q.X + q.Y * q.Z);
 | 
			
		||||
        double cosrCosp = 1 - 2 * (q.X * q.X + q.Y * q.Y);
 | 
			
		||||
        angles.X = (float)Math.Atan2(sinrCosp, cosrCosp);
 | 
			
		||||
 | 
			
		||||
        // pitch / y
 | 
			
		||||
        double sinp = 2 * (q.W * q.Y - q.Z * q.X);
 | 
			
		||||
        if (Math.Abs(sinp) >= 1)
 | 
			
		||||
        {
 | 
			
		||||
            angles.Y = (float)Math.CopySign(Math.PI / 2, sinp);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            angles.Y = (float)Math.Asin(sinp);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // yaw / z
 | 
			
		||||
        double sinyCosp = 2 * (q.W * q.Z + q.X * q.Y);
 | 
			
		||||
        double cosyCosp = 1 - 2 * (q.Y * q.Y + q.Z * q.Z);
 | 
			
		||||
        angles.Z = (float)Math.Atan2(sinyCosp, cosyCosp);
 | 
			
		||||
 | 
			
		||||
        return angles;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user