Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
PS 2021-03-24 19:20:26 -07:00
commit 2fa1a9b178
16 changed files with 581 additions and 210 deletions

View File

@ -25,12 +25,12 @@ SET LastError=%ERRORLEVEL%
del lock.tmp
cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib
cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib Winspool.lib
REM COMPILE UTILITY EXES
cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib Winspool.lib
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib

View File

@ -752,6 +752,17 @@ ui_PushOverlayLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction
return Result;
}
static gs_string
ui_PushLayoutCategoryName(ui_interface* Interface, gs_string Category, u32 Value)
{
gs_string Result = PushStringF(Interface->PerFrameMemory,
Category.Length + 25,
"%S%d",
Category.ConstString,
Value);
return Result;
}
static ui_widget*
ui_PushLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Name)
{
@ -770,6 +781,12 @@ ui_PushLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir
Interface->ActiveLayout = Result;
return Result;
}
static ui_widget*
ui_PushLayout(ui_interface* Interface, rect2 Bounds, ui_layout_direction FillDir, gs_string Category, u32 Value)
{
gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value);
return ui_PushLayout(Interface, Bounds, FillDir, Name);
}
static ui_widget*
ui_PushLayout(ui_interface* Interface, gs_string Name, bool Inset = true)
@ -837,7 +854,16 @@ ui_PopLayout(ui_interface* Interface, gs_string LayoutName)
// NOTE(pjs): If this isn't true then a layout was opened without being closed
// Go check for ui_PushLayout, ui_BeginDropdown, ui_BeginRow, etc that don't have
// a corresponding ui_Pop/ui_End*
Assert(StringsEqual(Layout->String, LayoutName));
//
// We use StringsEqualUpToLength here becuase its possible that
// the current layout used the Category + Identifier method
// for generating Layout->String. And if Identifier was a string
// that was edited within the scope of this layout, then
// Layout->String and LayoutName will no longer match.
//
// This is a compromise that will at least let us know if
// we aren't popping all our layouts correctly.
Assert(StringsEqualUpToLength(Layout->String, LayoutName, LayoutName.Length));
ui_ExpandToFitChildren(Layout);
@ -851,6 +877,12 @@ ui_PopLayout(ui_interface* Interface, gs_string LayoutName)
ui_CommitBounds(Interface->ActiveLayout, Layout->Bounds);
}
}
static void
ui_PopLayout(ui_interface* Interface, gs_string Category, u32 Value)
{
gs_string Name = ui_PushLayoutCategoryName(Interface, Category, Value);
ui_PopLayout(Interface, Name);
}
static ui_widget*
ui_BeginRow(ui_interface* Interface, u32 ColumnsMax)
@ -1050,6 +1082,7 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
else
{
OutChar(&State->EditString, Interface->TempInputString.Str[i]);
Interface->CursorPosition += 1;
}
}
}

View File

