From 4798002dfc00bf56962fe93b883b121e5ee0a959 Mon Sep 17 00:00:00 2001 From: PS Date: Sat, 16 Jan 2021 14:02:25 -0800 Subject: [PATCH] debug and profiler improvements. implemented sending data to multiple destinations on a per strip basis, rather than a full sculpture basis. new patterns. Added user data to patterns. --- src/app/blumen_lumen.h | 15 + .../foldhaus_panel_animation_timeline.h | 2 + .../panels/foldhaus_panel_assembly_debug.h | 51 +++ .../editor/panels/foldhaus_panel_profiler.h | 90 ++-- .../editor/panels/foldhaus_panel_types.cpp | 3 +- src/app/editor/panels/foldhaus_panel_types.h | 1 + src/app/engine/animation/foldhaus_animation.h | 2 +- .../animation/foldhaus_animation_renderer.cpp | 12 +- src/app/engine/assembly/foldhaus_assembly.h | 1 - .../engine/assembly/foldhaus_assembly_debug.h | 134 ++++++ src/app/engine/uart/foldhaus_uart.cpp | 86 +++- src/app/foldhaus_app.cpp | 9 +- src/app/foldhaus_app.h | 407 +----------------- src/app/foldhaus_platform.h | 2 +- src/app/interface.h | 28 +- src/app/patterns/blumen_patterns.h | 395 +++++++++++++++++ src/app/platform_win32/win32_foldhaus.cpp | 87 ++-- src/sculpture_gen/gen_blumen_lumen.cpp | 21 +- src/sculpture_gen/sculpture_gen.h | 6 +- test_motor_header.h | 19 + test_sound_interface_packet.h | 29 ++ 21 files changed, 885 insertions(+), 515 deletions(-) create mode 100644 src/app/blumen_lumen.h create mode 100644 src/app/editor/panels/foldhaus_panel_assembly_debug.h create mode 100644 src/app/engine/assembly/foldhaus_assembly_debug.h create mode 100644 src/app/patterns/blumen_patterns.h create mode 100644 test_motor_header.h create mode 100644 test_sound_interface_packet.h diff --git a/src/app/blumen_lumen.h b/src/app/blumen_lumen.h new file mode 100644 index 0000000..e93c247 --- /dev/null +++ b/src/app/blumen_lumen.h @@ -0,0 +1,15 @@ +// +// File: blumen_lumen.h +// Author: Peter Slattery +// Creation Date: 2021-01-15 +// +#ifndef BLUMEN_LUMEN_H + +typedef struct motor_packet +{ + u8 FlowerPositions[3]; +} motor_packet; + + +#define BLUMEN_LUMEN_H +#endif // BLUMEN_LUMEN_H \ No newline at end of file diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 0a32fc4..ca358a6 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -897,6 +897,8 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* { animation_timeline_state* TimelineState = Panel_GetStateStruct(Panel, animation_timeline_state); + ui_FillRect(&State->Interface, PanelBounds, v4{.1f,.1f,.1f,1.f}); + rect2 TimelineBounds, InfoBounds; RectVSplit(PanelBounds, 300, &InfoBounds, &TimelineBounds); diff --git a/src/app/editor/panels/foldhaus_panel_assembly_debug.h b/src/app/editor/panels/foldhaus_panel_assembly_debug.h new file mode 100644 index 0000000..d118e19 --- /dev/null +++ b/src/app/editor/panels/foldhaus_panel_assembly_debug.h @@ -0,0 +1,51 @@ +// +// File: foldhaus_panel_assembly_debug.h +// Author: Peter Slattery +// Creation Date: 2021-01-15 +// +#ifndef FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H + +GSMetaTag(panel_init); +GSMetaTag(panel_type_file_view); +internal void +AssemblyDebug_Init(panel* Panel, app_state* State, context Context) +{ +} + +GSMetaTag(panel_cleanup); +GSMetaTag(panel_type_file_view); +internal void +AssemblyDebug_Cleanup(panel* Panel, app_state* State) +{ + +} + +GSMetaTag(panel_render); +GSMetaTag(panel_type_file_view); +internal void +AssemblyDebug_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +{ + ui_interface* Interface = &State->Interface; + ui_PushLayout(Interface, PanelBounds, LayoutDirection_TopDown, MakeString("Assembly Debug Layout")); + + State->AssemblyDebugState.TargetAssembly = ui_LabeledTextEntryU64(Interface, MakeString("Assembly"), State->AssemblyDebugState.TargetAssembly); + + State->AssemblyDebugState.TargetStrip = ui_LabeledTextEntryU64(Interface, MakeString("Strip"), State->AssemblyDebugState.TargetStrip); + + + gs_string OverrideStr = MakeString(OverrideTypeStrings[State->AssemblyDebugState.Override]); + if (ui_BeginLabeledDropdown(Interface, MakeString("Override"), OverrideStr)) + { + for (u32 i = 0; i < ADS_Override_Count; i++) + { + if (ui_Button(Interface, MakeString(OverrideTypeStrings[i]))) + { + State->AssemblyDebugState.Override = (override_type)i; + } + } + } + ui_EndLabeledDropdown(Interface); +} + +#define FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H +#endif // FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H \ No newline at end of file diff --git a/src/app/editor/panels/foldhaus_panel_profiler.h b/src/app/editor/panels/foldhaus_panel_profiler.h index dca590d..a54827e 100644 --- a/src/app/editor/panels/foldhaus_panel_profiler.h +++ b/src/app/editor/panels/foldhaus_panel_profiler.h @@ -37,52 +37,68 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_widget* Layout, de rect2 Bounds = ui_LayoutRemaining(*Layout); r32 Width = Rect2Width(Bounds); - r32 DepthHeight = 64; + r32 DepthHeight = 32; s64 FrameStartCycles = VisibleFrame->FrameStartCycles; - s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; + r32 FrameTotalCycles = (r32)(VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles); - debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices, - VisibleFrame); + r32 NextThreadTop = Bounds.Max.y; - gs_string String = PushString(Transient, 256); - for (s32 i = 0; i < ThreadScopeCalls->Count; i++) + for (s32 t = 0; t < VisibleFrame->ThreadCount; t++) { - scope_record* Record = ThreadScopeCalls->Calls + i; - scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash); - r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles; - r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles; + debug_scope_record_list ThreadCalls = VisibleFrame->ThreadCalls[t]; - r32 PixelStart = Bounds.Min.x + (Width * PercentStart); - r32 PixelEnd = Bounds.Min.x + (Width * PercentEnd); - r32 MinY = Bounds.Max.y - ((Record->CallDepth + 1) * DepthHeight); - rect2 ScopeBounds = { - v2{ PixelStart, MinY }, - v2{ PixelEnd, MinY + (DepthHeight - 4) } - }; - if (Rect2Width(ScopeBounds) >= 1) + gs_string String = PushString(Transient, 256); + + r32 ThreadScopeMin = Bounds.Max.y; + + for (s32 i = 0; i < ThreadCalls.Count; i++) { - v4 Color = ThreadColors[0]; - if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) - { - Color = GreenV4; - - ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover")); - { - s64 Cycles = (Record->EndCycles - Record->StartCycles); - r64 PercentFrame = (r64)(Cycles) / (r64)(FrameTotalCycles); - PrintF(&String, "%S : %.2f%% frame | %dcy", - Name->Name, - PercentFrame, - Cycles); - ui_Label(Interface, String); - } - ui_EndMousePopup(Interface); - } + scope_record* Record = ThreadCalls.Calls + i; + scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash); + s64 OffsetStart = Record->StartCycles - FrameStartCycles; + s64 OffsetEnd = Record->EndCycles - FrameStartCycles; + r32 PercentStart = (r32)(OffsetStart) / FrameTotalCycles; + r32 PercentEnd = (r32)(OffsetEnd) / FrameTotalCycles; + r32 PercentWidth = PercentEnd - PercentStart; - ui_FillRect(Interface, ScopeBounds, Color); - ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); + rect2 ScopeBounds = { + v2{0, 0}, + v2{PercentWidth * Width, DepthHeight - 4}, + }; + v2 Offset = { + Bounds.Min.x + (PercentStart * Width), + NextThreadTop - ((Record->CallDepth + 1) * DepthHeight) + }; + ScopeBounds = Rect2Translate(ScopeBounds, Offset); + ThreadScopeMin = Min(ScopeBounds.Min.y, ThreadScopeMin); + + if (Rect2Width(ScopeBounds) >= 1) + { + v4 Color = ThreadColors[t]; + if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) + { + Color = GreenV4; + + ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover")); + { + s64 Cycles = (Record->EndCycles - Record->StartCycles); + r32 PercentFrame = (r32)(Cycles) / FrameTotalCycles; + PrintF(&String, "%S : %.2f%% frame | %dcy", + Name->Name, + PercentFrame, + Cycles); + ui_Label(Interface, String); + } + ui_EndMousePopup(Interface); + } + + ui_FillRect(Interface, ScopeBounds, Color); + ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); + } } + + NextThreadTop = ThreadScopeMin; } } diff --git a/src/app/editor/panels/foldhaus_panel_types.cpp b/src/app/editor/panels/foldhaus_panel_types.cpp index 9c006fa..ea56618 100644 --- a/src/app/editor/panels/foldhaus_panel_types.cpp +++ b/src/app/editor/panels/foldhaus_panel_types.cpp @@ -4,7 +4,7 @@ // Creation Date: 2020-10-17 // #ifndef FOLDHAUS_PANEL_TYPES_CPP -global s32 GlobalPanelDefsCount = 6; +global s32 GlobalPanelDefsCount = 7; global panel_definition GlobalPanelDefs[] = { { "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, @@ -12,6 +12,7 @@ global panel_definition GlobalPanelDefs[] = { { "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, + { "Assembly Debug", 14, AssemblyDebug_Init, AssemblyDebug_Cleanup, AssemblyDebug_Render, 0, 0 }, }; #define FOLDHAUS_PANEL_TYPES_CPP #endif // FOLDHAUS_PANEL_TYPES_CPP \ No newline at end of file diff --git a/src/app/editor/panels/foldhaus_panel_types.h b/src/app/editor/panels/foldhaus_panel_types.h index 7b1164b..85c93ed 100644 --- a/src/app/editor/panels/foldhaus_panel_types.h +++ b/src/app/editor/panels/foldhaus_panel_types.h @@ -12,6 +12,7 @@ enum panel_type { PanelType_HierarchyView, PanelType_NodeGraph, PanelType_ProfilerView, + PanelType_AssemblyDebug, }; #define FOLDHAUS_PANEL_TYPES_H #endif // FOLDHAUS_PANEL_TYPES_H \ No newline at end of file diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index e764ec6..9309c0b 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -5,7 +5,7 @@ // #ifndef FOLDHAUS_ANIMATION -#define ANIMATION_PROC(name) void name(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) +#define ANIMATION_PROC(name) void name(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) typedef ANIMATION_PROC(animation_proc); struct frame_range diff --git a/src/app/engine/animation/foldhaus_animation_renderer.cpp b/src/app/engine/animation/foldhaus_animation_renderer.cpp index 44075be..8915d59 100644 --- a/src/app/engine/animation/foldhaus_animation_renderer.cpp +++ b/src/app/engine/animation/foldhaus_animation_renderer.cpp @@ -81,20 +81,22 @@ LedBlend_GetProc(blend_mode BlendMode) } internal void -AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, assembly Assembly, animation_pattern_array Patterns, gs_memory_arena* Transient) +AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, assembly Assembly, animation_pattern_array Patterns, gs_memory_arena* Transient, + u8* UserData) { u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min; r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); - Pattern.Proc(Buffer, Assembly, SecondsIntoBlock, Transient); + Pattern.Proc(Buffer, Assembly, SecondsIntoBlock, Transient, UserData); } internal void AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies, led_system* LedSystem, animation_pattern_array Patterns, - gs_memory_arena* Transient) + gs_memory_arena* Transient, + u8* UserData) { s32 CurrentFrame = System->CurrentFrame; r32 FrameTime = CurrentFrame * System->SecondsPerFrame; @@ -148,14 +150,14 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse { led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer; animation_block Block = LayerFrame.Hot; - AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient); + AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient, UserData); } if (LayerFrame.HasNextHot) { led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer; animation_block Block = LayerFrame.NextHot; - AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient); + AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient, UserData); } } diff --git a/src/app/engine/assembly/foldhaus_assembly.h b/src/app/engine/assembly/foldhaus_assembly.h index f1d7ba9..90694d1 100644 --- a/src/app/engine/assembly/foldhaus_assembly.h +++ b/src/app/engine/assembly/foldhaus_assembly.h @@ -160,7 +160,6 @@ struct assembly_array assembly* Values; }; - internal led_buffer* LedSystemGetBuffer(led_system* System, u32 Index) { diff --git a/src/app/engine/assembly/foldhaus_assembly_debug.h b/src/app/engine/assembly/foldhaus_assembly_debug.h new file mode 100644 index 0000000..bb385d2 --- /dev/null +++ b/src/app/engine/assembly/foldhaus_assembly_debug.h @@ -0,0 +1,134 @@ +// +// File: foldhaus_assembly_debug.h +// Author: Peter Slattery +// Creation Date: 2021-01-15 +// +#ifndef FOLDHAUS_ASSEMBLY_DEBUG_H + +enum override_type +{ + ADS_Override_None, + + ADS_Override_Strip, + ADS_Override_SoloStrip, + ADS_Override_AllRed, + ADS_Override_AllGreen, + ADS_Override_AllBlue, + + ADS_Override_Count, +}; + +global gs_const_string OverrideTypeStrings[] = { + LitString("Override_None"), + LitString("Override_Strip"), + LitString("Override_SoloStrip" ), + LitString("Override_AllRed" ), + LitString("Override_AllGreen" ), + LitString("Override_AllBlue" ), + LitString("Override_Count"), +}; + +struct assembly_debug_state +{ + override_type Override; + u32 TargetAssembly; + u32 TargetStrip; + pixel TargetColor; +}; + +internal void +AssemblyDebug_OverrideOutput(assembly_debug_state State, assembly_array Assemblies, led_system LedSystem) +{ + if (State.Override == ADS_Override_None) return; + State.TargetColor = pixel{255,255,255}; + + assembly Assembly = Assemblies.Values[State.TargetAssembly]; + led_buffer LedBuffer = LedSystem.Buffers[Assembly.LedBufferIndex]; + + switch (State.Override) + { + case ADS_Override_Strip: + { + v2_strip Strip = Assembly.Strips[State.TargetStrip]; + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIdx = Strip.LedLUT[i]; + LedBuffer.Colors[LedIdx] = State.TargetColor; + } + }break; + + case ADS_Override_SoloStrip: + { + for (u32 s = 0; s < Assembly.StripCount; s++) + { + v2_strip Strip = Assembly.Strips[s]; + + pixel Color = pixel{0,0,0}; + if (s == State.TargetStrip) + { + Color = State.TargetColor; + } + + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIdx = Strip.LedLUT[i]; + LedBuffer.Colors[LedIdx] = Color; + } + } + }break; + + case ADS_Override_AllRed: + { + for (u32 s = 0; s < Assembly.StripCount; s++) + { + v2_strip Strip = Assembly.Strips[s]; + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIdx = Strip.LedLUT[i]; + LedBuffer.Colors[LedIdx] = pixel{255, 0, 0}; + } + } + }break; + + case ADS_Override_AllGreen: + { + for (u32 s = 0; s < Assembly.StripCount; s++) + { + v2_strip Strip = Assembly.Strips[s]; + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIdx = Strip.LedLUT[i]; + LedBuffer.Colors[LedIdx] = pixel{0, 255, 0}; + } + } + }break; + + case ADS_Override_AllBlue: + { + for (u32 s = 0; s < Assembly.StripCount; s++) + { + v2_strip Strip = Assembly.Strips[s]; + for (u32 i = 0; i < Strip.LedCount; i++) + { + u32 LedIdx = Strip.LedLUT[i]; + LedBuffer.Colors[LedIdx] = pixel{0, 0, 255}; + } + } + }break; + + case ADS_Override_None: + { + }break; + + InvalidDefaultCase; + } + + if (State.Override ) + { + + } +} + + +#define FOLDHAUS_ASSEMBLY_DEBUG_H +#endif // FOLDHAUS_ASSEMBLY_DEBUG_H \ No newline at end of file diff --git a/src/app/engine/uart/foldhaus_uart.cpp b/src/app/engine/uart/foldhaus_uart.cpp index d523f6d..c158412 100644 --- a/src/app/engine/uart/foldhaus_uart.cpp +++ b/src/app/engine/uart/foldhaus_uart.cpp @@ -56,7 +56,7 @@ UART_DrawAll_Create(gs_memory_cursor* WriteCursor) } internal void -UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem) +UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assemblies, led_system* LedSystem, gs_memory_arena* Transient) { uart_channel ChannelSettings = {0}; ChannelSettings.ElementsCount = 3; @@ -71,22 +71,88 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli assembly Assembly = Assemblies.Values[AssemblyIdx]; led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); - u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages - TotalBufferSize += MessageBaseSize; // DrawAll message - TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel + struct strips_to_data_buffer + { + gs_const_string ComPort; + u32* StripIndices; + u32 StripIndicesCount; + u32 StripIndicesCountMax; + + u64 LedCount; + + strips_to_data_buffer* Next; + }; - addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); - AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort.ConstString); - gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); + strips_to_data_buffer* BuffersNeededHead = 0; + strips_to_data_buffer* BuffersNeededTail = 0; for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) { v2_strip StripAt = Assembly.Strips[StripIdx]; - ChannelSettings.PixelsCount = StripAt.LedCount; - UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); + + // If there is a buffer for this com port already created + // we use that + strips_to_data_buffer* BufferSelected = 0; + for (strips_to_data_buffer* At = BuffersNeededHead; + At!= 0; + At = At->Next) + { + if (StringsEqual(At->ComPort, StripAt.UARTAddr.ComPort.ConstString)) + { + BufferSelected = At; + break; + } + } + + // if no existing buffer for this com port + // create a new one + if (!BufferSelected) + { + BufferSelected = PushStruct(Transient, strips_to_data_buffer); + *BufferSelected = {}; + BufferSelected->ComPort = StripAt.UARTAddr.ComPort.ConstString; + // we don't know at this point how many indices per + // com port so just make enough room to fit all the strips + // if necessary + BufferSelected->StripIndicesCountMax = Assembly.StripCount; + BufferSelected->StripIndices = PushArray(Transient, u32, BufferSelected->StripIndicesCountMax); + BufferSelected->LedCount = 0; + BufferSelected->Next = 0; + + SLLPushOrInit(BuffersNeededHead, BuffersNeededTail, BufferSelected); + } + + Assert(BufferSelected->StripIndicesCount < BufferSelected->StripIndicesCountMax); + u32 Index = BufferSelected->StripIndicesCount++; + BufferSelected->StripIndices[Index] = StripIdx; + BufferSelected->LedCount += StripAt.LedCount; } - UART_DrawAll_Create(&WriteCursor); + for (strips_to_data_buffer* At = BuffersNeededHead; + At!= 0; + At = At->Next) + { + u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages + TotalBufferSize += MessageBaseSize; // DrawAll message + TotalBufferSize += ChannelSettings.ElementsCount * At->LedCount; // pixels * channels per pixel + + addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); + gs_const_string ComPort = At->ComPort; + AddressedDataBuffer_SetCOMPort(Buffer, ComPort); + + gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); + + for (u32 i = 0; i < At->StripIndicesCount; i++) + { + u32 StripIdx = At->StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIdx]; + + ChannelSettings.PixelsCount = StripAt.LedCount; + UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer); + } + + UART_DrawAll_Create(&WriteCursor); + } } } diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 09b526c..900f228 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -25,6 +25,7 @@ ClearAndPushPatterns(animation_pattern_array* Patterns) Patterns_PushPattern(Patterns, Pattern_Spots); Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow); Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow); + Patterns_PushPattern(Patterns, Pattern_GrowAndFade); } RELOAD_STATIC_DATA(ReloadStaticData) @@ -133,16 +134,20 @@ UPDATE_AND_RENDER(UpdateAndRender) State->Assemblies, &State->LedSystem, State->Patterns, - State->Transient); + State->Transient, + State->UserData.Memory); } + AssemblyDebug_OverrideOutput(State->AssemblyDebugState, + State->Assemblies, + State->LedSystem); // 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); + UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient); Editor_Render(State, Context, RenderBuffer); } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 7f4d380..af5b98e 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -19,6 +19,7 @@ #include "engine/assembly/foldhaus_assembly.h" #include "engine/assembly/foldhaus_assembly_parser.cpp" +#include "engine/assembly/foldhaus_assembly_debug.h" #include "engine/sacn/foldhaus_sacn.h" #include "engine/uart/foldhaus_uart.h" @@ -51,6 +52,7 @@ struct app_state streaming_acn SACN; led_system LedSystem; assembly_array Assemblies; + assembly_debug_state AssemblyDebugState; animation_system AnimationSystem; event_log* GlobalLog; animation_pattern_array Patterns; @@ -65,411 +67,17 @@ struct app_state ui_interface Interface; panel_system PanelSystem; panel* HotPanel; + + // User Space + // + gs_data UserData; }; internal void OpenColorPicker(app_state* State, v4* Address); #include "engine/assembly/foldhaus_assembly.cpp" -// BEGIN TEMPORARY PATTERNS -internal void -TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient); - led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient); - - for (u32 i = 0; i < BlumenStrips.Count; i++) - { - u32 StripIndex = BlumenStrips.StripIndices[i]; - v2_strip StripAt = Assembly.Strips[StripIndex]; - - for (u32 j = 0; j < StripAt.LedCount; j++) - { - u32 LedIndex = StripAt.LedLUT[j]; - Leds->Colors[LedIndex] = { 255, 0, 0 }; - - } - } - - for (u32 i = 0; i < RadiaStrips.Count; i++) - { - u32 StripIndex = RadiaStrips.StripIndices[i]; - v2_strip StripAt = Assembly.Strips[StripIndex]; - - for (u32 j = 0; j < StripAt.LedCount; j++) - { - u32 LedIndex = StripAt.LedLUT[j]; - Leds->Colors[LedIndex] = { 0, 255, 0 }; - } - } -#if 0 - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 LedPosition = Leds->Positions[LedIndex]; - float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); - float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); - Leds->Colors[LedIndex].R = (u8)(PercentX * 255); - Leds->Colors[LedIndex].G = (u8)(PercentY * 255); - } -#endif - -} - -internal void -TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - r32 PeriodicTime = (Time / PiR32) * 2; - - r32 ZeroOneSin = (SinR32(PeriodicTime) * .5f) + .5f; - r32 ZeroOneCos = (CosR32(PeriodicTime) * .5f) + .5f; - pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; - - v4 Center = v4{0, 0, 0, 1}; - r32 ThetaZ = Time / 2; - v4 Normal = v4{CosR32(ThetaZ), 0, SinR32(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); - - v4 FrontCenter = Center + (Normal * 25); - v4 BackCenter = Center - (Normal * 25); - - r32 OuterRadiusSquared = 1000000; - r32 InnerRadiusSquared = 0; - - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 Position = Leds->Positions[LedIndex]; - - v4 ToFront = Position + FrontCenter; - v4 ToBack = Position + BackCenter; - - r32 ToFrontDotNormal = V4Dot(ToFront, Normal); - r32 ToBackDotNormal = V4Dot(ToBack, Normal); - - ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - - r32 SqDistToCenter = V4MagSquared(Position); - if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) - { - if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) - { - Leds->Colors[LedIndex] = Color; - } - else - { - //Leds->Colors[LedIndex] = {}; - } - } - else - { - //Leds->Colors[LedIndex] = {}; - } - } -} - -internal void -TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - v4 GreenCenter = v4{0, 0, 150, 1}; - r32 GreenRadius = Abs(SinR32(Time)) * 200; - - v4 TealCenter = v4{0, 0, 150, 1}; - r32 TealRadius = Abs(SinR32(Time + 1.5)) * 200; - - r32 FadeDist = 35; - - - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 LedPosition = Leds->Positions[LedIndex]; - u8 Red = 0; - u8 Green = 0; - u8 Blue = 0; - - r32 GreenDist = Abs(V4Mag(LedPosition - GreenCenter) - GreenRadius); - r32 GreenBrightness = Clamp(0.f, FadeDist - Abs(GreenDist), FadeDist); - Green = (u8)(GreenBrightness * 255); - - r32 TealDist = Abs(V4Mag(LedPosition - TealCenter) - TealRadius); - r32 TealBrightness = Clamp(0.f, FadeDist - Abs(TealDist), FadeDist); - Red = (u8)(TealBrightness * 255); - Blue = (u8)(TealBrightness * 255); - - Leds->Colors[LedIndex].R = Red; - Leds->Colors[LedIndex].B = Green; - Leds->Colors[LedIndex].G = Green; - } -} - -v4 HSVToRGB (v4 In) -{ - float Hue = In.x; - /* -while (Hue > 360.0f) { Hue -= 360.0f; } - while (Hue < 0.0f) { Hue += 360.0f; } - */ - Hue = ModR32(Hue, 360.0f); - if (Hue < 0) { Hue += 360.0f; } - if (Hue == MinR32) { Hue = 0; } - if (Hue == MaxR32) { Hue = 360; } - Assert(Hue >= 0 && Hue < 360); - - float Sat = In.y; - float Value = In.z; - - float hh, p, q, t, ff; - long i; - v4 Result = {}; - Result.a = In.a; - - if(Sat <= 0.0f) { // < is bogus, just shuts up warnings - Result.r = Value; - Result.g = Value; - Result.b = Value; - return Result; - } - hh = Hue; - if(hh >= 360.0f) hh = 0.0f; - hh /= 60.0f; - i = (long)hh; - ff = hh - i; - p = Value * (1.0f - Sat); - q = Value * (1.0f - (Sat * ff)); - t = Value * (1.0f - (Sat * (1.0f - ff))); - - switch(i) { - case 0: - {Result.r = Value; - Result.g = t; - Result.b = p; - }break; - - case 1: - { - Result.r = q; - Result.g = Value; - Result.b = p; - }break; - - case 2: - { - Result.r = p; - Result.g = Value; - Result.b = t; - }break; - - case 3: - { - Result.r = p; - Result.g = q; - Result.b = Value; - }break; - - case 4: - { - Result.r = t; - Result.g = p; - Result.b = Value; - }break; - - case 5: - default: - { - Result.r = Value; - Result.g = p; - Result.b = q; - }break; - } - - return Result; -} - -internal void -Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - r32 Height = SinR32(Time) * 25; - - r32 CycleLength = 5.0f; - r32 CycleProgress = FractR32(Time / CycleLength); - r32 CycleBlend = (SinR32(Time) * .5f) + .5f; - - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 Pos = Leds->Positions[LedIndex]; - r32 Dist = Pos.y - Height; - - v4 HSV = { (ModR32(Dist, 25) / 25) * 360, 1, 1, 1 }; - v4 RGB = HSVToRGB(HSV); - - u8 R = (u8)(RGB.x * 255); - u8 G = (u8)(RGB.y * 255); - u8 B = (u8)(RGB.z * 255); - - Leds->Colors[LedIndex].R = R; - Leds->Colors[LedIndex].G = G; - Leds->Colors[LedIndex].B = B; - } -} - -internal pixel -V4ToRGBPixel(v4 C) -{ - pixel Result = {}; - Result.R = (u8)(C.x * 255); - Result.G = (u8)(C.y * 255); - Result.B = (u8)(C.z * 255); - return Result; -} - -internal void -Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - r32 HueBase = ModR32(Time * 50, 360); - - r32 CycleLength = 5.0f; - r32 CycleProgress = FractR32(Time / CycleLength); - r32 CycleBlend = (SinR32(Time) * .5f) + .5f; - - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 Pos = Leds->Positions[LedIndex]; - r32 Hue = HueBase + Pos.y + Pos.x; - v4 HSV = { Hue, 1, 1, 1 }; - v4 RGB = HSVToRGB(HSV); - - Leds->Colors[LedIndex] = V4ToRGBPixel(RGB); - } -} - -internal void -Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - u32 I = LedIndex + 1; - Leds->Colors[LedIndex] = {}; - if (I % 3 == 0) - { - Leds->Colors[LedIndex].R = 255; - } - else if (I % 3 == 1) - { - Leds->Colors[LedIndex].G = 255; - } - else if (I % 3 == 2) - { - Leds->Colors[LedIndex].B = 255; - } - - } -} - -internal r32 -PatternHash(r32 Seed) -{ - return FractR32(Seed * 17.0 * FractR32(Seed * 0.3183099)); -} - -internal void -Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - pixel ColorA = { 0, 255, 255 }; - pixel ColorB = { 255, 0, 255 }; - - r32 Speed = .5f; - Time *= Speed; - r32 ScaleA = 2 * SinR32(Time / 5); - r32 ScaleB = 2.4f * CosR32(Time / 2.5f); - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 P = Leds->Positions[LedIndex]; - r32 V = P.y; - r32 Noise = .3f * PatternHash(V); - r32 ThetaY = (Leds->Positions[LedIndex].y / 10) + Time + Noise; - r32 ThetaX = (Leds->Positions[LedIndex].x / 13) + Time + Noise; - r32 Fade = (ScaleA * SinR32(ThetaY)) + (ScaleB * CosR32(3 * ThetaX)); - Fade = RemapClampedR32(Fade, -1, 1, 0, 1); - - Leds->Colors[LedIndex].R = (u8)LerpR32(Fade, ColorA.R, ColorB.R); - Leds->Colors[LedIndex].G = (u8)LerpR32(Fade, ColorA.G, ColorB.G); - Leds->Colors[LedIndex].B = (u8)LerpR32(Fade, ColorA.B, ColorB.B); - } -} - -internal void -Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) }); - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v2 Vector = v2{ - Leds->Positions[LedIndex].x, - Leds->Positions[LedIndex].z - }; - Vector = V2Normalize(Vector); - - r32 Angle = V2Dot(RefVector, Vector); - -#if 0 - r32 Fade = RemapR32(Angle, -1, 1, 0, 1); - Leds->Colors[LedIndex].R = (u8)(Fade * 255); - Leds->Colors[LedIndex].G = (u8)(Fade * 255); - Leds->Colors[LedIndex].B = (u8)(Fade * 255); -#endif - - v4 HSV = { (Angle * 30) + (Time * 10) + Leds->Positions[LedIndex].y, 1, 1, 1 }; - v4 RGB = HSVToRGB(HSV); - - Leds->Colors[LedIndex] = V4ToRGBPixel(RGB); - } -} - -internal r32 -Smoothstep(r32 T) -{ - r32 Result = (T * T * (3 - (2 * T))); - return Result; -} - -internal void -Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient) -{ - r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f; - r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f; - - //v4 HSV = { ColorCycleTime * 360, 1, 1, 1 }; - //v4 RGB0 = HSVToRGB(HSV); - //HSV.x += ; - //v4 RGB1 = HSVToRGB(HSV); - - v4 HSV = { 0, 1, 1, 1 }; - for (u32 s = 0; s < Assembly.StripCount; s++) - { - v2_strip Strip = Assembly.Strips[s]; - - v4 RGB0 = HSVToRGB(HSV); - for (u32 l = 0; l < Strip.LedCount; l++) - { - u32 LedIndex = Strip.LedLUT[l]; - Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0); - } - - HSV.x += 15; - } - -#if 0 - for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) - { - v4 P = Leds->Positions[LedIndex]; - - Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0); - - - } -#endif -} - -// END TEMPORARY PATTERNS +#include "patterns/blumen_patterns.h" internal void EndCurrentOperationMode(app_state* State) @@ -485,6 +93,7 @@ EndCurrentOperationMode(app_state* State) #include "editor/panels/foldhaus_panel_dmx_view.h" #include "editor/panels/foldhaus_panel_animation_timeline.h" #include "editor/panels/foldhaus_panel_hierarchy.h" +#include "editor/panels/foldhaus_panel_assembly_debug.h" #include "editor/panels/foldhaus_panel_types.cpp" diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index d40a71a..5778c7f 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -148,7 +148,7 @@ typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint); // Worker Threads -#define PLATFORM_THREAD_COUNT 0 +#define PLATFORM_THREAD_COUNT 3 RESET_WORK_QUEUE(ResetWorkQueue) { diff --git a/src/app/interface.h b/src/app/interface.h index d112c1c..3fada9f 100644 --- a/src/app/interface.h +++ b/src/app/interface.h @@ -1513,11 +1513,35 @@ ui_EndMousePopup(ui_interface* Interface) } // +internal void +ui_BeginLabelRow(ui_interface* Interface, gs_string Label, u32 Count = 2) +{ + ui_BeginRow(Interface, Count); + ui_Label(Interface, Label); +} + +internal bool +ui_LabeledToggle(ui_interface* Interface, gs_string Label, bool Value) +{ + ui_BeginLabelRow(Interface, Label); + bool Result = ui_Toggle(Interface, Label, Value); + ui_EndRow(Interface); + return Result; +} + +internal u64 +ui_LabeledTextEntryU64(ui_interface* Interface, gs_string Label, u32 Value) +{ + ui_BeginLabelRow(Interface, Label); + u64 Result = ui_TextEntryU64(Interface, Label, Value); + ui_EndRow(Interface); + return Result; +} + internal bool ui_BeginLabeledDropdown(ui_interface* Interface, gs_string Label, gs_string DropdownValue) { - ui_BeginRow(Interface, 2); - ui_Label(Interface, Label); + ui_BeginLabelRow(Interface, Label); return ui_BeginDropdown(Interface, DropdownValue); } diff --git a/src/app/patterns/blumen_patterns.h b/src/app/patterns/blumen_patterns.h new file mode 100644 index 0000000..a8940f9 --- /dev/null +++ b/src/app/patterns/blumen_patterns.h @@ -0,0 +1,395 @@ +// +// File: blumen_patterns.h +// Author: Peter Slattery +// Creation Date: 2021-01-15 +// +#ifndef BLUMEN_PATTERNS_H + +internal void +TestPatternOne(led_buffer* Leds, 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); + + for (u32 i = 0; i < BlumenStrips.Count; i++) + { + u32 StripIndex = BlumenStrips.StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIndex]; + + for (u32 j = 0; j < StripAt.LedCount; j++) + { + u32 LedIndex = StripAt.LedLUT[j]; + Leds->Colors[LedIndex] = { 255, 0, 0 }; + + } + } + + for (u32 i = 0; i < RadiaStrips.Count; i++) + { + u32 StripIndex = RadiaStrips.StripIndices[i]; + v2_strip StripAt = Assembly.Strips[StripIndex]; + + for (u32 j = 0; j < StripAt.LedCount; j++) + { + u32 LedIndex = StripAt.LedLUT[j]; + Leds->Colors[LedIndex] = { 0, 255, 0 }; + } + } +} + +internal void +TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + r32 PeriodicTime = (Time / PiR32) * 2; + + r32 ZeroOneSin = (SinR32(PeriodicTime) * .5f) + .5f; + r32 ZeroOneCos = (CosR32(PeriodicTime) * .5f) + .5f; + pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; + + v4 Center = v4{0, 0, 0, 1}; + r32 ThetaZ = Time / 2; + v4 Normal = v4{CosR32(ThetaZ), 0, SinR32(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); + + v4 FrontCenter = Center + (Normal * 25); + v4 BackCenter = Center - (Normal * 25); + + r32 OuterRadiusSquared = 1000000; + r32 InnerRadiusSquared = 0; + + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 Position = Leds->Positions[LedIndex]; + + v4 ToFront = Position + FrontCenter; + v4 ToBack = Position + BackCenter; + + r32 ToFrontDotNormal = V4Dot(ToFront, Normal); + r32 ToBackDotNormal = V4Dot(ToBack, Normal); + + ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); + + r32 SqDistToCenter = V4MagSquared(Position); + if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) + { + if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) + { + Leds->Colors[LedIndex] = Color; + } + else + { + //Leds->Colors[LedIndex] = {}; + } + } + else + { + //Leds->Colors[LedIndex] = {}; + } + } +} + +internal void +TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + v4 GreenCenter = v4{0, 0, 150, 1}; + r32 GreenRadius = Abs(SinR32(Time)) * 200; + + v4 TealCenter = v4{0, 0, 150, 1}; + r32 TealRadius = Abs(SinR32(Time + 1.5)) * 200; + + r32 FadeDist = 35; + + + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 LedPosition = Leds->Positions[LedIndex]; + u8 Red = 0; + u8 Green = 0; + u8 Blue = 0; + + r32 GreenDist = Abs(V4Mag(LedPosition - GreenCenter) - GreenRadius); + r32 GreenBrightness = Clamp(0.f, FadeDist - Abs(GreenDist), FadeDist); + Green = (u8)(GreenBrightness * 255); + + r32 TealDist = Abs(V4Mag(LedPosition - TealCenter) - TealRadius); + r32 TealBrightness = Clamp(0.f, FadeDist - Abs(TealDist), FadeDist); + Red = (u8)(TealBrightness * 255); + Blue = (u8)(TealBrightness * 255); + + Leds->Colors[LedIndex].R = Red; + Leds->Colors[LedIndex].B = Green; + Leds->Colors[LedIndex].G = Green; + } +} + +v4 HSVToRGB (v4 In) +{ + float Hue = In.x; + /* +while (Hue > 360.0f) { Hue -= 360.0f; } + while (Hue < 0.0f) { Hue += 360.0f; } + */ + Hue = ModR32(Hue, 360.0f); + if (Hue < 0) { Hue += 360.0f; } + if (Hue == MinR32) { Hue = 0; } + if (Hue == MaxR32) { Hue = 360; } + Assert(Hue >= 0 && Hue < 360); + + float Sat = In.y; + float Value = In.z; + + float hh, p, q, t, ff; + long i; + v4 Result = {}; + Result.a = In.a; + + if(Sat <= 0.0f) { // < is bogus, just shuts up warnings + Result.r = Value; + Result.g = Value; + Result.b = Value; + return Result; + } + hh = Hue; + if(hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + i = (long)hh; + ff = hh - i; + p = Value * (1.0f - Sat); + q = Value * (1.0f - (Sat * ff)); + t = Value * (1.0f - (Sat * (1.0f - ff))); + + switch(i) { + case 0: + {Result.r = Value; + Result.g = t; + Result.b = p; + }break; + + case 1: + { + Result.r = q; + Result.g = Value; + Result.b = p; + }break; + + case 2: + { + Result.r = p; + Result.g = Value; + Result.b = t; + }break; + + case 3: + { + Result.r = p; + Result.g = q; + Result.b = Value; + }break; + + case 4: + { + Result.r = t; + Result.g = p; + Result.b = Value; + }break; + + case 5: + default: + { + Result.r = Value; + Result.g = p; + Result.b = q; + }break; + } + + return Result; +} + +internal void +Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + r32 Height = SinR32(Time) * 25; + + r32 CycleLength = 5.0f; + r32 CycleProgress = FractR32(Time / CycleLength); + r32 CycleBlend = (SinR32(Time) * .5f) + .5f; + + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 Pos = Leds->Positions[LedIndex]; + r32 Dist = Pos.y - Height; + + v4 HSV = { (ModR32(Dist, 25) / 25) * 360, 1, 1, 1 }; + v4 RGB = HSVToRGB(HSV); + + u8 R = (u8)(RGB.x * 255); + u8 G = (u8)(RGB.y * 255); + u8 B = (u8)(RGB.z * 255); + + Leds->Colors[LedIndex].R = R; + Leds->Colors[LedIndex].G = G; + Leds->Colors[LedIndex].B = B; + } +} + +internal pixel +V4ToRGBPixel(v4 C) +{ + pixel Result = {}; + Result.R = (u8)(C.x * 255); + Result.G = (u8)(C.y * 255); + Result.B = (u8)(C.z * 255); + return Result; +} + +internal void +Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + r32 HueBase = ModR32(Time * 50, 360); + + r32 CycleLength = 5.0f; + r32 CycleProgress = FractR32(Time / CycleLength); + r32 CycleBlend = (SinR32(Time) * .5f) + .5f; + + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 Pos = Leds->Positions[LedIndex]; + r32 Hue = HueBase + Pos.y + Pos.x; + v4 HSV = { Hue, 1, 1, 1 }; + v4 RGB = HSVToRGB(HSV); + + Leds->Colors[LedIndex] = V4ToRGBPixel(RGB); + } +} + +internal void +Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + u32 I = LedIndex + 1; + Leds->Colors[LedIndex] = {}; + if (I % 3 == 0) + { + Leds->Colors[LedIndex].R = 255; + } + else if (I % 3 == 1) + { + Leds->Colors[LedIndex].G = 255; + } + else if (I % 3 == 2) + { + Leds->Colors[LedIndex].B = 255; + } + + } +} + +internal r32 +PatternHash(r32 Seed) +{ + return FractR32(Seed * 17.0 * FractR32(Seed * 0.3183099)); +} + +internal void +Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + pixel ColorA = { 0, 255, 255 }; + pixel ColorB = { 255, 0, 255 }; + + r32 Speed = .5f; + Time *= Speed; + r32 ScaleA = 2 * SinR32(Time / 5); + r32 ScaleB = 2.4f * CosR32(Time / 2.5f); + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 P = Leds->Positions[LedIndex]; + r32 V = P.y; + r32 Noise = .3f * PatternHash(V); + r32 ThetaY = (Leds->Positions[LedIndex].y / 10) + Time + Noise; + r32 ThetaX = (Leds->Positions[LedIndex].x / 13) + Time + Noise; + r32 Fade = (ScaleA * SinR32(ThetaY)) + (ScaleB * CosR32(3 * ThetaX)); + Fade = RemapClampedR32(Fade, -1, 1, 0, 1); + + Leds->Colors[LedIndex].R = (u8)LerpR32(Fade, ColorA.R, ColorB.R); + Leds->Colors[LedIndex].G = (u8)LerpR32(Fade, ColorA.G, ColorB.G); + Leds->Colors[LedIndex].B = (u8)LerpR32(Fade, ColorA.B, ColorB.B); + } +} + +internal void +Pattern_LighthouseRainbow(led_buffer* Leds, 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++) + { + v2 Vector = v2{ + Leds->Positions[LedIndex].x, + Leds->Positions[LedIndex].z + }; + Vector = V2Normalize(Vector); + + r32 Angle = V2Dot(RefVector, Vector); + + v4 HSV = { (Angle * 30) + (Time * 10) + Leds->Positions[LedIndex].y, 1, 1, 1 }; + v4 RGB = HSVToRGB(HSV); + + Leds->Colors[LedIndex] = V4ToRGBPixel(RGB); + } +} + +internal r32 +Smoothstep(r32 T) +{ + r32 Result = (T * T * (3 - (2 * T))); + return Result; +} + +internal void +Pattern_SmoothGrowRainbow(led_buffer* Leds, 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; + + v4 HSV = { 0, 1, 1, 1 }; + for (u32 s = 0; s < Assembly.StripCount; s++) + { + v2_strip Strip = Assembly.Strips[s]; + + v4 RGB0 = HSVToRGB(HSV); + for (u32 l = 0; l < Strip.LedCount; l++) + { + u32 LedIndex = Strip.LedLUT[l]; + Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0); + } + + HSV.x += 15; + } +} + +internal void +Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + r32 PercentCycle = ModR32(Time, 10) / 10; + v4 HSV = { PercentCycle * 360, 1, 1, 1 }; + v4 RGB = HSVToRGB(HSV); + + r32 RefHeight = -100 + (Smoothstep(PercentCycle * 1.4f) * 400); + r32 RefBrightness = 1.0f - Smoothstep(PercentCycle); + + for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) + { + v4 P = Leds->Positions[LedIndex]; + + v4 RgbFaded = v4{}; + if (P.y < RefHeight) + { + RgbFaded = RGB * RefBrightness; + } + Leds->Colors[LedIndex] = V4ToRGBPixel(RgbFaded); + } +} + +#define BLUMEN_PATTERNS_H +#endif // BLUMEN_PATTERNS_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index 47b625a..1e1dd7b 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -371,64 +371,56 @@ Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize) } internal void -Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_list OutputData) +Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer* BufferAt) { DEBUG_TRACK_FUNCTION; u32 BuffersSent = 0; u32 DataSizeSent = 0; - for (addressed_data_buffer* BufferAt = OutputData.Root; - BufferAt != 0; - BufferAt = BufferAt->Next) + switch(BufferAt->AddressType) { - switch(BufferAt->AddressType) + case AddressType_NetworkIP: { - case AddressType_NetworkIP: + Win32Socket_SendTo(BufferAt->SendSocket, + BufferAt->V4SendAddress, + BufferAt->SendPort, + (const char*)BufferAt->Memory, + BufferAt->MemorySize, + 0); + }break; + + case AddressType_ComPort: + { + if (BufferAt->ComPort.Length > 0) { - Win32Socket_SendTo(BufferAt->SendSocket, - BufferAt->V4SendAddress, - BufferAt->SendPort, - (const char*)BufferAt->Memory, - BufferAt->MemorySize, - 0); - }break; - - case AddressType_ComPort: - { - if (BufferAt->ComPort.Length > 0) + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); + if (SerialPort != INVALID_HANDLE_VALUE) { - HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); - if (SerialPort != INVALID_HANDLE_VALUE) + if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) { - if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) - { - BuffersSent += 1; - DataSizeSent += BufferAt->Data.Size; - } + BuffersSent += 1; + DataSizeSent += BufferAt->Data.Size; } } - else - { - OutputDebugStringA("Skipping data buffer because its COM Port isn't set"); - } - }break; - - InvalidDefaultCase; - } + } + else + { +#if 0 + OutputDebugStringA("Skipping data buffer because its COM Port isn't set"); +#endif + } + }break; + + InvalidDefaultCase; } - - gs_string OutputStr = AllocatorAllocString(Context.Allocator, 256); - PrintF(&OutputStr, "Buffers Sent: %d | Size Sent: %d\n", BuffersSent, DataSizeSent); - NullTerminate(&OutputStr); - OutputDebugStringA(OutputStr.Str); } internal void -Win32_SendAddressedDataBuffers_Job(gs_thread_context Context, gs_data Arg) +Win32_SendAddressedDataBuffer_Job(gs_thread_context Context, gs_data Arg) { - addressed_data_buffer_list* OutputData = (addressed_data_buffer_list*)Arg.Memory; - Win32_SendAddressedDataBuffers(Context, *OutputData); + addressed_data_buffer* OutputData = (addressed_data_buffer*)Arg.Memory; + Win32_SendAddressedDataBuffer(Context, OutputData); } #pragma pack(push, 1) @@ -571,10 +563,15 @@ WinMain ( if (true) { - gs_data ProcArg = {}; - ProcArg.Memory = (u8*)&OutputData; - ProcArg.Size = sizeof(OutputData); - Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffers_Job, ProcArg, ConstString("Send UART Data")); + 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")); + } } Mouse_Advance(&Context); @@ -583,7 +580,7 @@ WinMain ( SwapBuffers(DeviceContext); ReleaseDC(MainWindow.Handle, DeviceContext); - //Win32DoQueueWorkUntilDone(&WorkQueue, Context.ThreadContext); + Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); s64 FinishedWorkTime = GetWallClock(); r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); diff --git a/src/sculpture_gen/gen_blumen_lumen.cpp b/src/sculpture_gen/gen_blumen_lumen.cpp index b269cb2..a1fb63f 100644 --- a/src/sculpture_gen/gen_blumen_lumen.cpp +++ b/src/sculpture_gen/gen_blumen_lumen.cpp @@ -175,7 +175,7 @@ int main(int ArgCount, char** Args) 100, v3{0, 0, 0}, 69, - ComPort); + ""); u32 StemChannels[] = { FSC(2, 1), FSC(2, 2), FSC(2, 3), FSC(2, 4), FSC(2, 5), FSC(2, 6) }; u32 BloomOuterChannels[] = { FSC(1, 0), FSC(1, 1), FSC(1, 2), FSC(1, 3), FSC(1, 4), FSC(1, 5), FSC(1, 6), FSC(1, 7), FSC(2, 0) }; @@ -189,23 +189,24 @@ int main(int ArgCount, char** Args) F0.BloomInnerChannels = BloomInnerChannels; BuildFlower(&OutputBuffer, F0); - /* flower_desc F1 = {}; F1.Pos = v3{0, 0, 0}; + F1.ComPort = "\\\\.\\COM9"; F1.FlowerTagValue = "center"; F1.StemChannels = StemChannels; F1.BloomInnerChannels = BloomInnerChannels; F1.BloomOuterChannels = BloomOuterChannels; BuildFlower(&OutputBuffer, F1); - flower_desc F2 = {}; - F2.Pos = v3{1, 0, 0}; - F2.FlowerTagValue = "right"; - F2.StemChannels = StemChannels; - F2.BloomInnerChannels = BloomInnerChannels; - F2.BloomOuterChannels = BloomOuterChannels; - BuildFlower(&OutputBuffer, F2); - */ + /* + flower_desc F2 = {}; + F2.Pos = v3{1, 0, 0}; + F2.FlowerTagValue = "right"; + F2.StemChannels = StemChannels; + F2.BloomInnerChannels = BloomInnerChannels; + F2.BloomOuterChannels = BloomOuterChannels; + BuildFlower(&OutputBuffer, F2); + */ printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str); diff --git a/src/sculpture_gen/sculpture_gen.h b/src/sculpture_gen/sculpture_gen.h index 2b2a702..bbba18c 100644 --- a/src/sculpture_gen/sculpture_gen.h +++ b/src/sculpture_gen/sculpture_gen.h @@ -28,7 +28,11 @@ WriteAssemblyUARTOpen(gs_string* Buffer, char* Name, u32 Scale, v3 Center, u32 S WriteIndented(Buffer, 0, "assembly_center: (%f, %f, %f);\n", Center.x, Center.y, Center.z); WriteIndented(Buffer, 0, "led_strip_count: %d;\n", StripCount); WriteIndented(Buffer, 0, "output_mode: \"UART\";\n"); - WriteIndented(Buffer, 0, "com_port: \"%s\";\n", ComPort); + + if (ComPort) + { + WriteIndented(Buffer, 0, "com_port: \"%s\";\n", ComPort); + } } internal void diff --git a/test_motor_header.h b/test_motor_header.h new file mode 100644 index 0000000..3a443b3 --- /dev/null +++ b/test_motor_header.h @@ -0,0 +1,19 @@ +// +// File: test_motor_header.h +// Author: Peter Slattery +// Creation Date: 2021-01-14 +// +#ifndef TEST_MOTOR_HEADER_H + +struct +{ + u8 MotorOnePos; + u8 MotorTwoPos; + u8 MotorThreePos; +} typedef packet; + +static packet +UnpackPacket + +#define TEST_MOTOR_HEADER_H +#endif // TEST_MOTOR_HEADER_H \ No newline at end of file diff --git a/test_sound_interface_packet.h b/test_sound_interface_packet.h new file mode 100644 index 0000000..a046c21 --- /dev/null +++ b/test_sound_interface_packet.h @@ -0,0 +1,29 @@ +// +// File: test_sound_interface_packet.h +// Author: Peter Slattery +// Creation Date: 2021-01-14 +// +#ifndef TEST_SOUND_INTERFACE_PACKET_H + +enum selectable_patterns +{ +}; + +typedef struct +{ + u8 PrimaryColor[3]; + u8 SecondaryColor[3]; + u32 PatternIndex; // Set via selectable_patterns + u8 Speed; // +} sound_interface_packet; + +// expects V to be in the range -1:1 +u8 FloatToSpeed (float V) +{ + u8 Result = (u8)(((V + 1) / 2) * 255); + return Result; +} + + +#define TEST_SOUND_INTERFACE_PACKET_H +#endif // TEST_SOUND_INTERFACE_PACKET_H \ No newline at end of file