From 6b137154bcfd8e17e71b2fc65ed2d954e4e56ce4 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 27 Mar 2021 21:41:47 -0700 Subject: [PATCH] Animation Playlists, lots of cleanup, settings file stuff, etc. --- .gitignore | 1 + src/app/engine/animation/foldhaus_animation.h | 41 ++++- src/app/foldhaus_app.cpp | 5 + src/app/patterns/blumen_patterns.h | 2 +- src/app/platform_win32/win32_foldhaus.cpp | 67 +++++--- src/app/ss_blumen_lumen/blumen_lumen.cpp | 150 ++++++++++++++---- src/app/ss_blumen_lumen/blumen_lumen.h | 12 +- .../ss_blumen_lumen/blumen_lumen_settings.h | 65 +++++++- src/gs_libs/gs_types.cpp | 26 ++- src/gs_libs/gs_types.h | 3 + 10 files changed, 298 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index 4da1bd7..67d2a76 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ meta_run_tree/ process/ reference/ working_data/ +nssm_log.log \ No newline at end of file diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index a9a327d..adac56e 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -160,6 +160,9 @@ struct animation_system animation_array Animations; animation_repeat_mode RepeatMode; + animation_handle_array Playlist; + u32 PlaylistAt; + r32 PlaylistFadeTime; // 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 @@ -621,14 +624,21 @@ AnimationFadeGroup_Update(animation_fade_group* Group, r32 DeltaTime) internal void AnimationFadeGroup_FadeTo(animation_fade_group* Group, animation_handle To, r32 Duration) { - // complete current fade if there is one in progress - if (IsValid(Group->To)) + if (IsValid(Group->From)) { - 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 @@ -750,7 +760,15 @@ AnimationSystem_Update(animation_system* System, r32 DeltaTime) 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; 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 AnimationSystem_NeedsRender(animation_system System) { diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5519446..13852a5 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -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 // incorrect to clear the arena, and then access the memory later. ClearArena(State->Transient); + Assert(State->UserSpaceDesc.UserData.Memory != 0); if (State->RunEditor) { @@ -129,6 +130,7 @@ UPDATE_AND_RENDER(UpdateAndRender) AnimationSystem_Update(&State->AnimationSystem, Context->DeltaTime); if (AnimationSystem_NeedsRender(State->AnimationSystem)) { + Assert(State->UserSpaceDesc.UserData.Memory != 0); AnimationSystem_RenderToLedBuffers(&State->AnimationSystem, State->Assemblies, &State->LedSystem, @@ -138,7 +140,9 @@ UPDATE_AND_RENDER(UpdateAndRender) State->UserSpaceDesc.UserData.Memory); } + Assert(State->UserSpaceDesc.UserData.Memory != 0); US_CustomUpdate(&State->UserSpaceDesc, State, Context); + Assert(State->UserSpaceDesc.UserData.Memory != 0); AssemblyDebug_OverrideOutput(State->AssemblyDebugState, State->Assemblies, @@ -149,6 +153,7 @@ UPDATE_AND_RENDER(UpdateAndRender) Editor_Render(State, Context, RenderBuffer); } + Assert(State->UserSpaceDesc.UserData.Memory != 0); BuildAssemblyData(State, *Context, OutputData); } diff --git a/src/app/patterns/blumen_patterns.h b/src/app/patterns/blumen_patterns.h index 152d86c..4fe9588 100644 --- a/src/app/patterns/blumen_patterns.h +++ b/src/app/patterns/blumen_patterns.h @@ -1065,7 +1065,7 @@ Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 DEBUG_TRACK_FUNCTION; 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 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index cd1316d..82a98ff 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -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 WinMain ( HINSTANCE HInstance, @@ -636,6 +671,8 @@ WinMain ( Context.InitializeApplication(Context); + system_time StartTime = Win32GetSystemTime(); + Running = true; Context.WindowIsVisible = true; while (Running) @@ -647,31 +684,8 @@ WinMain ( 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_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; + Context.SystemTime_Current = Win32GetSystemTime(); #define PRINT_SYSTEM_TIME 0 #if PRINT_SYSTEM_TIME @@ -682,6 +696,11 @@ WinMain ( Context.SystemTime_Current.Minute, Context.SystemTime_Current.Second, 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); OutputDebugStringA(T.Str); #endif diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index d596bfc..4b4d224 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -174,6 +174,16 @@ BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData) 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 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_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 State->AnimationSystem.TimelineShouldAdvance = true; @@ -333,21 +343,16 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) BLState->AssemblyColors[0] = NewHue; BLState->AssemblyColors[1] = NewHue; BLState->AssemblyColors[2] = NewHue; - - animation_handle NewAnim = BLState->ModeAnimations[BlumenPattern_VoiceCommand].Handles[0]; - AnimationFadeGroup_FadeTo(&State->AnimationSystem.ActiveFadeGroup, - NewAnim, - VoiceCommandFadeDuration); } else { u32 AssemblyIdx = BLState->LastAssemblyColorSet; BLState->AssemblyColors[AssemblyIdx] = NewHue; + BLState->LastAssemblyColorSet = (BLState->LastAssemblyColorSet + 1) % 3; } - BLState->PatternMode = BlumenPattern_VoiceCommand; - // TODO(PS): get current time so we can fade back after - // a while + BlumenLumen_SetPatternMode(BlumenPattern_VoiceCommand, 5, &State->AnimationSystem, BLState); + BLState->TimeLastSetToVoiceMode = Context->SystemTime_Current; } }break; @@ -361,8 +366,18 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) Motor.Temperature = (T[0] << 8 | T[1] << 0); + motor_packet CurrPos = Motor.Pos; motor_packet LastPos = BLState->LastKnownMotorState; 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; }break; @@ -373,11 +388,11 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) if (Temp.Temperature > 0) { - BLState->BrightnessPercent = .25f; + BLState->BrightnessPercent = HighTemperatureBrightnessPercent; } else { - BLState->BrightnessPercent = 1.f; + BLState->BrightnessPercent = FullBrightnessPercent; } 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 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); } } - // 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]; - for (u32 j = 0; j < Buffer.LedCount; j++) + // have to map from "assembly load order" to + // 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; - Color->R = Color->R * BLState->BrightnessPercent; - Color->G = Color->G * BLState->BrightnessPercent; - Color->B = Color->B * BLState->BrightnessPercent; + u64 ChangedNanos = BLState->LastTimeMotorStateChanged[i]; + u64 NanosSinceChanged = NowNanos - ChangedNanos; + r64 SecondsSinceChanged = (r64)NanosSinceChanged * NanosToSeconds; + if (SecondsSinceChanged > TurnUpperLedsOffAfterMotorCloseCommandDelay) + { + BLState->ShouldDimUpperLeds[i] = true; + } } } // NOTE(PS): If the flowers are mostly open or full open // we mask off the top leds to prevent them from overheating // while telescoped inside the flower - motor_packet CurrMotorPos = BLState->LastKnownMotorState; - for (u32 a = 0; a < State->Assemblies.Count; a++) + for (u32 a = 0; a < BL_FLOWER_COUNT; a++) { assembly Assembly = State->Assemblies.Values[a]; - u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState); - - u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex]; - - if (MotorPos == MotorState_Closed || - MotorPos == MotorState_HalfOpen) - { - continue; - } + if (!BLState->ShouldDimUpperLeds[a]) continue; led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex]; - led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient); 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 { system_time LastSendTime = BLState->LastStatusUpdateTime; @@ -524,7 +576,7 @@ US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI) { 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); ui_BeginRow(I, 5); @@ -567,6 +619,40 @@ US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI) 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); } } diff --git a/src/app/ss_blumen_lumen/blumen_lumen.h b/src/app/ss_blumen_lumen/blumen_lumen.h index 1624a75..21d42c3 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.h +++ b/src/app/ss_blumen_lumen/blumen_lumen.h @@ -145,11 +145,8 @@ struct blumen_lumen_state mic_listen_job_data MicListenJobData; motor_packet LastKnownMotorState; - - r64 TimeElapsed; - - animation_handle AnimHandles[3]; - u32 CurrAnim; + u64 LastTimeMotorStateChanged[BL_FLOWER_COUNT]; + b8 ShouldDimUpperLeds[BL_FLOWER_COUNT]; // NOTE(pjs): Based on temperature data from weatherman // dim the leds. @@ -158,7 +155,7 @@ struct blumen_lumen_state system_time LastSendTime; - phrase_hue AssemblyColors[3]; + phrase_hue AssemblyColors[BL_FLOWER_COUNT]; u32 LastAssemblyColorSet; // 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; animation_handle_array ModeAnimations[BlumenPattern_Count]; - u32 CurrentAnimation; phrase_hue_map PhraseHueMap; + system_time TimeLastSetToVoiceMode; // Debug motor_packet DEBUG_PendingMotorPacket; + bool DEBUG_IgnoreWeatherDimmingLeds; }; #include "message_queue.cpp" diff --git a/src/app/ss_blumen_lumen/blumen_lumen_settings.h b/src/app/ss_blumen_lumen/blumen_lumen_settings.h index c254555..8fb514d 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen_settings.h +++ b/src/app/ss_blumen_lumen/blumen_lumen_settings.h @@ -3,16 +3,35 @@ #ifndef 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 Flower1AssemblyPath = ConstString("data/ss_blumen_two.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"); 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 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[] = { { 00, 30, 00, 40 }, { 00, 50, 01, 00 }, @@ -59,8 +78,52 @@ global time_range MotorOpenTimes[] = { { 14, 30, 14, 40 }, { 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 +// 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 diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index 64dec4a..8a6d074 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -2709,8 +2709,30 @@ PushSize_(gs_memory_arena* Arena, u64 Size, char* 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 gs_memory_cursor_list* CursorEntry = Arena->CursorList; diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index 293dbf2..49513f0 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -137,6 +137,9 @@ global_const r64 MinR64 = -MaxR64; global_const r64 SmallestPositiveR64 = 4.94065645841247e-324; 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 internal r32