aboutsummaryrefslogtreecommitdiff
path: root/source/EditorCore.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-05-07 17:27:01 -0700
committerrtk0c <[email protected]>2022-05-07 17:27:01 -0700
commit9fcdfe312fd9809a1cd52c08e7d8d7bd991a9fb3 (patch)
treec9820ea29a0d38c2adb7464386233415bfcccc10 /source/EditorCore.cpp
parentf348347f205f51800d0628021f193e63f5833f8d (diff)
Changeset: 25 Reduce dependency between editor headers and main game headers
Diffstat (limited to 'source/EditorCore.cpp')
-rw-r--r--source/EditorCore.cpp823
1 files changed, 0 insertions, 823 deletions
diff --git a/source/EditorCore.cpp b/source/EditorCore.cpp
deleted file mode 100644
index 8bdec40..0000000
--- a/source/EditorCore.cpp
+++ /dev/null
@@ -1,823 +0,0 @@
-#include "EditorCore.hpp"
-
-#include "App.hpp"
-#include "AppConfig.hpp"
-#include "EditorAccessories.hpp"
-#include "EditorAttachmentImpl.hpp"
-#include "EditorCommandPalette.hpp"
-#include "EditorNotification.hpp"
-#include "EditorUtils.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>
-
-#include <imgui.h>
-#include <misc/cpp/imgui_stdlib.h>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <functional>
-#include <limits>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <utility>
-
-using namespace std::literals;
-
-void EditorInspector::SelectTarget(TargetType type, void* object) {
- selectedItt = type;
- selectedItPtr = object;
- renaming = false;
- renamingScratchBuffer.clear();
-}
-
-EditorContentBrowser::EditorContentBrowser(EditorInspector* inspector)
- : mInspector{ inspector } {
-}
-
-EditorContentBrowser::~EditorContentBrowser() {
-}
-
-void EditorContentBrowser::Show(bool* open) {
- ImGuiWindowFlags windowFlags;
- if (mDocked) {
- // Center window horizontally, align bottom vertically
- auto& viewportSize = ImGui::GetMainViewport()->Size;
- ImGui::SetNextWindowPos(ImVec2(viewportSize.x / 2, viewportSize.y), ImGuiCond_Always, ImVec2(0.5f, 1.0f));
- ImGui::SetNextWindowSizeRelScreen(0.8f, mBrowserHeight);
- windowFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse;
- } else {
- windowFlags = 0;
- }
- ImGui::Begin("Content Browser", open, windowFlags);
-
- ImGui::Splitter(true, kSplitterThickness, &mSplitterLeft, &mSplitterRight, kLeftPaneMinWidth, kRightPaneMinWidth);
-
- ImGui::BeginChild("LeftPane", ImVec2(mSplitterLeft - kPadding, 0.0f));
- {
- if (ImGui::Selectable("Settings", mPane == P_Settings)) {
- mPane = P_Settings;
- }
- if (ImGui::Selectable("Ires", mPane == P_Ires)) {
- mPane = P_Ires;
- }
- }
- ImGui::EndChild();
-
- ImGui::SameLine(0.0f, kPadding + kSplitterThickness + kPadding);
- ImGui::BeginChild("RightPane"); // Fill remaining space
- switch (mPane) {
- case P_Settings: {
- ImGui::Checkbox("Docked", &mDocked);
- ImGui::SliderFloat("Height", &mBrowserHeight, 0.1f, 1.0f);
- } break;
-
- case P_Ires: {
- auto itt = mInspector->selectedItt;
- auto itPtr = mInspector->selectedItPtr;
- bool isIttIres = itt == EditorInspector::ITT_Ires;
-
- if (ImGui::Button("New")) {
- ImGui::OpenPopup("New Ires");
- }
- if (ImGui::BeginPopup("New Ires")) {
- for (int i = 0; i < IresObject::KD_COUNT; ++i) {
- auto kind = static_cast<IresObject::Kind>(i);
- if (ImGui::MenuItem(IresObject::ToString(kind).data())) {
- auto ires = IresObject::Create(kind);
- auto [DISCARD, success] = IresManager::instance->Add(ires.get());
- if (success) {
- (void)ires.release();
- }
- }
- }
- ImGui::EndPopup();
- }
-
- ImGui::SameLine();
- if (ImGui::Button("Refresh list") ||
- ImGui::IsKeyPressed(ImGuiKey_F5))
- {
- // TODO
- }
-
- ImGui::SameLine();
- if (ImGui::Button("Save", !isIttIres)) {
- auto ires = static_cast<IresObject*>(itPtr);
- IresManager::instance->Save(ires);
- }
-
- ImGui::SameLine();
- if (ImGui::Button("Reload", !isIttIres)) {
- auto ires = static_cast<IresObject*>(itPtr);
- IresManager::instance->Reload(ires);
- }
-
- ImGui::SameLine();
- if (ImGui::Button("Rename", !isIttIres) ||
- (isIttIres && ImGui::IsKeyPressed(ImGuiKey_F2, false)))
- {
- auto ires = static_cast<IresObject*>(itPtr);
- mInspector->renaming = true;
- mInspector->renamingScratchBuffer = ires->GetName();
- }
-
- ImGui::SameLine();
- if (ImGui::Button("Delete", !isIttIres) ||
- (isIttIres && ImGui::IsKeyPressed(ImGuiKey_Delete, false)))
- {
- ImGui::OpenPopup("Delete Ires");
- }
- bool openedDummy = true;
- if (ImGui::BeginPopupModal("Delete Ires", &openedDummy, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize)) {
- if (ImGui::Button("Confirm")) {
- auto ires = static_cast<IresObject*>(itPtr);
- IresManager::instance->Delete(ires);
- }
- ImGui::SameLine();
- if (ImGui::Button("Cancel")) {
- ImGui::CloseCurrentPopup();
- }
- ImGui::EndPopup();
- }
-
- auto& objects = IresManager::instance->GetObjects();
- for (auto it = objects.begin(); it != objects.end(); ++it) {
- auto ires = it->second.Get();
- auto& name = ires->GetName();
-
- bool selected = itPtr == ires;
-
- ImGuiSelectableFlags flags = 0;
- // When renaming, disable all other entries
- if (mInspector->renaming && !selected) {
- flags |= ImGuiSelectableFlags_Disabled;
- }
-
- if (mInspector->renaming && selected) {
- // State: being renamed
-
- ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 0, 0 });
- ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0);
- ImGui::SetKeyboardFocusHere();
- if (ImGui::InputText("##Rename", &mInspector->renamingScratchBuffer, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue)) {
- // Confirm
- ires->SetName(std::move(mInspector->renamingScratchBuffer));
- mInspector->renaming = false;
- }
- ImGui::PopStyleVar(2);
-
- if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
- // Cancel
- mInspector->renaming = false;
- }
- } else {
- // State: normal
-
- if (ImGui::Selectable(name.c_str(), selected, flags)) {
- mInspector->SelectTarget(EditorInspector::ITT_Ires, ires);
- }
- if (ImGui::BeginDragDropSource()) {
- auto kindName = IresObject::ToString(ires->GetKind());
- // Reason: intentionally using pointer as payload
- ImGui::SetDragDropPayload(kindName.data(), &ires, sizeof(ires)); // NOLINT(bugprone-sizeof-expression)
- ImGui::Text("%s '%s'", kindName.data(), name.c_str());
- ImGui::EndDragDropSource();
- }
- }
- }
- } break;
- }
- ImGui::EndChild();
-
- ImGui::End();
-}
-
-namespace ProjectBrussel_UNITY_ID {
-glm::quat CalcQuaternionFromDegreesEulerAngle(glm::vec3 eulerAngleDegrees) {
- glm::vec3 eulerAngleRadians;
- eulerAngleRadians.x = eulerAngleDegrees.x / 180 * M_PI;
- eulerAngleRadians.y = eulerAngleDegrees.y / 180 * M_PI;
- eulerAngleRadians.z = eulerAngleDegrees.z / 180 * M_PI;
- return glm::quat(eulerAngleRadians);
-}
-
-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;
- });
-}
-
-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)
- : mApp{ app }
- , mEdContentBrowser(&mEdInspector) {
- mEditorCamera.name = "Editor Camera"s;
- mEditorCamera.Move(glm::vec3(0, 0, 1));
- mEditorCamera.LookAtAngle(glm::vec3(0, 0, -1));
- mEditorCamera.SetHasPerspective(false);
-}
-
-EditorInstance::~EditorInstance() {
-}
-
-void EditorInstance::OnGameStateChanged(bool running) {
- if (running) {
- mApp->UnbindActiveCamera();
- } else {
- mApp->BindActiveCamera(&mEditorCamera);
- }
-}
-
-void EditorInstance::Show() {
- using namespace ProjectBrussel_UNITY_ID;
- using namespace Tags;
-
- auto world = mApp->GetWorld();
- auto& io = ImGui::GetIO();
-
- 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();
-
- if (mWindowVisible_ImGuiDemo) {
- ImGui::ShowDemoWindow(&mWindowVisible_ImGuiDemo);
- }
-
- if (io.KeyCtrl && io.KeyShift && ImGui::IsKeyPressed(GLFW_KEY_P, false)) {
- mWindowVisible_CommandPalette = !mWindowVisible_CommandPalette;
- }
- if (mWindowVisible_CommandPalette) {
- mEdCommandPalette.Show(&mWindowVisible_CommandPalette);
- }
-
- if (io.KeyCtrl && ImGui::IsKeyPressed(GLFW_KEY_SPACE, false)) {
- mWindowVisible_ContentBrowser = !mWindowVisible_ContentBrowser;
- }
- if (mWindowVisible_ContentBrowser) {
- mEdContentBrowser.Show(&mWindowVisible_ContentBrowser);
- }
-
- auto& camera = *mApp->GetActiveCamera();
- ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
- ImGuizmo::SetDrawlist(ImGui::GetForegroundDrawList());
-
- auto cameraPos = camera.pos;
- {
- if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) && !io.WantCaptureMouse && !mDragCam_Happening) {
- mDragCam_CamInitial = camera.pos;
- mDragCam_CursorInitial = ImGui::GetMousePos();
- mDragCam_Happening = true;
- }
- if (mDragCam_Happening) {
- auto newPos = ImGui::GetMousePos();
- // NOTE: we are emulating as if the mouse is dragging the "canvas", through moving the camera in the opposite direction of the natural position delta
- cameraPos.x = mDragCam_CamInitial.x + mDragCam_CursorInitial.x - newPos.x;
- cameraPos.y = mDragCam_CamInitial.y + -(mDragCam_CursorInitial.y - newPos.y); // Invert Y delta because ImGui uses top-left origin (mouse moving down translates to positive value, but in our coordinate system down is negative)
-
- // Draw movement indicator
- auto drawList = ImGui::GetForegroundDrawList();
- ImGui::DrawArrow(drawList, ImVec2(mDragCam_CursorInitial.x, mDragCam_CursorInitial.y), newPos, IM_COL32(0, 255, 255, 255));
- }
- if (ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
- mDragCam_Happening = false;
- }
-
- if (mMoveCamKeyboard) {
- constexpr float kCameraMoveSpeed = 5.0f;
- if (ImGui::IsKeyDown(ImGuiKey_W)) {
- cameraPos.y += kCameraMoveSpeed;
- }
- if (ImGui::IsKeyDown(ImGuiKey_S)) {
- cameraPos.y -= kCameraMoveSpeed;
- }
- if (ImGui::IsKeyDown(ImGuiKey_A)) {
- cameraPos.x -= kCameraMoveSpeed;
- }
- if (ImGui::IsKeyDown(ImGuiKey_D)) {
- cameraPos.x += kCameraMoveSpeed;
- }
- }
- }
- camera.Move(cameraPos);
-
- if (mWindowVisible_Inspector) {
- ImGui::Begin("Inspector");
- switch (mEdInspector.selectedItt) {
- case EditorInspector::ITT_GameObject: {
- auto object = static_cast<GameObject*>(mEdInspector.selectedItPtr);
- ShowInspector(object);
- } break;
-
- case EditorInspector::ITT_Ires: {
- auto ires = static_cast<IresObject*>(mEdInspector.selectedItPtr);
- ShowInspector(ires);
- } break;
-
- case EditorInspector::ITT_None: break;
- }
- ImGui::End();
- }
-
- if (mWindowVisible_WorldProperties) {
- ImGui::Begin("World properties");
- ShowWorldProperties();
- ImGui::End();
- }
-
- if (mWindowVisible_WorldStructure) {
- ImGui::Begin("World structure");
- GobjTreeNodeShowInfo showInfo{
- .in_editor = this,
- };
- GobjTreeNode(showInfo, &world->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(world);
- mPopupCurrent_GameObject->AddChild(object);
- }
- }
- ImGui::EndMenu();
- }
- ImGui::Separator();
- if (ImGui::MenuItem("Remove")) {
- ImGui::DialogConfirmation("Are you sure you want to delete this GameObject?", [object = mPopupCurrent_GameObject](bool yes) {
- object->RemoveSelfFromParent();
- delete object;
- });
- }
- ImGui::EndPopup();
- }
- ImGui::End();
- }
-
- ShowSpriteViewer();
-
- ImGui::ShowDialogs();
- 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.");
- }
- }
-
- auto& camera = *mApp->GetActiveCamera();
- ImGui::TextUnformatted("Active camera:");
- ImGui::Indent();
-#define CAMERA_POS_TEXT "at (%.3f, %.3f, %.3f)\nlooking at (%.3f, %.3f, %.3f)", camera.pos.x, camera.pos.y, camera.pos.z, camera.lookAt.x, camera.lookAt.y, camera.lookAt.z
- ImGui::TextUnformatted(camera.name.c_str());
- ImGui::Text(CAMERA_POS_TEXT);
- if (ImGui::BeginPopupContextItem("##CTXMENU")) {
- if (ImGui::MenuItem("Reset to origin")) {
- camera.Move(glm::vec3(1.0f, 1.0f, 1.0f));
- }
- if (ImGui::MenuItem("Copy")) {
- char buffer[2048];
- int result = snprintf(buffer, sizeof(buffer), CAMERA_POS_TEXT);
- ImGui::SetClipboardText(buffer);
- ImGui::AddNotification(ImGuiToast(ImGuiToastType_Success, "Copied to clipboard."));
- }
- ImGui::EndPopup();
- }
-#undef CAMERA_POS_TEXT
- ImGui::Checkbox("Move camera with WASD", &mMoveCamKeyboard);
- ImGui::Unindent();
-}
-
-// TOOD move resource-specific and gameobject-specific inspector code into attachments mechanism
-
-void EditorInstance::ShowInspector(IresObject* ires) {
- ires->ShowEditor(*this);
-}
-
-void EditorInstance::ShowInspector(GameObject* object) {
- using namespace Tags;
- using namespace ProjectBrussel_UNITY_ID;
-
- auto& io = ImGui::GetIO();
-
- auto objectEa = static_cast<EaGameObject*>(object->GetEditorAttachment());
-
- auto ShowInspector = [&](/*array[6]*/ float* bounds = nullptr) {
- glm::mat4 identityMatrix(1.00f);
-
- if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_T))
- mGuizmo.currOperation = ImGuizmo::TRANSLATE;
- if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_R))
- mGuizmo.currOperation = ImGuizmo::ROTATE;
- if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_S))
- mGuizmo.currOperation = ImGuizmo::SCALE;
- if (ImGui::RadioButton("Translate", mGuizmo.currOperation == ImGuizmo::TRANSLATE))
- mGuizmo.currOperation = ImGuizmo::TRANSLATE;
- ImGui::SameLine();
- if (ImGui::RadioButton("Rotate", mGuizmo.currOperation == ImGuizmo::ROTATE))
- mGuizmo.currOperation = ImGuizmo::ROTATE;
- ImGui::SameLine();
- if (ImGui::RadioButton("Scale", mGuizmo.currOperation == ImGuizmo::SCALE))
- mGuizmo.currOperation = ImGuizmo::SCALE;
- ImGui::SameLine();
- if (ImGui::RadioButton("Universal", mGuizmo.currOperation == ImGuizmo::UNIVERSAL))
- mGuizmo.currOperation = ImGuizmo::UNIVERSAL;
-
- if (mGuizmo.currOperation != ImGuizmo::SCALE) {
- if (ImGui::RadioButton("Local", mGuizmo.currMode == ImGuizmo::LOCAL))
- mGuizmo.currMode = ImGuizmo::LOCAL;
- ImGui::SameLine();
- if (ImGui::RadioButton("World", mGuizmo.currMode == ImGuizmo::WORLD))
- mGuizmo.currMode = ImGuizmo::WORLD;
- }
-
- ImGui::Checkbox("##UseSnap", &mGuizmo.useSnap);
- ImGui::SameLine();
- switch (mGuizmo.currOperation) {
- case ImGuizmo::TRANSLATE:
- ImGui::InputFloat3("Pos Snap", &mGuizmo.snap[0]);
- break;
- case ImGuizmo::ROTATE:
- ImGui::InputFloat("Angle Snap", &mGuizmo.snap[0]);
- break;
- case ImGuizmo::SCALE:
- ImGui::InputFloat("Scale Snap", &mGuizmo.snap[0]);
- break;
- default: break;
- }
-
- if (bounds) {
- ImGui::Checkbox("Bound Sizing", &mGuizmo.boundSizing);
- if (mGuizmo.boundSizing) {
- ImGui::PushID(3);
- ImGui::Checkbox("##BoundSizing", &mGuizmo.boundSizingSnap);
- ImGui::SameLine();
- ImGui::InputFloat3("Bound Snap", mGuizmo.boundsSnap);
- ImGui::PopID();
- }
- }
-
- ImGui::Separator();
-
- auto objectPos = object->GetPos();
- if (ImGui::InputFloat3("Translation", &objectPos.x)) {
- object->SetPos(objectPos);
- }
-
- auto objectRot = object->GetRotation();
- if (ImGui::InputFloat3("Rotation", &objectEa->eulerAnglesRotation.x)) {
- objectRot = CalcQuaternionFromDegreesEulerAngle(objectEa->eulerAnglesRotation);
- object->SetRotation(objectRot);
- }
-
- auto objectScale = object->GetScale();
- if (ImGui::InputFloat3("Scale", &objectScale.x)) {
- object->SetScale(objectScale);
- }
- };
-
- auto ShowGuizmo = [&](/*array[6]*/ float* bounds = nullptr) {
- glm::mat4 identityMatrix(1.00f);
-
- // TODO get rid of this massive hack: how to manage const better for intuitively read-only, but write doesn't-care data?
- auto& lastFrameInfo = const_cast<RendererFrameInfo&>(mApp->mWorldRenderer.GetLastFrameInfo());
- auto& cameraViewMat = lastFrameInfo.matrixView;
- float* cameraView = &cameraViewMat[0][0];
- auto& cameraProjMat = lastFrameInfo.matrixProj;
- float* cameraProj = &cameraProjMat[0][0];
-
- auto objectPos = object->GetPos();
- auto objectScale = object->GetScale();
-
- float matrix[16];
- ImGuizmo::RecomposeMatrixFromComponents(&objectPos.x, &objectEa->eulerAnglesRotation.x, &objectScale.x, matrix);
-
- bool edited = ImGuizmo::Manipulate(
- cameraView,
- cameraProj,
- mGuizmo.currOperation,
- mGuizmo.currMode,
- matrix,
- nullptr,
- mGuizmo.useSnap ? mGuizmo.snap : nullptr,
- mGuizmo.boundSizing ? bounds : nullptr,
- (bounds && mGuizmo.boundSizingSnap) ? mGuizmo.boundsSnap : nullptr);
-
- if (edited) {
- ImGuizmo::DecomposeMatrixToComponents(matrix, &objectPos.x, &objectEa->eulerAnglesRotation.x, &objectScale.x);
- object->SetPos(objectPos);
- object->SetRotation(CalcQuaternionFromDegreesEulerAngle(objectEa->eulerAnglesRotation));
- object->SetScale(objectScale);
- }
- };
-
- auto type = object->GetKind();
- switch (type) {
- case GameObject::KD_Player: {
- ShowInspector();
- ShowGuizmo();
- ImGui::Separator();
-
- auto player = static_cast<Player*>(object);
- auto ea = static_cast<EaPlayer*>(objectEa);
- 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);
- auto def = spritesheet->GetInstance();
- player->sprite.SetDefinition(def);
- player->renderObject.autofill_TextureAtlas.Attach(def->GetAtlas());
- }
- 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) {
- 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 GameObject::KD_SimpleGeometry: {
- auto sg = static_cast<SimpleGeometryObject*>(object);
-
- float bounds[6] = {
- /*x1*/ -sg->GetSize().x / 2.0f,
- /*y1*/ -sg->GetSize().y / 2.0f,
- /*z1*/ 0.0f,
- /*x2*/ +sg->GetSize().x / 2.0f,
- /*y2*/ +sg->GetSize().y / 2.0f,
- /*z2*/ 0.0f,
- };
-
- ShowInspector(bounds);
- ShowGuizmo(bounds);
- ImGui::Separator();
-
- sg->SetSize(glm::vec2(bounds[3] - bounds[0], bounds[4] - bounds[1]));
-
- auto size = sg->GetSize();
- if (ImGui::InputFloat2("Size", &size.x)) {
- sg->SetSize(size);
- }
- } break;
-
- case GameObject::KD_Building: {
- ShowInspector();
- ShowGuizmo();
- ImGui::Separator();
-
- auto b = static_cast<BuildingObject*>(object);
- // TODO
- } break;
-
- case GameObject::KD_LevelWrapper: {
- ShowInspector();
- ShowGuizmo();
- ImGui::Separator();
-
- auto lwo = static_cast<LevelWrapperObject*>(object);
- // TODO
- } break;
-
- default: {
- ShowInspector();
- ShowGuizmo();
- } break;
- }
-}
-
-void EditorInstance::OpenSpriteViewer(SpriteDefinition* sprite) {
- mSpriteView_Instance.Attach(sprite);
- mSpriteView_Frame = 0;
- mSpriteView_OpenNextFrame = true;
-}
-
-void EditorInstance::ShowSpriteViewer() {
- if (mSpriteView_Instance == nullptr) return;
- if (!mSpriteView_Instance->IsValid()) return;
-
- if (mSpriteView_OpenNextFrame) {
- mSpriteView_OpenNextFrame = false;
- ImGui::OpenPopup("Sprite Viewer");
- }
-
- bool windowOpen = true;
- if (ImGui::BeginPopupModal("Sprite Viewer", &windowOpen)) {
- auto atlas = mSpriteView_Instance->GetAtlas();
- auto atlasSize = atlas->GetInfo().size;
- auto& frames = mSpriteView_Instance->GetFrames();
-
- int frameCount = mSpriteView_Instance->GetFrames().size();
- if (ImGui::Button("<")) {
- --mSpriteView_Frame;
- }
- ImGui::SameLine();
- ImGui::Text("%d/%d", mSpriteView_Frame + 1, frameCount);
- ImGui::SameLine();
- if (ImGui::Button(">")) {
- ++mSpriteView_Frame;
- }
- // Scrolling down (negative value) should advance, so invert the sign
- mSpriteView_Frame += -std::round(ImGui::GetIO().MouseWheel);
- // Clamp mSpriteView_Frame to range [0, frameCount)
- if (mSpriteView_Frame < 0) {
- mSpriteView_Frame = frameCount - 1;
- } else if (mSpriteView_Frame >= frameCount) {
- mSpriteView_Frame = 0;
- }
-
- auto& currFrame = frames[mSpriteView_Frame];
- auto boundingBox = mSpriteView_Instance->GetBoundingBox();
- ImGui::Text("Frame size: (%d, %d)", boundingBox.x, boundingBox.y);
- ImGui::Text("Frame location: (%f, %f) to (%f, %f)", currFrame.u0, currFrame.v0, currFrame.u1, currFrame.v1);
- ImGui::Image(
- (ImTextureID)(uintptr_t)atlas->GetHandle(),
- Utils::FitImage(atlasSize),
- ImVec2(currFrame.u0, currFrame.v0),
- ImVec2(currFrame.u1, currFrame.v1));
-
- ImGui::EndPopup();
- }
-}