294 lines
10 KiB
C#
294 lines
10 KiB
C#
using System;
|
||
using UnityEngine.UI;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.EventSystems;
|
||
using UnityEngine.Serialization;
|
||
using ZGame;
|
||
|
||
namespace HK.FUJIFILM
|
||
{
|
||
public class PhotoItemOperation : UIItemBase, IPointerEnterHandler, IPointerExitHandler
|
||
{
|
||
[SerializeField] private Button btnToUp;
|
||
[SerializeField] private Button btnToDown;
|
||
[SerializeField] private Button btnRRotate;
|
||
[SerializeField] private Button btnLRotate;
|
||
[SerializeField] private Button btnDelete;
|
||
[SerializeField] private Button btnClose;
|
||
[SerializeField] private Button btnHCenter;
|
||
[SerializeField] private Button btnVCenter;
|
||
|
||
CanvasGroup canvasGroup;
|
||
|
||
[SerializeField] private GameObject target;
|
||
|
||
public override void OnInit()
|
||
{
|
||
base.OnInit();
|
||
|
||
#region AutoGen_Init
|
||
|
||
btnToUp = GetValue<Button>("btnToUp");
|
||
btnToDown = GetValue<Button>("btnToDown");
|
||
btnRRotate = GetValue<Button>("btnRRotate");
|
||
btnLRotate = GetValue<Button>("btnLRotate");
|
||
btnDelete = GetValue<Button>("btnDelete");
|
||
btnClose = GetValue<Button>("btnClose");
|
||
btnHCenter = GetValue<Button>("btnHCenter");
|
||
btnVCenter = GetValue<Button>("btnVCenter");
|
||
|
||
btnToUp.onClick.AddListener(OnClickbtnToUp);
|
||
btnToDown.onClick.AddListener(OnClickbtnToDown);
|
||
btnRRotate.onClick.AddListener(OnClickbtnRRotate);
|
||
btnLRotate.onClick.AddListener(OnClickbtnLRotate);
|
||
btnDelete.onClick.AddListener(OnClickbtnDelete);
|
||
btnHCenter.onClick.AddListener(OnClickbtnHCenter);
|
||
btnVCenter.onClick.AddListener(OnClickbtnVCenter);
|
||
btnClose.onClick.AddListener(OnClickbtnClose);
|
||
|
||
#endregion
|
||
|
||
canvas = GetComponentInParent<Canvas>();
|
||
_imageRect = transform.GetChild(1).GetComponent<RectTransform>();
|
||
canvasGroup = GetComponent<CanvasGroup>();
|
||
Close();
|
||
EventManager.Instance.Subscribe(PhotoItemOperationEventArgs.EventId, PhotoItemOperationEvent);
|
||
}
|
||
|
||
private void PhotoItemOperationEvent(object sender, GameEventArgs e)
|
||
{
|
||
// return;
|
||
var args = e as PhotoItemOperationEventArgs;
|
||
if (args == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (args.isStart)
|
||
{
|
||
// // 1. 获取鼠标点击的屏幕坐标
|
||
// Vector2 clickScreenPos = Input.mousePosition;
|
||
//
|
||
// // 2. 应用偏移量(让 Image 位置更灵活)
|
||
// clickScreenPos += clickOffset;
|
||
//
|
||
// // 3. (可选)限制 Image 在屏幕内
|
||
// if (clampToScreen)
|
||
// {
|
||
// clickScreenPos = ClampPosToScreen(clickScreenPos);
|
||
// }
|
||
//
|
||
// // 4. 根据 Canvas 模式,设置 Image 最终位置
|
||
// SetImagePosition(clickScreenPos);
|
||
|
||
Open(args.target);
|
||
isStarting = true;
|
||
}
|
||
else
|
||
Close();
|
||
}
|
||
|
||
Canvas canvas;
|
||
private RectTransform _imageRect;
|
||
[SerializeField] int screenMargin = 10;
|
||
[SerializeField] bool clampToScreen = true;
|
||
[SerializeField] Vector2 clickOffset = Vector2.zero;
|
||
|
||
/// <summary>
|
||
/// 限制位置在屏幕内,防止 Image 超出视野
|
||
/// </summary>
|
||
/// <param name="originalPos">原始点击位置</param>
|
||
/// <returns>限制后的位置</returns>
|
||
private Vector2 ClampPosToScreen(Vector2 originalPos)
|
||
{
|
||
// 计算 Image 自身的实际尺寸(考虑缩放)
|
||
Vector2 imageRealSize = new Vector2(
|
||
_imageRect.rect.width * Mathf.Abs(_imageRect.localScale.x),
|
||
_imageRect.rect.height * Mathf.Abs(_imageRect.localScale.y)
|
||
);
|
||
|
||
// 计算屏幕可显示的边界(留空 margin)
|
||
float minX = screenMargin + (imageRealSize.x / 2); // 左边界(加 Image 半宽,避免左半部分超出)
|
||
float maxX = Screen.width - screenMargin - (imageRealSize.x / 2); // 右边界
|
||
float minY = screenMargin + (imageRealSize.y / 2); // 下边界
|
||
float maxY = Screen.height - screenMargin - (imageRealSize.y / 2); // 上边界
|
||
|
||
// 限制位置在边界内
|
||
return new Vector2(
|
||
Mathf.Clamp(originalPos.x, minX, maxX),
|
||
Mathf.Clamp(originalPos.y, minY, maxY)
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据 Canvas 渲染模式,设置 Image 到目标位置
|
||
/// </summary>
|
||
/// <param name="targetScreenPos">目标屏幕坐标</param>
|
||
private void SetImagePosition(Vector2 targetScreenPos)
|
||
{
|
||
switch (canvas.renderMode)
|
||
{
|
||
// 1. 最常用:Screen Space - Overlay 模式(直接用屏幕坐标)
|
||
case RenderMode.ScreenSpaceOverlay:
|
||
_imageRect.position = targetScreenPos;
|
||
break;
|
||
|
||
// 2. Screen Space - Camera 模式(需通过相机转换坐标)
|
||
case RenderMode.ScreenSpaceCamera:
|
||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||
canvas.GetComponent<RectTransform>(), // Canvas 的 RectTransform
|
||
targetScreenPos, // 目标屏幕位置
|
||
canvas.worldCamera, // Canvas 关联的相机
|
||
out Vector2 canvasLocalPos // 转换后的 Canvas 局部坐标
|
||
))
|
||
{
|
||
_imageRect.localPosition = canvasLocalPos;
|
||
}
|
||
|
||
break;
|
||
|
||
// 3. World Space 模式(UI 作为3D物体,需转换为世界坐标)
|
||
case RenderMode.WorldSpace:
|
||
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(
|
||
_imageRect, // Image 自身的 RectTransform
|
||
targetScreenPos, // 目标屏幕位置
|
||
canvas.worldCamera, // Canvas 关联的相机
|
||
out Vector3 worldPos // 转换后的世界坐标
|
||
))
|
||
{
|
||
// 保持 Image 的 Z 轴位置不变(避免前后层叠问题)
|
||
worldPos.z = _imageRect.position.z;
|
||
_imageRect.position = worldPos;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
#region AutoGen_Method
|
||
|
||
private void OnClickbtnToUp()
|
||
{
|
||
var parent = target.transform.parent;
|
||
target.transform.SetSiblingIndex(parent.childCount - 1);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnToDown()
|
||
{
|
||
var index = target.transform.GetSiblingIndex() - 1;
|
||
var siblingIndex = index >= 0 ? index : 0;
|
||
target.transform.SetSiblingIndex(siblingIndex);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnRRotate()
|
||
{
|
||
target.transform.localEulerAngles -= new Vector3(0f, 0f, 90f);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnLRotate()
|
||
{
|
||
target.transform.localEulerAngles += new Vector3(0f, 0f, 90f);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnVCenter()
|
||
{
|
||
var rectTransform = target.GetComponent<RectTransform>();
|
||
rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, 0f);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnHCenter()
|
||
{
|
||
var rectTransform = target.GetComponent<RectTransform>();
|
||
rectTransform.anchoredPosition = new Vector2(0f, rectTransform.anchoredPosition.y);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnDelete()
|
||
{
|
||
GameObject.Destroy(target);
|
||
Close();
|
||
}
|
||
|
||
private void OnClickbtnClose()
|
||
{
|
||
Close();
|
||
}
|
||
|
||
void Close()
|
||
{
|
||
isStarting = false;
|
||
target = null;
|
||
canvasGroup.alpha = 0;
|
||
canvasGroup.interactable = false;
|
||
canvasGroup.blocksRaycasts = false;
|
||
}
|
||
|
||
void Open(Transform ta)
|
||
{
|
||
if (ta == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
target = ta.gameObject;
|
||
canvasGroup.alpha = 1;
|
||
canvasGroup.interactable = true;
|
||
canvasGroup.blocksRaycasts = true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
private void Update()
|
||
{
|
||
if (gameObject.activeSelf && isStarting)
|
||
{
|
||
if (Input.GetMouseButtonDown(0) && !isEntering)
|
||
{
|
||
Close();
|
||
}
|
||
}
|
||
}
|
||
|
||
public override void OnDispose()
|
||
{
|
||
base.OnDispose();
|
||
EventManager.Instance.Unsubscribe(PhotoItemOperationEventArgs.EventId, PhotoItemOperationEvent);
|
||
|
||
#region AutoGen_Dispose
|
||
|
||
btnToUp.onClick.RemoveListener(OnClickbtnToUp);
|
||
btnToDown.onClick.RemoveListener(OnClickbtnToDown);
|
||
btnRRotate.onClick.RemoveListener(OnClickbtnRRotate);
|
||
btnLRotate.onClick.RemoveListener(OnClickbtnLRotate);
|
||
btnDelete.onClick.RemoveListener(OnClickbtnDelete);
|
||
btnClose.onClick.RemoveListener(OnClickbtnClose);
|
||
|
||
btnToUp = null;
|
||
btnToDown = null;
|
||
btnRRotate = null;
|
||
btnDelete = null;
|
||
btnClose = null;
|
||
|
||
#endregion
|
||
}
|
||
|
||
private bool isEntering = false;
|
||
private bool isStarting = false;
|
||
|
||
public void OnPointerEnter(PointerEventData eventData)
|
||
{
|
||
isEntering = true;
|
||
}
|
||
|
||
public void OnPointerExit(PointerEventData eventData)
|
||
{
|
||
isEntering = false;
|
||
}
|
||
}
|
||
} |