add ImViewzmo, add floating window for QWER(select, translate, rotate, scale) , and add new debug button to floating (Experimental)
This commit is contained in:
@ -6,6 +6,9 @@
|
||||
#include <ImGuizmo.h>
|
||||
#include <filesystem>
|
||||
|
||||
#define IMVIEWGUIZMO_IMPLEMENTATION
|
||||
#include "ImViewGuizmo.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include "glm/gtx/matrix_decompose.hpp"
|
||||
|
||||
@ -46,7 +49,7 @@ namespace Prism
|
||||
|
||||
// OpenScene("assets/scenes/FPSDemo.scene");
|
||||
NewScene();
|
||||
m_CurrentScene = m_RuntimeScene;
|
||||
m_CurrentScene = m_EditorScene;
|
||||
|
||||
AssetEditorPanel::RegisterDefaultEditors();
|
||||
FileSystem::StartWatching();
|
||||
@ -589,122 +592,272 @@ namespace Prism
|
||||
|
||||
auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar
|
||||
auto viewportSize = ImGui::GetContentRegionAvail();
|
||||
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
if (m_RuntimeScene)
|
||||
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||
|
||||
|
||||
static int counter = 0;
|
||||
auto windowSize = ImGui::GetWindowSize();
|
||||
ImVec2 minBound = ImGui::GetWindowPos();
|
||||
minBound.x += viewportOffset.x;
|
||||
minBound.y += viewportOffset.y;
|
||||
|
||||
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
|
||||
m_ViewportBounds[0] = { minBound.x, minBound.y };
|
||||
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
|
||||
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
|
||||
|
||||
// ImGuizmo
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty())
|
||||
if (viewportSize.x != 0 && viewportSize.y != 0)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||
|
||||
const auto rw = (float)ImGui::GetWindowWidth();
|
||||
const auto rh = (float)ImGui::GetWindowHeight();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
|
||||
|
||||
bool snap = Input::IsKeyPressed(Key::LEFT_CONTROL);
|
||||
|
||||
TransformComponent& entityTransform = selection.Entity.Transform();
|
||||
// glm::mat4 transform = entityTransform.GetTransform();
|
||||
glm::mat4 transform = m_CurrentScene->GetTransformRelativeToParent(selection.Entity);
|
||||
float snapValue = GetSnapValue();
|
||||
float snapValues[3] = { snapValue, snapValue, snapValue };
|
||||
if (m_SelectionMode == SelectionMode::Entity)
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(transform),
|
||||
nullptr,
|
||||
snap ? snapValues : nullptr);
|
||||
|
||||
if (ImGuizmo::IsUsing())
|
||||
auto payload = ImGui::AcceptDragDropPayload("asset_payload");
|
||||
if (payload)
|
||||
{
|
||||
glm::vec3 translation, rotation, scale;
|
||||
Math::DecomposeTransform(transform, translation,rotation,scale);
|
||||
int count = payload->DataSize / sizeof(AssetHandle);
|
||||
|
||||
if (Entity parent = m_CurrentScene->FindEntityByUUID(selection.Entity.GetParentUUID()))
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
glm::vec3 parentTranslation, parentRotation, parentScale;
|
||||
Math::DecomposeTransform(m_CurrentScene->GetTransformRelativeToParent(parent), parentTranslation, parentRotation, parentScale);
|
||||
AssetHandle assetHandle = *(((AssetHandle*)payload->Data) + i);
|
||||
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(assetHandle);
|
||||
|
||||
glm::vec3 deltaRotation = (rotation - parentRotation) - entityTransform.Rotation;
|
||||
entityTransform.Translation = translation - parentTranslation;
|
||||
entityTransform.Rotation += deltaRotation;
|
||||
entityTransform.Scale = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
glm::vec3 deltaRotation = rotation - entityTransform.Rotation;
|
||||
entityTransform.Translation = translation;
|
||||
entityTransform.Rotation += deltaRotation;
|
||||
entityTransform.Scale = scale;
|
||||
// We can't really support dragging and dropping scenes when we're dropping multiple assets
|
||||
if (count == 1 && asset->Type == AssetType::Scene)
|
||||
{
|
||||
OpenScene(asset->FilePath);
|
||||
}
|
||||
|
||||
if (asset->Type == AssetType::Mesh)
|
||||
{
|
||||
Entity entity = m_EditorScene->CreateEntity(asset->FileName);
|
||||
entity.AddComponent<MeshComponent>(Ref<Mesh>(asset));
|
||||
SelectEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else
|
||||
{
|
||||
glm::mat4 transformBase = transform * selection.Mesh->Transform;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(transformBase),
|
||||
nullptr,
|
||||
snap ? snapValues : nullptr);
|
||||
|
||||
if (ImGuizmo::IsUsing())
|
||||
{
|
||||
selection.Mesh->Transform = glm::inverse(entityTransform.GetTransform()) * transformBase;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
auto payload = ImGui::AcceptDragDropPayload("asset_payload");
|
||||
if (payload)
|
||||
auto windowSize = ImGui::GetWindowSize();
|
||||
ImVec2 minBound = ImGui::GetWindowPos();
|
||||
minBound.x += viewportOffset.x;
|
||||
minBound.y += viewportOffset.y;
|
||||
|
||||
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
|
||||
m_ViewportBounds[0] = { minBound.x, minBound.y };
|
||||
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
|
||||
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
|
||||
|
||||
// ImGuizmo
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty())
|
||||
{
|
||||
int count = payload->DataSize / sizeof(AssetHandle);
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
const auto rw = (float)ImGui::GetWindowWidth();
|
||||
const auto rh = (float)ImGui::GetWindowHeight();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
|
||||
|
||||
bool snap = Input::IsKeyPressed(Key::LEFT_CONTROL);
|
||||
|
||||
TransformComponent& entityTransform = selection.Entity.Transform();
|
||||
// glm::mat4 transform = entityTransform.GetTransform();
|
||||
glm::mat4 transform = m_CurrentScene->GetTransformRelativeToParent(selection.Entity);
|
||||
float snapValue = GetSnapValue();
|
||||
float snapValues[3] = { snapValue, snapValue, snapValue };
|
||||
if (m_SelectionMode == SelectionMode::Entity)
|
||||
{
|
||||
AssetHandle assetHandle = *(((AssetHandle*)payload->Data) + i);
|
||||
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(assetHandle);
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(transform),
|
||||
nullptr,
|
||||
snap ? snapValues : nullptr);
|
||||
|
||||
// We can't really support dragging and dropping scenes when we're dropping multiple assets
|
||||
if (count == 1 && asset->Type == AssetType::Scene)
|
||||
if (ImGuizmo::IsUsing())
|
||||
{
|
||||
OpenScene(asset->FilePath);
|
||||
glm::vec3 translation, rotation, scale;
|
||||
Math::DecomposeTransform(transform, translation,rotation,scale);
|
||||
|
||||
if (Entity parent = m_CurrentScene->FindEntityByUUID(selection.Entity.GetParentUUID()))
|
||||
{
|
||||
glm::vec3 parentTranslation, parentRotation, parentScale;
|
||||
Math::DecomposeTransform(m_CurrentScene->GetTransformRelativeToParent(parent), parentTranslation, parentRotation, parentScale);
|
||||
|
||||
glm::vec3 deltaRotation = (rotation - parentRotation) - entityTransform.Rotation;
|
||||
entityTransform.Translation = translation - parentTranslation;
|
||||
entityTransform.Rotation += deltaRotation;
|
||||
entityTransform.Scale = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
glm::vec3 deltaRotation = rotation - entityTransform.Rotation;
|
||||
entityTransform.Translation = translation;
|
||||
entityTransform.Rotation += deltaRotation;
|
||||
entityTransform.Scale = scale;
|
||||
}
|
||||
}
|
||||
}else
|
||||
{
|
||||
glm::mat4 transformBase = transform * selection.Mesh->Transform;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(transformBase),
|
||||
nullptr,
|
||||
snap ? snapValues : nullptr);
|
||||
|
||||
if (asset->Type == AssetType::Mesh)
|
||||
if (ImGuizmo::IsUsing())
|
||||
{
|
||||
Entity entity = m_EditorScene->CreateEntity(asset->FileName);
|
||||
entity.AddComponent<MeshComponent>(Ref<Mesh>(asset));
|
||||
SelectEntity(entity);
|
||||
selection.Mesh->Transform = glm::inverse(entityTransform.GetTransform()) * transformBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
|
||||
// ImZmoToolBar
|
||||
{
|
||||
const float iconSize = 28.0f;
|
||||
const float padding = 6.0f;
|
||||
const ImU32 backgroundColor = IM_COL32(30, 30, 30, 140);
|
||||
const ImVec4 orangeMain = ImVec4(0.92f, 0.45f, 0.11f, 0.8f);
|
||||
|
||||
|
||||
ImGuiChildFlags child_flags = ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY;
|
||||
ImGuiWindowFlags Gizmo_window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(padding, padding));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 0));
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(10.0f, viewportOffset.y + 10.0f));
|
||||
|
||||
if (m_SceneState != SceneState::Play)
|
||||
{
|
||||
if (ImGui::BeginChild("GizmoToolbar", ImVec2(0, 0), child_flags, Gizmo_window_flags))
|
||||
{
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->AddRectFilled(ImGui::GetWindowPos(),
|
||||
ImVec2(ImGui::GetWindowPos().x + ImGui::GetWindowWidth(), ImGui::GetWindowPos().y + ImGui::GetWindowHeight()),
|
||||
backgroundColor, 6.0f);
|
||||
|
||||
auto drawGizmoBtn = [&](const char *label, int type, const char *tooltip)
|
||||
{
|
||||
bool isActive = (m_GizmoType == type);
|
||||
if (isActive)
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, orangeMain);
|
||||
else
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
|
||||
if (ImGui::Button(label, ImVec2(iconSize, iconSize)))
|
||||
m_GizmoType = type;
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
|
||||
ImGui::SetTooltip("%s", tooltip);
|
||||
ImGui::PopStyleColor();
|
||||
};
|
||||
|
||||
drawGizmoBtn("Q", -1, "Select (Q)");
|
||||
ImGui::SameLine();
|
||||
drawGizmoBtn("W", (int)ImGuizmo::TRANSLATE, "Translate (W)");
|
||||
ImGui::SameLine();
|
||||
drawGizmoBtn("E", (int)ImGuizmo::ROTATE, "Rotate (E)");
|
||||
ImGui::SameLine();
|
||||
drawGizmoBtn("R", (int)ImGuizmo::SCALE, "Scale (R)");
|
||||
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
|
||||
float centerX = minBound.x + viewportOffset.x + viewportSize.x * 0.5f;
|
||||
float topY = minBound.y + 10.0f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(centerX, topY), ImGuiCond_Always, ImVec2(0.5f, 0.0f));
|
||||
if (ImGui::BeginChild("DebugButton", ImVec2(0, 0), child_flags, Gizmo_window_flags))
|
||||
{
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->AddRectFilled(ImGui::GetWindowPos(),
|
||||
ImVec2(ImGui::GetWindowPos().x + ImGui::GetWindowWidth(), ImGui::GetWindowPos().y + ImGui::GetWindowHeight()),
|
||||
backgroundColor, 6.0f);
|
||||
|
||||
|
||||
// Scene control buttons
|
||||
const bool toolbarEnabled = (bool)m_CurrentScene;
|
||||
ImVec4 tintColor = toolbarEnabled ? ImVec4(1, 1, 1, 1) : ImVec4(1, 1, 1, 0.5f);
|
||||
|
||||
bool isEdit = m_SceneState == SceneState::Edit;
|
||||
bool isPlay = m_SceneState == SceneState::Play;
|
||||
// bool isSim = m_SceneState == SceneState::Pause;
|
||||
|
||||
auto drawImgBtn = [&](const char *id, Ref<Texture2D> iconRef, ImVec4 bg, auto func)
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, bg);
|
||||
const auto textureID = (ImTextureID)(uintptr_t)iconRef->GetRendererID();
|
||||
if (ImGui::ImageButton(id, textureID, ImVec2(iconSize - 6, iconSize - 6), {0, 0}, {1, 1}, {0, 0, 0, 0}, tintColor))
|
||||
{
|
||||
if (toolbarEnabled)
|
||||
func();
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
};
|
||||
|
||||
if (isEdit)
|
||||
{
|
||||
drawImgBtn("##Play", m_PlayButtonTex, ImVec4(0, 0, 0, 0), [this]()
|
||||
{ OnScenePlay(); });
|
||||
}
|
||||
else if (isPlay)
|
||||
{
|
||||
drawImgBtn("##Stop", m_StopButtonTex, ImVec4(0.8f, 0.1f, 0.1f, 0.6f), [this]()
|
||||
{ OnSceneStop(); });
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
// ImViewGuizmo
|
||||
if (m_SceneState != SceneState::Play)
|
||||
{
|
||||
ImViewGuizmo::BeginFrame();
|
||||
|
||||
auto &style = ImViewGuizmo::GetStyle();
|
||||
style.scale = 0.8f;
|
||||
|
||||
|
||||
const float gizmoSize = 256.0f * style.scale;
|
||||
const float inset = gizmoSize * 0.1f;
|
||||
|
||||
const ImVec2 gizmoCenter = ImVec2(
|
||||
maxBound.x - gizmoSize * 0.5f + inset,
|
||||
minBound.y + gizmoSize * 0.5f - inset);
|
||||
|
||||
glm::vec3 cameraPos = m_EditorCamera.GetPosition();
|
||||
glm::vec3 focusPosition = m_EditorCamera.GetFocusPosition();
|
||||
|
||||
float CameraYaw = m_EditorCamera.GetYaw();
|
||||
float CameraPitch = -m_EditorCamera.GetPitch();
|
||||
|
||||
glm::quat qYaw = glm::angleAxis(CameraYaw, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::quat qPitch = glm::angleAxis(CameraPitch, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
glm::quat cameraRot = qYaw * qPitch;
|
||||
|
||||
|
||||
if (ImViewGuizmo::Rotate(cameraPos, cameraRot, glm::vec3(0.0f), gizmoCenter))
|
||||
{
|
||||
|
||||
glm::vec3 forward = cameraRot * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
float newPitch = glm::asin(glm::clamp(-forward.y, -1.0f, 1.0f));
|
||||
float newYaw = -glm::atan(forward.x, -forward.z);
|
||||
|
||||
float distance = glm::length(cameraPos - focusPosition);
|
||||
m_EditorCamera.SetDistance(distance);
|
||||
m_EditorCamera.SetFocusPosition(focusPosition);
|
||||
m_EditorCamera.SetYawPitch(newYaw, newPitch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_RuntimeScene)
|
||||
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -756,7 +909,7 @@ namespace Prism
|
||||
break;
|
||||
|
||||
Entity selectedEntity = m_SelectionContext[0].Entity;
|
||||
m_EditorCamera.Focus(selectedEntity.Transform().Translation);
|
||||
m_EditorCamera.SetFocusPosition(selectedEntity.Transform().Translation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1059,23 +1212,25 @@ namespace Prism
|
||||
m_RuntimeScene = Ref<Scene>::Create();
|
||||
m_EditorScene->CopyTo(m_RuntimeScene);
|
||||
|
||||
m_RuntimeScene->OnRuntimeStart();
|
||||
m_SceneHierarchyPanel->SetContext(m_RuntimeScene);
|
||||
m_CurrentScene = m_RuntimeScene;
|
||||
|
||||
m_SceneHierarchyPanel->SetContext(m_CurrentScene);
|
||||
m_CurrentScene->OnRuntimeStart();
|
||||
}
|
||||
|
||||
void EditorLayer::OnSceneStop()
|
||||
{
|
||||
m_RuntimeScene->OnRuntimeStop();
|
||||
m_CurrentScene->OnRuntimeStop();
|
||||
m_SceneState = SceneState::Edit;
|
||||
|
||||
// Unload runtime scene
|
||||
m_RuntimeScene = nullptr;
|
||||
|
||||
m_SelectionContext.clear();
|
||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||
m_CurrentScene = m_EditorScene;
|
||||
|
||||
ScriptEngine::SetSceneContext(m_CurrentScene);
|
||||
m_SceneHierarchyPanel->SetContext(m_CurrentScene);
|
||||
}
|
||||
|
||||
float EditorLayer::GetSnapValue() const
|
||||
|
||||
Reference in New Issue
Block a user