Stabilize debug startup and modularize scene interactions
This commit is contained in:
parent
79fe8fb906
commit
706d4553f8
@ -325,7 +325,6 @@ public:
|
||||
BeginRename(editorContext, requestedRenameId);
|
||||
}
|
||||
|
||||
DrawToolbar(editorContext);
|
||||
ImGui::TextUnformatted("SampleScene");
|
||||
ImGui::Separator();
|
||||
|
||||
@ -339,20 +338,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void DrawToolbar(MetaCoreEditorContext& editorContext) {
|
||||
const bool keepWorld = editorContext.GetReparentTransformRule() == MetaCoreReparentTransformRule::KeepWorld;
|
||||
if (ImGui::Button("保持世界", ImVec2(84.0F, 0.0F))) {
|
||||
editorContext.SetReparentTransformRule(MetaCoreReparentTransformRule::KeepWorld);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("保持局部", ImVec2(84.0F, 0.0F))) {
|
||||
editorContext.SetReparentTransformRule(MetaCoreReparentTransformRule::KeepLocal);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled(keepWorld ? "当前: 世界" : "当前: 局部");
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
void DrawHierarchyNode(MetaCoreEditorContext& editorContext, MetaCoreId objectId) {
|
||||
MetaCoreScene& scene = editorContext.GetScene();
|
||||
MetaCoreGameObject* gameObject = scene.FindGameObject(objectId);
|
||||
|
||||
@ -54,7 +54,7 @@ void MetaCoreTraceStartup(const char*) {
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
constexpr bool GMetaCoreEnableImGuizmo = false;
|
||||
constexpr bool GMetaCoreEnableImGuizmo = true;
|
||||
#else
|
||||
constexpr bool GMetaCoreEnableImGuizmo = true;
|
||||
#endif
|
||||
@ -79,6 +79,25 @@ void MetaCoreApplyEditorStyle() {
|
||||
style.Colors[ImGuiCol_Tab] = ImVec4(0.12F, 0.14F, 0.16F, 1.0F);
|
||||
style.Colors[ImGuiCol_TabSelected] = ImVec4(0.20F, 0.26F, 0.34F, 1.0F);
|
||||
style.Colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
|
||||
// Optimize ImGuizmo style for premium feel and remove hatching artifacts (black dashed lines).
|
||||
ImGuizmo::Style& gizmoStyle = ImGuizmo::GetStyle();
|
||||
gizmoStyle.TranslationLineThickness = 3.5F;
|
||||
gizmoStyle.ScaleLineThickness = 3.5F;
|
||||
gizmoStyle.RotationLineThickness = 3.0F;
|
||||
gizmoStyle.RotationOuterLineThickness = 2.0F;
|
||||
gizmoStyle.CenterCircleSize = 4.0F;
|
||||
gizmoStyle.HatchedAxisLineThickness = 0.0F; // Disables the black dashed segments.
|
||||
gizmoStyle.TranslationLineArrowSize = 6.0F;
|
||||
|
||||
// Unity-style Color Palette
|
||||
gizmoStyle.Colors[ImGuizmo::DIRECTION_X] = ImVec4(0.85F, 0.25F, 0.25F, 1.0F); // Red
|
||||
gizmoStyle.Colors[ImGuizmo::DIRECTION_Y] = ImVec4(0.55F, 0.80F, 0.10F, 1.0F); // Green
|
||||
gizmoStyle.Colors[ImGuizmo::DIRECTION_Z] = ImVec4(0.25F, 0.50F, 0.95F, 1.0F); // Blue
|
||||
gizmoStyle.Colors[ImGuizmo::PLANE_X] = ImVec4(0.85F, 0.25F, 0.25F, 0.38F);
|
||||
gizmoStyle.Colors[ImGuizmo::PLANE_Y] = ImVec4(0.55F, 0.80F, 0.10F, 0.38F);
|
||||
gizmoStyle.Colors[ImGuizmo::PLANE_Z] = ImVec4(0.25F, 0.50F, 0.95F, 0.38F);
|
||||
gizmoStyle.Colors[ImGuizmo::SELECTION] = ImVec4(1.00F, 0.80F, 0.10F, 1.0F); // Orange-Yellow
|
||||
}
|
||||
|
||||
void MetaCoreConfigureChineseFont() {
|
||||
@ -122,89 +141,7 @@ void MetaCoreConfigureChineseFont() {
|
||||
#endif
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transform) {
|
||||
const glm::mat4 translationMatrix = glm::translate(glm::mat4(1.0F), transform.Position);
|
||||
const glm::mat4 rotationMatrix = glm::yawPitchRoll(
|
||||
glm::radians(transform.RotationEulerDegrees.y),
|
||||
glm::radians(transform.RotationEulerDegrees.x),
|
||||
glm::radians(transform.RotationEulerDegrees.z)
|
||||
);
|
||||
const glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0F), transform.Scale);
|
||||
return translationMatrix * rotationMatrix * scaleMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildPandaBasisMatrix() {
|
||||
glm::mat4 basis(1.0F);
|
||||
basis[0] = glm::vec4(1.0F, 0.0F, 0.0F, 0.0F);
|
||||
basis[1] = glm::vec4(0.0F, 0.0F, 1.0F, 0.0F);
|
||||
basis[2] = glm::vec4(0.0F, -1.0F, 0.0F, 0.0F);
|
||||
basis[3] = glm::vec4(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
return basis;
|
||||
}
|
||||
|
||||
glm::vec3 MetaCoreToPandaSpacePoint(const glm::vec3& value) {
|
||||
return glm::vec3(value.x, -value.z, value.y);
|
||||
}
|
||||
|
||||
glm::vec3 MetaCoreToPandaSpaceVector(const glm::vec3& value) {
|
||||
return glm::vec3(value.x, -value.z, value.y);
|
||||
}
|
||||
|
||||
glm::vec3 MetaCoreFromPandaSpacePoint(const glm::vec3& value) {
|
||||
return glm::vec3(value.x, value.z, -value.y);
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildPandaSpaceTransformMatrix(const MetaCoreTransformComponent& transform) {
|
||||
const glm::mat4 basis = MetaCoreBuildPandaBasisMatrix();
|
||||
const glm::mat4 inverseBasis = glm::inverse(basis);
|
||||
return basis * MetaCoreBuildTransformMatrix(transform) * inverseBasis;
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreConvertPandaSpaceMatrixToMetaCoreMatrix(const glm::mat4& pandaSpaceMatrix) {
|
||||
const glm::mat4 basis = MetaCoreBuildPandaBasisMatrix();
|
||||
const glm::mat4 inverseBasis = glm::inverse(basis);
|
||||
return inverseBasis * pandaSpaceMatrix * basis;
|
||||
}
|
||||
|
||||
void MetaCoreApplyMatrixToTransform(const glm::mat4& matrix, MetaCoreTransformComponent& transform) {
|
||||
glm::vec3 skew{};
|
||||
glm::vec4 perspective{};
|
||||
glm::quat rotation{};
|
||||
glm::decompose(matrix, transform.Scale, rotation, transform.Position, skew, perspective);
|
||||
transform.RotationEulerDegrees = glm::degrees(glm::eulerAngles(rotation));
|
||||
}
|
||||
|
||||
void MetaCoreApplyTranslationFromMatrix(const glm::mat4& matrix, MetaCoreTransformComponent& transform) {
|
||||
transform.Position = glm::vec3(matrix[3]);
|
||||
}
|
||||
|
||||
void MetaCoreApplyTranslationFromPandaSpaceMatrix(const glm::mat4& matrix, MetaCoreTransformComponent& transform) {
|
||||
transform.Position = MetaCoreFromPandaSpacePoint(glm::vec3(matrix[3]));
|
||||
}
|
||||
|
||||
void MetaCoreApplyTransformFromPandaSpaceMatrix(const glm::mat4& matrix, MetaCoreTransformComponent& transform) {
|
||||
MetaCoreApplyMatrixToTransform(MetaCoreConvertPandaSpaceMatrixToMetaCoreMatrix(matrix), transform);
|
||||
}
|
||||
|
||||
ImGuizmo::OPERATION MetaCoreToImGuizmoOperation(MetaCoreGizmoOperation operation) {
|
||||
switch (operation) {
|
||||
case MetaCoreGizmoOperation::Translate:
|
||||
return ImGuizmo::TRANSLATE;
|
||||
case MetaCoreGizmoOperation::Rotate:
|
||||
return ImGuizmo::ROTATE;
|
||||
case MetaCoreGizmoOperation::Scale:
|
||||
return ImGuizmo::SCALE;
|
||||
case MetaCoreGizmoOperation::None:
|
||||
default:
|
||||
return ImGuizmo::TRANSLATE;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuizmo::MODE MetaCoreToImGuizmoMode(MetaCoreGizmoMode mode) {
|
||||
return mode == MetaCoreGizmoMode::World ? ImGuizmo::WORLD : ImGuizmo::LOCAL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
MetaCoreEditorApp::~MetaCoreEditorApp() {
|
||||
Shutdown();
|
||||
@ -289,7 +226,6 @@ bool MetaCoreEditorApp::Initialize() {
|
||||
}
|
||||
|
||||
int MetaCoreEditorApp::Run() {
|
||||
MetaCoreTraceStartup("main: run loop enter");
|
||||
while (!Window_.ShouldClose()) {
|
||||
Window_.BeginFrame();
|
||||
|
||||
@ -370,6 +306,8 @@ void MetaCoreEditorApp::ShutdownImGui() {
|
||||
}
|
||||
|
||||
void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
SceneInteractionService_.HandleShortcuts(*EditorContext_);
|
||||
|
||||
const ImGuiViewport* mainViewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(mainViewport->WorkPos);
|
||||
ImGui::SetNextWindowSize(mainViewport->WorkSize);
|
||||
@ -465,6 +403,7 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
mousePosition.x <= centralNode->Pos.x + centralNode->Size.x &&
|
||||
mousePosition.y >= centralNode->Pos.y + sceneToolbarHeight &&
|
||||
mousePosition.y <= centralNode->Pos.y + centralNode->Size.y;
|
||||
// 1. Process Input and Viewport State
|
||||
viewportState.Focused = viewportState.Hovered && !ImGui::GetIO().WantCaptureMouse;
|
||||
|
||||
if (viewportState.Focused && !ImGui::GetIO().WantCaptureKeyboard && EditorContext_->GetInput().WasKeyPressed(MetaCoreInputKey::Focus)) {
|
||||
@ -474,18 +413,10 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Q)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::None);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_W)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Translate);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_E)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Rotate);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Scale);
|
||||
}
|
||||
}
|
||||
// 2. Handle Gizmo Mode/Operation Changes (State Updates BEFORE Rendering)
|
||||
// Handled by SceneInteractionService_.HandleShortcuts
|
||||
|
||||
// 3. Render Viewport Background
|
||||
MetaCoreSceneView sceneView = EditorContext_->GetCameraController().BuildSceneView();
|
||||
sceneView.SelectedObjectId = EditorContext_->GetSelectedObjectId();
|
||||
|
||||
@ -509,78 +440,44 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F));
|
||||
|
||||
constexpr ImGuiWindowFlags gizmoCanvasFlags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground |
|
||||
ImGuiWindowFlags_NoInputs;
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs;
|
||||
|
||||
bool gizmoCanvasOpen = true;
|
||||
ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags);
|
||||
if (ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags)) {
|
||||
SceneInteractionService_.HandleGizmoManipulation(*EditorContext_);
|
||||
|
||||
gizmoUsing = ImGuizmo::IsUsing();
|
||||
gizmoHovering = ImGuizmo::IsOver();
|
||||
|
||||
// View Cube (Unity-style perspective switching)
|
||||
const float cameraDistance = glm::distance(sceneView.CameraPosition, sceneView.CameraTarget);
|
||||
const float gizmoAspect = viewportState.Width / viewportState.Height;
|
||||
const ImVec2 viewCubePos = ImVec2(
|
||||
centralNode->Pos.x + viewportState.Width - 120.0F,
|
||||
centralNode->Pos.y + sceneToolbarHeight + 20.0F
|
||||
);
|
||||
const ImVec2 viewCubeSize = ImVec2(100.0F, 100.0F);
|
||||
|
||||
MetaCoreGameObject* selectedObject = EditorContext_->GetSelectedGameObject();
|
||||
if (selectedObject != nullptr &&
|
||||
EditorContext_->GetGizmoOperation() != MetaCoreGizmoOperation::None &&
|
||||
cameraDistance >= 0.001F &&
|
||||
gizmoAspect >= 0.001F) {
|
||||
glm::mat4 gizmoViewMatrix(1.0F);
|
||||
glm::mat4 gizmoProjectionMatrix(1.0F);
|
||||
if (!RenderDevice_.TryGetEditorCameraMatrices(gizmoViewMatrix, gizmoProjectionMatrix)) {
|
||||
gizmoProjectionMatrix = glm::perspective(
|
||||
glm::radians(sceneView.VerticalFieldOfViewDegrees),
|
||||
gizmoAspect, 0.05F, 500.0F
|
||||
);
|
||||
}
|
||||
glm::mat4 cubeViewMatrix = glm::lookAt(sceneView.CameraPosition, sceneView.CameraTarget, sceneView.CameraUp);
|
||||
const glm::mat4 originalCubeViewMatrix = cubeViewMatrix;
|
||||
|
||||
glm::mat4 transformMatrix = MetaCoreBuildPandaSpaceTransformMatrix(selectedObject->Transform);
|
||||
(void)ViewportRenderer_.TryGetObjectWorldMatrix(selectedObject->Id, transformMatrix);
|
||||
const glm::mat4 originalTransformMatrix = transformMatrix;
|
||||
ImGuizmo::ViewManipulate(
|
||||
glm::value_ptr(cubeViewMatrix),
|
||||
cameraDistance,
|
||||
viewCubePos,
|
||||
viewCubeSize,
|
||||
0x00000000 // transparent background
|
||||
);
|
||||
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::Enable(true);
|
||||
ImGuizmo::AllowAxisFlip(true);
|
||||
ImGuizmo::SetGizmoSizeClipSpace(0.30F);
|
||||
ImGuizmo::SetDrawlist(ImGui::GetWindowDrawList());
|
||||
ImGuizmo::SetRect(
|
||||
ImGui::GetWindowPos().x,
|
||||
ImGui::GetWindowPos().y,
|
||||
viewportState.Width,
|
||||
viewportState.Height
|
||||
);
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(gizmoViewMatrix),
|
||||
glm::value_ptr(gizmoProjectionMatrix),
|
||||
MetaCoreToImGuizmoOperation(EditorContext_->GetGizmoOperation()),
|
||||
MetaCoreToImGuizmoMode(EditorContext_->GetGizmoMode()),
|
||||
glm::value_ptr(transformMatrix)
|
||||
);
|
||||
|
||||
gizmoHovering = ImGuizmo::IsOver();
|
||||
gizmoUsing = ImGuizmo::IsUsing();
|
||||
SceneInteractionService_.HandleGizmoBeginUse(*EditorContext_, gizmoUsing);
|
||||
if (gizmoUsing) {
|
||||
switch (EditorContext_->GetGizmoOperation()) {
|
||||
case MetaCoreGizmoOperation::Translate:
|
||||
MetaCoreApplyTranslationFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::Rotate:
|
||||
case MetaCoreGizmoOperation::Scale:
|
||||
MetaCoreApplyTransformFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::None:
|
||||
default:
|
||||
transformMatrix = originalTransformMatrix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cubeViewMatrix != originalCubeViewMatrix) {
|
||||
const glm::mat4 cubeCameraWorldMatrix = glm::inverse(cubeViewMatrix);
|
||||
MetaCoreSceneView updatedView = sceneView;
|
||||
updatedView.CameraPosition = glm::vec3(cubeCameraWorldMatrix[3]);
|
||||
EditorContext_->GetCameraController().ApplySceneView(updatedView);
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
} else {
|
||||
@ -601,117 +498,13 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
viewportState,
|
||||
EditorContext_->GetInput().GetCursorPosition()
|
||||
);
|
||||
SceneInteractionService_.ApplyViewportSelection(*EditorContext_, Scene_, pickedObjectId);
|
||||
SceneInteractionService_.ApplyViewportSelection(*EditorContext_, pickedObjectId);
|
||||
sceneView.SelectedObjectId = EditorContext_->GetActiveObjectId();
|
||||
}
|
||||
|
||||
|
||||
SceneInteractionService_.HandleGizmoEndUse(*EditorContext_, gizmoUsing);
|
||||
|
||||
ImGui::SetNextWindowPos(centralNode->Pos);
|
||||
ImGui::SetNextWindowSize(centralNode->Size);
|
||||
ImGui::SetNextWindowBgAlpha(0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F));
|
||||
|
||||
constexpr ImGuiWindowFlags sceneOverlayFlags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoInputs |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground;
|
||||
|
||||
bool sceneOverlayOpen = true;
|
||||
ImGui::Begin("MetaCoreSceneViewportOverlay", &sceneOverlayOpen, sceneOverlayFlags);
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
const ImVec2 overlayOrigin = ImGui::GetWindowPos();
|
||||
const ImVec2 overlaySize = ImGui::GetWindowSize();
|
||||
drawList->AddRectFilled(
|
||||
overlayOrigin,
|
||||
ImVec2(overlayOrigin.x + overlaySize.x, overlayOrigin.y + sceneToolbarHeight),
|
||||
IM_COL32(28, 31, 36, 220)
|
||||
);
|
||||
drawList->AddLine(
|
||||
ImVec2(overlayOrigin.x, overlayOrigin.y + sceneToolbarHeight),
|
||||
ImVec2(overlayOrigin.x + overlaySize.x, overlayOrigin.y + sceneToolbarHeight),
|
||||
IM_COL32(72, 84, 98, 220),
|
||||
1.0F
|
||||
);
|
||||
|
||||
const char* helpText = "Alt+左键 环绕 | 中键 平移 | 滚轮 缩放 | F 聚焦";
|
||||
drawList->AddText(
|
||||
ImVec2(overlayOrigin.x + 14.0F, overlayOrigin.y + 9.0F),
|
||||
IM_COL32(220, 224, 230, 220),
|
||||
helpText
|
||||
);
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
|
||||
ImGui::SetNextWindowPos(centralNode->Pos);
|
||||
ImGui::SetNextWindowSize(ImVec2(centralNode->Size.x, sceneToolbarHeight));
|
||||
ImGui::SetNextWindowBgAlpha(0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0F, 4.0F));
|
||||
|
||||
constexpr ImGuiWindowFlags sceneToolbarFlags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground;
|
||||
|
||||
bool sceneToolbarOpen = true;
|
||||
ImGui::Begin("MetaCoreSceneToolbarOverlay", &sceneToolbarOpen, sceneToolbarFlags);
|
||||
ImGui::SetCursorPos(ImVec2(390.0F, 4.0F));
|
||||
const auto drawToolbarToggle = [](const char* label, bool selected) {
|
||||
if (selected) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20F, 0.36F, 0.62F, 1.0F));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.25F, 0.42F, 0.70F, 1.0F));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.18F, 0.31F, 0.54F, 1.0F));
|
||||
}
|
||||
const bool clicked = ImGui::Button(label, ImVec2(38.0F, 24.0F));
|
||||
if (selected) {
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
return clicked;
|
||||
};
|
||||
|
||||
if (drawToolbarToggle("Q", EditorContext_->GetGizmoOperation() == MetaCoreGizmoOperation::None)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::None);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("W", EditorContext_->GetGizmoOperation() == MetaCoreGizmoOperation::Translate)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Translate);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("E", EditorContext_->GetGizmoOperation() == MetaCoreGizmoOperation::Rotate)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Rotate);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("R", EditorContext_->GetGizmoOperation() == MetaCoreGizmoOperation::Scale)) {
|
||||
EditorContext_->SetGizmoOperation(MetaCoreGizmoOperation::Scale);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Dummy(ImVec2(10.0F, 0.0F));
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("Local", EditorContext_->GetGizmoMode() == MetaCoreGizmoMode::Local)) {
|
||||
EditorContext_->SetGizmoMode(MetaCoreGizmoMode::Local);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("World", EditorContext_->GetGizmoMode() == MetaCoreGizmoMode::World)) {
|
||||
EditorContext_->SetGizmoMode(MetaCoreGizmoMode::World);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
SceneInteractionService_.DrawViewportToolbar(*EditorContext_);
|
||||
} else {
|
||||
SceneInteractionService_.ResetFrameState();
|
||||
ViewportRenderer_.SetViewportRect(MetaCoreViewportRect{});
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
|
||||
#include <glm/geometric.hpp>
|
||||
#include <glm/trigonometric.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
@ -23,19 +22,36 @@ void MetaCoreEditorCameraController::Update(const MetaCoreSceneViewportState& vi
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewportState.Hovered && std::abs(io.MouseWheel) > 0.001F) {
|
||||
const bool altDown = input.IsKeyDown(MetaCoreInputKey::LeftAlt) || input.IsKeyDown(MetaCoreInputKey::RightAlt);
|
||||
|
||||
// Zoom: Alt + Right Drag or Mouse Wheel
|
||||
if (viewportState.Hovered && altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
|
||||
Distance_ *= (1.0F - io.MouseDelta.y * 0.01F);
|
||||
Distance_ = std::clamp(Distance_, 1.5F, 50.0F);
|
||||
} else if (viewportState.Hovered && std::abs(io.MouseWheel) > 0.001F) {
|
||||
Distance_ *= (io.MouseWheel > 0.0F) ? 0.88F : 1.12F;
|
||||
Distance_ = std::clamp(Distance_, 1.5F, 40.0F);
|
||||
Distance_ = std::clamp(Distance_, 1.5F, 50.0F);
|
||||
}
|
||||
|
||||
const bool altDown = input.IsKeyDown(MetaCoreInputKey::LeftAlt) || input.IsKeyDown(MetaCoreInputKey::RightAlt);
|
||||
// Orbit: Alt + Left Drag
|
||||
if (viewportState.Hovered && altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||
YawDegrees_ += io.MouseDelta.x * 0.35F;
|
||||
PitchDegrees_ -= io.MouseDelta.y * 0.35F;
|
||||
PitchDegrees_ = std::clamp(PitchDegrees_, -85.0F, 85.0F);
|
||||
}
|
||||
// Look Around: Right Drag (without Alt)
|
||||
else if (viewportState.Hovered && !altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
|
||||
const glm::vec3 oldPosition = GetCameraPosition();
|
||||
YawDegrees_ += io.MouseDelta.x * 0.35F;
|
||||
PitchDegrees_ -= io.MouseDelta.y * 0.35F;
|
||||
PitchDegrees_ = std::clamp(PitchDegrees_, -85.0F, 85.0F);
|
||||
|
||||
// Offset target to keep camera position stable during look-around
|
||||
Target_ = oldPosition + GetForwardDirection() * Distance_;
|
||||
}
|
||||
|
||||
if (viewportState.Hovered && ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
|
||||
// Pan: Middle Drag (with or without Alt)
|
||||
if (viewportState.Hovered && (ImGui::IsMouseDragging(ImGuiMouseButton_Middle) || (altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Left) && false /* reserved for future */))) {
|
||||
const glm::vec3 right = GetRightDirection();
|
||||
const glm::vec3 up = GetUpDirection();
|
||||
const float panScale = 0.01F * Distance_;
|
||||
|
||||
@ -1,20 +1,28 @@
|
||||
#include "MetaCoreEditor/MetaCoreSceneInteractionService.h"
|
||||
|
||||
#include "MetaCoreEditor/MetaCoreEditorContext.h"
|
||||
#include "MetaCoreEditorCameraController.h"
|
||||
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
||||
#include "MetaCoreScene/MetaCoreScene.h"
|
||||
#include "MetaCoreScene/MetaCoreGameObject.h"
|
||||
#include "MetaCoreScene/MetaCoreComponents.h"
|
||||
#include "MetaCorePlatform/MetaCoreInput.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <ImGuizmo.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace MetaCore {
|
||||
|
||||
namespace {
|
||||
|
||||
glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transform) {
|
||||
@ -28,6 +36,45 @@ glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transfo
|
||||
return translationMatrix * rotationMatrix * scaleMatrix;
|
||||
}
|
||||
|
||||
// Helper to convert Panda3D (Z-up) matrix to MetaCore (Y-up) space
|
||||
glm::mat4 MetaCoreConvertPandaSpaceMatrixToMetaCoreMatrix(const glm::mat4& pandaMatrix) {
|
||||
const glm::mat4 pandaToMetaCore(
|
||||
1.0F, 0.0F, 0.0F, 0.0F,
|
||||
0.0F, 0.0F, 1.0F, 0.0F,
|
||||
0.0F, 1.0F, 0.0F, 0.0F,
|
||||
0.0F, 0.0F, 0.0F, 1.0F
|
||||
);
|
||||
return pandaToMetaCore * pandaMatrix * pandaToMetaCore;
|
||||
}
|
||||
|
||||
// Helper to apply MetaCore matrix back to Transform component
|
||||
void MetaCoreApplyMatrixToTransform(const glm::mat4& matrix, MetaCoreTransformComponent& transform) {
|
||||
transform.Position = glm::vec3(matrix[3]);
|
||||
glm::vec3 scale;
|
||||
scale.x = glm::length(glm::vec3(matrix[0]));
|
||||
scale.y = glm::length(glm::vec3(matrix[1]));
|
||||
scale.z = glm::length(glm::vec3(matrix[2]));
|
||||
transform.Scale = scale;
|
||||
|
||||
const glm::mat3 rotationMatrix(
|
||||
glm::vec3(matrix[0]) / scale.x,
|
||||
glm::vec3(matrix[1]) / scale.y,
|
||||
glm::vec3(matrix[2]) / scale.z
|
||||
);
|
||||
glm::vec3 euler;
|
||||
glm::extractEulerAngleYXZ(glm::mat4(rotationMatrix), euler.y, euler.x, euler.z);
|
||||
transform.RotationEulerDegrees = glm::degrees(euler);
|
||||
}
|
||||
|
||||
ImGuizmo::OPERATION MetaCoreToImGuizmoOperation(MetaCoreGizmoOperation operation) {
|
||||
switch (operation) {
|
||||
case MetaCoreGizmoOperation::Translate: return ImGuizmo::TRANSLATE;
|
||||
case MetaCoreGizmoOperation::Rotate: return ImGuizmo::ROTATE;
|
||||
case MetaCoreGizmoOperation::Scale: return ImGuizmo::SCALE;
|
||||
default: return ImGuizmo::TRANSLATE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void MetaCoreSceneInteractionService::ResetFrameState() {
|
||||
@ -165,26 +212,13 @@ MetaCoreId MetaCoreSceneInteractionService::PickGameObjectFromViewport(
|
||||
return bestObjectId;
|
||||
}
|
||||
|
||||
void MetaCoreSceneInteractionService::ApplyViewportSelection(
|
||||
MetaCoreEditorContext& editorContext,
|
||||
const MetaCoreScene& scene,
|
||||
MetaCoreId pickedObjectId
|
||||
) const {
|
||||
const bool ctrlDown = ImGui::GetIO().KeyCtrl;
|
||||
const bool shiftDown = ImGui::GetIO().KeyShift;
|
||||
if (pickedObjectId != 0) {
|
||||
if (shiftDown) {
|
||||
editorContext.SelectRangeByOrderedIds(scene.BuildHierarchyPreorder(), pickedObjectId, ctrlDown);
|
||||
} else if (ctrlDown) {
|
||||
void MetaCoreSceneInteractionService::ApplyViewportSelection(MetaCoreEditorContext& editorContext, MetaCoreId pickedObjectId) const {
|
||||
if (editorContext.GetInput().IsKeyDown(MetaCoreInputKey::Control)) {
|
||||
if (pickedObjectId != 0) {
|
||||
editorContext.ToggleSelection(pickedObjectId);
|
||||
} else {
|
||||
editorContext.SelectOnly(pickedObjectId);
|
||||
}
|
||||
if (const MetaCoreGameObject* selectedObject = editorContext.GetSelectedGameObject(); selectedObject != nullptr) {
|
||||
editorContext.AddConsoleMessage(MetaCoreLogLevel::Info, "Scene", "视口已选中对象: " + selectedObject->Name);
|
||||
}
|
||||
} else if (!ctrlDown && !shiftDown) {
|
||||
editorContext.ClearSelection();
|
||||
} else {
|
||||
editorContext.SelectOnly(pickedObjectId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,12 +230,208 @@ void MetaCoreSceneInteractionService::HandleGizmoBeginUse(MetaCoreEditorContext&
|
||||
}
|
||||
|
||||
void MetaCoreSceneInteractionService::HandleGizmoEndUse(MetaCoreEditorContext& editorContext, bool gizmoUsing) {
|
||||
if (!gizmoUsing && GizmoWasUsing_ && HasGizmoBeforeSnapshot_) {
|
||||
const MetaCoreEditorStateSnapshot gizmoAfterSnapshot = editorContext.CaptureStateSnapshot();
|
||||
(void)editorContext.CommitStateTransition("修改变换", GizmoBeforeSnapshot_, gizmoAfterSnapshot, true);
|
||||
if (!gizmoUsing && GizmoWasUsing_) {
|
||||
if (HasGizmoBeforeSnapshot_) {
|
||||
const MetaCoreEditorStateSnapshot afterSnapshot = editorContext.CaptureStateSnapshot();
|
||||
editorContext.CommitStateTransition("Gizmo Transform", GizmoBeforeSnapshot_, afterSnapshot, true);
|
||||
}
|
||||
GizmoWasUsing_ = false;
|
||||
HasGizmoBeforeSnapshot_ = false;
|
||||
}
|
||||
GizmoWasUsing_ = gizmoUsing;
|
||||
}
|
||||
|
||||
void MetaCoreSceneInteractionService::HandleGizmoManipulation(MetaCoreEditorContext& editorContext) {
|
||||
if (editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaCoreGameObject* selectedObject = editorContext.GetSelectedGameObject();
|
||||
if (selectedObject == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const MetaCoreSceneView sceneView = editorContext.GetCameraController().BuildSceneView();
|
||||
const MetaCoreSceneViewportState& viewportState = editorContext.GetSceneViewportState();
|
||||
MetaCoreEditorViewportRenderer& viewportRenderer = editorContext.GetViewportRenderer();
|
||||
|
||||
const float gizmoAspect = viewportState.Width / viewportState.Height;
|
||||
const glm::mat4 gizmoViewMatrix = glm::lookAt(sceneView.CameraPosition, sceneView.CameraTarget, sceneView.CameraUp);
|
||||
const glm::mat4 gizmoProjectionMatrix = glm::perspective(
|
||||
glm::radians(sceneView.VerticalFieldOfViewDegrees),
|
||||
gizmoAspect, 0.05F, 500.0F
|
||||
);
|
||||
|
||||
// 1. Fetch World Matrix from ViewportRenderer (in Panda3D Z-up space).
|
||||
glm::mat4 worldMatrixPanda(1.0F);
|
||||
if (viewportRenderer.TryGetObjectWorldMatrix(selectedObject->Id, worldMatrixPanda)) {
|
||||
// 2. Convert to MetaCore Y-up World Space.
|
||||
glm::mat4 worldMatrixMetaCore = MetaCoreConvertPandaSpaceMatrixToMetaCoreMatrix(worldMatrixPanda);
|
||||
const glm::mat4 originalWorldMatrixMetaCore = worldMatrixMetaCore;
|
||||
|
||||
// 3. Setup ImGuizmo state.
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::Enable(true);
|
||||
ImGuizmo::AllowAxisFlip(false);
|
||||
ImGuizmo::SetGizmoSizeClipSpace(0.30F);
|
||||
ImGuizmo::SetDrawlist(ImGui::GetWindowDrawList());
|
||||
ImGuizmo::SetRect(
|
||||
ImGui::GetWindowPos().x,
|
||||
ImGui::GetWindowPos().y,
|
||||
viewportState.Width,
|
||||
viewportState.Height
|
||||
);
|
||||
|
||||
// 4. Determine Gizmo Mode (force Local for Scale).
|
||||
const MetaCoreGizmoOperation currentOp = editorContext.GetGizmoOperation();
|
||||
const MetaCoreGizmoMode mcMode = editorContext.GetGizmoMode();
|
||||
|
||||
ImGuizmo::MODE effectiveMode = (mcMode == MetaCoreGizmoMode::Global) ? ImGuizmo::WORLD : ImGuizmo::LOCAL;
|
||||
|
||||
if (currentOp == MetaCoreGizmoOperation::Scale) {
|
||||
effectiveMode = ImGuizmo::LOCAL;
|
||||
}
|
||||
|
||||
// 5. Manipulate.
|
||||
ImGuizmo::PushID(reinterpret_cast<void*>(selectedObject));
|
||||
|
||||
// WORLD mode handle alignment fix.
|
||||
glm::mat4 gizmoMatrix = worldMatrixMetaCore;
|
||||
if (effectiveMode == ImGuizmo::WORLD) {
|
||||
gizmoMatrix = glm::translate(glm::mat4(1.0F), glm::vec3(worldMatrixMetaCore[3]));
|
||||
}
|
||||
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(gizmoViewMatrix),
|
||||
glm::value_ptr(gizmoProjectionMatrix),
|
||||
MetaCoreToImGuizmoOperation(currentOp),
|
||||
effectiveMode,
|
||||
glm::value_ptr(gizmoMatrix)
|
||||
);
|
||||
|
||||
bool gizmoUsing = ImGuizmo::IsUsing();
|
||||
ImGuizmo::PopID();
|
||||
|
||||
if (gizmoUsing && (gizmoMatrix != worldMatrixMetaCore || gizmoMatrix != originalWorldMatrixMetaCore)) {
|
||||
if (effectiveMode == ImGuizmo::WORLD) {
|
||||
if (currentOp == MetaCoreGizmoOperation::Translate) {
|
||||
worldMatrixMetaCore[3] = gizmoMatrix[3];
|
||||
} else if (currentOp == MetaCoreGizmoOperation::Rotate) {
|
||||
worldMatrixMetaCore = gizmoMatrix;
|
||||
}
|
||||
} else {
|
||||
worldMatrixMetaCore = gizmoMatrix;
|
||||
}
|
||||
|
||||
// 6. Decompose back to Local Space.
|
||||
glm::mat4 newLocalMatrix = worldMatrixMetaCore;
|
||||
if (selectedObject->ParentId != 0) {
|
||||
glm::mat4 parentWorldMatrixPanda(1.0F);
|
||||
if (viewportRenderer.TryGetObjectWorldMatrix(selectedObject->ParentId, parentWorldMatrixPanda)) {
|
||||
const glm::mat4 parentWorldMatrixMetaCore = MetaCoreConvertPandaSpaceMatrixToMetaCoreMatrix(parentWorldMatrixPanda);
|
||||
newLocalMatrix = glm::inverse(parentWorldMatrixMetaCore) * worldMatrixMetaCore;
|
||||
}
|
||||
}
|
||||
MetaCoreApplyMatrixToTransform(newLocalMatrix, selectedObject->Transform);
|
||||
}
|
||||
|
||||
HandleGizmoBeginUse(editorContext, gizmoUsing);
|
||||
HandleGizmoEndUse(editorContext, gizmoUsing);
|
||||
}
|
||||
}
|
||||
|
||||
void MetaCoreSceneInteractionService::DrawViewportToolbar(MetaCoreEditorContext& editorContext) {
|
||||
const MetaCoreSceneViewportState& viewportState = editorContext.GetSceneViewportState();
|
||||
|
||||
// Position at top-left of the viewport window
|
||||
ImGui::SetNextWindowPos(ImVec2(viewportState.Left + 8.0f, viewportState.Top + 8.0f));
|
||||
ImGui::SetNextWindowBgAlpha(0.6f);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0F);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0F); // Subtle border
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.3f, 0.3f, 0.3f, 0.5f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4.0F, 4.0F));
|
||||
|
||||
constexpr ImGuiWindowFlags toolbarFlags =
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_AlwaysAutoResize;
|
||||
|
||||
if (ImGui::Begin("##ViewportToolbar", nullptr, toolbarFlags)) {
|
||||
const auto drawToolbarToggle = [](const char* label, bool selected) {
|
||||
if (selected) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20F, 0.36F, 0.62F, 1.0F));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.25F, 0.42F, 0.70F, 1.0F));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.18F, 0.31F, 0.54F, 1.0F));
|
||||
} else {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15F, 0.17F, 0.20F, 0.7F));
|
||||
}
|
||||
const bool clicked = ImGui::Button(label, ImVec2(32.0F, 24.0F));
|
||||
if (selected) {
|
||||
ImGui::PopStyleColor(3);
|
||||
} else {
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
return clicked;
|
||||
};
|
||||
|
||||
// Tools
|
||||
if (drawToolbarToggle("Q", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::None)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::None);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("W", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Translate)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Translate);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("E", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Rotate)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Rotate);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (drawToolbarToggle("R", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Scale)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Scale);
|
||||
}
|
||||
|
||||
ImGui::SameLine(0, 12);
|
||||
|
||||
// Mode Toggles (Unity uses "Global" instead of "World")
|
||||
if (drawToolbarToggle("Local", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Local)) {
|
||||
editorContext.SetGizmoMode(MetaCoreGizmoMode::Local);
|
||||
}
|
||||
ImGui::SameLine(0, 2);
|
||||
if (drawToolbarToggle("Global", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Global)) {
|
||||
editorContext.SetGizmoMode(MetaCoreGizmoMode::Global);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
void MetaCoreSceneInteractionService::HandleShortcuts(MetaCoreEditorContext& editorContext) {
|
||||
if (ImGui::GetIO().WantCaptureKeyboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Q, W, E, R for Tool Selection
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Q)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::None);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_W)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Translate);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_E)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Rotate);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
|
||||
editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Scale);
|
||||
}
|
||||
|
||||
// Z for Coordinate Space Toggle (Local/Global)
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Z)) {
|
||||
if (editorContext.GetGizmoMode() == MetaCoreGizmoMode::Local) {
|
||||
editorContext.SetGizmoMode(MetaCoreGizmoMode::Global);
|
||||
} else {
|
||||
editorContext.SetGizmoMode(MetaCoreGizmoMode::Local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MetaCore
|
||||
|
||||
@ -29,7 +29,7 @@ enum class MetaCoreGizmoOperation {
|
||||
|
||||
enum class MetaCoreGizmoMode {
|
||||
Local = 0,
|
||||
World
|
||||
Global
|
||||
};
|
||||
|
||||
enum class MetaCoreReparentTransformRule {
|
||||
|
||||
@ -21,9 +21,14 @@ public:
|
||||
const glm::vec2& cursorPosition
|
||||
) const;
|
||||
|
||||
void ApplyViewportSelection(MetaCoreEditorContext& editorContext, const MetaCoreScene& scene, MetaCoreId pickedObjectId) const;
|
||||
void ApplyViewportSelection(MetaCoreEditorContext& editorContext, MetaCoreId pickedObjectId) const;
|
||||
void HandleGizmoBeginUse(MetaCoreEditorContext& editorContext, bool gizmoUsing);
|
||||
void HandleGizmoEndUse(MetaCoreEditorContext& editorContext, bool gizmoUsing);
|
||||
|
||||
// Unity-style modular interactive features
|
||||
void HandleGizmoManipulation(MetaCoreEditorContext& editorContext);
|
||||
void DrawViewportToolbar(MetaCoreEditorContext& editorContext);
|
||||
void HandleShortcuts(MetaCoreEditorContext& editorContext);
|
||||
|
||||
private:
|
||||
bool GizmoWasUsing_ = false;
|
||||
|
||||
@ -262,6 +262,7 @@ void MetaCoreWindow::BeginFrame() {
|
||||
|
||||
Impl_->Input.SetKeyState(MetaCoreInputKey::LeftAlt, MetaCoreIsVirtualKeyDown(VK_LMENU));
|
||||
Impl_->Input.SetKeyState(MetaCoreInputKey::RightAlt, MetaCoreIsVirtualKeyDown(VK_RMENU));
|
||||
Impl_->Input.SetKeyState(MetaCoreInputKey::Control, MetaCoreIsVirtualKeyDown(VK_LCONTROL) || MetaCoreIsVirtualKeyDown(VK_RCONTROL));
|
||||
Impl_->Input.SetKeyState(MetaCoreInputKey::Focus, MetaCoreIsVirtualKeyDown('F'));
|
||||
Impl_->Input.SetMouseButtonState(MetaCoreMouseButton::Left, MetaCoreIsVirtualKeyDown(VK_LBUTTON));
|
||||
Impl_->Input.SetMouseButtonState(MetaCoreMouseButton::Right, MetaCoreIsVirtualKeyDown(VK_RBUTTON));
|
||||
@ -277,14 +278,7 @@ void MetaCoreWindow::EndFrame() {
|
||||
}
|
||||
|
||||
bool MetaCoreWindow::ShouldClose() const {
|
||||
if (!Impl_->Initialized) {
|
||||
return true;
|
||||
}
|
||||
if (Impl_->CloseRequested) {
|
||||
MetaCoreWindowTrace("window: should_close true (close requested)");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !Impl_->Initialized || Impl_->CloseRequested;
|
||||
}
|
||||
|
||||
void MetaCoreWindow::RequestClose() {
|
||||
|
||||
@ -10,6 +10,7 @@ namespace MetaCore {
|
||||
enum class MetaCoreInputKey : unsigned int {
|
||||
LeftAlt = 0,
|
||||
RightAlt,
|
||||
Control,
|
||||
Focus,
|
||||
Count
|
||||
};
|
||||
|
||||
@ -171,52 +171,6 @@ NodePath MetaCoreCreateGridNode(const NodePath& parentNode) {
|
||||
}
|
||||
}
|
||||
|
||||
NodePath MetaCoreCreateAxisNode(const NodePath& parentNode) {
|
||||
MetaCoreTrace("create_axis: begin");
|
||||
try {
|
||||
PT(GeomVertexData) vertexData = new GeomVertexData(
|
||||
"MetaCoreAxis",
|
||||
GeomVertexFormat::get_v3c4(),
|
||||
Geom::UH_static
|
||||
);
|
||||
|
||||
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
||||
GeomVertexWriter colorWriter(vertexData, "color");
|
||||
|
||||
// X Axis (Red)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(2.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.0F));
|
||||
|
||||
// Y Axis (Green)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 2.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
||||
|
||||
// Z Axis (Blue)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 2.0F)));
|
||||
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
||||
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
||||
lines->add_vertices(0, 1);
|
||||
lines->add_vertices(2, 3);
|
||||
lines->add_vertices(4, 5);
|
||||
|
||||
PT(Geom) geom = new Geom(vertexData);
|
||||
geom->add_primitive(lines.p());
|
||||
|
||||
PT(GeomNode) geomNode = new GeomNode("MetaCoreAxisNode");
|
||||
geomNode->add_geom(geom);
|
||||
|
||||
return parentNode.attach_new_node(geomNode);
|
||||
} catch (...) {
|
||||
return NodePath();
|
||||
}
|
||||
}
|
||||
|
||||
NodePath MetaCoreCreateUnitCubeNode(const NodePath& parentNode) {
|
||||
PT(GeomVertexData) vertexData = new GeomVertexData(
|
||||
@ -306,7 +260,6 @@ public:
|
||||
|
||||
MetaCoreRenderDevice* RenderDevice = nullptr;
|
||||
NodePath GridNode{};
|
||||
NodePath AxisNode{};
|
||||
NodePath AmbientLightNode{};
|
||||
MetaCoreId SelectedObjectId = 0;
|
||||
std::unordered_map<MetaCoreId, MetaCorePandaObjectState> ObjectStates{};
|
||||
@ -332,10 +285,7 @@ bool MetaCorePandaSceneBridge::Initialize(MetaCoreRenderDevice& renderDevice) {
|
||||
Impl_->RenderDevice = &renderDevice;
|
||||
|
||||
Impl_->GridNode = MetaCoreCreateGridNode(*sceneRootHandle);
|
||||
Impl_->AxisNode = MetaCoreCreateAxisNode(*sceneRootHandle);
|
||||
|
||||
Impl_->GridNode.set_light_off(1);
|
||||
Impl_->AxisNode.set_light_off(1);
|
||||
|
||||
PT(AmbientLight) ambientLight = new AmbientLight("MetaCoreAmbientLight");
|
||||
ambientLight->set_color(LColor(0.85F, 0.85F, 0.85F, 1.0F));
|
||||
@ -363,10 +313,6 @@ void MetaCorePandaSceneBridge::Shutdown() {
|
||||
Impl_->AmbientLightNode = NodePath();
|
||||
}
|
||||
|
||||
if (!Impl_->AxisNode.is_empty()) {
|
||||
Impl_->AxisNode.remove_node();
|
||||
Impl_->AxisNode = NodePath();
|
||||
}
|
||||
|
||||
if (!Impl_->GridNode.is_empty()) {
|
||||
Impl_->GridNode.remove_node();
|
||||
|
||||
BIN
diff_head.txt
Normal file
BIN
diff_head.txt
Normal file
Binary file not shown.
4
third_party/ImGuizmo/ImGuizmo.cpp
vendored
4
third_party/ImGuizmo/ImGuizmo.cpp
vendored
@ -787,8 +787,8 @@ namespace IMGUIZMO_NAMESPACE
|
||||
static const char* scaleInfoMask[] = { "X : %5.2f", "Y : %5.2f", "Z : %5.2f", "XYZ : %5.2f" };
|
||||
static const char* rotationInfoMask[] = { "X : %5.2f deg %5.2f rad", "Y : %5.2f deg %5.2f rad", "Z : %5.2f deg %5.2f rad", "Screen : %5.2f deg %5.2f rad" };
|
||||
static const int translationInfoIndex[] = { 0,0,0, 1,0,0, 2,0,0, 1,2,0, 0,2,0, 0,1,0, 0,1,2 };
|
||||
static const float quadMin = 0.5f;
|
||||
static const float quadMax = 0.8f;
|
||||
static const float quadMin = 0.12f;
|
||||
static const float quadMax = 0.38f;
|
||||
static const float quadUV[8] = { quadMin, quadMin, quadMin, quadMax, quadMax, quadMax, quadMax, quadMin };
|
||||
static const int halfCircleSegmentCount = 64;
|
||||
static const float snapTension = 0.5f;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user