window management in its own files
This commit is contained in:
parent
a6fa5b0570
commit
0f4d0d72d9
|
@ -42,6 +42,7 @@ executable(
|
||||||
'src/camera/camera.cpp',
|
'src/camera/camera.cpp',
|
||||||
'src/init/vulkan_instance.cpp',
|
'src/init/vulkan_instance.cpp',
|
||||||
'src/init/debug_messenger.cpp',
|
'src/init/debug_messenger.cpp',
|
||||||
|
'src/window/window_manager.cpp',
|
||||||
],
|
],
|
||||||
include_directories: include_directories('include', is_system: true),
|
include_directories: include_directories('include', is_system: true),
|
||||||
dependencies: deps,
|
dependencies: deps,
|
||||||
|
|
70
src/main.cpp
70
src/main.cpp
|
@ -34,6 +34,7 @@
|
||||||
#include "util/types.hpp" // Custom type definitions
|
#include "util/types.hpp" // Custom type definitions
|
||||||
#include "util/unique_image.hpp" // Custom image handling utilities
|
#include "util/unique_image.hpp" // Custom image handling utilities
|
||||||
#include "util/vertex.hpp" // Custom vertex structure definition
|
#include "util/vertex.hpp" // Custom vertex structure definition
|
||||||
|
#include "window/window_manager.hpp" // Window manager
|
||||||
|
|
||||||
// ImGui headers for GUI
|
// ImGui headers for GUI
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
@ -213,35 +214,11 @@ class VulkanApp {
|
||||||
* The window is created without a default OpenGL context, as we'll be using Vulkan.
|
* The window is created without a default OpenGL context, as we'll be using Vulkan.
|
||||||
*/
|
*/
|
||||||
fn initWindow() -> void {
|
fn initWindow() -> void {
|
||||||
// Initialize GLFW
|
// Initialize GLFW and create window
|
||||||
mVKFWInstance = vkfw::initUnique();
|
std::tie(mVKFWInstance, mWindow) = WindowManager::create(
|
||||||
|
"Vulkan",
|
||||||
// Set window creation hints
|
{
|
||||||
vkfw::WindowHints hints { .clientAPI = vkfw::ClientAPI::eNone }; // No OpenGL context
|
.on_cursor_move = [this](const vkfw::Window& /*window*/, f64 mouseX, f64 mouseY) -> void {
|
||||||
|
|
||||||
// Get the primary monitor and its resolution
|
|
||||||
vkfw::Monitor primaryMonitor = vkfw::getPrimaryMonitor();
|
|
||||||
const GLFWvidmode* videoMode = primaryMonitor.getVideoMode();
|
|
||||||
|
|
||||||
// Calculate window position to center it
|
|
||||||
i32 xpos = (videoMode->width - WIDTH) / 2;
|
|
||||||
i32 ypos = (videoMode->height - HEIGHT) / 2;
|
|
||||||
|
|
||||||
// Create the window
|
|
||||||
mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints);
|
|
||||||
|
|
||||||
// Set window position
|
|
||||||
mWindow->setPos(xpos, ypos);
|
|
||||||
|
|
||||||
// Set the user pointer to this instance, allowing us to access it in callbacks
|
|
||||||
mWindow->setUserPointer(this);
|
|
||||||
|
|
||||||
// Configure cursor for FPS-style camera control
|
|
||||||
mWindow->set<vkfw::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
|
|
||||||
|
|
||||||
// Set up mouse callback
|
|
||||||
mWindow->callbacks()->on_cursor_move =
|
|
||||||
[this](const vkfw::Window& /*window*/, f64 mouseX, f64 mouseY) -> void {
|
|
||||||
if (!mCursorCaptured)
|
if (!mCursorCaptured)
|
||||||
return; // Skip camera movement when cursor is not captured
|
return; // Skip camera movement when cursor is not captured
|
||||||
|
|
||||||
|
@ -259,10 +236,8 @@ class VulkanApp {
|
||||||
mLastY = mouseY;
|
mLastY = mouseY;
|
||||||
|
|
||||||
mCamera.rotate(-xoffset, yoffset); // Invert xoffset for correct horizontal movement
|
mCamera.rotate(-xoffset, yoffset); // Invert xoffset for correct horizontal movement
|
||||||
};
|
},
|
||||||
|
.on_key = [this](
|
||||||
// Set up key callback for escape
|
|
||||||
mWindow->callbacks()->on_key = [this](
|
|
||||||
const vkfw::Window& window,
|
const vkfw::Window& window,
|
||||||
const vkfw::Key& key,
|
const vkfw::Key& key,
|
||||||
const i32& /*scancode*/,
|
const i32& /*scancode*/,
|
||||||
|
@ -279,12 +254,12 @@ class VulkanApp {
|
||||||
mDevice->waitIdle();
|
mDevice->waitIdle();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
fmt::println("Shaders reloaded successfully!");
|
fmt::println("Shaders reloaded successfully!");
|
||||||
} catch (const std::exception& e) { fmt::println(stderr, "Failed to reload shaders: {}", e.what()); }
|
} catch (const std::exception& e) {
|
||||||
|
fmt::println(stderr, "Failed to reload shaders: {}", e.what());
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
},
|
||||||
// Set up mouse button callback for re-capture
|
.on_mouse_button = [this](
|
||||||
mWindow->callbacks()->on_mouse_button = [this](
|
|
||||||
const vkfw::Window& window,
|
const vkfw::Window& window,
|
||||||
const vkfw::MouseButton& button,
|
const vkfw::MouseButton& button,
|
||||||
const vkfw::MouseButtonAction& action,
|
const vkfw::MouseButtonAction& action,
|
||||||
|
@ -299,14 +274,14 @@ class VulkanApp {
|
||||||
window.set<vkfw::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
|
window.set<vkfw::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
.on_window_resize =
|
||||||
// Set up the window resize callback
|
|
||||||
mWindow->callbacks()->on_window_resize =
|
|
||||||
[this](const vkfw::Window& /*window*/, usize /*width*/, usize /*height*/) -> void {
|
[this](const vkfw::Window& /*window*/, usize /*width*/, usize /*height*/) -> void {
|
||||||
// Set the framebuffer resized flag when the window is resized
|
// Set the framebuffer resized flag when the window is resized
|
||||||
mFramebufferResized = true;
|
mFramebufferResized = true;
|
||||||
};
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,7 +412,7 @@ class VulkanApp {
|
||||||
f64 lastFpsUpdate = 0.0;
|
f64 lastFpsUpdate = 0.0;
|
||||||
i32 frameCounter = 0;
|
i32 frameCounter = 0;
|
||||||
|
|
||||||
while (!mWindow->shouldClose()) {
|
while (!WindowManager::shouldClose(mWindow.get())) {
|
||||||
f64 currentFrame = vkfw::getTime();
|
f64 currentFrame = vkfw::getTime();
|
||||||
deltaTime = currentFrame - lastFrame;
|
deltaTime = currentFrame - lastFrame;
|
||||||
lastFrame = currentFrame;
|
lastFrame = currentFrame;
|
||||||
|
@ -561,7 +536,8 @@ class VulkanApp {
|
||||||
fn updateFrameStats(f64& lastFpsUpdate, i32& frameCounter) -> void {
|
fn updateFrameStats(f64& lastFpsUpdate, i32& frameCounter) -> void {
|
||||||
f64 currentFrame = vkfw::getTime();
|
f64 currentFrame = vkfw::getTime();
|
||||||
if (currentFrame - lastFpsUpdate > 1.0) {
|
if (currentFrame - lastFpsUpdate > 1.0) {
|
||||||
mWindow->setTitle(
|
WindowManager::setTitle(
|
||||||
|
mWindow.get(),
|
||||||
fmt::format("Vulkan - {:.0f}FPS", static_cast<f32>(frameCounter / (currentFrame - lastFpsUpdate)))
|
fmt::format("Vulkan - {:.0f}FPS", static_cast<f32>(frameCounter / (currentFrame - lastFpsUpdate)))
|
||||||
);
|
);
|
||||||
lastFpsUpdate = currentFrame;
|
lastFpsUpdate = currentFrame;
|
||||||
|
@ -608,7 +584,7 @@ class VulkanApp {
|
||||||
fn recreateSwapChain() -> void {
|
fn recreateSwapChain() -> void {
|
||||||
i32 width = 0, height = 0;
|
i32 width = 0, height = 0;
|
||||||
while (width == 0 || height == 0) {
|
while (width == 0 || height == 0) {
|
||||||
std::tie(width, height) = mWindow->getFramebufferSize();
|
std::tie(width, height) = WindowManager::getFramebufferSize(mWindow.get());
|
||||||
vkfw::waitEvents();
|
vkfw::waitEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2688,7 +2664,7 @@ class VulkanApp {
|
||||||
|
|
||||||
// Get the window's resolution
|
// Get the window's resolution
|
||||||
u32 width = 0, height = 0;
|
u32 width = 0, height = 0;
|
||||||
std::tie(width, height) = mWindow->getFramebufferSize();
|
std::tie(width, height) = WindowManager::getFramebufferSize(mWindow.get());
|
||||||
|
|
||||||
// Return the resolution clamped to the supported range
|
// Return the resolution clamped to the supported range
|
||||||
return {
|
return {
|
||||||
|
|
78
src/window/window_manager.cpp
Normal file
78
src/window/window_manager.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include <vkfw.hpp>
|
||||||
|
|
||||||
|
#include "window_manager.hpp"
|
||||||
|
|
||||||
|
#include "../util/constants.hpp"
|
||||||
|
|
||||||
|
using namespace constants;
|
||||||
|
|
||||||
|
fn WindowManager::create(const char* title, const WindowCallbacks& callbacks)
|
||||||
|
-> std::tuple<vkfw::UniqueInstance, vkfw::UniqueWindow> {
|
||||||
|
// Initialize GLFW
|
||||||
|
vkfw::UniqueInstance instance = vkfw::initUnique();
|
||||||
|
|
||||||
|
// Don't create an OpenGL context
|
||||||
|
vkfw::WindowHints hints;
|
||||||
|
hints.clientAPI = vkfw::ClientAPI::eNone;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// Required for macOS
|
||||||
|
hints.cocoaRetinaFramebuffer = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create window
|
||||||
|
vkfw::UniqueWindow window = vkfw::createWindowUnique(WIDTH, HEIGHT, title, hints);
|
||||||
|
|
||||||
|
// Get the primary monitor and its resolution
|
||||||
|
vkfw::Monitor primaryMonitor = vkfw::getPrimaryMonitor();
|
||||||
|
const GLFWvidmode* videoMode = primaryMonitor.getVideoMode();
|
||||||
|
|
||||||
|
// Calculate window position to center it
|
||||||
|
i32 xpos = (videoMode->width - WIDTH) / 2;
|
||||||
|
i32 ypos = (videoMode->height - HEIGHT) / 2;
|
||||||
|
|
||||||
|
// Set window position
|
||||||
|
window->setPos(xpos, ypos);
|
||||||
|
|
||||||
|
// Configure cursor for FPS-style camera control
|
||||||
|
window->set<vkfw::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
|
||||||
|
|
||||||
|
// Set up callbacks
|
||||||
|
if (callbacks.on_cursor_move)
|
||||||
|
window->callbacks()->on_cursor_move = callbacks.on_cursor_move;
|
||||||
|
|
||||||
|
if (callbacks.on_key)
|
||||||
|
window->callbacks()->on_key = callbacks.on_key;
|
||||||
|
|
||||||
|
if (callbacks.on_mouse_button)
|
||||||
|
window->callbacks()->on_mouse_button = callbacks.on_mouse_button;
|
||||||
|
|
||||||
|
if (callbacks.on_window_resize)
|
||||||
|
window->callbacks()->on_window_resize = callbacks.on_window_resize;
|
||||||
|
|
||||||
|
return std::make_tuple(std::move(instance), std::move(window));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn WindowManager::getRequiredExtensions() -> std::vector<const char*> {
|
||||||
|
// Get the required extensions from GLFW
|
||||||
|
std::span<const char*> extensionsSpan = vkfw::getRequiredInstanceExtensions();
|
||||||
|
return { extensionsSpan.begin(), extensionsSpan.end() };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn WindowManager::getFramebufferSize(const vkfw::Window& window) -> std::pair<i32, i32> {
|
||||||
|
return window.getFramebufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn WindowManager::shouldClose(const vkfw::Window& window) -> bool { return window.shouldClose(); }
|
||||||
|
|
||||||
|
fn WindowManager::setTitle(const vkfw::Window& window, const std::string& title) -> void {
|
||||||
|
window.setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn WindowManager::setCursorMode(const vkfw::Window& window, vkfw::CursorMode mode) -> void {
|
||||||
|
window.set<vkfw::InputMode::eCursor>(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn WindowManager::setPosition(const vkfw::Window& window, i32 xpos, i32 ypos) -> void {
|
||||||
|
window.setPos(xpos, ypos);
|
||||||
|
}
|
81
src/window/window_manager.hpp
Normal file
81
src/window/window_manager.hpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VKFW_NO_STRUCT_CONSTRUCTORS // Use aggregate initialization for GLFW structs
|
||||||
|
#include <vkfw.hpp>
|
||||||
|
|
||||||
|
#include "../util/types.hpp"
|
||||||
|
|
||||||
|
struct WindowCallbacks {
|
||||||
|
std::function<void(const vkfw::Window&, f64, f64)> on_cursor_move;
|
||||||
|
std::function<
|
||||||
|
void(const vkfw::Window&, const vkfw::Key&, i32, const vkfw::KeyAction&, const vkfw::ModifierKeyFlags&)>
|
||||||
|
on_key;
|
||||||
|
std::function<
|
||||||
|
void(const vkfw::Window&, const vkfw::MouseButton&, const vkfw::MouseButtonAction&, const vkfw::ModifierKeyFlags&)>
|
||||||
|
on_mouse_button;
|
||||||
|
std::function<void(const vkfw::Window&, usize, usize)> on_window_resize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowManager {
|
||||||
|
public:
|
||||||
|
WindowManager() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a window with the specified dimensions and title.
|
||||||
|
*
|
||||||
|
* @param title Window title
|
||||||
|
* @param callbacks Window callbacks
|
||||||
|
* @return vkfw::UniqueWindow Unique pointer to the created window
|
||||||
|
*/
|
||||||
|
static fn create(const char* title, const WindowCallbacks& callbacks)
|
||||||
|
-> std::tuple<vkfw::UniqueInstance, vkfw::UniqueWindow>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the required instance extensions for window surface creation.
|
||||||
|
*
|
||||||
|
* @return std::vector<const char*> List of required extensions
|
||||||
|
*/
|
||||||
|
static fn getRequiredExtensions() -> std::vector<const char*>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the framebuffer size of the window.
|
||||||
|
*
|
||||||
|
* @param window GLFW window
|
||||||
|
* @return std::pair<i32, i32> Width and height of the framebuffer
|
||||||
|
*/
|
||||||
|
static fn getFramebufferSize(const vkfw::Window& window) -> std::pair<i32, i32>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the window should close.
|
||||||
|
*
|
||||||
|
* @param window GLFW window
|
||||||
|
* @return true Window should close
|
||||||
|
* @return false Window should stay open
|
||||||
|
*/
|
||||||
|
static fn shouldClose(const vkfw::Window& window) -> bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the window title.
|
||||||
|
*
|
||||||
|
* @param window GLFW window
|
||||||
|
* @param title New window title
|
||||||
|
*/
|
||||||
|
static fn setTitle(const vkfw::Window& window, const std::string& title) -> void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the cursor mode.
|
||||||
|
*
|
||||||
|
* @param window GLFW window
|
||||||
|
* @param mode Cursor mode (Normal or Disabled)
|
||||||
|
*/
|
||||||
|
static fn setCursorMode(const vkfw::Window& window, vkfw::CursorMode mode) -> void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the window position.
|
||||||
|
*
|
||||||
|
* @param window GLFW window
|
||||||
|
* @param xpos X position
|
||||||
|
* @param ypos Y position
|
||||||
|
*/
|
||||||
|
static fn setPosition(const vkfw::Window& window, i32 xpos, i32 ypos) -> void;
|
||||||
|
};
|
Loading…
Reference in a new issue