2023-05-29 20:09:34 +00:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using Starpelly;
|
|
|
|
|
|
|
|
namespace HeavenStudio.Games
|
|
|
|
{
|
|
|
|
public class CallAndResponseHandler
|
|
|
|
{
|
|
|
|
public struct CallAndResponseEventParam
|
|
|
|
{
|
|
|
|
public string propertyName;
|
|
|
|
public dynamic value;
|
|
|
|
public CallAndResponseEventParam(string propertyName, dynamic value)
|
|
|
|
{
|
|
|
|
this.propertyName = propertyName;
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public class CallAndResponseEvent
|
|
|
|
{
|
2023-06-10 19:17:06 +00:00
|
|
|
public double beat;
|
2023-05-29 20:09:34 +00:00
|
|
|
public float length;
|
2023-06-10 19:17:06 +00:00
|
|
|
public double relativeBeat; // this beat is relative to the intervalStartBeat
|
2023-05-29 20:09:34 +00:00
|
|
|
public Dictionary<string, dynamic> DynamicData; //if you need more properties for your queued event
|
|
|
|
public string tag;
|
|
|
|
|
2023-06-10 19:17:06 +00:00
|
|
|
public CallAndResponseEvent(double beat, double relativeBeat, string tag, float length = 0)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
this.beat = beat;
|
|
|
|
this.length = length;
|
|
|
|
this.relativeBeat = relativeBeat;
|
|
|
|
DynamicData = new Dictionary<string, dynamic>();
|
|
|
|
this.tag = tag;
|
|
|
|
this.length = length;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void CreateProperty(string name, dynamic defaultValue)
|
|
|
|
{
|
|
|
|
if (!DynamicData.ContainsKey(name))
|
|
|
|
{
|
|
|
|
DynamicData.Add(name, defaultValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public dynamic this[string propertyName]
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (DynamicData.ContainsKey(propertyName))
|
|
|
|
{
|
|
|
|
return DynamicData[propertyName];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Debug.LogWarning("This property does not exist on this callAndResponse event.");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (DynamicData.ContainsKey(propertyName))
|
|
|
|
{
|
|
|
|
DynamicData[propertyName] = value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Debug.LogError($"This callAndRespone event does not have a property named {propertyName}! Attempted to insert value of type {value.GetType()}");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-10 19:17:06 +00:00
|
|
|
public double intervalStartBeat = -1; // the first beat of the interval
|
2023-05-29 20:09:34 +00:00
|
|
|
public float intervalLength = -1; // the duration of the interval in beats
|
|
|
|
|
|
|
|
public float defaultIntervalLength; // when an event is queued and the interval has not started yet, it will use this as the interval length.
|
|
|
|
|
|
|
|
public CallAndResponseHandler(float defaultIntervalLength)
|
|
|
|
{
|
|
|
|
this.defaultIntervalLength = defaultIntervalLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<CallAndResponseEvent> queuedEvents = new List<CallAndResponseEvent>();
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns the normalized progress of the interval
|
|
|
|
/// </summary>
|
|
|
|
public float GetIntervalProgress(float lengthOffset = 0)
|
|
|
|
{
|
|
|
|
return Conductor.instance.GetPositionFromBeat(intervalStartBeat, intervalLength - lengthOffset);
|
|
|
|
}
|
|
|
|
|
2023-06-10 19:17:06 +00:00
|
|
|
public float GetIntervalProgressFromBeat(double beat, float lengthOffset = 0)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-10 19:17:06 +00:00
|
|
|
return (float)((beat - intervalStartBeat) / ((intervalStartBeat + intervalLength - lengthOffset) - intervalStartBeat));
|
2023-05-29 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Is the interval currently on-going?
|
|
|
|
/// </summary>
|
|
|
|
public bool IntervalIsActive()
|
|
|
|
{
|
|
|
|
float progress = GetIntervalProgress();
|
|
|
|
return progress >= 0 && progress <= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Starts the interval.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="beat">The interval start beat.</param>
|
|
|
|
/// <param name="length">The length of the interval.</param>
|
2023-06-10 19:17:06 +00:00
|
|
|
public void StartInterval(double beat, float length)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
2023-06-03 14:51:30 +00:00
|
|
|
if (!IntervalIsActive())
|
|
|
|
{
|
|
|
|
if (queuedEvents.Count > 0) queuedEvents.Clear();
|
|
|
|
}
|
2023-05-29 20:09:34 +00:00
|
|
|
intervalStartBeat = beat;
|
|
|
|
intervalLength = length;
|
|
|
|
defaultIntervalLength = length;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
|
|
/// Adds an event to the queued events list.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="beat">The current beat.</param>
|
|
|
|
/// <param name="crParams">Extra properties to add to the event.</param>
|
|
|
|
/// <param name="ignoreInterval">If true, this function will not start a new interval if the interval isn't active.</param>
|
|
|
|
/// <param name="overrideInterval">If true, overrides the current interval.</param>
|
2023-06-10 19:17:06 +00:00
|
|
|
public void AddEvent(double beat, float length = 0, string tag = "", List<CallAndResponseEventParam> crParams = null, bool ignoreInterval = false, bool overrideInterval = false)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if ((!IntervalIsActive() && !ignoreInterval) || overrideInterval)
|
|
|
|
{
|
|
|
|
StartInterval(beat, defaultIntervalLength);
|
|
|
|
}
|
|
|
|
CallAndResponseEvent addedEvent = new CallAndResponseEvent(beat, beat - intervalStartBeat, tag, length);
|
|
|
|
if (crParams != null && crParams.Count > 0)
|
|
|
|
{
|
|
|
|
foreach (var param in crParams)
|
|
|
|
{
|
|
|
|
addedEvent.CreateProperty(param.propertyName, param.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
queuedEvents.Add(addedEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Check if an event exists at beat.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="beat">The beat to check.</param>
|
2023-06-10 19:17:06 +00:00
|
|
|
public bool EventExistsAtBeat(double beat)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (queuedEvents.Count == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CallAndResponseEvent foundEvent = queuedEvents.Find(x => x.beat == beat);
|
|
|
|
return foundEvent != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Check if an event exists at relativeBeat.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="beat">The beat to check.</param>
|
2023-06-10 19:17:06 +00:00
|
|
|
public bool EventExistsAtRelativetBeat(double relativeBeat)
|
2023-05-29 20:09:34 +00:00
|
|
|
{
|
|
|
|
if (queuedEvents.Count == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CallAndResponseEvent foundEvent = queuedEvents.Find(x => x.relativeBeat == relativeBeat);
|
|
|
|
return foundEvent != null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|