Animation Playlists, lots of cleanup, settings file stuff, etc.

This commit is contained in:
Peter Slattery 2021-03-27 21:41:47 -07:00
parent 5ddca7fbac
commit 6b137154bc
10 changed files with 298 additions and 74 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ meta_run_tree/
process/ process/
reference/ reference/
working_data/ working_data/
nssm_log.log

View File

@ -160,6 +160,9 @@ struct animation_system
animation_array Animations; animation_array Animations;
animation_repeat_mode RepeatMode; animation_repeat_mode RepeatMode;
animation_handle_array Playlist;
u32 PlaylistAt;
r32 PlaylistFadeTime;
// NOTE(Peter): The frame currently being displayed/processed. you // NOTE(Peter): The frame currently being displayed/processed. you
// can see which frame you're on by looking at the time slider on the timeline // can see which frame you're on by looking at the time slider on the timeline
@ -621,14 +624,21 @@ AnimationFadeGroup_Update(animation_fade_group* Group, r32 DeltaTime)
internal void internal void
AnimationFadeGroup_FadeTo(animation_fade_group* Group, animation_handle To, r32 Duration) AnimationFadeGroup_FadeTo(animation_fade_group* Group, animation_handle To, r32 Duration)
{ {
// complete current fade if there is one in progress if (IsValid(Group->From))
if (IsValid(Group->To))
{ {
AnimationFadeGroup_Advance(Group); // complete current fade if there is one in progress
if (IsValid(Group->To))
{
AnimationFadeGroup_Advance(Group);
}
Group->To = To;
Group->FadeDuration = Duration;
}
else
{
Group->From = To;
} }
Group->To = To;
Group->FadeDuration = Duration;
} }
// System // System
@ -750,7 +760,15 @@ AnimationSystem_Update(animation_system* System, r32 DeltaTime)
case AnimationRepeat_Loop: case AnimationRepeat_Loop:
{ {
// TODO(pjs): Assert(System->Playlist.Count > 0);
u32 NextIndex = System->PlaylistAt;
System->PlaylistAt = (System->PlaylistAt + 1) % System->Playlist.Count;
animation_handle Next = System->Playlist.Handles[NextIndex];
AnimationFadeGroup_FadeTo(&System->ActiveFadeGroup,
Next,
System->PlaylistFadeTime);
System->CurrentFrame = 0;
}break; }break;
InvalidDefaultCase; InvalidDefaultCase;
@ -759,6 +777,15 @@ AnimationSystem_Update(animation_system* System, r32 DeltaTime)
} }
} }
internal void
AnimationSystem_FadeToPlaylist(animation_system* System, animation_handle_array Playlist)
{
System->Playlist = Playlist;
System->PlaylistAt = 0;
AnimationFadeGroup_FadeTo(&System->ActiveFadeGroup, Playlist.Handles[0], System->PlaylistFadeTime);
}
inline bool inline bool
AnimationSystem_NeedsRender(animation_system System) AnimationSystem_NeedsRender(animation_system System)
{ {

View File

@ -120,6 +120,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
// zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically
// incorrect to clear the arena, and then access the memory later. // incorrect to clear the arena, and then access the memory later.
ClearArena(State->Transient); ClearArena(State->Transient);
Assert(State->UserSpaceDesc.UserData.Memory != 0);
if (State->RunEditor) if (State->RunEditor)
{ {
@ -129,6 +130,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
AnimationSystem_Update(&State->AnimationSystem, Context->DeltaTime); AnimationSystem_Update(&State->AnimationSystem, Context->DeltaTime);
if (AnimationSystem_NeedsRender(State->AnimationSystem)) if (AnimationSystem_NeedsRender(State->AnimationSystem))
{ {
Assert(State->UserSpaceDesc.UserData.Memory != 0);
AnimationSystem_RenderToLedBuffers(&State->AnimationSystem, AnimationSystem_RenderToLedBuffers(&State->AnimationSystem,
State->Assemblies, State->Assemblies,
&State->LedSystem, &State->LedSystem,
@ -138,7 +140,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->UserSpaceDesc.UserData.Memory); State->UserSpaceDesc.UserData.Memory);
} }
Assert(State->UserSpaceDesc.UserData.Memory != 0);
US_CustomUpdate(&State->UserSpaceDesc, State, Context); US_CustomUpdate(&State->UserSpaceDesc, State, Context);
Assert(State->UserSpaceDesc.UserData.Memory != 0);
AssemblyDebug_OverrideOutput(State->AssemblyDebugState, AssemblyDebug_OverrideOutput(State->AssemblyDebugState,
State->Assemblies, State->Assemblies,
@ -149,6 +153,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
Editor_Render(State, Context, RenderBuffer); Editor_Render(State, Context, RenderBuffer);
} }
Assert(State->UserSpaceDesc.UserData.Memory != 0);
BuildAssemblyData(State, *Context, OutputData); BuildAssemblyData(State, *Context, OutputData);
} }

View File

@ -1065,7 +1065,7 @@ Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % BL_FLOWER_COUNT];
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});

