#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 "BsCamera.h" #include "BsEditorApplication.h" #include "BsEditorWidget.h" #include "BsEditorWindowBase.h" #include "BsRenderWindow.h" #include "BsCursor.h" #include "BsSelectionRenderer.h" #include "BsDebug.h" using namespace std::placeholders; namespace BansheeEngine { SceneViewHandler::SceneViewHandler(EditorWidgetBase* parentWidget, const SPtr& camera) :mCamera(camera), mSceneGrid(nullptr), mParentWidget(parentWidget) { mSelectionRenderer = bs_new(); mSceneGrid = bs_new(mCamera); mSceneGrid->setSettings(gEditorApplication().getEditorSettings()); HandleManager::instance().setSettings(gEditorApplication().getEditorSettings()); } SceneViewHandler::~SceneViewHandler() { bs_delete(mSceneGrid); bs_delete(mSelectionRenderer); 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::updateSelection() { // Call this after handle update to ensure its drawn at the right place mSelectionRenderer->update(mCamera); } 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(); } Vector2I SceneViewHandler::wrapCursorToWindow() { if (mParentWidget == nullptr) return Vector2I(); 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; } }