@ -14,7 +14,9 @@ struct animation_timeline_state
frame_range VisibleRange;
handle SelectedBlockHandle;
animation_handle EditingAnimationHandle;
u32 SelectedAnimationLayer;
s32 SelectedAnimationLayer;
animation_handle NextActiveAnim;
};
inline u32
@ -263,7 +265,8 @@ AnimationTimeline_AddAnimationBlockCommand(animation_timeline_state* TimelineSta
if ((EndFrame - StartFrame) > 0)
{
animation_pattern_handle PatternHandle = Patterns_IndexToHandle(0);
u32 Layer = TimelineState->SelectedAnimationLayer;
s32 Layer = TimelineState->SelectedAnimationLayer;
Assert(Layer >= 0);
handle NewBlockHandle = Animation_AddBlock(ActiveAnim, StartFrame, EndFrame, PatternHandle, Layer);
@ -504,13 +507,10 @@ PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback)
if (FileInfo.Path.Length > 0)
{
gs_file AnimFile = ReadEntireFile(Context.ThreadContext.FileHandler, FileInfo.Path);
gs_string AnimFileString = MakeString((char*)AnimFile.Data.Memory, AnimFile.Data.Size);
animation NewAnim = AnimParser_Parse(AnimFileString, State->AnimationSystem.Storage, State->Patterns);
NewAnim.FileInfo = AnimFile.FileInfo;
animation_handle NewAnimHandle = AnimationArray_Push(&State->AnimationSystem.Animations, NewAnim);
animation_handle NewAnimHandle = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem,
State->Patterns,
Context,
FileInfo.Path);
State->AnimationSystem.ActiveFadeGroup.From = NewAnimHandle;
}
}
@ -639,7 +639,7 @@ LayerList_Render(animation_timeline_state* TimelineState, animation* ActiveAnim,
if (ActiveAnim)
{
v2 LayerTextPos = {};
for (u32 i = 0; i < ActiveAnim->Layers.Count; i++)
for (s32 i = 0; i < (s32)ActiveAnim->Layers.Count; i++)
{
anim_layer* Layer = ActiveAnim->Layers.Values + i;
@ -762,11 +762,9 @@ PANEL_MODAL_OVERRIDE_CALLBACK(AnimInfoView_SaveAnimFileCallback)
}
internal void
AnimationTimeline_SetActiveAnimation (animation_handle Handle, animation_timeline_state* TimelineState,
animation_system* System)
AnimationTimeline_SetActiveAnimation (animation_handle Handle, animation_timeline_state* TimelineState)
{
System->ActiveFadeGroup.From = Handle;
TimelineState->EditingAnimationHandle = Handle;
TimelineState->NextActiveAnim = Handle;
}
internal void
@ -774,8 +772,9 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAn
{
animation_system* AnimSystem = &State->AnimationSystem;
animation_handle ActiveAnimHandle = State->AnimationSystem.ActiveFadeGroup.From;
ui_interface* Interface = &State->Interface;
ui_PushLayout(Interface, Bounds, LayoutDirection_TopDown, MakeString("AnimInfo Layout"));
ui_PushLayout(Interface, Bounds, LayoutDirection_TopDown, MakeString("AnimInfo Layout"), ActiveAnimHandle.Index);
ui_FillRect(&State->Interface, Bounds, Interface->Style.PanelBG);
@ -796,7 +795,7 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAn
{
animation_handle NewHandle = {};
NewHandle.Index = i;
AnimationTimeline_SetActiveAnimation(NewHandle, TimelineState, AnimSystem);
AnimationTimeline_SetActiveAnimation(NewHandle, TimelineState);
}
}
}
@ -806,18 +805,22 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAn
{
if (ui_Button(Interface, MakeString("New")))
{
animation NewAnim = {};
NewAnim.Name = PushString(State->AnimationSystem.Storage, 256);
animation_desc Desc = {};
Desc.NameSize = 256;
Desc.LayersCount = 8;
Desc.BlocksCount = 8;
Desc.MinFrames = 0;
Desc.MaxFrames = SecondsToFrames(15, State->AnimationSystem);
animation NewAnim = Animation_Create(Desc, &State->AnimationSystem);
animation_handle NewAnimHandle = AnimationArray_Push(&State->AnimationSystem.Animations, NewAnim);
State->AnimationSystem.ActiveFadeGroup.From = NewAnimHandle;
AnimationTimeline_SetActiveAnimation(NewAnimHandle, TimelineState);
}
if (ActiveAnim && ui_Button(Interface, MakeString("Save")))
{
// Save Animation File
// TODO(pjs): If you created the animation via the "new" button, there won't be a file attached.
// need to use the file browser to create a file
animation_handle ActiveAnimHandle = State->AnimationSystem.ActiveFadeGroup.From;
animation ActiveAnimation = *AnimationArray_GetSafe(State->AnimationSystem.Animations, ActiveAnimHandle);
if (!ActiveAnimation.FileInfo.Path.Str)
@ -853,22 +856,26 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAn
ui_Label(Interface, MakeString("Layer"));
u32 LayerIndex = TimelineState->SelectedAnimationLayer;
anim_layer* SelectedLayer = ActiveAnim->Layers.Values + LayerIndex;
ui_TextEntry(Interface, MakeString("Layer Name"), &SelectedLayer->Name);
gs_string BlendStr = BlendModeStrings[SelectedLayer->BlendMode];
if (ui_BeginLabeledDropdown(Interface, MakeString("Blend Mode"), BlendStr))
s32 LayerIndex = TimelineState->SelectedAnimationLayer;
anim_layer* SelectedLayer = 0;
if (LayerIndex >= 0)
{
for (u32 i = 0; i < BlendMode_Count; i++)
SelectedLayer = ActiveAnim->Layers.Values + LayerIndex;
ui_TextEntry(Interface, MakeString("Layer Name"), &SelectedLayer->Name);
gs_string BlendStr = BlendModeStrings[SelectedLayer->BlendMode];
if (ui_BeginLabeledDropdown(Interface, MakeString("Blend Mode"), BlendStr))
{
if (ui_Button(Interface, BlendModeStrings[i]))
for (u32 i = 0; i < BlendMode_Count; i++)
{
SelectedLayer->BlendMode = (blend_mode)i;
if (ui_Button(Interface, BlendModeStrings[i]))
{
SelectedLayer->BlendMode = (blend_mode)i;
}
}
}
ui_EndLabeledDropdown(Interface);
}
ui_EndLabeledDropdown(Interface);
ui_Label(Interface, MakeString("Pattern"));
@ -917,11 +924,12 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
animation* ActiveAnim = 0;
animation_handle Handle = State->AnimationSystem.ActiveFadeGroup.From;
TimelineState->EditingAnimationHandle = Handle;
if (IsValid(Handle))
{
animation_array Animations = State->AnimationSystem.Animations;
ActiveAnim = AnimationArray_GetSafe(Animations, Handle);
TimelineState->EditingAnimationHandle = Handle;
TimelineState->NextActiveAnim = Handle;
}
ui_FillRect(&State->Interface, PanelBounds, v4{.1f,.1f,.1f,1.f});
@ -944,6 +952,14 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
LayerList_Render(TimelineState, ActiveAnim, LayersBounds, Panel, RenderBuffer, State, Context);
TimeRange_Render(TimelineState, ActiveAnim, TimeRangeBounds, RenderBuffer, State, Context);
AnimInfoView_Render(TimelineState, ActiveAnim, InfoBounds, Panel, RenderBuffer, State, Context);
if (!AnimHandlesAreEqual(TimelineState->NextActiveAnim,
Handle))
{
State->AnimationSystem.ActiveFadeGroup.From = TimelineState->NextActiveAnim;
TimelineState->EditingAnimationHandle = TimelineState->NextActiveAnim;
TimelineState->SelectedAnimationLayer = -1;
}
}
#define FOLDHAUS_PANEL_ANIMATION_TIMELINE_H

View File

@ -5,7 +5,7 @@
//
#ifndef FOLDHAUS_ANIMATION
#define ANIMATION_PROC(name) void name(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
#define ANIMATION_PROC(name) void name(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
typedef ANIMATION_PROC(animation_proc);
struct frame_range
@ -164,6 +164,8 @@ struct animation_system
r32 SecondsPerFrame;
b32 TimelineShouldAdvance;
// Settings
bool Multithreaded;
};
// NOTE(pjs): A Pattern is a named procedure which can be used as
@ -174,6 +176,7 @@ struct animation_pattern
char* Name;
s32 NameLength;
animation_proc* Proc;
bool Multithreaded;
};
struct animation_pattern_array
@ -250,9 +253,14 @@ Patterns_Create(gs_memory_arena* Arena, s32 CountMax)
return Result;
}
#define Patterns_PushPattern(array, proc) Patterns_PushPattern_((array), (proc), Stringify(proc), sizeof(Stringify(proc)) - 1)
#define PATTERN_MULTITHREADED true
#define PATTERN_SINGLETHREADED false
#define Patterns_PushPattern(array, proc, multithread) \
Patterns_PushPattern_((array), (proc), Stringify(proc), sizeof(Stringify(proc)) - 1, (multithread))
internal void
Patterns_PushPattern_(animation_pattern_array* Array, animation_proc* Proc, char* Name, u32 NameLength)
Patterns_PushPattern_(animation_pattern_array* Array, animation_proc* Proc, char* Name, u32 NameLength, bool Multithreaded)
{
Assert(Array->Count < Array->CountMax);
@ -260,6 +268,7 @@ Patterns_PushPattern_(animation_pattern_array* Array, animation_proc* Proc, char
Pattern.Name = Name;
Pattern.NameLength = NameLength;
Pattern.Proc = Proc;
Pattern.Multithreaded = Multithreaded;
Array->Values[Array->Count++] = Pattern;
}
@ -410,6 +419,38 @@ AnimationArray_GetSafe(animation_array Array, animation_handle Handle)
//
// Animation
typedef struct animation_desc
{
u32 NameSize;
char* Name;
u32 LayersCount;
u32 BlocksCount;
u32 MinFrames;
u32 MaxFrames;
} animation_desc;
internal animation
Animation_Create(animation_desc Desc, animation_system* System)
{
animation Result = {};
u32 NameLen = Desc.NameSize;
if (Desc.Name)
{
NameLen = Max(CStringLength(Desc.Name), NameLen);
Result.Name = PushStringF(System->Storage, NameLen, "%s", Desc.Name);
} else {
Result.Name = PushStringF(System->Storage, NameLen, "[New Animation]");
}
Result.Layers = AnimLayerArray_Create(System->Storage, Desc.LayersCount);
Result.Blocks_ = AnimBlockArray_Create(System->Storage, Desc.BlocksCount);
Result.PlayableRange.Min = Desc.MinFrames;
Result.PlayableRange.Max = Desc.MaxFrames;
return Result;
}
internal handle
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, animation_pattern_handle AnimationProcHandle, u32 LayerIndex)
{
@ -604,6 +645,9 @@ AnimationSystem_Init(animation_system_desc Desc)
Clear(&Result.ActiveFadeGroup.To);
Result.ActiveFadeGroup.FadeElapsed = 0;
// Settings
Result.Multithreaded = true;
return Result;
}

