diff --git a/CMakeLists.txt b/CMakeLists.txt index d5bf0987..b185f239 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ find_package(SDL3 CONFIG REQUIRED) find_package(spdlog CONFIG REQUIRED) find_package(tinyobjloader CONFIG REQUIRED) find_package(imgui CONFIG REQUIRED) +find_package(unofficial-imgui-node-editor CONFIG REQUIRED) find_package(Vulkan REQUIRED) # Sources. diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 7a3b37d9..9b220494 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -11,6 +11,8 @@ add_executable(FrameEditor menubar_file.h window_start.cpp window_start.h + window_level.cpp + window_level.h ${CMAKE_CURRENT_SOURCE_DIR}/../asset/json/new_project_template.json ) @@ -30,6 +32,7 @@ target_link_libraries(FrameEditor FrameOpenGLGui FrameOpenGLFile FrameProto + unofficial::imgui-node-editor::imgui-node-editor imgui::imgui ImGuiColorTextEdit ) diff --git a/editor/menubar.cpp b/editor/menubar.cpp index a7c6acf3..4132014b 100644 --- a/editor/menubar.cpp +++ b/editor/menubar.cpp @@ -6,6 +6,7 @@ #include "frame/gui/window_logger.h" #include "frame/gui/window_resolution.h" #include "frame/logger.h" +#include "window_level.h" #include #include @@ -77,6 +78,11 @@ void Menubar::MenuEdit() std::make_unique( menubar_file_.GetFileName(), device_)); } + if (ImGui::MenuItem("Level Editor")) + { + menubar_view_.GetDrawGui().AddWindow( + std::make_unique(device_)); + } if (ImGui::BeginMenu("Shader")) { std::set shader_names; diff --git a/editor/window_level.cpp b/editor/window_level.cpp new file mode 100644 index 00000000..8f2376b1 --- /dev/null +++ b/editor/window_level.cpp @@ -0,0 +1,100 @@ +#include "window_level.h" + +#include +#include + +namespace ed = ax::NodeEditor; + +namespace frame::gui +{ + +WindowLevel::WindowLevel(DeviceInterface& device) : device_(device) +{ +} + +WindowLevel::~WindowLevel() +{ + if (context_) + ed::DestroyEditor(context_); +} + +void WindowLevel::DisplayNode(LevelInterface& level, EntityId id) +{ + std::string name = level.GetNameFromId(id); + ed::BeginNode(id); + ImGui::Text("%s", name.c_str()); + ed::EndNode(); + for (auto child : level.GetChildList(id)) + { + DisplayNode(level, child); + } +} + +bool WindowLevel::DrawCallback() +{ + auto& level = device_.GetLevel(); + if (!context_) + context_ = ed::CreateEditor(); + if (ImGui::BeginTabBar("##level_tabs")) + { + if (ImGui::BeginTabItem("Textures")) + { + for (auto id : level.GetTextures()) + { + auto& tex = level.GetTextureFromId(id); + ImGui::BulletText("%s", tex.GetName().c_str()); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Programs")) + { + for (auto id : level.GetPrograms()) + { + auto& prog = level.GetProgramFromId(id); + ImGui::BulletText("%s", prog.GetName().c_str()); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Materials")) + { + for (auto id : level.GetMaterials()) + { + auto& mat = level.GetMaterialFromId(id); + ImGui::BulletText("%s", mat.GetName().c_str()); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Scene")) + { + ed::SetCurrentEditor(context_); + ed::Begin("SceneEditor"); + auto root = level.GetDefaultRootSceneNodeId(); + if (root) + { + DisplayNode(level, root); + } + ed::End(); + ed::SetCurrentEditor(nullptr); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + return true; +} + +bool WindowLevel::End() const +{ + return end_; +} + +std::string WindowLevel::GetName() const +{ + return name_; +} + +void WindowLevel::SetName(const std::string& name) +{ + name_ = name; +} + +} // namespace frame::gui diff --git a/editor/window_level.h b/editor/window_level.h new file mode 100644 index 00000000..10f7c7fc --- /dev/null +++ b/editor/window_level.h @@ -0,0 +1,30 @@ +#pragma once + +#include "frame/device_interface.h" +#include "frame/gui/gui_window_interface.h" +#include + +namespace frame::gui +{ + +class WindowLevel : public GuiWindowInterface +{ + public: + explicit WindowLevel(DeviceInterface& device); + ~WindowLevel() override; + + bool DrawCallback() override; + bool End() const override; + std::string GetName() const override; + void SetName(const std::string& name) override; + + private: + void DisplayNode(LevelInterface& level, EntityId id); + + DeviceInterface& device_; + ax::NodeEditor::EditorContext* context_ = nullptr; + std::string name_ = "Level Editor"; + bool end_ = false; +}; + +} // namespace frame::gui diff --git a/src/frame/gui/CMakeLists.txt b/src/frame/gui/CMakeLists.txt index 25b65240..5a2169ca 100644 --- a/src/frame/gui/CMakeLists.txt +++ b/src/frame/gui/CMakeLists.txt @@ -32,6 +32,10 @@ add_library(FrameGui window_texture.cpp window_json_file.cpp window_glsl_file.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/imgui-node-editor/imgui_node_editor.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/imgui-node-editor/imgui_node_editor_api.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/imgui-node-editor/imgui_canvas.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/imgui-node-editor/crude_json.cpp ) target_include_directories(FrameGui @@ -39,8 +43,9 @@ target_include_directories(FrameGui ${CMAKE_CURRENT_SOURCE_DIR}/../../../include ${CMAKE_CURRENT_SOURCE_DIR}/../../../src ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/ImGuiColorTextEdit -) + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/ImGuiColorTextEdit + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/imgui-node-editor +) target_link_libraries(FrameGui PUBLIC diff --git a/vcpkg.json b/vcpkg.json index 5b98afed..7698dabd 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -13,6 +13,7 @@ "name": "imgui", "features": [ "opengl3-binding", "sdl3-binding", "docking-experimental" ] }, + "imgui-node-editor", "opengl", "protobuf", {