feat: refresh on demand in menu (adaptive framerate)

This commit is contained in:
MihailRis 2025-11-09 22:22:24 +03:00
parent ba0977a6f0
commit 7fc3703ad2
8 changed files with 56 additions and 16 deletions

View File

@ -255,8 +255,8 @@ void Engine::updateFrontend() {
gui->postAct(); gui->postAct();
} }
void Engine::nextFrame() { void Engine::nextFrame(bool waitForRefresh) {
windowControl->nextFrame(); windowControl->nextFrame(waitForRefresh);
} }
void Engine::startPauseLoop() { void Engine::startPauseLoop() {
@ -275,7 +275,7 @@ void Engine::startPauseLoop() {
if (isHeadless()) { if (isHeadless()) {
platform::sleep(1.0 / params.tps * 1000); platform::sleep(1.0 / params.tps * 1000);
} else { } else {
nextFrame(); nextFrame(false);
} }
} }
if (initialCursorLocked) { if (initialCursorLocked) {

View File

@ -99,7 +99,7 @@ public:
void applicationTick(); void applicationTick();
void updateFrontend(); void updateFrontend();
void renderFrame(); void renderFrame();
void nextFrame(); void nextFrame(bool waitForRefresh);
void startPauseLoop(); void startPauseLoop();
/// @brief Set screen (scene). /// @brief Set screen (scene).

View File

@ -45,7 +45,9 @@ void Mainloop::run() {
engine.renderFrame(); engine.renderFrame();
} }
engine.postUpdate(); engine.postUpdate();
engine.nextFrame(); engine.nextFrame(
dynamic_cast<const MenuScreen*>(engine.getScreen().get()) != nullptr
);
} }
logger.info() << "main loop stopped"; logger.info() << "main loop stopped";
} }

View File

@ -8,6 +8,7 @@
#include "window/input.hpp" #include "window/input.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "graphics/core/ImageData.hpp" #include "graphics/core/ImageData.hpp"
#include "util/platform.hpp"
static debug::Logger logger("window-control"); static debug::Logger logger("window-control");
@ -78,15 +79,19 @@ void WindowControl::toggleFullscreen() {
} }
} }
void WindowControl::nextFrame() { void WindowControl::nextFrame(bool waitForRefresh) {
const auto& settings = engine.getSettings(); const auto& settings = engine.getSettings();
auto& window = engine.getWindow(); auto& window = engine.getWindow();
auto& input = engine.getInput(); auto& input = engine.getInput();
if (waitForRefresh) {
window.setFramerate(Window::FPS_UNLIMITED);
} else {
window.setFramerate( window.setFramerate(
window.isIconified() && settings.display.limitFpsIconified.get() window.isIconified() && settings.display.limitFpsIconified.get()
? 20 ? 20
: settings.display.framerate.get() : settings.display.framerate.get()
); );
}
window.swapBuffers(); window.swapBuffers();
input.pollEvents(); input.pollEvents(waitForRefresh);
} }

View File

@ -16,7 +16,7 @@ public:
Result initialize(); Result initialize();
void nextFrame(); void nextFrame(bool waitForRefresh);
void saveScreenshot(); void saveScreenshot();

View File

