196 lines
7.5 KiB
C++
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
|