View File

@ -89,14 +89,79 @@ struct pattern_args
u8* UserData;
};
internal void
AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs)
struct render_anim_to_led_buffer_job_data
{
animation_pattern Pattern;
led_buffer Buffer;
led_buffer_range BufferRange;
pattern_args PatternArgs;
r32 SecondsIntoBlock;
};
internal void
AnimationSystem_RenderAnimationToLedBufferJob(gs_thread_context Context, gs_data Data)
{
render_anim_to_led_buffer_job_data JobData = *(render_anim_to_led_buffer_job_data*)Data.Memory;
JobData.Pattern.Proc(&JobData.Buffer,
JobData.BufferRange,
JobData.PatternArgs.Assembly,
JobData.SecondsIntoBlock,
JobData.PatternArgs.Transient,
JobData.PatternArgs.UserData);
}
#define MULTITHREAD_PATTERN_RENDERING 1
internal void
AnimationSystem_BeginRenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs,
context Context)
{
DEBUG_TRACK_FUNCTION;
u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle);
Pattern.Proc(Buffer, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData);
if (System->Multithreaded && Pattern.Multithreaded)
{
u32 JobsCount = 4;
u32 LedsPerJob = Buffer->LedCount / JobsCount;
for (u32 i = 0; i < JobsCount; i++)
{
gs_data Data = PushSizeToData(Context.ThreadContext.Transient, sizeof(render_anim_to_led_buffer_job_data));
render_anim_to_led_buffer_job_data* JobData = (render_anim_to_led_buffer_job_data*)Data.Memory;
JobData->Pattern = Pattern;
JobData->Buffer = *Buffer;
JobData->BufferRange.First = LedsPerJob * i;
JobData->BufferRange.OnePastLast = LedsPerJob * (i + 1);
JobData->PatternArgs = PatternArgs;
JobData->SecondsIntoBlock = SecondsIntoBlock;
Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue,
(thread_proc*)AnimationSystem_RenderAnimationToLedBufferJob,
Data,
ConstString("Render Pattern To Buffer"));
}
}
else
{
led_buffer_range Range = {};
Range.First = 0;
Range.OnePastLast = Buffer->LedCount;
Pattern.Proc(Buffer, Range, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData);
}
}
internal void
AnimationSystem_EndRenderBlockToLedBuffer (animation_system* System, context Context)
{
if (System->Multithreaded)
{
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
}
}
// NOTE(pjs): This mirrors animation_layer_frame to account
@ -114,7 +179,8 @@ RenderAnimationToLedBuffer (animation_system* System,
layer_led_buffer* LayerBuffers,
led_buffer* AssemblyLedBuffer,
animation_pattern_array Patterns,
gs_memory_arena* Transient)
gs_memory_arena* Transient,
context Context)
{
led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient);
@ -144,15 +210,17 @@ RenderAnimationToLedBuffer (animation_system* System,
{
led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer;
animation_block Block = LayerFrame.Hot;
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs);
AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
}
if (LayerFrame.HasNextHot)
{
led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer;
animation_block Block = LayerFrame.NextHot;
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs);
AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
}
AnimationSystem_EndRenderBlockToLedBuffer(System, Context);
}
// Blend together any layers that have a hot and next hot buffer
@ -193,8 +261,11 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
led_system* LedSystem,
animation_pattern_array Patterns,
gs_memory_arena* Transient,
context Context,
u8* UserData)
{
DEBUG_TRACK_FUNCTION;
s32 CurrentFrame = System->CurrentFrame;
r32 FrameTime = CurrentFrame * System->SecondsPerFrame;
@ -231,7 +302,8 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
FromLayerBuffers,
AssemblyLedBuffer,
Patterns,
Transient);
Transient,
Context);
led_buffer ConsolidatedBuffer = FromBuffer;
if (ToAnim) {
@ -241,7 +313,8 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
ToLayerBuffers,
AssemblyLedBuffer,
Patterns,
Transient);
Transient,
Context);
r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration;
LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent);

