using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Ichni.RhythmGame.Beatmap; using UniRx; using Unity.Mathematics; using UnityEngine; using UnityEngine.Events; namespace Ichni.RhythmGame { public partial class TimeDurationSubmodule : SubmoduleBase { public bool isOverridingDuration; //是否手动设置了时间区间,开启时,子物体的时间区间将被忽略,且在自动计算区间时跳过此模块 public float startTime, endTime; //起止时间 public IDisposable timeObserver; public TimeDurationSubmodule(GameElement attachedGameElement) : base(attachedGameElement) { isOverridingDuration = false; startTime = -32767; //TODO: 换为-delay endTime = 32767; //TODO: 换为songLength if (!HaveSameSubmodule) { (attachedGameElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = this; } } public TimeDurationSubmodule(GameElement attachedGameElement, bool isOverridingDuration, float startTime, float endTime) : base(attachedGameElement) { this.isOverridingDuration = isOverridingDuration; this.startTime = startTime; this.endTime = endTime; if (!HaveSameSubmodule) { (attachedGameElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = this; } } public bool CheckTimeInDuration(float time, float offset = 0.2f) { return time >= startTime - offset && time <= endTime + offset; } public void SetDuration(float startTime, float endTime) { this.startTime = startTime; this.endTime = endTime; this.isOverridingDuration = true; } public void SetDuration(params FlexibleFloat[] flexibleFloats) { List startTimes = new List(); List endTimes = new List(); foreach (FlexibleFloat flexibleFloat in flexibleFloats) { flexibleFloat.Sort(); if (flexibleFloat.animations.Count > 0) { startTimes.Add(flexibleFloat.animations[0].startTime); endTimes.Add(flexibleFloat.animations[^1].endTime); } else continue; } if (startTimes.Count == 0 || endTimes.Count == 0) { return; } startTime = startTimes.Min(); endTime = endTimes.Max(); } public void SetDurationFromChildren(List children) { List durations = new List(); if (children.Count == 0) { return; } foreach (var child in children) { durations.Add(new float2(child.startTime, child.endTime)); } startTime = durations.Min(duration => duration.x); endTime = durations.Max(duration => duration.y); } public override void SaveBM() { matchedBM = new TimeDurationSubmodule_BM(attachedGameElement); } } public partial class TimeDurationSubmodule { public void SetUpObserver(UnityAction enableAction, UnityAction disableAction = null) { timeObserver?.Dispose(); timeObserver = Observable.EveryUpdate().Subscribe(_ => { float songTime = GameManager.instance.songTime; if (CheckTimeInDuration(songTime, 0f) && !attachedGameElement.gameObject.activeSelf) { attachedGameElement.gameObject.SetActive(true); enableAction?.Invoke(); } else if (!CheckTimeInDuration(songTime, 0f) && attachedGameElement.gameObject.activeSelf) { attachedGameElement.gameObject.SetActive(false); disableAction?.Invoke(); } }); } } public interface IHaveTimeDurationSubmodule { public TimeDurationSubmodule timeDurationSubmodule { get; set; } } namespace Beatmap { public class TimeDurationSubmodule_BM : Submodule_BM { public bool isOverridingDuration; public float startTime, endTime; public TimeDurationSubmodule_BM() { } public TimeDurationSubmodule_BM(GameElement attachedElement) : base(attachedElement) { TimeDurationSubmodule timeDurationSubmodule = (attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule; isOverridingDuration = timeDurationSubmodule.isOverridingDuration; startTime = timeDurationSubmodule.startTime; endTime = timeDurationSubmodule.endTime; } public override void ExecuteBM() { attachedElement = GameElement_BM.GetElement(attachedElementGuid); (attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attachedElement, isOverridingDuration, startTime, endTime); } } } }