FM/Assets/Scripts/FUJIFILM/UI/Item/PhotoItemOperation.cs

294 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}