Skip to content

Commit

Permalink
feat: console window in editor
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMcAvoy committed Nov 5, 2024
1 parent b29e399 commit 34caa89
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 62 deletions.
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,21 @@ Come back later, sorry! Jenjin is not ready for real usage.
- [x] Icons everywhere
- [x] Code editor in the editor
- [x] Dynamic data attached to game objects at runtime
- [x] Console window in the editor showing output from the engine
- [ ] Improved meshing algorithm that gives same input meshes all one mesh reference instead of making multiple mesh references and data for them.
- [ ] Hierarchy and `.Parent` in Lua along with `workspace` (e.g. `Workspace.MyGameObject.Parent` == `Workspace`)
- [ ] Console window in the editor showing output from the engine
- [ ] Autocompletion in the editor
- [ ] Allow user to create UI from Lua
- [ ] Better Explorer, allowing right click and creation of new scripts if on the scripts context menu
- [ ] Serialization/Deserialization of scenes to better formats

## TODO (Future)
- [ ] Serialization/Deserialization of scenes to better formats
- [ ] Physics
- [ ] Installer
- [ ] Syntax highlighting in the editor
- [ ] Sprite animations
- [ ] Scripting (Python)
- [ ] Physics engine
- [ ] Instancing
- [ ] Installer
- [ ] 3D support
- [ ] Scripting (Python)

## License
License is in [`LICENSE.md`](LICENSE.md) file and should be read before using this software. (Custom source available license)
Expand Down
5 changes: 3 additions & 2 deletions engine/include/jenjin/editor/editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ class Manager {
void viewport(Jenjin::Scene *scene);
void explorer(Jenjin::Scene *scene);
void code(Jenjin::Scene *scene);
void console(Jenjin::Scene *scene);

void backup_prompts(Jenjin::Scene *scene);

void show_all(Jenjin::Scene *scene);

bool hasProjectOpen = false;
int renderTexture = -1;
bool hasProjectOpen = false;
int renderTexture = -1;

private:
Jenjin::GameObject *selectedObject = nullptr;
Expand Down
8 changes: 7 additions & 1 deletion engine/include/jenjin/engine.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "jenjin/log.h"
#include "jenjin/luamanager.h"
#include "jenjin/scene.h"
#include "jenjin/target.h"
Expand All @@ -21,11 +22,16 @@ class Engine {

Scene *GetCurrentScene() { return currentScene; }

void SetLogSink(Jenjin::LogSink *sink);
Jenjin::LogSink *GetLogSink() { return logSink; }

private:
std::vector<std::shared_ptr<Scene>> scenes = {};
Scene *currentScene = nullptr;

LuaManager luaManager;
LuaManager luaManager;

Jenjin::LogSink *logSink = nullptr;
};

extern Engine *EngineRef;
Expand Down
82 changes: 82 additions & 0 deletions engine/include/jenjin/log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma once

#include <spdlog/sinks/sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>

namespace Jenjin {
// A logger that writes to stdout and to a std::vector internally for display in
// ImGui
class LogSink : public spdlog::sinks::sink {
public:
LogSink() {
colour_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
colour_sink->set_level(spdlog::level::trace);
spdlog::set_level(spdlog::level::trace);
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
spdlog::set_pattern("%v");
}

void log(const spdlog::details::log_msg &msg) override;
void flush() override {}
void set_pattern(const std::string &pattern) override {}
void
set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override {}

std::unordered_map<std::string, int> &GetTraceLogs() {
std::lock_guard<std::mutex> lock(mutex);
return trace_logs;
}

std::unordered_map<std::string, int> &GetDebugLogs() {
std::lock_guard<std::mutex> lock(mutex);
return debug_logs;
}

std::unordered_map<std::string, int> &GetInfoLogs() {
std::lock_guard<std::mutex> lock(mutex);
return info_logs;
}

std::unordered_map<std::string, int> &GetWarnLogs() {
std::lock_guard<std::mutex> lock(mutex);
return warn_logs;
}

std::unordered_map<std::string, int> &GetErrorLogs() {
std::lock_guard<std::mutex> lock(mutex);
return error_logs;
}

std::unordered_map<std::string, int> &GetCriticalLogs() {
std::lock_guard<std::mutex> lock(mutex);
return critical_logs;
}

void ClearLogs() {
std::lock_guard<std::mutex> lock(mutex);
trace_logs.clear();
debug_logs.clear();
info_logs.clear();
warn_logs.clear();
error_logs.clear();
critical_logs.clear();
}

~LogSink() override {}

private:
// map: Line number -> details, times printed

std::unordered_map<std::string, int> trace_logs;
std::unordered_map<std::string, int> debug_logs;
std::unordered_map<std::string, int> info_logs;
std::unordered_map<std::string, int> warn_logs;
std::unordered_map<std::string, int> error_logs;
std::unordered_map<std::string, int> critical_logs;

std::shared_ptr<spdlog::sinks::stdout_color_sink_mt> colour_sink;

std::mutex mutex;
};
} // namespace Jenjin
6 changes: 3 additions & 3 deletions engine/include/jenjin/targets/editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class EditorTarget : public Jenjin::Target {
virtual glm::vec2 GetMousePosition() override;

virtual bool RespondsToWindowResize() override;
virtual void SetWindowPosition(ImVec2 pos) override;
virtual void SetWindowPosition(ImVec2 pos) override;

Jenjin::Framebuffer renderTexture;
int width, height;

Jenjin::Editor::Manager editor;
Jenjin::Editor::Manager manager;

ImVec2 pos;
ImVec2 pos;
};
} // namespace Targets
} // namespace Jenjin
68 changes: 64 additions & 4 deletions engine/src/editor/editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,20 @@ void Manager::dockspace() {

auto dock_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left,
0.25f, nullptr, &dockspace_id);
auto dock_left_up = ImGui::DockBuilderSplitNode(dock_left, ImGuiDir_Up,
0.8f, nullptr, &dock_left);
auto dock_right = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right,
0.6f, nullptr, &dockspace_id);
auto dock_down = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Down,
0.2f, nullptr, &dockspace_id);
auto middle = dockspace_id;

