From 23e7052d11f4da62007ccd7debb5b3037f8f2de6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 11:50:09 +0100 Subject: [PATCH 01/15] update transform when modified by guizmo in real time --- ICEBERG/include/Editor.h | 1 + ICEBERG/include/Inspector.h | 2 +- ICEBERG/include/Viewport.h | 4 +++- ICEBERG/src/Editor.cpp | 2 +- ICEBERG/src/Inspector.cpp | 4 ++-- ICEBERG/src/Viewport.cpp | 7 ++++++- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ICEBERG/include/Editor.h b/ICEBERG/include/Editor.h index 46ab83eb..4e2000be 100644 --- a/ICEBERG/include/Editor.h +++ b/ICEBERG/include/Editor.h @@ -27,6 +27,7 @@ class Editor : public Controller { std::unique_ptr m_inspector; std::unique_ptr m_assets; ICE::Entity m_selected_entity; + bool m_entity_transform_changed = false; //Popups NewMaterialWidget m_material_popup; diff --git a/ICEBERG/include/Inspector.h b/ICEBERG/include/Inspector.h index 1229e653..b7a32c94 100644 --- a/ICEBERG/include/Inspector.h +++ b/ICEBERG/include/Inspector.h @@ -12,7 +12,7 @@ class Inspector : public Controller { Inspector(const std::shared_ptr &engine); bool update() override; - void setSelectedEntity(ICE::Entity e); + void setSelectedEntity(ICE::Entity e, bool force_refesh = false); bool entityHasChanged(); private: diff --git a/ICEBERG/include/Viewport.h b/ICEBERG/include/Viewport.h index 7cde03fb..b5cf7c39 100644 --- a/ICEBERG/include/Viewport.h +++ b/ICEBERG/include/Viewport.h @@ -7,7 +7,7 @@ class Viewport : public Controller { public: - Viewport(const std::shared_ptr &engine); + Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback); bool update() override; void setSelectedEntity(ICE::Entity e); @@ -19,4 +19,6 @@ class Viewport : public Controller { const double camera_delta = 0.1; ImGuizmo::OPERATION m_guizmo_mode = ImGuizmo::TRANSLATE; ICE::Entity m_selected_entity = 0; + std::function m_entity_transformed_callback = [] { + }; }; diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index d73bf3f0..98df7249 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -7,7 +7,7 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ptr& g_factory) : m_engine(engine), m_material_popup(engine) { - m_viewport = std::make_unique(engine); + m_viewport = std::make_unique(engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }); m_hierarchy = std::make_unique(engine); m_inspector = std::make_unique(engine); m_assets = std::make_unique(engine, g_factory); diff --git a/ICEBERG/src/Inspector.cpp b/ICEBERG/src/Inspector.cpp index 33c0f6c0..a94b8fca 100644 --- a/ICEBERG/src/Inspector.cpp +++ b/ICEBERG/src/Inspector.cpp @@ -30,8 +30,8 @@ bool Inspector::entityHasChanged() { return (m_entity_has_changed + 1) != 0; } -void Inspector::setSelectedEntity(ICE::Entity e) { - if (m_selected_entity == e) { +void Inspector::setSelectedEntity(ICE::Entity e, bool force_refesh) { + if (m_selected_entity == e && !force_refesh) { return; } m_entity_has_changed = 0; diff --git a/ICEBERG/src/Viewport.cpp b/ICEBERG/src/Viewport.cpp index 15bfede2..8ec74a19 100644 --- a/ICEBERG/src/Viewport.cpp +++ b/ICEBERG/src/Viewport.cpp @@ -4,7 +4,9 @@ #include -Viewport::Viewport(const std::shared_ptr &engine) : m_engine(engine) { +Viewport::Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback) + : m_engine(engine), + m_entity_transformed_callback(entity_transformed_callback) { engine->setRenderFramebufferInternal(true); ui.registerCallback("w_pressed", [this]() { m_engine->getCamera()->forward(camera_delta); }); @@ -51,6 +53,9 @@ bool Viewport::update() { } else if (m_guizmo_mode == ImGuizmo::SCALE) { tc->scale() += (deltaS - Eigen::Vector3f(1, 1, 1)); } + if (ImGuizmo::IsUsingAny()) { + m_entity_transformed_callback(); + } } return m_done; } From 22ea9583aea6b388a42349246b1f68d2f91f1f5e Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 13:17:18 +0100 Subject: [PATCH 02/15] multi-scene and other ui fixes --- ICE/Core/include/ICEEngine.h | 2 ++ ICE/Core/src/ICEEngine.cpp | 21 ++++++----- ICE/Graphics/src/ForwardRenderer.cpp | 10 ++++-- ICEBERG/Components/UniformInputs.h | 13 ++++--- ICEBERG/UI/AddComponentPopup.h | 10 ++++++ ICEBERG/UI/EditorWidget.h | 10 ++++-- ICEBERG/UI/NewSceneWidget.h | 52 ++++++++++++++++++++++++++++ ICEBERG/include/Editor.h | 2 ++ ICEBERG/include/Hierarchy.h | 1 + ICEBERG/src/Editor.cpp | 13 ++++++- ICEBERG/src/Hierarchy.cpp | 4 +++ ICEBERG/src/Inspector.cpp | 7 ++-- 12 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 ICEBERG/UI/NewSceneWidget.h diff --git a/ICE/Core/include/ICEEngine.h b/ICE/Core/include/ICEEngine.h index 942584ef..4336b67a 100644 --- a/ICE/Core/include/ICEEngine.h +++ b/ICE/Core/include/ICEEngine.h @@ -24,6 +24,8 @@ class ICEEngine { void step(); + void setupScene(); + Eigen::Vector4i getPickingTextureAt(int x, int y); std::shared_ptr getCamera(); diff --git a/ICE/Core/src/ICEEngine.cpp b/ICE/Core/src/ICEEngine.cpp index 4273522b..93fdbfa6 100644 --- a/ICE/Core/src/ICEEngine.cpp +++ b/ICE/Core/src/ICEEngine.cpp @@ -37,6 +37,17 @@ void ICEEngine::step() { project->getCurrentScene()->getRegistry()->updateSystems(0.0); } +void ICEEngine::setupScene() { + auto renderer = std::make_shared(api, m_graphics_factory, project->getCurrentScene()->getRegistry(), project->getAssetBank()); + auto rs = std::make_shared(); + rs->setCamera(camera); + rs->setRenderer(renderer); + project->getCurrentScene()->getRegistry()->addSystem(rs); + + auto [w, h] = m_window->getSize(); + renderer->resize(w, h); +} + std::shared_ptr ICEEngine::getCamera() { return camera; } @@ -94,15 +105,7 @@ void ICEEngine::setProject(const std::shared_ptr &project) { this->project = project; this->camera->getPosition() = project->getCameraPosition(); this->camera->getRotation() = project->getCameraRotation(); - - auto renderer = std::make_shared(api, m_graphics_factory, project->getCurrentScene()->getRegistry(), project->getAssetBank()); - auto rs = std::make_shared(); - rs->setCamera(camera); - rs->setRenderer(renderer); - project->getCurrentScene()->getRegistry()->addSystem(rs); - - auto [w, h] = m_window->getSize(); - renderer->resize(w, h); + setupScene(); } EngineConfig &ICEEngine::getConfig() { diff --git a/ICE/Graphics/src/ForwardRenderer.cpp b/ICE/Graphics/src/ForwardRenderer.cpp index 8d6f14b2..11746728 100644 --- a/ICE/Graphics/src/ForwardRenderer.cpp +++ b/ICE/Graphics/src/ForwardRenderer.cpp @@ -38,10 +38,11 @@ ForwardRenderer::ForwardRenderer(const std::shared_ptr& api, const } void ForwardRenderer::submit(Entity e) { - if (std::find(m_render_queue.begin(), m_render_queue.end(), e) == m_render_queue.end() && m_registry->entityHasComponent(e)) { + remove(e); + if (m_registry->entityHasComponent(e)) { m_render_queue.emplace_back(e); } - if (std::find(m_lights.begin(), m_lights.end(), e) == m_lights.end() && m_registry->entityHasComponent(e)) { + if (m_registry->entityHasComponent(e)) { m_lights.emplace_back(e); } if (m_registry->entityHasComponent(e)) { @@ -71,7 +72,10 @@ void ForwardRenderer::prepareFrame(Camera& camera) { auto rc_b = m_registry->getComponent(b); auto material_b = m_asset_bank->getAsset(rc_b->material); - if (!material_a->isTransparent() && material_b->isTransparent()) { + bool a_transparent = material_a ? material_a->isTransparent() : false; + bool b_transparent = material_b ? material_b->isTransparent() : false; + + if (!a_transparent && b_transparent) { return true; } else { return false; diff --git a/ICEBERG/Components/UniformInputs.h b/ICEBERG/Components/UniformInputs.h index 337f8273..5563ad2f 100644 --- a/ICEBERG/Components/UniformInputs.h +++ b/ICEBERG/Components/UniformInputs.h @@ -29,11 +29,14 @@ class UniformInputs { std::string getLabel() const { return m_label; } void setAssetComboList(const std::vector &paths, const std::vector &ids) { - m_asset_combo.setValues(paths); - m_assets_ids = ids; - auto it = std::find(ids.begin(), ids.end(), std::get(m_value)); - if (it != ids.end()) { - m_asset_combo.setSelected(std::distance(ids.begin(), it)); + std::vector path_with_none = {""}; + path_with_none.insert(path_with_none.end(), paths.begin(), paths.end()); + m_asset_combo.setValues(path_with_none); + m_assets_ids = {0}; + m_assets_ids.insert(m_assets_ids.end(), ids.begin(), ids.end()); + auto it = std::find(m_assets_ids.begin(), m_assets_ids.end(), std::get(m_value)); + if (it != m_assets_ids.end()) { + m_asset_combo.setSelected(std::distance(m_assets_ids.begin(), it)); } m_asset_combo.onSelectionChanged( [cb = this->m_callback, id_list = this->m_assets_ids](const std::string &, int index) { cb(id_list[index]); }); diff --git a/ICEBERG/UI/AddComponentPopup.h b/ICEBERG/UI/AddComponentPopup.h index 59346040..9f436d51 100644 --- a/ICEBERG/UI/AddComponentPopup.h +++ b/ICEBERG/UI/AddComponentPopup.h @@ -36,14 +36,24 @@ class AddComponentPopup { break; } ImGui::CloseCurrentPopup(); + m_accepted = true; } ImGui::EndPopup(); } } + bool accepted() { + if (m_accepted) { + m_accepted = false; + return true; + } + return false; + } + private: ComboBox m_components_combo; bool m_open = false; + bool m_accepted = false; std::shared_ptr m_registry; ICE::Entity m_entity; }; \ No newline at end of file diff --git a/ICEBERG/UI/EditorWidget.h b/ICEBERG/UI/EditorWidget.h index 0e14481c..edbe20c4 100644 --- a/ICEBERG/UI/EditorWidget.h +++ b/ICEBERG/UI/EditorWidget.h @@ -43,7 +43,12 @@ class EditorWidget : public Widget { } ImGui::EndMenu(); } - //if (ImGui::MenuItem("Open", "Ctrl+O")) {} + if (ImGui::BeginMenu("Open")) { + if (ImGui::MenuItem("Scene")) { + callback("open_scene_clicked"); + } + ImGui::EndMenu(); + } //if (ImGui::MenuItem("Save", "Ctrl+S")) {} //if (ImGui::MenuItem("Save as..")) {} ImGui::EndMenu(); @@ -59,7 +64,8 @@ class EditorWidget : public Widget { ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout ImGui::DockBuilderAddNode(dockspace_id); // Add empty node - ImGuiID dock_main_id = dockspace_id; // This variable will track the document node, however we are not using it here as we aren't docking anything into it. + ImGuiID dock_main_id = + dockspace_id; // This variable will track the document node, however we are not using it here as we aren't docking anything into it. ImGuiID dock_top = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, 0.80f, NULL, &dock_main_id); ImGuiID dock_id_bottom = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, 0.20f, NULL, &dock_main_id); diff --git a/ICEBERG/UI/NewSceneWidget.h b/ICEBERG/UI/NewSceneWidget.h new file mode 100644 index 00000000..b5335747 --- /dev/null +++ b/ICEBERG/UI/NewSceneWidget.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include +#include + +#include "Components/InputText.h" +#include "Widget.h" + +class NewSceneWidget : public Widget { + public: + NewSceneWidget(const std::shared_ptr& engine) : m_engine(engine) {} + + void render() override { + ImGui::PushID("scene_edit"); + if (m_open) { + ImGui::OpenPopup("Scene Editor"); + m_open = false; + } + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + if (ImGui::BeginPopupModal("Scene Editor", 0, 0)) { + m_scene_name_in.render(); + if (ImGui::Button("Accept")) { + m_accepted = true; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::PopStyleVar(); + ImGui::PopID(); + } + + std::string getSceneName() { return m_scene_name_in.getText(); } + + void open() { m_open = true; } + + bool accepted() { + if (m_accepted) { + m_accepted = false; + return true; + } + return false; + } + + private: + bool m_open = false; + char m_name[512] = {0}; + bool m_accepted = false; + std::shared_ptr m_engine; + InputText m_scene_name_in{"Scene name", "New scene"}; +}; \ No newline at end of file diff --git a/ICEBERG/include/Editor.h b/ICEBERG/include/Editor.h index 4e2000be..f659e461 100644 --- a/ICEBERG/include/Editor.h +++ b/ICEBERG/include/Editor.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -31,4 +32,5 @@ class Editor : public Controller { //Popups NewMaterialWidget m_material_popup; + NewSceneWidget m_scene_popup; }; diff --git a/ICEBERG/include/Hierarchy.h b/ICEBERG/include/Hierarchy.h index ce6a86cb..1de2bb17 100644 --- a/ICEBERG/include/Hierarchy.h +++ b/ICEBERG/include/Hierarchy.h @@ -13,6 +13,7 @@ class Hierarchy : public Controller { SceneTreeView getTreeView(const std::shared_ptr &scene) const; ICE::Entity getSelectedEntity() const; + void setSelectedEntity(ICE::Entity e); void rebuildTree(); private: diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index 98df7249..d890b15d 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -6,11 +6,13 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ptr& g_factory) : m_engine(engine), - m_material_popup(engine) { + m_material_popup(engine), + m_scene_popup(engine) { m_viewport = std::make_unique(engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }); m_hierarchy = std::make_unique(engine); m_inspector = std::make_unique(engine); m_assets = std::make_unique(engine, g_factory); + ui.registerCallback("new_scene_clicked", [this] { m_scene_popup.open(); }); ui.registerCallback("new_material_clicked", [this] { auto material = std::make_shared(); auto path = ICE::AssetPath::WithTypePrefix(""); @@ -70,10 +72,19 @@ bool Editor::update() { m_viewport->setSelectedEntity(m_selected_entity); m_material_popup.render(); + m_scene_popup.render(); if (m_material_popup.accepted()) { m_assets->rebuildViewer(); } + if (m_scene_popup.accepted()) { + m_engine->getProject()->addScene(ICE::Scene(m_scene_popup.getSceneName())); + m_engine->getProject()->setCurrentScene(m_engine->getProject()->getScenes().back()); + m_engine->setupScene(); + m_hierarchy->setSelectedEntity(0); + m_viewport->setSelectedEntity(0); + m_inspector->setSelectedEntity(0); + } return m_done; } \ No newline at end of file diff --git a/ICEBERG/src/Hierarchy.cpp b/ICEBERG/src/Hierarchy.cpp index 43825415..1ebc834c 100644 --- a/ICEBERG/src/Hierarchy.cpp +++ b/ICEBERG/src/Hierarchy.cpp @@ -44,6 +44,10 @@ ICE::Entity Hierarchy::getSelectedEntity() const { return m_selected; } +void Hierarchy::setSelectedEntity(ICE::Entity e) { + m_selected = e; +} + void Hierarchy::rebuildTree() { m_need_rebuild_tree = true; } diff --git a/ICEBERG/src/Inspector.cpp b/ICEBERG/src/Inspector.cpp index a94b8fca..15e99cc6 100644 --- a/ICEBERG/src/Inspector.cpp +++ b/ICEBERG/src/Inspector.cpp @@ -9,17 +9,20 @@ Inspector::Inspector(const std::shared_ptr& engine) : m_engine(e [this] { m_add_component_popup.open(m_engine->getProject()->getCurrentScene()->getRegistry(), m_selected_entity); }); ui.registerCallback("remove_light_component_clicked", [this] { m_engine->getProject()->getCurrentScene()->getRegistry()->removeComponent(m_selected_entity); - setSelectedEntity(m_selected_entity); + setSelectedEntity(m_selected_entity, true); }); ui.registerCallback("remove_render_component_clicked", [this] { m_engine->getProject()->getCurrentScene()->getRegistry()->removeComponent(m_selected_entity); - setSelectedEntity(m_selected_entity); + setSelectedEntity(m_selected_entity, true); }); } bool Inspector::update() { m_add_component_popup.render(); ui.render(); + if (m_add_component_popup.accepted()) { + setSelectedEntity(m_selected_entity, true); + } return m_done; } From 2ed73e88c48b7a1c65a479691d0d9960ada3a8b9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 14:12:30 +0100 Subject: [PATCH 03/15] open scene dialog --- ICEBERG/UI/OpenSceneWidget.h | 59 ++++++++++++++++++++++++++++++++++++ ICEBERG/include/Editor.h | 2 ++ ICEBERG/src/Editor.cpp | 12 +++++++- 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 ICEBERG/UI/OpenSceneWidget.h diff --git a/ICEBERG/UI/OpenSceneWidget.h b/ICEBERG/UI/OpenSceneWidget.h new file mode 100644 index 00000000..9cc5e765 --- /dev/null +++ b/ICEBERG/UI/OpenSceneWidget.h @@ -0,0 +1,59 @@ +#pragma once +#include + +#include "Components/ComboBox.h" +#include "Components/InputText.h" +#include "Widget.h" + +class OpenSceneWidget : public Widget { + public: + OpenSceneWidget(const std::shared_ptr& engine) : m_engine(engine), m_scene_name_combo("Scene", {}) { + std::vector scenes_names; + for (const auto& s : m_engine->getProject()->getScenes()) { + scenes_names.push_back(s->getName()); + } + m_scene_name_combo.setValues(scenes_names); + m_scene_name_combo.setSelected(0); + } + + void render() override { + ImGui::PushID("scene_open"); + if (m_open) { + ImGui::OpenPopup("Scene Selection"); + m_open = false; + } + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + if (ImGui::BeginPopupModal("Scene Selection", 0, 0)) { + m_scene_name_combo.render(); + if (ImGui::Button("Accept")) { + m_accepted = true; + ImGui::CloseCurrentPopup(); + } + if (ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::PopStyleVar(); + ImGui::PopID(); + } + + int getSelectedIndex() { return m_scene_name_combo.getSelectedIndex(); } + + void open() { m_open = true; } + + bool accepted() { + if (m_accepted) { + m_accepted = false; + return true; + } + return false; + } + + private: + bool m_open = false; + bool m_accepted = false; + std::shared_ptr m_engine; + ComboBox m_scene_name_combo; +}; \ No newline at end of file diff --git a/ICEBERG/include/Editor.h b/ICEBERG/include/Editor.h index f659e461..536536c6 100644 --- a/ICEBERG/include/Editor.h +++ b/ICEBERG/include/Editor.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -33,4 +34,5 @@ class Editor : public Controller { //Popups NewMaterialWidget m_material_popup; NewSceneWidget m_scene_popup; + OpenSceneWidget m_open_scene_popup; }; diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index d890b15d..cfc9f50a 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -7,11 +7,13 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ptr& g_factory) : m_engine(engine), m_material_popup(engine), - m_scene_popup(engine) { + m_scene_popup(engine), + m_open_scene_popup(engine) { m_viewport = std::make_unique(engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }); m_hierarchy = std::make_unique(engine); m_inspector = std::make_unique(engine); m_assets = std::make_unique(engine, g_factory); + ui.registerCallback("open_scene_clicked", [this] { m_open_scene_popup.open(); }); ui.registerCallback("new_scene_clicked", [this] { m_scene_popup.open(); }); ui.registerCallback("new_material_clicked", [this] { auto material = std::make_shared(); @@ -73,6 +75,7 @@ bool Editor::update() { m_material_popup.render(); m_scene_popup.render(); + m_open_scene_popup.render(); if (m_material_popup.accepted()) { m_assets->rebuildViewer(); @@ -85,6 +88,13 @@ bool Editor::update() { m_viewport->setSelectedEntity(0); m_inspector->setSelectedEntity(0); } + if (m_open_scene_popup.accepted()) { + m_engine->getProject()->setCurrentScene(m_engine->getProject()->getScenes()[m_open_scene_popup.getSelectedIndex()]); + m_engine->setupScene(); + m_hierarchy->setSelectedEntity(0); + m_viewport->setSelectedEntity(0); + m_inspector->setSelectedEntity(0); + } return m_done; } \ No newline at end of file From 6a6ecec40e1564d24e80f97a56a45ffd3e909e90 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 15:37:40 +0100 Subject: [PATCH 04/15] allow custom when setting up scene --- ICE/Core/include/ICEEngine.h | 2 +- ICE/Core/src/ICEEngine.cpp | 6 +++--- ICEBERG/src/Editor.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ICE/Core/include/ICEEngine.h b/ICE/Core/include/ICEEngine.h index 4336b67a..0dfd6b82 100644 --- a/ICE/Core/include/ICEEngine.h +++ b/ICE/Core/include/ICEEngine.h @@ -24,7 +24,7 @@ class ICEEngine { void step(); - void setupScene(); + void setupScene(const std::shared_ptr& camera_); Eigen::Vector4i getPickingTextureAt(int x, int y); diff --git a/ICE/Core/src/ICEEngine.cpp b/ICE/Core/src/ICEEngine.cpp index 93fdbfa6..036c22d7 100644 --- a/ICE/Core/src/ICEEngine.cpp +++ b/ICE/Core/src/ICEEngine.cpp @@ -37,10 +37,10 @@ void ICEEngine::step() { project->getCurrentScene()->getRegistry()->updateSystems(0.0); } -void ICEEngine::setupScene() { +void ICEEngine::setupScene(const std::shared_ptr &camera_) { auto renderer = std::make_shared(api, m_graphics_factory, project->getCurrentScene()->getRegistry(), project->getAssetBank()); auto rs = std::make_shared(); - rs->setCamera(camera); + rs->setCamera(camera_); rs->setRenderer(renderer); project->getCurrentScene()->getRegistry()->addSystem(rs); @@ -105,7 +105,7 @@ void ICEEngine::setProject(const std::shared_ptr &project) { this->project = project; this->camera->getPosition() = project->getCameraPosition(); this->camera->getRotation() = project->getCameraRotation(); - setupScene(); + setupScene(camera); } EngineConfig &ICEEngine::getConfig() { diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index cfc9f50a..717ac048 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -83,14 +83,14 @@ bool Editor::update() { if (m_scene_popup.accepted()) { m_engine->getProject()->addScene(ICE::Scene(m_scene_popup.getSceneName())); m_engine->getProject()->setCurrentScene(m_engine->getProject()->getScenes().back()); - m_engine->setupScene(); + m_engine->setupScene(m_engine->getCamera()); m_hierarchy->setSelectedEntity(0); m_viewport->setSelectedEntity(0); m_inspector->setSelectedEntity(0); } if (m_open_scene_popup.accepted()) { m_engine->getProject()->setCurrentScene(m_engine->getProject()->getScenes()[m_open_scene_popup.getSelectedIndex()]); - m_engine->setupScene(); + m_engine->setupScene(m_engine->getCamera()); m_hierarchy->setSelectedEntity(0); m_viewport->setSelectedEntity(0); m_inspector->setSelectedEntity(0); From 2bd7edeaa8af849fd397d6e32b2a0f3f9bc8ffd9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 16:56:54 +0100 Subject: [PATCH 05/15] test picking, not quite working yet --- ICE/Core/include/ICEEngine.h | 2 - ICE/Core/src/ICEEngine.cpp | 25 ------------ .../OpenGL/src/OpenGLFramebuffer.cpp | 7 +++- ICEBERG/UI/ViewportWidget.h | 3 ++ ICEBERG/include/Viewport.h | 6 ++- ICEBERG/src/Editor.cpp | 4 +- ICEBERG/src/Viewport.cpp | 39 ++++++++++++++++++- 7 files changed, 54 insertions(+), 32 deletions(-) diff --git a/ICE/Core/include/ICEEngine.h b/ICE/Core/include/ICEEngine.h index 0dfd6b82..a27ff2c8 100644 --- a/ICE/Core/include/ICEEngine.h +++ b/ICE/Core/include/ICEEngine.h @@ -26,8 +26,6 @@ class ICEEngine { void setupScene(const std::shared_ptr& camera_); - Eigen::Vector4i getPickingTextureAt(int x, int y); - std::shared_ptr getCamera(); std::shared_ptr getAssetBank(); diff --git a/ICE/Core/src/ICEEngine.cpp b/ICE/Core/src/ICEEngine.cpp index 036c22d7..9da8002e 100644 --- a/ICE/Core/src/ICEEngine.cpp +++ b/ICE/Core/src/ICEEngine.cpp @@ -56,31 +56,6 @@ std::shared_ptr ICEEngine::getAssetBank() { return project->getAssetBank(); } -Eigen::Vector4i ICEEngine::getPickingTextureAt(int x, int y) { - /* pickingFB->bind(); - pickingFB->resize(gui.getSceneViewportWidth(), gui.getSceneViewportHeight()); - api->setViewport(0, 0, gui.getSceneViewportWidth(), gui.getSceneViewportHeight()); - camera.setParameters({60, (float) gui.getSceneViewportWidth() / (float) gui.getSceneViewportHeight(), 0.01f, 1000}); - api->setClearColor(0, 0, 0, 0); - api->clear(); - getAssetBank()->getAsset("__ice__picking_shader")->bind(); - getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("projection", camera.getProjection()); - getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("view", camera.lookThrough()); - int id = 1; - for (auto e : currentScene->getRegistry()->getEntities()) { - //getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("model", e->getComponent()->getTransformation()); - //getAssetBank()->getAsset("__ice__picking_shader")->loadInt("objectID", id++); - //if(e->hasComponent()) { - // api->renderVertexArray(getAssetBank()->getAsset(e->getComponent()->getMesh())->getVertexArray()); - //} - } - auto color = internalFB->readPixel(x, y); - internalFB->unbind(); - return color; - */ - return Eigen::Vector4i(); -} - std::shared_ptr ICEEngine::getApi() const { return api; } diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp index 664977cf..c5b67d5a 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp @@ -78,8 +78,13 @@ Eigen::Vector4i OpenGLFramebuffer::readPixel(int x, int y) { glFlush(); glFinish(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + unsigned char data[4]; auto pixels = Eigen::Vector4i(); - glReadPixels(x, format.height - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + glReadPixels(x, format.height - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); + pixels.x() = data[0]; + pixels.y() = data[1]; + pixels.z() = data[2]; + pixels.w() = data[3]; return pixels; } } // namespace ICE \ No newline at end of file diff --git a/ICEBERG/UI/ViewportWidget.h b/ICEBERG/UI/ViewportWidget.h index ace88e6a..3a1cd0d9 100644 --- a/ICEBERG/UI/ViewportWidget.h +++ b/ICEBERG/UI/ViewportWidget.h @@ -35,6 +35,9 @@ class ViewportWidget : public Widget { if (ImGui::IsMouseDragging(0)) { callback("mouse_dragged", drag.x, drag.y); ImGui::ResetMouseDragDelta(0); + } else if (ImGui::IsMouseClicked(0)) { + auto m_pos = ImGui::GetMousePos(); + callback("mouse_clicked", m_pos.x - pos.x, m_pos.y - pos.y); } } diff --git a/ICEBERG/include/Viewport.h b/ICEBERG/include/Viewport.h index b5cf7c39..0aae95fb 100644 --- a/ICEBERG/include/Viewport.h +++ b/ICEBERG/include/Viewport.h @@ -7,7 +7,8 @@ class Viewport : public Controller { public: - Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback); + Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback, + const std::function &entity_picked_callback); bool update() override; void setSelectedEntity(ICE::Entity e); @@ -21,4 +22,7 @@ class Viewport : public Controller { ICE::Entity m_selected_entity = 0; std::function m_entity_transformed_callback = [] { }; + std::function m_entity_picked_callback = [](ICE::Entity) { + }; + std::shared_ptr m_picking_frambuffer; }; diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index 717ac048..f64e6245 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -9,7 +9,9 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ m_material_popup(engine), m_scene_popup(engine), m_open_scene_popup(engine) { - m_viewport = std::make_unique(engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }); + m_viewport = std::make_unique( + engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }, + [this](ICE::Entity e) { m_hierarchy->setSelectedEntity(e); }); m_hierarchy = std::make_unique(engine); m_inspector = std::make_unique(engine); m_assets = std::make_unique(engine, g_factory); diff --git a/ICEBERG/src/Viewport.cpp b/ICEBERG/src/Viewport.cpp index 8ec74a19..6ae8214b 100644 --- a/ICEBERG/src/Viewport.cpp +++ b/ICEBERG/src/Viewport.cpp @@ -4,11 +4,15 @@ #include -Viewport::Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback) +Viewport::Viewport(const std::shared_ptr &engine, const std::function &entity_transformed_callback, + const std::function &entity_picked_callback) : m_engine(engine), - m_entity_transformed_callback(entity_transformed_callback) { + m_entity_transformed_callback(entity_transformed_callback), + m_entity_picked_callback(entity_picked_callback) { engine->setRenderFramebufferInternal(true); + m_picking_frambuffer = engine->getGraphicsFactory()->createFramebuffer({1, 1, 1}); + ui.registerCallback("w_pressed", [this]() { m_engine->getCamera()->forward(camera_delta); }); ui.registerCallback("s_pressed", [this]() { m_engine->getCamera()->backward(camera_delta); }); ui.registerCallback("a_pressed", [this]() { m_engine->getCamera()->left(camera_delta); }); @@ -21,6 +25,37 @@ Viewport::Viewport(const std::shared_ptr &engine, const std::fun m_engine->getCamera()->pitch(dy / 6.0); } }); + ui.registerCallback("mouse_clicked", [this](float x, float y) { + auto fmt = m_engine->getInternalFramebuffer()->getFormat(); + m_picking_frambuffer->bind(); + m_picking_frambuffer->resize(fmt.width, fmt.height); + m_engine->getApi()->setViewport(0, 0, fmt.width, fmt.height); + m_engine->getApi()->setClearColor(0, 0, 0, 0); + m_engine->getApi()->clear(); + + auto camera = m_engine->getCamera(); + m_engine->getAssetBank()->getAsset("__ice__picking_shader")->bind(); + m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("projection", camera->getProjection()); + m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("view", camera->lookThrough()); + auto registry = m_engine->getProject()->getCurrentScene()->getRegistry(); + for (auto e : registry->getEntities()) { + if (registry->entityHasComponent(e) && registry->entityHasComponent(e)) { + + auto tc = registry->getComponent(e); + auto rc = registry->getComponent(e); + m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("model", tc->getModelMatrix()); + m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadInt("objectID", e); + m_engine->getApi()->renderVertexArray(m_engine->getAssetBank()->getAsset(rc->mesh)->getVertexArray()); + } + } + auto color = m_picking_frambuffer->readPixel(x, y); + m_picking_frambuffer->unbind(); + ICE::Entity e = 0; + e += color.x(); + e += color.y() << 8; + e += color.z() << 16; + m_entity_picked_callback(e); + }); ui.registerCallback("resize", [this](float width, float height) { m_engine->getCamera()->resize(width, height); m_engine->getProject()->getCurrentScene()->getRegistry()->getSystem()->setViewport(0, 0, width, height); From 15c67279e641985d24c8b97105666f164d757e40 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Wed, 18 Dec 2024 08:21:52 +0100 Subject: [PATCH 06/15] picking done --- ICEBERG/UI/HierarchyWidget.h | 2 ++ ICEBERG/UI/ViewportWidget.h | 2 +- ICEBERG/src/Hierarchy.cpp | 1 + ICEBERG/src/Viewport.cpp | 5 ++++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ICEBERG/UI/HierarchyWidget.h b/ICEBERG/UI/HierarchyWidget.h index f0d5df9e..1f0ba452 100644 --- a/ICEBERG/UI/HierarchyWidget.h +++ b/ICEBERG/UI/HierarchyWidget.h @@ -18,6 +18,8 @@ struct SceneTreeView { }; class HierarchyWidget : public Widget { + friend class Hierarchy; + public: HierarchyWidget() = default; diff --git a/ICEBERG/UI/ViewportWidget.h b/ICEBERG/UI/ViewportWidget.h index 3a1cd0d9..77e9d18e 100644 --- a/ICEBERG/UI/ViewportWidget.h +++ b/ICEBERG/UI/ViewportWidget.h @@ -35,7 +35,7 @@ class ViewportWidget : public Widget { if (ImGui::IsMouseDragging(0)) { callback("mouse_dragged", drag.x, drag.y); ImGui::ResetMouseDragDelta(0); - } else if (ImGui::IsMouseClicked(0)) { + } else if (ImGui::IsMouseClicked(0) && !ImGuizmo::IsOver()) { auto m_pos = ImGui::GetMousePos(); callback("mouse_clicked", m_pos.x - pos.x, m_pos.y - pos.y); } diff --git a/ICEBERG/src/Hierarchy.cpp b/ICEBERG/src/Hierarchy.cpp index 1ebc834c..c33594b4 100644 --- a/ICEBERG/src/Hierarchy.cpp +++ b/ICEBERG/src/Hierarchy.cpp @@ -46,6 +46,7 @@ ICE::Entity Hierarchy::getSelectedEntity() const { void Hierarchy::setSelectedEntity(ICE::Entity e) { m_selected = e; + ui.selected_id = e; } void Hierarchy::rebuildTree() { diff --git a/ICEBERG/src/Viewport.cpp b/ICEBERG/src/Viewport.cpp index 6ae8214b..1b40a01f 100644 --- a/ICEBERG/src/Viewport.cpp +++ b/ICEBERG/src/Viewport.cpp @@ -45,7 +45,10 @@ Viewport::Viewport(const std::shared_ptr &engine, const std::fun auto rc = registry->getComponent(e); m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadMat4("model", tc->getModelMatrix()); m_engine->getAssetBank()->getAsset("__ice__picking_shader")->loadInt("objectID", e); - m_engine->getApi()->renderVertexArray(m_engine->getAssetBank()->getAsset(rc->mesh)->getVertexArray()); + auto mesh = m_engine->getAssetBank()->getAsset(rc->mesh); + mesh->getVertexArray()->bind(); + mesh->getVertexArray()->getIndexBuffer()->bind(); + m_engine->getApi()->renderVertexArray(mesh->getVertexArray()); } } auto color = m_picking_frambuffer->readPixel(x, y); From f69314808821c48d2170cc21b542d197671c3be3 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Wed, 18 Dec 2024 09:48:09 +0100 Subject: [PATCH 07/15] remove old code, use filename as default import name, fix light button --- ICE/Core/include/ICEEngine.h | 4 ---- ICE/Core/src/ICEEngine.cpp | 23 ----------------------- ICEBERG/UI/InspectorWidget.h | 4 ++++ ICEBERG/src/Editor.cpp | 4 ++-- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/ICE/Core/include/ICEEngine.h b/ICE/Core/include/ICEEngine.h index a27ff2c8..ad37c1c5 100644 --- a/ICE/Core/include/ICEEngine.h +++ b/ICE/Core/include/ICEEngine.h @@ -49,10 +49,6 @@ class ICEEngine { std::shared_ptr getInternalFramebuffer() const; void setRenderFramebufferInternal(bool use_internal); - void importMesh(); - - void importTexture(bool cubeMap); - private: std::shared_ptr m_graphics_factory; std::shared_ptr ctx; diff --git a/ICE/Core/src/ICEEngine.cpp b/ICE/Core/src/ICEEngine.cpp index 9da8002e..dc1464ad 100644 --- a/ICE/Core/src/ICEEngine.cpp +++ b/ICE/Core/src/ICEEngine.cpp @@ -94,27 +94,4 @@ std::shared_ptr ICEEngine::getGraphicsFactory() const { std::shared_ptr ICEEngine::getContext() const { return ctx; } - -int import_cnt = 0; -void ICEEngine::importMesh() { - const std::string file = FileUtils::openFileDialog("obj"); - if (file != "") { - std::string aname = "imported_mesh_" + std::to_string(import_cnt++); - getAssetBank()->addAsset(aname, {file}); - project->copyAssetFile("Meshes", aname, file); - } -} - -void ICEEngine::importTexture(bool cubeMap) { - const std::string file = FileUtils::openFileDialog(""); - if (file != "") { - std::string aname = "imported_texture_" + std::to_string(import_cnt++); - if (cubeMap) { - getAssetBank()->addAsset(aname, {file}); - } else { - getAssetBank()->addAsset(aname, {file}); - } - project->copyAssetFile("Textures", aname, file); - } -} } // namespace ICE diff --git a/ICEBERG/UI/InspectorWidget.h b/ICEBERG/UI/InspectorWidget.h index ef53a263..9a1fb371 100644 --- a/ICEBERG/UI/InspectorWidget.h +++ b/ICEBERG/UI/InspectorWidget.h @@ -30,6 +30,7 @@ class InspectorWidget : public Widget { ImGui::EndGroup(); } if (m_rc) { + ImGui::PushID("rc"); ImGui::SeparatorText("Render"); ImGui::BeginGroup(); if (ImGui::Button("Remove")) { @@ -40,8 +41,10 @@ class InspectorWidget : public Widget { input.render(); } ImGui::EndGroup(); + ImGui::PopID(); } if (m_lc) { + ImGui::PushID("lc"); ImGui::SeparatorText("Light"); ImGui::BeginGroup(); if (ImGui::Button("Remove")) { @@ -52,6 +55,7 @@ class InspectorWidget : public Widget { input.render(); } ImGui::EndGroup(); + ImGui::PopID(); } if (ImGui::Button("Add Component...")) { diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index f64e6245..d3f90126 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -31,7 +31,7 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ ui.registerCallback("import_mesh_clicked", [this] { std::filesystem::path file = open_native_dialog("*.obj"); if (!file.empty()) { - std::string import_name = "Imported Mesh "; + std::string import_name = file.stem().string(); int i = 0; do { import_name + std::to_string(++i); @@ -46,7 +46,7 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ ui.registerCallback("import_tex2d_clicked", [this] { std::filesystem::path file = open_native_dialog("*.png"); if (!file.empty()) { - std::string import_name = "Imported Texture "; + std::string import_name = file.stem().string(); int i = 0; do { import_name + std::to_string(++i); From 5f4165995b1f4e259affb8d8ffe05b1b04349402 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 14:27:36 +0100 Subject: [PATCH 08/15] fix crash with invalid entity --- ICE/Entity/include/Entity.h | 2 +- ICE/Scene/include/Scene.h | 1 + ICE/Scene/src/Scene.cpp | 5 +++++ ICEBERG/src/Editor.cpp | 5 ++++- ICEBERG/src/Inspector.cpp | 5 ++++- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ICE/Entity/include/Entity.h b/ICE/Entity/include/Entity.h index 23c7ee58..23246a8e 100644 --- a/ICE/Entity/include/Entity.h +++ b/ICE/Entity/include/Entity.h @@ -46,7 +46,7 @@ class EntityManager { void setSignature(Entity e, Signature s) { signatures[e] = s; } Signature getSignature(Entity e) const { - if (e == 0) { + if (e == 0 || !signatures.contains(e)) { return 0; } return signatures.at(e); diff --git a/ICE/Scene/include/Scene.h b/ICE/Scene/include/Scene.h index 29893a65..d1a0d3ac 100644 --- a/ICE/Scene/include/Scene.h +++ b/ICE/Scene/include/Scene.h @@ -30,6 +30,7 @@ class Scene { Entity createEntity(); void addEntity(Entity e, const std::string& alias, Entity parent); void removeEntity(Entity e); + bool hasEntity(Entity e); private: std::string name; diff --git a/ICE/Scene/src/Scene.cpp b/ICE/Scene/src/Scene.cpp index dc27f924..7e8c5d3f 100644 --- a/ICE/Scene/src/Scene.cpp +++ b/ICE/Scene/src/Scene.cpp @@ -57,4 +57,9 @@ void Scene::removeEntity(Entity e) { aliases.erase(e); m_graph->removeEntity(e); } + +bool Scene::hasEntity(Entity e) { + return aliases.contains(e); +} + } // namespace ICE \ No newline at end of file diff --git a/ICEBERG/src/Editor.cpp b/ICEBERG/src/Editor.cpp index d3f90126..5564b082 100644 --- a/ICEBERG/src/Editor.cpp +++ b/ICEBERG/src/Editor.cpp @@ -11,7 +11,10 @@ Editor::Editor(const std::shared_ptr& engine, const std::shared_ m_open_scene_popup(engine) { m_viewport = std::make_unique( engine, [this]() { m_inspector->setSelectedEntity(m_hierarchy->getSelectedEntity(), true); }, - [this](ICE::Entity e) { m_hierarchy->setSelectedEntity(e); }); + [this](ICE::Entity e) { + if (m_engine->getProject()->getCurrentScene()->hasEntity(e)) + m_hierarchy->setSelectedEntity(e); + }); m_hierarchy = std::make_unique(engine); m_inspector = std::make_unique(engine); m_assets = std::make_unique(engine, g_factory); diff --git a/ICEBERG/src/Inspector.cpp b/ICEBERG/src/Inspector.cpp index 15e99cc6..c3b94a3c 100644 --- a/ICEBERG/src/Inspector.cpp +++ b/ICEBERG/src/Inspector.cpp @@ -34,13 +34,16 @@ bool Inspector::entityHasChanged() { } void Inspector::setSelectedEntity(ICE::Entity e, bool force_refesh) { + if (!m_engine->getProject()->getCurrentScene()->hasEntity(e)) { + return; + } if (m_selected_entity == e && !force_refesh) { return; } m_entity_has_changed = 0; m_selected_entity = e; - auto registry = m_engine->getProject()->getCurrentScene()->getRegistry(); + auto registry = m_engine->getProject()->getCurrentScene()->getRegistry(); ui.setEntityName(m_engine->getProject()->getCurrentScene()->getAlias(e)); ui.setLightComponent(nullptr); ui.setRenderComponent(nullptr, {}, {}, {}, {}); From 8b85171e5db383a9acc49541e35f7ae4060d2bc4 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 14:43:25 +0100 Subject: [PATCH 09/15] remove duplication at each run --- ICEBERG/src/Iceberg.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ICEBERG/src/Iceberg.cpp b/ICEBERG/src/Iceberg.cpp index b4c955d2..3207d995 100644 --- a/ICEBERG/src/Iceberg.cpp +++ b/ICEBERG/src/Iceberg.cpp @@ -46,7 +46,7 @@ class Iceberg { if (m_state == UIState::EDITOR) { m_engine->step(); } - ImGui::ShowDemoWindow(); + //ImGui::ShowDemoWindow(); ImGui::Render(); @@ -58,7 +58,16 @@ class Iceberg { m_window->swapBuffers(); } if (m_engine->getProject()) { - m_engine->getConfig().getLocalProjects()->push_back(*m_engine->getProject()); + bool append_to_selector = true; + for (const auto& project : *m_engine->getConfig().getLocalProjects()) { + if (project.getBaseDirectory() == m_engine->getProject()->getBaseDirectory()) { + append_to_selector = false; + break; + } + } + if (append_to_selector) { + m_engine->getConfig().getLocalProjects()->push_back(*m_engine->getProject()); + } m_engine->getProject()->writeToFile(m_engine->getCamera()); m_engine->getConfig().save(); } From 97bd1c0b93e1173411c114ddc3c98819290ca6fa Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 15:12:47 +0100 Subject: [PATCH 10/15] color pickers instead of vector editors, shader default selection match --- ICEBERG/Components/UniformInputs.h | 94 +++++++++++++++++------------- ICEBERG/UI/AddComponentPopup.h | 6 +- ICEBERG/UI/InspectorWidget.h | 3 + ICEBERG/UI/NewMaterialWidget.h | 10 +++- 4 files changed, 69 insertions(+), 44 deletions(-) diff --git a/ICEBERG/Components/UniformInputs.h b/ICEBERG/Components/UniformInputs.h index 5563ad2f..8bbd29a1 100644 --- a/ICEBERG/Components/UniformInputs.h +++ b/ICEBERG/Components/UniformInputs.h @@ -42,6 +42,8 @@ class UniformInputs { [cb = this->m_callback, id_list = this->m_assets_ids](const std::string &, int index) { cb(id_list[index]); }); } + void setForceVectorNumeric(bool force_vector_numeric) { m_force_vector_numeric = force_vector_numeric; } + private: void render(int &i) { if (ImGui::InputInt(m_label.c_str(), &i)) { @@ -58,24 +60,30 @@ class UniformInputs { ImGui::PushID(m_label.c_str()); ImGui::PushItemWidth(60); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); - renderLabel("X", 0x990000FF); - if (ImGui::InputFloat("##X", &v.x())) { - m_callback(v); - } - ImGui::SameLine(); - renderLabel("Y", 0x9900FF00); - if (ImGui::InputFloat("##Y", &v.y())) { - m_callback(v); - } - ImGui::SameLine(); - renderLabel("Z", 0x99FF0000); - if (ImGui::InputFloat("##Z", &v.z())) { - m_callback(v); - } - ImGui::SameLine(); - renderLabel("W", 0x99FFFFFF); - if (ImGui::InputFloat("##W", &v.w())) { - m_callback(v); + if (m_force_vector_numeric) { + renderLabel("X", 0x990000FF); + if (ImGui::InputFloat("##X", &v.x())) { + m_callback(v); + } + ImGui::SameLine(); + renderLabel("Y", 0x9900FF00); + if (ImGui::InputFloat("##Y", &v.y())) { + m_callback(v); + } + ImGui::SameLine(); + renderLabel("Z", 0x99FF0000); + if (ImGui::InputFloat("##Z", &v.z())) { + m_callback(v); + } + ImGui::SameLine(); + renderLabel("W", 0x99FFFFFF); + if (ImGui::InputFloat("##W", &v.w())) { + m_callback(v); + } + } else { + if (ImGui::ColorEdit4("##vector_picker", v.data(), ImGuiColorEditFlags_NoInputs)) { + m_callback(v); + } } ImGui::PopStyleVar(); ImGui::PopItemWidth(); @@ -86,29 +94,34 @@ class UniformInputs { ImGui::PushID(m_label.c_str()); ImGui::PushItemWidth(60); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); - - ImGui::BeginGroup(); - renderLabel("X", 0x990000FF); - if (ImGui::InputFloat("##X", &v.x())) { - m_callback(v); + if (m_force_vector_numeric) { + ImGui::BeginGroup(); + renderLabel("X", 0x990000FF); + if (ImGui::InputFloat("##X", &v.x())) { + m_callback(v); + } + ImGui::EndGroup(); + ImGui::SameLine(); + + ImGui::BeginGroup(); + renderLabel("Y", 0x9900FF00); + if (ImGui::InputFloat("##Y", &v.y())) { + m_callback(v); + } + ImGui::EndGroup(); + ImGui::SameLine(); + + ImGui::BeginGroup(); + renderLabel("Z", 0x99FF0000); + if (ImGui::InputFloat("##Z", &v.z())) { + m_callback(v); + } + ImGui::EndGroup(); + } else { + if (ImGui::ColorEdit3("##vector_picker", v.data(), ImGuiColorEditFlags_NoInputs)) { + m_callback(v); + } } - ImGui::EndGroup(); - ImGui::SameLine(); - - ImGui::BeginGroup(); - renderLabel("Y", 0x9900FF00); - if (ImGui::InputFloat("##Y", &v.y())) { - m_callback(v); - } - ImGui::EndGroup(); - ImGui::SameLine(); - - ImGui::BeginGroup(); - renderLabel("Z", 0x99FF0000); - if (ImGui::InputFloat("##Z", &v.z())) { - m_callback(v); - } - ImGui::EndGroup(); ImGui::PopStyleVar(); ImGui::PopItemWidth(); ImGui::PopID(); @@ -164,4 +177,5 @@ class UniformInputs { //Used when it's an asset input ComboBox m_asset_combo; std::vector m_assets_ids; + bool m_force_vector_numeric = false; }; diff --git a/ICEBERG/UI/AddComponentPopup.h b/ICEBERG/UI/AddComponentPopup.h index 9f436d51..ed08c359 100644 --- a/ICEBERG/UI/AddComponentPopup.h +++ b/ICEBERG/UI/AddComponentPopup.h @@ -16,11 +16,12 @@ class AddComponentPopup { } void render() { + ImGui::PushID("add_component_popup"); if (m_open) { - ImGui::OpenPopup("add_component_popup"); + ImGui::OpenPopup("Add Component"); m_open = false; } - if (ImGui::BeginPopupModal("add_component_popup")) { + if (ImGui::BeginPopupModal("Add Component")) { m_components_combo.render(); if (ImGui::Button("Add")) { switch (m_components_combo.getSelectedIndex()) { @@ -40,6 +41,7 @@ class AddComponentPopup { } ImGui::EndPopup(); } + ImGui::PopID(); } bool accepted() { diff --git a/ICEBERG/UI/InspectorWidget.h b/ICEBERG/UI/InspectorWidget.h index 9a1fb371..d49e103b 100644 --- a/ICEBERG/UI/InspectorWidget.h +++ b/ICEBERG/UI/InspectorWidget.h @@ -73,10 +73,13 @@ class InspectorWidget : public Widget { m_tc_inputs.clear(); if (tc) { m_tc_inputs.emplace_back("Position", tc->getPosition()); + m_tc_inputs.back().setForceVectorNumeric(true); m_tc_inputs.back().onValueChanged([this](const ICE::UniformValue& v) { m_tc->setPosition(std::get(v)); }); m_tc_inputs.emplace_back("Rotation", tc->getRotation()); + m_tc_inputs.back().setForceVectorNumeric(true); m_tc_inputs.back().onValueChanged([this](const ICE::UniformValue& v) { m_tc->setRotation(std::get(v)); }); m_tc_inputs.emplace_back("Scale", tc->getScale()); + m_tc_inputs.back().setForceVectorNumeric(true); m_tc_inputs.back().onValueChanged([this](const ICE::UniformValue& v) { m_tc->setScale(std::get(v)); }); } } diff --git a/ICEBERG/UI/NewMaterialWidget.h b/ICEBERG/UI/NewMaterialWidget.h index d4819891..cd4def1e 100644 --- a/ICEBERG/UI/NewMaterialWidget.h +++ b/ICEBERG/UI/NewMaterialWidget.h @@ -83,17 +83,23 @@ class NewMaterialWidget : public Widget { void open(ICE::AssetUID id) { m_id = id; m_open = true; + m_material = m_engine->getAssetBank()->getAsset(id); auto shaders = m_engine->getAssetBank()->getAll(); std::vector shader_names; + int shader_idx = 0; + int i = 0; for (const auto& [id, shader] : shaders) { shader_names.push_back(m_engine->getAssetBank()->getName(id).toString()); + if (id == m_material->getShader()) { + shader_idx = i; + } + i++; } m_shaders_combo.setValues(shader_names); + m_shaders_combo.setSelected(shader_idx); auto name = m_engine->getAssetBank()->getName(id).getName(); memcpy(m_name, name.c_str(), name.size() + 1); - m_material = m_engine->getAssetBank()->getAsset(id); - m_shaders_combo.onSelectionChanged([this](const std::string& name, int) { m_material->setShader(m_engine->getAssetBank()->getUID(name)); }); m_uniform_names.clear(); From c6c89eafc3f93e34c996c0bf23d20d30df080501 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 15:20:35 +0100 Subject: [PATCH 11/15] fix material preview --- ICEBERG/UI/NewMaterialWidget.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ICEBERG/UI/NewMaterialWidget.h b/ICEBERG/UI/NewMaterialWidget.h index cd4def1e..a04b930c 100644 --- a/ICEBERG/UI/NewMaterialWidget.h +++ b/ICEBERG/UI/NewMaterialWidget.h @@ -180,6 +180,7 @@ class NewMaterialWidget : public Widget { camera->up(1); camera->pitch(-30); render_system->setCamera(camera); + render_system->setViewport(0, 0, 256, 256); s.getRegistry()->addSystem(render_system); From 45953013d75dc8267fca86a2ce1b2a763fe29d47 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 15:39:49 +0100 Subject: [PATCH 12/15] add light type and distance dropoff --- ICE/Components/include/LightComponent.h | 3 ++- ICEBERG/UI/InspectorWidget.h | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ICE/Components/include/LightComponent.h b/ICE/Components/include/LightComponent.h index eab56bf9..724b1fed 100644 --- a/ICE/Components/include/LightComponent.h +++ b/ICE/Components/include/LightComponent.h @@ -10,12 +10,13 @@ #include "Component.h" namespace ICE { -enum LightType { PointLight, DirectionalLight, SpotLight }; +enum LightType { PointLight = 0, DirectionalLight = 1, SpotLight = 2 }; struct LightComponent : public Component { LightComponent(LightType t, const Eigen::Vector3f &col) : type(t), color(col) {} LightType type; Eigen::Vector3f color; + float distance_dropoff = 0; }; } // namespace ICE diff --git a/ICEBERG/UI/InspectorWidget.h b/ICEBERG/UI/InspectorWidget.h index d49e103b..24379213 100644 --- a/ICEBERG/UI/InspectorWidget.h +++ b/ICEBERG/UI/InspectorWidget.h @@ -50,6 +50,7 @@ class InspectorWidget : public Widget { if (ImGui::Button("Remove")) { callback("remove_light_component_clicked"); } + m_lc_type_combo.render(); for (auto& input : m_lc_inputs) { ImGui::Text("%s", input.getLabel().c_str()); input.render(); @@ -106,8 +107,12 @@ class InspectorWidget : public Widget { m_lc = lc; m_lc_inputs.clear(); if (lc) { + m_lc_type_combo.setSelected(lc->type); + m_lc_type_combo.onSelectionChanged([this](const std::string&, int idx) { m_lc->type = static_cast(idx); }); m_lc_inputs.emplace_back("Color", m_lc->color); m_lc_inputs.back().onValueChanged([this](const ICE::UniformValue& v) { m_lc->color = std::get(v); }); + m_lc_inputs.emplace_back("Distance Dropoff", m_lc->distance_dropoff); + m_lc_inputs.back().onValueChanged([this](const ICE::UniformValue& v) { m_lc->distance_dropoff = std::get(v); }); } } @@ -120,6 +125,7 @@ class InspectorWidget : public Widget { ICE::LightComponent* m_lc = nullptr; std::vector m_lc_inputs; + ComboBox m_lc_type_combo{"Light Type", {"Point Light", "Directional Light", "Spot Light"}}; InputText m_input_entity_name{"##inspector_entity_name", ""}; }; From 64d877087918d589fddc9dccc1e3ce754ac342d8 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 15:43:33 +0100 Subject: [PATCH 13/15] Create new entity is now a child popup from tree items --- ICEBERG/UI/HierarchyWidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICEBERG/UI/HierarchyWidget.h b/ICEBERG/UI/HierarchyWidget.h index 1f0ba452..b6b1f22b 100644 --- a/ICEBERG/UI/HierarchyWidget.h +++ b/ICEBERG/UI/HierarchyWidget.h @@ -60,7 +60,7 @@ class HierarchyWidget : public Widget { } ImGui::EndDragDropTarget(); } - if (ImGui::BeginPopupContextWindow("hierarchy_popup")) { + if (ImGui::BeginPopupContextItem("hierarchy_popup")) { if (ImGui::Button("Create new entity")) { callback("create_entity_clicked", tree.id); ImGui::CloseCurrentPopup(); From 330675d0661fb628079d036bb5484c89f6f882d4 Mon Sep 17 00:00:00 2001 From: Thomas Ibanez Date: Fri, 20 Dec 2024 15:55:01 +0100 Subject: [PATCH 14/15] auto resize of popups (except material editor) --- ICEBERG/UI/AddComponentPopup.h | 3 ++- ICEBERG/UI/NewSceneWidget.h | 2 +- ICEBERG/UI/OpenSceneWidget.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ICEBERG/UI/AddComponentPopup.h b/ICEBERG/UI/AddComponentPopup.h index ed08c359..682e7ca0 100644 --- a/ICEBERG/UI/AddComponentPopup.h +++ b/ICEBERG/UI/AddComponentPopup.h @@ -21,7 +21,8 @@ class AddComponentPopup { ImGui::OpenPopup("Add Component"); m_open = false; } - if (ImGui::BeginPopupModal("Add Component")) { + ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX)); + if (ImGui::BeginPopupModal("Add Component", 0, ImGuiWindowFlags_AlwaysAutoResize)) { m_components_combo.render(); if (ImGui::Button("Add")) { switch (m_components_combo.getSelectedIndex()) { diff --git a/ICEBERG/UI/NewSceneWidget.h b/ICEBERG/UI/NewSceneWidget.h index b5335747..162a2f3b 100644 --- a/ICEBERG/UI/NewSceneWidget.h +++ b/ICEBERG/UI/NewSceneWidget.h @@ -19,7 +19,7 @@ class NewSceneWidget : public Widget { } ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - if (ImGui::BeginPopupModal("Scene Editor", 0, 0)) { + if (ImGui::BeginPopupModal("Scene Editor", 0, ImGuiWindowFlags_AlwaysAutoResize)) { m_scene_name_in.render(); if (ImGui::Button("Accept")) { m_accepted = true; diff --git a/ICEBERG/UI/OpenSceneWidget.h b/ICEBERG/UI/OpenSceneWidget.h index 9cc5e765..e2ac5919 100644 --- a/ICEBERG/UI/OpenSceneWidget.h +++ b/ICEBERG/UI/OpenSceneWidget.h @@ -24,7 +24,7 @@ class OpenSceneWidget : public Widget { } ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - if (ImGui::BeginPopupModal("Scene Selection", 0, 0)) { + if (ImGui::BeginPopupModal("Scene Selection", 0, ImGuiWindowFlags_AlwaysAutoResize)) { m_scene_name_combo.render(); if (ImGui::Button("Accept")) { m_accepted = true; From 862398250d20909d6fe79d6a446859f209042903 Mon Sep 17 00:00:00 2001 From: ProtectedVariable Date: Sat, 21 Dec 2024 00:27:09 +0100 Subject: [PATCH 15/15] only show available components in popup --- ICEBERG/UI/AddComponentPopup.h | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ICEBERG/UI/AddComponentPopup.h b/ICEBERG/UI/AddComponentPopup.h index 682e7ca0..48e55742 100644 --- a/ICEBERG/UI/AddComponentPopup.h +++ b/ICEBERG/UI/AddComponentPopup.h @@ -7,12 +7,21 @@ class AddComponentPopup { public: - AddComponentPopup() : m_components_combo("##add_component_combo", {"Render", "Transform", "Light"}) {} + AddComponentPopup() : m_components_combo("##add_component_combo", {"Render", "Light"}) {} void open(const std::shared_ptr ®istry, ICE::Entity entity) { m_registry = registry; m_entity = entity; m_open = true; + + std::vector values; + if(!registry->entityHasComponent(entity)) { + values.push_back("Render Component"); + } + if(!registry->entityHasComponent(entity)) { + values.push_back("Light Component"); + } + m_components_combo.setValues(values); } void render() { @@ -25,21 +34,19 @@ class AddComponentPopup { if (ImGui::BeginPopupModal("Add Component", 0, ImGuiWindowFlags_AlwaysAutoResize)) { m_components_combo.render(); if (ImGui::Button("Add")) { - switch (m_components_combo.getSelectedIndex()) { - case 0: - m_registry->addComponent(m_entity, ICE::RenderComponent(0, 0)); - break; - case 1: - m_registry->addComponent( - m_entity, ICE::TransformComponent(Eigen::Vector3f(0, 0, 0), Eigen::Vector3f(0, 0, 0), Eigen::Vector3f(1, 1, 1))); - break; - case 2: - m_registry->addComponent(m_entity, ICE::LightComponent(ICE::PointLight, Eigen::Vector3f(1, 1, 1))); - break; - } + if(m_components_combo.getSelectedItem() == "Render Component") + m_registry->addComponent(m_entity, ICE::RenderComponent(0, 0)); + + if(m_components_combo.getSelectedItem() == "Light Component") + m_registry->addComponent(m_entity, ICE::LightComponent(ICE::PointLight, Eigen::Vector3f(1, 1, 1))); ImGui::CloseCurrentPopup(); m_accepted = true; } + ImGui::SameLine(); + if(ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); + + } ImGui::EndPopup(); } ImGui::PopID();