View File

@ -182,9 +182,23 @@ AnimParser_Parse(gs_string File, gs_memory_arena* Arena, animation_pattern_array
}
}
}
return Result;
}
internal animation
AnimParser_Parse(gs_data File, gs_memory_arena* Arena, animation_pattern_array AnimPatterns)
{
gs_string FileString = MakeString((char*)File.Memory, File.Size);
return AnimParser_Parse(FileString, Arena, AnimPatterns);
}
internal animation_handle
AnimationSystem_LoadAnimationFromFile(animation_system* System, animation_pattern_array AnimPatterns, context Context, gs_const_string FilePath)
{
gs_file AnimFile = ReadEntireFile(Context.ThreadContext.FileHandler, FilePath);
animation NewAnim = AnimParser_Parse(AnimFile.Data, System->Storage, AnimPatterns);
NewAnim.FileInfo = AnimFile.FileInfo;
animation_handle NewAnimHandle = AnimationArray_Push(&System->Animations, NewAnim);
return NewAnimHandle;
}
#define FOLDHAUS_ANIMATION_SERIALIZER_CPP
#endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP

View File

@ -32,6 +32,12 @@ struct led_buffer
v4* Positions;
};
struct led_buffer_range
{
u32 First;
u32 OnePastLast;
};
struct led_system
{
gs_allocator PlatformMemory;
@ -184,6 +190,8 @@ LedBuffer_ClearToBlack(led_buffer* Buffer)
internal void
LedBuffer_Copy(led_buffer From, led_buffer* To)
{
DEBUG_TRACK_FUNCTION;
Assert(From.LedCount == To->LedCount);
u32 LedCount = To->LedCount;
for (u32 i = 0; i < LedCount; i++)
@ -195,6 +203,8 @@ LedBuffer_Copy(led_buffer From, led_buffer* To)
internal void
LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* BlendProc, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
Assert(A.LedCount == B.LedCount);
Assert(Dest->LedCount == A.LedCount);
Assert(BlendProc);
@ -211,6 +221,8 @@ LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* Bl
internal led_buffer
LedBuffer_CreateCopyCleared (led_buffer Buffer, gs_memory_arena* Arena)
{
DEBUG_TRACK_FUNCTION;
led_buffer Result = {};
Result.LedCount = Buffer.LedCount;
Result.Positions = Buffer.Positions;

View File

@ -95,6 +95,21 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->RunEditor = true;
}
internal void
BuildAssemblyData (app_state* State, context Context, addressed_data_buffer_list* OutputData)
{
#define SEND_DATA
#ifdef SEND_DATA
// NOTE(pjs): Building data buffers to be sent out to the sculpture
// This array is used on the platform side to actually send the information
assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient);
assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient);
SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem);
UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient);
#endif
}
UPDATE_AND_RENDER(UpdateAndRender)
{
DEBUG_TRACK_FUNCTION;
@ -119,6 +134,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
&State->LedSystem,
State->Patterns,
State->Transient,
*Context,
State->UserSpaceDesc.UserData.Memory);
}
@ -133,20 +149,21 @@ UPDATE_AND_RENDER(UpdateAndRender)
Editor_Render(State, Context, RenderBuffer);
}
#define SEND_DATA
#ifdef SEND_DATA
// NOTE(pjs): Building data buffers to be sent out to the sculpture
// This array is used on the platform side to actually send the information
assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient);
assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient);
SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem);
UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient);
#endif
BuildAssemblyData(State, *Context, OutputData);
}
CLEANUP_APPLICATION(CleanupApplication)
{
app_state* State = (app_state*)Context.MemoryBase;
for (u32 i = 0; i < State->Assemblies.Count; i++)
{
assembly Assembly = State->Assemblies.Values[i];
led_buffer LedBuffer = State->LedSystem.Buffers[Assembly.LedBufferIndex];
AssemblyDebug_OverrideWithColor(Assembly, LedBuffer, pixel{0, 0, 0});
}
BuildAssemblyData(State, Context, OutputData);
US_CustomCleanup(&State->UserSpaceDesc, State, Context);
SACN_Cleanup(&State->SACN, Context);
}

