Formalize scene viewport interaction resolver
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
#include "SceneViewPanel.h"
|
||||
#include "Viewport/SceneViewportEditorOverlayData.h"
|
||||
#include "Viewport/SceneViewportHudOverlay.h"
|
||||
#include "Viewport/SceneViewportInteractionResolver.h"
|
||||
#include "Viewport/SceneViewportOverlayHandleBuilder.h"
|
||||
#include "Viewport/SceneViewportOverlayHitTester.h"
|
||||
#include "Viewport/SceneViewportMath.h"
|
||||
#include "Viewport/SceneViewportTransformGizmoFrameBuilder.h"
|
||||
#include "ViewportPanelContent.h"
|
||||
@@ -30,33 +30,6 @@ struct SceneViewportToolOverlayResult {
|
||||
SceneViewportToolMode clickedTool = SceneViewportToolMode::Move;
|
||||
};
|
||||
|
||||
enum class SceneViewportInteractionKind : uint8_t {
|
||||
None = 0,
|
||||
MoveGizmo,
|
||||
RotateGizmo,
|
||||
ScaleGizmo,
|
||||
OrientationGizmo,
|
||||
SceneIcon
|
||||
};
|
||||
|
||||
struct SceneViewportInteractionCandidate {
|
||||
SceneViewportInteractionKind kind = SceneViewportInteractionKind::None;
|
||||
int priority = 0;
|
||||
int secondaryPriority = 0;
|
||||
float distanceSq = Math::FLOAT_MAX;
|
||||
float depth = Math::FLOAT_MAX;
|
||||
uint64_t entityId = 0;
|
||||
SceneViewportGizmoAxis moveAxis = SceneViewportGizmoAxis::None;
|
||||
SceneViewportGizmoPlane movePlane = SceneViewportGizmoPlane::None;
|
||||
SceneViewportRotateGizmoAxis rotateAxis = SceneViewportRotateGizmoAxis::None;
|
||||
SceneViewportScaleGizmoHandle scaleHandle = SceneViewportScaleGizmoHandle::None;
|
||||
SceneViewportOrientationAxis orientationAxis = SceneViewportOrientationAxis::None;
|
||||
|
||||
bool HasHit() const {
|
||||
return kind != SceneViewportInteractionKind::None;
|
||||
}
|
||||
};
|
||||
|
||||
const char* GetSceneViewportPivotModeLabel(SceneViewportPivotMode mode) {
|
||||
return mode == SceneViewportPivotMode::Pivot ? "Pivot" : "Center";
|
||||
}
|
||||
@@ -81,114 +54,6 @@ SceneViewportActiveGizmoKind ToActiveGizmoKind(SceneViewportInteractionKind kind
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBetterSceneViewportInteractionCandidate(
|
||||
const SceneViewportInteractionCandidate& candidate,
|
||||
const SceneViewportInteractionCandidate& current) {
|
||||
constexpr float kMetricEpsilon = 0.001f;
|
||||
|
||||
if (!candidate.HasHit()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!current.HasHit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (candidate.priority != current.priority) {
|
||||
return candidate.priority > current.priority;
|
||||
}
|
||||
|
||||
if (candidate.distanceSq + kMetricEpsilon < current.distanceSq) {
|
||||
return true;
|
||||
}
|
||||
if (current.distanceSq + kMetricEpsilon < candidate.distanceSq) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate.depth + kMetricEpsilon < current.depth) {
|
||||
return true;
|
||||
}
|
||||
if (current.depth + kMetricEpsilon < candidate.depth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return candidate.secondaryPriority > current.secondaryPriority;
|
||||
}
|
||||
|
||||
void AccumulateSceneViewportInteractionCandidate(
|
||||
const SceneViewportInteractionCandidate& candidate,
|
||||
SceneViewportInteractionCandidate& bestCandidate) {
|
||||
if (IsBetterSceneViewportInteractionCandidate(candidate, bestCandidate)) {
|
||||
bestCandidate = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
SceneViewportInteractionCandidate BuildOrientationGizmoInteractionCandidate(
|
||||
SceneViewportOrientationAxis axis) {
|
||||
SceneViewportInteractionCandidate candidate = {};
|
||||
if (axis == SceneViewportOrientationAxis::None) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
candidate.kind = SceneViewportInteractionKind::OrientationGizmo;
|
||||
candidate.priority = 200;
|
||||
candidate.distanceSq = 0.0f;
|
||||
candidate.depth = 0.0f;
|
||||
candidate.orientationAxis = axis;
|
||||
return candidate;
|
||||
}
|
||||
|
||||
SceneViewportInteractionCandidate BuildHudOverlayInteractionCandidate(
|
||||
const SceneViewportHudOverlayHitResult& hitResult) {
|
||||
switch (hitResult.kind) {
|
||||
case SceneViewportHudOverlayHitKind::OrientationAxis:
|
||||
return BuildOrientationGizmoInteractionCandidate(hitResult.orientationAxis);
|
||||
case SceneViewportHudOverlayHitKind::None:
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
SceneViewportInteractionCandidate BuildOverlayHandleInteractionCandidate(
|
||||
const SceneViewportOverlayHandleHitResult& hitResult) {
|
||||
SceneViewportInteractionCandidate candidate = {};
|
||||
if (!hitResult.HasHit()) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
candidate.priority = hitResult.priority;
|
||||
candidate.distanceSq = hitResult.distanceSq;
|
||||
candidate.depth = hitResult.depth;
|
||||
candidate.entityId = hitResult.entityId;
|
||||
switch (hitResult.kind) {
|
||||
case SceneViewportOverlayHandleKind::SceneIcon:
|
||||
candidate.kind = SceneViewportInteractionKind::SceneIcon;
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::MoveAxis:
|
||||
candidate.kind = SceneViewportInteractionKind::MoveGizmo;
|
||||
candidate.moveAxis = static_cast<SceneViewportGizmoAxis>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::MovePlane:
|
||||
candidate.kind = SceneViewportInteractionKind::MoveGizmo;
|
||||
candidate.movePlane = static_cast<SceneViewportGizmoPlane>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::RotateAxis:
|
||||
candidate.kind = SceneViewportInteractionKind::RotateGizmo;
|
||||
candidate.rotateAxis = static_cast<SceneViewportRotateGizmoAxis>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::ScaleAxis:
|
||||
case SceneViewportOverlayHandleKind::ScaleUniform:
|
||||
candidate.kind = SceneViewportInteractionKind::ScaleGizmo;
|
||||
candidate.scaleHandle = static_cast<SceneViewportScaleGizmoHandle>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::None:
|
||||
default:
|
||||
return SceneViewportInteractionCandidate{};
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
float GetSceneToolbarToggleWidth(const char* firstLabel, const char* secondLabel) {
|
||||
constexpr float kHorizontalPadding = 10.0f;
|
||||
constexpr float kMinWidth = 68.0f;
|
||||
@@ -539,13 +404,6 @@ void SceneViewPanel::Render() {
|
||||
hasInteractiveViewport
|
||||
? viewportHostService->GetSceneViewEditorOverlayFrameData(*m_context)
|
||||
: emptySceneOverlayFrameData;
|
||||
const SceneViewportOverlayHandleHitResult overlayHandleHit =
|
||||
hasInteractiveViewport
|
||||
? HitTestSceneViewportOverlayHandles(
|
||||
interactionOverlayFrameData,
|
||||
Math::Vector2(content.availableSize.x, content.availableSize.y),
|
||||
localMousePosition)
|
||||
: SceneViewportOverlayHandleHitResult{};
|
||||
const bool moveGizmoActive = showingMoveGizmo && m_moveGizmo.IsActive();
|
||||
const bool rotateGizmoActive = showingRotateGizmo && m_rotateGizmo.IsActive();
|
||||
const bool scaleGizmoActive = showingScaleGizmo && m_scaleGizmo.IsActive();
|
||||
@@ -561,7 +419,7 @@ void SceneViewPanel::Render() {
|
||||
const bool gizmoActive = activeGizmoKind != SceneViewportActiveGizmoKind::None;
|
||||
const SceneViewportHudOverlayData interactionHudOverlay =
|
||||
BuildSceneViewportHudOverlayData(overlay);
|
||||
SceneViewportInteractionCandidate hoveredInteraction = {};
|
||||
SceneViewportInteractionResult hoveredInteraction = {};
|
||||
const bool canResolveViewportInteraction =
|
||||
hasInteractiveViewport &&
|
||||
viewportContentHovered &&
|
||||
@@ -571,18 +429,15 @@ void SceneViewPanel::Render() {
|
||||
!toolOverlay.hovered &&
|
||||
!gizmoActive;
|
||||
if (canResolveViewportInteraction) {
|
||||
AccumulateSceneViewportInteractionCandidate(
|
||||
BuildOverlayHandleInteractionCandidate(overlayHandleHit),
|
||||
hoveredInteraction);
|
||||
|
||||
AccumulateSceneViewportInteractionCandidate(
|
||||
BuildHudOverlayInteractionCandidate(
|
||||
HitTestSceneViewportHudOverlay(
|
||||
interactionHudOverlay,
|
||||
content.itemMin,
|
||||
content.itemMax,
|
||||
io.MousePos)),
|
||||
hoveredInteraction);
|
||||
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);
|
||||
}
|
||||
|
||||
if (!gizmoActive) {
|
||||
|
||||
Reference in New Issue
Block a user