// 预览和拖动用的方块组 using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using asap.core; using DG.Tweening; using EventCubeMelt.UI; using EventCubeMelt.Utils; using Game; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using Debug = UnityEngine.Debug; namespace EventCubeMelt { public class PieceRenderer : MonoBehaviour,IPointerDownHandler,IPointerUpHandler, IBeginDragHandler, IDragHandler, IEndDragHandler { public int OffsetY { get; set; } = 320; public int OffsetYWithDelta { get; set; } = 320; public float ScaleFactor { get; set; } = 100F / 40; // 棋盘目标大小 public float TargetSize { get; set; } = 100F; public float DistanceFactor { get; set; } = 0.2f; // 当前的RectTransform [HideInInspector] public RectTransform rectTransform; // 删除 public TetrominoData Data { get; set; } public int Index { get; set; } // 对应的数值 // private Transform[,] _cellTransforms; // 记录当前顶端坐标的位置 private Vector2Int _currentPosition; // 数值 private EventCubeMeltManager _thisEventManager; // 记录当前 picece 和 第一个顶点的 位置 public Vector2 OffsetXY { get; set; } [SerializeField] private BoardRenderer boardRenderer; // private UIDragManager _dragManager; // private Canvas _canvas; //- 可拖动 private PieceRenderer _dragPiece; private bool _isDrag = false; private Transform _childRoot; private Transform _hotPlace; #region 周期函数 private void Awake() { rectTransform = GetComponent(); // canvasGroup = GetComponent(); _canvas = GetComponentInParent(); _hotPlace = transform.Find("hot_place"); _childRoot = transform.Find("ChildRoot"); } private void Start() { _dragManager = UIDragManager.Instance; } private void OnEnable() { } private void OnDisable() { } private void OnDestroy() { } #endregion #region Log private static void LogWarning(string message) { Debug.LogWarning($"PieceRender => {message}"); } private static void ELog(string message) { #if UNITY_EDITOR if (!EventCubeMeltLogPolicy.EnableELog) return; Debug.Log($" PieceRender => {message} "); #endif } #endregion #region 自定义函数 public void Initialize(int height, int width) { ELog($"Initialize height={height} width={width} index={Index}"); _thisEventManager = GContext.container.Resolve(); var datas = _thisEventManager.GetMeltPieceData(Index); Data = new TetrominoData(height, width); ELog($"Initialize dataLoaded dataRef={Data} pieceDataCount={datas?.Count ?? 0}"); Data.LoadData(datas); CreateGrid(); var layout = _childRoot.GetComponent(); OffsetXY = new Vector2((layout.cellSize.x + layout.spacing.x) * 2, (layout.cellSize.y + layout.spacing.y) * 2) * -1; // Log($"OffsetXY -> {OffsetXY}"); } public void LoadDataToGrid(TetrominoData data) { Data = (TetrominoData)data.Clone(); CreateGrid(); UpdateGridVisual(); } public void UpdatePiece() { ELog($"UpdatePiece {Index} "); var datas = _thisEventManager.GetMeltPieceData(Index); Data.LoadData(datas); UpdateGridVisual(); } private async void UpdateGridVisual() { for (var row = 0; row < Data.Height; ++row) { for (var col = 0; col < Data.Width; ++col) { var cellRenderer = _cellTransforms[row, col].GetComponent(); if (!cellRenderer) cellRenderer = _cellTransforms[row, col].gameObject.AddComponent(); cellRenderer?.UpdatePieceVisual(Data[row,col], Data[row,col-1],Data[row +1,col - 1] ,Data[row +1,col ] ); } } } public void CleanPiece() { for (var row = 0; row < Data.Height; ++row) { for (var col = 0; col < Data.Width; ++col) { var cellRenderer = _cellTransforms[row, col].GetComponent(); if (!cellRenderer) cellRenderer = _cellTransforms[row, col].gameObject.AddComponent(); cellRenderer?.UpdatePieceVisual(CellType.Empty); cellRenderer?.SetShadowAndDisplay(ShadowType.None); } } } public void UpdatePieceWithAnim(Sequence sequence,float scaleDuration, float delay) { UpdatePiece(); transform.localScale = Vector3.zero; sequence.Insert(delay, transform.DOScale(1.0f, scaleDuration) .SetEase(Ease.OutBack)); // 使用弹性缓动效果,看起来更自然 } //- // 返回最左上角的位置,然后进入检测 public Vector3 GetPiecePosition() { var diff = GetCenterPosition() - GetFirstPosition(); // ELog($"GetPiecePosition0 -> {diff}"); var rt = GetScreenPosition() - diff; return rt; } public Vector3 GetFirstPosition() { var cb0 = _childRoot.Find("CubeMeltCube_01"); // return cb0.transform.position - new Vector3(TargetSize * 0.5f -45f,0); return cb0.transform.position; } public Vector3 GetCenterPosition() { var cb = _childRoot.Find("CubeMeltCube_13"); return cb.transform.position; } public Vector3 GetScreenPosition() { var canvas = GetComponentInParent(); var screenPosition = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, transform.position); return screenPosition; } public void CreateGrid() { _cellTransforms = new Transform[Data.Width,Data.Height]; var cellList = GetDirectChildrenArray(); // 添加组件 for (var row = 0; row < Data.Height; ++row) { for (var col = 0; col < Data.Width; ++col) { _cellTransforms[row, col] = cellList[row * Data.Width + col]; var cellRenderer = _cellTransforms[row, col].GetComponent(); if (!cellRenderer) { cellRenderer = _cellTransforms[row, col].gameObject.AddComponent(); } // cellRenderer?.InitForPiece(); } } } private Transform[] GetDirectChildrenArray() { _childRoot = transform.Find("ChildRoot"); if (!_childRoot) _childRoot = transform; var arr = new Transform[_childRoot.childCount]; for (var i = 0; i < arr.Length; i++) arr[i] = _childRoot.GetChild(i); return arr; } #endregion public void BeginVisual() { // ELog($"BeginVisual-> {gameObject.name}"); } public void SetBlocksRaycasts(bool b) { var canvasGroupArr = GetComponentsInChildren(); foreach (var canvasGroup in canvasGroupArr) { canvasGroup.blocksRaycasts = b; } } public void CopyData(PieceRenderer otherPiece) { OffsetXY = otherPiece.OffsetXY; Data = otherPiece.Data; OffsetY = otherPiece.OffsetY; ScaleFactor = otherPiece.ScaleFactor; TargetSize = otherPiece.TargetSize; } private async Task SpawnNewPieceData(int index, int clearCount) { if (!_isIgnoreChecked) { _isIgnoreChecked = true; _sw = Stopwatch.StartNew(); await _thisEventManager.SpawnNewPiece(index,clearCount); _sw.Stop(); long el = _sw.ElapsedMilliseconds; _isIgnoreReqDelay = (el > 200); } else { await _thisEventManager.SpawnNewPiece(index,clearCount); } return _isIgnoreReqDelay; } // 生成新的Piece public async Task SpawnNewPiece(int clearCount = 0) { await _thisEventManager.SpawnNewPiece(Index,clearCount); RunSpawnNewPiece(); } private void RunSpawnNewPiece() { { UpdatePiece(); RestorePiece(); } transform.localScale = Vector3.zero; transform.DOScale(1.0f, 0.3f).SetEase(Ease.OutBack); ELog("RunSpawnNewPieceFinished"); } public void DestroyDragPiece() { Destroy(_dragPiece?.gameObject); _dragPiece = null; } public void OnPointerDown(PointerEventData eventData) { ELog($"OnPointDown-> {gameObject.name}"); if (_thisEventManager == null) return; if (_thisEventManager.EventData == null) return; if (_thisEventManager.EventData.IsFinished) return; if (_thisEventManager.EventData.TicketCount <= 0) { GContext.Publish(new EventCubeMeltShowNeoNormalPack()); return; } if (_thisEventManager.IsInGuideAnim()) GContext.Publish(new EventCubeMeltGuideFingerHide()); GContext.Publish(new EventUISound("audio_ui_block_cube_up")); CreateDragPiece(eventData); SetPieceVisible(false); } public void OnPointerUp(PointerEventData eventData) { // throw new NotImplementedException(); ELog($"OnPointerUp -> {eventData} {gameObject.name}"); // if (!_isDrag) { RestorePiece(); } } public void RestorePiece() { DestroyDragPiece(); SetPieceVisible(true); } private void SetPieceVisible(bool visible) { foreach (Transform trans in transform) { trans.gameObject.SetActive(visible); } } public void OnBeginDrag(PointerEventData eventData) { ELog($"OnBeginDrag-> {gameObject.name} _dragPiece: {_dragPiece}"); if (_dragPiece) { _isDrag = true; // _dragPiece.BeginVisual(); _dragPiece.SetBlocksRaycasts(false); _vibrationDelta = true; SaveOriginPos(eventData.position); var diff = UpdateDragDistance(eventData); UpdateDragPiecePos(eventData,diff); } } private bool _vibrationDelta; private void OnDragVibration() { if (_vibrationDelta) { GContext.Publish(new VibrationData(HapticTypes.SoftImpact)); _vibrationDelta = false; } } public void OnDrag(PointerEventData eventData) { // ELog($"OnDrag-> {gameObject.name} _dragPiece: {_dragPiece}"); if (!_dragPiece) return; OnDragVibration(); var diff = UpdateDragDistance(eventData); UpdateDragPiecePos(eventData,diff); // EventSystem 自动驱动 boardRenderer.UpdateVisual(_dragPiece,eventData.position); } private float UpdateDragDistance(PointerEventData eventData) { var diff = eventData.position.y - _originPos.y; // ELog($"UpdateDragDistance -> {diff}"); if (diff < 0) diff = 0; return diff * DistanceFactor; } // ReSharper disable once AsyncVoidMethod public void OnEndDrag(PointerEventData eventData) { ELog($"OnEndDrag-> {gameObject.name}"); if (_dragPiece) { CheckEndDrag(eventData); } _isDrag = false; } // private ProfileScope ps = new ProfileScope(); private Stopwatch _sw; // 需要先测试一下是否需要高这个东西 private bool _isIgnoreReqDelay = false; private bool _isIgnoreChecked = false; public async void CheckEndDrag(PointerEventData eventData) { await Awaiters.NextFrame; //- 处理最后 GContext.Publish(new EventUISound("audio_ui_block_cube_down")); if (_thisEventManager.IsInGuideAnim()) { if ( Index != _thisEventManager.GuideIndex || !boardRenderer.SatisfyNewGuide1(_dragPiece)) { GContext.Publish(new VibrationData(HapticTypes.RigidImpact)); boardRenderer.ClearGhostGrid(true); boardRenderer.RemoveLineEffect(); boardRenderer.RemoveDisappearEffect(); // DestroyDragPiece(); // SetPieceVisible(true); PubBackPiece(); GContext.Publish(new EventNewGuideFingerStart()); return; } GContext.Publish(new EventNewGuideFingerFinish()); _thisEventManager?.SetIsInGuideAnim(false); } var ret = boardRenderer.TryPlaceDown(_dragPiece); if (ret) { // ps.L_ProfileScope("TryPlaceDown"); _thisEventManager?.AddTicket(-1); // ClearGridAndCollectItems( pieceId,out rows,out cols, out list,out listBomb); boardRenderer.ClearGridAndCollectItems(Index, out var rows,out var cols, out var list,out var listBomb ); var clearCount = rows.Count + cols.Count; // ps.L_ProfileScopeEnd(); // ps.L_ProfileScope("SpawnNewPiece"); // if (!_isIgnoreChecked) // { // _isIgnoreChecked = true; // _sw = Stopwatch.StartNew(); // await SpawnNewPiece(clearCount); // _sw.Stop(); // long el = _sw.ElapsedMilliseconds; // _isIgnoreReqDelay = (el > 200); // } // else // { // await SpawnNewPiece(clearCount); // } // ps.L_ProfileScopeEnd(); // ps.L_ProfileScope("RestorePiece"); // ps.L_ProfileScopeEnd(); // ps.L_ProfileScope("OnGridAnimation"); ELog($"CheckEndDrag ignoreReqDelay={_isIgnoreReqDelay}"); DestroyDragPiece(); var task1 = SpawnNewPieceData(Index, clearCount); var task2 = boardRenderer.OnGridAnimation(Index, rows, cols, list, listBomb, false); await task1; // var taskList = new List // { // SpawnNewPieceData(Index,clearCount), // boardRenderer.OnGridAnimation(Index, rows, cols, list, listBomb,true) // }; // await Task.WhenAll(taskList); RunSpawnNewPiece(); await task2; } else { GContext.Publish(new VibrationData(HapticTypes.RigidImpact)); PubBackPiece(); } } private void PubBackPiece() { RestorePiece(); GContext.Publish(new EventUISound("audio_ui_block_cube_back_down")); } private void UpdateDragPiecePos(PointerEventData e,float diff = 0 ) { var offset = _dragPiece.OffsetYWithDelta + diff; var screenPosition = e.position; var scrPos = new Vector2(screenPosition.x, screenPosition.y + offset); RectTransformUtility.ScreenPointToWorldPointInRectangle( _dragManager.dragContainer, scrPos, _canvas.worldCamera, out var worldPos); _dragPiece.rectTransform.position = worldPos; } private async void CreateDragPiece(PointerEventData eventData) { try { _dragPiece = _dragManager.CreateDragPiece(gameObject, eventData); _dragPiece.gameObject.SetActive(false); await Awaiters.NextFrame; _dragPiece.gameObject.SetActive(true); _dragPiece.BeginVisual(); } catch (Exception e) { LogWarning($"CreateDragPieceFailed error={e.Message}"); } } // private Vector3 _originPos = Vector3.zero; public void SaveOriginPos(Vector3 position) { _originPos = position; } } }