View File

@ -76,7 +76,7 @@ typedef UPDATE_AND_RENDER(update_and_render);
#define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices)
typedef RELOAD_STATIC_DATA(reload_static_data);
#define CLEANUP_APPLICATION(name) void name(context Context)
#define CLEANUP_APPLICATION(name) void name(context Context, addressed_data_buffer_list* OutputData)
typedef CLEANUP_APPLICATION(cleanup_application);
// Platform Functions

View File

@ -411,30 +411,30 @@ GetColor(v4* Colors, u32 ColorsCount, r32 Percent)
}
internal void
SolidColorPattern(led_buffer* Leds, pixel Color)
SolidColorPattern(led_buffer* Leds, led_buffer_range Range, pixel Color)
{
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
Leds->Colors[LedIndex] = Color;
}
}
internal void
Pattern_Blue(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_Blue(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
pixel Blue = pixel{0, 0, 255};
SolidColorPattern(Leds, Blue);
SolidColorPattern(Leds, Range, Blue);
}
internal void
Pattern_Green(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_Green(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
pixel Green = pixel{0, 255, 0};
SolidColorPattern(Leds, Green);
SolidColorPattern(Leds, Range, Green);
}
internal void
Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_FlowerColors(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 CycleTime = 10;
r32 CyclePercent = ModR32(Time, CycleTime) / CycleTime;
@ -442,7 +442,7 @@ Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
v4 CA = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, CyclePercent);
v4 CB = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, 1.0f - CyclePercent);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 Pct = (Abs(ModR32(P.y, 150) / 150) + CycleTime) * PiR32;
@ -453,7 +453,7 @@ Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
}
internal void
TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
TestPatternOne(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient);
led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient);
@ -485,7 +485,7 @@ TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
}
internal void
TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
TestPatternTwo(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 PeriodicTime = (Time / PiR32) * 2;
@ -504,7 +504,7 @@ TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
r32 OuterRadiusSquared = 1000000;
r32 InnerRadiusSquared = 0;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 Position = Leds->Positions[LedIndex];
@ -537,7 +537,7 @@ TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
}
internal void
TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
TestPatternThree(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
v4 GreenCenter = v4{0, 0, 150, 1};
r32 GreenRadius = Abs(SinR32(Time)) * 200;
@ -548,7 +548,7 @@ TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
r32 FadeDist = 35;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 LedPosition = Leds->Positions[LedIndex];
u8 Red = 0;
@ -702,7 +702,7 @@ while (Hue > 360.0f) { Hue -= 360.0f; }
}
internal void
Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_HueShift(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 Height = SinR32(Time) * 25;
@ -713,7 +713,7 @@ Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
v4 HSV = { CycleProgress * 360, 1, 1, 1 };
v4 RGB = HSVToRGB(HSV);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 Pos = Leds->Positions[LedIndex];
r32 Dist = Pos.y - Height;
@ -732,7 +732,7 @@ Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
}
internal void
Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_HueFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 HueBase = ModR32(Time * 50, 360);
@ -740,7 +740,7 @@ Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
r32 CycleProgress = FractR32(Time / CycleLength);
r32 CycleBlend = (SinR32(Time) * .5f) + .5f;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 Pos = Leds->Positions[LedIndex];
r32 Hue = HueBase + Pos.y + Pos.x;
@ -752,9 +752,9 @@ Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
}
internal void
Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_AllGreen(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
u32 I = LedIndex + 1;
Leds->Colors[LedIndex] = {};
@ -781,7 +781,7 @@ PatternHash(r32 Seed)
}
internal void
Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_Spots(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
pixel ColorA = { 0, 255, 255 };
pixel ColorB = { 255, 0, 255 };
@ -790,7 +790,7 @@ Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
Time *= Speed;
r32 ScaleA = 2 * SinR32(Time / 5);
r32 ScaleB = 2.4f * CosR32(Time / 2.5f);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 V = P.y;
@ -807,10 +807,10 @@ Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
}
internal void
Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_LighthouseRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) });
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v2 Vector = v2{
Leds->Positions[LedIndex].x,
@ -828,7 +828,7 @@ Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memo
}
internal void
Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_SmoothGrowRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f;
r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f;
@ -850,7 +850,7 @@ Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memo
}
internal void
Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_GrowAndFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 PercentCycle = ModR32(Time, 10) / 10;
v4 HSV = { PercentCycle * 360, 1, 1, 1 };
@ -859,7 +859,7 @@ Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_are
r32 RefHeight = -100 + (Smoothstep(PercentCycle * 1.4f) * 400);
r32 RefBrightness = 1.0f - Smoothstep(PercentCycle);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
@ -873,7 +873,7 @@ Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_are
}
internal void
Pattern_ColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_ColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 FadeBottomBase = 50;
r32 FadeTop = 125;
@ -935,7 +935,7 @@ Pattern_ColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
}
internal void
Pattern_FlowerColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_FlowerColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
r32 FadeBottomBase = 50;
r32 FadeTop = 125;
@ -999,7 +999,7 @@ v4* FBC = &FlowerBColors[0];
v4* FCC = &FlowerCColors[0];
internal void
Pattern_BasicFlowers(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_BasicFlowers(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
if (TLastFrame > Time)
{
@ -1042,16 +1042,11 @@ Pattern_BasicFlowers(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
}
internal void
Pattern_Wavy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_Wavy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
}
internal void
Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
#if 0
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
@ -1072,8 +1067,14 @@ Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
//Leds->Colors[LedIndex] = pixel{NV, NV, NV};
}
#elif 1
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
}
internal void
Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f;
@ -1093,37 +1094,17 @@ Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
v4 C = CA + CB;
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
#else
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f;
r32 ScaleFactor = 1.0f / LedRange;
v3 Pp = P.xyz + v3{150, 100, 0};
r32 NoiseA = Fbm3D((Pp / 35), Time * 0.5f);
//NoiseA = PowR32(NoiseA, 3);
NoiseA = Smoothstep(NoiseA);
v4 CA = v4{1, 0, 1, 1} * NoiseA;
r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 5});
NoiseB = PowR32(NoiseB, 3);
NoiseB = Smoothstep(NoiseB);
v4 CB = v4{0, 1, 1, 1};
v4 C = V4Lerp(NoiseB, CA, CB);
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
#endif
}
internal void
Pattern_Leafy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_Leafy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
v4* Colors = &FlowerBColors[0];
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
@ -1177,15 +1158,70 @@ Pattern_Leafy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
}
internal void
Pattern_LeafyPatchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_LeafyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f;
r32 ScaleFactor = 1.0f / LedRange;
v3 Pp = P.xyz + v3{150, 100, 0};
r32 NoiseA = Fbm3D((Pp / 35), Time * 0.5f);
//NoiseA = PowR32(NoiseA, 3);
NoiseA = Smoothstep(NoiseA);
v4 CA = v4{1, 0, 1, 1} * NoiseA;
r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 5});
NoiseB = PowR32(NoiseB, 3);
NoiseB = Smoothstep(NoiseB);
v4 CB = v4{0, 1, 1, 1};
v4 C = V4Lerp(NoiseB, CA, CB);
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
}
internal void
Pattern_WavyPatchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
gs_random_series Random = InitRandomSeries(24601);
r32 LightSpeedMin = 1;
r32 LightSpeedMax = 5;
r32 LightHueMin = (ModR32(Time, 10) / 10) * 360;
r32 LightHueMax = ModR32((LightHueMin + 45), 360) ;
s32 LightTailLength = 10;
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
{
v2_strip Strip = Assembly.Strips[StripIndex];
r32 LightHue = LerpR32(NextRandomUnilateral(&Random),
LightHueMin,
LightHueMax);
r32 LightStartHeight = NextRandomUnilateral(&Random);
r32 LightSpeed = LerpR32(NextRandomUnilateral(&Random),
LightSpeedMin,
LightSpeedMax);
r32 LightCurrentHeight = LightStartHeight + (LightSpeed * Time * 0.1f);
s32 StartIndex = (s32)(LightCurrentHeight * (r32)Strip.LedCount) % Strip.LedCount;
for (s32 i = 0; i < LightTailLength; i++)
{
s32 StripLedIndex = StartIndex + i;
if (StripLedIndex >= (s32)Strip.LedCount) continue;
u32 LedIndex = Strip.LedLUT[StripLedIndex];
r32 PctTail = ((r32)i / (r32)LightTailLength);
v4 C = HSVToRGB(v4{LightHue, 1, 1, 1}) * PctTail;
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
}
}
#define BLUMEN_PATTERNS_H

