using UnityEngine;
using UnityInput = UnityEngine.Input;
namespace Core.Input
{
///
/// Base control scheme for desktop devices, which performs CameraRig motion
///
public class KeyboardMouseInput : CameraInputScheme
{
///
/// Pan threshold (how near to the edge before we pan. Also the denominator for RMB pan)
///
public float screenPanThreshold = 40f;
///
/// Pan speed for edge panning
///
public float mouseEdgePanSpeed = 30f;
///
/// Pan speed for RMB panning
///
public float mouseRmbPanSpeed = 15f;
///
/// Gets whether the scheme should be activated or not
///
public override bool shouldActivate
{
get
{
if (UnityInput.touchCount > 0)
{
return false;
}
bool anyKey = UnityInput.anyKey;
bool buttonPressedThisFrame = InputController.instance.mouseButtonPressedThisFrame;
bool movedMouseThisFrame = InputController.instance.mouseMovedOnThisFrame;
return (anyKey || buttonPressedThisFrame || movedMouseThisFrame);
}
}
///
/// This is the default scheme on desktop devices
///
public override bool isDefault
{
get
{
#if UNITY_STANDALONE || UNITY_EDITOR
return true;
#else
return false;
#endif
}
}
///
/// Register input events
///
protected virtual void OnEnable()
{
if (!InputController.instanceExists)
{
Debug.LogError("[UI] Keyboard and Mouse UI requires InputController");
return;
}
InputController controller = InputController.instance;
controller.spunWheel += OnWheel;
controller.dragged += OnDrag;
controller.pressed += OnPress;
}
///
/// Deregister input events
///
protected virtual void OnDisable()
{
if (!InputController.instanceExists)
{
return;
}
InputController controller = InputController.instance;
controller.pressed -= OnPress;
controller.dragged -= OnDrag;
controller.spunWheel -= OnWheel;
}
///
/// Handle camera panning behaviour
///
protected virtual void Update()
{
if (cameraRig != null)
{
DoScreenEdgePan();
DoKeyboardPan();
DecayZoom();
}
}
///
/// Called when we drag
///
protected virtual void OnDrag(PointerActionInfo pointer)
{
if (cameraRig != null)
{
DoRightMouseDragPan(pointer);
}
}
///
/// Called on mouse wheel input
///
protected virtual void OnWheel(WheelInfo wheel)
{
if (cameraRig != null)
{
DoWheelZoom(wheel);
}
}
///
/// Called on input press, for MMB panning
///
protected virtual void OnPress(PointerActionInfo pointer)
{
if (cameraRig != null)
{
DoMiddleMousePan(pointer);
}
}
///
/// Perform mouse screen-edge panning
///
protected void DoScreenEdgePan()
{
Vector2 mousePos = UnityInput.mousePosition;
bool mouseInside = (mousePos.x >= 0) &&
(mousePos.x < Screen.width) &&
(mousePos.y >= 0) &&
(mousePos.y < Screen.height);
// Mouse can be outside of our window
if (mouseInside)
{
PanWithScreenCoordinates(mousePos, screenPanThreshold, mouseEdgePanSpeed);
}
}
///
/// Perform keyboard panning
///
protected void DoKeyboardPan()
{
// Calculate zoom ratio
float zoomRatio = GetPanSpeedForZoomLevel();
// Left
if (UnityInput.GetKey(KeyCode.LeftArrow) || UnityInput.GetKey(KeyCode.A))
{
cameraRig.PanCamera(Vector3.left * Time.deltaTime * mouseEdgePanSpeed * zoomRatio);
cameraRig.StopTracking();
}
// Right
if (UnityInput.GetKey(KeyCode.RightArrow) || UnityInput.GetKey(KeyCode.D))
{
cameraRig.PanCamera(Vector3.right * Time.deltaTime * mouseEdgePanSpeed * zoomRatio);
cameraRig.StopTracking();
}
// Down
if (UnityInput.GetKey(KeyCode.DownArrow) || UnityInput.GetKey(KeyCode.S))
{
cameraRig.PanCamera(Vector3.back * Time.deltaTime * mouseEdgePanSpeed * zoomRatio);
cameraRig.StopTracking();
}
// Up
if (UnityInput.GetKey(KeyCode.UpArrow) || UnityInput.GetKey(KeyCode.W))
{
cameraRig.PanCamera(Vector3.forward * Time.deltaTime * mouseEdgePanSpeed * zoomRatio);
cameraRig.StopTracking();
}
}
///
/// Decay the zoom if it's springy
///
protected void DecayZoom()
{
cameraRig.ZoomDecay();
}
///
/// Pan with right mouse
///
/// The drag pointer event
protected void DoRightMouseDragPan(PointerActionInfo pointer)
{
var mouseInfo = pointer as MouseButtonInfo;
if ((mouseInfo != null) &&
(mouseInfo.mouseButtonId == 1))
{
// Calculate zoom ratio
float zoomRatio = GetPanSpeedForZoomLevel();
Vector2 panVector = mouseInfo.currentPosition - mouseInfo.startPosition;
panVector = (panVector * Time.deltaTime * mouseRmbPanSpeed * zoomRatio) / screenPanThreshold;
var camVector = new Vector3(panVector.x, 0, panVector.y);
cameraRig.PanCamera(camVector);
cameraRig.StopTracking();
}
}
///
/// Perform mouse wheel zooming
///
protected void DoWheelZoom(WheelInfo wheel)
{
float prevZoomDist = cameraRig.zoomDist;
cameraRig.ZoomCameraRelative(wheel.zoomAmount * -1);
// Calculate actual zoom change after clamping
float zoomChange = cameraRig.zoomDist / prevZoomDist;
// First get floor position of cursor
Ray ray = cameraRig.cachedCamera.ScreenPointToRay(UnityInput.mousePosition);
Vector3 worldPos = Vector3.zero;
float dist;
if (cameraRig.floorPlane.Raycast(ray, out dist))
{
worldPos = ray.GetPoint(dist);
}
// Vector from our current look pos to this point
Vector3 offsetValue = worldPos - cameraRig.lookPosition;
// Pan towards or away from our zoom center
cameraRig.PanCamera(offsetValue * (1 - zoomChange));
}
///
/// Pan with middle mouse
///
/// Pointer with press event
protected void DoMiddleMousePan(PointerActionInfo pointer)
{
var mouseInfo = pointer as MouseButtonInfo;
// Pan to mouse position on MMB
if ((mouseInfo != null) &&
(mouseInfo.mouseButtonId == 2))
{
// First get floor position of cursor
Ray ray = cameraRig.cachedCamera.ScreenPointToRay(UnityInput.mousePosition);
float dist;
if (cameraRig.floorPlane.Raycast(ray, out dist))
{
Vector3 worldPos = ray.GetPoint(dist);
cameraRig.PanTo(worldPos);
}
cameraRig.StopTracking();
}
}
}
}