refactor: extract window out of engine

This commit is contained in:
light7734 2025-07-11 01:42:56 +03:30
parent 03e8e11111
commit eb428d11d6
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
18 changed files with 58 additions and 586 deletions

View file

@ -10,6 +10,7 @@ add_subdirectory(./camera)
add_subdirectory(./input) add_subdirectory(./input)
add_subdirectory(./ui) add_subdirectory(./ui)
add_subdirectory(./window)
add_subdirectory(./renderer) add_subdirectory(./renderer)
add_subdirectory(./ecs) add_subdirectory(./ecs)
add_subdirectory(./engine) add_subdirectory(./engine)

View file

@ -5,7 +5,6 @@ if(NOT WIN32)
debug/instrumentor.cpp debug/instrumentor.cpp
layer/layer.cpp layer/layer.cpp
layer/layer_stack.cpp layer/layer_stack.cpp
os/linux/l_window.cpp
time/timer.cpp time/timer.cpp
utils/serializer.cpp utils/serializer.cpp
) )
@ -16,24 +15,25 @@ else()
debug/instrumentor.cpp debug/instrumentor.cpp
layer/layer.cpp layer/layer.cpp
layer/layer_stack.cpp layer/layer_stack.cpp
os/windows/w_window.cpp
time/timer.cpp time/timer.cpp
utils/serializer.cpp utils/serializer.cpp
) )
endif() endif()
target_link_libraries( target_link_libraries(engine
engine PUBLIC
PUBLIC renderer renderer
PUBLIC glad logger
PUBLIC logger ui
PUBLIC opengl::opengl asset_parser
PUBLIC glfw asset_manager
PUBLIC ui lt_debug
PUBLIC asset_parser ecs
PUBLIC asset_manager window
PUBLIC yaml-cpp::yaml-cpp
PUBLIC EnTT::EnTT glad
PUBLIC lt_debug
PUBLIC ecs opengl::opengl
yaml-cpp::yaml-cpp
EnTT::EnTT
) )

View file

