155 lines
4.2 KiB
C++
155 lines
4.2 KiB
C++
global animation_curve_state *Global_AnimationCurveState = 0;
|
|
|
|
inline animation_curve_state *AnimationCurve_GetState(void)
|
|
{
|
|
return(Global_AnimationCurveState);
|
|
}
|
|
|
|
inline void AnimationCurve_SetState(animation_curve_state *State)
|
|
{
|
|
Global_AnimationCurveState = State;
|
|
}
|
|
|
|
static void AnimationCurve_Init(animation_curve_state *State)
|
|
{
|
|
State->Arena = ArenaAllocate(Gigabytes(1));
|
|
}
|
|
|
|
inline animation_curve_key AnimationCurve_GenerateKeyFromString(string String)
|
|
{
|
|
animation_curve_key Key;
|
|
Key.Value = HashString(String);
|
|
|
|
return(Key);
|
|
}
|
|
|
|
static animation_curve_entry *AnimationCurve_GetEntryByKey(animation_curve_key Key, r32 Initial)
|
|
{
|
|
animation_curve_state *State = AnimationCurve_GetState();
|
|
|
|
u64 Hash = Key.Value;
|
|
u64 Slot = Hash % ArrayCount(State->Buckets);
|
|
|
|
animation_curve_bucket *Bucket = State->Buckets + Slot;
|
|
|
|
animation_curve_entry *Result = 0;
|
|
for(animation_curve_entry *Entry = Bucket->First;
|
|
Entry != 0;
|
|
Entry = Entry->Next)
|
|
{
|
|
if(AreEqual(Entry->Key, Key))
|
|
{
|
|
Result = Entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!Result)
|
|
{
|
|
if(DLLIsEmpty(State->FirstFreeEntry))
|
|
{
|
|
Result = PushStruct(State->Arena, animation_curve_entry);
|
|
}
|
|
else
|
|
{
|
|
Result = State->FirstFreeEntry;
|
|
DLLRemove(State->FirstFreeEntry, State->LastFreeEntry, Result);
|
|
}
|
|
|
|
DLLInsertLast(Bucket->First, Bucket->Last, Result);
|
|
|
|
Result->Value = Initial;
|
|
}
|
|
|
|
Result->Key = Key;
|
|
Result->LastFrameTouched = State->CurrentFrame;
|
|
|
|
return(Result);
|
|
}
|
|
|
|
inline r32 AnimationCurve_GetValue(string Name, r32 Initial)
|
|
{
|
|
animation_curve_key Key = AnimationCurve_GenerateKeyFromString(Name);
|
|
animation_curve_entry *Entry = AnimationCurve_GetEntryByKey(Key, Initial);
|
|
|
|
r32 Result = Entry->Value;
|
|
return(Result);
|
|
}
|
|
|
|
inline void AnimationCurve_SetValue(string Name, r32 Value)
|
|
{
|
|
animation_curve_key Key = AnimationCurve_GenerateKeyFromString(Name);
|
|
animation_curve_entry *Entry = AnimationCurve_GetEntryByKey(Key, Value);
|
|
|
|
Entry->Value = Value;
|
|
}
|
|
|
|
inline r32 AnimationCurve_AnimateValueDirect(r32 Target, r32 Duration, r32 *Value)
|
|
{
|
|
animation_curve_state *State = AnimationCurve_GetState();
|
|
|
|
r32 Result = *Value;
|
|
|
|
r32 Rate = 1.0 - Pow(2, -(10.0 / Duration * State->dtForFrame));
|
|
*Value += (Target - *Value) * Rate;
|
|
|
|
return(Result);
|
|
}
|
|
|
|
inline r32 AnimationCurve_AnimateValue(r32 Target, r32 Initial, r32 Duration, string Name)
|
|
{
|
|
animation_curve_key Key = AnimationCurve_GenerateKeyFromString(Name);
|
|
animation_curve_entry *Entry = AnimationCurve_GetEntryByKey(Key, Initial);
|
|
|
|
r32 Result = AnimationCurve_AnimateValueDirect(Target, Duration, &Entry->Value);
|
|
return(Result);
|
|
}
|
|
|
|
inline r32 AnimationCurve_AnimateValueF(r32 Target, r32 Initial, r32 Duration, char *Format, ...)
|
|
{
|
|
temporary_memory Scratch = GetScratch(0, 0);
|
|
|
|
va_list Arguments;
|
|
va_start(Arguments, Format);
|
|
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
|
|
va_end(Arguments);
|
|
|
|
r32 Result = AnimationCurve_AnimateValue(Target, Initial, Duration, String);
|
|
|
|
ReleaseScratch(Scratch);
|
|
|
|
return(Result);
|
|
}
|
|
|
|
static void AnimationCurve_NewFrame(animation_curve_state *State, r32 dtForFrame)
|
|
{
|
|
AnimationCurve_SetState(State);
|
|
State->dtForFrame = dtForFrame;
|
|
|
|
// sixten: Prune untouched entries.
|
|
for(s32 BucketIndex = 0;
|
|
BucketIndex < ArrayCount(State->Buckets);
|
|
++BucketIndex)
|
|
{
|
|
animation_curve_bucket *Bucket = State->Buckets + BucketIndex;
|
|
|
|
animation_curve_entry *Entry = Bucket->First;
|
|
while(Entry != 0)
|
|
{
|
|
if(Entry->LastFrameTouched != State->CurrentFrame)
|
|
{
|
|
animation_curve_entry *ToRemove = Entry;
|
|
Entry = Entry->Next;
|
|
|
|
DLLRemove(Bucket->First, Bucket->Last, ToRemove);
|
|
DLLInsertLast(State->FirstFreeEntry, State->LastFreeEntry, ToRemove);
|
|
}
|
|
else
|
|
{
|
|
Entry = Entry->Next;
|
|
}
|
|
}
|
|
}
|
|
|
|
++State->CurrentFrame;
|
|
} |