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.

This commit is contained in:
PS 2021-01-16 14:02:25 -08:00
parent 914523cb60
commit 4798002dfc
21 changed files with 885 additions and 515 deletions

15
src/app/blumen_lumen.h Normal file
View File

@ -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

View File

@ -897,6 +897,8 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
{ {
animation_timeline_state* TimelineState = Panel_GetStateStruct(Panel, animation_timeline_state); animation_timeline_state* TimelineState = Panel_GetStateStruct(Panel, animation_timeline_state);
ui_FillRect(&State->Interface, PanelBounds, v4{.1f,.1f,.1f,1.f});
rect2 TimelineBounds, InfoBounds; rect2 TimelineBounds, InfoBounds;
RectVSplit(PanelBounds, 300, &InfoBounds, &TimelineBounds); RectVSplit(PanelBounds, 300, &InfoBounds, &TimelineBounds);

View File

@ -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

View File

@ -37,52 +37,68 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_widget* Layout, de
rect2 Bounds = ui_LayoutRemaining(*Layout); rect2 Bounds = ui_LayoutRemaining(*Layout);
r32 Width = Rect2Width(Bounds); r32 Width = Rect2Width(Bounds);
r32 DepthHeight = 64; r32 DepthHeight = 32;
s64 FrameStartCycles = VisibleFrame->FrameStartCycles; s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; r32 FrameTotalCycles = (r32)(VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles);
debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices, r32 NextThreadTop = Bounds.Max.y;
VisibleFrame);
gs_string String = PushString(Transient, 256); for (s32 t = 0; t < VisibleFrame->ThreadCount; t++)
for (s32 i = 0; i < ThreadScopeCalls->Count; i++)
{ {
scope_record* Record = ThreadScopeCalls->Calls + i; debug_scope_record_list ThreadCalls = VisibleFrame->ThreadCalls[t];
scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash);
r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles;
r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles;
r32 PixelStart = Bounds.Min.x + (Width * PercentStart); gs_string String = PushString(Transient, 256);
r32 PixelEnd = Bounds.Min.x + (Width * PercentEnd);
r32 MinY = Bounds.Max.y - ((Record->CallDepth + 1) * DepthHeight); r32 ThreadScopeMin = Bounds.Max.y;
rect2 ScopeBounds = {
v2{ PixelStart, MinY }, for (s32 i = 0; i < ThreadCalls.Count; i++)
v2{ PixelEnd, MinY + (DepthHeight - 4) }
};
if (Rect2Width(ScopeBounds) >= 1)
{ {
v4 Color = ThreadColors[0]; scope_record* Record = ThreadCalls.Calls + i;
if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash);
{ s64 OffsetStart = Record->StartCycles - FrameStartCycles;
Color = GreenV4; s64 OffsetEnd = Record->EndCycles - FrameStartCycles;
r32 PercentStart = (r32)(OffsetStart) / FrameTotalCycles;
ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover")); r32 PercentEnd = (r32)(OffsetEnd) / FrameTotalCycles;
{ r32 PercentWidth = PercentEnd - PercentStart;
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);
}
ui_FillRect(Interface, ScopeBounds, Color); rect2 ScopeBounds = {
ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); 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;
} }
} }

View File

