Formalize scene viewport interaction frame helpers
This commit is contained in:
132
editor/src/Viewport/SceneViewportInteractionFrame.h
Normal file
132
editor/src/Viewport/SceneViewportInteractionFrame.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include "Core/IEditorContext.h"
|
||||
#include "IViewportHostService.h"
|
||||
#include "SceneViewportEditorModes.h"
|
||||
#include "SceneViewportHudOverlay.h"
|
||||
#include "SceneViewportInteractionResolver.h"
|
||||
#include "SceneViewportTransformGizmoCoordinator.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
|
||||
struct SceneViewportToolState {
|
||||
bool usingViewMoveTool = false;
|
||||
bool usingTransformTool = false;
|
||||
bool showingMoveGizmo = false;
|
||||
bool showingRotateGizmo = false;
|
||||
bool showingScaleGizmo = false;
|
||||
bool useCenterPivot = false;
|
||||
bool localSpace = false;
|
||||
SceneViewportTransformGizmoFrameOptions gizmoFrameOptions = {};
|
||||
};
|
||||
|
||||
inline SceneViewportToolState BuildSceneViewportToolState(
|
||||
SceneViewportToolMode toolMode,
|
||||
SceneViewportPivotMode pivotMode,
|
||||
SceneViewportTransformSpaceMode transformSpaceMode) {
|
||||
SceneViewportToolState state = {};
|
||||
state.usingViewMoveTool = toolMode == SceneViewportToolMode::ViewMove;
|
||||
state.usingTransformTool = toolMode == SceneViewportToolMode::Transform;
|
||||
state.showingMoveGizmo = toolMode == SceneViewportToolMode::Move || state.usingTransformTool;
|
||||
state.showingRotateGizmo = toolMode == SceneViewportToolMode::Rotate || state.usingTransformTool;
|
||||
state.showingScaleGizmo = toolMode == SceneViewportToolMode::Scale || state.usingTransformTool;
|
||||
state.useCenterPivot = pivotMode == SceneViewportPivotMode::Center;
|
||||
state.localSpace = transformSpaceMode == SceneViewportTransformSpaceMode::Local;
|
||||
state.gizmoFrameOptions = BuildSceneViewportTransformGizmoFrameOptions(
|
||||
state.useCenterPivot,
|
||||
state.localSpace,
|
||||
state.usingTransformTool,
|
||||
state.showingMoveGizmo,
|
||||
state.showingRotateGizmo,
|
||||
state.showingScaleGizmo);
|
||||
return state;
|
||||
}
|
||||
|
||||
struct SceneViewportFrameGeometry {
|
||||
Math::Vector2 viewportSize = Math::Vector2::Zero();
|
||||
Math::Vector2 localMousePosition = Math::Vector2::Zero();
|
||||
};
|
||||
|
||||
inline SceneViewportFrameGeometry BuildSceneViewportFrameGeometry(
|
||||
const ImVec2& viewportSize,
|
||||
const ImVec2& viewportMin,
|
||||
const ImVec2& absoluteMousePosition) {
|
||||
SceneViewportFrameGeometry geometry = {};
|
||||
geometry.viewportSize = Math::Vector2(viewportSize.x, viewportSize.y);
|
||||
geometry.localMousePosition = Math::Vector2(
|
||||
absoluteMousePosition.x - viewportMin.x,
|
||||
absoluteMousePosition.y - viewportMin.y);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
struct SceneViewportInteractionFrameState {
|
||||
bool hasInteractiveViewport = false;
|
||||
SceneViewportOverlayData overlay = {};
|
||||
SceneViewportTransformGizmoFrameUpdate gizmoFrameUpdate = {};
|
||||
SceneViewportTransformGizmoFrameState gizmoFrameState = {};
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
|
||||
SceneViewportActiveGizmoKind activeGizmoKind = SceneViewportActiveGizmoKind::None;
|
||||
bool gizmoActive = false;
|
||||
SceneViewportHudOverlayData hudOverlay = {};
|
||||
};
|
||||
|
||||
inline SceneViewportInteractionFrameState BuildSceneViewportInteractionFrameState(
|
||||
IEditorContext& context,
|
||||
IViewportHostService& viewportHostService,
|
||||
bool hasInteractiveViewport,
|
||||
const SceneViewportFrameGeometry& geometry,
|
||||
const SceneViewportTransformGizmoFrameOptions& gizmoFrameOptions,
|
||||
SceneViewportMoveGizmo& moveGizmo,
|
||||
SceneViewportRotateGizmo& rotateGizmo,
|
||||
SceneViewportScaleGizmo& scaleGizmo,
|
||||
const SceneViewportOverlayFrameData& emptyOverlayFrameData) {
|
||||
SceneViewportInteractionFrameState state = {};
|
||||
state.hasInteractiveViewport = hasInteractiveViewport;
|
||||
state.overlayFrameData = &emptyOverlayFrameData;
|
||||
|
||||
if (!hasInteractiveViewport) {
|
||||
CancelSceneViewportTransformGizmoFrame(context, moveGizmo, rotateGizmo, scaleGizmo);
|
||||
state.hudOverlay = BuildSceneViewportHudOverlayData(state.overlay);
|
||||
return state;
|
||||
}
|
||||
|
||||
state.overlay = viewportHostService.GetSceneViewOverlayData();
|
||||
state.gizmoFrameUpdate = RefreshAndSubmitSceneViewportTransformGizmoFrame(
|
||||
viewportHostService,
|
||||
BuildSceneViewportTransformGizmoRefreshRequest(
|
||||
context,
|
||||
state.overlay,
|
||||
geometry.viewportSize,
|
||||
geometry.localMousePosition,
|
||||
gizmoFrameOptions),
|
||||
moveGizmo,
|
||||
rotateGizmo,
|
||||
scaleGizmo);
|
||||
state.gizmoFrameState = state.gizmoFrameUpdate.frameState;
|
||||
state.overlayFrameData = &viewportHostService.GetSceneViewEditorOverlayFrameData(context);
|
||||
state.activeGizmoKind = state.gizmoFrameUpdate.overlaySubmission.activeGizmoKind;
|
||||
state.gizmoActive = state.gizmoFrameUpdate.overlaySubmission.GizmoActive();
|
||||
state.hudOverlay = BuildSceneViewportHudOverlayData(state.overlay);
|
||||
return state;
|
||||
}
|
||||
|
||||
inline SceneViewportInteractionResolveRequest BuildSceneViewportInteractionResolveRequest(
|
||||
const SceneViewportInteractionFrameState& frameState,
|
||||
const SceneViewportFrameGeometry& geometry,
|
||||
const ImVec2& viewportMin,
|
||||
const ImVec2& viewportMax,
|
||||
const ImVec2& absoluteMousePosition) {
|
||||
SceneViewportInteractionResolveRequest request = {};
|
||||
request.overlayFrameData = frameState.overlayFrameData;
|
||||
request.viewportSize = geometry.viewportSize;
|
||||
request.localMousePosition = geometry.localMousePosition;
|
||||
request.hudOverlay = &frameState.hudOverlay;
|
||||
request.viewportMin = viewportMin;
|
||||
request.viewportMax = viewportMax;
|
||||
request.absoluteMousePosition = absoluteMousePosition;
|
||||
return request;
|
||||
}
|
||||
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "SceneViewPanel.h"
|
||||
#include "Viewport/SceneViewportEditorOverlayData.h"
|
||||
#include "Viewport/SceneViewportHudOverlay.h"
|
||||
#include "Viewport/SceneViewportInteractionFrame.h"
|
||||
#include "Viewport/SceneViewportInteractionActions.h"
|
||||
#include "Viewport/SceneViewportInteractionResolver.h"
|
||||
#include "Viewport/SceneViewportMath.h"
|
||||
@@ -292,91 +293,51 @@ void SceneViewPanel::Render() {
|
||||
m_toolMode = toolShortcutAction.targetTool;
|
||||
}
|
||||
|
||||
const bool usingViewMoveTool = m_toolMode == SceneViewportToolMode::ViewMove;
|
||||
const bool usingTransformTool = m_toolMode == SceneViewportToolMode::Transform;
|
||||
const bool showingMoveGizmo = m_toolMode == SceneViewportToolMode::Move || usingTransformTool;
|
||||
const bool showingRotateGizmo = m_toolMode == SceneViewportToolMode::Rotate || usingTransformTool;
|
||||
const bool showingScaleGizmo = m_toolMode == SceneViewportToolMode::Scale || usingTransformTool;
|
||||
const bool useCenterPivot = m_pivotMode == SceneViewportPivotMode::Center;
|
||||
const bool localSpace = m_transformSpaceMode == SceneViewportTransformSpaceMode::Local;
|
||||
const SceneViewportTransformGizmoFrameOptions gizmoFrameOptions =
|
||||
BuildSceneViewportTransformGizmoFrameOptions(
|
||||
useCenterPivot,
|
||||
localSpace,
|
||||
usingTransformTool,
|
||||
showingMoveGizmo,
|
||||
showingRotateGizmo,
|
||||
showingScaleGizmo);
|
||||
const Math::Vector2 viewportSize(content.availableSize.x, content.availableSize.y);
|
||||
const Math::Vector2 localMousePosition(
|
||||
io.MousePos.x - content.itemMin.x,
|
||||
io.MousePos.y - content.itemMin.y);
|
||||
SceneViewportOverlayData overlay = {};
|
||||
SceneViewportTransformGizmoFrameUpdate interactionGizmoFrame = {};
|
||||
SceneViewportTransformGizmoFrameState gizmoFrameState = {};
|
||||
const SceneViewportToolState toolState = BuildSceneViewportToolState(
|
||||
m_toolMode,
|
||||
m_pivotMode,
|
||||
m_transformSpaceMode);
|
||||
const SceneViewportFrameGeometry frameGeometry = BuildSceneViewportFrameGeometry(
|
||||
content.availableSize,
|
||||
content.itemMin,
|
||||
io.MousePos);
|
||||
SceneViewportOverlayFrameData emptySceneOverlayFrameData = {};
|
||||
|
||||
if (hasInteractiveViewport) {
|
||||
overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
interactionGizmoFrame = RefreshAndSubmitSceneViewportTransformGizmoFrame(
|
||||
*viewportHostService,
|
||||
BuildSceneViewportTransformGizmoRefreshRequest(
|
||||
*m_context,
|
||||
overlay,
|
||||
viewportSize,
|
||||
localMousePosition,
|
||||
gizmoFrameOptions),
|
||||
m_moveGizmo,
|
||||
m_rotateGizmo,
|
||||
m_scaleGizmo);
|
||||
gizmoFrameState = interactionGizmoFrame.frameState;
|
||||
} else {
|
||||
CancelSceneViewportTransformGizmoFrame(
|
||||
const SceneViewportInteractionFrameState interactionFrameState =
|
||||
BuildSceneViewportInteractionFrameState(
|
||||
*m_context,
|
||||
*viewportHostService,
|
||||
hasInteractiveViewport,
|
||||
frameGeometry,
|
||||
toolState.gizmoFrameOptions,
|
||||
m_moveGizmo,
|
||||
m_rotateGizmo,
|
||||
m_scaleGizmo);
|
||||
}
|
||||
|
||||
const SceneViewportTransformGizmoOverlaySubmission interactionGizmoSubmission =
|
||||
hasInteractiveViewport
|
||||
? interactionGizmoFrame.overlaySubmission
|
||||
: SceneViewportTransformGizmoOverlaySubmission{};
|
||||
const SceneViewportOverlayFrameData& interactionOverlayFrameData =
|
||||
hasInteractiveViewport
|
||||
? viewportHostService->GetSceneViewEditorOverlayFrameData(*m_context)
|
||||
: emptySceneOverlayFrameData;
|
||||
const SceneViewportActiveGizmoKind activeGizmoKind = interactionGizmoSubmission.activeGizmoKind;
|
||||
const bool gizmoActive = interactionGizmoSubmission.GizmoActive();
|
||||
const SceneViewportHudOverlayData interactionHudOverlay =
|
||||
BuildSceneViewportHudOverlayData(overlay);
|
||||
m_scaleGizmo,
|
||||
emptySceneOverlayFrameData);
|
||||
SceneViewportInteractionResult hoveredInteraction = {};
|
||||
const bool canResolveViewportInteraction = CanResolveSceneViewportInteraction(
|
||||
hasInteractiveViewport,
|
||||
viewportContentHovered,
|
||||
usingViewMoveTool,
|
||||
toolState.usingViewMoveTool,
|
||||
m_navigationState,
|
||||
gizmoActive);
|
||||
interactionFrameState.gizmoActive);
|
||||
if (canResolveViewportInteraction) {
|
||||
SceneViewportInteractionResolveRequest interactionRequest = {};
|
||||
interactionRequest.overlayFrameData = &interactionOverlayFrameData;
|
||||
interactionRequest.viewportSize = viewportSize;
|
||||
interactionRequest.localMousePosition = localMousePosition;
|
||||
interactionRequest.hudOverlay = &interactionHudOverlay;
|
||||
interactionRequest.viewportMin = content.itemMin;
|
||||
interactionRequest.viewportMax = content.itemMax;
|
||||
interactionRequest.absoluteMousePosition = io.MousePos;
|
||||
hoveredInteraction = ResolveSceneViewportInteraction(interactionRequest);
|
||||
hoveredInteraction = ResolveSceneViewportInteraction(
|
||||
BuildSceneViewportInteractionResolveRequest(
|
||||
interactionFrameState,
|
||||
frameGeometry,
|
||||
content.itemMin,
|
||||
content.itemMax,
|
||||
io.MousePos));
|
||||
}
|
||||
|
||||
ApplySceneViewportHoveredHandleState(
|
||||
BuildSceneViewportHoveredHandleState(hoveredInteraction),
|
||||
gizmoActive,
|
||||
showingMoveGizmo,
|
||||
interactionFrameState.gizmoActive,
|
||||
toolState.showingMoveGizmo,
|
||||
m_moveGizmo,
|
||||
showingRotateGizmo,
|
||||
toolState.showingRotateGizmo,
|
||||
m_rotateGizmo,
|
||||
showingScaleGizmo,
|
||||
toolState.showingScaleGizmo,
|
||||
m_scaleGizmo);
|
||||
|
||||
const SceneViewportInteractionActions interactionActions =
|
||||
@@ -389,8 +350,8 @@ void SceneViewPanel::Render() {
|
||||
navigationRequest.state = m_navigationState;
|
||||
navigationRequest.hasInteractiveViewport = hasInteractiveViewport;
|
||||
navigationRequest.viewportHovered = viewportContentHovered;
|
||||
navigationRequest.usingViewMoveTool = usingViewMoveTool;
|
||||
navigationRequest.gizmoActive = gizmoActive;
|
||||
navigationRequest.usingViewMoveTool = toolState.usingViewMoveTool;
|
||||
navigationRequest.gizmoActive = interactionFrameState.gizmoActive;
|
||||
navigationRequest.clickedLeft = content.clickedLeft;
|
||||
navigationRequest.clickedRight = content.clickedRight;
|
||||
navigationRequest.clickedMiddle = content.clickedMiddle;
|
||||
@@ -409,7 +370,7 @@ void SceneViewPanel::Render() {
|
||||
ExecuteSceneViewportTransformGizmoLifecycleCommand(
|
||||
BuildBeginSceneViewportTransformGizmoLifecycleCommand(interactionActions),
|
||||
m_context->GetUndoManager(),
|
||||
gizmoFrameState,
|
||||
interactionFrameState.gizmoFrameState,
|
||||
m_moveGizmo,
|
||||
m_rotateGizmo,
|
||||
m_scaleGizmo);
|
||||
@@ -419,14 +380,14 @@ void SceneViewPanel::Render() {
|
||||
*m_context,
|
||||
*viewportHostService,
|
||||
content.availableSize,
|
||||
localMousePosition);
|
||||
frameGeometry.localMousePosition);
|
||||
|
||||
ExecuteSceneViewportTransformGizmoLifecycleCommand(
|
||||
BuildFrameSceneViewportTransformGizmoLifecycleCommand(
|
||||
activeGizmoKind,
|
||||
interactionFrameState.activeGizmoKind,
|
||||
ImGui::IsMouseDown(ImGuiMouseButton_Left)),
|
||||
m_context->GetUndoManager(),
|
||||
gizmoFrameState,
|
||||
interactionFrameState.gizmoFrameState,
|
||||
m_moveGizmo,
|
||||
m_rotateGizmo,
|
||||
m_scaleGizmo);
|
||||
@@ -466,15 +427,15 @@ void SceneViewPanel::Render() {
|
||||
viewportHostService->UpdateSceneViewInput(*m_context, input);
|
||||
|
||||
if (content.hasViewportArea && content.frame.hasTexture) {
|
||||
overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
const SceneViewportOverlayData overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
RefreshAndSubmitSceneViewportTransformGizmoFrame(
|
||||
*viewportHostService,
|
||||
BuildSceneViewportTransformGizmoRefreshRequest(
|
||||
*m_context,
|
||||
overlay,
|
||||
viewportSize,
|
||||
localMousePosition,
|
||||
gizmoFrameOptions),
|
||||
frameGeometry.viewportSize,
|
||||
frameGeometry.localMousePosition,
|
||||
toolState.gizmoFrameOptions),
|
||||
m_moveGizmo,
|
||||
m_rotateGizmo,
|
||||
m_scaleGizmo);
|
||||
|
||||
Reference in New Issue
Block a user