#include "BsSceneViewHandler.h" #include "BsRendererManager.h" #include "BsRenderer.h" #include "BsGizmoManager.h" #include "BsHandleManager.h" #include "BsSceneGrid.h" #include "BsSelection.h" #include "BsScenePicking.h" #include "BsCameraHandler.h" #include "BsEditorApplication.h" #include "BsEditorWidget.h" #include "BsEditorWindowBase.h" #include "BsRenderWindow.h" #include "BsCursor.h" #include "BsDebug.h" using namespace std::placeholders; namespace BansheeEngine { SceneViewHandler::SceneViewHandler(EditorWidgetBase* parentWidget, const SPtr& camera) :mCamera(camera), mSceneGrid(nullptr), mParentWidget(parentWidget) { mRenderCallback = RendererManager::instance().getActive()->onRenderViewport.connect(std::bind(&SceneViewHandler::render, this, _1, _2)); mSceneGrid = bs_new(); mSceneGrid->setSettings(gEditorApplication().getEditorSettings()); HandleManager::instance().setSettings(gEditorApplication().getEditorSettings()); } SceneViewHandler::~SceneViewHandler() { bs_delete(mSceneGrid); mRenderCallback.disconnect(); if (GizmoManager::isStarted()) // If not active, we don't care GizmoManager::instance().clearRenderData(); } void SceneViewHandler::update() { GizmoManager::instance().update(mCamera); mSceneGrid->update(); } void SceneViewHandler::updateHandle(const Vector2I& position, const Vector2I& delta) { // If mouse wrapped around last frame then we need to compensate for the jump amount Vector2I realDelta = delta - mMouseDeltaCompensate; mMouseDeltaCompensate = Vector2I::ZERO; if (HandleManager::instance().isHandleActive()) mMouseDeltaCompensate = wrapCursorToWindow(); HandleManager::instance().update(mCamera, position, realDelta); } void SceneViewHandler::trySelectHandle(const Vector2I& position) { HandleManager::instance().trySelect(mCamera, position); } bool SceneViewHandler::isHandleActive() const { return HandleManager::instance().isHandleActive(); } void SceneViewHandler::clearHandleSelection() { HandleManager::instance().clearSelection(); } void SceneViewHandler::pickObject(const Vector2I& position, bool additive) { // TODO - Handle multi-selection (i.e. selection rectangle when dragging) HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(mCamera, position, Vector2I(1, 1)); if (pickedObject) { if (additive) // Append to existing selection { Vector selectedSOs = Selection::instance().getSceneObjects(); auto iterFind = std::find_if(selectedSOs.begin(), selectedSOs.end(), [&](const HSceneObject& obj) { return obj == pickedObject; } ); if (iterFind != selectedSOs.end()) selectedSOs.push_back(pickedObject); Selection::instance().setSceneObjects(selectedSOs); } else { Vector selectedSOs = { pickedObject }; Selection::instance().setSceneObjects(selectedSOs); } } else Selection::instance().clearSceneSelection(); } void SceneViewHandler::render(const Viewport* viewport, DrawList& drawList) { if (mCamera == nullptr) return; if (mCamera->getViewport().get() != viewport) return; mSceneGrid->render(mCamera, drawList); } Vector2I SceneViewHandler::wrapCursorToWindow() { RenderWindowPtr parentWindow = mParentWidget->getParentWindow()->getRenderWindow(); Vector2I windowPos = parentWindow->screenToWindowPos(Cursor::instance().getScreenPosition()); const RenderWindowProperties& rwProps = parentWindow->getProperties(); INT32 maxWidth = std::max(0, (INT32)rwProps.getWidth() - 1); INT32 maxHeight = std::max(0, (INT32)rwProps.getHeight() - 1); Vector2I offset; if (windowPos.x <= 0) offset.x = maxWidth; else if (windowPos.x >= maxWidth) offset.x = -maxWidth; if (windowPos.y <= 0) offset.y = maxHeight; else if (windowPos.y >= maxHeight) offset.y = -maxHeight; windowPos += offset; Vector2I wrappedScreenPos = parentWindow->windowToScreenPos(windowPos); Cursor::instance().setScreenPosition(wrappedScreenPos); return offset; } }