@ -4,7 +4,7 @@
// Creation Date: 2020-10-17 // Creation Date: 2020-10-17
// //
#ifndef FOLDHAUS_PANEL_TYPES_CPP #ifndef FOLDHAUS_PANEL_TYPES_CPP
global s32 GlobalPanelDefsCount = 6; global s32 GlobalPanelDefsCount = 7;
global panel_definition GlobalPanelDefs[] = { global panel_definition GlobalPanelDefs[] = {
{ "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, { "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 }, { "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 }, { "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 }, { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount },
{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_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 #define FOLDHAUS_PANEL_TYPES_CPP
#endif // FOLDHAUS_PANEL_TYPES_CPP #endif // FOLDHAUS_PANEL_TYPES_CPP

View File

@ -12,6 +12,7 @@ enum panel_type {
PanelType_HierarchyView, PanelType_HierarchyView,
PanelType_NodeGraph, PanelType_NodeGraph,
PanelType_ProfilerView, PanelType_ProfilerView,
PanelType_AssemblyDebug,
}; };
#define FOLDHAUS_PANEL_TYPES_H #define FOLDHAUS_PANEL_TYPES_H
#endif // FOLDHAUS_PANEL_TYPES_H #endif // FOLDHAUS_PANEL_TYPES_H

View File

@ -5,7 +5,7 @@
// //
#ifndef FOLDHAUS_ANIMATION #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); typedef ANIMATION_PROC(animation_proc);
struct frame_range struct frame_range

View File

@ -81,20 +81,22 @@ LedBlend_GetProc(blend_mode BlendMode)
} }
internal void 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; u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle);
Pattern.Proc(Buffer, Assembly, SecondsIntoBlock, Transient); Pattern.Proc(Buffer, Assembly, SecondsIntoBlock, Transient, UserData);
} }
internal void internal void
AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies, AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies,
led_system* LedSystem, led_system* LedSystem,
animation_pattern_array Patterns, animation_pattern_array Patterns,
gs_memory_arena* Transient) gs_memory_arena* Transient,
u8* UserData)
{ {
s32 CurrentFrame = System->CurrentFrame; s32 CurrentFrame = System->CurrentFrame;
r32 FrameTime = CurrentFrame * System->SecondsPerFrame; r32 FrameTime = CurrentFrame * System->SecondsPerFrame;
@ -148,14 +150,14 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
{ {
led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer; led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer;
animation_block Block = LayerFrame.Hot; 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) if (LayerFrame.HasNextHot)
{ {
led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer; led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer;
animation_block Block = LayerFrame.NextHot; animation_block Block = LayerFrame.NextHot;
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient); AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, *Assembly, Patterns, Transient, UserData);
} }
} }

View File

@ -160,7 +160,6 @@ struct assembly_array
assembly* Values; assembly* Values;
}; };
internal led_buffer* internal led_buffer*
LedSystemGetBuffer(led_system* System, u32 Index) LedSystemGetBuffer(led_system* System, u32 Index)
{ {

View File

@ -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

View File

@ -56,7 +56,7 @@ UART_DrawAll_Create(gs_memory_cursor* WriteCursor)
} }
internal void 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}; uart_channel ChannelSettings = {0};
ChannelSettings.ElementsCount = 3; ChannelSettings.ElementsCount = 3;
@ -71,22 +71,88 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli
assembly Assembly = Assemblies.Values[AssemblyIdx]; assembly Assembly = Assemblies.Values[AssemblyIdx];
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages struct strips_to_data_buffer
TotalBufferSize += MessageBaseSize; // DrawAll message {
TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel 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); strips_to_data_buffer* BuffersNeededHead = 0;
AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort.ConstString); strips_to_data_buffer* BuffersNeededTail = 0;
gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data);
for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++)
{ {
v2_strip StripAt = Assembly.Strips[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);
}
} }
} }

View File

@ -25,6 +25,7 @@ ClearAndPushPatterns(animation_pattern_array* Patterns)
Patterns_PushPattern(Patterns, Pattern_Spots); Patterns_PushPattern(Patterns, Pattern_Spots);
Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow); Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow);
Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow); Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow);
Patterns_PushPattern(Patterns, Pattern_GrowAndFade);
} }
RELOAD_STATIC_DATA(ReloadStaticData) RELOAD_STATIC_DATA(ReloadStaticData)
@ -133,16 +134,20 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->Assemblies, State->Assemblies,
&State->LedSystem, &State->LedSystem,
State->Patterns, 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 // 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 // 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 SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient);
assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient); assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient);
SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem); 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); Editor_Render(State, Context, RenderBuffer);
} }

