mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Add / Remove Components
This commit is contained in:
@@ -2,6 +2,7 @@ using ImGui;
|
|||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
using System;
|
using System;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
namespace GlitchyEditor.EditWindows
|
namespace GlitchyEditor.EditWindows
|
||||||
{
|
{
|
||||||
@@ -13,9 +14,19 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
private EntityHierarchyWindow _entityHierarchyWindow;
|
private EntityHierarchyWindow _entityHierarchyWindow;
|
||||||
|
|
||||||
|
private List<(Type, ComponentAttribute attribute)> _componentTypes = new .() ~ delete _;
|
||||||
|
|
||||||
public this(EntityHierarchyWindow entityHierarchyWindow)
|
public this(EntityHierarchyWindow entityHierarchyWindow)
|
||||||
{
|
{
|
||||||
_entityHierarchyWindow = entityHierarchyWindow;
|
_entityHierarchyWindow = entityHierarchyWindow;
|
||||||
|
|
||||||
|
for (let type in Type.Types)
|
||||||
|
{
|
||||||
|
if (let componentAttribute = type.GetCustomAttribute<ComponentAttribute>())
|
||||||
|
{
|
||||||
|
_componentTypes.Add((type, componentAttribute));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void InternalShow()
|
protected override void InternalShow()
|
||||||
@@ -39,9 +50,56 @@ namespace GlitchyEditor.EditWindows
|
|||||||
private void ShowComponents(Entity entity)
|
private void ShowComponents(Entity entity)
|
||||||
{
|
{
|
||||||
ShowNameComponentEditor(entity);
|
ShowNameComponentEditor(entity);
|
||||||
ShowTransformComponentEditor(entity);
|
|
||||||
ShowCameraComponentEditor(entity);
|
ShowComponentEditor<TransformComponent>("Transform", entity, => ShowTransformComponentEditor);
|
||||||
ShowSpriteRendererComponentEditor(entity);
|
ShowComponentEditor<CameraComponent>("Camera", entity, => ShowCameraComponentEditor, => ShowComponentContextMenu<CameraComponent>);
|
||||||
|
ShowComponentEditor<SpriterRendererComponent>("Sprite Renderer", entity, => ShowSpriteRendererComponentEditor, => ShowComponentContextMenu<SpriterRendererComponent>);
|
||||||
|
|
||||||
|
ShowAddComponentButton(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ShowComponentContextMenu<TComponent>(Entity entity, TComponent* component) where TComponent: struct, new
|
||||||
|
{
|
||||||
|
if (ImGui.Selectable("Remove Component"))
|
||||||
|
entity.RemoveComponent<TComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ShowComponentEditor<TComponent>(String header, Entity entity, function void(Entity, TComponent*) showComponentEditor, function void(Entity, TComponent*) showComponentContextMenu = null) where TComponent: struct, new
|
||||||
|
{
|
||||||
|
if (!entity.HasComponent<TComponent>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
TComponent* component = entity.GetComponent<TComponent>();
|
||||||
|
|
||||||
|
ImGui.PushID(header);
|
||||||
|
|
||||||
|
bool nodeOpen = ImGui.TreeNodeEx(header.CStr(), .DefaultOpen | .AllowItemOverlap | .Framed);
|
||||||
|
|
||||||
|
if (showComponentContextMenu != null)
|
||||||
|
{
|
||||||
|
ImGui.SameLine(ImGui.GetWindowContentRegionMax().x - ImGui.CalcTextSize("...").x);
|
||||||
|
|
||||||
|
if (ImGui.SmallButton("..."))
|
||||||
|
{
|
||||||
|
ImGui.OpenPopup("component_popup");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginPopup("component_popup"))
|
||||||
|
{
|
||||||
|
showComponentContextMenu(entity, component);
|
||||||
|
|
||||||
|
ImGui.EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeOpen)
|
||||||
|
{
|
||||||
|
showComponentEditor(entity, component);
|
||||||
|
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ShowNameComponentEditor(Entity entity)
|
private static void ShowNameComponentEditor(Entity entity)
|
||||||
@@ -79,124 +137,25 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool Vector3Control(StringView label, ref Vector3 value, Vector3 resetValues = .Zero, float dragSpeed = 0.1f, float columnWidth = 100f)
|
private static void ShowTransformComponentEditor(Entity entity, TransformComponent* transform)
|
||||||
{
|
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
ImGui.PushID(label);
|
|
||||||
defer ImGui.PopID();
|
|
||||||
|
|
||||||
ImGui.Columns(2);
|
|
||||||
defer ImGui.Columns(1);
|
|
||||||
ImGui.SetColumnWidth(0, columnWidth);
|
|
||||||
|
|
||||||
ImGui.TextUnformatted(label);
|
|
||||||
|
|
||||||
ImGui.NextColumn();
|
|
||||||
|
|
||||||
ImGui.PushMultiItemsWidths(3, ImGui.CalcItemWidth());
|
|
||||||
ImGui.PushStyleVar(.ItemSpacing, ImGui.Vec2.Zero);
|
|
||||||
defer ImGui.PopStyleVar();
|
|
||||||
|
|
||||||
float lineHeight = ImGui.GetFont().FontSize + ImGui.GetStyle().FramePadding.y * 2.0f;
|
|
||||||
ImGui.Vec2 buttonSize = .(lineHeight + 3.0f, lineHeight);
|
|
||||||
|
|
||||||
ImGui.PushStyleColor(.Button, ImGui.Color(230, 25, 45).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(150, 25, 45).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonActive, ImGui.Color(230, 120, 130).Value);
|
|
||||||
|
|
||||||
if (ImGui.Button("X", buttonSize))
|
|
||||||
{
|
|
||||||
value.X = resetValues.X;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
if (ImGui.DragFloat("##X", &value.X, dragSpeed))
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
ImGui.PopItemWidth();
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
ImGui.PopStyleColor(3);
|
|
||||||
ImGui.PushStyleColor(.Button, ImGui.Color(50, 190, 15).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(50, 120, 15).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonActive, ImGui.Color(116, 190, 99).Value);
|
|
||||||
|
|
||||||
if (ImGui.Button("Y", buttonSize))
|
|
||||||
{
|
|
||||||
value.Y = resetValues.Y;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
if (ImGui.DragFloat("##Y", &value.Y, dragSpeed))
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
ImGui.PopItemWidth();
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
ImGui.PopStyleColor(3);
|
|
||||||
ImGui.PushStyleColor(.Button, ImGui.Color(55, 55, 230).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonHovered, ImGui.Color(55, 55, 150).Value);
|
|
||||||
ImGui.PushStyleColor(.ButtonActive, ImGui.Color(90, 90, 230).Value);
|
|
||||||
|
|
||||||
if (ImGui.Button("Z", buttonSize))
|
|
||||||
{
|
|
||||||
value.Z = resetValues.Z;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
if (ImGui.DragFloat("##Z", &value.Z, dragSpeed))
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
ImGui.PopItemWidth();
|
|
||||||
|
|
||||||
ImGui.PopStyleColor(3);
|
|
||||||
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ShowTransformComponentEditor(Entity entity)
|
|
||||||
{
|
|
||||||
if (!entity.HasComponent<TransformComponent>())
|
|
||||||
return;
|
|
||||||
|
|
||||||
var transform = entity.GetComponent<TransformComponent>();
|
|
||||||
|
|
||||||
if(ImGui.TreeNodeEx("Transform", .DefaultOpen))
|
|
||||||
{
|
{
|
||||||
Vector3 position = transform.Position;
|
Vector3 position = transform.Position;
|
||||||
if (Vector3Control("Position", ref position))
|
if (ImGui.EditVector3("Position", ref position))
|
||||||
transform.Position = position;
|
transform.Position = position;
|
||||||
|
|
||||||
Vector3 rotationEuler = MathHelper.ToDegrees(transform.EditorRotationEuler);
|
Vector3 rotationEuler = MathHelper.ToDegrees(transform.EditorRotationEuler);
|
||||||
if (Vector3Control("Rotation", ref rotationEuler))
|
if (ImGui.EditVector3("Rotation", ref rotationEuler))
|
||||||
transform.EditorRotationEuler = MathHelper.ToRadians(rotationEuler);
|
transform.EditorRotationEuler = MathHelper.ToRadians(rotationEuler);
|
||||||
|
|
||||||
Vector3 scale = transform.Scale;
|
Vector3 scale = transform.Scale;
|
||||||
if (Vector3Control("Scale", ref scale, .One))
|
if (ImGui.EditVector3("Scale", ref scale, .One))
|
||||||
transform.Scale = scale;
|
transform.Scale = scale;
|
||||||
|
|
||||||
ImGui.TreePop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String[] strings = new String[]("Orthographic", "Perspective", "Perspective (Infinite)") ~ delete _;
|
static String[] strings = new String[]("Orthographic", "Perspective", "Perspective (Infinite)") ~ delete _;
|
||||||
|
|
||||||
private static void ShowCameraComponentEditor(Entity entity)
|
private static void ShowCameraComponentEditor(Entity entity, CameraComponent* cameraComponent)
|
||||||
{
|
{
|
||||||
if (!entity.HasComponent<CameraComponent>())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(ImGui.TreeNodeEx("Camera", .DefaultOpen))
|
|
||||||
{
|
|
||||||
var cameraComponent = entity.GetComponent<CameraComponent>();
|
|
||||||
|
|
||||||
ImGui.Checkbox("Primary", &cameraComponent.Primary);
|
ImGui.Checkbox("Primary", &cameraComponent.Primary);
|
||||||
|
|
||||||
var camera = ref cameraComponent.Camera;
|
var camera = ref cameraComponent.Camera;
|
||||||
@@ -270,24 +229,60 @@ namespace GlitchyEditor.EditWindows
|
|||||||
if (ImGui.DragFloat("Aspect Ratio", &aspect, 0.1f))
|
if (ImGui.DragFloat("Aspect Ratio", &aspect, 0.1f))
|
||||||
camera.AspectRatio = aspect;
|
camera.AspectRatio = aspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.TreePop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ShowSpriteRendererComponentEditor(Entity entity)
|
private static void ShowSpriteRendererComponentEditor(Entity entity, SpriterRendererComponent* spriteRendererComponent)
|
||||||
{
|
{
|
||||||
if (!entity.HasComponent<SpriterRendererComponent>())
|
ImGui.ColorEdit4("Color", ref spriteRendererComponent.Color);
|
||||||
return;
|
}
|
||||||
|
|
||||||
var spriterRendererComponent = entity.GetComponent<SpriterRendererComponent>();
|
private static void ShowAddComponentButton(Entity entity)
|
||||||
|
|
||||||
if(ImGui.TreeNodeEx("Sprite Renderer", .DefaultOpen))
|
|
||||||
{
|
{
|
||||||
ImGui.ColorEdit4("Color", ref spriterRendererComponent.Color);
|
static char8[128] searchBuffer = .();
|
||||||
|
static StringView searchFilter = .();
|
||||||
|
|
||||||
ImGui.TreePop();
|
static float buttonWidth = 100;
|
||||||
|
|
||||||
|
ImGui.NewLine();
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.NewLine();
|
||||||
|
|
||||||
|
void ShowComponentButton<TComponent>(String name) where TComponent : struct, new
|
||||||
|
{
|
||||||
|
float textWidth = ImGui.CalcTextSize(name.CStr()).x;
|
||||||
|
buttonWidth = Math.Max(buttonWidth, textWidth + ImGui.GetStyle().FramePadding.x * 2);
|
||||||
|
|
||||||
|
if (name.Contains(searchFilter, true) && ImGui.Selectable(name))
|
||||||
|
{
|
||||||
|
if (!entity.HasComponent<TComponent>())
|
||||||
|
entity.AddComponent<TComponent>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float textWidth = ImGui.CalcTextSize("Add Component...").x;
|
||||||
|
buttonWidth = Math.Max(buttonWidth, textWidth + ImGui.GetStyle().FramePadding.x * 2);
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(buttonWidth);
|
||||||
|
|
||||||
|
ImGui.NewLine();
|
||||||
|
ImGui.SameLine(ImGui.GetContentRegionMax().x / 2 - buttonWidth / 2);
|
||||||
|
|
||||||
|
if (ImGui.BeginCombo("##add_component_combo", "Add Component...", .NoArrowButton))
|
||||||
|
{
|
||||||
|
if (ImGui.InputText("##search_component_name", &searchBuffer, (.)searchBuffer.Count))
|
||||||
|
{
|
||||||
|
searchFilter = .(&searchBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
ShowComponentButton<CameraComponent>("Camera");
|
||||||
|
ShowComponentButton<SpriterRendererComponent>("Sprite Renderer");
|
||||||
|
|
||||||
|
ImGui.EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PopItemWidth();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace System
|
||||||
|
{
|
||||||
|
extension String
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
public void CopyTo(Span<char8> target)
|
||||||
|
{
|
||||||
|
CopyTo(target.Ptr, target.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public void CopyTo(char8* target, int targetLength)
|
||||||
|
{
|
||||||
|
int copiedChars = Math.Min(targetLength - 1, Length);
|
||||||
|
|
||||||
|
Internal.MemCpy(target, Ptr, copiedChars);
|
||||||
|
|
||||||
|
target[copiedChars] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,19 @@ namespace ImGui
|
|||||||
{
|
{
|
||||||
extension ImGui
|
extension ImGui
|
||||||
{
|
{
|
||||||
// TODO: Color-functions
|
extension Vec2
|
||||||
|
{
|
||||||
|
public static explicit operator Vector2(Vec2 v) => .(v.x, v.y);
|
||||||
|
public static explicit operator Vec2(Vector2 v) => .(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Vec4
|
||||||
|
{
|
||||||
|
public static explicit operator Vector4(Vec4 v) => .(v.x, v.y, v.z, v.w);
|
||||||
|
public static explicit operator Vec4(Vector4 v) => .(v.X, v.Y, v.Z, v.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Color-functions
|
||||||
public static bool ColorEdit3(char* label, ref ColorRGB col, ColorEditFlags flags = (ColorEditFlags) 0) => ColorEdit3Impl(label, *(float[3]*)&col, flags);
|
public static bool ColorEdit3(char* label, ref ColorRGB col, ColorEditFlags flags = (ColorEditFlags) 0) => ColorEdit3Impl(label, *(float[3]*)&col, flags);
|
||||||
public static bool ColorEdit3(char* label, ref ColorRGBA col, ColorEditFlags flags = (ColorEditFlags) 0) => ColorEdit3Impl(label, *(float[3]*)&col, flags);
|
public static bool ColorEdit3(char* label, ref ColorRGBA col, ColorEditFlags flags = (ColorEditFlags) 0) => ColorEdit3Impl(label, *(float[3]*)&col, flags);
|
||||||
|
|
||||||
@@ -29,16 +40,87 @@ namespace ImGui
|
|||||||
/// Releases references that accumulated calls like ImGui::Image
|
/// Releases references that accumulated calls like ImGui::Image
|
||||||
protected internal static extern void CleanupFrame();
|
protected internal static extern void CleanupFrame();
|
||||||
|
|
||||||
extension Vec2
|
/// Control to edit a vector 3 with drag functionality and reset buttons
|
||||||
|
public static bool EditVector3(StringView label, ref Vector3 value, Vector3 resetValues = .Zero, float dragSpeed = 0.1f, float columnWidth = 100f)
|
||||||
{
|
{
|
||||||
public static explicit operator Vector2(Vec2 v) => .(v.x, v.y);
|
bool changed = false;
|
||||||
public static explicit operator Vec2(Vector2 v) => .(v.X, v.Y);
|
|
||||||
|
PushID(label);
|
||||||
|
defer PopID();
|
||||||
|
|
||||||
|
Columns(2);
|
||||||
|
defer Columns(1);
|
||||||
|
SetColumnWidth(0, columnWidth);
|
||||||
|
|
||||||
|
TextUnformatted(label);
|
||||||
|
|
||||||
|
NextColumn();
|
||||||
|
|
||||||
|
PushMultiItemsWidths(3, CalcItemWidth());
|
||||||
|
PushStyleVar(.ItemSpacing, Vec2.Zero);
|
||||||
|
defer PopStyleVar();
|
||||||
|
|
||||||
|
float lineHeight = GetFont().FontSize + GetStyle().FramePadding.y * 2.0f;
|
||||||
|
ImGui.Vec2 buttonSize = .(lineHeight + 3.0f, lineHeight);
|
||||||
|
|
||||||
|
PushStyleColor(.Button, Color(230, 25, 45).Value);
|
||||||
|
PushStyleColor(.ButtonHovered, Color(150, 25, 45).Value);
|
||||||
|
PushStyleColor(.ButtonActive, Color(230, 120, 130).Value);
|
||||||
|
|
||||||
|
if (Button("X", buttonSize))
|
||||||
|
{
|
||||||
|
value.X = resetValues.X;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Vec4
|
SameLine();
|
||||||
|
|
||||||
|
if (DragFloat("##X", &value.X, dragSpeed))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
PopItemWidth();
|
||||||
|
SameLine();
|
||||||
|
|
||||||
|
PopStyleColor(3);
|
||||||
|
PushStyleColor(.Button, Color(50, 190, 15).Value);
|
||||||
|
PushStyleColor(.ButtonHovered, Color(50, 120, 15).Value);
|
||||||
|
PushStyleColor(.ButtonActive, Color(116, 190, 99).Value);
|
||||||
|
|
||||||
|
if (Button("Y", buttonSize))
|
||||||
{
|
{
|
||||||
public static explicit operator Vector4(Vec4 v) => .(v.x, v.y, v.z, v.w);
|
value.Y = resetValues.Y;
|
||||||
public static explicit operator Vec4(Vector4 v) => .(v.X, v.Y, v.Z, v.W);
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SameLine();
|
||||||
|
|
||||||
|
if (DragFloat("##Y", &value.Y, dragSpeed))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
PopItemWidth();
|
||||||
|
SameLine();
|
||||||
|
|
||||||
|
PopStyleColor(3);
|
||||||
|
PushStyleColor(.Button, Color(55, 55, 230).Value);
|
||||||
|
PushStyleColor(.ButtonHovered, Color(55, 55, 150).Value);
|
||||||
|
PushStyleColor(.ButtonActive, Color(90, 90, 230).Value);
|
||||||
|
|
||||||
|
if (Button("Z", buttonSize))
|
||||||
|
{
|
||||||
|
value.Z = resetValues.Z;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SameLine();
|
||||||
|
|
||||||
|
if (DragFloat("##Z", &value.Z, dragSpeed))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
PopItemWidth();
|
||||||
|
|
||||||
|
PopStyleColor(3);
|
||||||
|
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,17 @@ using System;
|
|||||||
|
|
||||||
namespace GlitchyEngine.World
|
namespace GlitchyEngine.World
|
||||||
{
|
{
|
||||||
|
[AttributeUsage(.Struct, .ReflectAttribute, ReflectUser=.Methods | .NonStaticFields)]
|
||||||
|
struct ComponentAttribute : Attribute
|
||||||
|
{
|
||||||
|
public String Name;
|
||||||
|
|
||||||
|
public this(String name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// If an entity has the EditorComponent it won't be displayed in the scene hierarchy.
|
/// If an entity has the EditorComponent it won't be displayed in the scene hierarchy.
|
||||||
struct EditorComponent
|
struct EditorComponent
|
||||||
{
|
{
|
||||||
@@ -14,6 +25,7 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Component("Sprite Renderer")]
|
||||||
struct SpriterRendererComponent : IDisposableComponent
|
struct SpriterRendererComponent : IDisposableComponent
|
||||||
{
|
{
|
||||||
public Texture2D Sprite = null;
|
public Texture2D Sprite = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user