@ -1,9 +1,6 @@
#pragma once #pragma once
#include <engine/layer/layer_stack.hpp>
#include <engine/time/timer.hpp> #include <engine/time/timer.hpp>
#include <input/input.hpp>
#include <ui/ui.hpp>
namespace lt { namespace lt {
@ -11,6 +8,8 @@ class Renderer;
class Window; class Window;
class Event; class Event;
class GraphicsContext; class GraphicsContext;
class UserInterface;
class LayerStack;
extern Scope<class Application> create_application(); extern Scope<class Application> create_application();
@ -25,7 +24,7 @@ public:
auto operator=(Application &&) -> Application & = delete; auto operator=(Application &&) -> Application & = delete;
virtual ~Application() = default; virtual ~Application();
[[nodiscard]] auto sanity_check() const -> bool; [[nodiscard]] auto sanity_check() const -> bool;

View file

@ -1,32 +1,16 @@
#pragma once #pragma once
// core
#include <engine/core/application.hpp> #include <engine/core/application.hpp>
#include <engine/core/window.hpp> #include <engine/layer/layer.hpp>
#include <engine/layer/layer_stack.hpp>
// debug #include <engine/time/timer.hpp>
#include <imgui.h>
#include <logger/logger.hpp> #include <logger/logger.hpp>
// graphics
#include <renderer/framebuffer.hpp> #include <renderer/framebuffer.hpp>
#include <renderer/graphics_context.hpp> #include <renderer/graphics_context.hpp>
#include <renderer/renderer.hpp> #include <renderer/renderer.hpp>
#include <renderer/texture.hpp> #include <renderer/texture.hpp>
// layer
#include <engine/layer/layer.hpp>
#include <engine/layer/layer_stack.hpp>
// time
#include <engine/time/timer.hpp>
// base
// third party
#include <imgui.h>
// entry point
#ifdef LIGHT_ENTRY_POINT #ifdef LIGHT_ENTRY_POINT
#include <engine/core/entrypoint.hpp> #include <engine/core/entrypoint.hpp>
#endif #endif

View file

@ -1,244 +0,0 @@
#include <GLFW/glfw3.h>
#include <engine/events/char.hpp>
#include <engine/events/event.hpp>
#include <engine/events/keyboard.hpp>
#include <engine/events/mouse.hpp>
#include <engine/events/window.hpp>
#include <renderer/graphics_context.hpp>
#include <engine/platform/os/windows/w_window.hpp>
extern "C"
{
// Force Machine to use Dedicated Graphics
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; // NVidia
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; // AMD
}
namespace lt {
Scope<Window> Window::create(std::function<void(Event &)> callback)
{
return create_scope<wWindow>(callback);
}
wWindow::wWindow(std::function<void(Event &)> callback)
: m_handle(nullptr)
, m_event_callback(callback)
{
// init glfw
lt_assert(glfwInit(), "wWindow::wWindow: failed to initialize 'glfw'");
// create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
lt_assert(m_handle, "wWindow::wWindow: glfwCreateWindow: failed to create 'GLFWwindow'");
// bind event stuff
glfwSetWindowUserPointer(m_handle, &m_event_callback);
bind_glfw_events();
// create graphics context
m_graphics_context = GraphicsContext::create(GraphicsAPI::DirectX, m_handle);
lt_assert(m_graphics_context, "wWindow::wWindow: failed to create 'GraphicsContext'");
}
wWindow::~wWindow()
{
glfwDestroyWindow(m_handle);
}
void wWindow::poll_events()
{
glfwPollEvents();
}
void wWindow::on_event(const Event &event)
{
switch (event.get_event_type())
{
/* closed */
case EventType::WindowClosed: b_Closed = true; break;
/* resized */
case EventType::WindowResized: on_window_resize((const WindowResizedEvent &)event); break;
}
}
void wWindow::on_window_resize(const WindowResizedEvent &event)
{
m_properties.size = event.get_size();
}
void wWindow::
set_properties(const WindowProperties &properties, bool overrideVisiblity /* = false */)
{
// save the visibility status and re-assign if 'overrideVisibility' is false
bool visible = overrideVisiblity ? properties.visible : m_properties.visible;
m_properties = properties;
m_properties.visible = visible;
// set properties
set_title(properties.title);
set_size(properties.size);
set_v_sync(properties.vsync);
set_visibility(visible);
}
void wWindow::set_title(const std::string &title)
{
m_properties.title = title;
glfwSetWindowTitle(m_handle, m_properties.title.c_str());
}
void wWindow::set_size(const glm::uvec2 &size, bool additive /* = false */)
{
m_properties.size.x = size.x == 0u ? m_properties.size.x :
additive ? m_properties.size.x + size.x :
size.x;
m_properties.size.y = size.y == 0u ? m_properties.size.y :
additive ? m_properties.size.y + size.y :
size.y;
glfwSetWindowSize(m_handle, size.x, size.y);
}
void wWindow::set_v_sync(bool vsync, bool toggle /* = false */)
{
m_properties.vsync = toggle ? !m_properties.vsync : vsync;
glfwSwapInterval(m_properties.vsync);
}
void wWindow::set_visibility(bool visible, bool toggle)
{
m_properties.visible = toggle ? !m_properties.visible : visible;
if (m_properties.visible)
glfwShowWindow(m_handle);
else
glfwHideWindow(m_handle);
}
void wWindow::bind_glfw_events()
{
//============================== MOUSE_EVENTS ==============================//
/* cursor position */
glfwSetCursorPosCallback(m_handle, [](GLFWwindow *window, double xpos, double ypos) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
MouseMovedEvent event(xpos, ypos);
callback(event);
});
/* mouse button */
glfwSetMouseButtonCallback(m_handle, [](GLFWwindow *window, int button, int action, int mods) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
ButtonPressedEvent event(button);
callback(event);
}
else if (action == GLFW_RELEASE)
{
ButtonReleasedEvent event(button);
callback(event);
}
});
/* scroll */
glfwSetScrollCallback(m_handle, [](GLFWwindow *window, double xoffset, double yoffset) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WheelScrolledEvent event(yoffset);
callback(event);
});
//============================== MOUSE_EVENTS ==============================//
//============================== KEYBOARD_EVENTS ==============================//
/* key */
glfwSetKeyCallback(
m_handle,
[](GLFWwindow *window, int key, int scancode, int action, int mods) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
KeyPressedEvent event(key);
callback(event);
}
else if (action == GLFW_RELEASE)
{
KeyReleasedEvent event(key);
callback(event);
}
}
);
/* char */
glfwSetCharCallback(m_handle, [](GLFWwindow *window, unsigned int character) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
SetCharEvent event(character);
callback(event);
});
//============================== KEYBOARD_EVENTS ==============================//
//============================== WINDOW_EVENTS ==============================//
/* window position */
glfwSetWindowPosCallback(m_handle, [](GLFWwindow *window, int xpos, int ypos) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowMovedEvent event(xpos, ypos);
callback(event);
});
/* window size */
glfwSetWindowSizeCallback(m_handle, [](GLFWwindow *window, int width, int height) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowResizedEvent event(width, height);
callback(event);
});
/* window close */
glfwSetWindowCloseCallback(m_handle, [](GLFWwindow *window) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowClosedEvent event;
callback(event);
});
/* window focus */
glfwSetWindowFocusCallback(m_handle, [](GLFWwindow *window, int focus) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (focus == GLFW_TRUE)
{
WindowGainFocusEvent event;
callback(event);
}
else
{
WindowLostFocusEvent event;
callback(event);
}
});
//============================== WINDOW_EVENTS ==============================// }
}
} // namespace lt

