Compare commits
No commits in common. "5eaf3547dcf56630d5a4088a4c2f42971cbbee41" and "57b42d8daace146bacd125ff9d06bdf34fdfd568" have entirely different histories.
5eaf3547dc
...
57b42d8daa
@ -4,7 +4,6 @@
|
|||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/FAudio" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/FAudio" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/ImGui.NET" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/ImGui.NET" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/MoonTools.ECS" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/RefreshCS" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/RefreshCS" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/SDL2CS" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/SDL2CS" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/WellspringCS" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/WellspringCS" vcs="Git" />
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
using System.Numerics;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using MoonTools.ECS;
|
using MoonTools.ECS;
|
||||||
using Nerfed.Editor.Components;
|
using Nerfed.Editor.Components;
|
||||||
using Nerfed.Runtime.Serialization;
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
namespace Nerfed.Editor.Systems
|
namespace Nerfed.Editor.Systems
|
||||||
@ -31,69 +29,27 @@ public override void Update(TimeSpan delta)
|
|||||||
|
|
||||||
private void DrawEntityComponents(Entity entity)
|
private void DrawEntityComponents(Entity entity)
|
||||||
{
|
{
|
||||||
World.ComponentTypeEnumerator componentTypes = World.Debug_GetAllComponentTypes(entity);
|
World.ComponentTypeEnumerator components = World.Debug_GetAllComponentTypes(entity);
|
||||||
|
|
||||||
// Add button of all types that we can add. Also filter out types we already have.
|
foreach (Type type in components)
|
||||||
List<Type> componentTypesToAdd = ComponentHelper.AddComponentByType.Keys.ToList();
|
|
||||||
foreach (Type componentType in componentTypes)
|
|
||||||
{
|
{
|
||||||
componentTypesToAdd.Remove(componentType);
|
ImGui.Text(type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string popupId = "AddComponentPopup";
|
ImGui.Separator();
|
||||||
if (ImGui.Button("Add Component"))
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
ImGui.OpenPopup(popupId);
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
|
||||||
foreach (Type componentType in componentTypes)
|
|
||||||
{
|
|
||||||
if (ComponentHelper.ComponentInspectorByType.TryGetValue(componentType, out Action<World, Entity> componentInspector))
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
ImGui.Text(componentType.Name);
|
|
||||||
}
|
|
||||||
ImGui.Separator();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.Dummy(new Vector2(16, 16));
|
|
||||||
|
|
||||||
// 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());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@ namespace Nerfed.Runtime.Components
|
|||||||
{
|
{
|
||||||
public readonly record struct LocalTransform(Vector3 position, Quaternion rotation, Vector3 scale)
|
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);
|
public static readonly LocalTransform Identity = new(Vector3.Zero, Quaternion.Identity, Vector3.One);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,68 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
using ImGuiNET;
|
|
||||||
using MoonTools.ECS;
|
|
||||||
using Nerfed.Runtime.Components;
|
|
||||||
|
|
||||||
namespace Nerfed.Runtime.Serialization;
|
|
||||||
|
|
||||||
public static class ComponentHelper
|
|
||||||
{
|
|
||||||
// Auto generate this.
|
|
||||||
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) },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Auto generate this.
|
|
||||||
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) },
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
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,5 +1,3 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Nerfed.Runtime;
|
namespace Nerfed.Runtime;
|
||||||
|
|
||||||
public static class MathEx
|
public static class MathEx
|
||||||
@ -19,51 +17,4 @@ public static float Denormalize(float value, float newMin, float newMax) {
|
|||||||
public static float Remap(float value, float oldMin, float oldMax, float newMin, float newMax) {
|
public static float Remap(float value, float oldMin, float oldMax, float newMin, float newMax) {
|
||||||
return (value - oldMin) / (oldMax - oldMin) * (newMax - newMin) + newMin;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,13 +0,0 @@
|
|||||||
using System.Security.Cryptography;
|
|
||||||
|
|
||||||
namespace Nerfed.Runtime.Util;
|
|
||||||
|
|
||||||
public static class RandomId
|
|
||||||
{
|
|
||||||
public static uint GenerateSecureRandomUInt()
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[4];
|
|
||||||
RandomNumberGenerator.Fill(buffer);
|
|
||||||
return BitConverter.ToUInt32(buffer, 0);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user