#include #include #include #include #include #include #include #include #include #include #include namespace Light { Application *Application::s_context = nullptr; Application::Application() : m_instrumentor(nullptr) , m_layer_stack(nullptr) , m_input(nullptr) , m_window(nullptr) { lt_assert(!s_context, "Repeated singleton construction"); s_context = this; log_debug_data(); m_instrumentor = Instrumentor::create(); m_instrumentor->begin_session("Logs/ProfileResults_Startup.json"); m_layer_stack = LayerStack::create(); m_input = Input::create(); m_resource_manager = ResourceManager::create(); m_window = Window::create(std::bind(&Application::on_event, this, std::placeholders::_1)); } Application::~Application() { log_trc("Application::~Application()"); m_instrumentor->end_session(); } void Application::game_loop() { // check lt_assert(!m_layer_stack->is_empty(), "layer_stack is empty"); // log debug data m_window->get_graphics_context()->log_debug_data(); m_window->get_graphics_context()->get_user_interface()->log_debug_data(); // reveal window m_window->set_visibility(true); m_instrumentor->end_session(); m_instrumentor->begin_session("Logs/ProfileResults_GameLoop.json"); /* game loop */ auto delta_timer = DeltaTimer {}; while (!m_window->is_closed()) { { // update layers lt_profile_scope("game_loop::update"); for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++) (*it)->on_update(delta_timer.get_delta_time()); } { // render layers lt_profile_scope("game_loop::Render"); m_window->get_graphics_context()->get_renderer()->begin_frame(); for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++) (*it)->on_render(); m_window->get_graphics_context()->get_renderer()->end_frame(); } { // render user interface lt_profile_scope("game_loop::UserInterface"); m_window->get_graphics_context()->get_user_interface()->begin(); for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++) (*it)->on_user_interface_update(); m_window->get_graphics_context()->get_user_interface()->end(); } { // poll events lt_profile_scope("game_loop::Events"); m_window->poll_events(); } /// update delta time delta_timer.update(); } m_instrumentor->end_session(); m_instrumentor->begin_session("Logs/ProfileResults_Termination.json"); } void Application::quit() { s_context->m_window->close(); } void Application::on_event(const Event &event) { // window if (event.has_category(WindowEventCategory)) { m_window->on_event(event); if (event.get_event_type() == EventType::WindowResized) m_window->get_graphics_context()->get_renderer()->on_window_resize( (const WindowResizedEvent &)event ); } // input if (event.has_category(InputEventCategory)) { m_input->on_event(event); if (!m_input->is_receiving_game_events()) { return; } } for (auto &it : std::ranges::reverse_view(*m_layer_stack)) { if (it->on_event(event)) { return; } } } void Application::log_debug_data() { // #todo: log more information log_inf("________________________________________"); log_inf("Platform::"); log_inf(" Platform name: {}", constants::platform_name); log_inf(" Platform identifier: {}", std::to_underlying(constants::platform)); log_inf(" CWD: {}", std::filesystem::current_path().generic_string()); log_inf("________________________________________"); } } // namespace Light