165 lines
6.2 KiB
C#
165 lines
6.2 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace Aiwaz.Common.Animations
|
|
{
|
|
struct AnimationInterval
|
|
{
|
|
public AnimationInterval(double argBegin, double argEnd)
|
|
{
|
|
begin = argBegin;
|
|
end = argEnd;
|
|
}
|
|
|
|
public double begin;
|
|
public double end;
|
|
}
|
|
|
|
class ForwardComparer : IComparer<AnimationInterval>
|
|
{
|
|
public int Compare(AnimationInterval a, AnimationInterval b)
|
|
{
|
|
return a.begin < b.begin ? -1 : (a.begin > b.begin ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
class BackwardComparer : IComparer<AnimationInterval>
|
|
{
|
|
public int Compare(AnimationInterval a, AnimationInterval b)
|
|
{
|
|
return a.end > b.end ? -1 : (a.end > b.end ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
public static class AnimationManager
|
|
{
|
|
private static SortedList<AnimationInterval, List<Pair<Animation, uint>>> forwardSortedAnimations = new SortedList<AnimationInterval, List<Pair<Animation, uint>>>(new ForwardComparer());
|
|
private static SortedList<AnimationInterval, List<Pair<Animation, uint>>> backwardSortedAnimations = new SortedList<AnimationInterval, List<Pair<Animation, uint>>>(new BackwardComparer());
|
|
private static SortedList<AnimationInterval, List<Pair<Animation, uint>>> realTimeAnimations = new SortedList<AnimationInterval, List<Pair<Animation, uint>>>(new ForwardComparer());
|
|
private static SortedList<double, List<Pair<Event, uint>>> demoTimeEvents = new SortedList<double, List<Pair<Event, uint>>>();
|
|
private static SortedList<double, List<Pair<Event, uint>>> realTimeEvents = new SortedList<double, List<Pair<Event, uint>>>();
|
|
|
|
private static double previousDemoTime;
|
|
private static double previousRealTime;
|
|
|
|
public static void AddDemoTimeAnimation(double argBeginTime, double argEndTime, Animation argAnimation, uint argUserData)
|
|
{
|
|
forwardSortedAnimations[new AnimationInterval(argBeginTime, argEndTime)].Add(new Pair<Animation, uint>(argAnimation, argUserData));
|
|
backwardSortedAnimations[new AnimationInterval(argBeginTime, argEndTime)].Add(new Pair<Animation, uint>(argAnimation, argUserData));
|
|
}
|
|
|
|
public static void AddRealTimeAnimation(double argBeginTime, double argEndTime, Animation argAnimation, uint argUserData)
|
|
{
|
|
realTimeAnimations[new AnimationInterval(argBeginTime, argEndTime)].Add(new Pair<Animation, uint>(argAnimation, argUserData));
|
|
}
|
|
|
|
public static void AddDemoTimeEvent(double argTime, Event argEvent, uint argUserData)
|
|
{
|
|
demoTimeEvents[argTime].Add(new Pair<Event, uint>(argEvent, argUserData));
|
|
}
|
|
|
|
public static void AddRealTimeEvent(double argTime, Event argEvent, uint argUserData)
|
|
{
|
|
realTimeEvents[argTime].Add(new Pair<Event, uint>(argEvent, argUserData));
|
|
}
|
|
|
|
public static void Animate()
|
|
{
|
|
double demoTime = Timeline.DemoTime;
|
|
double realTime = Timeline.RealTime;
|
|
|
|
// Gather all active animations, they are the ones that started before now and end after now.
|
|
// Do this for both the demo time and real time.
|
|
List<Pair<Pair<Animation, uint>, double>> lk_ActiveAnimations = new List<Pair<Pair<Animation, uint>, double>>();
|
|
|
|
// Demo time animations: Demo time can go backwards, so search from both directions
|
|
if (Timeline.SpeedAndDirection > 0)
|
|
{
|
|
foreach (var entry in forwardSortedAnimations)
|
|
{
|
|
if (entry.Key.begin <= demoTime && entry.Key.end >= demoTime)
|
|
{
|
|
foreach (var animation in entry.Value)
|
|
{
|
|
lk_ActiveAnimations.Add(new Pair<Pair<Animation, uint>, double>(animation, (demoTime - entry.Key.begin) / (entry.Key.end - entry.Key.begin)));
|
|
}
|
|
}
|
|
|
|
if (entry.Key.begin > demoTime)
|
|
break;
|
|
}
|
|
}
|
|
else if (Timeline.SpeedAndDirection < 0)
|
|
{
|
|
foreach (var entry in backwardSortedAnimations)
|
|
{
|
|
if (entry.Key.end >= demoTime && entry.Key.begin <= demoTime)
|
|
{
|
|
foreach (var animation in entry.Value)
|
|
{
|
|
lk_ActiveAnimations.Add(new Pair<Pair<Animation, uint>, double>(animation, (demoTime - entry.Key.begin) / (entry.Key.end - entry.Key.begin)));
|
|
}
|
|
}
|
|
|
|
if (entry.Key.end < demoTime)
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Real time animations: The time that we know doesn't allow us to travel to the past, so just check into the future:
|
|
foreach (var entry in realTimeAnimations)
|
|
{
|
|
if (entry.Key.begin <= demoTime && entry.Key.end >= demoTime)
|
|
{
|
|
foreach (var animation in entry.Value)
|
|
{
|
|
lk_ActiveAnimations.Add(new Pair<Pair<Animation, uint>, double>(animation, (demoTime - entry.Key.begin) / (entry.Key.end - entry.Key.begin)));
|
|
}
|
|
}
|
|
|
|
if (entry.Key.begin > demoTime)
|
|
break;
|
|
}
|
|
|
|
// Now that we know what animations correspond to this time, animate them!
|
|
foreach (var anim in lk_ActiveAnimations)
|
|
{
|
|
anim.First.First.Animate(anim.Second, anim.First.Second);
|
|
}
|
|
|
|
// Fire all events that happened since last time:
|
|
foreach (var entry in demoTimeEvents)
|
|
{
|
|
double time = entry.Key;
|
|
|
|
foreach (var evt in entry.Value)
|
|
{
|
|
if ((Timeline.SpeedAndDirection > 0) && (time >= previousDemoTime && time <= demoTime))
|
|
{
|
|
evt.First.Do(evt.Second);
|
|
}
|
|
else if ((Timeline.SpeedAndDirection < 0) && (time <= previousDemoTime && time >= demoTime))
|
|
{
|
|
evt.First.Undo(evt.Second);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var entry in realTimeEvents)
|
|
{
|
|
double time = entry.Key;
|
|
|
|
foreach (var evt in entry.Value)
|
|
{
|
|
if (time >= previousDemoTime && time <= demoTime)
|
|
{
|
|
evt.First.Do(evt.Second);
|
|
}
|
|
}
|
|
}
|
|
|
|
previousDemoTime = demoTime;
|
|
previousRealTime = realTime;
|
|
}
|
|
}
|
|
}
|