View File

@ -556,6 +556,41 @@ Win32_SendOutputData(gs_thread_context ThreadContext, addressed_data_buffer_list
} }
// Time
internal system_time
Win32GetSystemTime()
{
system_time Result = {};
SYSTEMTIME WinLocalTime;
GetLocalTime(&WinLocalTime);
SYSTEMTIME WinSysTime;
FILETIME WinSysFileTime;
GetSystemTime(&WinSysTime);
if (SystemTimeToFileTime((const SYSTEMTIME*)&WinSysTime, &WinSysFileTime))
{
ULARGE_INTEGER SysTime = {};
SysTime.LowPart = WinSysFileTime.dwLowDateTime;
SysTime.HighPart = WinSysFileTime.dwHighDateTime;
Result.NanosSinceEpoch = SysTime.QuadPart;
Result.Year = WinLocalTime.wYear;
Result.Month = WinLocalTime.wMonth;
Result.Day = WinLocalTime.wDay;
Result.Hour = WinLocalTime.wHour;
Result.Minute = WinLocalTime.wMinute;
Result.Second = WinLocalTime.wSecond;
}
else
{
u32 Error = GetLastError();
InvalidCodePath;
}
return Result;
}
int WINAPI int WINAPI
WinMain ( WinMain (
HINSTANCE HInstance, HINSTANCE HInstance,
@ -636,6 +671,8 @@ WinMain (
Context.InitializeApplication(Context); Context.InitializeApplication(Context);
system_time StartTime = Win32GetSystemTime();
Running = true; Running = true;
Context.WindowIsVisible = true; Context.WindowIsVisible = true;
while (Running) while (Running)
@ -647,31 +684,8 @@ WinMain (
DEBUG_TRACK_SCOPE(MainLoop); DEBUG_TRACK_SCOPE(MainLoop);
{ {
// update system time
SYSTEMTIME WinLocalTime;
GetLocalTime(&WinLocalTime);
SYSTEMTIME WinSysTime;
FILETIME WinSysFileTime;
GetSystemTime(&WinSysTime);
if (!SystemTimeToFileTime((const SYSTEMTIME*)&WinSysTime, &WinSysFileTime))
{
u32 Error = GetLastError();
InvalidCodePath;
}
ULARGE_INTEGER SysTime = {};
SysTime.LowPart = WinSysFileTime.dwLowDateTime;
SysTime.HighPart = WinSysFileTime.dwHighDateTime;
Context.SystemTime_Last = Context.SystemTime_Current; Context.SystemTime_Last = Context.SystemTime_Current;
Context.SystemTime_Current = Win32GetSystemTime();
Context.SystemTime_Current.NanosSinceEpoch = SysTime.QuadPart;
Context.SystemTime_Current.Year = WinLocalTime.wYear;
Context.SystemTime_Current.Month = WinLocalTime.wMonth;
Context.SystemTime_Current.Day = WinLocalTime.wDay;
Context.SystemTime_Current.Hour = WinLocalTime.wHour;
Context.SystemTime_Current.Minute = WinLocalTime.wMinute;
Context.SystemTime_Current.Second = WinLocalTime.wSecond;
#define PRINT_SYSTEM_TIME 0 #define PRINT_SYSTEM_TIME 0
#if PRINT_SYSTEM_TIME #if PRINT_SYSTEM_TIME
@ -682,6 +696,11 @@ WinMain (
Context.SystemTime_Current.Minute, Context.SystemTime_Current.Minute,
Context.SystemTime_Current.Second, Context.SystemTime_Current.Second,
Context.SystemTime_Current.NanosSinceEpoch); Context.SystemTime_Current.NanosSinceEpoch);
u64 NanosElapsed = Context.SystemTime_Current.NanosSinceEpoch - StartTime.NanosSinceEpoch;
r64 SecondsElapsed = (r64)NanosElapsed * NanosToSeconds;
PrintF(&T, "%lld %f Seconds\n", NanosElapsed, SecondsElapsed);
NullTerminate(&T); NullTerminate(&T);
OutputDebugStringA(T.Str); OutputDebugStringA(T.Str);
#endif #endif

View File

@ -174,6 +174,16 @@ BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData)
CloseSocket(Data->SocketManager, ListenSocket); CloseSocket(Data->SocketManager, ListenSocket);
} }
internal void
BlumenLumen_SetPatternMode(bl_pattern_mode Mode, r32 FadeDuration, animation_system* System, blumen_lumen_state* BLState)
{
BLState->PatternMode = Mode;
animation_handle_array Playlist = BLState->ModeAnimations[Mode];
System->RepeatMode = AnimationRepeat_Loop;
System->PlaylistFadeTime = FadeDuration;
AnimationSystem_FadeToPlaylist(System, Playlist);
}
internal void internal void
BlumenLumen_LoadPatterns(app_state* State) BlumenLumen_LoadPatterns(app_state* State)
{ {
@ -298,7 +308,7 @@ BlumenLumen_CustomInit(app_state* State, context Context)
BLState->ModeAnimations[BlumenPattern_Standard] = LoadAllAnimationsInDir(AmbientPatternFolder, BLState, State, Context); BLState->ModeAnimations[BlumenPattern_Standard] = LoadAllAnimationsInDir(AmbientPatternFolder, BLState, State, Context);
BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context); BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context);
State->AnimationSystem.ActiveFadeGroup.From = BLState->ModeAnimations[BlumenPattern_Standard].Handles[0]; BlumenLumen_SetPatternMode(BlumenPattern_Standard, 5, &State->AnimationSystem, BLState);
#endif #endif
State->AnimationSystem.TimelineShouldAdvance = true; State->AnimationSystem.TimelineShouldAdvance = true;
@ -333,21 +343,16 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
BLState->AssemblyColors[0] = NewHue; BLState->AssemblyColors[0] = NewHue;
BLState->AssemblyColors[1] = NewHue; BLState->AssemblyColors[1] = NewHue;
BLState->AssemblyColors[2] = NewHue; BLState->AssemblyColors[2] = NewHue;
animation_handle NewAnim = BLState->ModeAnimations[BlumenPattern_VoiceCommand].Handles[0];
AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup,
NewAnim,
VoiceCommandFadeDuration);
} }
else else
{ {
u32 AssemblyIdx = BLState->LastAssemblyColorSet; u32 AssemblyIdx = BLState->LastAssemblyColorSet;
BLState->AssemblyColors[AssemblyIdx] = NewHue; BLState->AssemblyColors[AssemblyIdx] = NewHue;
BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3;
} }
BLState->PatternMode = BlumenPattern_VoiceCommand; BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, 5, &State->AnimationSystem, BLState);
// TODO(PS): get current time so we can fade back after BLState->TimeLastSetToVoiceMode = Context->SystemTime_Current;
// a while
} }
}break; }break;
@ -361,8 +366,18 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
Motor.Temperature = (T[0] << 8 | Motor.Temperature = (T[0] << 8 |
T[1] << 0); T[1] << 0);
motor_packet CurrPos = Motor.Pos;
motor_packet LastPos = BLState->LastKnownMotorState; motor_packet LastPos = BLState->LastKnownMotorState;
DEBUG_ReceivedMotorPositions(LastPos, Motor.Pos, Context->ThreadContext); DEBUG_ReceivedMotorPositions(LastPos, Motor.Pos, Context->ThreadContext);
for (u32 i = 0; i < BL_FLOWER_COUNT; i++)
{
if (LastPos.FlowerPositions[i] != CurrPos.FlowerPositions[i])
{
BLState->LastTimeMotorStateChanged[i] = Context->SystemTime_Current.NanosSinceEpoch;
}
}
BLState->LastKnownMotorState = Motor.Pos; BLState->LastKnownMotorState = Motor.Pos;
}break; }break;
@ -373,11 +388,11 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
if (Temp.Temperature > 0) if (Temp.Temperature > 0)
{ {
BLState->BrightnessPercent = .25f; BLState->BrightnessPercent = HighTemperatureBrightnessPercent;
} }
else else
{ {
BLState->BrightnessPercent = 1.f; BLState->BrightnessPercent = FullBrightnessPercent;
} }
DEBUG_ReceivedTemperature(Temp, Context->ThreadContext); DEBUG_ReceivedTemperature(Temp, Context->ThreadContext);
@ -387,6 +402,23 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
} }
} }
// Transition back to standard mode after some time
if (BLState->PatternMode == BlumenPattern_VoiceCommand)
{
u64 LastChangeClock = BLState->TimeLastSetToVoiceMode.NanosSinceEpoch;
u64 NowClocks = Context->SystemTime_Current.NanosSinceEpoch;
s64 NanosSinceChange = NowClocks - LastChangeClock;
r64 SecondsSinceChange = (r64)NanosSinceChange * NanosToSeconds;
if (SecondsSinceChange > VoiceCommandSustainDuration)
{
BLState->PatternMode = BlumenPattern_Standard;
animation_handle NewAnim = BLState->ModeAnimations[BlumenPattern_Standard].Handles[0];
AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup,
NewAnim,
VoiceCommandFadeDuration);
}
}
// Open / Close the Motor // Open / Close the Motor
if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue)) if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue))
@ -441,38 +473,42 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
DEBUG_SentMotorCommand(MotorCommand.MotorPacket, Context->ThreadContext); DEBUG_SentMotorCommand(MotorCommand.MotorPacket, Context->ThreadContext);
} }
} }
// Dim the leds based on temp data
for (u32 i = 0; i < State->LedSystem.BuffersCount; i++) // When a motor state changes to being open, wait to turn Upper Leds on
// in order to hide the fact that they are turning off
motor_packet CurrMotorPos = BLState->LastKnownMotorState;
u64 NowNanos = Context->SystemTime_Current.NanosSinceEpoch;
for (u32 i = 0; i < BL_FLOWER_COUNT; i++)
{ {
led_buffer Buffer = State->LedSystem.Buffers[i]; // have to map from "assembly load order" to
for (u32 j = 0; j < Buffer.LedCount; j++) // the order that the clear core is referencing the
// motors by
assembly Assembly = State->Assemblies.Values[i];
u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState);
u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex];
if ((MotorPos == MotorState_Open || MotorPos == MotorState_MostlyOpen) &&
!BLState->ShouldDimUpperLeds[i])
{ {
pixel* Color = Buffer.Colors + j; u64 ChangedNanos = BLState->LastTimeMotorStateChanged[i];
Color->R = Color->R * BLState->BrightnessPercent; u64 NanosSinceChanged = NowNanos - ChangedNanos;
Color->G = Color->G * BLState->BrightnessPercent; r64 SecondsSinceChanged = (r64)NanosSinceChanged * NanosToSeconds;
Color->B = Color->B * BLState->BrightnessPercent; if (SecondsSinceChanged > TurnUpperLedsOffAfterMotorCloseCommandDelay)
{
BLState->ShouldDimUpperLeds[i] = true;
}
} }
} }
// NOTE(PS): If the flowers are mostly open or full open // NOTE(PS): If the flowers are mostly open or full open
// we mask off the top leds to prevent them from overheating // we mask off the top leds to prevent them from overheating
// while telescoped inside the flower // while telescoped inside the flower
motor_packet CurrMotorPos = BLState->LastKnownMotorState; for (u32 a = 0; a < BL_FLOWER_COUNT; a++)
for (u32 a = 0; a < State->Assemblies.Count; a++)
{ {
assembly Assembly = State->Assemblies.Values[a]; assembly Assembly = State->Assemblies.Values[a];
u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState); if (!BLState->ShouldDimUpperLeds[a]) continue;
u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex];
if (MotorPos == MotorState_Closed ||
MotorPos == MotorState_HalfOpen)
{
continue;
}
led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex];
led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient); led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient);
for (u32 s = 0; s < TopStrips.Count; s++) for (u32 s = 0; s < TopStrips.Count; s++)
{ {
@ -486,6 +522,22 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
} }
} }
// Dim the leds based on temp data
if (!BLState->DEBUG_IgnoreWeatherDimmingLeds)
{
for (u32 i = 0; i < State->LedSystem.BuffersCount; i++)
{
led_buffer Buffer = State->LedSystem.Buffers[i];
for (u32 j = 0; j < Buffer.LedCount; j++)
{
pixel* Color = Buffer.Colors + j;
Color->R = Color->R * BLState->BrightnessPercent;
Color->G = Color->G * BLState->BrightnessPercent;
Color->B = Color->B * BLState->BrightnessPercent;
}
}
}
// Send Status Packet // Send Status Packet
{ {
system_time LastSendTime = BLState->LastStatusUpdateTime; system_time LastSendTime = BLState->LastStatusUpdateTime;
@ -524,7 +576,7 @@ US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI)
{ {
motor_packet PendingPacket = BLState->DEBUG_PendingMotorPacket; motor_packet PendingPacket = BLState->DEBUG_PendingMotorPacket;
for (u32 MotorIndex = 0; MotorIndex < 3; MotorIndex++) for (u32 MotorIndex = 0; MotorIndex < BL_FLOWER_COUNT; MotorIndex++)
{ {
gs_string Label = PushStringF(State->Transient, 32, "Motor %d", MotorIndex); gs_string Label = PushStringF(State->Transient, 32, "Motor %d", MotorIndex);
ui_BeginRow(I, 5); ui_BeginRow(I, 5);
@ -567,6 +619,40 @@ US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI)
DEBUG_SentMotorCommand(Packet.MotorPacket, Context.ThreadContext); DEBUG_SentMotorCommand(Packet.MotorPacket, Context.ThreadContext);
} }
motor_packet MotorPos = BLState->LastKnownMotorState;
ui_Label(I, MakeString("Current Motor Positions"));
{
for (u32 i = 0; i < BL_FLOWER_COUNT; i++)
{
ui_BeginRow(I, 2);
gs_string MotorStr = PushStringF(State->Transient, 32,
"Motor %d",
i);
ui_Label(I, MotorStr);
gs_string StateStr = {};
switch (MotorPos.FlowerPositions[i])
{
case MotorState_Closed: {
StateStr = MakeString("Closed");
} break;
case MotorState_HalfOpen: {
StateStr = MakeString("Half Open");
} break;
case MotorState_MostlyOpen: {
StateStr = MakeString("Mostly Open");
} break;
case MotorState_Open: {
StateStr = MakeString("Open");
} break;
}
ui_Label(I, StateStr);
ui_EndRow(I);
}
}
BLState->DEBUG_IgnoreWeatherDimmingLeds = ui_LabeledToggle(I, MakeString("Ignore Weather Dimming Leds"), BLState->DEBUG_IgnoreWeatherDimmingLeds);
} }
} }

