diff --git a/src/Bliss.Test/Game.cs b/src/Bliss.Test/Game.cs index cae5649..a0979fe 100644 --- a/src/Bliss.Test/Game.cs +++ b/src/Bliss.Test/Game.cs @@ -5,6 +5,8 @@ using Bliss.CSharp.Graphics.Rendering.Batches.Primitives; using Bliss.CSharp.Graphics.Rendering.Batches.Sprites; using Bliss.CSharp.Graphics.Rendering.Passes; +using Bliss.CSharp.Interact; +using Bliss.CSharp.Interact.Keyboards; using Bliss.CSharp.Logging; using Bliss.CSharp.Textures; using Bliss.CSharp.Windowing; @@ -76,7 +78,7 @@ public void Run() { this.CommandList = this.GraphicsDevice.ResourceFactory.CreateCommandList(); Logger.Info("Initialize input..."); - //TODO: Input.Init(this.MainWindow); + Input.Init(this.MainWindow); this.Init(); @@ -88,7 +90,7 @@ public void Run() { Time.Update(); this.MainWindow.PumpEvents(); - //TODO: Input.Begin(this.MainWindow.PumpEvents()); + Input.Begin(); if (!this.MainWindow.Exists) { break; @@ -104,7 +106,7 @@ public void Run() { } this.Draw(this.GraphicsDevice, this.CommandList); - //TODO: Input.End(); + Input.End(); } Logger.Warn("Application shuts down!"); @@ -121,7 +123,19 @@ protected virtual void Init() { this._font = new Font("content/fonts/fontoe.ttf"); } - protected virtual void Update() { } + protected virtual void Update() { + if (Input.IsKeyPressed(KeyboardKey.A)) { + Logger.Warn("A GOT PRESSED!!!!"); + } + + if (Input.IsKeyDown(KeyboardKey.D)) { + Logger.Warn("D IS DOWN!!!!"); + } + + if (Input.IsKeyReleased(KeyboardKey.D)) { + Logger.Warn("D IS Released!!!!"); + } + } protected virtual void AfterUpdate() { } diff --git a/src/Bliss/CSharp/Interact/Input.cs b/src/Bliss/CSharp/Interact/Input.cs index 4fedc87..4ff8161 100644 --- a/src/Bliss/CSharp/Interact/Input.cs +++ b/src/Bliss/CSharp/Interact/Input.cs @@ -1,111 +1,114 @@ using System.Numerics; using System.Runtime.CompilerServices; using Bliss.CSharp.Interact.Gamepads; +using Bliss.CSharp.Interact.Keyboards; using Bliss.CSharp.Interact.Mice; using Bliss.CSharp.Logging; using Bliss.CSharp.Windowing; +using Bliss.CSharp.Windowing.Events; +using SDL; namespace Bliss.CSharp.Interact; public static class Input { -// -// public static IWindow Window { get; private set; } -// public static InputSnapshot Snapshot { get; private set; } -// -// // Mouse -// private static (SDL_Cursor?, MouseCursor) _sdlCursor; -// private static List _miceSrolling; -// private static List _miceMoving; -// private static List _mouseButtonsPressed; -// private static List _mouseButtonsDown; -// private static List _mouseButtonsReleased; -// -// // Keyboard -// private static List _keyboardKeysPressed; -// private static List _keyboardKeysDown; -// private static List _keyboardKeysReleased; -// -// // Gamepad -// private static Dictionary _gamepads; -// -// // Other -// private static List _filesDragDropped; -// -// /// -// /// Initializes mouse input tracking and event handlers for the specified window. -// /// -// /// The window instance to attach mouse input event handlers to. -// public static void Init(IWindow window) { -// Window = window; -// Sdl2Events.Subscribe(ProcessEvent); -// -// // Mouse -// _miceSrolling = new List(); -// _miceMoving = new List(); -// _mouseButtonsPressed = new List(); -// _mouseButtonsDown = new List(); -// _mouseButtonsReleased = new List(); -// -// Window.MouseWheel += OnMouseWheel; -// Window.MouseMove += OnMouseMove; -// Window.MouseDown += OnMouseDown; -// Window.MouseUp += OnMouseUp; -// -// // Keyboard -// _keyboardKeysPressed = new List(); -// _keyboardKeysDown = new List(); -// _keyboardKeysReleased = new List(); -// -// Window.KeyDown += OnKeyDown; -// Window.KeyUp += OnKeyUp; -// -// // Gamepads -// _gamepads = new Dictionary(); -// -// // Other -// _filesDragDropped = new List(); -// -// Window.DragDrop += OnDragDrop; -// } -// -// /// -// /// Sets the current input snapshot to the provided instance for processing input data. -// /// -// /// The input snapshot containing the current state of input devices. -// public static void Begin(InputSnapshot snapshot) { -// Snapshot = snapshot; -// } -// -// /// -// /// Clears all tracked mouse input data and button states, resetting them for the next input processing cycle. -// /// -// public static void End() { -// -// // Mouse -// _miceSrolling.Clear(); -// _miceMoving.Clear(); -// _mouseButtonsPressed.Clear(); -// _mouseButtonsReleased.Clear(); -// -// // Keyboard -// _keyboardKeysPressed.Clear(); -// _keyboardKeysReleased.Clear(); -// -// // Gamepad -// foreach (Gamepad gamepad in _gamepads.Values) { -// gamepad.CleanStates(); -// } -// -// // Other -// _filesDragDropped.Clear(); -// } -// -// /* ------------------------------------ Mouse ------------------------------------ */ -// -// /// -// /// Checks if the cursor is currently shown. -// /// -// /// True if the cursor is shown; otherwise, false. + + public static IWindow Window { get; private set; } + //public static InputSnapshot Snapshot { get; private set; } + + // Mouse + //private static (SDL_Cursor?, MouseCursor) _sdlCursor; + //private static List _miceSrolling; + //private static List _miceMoving; + //private static List _mouseButtonsPressed; + //private static List _mouseButtonsDown; + //private static List _mouseButtonsReleased; + + // Keyboard + private static List _keyboardKeysPressed; + private static List _keyboardKeysDown; + private static List _keyboardKeysReleased; + + // Gamepad + //private static Dictionary _gamepads; + + // Other + //private static List _filesDragDropped; + + /// + /// Initializes mouse input tracking and event handlers for the specified window. + /// + /// The window instance to attach mouse input event handlers to. + public static void Init(IWindow window) { + Window = window; + //Sdl2Events.Subscribe(ProcessEvent); + + // Mouse + //_miceSrolling = new List(); + //_miceMoving = new List(); + //_mouseButtonsPressed = new List(); + //_mouseButtonsDown = new List(); + //_mouseButtonsReleased = new List(); + + //Window.MouseWheel += OnMouseWheel; + //Window.MouseMove += OnMouseMove; + //Window.MouseDown += OnMouseDown; + //Window.MouseUp += OnMouseUp; + + // Keyboard + _keyboardKeysPressed = new List(); + _keyboardKeysDown = new List(); + _keyboardKeysReleased = new List(); + + Window.KeyDown += OnKeyDown; + Window.KeyUp += OnKeyUp; + + // Gamepads + //_gamepads = new Dictionary(); + + // Other + //_filesDragDropped = new List(); + + //Window.DragDrop += OnDragDrop; + } + + /// + /// Sets the current input snapshot to the provided instance for processing input data. + /// + /// The input snapshot containing the current state of input devices. + public static void Begin(/*InputSnapshot snapshot*/) { + //Snapshot = snapshot; + } + + /// + /// Clears all tracked mouse input data and button states, resetting them for the next input processing cycle. + /// + public static void End() { + + // Mouse + //_miceSrolling.Clear(); + //_miceMoving.Clear(); + //_mouseButtonsPressed.Clear(); + //_mouseButtonsReleased.Clear(); + + // Keyboard + _keyboardKeysPressed.Clear(); + _keyboardKeysReleased.Clear(); + + // Gamepad + //foreach (Gamepad gamepad in _gamepads.Values) { + // gamepad.CleanStates(); + //} + + // Other + //_filesDragDropped.Clear(); + } + + /* ------------------------------------ Mouse ------------------------------------ */ + + /// + /// Checks if the cursor is currently shown. + /// + /// True if the cursor is shown; otherwise, false. // public static bool IsCursorShown() { // return Sdl2Native.SDL_ShowCursor(Sdl2Native.SDL_QUERY) == Sdl2Native.SDL_ENABLE; // } @@ -252,71 +255,71 @@ public static class Input { // wheelDelta = 0; // return false; // } -// -// /* ------------------------------------ Keyboard ------------------------------------ */ -// -// /// -// /// Checks if a specific key is currently pressed. -// /// -// /// The key to check. -// /// True if the key is pressed, false otherwise. -// public static bool IsKeyPressed(Key key) { -// return _keyboardKeysPressed.Contains(key); -// } -// -// /// -// /// Checks if a specific key is currently down. -// /// -// /// The key to check. -// /// True if the key is down, false otherwise. -// public static bool IsKeyDown(Key key) { -// return _keyboardKeysDown.Contains(key); -// } -// -// /// -// /// Checks if a specific key has been released. -// /// -// /// The key to check. -// /// True if the key has been released, false otherwise. -// public static bool IsKeyReleased(Key key) { -// return _keyboardKeysReleased.Contains(key); -// } -// -// /// -// /// Checks if a specific key is currently up (not pressed). -// /// -// /// The key to check. -// /// True if the key is up, false otherwise. -// public static bool IsKeyUp(Key key) { -// return !_keyboardKeysDown.Contains(key); -// } -// -// /// -// /// Gets an array of characters that have been pressed. -// /// -// /// An array of pressed characters. -// public static char[] GetPressedChars() { -// return Snapshot.KeyCharPresses.ToArray(); -// } -// -// /// -// /// Gets the current text from the clipboard. -// /// -// /// The text from the clipboard. -// public static string GetClipboardText() { -// return Sdl2Native.SDL_GetClipboardText(); -// } -// -// /// -// /// Sets the specified text to the clipboard. -// /// -// /// The text to set to the clipboard. -// public static void SetClipboardText(string text) { -// Sdl2Native.SDL_SetClipboardText(text); -// } -// -// /* ------------------------------------ Gamepad ------------------------------------ */ -// + + /* ------------------------------------ Keyboard ------------------------------------ */ + + /// + /// Checks if a specific key is currently pressed. + /// + /// The key to check. + /// True if the key is pressed, false otherwise. + public static bool IsKeyPressed(KeyboardKey key) { + return _keyboardKeysPressed.Contains(key); + } + + /// + /// Checks if a specific key is currently down. + /// + /// The key to check. + /// True if the key is down, false otherwise. + public static bool IsKeyDown(KeyboardKey key) { + return _keyboardKeysDown.Contains(key); + } + + /// + /// Checks if a specific key has been released. + /// + /// The key to check. + /// True if the key has been released, false otherwise. + public static bool IsKeyReleased(KeyboardKey key) { + return _keyboardKeysReleased.Contains(key); + } + + /// + /// Checks if a specific key is currently up (not pressed). + /// + /// The key to check. + /// True if the key is up, false otherwise. + public static bool IsKeyUp(KeyboardKey key) { + return !_keyboardKeysDown.Contains(key); + } + + /// + /// Gets an array of characters that have been pressed. + /// + /// An array of pressed characters. + //public static char[] GetPressedChars() { + // return Snapshot.KeyCharPresses.ToArray(); + //} + + /// + /// Gets the current text from the clipboard. + /// + /// The text from the clipboard. + //public static string GetClipboardText() { + // return Sdl2Native.SDL_GetClipboardText(); + //} + + /// + /// Sets the specified text to the clipboard. + /// + /// The text to set to the clipboard. + //public static void SetClipboardText(string text) { + // Sdl2Native.SDL_SetClipboardText(text); + //} + + /* ------------------------------------ Gamepad ------------------------------------ */ + // /// // /// Checks if a specific gamepad is available. // /// @@ -433,31 +436,31 @@ public static class Input { // _mouseButtonsDown.Remove(args.MouseButton); // _mouseButtonsReleased.Add(args.MouseButton); // } -// -// /* ------------------------------------ Keyboard ------------------------------------ */ -// -// private static void OnKeyDown(KeyEvent args) { -// if (!args.Repeat) { -// _keyboardKeysPressed.Add(args.Key); -// _keyboardKeysDown.Add(args.Key); -// } -// } -// -// private static void OnKeyUp(KeyEvent args) { -// _keyboardKeysDown.Remove(args.Key); -// _keyboardKeysReleased.Add(args.Key); -// } -// -// /* ------------------------------------ Other ------------------------------------ */ -// + + /* ------------------------------------ Keyboard ------------------------------------ */ + + private static void OnKeyDown(KeyEvent keyEvent) { + if (!keyEvent.Repeat) { + _keyboardKeysPressed.Add(keyEvent.KeyboardKey); + _keyboardKeysDown.Add(keyEvent.KeyboardKey); + } + } + + private static void OnKeyUp(KeyEvent keyEvent) { + _keyboardKeysDown.Remove(keyEvent.KeyboardKey); + _keyboardKeysReleased.Add(keyEvent.KeyboardKey); + } + + /* ------------------------------------ Other ------------------------------------ */ + // private static void OnDragDrop(DragDropEvent args) { // _filesDragDropped.Add(args.File); // } -// -// /// -// /// Processes SDL events related to gamepad devices being added or removed, and updates the list of active gamepads accordingly. -// /// -// /// The SDL event to process. + + /// + /// Processes SDL events related to gamepad devices being added or removed, and updates the list of active gamepads accordingly. + /// + /// The SDL event to process. // private static void ProcessEvent(ref SDL_Event ev) { // switch (ev.type) { // case SDL_EventType.ControllerDeviceAdded: @@ -481,35 +484,35 @@ public static class Input { // gamepad.ProcessEvent(ref ev); // } // } -// -// /// -// /// Destroys resources (like free a mouse cursor). -// /// -// public static void Destroy() { -// -// // Mouse -// SetMouseCursor(MouseCursor.Default); // To free the Cursor. -// -// Window.MouseWheel -= OnMouseWheel; -// Window.MouseMove -= OnMouseMove; -// Window.MouseDown -= OnMouseDown; -// Window.MouseUp -= OnMouseUp; -// -// // Keyboard -// Window.KeyDown -= OnKeyDown; -// Window.KeyUp -= OnKeyUp; -// -// // Gamepad -// foreach (Gamepad gamepad in _gamepads.Values) { -// gamepad.Dispose(); -// } -// -// _gamepads.Clear(); -// -// // Other -// Window.DragDrop -= OnDragDrop; -// -// // Event -// Sdl2Events.Unsubscribe(ProcessEvent); -// } + + /// + /// Destroys resources (like free a mouse cursor). + /// + public static void Destroy() { + + // Mouse + //SetMouseCursor(MouseCursor.Default); // To free the Cursor. + + //Window.MouseWheel -= OnMouseWheel; + //Window.MouseMove -= OnMouseMove; + //Window.MouseDown -= OnMouseDown; + //Window.MouseUp -= OnMouseUp; + + // Keyboard + Window.KeyDown -= OnKeyDown; + Window.KeyUp -= OnKeyUp; + + // Gamepad + //foreach (Gamepad gamepad in _gamepads.Values) { + // gamepad.Dispose(); + //} + + //_gamepads.Clear(); + + // Other + //Window.DragDrop -= OnDragDrop; + + // Event + //Sdl2Events.Unsubscribe(ProcessEvent); + } } \ No newline at end of file diff --git a/src/Bliss/CSharp/Interact/Mice/MouseCursor.cs b/src/Bliss/CSharp/Interact/Mice/MouseCursor.cs index 231e7ac..9e0e0e7 100644 --- a/src/Bliss/CSharp/Interact/Mice/MouseCursor.cs +++ b/src/Bliss/CSharp/Interact/Mice/MouseCursor.cs @@ -1,70 +1,109 @@ namespace Bliss.CSharp.Interact.Mice; public enum MouseCursor { - /* + /// - /// The default cursor. Represents the system's default cursor. + /// The default arrow cursor. /// - Default = default, + Default = 0, /// - /// The arrow cursor. Typically used for standard pointing interactions. + /// A cursor indicating text selection or editing. /// - Arrow = SDL_SystemCursor.Arrow, + Text = 1, /// - /// The I-beam cursor. Typically used for text selection. + /// A cursor indicating that the application is busy and the user should wait. /// - IBeam = SDL_SystemCursor.IBeam, + Wait = 2, /// - /// The wait cursor. Typically used to indicate that the application is busy. + /// A cursor indicating a crosshair, typically used for precise selection or drawing. /// - Wait = SDL_SystemCursor.Wait, + Crosshair = 3, /// - /// The crosshair cursor. Typically used for precise selections or aiming. + /// A cursor indicating a progress or loading state. /// - Crosshair = SDL_SystemCursor.Crosshair, + Progress = 4, /// - /// The wait arrow cursor. Typically used to indicate that the application is busy, but still allows pointing. + /// A cursor indicating a resize action from the northwest to the southeast. /// - WaitArrow = SDL_SystemCursor.WaitArrow, + NWSEResize = 5, /// - /// The size NW-SE cursor. Typically used for resizing diagonally from the northwest to the southeast. + /// A cursor indicating a resize action from the northeast to the southwest. /// - SizeNWSE = SDL_SystemCursor.SizeNWSE, + NESWResize = 6, /// - /// The size NE-SW cursor. Typically used for resizing diagonally from the northeast to the southwest. + /// A cursor indicating a horizontal resize action. /// - SizeNESW = SDL_SystemCursor.SizeNESW, + EWResize = 7, /// - /// The size horizontal cursor. Typically used for resizing horizontally. + /// A cursor indicating a vertical resize action. /// - SizeWE = SDL_SystemCursor.SizeWE, + NSResize = 8, /// - /// The size vertical cursor. Typically used for resizing vertically. + /// A cursor indicating a move action. /// - SizeNS = SDL_SystemCursor.SizeNS, + Move = 9, /// - /// The size all cursor. Typically used for resizing in any direction. + /// A cursor indicating that the action is not allowed. /// - SizeAll = SDL_SystemCursor.SizeAll, + NotAllowed = 10, /// - /// The no cursor. Typically used to indicate that an action is not allowed. + /// A cursor indicating a pointing hand, often used for hyperlinks. /// - No = SDL_SystemCursor.No, + Pointer = 11, /// - /// The hand cursor. Typically used for indicating clickable elements, such as hyperlinks. + /// A cursor indicating a resize action from the northwest. /// - Hand = SDL_SystemCursor.Hand - */ + NWResize = 12, + + /// + /// A cursor indicating a resize action from the north. + /// + NResize = 13, + + /// + /// A cursor indicating a resize action from the northeast. + /// + NEResize = 14, + + /// + /// A cursor indicating a resize action from the east. + /// + EResize = 15, + + /// + /// A cursor indicating a resize action from the southeast. + /// + SEResize = 16, + + /// + /// A cursor indicating a resize action from the south. + /// + SResize = 17, + + /// + /// A cursor indicating a resize action from the southwest. + /// + SWResize = 18, + + /// + /// A cursor indicating a resize action from the west. + /// + WResize = 19, + + /// + /// The total number of cursor types available. + /// + Count = 20 } \ No newline at end of file diff --git a/src/Bliss/CSharp/Windowing/Events/KeyEvent.cs b/src/Bliss/CSharp/Windowing/Events/KeyEvent.cs index 512184b..585032c 100644 --- a/src/Bliss/CSharp/Windowing/Events/KeyEvent.cs +++ b/src/Bliss/CSharp/Windowing/Events/KeyEvent.cs @@ -15,12 +15,19 @@ public struct KeyEvent { public bool IsDown; /// - /// Initializes a new instance of the class with the specified keyboard key and key state. + /// Indicates whether the key press event is a repeat of the previous key press action. + /// + public bool Repeat; + + /// + /// Initializes a new instance of the class with the specified keyboard key, key state, and repeat flag. /// /// The representing the key involved in the event. /// Indicates whether the key is pressed down (true) or released (false). - public KeyEvent(KeyboardKey keyboardKey, bool isDown) { + /// Indicates whether the key event is a repeated key press (true) or a single press (false). + public KeyEvent(KeyboardKey keyboardKey, bool isDown, bool repeat) { this.KeyboardKey = keyboardKey; this.IsDown = isDown; + this.Repeat = repeat; } } \ No newline at end of file diff --git a/src/Bliss/CSharp/Windowing/IWindow.cs b/src/Bliss/CSharp/Windowing/IWindow.cs index 37e8e7c..47fa53c 100644 --- a/src/Bliss/CSharp/Windowing/IWindow.cs +++ b/src/Bliss/CSharp/Windowing/IWindow.cs @@ -42,38 +42,6 @@ public interface IWindow : IDisposable { /// This property can be used to check if the window is the foreground window. /// bool IsFocused { get; } - - /// - /// Gets or sets the state of the window, which defines its appearance and behavior. - /// The possible states include resizable, full screen, maximized, minimized, - /// borderless full screen, and hidden. - /// - WindowState State { get; set; } - - /// - /// Gets or sets a value indicating whether the window is visible on the screen. - /// If set to true, the window will be displayed; otherwise, it will be hidden. - /// - bool Visible { get; set; } - - /// - /// Gets or sets the opacity level of the window. The value ranges from 0.0 (completely transparent) - /// to 1.0 (completely opaque). Adjusting the opacity can be used for visual effects or overlay purposes. - /// - float Opacity { get; set; } - - /// - /// Indicates whether the window can be resized by the user. - /// If set to true, the window can be resized; otherwise, it cannot be resized. - /// - bool Resizable { get; set; } - - /// - /// Gets or sets a value indicating whether the window border is visible. When set to true, the window - /// will have a visible border, which typically includes the title bar and the window frame that allows - /// users to resize and move the window. When set to false, the window will be borderless. - /// - bool BorderVisible { get; set; } /// /// Occurs when the window is resized. @@ -160,6 +128,30 @@ public interface IWindow : IDisposable { /// public event Action? DragDrop; + /// + /// Retrieves the current state of the window. + /// + /// The current state of the window as a WindowState enum value. + WindowState GetState(); + + /// + /// Checks if the current state of the window matches the specified state. + /// + /// The state to be checked against the current window state. + /// True if the current state of the window matches the specified state, otherwise false. + bool HasState(WindowState state); + + /// + /// Sets the state of the window to the specified WindowState. + /// + /// The desired state to set the window to, represented by the WindowState enum. + void SetState(WindowState state); + + /// + /// Clears the current state of the window, resetting it to its default state. + /// + void ClearState(); + /// /// Retrieves the current title of the window. /// diff --git a/src/Bliss/CSharp/Windowing/Sdl3Window.cs b/src/Bliss/CSharp/Windowing/Sdl3Window.cs index ff825bb..96bf2f4 100644 --- a/src/Bliss/CSharp/Windowing/Sdl3Window.cs +++ b/src/Bliss/CSharp/Windowing/Sdl3Window.cs @@ -51,13 +51,6 @@ public class Sdl3Window : Disposable, IWindow { /// public bool IsFocused { get; private set; } - public WindowState State { get; set; } - - public bool Visible { get; set; } - public float Opacity { get; set; } - public bool Resizable { get; set; } - public bool BorderVisible { get; set; } - /// /// Represents an event that is triggered whenever an SDL event occurs within the window. /// @@ -148,6 +141,11 @@ public class Sdl3Window : Disposable, IWindow { /// public event Action? DragDrop; + /// + /// Represents the current state of the SDL window, such as whether it is resizable, full screen, maximized, minimized, hidden, etc. + /// + private WindowState _state; + /// /// Contains a collection of SDL_Event objects used for polling and handling SDL events. /// @@ -170,14 +168,14 @@ public class Sdl3Window : Disposable, IWindow { private (int, int)? _maxSupportedGlEsVersion; /// - /// Initializes a new instance of the class with the specified dimensions, title, and window flags. + /// Initializes a new instance of the class with the specified width, height, title, and window state. /// /// The width of the window in pixels. /// The height of the window in pixels. /// The title of the window. - /// Window flags that define the behavior and appearance of the window, specified as . + /// The initial state of the window, specified as a value. /// Thrown if SDL fails to initialize the subsystem required for creating the window. - public unsafe Sdl3Window(int width, int height, string title, SDL_WindowFlags flags) { + public unsafe Sdl3Window(int width, int height, string title, WindowState state) { this.Exists = true; SDL3.SDL_SetHint(SDL3.SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); @@ -190,7 +188,7 @@ public unsafe Sdl3Window(int width, int height, string title, SDL_WindowFlags fl SDL3.SDL_SetGamepadEventsEnabled(SDL_bool.SDL_TRUE); SDL3.SDL_SetJoystickEventsEnabled(SDL_bool.SDL_TRUE); - this.Handle = (nint) SDL3.SDL_CreateWindow(title, width, height, flags); + this.Handle = (nint) SDL3.SDL_CreateWindow(title, width, height, this.MapWindowState(state) | SDL_WindowFlags.SDL_WINDOW_OPENGL); this.Id = (uint) SDL3.SDL_GetWindowID((SDL_Window*) this.Handle); this.SwapchainSource = this.CreateSwapchainSource(); @@ -205,6 +203,69 @@ public unsafe Sdl3Window(int width, int height, string title, SDL_WindowFlags fl /// Thrown if an error occurs when retrieving the module handle. [DllImport("kernel32", ExactSpelling = true)] private static extern unsafe nint GetModuleHandleW(ushort* lpModuleName); + + /// + /// Retrieves the current state of the window. + /// + /// The current state of the window represented by the enumeration. + public WindowState GetState() { + return this._state; + } + + /// + /// Determines if the current window state matches the specified state. + /// + /// The window state to compare with the current state. + /// True if the current window state matches the specified state; otherwise, false. + public bool HasState(WindowState state) { + return this._state.HasFlag(state); + } + + /// + /// Sets the state of the window to the specified state. + /// + /// The desired state for the window, specified as a . + public unsafe void SetState(WindowState state) { + switch (state) { + case WindowState.Resizable: + SDL3.SDL_SetWindowResizable((SDL_Window*) this.Handle, SDL_bool.SDL_TRUE); + break; + case WindowState.FullScreen: + SDL3.SDL_SetWindowFullscreen((SDL_Window*) this.Handle, SDL_bool.SDL_TRUE); + break; + case WindowState.BorderlessFullScreen: + SDL3.SDL_SetWindowBordered((SDL_Window*) this.Handle, SDL_bool.SDL_TRUE); + break; + case WindowState.Maximized: + SDL3.SDL_MaximizeWindow((SDL_Window*) this.Handle); + break; + case WindowState.Minimized: + SDL3.SDL_MinimizeWindow((SDL_Window*) this.Handle); + break; + case WindowState.Hidden: + SDL3.SDL_HideWindow((SDL_Window*) this.Handle); + break; + case WindowState.CaptureMouse: + SDL3.SDL_CaptureMouse(SDL_bool.SDL_TRUE); + break; + case WindowState.AlwaysOnTop: + SDL3.SDL_SetWindowAlwaysOnTop((SDL_Window*) this.Handle, SDL_bool.SDL_TRUE); + break; + } + } + + /// + /// Resets the window to its default state by clearing various settings such as resizability, fullscreen mode, border visibility, and always-on-top status. + /// + /// Thrown if the window handle is invalid. + public unsafe void ClearState() { + SDL3.SDL_SetWindowResizable((SDL_Window*) this.Handle, SDL_bool.SDL_FALSE); + SDL3.SDL_SetWindowFullscreen((SDL_Window*) this.Handle, SDL_bool.SDL_FALSE); + SDL3.SDL_SetWindowBordered((SDL_Window*) this.Handle, SDL_bool.SDL_FALSE); + SDL3.SDL_ShowWindow((SDL_Window*) this.Handle); + SDL3.SDL_CaptureMouse(SDL_bool.SDL_FALSE); + SDL3.SDL_SetWindowAlwaysOnTop((SDL_Window*) this.Handle, SDL_bool.SDL_FALSE); + } /// /// Retrieves the title of the window. @@ -625,6 +686,35 @@ private unsafe SwapchainSource CreateSwapchainSource() { throw new PlatformNotSupportedException("Filed to create a SwapchainSource!"); } + /// + /// Maps a given to the corresponding . + /// + /// The state of the window to map, specified as . + /// The corresponding for the provided . + /// Thrown when an invalid is provided. + private SDL_WindowFlags MapWindowState(WindowState state) { + switch (state) { + case WindowState.Resizable: + return SDL_WindowFlags.SDL_WINDOW_RESIZABLE; + case WindowState.FullScreen: + return SDL_WindowFlags.SDL_WINDOW_FULLSCREEN; + case WindowState.BorderlessFullScreen: + return SDL_WindowFlags.SDL_WINDOW_BORDERLESS; + case WindowState.Maximized: + return SDL_WindowFlags.SDL_WINDOW_MAXIMIZED; + case WindowState.Minimized: + return SDL_WindowFlags.SDL_WINDOW_MINIMIZED; + case WindowState.Hidden: + return SDL_WindowFlags.SDL_WINDOW_HIDDEN; + case WindowState.CaptureMouse: + return SDL_WindowFlags.SDL_WINDOW_MOUSE_CAPTURE; + case WindowState.AlwaysOnTop: + return SDL_WindowFlags.SDL_WINDOW_ALWAYS_ON_TOP; + default: + throw new Exception($"Invalid WindowState: [{state}]"); + } + } + /// /// Handles a given SDL event and triggers the appropriate window event based on the type of the SDL event. /// @@ -684,10 +774,10 @@ private void HandleEvent(SDL_Event sdlEvent) { this.MouseUp?.Invoke(new MouseEvent((MouseButton) sdlEvent.button.Button, sdlEvent.button.down == SDL_bool.SDL_TRUE)); break; case SDL_EventType.SDL_EVENT_KEY_DOWN: - this.KeyDown?.Invoke(new KeyEvent(this.MapKey(sdlEvent.key.scancode), sdlEvent.key.down == SDL_bool.SDL_TRUE)); + this.KeyDown?.Invoke(new KeyEvent(this.MapKey(sdlEvent.key.scancode), sdlEvent.key.down == SDL_bool.SDL_TRUE, sdlEvent.key.repeat == SDL_bool.SDL_TRUE)); break; case SDL_EventType.SDL_EVENT_KEY_UP: - this.KeyUp?.Invoke(new KeyEvent(this.MapKey(sdlEvent.key.scancode), sdlEvent.key.down == SDL_bool.SDL_TRUE)); + this.KeyUp?.Invoke(new KeyEvent(this.MapKey(sdlEvent.key.scancode), sdlEvent.key.down == SDL_bool.SDL_TRUE, sdlEvent.key.repeat == SDL_bool.SDL_TRUE)); break; case SDL_EventType.SDL_EVENT_DROP_FILE: this.DragDrop?.Invoke(new DragDropEvent((int) sdlEvent.drop.x, (int) sdlEvent.drop.y, sdlEvent.drop.GetSource() ?? string.Empty)); diff --git a/src/Bliss/CSharp/Windowing/Window.cs b/src/Bliss/CSharp/Windowing/Window.cs index 87f2361..069a809 100644 --- a/src/Bliss/CSharp/Windowing/Window.cs +++ b/src/Bliss/CSharp/Windowing/Window.cs @@ -1,4 +1,3 @@ -using SDL; using Veldrid; namespace Bliss.CSharp.Windowing; @@ -20,37 +19,13 @@ public static class Window { public static IWindow CreateWindow(WindowType type, int width, int height, string title, WindowState state, GraphicsDeviceOptions options, GraphicsBackend preferredBackend, out GraphicsDevice graphicsDevice) { switch (type) { case WindowType.Sdl3: - Sdl3Window window = new Sdl3Window(width, height, title, GetSdl3WindowStates(state) | SDL_WindowFlags.SDL_WINDOW_OPENGL); + Sdl3Window window = new Sdl3Window(width, height, title, state); graphicsDevice = CreateGraphicsDevice(window, options, preferredBackend); return window; default: throw new Exception($"The window type: [{type}] is not supported!"); } } - - /// - /// Converts the specified to the corresponding SDL window flags. - /// - /// The state of the window (e.g., normal, fullscreen, maximized). - /// The SDL window flags that correspond to the specified window state. - private static SDL_WindowFlags GetSdl3WindowStates(WindowState state) { - switch (state) { - case WindowState.Resizable: - return SDL_WindowFlags.SDL_WINDOW_RESIZABLE; - case WindowState.FullScreen: - return SDL_WindowFlags.SDL_WINDOW_FULLSCREEN; - case WindowState.BorderlessFullScreen: - return SDL_WindowFlags.SDL_WINDOW_BORDERLESS; - case WindowState.Maximized: - return SDL_WindowFlags.SDL_WINDOW_MAXIMIZED; - case WindowState.Minimized: - return SDL_WindowFlags.SDL_WINDOW_MINIMIZED; - case WindowState.Hidden: - return SDL_WindowFlags.SDL_WINDOW_HIDDEN; - default: - throw new Exception($"Invalid WindowState: [{state}]"); - } - } private static GraphicsDevice CreateGraphicsDevice(IWindow window, GraphicsDeviceOptions options, GraphicsBackend preferredBackend) { switch (preferredBackend) { diff --git a/src/Bliss/CSharp/Windowing/WindowState.cs b/src/Bliss/CSharp/Windowing/WindowState.cs index 46a7d55..2362c0b 100644 --- a/src/Bliss/CSharp/Windowing/WindowState.cs +++ b/src/Bliss/CSharp/Windowing/WindowState.cs @@ -1,10 +1,45 @@ namespace Bliss.CSharp.Windowing; -public enum WindowState { // TODO: Rework this! +[Flags] +public enum WindowState { + + /// + /// The window is resizable, allowing the user to adjust its size. + /// Resizable, + + /// + /// The window is in full-screen mode, occupying the entire screen. + /// FullScreen, + + /// + /// The window is borderless, removing the title bar and window borders. + /// + BorderlessFullScreen, + + /// + /// The window is maximized, taking up the largest possible area on the screen. + /// Maximized, + + /// + /// The window is minimized, reducing it to an icon or taskbar entry. + /// Minimized, - BorderlessFullScreen, - Hidden + + /// + /// The window is hidden and not visible to the user. + /// + Hidden, + + /// + /// The window captures the mouse, confining its movement to the window area. + /// + CaptureMouse, + + /// + /// The window is always on top of other windows, maintaining its topmost position. + /// + AlwaysOnTop } \ No newline at end of file