Files
Cielonos/Assets/Scripts/SLSUtilities/FunctionalAnimation/RuntimeFuncAnim.cs
SoulliesOfficial ef7b479712 initial
2025-11-25 08:19:33 -05:00

219 lines
7.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Cielonos.MainGame.Characters;
using SLSFramework.General;
using UnityEngine;
namespace SLSUtilities.FunctionalAnimation
{
public class RuntimeFuncAnim
{
public FuncAnimData funcAnimData;
public bool isLooping => funcAnimData.animationClip.isLooping;
public CharacterBase executor;
public float currentPlayTime;
public bool isDisrupted;
public int dataAnimEventIndex;
public int runtimeAnimEventIndex;
public EventCollection dataEvents;
public EventCollection runtimeEvents;
public Dictionary<string, bool> updateUntilStatus;
private List<FuncAnimEvent> playedEndEvents;
public RuntimeFuncAnim(FuncAnimData funcAnimData, CharacterBase character)
{
this.funcAnimData = funcAnimData;
this.executor = character;
isDisrupted = false;
dataAnimEventIndex = 0;
dataEvents = funcAnimData.eventCollection.Clone();
runtimeEvents = new EventCollection();
updateUntilStatus = new Dictionary<string, bool>();
playedEndEvents = new List<FuncAnimEvent>();
dataEvents.animEvents.ForEach(animEvt => animEvt.payload.runtimeFuncAnim = this);
dataEvents.startEvents.ForEach(payload => payload.runtimeFuncAnim = this);
dataEvents.disruptionEvents.ForEach(payload => payload.runtimeFuncAnim = this);
dataEvents.updateEvents.ForEach(payload => payload.runtimeFuncAnim = this);
dataEvents.updateUntilEvents.ForEach(payload => payload.runtimeFuncAnim = this);
}
public void AddAnimEvent(float time, FuncAnimPayloadBase payload, bool isEnd = false)
{
payload.runtimeFuncAnim = this;
runtimeEvents.animEvents.Add(new FuncAnimEvent(funcAnimData, time, payload, isEnd));
}
public void UpdateAnimEvent()
{
while (dataAnimEventIndex < dataEvents.animEvents.Count)
{
FuncAnimEvent animEvent = dataEvents.animEvents[dataAnimEventIndex];
if (currentPlayTime >= animEvent.triggerTime)
{
animEvent.payload.Invoke();
dataAnimEventIndex++;
if (animEvent.isEnd)
{
playedEndEvents.Add(animEvent);
}
}
else
{
break;
}
}
while (runtimeAnimEventIndex < runtimeEvents.animEvents.Count)
{
FuncAnimEvent animEvent = runtimeEvents.animEvents[runtimeAnimEventIndex];
if (currentPlayTime >= animEvent.triggerTime)
{
animEvent.payload.Invoke();
runtimeAnimEventIndex++;
if (animEvent.isEnd)
{
playedEndEvents.Add(animEvent);
}
}
else
{
break;
}
}
}
public void InvokeEndEvents()
{
dataEvents.endEvents.Exclude(playedEndEvents).Invoke();
runtimeEvents.endEvents.Exclude(playedEndEvents).Invoke();
}
public RuntimeFuncAnim AddStartEvent(FuncAnimPayloadBase payload)
{
payload.runtimeFuncAnim = this;
runtimeEvents.startEvents.Add(payload);
return this;
}
public void InvokeStartEvents()
{
dataEvents.startEvents.Invoke();
runtimeEvents.startEvents.Invoke();
}
public RuntimeFuncAnim AddDisruptionEvent(FuncAnimPayloadBase payload)
{
payload.runtimeFuncAnim = this;
runtimeEvents.disruptionEvents.Add(payload);
return this;
}
public void InvokeDisruptionEvents()
{
dataEvents.disruptionEvents.Invoke();
runtimeEvents.disruptionEvents.Invoke();
}
public RuntimeFuncAnim AddUpdateEvent(FuncAnimPayloadBase payload)
{
payload.runtimeFuncAnim = this;
runtimeEvents.updateEvents.Add(payload);
return this;
}
public void InvokeUpdateEvents()
{
dataEvents.updateEvents.Invoke();
runtimeEvents.updateEvents.Invoke();
}
public RuntimeFuncAnim AddUpdateUntilEvent(FuncAnimPayloadBase<bool> payload)
{
payload.runtimeFuncAnim = this;
runtimeEvents.updateUntilEvents.Add(payload);
updateUntilStatus.Add(payload.eventName, false);
return this;
}
public void InvokeUpdateUntilEvents()
{
foreach (FuncAnimPayloadBase<bool> updateUntilEvent in dataEvents.updateUntilEvents)
{
if (!updateUntilStatus[updateUntilEvent.eventName])
{
updateUntilStatus[updateUntilEvent.eventName] = updateUntilEvent.Invoke();
}
}
foreach (FuncAnimPayloadBase<bool> updateUntilEvent in runtimeEvents.updateUntilEvents)
{
if (!updateUntilStatus[updateUntilEvent.eventName])
{
updateUntilStatus[updateUntilEvent.eventName] = updateUntilEvent.Invoke();
}
}
}
public void ClearRuntimeEvents()
{
runtimeEvents.animEvents.Clear();
runtimeEvents.startEvents.Clear();
runtimeEvents.disruptionEvents.Clear();
runtimeEvents.updateEvents.Clear();
runtimeEvents.updateUntilEvents.Clear();
SetUpdateUntilEventsStatus();
}
public void SetUpdateUntilEventsStatus(List<FuncAnimPayloadBase<bool>> events = null)
{
updateUntilStatus.Clear();
if (events == null)
{
foreach (FuncAnimPayloadBase<bool> evt in dataEvents.updateUntilEvents)
{
updateUntilStatus.Add(evt.eventName, false);
}
foreach (FuncAnimPayloadBase<bool> evt in runtimeEvents.updateUntilEvents)
{
updateUntilStatus.Add(evt.eventName, false);
}
}
else
{
foreach (FuncAnimPayloadBase<bool> evt in events)
{
updateUntilStatus.Add(evt.eventName, false);
}
}
}
public void ResetUpdateUntilEventsStatus()
{
List<string> keys = updateUntilStatus.Keys.ToList();
foreach (string key in keys)
{
updateUntilStatus[key] = false;
}
}
public List<FuncAnimInterval> GetEnablingIntervals() => GetEnablingIntervals(currentPlayTime);
public List<FuncAnimInterval> GetEnablingIntervals(float time)
{
if (funcAnimData == null || funcAnimData.intervals == null)
{
Debug.LogWarning($"[FuncAnimData.RuntimeInfo] Parent data or intervals list is null.");
return new List<FuncAnimInterval>();
}
return funcAnimData.intervals.Where(interval => time >= interval.StartTime && time <= interval.EndTime).ToList();
}
}
}