View File

@ -19,6 +19,7 @@
#include "engine/assembly/foldhaus_assembly.h" #include "engine/assembly/foldhaus_assembly.h"
#include "engine/assembly/foldhaus_assembly_parser.cpp" #include "engine/assembly/foldhaus_assembly_parser.cpp"
#include "engine/assembly/foldhaus_assembly_debug.h"
#include "engine/sacn/foldhaus_sacn.h" #include "engine/sacn/foldhaus_sacn.h"
#include "engine/uart/foldhaus_uart.h" #include "engine/uart/foldhaus_uart.h"
@ -51,6 +52,7 @@ struct app_state
streaming_acn SACN; streaming_acn SACN;
led_system LedSystem; led_system LedSystem;
assembly_array Assemblies; assembly_array Assemblies;
assembly_debug_state AssemblyDebugState;
animation_system AnimationSystem; animation_system AnimationSystem;
event_log* GlobalLog; event_log* GlobalLog;
animation_pattern_array Patterns; animation_pattern_array Patterns;
@ -65,411 +67,17 @@ struct app_state
ui_interface Interface; ui_interface Interface;
panel_system PanelSystem; panel_system PanelSystem;
panel* HotPanel; panel* HotPanel;
// User Space
//
gs_data UserData;
}; };
internal void OpenColorPicker(app_state* State, v4* Address); internal void OpenColorPicker(app_state* State, v4* Address);
#include "engine/assembly/foldhaus_assembly.cpp" #include "engine/assembly/foldhaus_assembly.cpp"
// BEGIN TEMPORARY PATTERNS #include "patterns/blumen_patterns.h"
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
internal void internal void
EndCurrentOperationMode(app_state* State) 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_dmx_view.h"
#include "editor/panels/foldhaus_panel_animation_timeline.h" #include "editor/panels/foldhaus_panel_animation_timeline.h"
#include "editor/panels/foldhaus_panel_hierarchy.h" #include "editor/panels/foldhaus_panel_hierarchy.h"
#include "editor/panels/foldhaus_panel_assembly_debug.h"
#include "editor/panels/foldhaus_panel_types.cpp" #include "editor/panels/foldhaus_panel_types.cpp"

View File