View File

@ -396,7 +396,7 @@ Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer*
{
if (BufferAt->ComPort.Length > 0)
{
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1, Context.Transient);
if (SerialPort != INVALID_HANDLE_VALUE)
{
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
@ -524,9 +524,39 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
}
#include "../../gs_libs/gs_path.h"
#include "../../gs_libs/gs_csv.h"
internal void
Win32_SendOutputData(gs_thread_context ThreadContext, addressed_data_buffer_list OutputData)
{
bool Multithread = true;
if (Multithread)
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data"));
}
}
else
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg);
}
}
}
int WINAPI
WinMain (
HINSTANCE HInstance,
@ -707,31 +737,7 @@ WinMain (
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
bool Multithread = false;
if (Multithread)
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data"));
}
}
else
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg);
}
}
Win32_SendOutputData(ThreadContext, OutputData);
RenderCommandBuffer(RenderBuffer);
ClearRenderBuffer(&RenderBuffer);
@ -759,7 +765,9 @@ WinMain (
LastFrameEnd = GetWallClock();
}
Context.CleanupApplication(Context);
Context.CleanupApplication(Context, &OutputData);
Win32_SendOutputData(ThreadContext, OutputData);
Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext);
Win32WorkQueue_Cleanup();
//Win32_TestCode_SocketReading_Cleanup();

View File