static auto hierarchy_title = ICON_FA_SITEMAP " Hierarchy";
ImGui::DockBuilderDockWindow(hierarchy_title, dock_left_up);
ImGui::DockBuilderDockWindow(hierarchy_title, dock_left);

static auto explorer_title = ICON_FA_FOLDER " Explorer";
ImGui::DockBuilderDockWindow(explorer_title, dock_left);
ImGui::DockBuilderDockWindow(explorer_title, dock_down);

static auto console_title = ICON_FA_TERMINAL " Console";
ImGui::DockBuilderDockWindow(console_title, dock_down);

static auto inspector_title = ICON_FA_EYE " Inspector";
ImGui::DockBuilderDockWindow(inspector_title, dock_right);
Expand Down Expand Up @@ -549,6 +552,62 @@ void Manager::code(Jenjin::Scene *scene) {
ImGui::End();
}

void Manager::console(Jenjin::Scene *scene) {
static auto sink = Jenjin::EngineRef->GetLogSink();

if (sink == nullptr) {
ImGui::Begin("Console", nullptr);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 0, 0, 1));
ImGui::Text("No sink set");
ImGui::PopStyleColor();
ImGui::End();
return;
}

static auto title = ICON_FA_TERMINAL " Console";
ImGui::Begin(title, nullptr, ImGuiWindowFlags_MenuBar);

if (ImGui::BeginMenuBar()) {
if (ImGui::MenuItem("Clear")) {
spdlog::info("Clearing logs");
sink->ClearLogs();
}

ImGui::EndMenuBar();
}

if (ImGui::CollapsingHeader("Error")) {
auto &error_logs = sink->GetErrorLogs();
for (auto &log : sink->GetErrorLogs()) {
ImGui::Text("(%d) %s", log.second, log.first.c_str());
}
}

