/// <summary>
 /// Use this method to center the pan target on the current camera position.
 /// Useful for situations where you controlled the camera using other methods (like cinematics)
 /// </summary>
 public void CenterPanTargetOnCamera(float interpolant = 1f)
 {
     if (_panTarget != null)
     {
         _panTarget.position = Vector3.Lerp(
             _panTarget.position,
             VectorHV(Vector3H(ProCamera2D.LocalPosition) - ProCamera2D.GetOffsetX(), Vector3V(ProCamera2D.LocalPosition) - ProCamera2D.GetOffsetY()),
             interpolant);
     }
 }
        void Pan(float deltaTime)
        {
            _panDelta = Vector2.zero;

            if (UseTouchInput)
            {
                // Time since zoom
                if (Time.time - _touchZoomTime < .1f)
                {
                    if (Input.touchCount > 0)
                    {
                        _prevTouchPosition = new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, Mathf.Abs(Vector3D(ProCamera2D.LocalPosition)));
                    }

                    return;
                }

                // Touch delta
                if (AllowZoom && Input.touchCount == 1 ||
                    !AllowZoom && Input.touchCount > 0)
                {
                    var touch = Input.GetTouch(Input.touchCount - 1);

                    if (touch.phase == TouchPhase.Began)
                    {
                        _prevTouchId       = touch.fingerId;
                        _prevTouchPosition = new Vector3(touch.position.x, touch.position.y, Mathf.Abs(Vector3D(ProCamera2D.LocalPosition)));

                        _startPanWorldPos = ProCamera2D.GameCamera.ScreenToWorldPoint(_prevTouchPosition);
                    }

                    // Ignore if using different finger or touch not moving
                    if (touch.fingerId != _prevTouchId || touch.phase != TouchPhase.Moved)
                    {
                        return;
                    }

                    var touchPos           = new Vector3(touch.position.x, touch.position.y, Mathf.Abs(Vector3D(ProCamera2D.LocalPosition)));
                    var normalizedTouchPos = new Vector2(touch.position.x / ProCamera2D.GameCamera.pixelWidth, touch.position.y / ProCamera2D.GameCamera.pixelHeight);

                    if (ProCamera2D.GameCamera.pixelRect.Contains(touchPos) && InsideDraggableArea(normalizedTouchPos))
                    {
                        var prevTouchPositionWorldCoord    = ProCamera2D.GameCamera.ScreenToWorldPoint(_prevTouchPosition);
                        var currentTouchPositionWorldCoord = ProCamera2D.GameCamera.ScreenToWorldPoint(touchPos);

                        if (IsPanning)
                        {
                            if (ResetPrevPanPoint)
                            {
                                prevTouchPositionWorldCoord = ProCamera2D.GameCamera.ScreenToWorldPoint(touchPos);
                                ResetPrevPanPoint           = false;
                            }

                            var panDelta = prevTouchPositionWorldCoord - currentTouchPositionWorldCoord;
                            _panDelta = new Vector2(Vector3H(panDelta), Vector3V(panDelta));
                        }
                        else
                        {
                            // Detect pan start
                            var screenSize       = (ProCamera2D.ScreenSizeInWorldCoordinates.x + ProCamera2D.ScreenSizeInWorldCoordinates.y) / 2;
                            var dragDistancePerc = Vector3.Distance(currentTouchPositionWorldCoord, _startPanWorldPos) / screenSize;
                            if (dragDistancePerc > MinPanAmount)
                            {
                                CenterPanTargetOnCamera(StopSpeedOnDragStart);
                                StartPanning();
                            }
                        }
                    }

                    _prevTouchPosition = touchPos;
                }

                if (IsPanning && Input.touchCount == 0)
                {
                    StopPanning();
                }
            }

            var panSpeed = DragPanSpeedMultiplier;

            if (UseMouseInput)
            {
                var mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,
                                           Mathf.Abs(Vector3D(ProCamera2D.LocalPosition)));

                if (Input.GetMouseButtonDown((int)PanMouseButton))
                {
                    _startPanWorldPos = ProCamera2D.GameCamera.ScreenToWorldPoint(mousePos);
                }

                // Detect pan start
                if (UsePanByDrag && Input.GetMouseButton((int)PanMouseButton) && !IsPanning)
                {
                    var mousePosWorldCoord = ProCamera2D.GameCamera.ScreenToWorldPoint(mousePos);
                    var screenSize         = (ProCamera2D.ScreenSizeInWorldCoordinates.x + ProCamera2D.ScreenSizeInWorldCoordinates.y) / 2;
                    var dragDistancePerc   = Vector3.Distance(mousePosWorldCoord, _startPanWorldPos) / screenSize;
                    if (dragDistancePerc > MinPanAmount)
                    {
                        CenterPanTargetOnCamera(StopSpeedOnDragStart);
                        StartPanning();
                    }
                }

                // Mouse drag delta
                if (IsPanning && UsePanByDrag && Input.GetMouseButton((int)PanMouseButton))
                {
                    var normalizedMousePos = new Vector2(Input.mousePosition.x / ProCamera2D.GameCamera.pixelWidth, Input.mousePosition.y / ProCamera2D.GameCamera.pixelHeight);
                    if (ProCamera2D.GameCamera.pixelRect.Contains(mousePos) && InsideDraggableArea(normalizedMousePos))
                    {
                        var prevMousePositionWorldCoord = ProCamera2D.GameCamera.ScreenToWorldPoint(_prevMousePosition);

                        if (ResetPrevPanPoint)
                        {
                            prevMousePositionWorldCoord = ProCamera2D.GameCamera.ScreenToWorldPoint(mousePos);
                            ResetPrevPanPoint           = false;
                        }

                        var panDelta = prevMousePositionWorldCoord - ProCamera2D.GameCamera.ScreenToWorldPoint(mousePos);
                        _panDelta = new Vector2(Vector3H(panDelta), Vector3V(panDelta));
                    }
                }
                // Move to edges delta
                else if (UsePanByMoveToEdges && !Input.GetMouseButton((int)PanMouseButton))
                {
                    var normalizedMousePosX = (-Screen.width * .5f + Input.mousePosition.x) / Screen.width;
                    var normalizedMousePosY = (-Screen.height * .5f + Input.mousePosition.y) / Screen.height;

                    if (normalizedMousePosX < 0)
                    {
                        normalizedMousePosX = normalizedMousePosX.Remap(-.5f, -LeftPanEdge * .5f, -.5f, 0f);
                    }
                    else if (normalizedMousePosX > 0)
                    {
                        normalizedMousePosX = normalizedMousePosX.Remap(RightPanEdge * .5f, .5f, 0f, .5f);
                    }

                    if (normalizedMousePosY < 0)
                    {
                        normalizedMousePosY = normalizedMousePosY.Remap(-.5f, -BottomPanEdge * .5f, -.5f, 0f);
                    }
                    else if (normalizedMousePosY > 0)
                    {
                        normalizedMousePosY = normalizedMousePosY.Remap(TopPanEdge * .5f, .5f, 0f, .5f);
                    }

                    _panDelta = new Vector2(normalizedMousePosX, normalizedMousePosY) * deltaTime;

                    if (_panDelta != Vector2.zero)
                    {
                        panSpeed = EdgesPanSpeed;
                    }
                }

                if (IsPanning && UsePanByDrag && !Input.GetMouseButton((int)PanMouseButton))
                {
                    StopPanning();
                }

                // Prevent unintentional pans when outside of the GameView on the editor