@ -70,20 +70,74 @@ Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Par
bool Success = SetCommState(ComPortHandle, &ControlSettings);
}
gs_const_string_array
Win32SerialPorts_List(gs_memory_arena* Arena, gs_memory_arena* Transient)
{
gs_const_string_array Result = {};
DWORD SizeNeeded0 = 0;
DWORD CountReturned0 = 0;
EnumPorts(NULL, 1, 0, 0, &SizeNeeded0, &CountReturned0);
Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
DWORD SizeNeeded1 = 0;
DWORD CountReturned1 = 0;
PORT_INFO_1* PortsArray = (PORT_INFO_1*)PushSize(Transient, SizeNeeded0);
if (EnumPorts(NULL,
1,
(u8*)PortsArray,
SizeNeeded0,
&SizeNeeded1,
&CountReturned1))
{
Result.CountMax = (u64)CountReturned1;
Result.Strings = PushArray(Arena, gs_const_string, Result.CountMax);
for (; Result.Count < Result.CountMax; Result.Count++)
{
u64 Index = Result.Count;
u64 StrLen = CStringLength(PortsArray[Index].pName);
gs_string Str = PushString(Arena, StrLen);
PrintF(&Str, "%.*s", StrLen, PortsArray[Index].pName);
Result.Strings[Result.Count] = Str.ConstString;
}
}
return Result;
}
bool
Win32SerialPort_Exists(char* PortName, gs_memory_arena* Transient)
{
bool Result = false;
if (PortName != 0)
{
gs_const_string PortIdent = ConstString(PortName);
u32 IdentBegin = FindLast(PortIdent, '\\') + 1;
PortIdent = Substring(PortIdent, IdentBegin, PortIdent.Length);
gs_const_string_array PortsAvailable = Win32SerialPorts_List(Transient, Transient);
for (u64 i = 0; i < PortsAvailable.Count; i++)
{
gs_const_string AvailablePortName = PortsAvailable.Strings[i];
if (StringsEqualUpToLength(AvailablePortName, PortIdent, PortIdent.Length))
{
Result = true;
break;
}
}
}
return Result;
}
HANDLE
Win32SerialPort_Open(char* PortName)
Win32SerialPort_Open(char* PortName, gs_memory_arena* Transient)
{
DEBUG_TRACK_FUNCTION;
HANDLE ComPortHandle = INVALID_HANDLE_VALUE;;
WIN32_FIND_DATA FindData;
HANDLE ComPortExists = FindFirstFile(PortName, &FindData);
// TODO(PS): we aren't sure yet if FindFirstFile will actually work
// for the purpose of checking to see if a ComPort actually exists.
// When you go to Foldspace next time, make sure we are still connecting
// the sculpture
if (ComPortExists != INVALID_HANDLE_VALUE)
if (Win32SerialPort_Exists(PortName, Transient))
{
ComPortHandle = CreateFile(PortName,
@ -289,7 +343,7 @@ Win32SerialArray_Get(gs_const_string PortName)
}
HANDLE
Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits)
Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits, gs_memory_arena* Transient)
{
DEBUG_TRACK_FUNCTION;
@ -297,7 +351,7 @@ Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize,
if (PortHandle == INVALID_HANDLE_VALUE)
{
Assert(IsNullTerminated(PortName));
PortHandle = Win32SerialPort_Open(PortName.Str);
PortHandle = Win32SerialPort_Open(PortName.Str, Transient);
if (PortHandle != INVALID_HANDLE_VALUE)
{
Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits);

View File

@ -43,6 +43,9 @@ MessageQueue_Write(blumen_network_msg_queue* Queue, gs_data Msg)
Assert(Msg.Size <= DEFAULT_QUEUE_ENTRY_SIZE);
u32 Index = Queue->WriteHead;
Assert(Index >= 0 &&
Index < BLUMEN_MESSAGE_QUEUE_COUNT);
gs_data* Dest = Queue->Buffers + Index;
CopyMemoryTo(Msg.Memory, Dest->Memory, Msg.Size);
Dest->Size = Msg.Size;
@ -50,7 +53,7 @@ MessageQueue_Write(blumen_network_msg_queue* Queue, gs_data Msg)
// NOTE(pjs): We increment write head at the end of writing so that
// a reader thread doesn't pull the message off before we've finished
// filling it out
Queue->WriteHead++;
Queue->WriteHead = (Queue->WriteHead + 1) % BLUMEN_MESSAGE_QUEUE_COUNT;
return true;
}
@ -116,25 +119,28 @@ BlumenLumen_LoadPatterns(app_state* State)
}
Patterns->Count = 0;
Patterns_PushPattern(Patterns, TestPatternOne);
Patterns_PushPattern(Patterns, TestPatternTwo);
Patterns_PushPattern(Patterns, TestPatternThree);
Patterns_PushPattern(Patterns, Pattern_AllGreen);
Patterns_PushPattern(Patterns, Pattern_HueShift);
Patterns_PushPattern(Patterns, Pattern_HueFade);
Patterns_PushPattern(Patterns, Pattern_Spots);
Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow);
Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow);
Patterns_PushPattern(Patterns, Pattern_GrowAndFade);
Patterns_PushPattern(Patterns, Pattern_ColorToWhite);
Patterns_PushPattern(Patterns, Pattern_Blue);
Patterns_PushPattern(Patterns, Pattern_Green);
Patterns_PushPattern(Patterns, Pattern_FlowerColors);
Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite);
Patterns_PushPattern(Patterns, Pattern_BasicFlowers);
Patterns_PushPattern(Patterns, TestPatternOne, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, TestPatternTwo, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, TestPatternThree, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_AllGreen, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_HueShift, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_HueFade, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Spots, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_GrowAndFade, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_ColorToWhite, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Blue, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Green, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_FlowerColors, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_BasicFlowers, PATTERN_MULTITHREADED);
// 15
Patterns_PushPattern(Patterns, Pattern_Patchy);
Patterns_PushPattern(Patterns, Pattern_Leafy);
Patterns_PushPattern(Patterns, Pattern_Wavy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Patchy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Leafy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_LeafyPatchy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_WavyPatchy, PATTERN_SINGLETHREADED);
}
internal v4
@ -180,46 +186,45 @@ BlumenLumen_CustomInit(app_state* State, context Context)
gs_const_string SculpturePath = ConstString("data/test_blumen.fold");
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
#if 0
{ // Animation PLAYGROUND
animation Anim0 = {0};
Anim0.Name = PushStringF(&State->Permanent, 256, "test_anim_zero");
Anim0.Layers = AnimLayerArray_Create(State->AnimationSystem.Storage, 8);
Anim0.Blocks_ = AnimBlockArray_Create(State->AnimationSystem.Storage, 8);
Anim0.PlayableRange.Min = 0;
Anim0.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
animation_desc Desc = {};
Desc.NameSize = 256;
Desc.LayersCount = 8;
Desc.BlocksCount = 8;
Desc.MinFrames = 0;
Desc.MaxFrames = SecondsToFrames(15, State->AnimationSystem);
animation_desc Desc0 = Desc;
Desc.Name = "test_anim_zero";
animation Anim0 = Animation_Create(Desc0, &State->AnimationSystem);
Animation_AddLayer(&Anim0, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
Animation_AddBlock(&Anim0, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(15), 0);
BLState->AnimHandles[0] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim0);
animation Anim1 = {0};
Anim1.Name = PushStringF(&State->Permanent, 256, "test_anim_one");
Anim1.Layers = AnimLayerArray_Create(State->AnimationSystem.Storage, 8);
Anim1.Blocks_ = AnimBlockArray_Create(State->AnimationSystem.Storage, 8);
Anim1.PlayableRange.Min = 0;
Anim1.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
animation_desc Desc1 = Desc;
Desc1.Name = "test_anim_one";
animation Anim1 = Animation_Create(Desc1, &State->AnimationSystem);
Animation_AddLayer(&Anim1, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
Animation_AddBlock(&Anim1, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(12), 0);
BLState->AnimHandles[1] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim1);
animation Anim2 = {0};
Anim2.Name = PushStringF(&State->Permanent, 256, "i_love_you");
Anim2.Layers = AnimLayerArray_Create(State->AnimationSystem.Storage, 8);
Anim2.Blocks_ = AnimBlockArray_Create(State->AnimationSystem.Storage, 8);
Anim2.PlayableRange.Min = 0;
Anim2.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
animation_desc Desc2 = Desc;
Desc2.Name = "i_love_you";
animation Anim2 = Animation_Create(Desc2, &State->AnimationSystem);;
Animation_AddLayer(&Anim2, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
Animation_AddBlock(&Anim2, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(16), 0);
Animation_AddBlock(&Anim2, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(20), 0);
BLState->AnimHandles[2] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim2);
State->AnimationSystem.ActiveFadeGroup.From = BLState->AnimHandles[2];
State->AnimationSystem.TimelineShouldAdvance = true;
} // End Animation Playground
#endif
animation_handle DemoPatternsAnim = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem,
State->Patterns,
Context,
ConstString("data/demo_patterns.foldanim"));
State->AnimationSystem.ActiveFadeGroup.From = DemoPatternsAnim;
State->AnimationSystem.TimelineShouldAdvance = true;
for (u32 i = 0; i < FLOWER_COLORS_COUNT; i++)
{
@ -404,6 +409,7 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
}
}
// Dim the leds based on temp data
#define DIM_LED_BRIGHTNESS 1
#if DIM_LED_BRIGHTNESS
for (u32 i = 0; i < State->LedSystem.BuffersCount; i++)
{
@ -417,7 +423,25 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
}
}
// TODO(pjs): dim stem to 50%
// TODO(PS): This should really only happen if we think the
// flower _might_ be open
for (u32 a = 0; a < State->Assemblies.Count; a++)
{
assembly Assembly = State->Assemblies.Values[a];
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++)
{
u32 SIndex = TopStrips.StripIndices[s];
v2_strip Strip = Assembly.Strips[SIndex];
for (u32 l = 0; l < Strip.LedCount; l++)
{
u32 LIndex = Strip.LedLUT[l];
Buffer.Colors[LIndex] = {0};
}
}
}
#endif
// Send Status Packet

