From 37c30e1cb21f7ddeb2adc0d4011b9161806510f0 Mon Sep 17 00:00:00 2001 From: PS Date: Fri, 9 Apr 2021 14:59:55 -1000 Subject: [PATCH 1/4] Lumenarium now repeatedly sends the current motor position desired based on a variable in settings --- src/app/ss_blumen_lumen/blumen_lumen.cpp | 12 +++++++++++- src/app/ss_blumen_lumen/blumen_lumen_settings.h | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index b36653c..1a91994 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -616,6 +616,10 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue) && !BLState->IgnoreTimeOfDay_MotorState) { + u64 NanosSinceLastSend = Context->SystemTime_Current.NanosSinceEpoch - BLState->LastSendTime.NanosSinceEpoch; + r32 SecondsSinceLastSend = (r64)NanosSinceLastSend * NanosToSeconds; + bool ShouldSendCurrentState = SecondsSinceLastSend >= MotorResendStatePeriod; + for (u32 i = 0; i < MotorOpenTimesCount; i++) { time_range Range = MotorOpenTimes[i]; @@ -626,9 +630,13 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) bool LastTimeInRange = SystemTimeIsInTimeRange(Context->SystemTime_Last, Range); +#if 0 bool SendOpen = CurrTimeInRange && !LastSendTimeInRange; bool SendClose = !CurrTimeInRange && LastSendTimeInRange; - +#else + bool SendOpen = CurrTimeInRange && ShouldSendCurrentState; + bool SendClose = !CurrTimeInRange && ShouldSendCurrentState; +#endif //SendOpen = SecondsSinceLastSend > 2; if (SendOpen) { @@ -643,6 +651,7 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) Packet.MotorPacket.FlowerPositions[1] = 2; Packet.MotorPacket.FlowerPositions[2] = 2; MotorCommand = Packet; + break; } else if (SendClose) { @@ -656,6 +665,7 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) Packet.MotorPacket.FlowerPositions[1] = 1; Packet.MotorPacket.FlowerPositions[2] = 1; MotorCommand = Packet; + break; } } diff --git a/src/app/ss_blumen_lumen/blumen_lumen_settings.h b/src/app/ss_blumen_lumen/blumen_lumen_settings.h index b33a224..a55ce1b 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen_settings.h +++ b/src/app/ss_blumen_lumen/blumen_lumen_settings.h @@ -41,6 +41,11 @@ global time_range MotorOpenTimes[] = { }; global u32 MotorOpenTimesCount = CArrayLength(MotorOpenTimes); // do not edit +// Lumenarium repeatedly resends the current motor state to the python +// server. This variable determines how much time elapses between each +// message. +global r32 MotorResendStatePeriod = 90.0f; // seconds + // The times of day when the leds should be on // Search for @TimeFormat to find documentation global time_range LedOnTimes[] = { From cbd6433a30b8def5ebbfc95e116d5b13a6425f50 Mon Sep 17 00:00:00 2001 From: PS Date: Fri, 9 Apr 2021 15:45:28 -1000 Subject: [PATCH 2/4] Hue fading --- src/app/engine/animation/foldhaus_animation.h | 2 +- src/app/ss_blumen_lumen/phrase_hue_map.h | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 313ee68..8ae3430 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -678,7 +678,7 @@ AnimationSystem_Init(animation_system_desc Desc) Result.ActiveFadeGroup.FadeElapsed = 0; // Settings - Result.Multithreaded = true; + Result.Multithreaded = false; return Result; } diff --git a/src/app/ss_blumen_lumen/phrase_hue_map.h b/src/app/ss_blumen_lumen/phrase_hue_map.h index da3516d..3667210 100644 --- a/src/app/ss_blumen_lumen/phrase_hue_map.h +++ b/src/app/ss_blumen_lumen/phrase_hue_map.h @@ -70,11 +70,17 @@ LerpPHue(r32 T, p_hue A, p_hue B) { Result.Hue = LerpR64(T, A.Hue, B.Hue); } + else if (B.Hue > A.Hue) + { + Result.Hue = LerpR64(T, A.Hue, B.Hue - 360.0f); + } else { - Result.Hue = LerpR64(T, A.Hue + 360.0f, B.Hue); - Result.Hue = ModR32(Result.Hue, 360.0f); + Result.Hue = LerpR64(T, A.Hue - 360.0f, B.Hue); } + if (Result.Hue < 360) Result.Hue += 360; + if (Result.Hue > 360) Result.Hue -= 360; + Result.Hue = Clamp(0, Result.Hue, 360); if (T < 0.5f) { From 6f1d247bc8813b6ff3db774c5bc1f7853c91736d Mon Sep 17 00:00:00 2001 From: PS Date: Fri, 9 Apr 2021 15:59:32 -1000 Subject: [PATCH 3/4] Made Hues capable of smoothly lerping to white or black --- src/app/ss_blumen_lumen/blumen_lumen.cpp | 25 +++++++---- .../ss_blumen_lumen/blumen_lumen_settings.h | 2 +- src/app/ss_blumen_lumen/phrase_hue_map.h | 45 +++++++------------ 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index 1a91994..cee7f4e 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -413,14 +413,15 @@ BlumenLumen_CustomInit(app_state* State, context Context) #endif State->AnimationSystem.TimelineShouldAdvance = true; - BLState->StandardPatternHues.Hue0.Flags = Hue_Value; - BLState->StandardPatternHues.Hue1.Flags = Hue_Value; - BLState->StandardPatternHues.Hue2.Flags = Hue_Value; BLState->StandardPatternHues.Granularity = 1; BLState->StandardPatternHues.Speed = 1; BLState->StandardPatternHues.AddIn = AddIn_Rotary; BLState->StandardPatternHues.Pattern = HuePattern_Wavy; + BLState->DebugHue.Hue0.HSV = v4{0, 1, 1, 1}; + BLState->DebugHue.Hue1.HSV = v4{0, 1, 1, 1}; + BLState->DebugHue.Hue2.HSV = v4{0, 1, 1, 1}; + BlumenLumen_AppendBootupLog(State, BLState, Context); return Result; } @@ -581,9 +582,15 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) r32 ColorRelOscSpeed = 1 * ColorSpeed;; r32 ColorOscillation = (SinR32(BaseTime * ColorOscSpeed) + 1) / 2; r32 ColorRelationship = 30 + (((1 + SinR32(BaseTime * ColorRelOscSpeed)) / 2) * 300); - BLState->StandardPatternHues.Hue0.Hue = ModR32(ColorOscillation * 360, 360); - BLState->StandardPatternHues.Hue1.Hue = ModR32(BaseTime + ColorRelationship, 360); - BLState->StandardPatternHues.Hue2.Hue = LerpR32(.3f, BLState->StandardPatternHues.Hue0.Hue, BLState->StandardPatternHues.Hue1.Hue); + + r32 H0 = ModR32(ColorOscillation * 360, 360); + r32 H1 = ModR32(BaseTime + ColorRelationship, 360); + // TODO(PS): use our new HSV lerp + r32 H2 = LerpR32(.3f, H0, H1); + + BLState->StandardPatternHues.Hue0.HSV = v4{ H0, 1, 1, 1 }; + BLState->StandardPatternHues.Hue1.HSV = v4{ H1, 1, 1, 1 }; + BLState->StandardPatternHues.Hue2.HSV = v4{ H2, 1, 1, 1 }; // Transition back to standard mode after some time if (BLState->PatternMode == BlumenPattern_VoiceCommand) @@ -963,9 +970,9 @@ US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI) if (BLState->DebugOverrideHue) { phrase_hue PHue = BLState->DebugHue; - PHue.Hue0.Hue = (r64)ui_LabeledRangeSlider(I, MakeString("Hue0"), (r32)PHue.Hue0.Hue, 0, 360); - PHue.Hue1.Hue = (r64)ui_LabeledRangeSlider(I, MakeString("Hue1"), (r32)PHue.Hue1.Hue, 0, 360); - PHue.Hue2.Hue = (r64)ui_LabeledRangeSlider(I, MakeString("Hue2"), (r32)PHue.Hue2.Hue, 0, 360); + PHue.Hue0.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue0"), (r32)PHue.Hue0.HSV.x, 0, 360); + PHue.Hue1.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue1"), (r32)PHue.Hue1.HSV.x, 0, 360); + PHue.Hue2.HSV.x = (r64)ui_LabeledRangeSlider(I, MakeString("Hue2"), (r32)PHue.Hue2.HSV.x, 0, 360); PHue.Granularity = (u32)ui_LabeledRangeSlider(I, MakeString("Granularity"), (r32)PHue.Granularity, 0, 5); PHue.Speed = ui_LabeledRangeSlider(I, MakeString("Speed"), PHue.Speed, 0, 4); diff --git a/src/app/ss_blumen_lumen/blumen_lumen_settings.h b/src/app/ss_blumen_lumen/blumen_lumen_settings.h index a55ce1b..6f8c46c 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen_settings.h +++ b/src/app/ss_blumen_lumen/blumen_lumen_settings.h @@ -121,7 +121,7 @@ r32 GlobalAnimSpeed = 1.0f; r32 GlobalAnimTransitionSpeed = 0.0f; // how long it takes to fade from the old voice hue to the new one -r32 PhraseHueFadeInDuration = 2.0f; // seconds +r32 PhraseHueFadeInDuration = 1.0f; // seconds r64 PhrasePriorityMessageGroupingTime = 0.0f; diff --git a/src/app/ss_blumen_lumen/phrase_hue_map.h b/src/app/ss_blumen_lumen/phrase_hue_map.h index 3667210..39b36d2 100644 --- a/src/app/ss_blumen_lumen/phrase_hue_map.h +++ b/src/app/ss_blumen_lumen/phrase_hue_map.h @@ -29,8 +29,7 @@ enum p_hue_add_in typedef struct p_hue { - r64 Hue; - p_hue_flag Flags; + v4 HSV; } p_hue; typedef struct phrase_hue_map @@ -66,28 +65,25 @@ LerpPHue(r32 T, p_hue A, p_hue B) { p_hue Result = {}; - if (Abs(A.Hue - B.Hue) < 180.0f) + if (Abs(A.HSV.x - B.HSV.x) < 180.0f) { - Result.Hue = LerpR64(T, A.Hue, B.Hue); + Result.HSV.x = LerpR64(T, A.HSV.x, B.HSV.x); } - else if (B.Hue > A.Hue) + else if (B.HSV.x > A.HSV.x) { - Result.Hue = LerpR64(T, A.Hue, B.Hue - 360.0f); + Result.HSV.x = LerpR64(T, A.HSV.x, B.HSV.x - 360.0f); } else { - Result.Hue = LerpR64(T, A.Hue - 360.0f, B.Hue); + Result.HSV.x = LerpR64(T, A.HSV.x - 360.0f, B.HSV.x); } - if (Result.Hue < 360) Result.Hue += 360; - if (Result.Hue > 360) Result.Hue -= 360; - Result.Hue = Clamp(0, Result.Hue, 360); + if (Result.HSV.x < 360) Result.HSV.x += 360; + if (Result.HSV.x > 360) Result.HSV.x -= 360; + Result.HSV.x = Clamp(0, Result.HSV.x, 360); + Result.HSV.y = LerpR32(T, A.HSV.y, B.HSV.y); + Result.HSV.z = LerpR32(T, A.HSV.z, B.HSV.z); + Result.HSV.w = LerpR32(T, A.HSV.w, B.HSV.w); - if (T < 0.5f) - { - Result.Flags = A.Flags; - } else { - Result.Flags = B.Flags; - } return Result; } @@ -122,18 +118,18 @@ CreateHueFromString(gs_const_string Str) { p_hue Result = {}; if (Str.Str[0] == 'b') { - Result.Flags = Hue_Black; + Result.HSV = v4{0, 0, 1, 1 }; } else if (Str.Str[0] == 'w') { - Result.Flags = Hue_White; + Result.HSV = v4{0, 0, 0, 1 };; } else { - Result.Flags = Hue_Value; parse_float_result Parsed = ValidateAndParseFloat(Str); if (!Parsed.Success) { OutputDebugString("Failed to Parse CSV Float\n"); Parsed.Value = 0.0; } - Result.Hue = Parsed.Value; + Result.HSV = v4{ (r32)Parsed.Value, 1, 1, 1 }; + } return Result; } @@ -141,14 +137,7 @@ CreateHueFromString(gs_const_string Str) internal v4 RGBFromPhraseHue (p_hue H) { - v4 Result = {}; - switch (H.Flags) - { - case Hue_Black: { Result = v4{1, 0, 0, 1}; } break; - case Hue_White: { Result = v4{1, 0, 1, 1}; } break; - case Hue_Value: { Result = v4{(r32)H.Hue, 1, 1, 1}; } break; - InvalidDefaultCase; - } + v4 Result = H.HSV; Result = HSVToRGB(Result); return Result; } From 9404a6b57de5e52e8d7a8127f50f6aa8242fd3c4 Mon Sep 17 00:00:00 2001 From: PS Date: Fri, 9 Apr 2021 16:15:25 -1000 Subject: [PATCH 4/4] Override all hue phrases --- src/app/ss_blumen_lumen/blumen_lumen.cpp | 3 ++- src/app/ss_blumen_lumen/phrase_hue_map.h | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index cee7f4e..d711f23 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -457,7 +457,8 @@ BlumenLumen_ApplyNextHotHue(blumen_lumen_state* BLState, context Context, gs_str OutputDebugString(DebugStr->Str); - if (BLState->PatternMode == BlumenPattern_Standard) + if (BLState->PatternMode == BlumenPattern_Standard || + NewHue.OverrideAll) { BlumenLumen_SetNextHue(BLState, 0, NewHue); BlumenLumen_SetNextHue(BLState, 1, NewHue); diff --git a/src/app/ss_blumen_lumen/phrase_hue_map.h b/src/app/ss_blumen_lumen/phrase_hue_map.h index 39b36d2..89ec6e0 100644 --- a/src/app/ss_blumen_lumen/phrase_hue_map.h +++ b/src/app/ss_blumen_lumen/phrase_hue_map.h @@ -45,6 +45,7 @@ typedef struct phrase_hue_map r32* Speed; u8* Pattern; u8* AddIn; + bool* OverrideAll; } phrase_hue_map; typedef struct phrase_hue @@ -58,6 +59,7 @@ typedef struct phrase_hue r32 Speed; u8 Pattern; u8 AddIn; + bool OverrideAll; } phrase_hue; internal p_hue @@ -118,9 +120,9 @@ CreateHueFromString(gs_const_string Str) { p_hue Result = {}; if (Str.Str[0] == 'b') { - Result.HSV = v4{0, 0, 1, 1 }; + Result.HSV = v4{0, 0, 0, 1 }; } else if (Str.Str[0] == 'w') { - Result.HSV = v4{0, 0, 0, 1 };; + Result.HSV = v4{0, 0, 1, 1 };; } else { parse_float_result Parsed = ValidateAndParseFloat(Str); if (!Parsed.Success) @@ -158,6 +160,7 @@ PhraseHueMap_GenFromCSV(gscsv_sheet Sheet, gs_memory_arena* Arena) Result.Pattern = PushArray(Arena, u8, Result.CountMax); Result.Speed = PushArray(Arena, r32, Result.CountMax); Result.AddIn = PushArray(Arena, u8, Result.CountMax); + Result.OverrideAll = PushArray(Arena, bool, Result.CountMax); // this lets us tightly pack phrase_hues even if there is a // row in the csv that is empty or invalid @@ -177,6 +180,7 @@ PhraseHueMap_GenFromCSV(gscsv_sheet Sheet, gs_memory_arena* Arena) gs_const_string Speed = CSVSheet_GetCell(Sheet, 6, Row); gs_const_string Pattern = CSVSheet_GetCell(Sheet, 7, Row); gs_const_string AddIn = CSVSheet_GetCell(Sheet, 8, Row); + gs_const_string OverrideAll = CSVSheet_GetCell(Sheet, 9, Row); // essential parameters if (Phrase.Length == 0 || @@ -234,6 +238,8 @@ PhraseHueMap_GenFromCSV(gscsv_sheet Sheet, gs_memory_arena* Arena) ParsedGranularity.Value = 1; } Result.Gran[Index] = ParsedGranularity.Value; + + Result.OverrideAll[Index] = StringsEqualUpToLength(OverrideAll, ConstString("yes"), 3); } Result.Count = Result.CountMax + DestOffset; @@ -255,6 +261,7 @@ PhraseHueMap_Get(phrase_hue_map Map, u32 Index) Result.Speed = Map.Speed[Index]; Result.AddIn = Map.AddIn[Index]; Result.Pattern = Map.Pattern[Index]; + Result.OverrideAll = Map.OverrideAll[Index]; return Result; }