Files
ichni_Creator_Studio/Assets/Scripts/DynamicUI/Timeline/TimePointerModule.cs

244 lines
8.8 KiB
C#
Raw Normal View History

2025-02-14 22:04:21 -05:00
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.Editor
{
public partial class TimePointerModule : MonoBehaviour
{
private Timeline timeline => EditorManager.instance.uiManager.timeline;
private SongInformation songInformation => EditorManager.instance.songInformation;
2025-02-14 22:04:21 -05:00
public GameObject timePointerPrefab;
public List<TimePointer> timePointerList;
2025-02-14 22:04:21 -05:00
public RectTransform timePointerArea;
public RectTransform visibleTimePointerArea;
public RectTransform moveTabPoint;//用于显示timeline上的tab
2025-02-14 22:04:21 -05:00
public RectTransform mainTimePointer;
2025-02-14 22:04:21 -05:00
public float intervalUnit;
public float timePointerInterval;
public float sizeNegative, sizePositive;
public int negativePointerAmount; // 负方向指示线的数量
public int positivePointerAmount, totalPointerAmount;
2025-02-14 22:04:21 -05:00
/// <summary>
/// delay时间区间中(-delay, 0)的距离偏移量
/// </summary>
public float delayDistanceOffset;
2025-02-14 22:04:21 -05:00
public float leftSideSongTime, rightSideSongTime, songTimeDistance;
private void Start()
{
Observable.NextFrame().Subscribe(_ =>
{
timePointerList = new List<TimePointer>();
2025-03-09 10:56:58 +08:00
Initialize(songInformation.delay, songInformation.bpm);
2025-02-14 22:04:21 -05:00
});
}
private void Update()
{
if (EditorManager.instance.musicPlayer.isPlaying)
2025-02-14 22:04:21 -05:00
{
SetRange(songInformation.songTime);
2025-02-14 22:04:21 -05:00
}
2025-02-14 22:04:21 -05:00
timePointerList.ForEach(pointer =>
{
bool isActive = pointer.time >= leftSideSongTime && pointer.time <= rightSideSongTime;
2025-05-10 23:55:51 -04:00
if(isActive != pointer.gameObject.activeSelf) pointer.gameObject.SetActive(isActive);
2025-02-14 22:04:21 -05:00
});
2025-03-16 00:42:27 +08:00
if (OnePointer != null) moveTabPoint.localPosition =
new Vector3(timePointerArea.localPosition.x + OnePointer.transform.localPosition.x - 30f, 0, 0);
2025-03-09 10:56:58 +08:00
foreach (var i in moveTabPoint.transform.GetComponentsInChildren<SubTab>())
{
i.gameObject.transform.localScale = i.Time >= timeline.songTime ? Vector3.one : Vector3.zero;
}
2025-02-14 22:04:21 -05:00
}
/// <summary>
/// 初始化所有Timeline指示线
/// </summary>
/// <param name="delay"></param>
/// <param name="bpm"></param>
public void Initialize(float delay, float bpm)
{
2025-04-19 23:21:27 +08:00
timePointerInterval = 80;
2025-02-14 22:04:21 -05:00
ClearPointers();
2025-02-14 22:04:21 -05:00
int beatDivider = 1;
2025-02-14 22:04:21 -05:00
intervalUnit = (60f / bpm) / beatDivider * 1000;
2025-02-14 22:04:21 -05:00
sizeNegative = delay * beatDivider / timeline.timePerBeat;
// 计算负方向指示线的数量
2025-02-14 22:04:21 -05:00
negativePointerAmount = Mathf.CeilToInt(sizeNegative);
sizePositive = songInformation.song.length * beatDivider / timeline.timePerBeat;
2025-02-14 22:04:21 -05:00
positivePointerAmount = Mathf.CeilToInt(sizePositive);
2025-02-14 22:04:21 -05:00
totalPointerAmount = negativePointerAmount + positivePointerAmount;
timePointerArea.sizeDelta = new Vector2(timePointerInterval * (sizeNegative + sizePositive), 60f);
delayDistanceOffset = timePointerInterval * (negativePointerAmount - sizeNegative);
leftSideSongTime = timeline.beatmapStartTime;
rightSideSongTime = timeline.timePerBeat * (visibleTimePointerArea.rect.width / timePointerInterval);
songTimeDistance = rightSideSongTime;
for (int i = -negativePointerAmount; i <= positivePointerAmount; i++)
{
CreatePointer(beatDivider, i);
}
2025-02-14 22:04:21 -05:00
//ChangeSongTimeDistance(0);
SetRange(timeline.beatmapStartTime);
}
}
2025-02-14 22:04:21 -05:00
public partial class TimePointerModule
{
/// <summary>
/// 设置Timeline的显示区间区间宽度使用当前的区间宽度
/// </summary>
/// <param name="startTime">开始时间,结束时间即(开始时间+区间宽度)</param>
public void SetRange(float startTime)
{
startTime = Mathf.Clamp(startTime, timeline.beatmapStartTime, songInformation.song.length);
timePointerArea.anchoredPosition =
new Vector2((timePointerArea.sizeDelta.x / 2) -
(startTime + songInformation.delay) / timeline.timePerBeat * timePointerInterval, 0);
2025-02-14 22:04:21 -05:00
float proportion = mainTimePointer.anchoredPosition.x / visibleTimePointerArea.rect.width;
leftSideSongTime = startTime - songTimeDistance * proportion;
rightSideSongTime = startTime + songTimeDistance * (1 - proportion);
}
2025-02-14 22:04:21 -05:00
/// <summary>
/// 生成指示线
/// </summary>
/// <param name="beatDivider">细分X分音符</param>
/// <param name="index"></param>
TimePointer OnePointer = null;//第一个pointer
2025-02-14 22:04:21 -05:00
private void CreatePointer(int beatDivider, int index)
{
TimePointer pointer = Instantiate(timePointerPrefab, timePointerArea).GetComponent<TimePointer>();
timePointerList.Add(pointer);
pointer.index = index;
pointer.GetComponent<RectTransform>().anchoredPosition =
new Vector2((index + negativePointerAmount) * timePointerInterval + 15f - delayDistanceOffset, 0);
pointer.time = index * intervalUnit / 1000f;
pointer.intervalUnitText.text = Mathf.RoundToInt(index * intervalUnit).ToString();
if (index == 0)
{
OnePointer = pointer;
}
if (beatDivider > 1)
{
}
2025-02-14 22:04:21 -05:00
}
2025-02-14 22:04:21 -05:00
/// <summary>
/// 更新指示线位置
/// </summary>
public void UpdatePointers()
2025-02-14 22:04:21 -05:00
{
// 计算延迟距离偏移量
2025-02-14 22:04:21 -05:00
delayDistanceOffset = timePointerInterval * (negativePointerAmount - sizeNegative);
// 更新指示线区域的大小
2025-02-14 22:04:21 -05:00
timePointerArea.sizeDelta = new Vector2(timePointerInterval * totalPointerAmount, 55f);
// 更新每个指示线的位置
2025-02-14 22:04:21 -05:00
foreach (var pointer in timePointerList)
{
pointer.GetComponent<RectTransform>().anchoredPosition =
new Vector2((pointer.index + negativePointerAmount) * timePointerInterval + 15f - delayDistanceOffset, 0);
}
}
2025-02-14 22:04:21 -05:00
/// <summary>
/// 清楚所有指示线
/// </summary>
private void ClearPointers()
{
foreach (var pointer in timePointerList)
{
Destroy(pointer.gameObject);
}
timePointerList.Clear();
}
2025-02-14 22:04:21 -05:00
/// <summary>
/// 缩放时间线的展示时间宽度
/// </summary>
/// <param name="value">增减值</param>
public void ChangeSongTimeDistance(float value)
{
float oldDistance = songTimeDistance;
float changedDistance = songTimeDistance + value;
float songLength = songInformation.song.length;
if (changedDistance < 1 || changedDistance > songLength)
{
return;
}
float finalDistance = 0, finalValue = 0;
float superfluousDistance = changedDistance - songLength;
if (superfluousDistance > 0)
{
finalDistance = songLength;
finalValue = value - superfluousDistance;
}
else
{
finalDistance = changedDistance;
finalValue = value;
}
songTimeDistance = finalDistance;
float proportion = mainTimePointer.anchoredPosition.x /
visibleTimePointerArea.rect.width;
leftSideSongTime -= finalValue * (proportion);
rightSideSongTime += finalValue * (1 - proportion);
if (leftSideSongTime < -songInformation.delay)
{
rightSideSongTime += Mathf.Abs(leftSideSongTime);
leftSideSongTime = -songInformation.delay;
}
else if (rightSideSongTime > songLength)
{
leftSideSongTime -= (rightSideSongTime - songLength);
rightSideSongTime = songLength;
}
timePointerInterval = timePointerInterval / finalDistance * oldDistance;
UpdatePointers();
//UpdateListItems();
SetRange(leftSideSongTime);
}
}
}