vn/code/vn_animation_curve.cpp

158 lines
4.0 KiB
C++
Raw Normal View History

2023-06-17 17:00:55 +00:00
global animation_curve_state *Global_AnimationCurveState = 0;
2023-08-22 03:19:51 +00:00
////////////////////////////////
//~ sixten: Animation Curve Functions
inline animation_curve_state *AC_GetState(void)
2023-06-17 17:00:55 +00:00
{
return(Global_AnimationCurveState);
}
2023-08-22 03:19:51 +00:00
inline void AC_SetState(animation_curve_state *State)
2023-06-17 17:00:55 +00:00
{
Global_AnimationCurveState = State;
}
2023-08-22 03:19:51 +00:00
static void AC_Init(animation_curve_state *State)
2023-07-19 15:09:41 +00:00
{
State->Arena = ArenaAllocate(Gigabytes(1));
}
2023-08-22 03:19:51 +00:00
inline animation_curve_key AC_GenerateKeyFromString(string String)
2023-06-17 17:00:55 +00:00
{
animation_curve_key Key;
Key.Value = HashString(String);
return(Key);
}
2023-08-22 03:19:51 +00:00
static animation_curve_entry *AC_GetEntryByKey(animation_curve_key Key, r32 Initial)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
animation_curve_state *State = AC_GetState();
2023-06-17 17:00:55 +00:00
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))
{
2023-07-19 15:09:41 +00:00
Result = PushStruct(State->Arena, animation_curve_entry);
2023-06-17 17:00:55 +00:00
}
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);
}
2023-08-22 03:19:51 +00:00
inline r32 AC_GetValue(string Name, r32 Initial)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
animation_curve_key Key = AC_GenerateKeyFromString(Name);
animation_curve_entry *Entry = AC_GetEntryByKey(Key, Initial);
2023-06-17 17:00:55 +00:00
r32 Result = Entry->Value;
return(Result);
}
2023-08-22 03:19:51 +00:00
inline void AC_SetValue(string Name, r32 Value)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
animation_curve_key Key = AC_GenerateKeyFromString(Name);
animation_curve_entry *Entry = AC_GetEntryByKey(Key, Value);
2023-06-17 17:00:55 +00:00
Entry->Value = Value;
}
2023-08-22 03:19:51 +00:00
inline r32 AC_AnimateValueDirect(r32 Target, r32 Duration, r32 *Value)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
animation_curve_state *State = AC_GetState();
2023-06-17 17:00:55 +00:00
r32 Result = *Value;
r32 Rate = 1.0 - Pow(2, -(10.0 / Duration * State->dtForFrame));
*Value += (Target - *Value) * Rate;
return(Result);
}
2023-08-22 03:19:51 +00:00
inline r32 AC_AnimateValue(r32 Target, r32 Initial, r32 Duration, string Name)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
animation_curve_key Key = AC_GenerateKeyFromString(Name);
animation_curve_entry *Entry = AC_GetEntryByKey(Key, Initial);
2023-06-17 17:00:55 +00:00
2023-08-22 03:19:51 +00:00
r32 Result = AC_AnimateValueDirect(Target, Duration, &Entry->Value);
2023-06-17 17:00:55 +00:00
return(Result);
}
2023-08-22 03:19:51 +00:00
inline r32 AC_AnimateValueF(r32 Target, r32 Initial, r32 Duration, char *Format, ...)
2023-06-17 17:00:55 +00:00
{
temporary_memory Scratch = GetScratch(0, 0);
va_list Arguments;
va_start(Arguments, Format);
string String = PushFormatVariadic(Scratch.Arena, Format, Arguments);
va_end(Arguments);
2023-08-22 03:19:51 +00:00
r32 Result = AC_AnimateValue(Target, Initial, Duration, String);
2023-06-17 17:00:55 +00:00
ReleaseScratch(Scratch);
return(Result);
}
2023-08-22 03:19:51 +00:00
static void AC_NewFrame(animation_curve_state *State, r32 dtForFrame)
2023-06-17 17:00:55 +00:00
{
2023-08-22 03:19:51 +00:00
AC_SetState(State);
2023-06-17 17:00:55 +00:00
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;
}