if (ImGui::CollapsingHeader("Info")) {
auto &info_logs = sink->GetInfoLogs();
for (auto &log : sink->GetInfoLogs()) {
ImGui::Text("(%d) %s", log.second, log.first.c_str());
}
}

if (ImGui::CollapsingHeader("Warn")) {
auto &warn_logs = sink->GetWarnLogs();
for (auto &log : sink->GetWarnLogs()) {
ImGui::Text("(%d) %s", log.second, log.first.c_str());
}
}

if (ImGui::CollapsingHeader("Trace")) {
auto &trace_logs = sink->GetTraceLogs();
for (auto &log : sink->GetTraceLogs()) {
ImGui::Text("(%d) %s", log.second, log.first.c_str());
}
}


ImGui::End();
}

void Manager::show_all(Jenjin::Scene *scene) {
bool isRunning = this->running;
if (isRunning) {
Expand Down Expand Up @@ -582,6 +641,7 @@ void Manager::show_all(Jenjin::Scene *scene) {
explorer(scene);
viewport(scene);
code(scene);
console(scene);
}

void Manager::welcome() {
Expand Down
2 changes: 2 additions & 0 deletions engine/src/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,5 @@ void Engine::Render(Target *target) {

target->PostRender();
}

void Engine::SetLogSink(Jenjin::LogSink *sink) { this->logSink = sink; }
47 changes: 47 additions & 0 deletions engine/src/log.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "jenjin/log.h"
#include <fmt/format.h>

using namespace Jenjin;

void handle(std::unordered_map<std::string, int> &map,
const std::string &data) {
bool exists = map.find(data) != map.end();

if (!exists)
map[data] = 1;

if (exists)
map[data]++;
}

void LogSink::log(const spdlog::details::log_msg &msg) {
std::lock_guard<std::mutex> lock(mutex);
colour_sink->log(msg);

std::string data = msg.payload.data();
bool exists = false;
switch (msg.level) {
case spdlog::level::trace:
handle(trace_logs, data);
break;
case spdlog::level::debug:
handle(debug_logs, data);
break;
case spdlog::level::info:
handle(info_logs, data);
break;
case spdlog::level::warn:
handle(warn_logs, data);
break;
case spdlog::level::err:
handle(error_logs, data);
break;
case spdlog::level::critical:
handle(critical_logs, data);
break;
case spdlog::level::off:
break;
default:
break;
}
}
24 changes: 12 additions & 12 deletions engine/src/luamanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ void Bindings(LuaManager *lm, sol::state &lua) {
return ss.str();
};

lua.set_function("trace", [&](sol::variadic_args va) {
spdlog::trace("[LUA] {}", construct_string(va));
});

lua.set_function("debug", [&](sol::variadic_args va) {
spdlog::debug("[LUA] {}", construct_string(va));
});

lua.set_function("print", [&](sol::variadic_args va) {
spdlog::info("[LUA] {}", construct_string(va));
});

lua.set_function("info", [&](sol::variadic_args va) {
spdlog::info("[LUA] {}", construct_string(va));
});
Expand All @@ -80,22 +92,10 @@ void Bindings(LuaManager *lm, sol::state &lua) {
spdlog::error("[LUA] {}", construct_string(va));
});

lua.set_function("debug", [&](sol::variadic_args va) {
spdlog::debug("[LUA] {}", construct_string(va));
});

lua.set_function("trace", [&](sol::variadic_args va) {
spdlog::trace("[LUA] {}", construct_string(va));
});

lua.set_function("critical", [&](sol::variadic_args va) {
spdlog::critical("[LUA] {}", construct_string(va));
});

lua.set_function("print", [&](sol::variadic_args va) {
spdlog::info("[LUA] {}", construct_string(va));
});

// ========================================================================
// Userdata
// ========================================================================
Expand Down
Loading

0 comments on commit 34caa89

Please sign in to comment.