262 lines
7.4 KiB
C++
262 lines
7.4 KiB
C++
|
inline void
|
||
|
SetTransition(pattern_transition* Transition, r32 Duration, r32 Elapsed)
|
||
|
{
|
||
|
Transition->Duration = Duration;
|
||
|
Transition->TimeElapsed = Elapsed;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
InitLEDChannelSystem (led_channel_system* System, memory_arena* ParentStorage, s32 StorageSize)
|
||
|
{
|
||
|
System->Channels = 0;
|
||
|
System->ChannelCount = 0;
|
||
|
InitMemoryArena(&System->Storage, PushSize(ParentStorage, StorageSize), StorageSize, 0);
|
||
|
System->FreeList = 0;
|
||
|
}
|
||
|
|
||
|
inline void
|
||
|
ResetChannel (led_channel* Channel, led_channel_system* ChannelSystem)
|
||
|
{
|
||
|
if (Channel->Patterns == 0)
|
||
|
{
|
||
|
Channel->Patterns = PushArray(&ChannelSystem->Storage,
|
||
|
pattern_index_id_key,
|
||
|
CHANNEL_MAX_PATTERNS);
|
||
|
}
|
||
|
Channel->ActivePatterns = 0;
|
||
|
Channel->ActivePatternIndex = -1;
|
||
|
|
||
|
SetTransition(&Channel->Transition, 3, 0);
|
||
|
|
||
|
Channel->BlendMode = ChannelBlend_Override;
|
||
|
Channel->ChannelID = ChannelIDAccumulator++;
|
||
|
|
||
|
Channel->Next = 0;
|
||
|
}
|
||
|
|
||
|
internal led_channel*
|
||
|
AddLEDChannel (led_channel_system* ChannelSystem)
|
||
|
{
|
||
|
led_channel* Channel = 0;
|
||
|
|
||
|
if (ChannelSystem->FreeList)
|
||
|
{
|
||
|
Channel = ChannelSystem->FreeList;
|
||
|
ChannelSystem->FreeList = ChannelSystem->FreeList->Next;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Channel = PushStruct(&ChannelSystem->Storage, led_channel);
|
||
|
}
|
||
|
ResetChannel(Channel, ChannelSystem);
|
||
|
|
||
|
Channel->Next = ChannelSystem->Channels;
|
||
|
ChannelSystem->Channels = Channel;
|
||
|
ChannelSystem->ChannelCount++;
|
||
|
|
||
|
return Channel;
|
||
|
}
|
||
|
|
||
|
internal b32
|
||
|
RemoveLEDChannel_ (led_channel* PrevChannel, led_channel* ToRemove, led_channel_system* ChannelSystem)
|
||
|
{
|
||
|
b32 Result = true;
|
||
|
|
||
|
if (PrevChannel->Next == ToRemove)
|
||
|
{
|
||
|
PrevChannel->Next = ToRemove->Next;
|
||
|
ToRemove->Next = ChannelSystem->FreeList;
|
||
|
ChannelSystem->FreeList = ToRemove;
|
||
|
ChannelSystem->ChannelCount--;
|
||
|
Result = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = false;
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal b32
|
||
|
RemoveLEDChannel (led_channel* Channel, led_channel_system* ChannelSystem)
|
||
|
{
|
||
|
b32 Result = true;
|
||
|
|
||
|
led_channel* Cursor = ChannelSystem->Channels;
|
||
|
for (s32 i = 0;
|
||
|
(Cursor->Next != Channel && i < ChannelSystem->ChannelCount);
|
||
|
Cursor = Cursor->Next, i++){}
|
||
|
|
||
|
Result = RemoveLEDChannel_(Cursor, Channel, ChannelSystem);
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal b32
|
||
|
RemoveLEDChannel (s32 Index, led_channel_system* ChannelSystem)
|
||
|
{
|
||
|
Assert(Index < ChannelSystem->ChannelCount);
|
||
|
b32 Result = true;
|
||
|
|
||
|
if (Index == 0)
|
||
|
{
|
||
|
led_channel* FirstChannel = ChannelSystem->Channels;
|
||
|
ChannelSystem->Channels = FirstChannel->Next;
|
||
|
FirstChannel->Next = ChannelSystem->FreeList;
|
||
|
ChannelSystem->FreeList = FirstChannel;
|
||
|
ChannelSystem->ChannelCount--;
|
||
|
Result = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
led_channel* PrevChannel = ChannelSystem->Channels;
|
||
|
for (s32 i = 0; i < Index - 1; i++)
|
||
|
{
|
||
|
PrevChannel = PrevChannel->Next;
|
||
|
}
|
||
|
|
||
|
Result = RemoveLEDChannel_(PrevChannel, PrevChannel->Next, ChannelSystem);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal led_channel*
|
||
|
GetChannelByIndex (s32 Index, led_channel_system ChannelSystem)
|
||
|
{
|
||
|
Assert(Index < ChannelSystem.ChannelCount);
|
||
|
led_channel* Result = ChannelSystem.Channels;
|
||
|
|
||
|
for (s32 i = 0; i < Index; i++)
|
||
|
{
|
||
|
Result = Result->Next;
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
AddPatternKeyToChannel (pattern_index_id_key Key, led_channel* Channel)
|
||
|
{
|
||
|
Assert(Channel->ActivePatterns < CHANNEL_MAX_PATTERNS);
|
||
|
Channel->Patterns[Channel->ActivePatterns++] = Key;
|
||
|
}
|
||
|
|
||
|
internal b32
|
||
|
RemovePatternKeyFromChannel (pattern_index_id_key Key, led_channel* Channel)
|
||
|
{
|
||
|
b32 Result = false;
|
||
|
|
||
|
s32 RemoveFrom = -1;
|
||
|
for (s32 i = 0; i < Channel->ActivePatterns; i++)
|
||
|
{
|
||
|
if (Channel->Patterns[i].ID == Key.ID)
|
||
|
{
|
||
|
RemoveFrom = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (RemoveFrom >= 0)
|
||
|
{
|
||
|
for (s32 j = 0; j < Channel->ActivePatterns; j++)
|
||
|
{
|
||
|
Channel->Patterns[j] = Channel->Patterns[j + 1];
|
||
|
}
|
||
|
Channel->ActivePatterns--;
|
||
|
Result = true;
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
PushPatternKeyOnUpdateList (pattern_index_id_key Key,
|
||
|
pattern_push_color_proc* PushColorProc,
|
||
|
patterns_update_list* UpdateList,
|
||
|
memory_arena* Storage)
|
||
|
{
|
||
|
if (UpdateList->Used >= UpdateList->Size)
|
||
|
{
|
||
|
if (!UpdateList->Next)
|
||
|
{
|
||
|
UpdateList->Next = PushStruct(Storage, patterns_update_list);
|
||
|
UpdateList->Next->Size = UpdateList->Size;
|
||
|
UpdateList->Next->Used = 0;
|
||
|
UpdateList->Next->Patterns = PushArray(Storage, pattern_update_list_entry, UpdateList->Next->Size);
|
||
|
}
|
||
|
PushPatternKeyOnUpdateList(Key, PushColorProc, UpdateList->Next, Storage);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pattern_update_list_entry Entry = {};
|
||
|
Entry.Key = Key;
|
||
|
Entry.PushColorProc = PushColorProc;
|
||
|
UpdateList->Patterns[UpdateList->Used++] = Entry;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
UpdateChannel (led_channel* Channel,
|
||
|
patterns_update_list* PatternsNeedUpdateList,
|
||
|
r32 DeltaTime,
|
||
|
memory_arena* Storage)
|
||
|
{
|
||
|
// Update Transition
|
||
|
Channel->Transition.TimeElapsed += DeltaTime;
|
||
|
if (Channel->Transition.TimeElapsed >= Channel->Transition.Duration ||
|
||
|
(Channel->ActivePatternIndex < 0 && Channel->ActivePatterns > 0))
|
||
|
{
|
||
|
Channel->Transition.TimeElapsed -= Channel->Transition.Duration;
|
||
|
Channel->ActivePatternIndex++;
|
||
|
if (Channel->ActivePatternIndex >= Channel->ActivePatterns)
|
||
|
{
|
||
|
Channel->ActivePatternIndex = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create Active Pattern List
|
||
|
if (Channel->ActivePatterns > 0)
|
||
|
{
|
||
|
Assert(Channel->ActivePatternIndex >= 0 && Channel->ActivePatternIndex < Channel->ActivePatterns);
|
||
|
|
||
|
pattern_push_color_proc* PushColorProc = 0;
|
||
|
switch (Channel->BlendMode)
|
||
|
{
|
||
|
case ChannelBlend_Override: { PushColorProc = PushColor_Override; } break;
|
||
|
case ChannelBlend_Add: { PushColorProc = PushColor_Add; } break;
|
||
|
case ChannelBlend_Multiply: { PushColorProc = PushColor_Multiply; } break;
|
||
|
default:
|
||
|
{
|
||
|
InvalidCodePath;
|
||
|
}break;
|
||
|
}
|
||
|
|
||
|
PushPatternKeyOnUpdateList(Channel->Patterns[Channel->ActivePatternIndex],
|
||
|
PushColorProc,
|
||
|
PatternsNeedUpdateList, Storage);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal patterns_update_list
|
||
|
UpdateAllChannels (led_channel_system* ChannelSystem, r32 DeltaTime, memory_arena* Transient)
|
||
|
{
|
||
|
patterns_update_list Result = {};
|
||
|
// NOTE(Peter): The initial size of this array is ChannelCount * 2 b/c at the moment, in the worst case,
|
||
|
// we need to update the two patterns a channel is blending between, and there isn't a case where we'd
|
||
|
// update 3 per channel
|
||
|
Result.Size = ChannelSystem->ChannelCount * 2;
|
||
|
Result.Used = 0;
|
||
|
Result.Patterns = PushArray(Transient, pattern_update_list_entry, Result.Size);
|
||
|
Result.Next = 0;
|
||
|
|
||
|
for (led_channel* Channel = ChannelSystem->Channels;
|
||
|
Channel;
|
||
|
Channel = Channel->Next)
|
||
|
{
|
||
|
UpdateChannel(Channel, &Result, DeltaTime, Transient);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|