using UnityEngine; using UnityEngine.EventSystems; // Un bouton de la palette des trous : SinkRectangle, SinkRound, SmallRound, ... // // Deux gestes pour poser le trou qu'il décrit : // double-clic : il se pose au centre du comptoir ; // glisser : il suit le doigt et reste là où on le lâche. // // Lâché hors du comptoir, le trou n'est pas retenu : c'est ce qui annule une pose // commencée par mégarde. // // Hiérarchie attendue : // Btn_SinkRectangle <- ce script // Icon <- l'image du bouton, libre public class HoleButton : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler { [Tooltip("Le plateau du panneau, qui garde les trous posés. Vide = le premier trouvé dans la scène.")] [SerializeField] private HoleBoard board; [Header("Le trou décrit par ce bouton")] [Tooltip("Son contour : rectangle, rectangle à coins arrondis, ou rond.")] [SerializeField] private Hole.Kind kind = Hole.Kind.Rectangle; [Tooltip("Largeur et profondeur, en pouces. Un rond y prend ses deux diamètres : 18 x 18 pour un rond de 18\".")] [SerializeField] private Vector2 sizeInches = new Vector2(30f, 18f); [Tooltip("Rayon des coins, en pouces. Sans effet sur les deux autres contours.")] [SerializeField] private float cornerInches = 2f; [Header("Double-clic")] [Tooltip("Délai maximal entre deux clics, en secondes.")] [SerializeField] private float doubleClickDelay = 0.4f; // Le trou créé par le glisser en cours. private Hole _dragged; // Quand le clic précédent a eu lieu. -1 = aucun clic en attente d'un second. private float _lastClick = -1f; private HoleBoard Board { get { if (board != null) return board; // Le plateau du même panneau d'abord : un plateau pris ailleurs poserait // le trou dans un panneau fermé, invisible sous le doigt qui le glisse. for (Transform parent = transform.parent; parent != null; parent = parent.parent) { board = parent.GetComponentInChildren(true); if (board != null) return board; } board = FindAnyObjectByType(FindObjectsInactive.Include); return board; } } public void OnPointerClick(PointerEventData eventData) { if (Board == null || !Board.Editable) return; // clickCount vient de l'Event System quand il sait compter les clics ; le // délai prend le relais là où il ne le sait pas, sur écran tactile. bool second = eventData.clickCount >= 2 || (_lastClick >= 0f && Time.unscaledTime - _lastClick <= doubleClickDelay); if (!second) { _lastClick = Time.unscaledTime; return; } // Reparti de zéro : un troisième clic ne pose pas un deuxième trou. _lastClick = -1f; Hole hole = Board.Add(kind, sizeInches, cornerInches, Board.CenterInches); // Posé au centre, il y tient sauf comptoir plus petit que le trou. if (hole != null) Board.Drop(hole); } public void OnBeginDrag(PointerEventData eventData) { if (Board == null || !Board.Editable) return; // Un glisser n'est pas un clic : sinon le double-clic se déclencherait au // relâchement d'un glisser suivi d'un clic. _lastClick = -1f; // Poser un nouveau trou lâche celui qui était choisi : ses deux boutons // n'ont plus rien à faire à l'écran pendant qu'on en place un autre. Board.ClearSelection(); Board.BeginDrag(); _dragged = Board.Add(kind, sizeInches, cornerInches, Board.PointerToInches(eventData)); } public void OnDrag(PointerEventData eventData) { if (_dragged == null) return; _dragged.PositionInches = Board.PointerToInches(eventData); } public void OnEndDrag(PointerEventData eventData) { // Même sans trou créé, le lâcher doit être annoncé : sinon le plateau // resterait en glisser et ses deux boutons ne reviendraient jamais. if (Board != null) Board.Drop(_dragged); _dragged = null; } }