关键节点
This commit is contained in:
545
editor/app/Features/Scene/SceneViewportController.cpp
Normal file
545
editor/app/Features/Scene/SceneViewportController.cpp
Normal file
@@ -0,0 +1,545 @@
|
||||
#include "Features/Scene/SceneViewportController.h"
|
||||
|
||||
#include "Rendering/Viewport/ViewportObjectPickerService.h"
|
||||
#include "Scene/EditorSceneRuntime.h"
|
||||
#include "State/EditorCommandFocusService.h"
|
||||
|
||||
#include "Composition/EditorPanelIds.h"
|
||||
#include <XCEditor/Viewport/UIEditorViewportInputBridge.h>
|
||||
#include <XCEditor/Viewport/UIEditorViewportSlot.h>
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::XCEngine::Input::KeyCode;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIPointerButton;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
constexpr float kWheelDeltaPerStep = 120.0f;
|
||||
|
||||
bool ContainsPoint(const UIRect& rect, const UIPoint& point) {
|
||||
return point.x >= rect.x &&
|
||||
point.x <= rect.x + rect.width &&
|
||||
point.y >= rect.y &&
|
||||
point.y <= rect.y + rect.height;
|
||||
}
|
||||
|
||||
bool IsKeyDown(
|
||||
const UIEditorViewportInputBridgeState& state,
|
||||
KeyCode keyCode) {
|
||||
return IsUIEditorViewportInputBridgeKeyDown(
|
||||
state,
|
||||
static_cast<std::int32_t>(keyCode));
|
||||
}
|
||||
|
||||
bool WasKeyPressed(
|
||||
const UIEditorViewportInputBridgeFrame& frame,
|
||||
KeyCode keyCode) {
|
||||
const std::int32_t expected = static_cast<std::int32_t>(keyCode);
|
||||
return std::find(
|
||||
frame.pressedKeyCodes.begin(),
|
||||
frame.pressedKeyCodes.end(),
|
||||
expected) != frame.pressedKeyCodes.end();
|
||||
}
|
||||
|
||||
bool HasCameraInput(const SceneViewportCameraInputState& input) {
|
||||
return input.lookDeltaX != 0.0f ||
|
||||
input.lookDeltaY != 0.0f ||
|
||||
input.panDeltaX != 0.0f ||
|
||||
input.panDeltaY != 0.0f ||
|
||||
input.zoomDelta != 0.0f ||
|
||||
input.flySpeedDelta != 0.0f ||
|
||||
input.moveForward != 0.0f ||
|
||||
input.moveRight != 0.0f ||
|
||||
input.moveUp != 0.0f;
|
||||
}
|
||||
|
||||
float NormalizeWheelDelta(float wheelDelta) {
|
||||
return wheelDelta / kWheelDeltaPerStep;
|
||||
}
|
||||
|
||||
bool IsViewMoveTool(SceneToolMode mode) {
|
||||
return mode == SceneToolMode::View;
|
||||
}
|
||||
|
||||
bool IsPanDragButtonDown(
|
||||
const UIEditorViewportInputBridgeState& state,
|
||||
UIPointerButton button) {
|
||||
return button != UIPointerButton::None &&
|
||||
IsUIEditorViewportInputBridgePointerButtonDown(state, button);
|
||||
}
|
||||
|
||||
bool TryResolveToolModeShortcut(
|
||||
const UIEditorViewportInputBridgeFrame& inputFrame,
|
||||
SceneToolMode& outMode) {
|
||||
if (inputFrame.modifiers.control ||
|
||||
inputFrame.modifiers.alt ||
|
||||
inputFrame.modifiers.super) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WasKeyPressed(inputFrame, KeyCode::Q)) {
|
||||
outMode = SceneToolMode::View;
|
||||
return true;
|
||||
}
|
||||
if (WasKeyPressed(inputFrame, KeyCode::W)) {
|
||||
outMode = SceneToolMode::Translate;
|
||||
return true;
|
||||
}
|
||||
if (WasKeyPressed(inputFrame, KeyCode::E)) {
|
||||
outMode = SceneToolMode::Rotate;
|
||||
return true;
|
||||
}
|
||||
if (WasKeyPressed(inputFrame, KeyCode::R)) {
|
||||
outMode = SceneToolMode::Scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ApplySceneToolMode(
|
||||
SceneToolMode mode,
|
||||
EditorSceneRuntime& sceneRuntime,
|
||||
SceneViewportTransformGizmo& transformGizmo) {
|
||||
if (sceneRuntime.GetToolMode() == mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
transformGizmo.CancelDrag(sceneRuntime);
|
||||
sceneRuntime.SetToolMode(mode);
|
||||
}
|
||||
|
||||
void ApplySceneViewportToggleButton(
|
||||
std::size_t toggleIndex,
|
||||
EditorSceneRuntime& sceneRuntime) {
|
||||
if (toggleIndex == 0u) {
|
||||
sceneRuntime.SetToolPivotMode(
|
||||
sceneRuntime.GetToolPivotMode() == SceneToolPivotMode::Pivot
|
||||
? SceneToolPivotMode::Center
|
||||
: SceneToolPivotMode::Pivot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (toggleIndex == 1u) {
|
||||
sceneRuntime.SetToolSpaceMode(
|
||||
sceneRuntime.GetToolSpaceMode() == SceneToolSpaceMode::World
|
||||
? SceneToolSpaceMode::Local
|
||||
: SceneToolSpaceMode::World);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SceneViewportController::Initialize(
|
||||
const std::filesystem::path& repoRoot,
|
||||
Rendering::Host::UiTextureHost& renderer,
|
||||
const BuiltInIcons* builtInIcons) {
|
||||
m_toolOverlay.Initialize(repoRoot, renderer);
|
||||
m_sceneOverlay.SetBuiltInIcons(builtInIcons);
|
||||
ResetInteractionState();
|
||||
}
|
||||
|
||||
void SceneViewportController::Shutdown(Rendering::Host::UiTextureHost& renderer) {
|
||||
m_toolOverlay.Shutdown(renderer);
|
||||
ResetInteractionState();
|
||||
}
|
||||
|
||||
void SceneViewportController::ResetInteractionState() {
|
||||
ResetFrameState();
|
||||
m_sceneOverlay.ResetFrame();
|
||||
m_toolOverlay.ResetFrame();
|
||||
m_transformGizmo.ResetVisualState();
|
||||
}
|
||||
|
||||
void SceneViewportController::SetCommandFocusService(
|
||||
EditorCommandFocusService* commandFocusService) {
|
||||
m_commandFocusService = commandFocusService;
|
||||
}
|
||||
|
||||
void SceneViewportController::Update(
|
||||
EditorSceneRuntime& sceneRuntime,
|
||||
const IViewportObjectPickerService& viewportObjectPicker,
|
||||
const UIEditorWorkspaceComposeState& composeState,
|
||||
const UIEditorWorkspaceComposeFrame& composeFrame) {
|
||||
const UIEditorWorkspaceViewportComposeFrame* viewportFrame =
|
||||
FindUIEditorWorkspaceViewportPresentationFrame(composeFrame, kScenePanelId);
|
||||
const UIEditorWorkspacePanelPresentationState* panelState =
|
||||
FindUIEditorWorkspacePanelPresentationState(composeState, kScenePanelId);
|
||||
if (viewportFrame == nullptr || panelState == nullptr) {
|
||||
if (m_transformGizmo.IsActive()) {
|
||||
m_transformGizmo.CancelDrag(sceneRuntime);
|
||||
}
|
||||
sceneRuntime.SetHoveredToolHandle(SceneToolHandle::None);
|
||||
ResetInteractionState();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& inputFrame = viewportFrame->viewportShellFrame.inputFrame;
|
||||
const auto& inputState = panelState->viewportShellState.inputBridgeState;
|
||||
const auto& slotLayout = viewportFrame->viewportShellFrame.slotLayout;
|
||||
const bool leftMouseDown = IsUIEditorViewportInputBridgePointerButtonDown(
|
||||
inputState,
|
||||
UIPointerButton::Left);
|
||||
const bool rightMouseDown = IsUIEditorViewportInputBridgePointerButtonDown(
|
||||
inputState,
|
||||
UIPointerButton::Right);
|
||||
const bool middleMouseDown = IsUIEditorViewportInputBridgePointerButtonDown(
|
||||
inputState,
|
||||
UIPointerButton::Middle);
|
||||
const UIPoint pointerScreen = inputState.hasPointerPosition
|
||||
? inputState.lastScreenPointerPosition
|
||||
: inputFrame.screenPointerPosition;
|
||||
|
||||
if (m_commandFocusService != nullptr &&
|
||||
(inputFrame.focused ||
|
||||
std::any_of(
|
||||
inputFrame.pointerButtonTransitions.begin(),
|
||||
inputFrame.pointerButtonTransitions.end(),
|
||||
[&](const auto& transition) {
|
||||
return transition.pressed &&
|
||||
ContainsPoint(slotLayout.bounds, transition.screenPosition);
|
||||
}))) {
|
||||
m_commandFocusService->ClaimFocus(EditorActionRoute::Scene);
|
||||
}
|
||||
|
||||
if (inputFrame.focusLost) {
|
||||
m_navigationState = {};
|
||||
m_hoveredToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_hoveredToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
if (m_transformGizmo.IsActive()) {
|
||||
m_transformGizmo.CancelDrag(sceneRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
m_toolOverlay.BuildFrame(
|
||||
slotLayout.inputRect,
|
||||
slotLayout.topBarRect,
|
||||
slotLayout.bounds,
|
||||
sceneRuntime.GetToolMode(),
|
||||
sceneRuntime.GetToolPivotMode(),
|
||||
sceneRuntime.GetToolSpaceMode(),
|
||||
kSceneViewportToolOverlayInvalidIndex,
|
||||
kSceneViewportToolOverlayInvalidIndex,
|
||||
kSceneViewportToolOverlayInvalidIndex,
|
||||
kSceneViewportToolOverlayInvalidIndex);
|
||||
const bool pointerOverOverlay =
|
||||
inputState.hasPointerPosition &&
|
||||
m_toolOverlay.Contains(pointerScreen);
|
||||
const std::size_t hoveredToggleOverlayIndex =
|
||||
inputState.hasPointerPosition
|
||||
? m_toolOverlay.HitTestToggle(pointerScreen)
|
||||
: kSceneViewportToolOverlayInvalidIndex;
|
||||
const std::size_t hoveredToolOverlayIndex =
|
||||
inputState.hasPointerPosition
|
||||
? m_toolOverlay.HitTest(pointerScreen)
|
||||
: kSceneViewportToolOverlayInvalidIndex;
|
||||
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (transition.button != UIPointerButton::Left) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::size_t transitionHoveredToggleOverlayIndex =
|
||||
m_toolOverlay.HitTestToggle(transition.screenPosition);
|
||||
if (transition.pressed &&
|
||||
transitionHoveredToggleOverlayIndex !=
|
||||
kSceneViewportToolOverlayInvalidIndex &&
|
||||
!m_transformGizmo.IsActive()) {
|
||||
m_activeToggleOverlayIndex = transitionHoveredToggleOverlayIndex;
|
||||
ApplySceneViewportToggleButton(
|
||||
m_activeToggleOverlayIndex,
|
||||
sceneRuntime);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::size_t transitionHoveredToolOverlayIndex =
|
||||
m_toolOverlay.HitTest(transition.screenPosition);
|
||||
if (transition.pressed &&
|
||||
transitionHoveredToolOverlayIndex !=
|
||||
kSceneViewportToolOverlayInvalidIndex &&
|
||||
!m_transformGizmo.IsActive()) {
|
||||
m_activeToolOverlayIndex = transitionHoveredToolOverlayIndex;
|
||||
if (m_activeToolOverlayIndex < m_toolOverlay.GetFrame().buttons.size()) {
|
||||
ApplySceneToolMode(
|
||||
m_toolOverlay.GetFrame().buttons[m_activeToolOverlayIndex].mode,
|
||||
sceneRuntime,
|
||||
m_transformGizmo);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
m_activeToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
}
|
||||
if (!leftMouseDown) {
|
||||
m_activeToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
}
|
||||
m_hoveredToggleOverlayIndex = hoveredToggleOverlayIndex;
|
||||
m_hoveredToolOverlayIndex = hoveredToolOverlayIndex;
|
||||
|
||||
m_toolOverlay.BuildFrame(
|
||||
slotLayout.inputRect,
|
||||
slotLayout.topBarRect,
|
||||
slotLayout.bounds,
|
||||
sceneRuntime.GetToolMode(),
|
||||
sceneRuntime.GetToolPivotMode(),
|
||||
sceneRuntime.GetToolSpaceMode(),
|
||||
m_hoveredToolOverlayIndex,
|
||||
m_activeToolOverlayIndex,
|
||||
m_hoveredToggleOverlayIndex,
|
||||
m_activeToggleOverlayIndex);
|
||||
|
||||
const bool overlayInteractionActive =
|
||||
m_activeToolOverlayIndex != kSceneViewportToolOverlayInvalidIndex ||
|
||||
m_activeToggleOverlayIndex != kSceneViewportToolOverlayInvalidIndex;
|
||||
|
||||
const bool usingViewMoveTool = IsViewMoveTool(sceneRuntime.GetToolMode());
|
||||
|
||||
if (!m_transformGizmo.IsActive()) {
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (!transition.pressed ||
|
||||
!ContainsPoint(slotLayout.inputRect, transition.screenPosition) ||
|
||||
m_toolOverlay.Contains(transition.screenPosition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usingViewMoveTool &&
|
||||
transition.button == UIPointerButton::Left) {
|
||||
m_navigationState.panDragging = true;
|
||||
m_navigationState.lookDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::Left;
|
||||
} else if (transition.button == UIPointerButton::Right) {
|
||||
m_navigationState.lookDragging = true;
|
||||
m_navigationState.panDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::None;
|
||||
} else if (transition.button == UIPointerButton::Middle) {
|
||||
m_navigationState.panDragging = true;
|
||||
m_navigationState.lookDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::Middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_navigationState.lookDragging && !rightMouseDown) {
|
||||
m_navigationState.lookDragging = false;
|
||||
}
|
||||
if (m_navigationState.panDragging &&
|
||||
!IsPanDragButtonDown(inputState, m_navigationState.panDragButton)) {
|
||||
m_navigationState.panDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::None;
|
||||
}
|
||||
|
||||
const bool viewportHoverEligible =
|
||||
inputState.hasPointerPosition &&
|
||||
ContainsPoint(slotLayout.inputRect, pointerScreen) &&
|
||||
!pointerOverOverlay &&
|
||||
!overlayInteractionActive &&
|
||||
!m_navigationState.lookDragging &&
|
||||
!m_navigationState.panDragging;
|
||||
|
||||
if (!m_transformGizmo.IsActive() &&
|
||||
!overlayInteractionActive &&
|
||||
inputFrame.focused &&
|
||||
!m_navigationState.lookDragging &&
|
||||
!m_navigationState.panDragging) {
|
||||
SceneToolMode shortcutMode = SceneToolMode::View;
|
||||
if (TryResolveToolModeShortcut(inputFrame, shortcutMode)) {
|
||||
ApplySceneToolMode(shortcutMode, sceneRuntime, m_transformGizmo);
|
||||
}
|
||||
}
|
||||
|
||||
if (inputFrame.focused &&
|
||||
!m_transformGizmo.IsActive() &&
|
||||
WasKeyPressed(inputFrame, KeyCode::F)) {
|
||||
sceneRuntime.FocusSceneSelection();
|
||||
}
|
||||
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
sceneRuntime.SetHoveredToolHandle(SceneToolHandle::None);
|
||||
|
||||
if (m_transformGizmo.IsActive()) {
|
||||
if (WasKeyPressed(inputFrame, KeyCode::Escape)) {
|
||||
m_transformGizmo.CancelDrag(sceneRuntime);
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!leftMouseDown) {
|
||||
m_transformGizmo.EndDrag(sceneRuntime);
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
m_transformGizmo.UpdateDrag(sceneRuntime);
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!usingViewMoveTool) {
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (!transition.pressed ||
|
||||
transition.button != UIPointerButton::Left ||
|
||||
!ContainsPoint(slotLayout.inputRect, transition.screenPosition) ||
|
||||
m_toolOverlay.Contains(transition.screenPosition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
transition.screenPosition,
|
||||
true);
|
||||
if (m_transformGizmo.IsHoveringHandle() &&
|
||||
m_transformGizmo.TryBeginDrag(sceneRuntime)) {
|
||||
m_navigationState = {};
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneViewportSceneOverlay::HitResult sceneIconHit =
|
||||
m_sceneOverlay.HitTest(transition.screenPosition);
|
||||
if (sceneIconHit.HasHit()) {
|
||||
sceneRuntime.SetSelection(sceneIconHit.entityId);
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
const ViewportObjectIdPickResult pickResult =
|
||||
viewportObjectPicker.PickObject(
|
||||
viewportFrame->viewportShellFrame.requestedViewportSize,
|
||||
transition.localPointerPosition);
|
||||
if (pickResult.status == ViewportObjectIdPickStatus::Success) {
|
||||
if (pickResult.HasResolvedEntity()) {
|
||||
sceneRuntime.SetSelection(pickResult.resolvedEntityId);
|
||||
} else {
|
||||
sceneRuntime.ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayInteractionActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
SceneViewportCameraInputState input = {};
|
||||
input.deltaTime = ConsumeDeltaTimeSeconds();
|
||||
input.viewportHeight =
|
||||
viewportFrame->viewportShellFrame.requestedViewportSize.height;
|
||||
|
||||
if (m_navigationState.lookDragging) {
|
||||
input.lookDeltaX = inputFrame.pointerDelta.x;
|
||||
input.lookDeltaY = inputFrame.pointerDelta.y;
|
||||
input.flySpeedDelta = NormalizeWheelDelta(inputFrame.wheelDelta);
|
||||
input.fastMove = inputFrame.modifiers.shift;
|
||||
input.moveForward =
|
||||
(IsKeyDown(inputState, KeyCode::W) ? 1.0f : 0.0f) -
|
||||
(IsKeyDown(inputState, KeyCode::S) ? 1.0f : 0.0f);
|
||||
input.moveRight =
|
||||
(IsKeyDown(inputState, KeyCode::D) ? 1.0f : 0.0f) -
|
||||
(IsKeyDown(inputState, KeyCode::A) ? 1.0f : 0.0f);
|
||||
input.moveUp =
|
||||
(IsKeyDown(inputState, KeyCode::E) ? 1.0f : 0.0f) -
|
||||
(IsKeyDown(inputState, KeyCode::Q) ? 1.0f : 0.0f);
|
||||
} else if (m_navigationState.panDragging) {
|
||||
input.panDeltaX = inputFrame.pointerDelta.x;
|
||||
input.panDeltaY = inputFrame.pointerDelta.y;
|
||||
} else if (ContainsPoint(slotLayout.inputRect, pointerScreen) && !pointerOverOverlay) {
|
||||
input.zoomDelta = NormalizeWheelDelta(inputFrame.wheelDelta);
|
||||
}
|
||||
|
||||
if (HasCameraInput(input)) {
|
||||
sceneRuntime.ApplySceneViewportCameraInput(input);
|
||||
RefreshSceneOverlays(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
} else {
|
||||
m_sceneOverlay.Refresh(sceneRuntime, slotLayout.inputRect);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneViewportController::Append(::XCEngine::UI::UIDrawList& drawList) const {
|
||||
m_sceneOverlay.Append(drawList);
|
||||
AppendSceneViewportTransformGizmo(drawList, m_transformGizmo.GetFrame());
|
||||
AppendSceneViewportToolOverlay(drawList, m_toolOverlay.GetFrame());
|
||||
}
|
||||
|
||||
void SceneViewportController::ResetFrameState() {
|
||||
m_navigationState = {};
|
||||
m_hoveredToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToggleOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_hoveredToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
m_lastUpdateTime = {};
|
||||
m_hasLastUpdateTime = false;
|
||||
}
|
||||
|
||||
float SceneViewportController::ConsumeDeltaTimeSeconds() {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (!m_hasLastUpdateTime) {
|
||||
m_lastUpdateTime = now;
|
||||
m_hasLastUpdateTime = true;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float deltaTime =
|
||||
std::chrono::duration<float>(now - m_lastUpdateTime).count();
|
||||
m_lastUpdateTime = now;
|
||||
return std::clamp(deltaTime, 0.0f, 0.1f);
|
||||
}
|
||||
|
||||
void SceneViewportController::RefreshSceneOverlays(
|
||||
EditorSceneRuntime& sceneRuntime,
|
||||
const UIRect& viewportRect,
|
||||
const UIPoint& pointerScreen,
|
||||
bool hoverEnabled) {
|
||||
m_sceneOverlay.Refresh(sceneRuntime, viewportRect);
|
||||
m_transformGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
viewportRect,
|
||||
pointerScreen,
|
||||
hoverEnabled);
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
Reference in New Issue
Block a user