#include "EditorCore.hpp" #include "App.hpp" #include "AppConfig.hpp" #include "CpuMesh.hpp" #include "EditorAccessories.hpp" #include "EditorAttachmentImpl.hpp" #include "EditorNotification.hpp" #include "EditorUtils.hpp" #include "GameObjectTypeTag.hpp" #include "Level.hpp" #include "Mesh.hpp" #include "Player.hpp" #define GLFW_INCLUDE_NONE #include #include #include #include #include namespace ProjectBrussel_UNITY_ID { void PushKeyCodeRecorder(App* app, int* writeKey, bool* writeKeyStatus) { app->PushKeyCaptureCallback([=](int key, int action) { // Allow the user to cancel by pressing Esc if (key == GLFW_KEY_ESCAPE) { return true; } if (action == GLFW_PRESS) { *writeKey = key; *writeKeyStatus = writeKeyStatus; return true; } return false; }); } } // namespace ProjectBrussel_UNITY_ID EditorInstance::EditorInstance(App* app, GameWorld* world) : mApp{ app } , mWorld{ world } , mEdInspector() , mEdContentBrowser(&mEdInspector) {} EditorInstance::~EditorInstance() { } void EditorInstance::Show() { if (!mWorld) return; ImGui::Begin("World properties"); ShowWorldProperties(); ImGui::End(); ImGui::Begin("World structure"); ShowGameObjectInTree(&mWorld->GetRoot()); ImGui::End(); ImGui::Begin("Inspector"); if (mSelectedGameObject) { ShowInspector(mSelectedGameObject); } ImGui::End(); } void EditorInstance::ShowWorldProperties() { } void EditorInstance::ShowInspector(GameObject* object) { using namespace Tags; using namespace ProjectBrussel_UNITY_ID; auto type = object->GetTypeTag(); switch (type) { case Tags::GOT_Player: { ShowGameObjecetFields(object); ImGui::Separator(); auto player = static_cast(object); auto& kb = player->keybinds; ImGui::Text("Player #%d", player->GetId()); if (ImGui::Button("Load config")) { bool success = player->LoadFromFile(); if (success) { ImGui::AddNotification(ImGuiToast(ImGuiToastType_Success, "Successfully loaded player config")); } } ImGui::SameLine(); if (ImGui::Button("Save config")) { bool success = player->SaveToFile(); if (success) { ImGui::AddNotification(ImGuiToast(ImGuiToastType_Success, "Successfully saved player config")); } } ImGui::Text("Move left (%s)", ImGui::GetKeyNameGlfw(kb.keyLeft)); ImGui::SameLine(); if (ImGui::Button("Change##Move left")) { PushKeyCodeRecorder(mApp, &kb.keyLeft, &kb.pressedLeft); } ImGui::Text("Move right (%s)", ImGui::GetKeyNameGlfw(kb.keyRight)); ImGui::SameLine(); if (ImGui::Button("Change##Move right")) { PushKeyCodeRecorder(mApp, &kb.keyRight, &kb.pressedRight); } ImGui::Text("Jump (%s)", ImGui::GetKeyNameGlfw(kb.keyJump)); ImGui::SameLine(); if (ImGui::Button("Change##Jump")) { PushKeyCodeRecorder(mApp, &kb.keyJump, &kb.pressedJump); } ImGui::Text("Attack (%s)", ImGui::GetKeyNameGlfw(kb.keyAttack)); ImGui::SameLine(); if (ImGui::Button("Change##Attack")) { PushKeyCodeRecorder(mApp, &kb.keyAttack, &kb.pressedAttack); } } break; case Tags::GOT_LevelWrapper: { ShowGameObjecetFields(object); ImGui::Separator(); auto lwo = static_cast(object); // TODO } break; default: ShowGameObjecetFields(object); break; } } void EditorInstance::ShowGameObjecetFields(GameObject* object) { auto pos = object->GetPos(); if (ImGui::InputFloat3("Position", &pos.x)) { object->SetPos(pos); } auto quat = object->GetRotation(); if (ImGui::InputFloat4("Rotation", &quat.x)) { object->SetRotation(quat); } } void EditorInstance::ShowGameObjectInTree(GameObject* object) { auto attachment = object->GetEditorAttachment(); if (!attachment) { attachment = EaGameObject::Create(object).release(); object->SetEditorAttachment(attachment); // NOTE: takes ownership } ImGuiTreeNodeFlags flags = 0; flags |= ImGuiTreeNodeFlags_DefaultOpen; flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; flags |= ImGuiTreeNodeFlags_OpenOnArrow; flags |= ImGuiTreeNodeFlags_SpanAvailWidth; if (mSelectedGameObject == object) { flags |= ImGuiTreeNodeFlags_Selected; } if (ImGui::TreeNodeEx(attachment->name.c_str(), flags)) { if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { mSelectedGameObject = object; } for (auto& child : object->GetChildren()) { ShowGameObjectInTree(child); } ImGui::TreePop(); } }