new update loop
This commit is contained in:
parent
a99f58e475
commit
b8f041584f
@ -20,7 +20,9 @@ f32 MainWindow::getDPI(){
|
|||||||
return dpi;
|
return dpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::init(const char* window_title){
|
void MainWindow::open(const char* window_title, UpdatingFunc _update){
|
||||||
|
update = _update;
|
||||||
|
|
||||||
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
|
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
|
||||||
SDL_version v;
|
SDL_version v;
|
||||||
SDL_GetVersion(&v);
|
SDL_GetVersion(&v);
|
||||||
@ -76,9 +78,9 @@ void MainWindow::init(const char* window_title){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait, poll and handle events (inputs, window resize, etc.)
|
// Wait, poll and handle events (inputs, window resize, etc.)
|
||||||
void MainWindow::poll_events(u16& frame_updates_requested, bool wait){
|
void MainWindow::poll_events(bool waitForEvent){
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
if(wait){
|
if(waitForEvent){
|
||||||
// waits for first event in cpu-efficient way
|
// waits for first event in cpu-efficient way
|
||||||
SDL_TRY(SDL_WaitEvent(&event) != 1);
|
SDL_TRY(SDL_WaitEvent(&event) != 1);
|
||||||
}
|
}
|
||||||
@ -87,8 +89,7 @@ void MainWindow::poll_events(u16& frame_updates_requested, bool wait){
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(ImGui_ImplSDL2_ProcessEvent(&event))
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
frame_updates_requested=2;
|
|
||||||
switch(event.type){
|
switch(event.type){
|
||||||
case SDL_QUIT: {
|
case SDL_QUIT: {
|
||||||
close();
|
close();
|
||||||
@ -170,51 +171,34 @@ void MainWindow::draw_frame(){
|
|||||||
SDL_RenderPresent(sdl_renderer);
|
SDL_RenderPresent(sdl_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::startAndWait(){
|
void MainWindow::startUpdateLoop(){
|
||||||
if(loop_running)
|
if(loop_running)
|
||||||
throw UsefulException("loop is already running");
|
throw UsefulException("loop is running already");
|
||||||
|
|
||||||
// draw first frame
|
nsec_t prev_update_time_ns = getMonotonicTimeNsec();
|
||||||
draw_frame();
|
|
||||||
|
|
||||||
u16 frame_updates_requested=1;
|
|
||||||
u64 prev_update_time_ms=SDL_GetTicks64();
|
|
||||||
loop_running=true;
|
loop_running=true;
|
||||||
// main loop
|
// main loop
|
||||||
while(loop_running){
|
while(loop_running){
|
||||||
// waits for events
|
poll_events(false);
|
||||||
poll_events(frame_updates_requested, main_loop_wait_for_input);
|
|
||||||
|
nsec_t update_time_ns = getMonotonicTimeNsec();
|
||||||
|
if(update_time_ns < prev_update_time_ns)
|
||||||
|
throw UsefulException("monotonic clock returned unexpected value");
|
||||||
|
f64 delta_time_s = (f64)(update_time_ns - prev_update_time_ns) / 1e9;
|
||||||
|
prev_update_time_ns = update_time_ns;
|
||||||
|
|
||||||
if(frame_updates_requested==0)
|
update(delta_time_s);
|
||||||
{
|
draw_frame();
|
||||||
u64 update_time_ms=SDL_GetTicks64();
|
|
||||||
if(update_time_ms >= prev_update_time_ms + 1000/fps_min){
|
|
||||||
// if frame rate < fps_min then requests frame draw
|
|
||||||
// works only if main_loop_wait_for_input = false
|
|
||||||
frame_updates_requested=1;
|
|
||||||
prev_update_time_ms=update_time_ms;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// skips frame rendering and waits to limit fps
|
|
||||||
u32 frame_delay_ms=1000/fps_max;
|
|
||||||
SDL_Delay(frame_delay_ms);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deaws requested number of frames
|
nsec_t after_update_time_ns = getMonotonicTimeNsec();
|
||||||
while(frame_updates_requested>0) {
|
nsec_t frame_delay_ns = (nsec_t)1e9 / fps_max - (after_update_time_ns - update_time_ns);
|
||||||
draw_frame();
|
if(frame_delay_ns > 0){
|
||||||
frame_updates_requested--;
|
std::cout<<"frameDelay: "<<frame_delay_ns / 1e9f<<std::endl;
|
||||||
|
SDL_Delay(frame_delay_ns / 1e6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
destroy();
|
||||||
MainWindow::destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::close(){
|
|
||||||
loop_running=false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::destroy(){
|
void MainWindow::destroy(){
|
||||||
@ -226,6 +210,10 @@ void MainWindow::destroy(){
|
|||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::close(){
|
||||||
|
loop_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::draw_bg_window(){
|
void MainWindow::draw_bg_window(){
|
||||||
const ImGuiDockNodeFlags dockspace_flags =
|
const ImGuiDockNodeFlags dockspace_flags =
|
||||||
ImGuiDockNodeFlags_PassthruCentralNode;
|
ImGuiDockNodeFlags_PassthruCentralNode;
|
||||||
@ -292,13 +280,12 @@ void MainWindow::draw_bg_window(){
|
|||||||
|
|
||||||
void MainWindow::draw_debug_window(){
|
void MainWindow::draw_debug_window(){
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui::Begin("Debug Options");
|
ImGui::Begin("Debug Options");
|
||||||
ImGui::ColorEdit3("clear_color", (float*)&clear_color);
|
ImGui::ColorEdit3("clear_color", (float*)&clear_color);
|
||||||
ImGui::Checkbox("main_loop_wait_for_input", &main_loop_wait_for_input);
|
ImGui::InputInt("fps_max", &fps_max);
|
||||||
ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||||
ImGui::Checkbox("Demo Window", &show_demo_window);
|
ImGui::Checkbox("Demo Window", &show_demo_window);
|
||||||
ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window);
|
ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if (show_demo_window)
|
if (show_demo_window)
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "../std.hpp"
|
#include "../std.hpp"
|
||||||
|
#include "../time.hpp"
|
||||||
|
|
||||||
/// converts hex color to float vector
|
/// converts hex color to float vector
|
||||||
#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f)
|
#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f)
|
||||||
@ -13,30 +14,32 @@ namespace ougge::GUI {
|
|||||||
|
|
||||||
#define default_font "DroidSans"
|
#define default_font "DroidSans"
|
||||||
|
|
||||||
|
using UpdatingFunc = void (*)(f64 deltaTime);
|
||||||
|
|
||||||
class MainWindow {
|
class MainWindow {
|
||||||
public:
|
public:
|
||||||
ImVec4 clear_color = RGBAHexToF(35,35,50,255);
|
ImVec4 clear_color = RGBAHexToF(35,35,50,255);
|
||||||
f32 default_font_size = 14.0f;
|
f32 default_font_size = 14.0f;
|
||||||
u8 fps_min = 30;
|
int fps_max = 30;
|
||||||
u8 fps_max = 60;
|
// called on each frame
|
||||||
|
UpdatingFunc update = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool loop_running=false;
|
bool loop_running = false;
|
||||||
bool main_loop_wait_for_input=true;
|
|
||||||
bool show_demo_window = false;
|
bool show_demo_window = false;
|
||||||
bool show_metrics_window = false;
|
bool show_metrics_window = false;
|
||||||
SDL_Window* sdl_window = nullptr;
|
SDL_Window* sdl_window = nullptr;
|
||||||
SDL_Renderer* sdl_renderer = nullptr;
|
SDL_Renderer* sdl_renderer = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(const char* window_title);
|
void open(const char* window_title, UpdatingFunc update);
|
||||||
void startAndWait();
|
void startUpdateLoop();
|
||||||
void close();
|
void close();
|
||||||
f32 getDPI();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void destroy();
|
void destroy();
|
||||||
void poll_events(u16& frame_updates_requested, bool wait);
|
f32 getDPI();
|
||||||
|
void poll_events(bool waitForEvent);
|
||||||
void draw_frame();
|
void draw_frame();
|
||||||
void draw_ui();
|
void draw_ui();
|
||||||
void draw_debug_window();
|
void draw_debug_window();
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@ -8,15 +8,16 @@
|
|||||||
|
|
||||||
using namespace ougge;
|
using namespace ougge;
|
||||||
|
|
||||||
int main(int argc, const char** argv){
|
void update(f64 deltaTime){
|
||||||
if(setlocale(LC_CTYPE, "C.UTF-8")!=0)
|
std::cout<<"deltaTime: "<<deltaTime<<std::endl;
|
||||||
std::cerr<<"\e[93msetlocale failed!\n";
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char** argv){
|
||||||
try {
|
try {
|
||||||
Resources::init();
|
Resources::init();
|
||||||
GUI::MainWindow w;
|
GUI::MainWindow w;
|
||||||
w.init("ougge");
|
w.open("ougge", update);
|
||||||
w.startAndWait();
|
w.startUpdateLoop();
|
||||||
}
|
}
|
||||||
catch(const std::exception& e){
|
catch(const std::exception& e){
|
||||||
std::cerr<<"Catched exception: "<<e.what()<<std::endl;
|
std::cerr<<"Catched exception: "<<e.what()<<std::endl;
|
||||||
|
|||||||
19
src/time.cpp
Normal file
19
src/time.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// posix version definition to use clock_gettime
|
||||||
|
#ifndef _XOPEN_SOURCE
|
||||||
|
#if __STDC_VERSION__ >= 199901L
|
||||||
|
#define _XOPEN_SOURCE 600
|
||||||
|
#else
|
||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "time.hpp"
|
||||||
|
#include <ctime>
|
||||||
|
#include "UsefulException.hpp"
|
||||||
|
|
||||||
|
nsec_t getMonotonicTimeNsec(){
|
||||||
|
struct timespec t;
|
||||||
|
if(clock_gettime(CLOCK_MONOTONIC, &t) != 0)
|
||||||
|
throw UsefulException("clock_gettime(CLOCK_MONOTONIC) error");
|
||||||
|
return (nsec_t)t.tv_sec * 1e9 + (nsec_t)t.tv_nsec;
|
||||||
|
}
|
||||||
10
src/time.hpp
Normal file
10
src/time.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
|
/// nanoseconds
|
||||||
|
typedef i64 nsec_t;
|
||||||
|
|
||||||
|
/// can be used to measure delta time
|
||||||
|
///@return time from some moment in nanoseconds.
|
||||||
|
nsec_t getMonotonicTimeNsec();
|
||||||
Loading…
Reference in New Issue
Block a user