add basic editor
This commit is contained in:
parent
d1f132b07e
commit
a30e94dee9
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <NazaraEditor/Core/Core.hpp>
|
||||
#include <NazaraEditor/Core/UI/Window.hpp>
|
||||
#include <NazaraEditor/Core/Reflection/Math.hpp>
|
||||
#include <NazaraEditor/Core/Reflection/Core.hpp>
|
||||
#include <NazaraEditor/Core/Reflection/Utility.hpp>
|
||||
#include <NazaraEditor/Core/Reflection/Graphics.hpp>
|
||||
#include <NazaraEditor/Core/Reflection/Editor.hpp>
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <Nazara/Core.hpp>
|
||||
#include <Nazara/Graphics.hpp>
|
||||
#include <Nazara/Platform.hpp>
|
||||
#include <Nazara/Renderer.hpp>
|
||||
#include <Nazara/Utility.hpp>
|
||||
|
||||
#include <NazaraEditor/Core.hpp>
|
||||
#include <NazaraImgui/NazaraImgui.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class EditorApplication
|
||||
: public Nz::Application<Nz::Graphics, Nz::Imgui, Nz::EditorCore>
|
||||
{
|
||||
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<typename T>
|
||||
void RegisterWindow()
|
||||
{
|
||||
static_assert(std::is_base_of<Nz::EditorWindow, T>::value, "Register Window should be called with a subclass of Nz::EditorWindow");
|
||||
m_windows.push_back(std::make_unique<T>());
|
||||
}
|
||||
|
||||
private:
|
||||
EditorApplication();
|
||||
|
||||
std::unique_ptr<Nz::WindowSwapchain> m_windowSwapchain;
|
||||
Nz::EnttWorld* m_world;
|
||||
|
||||
std::vector<std::unique_ptr<Nz::EditorWindow>> m_windows;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <NazaraEditor/Core/UI/Window.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class EditorAssetsWindow
|
||||
: public Nz::EditorWindow
|
||||
{
|
||||
public:
|
||||
EditorAssetsWindow();
|
||||
|
||||
void ImportAsset();
|
||||
|
||||
protected:
|
||||
void BuildMenuBar();
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#include <NazaraEditor/Core/UI/Window.hpp>
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <NazaraEditor/Core/UI/Window.hpp>
|
||||
|
||||
#include <Nazara/Core.hpp>
|
||||
#include <Nazara/Utility.hpp>
|
||||
|
||||
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<Nz::Node*> m_rootNodes;
|
||||
std::map<Nz::Node*, entt::handle> m_nodeToEntity;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <NazaraEditor/Core/UI/Window.hpp>
|
||||
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
#include <NazaraEditor/Editor/Application.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
EditorApplication::EditorApplication()
|
||||
: m_world(nullptr)
|
||||
{
|
||||
auto& windowing = AddComponent<Nz::AppWindowingComponent>();
|
||||
|
||||
std::shared_ptr<Nz::RenderDevice> 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<Nz::WindowSwapchain>(device, window);
|
||||
|
||||
// connect basic handler
|
||||
window.GetEventHandler().OnQuit.Connect([&window](const auto* handler) {
|
||||
NazaraUnused(handler);
|
||||
window.Close();
|
||||
});
|
||||
|
||||
AddComponent<Nz::AppEntitySystemComponent>();
|
||||
|
||||
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<Nz::NodeComponent>();
|
||||
|
||||
OnEntityCreated(entity);
|
||||
OnEntitySelected(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void EditorApplication::NewWorld()
|
||||
{
|
||||
auto& ecs = GetComponent<Nz::AppEntitySystemComponent>();
|
||||
m_world = &ecs.AddWorld<Nz::EnttWorld>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <NazaraEditor/Editor/UI/AssetsWindow.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
EditorAssetsWindow::EditorAssetsWindow()
|
||||
: Nz::EditorWindow("Assets Browser")
|
||||
{
|
||||
BuildMenuBar();
|
||||
}
|
||||
|
||||
void EditorAssetsWindow::ImportAsset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditorAssetsWindow::BuildMenuBar()
|
||||
{
|
||||
AddMenuAction("Import", "Ctrl+I", [this]() { ImportAsset(); });
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <NazaraEditor/Editor/UI/InspectorWindow.hpp>
|
||||
|
||||
#include <NazaraEditor/Editor/Application.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
EditorInspectorWindow::EditorInspectorWindow()
|
||||
: Nz::EditorWindow("Inspector")
|
||||
{
|
||||
EditorApplication::Instance().OnEntitySelected.Connect(this, &EditorInspectorWindow::OnEntitySelected);
|
||||
}
|
||||
|
||||
void EditorInspectorWindow::OnEditorGUI()
|
||||
{
|
||||
if (!m_currentEntity)
|
||||
return;
|
||||
|
||||
Nz::EditorPropertyInspector<Nz::EditorRenderer> enumerator;
|
||||
enumerator.AddProperty(m_currentEntity, "", "");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void EditorInspectorWindow::OnEntitySelected(entt::handle entity)
|
||||
{
|
||||
m_currentEntity = entity;
|
||||
}
|
||||
|
||||
void EditorInspectorWindow::OnEntityDeselected(entt::handle)
|
||||
{
|
||||
m_currentEntity = {};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include <NazaraEditor/Editor/UI/LevelWindow.hpp>
|
||||
|
||||
#include <NazaraEditor/Editor/Application.hpp>
|
||||
|
||||
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<void(Nz::Node*)> 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<Nz::NodeComponent>();
|
||||
if (component != nullptr)
|
||||
{
|
||||
m_nodeToEntity[component] = handle;
|
||||
if (component->GetParent() == nullptr)
|
||||
m_rootNodes.push_back(component);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#include <NazaraEditor/Editor/UI/MainWindow.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
#include <Nazara/Core.hpp>
|
||||
#include <Nazara/Graphics.hpp>
|
||||
#include <Nazara/Platform.hpp>
|
||||
#include <Nazara/Renderer.hpp>
|
||||
#include <Nazara/Utility.hpp>
|
||||
|
||||
#include <NazaraImgui/NazaraImgui.hpp>
|
||||
#include <NazaraEditor/Core.hpp>
|
||||
|
||||
#include <NazaraEditor/Editor/Application.hpp>
|
||||
#include <NazaraEditor/Editor/UI/AssetsWindow.hpp>
|
||||
#include <NazaraEditor/Editor/UI/InspectorWindow.hpp>
|
||||
#include <NazaraEditor/Editor/UI/LevelWindow.hpp>
|
||||
#include <NazaraEditor/Editor/UI/MainWindow.hpp>
|
||||
|
||||
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<Nz::EditorMainWindow>();
|
||||
app.RegisterWindow<Nz::EditorAssetsWindow>();
|
||||
app.RegisterWindow<Nz::EditorLevelWindow>();
|
||||
app.RegisterWindow<Nz::EditorInspectorWindow>();
|
||||
|
||||
entt::meta<Nz::NodeComponent>()
|
||||
.type(entt::type_hash<Nz::NodeComponent>::value())
|
||||
.func<&Nz::ReflectComponent<Nz::EditorPropertyInspector<Nz::EditorRenderer>, Nz::NodeComponent>>(entt::hashed_string("Reflect"));
|
||||
entt::meta<Nz::LightComponent>()
|
||||
.type(entt::type_hash<Nz::LightComponent>::value())
|
||||
.func<&Nz::ReflectComponent<Nz::EditorPropertyInspector<Nz::EditorRenderer>, Nz::LightComponent>>(entt::hashed_string("Reflect"));
|
||||
|
||||
entt::handle entity = app.CreateEntity();
|
||||
|
||||
return app.Run();
|
||||
}
|
||||
Loading…
Reference in New Issue