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