start screen refactor
This commit is contained in:
parent
9c0ffd38ce
commit
5a0252d8d0
117
src/main.cpp
117
src/main.cpp
@ -21,7 +21,8 @@ int main(int argc, char** argv) {
|
|||||||
std::cerr << "Failed to set '" << SDL_HINT_VIDEO_ALLOW_SCREENSAVER << "' to 1\n";
|
std::cerr << "Failed to set '" << SDL_HINT_VIDEO_ALLOW_SCREENSAVER << "' to 1\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto last_time = std::chrono::steady_clock::now();
|
auto last_time_render = std::chrono::steady_clock::now();
|
||||||
|
auto last_time_tick = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
// actual setup
|
// actual setup
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
@ -68,54 +69,96 @@ int main(int argc, char** argv) {
|
|||||||
bool quit = false;
|
bool quit = false;
|
||||||
while (!quit) {
|
while (!quit) {
|
||||||
auto new_time = std::chrono::steady_clock::now();
|
auto new_time = std::chrono::steady_clock::now();
|
||||||
//const float time_delta {std::chrono::duration<float, std::chrono::seconds::period>(new_time - last_time).count()};
|
|
||||||
last_time = new_time;
|
|
||||||
|
|
||||||
SDL_Event event;
|
const float time_delta_tick = std::chrono::duration<float, std::chrono::seconds::period>(new_time - last_time_tick).count();
|
||||||
while (SDL_PollEvent(&event)) {
|
const float time_delta_render = std::chrono::duration<float, std::chrono::seconds::period>(new_time - last_time_render).count();
|
||||||
if (event.type == SDL_EVENT_QUIT) {
|
|
||||||
quit = true;
|
bool tick = time_delta_tick >= screen->nextTick();
|
||||||
|
bool render = time_delta_render >= screen->nextRender();
|
||||||
|
|
||||||
|
if (tick) {
|
||||||
|
Screen* ret_screen = screen->tick(time_delta_tick, quit);
|
||||||
|
if (ret_screen != nullptr) {
|
||||||
|
screen.reset(ret_screen);
|
||||||
|
}
|
||||||
|
last_time_tick = new_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// can do both in the same loop
|
||||||
|
if (render) {
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
if (event.type == SDL_EVENT_QUIT) {
|
||||||
|
quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen->handleEvent(event)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||||
|
}
|
||||||
|
if (quit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screen->handleEvent(event)) {
|
//float fps_target = 60.f;
|
||||||
continue;
|
//if (SDL_GetWindowFlags(window.get()) & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) {
|
||||||
|
//fps_target = 30.f;
|
||||||
|
//}
|
||||||
|
|
||||||
|
ImGui_ImplSDLRenderer3_NewFrame();
|
||||||
|
ImGui_ImplSDL3_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
{ // render
|
||||||
|
Screen* ret_screen = screen->render(time_delta_render, quit);
|
||||||
|
if (ret_screen != nullptr) {
|
||||||
|
screen.reset(ret_screen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
ImGui::Render();
|
||||||
}
|
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData());
|
||||||
if (quit) {
|
|
||||||
break;
|
SDL_RenderPresent(renderer.get());
|
||||||
|
// clearing after present is (should) more performant, but first frame is a mess
|
||||||
|
SDL_SetRenderDrawColor(renderer.get(), 0x10, 0x10, 0x10, SDL_ALPHA_OPAQUE);
|
||||||
|
SDL_RenderClear(renderer.get());
|
||||||
|
|
||||||
|
last_time_render = new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
//float fps_target = 60.f;
|
//// TODO: seperate out render and tick
|
||||||
//if (SDL_GetWindowFlags(window.get()) & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) {
|
//const float time_to_next_loop = std::min<float>(screen->nextRender(), screen->nextTick());
|
||||||
//fps_target = 30.f;
|
|
||||||
//}
|
|
||||||
|
|
||||||
ImGui_ImplSDLRenderer3_NewFrame();
|
//std::this_thread::sleep_for( // time left to get to 60fps
|
||||||
ImGui_ImplSDL3_NewFrame();
|
//std::chrono::duration<float, std::chrono::seconds::period>(time_to_next_loop)
|
||||||
ImGui::NewFrame();
|
//- std::chrono::duration<float, std::chrono::seconds::period>(std::chrono::steady_clock::now() - new_time) // time used for rendering
|
||||||
|
//);
|
||||||
|
|
||||||
//ImGui::ShowDemoWindow();
|
|
||||||
|
|
||||||
Screen* ret_screen = screen->poll(quit);
|
if (render || tick) {
|
||||||
if (ret_screen != nullptr) {
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // yield for 1ms
|
||||||
screen.reset(ret_screen);
|
} else {
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// pretty hacky and spins if close to next update
|
||||||
|
// if next loop >= 1ms away, wait 1ms
|
||||||
|
if (time_delta_tick+0.001f < screen->nextTick() && time_delta_render+0.001f < screen->nextRender()) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // yield for 1ms
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// dynamic sleep, sleeps the reminder till next update
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<float, std::chrono::seconds::period>(
|
||||||
|
std::min<float>(
|
||||||
|
screen->nextTick() - time_delta_tick,
|
||||||
|
screen->nextRender() - time_delta_render
|
||||||
|
)
|
||||||
|
));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Render();
|
|
||||||
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData());
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer.get());
|
|
||||||
// clearing after present is (should) more performant, but first frame is a mess
|
|
||||||
SDL_SetRenderDrawColor(renderer.get(), 0x10, 0x10, 0x10, SDL_ALPHA_OPAQUE);
|
|
||||||
SDL_RenderClear(renderer.get());
|
|
||||||
|
|
||||||
std::this_thread::sleep_for( // time left to get to 60fps
|
|
||||||
std::chrono::duration<float, std::chrono::seconds::period>(0.0166f) // 60fps frame duration
|
|
||||||
- std::chrono::duration<float, std::chrono::seconds::period>(std::chrono::steady_clock::now() - new_time) // time used for rendering
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -81,11 +81,7 @@ bool MainScreen::handleEvent(SDL_Event& e) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen* MainScreen::poll(bool& quit) {
|
Screen* MainScreen::render(float time_delta, bool& quit) {
|
||||||
auto new_time = std::chrono::high_resolution_clock::now();
|
|
||||||
const float time_delta {std::chrono::duration<float, std::chrono::seconds::period>(new_time - last_time).count()};
|
|
||||||
last_time = new_time;
|
|
||||||
|
|
||||||
quit = !tc.iterate();
|
quit = !tc.iterate();
|
||||||
|
|
||||||
tcm.iterate(time_delta);
|
tcm.iterate(time_delta);
|
||||||
@ -123,34 +119,14 @@ Screen* MainScreen::poll(bool& quit) {
|
|||||||
ImGui::ShowDemoWindow();
|
ImGui::ShowDemoWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
return nullptr;
|
||||||
{ // texture tests
|
}
|
||||||
const size_t width = 8;
|
|
||||||
const size_t height = 8;
|
|
||||||
#define W 0xff, 0xff, 0xff, 0xff
|
|
||||||
#define B 0x00, 0x00, 0x00, 0xff
|
|
||||||
#define P 0xff, 0x00, 0xff, 0xff
|
|
||||||
static uint8_t raw_pixel[width*height*4] {
|
|
||||||
P, W, W, W, W, W, W, P,
|
|
||||||
W, W, W, W, W, W, W, W,
|
|
||||||
W, W, W, W, W, W, W, W,
|
|
||||||
W, W, W, B, B, W, W, W,
|
|
||||||
W, W, W, B, B, W, W, W,
|
|
||||||
W, W, W, W, W, W, W, W,
|
|
||||||
W, W, W, W, W, W, W, W,
|
|
||||||
P, W, W, W, W, W, W, P,
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint64_t texture = sdlrtu.uploadRGBA(raw_pixel, width, height);
|
Screen* MainScreen::tick(float time_delta, bool& quit) {
|
||||||
|
_min_tick_interval = std::min<float>(
|
||||||
if (ImGui::Begin("test texture")) {
|
tc.toxIterationInterval()/1000.f,
|
||||||
ImGui::Text("test texture windoajsdf");
|
0.03f // HACK: 30ms upper bound, should be the same as tox but will change
|
||||||
|
);
|
||||||
ImGui::Image(reinterpret_cast<void*>(texture), {width*10, height*10});
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,13 @@ struct MainScreen final : public Screen {
|
|||||||
|
|
||||||
// return nullptr if not next
|
// return nullptr if not next
|
||||||
// sets bool quit to true if exit
|
// sets bool quit to true if exit
|
||||||
Screen* poll(bool&) override;
|
Screen* render(float time_delta, bool&) override;
|
||||||
|
Screen* tick(float time_delta, bool&) override;
|
||||||
|
|
||||||
|
float _render_interval {1.f/60.f};
|
||||||
|
float _min_tick_interval {0.f};
|
||||||
|
|
||||||
|
float nextRender(void) override { return _render_interval; }
|
||||||
|
float nextTick(void) override { return _min_tick_interval; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,14 +2,21 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
// all time values are in seconds
|
||||||
struct Screen {
|
struct Screen {
|
||||||
virtual ~Screen(void) = default;
|
virtual ~Screen(void) = default;
|
||||||
|
|
||||||
// return true if handled
|
// return true if handled
|
||||||
virtual bool handleEvent(SDL_Event& e) { return false; }
|
virtual bool handleEvent(SDL_Event&) { return false; }
|
||||||
|
|
||||||
// return nullptr if not next
|
// return nullptr if not next
|
||||||
// sets bool quit to true if exit
|
// sets bool quit to true if exit
|
||||||
virtual Screen* poll(bool& quit) = 0;
|
// both render and tick get called in the selfreported intervals
|
||||||
|
virtual Screen* render(float time_delta, bool& quit) = 0; // pure since this is a graphical app
|
||||||
|
virtual Screen* tick(float time_delta, bool& quit) = 0;
|
||||||
|
|
||||||
|
// TODO: const?
|
||||||
|
virtual float nextRender(void) { return 1.f/60.f; }
|
||||||
|
virtual float nextTick(void) { return 0.03f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
StartScreen::StartScreen(SDL_Renderer* renderer) : _renderer(renderer) {
|
StartScreen::StartScreen(SDL_Renderer* renderer) : _renderer(renderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen* StartScreen::poll(bool&) {
|
Screen* StartScreen::render(float, bool&) {
|
||||||
|
|
||||||
// TODO: imgui tox profile selector?
|
// TODO: imgui tox profile selector?
|
||||||
|
|
||||||
@ -137,3 +137,7 @@ Screen* StartScreen::poll(bool&) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Screen* StartScreen::tick(float, bool&) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ struct StartScreen final : public Screen {
|
|||||||
|
|
||||||
// return nullptr if not next
|
// return nullptr if not next
|
||||||
// sets bool quit to true if exit
|
// sets bool quit to true if exit
|
||||||
Screen* poll(bool&) override;
|
Screen* render(float, bool&) override;
|
||||||
|
Screen* tick(float, bool&) override;
|
||||||
|
|
||||||
|
// use default nextRender and nextTick
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user