#include "BsSceneCameraController.h" #include "BsVirtualInput.h" #include "BsVector3.h" #include "BsTime.h" #include "BsMath.h" #include "BsSceneObject.h" #include "BsCamera.h" #include "BsPlatform.h" #include "BsEditorApplication.h" #include "BsCursor.h" #include "BsDebug.h" namespace BansheeEngine { const String SceneCameraController::MOVE_FORWARD_BTN = "SceneForward"; const String SceneCameraController::MOVE_LEFT_BTN = "SceneLeft"; const String SceneCameraController::MOVE_RIGHT_BTN = "SceneRight"; const String SceneCameraController::MOVE_BACKWARD_BTN = "SceneBackward"; const String SceneCameraController::FAST_MOVE_BTN = "SceneFastMove"; const String SceneCameraController::ROTATE_BTN = "SceneRotate"; const String SceneCameraController::HORIZONTAL_AXIS = "SceneHorizontal"; const String SceneCameraController::VERTICAL_AXIS = "SceneVertical"; const float SceneCameraController::START_SPEED = 4.0f; const float SceneCameraController::TOP_SPEED = 12.0f; const float SceneCameraController::ACCELERATION = 1.0f; const float SceneCameraController::FAST_MODE_MULTIPLIER = 2.0f; const float SceneCameraController::ROTATION_SPEED = 360.0f; // Degrees/second Degree wrapAngle(Degree angle) { if (angle.valueDegrees() < -360.0f) angle += Degree(360.0f); if (angle.valueDegrees() > 360.0f) angle -= Degree(360.0f); return angle; } SceneCameraController::SceneCameraController(const HSceneObject& parent) :Component(parent), mPitch(0.0f), mYaw(0.0f), mLastButtonState(false) { setName("SceneCameraController"); mMoveForward = VirtualButton(MOVE_FORWARD_BTN); mMoveLeft = VirtualButton(MOVE_LEFT_BTN); mMoveRight = VirtualButton(MOVE_RIGHT_BTN); mMoveBackward = VirtualButton(MOVE_BACKWARD_BTN); mFastMove = VirtualButton(FAST_MOVE_BTN); mRotate = VirtualButton(ROTATE_BTN); mHorizontal = VirtualAxis(HORIZONTAL_AXIS); mVertical = VirtualAxis(VERTICAL_AXIS); } void SceneCameraController::update() { if (!gEditorApplication().isSceneViewFocused()) return; bool goingForward = gVirtualInput().isButtonHeld(mMoveForward); bool goingBack = gVirtualInput().isButtonHeld(mMoveBackward); bool goingLeft = gVirtualInput().isButtonHeld(mMoveLeft); bool goingRight = gVirtualInput().isButtonHeld(mMoveRight); bool fastMove = gVirtualInput().isButtonHeld(mFastMove); bool camRotating = gVirtualInput().isButtonHeld(mRotate); if (camRotating != mLastButtonState) { if (camRotating) Cursor::instance().hide(); else Cursor::instance().show(); mLastButtonState = camRotating; } float frameDelta = gTime().getFrameDelta(); if (camRotating) { mYaw += Degree(gVirtualInput().getAxisValue(mHorizontal) * ROTATION_SPEED * frameDelta); mPitch += Degree(gVirtualInput().getAxisValue(mVertical) * ROTATION_SPEED * frameDelta); mYaw = wrapAngle(mYaw); mPitch = wrapAngle(mPitch); Quaternion yRot; yRot.fromAxisAngle(Vector3::UNIT_Y, Radian(mYaw)); Quaternion xRot; xRot.fromAxisAngle(Vector3::UNIT_X, Radian(mPitch)); Quaternion camRot = yRot * xRot; camRot.normalize(); SO()->setRotation(camRot); } Vector3 direction = Vector3::ZERO; if (goingForward) direction += SO()->getForward(); if (goingBack) direction -= SO()->getForward(); if (goingRight) direction += SO()->getRight(); if (goingLeft) direction -= SO()->getRight(); if (direction.squaredLength() != 0) { direction.normalize(); float multiplier = 1.0f; if (fastMove) multiplier = FAST_MODE_MULTIPLIER; mCurrentSpeed = Math::clamp(mCurrentSpeed + ACCELERATION * frameDelta, START_SPEED, TOP_SPEED); mCurrentSpeed *= multiplier; } else { mCurrentSpeed = 0.0f; } float tooSmall = std::numeric_limits::epsilon(); if (mCurrentSpeed > tooSmall) { Vector3 velocity = direction * mCurrentSpeed; SO()->move(velocity * frameDelta); } } }