Timeline
This commit is contained in:
52
Assets/Scripts/DynamicUI/Timeline/MusicPlayer.cs
Normal file
52
Assets/Scripts/DynamicUI/Timeline/MusicPlayer.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class MusicPlayer : MonoBehaviour
|
||||
{
|
||||
public bool isPlaying;
|
||||
public AudioSource audioSource;
|
||||
|
||||
public Button playButton;
|
||||
public Button pauseButton;
|
||||
public Button stopButton;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
playButton.onClick.AddListener(PlayMusic);
|
||||
pauseButton.onClick.AddListener(PauseMusic);
|
||||
stopButton.onClick.AddListener(StopMusic);
|
||||
}
|
||||
|
||||
public void PlayMusic()
|
||||
{
|
||||
isPlaying = true;
|
||||
Trail.SetAllTrails(true, false);
|
||||
EditorManager.instance.songInformation.songTime = audioSource.time;
|
||||
audioSource.Play();
|
||||
}
|
||||
|
||||
public void PauseMusic()
|
||||
{
|
||||
isPlaying = false;
|
||||
Trail.SetAllTrails(false, false);
|
||||
EditorManager.instance.songInformation.songTime = audioSource.time;
|
||||
audioSource.Pause();
|
||||
}
|
||||
|
||||
public void StopMusic()
|
||||
{
|
||||
isPlaying = false;
|
||||
Trail.SetAllTrails(false, true);
|
||||
EditorManager.instance.songInformation.songTime = 0;
|
||||
audioSource.Stop();
|
||||
EditorManager.instance.uiManager.timeline.timePointerModule.SetRange(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/DynamicUI/Timeline/MusicPlayer.cs.meta
Normal file
11
Assets/Scripts/DynamicUI/Timeline/MusicPlayer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d97c1cf488304279b0c7c7bdb1fb3d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Assets/Scripts/DynamicUI/Timeline/TimeInfoModule.cs
Normal file
18
Assets/Scripts/DynamicUI/Timeline/TimeInfoModule.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class TimeInfoModule : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/DynamicUI/Timeline/TimeInfoModule.cs.meta
Normal file
11
Assets/Scripts/DynamicUI/Timeline/TimeInfoModule.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5b697045922f4d4d90c9f8b499b5ac6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Assets/Scripts/DynamicUI/Timeline/TimePointer.cs
Normal file
15
Assets/Scripts/DynamicUI/Timeline/TimePointer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class TimePointer : MonoBehaviour
|
||||
{
|
||||
public TMP_Text intervalUnitText;
|
||||
public float time;
|
||||
public int index;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/DynamicUI/Timeline/TimePointer.cs.meta
Normal file
11
Assets/Scripts/DynamicUI/Timeline/TimePointer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 644b6d8f3317b4ed783580811fef5da7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
216
Assets/Scripts/DynamicUI/Timeline/TimePointerModule.cs
Normal file
216
Assets/Scripts/DynamicUI/Timeline/TimePointerModule.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
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;
|
||||
|
||||
public GameObject timePointerPrefab;
|
||||
public List<TimePointer> timePointerList;
|
||||
|
||||
public RectTransform timePointerArea;
|
||||
public RectTransform visibleTimePointerArea;
|
||||
|
||||
public RectTransform mainTimePointer;
|
||||
|
||||
public float intervalUnit;
|
||||
public float timePointerInterval;
|
||||
public float sizeNegative, sizePositive;
|
||||
public int negativePointerAmount, positivePointerAmount, totalPointerAmount;
|
||||
/// <summary>
|
||||
/// delay时间区间中,(-delay, 0)的距离偏移量
|
||||
/// </summary>
|
||||
public float delayDistanceOffset;
|
||||
|
||||
public float leftSideSongTime, rightSideSongTime, songTimeDistance;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Observable.NextFrame().Subscribe(_ =>
|
||||
{
|
||||
timePointerList = new List<TimePointer>();
|
||||
Initialize(2, 120);
|
||||
});
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (timeline.musicPlayer.isPlaying)
|
||||
{
|
||||
songInformation.songTime = timeline.musicPlayer.audioSource.time;
|
||||
SetRange(songInformation.songTime);
|
||||
}
|
||||
|
||||
timePointerList.ForEach(pointer =>
|
||||
{
|
||||
bool isActive = pointer.time >= leftSideSongTime && pointer.time <= rightSideSongTime;
|
||||
pointer.gameObject.SetActive(isActive);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化所有Timeline指示线
|
||||
/// </summary>
|
||||
/// <param name="delay"></param>
|
||||
/// <param name="bpm"></param>
|
||||
public void Initialize(float delay, float bpm)
|
||||
{
|
||||
timePointerInterval = 30;
|
||||
ClearPointers();
|
||||
|
||||
int beatDivider = 1;
|
||||
|
||||
intervalUnit = (60f / bpm) / beatDivider * 1000;
|
||||
|
||||
sizeNegative = delay * beatDivider / timeline.timePerBeat;
|
||||
sizePositive = songInformation.song.length * beatDivider / timeline.timePerBeat;
|
||||
|
||||
negativePointerAmount = Mathf.CeilToInt(sizeNegative);
|
||||
positivePointerAmount = Mathf.CeilToInt(sizePositive);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//ChangeSongTimeDistance(0);
|
||||
SetRange(timeline.beatmapStartTime);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
float proportion = mainTimePointer.anchoredPosition.x / visibleTimePointerArea.rect.width;
|
||||
|
||||
leftSideSongTime = startTime - songTimeDistance * proportion;
|
||||
rightSideSongTime = startTime + songTimeDistance * (1 - proportion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成指示线
|
||||
/// </summary>
|
||||
/// <param name="beatDivider">细分X分音符</param>
|
||||
/// <param name="index"></param>
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新指示线位置
|
||||
/// </summary>
|
||||
private void UpdatePointers()
|
||||
{
|
||||
delayDistanceOffset = timePointerInterval * (negativePointerAmount - sizeNegative);
|
||||
timePointerArea.sizeDelta = new Vector2(timePointerInterval * totalPointerAmount, 55f);
|
||||
|
||||
foreach (var pointer in timePointerList)
|
||||
{
|
||||
pointer.GetComponent<RectTransform>().anchoredPosition =
|
||||
new Vector2((pointer.index + negativePointerAmount) * timePointerInterval + 15f - delayDistanceOffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清楚所有指示线
|
||||
/// </summary>
|
||||
private void ClearPointers()
|
||||
{
|
||||
foreach (var pointer in timePointerList)
|
||||
{
|
||||
Destroy(pointer.gameObject);
|
||||
}
|
||||
timePointerList.Clear();
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/DynamicUI/Timeline/TimePointerModule.cs.meta
Normal file
11
Assets/Scripts/DynamicUI/Timeline/TimePointerModule.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dab236b468fc9494a93c37370df10557
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Assets/Scripts/DynamicUI/Timeline/Timeline.cs
Normal file
17
Assets/Scripts/DynamicUI/Timeline/Timeline.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class Timeline : MonoBehaviour
|
||||
{
|
||||
public float songTime => EditorManager.instance.songInformation.songTime;
|
||||
public float songBeat => EditorManager.instance.songInformation.songBeat;
|
||||
public float beatmapStartTime => -EditorManager.instance.songInformation.delay;
|
||||
public float timePerBeat => 60f / EditorManager.instance.songInformation.bpm;
|
||||
|
||||
public TimePointerModule timePointerModule;
|
||||
public MusicPlayer musicPlayer;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/DynamicUI/Timeline/Timeline.cs.meta
Normal file
11
Assets/Scripts/DynamicUI/Timeline/Timeline.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aee0e6022210846a7bd6e0e20af73e3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user