Checkpoint workspace changes

This commit is contained in:
2026-04-29 01:24:21 +08:00
parent 9b6adf1806
commit ef11651ec2
67 changed files with 3161 additions and 1904 deletions

View File

@@ -1,8 +1,5 @@
#include "Scene/SceneViewportTransformGizmoSupport.h"
#include <XCEngine/Components/GameObject.h>
#include <XCEngine/Components/TransformComponent.h>
#include <algorithm>
#include <cmath>
@@ -33,8 +30,6 @@ constexpr float kScaleGizmoVisualScaleMax = 2.25f;
constexpr float kSceneViewportMoveArrowLengthPixels = 14.0f;
constexpr float kSceneViewportMoveArrowHalfWidthPixels = 7.0f;
using ::XCEngine::Components::GameObject;
using ::XCEngine::Components::TransformComponent;
using ::XCEngine::Math::Color;
using ::XCEngine::Math::Matrix4x4;
using ::XCEngine::Math::Plane;
@@ -262,20 +257,13 @@ Vector3 GetBaseRotateAxisVector(SceneViewportRotateGizmoAxis axis) {
}
}
Quaternion ComputeStableWorldRotation(const GameObject* gameObject) {
if (gameObject == nullptr || gameObject->GetTransform() == nullptr) {
Quaternion ComputeStableWorldRotation(
const EditorSceneViewportSelectionSnapshot& selection) {
if (!selection.IsValid()) {
return Quaternion::Identity();
}
const TransformComponent* transform = gameObject->GetTransform();
Quaternion worldRotation = transform->GetLocalRotation();
for (const TransformComponent* parent = transform->GetParent();
parent != nullptr;
parent = parent->GetParent()) {
worldRotation = parent->GetLocalRotation() * worldRotation;
}
return worldRotation.Normalized();
return selection.worldRotation.Normalized();
}
Color GetRotateAxisBaseColor(SceneViewportRotateGizmoAxis axis) {
@@ -434,14 +422,14 @@ SceneViewportScaleGizmoHandle GetHandleForIndex(size_t index) {
Vector3 GetHandleWorldAxis(
SceneViewportScaleGizmoHandle handle,
const TransformComponent& transform) {
const Quaternion& worldRotation) {
switch (handle) {
case SceneViewportScaleGizmoHandle::X:
return NormalizeVector3(transform.GetRight(), Vector3::Right());
return NormalizeVector3(worldRotation * Vector3::Right(), Vector3::Right());
case SceneViewportScaleGizmoHandle::Y:
return NormalizeVector3(transform.GetUp(), Vector3::Up());
return NormalizeVector3(worldRotation * Vector3::Up(), Vector3::Up());
case SceneViewportScaleGizmoHandle::Z:
return NormalizeVector3(transform.GetForward(), Vector3::Forward());
return NormalizeVector3(worldRotation * Vector3::Forward(), Vector3::Forward());
case SceneViewportScaleGizmoHandle::Uniform:
case SceneViewportScaleGizmoHandle::None:
default:
@@ -1050,7 +1038,7 @@ bool SceneViewportMoveGizmo::TryBeginDrag(
if (m_dragMode != DragMode::None ||
(m_hoveredAxis == SceneViewportGizmoAxis::None &&
m_hoveredPlane == SceneViewportGizmoPlane::None) ||
context.selectedObject == nullptr ||
!context.selectedObject.IsValid() ||
!m_drawData.visible ||
undoManager.HasPendingInteractiveChange()) {
return false;
@@ -1101,7 +1089,7 @@ bool SceneViewportMoveGizmo::TryBeginDrag(
m_hoveredAxis != SceneViewportGizmoAxis::None ? DragMode::Axis : DragMode::Plane;
m_activeAxis = m_hoveredAxis;
m_activePlane = m_hoveredPlane;
m_activeEntityId = context.selectedObject->GetID();
m_activeEntityId = context.selectedObject.objectId;
m_activeAxisDirection = worldAxis;
m_activePlaneNormal = dragPlaneNormal;
m_dragPlane = dragPlane;
@@ -1115,10 +1103,10 @@ bool SceneViewportMoveGizmo::TryBeginDrag(
m_dragStartObjectWorldPositions.clear();
m_dragStartObjectWorldPositions.reserve(m_dragObjects.size());
for (GameObject* gameObject : m_dragObjects) {
for (const EditorSceneViewportSelectionSnapshot& gameObject : m_dragObjects) {
m_dragStartObjectWorldPositions.push_back(
gameObject != nullptr && gameObject->GetTransform() != nullptr
? gameObject->GetTransform()->GetPosition()
gameObject.IsValid()
? gameObject.worldPosition
: Vector3::Zero());
}
@@ -1130,8 +1118,8 @@ void SceneViewportMoveGizmo::UpdateDrag(
const SceneViewportMoveGizmoContext& context,
IUndoManager& undoManager) {
if (m_dragMode == DragMode::None ||
context.selectedObject == nullptr ||
context.selectedObject->GetID() != m_activeEntityId ||
!context.selectedObject.IsValid() ||
context.selectedObject.objectId != m_activeEntityId ||
m_dragObjects.empty() ||
m_dragObjects.size() != m_dragStartObjectWorldPositions.size()) {
return;
@@ -1158,14 +1146,13 @@ void SceneViewportMoveGizmo::UpdateDrag(
const float deltaScalar = currentAxisScalar - m_dragStartAxisScalar;
const Vector3 worldDelta = m_activeAxisDirection * deltaScalar;
for (size_t index = 0; index < m_dragObjects.size(); ++index) {
if (m_dragObjects[index] == nullptr ||
m_dragObjects[index]->GetTransform() == nullptr) {
if (!m_dragObjects[index].IsValid()) {
continue;
}
undoManager.ApplyWorldTransformPreview(
m_dragObjects[index]->GetID(),
m_dragObjects[index].objectId,
m_dragStartObjectWorldPositions[index] + worldDelta,
m_dragObjects[index]->GetTransform()->GetRotation());
m_dragObjects[index].worldRotation);
}
return;
}
@@ -1178,14 +1165,13 @@ void SceneViewportMoveGizmo::UpdateDrag(
hitPoint - m_dragStartHitWorldPosition,
m_activePlaneNormal);
for (size_t index = 0; index < m_dragObjects.size(); ++index) {
if (m_dragObjects[index] == nullptr ||
m_dragObjects[index]->GetTransform() == nullptr) {
if (!m_dragObjects[index].IsValid()) {
continue;
}
undoManager.ApplyWorldTransformPreview(
m_dragObjects[index]->GetID(),
m_dragObjects[index].objectId,
m_dragStartObjectWorldPositions[index] + worldDelta,
m_dragObjects[index]->GetTransform()->GetRotation());
m_dragObjects[index].worldRotation);
}
}
@@ -1315,7 +1301,7 @@ void SceneViewportMoveGizmo::BuildDrawData(
m_drawData = {};
m_drawData.pivotRadius = 5.0f;
if ((context.selectedObject == nullptr && context.selectedObjects.empty()) ||
if ((!context.selectedObject.IsValid() && context.selectedObjects.empty()) ||
!context.overlay.valid ||
context.viewportSize.x <= 1.0f ||
context.viewportSize.y <= 1.0f) {
@@ -1474,7 +1460,7 @@ bool SceneViewportRotateGizmo::TryBeginDrag(
IUndoManager& undoManager) {
if (m_activeAxis != SceneViewportRotateGizmoAxis::None ||
m_hoveredAxis == SceneViewportRotateGizmoAxis::None ||
context.selectedObject == nullptr ||
!context.selectedObject.IsValid() ||
!m_drawData.visible ||
undoManager.HasPendingInteractiveChange()) {
return false;
@@ -1529,7 +1515,7 @@ bool SceneViewportRotateGizmo::TryBeginDrag(
}
m_activeAxis = m_hoveredAxis;
m_activeEntityId = context.selectedObject->GetID();
m_activeEntityId = context.selectedObject.objectId;
m_localSpace =
context.localSpace && m_hoveredAxis != SceneViewportRotateGizmoAxis::View;
m_rotateAroundSharedPivot = context.rotateAroundSharedPivot;
@@ -1548,14 +1534,13 @@ bool SceneViewportRotateGizmo::TryBeginDrag(
m_dragStartWorldRotations.clear();
m_dragStartWorldPositions.reserve(m_dragObjects.size());
m_dragStartWorldRotations.reserve(m_dragObjects.size());
for (GameObject* gameObject : m_dragObjects) {
if (gameObject != nullptr && gameObject->GetTransform() != nullptr) {
m_dragStartWorldPositions.push_back(gameObject->GetTransform()->GetPosition());
m_dragStartWorldRotations.push_back(gameObject->GetTransform()->GetRotation());
} else {
m_dragStartWorldPositions.push_back(Vector3::Zero());
m_dragStartWorldRotations.push_back(Quaternion::Identity());
}
for (const EditorSceneViewportSelectionSnapshot& gameObject : m_dragObjects) {
m_dragStartWorldPositions.push_back(
gameObject.IsValid() ? gameObject.worldPosition : Vector3::Zero());
m_dragStartWorldRotations.push_back(
gameObject.IsValid()
? gameObject.worldRotation
: Quaternion::Identity());
}
RefreshHandleState();
@@ -1566,8 +1551,8 @@ void SceneViewportRotateGizmo::UpdateDrag(
const SceneViewportRotateGizmoContext& context,
IUndoManager& undoManager) {
if (m_activeAxis == SceneViewportRotateGizmoAxis::None ||
context.selectedObject == nullptr ||
context.selectedObject->GetID() != m_activeEntityId ||
!context.selectedObject.IsValid() ||
context.selectedObject.objectId != m_activeEntityId ||
m_dragObjects.empty() ||
m_dragObjects.size() != m_dragStartWorldPositions.size() ||
m_dragObjects.size() != m_dragStartWorldRotations.size()) {
@@ -1624,8 +1609,8 @@ void SceneViewportRotateGizmo::UpdateDrag(
: Quaternion::Identity();
for (size_t index = 0; index < m_dragObjects.size(); ++index) {
GameObject* gameObject = m_dragObjects[index];
if (gameObject == nullptr || gameObject->GetTransform() == nullptr) {
const EditorSceneViewportSelectionSnapshot& gameObject = m_dragObjects[index];
if (!gameObject.IsValid()) {
continue;
}
@@ -1641,14 +1626,14 @@ void SceneViewportRotateGizmo::UpdateDrag(
? m_dragStartWorldRotations[index] * localDeltaRotation
: worldDeltaRotation * m_dragStartWorldRotations[index];
undoManager.ApplyWorldTransformPreview(
gameObject->GetID(),
gameObject.objectId,
previewPosition,
previewRotation);
}
SceneViewportRotateGizmoContext drawContext = context;
drawContext.pivotWorldPosition = m_dragStartPivotWorldPosition;
if (drawContext.localSpace && drawContext.selectedObject != nullptr) {
if (drawContext.localSpace && drawContext.selectedObject.IsValid()) {
drawContext.axisOrientation =
ComputeStableWorldRotation(drawContext.selectedObject);
}
@@ -1767,7 +1752,7 @@ void SceneViewportRotateGizmo::BuildDrawData(
const SceneViewportRotateGizmoContext& context) {
m_drawData = {};
if ((context.selectedObject == nullptr && context.selectedObjects.empty()) ||
if ((!context.selectedObject.IsValid() && context.selectedObjects.empty()) ||
!context.overlay.valid ||
context.viewportSize.x <= 1.0f ||
context.viewportSize.y <= 1.0f) {
@@ -2048,8 +2033,7 @@ bool SceneViewportScaleGizmo::TryBeginDrag(
IUndoManager& undoManager) {
if (m_activeHandle != SceneViewportScaleGizmoHandle::None ||
m_hoveredHandle == SceneViewportScaleGizmoHandle::None ||
context.selectedObject == nullptr ||
context.selectedObject->GetTransform() == nullptr ||
!context.selectedObject.IsValid() ||
!m_drawData.visible ||
undoManager.HasPendingInteractiveChange()) {
return false;
@@ -2072,7 +2056,7 @@ bool SceneViewportScaleGizmo::TryBeginDrag(
context.pivotWorldPosition,
GetHandleWorldAxis(
m_hoveredHandle,
*context.selectedObject->GetTransform()),
context.selectedObject.worldRotation),
activeScreenDirection)) {
return false;
}
@@ -2087,8 +2071,8 @@ bool SceneViewportScaleGizmo::TryBeginDrag(
}
m_activeHandle = m_hoveredHandle;
m_activeEntityId = context.selectedObject->GetID();
m_dragStartLocalScale = context.selectedObject->GetTransform()->GetLocalScale();
m_activeEntityId = context.selectedObject.objectId;
m_dragStartLocalScale = context.selectedObject.localScale;
m_dragCurrentVisualScale = Vector3::One();
m_dragStartMousePosition = context.mousePosition;
m_activeScreenDirection = activeScreenDirection;
@@ -2100,9 +2084,8 @@ void SceneViewportScaleGizmo::UpdateDrag(
const SceneViewportScaleGizmoContext& context,
IUndoManager& undoManager) {
if (m_activeHandle == SceneViewportScaleGizmoHandle::None ||
context.selectedObject == nullptr ||
context.selectedObject->GetTransform() == nullptr ||
context.selectedObject->GetID() != m_activeEntityId) {
!context.selectedObject.IsValid() ||
context.selectedObject.objectId != m_activeEntityId) {
return;
}
@@ -2144,7 +2127,7 @@ void SceneViewportScaleGizmo::UpdateDrag(
}
}
undoManager.ApplyLocalScalePreview(context.selectedObject->GetID(), localScale);
undoManager.ApplyLocalScalePreview(context.selectedObject.objectId, localScale);
switch (m_activeHandle) {
case SceneViewportScaleGizmoHandle::X:
m_dragCurrentVisualScale = Vector3(
@@ -2302,9 +2285,9 @@ void SceneViewportScaleGizmo::BuildDrawData(
const SceneViewportScaleGizmoContext& context) {
m_drawData = {};
const GameObject* selectedObject = context.selectedObject;
if (selectedObject == nullptr ||
selectedObject->GetTransform() == nullptr ||
const EditorSceneViewportSelectionSnapshot& selectedObject =
context.selectedObject;
if (!selectedObject.IsValid() ||
!context.overlay.valid ||
context.viewportSize.x <= 1.0f ||
context.viewportSize.y <= 1.0f) {
@@ -2340,7 +2323,7 @@ void SceneViewportScaleGizmo::BuildDrawData(
const bool hasVisualDragFeedback =
m_activeHandle != SceneViewportScaleGizmoHandle::None &&
selectedObject->GetID() == m_activeEntityId;
selectedObject.objectId == m_activeEntityId;
for (size_t index = 0; index < m_drawData.axisHandles.size(); ++index) {
SceneViewportScaleGizmoAxisHandleDrawData& handle =
m_drawData.axisHandles[index];
@@ -2350,7 +2333,7 @@ void SceneViewportScaleGizmo::BuildDrawData(
handle.color = GetScaleHandleBaseColor(handle.handle);
const Vector3 axisWorld =
GetHandleWorldAxis(handle.handle, *selectedObject->GetTransform());
GetHandleWorldAxis(handle.handle, selectedObject.worldRotation);
if (axisWorld.SqrMagnitude() <= Math::EPSILON) {
continue;
}