View file

@ -1,45 +0,0 @@
#pragma once
#include <engine/core/window.hpp>
struct GLFWwindow;
namespace lt {
class Event;
class WindowResizedEvent;
class wWindow: public Window
{
public:
wWindow(std::function<void(Event &)> callback);
~wWindow();
void poll_events() override;
void on_event(const Event &event) override;
void set_properties(const WindowProperties &properties, bool overrideVisibility = false)
override;
void set_title(const std::string &title) override;
void set_size(const glm::uvec2 &size, bool additive = false) override;
void set_v_sync(bool vsync, bool toggle = false) override;
void set_visibility(bool visible, bool toggle = false) override;
private:
GLFWwindow *m_handle;
std::function<void(Event &)> m_event_callback;
void on_window_resize(const WindowResizedEvent &event);
void bind_glfw_events();
};
} // namespace lt

View file

@ -1,18 +1,20 @@
#include <asset_manager/asset_manager.hpp> #include <asset_manager/asset_manager.hpp>
#include <debug/assertions.hpp> #include <debug/assertions.hpp>
#include <engine/core/application.hpp> #include <engine/core/application.hpp>
#include <engine/core/window.hpp>
#include <engine/layer/layer.hpp> #include <engine/layer/layer.hpp>
#include <engine/layer/layer_stack.hpp>
#include <engine/time/timer.hpp> #include <engine/time/timer.hpp>
#include <input/events/event.hpp> #include <input/events/event.hpp>
#include <input/events/keyboard.hpp> #include <input/events/keyboard.hpp>
#include <input/events/window.hpp> #include <input/events/window.hpp>
#include <input/input.hpp>
#include <ranges> #include <ranges>
#include <renderer/blender.hpp> #include <renderer/blender.hpp>
#include <renderer/graphics_context.hpp> #include <renderer/graphics_context.hpp>
#include <renderer/render_command.hpp> #include <renderer/render_command.hpp>
#include <renderer/renderer.hpp> #include <renderer/renderer.hpp>
#include <ui/ui.hpp> #include <ui/ui.hpp>
#include <window/linux/window.hpp>
namespace lt { namespace lt {
@ -70,6 +72,13 @@ Application::Application(): m_window(nullptr)
m_layer_stack = create_scope<LayerStack>(); m_layer_stack = create_scope<LayerStack>();
} }
Application::~Application()
{
/** This is required to make forward-declarations possible:
* https://stackoverflow.com/questions/34072862/why-is-error-invalid-application-of-sizeof-to-an-incomplete-type-using-uniqu
*/
}
void Application::game_loop() void Application::game_loop()
{ {
m_window->set_visibility(true); m_window->set_visibility(true);

View file

@ -1,244 +0,0 @@
#include <GLFW/glfw3.h>
#include <engine/events/char.hpp>
#include <engine/events/event.hpp>
#include <engine/events/keyboard.hpp>
#include <engine/events/mouse.hpp>
#include <engine/events/window.hpp>
#include <renderer/graphics_context.hpp>
#include <engine/platform/os/windows/w_window.hpp>
extern "C"
{
// Force Machine to use Dedicated Graphics
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; // NVidia
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; // AMD
}
namespace lt {
Scope<Window> Window::create(std::function<void(Event &)> callback)
{
return create_scope<wWindow>(callback);
}
wWindow::wWindow(std::function<void(Event &)> callback)
: m_handle(nullptr)
, m_event_callback(callback)
{
// init glfw
lt_assert(glfwInit(), "wWindow::wWindow: failed to initialize 'glfw'");
// create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
lt_assert(m_handle, "wWindow::wWindow: glfwCreateWindow: failed to create 'GLFWwindow'");
// bind event stuff
glfwSetWindowUserPointer(m_handle, &m_event_callback);
bind_glfw_events();
// create graphics context
m_graphics_context = GraphicsContext::create(GraphicsAPI::DirectX, m_handle);
lt_assert(m_graphics_context, "wWindow::wWindow: failed to create 'GraphicsContext'");
}
wWindow::~wWindow()
{
glfwDestroyWindow(m_handle);
}
void wWindow::poll_events()
{
glfwPollEvents();
}
void wWindow::on_event(const Event &event)
{
switch (event.get_event_type())
{
/* closed */
case EventType::WindowClosed: b_Closed = true; break;
/* resized */
case EventType::WindowResized: on_window_resize((const WindowResizedEvent &)event); break;
}
}
void wWindow::on_window_resize(const WindowResizedEvent &event)
{
m_properties.size = event.get_size();
}
void wWindow::
set_properties(const WindowProperties &properties, bool overrideVisiblity /* = false */)
{
// save the visibility status and re-assign if 'overrideVisibility' is false
bool visible = overrideVisiblity ? properties.visible : m_properties.visible;
m_properties = properties;
m_properties.visible = visible;
// set properties
set_title(properties.title);
set_size(properties.size);
set_v_sync(properties.vsync);
set_visibility(visible);
}
void wWindow::set_title(const std::string &title)
{
m_properties.title = title;
glfwSetWindowTitle(m_handle, m_properties.title.c_str());
}
void wWindow::set_size(const glm::uvec2 &size, bool additive /* = false */)
{
m_properties.size.x = size.x == 0u ? m_properties.size.x :
additive ? m_properties.size.x + size.x :
size.x;
m_properties.size.y = size.y == 0u ? m_properties.size.y :
additive ? m_properties.size.y + size.y :
size.y;
glfwSetWindowSize(m_handle, size.x, size.y);
}
void wWindow::set_v_sync(bool vsync, bool toggle /* = false */)
{
m_properties.vsync = toggle ? !m_properties.vsync : vsync;
glfwSwapInterval(m_properties.vsync);
}
void wWindow::set_visibility(bool visible, bool toggle)
{
m_properties.visible = toggle ? !m_properties.visible : visible;
if (m_properties.visible)
glfwShowWindow(m_handle);
else
glfwHideWindow(m_handle);
}
void wWindow::bind_glfw_events()
{
//============================== MOUSE_EVENTS ==============================//
/* cursor position */
glfwSetCursorPosCallback(m_handle, [](GLFWwindow *window, double xpos, double ypos) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
MouseMovedEvent event(xpos, ypos);
callback(event);
});
/* mouse button */
glfwSetMouseButtonCallback(m_handle, [](GLFWwindow *window, int button, int action, int mods) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
ButtonPressedEvent event(button);
callback(event);
}
else if (action == GLFW_RELEASE)
{
ButtonReleasedEvent event(button);
callback(event);
}
});
/* scroll */
glfwSetScrollCallback(m_handle, [](GLFWwindow *window, double xoffset, double yoffset) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WheelScrolledEvent event(yoffset);
callback(event);
});
//============================== MOUSE_EVENTS ==============================//
//============================== KEYBOARD_EVENTS ==============================//
/* key */
glfwSetKeyCallback(
m_handle,
[](GLFWwindow *window, int key, int scancode, int action, int mods) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
KeyPressedEvent event(key);
callback(event);
}
else if (action == GLFW_RELEASE)
{
KeyReleasedEvent event(key);
callback(event);
}
}
);
/* char */
glfwSetCharCallback(m_handle, [](GLFWwindow *window, unsigned int character) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
SetCharEvent event(character);
callback(event);
});
//============================== KEYBOARD_EVENTS ==============================//
//============================== WINDOW_EVENTS ==============================//
/* window position */
glfwSetWindowPosCallback(m_handle, [](GLFWwindow *window, int xpos, int ypos) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowMovedEvent event(xpos, ypos);
callback(event);
});
/* window size */
glfwSetWindowSizeCallback(m_handle, [](GLFWwindow *window, int width, int height) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowResizedEvent event(width, height);
callback(event);
});
/* window close */
glfwSetWindowCloseCallback(m_handle, [](GLFWwindow *window) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
WindowClosedEvent event;
callback(event);
});
/* window focus */
glfwSetWindowFocusCallback(m_handle, [](GLFWwindow *window, int focus) {
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
glfwGetWindowUserPointer(window);
if (focus == GLFW_TRUE)
{
WindowGainFocusEvent event;
callback(event);
}
else
{
WindowLostFocusEvent event;
callback(event);
}
});
//============================== WINDOW_EVENTS ==============================// }
}
} // namespace lt

