Files
XCEngine/editor/src/panels/SceneViewPanel.cpp

214 lines
9.6 KiB
C++

#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 <imgui.h>
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);
}
}
}