@ -148,7 +148,7 @@ typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint);
// Worker Threads // Worker Threads
#define PLATFORM_THREAD_COUNT 0 #define PLATFORM_THREAD_COUNT 3
RESET_WORK_QUEUE(ResetWorkQueue) RESET_WORK_QUEUE(ResetWorkQueue)
{ {

View File

@ -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 internal bool
ui_BeginLabeledDropdown(ui_interface* Interface, gs_string Label, gs_string DropdownValue) ui_BeginLabeledDropdown(ui_interface* Interface, gs_string Label, gs_string DropdownValue)
{ {
ui_BeginRow(Interface, 2); ui_BeginLabelRow(Interface, Label);
ui_Label(Interface, Label);
return ui_BeginDropdown(Interface, DropdownValue); return ui_BeginDropdown(Interface, DropdownValue);
} }

View File

@ -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

View File

@ -371,64 +371,56 @@ Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize)
} }
internal void 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; DEBUG_TRACK_FUNCTION;
u32 BuffersSent = 0; u32 BuffersSent = 0;
u32 DataSizeSent = 0; u32 DataSizeSent = 0;
for (addressed_data_buffer* BufferAt = OutputData.Root; switch(BufferAt->AddressType)
BufferAt != 0;
BufferAt = BufferAt->Next)
{ {
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, HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
BufferAt->V4SendAddress, if (SerialPort != INVALID_HANDLE_VALUE)
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 (Win32SerialPort_Write(SerialPort, BufferAt->Data))
if (SerialPort != INVALID_HANDLE_VALUE)
{ {
if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) BuffersSent += 1;
{ DataSizeSent += BufferAt->Data.Size;
BuffersSent += 1;
DataSizeSent += BufferAt->Data.Size;
}
} }
} }
else }
{ else
OutputDebugStringA("Skipping data buffer because its COM Port isn't set"); {
} #if 0
}break; OutputDebugStringA("Skipping data buffer because its COM Port isn't set");
#endif
InvalidDefaultCase; }
} }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 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; addressed_data_buffer* OutputData = (addressed_data_buffer*)Arg.Memory;
Win32_SendAddressedDataBuffers(Context, *OutputData); Win32_SendAddressedDataBuffer(Context, OutputData);
} }
#pragma pack(push, 1) #pragma pack(push, 1)
@ -571,10 +563,15 @@ WinMain (
if (true) if (true)
{ {
gs_data ProcArg = {}; for (addressed_data_buffer* At = OutputData.Root;
ProcArg.Memory = (u8*)&OutputData; At != 0;
ProcArg.Size = sizeof(OutputData); At = At->Next)
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffers_Job, ProcArg, ConstString("Send UART Data")); {
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); Mouse_Advance(&Context);
@ -583,7 +580,7 @@ WinMain (
SwapBuffers(DeviceContext); SwapBuffers(DeviceContext);
ReleaseDC(MainWindow.Handle, DeviceContext); ReleaseDC(MainWindow.Handle, DeviceContext);
//Win32DoQueueWorkUntilDone(&WorkQueue, Context.ThreadContext); Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext);
s64 FinishedWorkTime = GetWallClock(); s64 FinishedWorkTime = GetWallClock();
r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency);

View File

@ -175,7 +175,7 @@ int main(int ArgCount, char** Args)
100, 100,
v3{0, 0, 0}, v3{0, 0, 0},
69, 69,
ComPort); "");
u32 StemChannels[] = { FSC(2, 1), FSC(2, 2), FSC(2, 3), FSC(2, 4), FSC(2, 5), FSC(2, 6) }; 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) }; 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; F0.BloomInnerChannels = BloomInnerChannels;
BuildFlower(&OutputBuffer, F0); BuildFlower(&OutputBuffer, F0);
/*
flower_desc F1 = {}; flower_desc F1 = {};
F1.Pos = v3{0, 0, 0}; F1.Pos = v3{0, 0, 0};
F1.ComPort = "\\\\.\\COM9";
F1.FlowerTagValue = "center"; F1.FlowerTagValue = "center";
F1.StemChannels = StemChannels; F1.StemChannels = StemChannels;
F1.BloomInnerChannels = BloomInnerChannels; F1.BloomInnerChannels = BloomInnerChannels;
F1.BloomOuterChannels = BloomOuterChannels; F1.BloomOuterChannels = BloomOuterChannels;
BuildFlower(&OutputBuffer, F1); BuildFlower(&OutputBuffer, F1);
flower_desc F2 = {}; /*
F2.Pos = v3{1, 0, 0}; flower_desc F2 = {};
F2.FlowerTagValue = "right"; F2.Pos = v3{1, 0, 0};
F2.StemChannels = StemChannels; F2.FlowerTagValue = "right";
F2.BloomInnerChannels = BloomInnerChannels; F2.StemChannels = StemChannels;
F2.BloomOuterChannels = BloomOuterChannels; F2.BloomInnerChannels = BloomInnerChannels;
BuildFlower(&OutputBuffer, F2); F2.BloomOuterChannels = BloomOuterChannels;
*/ BuildFlower(&OutputBuffer, F2);
*/
printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str); printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str);

View File

@ -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, "assembly_center: (%f, %f, %f);\n", Center.x, Center.y, Center.z);
WriteIndented(Buffer, 0, "led_strip_count: %d;\n", StripCount); WriteIndented(Buffer, 0, "led_strip_count: %d;\n", StripCount);
WriteIndented(Buffer, 0, "output_mode: \"UART\";\n"); 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 internal void

19
test_motor_header.h Normal file
View File

@ -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

View File

@ -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