View file

@ -3,6 +3,7 @@
#include <ecs/components.hpp> #include <ecs/components.hpp>
#include <ecs/scene.hpp> #include <ecs/scene.hpp>
#include <engine/utils/serializer.hpp> #include <engine/utils/serializer.hpp>
#include <input/input.hpp>
#include <input/key_codes.hpp> #include <input/key_codes.hpp>
#include <mirror/editor_layer.hpp> #include <mirror/editor_layer.hpp>
#include <ui/ui.hpp> #include <ui/ui.hpp>

View file

@ -2,6 +2,7 @@
// //
#include <mirror/editor_layer.hpp> #include <mirror/editor_layer.hpp>
#include <window/window.hpp>
// //
#include <engine/engine.hpp> #include <engine/engine.hpp>

View file

@ -0,0 +1,12 @@
if (NOT WIN32)
add_library_module(window linux/window.cpp)
else()
add_library_module(window windows/window.cpp)
endif()
target_link_libraries(window PUBLIC
glfw
logger
lt_debug
input
)

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <engine/core/window.hpp> #include <window/window.hpp>
struct GLFWwindow; struct GLFWwindow;

View file

@ -1,8 +1,6 @@
#pragma once #pragma once
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <renderer/graphics_context.hpp>
namespace lt { namespace lt {
@ -22,15 +20,13 @@ class Window
public: public:
static Scope<Window> create(const std::function<void(Event &)> &callback); static Scope<Window> create(const std::function<void(Event &)> &callback);
Window(): m_properties {} Window() = default;
{
}
Window(const Window &) = delete; Window(const Window &) = delete;
Window &operator=(const Window &) = delete; Window &operator=(const Window &) = delete;
virtual ~Window() = default; virtual ~Window();
virtual void poll_events() = 0; virtual void poll_events() = 0;
@ -88,9 +84,9 @@ public:
virtual auto get_handle() -> void * = 0; virtual auto get_handle() -> void * = 0;
protected: protected:
WindowProperties m_properties; WindowProperties m_properties {};
bool b_Closed { false }; bool b_Closed {};
}; };
} // namespace lt } // namespace lt

