Search Unity

Drag Window Script with Window Clamped within Canvas

Discussion in 'UGUI & TextMesh Pro' started by MMOERPG, Jan 27, 2017.

  1. MMOERPG

    MMOERPG

    Joined:
    Mar 21, 2014
    Posts:
    50
    I spent some time working on a script that would allow me to drag a window anywhere within the canvas but not let any part of that window escape the bounds of the canvas. Simply drop this script on a window, no matter the pivot of that window and it should allow you to drag that window within the canvas but not let any part of that window escape the bounds of the canvas. Thanks to Unity for their excellent tutorial which got me started https://unity3d.com/learn/tutorials/modules/intermediate/live-training-archive/panels-panes-windows

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6.  
    7. public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
    8.  
    9.     private Vector2 pointerOffset;
    10.     private RectTransform canvasRectTransform;
    11.     private RectTransform panelRectTransform;
    12.     private bool clampedToLeft;
    13.     private bool clampedToRight;
    14.     private bool clampedToTop;
    15.     private bool clampedToBottom;
    16.  
    17.     public void Start(){
    18.        
    19.         Canvas canvas = GetComponentInParent<Canvas> ();
    20.         if(canvas != null){
    21.             canvasRectTransform = canvas.transform as RectTransform;
    22.             panelRectTransform = transform as RectTransform;
    23.         }
    24.         clampedToLeft = false;
    25.         clampedToRight = false;
    26.         clampedToTop = false;
    27.         clampedToBottom = false;
    28.     }
    29.  
    30.     #region IBeginDragHandler implementation
    31.  
    32.     public void OnBeginDrag (PointerEventData eventData)
    33.     {
    34.         panelRectTransform.SetAsLastSibling ();
    35.         RectTransformUtility.ScreenPointToLocalPointInRectangle (panelRectTransform, eventData.position, eventData.pressEventCamera, out pointerOffset);
    36.  
    37.     }
    38.  
    39.     #endregion
    40.  
    41.     #region IDragHandler implementation
    42.  
    43.     public void OnDrag (PointerEventData eventData)
    44.     {
    45.         if(panelRectTransform == null){
    46.             return;
    47.         }
    48.         Vector2 localPointerPosition;
    49.         if(RectTransformUtility.ScreenPointToLocalPointInRectangle (canvasRectTransform, eventData.position, eventData.pressEventCamera, out localPointerPosition)){
    50.             panelRectTransform.localPosition = localPointerPosition - pointerOffset;
    51.             ClampToWindow ();
    52.             Vector2 clampedPosition = panelRectTransform.localPosition;
    53.             if (clampedToRight) {
    54.                 clampedPosition.x = (canvasRectTransform.rect.width * 0.5f) - (panelRectTransform.rect.width * (1 - panelRectTransform.pivot.x));
    55.             } else if(clampedToLeft){
    56.                 clampedPosition.x = (-canvasRectTransform.rect.width * 0.5f) + (panelRectTransform.rect.width * panelRectTransform.pivot.x);
    57.             }
    58.  
    59.             if(clampedToTop){
    60.                 clampedPosition.y = (canvasRectTransform.rect.height * 0.5f) - (panelRectTransform.rect.height * (1 - panelRectTransform.pivot.y));
    61.             }else if(clampedToBottom){
    62.                 clampedPosition.y = (-canvasRectTransform.rect.height * 0.5f) + (panelRectTransform.rect.height * panelRectTransform.pivot.y);
    63.             }
    64.             panelRectTransform.localPosition = clampedPosition;
    65.         }
    66.     }
    67.  
    68.     #endregion
    69.  
    70.     #region IEndDragHandler implementation
    71.  
    72.     public void OnEndDrag (PointerEventData eventData)
    73.     {
    74.  
    75.     }
    76.  
    77.     #endregion
    78.  
    79.     void ClampToWindow(){
    80.         Vector3[] canvasCorners = new Vector3[4];
    81.         Vector3[] panelRectCorners = new Vector3[4];
    82.         canvasRectTransform.GetWorldCorners (canvasCorners);
    83.         panelRectTransform.GetWorldCorners (panelRectCorners);
    84.  
    85.         if (panelRectCorners [2].x > canvasCorners [2].x) {
    86.             Debug.Log ("Panel is to the right of canvas limits");
    87.             if (!clampedToRight) {
    88.                 clampedToRight = true;
    89.             }
    90.         } else if (clampedToRight) {
    91.             clampedToRight = false;
    92.         } else if (panelRectCorners [0].x < canvasCorners [0].x) {
    93.             Debug.Log ("Panel is to the left of canvas limits");
    94.             if(!clampedToLeft){
    95.                 clampedToLeft = true;
    96.             }
    97.         }else if(clampedToLeft){
    98.             clampedToLeft = false;
    99.         }
    100.  
    101.         if (panelRectCorners [2].y > canvasCorners [2].y) {
    102.             Debug.Log ("Panel is to the top of canvas limits");
    103.             if (!clampedToTop) {
    104.                 clampedToTop = true;
    105.             }
    106.         }else if(clampedToTop){
    107.             clampedToTop = false;
    108.         }else if(panelRectCorners[0].y < canvasCorners[0].y){
    109.             Debug.Log ("Panel is to the bottom of canvas limits");
    110.             if(!clampedToBottom){
    111.                 clampedToBottom = true;
    112.             }
    113.         }else if(clampedToBottom){
    114.             clampedToBottom = false;
    115.         }
    116.     }
    117. }
    118.  
     
    Julber, Vagonn, sparkwd and 12 others like this.
  2. gegebel

    gegebel

    Joined:
    Jan 29, 2014
    Posts:
    469
    Thanks for that, I always forget to store my version somewhere :D works great.
     
  3. cyberbum

    cyberbum

    Joined:
    Nov 11, 2017
    Posts:
    3
    This is great, thanks!!
     
  4. Seti_

    Seti_

    Joined:
    Mar 27, 2020
    Posts:
    1
    Thank you for uploading this
     
  5. _Eyesgood_

    _Eyesgood_

    Joined:
    Apr 19, 2013
    Posts:
    55
    6 years later and you are still helping the community! Thanks a million for giving the community this awesome solution to a most common feature request!
     
  6. Juskiesskalt

    Juskiesskalt

    Joined:
    May 24, 2022
    Posts:
    1
    Works great!
    Even exposed the panel so I could put the script on a child "Window Title Bar" and it still worked fine.
    Thanks a bunch.
     
  7. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    514
    This is an awsome script thanks MMOERPG