2025-07-05 13:28:41 +03:30
|
|
|
#include <engine/core/application.hpp>
|
|
|
|
#include <engine/core/window.hpp>
|
|
|
|
#include <engine/debug/instrumentor.hpp>
|
|
|
|
#include <engine/events/event.hpp>
|
|
|
|
#include <engine/graphics/graphics_context.hpp>
|
|
|
|
#include <engine/graphics/render_command.hpp>
|
|
|
|
#include <engine/graphics/renderer.hpp>
|
|
|
|
#include <engine/layer/layer.hpp>
|
|
|
|
#include <engine/time/timer.hpp>
|
|
|
|
#include <engine/user_interface/user_interface.hpp>
|
2021-07-01 19:25:46 +04:30
|
|
|
|
2021-05-20 10:21:08 +04:30
|
|
|
namespace Light {
|
|
|
|
|
2025-07-05 13:28:41 +03:30
|
|
|
Application *Application::s_Context = nullptr;
|
2021-10-02 08:51:54 +03:30
|
|
|
|
2025-07-05 13:28:41 +03:30
|
|
|
Application::Application()
|
2025-07-05 14:23:01 +03:30
|
|
|
: m_instrumentor(nullptr)
|
|
|
|
, m_layer_stack(nullptr)
|
|
|
|
, m_input(nullptr)
|
|
|
|
, m_window(nullptr)
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
|
|
|
ASSERT(!s_Context, "Repeated singleton construction");
|
|
|
|
s_Context = this;
|
2021-10-02 08:51:54 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_logger = Logger::Create();
|
2022-03-07 21:57:00 +03:30
|
|
|
LogDebugData();
|
2021-07-29 17:12:13 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_instrumentor = Instrumentor::Create();
|
|
|
|
m_instrumentor->BeginSession("Logs/ProfileResults_Startup.json");
|
2021-07-29 17:12:13 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_layer_stack = LayerStack::Create();
|
|
|
|
m_input = Input::Create();
|
2021-07-12 15:20:47 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_resource_manager = ResourceManager::Create();
|
2021-10-02 08:51:54 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window = Window::Create(std::bind(&Application::OnEvent, this, std::placeholders::_1));
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-05-20 10:21:08 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
Application::~Application()
|
|
|
|
{
|
|
|
|
LOG(trace, "Application::~Application()");
|
2025-07-05 14:23:01 +03:30
|
|
|
m_instrumentor->EndSession(); // ProfileResults_Termination //
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-05-20 10:21:08 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
void Application::GameLoop()
|
|
|
|
{
|
|
|
|
// check
|
2025-07-05 14:23:01 +03:30
|
|
|
ASSERT(!m_layer_stack->IsEmpty(), "LayerStack is empty");
|
2021-05-27 19:54:05 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
// log debug data
|
2025-07-05 14:23:01 +03:30
|
|
|
m_logger->LogDebugData();
|
|
|
|
m_window->GetGfxContext()->LogDebugData();
|
|
|
|
m_window->GetGfxContext()->GetUserInterface()->LogDebugData();
|
2021-06-01 11:23:41 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
// reveal window
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->SetVisibility(true);
|
2021-06-14 10:01:28 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_instrumentor->EndSession(); // ProfileResults_GameLoop //
|
|
|
|
m_instrumentor->BeginSession("Logs/ProfileResults_GameLoop.json");
|
2021-07-09 09:55:05 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
/* game loop */
|
|
|
|
DeltaTimer deltaTimer;
|
2025-07-05 14:23:01 +03:30
|
|
|
while (!m_window->IsClosed())
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
2021-05-23 21:25:31 +04:30
|
|
|
{
|
2022-03-07 21:57:00 +03:30
|
|
|
// update layers
|
|
|
|
LT_PROFILE_SCOPE("GameLoop::Update");
|
2021-07-12 15:20:47 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++)
|
2022-03-07 21:57:00 +03:30
|
|
|
(*it)->OnUpdate(deltaTimer.GetDeltaTime());
|
|
|
|
}
|
2021-07-21 15:14:22 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
|
|
|
// render layers
|
|
|
|
LT_PROFILE_SCOPE("GameLoop::Render");
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->GetGfxContext()->GetRenderer()->BeginFrame();
|
2021-07-21 15:14:22 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++)
|
2022-03-07 21:57:00 +03:30
|
|
|
(*it)->OnRender();
|
2021-07-12 15:20:47 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->GetGfxContext()->GetRenderer()->EndFrame();
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-07-21 15:14:22 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
|
|
|
// render user interface
|
|
|
|
LT_PROFILE_SCOPE("GameLoop::UserInterface");
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->GetGfxContext()->GetUserInterface()->Begin();
|
2021-07-21 15:14:22 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
for (auto it = m_layer_stack->begin(); it != m_layer_stack->end(); it++)
|
2022-03-07 21:57:00 +03:30
|
|
|
(*it)->OnUserInterfaceUpdate();
|
2021-07-12 15:20:47 +04:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->GetGfxContext()->GetUserInterface()->End();
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-07-09 09:55:05 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
|
|
|
// poll events
|
|
|
|
LT_PROFILE_SCOPE("GameLoop::Events");
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->PollEvents();
|
2021-05-23 21:25:31 +04:30
|
|
|
}
|
2021-05-20 10:21:08 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
/// update delta time
|
|
|
|
deltaTimer.Update();
|
2021-10-02 08:51:54 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_instrumentor->EndSession(); // ProfileResults_GameLoop //
|
|
|
|
m_instrumentor->BeginSession("Logs/ProfileResults_Termination.json");
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-07-14 00:17:30 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
void Application::Quit()
|
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
s_Context->m_window->Close();
|
2022-03-07 21:57:00 +03:30
|
|
|
}
|
2021-05-27 18:55:30 +04:30
|
|
|
|
2025-07-05 13:28:41 +03:30
|
|
|
void Application::OnEvent(const Event &event)
|
2022-03-07 21:57:00 +03:30
|
|
|
{
|
|
|
|
// window
|
|
|
|
if (event.HasCategory(WindowEventCategory))
|
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->OnEvent(event);
|
2021-07-21 20:03:39 +04:30
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
if (event.GetEventType() == EventType::WindowResized)
|
2025-07-05 14:23:01 +03:30
|
|
|
m_window->GetGfxContext()->GetRenderer()->OnWindowResize(
|
2025-07-05 13:28:41 +03:30
|
|
|
(const WindowResizedEvent &)event
|
|
|
|
);
|
2021-05-23 18:10:11 +04:30
|
|
|
}
|
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
// input
|
|
|
|
if (event.HasCategory(InputEventCategory))
|
2021-06-15 09:39:11 +04:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_input->OnEvent(event);
|
2022-03-07 21:57:00 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
if (!m_input->IsReceivingGameEvents()) // return if the event is an input event and 'Input'
|
2025-07-05 13:28:41 +03:30
|
|
|
// has disabled the game events
|
2022-03-07 21:57:00 +03:30
|
|
|
return;
|
2021-06-15 09:39:11 +04:30
|
|
|
}
|
|
|
|
|
2022-03-07 21:57:00 +03:30
|
|
|
/* layers */
|
2025-07-05 14:23:01 +03:30
|
|
|
for (auto it = m_layer_stack->rbegin(); it != m_layer_stack->rend(); it++)
|
2022-03-07 21:57:00 +03:30
|
|
|
if ((*it)->OnEvent(event))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Application::LogDebugData()
|
|
|
|
{
|
|
|
|
// #todo: log more information
|
|
|
|
LOG(info, "________________________________________");
|
|
|
|
LOG(info, "Platform::");
|
|
|
|
LOG(info, " OS: {}", LT_BUILD_PLATFORM);
|
|
|
|
LOG(info, " DIR: {}", std::filesystem::current_path().generic_string());
|
|
|
|
LOG(info, "________________________________________");
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Light
|