aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-23 22:39:47 +0200
committerhachem <im@hachem.wtf>2026-08-23 22:39:47 +0200
commit90ff03c2fdffc09ddb26bdc7e32c3968a6d274fb (patch)
tree2fdb1b6f54c4e380af43c75f1051935587a87faa /src/core
parent5ea6c14c0e14bacee766ce1280ab2c71564e05ec (diff)
[feat]: wire in scene into the simulation engine
Diffstat (limited to 'src/core')
-rw-r--r--src/core/application.cpp62
-rw-r--r--src/core/application.h13
2 files changed, 71 insertions, 4 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);
diff --git a/src/core/application.h b/src/core/application.h
index cbd741d..10a375f 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -19,7 +19,7 @@ namespace Donut
// RenderPath (device-side rendering) and the UILayer (tabbed workspaces), and
// runs the frame loop that wires them together. All the rendering lives in the
// RHI + shared renderers; all the editing lives in the Scene + workspaces.
- class Application
+ class Application : public AppActions
{
public:
Application(const std::string& name = "Donut",
@@ -32,6 +32,14 @@ namespace Donut
auto get_window() -> Window& { return *m_window; }
static auto get() -> Application& { return *s_instance; }
+ // AppActions — window/device changes requested by the Setup workspace.
+ auto set_resolution(int w, int h) -> void override;
+ auto set_fullscreen(bool on) -> void override;
+ auto set_vsync(bool on) -> void override;
+ auto set_ui_scale(float scale) -> void override;
+ auto get_window_size(int& w, int& h) const -> void override;
+ auto is_fullscreen() const -> bool override;
+
private:
auto on_init() -> void;
auto on_shutdown() -> void;
@@ -54,6 +62,9 @@ namespace Donut
double m_start_time = 0.0;
bool m_user_moving = false;
+ // windowed-mode geometry saved across a fullscreen toggle
+ int m_windowed_x = 100, m_windowed_y = 100, m_windowed_w = 1280, m_windowed_h = 720;
+
bool m_running = true;
bool m_minimized = false;