port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Common.Animations
{
[AttributeUsage(AttributeTargets.Property)]
public class Animateable : Attribute
{
}
}

View File

@@ -0,0 +1,16 @@
namespace Aiwaz.Common.Animations
{
abstract public class Animation
{
public double StartTime { get; set; }
public double EndTime { get; set; }
public string AnimationName;
public Animation()
{
AnimationName = "Erroneous";
}
public abstract void Animate(double time, uint userData);
}
}

View File

@@ -0,0 +1,164 @@
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;
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Common.Animations
{
public class CosineValueAnimation : ValueAnimation
{
public CosineValueAnimation()
: base()
{
AnimationName = "Cosine";
}
protected override float Calculate(double NormalizedTime)
{
float Interpolant = (float)((1.0 - Math.Cos(NormalizedTime * Math.PI)) / 2.0);
return (StartValue * (1.0f - Interpolant) + EndValue * Interpolant);
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Common.Animations
{
abstract public class Event
{
abstract public Action<uint> Do { get; }
abstract public Action<uint> Undo { get; }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Common.Animations
{
public class LinearValueAnimation : ValueAnimation
{
public LinearValueAnimation()
: base()
{
AnimationName = "Linear";
}
protected override float Calculate(double NormalizedTime)
{
return (float)(StartValue * (1.0 - NormalizedTime) + EndValue * NormalizedTime);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Common.Animations
{
abstract public class ValueAnimation : Animation
{
public float StartValue { get; set; }
public float EndValue { get; set; }
public Func<float> ValueGetter;
public Action<float> ValueSetter;
public Func<string> ValueNamer;
public float Value
{
get { return ValueGetter(); }
set { ValueSetter(value); }
}
public ValueAnimation()
: base()
{
AnimationName = "Erroneous (Value)";
}
public override void Animate(double time, uint userData)
{
if (time < StartTime || time > EndTime)
return;
double Time = (time - StartTime) / (EndTime - StartTime);
Value = Calculate(Time);
}
protected abstract float Calculate(double NormalizedTime);
}
}