Remove ProxyAttribute

wip/source-generators
copygirl 1 year ago
parent 6eb1ef0de9
commit 13f69a0856
  1. 14
      src/gaemstone.Client/Systems/ImGuiManager.cs
  2. 83
      src/gaemstone.Client/Systems/InputManager.cs
  3. 15
      src/gaemstone/ECS/Attributes.cs
  4. 16
      src/gaemstone/Universe+Modules.cs

@ -10,6 +10,7 @@ using ImGuiNET;
using Silk.NET.Input; using Silk.NET.Input;
using Silk.NET.OpenGL.Extensions.ImGui; using Silk.NET.OpenGL.Extensions.ImGui;
using static gaemstone.Client.Components.InputComponents; using static gaemstone.Client.Components.InputComponents;
using static gaemstone.Client.Systems.InputManager;
using static gaemstone.Client.Systems.Windowing; using static gaemstone.Client.Systems.Windowing;
namespace gaemstone.Client.Systems; namespace gaemstone.Client.Systems;
@ -85,9 +86,9 @@ public class ImGuiManager
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public unsafe void Initialize(Universe universe, GameWindow window, Canvas canvas, public unsafe void Initialize(Universe universe, GameWindow window, Canvas canvas,
[Source<Input>] IInputContext inputContext, [Not] ImGuiData _) [Source<Input>] InputContext inputContext, [Not] ImGuiData _)
=> universe.LookupByTypeOrThrow<ImGuiData>().Set(new ImGuiData( => universe.LookupByTypeOrThrow<ImGuiData>().Set(new ImGuiData(
new(canvas.GL, window.Handle, inputContext, () => { new(canvas.GL, window.Handle, inputContext.Value, () => {
var io = ImGui.GetIO(); var io = ImGui.GetIO();
var style = ImGui.GetStyle(); var style = ImGui.GetStyle();
@ -140,8 +141,9 @@ public class ImGuiManager
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public static void UpdateMouse(Universe universe, public static void UpdateMouse(Universe universe,
[Source<Mouse>] IMouse impl, ImGuiData _) [Source<Mouse>] MouseImpl impl, ImGuiData _)
{ {
var mouse = impl.Value;
var input = universe.LookupByTypeOrThrow<Input>(); var input = universe.LookupByTypeOrThrow<Input>();
var module = universe.LookupByTypeOrThrow<ImGuiManager>(); var module = universe.LookupByTypeOrThrow<ImGuiManager>();
var capturedBy = input.GetTargets<MouseInputCapturedBy>().FirstOrDefault();; var capturedBy = input.GetTargets<MouseInputCapturedBy>().FirstOrDefault();;
@ -152,7 +154,7 @@ public class ImGuiManager
var IO = ImGui.GetIO(); var IO = ImGui.GetIO();
// Set the mouse position if ImGui wants to move it. // Set the mouse position if ImGui wants to move it.
if (IO.WantSetMousePos) impl.Position = IO.MousePos; if (IO.WantSetMousePos) mouse.Position = IO.MousePos;
// Capture the mouse input it is above GUI elements. // Capture the mouse input it is above GUI elements.
if (IO.WantCaptureMouse != isCaptured) { if (IO.WantCaptureMouse != isCaptured) {
@ -161,10 +163,10 @@ public class ImGuiManager
} }
var cursor = ImGui.GetMouseCursor(); var cursor = ImGui.GetMouseCursor();
impl.Cursor.CursorMode = (cursor == ImGuiMouseCursor.None) mouse.Cursor.CursorMode = (cursor == ImGuiMouseCursor.None)
? CursorMode.Hidden : CursorMode.Normal; ? CursorMode.Hidden : CursorMode.Normal;
// TODO: Use additional cursors once Silk.NET supports GLFW 3.4. // TODO: Use additional cursors once Silk.NET supports GLFW 3.4.
impl.Cursor.StandardCursor = cursor switch { mouse.Cursor.StandardCursor = cursor switch {
ImGuiMouseCursor.Arrow => StandardCursor.Arrow, ImGuiMouseCursor.Arrow => StandardCursor.Arrow,
ImGuiMouseCursor.TextInput => StandardCursor.IBeam, ImGuiMouseCursor.TextInput => StandardCursor.IBeam,
// ImGuiMouseCursor.ResizeAll => StandardCursor., // ImGuiMouseCursor.ResizeAll => StandardCursor.,

@ -15,28 +15,28 @@ namespace gaemstone.Client.Systems;
[DependsOn<gaemstone.Client.Systems.Windowing>] [DependsOn<gaemstone.Client.Systems.Windowing>]
public class InputManager public class InputManager
{ {
[Component, Path("InputContext"), Proxy<IInputContext>] public struct ContextProxy { } [Component] public record class InputContext(IInputContext Value) { }
[Component, Path("MouseImpl" ), Proxy<IMouse >] public struct MouseProxy { } [Component] public record class MouseImpl(IMouse Value) { }
[Component, Path("KeyboardImpl"), Proxy<IKeyboard>] public struct KeyboardProxy { } [Component] public record class KeyboardImpl(IKeyboard Value) { }
[Component, Path("GamepadImpl" ), Proxy<IGamepad >] public struct GamepadProxy { } [Component] public record class GamepadImpl(IGamepad Value) { }
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public static void Initialize(Universe universe, public static void Initialize(Universe universe,
[Game] GameWindow window, [Source<Input>, Not] IInputContext _) [Game] GameWindow window, [Source<Input>, Not] InputContext _)
{ {
var input = universe.LookupByTypeOrThrow<Input>(); var input = universe.LookupByTypeOrThrow<Input>();
var context = window.Handle.CreateInput(); var context = window.Handle.CreateInput();
input.Set(context); input.Set(new InputContext(context));
// TODO: Add device names as documentation names to these entities. // TODO: Add device names as documentation names to these entities.
foreach (var impl in context.Mice.Take(1)) foreach (var mouse in context.Mice.Take(1))
input.LookupChildOrThrow("Mouse").Set(impl); input.LookupChildOrThrow("Mouse").Set(new MouseImpl(mouse));
foreach (var impl in context.Keyboards.Take(1)) foreach (var keyboard in context.Keyboards.Take(1))
input.LookupChildOrThrow("Keyboard").Set(impl); input.LookupChildOrThrow("Keyboard").Set(new KeyboardImpl(keyboard));
foreach (var impl in context.Gamepads) foreach (var gamepad in context.Gamepads)
input.NewChild("Gamepad" + impl.Index).Add<Gamepad>().Set(impl).Build(); input.NewChild("Gamepad" + gamepad.Index).Add<Gamepad>().Set(new GamepadImpl(gamepad)).Build();
// TODO: Should we even support joysticks? // TODO: Should we even support joysticks?
} }
@ -45,53 +45,56 @@ public class InputManager
[Observer<ObserverEvent.OnAdd>] [Observer<ObserverEvent.OnAdd>]
[Expression("CursorCapturedBy(Input, *)")] [Expression("CursorCapturedBy(Input, *)")]
public static void OnCursorCaptured(Universe universe) public static void OnCursorCaptured(Universe universe)
=> universe.LookupByTypeOrThrow<Mouse>().GetOrThrow<IMouse>() => universe.LookupByTypeOrThrow<Mouse>().GetOrThrow<MouseImpl>()
.Cursor.CursorMode = CursorMode.Raw; .Value.Cursor.CursorMode = CursorMode.Raw;
[Observer<ObserverEvent.OnRemove>] [Observer<ObserverEvent.OnRemove>]
[Expression("CursorCapturedBy(Input, *)")] [Expression("CursorCapturedBy(Input, *)")]
public static void OnCursorReleased(Universe universe) public static void OnCursorReleased(Universe universe)
=> universe.LookupByTypeOrThrow<Mouse>().GetOrThrow<IMouse>() => universe.LookupByTypeOrThrow<Mouse>().GetOrThrow<MouseImpl>()
.Cursor.CursorMode = CursorMode.Normal; .Value.Cursor.CursorMode = CursorMode.Normal;
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public static void ProcessMouse(TimeSpan delta, EntityRef mouse, IMouse impl) public static void ProcessMouse(TimeSpan delta, EntityRef entity, MouseImpl impl)
{ {
var isCaptured = mouse.Parent!.Has<CursorCapturedBy, Core.Any>(); var mouse = impl.Value;
ref var position = ref mouse.NewChild("Position").Build().GetMut<RawValue2D>(); var isCaptured = entity.Parent!.Has<CursorCapturedBy, Core.Any>();
ref var posDelta = ref mouse.NewChild("Delta" ).Build().GetMut<RawValue2D>(); ref var position = ref entity.NewChild("Position").Build().GetMut<RawValue2D>();
posDelta = impl.Position - position; ref var posDelta = ref entity.NewChild("Delta" ).Build().GetMut<RawValue2D>();
if (isCaptured) impl.Position = position; posDelta = mouse.Position - position;
else position = impl.Position; if (isCaptured) mouse.Position = position;
else position = mouse.Position;
Update1D(delta, mouse.NewChild("Wheel").Build(), impl.ScrollWheels[0].Y);
Update1D(delta, entity.NewChild("Wheel").Build(), mouse.ScrollWheels[0].Y);
var buttons = mouse.NewChild("Buttons").Build();
foreach (var button in impl.SupportedButtons) var buttons = entity.NewChild("Buttons").Build();
foreach (var button in mouse.SupportedButtons)
Update1D(delta, buttons.NewChild(button.ToString()).Build(), Update1D(delta, buttons.NewChild(button.ToString()).Build(),
impl.IsButtonPressed(button) ? 1 : 0); mouse.IsButtonPressed(button) ? 1 : 0);
} }
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public static void ProcessKeyboard(TimeSpan delta, EntityRef keyboard, IKeyboard impl) public static void ProcessKeyboard(TimeSpan delta, EntityRef entity, KeyboardImpl impl)
{ {
foreach (var key in impl.SupportedKeys) { var keyboard = impl.Value;
var entity = keyboard.NewChild(key.ToString()).Build(); foreach (var key in keyboard.SupportedKeys) {
Update1D(delta, entity, impl.IsKeyPressed(key) ? 1 : 0); var keyEntity = entity.NewChild(key.ToString()).Build();
Update1D(delta, keyEntity, keyboard.IsKeyPressed(key) ? 1 : 0);
} }
} }
[System<SystemPhase.OnLoad>] [System<SystemPhase.OnLoad>]
public static void ProcessGamepad(TimeSpan delta, EntityRef gamepad, IGamepad impl) public static void ProcessGamepad(TimeSpan delta, EntityRef entity, GamepadImpl impl)
{ {
var buttons = gamepad.NewChild("Buttons").Build(); var gamepad = impl.Value;
foreach (var button in impl.Buttons) var buttons = entity.NewChild("Buttons").Build();
foreach (var button in gamepad.Buttons)
Update1D(delta, buttons.NewChild(button.Name.ToString()).Build(), button.Pressed ? 1 : 0); Update1D(delta, buttons.NewChild(button.Name.ToString()).Build(), button.Pressed ? 1 : 0);
foreach (var trigger in impl.Triggers) foreach (var trigger in gamepad.Triggers)
Update1D(delta, gamepad.NewChild("Trigger" + trigger.Index).Build(), trigger.Position); Update1D(delta, entity.NewChild("Trigger" + trigger.Index).Build(), trigger.Position);
foreach (var thumbstick in impl.Thumbsticks) foreach (var thumbstick in gamepad.Thumbsticks)
Update2D(delta, gamepad.NewChild("Thumbstick" + thumbstick.Index).Build(), new(thumbstick.X, thumbstick.Y)); Update2D(delta, entity.NewChild("Thumbstick" + thumbstick.Index).Build(), new(thumbstick.X, thumbstick.Y));
} }

@ -45,14 +45,6 @@ public class SymbolAttribute : Attribute, ICreateEntityAttribute
public class SingletonAttribute : Attribute, ICreateEntityAttribute public class SingletonAttribute : Attribute, ICreateEntityAttribute
{ public bool AutoAdd { get; init; } = true; } { public bool AutoAdd { get; init; } = true; }
/// <summary>
/// Register the proxied type instead of the one marked with this attribute.
/// This can be used to make types not registered in a module available,
/// including types registered in other assemblies.
/// </summary>
public class ProxyAttribute<T> : ProxyAttribute
{ public ProxyAttribute() : base(typeof(T)) { } }
/// <summary> /// <summary>
/// Marked entity automatically has the specified entity added to it when /// Marked entity automatically has the specified entity added to it when
@ -112,13 +104,6 @@ public class WithAttribute<TTarget> : AddAttribute<With, TTarget> { }
// Base attributes for other attributes. // Base attributes for other attributes.
[AttributeUsage(AttributeTargets.Struct)]
public class ProxyAttribute : Attribute
{
public Type Type { get; }
internal ProxyAttribute(Type type) => Type = type;
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true)]
public class AddEntityAttribute : Attribute public class AddEntityAttribute : Attribute
{ {

@ -183,16 +183,10 @@ public class ModuleManager
{ {
if (!type.GetCustomAttributes(true).OfType<ICreateEntityAttribute>().Any()) return; if (!type.GetCustomAttributes(true).OfType<ICreateEntityAttribute>().Any()) return;
// If proxied type is specified, use it instead of the marked type. if (!type.Has<ComponentAttribute>() && (!type.IsValueType || (type.GetFields().Length > 0)))
// Attributes are still read from the original type. throw new Exception($"Type {type} must be an empty, used-defined struct.");
var proxyType = type.Get<ProxyAttribute>()?.Type ?? type;
if (!type.Has<ComponentAttribute>() && (!proxyType.IsValueType || (proxyType.GetFields().Length > 0))) { var path = EntityPath.Parse(type.Get<PathAttribute>()?.Value ?? type.Name);
var typeHint = (proxyType != type) ? $"{proxyType.Name} (proxied by {type})" : type.ToString();
throw new Exception($"Type {typeHint} must be an empty, used-defined struct.");
}
var path = EntityPath.Parse(type.Get<PathAttribute>()?.Value ?? proxyType.Name);
var builder = path.IsAbsolute ? Universe.New(path) : Entity.NewChild(path); var builder = path.IsAbsolute ? Universe.New(path) : Entity.NewChild(path);
if (type.Get<SymbolAttribute>() is SymbolAttribute symbolAttr) if (type.Get<SymbolAttribute>() is SymbolAttribute symbolAttr)
@ -208,8 +202,8 @@ public class ModuleManager
entity.Add(Lookup(attr.Relation), Lookup(attr.Target)); entity.Add(Lookup(attr.Relation), Lookup(attr.Target));
if (type.Get<SingletonAttribute>()?.AutoAdd == true) entity.Add(entity); if (type.Get<SingletonAttribute>()?.AutoAdd == true) entity.Add(entity);
if (type.Has<ComponentAttribute>()) entity.InitComponent(proxyType); if (type.Has<ComponentAttribute>()) entity.InitComponent(type);
else entity.CreateLookup(proxyType); else entity.CreateLookup(type);
if (type.Has<RelationAttribute>()) entity.Add<Doc.Relation>(); if (type.Has<RelationAttribute>()) entity.Add<Doc.Relation>();
if (type.Has<TagAttribute>()) entity.Add<Tag>(); if (type.Has<TagAttribute>()) entity.Add<Tag>();
} }

Loading…
Cancel
Save