#include "Actions/ActionRouting.h" #include "Core/IEditorContext.h" #include "Core/ISceneManager.h" #include "Core/ISelectionManager.h" #include "SceneViewPanel.h" #include "Viewport/SceneViewportChrome.h" #include "Viewport/SceneViewportEditorOverlayData.h" #include "Viewport/SceneViewportInteractionFrame.h" #include "Viewport/SceneViewportInteractionActions.h" #include "Viewport/SceneViewportInteractionResolver.h" #include "Viewport/SceneViewportMath.h" #include "Viewport/SceneViewportNavigation.h" #include "Viewport/SceneViewportTransformGizmoCoordinator.h" #include "ViewportPanelContent.h" #include namespace XCEngine { namespace Editor { 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; SceneViewportToolShortcutRequest toolShortcutRequest = {}; toolShortcutRequest.wantTextInput = io.WantTextInput; toolShortcutRequest.lookDragging = m_navigationState.lookDragging; toolShortcutRequest.panDragging = m_navigationState.panDragging; toolShortcutRequest.pressedViewMove = ImGui::IsKeyPressed(ImGuiKey_Q, false); toolShortcutRequest.pressedMove = ImGui::IsKeyPressed(ImGuiKey_W, false); toolShortcutRequest.pressedRotate = ImGui::IsKeyPressed(ImGuiKey_E, false); toolShortcutRequest.pressedScale = ImGui::IsKeyPressed(ImGuiKey_R, false); const SceneViewportToolShortcutAction toolShortcutAction = BuildSceneViewportToolShortcutAction(toolShortcutRequest); const SceneViewportToolCommand toolCommand = BuildSceneViewportToolCommand(toolOverlay, toolShortcutAction); ExecuteSceneViewportToolCommand( toolCommand, m_context->GetUndoManager(), m_moveGizmo, m_rotateGizmo, m_scaleGizmo, m_toolMode); const SceneViewportToolState toolState = BuildSceneViewportToolState( m_toolMode, m_pivotMode, m_transformSpaceMode); const SceneViewportFrameGeometry frameGeometry = BuildSceneViewportFrameGeometry( content.availableSize, content.itemMin, io.MousePos); SceneViewportOverlayFrameData emptySceneOverlayFrameData = {}; const SceneViewportInteractionFrameState interactionFrameState = BuildSceneViewportInteractionFrameState( *m_context, *viewportHostService, hasInteractiveViewport, frameGeometry, toolState.gizmoFrameOptions, m_moveGizmo, m_rotateGizmo, m_scaleGizmo, emptySceneOverlayFrameData); SceneViewportInteractionResult hoveredInteraction = {}; const bool canResolveViewportInteraction = CanResolveSceneViewportInteraction( hasInteractiveViewport, viewportContentHovered, toolState.usingViewMoveTool, m_navigationState, interactionFrameState.gizmoActive); if (canResolveViewportInteraction) { hoveredInteraction = ResolveSceneViewportInteraction( BuildSceneViewportInteractionResolveRequest( interactionFrameState, frameGeometry, content.itemMin, content.itemMax, io.MousePos)); } ApplySceneViewportHoveredHandleState( BuildSceneViewportHoveredHandleState(hoveredInteraction), interactionFrameState.gizmoActive, toolState.showingMoveGizmo, m_moveGizmo, toolState.showingRotateGizmo, m_rotateGizmo, toolState.showingScaleGizmo, m_scaleGizmo); const SceneViewportInteractionActions interactionActions = BuildSceneViewportInteractionActions( hoveredInteraction, hasInteractiveViewport, content.clickedLeft, canResolveViewportInteraction); SceneViewportNavigationRequest navigationRequest = {}; navigationRequest.state = m_navigationState; navigationRequest.hasInteractiveViewport = hasInteractiveViewport; navigationRequest.viewportHovered = viewportContentHovered; navigationRequest.usingViewMoveTool = toolState.usingViewMoveTool; navigationRequest.gizmoActive = interactionFrameState.gizmoActive; navigationRequest.clickedLeft = content.clickedLeft; navigationRequest.clickedRight = content.clickedRight; navigationRequest.clickedMiddle = content.clickedMiddle; navigationRequest.leftMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); navigationRequest.rightMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); navigationRequest.middleMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); const SceneViewportNavigationUpdate navigationUpdate = UpdateSceneViewportNavigationState(navigationRequest); m_navigationState = navigationUpdate.state; if (ShouldFocusSceneViewportAfterInteraction( toolCommand.HasAction(), interactionActions, navigationUpdate)) { ImGui::SetWindowFocus(); } ExecuteSceneViewportTransformGizmoLifecycleCommand( BuildBeginSceneViewportTransformGizmoLifecycleCommand(interactionActions), m_context->GetUndoManager(), interactionFrameState.gizmoFrameState, m_moveGizmo, m_rotateGizmo, m_scaleGizmo); DispatchSceneViewportInteractionActions( interactionActions, *m_context, *viewportHostService, ::XCEngine::UI::UISize(content.availableSize.x, content.availableSize.y), frameGeometry.localMousePosition); ExecuteSceneViewportTransformGizmoLifecycleCommand( BuildFrameSceneViewportTransformGizmoLifecycleCommand( interactionFrameState.activeGizmoKind, ImGui::IsMouseDown(ImGuiMouseButton_Left)), m_context->GetUndoManager(), interactionFrameState.gizmoFrameState, m_moveGizmo, m_rotateGizmo, m_scaleGizmo); const SceneViewportCaptureFlags captureFlags = BuildSceneViewportCaptureFlags( SceneViewportCaptureRequest{ m_navigationState, m_moveGizmo.IsActive(), m_rotateGizmo.IsActive(), m_scaleGizmo.IsActive()}); if (captureFlags.captureMouse) { ImGui::SetNextFrameWantCaptureMouse(true); } if (captureFlags.captureKeyboard) { ImGui::SetNextFrameWantCaptureKeyboard(true); } SceneViewportInputBuildRequest inputRequest = {}; inputRequest.state = m_navigationState; inputRequest.viewportSize = ::XCEngine::UI::UISize(content.availableSize.x, content.availableSize.y); inputRequest.mouseDelta = ::XCEngine::UI::UIPoint(io.MouseDelta.x, io.MouseDelta.y); inputRequest.mouseWheel = io.MouseWheel; inputRequest.deltaTime = io.DeltaTime; inputRequest.viewportHovered = viewportContentHovered; inputRequest.viewportFocused = content.focused; inputRequest.wantTextInput = io.WantTextInput; inputRequest.fastMove = io.KeyShift; inputRequest.focusSelectionKeyPressed = ImGui::IsKeyPressed(ImGuiKey_F, false); inputRequest.moveForwardKeyDown = ImGui::IsKeyDown(ImGuiKey_W); inputRequest.moveBackwardKeyDown = ImGui::IsKeyDown(ImGuiKey_S); inputRequest.moveRightKeyDown = ImGui::IsKeyDown(ImGuiKey_D); inputRequest.moveLeftKeyDown = ImGui::IsKeyDown(ImGuiKey_A); inputRequest.moveUpKeyDown = ImGui::IsKeyDown(ImGuiKey_E); inputRequest.moveDownKeyDown = ImGui::IsKeyDown(ImGuiKey_Q); const SceneViewportInput input = BuildSceneViewportInput(inputRequest); viewportHostService->UpdateSceneViewInput(*m_context, input); SceneViewportPresentationRequest presentationRequest = {}; presentationRequest.context = m_context; presentationRequest.viewportHostService = viewportHostService; presentationRequest.hasInteractiveViewport = hasInteractiveViewport; presentationRequest.geometry = frameGeometry; presentationRequest.gizmoFrameOptions = toolState.gizmoFrameOptions; presentationRequest.moveGizmo = &m_moveGizmo; presentationRequest.rotateGizmo = &m_rotateGizmo; presentationRequest.scaleGizmo = &m_scaleGizmo; presentationRequest.drawList = ImGui::GetWindowDrawList(); presentationRequest.viewportMin = content.itemMin; presentationRequest.viewportMax = content.itemMax; RefreshAndDrawSceneViewportPresentation(presentationRequest); } Actions::ObserveInactiveActionRoute(*m_context); } } }