Example-Code / CardArchitecture / BattleCard_InputHandling.cs
BattleCard_InputHandling.cs
Raw
using CCG.Bigfoot.ScriptableObjects;
using CCG.Bigfoot.TestScripts;
using CCG.Bigfoot.Utility;
using UnityEngine;
using UnityEngine.EventSystems;
namespace CCG.Bigfoot.CardScripts
{
    /// <summary>
    /// This - BattleCard_InputHandling.cs is a partial class to BattleCard.cs to handle input events.
    /// </summary>
    /// <remarks> This is for organizational purposes.
    /// Authors: CS
    /// Created: 2024-01-11
    /// </remarks>
    public sealed partial class BattleCard : IDragHandler, IBeginDragHandler, IEndDragHandler
    {
        /// <summary>
        /// WARNING! You MUST unsubscribe from static events before resubscribing/shutdown.
        /// </summary>
        public static event System.Action<BattleCard,CardSpace> BattleCardDroppedEvent;

        [SerializeField] private Transform _dragCardParent;
        /// <summary>
        /// Must be set to true to receive drag callbacks
        /// </summary>
        private bool _isDragAndDropEnabled = true;//false;
        private static RectTransform _dragCardCanvasRect;
        private static float _initialPlaneDistance;  //--This is the plane distance property on the card selection canvas.
        private static float _draggingPlaneDistance; //--This is the plane distance property on the drag card canvas.
        private float _initialScaleFactor;           //--This is the ratio between the object's local scale and the distance from the camera plane to the canvas.
        private Vector3 _scaleVector;
        private static LayerMask _cardSpaceLayerMask;
        private Transform _initialParent;
        private Vector3 _initialLocalScale;
        private Vector3 _initialLocalPosition;

        /// <summary>
        /// Sets parent and transform values back to cached values set in OnBeginDrag.
        /// </summary>
        public void SnapToPreviousParentAndTransformValues()
        {
            if (transform.parent == _initialParent) return;

            transform.SetParent(_initialParent);
            transform.localScale = _initialLocalScale;
            transform.localPosition   = _initialLocalPosition;
        }

        public void OnBeginDrag(PointerEventData ped)
        {
            if (!_isDragAndDropEnabled || transform.parent == _dragCardParent) return;

            _initialParent = transform.parent;
            _initialLocalScale = transform.localScale;
            _initialLocalPosition = transform.localPosition;

            transform.SetParent(_dragCardParent);
            _initialScaleFactor = transform.localScale.z / _initialPlaneDistance;
        }

        public void OnDrag(PointerEventData ped)
        {
            if (!_isDragAndDropEnabled) return;
            /*README How it works
             * --This is converting a screen point to a world point, in canvas space.
             * --The DragCardCanvas is a copy of the canvas that it is pulled out of, with a lower plane distance.
             * --Plane distance determines the depth at which the canvas is rendered relative to the camera,
             * --so lowering it brings the canvas closer to the camera, making its content render on top.
             * --This means that it will always look a bit larger when you pull it out of that first canvas.
             * --Due to that, we need to adjust the scale, so it doesn't look larger.
             */

            Vector3 targetPosition = Vector3.zero;
            Vector3 screenPoint = ped.position;
            float scaleFactor = _initialScaleFactor * _draggingPlaneDistance;//-- Calc the scale adjustment ratio based on the change in plane distance

            screenPoint.z = transform.position.z;
            RectTransformUtility.ScreenPointToWorldPointInRectangle(_dragCardCanvasRect, screenPoint, ped.pressEventCamera, out targetPosition);
            _scaleVector.Set(scaleFactor, scaleFactor, scaleFactor);

            transform.localScale = _scaleVector;
            transform.position = targetPosition;
        }

        public void OnEndDrag(PointerEventData ped)
        {
            _ = RaycasterHelper.IsMouseOverLayerMask(_cardSpaceLayerMask, ped.position, out CardSpace cardSpace);
            BattleCardDroppedEvent?.Invoke(this,cardSpace);
        }
    }
}