/* * UniWindowDragMove.cs * * 作者: Kirurobo http://twitter.com/kirurobo * 许可证: MIT */ using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.EventSystems; #if ENABLE_LEGACY_INPUT_MANAGER #elif ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif namespace Kirurobo { public class UniWindowMoveHandle : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerUpHandler { private UniWindowController _uniwinc; /// /// 窗口最大化时是否禁用移动 /// [Tooltip("窗口已最大化(缩放)时禁用拖拽移动。")] public bool disableOnZoomed = true; /// /// 拖动中则为 true /// public bool IsDragging { get { return _isDragging; } } private bool _isDragging = false; /// /// 是否进行拖动 /// private bool IsEnabled { get { return enabled && (!disableOnZoomed || !IsZoomed); } } /// /// 是否适配显示器或最大化 /// private bool IsZoomed { get { return (_uniwinc && (_uniwinc.shouldFitMonitor || _uniwinc.isZoomed)); } } /// /// 记录拖动前自动命中测试是否启用 /// private bool _isHitTestEnabled; /// /// 拖动开始时窗口内坐标[像素] /// private Vector2 _dragStartedPosition; // 首次帧更新前调用 Start void Start() { // 获取场景中的 UniWindowController #if UNITY_2022_1_OR_NEWER _uniwinc = GameObject.FindAnyObjectByType(); #else _uniwinc = GameObject.FindObjectOfType(); #endif if (_uniwinc) _isHitTestEnabled = _uniwinc.isHitTestEnabled; //// 下面的代码似乎不需要,所以注释掉以免擅自更改 //Input.simulateMouseWithTouches = false; } /// /// 拖动开始时的处理 /// public void OnBeginDrag(PointerEventData eventData) { if (!IsEnabled) { return; } // 仅通过鼠标左键拖动 if (eventData.button != PointerEventData.InputButton.Left) return; // Mac 上行为会有所不同 // 实际上仅在 Retina 支持启用时,但 eventData.position 的坐标系与窗口坐标系的缩放会不一致 #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX _dragStartedPosition = _uniwinc.windowPosition - _uniwinc.cursorPosition; #else _dragStartedPosition = eventData.position; #endif // 如果 _isDragging 为 false,则判断即将开始拖动 if (!_isDragging) { // 拖动期间禁用命中测试 _isHitTestEnabled = _uniwinc.isHitTestEnabled; _uniwinc.isHitTestEnabled = false; _uniwinc.isClickThrough = false; } _isDragging = true; } /// /// 拖动结束时的处理 /// public void OnEndDrag(PointerEventData eventData) { EndDragging(); } /// /// 鼠标抬起时也视为拖动结束 /// /// public void OnPointerUp(PointerEventData eventData) { EndDragging(); } /// /// 结束拖动 /// private void EndDragging() { if (_isDragging) { _uniwinc.isHitTestEnabled = _isHitTestEnabled; } _isDragging = false; } /// /// 非最大化时,通过鼠标拖动移动窗口 /// public void OnDrag(PointerEventData eventData) { if (!_uniwinc || !_isDragging) return; // 如果拖动移动已被禁用,则结束拖动 if (!IsEnabled) { EndDragging(); return; } // // 如果鼠标左键未按下,则结束拖动 // if (eventData.button != PointerEventData.InputButton.Left) return; // [Shift]、[Ctrl]、[Alt]、[Command] 键按下期间不视为拖动 var modifiers = UniWindowController.GetModifierKeys(); if (modifiers != UniWindowController.ModifierKey.None) return; // 如果鼠标按钮已松开,则结束拖动 var buttons = UniWindowController.GetMouseButtons(); if ((buttons & UniWindowController.MouseButton.Left) == UniWindowController.MouseButton.None) { EndDragging(); return; } // #if ENABLE_LEGACY_INPUT_MANAGER // // 在 Mac 上,如果在多显示器之间移动,EventSystem 的 OnEndDrag 可能无法正确调用,因此始终监控鼠标按钮 // if (!Input.Mouse.Button(0).IsPressed) { // EndDragging(); // return; // } // if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) // || Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl) // || Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) return; // #elif ENABLE_INPUT_SYSTEM // // 在 Mac 上,如果在多显示器之间移动,EventSystem 的 OnEndDrag 可能无法正确调用,因此始终监控鼠标按钮 // if (!Mouse.current.leftButton.isPressed) { // EndDragging(); // return; // } // if (Keyboard.current[Key.LeftShift].isPressed || Keyboard.current[Key.RightShift].isPressed // || Keyboard.current[Key.LeftCtrl].isPressed || Keyboard.current[Key.RightCtrl].isPressed // || Keyboard.current[Key.LeftAlt].isPressed || Keyboard.current[Key.RightAlt].isPressed) return; // #endif // 如果是全屏则不移动窗口 // 在编辑器中可能会变为 true,因此仅在非编辑器环境下确认 #if !UNITY_EDITOR if (Screen.fullScreen) { EndDragging(); return; } #endif #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX // 在 Mac 上,通过原生插件获取/设置光标位置 _uniwinc.windowPosition = _uniwinc.cursorPosition + _dragStartedPosition; //Debug.Log("Drag start: " + _dragStartedPosition); #else // 在 Windows 上,为支持触控操作而使用 eventData.position // 将窗口移动与起始位置一致的屏幕位置偏移量 _uniwinc.windowPosition += eventData.position - _dragStartedPosition; #endif } } }