View File

@ -1557,6 +1557,25 @@ FindFirst(gs_string String, char C)
return FindFirst(String.ConstString, 0, C);
}
internal s64
FindLast(char* String, s64 StartIndex, char C)
{
s64 Result = -1;
s64 i = 0;
while (String[i] != 0 && i < StartIndex)
{
i++;
}
while (String[i])
{
if (String[i] == C)
{
Result = i;
}
i++;
}
return Result;
}
internal s64
FindLast(gs_const_string String, u64 StartIndex, char C)
{

View File

@ -232,7 +232,7 @@ struct u64_array
# define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break;
# define StaticAssert(c) \
enum { \
Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \
Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \
}
#else
# define Assert(c)
@ -560,7 +560,7 @@ struct gs_const_string_array
{
gs_const_string* Strings;
u64 Count;
u64 Used;
u64 CountMax;
};
struct gs_string_array
@ -579,6 +579,27 @@ CStringLength(char* Str)
return Result;
}
internal bool
CStringsEqual(char* A, char* B)
{
bool Result = true;
char* AAt = A;
char* BAt = B;
while (AAt[0] && BAt[0])
{
if (AAt[0] != BAt[0])
{
Result = false;
break;
}
AAt++;
BAt++;
}
if (AAt[0] != 0 || BAt[0] != 0) { Result = false; }
return Result;
}
#define StringExpand(str) (int)(str).Length, (str).Str
#define LitString(cstr) gs_const_string{(char*)(cstr), CStringLength((char*)cstr) }

View File

@ -93,7 +93,7 @@ int main(int ArgCount, char** Args)
{
gs_thread_context Ctx = Win32CreateThreadContext();
HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9");
HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9", Ctx.Transient);
Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1);
gs_const_string OutFileName = ConstString("./serial_dump.data");