View file

@ -1,14 +1,17 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <engine/os/linux/l_window.hpp>
#include <input/events/char.hpp> #include <input/events/char.hpp>
#include <input/events/event.hpp> #include <input/events/event.hpp>
#include <input/events/keyboard.hpp> #include <input/events/keyboard.hpp>
#include <input/events/mouse.hpp> #include <input/events/mouse.hpp>
#include <input/events/window.hpp> #include <input/events/window.hpp>
#include <renderer/graphics_context.hpp> #include <window/linux/window.hpp>
namespace lt { namespace lt {
Window::~Window()
{
}
auto Window::create(const std::function<void(Event &)> &callback) -> Scope<Window> auto Window::create(const std::function<void(Event &)> &callback) -> Scope<Window>
{ {
return create_scope<lWindow>(callback); return create_scope<lWindow>(callback);
@ -29,7 +32,6 @@ lWindow::lWindow(std::function<void(Event &)> callback)
m_handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr); m_handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
lt_assert(m_handle, "lWindow::lWindow: failed to create 'GLFWwindow'"); lt_assert(m_handle, "lWindow::lWindow: failed to create 'GLFWwindow'");
// bind event stuff
glfwSetWindowUserPointer(m_handle, &m_event_callback); glfwSetWindowUserPointer(m_handle, &m_event_callback);
bind_glfw_events(); bind_glfw_events();
} }

View file

View file