Files
Hasebe/Assets/Code/OfficeGame/BattleMode/UI/BattleTimelinePanel.cs
T
2026-10-27 20:47:16 +03:00

91 lines
3.2 KiB
C#

using System.Collections.Generic;
using System.Threading;
using Code.Infrastructure.UI;
using Code.OfficeGame.BattleMode.Timeline;
using Cysharp.Threading.Tasks;
using LitMotion;
using LitMotion.Extensions;
using UnityEngine;
namespace Code.OfficeGame.BattleMode.UI
{
public class BattleTimelinePanel : UIPanel
{
[SerializeField] private int maxFrames = 250;
[SerializeField] private GameObject timelineKeyPrefab;
[SerializeField] private float duration = 0.35f;
[SerializeField] private RectTransform timelineItself;
// TODO Вырезать или пощадить
private readonly Dictionary<EntityId, int> _entityEndFrames = new();
private readonly Dictionary<EntityId, RectTransform> _entityKeys = new();
private int _lastKnownCurrentFrame;
private MotionHandle _motionHandle;
public void SetAction(TimelineBattleAction action)
{
_entityEndFrames[action.EntityId] = action.Frame;
if (!_entityKeys.TryGetValue(action.EntityId, out RectTransform keyRect))
{
keyRect = (RectTransform)Instantiate(timelineKeyPrefab, timelineItself).transform;
_entityKeys[action.EntityId] = keyRect;
}
UpdateKeyPosition(keyRect, action.Frame - _lastKnownCurrentFrame);
}
public void OnFrameTick(int currentFrame)
{
_lastKnownCurrentFrame = currentFrame;
foreach (var (entityId, endFrame) in _entityEndFrames)
{
if (_entityKeys.TryGetValue(entityId, out RectTransform keyRect))
{
int remainingFrames = Mathf.Max(0, endFrame - currentFrame);
UpdateKeyPosition(keyRect, remainingFrames);
}
}
}
private void UpdateKeyPosition(RectTransform keyRect, int relativeFrame)
{
var rectWidth = timelineItself.rect.width;
var frameSize = rectWidth / maxFrames;
keyRect.anchoredPosition = new Vector2(frameSize * relativeFrame - rectWidth / 2f, 0f);
}
public override async UniTask Open(CancellationToken cts = default)
{
gameObject.SetActive(true);
float startY = -((RectTransform)transform).rect.height;
float targetY = 0f;
_motionHandle = LMotion.Create(startY, targetY, duration)
.WithEase(Ease.OutCubic)
.WithScheduler(MotionScheduler.UpdateIgnoreTimeScale)
.BindToAnchoredPositionY((RectTransform)transform);
await _motionHandle.ToUniTask(cts);
}
public override async UniTask Close(CancellationToken cts = default)
{
float startY = 0;
float targetY = ((RectTransform)transform).rect.height;
_motionHandle = LMotion.Create(startY, targetY, duration)
.WithEase(Ease.InBack)
.WithScheduler(MotionScheduler.UpdateIgnoreTimeScale)
.BindToAnchoredPositionY((RectTransform)transform);
await _motionHandle.ToUniTask(cts);
gameObject.SetActive(false);
}
}
}