View File

@ -145,11 +145,8 @@ struct blumen_lumen_state
mic_listen_job_data MicListenJobData; mic_listen_job_data MicListenJobData;
motor_packet LastKnownMotorState; motor_packet LastKnownMotorState;
u64 LastTimeMotorStateChanged[BL_FLOWER_COUNT];
r64 TimeElapsed; b8 ShouldDimUpperLeds[BL_FLOWER_COUNT];
animation_handle AnimHandles[3];
u32 CurrAnim;
// NOTE(pjs): Based on temperature data from weatherman // NOTE(pjs): Based on temperature data from weatherman
// dim the leds. // dim the leds.
@ -158,7 +155,7 @@ struct blumen_lumen_state
system_time LastSendTime; system_time LastSendTime;
phrase_hue AssemblyColors[3]; phrase_hue AssemblyColors[BL_FLOWER_COUNT];
u32 LastAssemblyColorSet; u32 LastAssemblyColorSet;
// The indices of this array are the index the clear core uses to // The indices of this array are the index the clear core uses to
@ -171,12 +168,13 @@ struct blumen_lumen_state
bl_pattern_mode PatternMode; bl_pattern_mode PatternMode;
animation_handle_array ModeAnimations[BlumenPattern_Count]; animation_handle_array ModeAnimations[BlumenPattern_Count];
u32 CurrentAnimation;
phrase_hue_map PhraseHueMap; phrase_hue_map PhraseHueMap;
system_time TimeLastSetToVoiceMode;
// Debug // Debug
motor_packet DEBUG_PendingMotorPacket; motor_packet DEBUG_PendingMotorPacket;
bool DEBUG_IgnoreWeatherDimmingLeds;
}; };
#include "message_queue.cpp" #include "message_queue.cpp"

