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.OpenGL.Extensions.ImGui;
using static gaemstone.Client.Components.InputComponents;
using static gaemstone.Client.Systems.InputManager;
using static gaemstone.Client.Systems.Windowing;
namespace gaemstone.Client.Systems;
@ -85,9 +86,9 @@ public class ImGuiManager
[System<SystemPhase.OnLoad>]
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(
new(canvas.GL, window.Handle, inputContext, () => {
new(canvas.GL, window.Handle, inputContext.Value, () => {
var io = ImGui.GetIO();
var style = ImGui.GetStyle();
@ -140,8 +141,9 @@ public class ImGuiManager
[System<SystemPhase.OnLoad>]
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 module = universe.LookupByTypeOrThrow<ImGuiManager>();
var capturedBy = input.GetTargets<MouseInputCapturedBy>().FirstOrDefault();;
@ -152,7 +154,7 @@ public class ImGuiManager
var IO = ImGui.GetIO();
// 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.
if (IO.WantCaptureMouse != isCaptured) {
@ -161,10 +163,10 @@ public class ImGuiManager
}
var cursor = ImGui.GetMouseCursor();
impl.Cursor.CursorMode = (cursor == ImGuiMouseCursor.None)
mouse.Cursor.CursorMode = (cursor == ImGuiMouseCursor.None)
? CursorMode.Hidden : CursorMode.Normal;
// 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.TextInput => StandardCursor.IBeam,
// ImGuiMouseCursor.ResizeAll => StandardCursor.,

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

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

Loading…
Cancel
Save