docs: add editor runtime flow docs

This commit is contained in:
2026-04-04 00:45:13 +08:00
parent 8abca3dec5
commit 2620b5914b
41 changed files with 2367 additions and 126 deletions

View File

@@ -85,6 +85,7 @@ add_executable(${PROJECT_NAME} WIN32
src/Viewport/SceneViewportHudOverlay.cpp
src/Viewport/SceneViewportInteractionActions.cpp
src/Viewport/SceneViewportInteractionResolver.cpp
src/Viewport/SceneViewportTransformGizmoCoordinator.cpp
src/Viewport/SceneViewportOrientationGizmo.cpp
src/Viewport/SceneViewportOverlayBuilder.cpp
src/Viewport/SceneViewportOverlayProviders.cpp

View File

@@ -0,0 +1,156 @@
#include "SceneViewportTransformGizmoCoordinator.h"
#include "Core/IUndoManager.h"
namespace XCEngine {
namespace Editor {
SceneViewportTransformGizmoOverlaySubmission BuildSceneViewportTransformGizmoOverlaySubmission(
const SceneViewportTransformGizmoFrameState& frameState,
bool showingMoveGizmo,
const SceneViewportMoveGizmo& moveGizmo,
bool showingRotateGizmo,
const SceneViewportRotateGizmo& rotateGizmo,
bool showingScaleGizmo,
const SceneViewportScaleGizmo& scaleGizmo) {
SceneViewportTransformGizmoOverlaySubmission submission = {};
submission.overlayState = BuildSceneViewportTransformGizmoOverlayState(
BuildSceneViewportTransformGizmoHandleBuildInputs(
showingMoveGizmo,
moveGizmo,
frameState.moveContext,
showingRotateGizmo,
rotateGizmo,
frameState.rotateContext,
showingScaleGizmo,
scaleGizmo,
frameState.scaleContext));
submission.activeGizmoKind = GetActiveSceneViewportGizmoKind(moveGizmo, rotateGizmo, scaleGizmo);
return submission;
}
void SubmitSceneViewportTransformGizmoOverlaySubmission(
IViewportHostService& viewportHostService,
const SceneViewportTransformGizmoOverlaySubmission& submission) {
viewportHostService.SetSceneViewTransformGizmoOverlayState(submission.overlayState);
}
SceneViewportTransformGizmoLifecycleCommand BuildBeginSceneViewportTransformGizmoLifecycleCommand(
const SceneViewportInteractionActions& actions) {
if (!actions.beginTransformGizmo) {
return {};
}
SceneViewportTransformGizmoLifecycleCommand command = {};
command.stage = SceneViewportTransformGizmoLifecycleStage::Begin;
command.gizmoKind = actions.hoveredGizmoKind;
return command;
}
SceneViewportTransformGizmoLifecycleCommand BuildFrameSceneViewportTransformGizmoLifecycleCommand(
SceneViewportActiveGizmoKind activeGizmoKind,
bool leftMouseDown) {
if (activeGizmoKind == SceneViewportActiveGizmoKind::None) {
return {};
}
SceneViewportTransformGizmoLifecycleCommand command = {};
command.stage = leftMouseDown
? SceneViewportTransformGizmoLifecycleStage::Update
: SceneViewportTransformGizmoLifecycleStage::End;
command.gizmoKind = activeGizmoKind;
return command;
}
namespace {
void ExecuteMoveGizmoLifecycleCommand(
SceneViewportTransformGizmoLifecycleStage stage,
IUndoManager& undoManager,
const SceneViewportMoveGizmoContext& context,
SceneViewportMoveGizmo& moveGizmo) {
switch (stage) {
case SceneViewportTransformGizmoLifecycleStage::Begin:
moveGizmo.TryBeginDrag(context, undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::Update:
moveGizmo.UpdateDrag(context);
return;
case SceneViewportTransformGizmoLifecycleStage::End:
moveGizmo.EndDrag(undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::None:
default:
return;
}
}
void ExecuteRotateGizmoLifecycleCommand(
SceneViewportTransformGizmoLifecycleStage stage,
IUndoManager& undoManager,
const SceneViewportRotateGizmoContext& context,
SceneViewportRotateGizmo& rotateGizmo) {
switch (stage) {
case SceneViewportTransformGizmoLifecycleStage::Begin:
rotateGizmo.TryBeginDrag(context, undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::Update:
rotateGizmo.UpdateDrag(context);
return;
case SceneViewportTransformGizmoLifecycleStage::End:
rotateGizmo.EndDrag(undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::None:
default:
return;
}
}
void ExecuteScaleGizmoLifecycleCommand(
SceneViewportTransformGizmoLifecycleStage stage,
IUndoManager& undoManager,
const SceneViewportScaleGizmoContext& context,
SceneViewportScaleGizmo& scaleGizmo) {
switch (stage) {
case SceneViewportTransformGizmoLifecycleStage::Begin:
scaleGizmo.TryBeginDrag(context, undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::Update:
scaleGizmo.UpdateDrag(context);
return;
case SceneViewportTransformGizmoLifecycleStage::End:
scaleGizmo.EndDrag(undoManager);
return;
case SceneViewportTransformGizmoLifecycleStage::None:
default:
return;
}
}
} // namespace
void ExecuteSceneViewportTransformGizmoLifecycleCommand(
const SceneViewportTransformGizmoLifecycleCommand& command,
IUndoManager& undoManager,
const SceneViewportTransformGizmoFrameState& frameState,
SceneViewportMoveGizmo& moveGizmo,
SceneViewportRotateGizmo& rotateGizmo,
SceneViewportScaleGizmo& scaleGizmo) {
switch (command.gizmoKind) {
case SceneViewportActiveGizmoKind::Move:
ExecuteMoveGizmoLifecycleCommand(command.stage, undoManager, frameState.moveContext, moveGizmo);
return;
case SceneViewportActiveGizmoKind::Rotate:
ExecuteRotateGizmoLifecycleCommand(command.stage, undoManager, frameState.rotateContext, rotateGizmo);
return;
case SceneViewportActiveGizmoKind::Scale:
ExecuteScaleGizmoLifecycleCommand(command.stage, undoManager, frameState.scaleContext, scaleGizmo);
return;
case SceneViewportActiveGizmoKind::None:
default:
return;
}
}
} // namespace Editor
} // namespace XCEngine

View File

@@ -0,0 +1,68 @@
#pragma once
#include "SceneViewportInteractionActions.h"
#include "SceneViewportOverlayHandleBuilder.h"
#include <cstdint>
namespace XCEngine {
namespace Editor {
class IUndoManager;
struct SceneViewportTransformGizmoOverlaySubmission {
SceneViewportTransformGizmoOverlayState overlayState = {};
SceneViewportActiveGizmoKind activeGizmoKind = SceneViewportActiveGizmoKind::None;
bool GizmoActive() const {
return activeGizmoKind != SceneViewportActiveGizmoKind::None;
}
};
enum class SceneViewportTransformGizmoLifecycleStage : uint8_t {
None = 0,
Begin,
Update,
End
};
struct SceneViewportTransformGizmoLifecycleCommand {
SceneViewportTransformGizmoLifecycleStage stage = SceneViewportTransformGizmoLifecycleStage::None;
SceneViewportActiveGizmoKind gizmoKind = SceneViewportActiveGizmoKind::None;
bool HasWork() const {
return stage != SceneViewportTransformGizmoLifecycleStage::None &&
gizmoKind != SceneViewportActiveGizmoKind::None;
}
};
SceneViewportTransformGizmoOverlaySubmission BuildSceneViewportTransformGizmoOverlaySubmission(
const SceneViewportTransformGizmoFrameState& frameState,
bool showingMoveGizmo,
const SceneViewportMoveGizmo& moveGizmo,
bool showingRotateGizmo,
const SceneViewportRotateGizmo& rotateGizmo,
bool showingScaleGizmo,
const SceneViewportScaleGizmo& scaleGizmo);
void SubmitSceneViewportTransformGizmoOverlaySubmission(
IViewportHostService& viewportHostService,
const SceneViewportTransformGizmoOverlaySubmission& submission);
SceneViewportTransformGizmoLifecycleCommand BuildBeginSceneViewportTransformGizmoLifecycleCommand(
const SceneViewportInteractionActions& actions);
SceneViewportTransformGizmoLifecycleCommand BuildFrameSceneViewportTransformGizmoLifecycleCommand(
SceneViewportActiveGizmoKind activeGizmoKind,
bool leftMouseDown);
void ExecuteSceneViewportTransformGizmoLifecycleCommand(
const SceneViewportTransformGizmoLifecycleCommand& command,
IUndoManager& undoManager,
const SceneViewportTransformGizmoFrameState& frameState,
SceneViewportMoveGizmo& moveGizmo,
SceneViewportRotateGizmo& rotateGizmo,
SceneViewportScaleGizmo& scaleGizmo);
} // namespace Editor
} // namespace XCEngine

View File

@@ -7,8 +7,8 @@
#include "Viewport/SceneViewportHudOverlay.h"
#include "Viewport/SceneViewportInteractionActions.h"
#include "Viewport/SceneViewportInteractionResolver.h"
#include "Viewport/SceneViewportOverlayHandleBuilder.h"
#include "Viewport/SceneViewportMath.h"
#include "Viewport/SceneViewportTransformGizmoCoordinator.h"
#include "Viewport/SceneViewportTransformGizmoFrameBuilder.h"
#include "ViewportPanelContent.h"
#include "Platform/Win32Utf8.h"
@@ -346,7 +346,6 @@ void SceneViewPanel::Render() {
SceneViewportOverlayData overlay = {};
SceneViewportTransformGizmoFrameState gizmoFrameState = {};
SceneViewportOverlayFrameData emptySceneOverlayFrameData = {};
SceneViewportActiveGizmoKind activeGizmoKind = SceneViewportActiveGizmoKind::None;
if (hasInteractiveViewport) {
overlay = viewportHostService->GetSceneViewOverlayData();
@@ -364,44 +363,28 @@ void SceneViewPanel::Render() {
m_rotateGizmo,
showingScaleGizmo,
m_scaleGizmo);
activeGizmoKind = gizmoFrameState.activeGizmoKind;
} else {
CancelSceneViewportTransformGizmoDrags(*m_context, m_moveGizmo, m_rotateGizmo, m_scaleGizmo);
}
const SceneViewportTransformGizmoHandleBuildInputs interactionGizmoInputs =
const SceneViewportTransformGizmoOverlaySubmission interactionGizmoSubmission =
hasInteractiveViewport
? BuildSceneViewportTransformGizmoHandleBuildInputs(
? BuildSceneViewportTransformGizmoOverlaySubmission(
gizmoFrameState,
showingMoveGizmo,
m_moveGizmo,
gizmoFrameState.moveContext,
showingRotateGizmo,
m_rotateGizmo,
gizmoFrameState.rotateContext,
showingScaleGizmo,
m_scaleGizmo,
gizmoFrameState.scaleContext)
: SceneViewportTransformGizmoHandleBuildInputs{};
const SceneViewportTransformGizmoOverlayState interactionGizmoOverlayState =
BuildSceneViewportTransformGizmoOverlayState(interactionGizmoInputs);
viewportHostService->SetSceneViewTransformGizmoOverlayState(interactionGizmoOverlayState);
m_scaleGizmo)
: SceneViewportTransformGizmoOverlaySubmission{};
SubmitSceneViewportTransformGizmoOverlaySubmission(*viewportHostService, interactionGizmoSubmission);
const SceneViewportOverlayFrameData& interactionOverlayFrameData =
hasInteractiveViewport
? viewportHostService->GetSceneViewEditorOverlayFrameData(*m_context)
: emptySceneOverlayFrameData;
const bool moveGizmoActive = showingMoveGizmo && m_moveGizmo.IsActive();
const bool rotateGizmoActive = showingRotateGizmo && m_rotateGizmo.IsActive();
const bool scaleGizmoActive = showingScaleGizmo && m_scaleGizmo.IsActive();
if (moveGizmoActive) {
activeGizmoKind = SceneViewportActiveGizmoKind::Move;
} else if (rotateGizmoActive) {
activeGizmoKind = SceneViewportActiveGizmoKind::Rotate;
} else if (scaleGizmoActive) {
activeGizmoKind = SceneViewportActiveGizmoKind::Scale;
} else {
activeGizmoKind = SceneViewportActiveGizmoKind::None;
}
const bool gizmoActive = activeGizmoKind != SceneViewportActiveGizmoKind::None;
const SceneViewportActiveGizmoKind activeGizmoKind = interactionGizmoSubmission.activeGizmoKind;
const bool gizmoActive = interactionGizmoSubmission.GizmoActive();
const SceneViewportHudOverlayData interactionHudOverlay =
BuildSceneViewportHudOverlayData(overlay);
SceneViewportInteractionResult hoveredInteraction = {};
@@ -471,15 +454,13 @@ void SceneViewPanel::Render() {
ImGui::SetWindowFocus();
}
if (interactionActions.beginTransformGizmo) {
if (interactionActions.hoveredGizmoKind == SceneViewportActiveGizmoKind::Scale) {
m_scaleGizmo.TryBeginDrag(gizmoFrameState.scaleContext, m_context->GetUndoManager());
} else if (interactionActions.hoveredGizmoKind == SceneViewportActiveGizmoKind::Move) {
m_moveGizmo.TryBeginDrag(gizmoFrameState.moveContext, m_context->GetUndoManager());
} else if (interactionActions.hoveredGizmoKind == SceneViewportActiveGizmoKind::Rotate) {
m_rotateGizmo.TryBeginDrag(gizmoFrameState.rotateContext, m_context->GetUndoManager());
}
}
ExecuteSceneViewportTransformGizmoLifecycleCommand(
BuildBeginSceneViewportTransformGizmoLifecycleCommand(interactionActions),
m_context->GetUndoManager(),
gizmoFrameState,
m_moveGizmo,
m_rotateGizmo,
m_scaleGizmo);
DispatchSceneViewportInteractionActions(
interactionActions,
@@ -488,25 +469,15 @@ void SceneViewPanel::Render() {
content.availableSize,
localMousePosition);
if (gizmoActive) {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) {
m_moveGizmo.UpdateDrag(gizmoFrameState.moveContext);
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Rotate) {
m_rotateGizmo.UpdateDrag(gizmoFrameState.rotateContext);
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Scale) {
m_scaleGizmo.UpdateDrag(gizmoFrameState.scaleContext);
}
} else {
if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) {
m_moveGizmo.EndDrag(m_context->GetUndoManager());
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Rotate) {
m_rotateGizmo.EndDrag(m_context->GetUndoManager());
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Scale) {
m_scaleGizmo.EndDrag(m_context->GetUndoManager());
}
}
}
ExecuteSceneViewportTransformGizmoLifecycleCommand(
BuildFrameSceneViewportTransformGizmoLifecycleCommand(
activeGizmoKind,
ImGui::IsMouseDown(ImGuiMouseButton_Left)),
m_context->GetUndoManager(),
gizmoFrameState,
m_moveGizmo,
m_rotateGizmo,
m_scaleGizmo);
if (beginLookDrag) {
m_lookDragging = true;
@@ -604,18 +575,16 @@ void SceneViewPanel::Render() {
showingScaleGizmo,
m_scaleGizmo);
viewportHostService->SetSceneViewTransformGizmoOverlayState(
BuildSceneViewportTransformGizmoOverlayState(
BuildSceneViewportTransformGizmoHandleBuildInputs(
showingMoveGizmo,
m_moveGizmo,
drawGizmoFrameState.moveContext,
showingRotateGizmo,
m_rotateGizmo,
drawGizmoFrameState.rotateContext,
showingScaleGizmo,
m_scaleGizmo,
drawGizmoFrameState.scaleContext)));
SubmitSceneViewportTransformGizmoOverlaySubmission(
*viewportHostService,
BuildSceneViewportTransformGizmoOverlaySubmission(
drawGizmoFrameState,
showingMoveGizmo,
m_moveGizmo,
showingRotateGizmo,
m_rotateGizmo,
showingScaleGizmo,
m_scaleGizmo));
DrawSceneViewportHudOverlay(
ImGui::GetWindowDrawList(),