diff options
author | hnOsmium0001 <[email protected]> | 2022-04-25 20:22:07 -0700 |
---|---|---|
committer | hnOsmium0001 <[email protected]> | 2022-04-25 20:22:07 -0700 |
commit | f54370de7e4214cb7813d26b1a39a8f6e42b7b56 (patch) | |
tree | 20913b4099b77af933fcd2ebb4e73f53b366ad8f /source/EditorCore.cpp | |
parent | c8ebee643f23c34ff57f69f8dfcf1903b59ea9d1 (diff) |
Initial work on rendering sprites to screen
Diffstat (limited to 'source/EditorCore.cpp')
-rw-r--r-- | source/EditorCore.cpp | 289 |
1 files changed, 234 insertions, 55 deletions
diff --git a/source/EditorCore.cpp b/source/EditorCore.cpp index 59da2b3..601a850 100644 --- a/source/EditorCore.cpp +++ b/source/EditorCore.cpp @@ -2,17 +2,20 @@ #include "App.hpp" #include "AppConfig.hpp" -#include "CpuMesh.hpp" #include "EditorAccessories.hpp" #include "EditorAttachmentImpl.hpp" +#include "EditorCommandPalette.hpp" #include "EditorNotification.hpp" #include "EditorUtils.hpp" -#include "GameObjectTags.hpp" +#include "GameObject.hpp" #include "Level.hpp" #include "Macros.hpp" #include "Mesh.hpp" #include "Player.hpp" +#include "SceneThings.hpp" #include "ScopeGuard.hpp" +#include "VertexIndex.hpp" +#include "YCombinator.hpp" #define GLFW_INCLUDE_NONE #include <GLFW/glfw3.h> @@ -217,6 +220,84 @@ void PushKeyCodeRecorder(App* app, int* writeKey, bool* writeKeyStatus) { return false; }); } + +struct GobjTreeNodeShowInfo { + EditorInstance* in_editor; + GameObject* out_openPopup = nullptr; +}; + +void GobjTreeNode(GobjTreeNodeShowInfo& showInfo, GameObject* object) { + auto& inspector = showInfo.in_editor->GetInspector(); + + auto attachment = object->GetEditorAttachment(); + if (!attachment) { + attachment = EaGameObject::Create(object).release(); + object->SetEditorAttachment(attachment); // NOTE: takes ownership + } + + ImGuiTreeNodeFlags flags = + ImGuiTreeNodeFlags_DefaultOpen | + ImGuiTreeNodeFlags_OpenOnDoubleClick | + ImGuiTreeNodeFlags_OpenOnArrow | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_NoTreePushOnOpen; + if (inspector.selectedItPtr == object) { + flags |= ImGuiTreeNodeFlags_Selected; + } + + ImGui::PushID(reinterpret_cast<uintptr_t>(object)); + // BEGIN tree node + + bool opened = ImGui::TreeNodeEx(attachment->name.c_str(), flags); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + inspector.SelectTarget(EditorInspector::ITT_GameObject, object); + } + if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + { + showInfo.out_openPopup = object; + } + + if (opened) { + ImGui::Indent(); + for (auto& child : object->GetChildren()) { + GobjTreeNode(showInfo, child); + } + ImGui::Unindent(); + } + + // END tree node + ImGui::PopID(); +}; + +#define GAMEOBJECT_CONSTRUCTOR(ClassName) [](GameWorld* world) -> GameObject* { return new ClassName(world); } +struct CreatableGameObject { + GameObject* (*factory)(GameWorld*); + const char* name; + GameObject::Kind kind; +} creatableGameObjects[] = { + { + .factory = GAMEOBJECT_CONSTRUCTOR(GameObject), + .name = "GameObject", + .kind = GameObject::KD_Generic, + }, + { + .factory = GAMEOBJECT_CONSTRUCTOR(SimpleGeometryObject), + .name = "Simple Geometry", + .kind = GameObject::KD_SimpleGeometry, + }, + { + .factory = GAMEOBJECT_CONSTRUCTOR(BuildingObject), + .name = "Building", + .kind = GameObject::KD_Building, + }, + { + .factory = GAMEOBJECT_CONSTRUCTOR(LevelWrapperObject), + .name = "Level Wrapper", + .kind = GameObject::KD_LevelWrapper, + }, +}; +#undef GAMEOBJECT_CONSTRUCTOR } // namespace ProjectBrussel_UNITY_ID EditorInstance::EditorInstance(App* app, GameWorld* world) @@ -228,44 +309,129 @@ EditorInstance::~EditorInstance() { } void EditorInstance::Show() { - if (!mWorld) return; + using namespace ProjectBrussel_UNITY_ID; + using namespace Tags; + + if (!mWorld) { + return; + } auto& io = ImGui::GetIO(); - if (io.KeyCtrl && ImGui::IsKeyPressed(GLFW_KEY_SPACE, false)) { - mEdContentBrowserVisible = !mEdContentBrowserVisible; + + ImGui::BeginMainMenuBar(); + if (ImGui::BeginMenu("View")) { + ImGui::MenuItem("ImGui Demo", nullptr, &mWindowVisible_ImGuiDemo); + ImGui::MenuItem("Command Palette", "Ctrl+Shift+P", &mWindowVisible_CommandPalette); + ImGui::MenuItem("Inspector", nullptr, &mWindowVisible_Inspector); + ImGui::MenuItem("Content Browser", "Ctrl+Space", &mWindowVisible_ContentBrowser); + ImGui::MenuItem("World Structure", nullptr, &mWindowVisible_WorldStructure); + ImGui::MenuItem("World Properties", nullptr, &mWindowVisible_WorldProperties); + ImGui::EndMenu(); } + ImGui::EndMainMenuBar(); - ImGui::Begin("World properties"); - ShowWorldProperties(); - ImGui::End(); + if (mWindowVisible_ImGuiDemo) { + ImGui::ShowDemoWindow(&mWindowVisible_ImGuiDemo); + } - ImGui::Begin("World structure"); - ShowGameObjectInTree(&mWorld->GetRoot()); - ImGui::End(); + if (io.KeyCtrl && io.KeyShift && ImGui::IsKeyPressed(GLFW_KEY_P, false)) { + mWindowVisible_CommandPalette = !mWindowVisible_CommandPalette; + } + if (mWindowVisible_CommandPalette) { + ImCmd::ShowCommandPaletteWindow("Command Palette", &mWindowVisible_CommandPalette); + } - ImGui::Begin("Inspector"); - switch (mEdInspector.selectedItt) { - case EditorInspector::ITT_GameObject: { - ShowInspector(static_cast<GameObject*>(mEdInspector.selectedItPtr)); - } break; + if (io.KeyCtrl && ImGui::IsKeyPressed(GLFW_KEY_SPACE, false)) { + mWindowVisible_ContentBrowser = !mWindowVisible_ContentBrowser; + } + if (mWindowVisible_ContentBrowser) { + mEdContentBrowser.Show(&mWindowVisible_ContentBrowser); + } - case EditorInspector::ITT_Ires: { - auto ires = static_cast<IresObject*>(mEdInspector.selectedItPtr); - ShowInspector(ires); - } break; + if (mWindowVisible_Inspector) { + ImGui::Begin("Inspector"); + switch (mEdInspector.selectedItt) { + case EditorInspector::ITT_GameObject: { + ShowInspector(static_cast<GameObject*>(mEdInspector.selectedItPtr)); + } break; - case EditorInspector::ITT_None: break; + case EditorInspector::ITT_Ires: { + auto ires = static_cast<IresObject*>(mEdInspector.selectedItPtr); + ShowInspector(ires); + } break; + + case EditorInspector::ITT_None: break; + } + ImGui::End(); } - ImGui::End(); - if (mEdContentBrowserVisible) { - mEdContentBrowser.Show(&mEdContentBrowserVisible); + if (mWindowVisible_WorldProperties) { + ImGui::Begin("World properties"); + ShowWorldProperties(); + ImGui::End(); + } + + if (mWindowVisible_WorldStructure) { + ImGui::Begin("World structure"); + { + GobjTreeNodeShowInfo showInfo{ + .in_editor = this, + }; + GobjTreeNode(showInfo, &mWorld->GetRoot()); + + if (showInfo.out_openPopup) { + mPopupCurrent_GameObject = showInfo.out_openPopup; + + ImGui::OpenPopup("GameObject Popup"); + ImGui::SetNextWindowPos(ImGui::GetMousePos()); + } + if (ImGui::BeginPopup("GameObject Popup")) { + // Target no longer selected during popup open + if (!mPopupCurrent_GameObject) { + ImGui::CloseCurrentPopup(); + } + + if (ImGui::BeginMenu("Add child")) { + for (size_t i = 0; i < std::size(creatableGameObjects); ++i) { + auto& info = creatableGameObjects[i]; + if (ImGui::MenuItem(info.name)) { + auto object = info.factory(mWorld); + mPopupCurrent_GameObject->AddChild(object); + } + } + ImGui::EndMenu(); + } + ImGui::Separator(); + if (ImGui::MenuItem("Remove")) { + // TODO + } + ImGui::EndPopup(); + } + } + ImGui::End(); } ShowSpriteViewer(); + + ImGui::ShowNotifications(); } void EditorInstance::ShowWorldProperties() { + if (mApp->IsGameRunning()) { + if (ImGui::Button("Pause")) { + mApp->SetGameRunning(false); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("The game is currently running. Click to pause."); + } + } else { + if (ImGui::Button("Play")) { + mApp->SetGameRunning(true); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("The game is currently paused. Click to run."); + } + } } // TOOD move resource-specific and gameobject-specific inspector code into attachments mechanism @@ -290,17 +456,42 @@ void EditorInstance::ShowInspector(GameObject* object) { } }; - auto type = object->GetTypeTag(); + auto type = object->GetKind(); switch (type) { - case Tags::GOT_Player: { + case GameObject::KD_Player: { ShowFields(); ImGui::Separator(); auto player = static_cast<Player*>(object); + auto ea = static_cast<EaPlayer*>(player->GetEditorAttachment()); auto& kb = player->keybinds; ImGui::Text("Player #%d", player->GetId()); + ImGui::TextUnformatted("Spritesheet: "); + ImGui::SameLine(); + IresObject::ShowReferenceSafe(*this, ea->confSprite.Get()); + if (ImGui::BeginDragDropTarget()) { + if (auto payload = ImGui::AcceptDragDropPayload(IresObject::ToString(IresObject::KD_Spritesheet).data())) { + auto spritesheet = *static_cast<IresSpritesheet* const*>(payload->Data); + ea->confSprite.Attach(spritesheet); + player->sprite.SetDefinition(spritesheet->GetInstance()); + } + ImGui::EndDragDropTarget(); + } + + ImGui::TextUnformatted("Material: "); + ImGui::SameLine(); + IresObject::ShowReferenceSafe(*this, ea->confMaterial.Get()); + if (ImGui::BeginDragDropTarget()) { + if (auto payload = ImGui::AcceptDragDropPayload(IresObject::ToString(IresObject::KD_Material).data())) { + auto material = *static_cast<IresMaterial* const*>(payload->Data); + ea->confMaterial.Attach(material); + player->SetMaterial(material->GetInstance()); + } + ImGui::EndDragDropTarget(); + } + if (ImGui::Button("Load config")) { bool success = player->LoadFromFile(); if (success) { @@ -340,49 +531,37 @@ void EditorInstance::ShowInspector(GameObject* object) { } } break; - case Tags::GOT_LevelWrapper: { + case GameObject::KD_SimpleGeometry: { ShowFields(); ImGui::Separator(); - auto lwo = static_cast<LevelWrapperObject*>(object); + auto sg = static_cast<SimpleGeometryObject*>(object); // TODO } break; - default: { + case GameObject::KD_Building: { ShowFields(); - } break; - } -} + ImGui::Separator(); -void EditorInstance::ShowGameObjectInTree(GameObject* object) { - auto attachment = object->GetEditorAttachment(); - if (!attachment) { - attachment = EaGameObject::Create(object).release(); - object->SetEditorAttachment(attachment); // NOTE: takes ownership - } + auto b = static_cast<BuildingObject*>(object); + // TODO + } break; - ImGuiTreeNodeFlags flags = 0; - flags |= ImGuiTreeNodeFlags_DefaultOpen; - flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; - flags |= ImGuiTreeNodeFlags_OpenOnArrow; - flags |= ImGuiTreeNodeFlags_SpanAvailWidth; - if (mEdInspector.selectedItPtr == object) { - flags |= ImGuiTreeNodeFlags_Selected; - } + case GameObject::KD_LevelWrapper: { + ShowFields(); + ImGui::Separator(); - if (ImGui::TreeNodeEx(attachment->name.c_str(), flags)) { - if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { - mEdInspector.SelectTarget(EditorInspector::ITT_GameObject, object); - } + auto lwo = static_cast<LevelWrapperObject*>(object); + // TODO + } break; - for (auto& child : object->GetChildren()) { - ShowGameObjectInTree(child); - } - ImGui::TreePop(); + default: { + ShowFields(); + } break; } } -void EditorInstance::OpenSpriteViewer(Sprite* sprite) { +void EditorInstance::OpenSpriteViewer(SpriteDefinition* sprite) { mSpriteView_Instance.Attach(sprite); mSpriteView_Frame = 0; mSpriteView_OpenNextFrame = true; |