aboutsummaryrefslogtreecommitdiff
path: root/src/core/application.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/application.cpp')
-rw-r--r--src/core/application.cpp62
1 files changed, 59 insertions, 3 deletions
diff --git a/src/core/application.cpp b/src/core/application.cpp
index 1541e34..3a21cac 100644
--- a/src/core/application.cpp
+++ b/src/core/application.cpp
@@ -10,6 +10,8 @@
#include <imgui.h>
#include <glm/glm.hpp>
#include <algorithm>
+#include <thread>
+#include <chrono>
namespace Donut
{
@@ -85,6 +87,9 @@ namespace Donut
g_prev_scroll = glfwSetScrollCallback((GLFWwindow*)m_window->get_native_window(), donut_scroll_callback);
+ m_device->set_vsync(SettingsManager::get_v_sync_enabled()); // apply the persisted preference
+ glfwGetWindowSize((GLFWwindow*)m_window->get_native_window(), &m_windowed_w, &m_windowed_h);
+
m_start_time = glfwGetTime();
DONUT_INFO("Application ready on {} backend", m_device->device_name());
}
@@ -93,24 +98,75 @@ namespace Donut
{
while (m_running)
{
+ double frame_start = glfwGetTime();
glfwPollEvents();
if (!m_minimized && m_device)
render_frame();
+
+ // With vsync off, cap to the target FPS (vsync itself paces otherwise).
+ if (!SettingsManager::get_v_sync_enabled())
+ {
+ int fps = SettingsManager::get_target_fps();
+ if (fps > 0)
+ {
+ double budget = 1.0 / (double)fps;
+ double elapsed = glfwGetTime() - frame_start;
+ if (elapsed < budget)
+ std::this_thread::sleep_for(std::chrono::duration<double>(budget - elapsed));
+ }
+ }
+ }
+ }
+
+ auto Application::set_resolution(int w, int h) -> void
+ {
+ if (m_window && !is_fullscreen())
+ glfwSetWindowSize((GLFWwindow*)m_window->get_native_window(), w, h);
+ }
+
+ auto Application::set_fullscreen(bool on) -> void
+ {
+ if (!m_window) return;
+ GLFWwindow* win = (GLFWwindow*)m_window->get_native_window();
+ if (on == is_fullscreen()) return;
+ if (on)
+ {
+ glfwGetWindowPos(win, &m_windowed_x, &m_windowed_y);
+ glfwGetWindowSize(win, &m_windowed_w, &m_windowed_h);
+ GLFWmonitor* mon = glfwGetPrimaryMonitor();
+ const GLFWvidmode* mode = glfwGetVideoMode(mon);
+ glfwSetWindowMonitor(win, mon, 0, 0, mode->width, mode->height, mode->refreshRate);
+ }
+ else
+ {
+ glfwSetWindowMonitor(win, nullptr, m_windowed_x, m_windowed_y, m_windowed_w, m_windowed_h, 0);
}
}
+ auto Application::set_vsync(bool on) -> void { if (m_device) m_device->set_vsync(on); }
+ auto Application::set_ui_scale(float scale) -> void { ImGui::GetIO().FontGlobalScale = scale; }
+ auto Application::is_fullscreen() const -> bool
+ { return m_window && glfwGetWindowMonitor((GLFWwindow*)m_window->get_native_window()) != nullptr; }
+ auto Application::get_window_size(int& w, int& h) const -> void
+ { w = 0; h = 0; if (m_window) glfwGetWindowSize((GLFWwindow*)m_window->get_native_window(), &w, &h); }
+
auto Application::render_frame() -> void
{
RHI::CommandList* cmd = m_device->begin_frame(glm::vec4(0.05f, 0.06f, 0.10f, 1.0f));
if (!cmd) return; // frame skipped (e.g. swapchain recreation)
m_device->imgui_new_frame();
- View view = m_ui->draw(UIContext{ *m_scene, m_device->device_name() });
- update_input(view);
- m_render_path->sync_hdri(m_scene->hdri_path);
+ // Keep the scene camera's projection current before the UI builds, so the
+ // scene-tab gizmo and the render agree on the same matrices this frame.
int w = 0, h = 0;
glfwGetFramebufferSize((GLFWwindow*)m_window->get_native_window(), &w, &h);
+ m_scene->scene_camera.set_projection(45.0f, (float)w / (float)std::max(h, 1), 0.1f, 1000.0f);
+
+ View view = m_ui->draw(UIContext{ *m_scene, m_device->device_name(), *this });
+ update_input(view);
+ m_render_path->sync_hdri(m_scene->hdri_path);
+
float time = (float)(glfwGetTime() - m_start_time);
m_render_path->render(*cmd, *m_scene, view, w, h, m_user_moving, time);