View File

@ -3,16 +3,35 @@
#ifndef BLUMEN_LUMEN_SETTINGS_H #ifndef BLUMEN_LUMEN_SETTINGS_H
#define BLUMEN_LUMEN_SETTINGS_H #define BLUMEN_LUMEN_SETTINGS_H
// Hey you never know, might need to change this some day lololol
// The number of flowers in the sculpture. Used to size all sorts of
// arrays. Maybe don't touch this unless you really know what you're doing?
#define BL_FLOWER_COUNT 3
// The path to the three flower assembly files
// PS is 90% sure you don't need to touch these ever
gs_const_string Flower0AssemblyPath = ConstString("data/ss_blumen_one.fold"); gs_const_string Flower0AssemblyPath = ConstString("data/ss_blumen_one.fold");
gs_const_string Flower1AssemblyPath = ConstString("data/ss_blumen_two.fold"); gs_const_string Flower1AssemblyPath = ConstString("data/ss_blumen_two.fold");
gs_const_string Flower2AssemblyPath = ConstString("data/ss_blumen_three.fold"); gs_const_string Flower2AssemblyPath = ConstString("data/ss_blumen_three.fold");
// The path to the phrase map CSV. Can be an absolute path, or relative
// to the app_run_tree folder
gs_const_string PhraseMapCSVPath = ConstString("data/flower_codes.csv"); gs_const_string PhraseMapCSVPath = ConstString("data/flower_codes.csv");
char PhraseMapCSVSeparator = ','; char PhraseMapCSVSeparator = ',';
// Search Strings for which folders to find ambient animation files and
// voice animation files in.
// these search patterns should always end in *.foldanim so they only
// return valid animation files
gs_const_string AmbientPatternFolder = ConstString("data/blumen_animations/ambient_patterns/*.foldanim"); gs_const_string AmbientPatternFolder = ConstString("data/blumen_animations/ambient_patterns/*.foldanim");
gs_const_string VoicePatternFolder = ConstString("data/blumen_animations/audio_responses/*.foldanim"); gs_const_string VoicePatternFolder = ConstString("data/blumen_animations/audio_responses/*.foldanim");
// The times of day when the motors should be open.
// these are in the format { Start_Hour, Start_Minute, End_Hour, End_Minute }
// Hours are in the range 0-23 inclusive
// Minutes are in the range 0-59 inclusive
// NOTE: There is no need to modify the MotorOpenTimesCount variable -
// it is a compile time constant that gets calculated automatically
global time_range MotorOpenTimes[] = { global time_range MotorOpenTimes[] = {
{ 00, 30, 00, 40 }, { 00, 30, 00, 40 },
{ 00, 50, 01, 00 }, { 00, 50, 01, 00 },
@ -59,8 +78,52 @@ global time_range MotorOpenTimes[] = {
{ 14, 30, 14, 40 }, { 14, 30, 14, 40 },
{ 14, 50, 15, 00 }, { 14, 50, 15, 00 },
}; };
global u32 MotorOpenTimesCount = CArrayLength(MotorOpenTimes); global u32 MotorOpenTimesCount = CArrayLength(MotorOpenTimes); // do not edit
// How long it takes to fade from the default pattern to the
// voice activated pattern
r32 VoiceCommandFadeDuration = 1.0f; // in seconds r32 VoiceCommandFadeDuration = 1.0f; // in seconds
// How long the voice activated pattern will remain active
// without additional voice commands, before fading back to
// default behaviour.
// ie.
// if this is set to 30 seconds, upon receiving a voice command
// lumenarium will fade to the requested pattern/color palette
// and then wait 30 seconds before fading back to the original
// pattern. If, in that 30 second window, another voice command
// is issued, lumenarium will reset the 30 second counter.
r64 VoiceCommandSustainDuration = 30.0; // in seconds
// When we send a Motor Close command, we don't want the upper leds to
// immediately turn off. Instead, we want to wait until the flower is
// at least some of the way closed. This variable dictates how long
// we wait for.
// For example:
// 1. We send a 'motor close' command to the clear core
// 2. the clear core sends back a 'motor closed' state packet
// 3. We begin a timer
// 4. When the timer reaches the value set in this variable,
// we turn the upper leds off.
//
// NOTE: This is not a symmetric operation. When we send a 'motor open'
// command, we want to immediately turn the upper leds on so they appear
// to have been on the whole time.
r64 TurnUpperLedsOffAfterMotorCloseCommandDelay = 5.0; // in seconds
// NOTE: Temperature & Time of Day Based Led Brightness Settings
// The percent brightness we set leds to during high temperatures.
// A value in the range 0:1 inclusive
// This is multiplied by each pixels R, G, & B channels before being
// sent. So if it is set to .1f, then the maximum brightness value sent
// to any channel of any pixel will be 25 (255 * .1 = 25).
r32 HighTemperatureBrightnessPercent = .25f;
// The percent brightness we set leds to when no other conditions apply
// A value in the range 0:1 inclusive.
// Probably wants to be something high like 1 but we might want to
// lower it for heat reasons?
r32 FullBrightnessPercent = 1.0f;
#endif //BLUMEN_LUMEN_SETTINGS_H #endif //BLUMEN_LUMEN_SETTINGS_H

View File

@ -2709,8 +2709,30 @@ PushSize_(gs_memory_arena* Arena, u64 Size, char* Location)
{ {
CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); CursorEntry = MemoryArenaNewCursor(Arena, Size, Location);
} }
Assert(CursorEntry);
Assert(CursorHasRoom(CursorEntry->Cursor, Size)); if (!CursorEntry || !CursorHasRoom(CursorEntry->Cursor, Size))
{
__debugbreak();
CursorEntry = 0;
for (u64 i = 0;
i < Arena->CursorsCount;
i++)
{
gs_memory_cursor_list* At = Arena->Cursors + i;
if (CursorHasRoom(At->Cursor, Size))
{
CursorEntry = At;
break;
}
}
if (!CursorEntry)
{
CursorEntry = MemoryArenaNewCursor(Arena, Size, Location);
}
}
//Assert(CursorEntry);
//Assert(CursorHasRoom(CursorEntry->Cursor, Size));
#else #else
gs_memory_cursor_list* CursorEntry = Arena->CursorList; gs_memory_cursor_list* CursorEntry = Arena->CursorList;

View File

@ -137,6 +137,9 @@ global_const r64 MinR64 = -MaxR64;
global_const r64 SmallestPositiveR64 = 4.94065645841247e-324; global_const r64 SmallestPositiveR64 = 4.94065645841247e-324;
global_const r64 EpsilonR64 = 1.11022302462515650e-16; global_const r64 EpsilonR64 = 1.11022302462515650e-16;
global_const r64 NanosToSeconds = 1 / 10000000.0;
global_const r64 SecondsToNanos = 10000000.0;
// TODO: va_start and va_arg replacements // TODO: va_start and va_arg replacements
internal r32 internal r32