diff --git a/.gitmodules b/.gitmodules index 30b5266..40fec6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vendor/directx"] path = GlitchyEngine/vendor/directx url = https://github.com/aharabada/directx-beef.git +[submodule "GlitchyEngine/vendor/imgui-beef"] + path = GlitchyEngine/vendor/imgui-beef + url = https://github.com/qzole/imgui-beef.git diff --git a/BeefSpace.toml b/BeefSpace.toml index a40b1d4..560156f 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -1,5 +1,5 @@ FileVersion = 1 -Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "vendor/directx/DirectX"}} +Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, imgui-beef = {Path = "GlitchyEngine/vendor/imgui-beef/imgui-beef"}, imgui-impl-win32 = {Path = "GlitchyEngine/vendor/imgui-beef/imgui-impl-win32"}, imgui-impl-dx11 = {Path = "GlitchyEngine/vendor/imgui-beef/imgui-impl-dx11"}} [Workspace] StartupProject = "Sandbox" diff --git a/GlitchLog/src/DebugLogger.bf b/GlitchLog/src/DebugLogger.bf index 433a760..30d92c4 100644 --- a/GlitchLog/src/DebugLogger.bf +++ b/GlitchLog/src/DebugLogger.bf @@ -45,7 +45,6 @@ namespace GlitchLog { Runtime.Assert(Debug.IsDebuggerPresent, "The DebugLogger requires a debugger to be present."); } - #if GL_NOLOG || GL_NOTRACE [SkipCall] diff --git a/GlitchyEngine/BeefProj.toml b/GlitchyEngine/BeefProj.toml index 4b9001e..d8cbb75 100644 --- a/GlitchyEngine/BeefProj.toml +++ b/GlitchyEngine/BeefProj.toml @@ -1,5 +1,5 @@ FileVersion = 1 -Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*"} +Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", imgui-beef = "*", imgui-impl-win32 = "*", imgui-impl-dx11 = "*"} [Project] Name = "GlitchyEngine" diff --git a/GlitchyEngine/src/Application.bf b/GlitchyEngine/src/Application.bf index fe64c8a..238ad8f 100644 --- a/GlitchyEngine/src/Application.bf +++ b/GlitchyEngine/src/Application.bf @@ -1,20 +1,33 @@ +using System; using GlitchyEngine.Events; using GlitchyEngine.Platform.Windows; +using GlitchyEngine.Platform.DX11; namespace GlitchyEngine { public class Application { + static Application s_Instance = null; + private Window _window ~ delete _; private bool _running = true; private LayerStack _layerStack = new LayerStack() ~ delete _; + private GameTime _gameTime = new GameTime(true) ~ delete _; + public bool IsRunning => _running; + public Window Window => _window; + + [Inline] + public static Application Get => s_Instance; public this() { - _window = Window.CreateWindow(WindowDescription()); + Runtime.Assert(s_Instance == null, "Tried to create a second application."); + s_Instance = this; + + _window = GlitchyEngine.Window.CreateWindow(WindowDescription()); _window.EventCallback = new => OnEvent; } @@ -35,10 +48,16 @@ namespace GlitchyEngine { while(_running) { + DirectX.ImmediateContext.ClearRenderTargetView(DirectX.BackBufferTarget, .(1, 0, 1)); + + _gameTime.Tick(); + for(Layer layer in _layerStack) - layer.Update(); + layer.Update(_gameTime); _window.Update(); + + DirectX.Present(); } } diff --git a/GlitchyEngine/src/Events/ApplicationEvent.bf b/GlitchyEngine/src/Events/ApplicationEvent.bf index 00007ad..b6a49aa 100644 --- a/GlitchyEngine/src/Events/ApplicationEvent.bf +++ b/GlitchyEngine/src/Events/ApplicationEvent.bf @@ -22,8 +22,8 @@ namespace GlitchyEngine.Events public class WindowResizeEvent : Event, IEvent { - public int32 _width, _height; - public bool _isResizing; + private int32 _width, _height; + private bool _isResizing; /// The new width of the window. public int32 Width = _width; @@ -57,8 +57,8 @@ namespace GlitchyEngine.Events public class WindowMoveEvent : Event, IEvent { - public int32 _x, _y; - public bool _isMoving; + private int32 _x, _y; + private bool _isMoving; /// The new x-coordinate of the window. public int32 X = _x; diff --git a/GlitchyEngine/src/Events/Event.bf b/GlitchyEngine/src/Events/Event.bf index 182fd02..c60a1fa 100644 --- a/GlitchyEngine/src/Events/Event.bf +++ b/GlitchyEngine/src/Events/Event.bf @@ -6,7 +6,7 @@ namespace GlitchyEngine.Events None = 0, WindowClose, WindowResize, WindowFocus, WindowLostFocus, WindowMoved, AppTick, AppUpdate, AppRender, - KeyPressed, KeyReleased, + KeyPressed, KeyReleased, KeyTyped, MouseButtonPressed, MouseButtonReleased, MouseMoved, MouseScrolled } diff --git a/GlitchyEngine/src/Events/KeyEvent.bf b/GlitchyEngine/src/Events/KeyEvent.bf index 8cf4706..cb7cd25 100644 --- a/GlitchyEngine/src/Events/KeyEvent.bf +++ b/GlitchyEngine/src/Events/KeyEvent.bf @@ -53,4 +53,29 @@ namespace GlitchyEngine.Events strBuffer.AppendF("KeyReleasedEvent: {}", _keyCode); } } + + public class KeyTypedEvent : Event, IEvent + { + private char16 _char; + + [Inline] + public char16 Char => _char; + + public override EventCategory Category => .Input | .Keyboard + + public override EventType EventType => .KeyTyped; + public static EventType StaticType => .KeyTyped; + + public override StringView Name => "KeyTyped"; + + public this(char16 char) + { + _char = char; + } + + public override void ToString(String strBuffer) + { + strBuffer.AppendF("KeyTypedEvent: {}", _char); + } + } } diff --git a/GlitchyEngine/src/GameTime.bf b/GlitchyEngine/src/GameTime.bf new file mode 100644 index 0000000..3e05feb --- /dev/null +++ b/GlitchyEngine/src/GameTime.bf @@ -0,0 +1,90 @@ +using System; +using System.Diagnostics; + +namespace GlitchyEngine +{ + /** + * A timer providing functionality to meassure frame times and game runtime. + */ + public class GameTime : Stopwatch + { + private uint64 _frameCount; + + private TimeSpan _totalTime; + private TimeSpan _frameTime; + + /** + The amount of time that has passed since the timer was started. + */ + public TimeSpan TotalTime => _totalTime; + /** + The amount of time that has passed since the start of the last frame. + */ + public TimeSpan FrameTime => _frameTime; + /** + The number of frames that have been computed since the timer was started. + */ + public uint64 FrameCount => _frameCount; + + private Stopwatch _stopWatch ~ delete _; + + public this() : base(){} + + /** + * Initializes a new instance of a GameTime. + * @param startNow If set to true, the timer will start immediately. + * If set to false, the timer has to be started manually. + */ + public this(bool startNow) : base(startNow){} + + /** + * Starts or continues the internal timer. + */ + public new void Start() + { + _stopWatch.Start(); + } + + /** + * Restarts the internal timer and resets the counters. + */ + public new void Restart() + { + _totalTime = 0; + _frameTime = 0; + _frameCount = 0; + base.Restart(); + } + + /** + * Stops the internal timer. + */ + public new void Stop() + { + base.Stop(); + } + + /** + * Resets the timer. + */ + public new void Reset() + { + _totalTime = 0; + _frameTime = 0; + _frameCount = 0; + base.Reset(); + } + + /** + * Tells the timer that a frame has passed and updates the counters. + */ + public void Tick() + { + TimeSpan old = _totalTime; + _totalTime = Elapsed; + _frameTime = _totalTime - old; + + _frameCount++; + } + } +} diff --git a/GlitchyEngine/src/ImGui/ImGuiLayer.bf b/GlitchyEngine/src/ImGui/ImGuiLayer.bf new file mode 100644 index 0000000..9a948e7 --- /dev/null +++ b/GlitchyEngine/src/ImGui/ImGuiLayer.bf @@ -0,0 +1,182 @@ +using System; +using imgui_beef; +using GlitchyEngine.Events; + +// Temporary +using DirectX.Windows.VirtualKeyCodes; +using GlitchyEngine.Platform.DX11; + +namespace GlitchyEngine.ImGui +{ + public class ImGuiLayer : Layer + { + public this() : base("ImGuiLayer") { } + + public override void OnAttach() + { + Log.EngineLogger.Trace("Initializing ImGui..."); + + ImGui.CHECKVERSION(); + ImGui.CreateContext(); + ImGui.StyleColorsDark(); + + ref ImGui.IO io = ref ImGui.GetIO(); + io.BackendFlags |= .HasMouseCursors | .HasSetMousePos; + + // Todo: Temporary, needs own keymap + // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. + io.KeyMap[(int32)ImGui.Key.Tab] = VK_TAB; + io.KeyMap[(int32)ImGui.Key.LeftArrow] = VK_LEFT; + io.KeyMap[(int32)ImGui.Key.RightArrow] = VK_RIGHT; + io.KeyMap[(int32)ImGui.Key.UpArrow] = VK_UP; + io.KeyMap[(int32)ImGui.Key.DownArrow] = VK_DOWN; + io.KeyMap[(int32)ImGui.Key.PageUp] = VK_PRIOR; + io.KeyMap[(int32)ImGui.Key.PageDown] = VK_NEXT; + io.KeyMap[(int32)ImGui.Key.Home] = VK_HOME; + io.KeyMap[(int32)ImGui.Key.End] = VK_END; + io.KeyMap[(int32)ImGui.Key.Insert] = VK_INSERT; + io.KeyMap[(int32)ImGui.Key.Delete] = VK_DELETE; + io.KeyMap[(int32)ImGui.Key.Backspace] = VK_BACK; + io.KeyMap[(int32)ImGui.Key.Space] = VK_SPACE; + io.KeyMap[(int32)ImGui.Key.Enter] = VK_RETURN; + io.KeyMap[(int32)ImGui.Key.Escape] = VK_ESCAPE; + io.KeyMap[(int32)ImGui.Key.KeyPadEnter] = VK_RETURN; + io.KeyMap[(int32)ImGui.Key.A] = (int32)'A'; + io.KeyMap[(int32)ImGui.Key.C] = (int32)'C'; + io.KeyMap[(int32)ImGui.Key.V] = (int32)'V'; + io.KeyMap[(int32)ImGui.Key.X] = (int32)'X'; + io.KeyMap[(int32)ImGui.Key.Y] = (int32)'Y'; + io.KeyMap[(int32)ImGui.Key.Z] = (int32)'Z'; + + // Todo: temporary, needs to be platform independant + ImGuiImplDx11.Init(Platform.DX11.DirectX.Device, Platform.DX11.DirectX.ImmediateContext); + } + + public override void OnDetach() + { + } + + public override void OnEvent(Event event) + { + EventDispatcher dispatcher = scope EventDispatcher(event); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.DisplaySize = .(e.Width, e.Height); + io.DisplayFramebufferScale = .(1.0f, 1.0f); + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.MousePos = ImGui.Vec2(e.PositionX, e.PositionY); + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + + switch(e.MouseButton) + { + case .LeftButton: + io.MouseDown[(uint)ImGui.MouseButton.Left] = true; + case .RightButton: + io.MouseDown[(uint)ImGui.MouseButton.Right] = true; + case .MiddleButton: + io.MouseDown[(uint)ImGui.MouseButton.Middle] = true; + default: + } + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + + switch(e.MouseButton) + { + case .LeftButton: + io.MouseDown[(uint)ImGui.MouseButton.Left] = false; + case .RightButton: + io.MouseDown[(uint)ImGui.MouseButton.Right] = false; + case .MiddleButton: + io.MouseDown[(uint)ImGui.MouseButton.Middle] = false; + default: + } + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.MouseWheel += e.YOffset; + io.MouseWheelH += e.XOffset; // Todo: horizontal mousewheel inverted?! + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.KeysDown[e.KeyCode] = true; + + io.KeyCtrl = io.KeysDown[VK_CONTROL]; + io.KeyShift = io.KeysDown[VK_SHIFT]; + io.KeyAlt = io.KeysDown[VK_MENU]; + io.KeySuper = io.KeysDown[VK_LWIN] || io.KeysDown[VK_RWIN]; + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.KeysDown[e.KeyCode] = false; + + io.KeyCtrl = io.KeysDown[VK_CONTROL]; + io.KeyShift = io.KeysDown[VK_SHIFT]; + io.KeyAlt = io.KeysDown[VK_MENU]; + io.KeySuper = io.KeysDown[VK_LWIN] || io.KeysDown[VK_RWIN]; + + return false; + }); + + dispatcher.Dispatch(scope (e) => + { + ref ImGui.IO io = ref ImGui.GetIO(); + io.AddInputCharacterUTF16((int16)e.Char); + + return false; + }); + } + + bool showDemo = true; + public override void Update(GameTime gameTime) + { + var v = DirectX.ImmediateContext; + + v.OutputMerger.SetRenderTargets(1, &DirectX.BackBufferTarget, null); + + ref ImGui.IO io = ref ImGui.GetIO(); + + let window = Application.Get.Window; + io.DisplaySize = .(window.Width, window.Height); + io.DeltaTime = (float)gameTime.FrameTime.TotalSeconds; + + ImGuiImplDx11.NewFrame(); + ImGui.NewFrame(); + + ImGui.ShowDemoWindow(&showDemo); + + ImGui.Render(); + ImGuiImplDx11.RenderDrawData(ImGui.GetDrawData()); + } + } +} diff --git a/GlitchyEngine/src/Layer.bf b/GlitchyEngine/src/Layer.bf index b996e01..180ad86 100644 --- a/GlitchyEngine/src/Layer.bf +++ b/GlitchyEngine/src/Layer.bf @@ -5,21 +5,22 @@ namespace GlitchyEngine { public abstract class Layer { - protected String _debugName; + protected String _debugName ~ delete _; [Inline] public StringView Name => _debugName; - [AllowAppend] + //[AllowAppend] public this(StringView name = "Layer") { - String debugName = append String(name); - _debugName = debugName; + //String debugName = append String(name); + //_debugName = debugName; + _debugName = new String(name); } public virtual void OnAttach() { } public virtual void OnDetach() { } - public virtual void Update() { } + public virtual void Update(GameTime gameTime) { } public virtual void OnEvent(Event event) { } } } diff --git a/GlitchyEngine/src/LayerStack.bf b/GlitchyEngine/src/LayerStack.bf index 3b335b5..1190201 100644 --- a/GlitchyEngine/src/LayerStack.bf +++ b/GlitchyEngine/src/LayerStack.bf @@ -20,6 +20,7 @@ namespace GlitchyEngine public void PushLayer(Layer ownLayer) { _layers.Insert(_insertIndex++, ownLayer); + ownLayer.OnAttach(); } /** @@ -30,6 +31,7 @@ namespace GlitchyEngine public void PushOverlay(Layer ownOverlay) { _layers.Add(ownOverlay); + ownOverlay.OnAttach(); } /** @@ -41,6 +43,7 @@ namespace GlitchyEngine if(_layers.Remove(layer)) { _insertIndex--; + layer.OnDetach(); } } @@ -50,7 +53,10 @@ namespace GlitchyEngine */ public void PopOverlay(Layer overlay) { - _layers.Remove(overlay); + if(_layers.Remove(overlay)) + { + overlay.OnDetach(); + } } /** diff --git a/GlitchyEngine/src/Platform/DX11/DirectX.bf b/GlitchyEngine/src/Platform/DX11/DirectX.bf new file mode 100644 index 0000000..0850f96 --- /dev/null +++ b/GlitchyEngine/src/Platform/DX11/DirectX.bf @@ -0,0 +1,128 @@ +using System; +using DirectX; +using DirectX.D3D11; +using DirectX.Common; +using System.Diagnostics; +using DirectX.DXGI; +using DirectX.DXGI.DXGI1_2; +using static System.Windows; + +namespace GlitchyEngine.Platform.DX11 +{ + public static class DirectX + { + public static ID3D11Device* Device; + public static ID3D11DeviceContext* ImmediateContext; + + public static IDXGIDevice* DxgiDevice; + public static IDXGISwapChain1* SwapChain; + + public static ID3D11RenderTargetView* BackBufferTarget; + public static Viewport BackBufferViewport; + + static HWnd _windowHandle; + + static ~this() + { + Shutdown(); + } + + public static void Init(HWnd windowHandle, uint32 width, uint32 height) + { + _windowHandle = windowHandle; + + InitDevice(); + UpdateSwapchain(width, height); + } + + /** + * Initializes the Device and ImmediateContext. + */ + static void InitDevice() + { + IUnknown.ReleaseAndNull!(ref Device); + IUnknown.ReleaseAndNull!(ref ImmediateContext); + + Log.EngineLogger.Trace("Creating D3D11 Device and Context..."); + + DeviceCreationFlags deviceFlags = .None; +#if DEBUG + deviceFlags |= .Debug; +#endif + + FeatureLevel[] levels = scope .(.Level_11_0); + + FeatureLevel deviceLevel = ?; + var deviceResult = D3D11.CreateDevice(null, .Hardware, 0, deviceFlags, levels, &Device, &deviceLevel, &ImmediateContext); + Debug.Assert(deviceResult.Succeeded, scope $"Failed to create D3D11 Device. Message(0x{(int32)deviceResult}): {deviceResult}"); + + Log.EngineLogger.Trace("D3D11 Device and Context created (Feature level: {})", deviceLevel); + } + + /** + * Initializes the swapchain. + */ + public static void UpdateSwapchain(uint32 width, uint32 height) + { + uint32 backBufferCount = 2; + Format backBufferFormat = .R8G8B8A8_UNorm; + Format backBufferViewFormat = .R8G8B8A8_UNorm; // _SRGB + + if(SwapChain != null) + { + BackBufferTarget.Release(); + + SwapChain.ResizeBuffers(backBufferCount, width, height, backBufferFormat, .None); + } + else + { + Device.QueryInterface(out DxgiDevice); + + DxgiDevice.GetAdapter(let adapter); + adapter.GetParent(let factory); + adapter.Release(); + + SwapChainDescription1 swDesc = .(); + swDesc.Width = width; + swDesc.Height = height; + swDesc.Format = backBufferFormat; + swDesc.SampleDescription = .(1, 0); + swDesc.BufferUsage = .RenderTargetOutput; + swDesc.BufferCount = backBufferCount; + swDesc.SwapEffect = .FlipDiscard; + + SwapChainFullscreenDescription fsSwapChainDesc = .(); + fsSwapChainDesc.Windowed = true; + + factory.CreateSwapChainForHwnd((.)Device, _windowHandle, ref swDesc, &fsSwapChainDesc, null, &SwapChain); + + factory.Release(); + } + + SwapChain.GetBuffer(0, let backBuffer); + + RenderTargetViewDescription rtvDesc = .(backBuffer, .Texture2D, backBufferViewFormat); + Device.CreateRenderTargetView(backBuffer, &rtvDesc, &BackBufferTarget); + + BackBufferViewport = Viewport(0, 0, width, height, 0.0f, 1.0f); + + backBuffer.Release(); + } + + public static void Shutdown() + { + IUnknown.ReleaseAndNull!(ref Device); + IUnknown.ReleaseAndNull!(ref ImmediateContext); + + IUnknown.ReleaseAndNull!(ref DxgiDevice); + IUnknown.ReleaseAndNull!(ref SwapChain); + + IUnknown.ReleaseAndNull!(ref BackBufferTarget); + } + + public static void Present() + { + SwapChain.Present(Application.Get.Window.IsVSync ? 1 : 0, .None); + } + } +} diff --git a/GlitchyEngine/src/Platform/Windows/WindowsWindow.bf b/GlitchyEngine/src/Platform/Windows/WindowsWindow.bf index e06f578..895270b 100644 --- a/GlitchyEngine/src/Platform/Windows/WindowsWindow.bf +++ b/GlitchyEngine/src/Platform/Windows/WindowsWindow.bf @@ -6,6 +6,9 @@ using DirectX.Windows.Kernel32; using DirectX.Windows.WindowMessages; using GlitchyEngine.Events; using System.Diagnostics; +using imgui_beef; +using GlitchyEngine.Platform.DX11; +using static System.Windows; namespace GlitchyEngine.Platform.Windows { @@ -22,6 +25,8 @@ namespace GlitchyEngine.Platform.Windows private String _title ~ delete _; + private bool _isVSync = true; + public override int32 MinWidth { get => _minMaxInfo.MinimumTrackingSize.x; @@ -38,7 +43,7 @@ namespace GlitchyEngine.Platform.Windows get => _minMaxInfo.MaximumTrackingSize.x; set => _minMaxInfo.MaximumTrackingSize.x = value; } - + public override int32 MaxHeight { get => _minMaxInfo.MaximumTrackingSize.y; @@ -93,7 +98,7 @@ namespace GlitchyEngine.Platform.Windows { get { - if(_title == null) + if (_title == null) LoadTitle(); return _title; @@ -104,8 +109,8 @@ namespace GlitchyEngine.Platform.Windows public override bool IsVSync { - get; - set; + get => _isVSync; + set => _isVSync = value; } #if GE_WINDOWS @@ -135,16 +140,16 @@ namespace GlitchyEngine.Platform.Windows _windowClass.WindowProcedure = => MessageHandler; _windowClass.HInstance = (.)_instanceHandle; - if(desc.Icon.Ptr != null) + if (desc.Icon.Ptr != null) _windowClass.Icon = LoadImageW(0, desc.Icon.ToScopedNativeWChar!(), .Icon, 0, 0, .LoadFromFile); else _windowClass.Icon = 0; - + _windowClass.Cursor = LoadCursorW(0, IDC_ARROW); _windowClass.BackgroundBrush = (HBRUSH)SystemColor.WindowFrame; _windowClass.ClassName = "GlitchyEngineWindow".ToScopedNativeWChar!(); - if(RegisterClassExW(ref _windowClass) == 0) + if (RegisterClassExW(ref _windowClass) == 0) { Log.EngineLogger.Error("Failed to register window class.", (HResult)GetLastError()); Runtime.FatalError("Failed to register window class"); @@ -158,24 +163,29 @@ namespace GlitchyEngine.Platform.Windows SetWindowLongPtrW(_windowHandle, GWL_USERDATA, (int)myPtr); LoadWindowRectangle(); - + Log.EngineLogger.Trace("Created window \"{}\" ({}, {})", Title, Width, Height); + + DirectX.Init(_windowHandle, (.)Width, (.)Height); } private bool _isResizingOrMoving; private bool _isMinimized; + [CLink] + static extern IntBool IsWindowUnicode(HWND whnd); + private static LRESULT MessageHandler(HWND hwnd, uint32 uMsg, WPARAM wParam, LPARAM lParam) { void* windowPtr = (void*)GetWindowLongPtrW(hwnd, GWL_USERDATA); WindowsWindow window = (WindowsWindow)Internal.UnsafeCastToObject(windowPtr); - - if(window == null) + + if (window == null) { return DefWindowProcW(hwnd, uMsg, wParam, lParam); } - - switch(uMsg) + + switch (uMsg) { //// //// Sizing and Moving @@ -184,20 +194,20 @@ namespace GlitchyEngine.Platform.Windows // Window min/max size requested case WM_GETMINMAXINFO: { - MinMaxInfo *info = (.)(void*)lParam; + MinMaxInfo* info = (.)(void*)lParam; info.MinimumTrackingSize = window._minMaxInfo.MinimumTrackingSize; info.MaximumTrackingSize = window._minMaxInfo.MaximumTrackingSize; } // Window size changed case WM_SIZE: { - if(wParam == (.)ResizingType.Minimized) + if (wParam == (.)ResizingType.Minimized) { - window._isMinimized = true; + window._isMinimized = true; } else if (window._isMinimized) { - window._isMinimized = false; + window._isMinimized = false; } else { @@ -210,13 +220,13 @@ namespace GlitchyEngine.Platform.Windows // Window position changed case WM_MOVE: { - if(wParam == (.)ResizingType.Minimized) + if (wParam == (.)ResizingType.Minimized) { - window._isMinimized = true; + window._isMinimized = true; } else if (window._isMinimized) { - window._isMinimized = false; + window._isMinimized = false; } else { @@ -228,12 +238,14 @@ namespace GlitchyEngine.Platform.Windows } // Window resizing/moving started case WM_ENTERSIZEMOVE: - window._isResizingOrMoving = true; + window._isResizingOrMoving = true; // Window resizing/moving ended case WM_EXITSIZEMOVE: { window._isResizingOrMoving = false; + DirectX.UpdateSwapchain((.)window.Width, (.)window.Height); + var resEvent = scope WindowResizeEvent(window._clientRect.Width, window._clientRect.Height, false); window._eventCallback(resEvent); var moveEvent = scope WindowMoveEvent(window._clientRect.X, window._clientRect.Y, false); @@ -296,7 +308,7 @@ namespace GlitchyEngine.Platform.Windows case WM_XBUTTONDOWN: { MouseButton button = .None; - if(HighOrder!((int64)wParam) == 1) + if (HighOrder!((int64)wParam) == 1) button = .XButton1; else button = .XButton2; @@ -307,7 +319,7 @@ namespace GlitchyEngine.Platform.Windows case WM_XBUTTONUP: { MouseButton button = .None; - if(HighOrder!((int64)wParam) == 1) + if (HighOrder!((int64)wParam) == 1) button = .XButton1; else button = .XButton2; @@ -334,7 +346,7 @@ namespace GlitchyEngine.Platform.Windows case WM_MOUSEMOVE: { SplitHighAndLowOrder!(lParam, let x, let y); - + var event = scope MouseMovedEvent(x, y); window._eventCallback(event); } @@ -344,6 +356,13 @@ namespace GlitchyEngine.Platform.Windows //// //// Application //// + case WM_CHAR: + { + var event = scope KeyTypedEvent((char16)wParam); + window._eventCallback(event); + + return 0; + } // Window title changed case WM_SETTEXT: @@ -355,8 +374,8 @@ namespace GlitchyEngine.Platform.Windows case WM_SYSCOMMAND: { /* Remove beeping sound when ALT + some key is pressed. */ - if ( wParam == SC_KEYMENU ) - return 0; + if (wParam == SC_KEYMENU) + return 0; } // Window closing case WM_CLOSE: @@ -380,7 +399,7 @@ namespace GlitchyEngine.Platform.Windows DispatchMessageW(&message); } } - + private void LoadWindowRectangle() { GetWindowRect(_windowHandle, let rectangle); @@ -396,6 +415,9 @@ namespace GlitchyEngine.Platform.Windows SetWindowPos(_windowHandle, 0, _clientRect.X, _clientRect.Y, _clientRect.Width, _clientRect.Height, 0); } + [LinkName(.C)] + private static extern IntBool SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int32 X, int32 Y, int32 cx, int32 cy, uint32 uFlags); + /** * Gets the window title via WinApi and stores it in _title. */ diff --git a/GlitchyEngine/src/Program.bf b/GlitchyEngine/src/Program.bf index 600a1f8..37012c1 100644 --- a/GlitchyEngine/src/Program.bf +++ b/GlitchyEngine/src/Program.bf @@ -3,6 +3,8 @@ using GlitchLog; using System.Diagnostics; using GlitchyEngine.Platform.Windows; +using imgui_beef; + namespace GlitchyEngine { class Program diff --git a/GlitchyEngine/vendor/imgui-beef b/GlitchyEngine/vendor/imgui-beef new file mode 160000 index 0000000..cdc410f --- /dev/null +++ b/GlitchyEngine/vendor/imgui-beef @@ -0,0 +1 @@ +Subproject commit cdc410faf55b854d84fe6cb50a856f9f65190acc diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index a9cdf4d..64eb164 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -3,6 +3,7 @@ using GlitchyEngine; using GlitchyEngine.Events; using System.Diagnostics; using GlitchLog; +using GlitchyEngine.ImGui; namespace Sandbox { @@ -11,13 +12,13 @@ namespace Sandbox [AllowAppend] public this() : base("Example") { } - public override void Update() + public override void Update(GameTime gameTime) { Log.ClientLogger.Info("ExampleLayer.Update"); // Just for temporary vsyncing // Todo: remove - DwmFlush(); + //DwmFlush(); } [CLink, Import("Dwmapi.lib")] @@ -34,6 +35,7 @@ namespace Sandbox public this() { PushLayer(new ExampleLayer()); + PushOverlay(new ImGuiLayer()); } [Export, LinkName("CreateApplication")]