#include "critter.hpp" #include "database.hpp" #include "ui.hpp" #include "../vendor/stb/stb_image.h" #include "../vendor/stb/stb_image_write.h" #include #include #include #include #include #include #include #include #include static bool is_initalized = false; static bool is_running = false; static Rml::Context *ctx = nullptr; static std::map critters; static std::vector critter_list; static Rml::ElementDocument *doc; static AppData app_data; void shutdown() { Rml::Shutdown(); Backend::Shutdown(); SDL_Quit(); } bool initialize() { if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { std::cout << "[ERROR] Failed to initialize SDL3: " << SDL_GetError() << "\n"; return false; } if (!Backend::Initialize("CritterFolio", 800, 600, true)) { std::cout << "[ERROR] Failed to initialize backend.\n"; return false; } std::cout << "[INFO] RmlUI Backend initialized.\n"; Rml::SetSystemInterface(Backend::GetSystemInterface()); Rml::SetRenderInterface(Backend::GetRenderInterface()); Rml::Initialise(); Rml::Lua::Initialise(); std::cout << "[INFO] Loading local DB...\n"; if (!db_get_all_critters(critters)) { std::cout << "[ERROR] Local DB failed to initialize.\n"; return false; } std::cout << "[INFO] Local DB initialized.\n"; sync_map_to_list(critters, critter_list); ctx = Rml::CreateContext("main", Rml::Vector2i(800, 600)); if (!ctx) { std::cout << "[ERROR] Failed to create context.\n"; return false; } std::cout << "[INFO] Main context initialized.\n"; Rml::LoadFontFace("./assets/fonts/Hubballi-Regular.ttf"); Rml::Debugger::Initialise(ctx); return true; } bool load_document() { doc = ctx->LoadDocument("./assets/main.rml"); if (!doc) { std::cout << "[ERROR] Could not load assets/main.rml document, shutting down.\n"; shutdown(); return false; } std::cout << "[INFO] Document loaded\n"; doc->Show(); return true; } bool reload_doc() { if (doc) { Rml::Factory::ClearStyleSheetCache(); Rml::Factory::ClearTemplateCache(); doc->Close(); doc = nullptr; } if (!load_document()) { return false; } return true; } bool f5_was_pressed = false; bool f8_was_pressed = false; void handle_input() { const bool *state = SDL_GetKeyboardState(NULL); if (state) { // Reload ui bool f5_state = state[SDL_SCANCODE_F5]; if (f5_state && !f5_was_pressed) { f5_was_pressed = true; reload_doc(); } else if (!f5_state) { f5_was_pressed = false; } // Toggle debugger window bool f8_state = state[SDL_SCANCODE_F8]; if (f8_state && !f8_was_pressed) { f8_was_pressed = true; bool is_visible = Rml::Debugger::IsVisible(); Rml::Debugger::SetVisible(!is_visible); } else if (!f8_state) { f8_was_pressed = false; } } } int main() { std::cout << "[INFO] Starting CritterFolio...\n"; is_initalized = initialize(); if (!is_initalized) { std::cout << "[ERROR] Failed to initialize, shutting down.\n"; shutdown(); return 1; } is_running = true; Rml::DataModelHandle app_data_handle; if (!setup_data_binding(ctx, app_data_handle, app_data, critter_list, critters)) { shutdown(); return 1; } if (!load_document()) { shutdown(); return 1; } std::cout << "[INFO] Main page loaded.\n"; while (is_running) { is_running = Backend::ProcessEvents(ctx); handle_input(); ctx->Update(); Backend::BeginFrame(); ctx->Render(); Backend::PresentFrame(); } shutdown(); return 0; }