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 { public int Compare(AnimationInterval a, AnimationInterval b) { return a.begin < b.begin ? -1 : (a.begin > b.begin ? 1 : 0); } } class BackwardComparer : IComparer { 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>> forwardSortedAnimations = new SortedList>>(new ForwardComparer()); private static SortedList>> backwardSortedAnimations = new SortedList>>(new BackwardComparer()); private static SortedList>> realTimeAnimations = new SortedList>>(new ForwardComparer()); private static SortedList>> demoTimeEvents = new SortedList>>(); private static SortedList>> realTimeEvents = new SortedList>>(); 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(argAnimation, argUserData)); backwardSortedAnimations[new AnimationInterval(argBeginTime, argEndTime)].Add(new Pair(argAnimation, argUserData)); } public static void AddRealTimeAnimation(double argBeginTime, double argEndTime, Animation argAnimation, uint argUserData) { realTimeAnimations[new AnimationInterval(argBeginTime, argEndTime)].Add(new Pair(argAnimation, argUserData)); } public static void AddDemoTimeEvent(double argTime, Event argEvent, uint argUserData) { demoTimeEvents[argTime].Add(new Pair(argEvent, argUserData)); } public static void AddRealTimeEvent(double argTime, Event argEvent, uint argUserData) { realTimeEvents[argTime].Add(new Pair(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, double>> lk_ActiveAnimations = new List, 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, 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, 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, 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; } } }