#include "Actions/ActionRouting.h" #include "Core/IEditorContext.h" #include "Core/ISceneManager.h" #include "Core/ISelectionManager.h" #include "SceneViewPanel.h" #include "Viewport/SceneViewportEditorOverlayData.h" #include "Viewport/SceneViewportHudOverlay.h" #include "Viewport/SceneViewportInteractionResolver.h" #include "Viewport/SceneViewportOverlayHandleBuilder.h" #include "Viewport/SceneViewportMath.h" #include "Viewport/SceneViewportTransformGizmoFrameBuilder.h" #include "ViewportPanelContent.h" #include "Platform/Win32Utf8.h" #include "UI/UI.h" #include #include #include #include namespace XCEngine { namespace Editor { namespace { struct SceneViewportToolOverlayResult { bool hovered = false; bool clicked = false; SceneViewportToolMode clickedTool = SceneViewportToolMode::Move; }; const char* GetSceneViewportPivotModeLabel(SceneViewportPivotMode mode) { return mode == SceneViewportPivotMode::Pivot ? "Pivot" : "Center"; } const char* GetSceneViewportTransformSpaceModeLabel(SceneViewportTransformSpaceMode mode) { return mode == SceneViewportTransformSpaceMode::Global ? "Global" : "Local"; } SceneViewportActiveGizmoKind ToActiveGizmoKind(SceneViewportInteractionKind kind) { switch (kind) { case SceneViewportInteractionKind::MoveGizmo: return SceneViewportActiveGizmoKind::Move; case SceneViewportInteractionKind::RotateGizmo: return SceneViewportActiveGizmoKind::Rotate; case SceneViewportInteractionKind::ScaleGizmo: return SceneViewportActiveGizmoKind::Scale; case SceneViewportInteractionKind::OrientationGizmo: case SceneViewportInteractionKind::SceneIcon: case SceneViewportInteractionKind::None: default: return SceneViewportActiveGizmoKind::None; } } float GetSceneToolbarToggleWidth(const char* firstLabel, const char* secondLabel) { constexpr float kHorizontalPadding = 10.0f; constexpr float kMinWidth = 68.0f; const float maxLabelWidth = (std::max)( ImGui::CalcTextSize(firstLabel).x, ImGui::CalcTextSize(secondLabel).x); return (std::max)(kMinWidth, maxLabelWidth + kHorizontalPadding * 2.0f); } void RenderSceneViewportTopBar( SceneViewportPivotMode& pivotMode, SceneViewportTransformSpaceMode& transformSpaceMode) { constexpr float kSceneToolbarHeight = 24.0f; constexpr float kSceneToolbarPaddingY = 0.0f; constexpr float kSceneToolbarButtonHeight = kSceneToolbarHeight - kSceneToolbarPaddingY * 2.0f; constexpr ImVec2 kSceneToolbarButtonFramePadding(8.0f, 1.0f); UI::PanelToolbarScope toolbar( "SceneToolbar", kSceneToolbarHeight, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse, true, ImVec2(UI::ToolbarPadding().x, kSceneToolbarPaddingY), ImVec2(0.0f, UI::ToolbarItemSpacing().y), ImVec4(0.23f, 0.23f, 0.23f, 1.0f)); if (!toolbar.IsOpen()) { return; } ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, kSceneToolbarButtonFramePadding); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); if (UI::ToolbarButton( GetSceneViewportPivotModeLabel(pivotMode), true, ImVec2(GetSceneToolbarToggleWidth("Pivot", "Center"), kSceneToolbarButtonHeight))) { pivotMode = pivotMode == SceneViewportPivotMode::Pivot ? SceneViewportPivotMode::Center : SceneViewportPivotMode::Pivot; } ImGui::SameLine(0.0f, 0.0f); if (UI::ToolbarButton( GetSceneViewportTransformSpaceModeLabel(transformSpaceMode), true, ImVec2(GetSceneToolbarToggleWidth("Global", "Local"), kSceneToolbarButtonHeight))) { transformSpaceMode = transformSpaceMode == SceneViewportTransformSpaceMode::Global ? SceneViewportTransformSpaceMode::Local : SceneViewportTransformSpaceMode::Global; } ImGui::PopStyleVar(2); } const char* GetSceneViewportToolTooltip(SceneViewportToolMode toolMode) { switch (toolMode) { case SceneViewportToolMode::ViewMove: return "View Move"; case SceneViewportToolMode::Move: return "Move"; case SceneViewportToolMode::Rotate: return "Rotate"; case SceneViewportToolMode::Scale: return "Scale"; case SceneViewportToolMode::Transform: return "Transform"; default: return ""; } } const char* GetSceneViewportToolIconBaseName(SceneViewportToolMode toolMode) { switch (toolMode) { case SceneViewportToolMode::ViewMove: return "view_move_tool"; case SceneViewportToolMode::Move: return "move_tool"; case SceneViewportToolMode::Rotate: return "rotate_tool"; case SceneViewportToolMode::Scale: return "scale_tool"; case SceneViewportToolMode::Transform: return "transform_tool"; default: return ""; } } std::string BuildSceneViewportIconPath(const char* iconBaseName, bool active = false) { const std::filesystem::path exeDir( XCEngine::Editor::Platform::Utf8ToWide(XCEngine::Editor::Platform::GetExecutableDirectoryUtf8())); std::filesystem::path iconPath = exeDir / L".." / L".." / L"resources" / L"Icons" / std::filesystem::path(XCEngine::Editor::Platform::Utf8ToWide(iconBaseName)); if (active) { iconPath += L"_on"; } iconPath += L".png"; return XCEngine::Editor::Platform::WideToUtf8(iconPath.lexically_normal().wstring()); } const std::string& GetSceneViewportToolIconPath(SceneViewportToolMode toolMode, bool active) { static std::string cachedPaths[5][2] = {}; const size_t toolIndex = static_cast(toolMode); const size_t stateIndex = active ? 1u : 0u; std::string& cachedPath = cachedPaths[toolIndex][stateIndex]; if (!cachedPath.empty()) { return cachedPath; } cachedPath = BuildSceneViewportIconPath(GetSceneViewportToolIconBaseName(toolMode), active); return cachedPath; } SceneViewportToolOverlayResult RenderSceneViewportToolOverlay( const ViewportPanelContentResult& content, SceneViewportToolMode activeTool) { SceneViewportToolOverlayResult result = {}; if (!content.hasViewportArea) { return result; } constexpr float kButtonExtent = 30.0f; constexpr float kButtonSpacing = 6.0f; constexpr float kPanelPadding = 6.0f; constexpr float kViewportInset = 10.0f; constexpr float kIconInset = 4.0f; constexpr size_t kToolCount = 5; ImDrawList* drawList = ImGui::GetWindowDrawList(); if (drawList == nullptr) { return result; } const ImVec2 panelMin( content.itemMin.x + kViewportInset, content.itemMin.y + kViewportInset); const ImVec2 panelMax( panelMin.x + kPanelPadding * 2.0f + kButtonExtent, panelMin.y + kPanelPadding * 2.0f + kToolCount * kButtonExtent + (kToolCount - 1) * kButtonSpacing); drawList->AddRectFilled(panelMin, panelMax, IM_COL32(24, 26, 29, 220), 7.0f); drawList->AddRect(panelMin, panelMax, IM_COL32(255, 255, 255, 28), 7.0f, 0, 1.0f); const SceneViewportToolMode toolModes[kToolCount] = { SceneViewportToolMode::ViewMove, SceneViewportToolMode::Move, SceneViewportToolMode::Rotate, SceneViewportToolMode::Scale, SceneViewportToolMode::Transform }; for (size_t index = 0; index < kToolCount; ++index) { const SceneViewportToolMode toolMode = toolModes[index]; const bool active = toolMode == activeTool; const ImVec2 buttonMin( panelMin.x + kPanelPadding, panelMin.y + kPanelPadding + index * (kButtonExtent + kButtonSpacing)); const ImVec2 buttonMax(buttonMin.x + kButtonExtent, buttonMin.y + kButtonExtent); ImGui::SetCursorScreenPos(buttonMin); const std::string buttonId = std::string("##SceneToolButton") + std::to_string(static_cast(toolMode)); const bool clicked = ImGui::InvisibleButton( buttonId.c_str(), ImVec2(kButtonExtent, kButtonExtent), ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_AllowOverlap); const bool hovered = ImGui::IsItemHovered(); const bool held = ImGui::IsItemActive(); result.hovered = result.hovered || hovered; result.clicked = result.clicked || clicked; if (clicked) { result.clickedTool = toolMode; } const ImU32 backgroundColor = ImGui::GetColorU32( held ? UI::ToolbarButtonActiveColor() : hovered ? UI::ToolbarButtonHoveredColor(active) : UI::ToolbarButtonColor(active)); drawList->AddRectFilled(buttonMin, buttonMax, backgroundColor, 5.0f); drawList->AddRect(buttonMin, buttonMax, IM_COL32(255, 255, 255, active ? 48 : 24), 5.0f, 0, 1.0f); const ImVec2 iconMin(buttonMin.x + kIconInset, buttonMin.y + kIconInset); const ImVec2 iconMax(buttonMax.x - kIconInset, buttonMax.y - kIconInset); if (!UI::DrawTextureAssetPreview( drawList, iconMin, iconMax, GetSceneViewportToolIconPath(toolMode, active))) { drawList->AddText( ImVec2(buttonMin.x + 8.0f, buttonMin.y + 7.0f), IM_COL32(230, 230, 230, 255), GetSceneViewportToolTooltip(toolMode)); } if (hovered) { ImGui::SetTooltip("%s", GetSceneViewportToolTooltip(toolMode)); } } return result; } bool ShouldBeginSceneViewportNavigationDrag( bool hasInteractiveViewport, bool hovered, bool activeDrag, bool otherDrag, bool gizmoActive, ImGuiMouseButton button) { return hasInteractiveViewport && hovered && !activeDrag && !otherDrag && !gizmoActive && ImGui::IsMouseClicked(button); } } // namespace SceneViewPanel::SceneViewPanel() : Panel("Scene") {} void SceneViewPanel::Render() { ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); UI::PanelWindowScope panel(m_name.c_str()); ImGui::PopStyleVar(); if (!panel.IsOpen()) { return; } RenderSceneViewportTopBar(m_pivotMode, m_transformSpaceMode); const ViewportPanelContentResult content = RenderViewportPanelContent(*m_context, EditorViewportKind::Scene); if (IViewportHostService* viewportHostService = m_context->GetViewportHostService()) { const ImGuiIO& io = ImGui::GetIO(); const bool hasInteractiveViewport = content.hasViewportArea && content.frame.hasTexture; const SceneViewportToolOverlayResult toolOverlay = RenderSceneViewportToolOverlay(content, m_toolMode); const bool viewportContentHovered = content.hovered && !toolOverlay.hovered; if (toolOverlay.clicked) { if (m_moveGizmo.IsActive()) { m_moveGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_rotateGizmo.IsActive()) { m_rotateGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_scaleGizmo.IsActive()) { m_scaleGizmo.CancelDrag(&m_context->GetUndoManager()); } m_toolMode = toolOverlay.clickedTool; } const bool allowToolShortcut = !io.WantTextInput && !m_lookDragging && !m_panDragging; if (allowToolShortcut) { if (ImGui::IsKeyPressed(ImGuiKey_Q, false)) { if (m_moveGizmo.IsActive()) { m_moveGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_rotateGizmo.IsActive()) { m_rotateGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_scaleGizmo.IsActive()) { m_scaleGizmo.CancelDrag(&m_context->GetUndoManager()); } m_toolMode = SceneViewportToolMode::ViewMove; } else if (ImGui::IsKeyPressed(ImGuiKey_W, false)) { if (m_rotateGizmo.IsActive()) { m_rotateGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_scaleGizmo.IsActive()) { m_scaleGizmo.CancelDrag(&m_context->GetUndoManager()); } m_toolMode = SceneViewportToolMode::Move; } else if (ImGui::IsKeyPressed(ImGuiKey_E, false)) { if (m_moveGizmo.IsActive()) { m_moveGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_scaleGizmo.IsActive()) { m_scaleGizmo.CancelDrag(&m_context->GetUndoManager()); } m_toolMode = SceneViewportToolMode::Rotate; } else if (ImGui::IsKeyPressed(ImGuiKey_R, false)) { if (m_moveGizmo.IsActive()) { m_moveGizmo.CancelDrag(&m_context->GetUndoManager()); } if (m_rotateGizmo.IsActive()) { m_rotateGizmo.CancelDrag(&m_context->GetUndoManager()); } m_toolMode = SceneViewportToolMode::Scale; } } 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 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 = {}; SceneViewportTransformGizmoFrameState gizmoFrameState = {}; SceneViewportOverlayFrameData emptySceneOverlayFrameData = {}; SceneViewportActiveGizmoKind activeGizmoKind = SceneViewportActiveGizmoKind::None; if (hasInteractiveViewport) { overlay = viewportHostService->GetSceneViewOverlayData(); gizmoFrameState = RefreshSceneViewportTransformGizmos( *m_context, overlay, viewportSize, localMousePosition, useCenterPivot, localSpace, usingTransformTool, showingMoveGizmo, m_moveGizmo, showingRotateGizmo, m_rotateGizmo, showingScaleGizmo, m_scaleGizmo); activeGizmoKind = gizmoFrameState.activeGizmoKind; } else { CancelSceneViewportTransformGizmoDrags(*m_context, m_moveGizmo, m_rotateGizmo, m_scaleGizmo); } const SceneViewportTransformGizmoHandleBuildInputs interactionGizmoInputs = hasInteractiveViewport ? BuildSceneViewportTransformGizmoHandleBuildInputs( showingMoveGizmo, m_moveGizmo, gizmoFrameState.moveContext, showingRotateGizmo, m_rotateGizmo, gizmoFrameState.rotateContext, showingScaleGizmo, m_scaleGizmo, gizmoFrameState.scaleContext) : SceneViewportTransformGizmoHandleBuildInputs{}; const SceneViewportTransformGizmoOverlayState interactionGizmoOverlayState = BuildSceneViewportTransformGizmoOverlayState(interactionGizmoInputs); viewportHostService->SetSceneViewTransformGizmoOverlayState(interactionGizmoOverlayState); const SceneViewportOverlayFrameData& interactionOverlayFrameData = hasInteractiveViewport ? viewportHostService->GetSceneViewEditorOverlayFrameData(*m_context) : emptySceneOverlayFrameData; const bool moveGizmoActive = showingMoveGizmo && m_moveGizmo.IsActive(); const bool rotateGizmoActive = showingRotateGizmo && m_rotateGizmo.IsActive(); const bool scaleGizmoActive = showingScaleGizmo && m_scaleGizmo.IsActive(); if (moveGizmoActive) { activeGizmoKind = SceneViewportActiveGizmoKind::Move; } else if (rotateGizmoActive) { activeGizmoKind = SceneViewportActiveGizmoKind::Rotate; } else if (scaleGizmoActive) { activeGizmoKind = SceneViewportActiveGizmoKind::Scale; } else { activeGizmoKind = SceneViewportActiveGizmoKind::None; } const bool gizmoActive = activeGizmoKind != SceneViewportActiveGizmoKind::None; const SceneViewportHudOverlayData interactionHudOverlay = BuildSceneViewportHudOverlayData(overlay); SceneViewportInteractionResult hoveredInteraction = {}; const bool canResolveViewportInteraction = hasInteractiveViewport && viewportContentHovered && !usingViewMoveTool && !m_lookDragging && !m_panDragging && !toolOverlay.hovered && !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); } if (!gizmoActive) { if (showingMoveGizmo) { m_moveGizmo.SetHoveredHandle( hoveredInteraction.kind == SceneViewportInteractionKind::MoveGizmo ? hoveredInteraction.moveAxis : SceneViewportGizmoAxis::None, hoveredInteraction.kind == SceneViewportInteractionKind::MoveGizmo ? hoveredInteraction.movePlane : SceneViewportGizmoPlane::None); } if (showingRotateGizmo) { m_rotateGizmo.SetHoveredHandle( hoveredInteraction.kind == SceneViewportInteractionKind::RotateGizmo ? hoveredInteraction.rotateAxis : SceneViewportRotateGizmoAxis::None); } if (showingScaleGizmo) { m_scaleGizmo.SetHoveredHandle( hoveredInteraction.kind == SceneViewportInteractionKind::ScaleGizmo ? hoveredInteraction.scaleHandle : SceneViewportScaleGizmoHandle::None); } } const SceneViewportActiveGizmoKind hoveredGizmoKind = ToActiveGizmoKind(hoveredInteraction.kind); const bool gizmoHovering = hoveredGizmoKind != SceneViewportActiveGizmoKind::None; const SceneViewportOrientationAxis orientationAxisHit = hoveredInteraction.kind == SceneViewportInteractionKind::OrientationGizmo ? hoveredInteraction.orientationAxis : SceneViewportOrientationAxis::None; const uint64_t clickedSceneIconEntity = hoveredInteraction.kind == SceneViewportInteractionKind::SceneIcon ? hoveredInteraction.entityId : 0; const bool beginTransformGizmo = hasInteractiveViewport && content.clickedLeft && gizmoHovering; const bool orientationGizmoClick = hasInteractiveViewport && content.clickedLeft && orientationAxisHit != SceneViewportOrientationAxis::None; const bool sceneIconClick = hasInteractiveViewport && content.clickedLeft && clickedSceneIconEntity != 0; const bool selectClick = hasInteractiveViewport && content.clickedLeft && canResolveViewportInteraction && !hoveredInteraction.HasHit(); const bool beginLeftPanDrag = usingViewMoveTool ? ShouldBeginSceneViewportNavigationDrag( hasInteractiveViewport, viewportContentHovered, m_panDragging, m_lookDragging, gizmoActive, ImGuiMouseButton_Left) : false; const bool beginLookDrag = ShouldBeginSceneViewportNavigationDrag( hasInteractiveViewport, viewportContentHovered, m_lookDragging, m_panDragging, gizmoActive, ImGuiMouseButton_Right); const bool beginMiddlePanDrag = ShouldBeginSceneViewportNavigationDrag( hasInteractiveViewport, viewportContentHovered, m_panDragging, m_lookDragging, gizmoActive, ImGuiMouseButton_Middle); const bool beginPanDrag = beginLeftPanDrag || beginMiddlePanDrag; if (toolOverlay.clicked || beginTransformGizmo || orientationGizmoClick || sceneIconClick || selectClick || beginLookDrag || beginPanDrag) { ImGui::SetWindowFocus(); } if (beginTransformGizmo) { if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Scale) { m_scaleGizmo.TryBeginDrag(gizmoFrameState.scaleContext, m_context->GetUndoManager()); } else if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Move) { m_moveGizmo.TryBeginDrag(gizmoFrameState.moveContext, m_context->GetUndoManager()); } else if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Rotate) { m_rotateGizmo.TryBeginDrag(gizmoFrameState.rotateContext, m_context->GetUndoManager()); } } if (orientationGizmoClick) { viewportHostService->AlignSceneViewToOrientationAxis(orientationAxisHit); } if (sceneIconClick) { m_context->GetSelectionManager().SetSelectedEntity(clickedSceneIconEntity); } else if (selectClick) { const uint64_t selectedEntity = viewportHostService->PickSceneViewEntity( *m_context, content.availableSize, ImVec2(localMousePosition.x, localMousePosition.y)); if (selectedEntity != 0) { m_context->GetSelectionManager().SetSelectedEntity(selectedEntity); } else { m_context->GetSelectionManager().ClearSelection(); } } if (gizmoActive) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) { if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) { m_moveGizmo.UpdateDrag(gizmoFrameState.moveContext); } else if (activeGizmoKind == SceneViewportActiveGizmoKind::Rotate) { m_rotateGizmo.UpdateDrag(gizmoFrameState.rotateContext); } else if (activeGizmoKind == SceneViewportActiveGizmoKind::Scale) { m_scaleGizmo.UpdateDrag(gizmoFrameState.scaleContext); } } else { if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) { m_moveGizmo.EndDrag(m_context->GetUndoManager()); } else if (activeGizmoKind == SceneViewportActiveGizmoKind::Rotate) { m_rotateGizmo.EndDrag(m_context->GetUndoManager()); } else if (activeGizmoKind == SceneViewportActiveGizmoKind::Scale) { m_scaleGizmo.EndDrag(m_context->GetUndoManager()); } } } if (beginLookDrag) { m_lookDragging = true; m_panDragging = false; m_loggedLookDelta = false; m_loggedPanDelta = false; } if (beginPanDrag) { m_panDragging = true; m_lookDragging = false; m_panDragButton = beginLeftPanDrag ? ImGuiMouseButton_Left : ImGuiMouseButton_Middle; m_loggedPanDelta = false; m_loggedLookDelta = false; } if (m_lookDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) { m_lookDragging = false; m_loggedLookDelta = false; } if (m_panDragging && !ImGui::IsMouseDown(m_panDragButton)) { m_panDragging = false; m_panDragButton = ImGuiMouseButton_Middle; m_loggedPanDelta = false; } if (m_lookDragging || m_panDragging || m_moveGizmo.IsActive() || m_rotateGizmo.IsActive() || m_scaleGizmo.IsActive()) { ImGui::SetNextFrameWantCaptureMouse(true); } if (m_lookDragging) { ImGui::SetNextFrameWantCaptureKeyboard(true); } SceneViewportInput input = {}; input.viewportSize = content.availableSize; input.deltaTime = io.DeltaTime; input.hovered = viewportContentHovered; input.focused = content.focused || m_lookDragging || m_panDragging; input.mouseWheel = (viewportContentHovered && !m_lookDragging) ? io.MouseWheel : 0.0f; input.flySpeedDelta = (viewportContentHovered && m_lookDragging) ? io.MouseWheel : 0.0f; input.looking = m_lookDragging; input.orbiting = false; input.panning = m_panDragging; input.fastMove = io.KeyShift; input.focusSelectionRequested = input.focused && !io.WantTextInput && ImGui::IsKeyPressed(ImGuiKey_F, false); if (m_lookDragging && !io.WantTextInput) { input.moveForward = (ImGui::IsKeyDown(ImGuiKey_W) ? 1.0f : 0.0f) - (ImGui::IsKeyDown(ImGuiKey_S) ? 1.0f : 0.0f); input.moveRight = (ImGui::IsKeyDown(ImGuiKey_D) ? 1.0f : 0.0f) - (ImGui::IsKeyDown(ImGuiKey_A) ? 1.0f : 0.0f); input.moveUp = (ImGui::IsKeyDown(ImGuiKey_E) ? 1.0f : 0.0f) - (ImGui::IsKeyDown(ImGuiKey_Q) ? 1.0f : 0.0f); } if (m_lookDragging || m_panDragging) { if (m_lookDragging) { input.mouseDelta = io.MouseDelta; if (!m_loggedLookDelta && (input.mouseDelta.x != 0.0f || input.mouseDelta.y != 0.0f)) { m_loggedLookDelta = true; } } if (m_panDragging) { input.mouseDelta = io.MouseDelta; if (!m_loggedPanDelta && (input.mouseDelta.x != 0.0f || input.mouseDelta.y != 0.0f)) { m_loggedPanDelta = true; } } } viewportHostService->UpdateSceneViewInput(*m_context, input); if (content.hasViewportArea && content.frame.hasTexture) { overlay = viewportHostService->GetSceneViewOverlayData(); const SceneViewportTransformGizmoFrameState drawGizmoFrameState = RefreshSceneViewportTransformGizmos( *m_context, overlay, viewportSize, localMousePosition, useCenterPivot, localSpace, usingTransformTool, showingMoveGizmo, m_moveGizmo, showingRotateGizmo, m_rotateGizmo, showingScaleGizmo, m_scaleGizmo); viewportHostService->SetSceneViewTransformGizmoOverlayState( BuildSceneViewportTransformGizmoOverlayState( BuildSceneViewportTransformGizmoHandleBuildInputs( showingMoveGizmo, m_moveGizmo, drawGizmoFrameState.moveContext, showingRotateGizmo, m_rotateGizmo, drawGizmoFrameState.rotateContext, showingScaleGizmo, m_scaleGizmo, drawGizmoFrameState.scaleContext))); DrawSceneViewportHudOverlay( ImGui::GetWindowDrawList(), BuildSceneViewportHudOverlayData(overlay), content.itemMin, content.itemMax); } } Actions::ObserveInactiveActionRoute(*m_context); } } }