@ -18,6 +18,8 @@ enum class WindowMode {
class Window { class Window {
public: public:
static inline constexpr int FPS_UNLIMITED = 0;
Window(glm::ivec2 size) : size(std::move(size)) {} Window(glm::ivec2 size) : size(std::move(size)) {}
virtual ~Window() = default; virtual ~Window() = default;
@ -40,6 +42,9 @@ public:
virtual void popScissor() = 0; virtual void popScissor() = 0;
virtual void resetScissor() = 0; virtual void resetScissor() = 0;
virtual void setShouldRefresh() = 0;
virtual bool checkShouldRefresh() = 0;
virtual double time() = 0; virtual double time() = 0;
virtual void setFramerate(int framerate) = 0; virtual void setFramerate(int framerate) = 0;

View File

@ -180,14 +180,18 @@ public:
: window(window) { : window(window) {
} }
void pollEvents() override { void pollEvents(bool waitForRefresh) override {
delta.x = 0.0f; delta.x = 0.0f;
delta.y = 0.0f; delta.y = 0.0f;
scroll = 0; scroll = 0;
currentFrame++; currentFrame++;
codepoints.clear(); codepoints.clear();
pressedKeys.clear(); pressedKeys.clear();
if (waitForRefresh) {
glfwWaitEvents();
} else {
glfwPollEvents(); glfwPollEvents();
}
for (auto& [_, binding] : bindings.getAll()) { for (auto& [_, binding] : bindings.getAll()) {
if (!binding.enabled) { if (!binding.enabled) {
@ -377,6 +381,18 @@ public:
prevSwap = time(); prevSwap = time();
} }
void setShouldRefresh() override {
shouldRefresh = true;
}
bool checkShouldRefresh() override {
if (shouldRefresh) {
shouldRefresh = false;
return true;
}
return false;
}
bool isMaximized() const override { bool isMaximized() const override {
return glfwGetWindowAttrib(window, GLFW_MAXIMIZED); return glfwGetWindowAttrib(window, GLFW_MAXIMIZED);
} }
@ -557,12 +573,14 @@ private:
double prevSwap = 0.0; double prevSwap = 0.0;
int posX = 0; int posX = 0;
int posY = 0; int posY = 0;
bool shouldRefresh = true;
}; };
static_assert(!std::is_abstract<GLFWWindow>()); static_assert(!std::is_abstract<GLFWWindow>());
static void mouse_button_callback(GLFWwindow* window, int button, int action, int) { static void mouse_button_callback(GLFWwindow* window, int button, int action, int) {
auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window)); auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
handler->input.onMouseCallback(button, action == GLFW_PRESS); handler->input.onMouseCallback(button, action == GLFW_PRESS);
handler->setShouldRefresh();
} }
static void character_callback(GLFWwindow* window, unsigned int codepoint) { static void character_callback(GLFWwindow* window, unsigned int codepoint) {
@ -574,6 +592,8 @@ static void key_callback(
GLFWwindow* window, int key, int /*scancode*/, int action, int /*mode*/ GLFWwindow* window, int key, int /*scancode*/, int action, int /*mode*/
) { ) {
auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window)); auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
handler->setShouldRefresh();
auto& input = handler->input; auto& input = handler->input;
if (key == GLFW_KEY_UNKNOWN) { if (key == GLFW_KEY_UNKNOWN) {
return; return;
@ -599,11 +619,13 @@ static void window_size_callback(GLFWwindow* window, int width, int height) {
static void scroll_callback(GLFWwindow* window, double, double yoffset) { static void scroll_callback(GLFWwindow* window, double, double yoffset) {
auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window)); auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
handler->input.scroll += yoffset; handler->input.scroll += yoffset;
handler->setShouldRefresh();
} }
static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) {
auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window)); auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
handler->input.setCursorPosition(xpos, ypos); handler->input.setCursorPosition(xpos, ypos);
handler->setShouldRefresh();
} }
static void iconify_callback(GLFWwindow* window, int iconified) { static void iconify_callback(GLFWwindow* window, int iconified) {
@ -629,6 +651,11 @@ static void create_standard_cursors() {
} }
} }
static void refresh_callback(GLFWwindow* window) {
auto handler = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
handler->setShouldRefresh();
}
static void setup_callbacks(GLFWwindow* window) { static void setup_callbacks(GLFWwindow* window) {
glfwSetKeyCallback(window, key_callback); glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback); glfwSetMouseButtonCallback(window, mouse_button_callback);
@ -637,6 +664,7 @@ static void setup_callbacks(GLFWwindow* window) {
glfwSetCharCallback(window, character_callback); glfwSetCharCallback(window, character_callback);
glfwSetScrollCallback(window, scroll_callback); glfwSetScrollCallback(window, scroll_callback);
glfwSetWindowIconifyCallback(window, iconify_callback); glfwSetWindowIconifyCallback(window, iconify_callback);
glfwSetWindowRefreshCallback(window, refresh_callback);
} }
std::tuple< std::tuple<

View File

@ -261,7 +261,7 @@ class Input {
public: public:
virtual ~Input() = default; virtual ~Input() = default;
virtual void pollEvents() = 0; virtual void pollEvents(bool waitForRefresh) = 0;
virtual const char* getClipboardText() const = 0; virtual const char* getClipboardText() const = 0;
virtual void setClipboardText(const char* str) = 0; virtual void setClipboardText(const char* str) = 0;