Animation Playlists, lots of cleanup, settings file stuff, etc.
This commit is contained in:
parent
5ddca7fbac
commit
6b137154bc
|
@ -3,3 +3,4 @@ meta_run_tree/
|
||||||
process/
|
process/
|
||||||
reference/
|
reference/
|
||||||
working_data/
|
working_data/
|
||||||
|
nssm_log.log
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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});
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue