using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
namespace UI
{
///
/// A draggable window component with title bar dragging and close button functionality.
/// Automatically creates UI structure on Awake.
///
public class Window : MonoBehaviour
{
[Header("Window Settings")]
[SerializeField] private Vector2 windowSize = new Vector2(600, 400);
[SerializeField] private string windowTitle = "Window";
[SerializeField] private Color backgroundColor = new Color(0.2f, 0.2f, 0.2f, 1f);
[SerializeField] private Color titleBarColor = new Color(0.3f, 0.3f, 0.3f, 1f);
[SerializeField] private float titleBarHeight = 30f;
private RectTransform rectTransform;
private RectTransform titleBarRect;
private Image titleBarImage;
private bool isDragging = false;
private Vector2 dragOffset;
private bool wasMouseDownLastFrame = false;
private void Awake()
{
rectTransform = GetComponent();
if (rectTransform == null)
{
rectTransform = gameObject.AddComponent();
}
CreateUIStructure();
}
private void Update()
{
// Fallback: Check for mouse down on title bar if interface didn't fire
bool isMouseDown = Mouse.current.leftButton.isPressed;
if (isMouseDown && !wasMouseDownLastFrame && !isDragging)
{
CheckTitleBarClick();
}
wasMouseDownLastFrame = isMouseDown;
HandleDragging();
}
///
/// Fallback method to check if mouse clicked on title bar using raycasting
///
private void CheckTitleBarClick()
{
Debug.Log("CheckTitleBarClick");
if (EventSystem.current == null) return;
Vector2 mousePosition = Mouse.current.position.ReadValue();
// Use EventSystem to raycast
PointerEventData pointerData = new PointerEventData(EventSystem.current);
pointerData.position = mousePosition;
var results = new System.Collections.Generic.List();
EventSystem.current.RaycastAll(pointerData, results);
foreach (var result in results)
{
// Check if we hit the title bar (but not the close button or its children)
Transform hitTransform = result.gameObject.transform;
if (hitTransform.name == "TitleBar" && hitTransform.IsChildOf(transform))
{
OnTitleBarPointerDown(mousePosition);
break;
}
// If we hit a child of TitleBar, check if it's not the close button
else if (hitTransform.IsChildOf(transform.Find("TitleBar")))
{
// Skip if it's the close button or its children
if (!hitTransform.name.Contains("CloseButton") && hitTransform.parent != null && hitTransform.parent.name != "CloseButton")
{
OnTitleBarPointerDown(mousePosition);
break;
}
}
}
}
///
/// Creates the UI structure: background, title bar, close button, and content area
///
private void CreateUIStructure()
{
// Set up root RectTransform
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.sizeDelta = windowSize;
rectTransform.anchoredPosition = Vector2.zero;
// Create Background
GameObject backgroundObj = new GameObject("Background");
backgroundObj.transform.SetParent(transform, false);
Image backgroundImage = backgroundObj.AddComponent();
backgroundImage.color = backgroundColor;
RectTransform backgroundRect = backgroundObj.GetComponent();
backgroundRect.anchorMin = Vector2.zero;
backgroundRect.anchorMax = Vector2.one;
backgroundRect.sizeDelta = Vector2.zero;
backgroundRect.anchoredPosition = Vector2.zero;
// Create Title Bar
GameObject titleBarObj = new GameObject("TitleBar");
titleBarObj.transform.SetParent(transform, false);
Image titleBarImage = titleBarObj.AddComponent();
titleBarImage.color = titleBarColor;
titleBarRect = titleBarObj.GetComponent();
titleBarRect.anchorMin = new Vector2(0, 1);
titleBarRect.anchorMax = new Vector2(1, 1);
titleBarRect.pivot = new Vector2(0.5f, 1);
titleBarRect.sizeDelta = new Vector2(0, titleBarHeight);
titleBarRect.anchoredPosition = new Vector2(0, 0);
this.titleBarImage = titleBarImage;
// Add TitleBarDragHandler component for dragging
TitleBarDragHandler dragHandler = titleBarObj.AddComponent();
dragHandler.Initialize(this);
// Create Title Text
GameObject titleTextObj = new GameObject("TitleText");
titleTextObj.transform.SetParent(titleBarObj.transform, false);
Text titleText = titleTextObj.AddComponent();
titleText.text = windowTitle;
titleText.color = Color.white;
titleText.font = Resources.GetBuiltinResource("LegacyRuntime.ttf");
titleText.fontSize = 14;
titleText.alignment = TextAnchor.MiddleLeft;
RectTransform titleTextRect = titleTextObj.GetComponent();
titleTextRect.anchorMin = new Vector2(0, 0);
titleTextRect.anchorMax = new Vector2(1, 1);
titleTextRect.sizeDelta = new Vector2(-60, 0); // Leave space for close button
titleTextRect.anchoredPosition = new Vector2(10, 0);
// Create Close Button
GameObject closeButtonObj = new GameObject("CloseButton");
closeButtonObj.transform.SetParent(titleBarObj.transform, false);
Image closeButtonImage = closeButtonObj.AddComponent();
closeButtonImage.color = new Color(0.5f, 0.5f, 0.5f, 1f);
Button closeButton = closeButtonObj.AddComponent