Files
XCEngine/editor/src/Viewport/SceneViewportInteractionFrame.h

196 lines
7.5 KiB
C++

#pragma once
#include "Core/IEditorContext.h"
#include "SceneViewportNavigation.h"
#include "IViewportHostService.h"
#include "SceneViewportEditorModes.h"
#include "SceneViewportHudOverlay.h"
#include "SceneViewportInteractionActions.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;
}
inline bool ShouldFocusSceneViewportAfterInteraction(
bool toolCommandTriggered,
const SceneViewportInteractionActions& interactionActions,
const SceneViewportNavigationUpdate& navigationUpdate) {
return toolCommandTriggered ||
interactionActions.HasClickAction() ||
navigationUpdate.beginLookDrag ||
navigationUpdate.beginPanDrag;
}
struct SceneViewportPresentationRequest {
IEditorContext* context = nullptr;
IViewportHostService* viewportHostService = nullptr;
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
bool hasInteractiveViewport = false;
SceneViewportFrameGeometry geometry = {};
SceneViewportTransformGizmoFrameOptions gizmoFrameOptions = {};
SceneViewportMoveGizmo* moveGizmo = nullptr;
SceneViewportRotateGizmo* rotateGizmo = nullptr;
SceneViewportScaleGizmo* scaleGizmo = nullptr;
ImDrawList* drawList = nullptr;
ImVec2 viewportMin = ImVec2(0.0f, 0.0f);
ImVec2 viewportMax = ImVec2(0.0f, 0.0f);
bool IsValid() const {
return context != nullptr &&
viewportHostService != nullptr &&
moveGizmo != nullptr &&
rotateGizmo != nullptr &&
scaleGizmo != nullptr;
}
};
inline void RefreshAndDrawSceneViewportPresentation(const SceneViewportPresentationRequest& request) {
if (!request.IsValid() || !request.hasInteractiveViewport) {
return;
}
const SceneViewportOverlayData overlay = request.viewportHostService->GetSceneViewOverlayData();
RefreshAndSubmitSceneViewportTransformGizmoFrame(
*request.viewportHostService,
BuildSceneViewportTransformGizmoRefreshRequest(
*request.context,
overlay,
request.geometry.viewportSize,
request.geometry.localMousePosition,
request.gizmoFrameOptions),
*request.moveGizmo,
*request.rotateGizmo,
*request.scaleGizmo);
DrawSceneViewportHudOverlay(
request.drawList,
BuildSceneViewportHudOverlayData(
overlay,
true,
request.overlayFrameData),
request.viewportMin,
request.viewportMax);
}
} // namespace Editor
} // namespace XCEngine