Skip to content

Commit

Permalink
chore cleanup & abstract out of application
Browse files Browse the repository at this point in the history
  • Loading branch information
arozx committed Jan 21, 2025
1 parent de305fb commit 1c2f909
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 149 deletions.
154 changes: 66 additions & 88 deletions src/Application.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include <pch.h>
#include "Application.h"

// External dependencies
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <imgui.h>

// Core headers
Expand Down Expand Up @@ -54,35 +52,27 @@
* @note All engine components should be initialized through the Application class
*/
namespace Engine {
constexpr float EVENT_PROCESS_RATE = 60.0f;
constexpr float EVENT_PROCESS_INTERVAL = 1.0f / EVENT_PROCESS_RATE;

/**
* @brief Initialize the application and all subsystems
*/
Application::Application()
{
LOG_INFO("Creating Application");

// Configure profiler
auto& profiler = Engine::Profiler::Get();
profiler.SetMaxSamples(500);
profiler.SetPrecision(2);
profiler.SetJSONOutputPath("profile_results.json");
profiler.SetOutputFormat(Engine::Profiler::OutputFormat::JSON);
Engine::Profiler::Get().BeginSession("Runtime");

InitWindow("Voxel Engine", 1280, 720);
if (!m_Window) {
LOG_ERROR("Failed to create window!");
m_Running = false;
return;
}

m_Window->SetContext();

// Initialize core systems

// Initialize renderer before other systems
m_Renderer.Init();

// Initialize ImGui after renderer
m_ImGuiLayer = std::make_unique<ImGuiLayer>();
m_ImGuiLayer->Init(m_Window.get());

m_Renderer.Init();

// Initialize subsystems
m_TerrainSystem = std::make_unique<TerrainSystem>();
m_TerrainSystem->Initialize(m_Renderer);
Expand Down Expand Up @@ -124,7 +114,7 @@ namespace Engine {
float lastFrameTime = 0.0f;

while (m_Running && m_Window) {
float time = static_cast<float>(glfwGetTime());
auto time = static_cast<float>(glfwGetTime());
float deltaTime = time - lastFrameTime;
lastFrameTime = time;

Expand All @@ -143,7 +133,7 @@ namespace Engine {
m_ImGuiEnabled = m_KeyToggles[GLFW_KEY_F2].currentValue;
}

UpdateFPSCounter(deltaTime, time);
if (m_ShowFPSCounter) { UpdateFPSCounter(deltaTime); };

#ifdef ENGINE_DEBUG
// Update hot-reloading system
Expand All @@ -152,8 +142,7 @@ namespace Engine {

// Render frame
BeginScene();
m_TerrainSystem->Render(m_Renderer);
m_Renderer.Draw();
Present();
EndScene();
}
}
Expand All @@ -163,36 +152,31 @@ namespace Engine {
*/
void Application::ProcessEvents() {
static float eventTimer = 0.0f;
// TODO: Sync to FPS
eventTimer += 0.016f; // Approximate for 60fps

if (eventTimer >= 1.0f) { // Create a test event every second
auto testEvent = std::make_shared<KeyPressedEvent>(GLFW_KEY_T);
testEvent->SetPriority(EventPriority::Normal);
EventQueue::Get().PushEvent(testEvent);
eventTimer = 0.0f;
}
eventTimer += ImGui::GetIO().DeltaTime;

EventQueue::Get().ProcessEvents([this](std::shared_ptr<Event> event) {
EventDispatcher dispatcher(*event.get());
// Process events at fixed 60Hz rate
if (eventTimer >= EVENT_PROCESS_INTERVAL) {
eventTimer = 0.0f;

dispatcher.Dispatch<WindowCloseEvent>([this](WindowCloseEvent& e) -> bool {
LOG_INFO("Window Close Event received");
m_Running = false;
EventQueue::Get().ProcessEvents([this](std::shared_ptr<Event> event) {
EventDispatcher dispatcher(*event.get());

dispatcher.Dispatch<WindowCloseEvent>([this](const WindowCloseEvent& [[maybe_unused]] e) {
LOG_INFO("Window Close Event received");
m_Running = false;
return true;
});

if (!event->IsHandled()) {
m_InputSystem->OnEvent(*event);
}
return true;
});

if (!event->IsHandled()) {
m_InputSystem->OnEvent(*event);
}
return true;
});

// Add chunk range control with number keys
if (auto* window = static_cast<GLFWwindow*>(m_Window->GetNativeWindow())) {
// Replace GLFW key checking with input system
for (int i = 0; i <= 9; i++) {
if (glfwGetKey(window, GLFW_KEY_0 + i) == GLFW_PRESS) {
auto event = std::make_shared<KeyPressedEvent>(GLFW_KEY_0 + i);
if (m_InputSystem->IsKeyPressed(KeyCode::NUM_0 + i)) {
auto event = std::make_shared<KeyPressedEvent>(KeyCode::NUM_0 + i);
EventQueue::Get().PushEvent(event);
break;
}
Expand All @@ -205,7 +189,7 @@ namespace Engine {
* @param deltaTime Time since last frame
* @param currentTime Current application time
*/
void Application::UpdateFPSCounter(float deltaTime, float currentTime) {
void Application::UpdateFPSCounter(float deltaTime) {
m_FPSCounter.Update(deltaTime);
}

Expand All @@ -220,30 +204,30 @@ namespace Engine {
WindowProps props(title, width, height);
m_Window = std::unique_ptr<Window>(Window::Create(props));

m_Window->SetEventCallback([this](Event& e) -> bool {
m_Window->SetEventCallback([this](const Event& e) {
std::shared_ptr<Event> eventPtr = nullptr;

if (e.GetEventType() == EventType::WindowResize) {
auto& resizeEvent = static_cast<WindowResizeEvent&>(e);
SetViewport(0, 0, resizeEvent.GetWidth(), resizeEvent.GetHeight());
const auto* resizeEvent = static_cast<const WindowResizeEvent*>(&e);
SetViewport(0, 0, resizeEvent->GetWidth(), resizeEvent->GetHeight());
}

// Clone the event based on its type
if (e.GetEventType() == EventType::KeyPressed) {
auto& keyEvent = static_cast<KeyPressedEvent&>(e);
eventPtr = std::make_shared<KeyPressedEvent>(keyEvent.GetKeyCode(), keyEvent.IsRepeat());
const auto* keyEvent = static_cast<const KeyPressedEvent*>(&e);
eventPtr = std::make_shared<KeyPressedEvent>(keyEvent->GetKeyCode(), keyEvent->IsRepeat());
}
else if (e.GetEventType() == EventType::MouseMoved) {
auto& mouseEvent = static_cast<MouseMovedEvent&>(e);
eventPtr = std::make_shared<MouseMovedEvent>(mouseEvent.GetX(), mouseEvent.GetY());
const auto* mouseEvent = static_cast<const MouseMovedEvent*>(&e);
eventPtr = std::make_shared<MouseMovedEvent>(mouseEvent->GetX(), mouseEvent->GetY());
}
// TODO: add more event types

if (eventPtr) {
EventQueue::Get().PushEvent(eventPtr);
}
return false;
});
m_Window->SetContext();
}

void Application::ShutdownWindow() {
Expand All @@ -254,15 +238,14 @@ namespace Engine {
void Application::BeginScene() {
PROFILE_FUNCTION();

m_Window->SetClear(0.1f, 0.1f, 0.1f, 1.0f);
m_Renderer.Clear({0.1f, 0.1f, 0.1f, 1.0f});

m_TerrainSystem->Render(m_Renderer);
m_Renderer.Draw();

m_ImGuiLayer->Begin();

if (m_ImGuiEnabled) {
static RenderObject dummyRenderObject; // Create a static dummy object
static RenderObject dummyRenderObject;
m_ImGuiOverlay->OnRender(dummyRenderObject, m_ShowFPSCounter,
m_FPSCounter.GetCurrentFPS(),
m_FPSCounter.GetAverageFPS(),
Expand All @@ -276,49 +259,44 @@ namespace Engine {
}
}

void Application::Present() {
PROFILE_FUNCTION();

m_Renderer.Draw();
}

void Application::EndScene() {
PROFILE_FUNCTION();

m_ImGuiLayer->End();
m_Window->OnUpdate();
}

void Application::Present() {

}

void Application::SetViewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
LOG_TRACE_CONCAT("Set Viewport: ", x, ",", y, ",", width, ",", height);
}

void Application::InitializeToggleStates() {
AddToggleState(GLFW_KEY_F2, true); // ImGui enabled by default
AddToggleState(GLFW_KEY_F3, true); // FPS counter enabled by default
}

bool Application::HandleKeyToggle(int key, float currentTime) {
if (auto* window = static_cast<GLFWwindow*>(m_Window->GetNativeWindow())) {
auto& state = m_KeyToggles[key];
bool currentState = glfwGetKey(window, key) == GLFW_PRESS;

// Track when key is first pressed
if (currentState && !state.previousState) {
state.pressStartTime = currentTime;
}

// Check for toggle condition on release
if (state.previousState && !currentState) {
bool shouldToggle = (currentTime - state.pressStartTime) < MAX_TOGGLE_HOLD_TIME;
state.previousState = currentState;
if (shouldToggle) {
state.currentValue = !state.currentValue;
return true;
}
}

auto& state = m_KeyToggles[key];
bool currentState = m_InputSystem->IsKeyPressed(key);

// Track when key is first pressed
if (currentState && !state.previousState) {
state.pressStartTime = currentTime;
}

// Check for toggle condition on release
if (state.previousState && !currentState) {
bool shouldToggle = (currentTime - state.pressStartTime) < MAX_TOGGLE_HOLD_TIME;
state.previousState = currentState;
if (shouldToggle) {
state.currentValue = !state.currentValue;
return true;
}
}

state.previousState = currentState;
return false;
}

Expand Down
10 changes: 6 additions & 4 deletions src/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace Engine {
struct KeyToggleState {
bool previousState = false; ///< Previous key state
float pressStartTime = 0.0f; ///< Time when key was pressed
bool currentValue = false; ///< Current toggle state
bool currentValue = true; ///< Current toggle state
};

/**
Expand Down Expand Up @@ -92,8 +92,10 @@ namespace Engine {
/**
* @brief Set the viewport dimensions
*/
void SetViewport(int x, int y, int width, int height);

void SetViewport(int x, int y, int width, int height) {
m_Renderer.SetViewport(x, y, width, height);
}

/**
* @brief Process pending events
*/
Expand Down Expand Up @@ -164,7 +166,7 @@ namespace Engine {

std::unique_ptr<ImGuiOverlay> m_ImGuiOverlay;

void UpdateFPSCounter(float deltaTime, float currentTime);
void UpdateFPSCounter(float deltaTime);

std::unique_ptr<Light> m_Light;
};
Expand Down
2 changes: 1 addition & 1 deletion src/Core/AssetManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AssetManager {
// Create new resource
auto resource = std::make_shared<T>();
if (!resource->Load(path)) {
LOG_ERROR("Failed to load resource: {}", path);
LOG_ERROR_CONCAT("Failed to load resource: ", path);
return nullptr;
}

Expand Down
16 changes: 6 additions & 10 deletions src/Debug/Profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ namespace Engine {
*/
class ProfilerTimer {
public:
/**
* @brief Starts timing a named block of code
* @param name Identifier for the profiled code block
*/
ProfilerTimer(std::string_view name);
explicit ProfilerTimer(std::string_view name);
~ProfilerTimer();
private:
const std::string_view m_Name; // Changed from std::string to std::string_view
Expand Down Expand Up @@ -409,12 +405,12 @@ class Profiler {

bool m_Enabled{true};
std::unordered_set<std::string> m_StringPool;
OutputFormat m_OutputFormat;
std::string m_JSONOutputPath;
bool m_HasUnsavedData = false;
OutputFormat m_OutputFormat{OutputFormat::JSON};
std::string m_JSONOutputPath{"profile_results.json"};
bool m_HasUnsavedData{false};
static bool s_SignalsInitialized;
size_t m_MaxSamples = 1000; // Keep last 1000 samples per profile
int m_Precision = 3; // 3 decimal places for ms
size_t m_MaxSamples{500};
int m_Precision{4};
std::shared_mutex m_Mutex;

struct BatchEntry {
Expand Down
Loading

0 comments on commit 1c2f909

Please sign in to comment.