using DG.Tweening;
using SC.XR.Unity.Module_InputSystem;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using XRTool.Util;
using XRTool.WorldUI;
using System.Collections;
using UnityEditor;
using ShadowStudio.Model;
using UnityEngine.UIElements;
using static BoundingBox;
namespace ShadowStudio.Tool
{
///
/// 编辑状态
///
public enum TransferState
{
///
/// 克隆状态,此状态不同,仅克隆物体时使用此作为参数
/// 克隆完成后,状态自动切换
///
Clone = -1,
///
/// 同步时不存在此状态,仅做初始化处理
///
Init = 0,
///
/// 状态同步开始
///
Start = 1,
///
/// 状态同步执行中
///
Doing = 2,
///
/// 状态同步结束,但是同步并没有完成
///
Stop = 3,
///
/// 状态同步结束,不再对此数据进行同步
///
Over = 4,
}
[RequireComponent(typeof(XBoundingBox))]
[RequireComponent(typeof(XDragComponent))]
///
/// 物体姿态控制器
/// 选中状态,非选中状态
/// 默认所有物体都是非选中状态
/// 当处于选中状态时,此物体只有选中人可编辑,同时将此物体的状态进行同步,其他人能看到选中的状态
///
public class TransferCell : MonoBehaviour, IPointerDownHandler
{
[SerializeField]
///
/// 是否垂直水平面
///
private bool isLookHead;
///
/// 拖拽事件
///
public event Action DragTransfer;
///
/// 缩放事件
///
public event Action ZoomTransfer;
///
/// 旋转事件
///
public event Action RoteTransfer;
///
/// 编辑事件
/// 当物体进行拖拽,缩放,旋转时都会触发
///
public event Action EditTransfer;
public event Action TransferStateChange;
public HandleType normalHandType = HandleType.Rotation | HandleType.Scale;
public HandleType editorHandType = HandleType.Rotation | HandleType.Scale | HandleType.AxisScale;
///
/// 选中和非选中的事件
///
//public event Action TransferSelect;
public static TransferCell curActiveCell;
private XDragComponent dragCell;
private XBoundingBox boundBox;
private Coroutine editCoroutine;
private bool isLock;
private TransferState transferState = TransferState.Init;
private bool isCanEditor = true;
private bool isInitBound = false;
///
/// 编辑模式
/// -1代表未编辑
/// 0代表拖拽
/// 1代表旋转
/// 2代表缩放
/// 开始前/结束后要设置为-1
/// 开始后到执行中设置对应的状态
///
private int editType = -1;
private Timer dragTimer;
public float autoDisDrag = 5f;
private Stack postureHistroy;
private Stack postureFuture;
private GameObject boundCell;
private bool isSelect;
[SerializeField]
private bool isDragEnable;
private bool isInit = false;
public event Action TransferDisEnable;
///
/// 后退的栈
///
public Stack PostureBack
{
get
{
if (postureHistroy == null)
{
postureHistroy = new Stack();
}
return postureHistroy;
}
}
///
/// 前进的栈
///
public Stack PostureAhead
{
get
{
if (postureFuture == null)
{
postureFuture = new Stack();
}
return postureFuture;
}
}
///
/// 锁定
///
public bool IsLock
{
get
{
return isLock;
}
set
{
isLock = value;
if (isLock)
{
PostureAhead.Clear();
PostureBack.Clear();
IsDragEnable = false;
SetBoundActive(true);
SetBoundColor(value, Color.yellow);
}
else
{
SetBoundColor(value, Color.white);
if (curActiveCell != this)
{
SetBoundActive(false);
}
}
}
}
///
/// 拖拽组件
///
public XDragComponent DragCell
{
get
{
if (!dragCell)
{
dragCell = GetComponent();
dragCell.PointerDrag.AddListener(OnPointerDrag);
//dragCell.PointerDown.AddListener(OnPointerDown);
dragCell.PointerUp.AddListener(OnPointerUp);
}
return dragCell;
}
}
///
/// 包围盒显示对象
///
public GameObject BoundCell
{
get
{
if (!boundCell)
{
boundCell = UnityUtil.GetBreadthChild(transform, "XRTool.Util.XBoundingBox");
ChangeLayerRecursively(boundCell.transform);
}
return boundCell;
}
}
///
/// 更改层级
///
///
public void ChangeLayerRecursively(Transform parentTransform)
{
// 修改父物体的层级
parentTransform.gameObject.layer = LayerMask.NameToLayer("Arrow");
// 遍历所有子物体,并递归调用ChangeLayerRecursively方法
for (int i = 0; i < parentTransform.childCount; i++)
{
Transform childTransform = parentTransform.GetChild(i);
ChangeLayerRecursively(childTransform);
}
}
///
/// 包围盒算法组件
///
public XBoundingBox BoundBox
{
get
{
if (!boundBox)
{
boundBox = GetComponent();
if (!boundBox)
{
UnityLog.LogError(gameObject.name + "this is no XBoundingBox");
}
else
{
DragTransfer += state => { EditTransfer?.Invoke(state); };
ZoomTransfer += state => { EditTransfer?.Invoke(state); };
RoteTransfer += state => { EditTransfer?.Invoke(state); };
EditTransfer += OnEditTransfer;
boundBox.ScaleStarted.AddListener(OnScaleStarted);
boundBox.Scaling.AddListener(OnScaling);
boundBox.ScaleStopped.AddListener(OnScaleStopped);
boundBox.RotateStarted.AddListener(OnRotateStarted);
boundBox.Rotating.AddListener(OnRotating);
boundBox.RotateStopped.AddListener(OnRotateStopped);
}
}
return boundBox;
}
}
private void OnRotating()
{
RoteTransfer?.Invoke(TransferState.Doing);
}
private void OnScaling()
{
ZoomTransfer?.Invoke(TransferState.Doing);
}
public void SetBoundActive(bool isShow)
{
if (BoundCell)
{
BoundCell.SetActive(isShow);
}
}
///
/// 初始化
///
private void Start()
{
if (BoundBox)
{
TimerMgr.Instance.CreateTimer(() =>
{
IsDragEnable = false;
IsInit = true;
}, 0);
}
}
///
/// 当编辑物体的时候
///
///
public void OnEditTransfer(TransferState state)
{
if (state == TransferState.Start && editType != -1)
{
ClearTime();
AddBackNode(UnityUtil.GetPosture(transform));
}
if (state == TransferState.Stop)
{
ClearTime();
if (autoDisDrag > 0)
{
dragTimer = TimerMgr.Instance.CreateTimer(() => { IsDragEnable = false; }, autoDisDrag);
}
}
TransferState = state;
}
///
/// 清除协程
///
private void ClearEditor()
{
if (editCoroutine != null)
{
StopCoroutine(editCoroutine);
editCoroutine = null;
}
}
///
/// 旋转结束
///
public void OnRotateStopped()
{
ClearEditor();
editType = 1;
RoteTransfer?.Invoke(TransferState.Stop);
editType = -1;
}
///
/// 旋转开始
///
private void OnRotateStarted()
{
ClearEditor();
editType = 1;
RoteTransfer?.Invoke(TransferState.Start);
//editCoroutine = StartCoroutine(EditorCoroutine());
}
///
/// 缩放结束
///
public void OnScaleStopped()
{
ClearEditor();
editType = 2;
ZoomTransfer?.Invoke(TransferState.Stop);
editType = -1;
TimerMgr.Instance.CreateTimer(RemoveBound, 0.01f);
}
///
/// 缩放开始
///
private void OnScaleStarted()
{
ClearEditor();
editType = 2;
ZoomTransfer?.Invoke(TransferState.Start);
//editCoroutine = StartCoroutine(EditorCoroutine());
}
///
/// 编辑的协程
///
///
//private IEnumerator EditorCoroutine()
//{
// while (editType != -1)
// {
// yield return new WaitForFixedUpdate();
// yield return null;
// if (editType == 1)
// {
// RoteTransfer?.Invoke(TransferState.Doing);
// }
// else if (editType == 2)
// {
// ZoomTransfer?.Invoke(TransferState.Doing);
// }
// }
//}
///
/// 当按下的时候
/// 如果物体没有被锁定,处于可操作的状态时,显示操作框
///
///
public void OnPointerDown(PointerEventData eventData)
{
if (IsLock || (SCInputModule.Instance && !SCInputModule.Instance.CanDrag) || !IsCanEditor)
{
return;
}
transform.DOKill();
IsDragEnable = true;
if (!isInitBound)
{
RemoveBound();
}
if (BoundBox)
{
BoundBox.OnPointerDown(eventData);
}
if (DragCell)
{
DragCell.OnPointerDown(eventData);
}
editType = -1;
EditTransfer?.Invoke(TransferState.Start);
}
///
/// 当抬起的时候
///
///
public virtual void OnPointerUp(PointerEventData eventData)
{
if (SCInputModule.Instance && !SCInputModule.Instance.CanDrag || !IsCanEditor)
{
return;
}
if (editType != -1)
{
DragTransfer?.Invoke(TransferState.Stop);
editType = -1;
}
else
{
EditTransfer?.Invoke(TransferState.Stop);
}
ClearTime();
if (autoDisDrag > 0)
{
dragTimer = TimerMgr.Instance.CreateTimer(() => { IsDragEnable = false; }, autoDisDrag);
}
}
///
/// 拖拽事件
///
///
private void OnPointerDrag(PointerEventData eventData)
{
if (editType == -1)
{
editType = 0;
DragTransfer?.Invoke(TransferState.Start);
//EditorTransfer?.Invoke(state, false);
}
if (isLookHead)
{
editType = 1;
}
else
{
editType = 0;
}
//if (isLookHead && GameSession.Instance && GameSession.Instance.gameHead)
//{
// Vector3 pos = GameSession.Instance.gameHead.position;
// pos.y = transform.position.y;
// Vector3 forward = (transform.position - pos).normalized;
// pos.y = 0;
// if (forward != Vector3.zero)
// {
// transform.forward = forward;
// }
//}
DragTransfer?.Invoke(TransferState.Doing);
}
///
/// 添加一个后退的节点
/// 当退出一个前进的节点或者编辑物体的时候添加
///
///
public void AddBackNode(Posture posture)
{
if (PostureBack != null)
{
PostureBack.Push(posture);
}
}
///
/// 退出一个后退的节点
///
public bool PeekBackNode()
{
if (PostureBack != null && PostureBack.Count > 0)
{
AddAheadNode(UnityUtil.GetPosture(transform));
Posture posture = PostureBack.Pop();
DelaySyn(posture, 0.2f);
return true;
}
return false;
}
///
/// 延时控制
///
///
///
public void DelaySyn(Posture posture, float time)
{
ClearTime();
editType = -1;
//EditTransfer?.Invoke(TransferState.Start);
editType = 2;
UnityUtil.SetPosture(transform, posture, time);
///同步3次位置,保持位移的实时性
TimerMgr.Instance.CreateTimer(() =>
{
EditTransfer?.Invoke(TransferState.Doing);
}, time / 4f, 3);
TimerMgr.Instance.CreateTimer(() =>
{
EditTransfer?.Invoke(TransferState.Stop);
editType = -1;
}, time + 0.01f);
}
///
/// 添加一个前进的节点,仅当回退的时候添加
///
///
public void AddAheadNode(Posture posture)
{
if (PostureAhead != null)
{
PostureAhead.Push(posture);
}
}
///
/// 退出一个前进的节点
///
public bool PeekAheadNode()
{
if (PostureAhead != null && PostureAhead.Count > 0)
{
AddBackNode(UnityUtil.GetPosture(transform));
Posture posture = PostureAhead.Pop();
DelaySyn(posture, 0.2f);
return true;
}
return false;
}
///
/// 清理此计时器
///
public void ClearTime()
{
if (dragTimer != null && TimerMgr.Instance)
{
TimerMgr.Instance.DestroyTimer(dragTimer);
}
dragTimer = null;
}
///
/// 重构包围盒
///
///
public void RemoveBound()
{
if (BoundCell)
{
Destroy(BoundCell);
}
BoundBox.Redraw();
isInitBound = true;
}
///
/// 设置编辑框的颜色
/// 用来判定颜色无法被选中的效果
///
///
public void SetBoundColor(bool isLock, Color color)
{
if (BoundBox)
{
BoundBox.SetZoomColor(isLock, color);
}
}
///
/// 获得距离最近的低啊
///
///
///
public Vector3 GetCastPoint(Vector3 point)
{
if (BoundBox)
{
return BoundBox.GetCastPoint(point);
}
return transform.position;
}
///
/// 设置位移编辑激活和失活
///
///
public void SetTransferActive(bool isActive)
{
if (BoundBox && BoundBox.isActiveAndEnabled != isActive)
{
BoundBox.enabled = isActive;
}
if (DragCell && DragCell.isActiveAndEnabled != isActive)
{
DragCell.enabled = isActive;
}
SetBoundActive(isActive);
if (!isActive)
{
DisActiveCell();
}
}
private void OnDisable()
{
ClearTime();
TransferDisEnable?.Invoke();
//IsDragEnable = false;
}
///
/// 设置可操作性
///
public bool IsDragEnable
{
get => isDragEnable;
set
{
isDragEnable = value;
SetTransferActive(isDragEnable);
if (!IsLock)
{
if (isDragEnable)
{
ChangeActive();
}
IsSelect = value;
}
}
}
public bool IsSelect { get => isSelect; set => isSelect = value; }
public TransferState TransferState
{
get => transferState; set
{
if (transferState != value)
{
transferState = value;
TransferStateChange?.Invoke(transferState);
}
}
}
public bool IsInit { get => isInit; set => isInit = value; }
public void ChangeActive()
{
if (curActiveCell && curActiveCell != this)
{
if (!curActiveCell.IsLock)
{
curActiveCell.IsDragEnable = false;
}
}
if (!IsLock)
{
if (curActiveCell != this)
{
curActiveCell = this;
//TransferSelect?.Invoke(this, true);
}
if (curActiveCell)
{
curActiveCell.SetBoundActive(true);
}
}
}
public void DisActiveCell()
{
if (curActiveCell == this)
{
EditTransfer?.Invoke(TransferState.Over);
//TransferSelect?.Invoke(this, false);
curActiveCell = null;
}
}
public static void CancelCell()
{
if (curActiveCell)
{
curActiveCell.DisActiveCell();
}
}
///
/// 切换畸形缩放和非畸形缩放
///
///
public void SetScaleModel(bool isJiXing = true)
{
if (BoundBox)
{
BoundBox.SetScaleModel(isJiXing);
}
}
///
/// 畸形设置面板
///
public bool IsJiXingScale
{
get => BoundBox.IsJiXingScale;
set
{
BoundBox.IsJiXingScale = value;
if (value)
{
BoundBox.ActiveHandle = editorHandType;
}
else
{
BoundBox.ActiveHandle = normalHandType;
}
}
}
public bool IsCanEditor { get => isCanEditor; set => isCanEditor = value; }
}
}