#if UNITY_EDITOR
                Rect screenRect = new Rect(0, 0, Screen.width, Screen.height);
                if (screenRect.Contains(Input.mousePosition) == false ||
                    screenRect.Contains(_prevMousePosition) == false)
                {
                    _panDelta = Vector2.zero;
                }
#endif
                _prevMousePosition = mousePos;
            }

            // Move
            if (_panDelta != Vector2.zero)
            {
                var delta = VectorHV(_panDelta.x * panSpeed.x, _panDelta.y * panSpeed.y);
                _panTarget.Translate(delta);
            }

            // Check if target is outside of bounds
            if ((ProCamera2D.IsCameraPositionLeftBounded && Vector3H(_panTarget.position) < Vector3H(ProCamera2D.LocalPosition)) ||
                (ProCamera2D.IsCameraPositionRightBounded && Vector3H(_panTarget.position) > Vector3H(ProCamera2D.LocalPosition)))
            {
                _panTarget.position = VectorHVD(
                    Vector3H(ProCamera2D.LocalPosition) - ProCamera2D.GetOffsetX() * 0.9999f,                     // The multiplier avoids floating-point comparison errors
                    Vector3V(_panTarget.position),
                    Vector3D(_panTarget.position));
            }


            if ((ProCamera2D.IsCameraPositionBottomBounded && Vector3V(_panTarget.position) < Vector3V(ProCamera2D.LocalPosition)) ||
                (ProCamera2D.IsCameraPositionTopBounded && Vector3V(_panTarget.position) > Vector3V(ProCamera2D.LocalPosition)))
            {
                _panTarget.position = VectorHVD(
                    Vector3H(_panTarget.position),
                    Vector3V(ProCamera2D.LocalPosition) - ProCamera2D.GetOffsetY() * 0.9999f,                     // The multiplier avoids floating-point comparison errors
                    Vector3D(_panTarget.position));
            }
        }