vn/code/vn_animation_curve.cpp

150 lines
4.1 KiB
C++
Raw Normal View History

2023-06-17 17:00:55 +00:00
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;
}
inline animation_curve_key AnimationCurve_GenerateKeyFromString(string String)
{
animation_curve_key Key;
Key.Value = HashString(String);
return(Key);
}
2023-06-19 17:12:26 +00:00
static animation_curve_entry *AnimationCurve_GetEntryByKey(animation_curve_key Key, r32 Initial)
2023-06-17 17:00:55 +00:00
{
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;
}