#include "Actions/ActionRouting.h" #include "Core/IEditorContext.h" #include "Core/ISelectionManager.h" #include "SceneViewPanel.h" #include "Viewport/SceneViewportOverlayRenderer.h" #include "ViewportPanelContent.h" #include "UI/UI.h" #include namespace XCEngine { namespace Editor { SceneViewPanel::SceneViewPanel() : Panel("Scene") {} void SceneViewPanel::Render() { UI::PanelWindowScope panel(m_name.c_str()); if (!panel.IsOpen()) { return; } const ViewportPanelContentResult content = RenderViewportPanelContent(*m_context, EditorViewportKind::Scene); if (IViewportHostService* viewportHostService = m_context->GetViewportHostService()) { const ImGuiIO& io = ImGui::GetIO(); const bool selectClick = content.hovered && content.frame.hasTexture && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !m_lookDragging && !m_panDragging; const bool beginLookDrag = content.hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right); const bool beginPanDrag = content.hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Middle); if (selectClick || beginLookDrag || beginPanDrag) { ImGui::SetWindowFocus(); } if (selectClick) { const ImVec2 localMousePosition( io.MousePos.x - content.itemMin.x, io.MousePos.y - content.itemMin.y); const uint64_t selectedEntity = viewportHostService->PickSceneViewEntity( *m_context, content.availableSize, localMousePosition); if (selectedEntity != 0) { m_context->GetSelectionManager().SetSelectedEntity(selectedEntity); } else { m_context->GetSelectionManager().ClearSelection(); } } if (beginLookDrag) { m_lookDragging = true; m_lastLookDragDelta = ImVec2(0.0f, 0.0f); } if (beginPanDrag) { m_panDragging = true; m_lastPanDragDelta = ImVec2(0.0f, 0.0f); } if (m_lookDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) { m_lookDragging = false; m_lastLookDragDelta = ImVec2(0.0f, 0.0f); } if (m_panDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Middle)) { m_panDragging = false; m_lastPanDragDelta = ImVec2(0.0f, 0.0f); } if (m_lookDragging || m_panDragging) { ImGui::SetNextFrameWantCaptureMouse(true); } if (m_lookDragging) { ImGui::SetNextFrameWantCaptureKeyboard(true); } SceneViewportInput input = {}; input.viewportSize = content.availableSize; input.deltaTime = io.DeltaTime; input.hovered = content.hovered; input.focused = content.focused || m_lookDragging || m_panDragging; input.mouseWheel = (content.hovered && !m_lookDragging) ? io.MouseWheel : 0.0f; input.flySpeedDelta = (content.hovered && 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) { const ImVec2 lookDragDelta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right, 0.0f); input.mouseDelta.x += lookDragDelta.x - m_lastLookDragDelta.x; input.mouseDelta.y += lookDragDelta.y - m_lastLookDragDelta.y; m_lastLookDragDelta = lookDragDelta; } else { m_lastLookDragDelta = ImVec2(0.0f, 0.0f); } if (m_panDragging) { const ImVec2 panDragDelta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Middle, 0.0f); input.mouseDelta.x += panDragDelta.x - m_lastPanDragDelta.x; input.mouseDelta.y += panDragDelta.y - m_lastPanDragDelta.y; m_lastPanDragDelta = panDragDelta; } else { m_lastPanDragDelta = ImVec2(0.0f, 0.0f); } } viewportHostService->UpdateSceneViewInput(*m_context, input); if (content.hasViewportArea && content.frame.hasTexture) { const SceneViewportOverlayData overlay = viewportHostService->GetSceneViewOverlayData(); DrawSceneViewportOverlay( ImGui::GetWindowDrawList(), overlay, content.itemMin, content.itemMax, content.availableSize); } } Actions::ObserveInactiveActionRoute(*m_context); } } }