314 lines
13 KiB
C#
314 lines
13 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using DG.Tweening;
|
|
using Ichni.RhythmGame;
|
|
using Sirenix.Utilities;
|
|
using TMPro;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.Serialization;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Ichni.Editor
|
|
{
|
|
public partial class Timeline : StaticWindow
|
|
{
|
|
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 GameObject timelineTabRect;
|
|
public TimePointerModule timePointerModule;
|
|
public MusicPlayModule musicPlayModule;
|
|
|
|
private TimePointer MarkedPointer;
|
|
public TMP_InputField TimeField;
|
|
public TMP_InputField BeatField;
|
|
public Slider ProgressSlider;
|
|
public RectTransform GetinputArea;
|
|
|
|
private string BeatText;
|
|
private string TimeText;
|
|
protected override void Start()
|
|
{
|
|
TimeField.onSelect.AddListener(_ => EditorManager.instance.musicPlayer.PauseMusic());
|
|
BeatField.onSelect.AddListener(_ => EditorManager.instance.musicPlayer.PauseMusic());
|
|
ProgressSlider.onValueChanged.AddListener(_ =>
|
|
{
|
|
EditorManager.instance.musicPlayer.PauseMusic();
|
|
EditorManager.instance.songInformation.songTime = (ProgressSlider.value * EditorManager.instance.songInformation.songLength) - EditorManager.instance.songInformation.offset;
|
|
UpdateTime();
|
|
});
|
|
|
|
}
|
|
public void Update()
|
|
{
|
|
if (EditorManager.instance.musicPlayer.isPlaying)
|
|
{
|
|
UpdateTime();
|
|
|
|
|
|
}
|
|
|
|
if (RectTransformUtility.RectangleContainsScreenPoint(GetinputArea, Mouse.current.position.ReadValue()))
|
|
{
|
|
|
|
DetectSetRange();
|
|
DetectPointer();
|
|
}
|
|
|
|
|
|
}
|
|
private void DetectSetRange()
|
|
{
|
|
if (Keyboard.current.spaceKey.wasPressedThisFrame)
|
|
{
|
|
|
|
EditorManager.instance.musicPlayer.PlayMusic();
|
|
|
|
}
|
|
if (Mouse.current.scroll.ReadValue().y != 0)
|
|
{
|
|
|
|
if (Keyboard.current.leftCtrlKey.isPressed || Keyboard.current.rightCtrlKey.isPressed)
|
|
{
|
|
float scrollValue = Mouse.current.scroll.ReadValue().y / 12;
|
|
if (timePointerModule.timePointerInterval + scrollValue >= 30)
|
|
{
|
|
timePointerModule.timePointerInterval += scrollValue;
|
|
timePointerModule.SortPos();
|
|
SetTimeLine(EditorManager.instance.uiManager.inspector.connectedGameElement);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (Mouse.current.scroll.ReadValue().y >= 0)
|
|
{
|
|
SetTime((EditorManager.instance.songInformation.songTime + timePerBeat).ToString());
|
|
}
|
|
else
|
|
{
|
|
if (EditorManager.instance.songInformation.songTime - timePerBeat >= 0)
|
|
SetTime((EditorManager.instance.songInformation.songTime - timePerBeat).ToString());
|
|
else
|
|
SetTime("0");
|
|
|
|
}
|
|
UpdateTime();
|
|
}
|
|
}
|
|
}
|
|
private void DetectPointer()
|
|
{
|
|
if (Mouse.current.leftButton.wasPressedThisFrame)
|
|
{
|
|
foreach (var pointer in timePointerModule.ActivePointer)
|
|
{
|
|
if (RectTransformUtility.RectangleContainsScreenPoint(pointer.intervalUnitText.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
|
{
|
|
GUIUtility.systemCopyBuffer = pointer.intervalUnitText.text;
|
|
LogWindow.Log("Copied Time: " + pointer.intervalUnitText.text + " Marked Pointer");
|
|
if (MarkedPointer != null) MarkedPointer.intervalUnitText.color = Color.white;
|
|
|
|
pointer.intervalUnitText.color = Color.yellow;
|
|
pointer.PlayAnim();
|
|
MarkedPointer = pointer;
|
|
}
|
|
}
|
|
}
|
|
if (Mouse.current.rightButton.wasPressedThisFrame)
|
|
{
|
|
foreach (var pointer in timePointerModule.ActivePointer)
|
|
{
|
|
if (RectTransformUtility.RectangleContainsScreenPoint(pointer.intervalUnitText.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
|
{
|
|
GUIUtility.systemCopyBuffer = Mathf.Abs(pointer.time - MarkedPointer.time).ToString("F3");
|
|
LogWindow.Log("Total Time: " + Mathf.Abs(pointer.time - MarkedPointer.time).ToString("F3"));
|
|
|
|
pointer.PlayAnim();
|
|
pointer.intervalUnitText.color = Color.yellow;
|
|
pointer.intervalUnitText.DOColor(Color.white, 0.5f);
|
|
// 灰色矩形动画效果
|
|
if (MarkedPointer != null && pointer != MarkedPointer)
|
|
{
|
|
var rt1 = pointer.intervalUnitText.GetComponent<RectTransform>();
|
|
var rt2 = MarkedPointer.intervalUnitText.GetComponent<RectTransform>();
|
|
var parentRect = timePointerModule.timePointerContainer;
|
|
|
|
// 世界坐标转父级本地坐标
|
|
Vector3 localPos1 = parentRect.InverseTransformPoint(rt1.position);
|
|
Vector3 localPos2 = parentRect.InverseTransformPoint(rt2.position);
|
|
|
|
float minX = Mathf.Min(localPos1.x, localPos2.x);
|
|
float width = Mathf.Abs(localPos1.x - localPos2.x);
|
|
float minY = Mathf.Min(localPos1.y, localPos2.y);
|
|
float height = Mathf.Max(rt1.rect.height, rt2.rect.height);
|
|
|
|
GameObject rectObj = new GameObject("PointerRangeRect", typeof(RectTransform), typeof(Image));
|
|
rectObj.transform.SetParent(parentRect, false);
|
|
var rectTrans = rectObj.GetComponent<RectTransform>();
|
|
var image = rectObj.GetComponent<Image>();
|
|
image.color = new Color(1f, 1f, 1f, 0.5f);
|
|
|
|
rectTrans.anchorMin = new Vector2(0, 0);
|
|
rectTrans.anchorMax = new Vector2(0, 0);
|
|
rectTrans.pivot = new Vector2(0, 0);
|
|
rectTrans.localPosition = new Vector3(minX, minY - (height / 2), 0);
|
|
rectTrans.sizeDelta = new Vector2(width, height);
|
|
|
|
DOTween.ToAlpha(() => image.color, c => image.color = c, 0f, 1f)
|
|
.OnComplete(() => Destroy(rectObj));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void UpdateTime()
|
|
{
|
|
TimeText = songTime.ToString("F2");
|
|
BeatText = songBeat.ToString("F2");
|
|
if (BeatField.text != BeatText)
|
|
{
|
|
BeatField.text = BeatText;
|
|
}
|
|
if (TimeField.text != TimeText)
|
|
{
|
|
TimeField.text = TimeText;
|
|
}
|
|
ProgressSlider.SetValueWithoutNotify((songTime - EditorManager.instance.songInformation.offset) / EditorManager.instance.songInformation.songLength);
|
|
}
|
|
|
|
private Tweener _activeTweener = null; // 保存当前动画的引用
|
|
public void SetTime(string time)
|
|
{
|
|
EditorManager.instance.musicPlayer.PauseMusic();
|
|
float parsedTime = float.Parse(time);
|
|
float offsetedtime = Mathf.Clamp(parsedTime - EditorManager.instance.songInformation.offset, 0, EditorManager.instance.songInformation.songLength);
|
|
EditorManager.instance.musicPlayer.audioSource.time = offsetedtime;
|
|
if (_activeTweener != null && _activeTweener.IsActive())
|
|
{
|
|
_activeTweener.Complete();
|
|
}
|
|
// 使用 DOTween 来平滑过渡到新的时间
|
|
_activeTweener = DOTween.To(() => EditorManager.instance.songInformation.songTime, x => EditorManager.instance.songInformation.songTime = x, parsedTime, 0.2f)
|
|
.OnUpdate(UpdateTime)
|
|
;
|
|
|
|
// timePointerModule.UpdatePointers();
|
|
// timePointerModule.SetRange(songTime);
|
|
|
|
}
|
|
public void SetBeat(string beat)
|
|
{
|
|
EditorManager.instance.musicPlayer.PauseMusic();
|
|
float parsedTime = float.Parse(beat) * timePerBeat;
|
|
float offsetedtime = Mathf.Clamp(parsedTime - EditorManager.instance.songInformation.offset, 0, EditorManager.instance.songInformation.songLength);
|
|
EditorManager.instance.musicPlayer.audioSource.time = offsetedtime;
|
|
if (_activeTweener != null && _activeTweener.IsActive())
|
|
{
|
|
_activeTweener.Complete();
|
|
}
|
|
|
|
_activeTweener = DOTween.To(() => EditorManager.instance.songInformation.songTime, x => EditorManager.instance.songInformation.songTime = x, parsedTime, 0.2f)
|
|
.OnUpdate(UpdateTime);
|
|
// EditorManager.instance.musicPlayer.audioSource.time = Mathf.Clamp((float.Parse(beat) * timePerBeat) - EditorManager.instance.songInformation.offset, 0, EditorManager.instance.songInformation.songLength);
|
|
// EditorManager.instance.songInformation.songTime = float.Parse(beat) * timePerBeat;
|
|
|
|
// timePointerModule.UpdatePointers();
|
|
// timePointerModule.SetRange(songTime);
|
|
}
|
|
}
|
|
|
|
|
|
public partial class Timeline
|
|
{
|
|
public TimelineTab timelineTabPrefab;
|
|
public Dictionary<Type, TimelineTab> timelineTabList = new Dictionary<Type, TimelineTab>();
|
|
private int TabIndex = 0;
|
|
public void SetTimeLine(GameElement element)//暂时好了(别的类型什么的传时间就好了)
|
|
{
|
|
TabIndex = 0;
|
|
for (int i = timePointerModule.moveTabPoint.childCount - 1; i >= 0; i--)
|
|
{
|
|
var transform = timePointerModule.moveTabPoint.transform.GetChild(i);
|
|
Destroy(transform.gameObject);
|
|
}
|
|
for (int i = timelineTabList.Count - 1; i >= 0; i--)
|
|
{
|
|
Destroy(timelineTabList.ElementAt(i).Value.gameObject);
|
|
timelineTabList.Remove(timelineTabList.ElementAt(i).Key);
|
|
}
|
|
|
|
Elementfind(element);
|
|
|
|
|
|
}
|
|
|
|
public RectTransform moveTabPoint;
|
|
public void Elementfind(GameElement element)
|
|
{
|
|
if (element == null) return;
|
|
foreach (var i in element.childElementList)
|
|
{
|
|
if (i is NoteBase)
|
|
{
|
|
if (!timelineTabList.ContainsKey(i.GetType()))
|
|
{
|
|
Add(i);
|
|
}
|
|
else
|
|
{
|
|
timelineTabList[i.GetType()].AddElement(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (element is NoteBase)
|
|
{
|
|
if (!timelineTabList.ContainsKey(element.GetType()))
|
|
{
|
|
Add(element);
|
|
}
|
|
else
|
|
{
|
|
timelineTabList[element.GetType()].AddElement(element);
|
|
}
|
|
}
|
|
|
|
if (element is Track track)
|
|
{
|
|
var trackTimeSubmodule = track.submoduleList.FirstOrDefault(w => w is TrackTimeSubmodule) as TrackTimeSubmodule;
|
|
if (trackTimeSubmodule != null)
|
|
{
|
|
Add(trackTimeSubmodule);
|
|
}
|
|
}
|
|
|
|
|
|
var timeDurationSubmodule = element.submoduleList.FirstOrDefault(w => w is TimeDurationSubmodule) as TimeDurationSubmodule;
|
|
if (timeDurationSubmodule != null && timeDurationSubmodule.isOverridingDuration)
|
|
{
|
|
Add(timeDurationSubmodule);
|
|
}
|
|
}
|
|
private void Add(IBaseElement obj)
|
|
{
|
|
TimelineTab timelineTab = Instantiate(timelineTabPrefab, timelineTabRect.transform);
|
|
timelineTab.MoveArea = moveTabPoint;
|
|
timelineTab.TabIndex = TabIndex;
|
|
timelineTab.SetTab(obj, obj.GetType());
|
|
timelineTabList.Add(obj.GetType(), timelineTab);
|
|
|
|
TabIndex++;
|
|
}
|
|
|
|
|
|
}
|
|
} |