Skip to content

Commit

Permalink
feat(tesseratos): add logging functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Scarface1809 committed Jul 21, 2024
1 parent fedd0bf commit 071ab63
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Image asset and UI Image component (#1270, **@DiogoMendonc-a**).
- Raycasting, collisions between rays and box/capsule colliders (#225, **@diogomsmiranda**).
- Change speed of the debug-camera using Tab and LShift, positive and negative respectively (#1159, **@diogomsmiranda**)
- Console plugin (#875, **@Scarface1809**).

### Changed

Expand Down
1 change: 1 addition & 0 deletions tools/tesseratos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(TESSERATOS_SOURCE
"src/tesseratos/collider_gizmos/plugin.cpp"
"src/tesseratos/play_pause/plugin.cpp"
"src/tesseratos/ecs_statistics/plugin.cpp"
"src/tesseratos/console/plugin.cpp"
)

add_executable(tesseratos ${TESSERATOS_SOURCE})
Expand Down
265 changes: 265 additions & 0 deletions tools/tesseratos/src/tesseratos/console/plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
#include "plugin.hpp"

#include <imgui.h>

#include <cubos/core/log.hpp>

#include <cubos/engine/imgui/plugin.hpp>

#include "../toolbox/plugin.hpp"

using cubos::engine::Cubos;

using namespace tesseratos;

namespace
{
// Resource used to store the state of the console
struct State
{
std::vector<cubos::core::Logger::Entry> uiEntries;
std::size_t cursor = 0;
char searchString[256];
bool clearEnabled = false;
bool collapseEnabled = false;
bool traceEnabled = true;
bool debugEnabled = true;
bool infoEnabled = true;
bool warnEnabled = true;
bool errorEnabled = true;
bool criticalEnabled = true;
};
} // namespace

// Function to convert log level to a string
static std::string levelToString(cubos::core::Logger::Level level)
{
switch (level)
{
case cubos::core::Logger::Level::Trace:
return "Trace";
case cubos::core::Logger::Level::Debug:
return "Debug";
case cubos::core::Logger::Level::Info:
return "Info";
case cubos::core::Logger::Level::Warn:
return "Warn";
case cubos::core::Logger::Level::Error:
return "Error";
case cubos::core::Logger::Level::Critical:
return "Critical";
default:
return "Unknown";
}
}

// Function to convert log level to a color
static ImVec4 levelToColor(cubos::core::Logger::Level level)
{
switch (level)
{
case cubos::core::Logger::Level::Trace:
return {1.0F, 1.0F, 1.0F, 1.0F}; // White
case cubos::core::Logger::Level::Debug:
return {0.0F, 1.0F, 1.0F, 1.0F}; // Cyan
case cubos::core::Logger::Level::Info:
return {0.0F, 1.0F, 0.0F, 1.0F}; // Green
case cubos::core::Logger::Level::Warn:
return {1.0F, 1.0F, 0.0F, 1.0F}; // Yellow
case cubos::core::Logger::Level::Error:
return {1.0F, 0.0F, 0.0F, 1.0F}; // Red
case cubos::core::Logger::Level::Critical:
return {1.0F, 0.0F, 1.0F, 1.0F}; // Magenta
default:
return {1.0F, 1.0F, 1.0F, 1.0F}; // Default to white
}
}

void tesseratos::consolePlugin(Cubos& cubos)
{
cubos.depends(cubos::engine::imguiPlugin);
cubos.depends(toolboxPlugin);
cubos.resource<State>();

cubos.system("show Logger UI").tagged(cubos::engine::imguiTag).call([](Toolbox& toolbox, State& state) {
if (!toolbox.isOpen("Console"))
{
return;
}

ImGui::SetNextWindowSize(ImVec2(930, 310), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiCond_FirstUseEver);
ImGui::Begin("Console");

ImGui::Columns(2, "ConsoleLayout", true);

// Log Scrollable Window
ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() * 0.8F);

cubos::core::Logger::Entry entry;
cubos::core::Logger::Entry previousEntry;

// Counters for each log level
std::unordered_map<cubos::core::Logger::Level, int> logCounts = {
{cubos::core::Logger::Level::Trace, 0}, {cubos::core::Logger::Level::Debug, 0},
{cubos::core::Logger::Level::Info, 0}, {cubos::core::Logger::Level::Warn, 0},
{cubos::core::Logger::Level::Error, 0}, {cubos::core::Logger::Level::Critical, 0}};

ImGui::BeginChild("Log", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()));

while (cubos::core::Logger::read(state.cursor, entry))
{
state.uiEntries.push_back(entry);
}

if (state.clearEnabled)
{
state.clearEnabled = false;
state.uiEntries.clear();
}

std::size_t counter = 0;
bool isFirstEntry = true;
for (cubos::core::Logger::Entry& e : state.uiEntries)
{
if (e.level != cubos::core::Logger::Level::Off)
{
logCounts[e.level]++;
}

switch (e.level)
{
case cubos::core::Logger::Level::Trace:
if (!state.traceEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Debug:
if (!state.debugEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Info:
if (!state.infoEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Warn:
if (!state.warnEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Error:
if (!state.errorEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Critical:
if (!state.criticalEnabled)
{
continue;
}
break;
case cubos::core::Logger::Level::Off:
break;
}

if (state.searchString[0] != '\0' && e.message.find(state.searchString) == std::string::npos)
{
continue;
}

if (state.collapseEnabled)
{
if (!isFirstEntry && previousEntry.message == e.message)
{
counter++;
continue;
}
if (!isFirstEntry && counter > 0)
{
ImGui::TextColored(levelToColor(previousEntry.level), "[%s] %s (x%zu)",
levelToString(previousEntry.level).c_str(), previousEntry.message.c_str(),
counter + 1);
counter = 0;
}
else if (!isFirstEntry)
{
ImGui::TextColored(levelToColor(previousEntry.level), "[%s] %s",
levelToString(previousEntry.level).c_str(), previousEntry.message.c_str());
}
previousEntry = e;
isFirstEntry = false;
}
else
{
ImGui::TextColored(levelToColor(e.level), "[%s] %s", levelToString(e.level).c_str(), e.message.c_str());
}
}

ImGui::EndChild();

// Input Search Bar
ImGui ::InputTextWithHint("##Search", "Filter Messages", state.searchString, sizeof(state.searchString));

ImGui::NextColumn();

ImGui::SetColumnWidth(1, 128);

// Clear Button
if (ImGui::SmallButton("Clear"))
{
state.clearEnabled = true;
}

// Collapse Button
if (ImGui::SmallButton("Collapse"))
{
state.collapseEnabled = !state.collapseEnabled;
}

std::string traceText = "Trace (" + std::to_string(logCounts[cubos::core::Logger::Level::Trace]) + ")";
if (ImGui::SmallButton(traceText.c_str()))
{
state.traceEnabled = !state.traceEnabled;
}

std::string debugText = "Debug (" + std::to_string(logCounts[cubos::core::Logger::Level::Debug]) + ")";
if (ImGui::SmallButton(debugText.c_str()))
{
state.debugEnabled = !state.debugEnabled;
}

std::string infoText = "Info (" + std::to_string(logCounts[cubos::core::Logger::Level::Info]) + ")";
if (ImGui::SmallButton(infoText.c_str()))
{
state.infoEnabled = !state.infoEnabled;
}

std::string warnText = "Warn (" + std::to_string(logCounts[cubos::core::Logger::Level::Warn]) + ")";
if (ImGui::SmallButton(warnText.c_str()))
{
state.warnEnabled = !state.warnEnabled;
}

std::string errorText = "Error (" + std::to_string(logCounts[cubos::core::Logger::Level::Error]) + ")";
if (ImGui::SmallButton(errorText.c_str()))
{
}

std::string criticalText = "Critical (" + std::to_string(logCounts[cubos::core::Logger::Level::Critical]) + ")";
if (ImGui::SmallButton(criticalText.c_str()))
{
state.criticalEnabled = !state.criticalEnabled;
}

ImGui::Columns(1); // Reset columns

ImGui::End();
});
}
26 changes: 26 additions & 0 deletions tools/tesseratos/src/tesseratos/console/plugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// @dir
/// @brief @ref tesseratos-console-plugin plugin directory.

/// @file
/// @brief Plugin entry point.
/// @ingroup tesseratos-console-plugin

#pragma once

#include <cubos/engine/assets/plugin.hpp>

namespace tesseratos
{
/// @defgroup tesseratos-console-plugin Console/Logs
/// @ingroup tesseratos
/// @brief Displays Cubos Logs.
///
/// ## Dependencies
/// - @ref imgui-plugin
/// - @ref log-plugin

/// @brief Plugin entry function.
/// @param cubos @b CUBOS. main class
/// @ingroup tesseratos-console-plugin
void consolePlugin(cubos::engine::Cubos& cubos);
} // namespace tesseratos
2 changes: 2 additions & 0 deletions tools/tesseratos/src/tesseratos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "asset_explorer/plugin.hpp"
#include "collider_gizmos/plugin.hpp"
#include "console/plugin.hpp"
#include "debug_camera/plugin.hpp"
#include "ecs_statistics/plugin.hpp"
#include "entity_inspector/plugin.hpp"
Expand Down Expand Up @@ -51,6 +52,7 @@ int main(int argc, char** argv)
cubos.plugin(transformGizmoPlugin);
cubos.plugin(playPausePlugin);
cubos.plugin(ecsStatisticsPlugin);
cubos.plugin(consolePlugin);

cubos.plugin(sceneEditorPlugin);
cubos.plugin(voxelPaletteEditorPlugin);
Expand Down

0 comments on commit 071ab63

Please sign in to comment.