Refactor scene viewport state into local sessions

This commit is contained in:
2026-04-29 14:13:47 +08:00
parent da6f37dafe
commit 212d4016e0
16 changed files with 353 additions and 380 deletions

View File

@@ -36,16 +36,6 @@ bool TransformSnapshotsMatch(
NearlyEqual(lhs.scale, rhs.scale);
}
std::uint64_t CombineSceneViewportRequestRevisions(
std::uint64_t sceneContentRevision,
std::uint64_t sceneViewCameraRevision) {
constexpr std::uint64_t kRevisionMixConstant = 0x9e3779b97f4a7c15ull;
return sceneContentRevision ^
(sceneViewCameraRevision + kRevisionMixConstant +
(sceneContentRevision << 6u) +
(sceneContentRevision >> 2u));
}
} // namespace
std::string_view GetSceneToolModeName(SceneToolMode mode) {
@@ -116,12 +106,9 @@ void EditorSceneRuntime::Reset() {
m_startupSceneResult = {};
m_ownedSelectionService.ClearSelection();
m_selectionService = &m_ownedSelectionService;
m_sceneViewCameraController.Reset();
m_toolState = {};
ResetTransformEditHistory();
m_inspectorRevision = 0u;
m_sceneContentRevision = 0u;
m_sceneViewCameraRevision = 0u;
}
void EditorSceneRuntime::SetBackend(std::unique_ptr<EditorSceneBackend> backend) {
@@ -153,11 +140,7 @@ void EditorSceneRuntime::RefreshScene() {
} else {
RevalidateSelection();
}
} else if (m_toolState.dragState.active) {
ResetToolInteractionState();
}
ClearInvalidToolInteractionState();
}
void EditorSceneRuntime::EnsureSceneSelection() {
@@ -179,39 +162,6 @@ EditorSceneHierarchySnapshot EditorSceneRuntime::BuildHierarchySnapshot() const
: EditorSceneHierarchySnapshot{};
}
float EditorSceneRuntime::GetSceneViewOrbitDistance() const {
return m_sceneViewCameraController.GetDistance();
}
SceneViewportRenderRequest EditorSceneRuntime::BuildSceneViewportRenderRequest() {
SceneViewportRenderRequest request = {};
request.camera = BuildSceneViewCameraSnapshot();
request.requestRevision = BuildSceneViewportRequestRevision();
if (const std::optional<EditorSceneObjectId> selectedId = GetSelectedObjectId();
selectedId.has_value()) {
request.selectedObjectIds.push_back(selectedId.value());
if (m_backend != nullptr) {
request.selectedHelpers =
m_backend->BuildViewportHelperSnapshots(selectedId.value());
}
}
return request;
}
EditorSceneCameraSnapshot EditorSceneRuntime::BuildSceneViewCameraSnapshot() const {
EditorSceneCameraSnapshot snapshot = {};
snapshot.valid = true;
snapshot.position = m_sceneViewCameraController.GetPosition();
snapshot.forward = m_sceneViewCameraController.GetForward();
snapshot.right = m_sceneViewCameraController.GetRight();
snapshot.up = m_sceneViewCameraController.GetUp();
snapshot.verticalFovDegrees = 60.0f;
snapshot.nearClipPlane = 0.03f;
snapshot.farClipPlane = 2000.0f;
snapshot.orbitDistance = GetSceneViewOrbitDistance();
return snapshot;
}
std::vector<EditorSceneViewportIconSnapshot>
EditorSceneRuntime::BuildSceneViewportIconSnapshots() const {
return m_backend != nullptr
@@ -229,21 +179,14 @@ EditorSceneRuntime::BuildSceneViewportSelectionSnapshot() const {
return m_backend->BuildViewportSelectionSnapshot(selectedId.value());
}
void EditorSceneRuntime::ApplySceneViewportCameraInput(
const SceneViewportCameraInputState& input) {
m_sceneViewCameraController.ApplyInput(input);
IncrementSceneViewCameraRevision();
}
bool EditorSceneRuntime::FocusSceneSelection() {
SceneTransformSnapshot snapshot = {};
if (!CaptureSelectedTransformSnapshot(snapshot)) {
return false;
std::vector<EditorSceneViewportHelperSnapshot>
EditorSceneRuntime::BuildSelectedViewportHelperSnapshots() const {
const std::optional<EditorSceneObjectId> selectedId = GetSelectedObjectId();
if (!selectedId.has_value() || m_backend == nullptr) {
return {};
}
m_sceneViewCameraController.Focus(snapshot.position);
IncrementSceneViewCameraRevision();
return true;
return m_backend->BuildViewportHelperSnapshots(selectedId.value());
}
bool EditorSceneRuntime::HasSceneSelection() const {
@@ -326,18 +269,13 @@ bool EditorSceneRuntime::SetSelection(EditorSceneObjectId id) {
!previousId.has_value() ||
previousId.value() != id ||
!HasHierarchySelection();
if (changed) {
ResetToolInteractionState();
}
SelectionService().SetHierarchySelection(
MakeEditorGameObjectItemId(id),
snapshot->displayName);
ClearInvalidToolInteractionState();
return changed;
}
void EditorSceneRuntime::ClearSelection() {
ResetToolInteractionState();
SelectionService().ClearSelection();
}
@@ -359,7 +297,6 @@ bool EditorSceneRuntime::NewScene(std::string_view sceneName) {
}
ResetTransformEditHistory();
ResetToolInteractionState();
SelectionService().ClearSelection();
IncrementInspectorRevision();
IncrementSceneContentRevision();
@@ -379,7 +316,6 @@ bool EditorSceneRuntime::OpenSceneAsset(const std::filesystem::path& scenePath)
m_startupSceneResult.sceneName = scenePath.stem().string();
ResetTransformEditHistory();
ResetToolInteractionState();
SelectionService().ClearSelection();
IncrementInspectorRevision();
IncrementSceneContentRevision();
@@ -661,70 +597,6 @@ bool EditorSceneRuntime::ApplySelectedComponentMutation(
return true;
}
const SceneToolState& EditorSceneRuntime::GetToolState() const {
return m_toolState;
}
SceneToolMode EditorSceneRuntime::GetToolMode() const {
return m_toolState.mode;
}
SceneToolSpaceMode EditorSceneRuntime::GetToolSpaceMode() const {
return m_toolState.spaceMode;
}
SceneToolPivotMode EditorSceneRuntime::GetToolPivotMode() const {
return m_toolState.pivotMode;
}
void EditorSceneRuntime::SetToolMode(SceneToolMode mode) {
if (m_toolState.mode == mode) {
return;
}
ResetToolInteractionState();
m_toolState.mode = mode;
}
void EditorSceneRuntime::SetToolSpaceMode(SceneToolSpaceMode mode) {
if (m_toolState.spaceMode == mode) {
return;
}
ResetToolInteractionState();
m_toolState.spaceMode = mode;
}
void EditorSceneRuntime::SetToolPivotMode(SceneToolPivotMode mode) {
if (m_toolState.pivotMode == mode) {
return;
}
ResetToolInteractionState();
m_toolState.pivotMode = mode;
}
void EditorSceneRuntime::SetHoveredToolHandle(SceneToolHandle handle) {
if (m_toolState.dragState.active) {
return;
}
m_toolState.hoveredHandle = handle;
}
void EditorSceneRuntime::SetToolInteractionLock(SceneToolInteractionLock lock) {
m_toolState.interactionLock = lock;
}
void EditorSceneRuntime::ClearToolInteractionLock() {
m_toolState.interactionLock = SceneToolInteractionLock::None;
}
void EditorSceneRuntime::ResetToolInteractionState() {
CancelTransformToolDrag();
ResetToolInteractionTransientState();
}
bool EditorSceneRuntime::CaptureSelectedTransformSnapshot(
SceneTransformSnapshot& outSnapshot) const {
const std::optional<EditorSceneObjectId> selectedId = GetSelectedObjectId();
@@ -782,51 +654,6 @@ bool EditorSceneRuntime::RecordTransformEdit(
return true;
}
bool EditorSceneRuntime::BeginTransformToolDrag(
SceneToolHandle handle,
const ::XCEngine::UI::UIPoint& startPointerPosition) {
if (handle == SceneToolHandle::None ||
m_toolState.mode == SceneToolMode::View) {
return false;
}
SceneTransformSnapshot snapshot = {};
if (!CaptureSelectedTransformSnapshot(snapshot)) {
return false;
}
CancelTransformToolDrag();
m_toolState.dragState = {};
m_toolState.dragState.active = true;
m_toolState.dragState.mode = m_toolState.mode;
m_toolState.dragState.handle = handle;
m_toolState.dragState.startPointerPosition = startPointerPosition;
m_toolState.dragState.initialTransform = snapshot;
m_toolState.hoveredHandle = handle;
m_toolState.activeHandle = handle;
SetToolInteractionLock(SceneToolInteractionLock::TransformDrag);
return true;
}
bool EditorSceneRuntime::HasActiveTransformToolDrag() const {
return m_toolState.dragState.active;
}
const SceneToolDragState* EditorSceneRuntime::GetActiveTransformToolDrag() const {
return m_toolState.dragState.active ? &m_toolState.dragState : nullptr;
}
bool EditorSceneRuntime::ApplyTransformToolPreview(
const SceneTransformSnapshot& snapshot) {
if (!m_toolState.dragState.active ||
!snapshot.IsValid() ||
snapshot.targetId != m_toolState.dragState.initialTransform.targetId) {
return false;
}
return ApplyTransformSnapshot(snapshot);
}
bool EditorSceneRuntime::ApplyTransformToolWorldPreview(
EditorSceneObjectId targetId,
const Vector3& position,
@@ -836,9 +663,7 @@ bool EditorSceneRuntime::ApplyTransformToolWorldPreview(
}
const EditorSceneObjectId activeTargetId =
m_toolState.dragState.active
? m_toolState.dragState.initialTransform.targetId
: GetSelectedObjectId().value_or(kInvalidEditorSceneObjectId);
GetSelectedObjectId().value_or(kInvalidEditorSceneObjectId);
if (activeTargetId == kInvalidEditorSceneObjectId ||
targetId != activeTargetId) {
return false;
@@ -862,9 +687,7 @@ bool EditorSceneRuntime::ApplyTransformToolLocalScalePreview(
}
const EditorSceneObjectId activeTargetId =
m_toolState.dragState.active
? m_toolState.dragState.initialTransform.targetId
: GetSelectedObjectId().value_or(kInvalidEditorSceneObjectId);
GetSelectedObjectId().value_or(kInvalidEditorSceneObjectId);
if (activeTargetId == kInvalidEditorSceneObjectId ||
targetId != activeTargetId) {
return false;
@@ -880,37 +703,6 @@ bool EditorSceneRuntime::ApplyTransformToolLocalScalePreview(
return true;
}
bool EditorSceneRuntime::CommitTransformToolDrag() {
if (!m_toolState.dragState.active) {
return false;
}
SceneTransformSnapshot afterSnapshot = {};
const bool captured = CaptureSelectedTransformSnapshot(afterSnapshot);
const SceneTransformSnapshot beforeSnapshot =
m_toolState.dragState.initialTransform;
ResetToolInteractionTransientState();
if (!captured || !afterSnapshot.IsValid() || !beforeSnapshot.IsValid()) {
return false;
}
return RecordTransformEdit(beforeSnapshot, afterSnapshot);
}
void EditorSceneRuntime::CancelTransformToolDrag() {
if (!m_toolState.dragState.active) {
return;
}
const SceneTransformSnapshot snapshot = m_toolState.dragState.initialTransform;
if (snapshot.IsValid()) {
ApplyTransformSnapshot(snapshot);
}
ResetToolInteractionTransientState();
}
bool EditorSceneRuntime::CanUndoTransformEdit() const {
return !m_transformUndoStack.empty();
}
@@ -1027,46 +819,4 @@ void EditorSceneRuntime::IncrementSceneContentRevision() {
++m_sceneContentRevision;
}
void EditorSceneRuntime::IncrementSceneViewCameraRevision() {
++m_sceneViewCameraRevision;
}
std::uint64_t EditorSceneRuntime::BuildSceneViewportRequestRevision() const {
return CombineSceneViewportRequestRevisions(
m_sceneContentRevision,
m_sceneViewCameraRevision);
}
void EditorSceneRuntime::ResetToolInteractionTransientState() {
m_toolState.hoveredHandle = SceneToolHandle::None;
m_toolState.activeHandle = SceneToolHandle::None;
ClearToolInteractionLock();
m_toolState.dragState = {};
}
void EditorSceneRuntime::ClearInvalidToolInteractionState() {
if (!HasSceneSelection()) {
ResetToolInteractionTransientState();
return;
}
if (!m_toolState.dragState.active) {
return;
}
const SceneTransformSnapshot snapshot = m_toolState.dragState.initialTransform;
if (!snapshot.IsValid()) {
ResetToolInteractionTransientState();
return;
}
const std::optional<EditorSceneViewportSelectionSnapshot> selectionSnapshot =
m_backend != nullptr
? m_backend->BuildViewportSelectionSnapshot(snapshot.targetId)
: std::nullopt;
if (!selectionSnapshot.has_value() || !selectionSnapshot->IsValid()) {
ResetToolInteractionTransientState();
}
}
} // namespace XCEngine::UI::Editor::App