537 lines
18 KiB
C#
537 lines
18 KiB
C#
// 预览和拖动用的方块组
|
|
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<RectTransform>();
|
|
// canvasGroup = GetComponent<CanvasGroup>();
|
|
_canvas = GetComponentInParent<Canvas>();
|
|
|
|
_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($"<color=yellow>PieceRender => {message}</color>");
|
|
}
|
|
|
|
private static void ELog(string message)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!EventCubeMeltLogPolicy.EnableELog) return;
|
|
Debug.Log($"<color=orange> PieceRender => {message} </color>");
|
|
#endif
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region 自定义函数
|
|
public void Initialize(int height, int width)
|
|
{
|
|
ELog($"Initialize height={height} width={width} index={Index}");
|
|
|
|
_thisEventManager = GContext.container.Resolve<EventCubeMeltManager>();
|
|
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<GridLayoutGroup>();
|
|
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<CellRenderer>();
|
|
if (!cellRenderer)
|
|
cellRenderer = _cellTransforms[row, col].gameObject.AddComponent<CellRenderer>();
|
|
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<CellRenderer>();
|
|
if (!cellRenderer)
|
|
cellRenderer = _cellTransforms[row, col].gameObject.AddComponent<CellRenderer>();
|
|
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<Canvas>();
|
|
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<CellRenderer>();
|
|
if (!cellRenderer)
|
|
{
|
|
cellRenderer = _cellTransforms[row, col].gameObject.AddComponent<CellRenderer>();
|
|
}
|
|
// 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<CanvasGroup>();
|
|
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<bool> 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<Task>
|
|
// {
|
|
// 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;
|
|
}
|
|
}
|
|
} |