diff --git a/include/NazaraEditor/Core.hpp b/include/NazaraEditor/Core.hpp new file mode 100644 index 0000000..6e4cc9f --- /dev/null +++ b/include/NazaraEditor/Core.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/include/NazaraEditor/Editor/Application.hpp b/include/NazaraEditor/Editor/Application.hpp new file mode 100644 index 0000000..67e2ac6 --- /dev/null +++ b/include/NazaraEditor/Editor/Application.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace Nz +{ + class EditorApplication + : public Nz::Application + { + public: + NazaraSignal(OnWorldChanged, Nz::EnttWorld*); + + // Entity lifetime events + NazaraSignal(OnEntityCreated, entt::handle); + NazaraSignal(OnEntityDestroyed, entt::handle); + NazaraSignal(OnEntityParentChanged, entt::handle); + + // Entity selection events + NazaraSignal(OnEntitySelected, entt::handle); + NazaraSignal(OnEntityDeselected, entt::handle); + + static EditorApplication& Instance(); + + void NewWorld(); + Nz::EnttWorld* GetCurrentWorld(); + + entt::handle CreateEntity(); + + template + void RegisterWindow() + { + static_assert(std::is_base_of::value, "Register Window should be called with a subclass of Nz::EditorWindow"); + m_windows.push_back(std::make_unique()); + } + + private: + EditorApplication(); + + std::unique_ptr m_windowSwapchain; + Nz::EnttWorld* m_world; + + std::vector> m_windows; + }; +} \ No newline at end of file diff --git a/include/NazaraEditor/Editor/UI/AssetsWindow.hpp b/include/NazaraEditor/Editor/UI/AssetsWindow.hpp new file mode 100644 index 0000000..78f14c8 --- /dev/null +++ b/include/NazaraEditor/Editor/UI/AssetsWindow.hpp @@ -0,0 +1,16 @@ +#include + +namespace Nz +{ + class EditorAssetsWindow + : public Nz::EditorWindow + { + public: + EditorAssetsWindow(); + + void ImportAsset(); + + protected: + void BuildMenuBar(); + }; +} diff --git a/include/NazaraEditor/Editor/UI/InspectorWindow.hpp b/include/NazaraEditor/Editor/UI/InspectorWindow.hpp new file mode 100644 index 0000000..ff6e278 --- /dev/null +++ b/include/NazaraEditor/Editor/UI/InspectorWindow.hpp @@ -0,0 +1,21 @@ +#include + +#include + +namespace Nz +{ + class EditorInspectorWindow + : public Nz::EditorWindow + { + public: + EditorInspectorWindow(); + + virtual void OnEditorGUI() override; + + protected: + void OnEntitySelected(entt::handle entity); + void OnEntityDeselected(entt::handle); + + entt::handle m_currentEntity; + }; +} \ No newline at end of file diff --git a/include/NazaraEditor/Editor/UI/LevelWindow.hpp b/include/NazaraEditor/Editor/UI/LevelWindow.hpp new file mode 100644 index 0000000..4a1c20f --- /dev/null +++ b/include/NazaraEditor/Editor/UI/LevelWindow.hpp @@ -0,0 +1,25 @@ +#include + +#include +#include + +namespace Nz +{ + class EditorLevelWindow + : public Nz::EditorWindow + { + public: + EditorLevelWindow(); + + virtual void OnEditorGUI() override; + + protected: + void RefreshEntities(); + + Nz::EnttWorld* m_currentWorld; + bool m_dirty; + + std::vector m_rootNodes; + std::map m_nodeToEntity; + }; +} \ No newline at end of file diff --git a/include/NazaraEditor/Editor/UI/MainWindow.hpp b/include/NazaraEditor/Editor/UI/MainWindow.hpp new file mode 100644 index 0000000..4b185a4 --- /dev/null +++ b/include/NazaraEditor/Editor/UI/MainWindow.hpp @@ -0,0 +1,24 @@ +#include + +namespace Nz +{ + class EditorMainWindow + : public Nz::EditorWindow + { + public: + EditorMainWindow(); + + bool Quit(); + + bool NewLevel(); + bool OpenLevel(); + bool SaveLevel(); + + bool NewProject(); + bool OpenProject(); + bool SaveProject(); + + protected: + void BuildMenuBar(); + }; +} \ No newline at end of file diff --git a/include/NazaraEditor/Nouveau Text Document.txt b/include/NazaraEditor/Nouveau Text Document.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/NazaraEditor/Editor/Application.cpp b/src/NazaraEditor/Editor/Application.cpp new file mode 100644 index 0000000..e61f79e --- /dev/null +++ b/src/NazaraEditor/Editor/Application.cpp @@ -0,0 +1,76 @@ +#include + +namespace Nz +{ + EditorApplication::EditorApplication() + : m_world(nullptr) + { + auto& windowing = AddComponent(); + + std::shared_ptr device = Nz::Graphics::Instance()->GetRenderDevice(); + + std::string windowTitle = "Nazara Editor"; + Nz::Window& window = windowing.CreateWindow(Nz::VideoMode(1280, 720, 32), windowTitle); + m_windowSwapchain = std::make_unique(device, window); + + // connect basic handler + window.GetEventHandler().OnQuit.Connect([&window](const auto* handler) { + NazaraUnused(handler); + window.Close(); + }); + + AddComponent(); + + Nz::Imgui::Instance()->Init(window); + ImGui::EnsureContextOnThisThread(); + + NewWorld(); + + AddUpdaterFunc(Interval{ Nz::Time::Milliseconds(16) }, [&](Nz::Time elapsed) { + if (!window.IsOpen()) + return; + + window.ProcessEvents(); + + Nz::RenderFrame frame = m_windowSwapchain->AcquireFrame(); + if (!frame) + return; + + Nz::Imgui::Instance()->Update(window, elapsed.AsSeconds()); + + Nz::Imgui::Instance()->Render(m_windowSwapchain.get(), frame); + + frame.Present(); + }); + } + + EditorApplication& EditorApplication::Instance() + { + static EditorApplication e; + return e; + } + + Nz::EnttWorld* EditorApplication::GetCurrentWorld() + { + return m_world; + } + + entt::handle EditorApplication::CreateEntity() + { + if (m_world == nullptr) + return {}; + + entt::handle entity = m_world->CreateEntity(); + entity.emplace(); + + OnEntityCreated(entity); + OnEntitySelected(entity); + return entity; + } + + void EditorApplication::NewWorld() + { + auto& ecs = GetComponent(); + m_world = &ecs.AddWorld(); + } +} \ No newline at end of file diff --git a/src/NazaraEditor/Editor/UI/AssetsWindow.cpp b/src/NazaraEditor/Editor/UI/AssetsWindow.cpp new file mode 100644 index 0000000..71ff874 --- /dev/null +++ b/src/NazaraEditor/Editor/UI/AssetsWindow.cpp @@ -0,0 +1,20 @@ +#include + +namespace Nz +{ + EditorAssetsWindow::EditorAssetsWindow() + : Nz::EditorWindow("Assets Browser") + { + BuildMenuBar(); + } + + void EditorAssetsWindow::ImportAsset() + { + + } + + void EditorAssetsWindow::BuildMenuBar() + { + AddMenuAction("Import", "Ctrl+I", [this]() { ImportAsset(); }); + } +} \ No newline at end of file diff --git a/src/NazaraEditor/Editor/UI/InspectorWindow.cpp b/src/NazaraEditor/Editor/UI/InspectorWindow.cpp new file mode 100644 index 0000000..af43194 --- /dev/null +++ b/src/NazaraEditor/Editor/UI/InspectorWindow.cpp @@ -0,0 +1,32 @@ +#include + +#include + +namespace Nz +{ + EditorInspectorWindow::EditorInspectorWindow() + : Nz::EditorWindow("Inspector") + { + EditorApplication::Instance().OnEntitySelected.Connect(this, &EditorInspectorWindow::OnEntitySelected); + } + + void EditorInspectorWindow::OnEditorGUI() + { + if (!m_currentEntity) + return; + + Nz::EditorPropertyInspector enumerator; + enumerator.AddProperty(m_currentEntity, "", ""); + ImGui::End(); + } + + void EditorInspectorWindow::OnEntitySelected(entt::handle entity) + { + m_currentEntity = entity; + } + + void EditorInspectorWindow::OnEntityDeselected(entt::handle) + { + m_currentEntity = {}; + } +} \ No newline at end of file diff --git a/src/NazaraEditor/Editor/UI/LevelWindow.cpp b/src/NazaraEditor/Editor/UI/LevelWindow.cpp new file mode 100644 index 0000000..428b0b9 --- /dev/null +++ b/src/NazaraEditor/Editor/UI/LevelWindow.cpp @@ -0,0 +1,58 @@ +#include + +#include + +namespace Nz +{ + EditorLevelWindow::EditorLevelWindow() + : Nz::EditorWindow("Level") + , m_currentWorld(EditorApplication::Instance().GetCurrentWorld()) + , m_dirty(true) + { + EditorApplication::Instance().OnWorldChanged.Connect([this](Nz::EnttWorld* world) { m_currentWorld = world; m_dirty = true; }); + EditorApplication::Instance().OnEntityCreated.Connect([this](entt::handle) { m_dirty = true; }); + EditorApplication::Instance().OnEntityDestroyed.Connect([this](entt::handle) { m_dirty = true; }); + EditorApplication::Instance().OnEntityParentChanged.Connect([this](entt::handle) { m_dirty = true; }); + } + + void EditorLevelWindow::OnEditorGUI() + { + RefreshEntities(); + + std::function drawHierarchy = [&](Nz::Node* c) + { + entt::handle entity = m_nodeToEntity[c]; + Nz::EditorImgui::Begin(entity, "", ""); + for (auto& child : c->GetChilds()) + drawHierarchy(child); + Nz::EditorImgui::End(entity); + }; + + for (auto& node : m_rootNodes) + drawHierarchy(node); + } + + void EditorLevelWindow::RefreshEntities() + { + if (!m_dirty) + return; + + m_dirty = false; + m_rootNodes.clear(); + m_nodeToEntity.clear(); + + if (m_currentWorld == nullptr) + return; + + m_currentWorld->GetRegistry().each([&](const entt::entity entity) { + entt::handle handle(m_currentWorld->GetRegistry(), entity); + Nz::NodeComponent* component = handle.try_get(); + if (component != nullptr) + { + m_nodeToEntity[component] = handle; + if (component->GetParent() == nullptr) + m_rootNodes.push_back(component); + } + }); + } +} \ No newline at end of file diff --git a/src/NazaraEditor/Editor/UI/MainWindow.cpp b/src/NazaraEditor/Editor/UI/MainWindow.cpp new file mode 100644 index 0000000..03269e8 --- /dev/null +++ b/src/NazaraEditor/Editor/UI/MainWindow.cpp @@ -0,0 +1,62 @@ +#include + +namespace Nz +{ + EditorMainWindow::EditorMainWindow() + : Nz::EditorWindow("MainWindow") + { + BuildMenuBar(); + } + + void EditorMainWindow::BuildMenuBar() + { + AddMenuAction("File|Project|New", "Ctrl+Shift+N", [this]() { NewProject(); }); + AddMenuAction("File|Project|Open", "Ctrl+Shift+O", [this]() { OpenProject(); }); + AddMenuAction("File|Project|Save", "Ctrl+Shift+S", [this]() { SaveProject(); }); + AddMenuAction("File|Level|New", "Ctrl+N", [this]() { NewLevel(); }); + AddMenuAction("File|Level|Open", "Ctrl+O", [this]() { OpenLevel(); }); + AddMenuAction("File|Level|Save", "Ctrl+S", [this]() { SaveLevel(); }); + AddMenuSeparator("File"); + AddMenuAction("File|Quit", "Ctrl+W", [this]() { Quit(); }); + } + + void EditorMainWindow::OnEditorGUI() + { + + } + + bool EditorMainWindow::Quit() + { + return true; + } + + bool EditorMainWindow::NewLevel() + { + return true; + } + + bool EditorMainWindow::OpenLevel() + { + return true; + } + + bool EditorMainWindow::SaveLevel() + { + return true; + } + + bool EditorMainWindow::NewProject() + { + return true; + } + + bool EditorMainWindow::OpenProject() + { + return true; + } + + bool EditorMainWindow::SaveProject() + { + return true; + } +} \ No newline at end of file diff --git a/src/NazaraEditor/Editor/main.cpp b/src/NazaraEditor/Editor/main.cpp new file mode 100644 index 0000000..df749ea --- /dev/null +++ b/src/NazaraEditor/Editor/main.cpp @@ -0,0 +1,44 @@ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +NAZARA_REQUEST_DEDICATED_GPU() + +#if 1 +int main(int argc, char* argv[]) +#else +int WinMain(int argc, char* argv[]) +#endif +{ + NazaraUnused(argc); + NazaraUnused(argv); + + Nz::EditorApplication& app = Nz::EditorApplication::Instance(); + app.RegisterWindow(); + app.RegisterWindow(); + app.RegisterWindow(); + app.RegisterWindow(); + + entt::meta() + .type(entt::type_hash::value()) + .func<&Nz::ReflectComponent, Nz::NodeComponent>>(entt::hashed_string("Reflect")); + entt::meta() + .type(entt::type_hash::value()) + .func<&Nz::ReflectComponent, Nz::LightComponent>>(entt::hashed_string("Reflect")); + + entt::handle entity = app.CreateEntity(); + + return app.Run(); +} \ No newline at end of file