From bfd50c91297e501a12a44f6e7168038485660588 Mon Sep 17 00:00:00 2001 From: PS Date: Sun, 11 Oct 2020 20:54:38 -0700 Subject: [PATCH] implemented segmented led strips --- .../panels/foldhaus_panel_sculpture_view.h | 2 +- src/app/engine/foldhaus_assembly.cpp | 53 +++- src/app/engine/foldhaus_assembly.h | 83 +++++- src/app/engine/foldhaus_assembly_parser.cpp | 262 +++++++++++++----- src/app/engine/foldhaus_parser.h | 18 -- src/app/engine/foldhaus_serializer.h | 171 ++++++++---- src/app/engine/uart/foldhaus_uart.cpp | 2 +- src/app/foldhaus_app.cpp | 2 +- src/app/platform_win32/win32_foldhaus.cpp | 15 +- 9 files changed, 451 insertions(+), 157 deletions(-) delete mode 100644 src/app/engine/foldhaus_parser.h diff --git a/src/app/editor/panels/foldhaus_panel_sculpture_view.h b/src/app/editor/panels/foldhaus_panel_sculpture_view.h index 30ede9c..a4f7246 100644 --- a/src/app/editor/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/editor/panels/foldhaus_panel_sculpture_view.h @@ -166,7 +166,7 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); - u32 FocusPixel = 256; + u32 FocusPixel = 100; for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) { diff --git a/src/app/engine/foldhaus_assembly.cpp b/src/app/engine/foldhaus_assembly.cpp index fce8922..f183f4c 100644 --- a/src/app/engine/foldhaus_assembly.cpp +++ b/src/app/engine/foldhaus_assembly.cpp @@ -135,6 +135,46 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) Buffer->Positions[Led] = Position; } +internal u32 +Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex) +{ + u32 LedsAdded = 0; + + switch (GenData.Method) + { + case StripGeneration_InterpolatePoints: + { + strip_gen_interpolate_points InterpPoints = GenData.InterpolatePoints; + v4 WS_StripStart = RootPosition + ToV4Point(InterpPoints.StartPosition * Assembly->Scale); + v4 WS_StripEnd = RootPosition + ToV4Point(InterpPoints.EndPosition * Assembly->Scale); + + v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)InterpPoints.LedCount; + for (u32 Step = 0; Step < InterpPoints.LedCount; Step++) + { + s32 LedIndex = LedStartIndex + LedsAdded++; + v4 LedPosition = WS_StripStart + (SingleStep * Step); + LedBufferSetLed(LedBuffer, LedIndex, LedPosition); + StripAt->LedLUT[Step] = LedIndex; + } + }break; + + case StripGeneration_Sequence: + { + strip_gen_sequence Sequence = GenData.Sequence; + for (u32 i = 0; i < Sequence.ElementsCount; i++) + { + __debugbreak(); + strip_gen_data SegmentGenData = Sequence.Elements[i]; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded); + } + }break; + + InvalidDefaultCase; + } + + return LedsAdded; +} + internal void ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) { @@ -150,17 +190,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem) v2_strip* StripAt = &Assembly->Strips[StripIdx]; StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale); - v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale); - - v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount; - for (u32 Step = 0; Step < StripAt->LedCount; Step++) - { - s32 LedIndex = LedsAdded++; - v4 LedPosition = WS_StripStart + (SingleStep * Step); - LedBufferSetLed(LedBuffer, LedIndex, LedPosition); - StripAt->LedLUT[Step] = LedIndex; - } + strip_gen_data GenData = StripAt->GenerationData; + LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded); } } diff --git a/src/app/engine/foldhaus_assembly.h b/src/app/engine/foldhaus_assembly.h index aa422f3..94982a5 100644 --- a/src/app/engine/foldhaus_assembly.h +++ b/src/app/engine/foldhaus_assembly.h @@ -58,6 +58,41 @@ struct strip_sacn_addr struct strip_uart_addr { u8 Channel; + + gs_string ComPort; + // This may not be used based on the value of the parent + // assembly's NetworkPortMode field +}; + +enum strip_gen_method +{ + StripGeneration_InterpolatePoints, + StripGeneration_Sequence, + + StripGeneration_Count, +}; + +typedef struct strip_gen_data strip_gen_data; + +struct strip_gen_interpolate_points +{ + v3 StartPosition; + v3 EndPosition; + u32 LedCount; +}; + +struct strip_gen_sequence +{ + strip_gen_data* Elements; + u32 ElementsCount; +}; + +struct strip_gen_data +{ + strip_gen_method Method; + + strip_gen_interpolate_points InterpolatePoints; + strip_gen_sequence Sequence; }; struct v2_strip @@ -67,10 +102,7 @@ struct v2_strip strip_sacn_addr SACNAddr; strip_uart_addr UARTAddr; - // TODO(Peter): When we create more ways to calculate points, this needs to become - // a type enum and a union - v3 StartPosition; - v3 EndPosition; + strip_gen_data GenerationData; u32 LedCount; u32* LedLUT; @@ -86,6 +118,21 @@ struct led_strip_list u32* StripIndices; }; +enum network_port_mode +{ + // This enum defines the scope which contains what network + // port each address should be sent over. + + NetworkPortMode_GlobalPort, + // GlobalPort means that the port is defined in the assembly structure + + NetworkPortMode_PortPerStrip, + // PortPerStrip means that the address stored in the strip structure + // should be used, and each strip might have a different port + + NetworkPortMode_Count, +}; + struct assembly { gs_memory_arena Arena; @@ -102,7 +149,8 @@ struct assembly v2_strip* Strips; network_protocol OutputMode; - gs_const_string UARTComPort; + network_port_mode NetPortMode; + gs_string UARTComPort; }; struct assembly_array @@ -120,6 +168,31 @@ LedSystemGetBuffer(led_system* System, u32 Index) return Result; } +internal u32 +StripGenData_CountLeds(strip_gen_data Data) +{ + u32 Result = 0; + + switch (Data.Method) + { + case StripGeneration_InterpolatePoints: + { + Result += Data.InterpolatePoints.LedCount; + }break; + + case StripGeneration_Sequence: + { + for (u32 i = 0; i < Data.Sequence.ElementsCount; i++) + { + Result += StripGenData_CountLeds(Data.Sequence.Elements[i]); + } + }break; + + InvalidDefaultCase; + } + + return Result; +} #define FOLDHAUS_ASSEMBLY_H #endif // FOLDHAUS_ASSEMBLY_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_assembly_parser.cpp b/src/app/engine/foldhaus_assembly_parser.cpp index 3f95b16..ff2cbc0 100644 --- a/src/app/engine/foldhaus_assembly_parser.cpp +++ b/src/app/engine/foldhaus_assembly_parser.cpp @@ -33,10 +33,16 @@ enum assembly_field AssemblyField_UART_ComPort, AssemblyField_PointPlacementType, + AssemblyField_InterpolatePoints, AssemblyField_Start, AssemblyField_End, AssemblyField_LedCount, + + AssemblyField_SegmentSequence, + AssemblyField_SegmentSequenceLength, + AssemblyField_Segment, + AssemblyField_TagsCount, AssemblyField_Tag, AssemblyField_Name, @@ -63,12 +69,16 @@ global gs_const_string AssemblyFieldIdentifiers[] = { ConstString("com_port"), // AssemblyField_UART_ComPort ConstString("point_placement_type"), // AssemblyField_PointPlacementType + ConstString("interpolate_points"), // AssemblyField_InterpolatePoints ConstString("start"), // AssemblyField_Start ConstString("end"), // AssemblyField_End - ConstString("led_count"), // AssemblyField_LedCount + ConstString("segment_sequence"), // AssemblyField_SegmentSequence + ConstString("segment_count"), // AssemblyField_SegmentSequenceLength + ConstString("segment"), // AssemblyField_Segment + ConstString("tags_count"), // AssemblyField_TagCount ConstString("tag"), // AssemblyField_Tag ConstString("name"), // AssemblyField_Name @@ -84,6 +94,170 @@ StripSetTag(v2_strip* Strip, u32 TagIndex, gs_const_string TagName, gs_const_str TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); } +internal strip_sacn_addr +AssemblyParser_ReadSACNAddr(parser* Parser, assembly Assembly) +{ + strip_sacn_addr Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputSACN)) + { + Result.StartUniverse = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartUniverse); + Result.StartChannel = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartChannel); + + if (!Parser_ReadCloseStruct(Parser)) + { + //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + } + } + + return Result; +} + +internal strip_uart_addr +AssemblyParser_ReadUARTAddr(parser* Parser, assembly Assembly) +{ + strip_uart_addr Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputUART)) + { + Result.Channel = (u8)Parser_ReadU32Value(Parser, AssemblyField_UART_Channel); + + bool HasNetPort = Parser_ReadStringValue(Parser, AssemblyField_UART_ComPort, &Result.ComPort, true); + if (Assembly.NetPortMode == NetworkPortMode_PortPerStrip && !HasNetPort) + { + Parser_PushErrorF(Parser, "NetPortMode for assembly is PortPerStrip, but this strip doesn't have an output port."); + } + + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Struct doesn't close where expected"); + } + } + + return Result; +} + +internal void +AssemblyParser_ReadTag(parser* Parser, v2_strip* StripAt, u32 TagIndex) +{ + if (Parser_ReadOpenStruct(Parser, AssemblyField_Tag)) + { + // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface + // right now they are stored in temp memory and won't persist + gs_string TagName = Parser_ReadStringValue(Parser, AssemblyField_Name); + gs_string TagValue = Parser_ReadStringValue(Parser, AssemblyField_Value); + StripSetTag(StripAt, TagIndex, TagName.ConstString, TagValue.ConstString); + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Tag struct doesn't close where expected"); + } + } + else + { + Parser_PushErrorF(Parser, "Expected a tag struct, but none was found."); + } +} + + +internal void +AssemblyParser_ReadTagList(parser* Parser, v2_strip* StripAt, assembly* Assembly) +{ + StripAt->TagsCount = Parser_ReadU32Value(Parser, AssemblyField_TagsCount); + // NOTE(pjs): Always add one tag to the input to leave room for the assembly name + StripAt->TagsCount += 1; + StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); + + StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); + + for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) + { + AssemblyParser_ReadTag(Parser, StripAt, Tag); + } +} + +internal strip_gen_data AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly); + +internal strip_gen_interpolate_points +AssemblyParser_ReadInterpolatePoints(parser* Parser) +{ + strip_gen_interpolate_points Result = {0}; + if (Parser_ReadOpenStruct(Parser, AssemblyField_InterpolatePoints)) + { + Result.StartPosition = Parser_ReadV3Value(Parser, AssemblyField_Start); + Result.EndPosition = Parser_ReadV3Value(Parser, AssemblyField_End); + Result.LedCount = Parser_ReadU32Value(Parser, AssemblyField_LedCount); + if (!Parser_ReadCloseStruct(Parser)) + { + // TODO(pjs): + } + } + else + { + // TODO(pjs): + } + return Result; +} + +internal strip_gen_sequence +AssemblyParser_ReadSequence(parser* Parser, assembly* Assembly) +{ + strip_gen_sequence Result = {0}; + if (Parser_ReadOpenStruct(Parser, AssemblyField_SegmentSequence)) + { + Result.ElementsCount = Parser_ReadU32Value(Parser, AssemblyField_SegmentSequenceLength); + Result.Elements = PushArray(&Assembly->Arena, strip_gen_data, Result.ElementsCount); + for (u32 i = 0; i < Result.ElementsCount; i++) + { + Result.Elements[i] = AssemblyParser_ReadStripGenData(Parser, Assembly); + } + if (!Parser_ReadCloseStruct(Parser)) + { + // TODO(pjs): + } + } + else + { + // TODO(pjs): + } + return Result; +} + +internal strip_gen_data +AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly) +{ + strip_gen_data Result = {0}; + + if (Parser_ReadOpenStruct(Parser, AssemblyField_Segment)) + { + gs_string PointPlacementType = Parser_ReadStringValue(Parser, AssemblyField_PointPlacementType); + + // TODO(pjs): We want to store enum strings in some unified way + // :EnumStringsGen + if (StringsEqual(PointPlacementType.ConstString, ConstString("InterpolatePoints"))) + { + Result.Method = StripGeneration_InterpolatePoints; + Result.InterpolatePoints = AssemblyParser_ReadInterpolatePoints(Parser); + } + else if (StringsEqual(PointPlacementType.ConstString, + ConstString("SegmentSequence"))) + { + Result.Method = StripGeneration_Sequence; + Result.Sequence = AssemblyParser_ReadSequence(Parser, Assembly); + } + else + { + Parser_PushErrorF(Parser, "Incorrect Point Placement Type found for segment"); + } + + if (!Parser_ReadCloseStruct(Parser)) + { + Parser_PushErrorF(Parser, "Strip Gen Data did not close the struct where expected"); + } + } + + return Result; +} + internal bool ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient) { @@ -96,19 +270,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe Parser.At = Parser.String.Str; Parser.LineStart = Parser.At; Parser.Arena = &Assembly->Arena; + Parser.Transient = Transient; Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName); Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale); Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter); Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount); - Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode); if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) { Assembly->OutputMode = NetworkProtocol_UART; - Assembly->UARTComPort = Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, true).ConstString; + if (Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, &Assembly->UARTComPort, true)) + { + Assembly->NetPortMode = NetworkPortMode_GlobalPort; + } + else + { + Assembly->NetPortMode = NetworkPortMode_PortPerStrip; + } } else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) { @@ -116,7 +297,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe } else { - //TokenizerPushError(&Tokenizer, "Invalid output mode specified."); + Parser_PushErrorF(&Parser, "Invalid output mode specified for assembly."); } for (u32 i = 0; i < Assembly->StripCount; i++) @@ -124,83 +305,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe v2_strip* StripAt = Assembly->Strips + i; if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip)) { - if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputSACN)) - { - StripAt->SACNAddr.StartUniverse = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartUniverse); - StripAt->SACNAddr.StartChannel = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartChannel); - - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } + StripAt->SACNAddr = AssemblyParser_ReadSACNAddr(&Parser, *Assembly); + StripAt->UARTAddr = AssemblyParser_ReadUARTAddr(&Parser, *Assembly); + StripAt->GenerationData = AssemblyParser_ReadStripGenData(&Parser, Assembly); + StripAt->LedCount = StripGenData_CountLeds(StripAt->GenerationData); + AssemblyParser_ReadTagList(&Parser, StripAt, Assembly); - if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputUART)) - { - StripAt->UARTAddr.Channel = (u8)Parser_ReadU32Value(&Parser, AssemblyField_UART_Channel); - - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } - - // TODO(Peter): Need to store this - gs_string PointPlacementType = Parser_ReadStringValue(&Parser, AssemblyField_PointPlacementType); - // TODO(Peter): Switch on value of PointPlacementType - if (Parser_ReadOpenStruct(&Parser, AssemblyField_InterpolatePoints)) - { - StripAt->StartPosition = Parser_ReadV3Value(&Parser, AssemblyField_Start); - StripAt->EndPosition = Parser_ReadV3Value(&Parser, AssemblyField_End); - if (!Parser_ReadCloseStruct(&Parser)) - { - // TODO(Peter): @ErrorHandling - // Have this function prepend the filename and line number. - // Create an error display popup window, or an error log window that takes over a panel automatically - // TokenizerPushError(&Tokenizer, "Unable to read - } - } - - StripAt->LedCount = Parser_ReadU32Value(&Parser, AssemblyField_LedCount); Assembly->LedCountTotal += StripAt->LedCount; - StripAt->TagsCount = Parser_ReadU32Value(&Parser, AssemblyField_TagsCount); - // NOTE(pjs): Always add one tag to the input to leave room for the assembly name - StripAt->TagsCount += 1; - StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount); - StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString); - for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++) - { - if (Parser_ReadOpenStruct(&Parser, AssemblyField_Tag)) - { - // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface - // right now they are stored in temp memory and won't persist - gs_string TagName = Parser_ReadStringValue(&Parser, AssemblyField_Name); - gs_string TagValue = Parser_ReadStringValue(&Parser, AssemblyField_Value); - StripSetTag(StripAt, Tag, TagName.ConstString, TagValue.ConstString); - if (!Parser_ReadCloseStruct(&Parser)) - { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); - } - } - else - { - //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); - } - } - - if (!Parser_ReadCloseStruct(&Parser)) { - //TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); + Parser_PushErrorF(&Parser, "Strip struct doesn't close where expected"); } } else { - //TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); + Parser_PushErrorF(&Parser, "Expected a strip struct but none was found"); } } + // TODO(pjs): invalidate the file if its incorrect return true; //Tokenizer.ParsingIsValid; } diff --git a/src/app/engine/foldhaus_parser.h b/src/app/engine/foldhaus_parser.h deleted file mode 100644 index 709f375..0000000 --- a/src/app/engine/foldhaus_parser.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// File: foldhaus_parser.h -// Author: Peter Slattery -// Creation Date: 2020-10-09 -// -#ifndef FOLDHAUS_PARSER_H - -struct parser -{ - gs_string String; - gs_const_string* Identifiers; - u32 IdentifiersCount; -}; - - - -#define FOLDHAUS_PARSER_H -#endif // FOLDHAUS_PARSER_H \ No newline at end of file diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h index a55ea2e..06f9d71 100644 --- a/src/app/engine/foldhaus_serializer.h +++ b/src/app/engine/foldhaus_serializer.h @@ -134,11 +134,17 @@ Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value) struct parser_error { gs_string Message; + + gs_string FileName; + u32 LineNumber; + parser_error* Next; }; struct parser { + gs_string FileName; + gs_string String; gs_const_string* Identifiers; @@ -160,7 +166,11 @@ internal void Parser_PushErrorF(parser* Parser, char* Format, ...) { parser_error* Error = PushStruct(Parser->Transient, parser_error); + Error->FileName = Parser->FileName; + Error->LineNumber = Parser->Line; + Error->Message = PushString(Parser->Transient, 1024); + PrintF(&Error->Message, "File: %S Line: %d - ", Error->FileName, Error->LineNumber); va_list Args; va_start(Args, Format); @@ -268,11 +278,13 @@ Parser_ReadString(parser* P, u32 IdentIndex) return Parser_ReadString(P, Ident); } -internal gs_string -Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false) +internal bool +Parser_ReadStringValue(parser* P, gs_const_string Ident, gs_string* Output, bool ShouldNullTerminate = false) { + Assert(Output != 0); + // ident: "value"; - gs_string Result = {}; + bool Result = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":")) && Parser_AdvanceIfTokenEquals(P, ConstString("\""))) @@ -294,10 +306,12 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat { StringLength += 1; } - Result = PushStringF(P->Arena, StringLength, "%S", FileString); + + Result = true; + *Output = PushStringF(P->Arena, StringLength, "%S", FileString); if (ShouldNullTerminate) { - NullTerminate(&Result); + NullTerminate(Output); } } else @@ -305,14 +319,25 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat Parser_PushErrorF(P, "String doesn't have a closing quote, or line doesn't end with a semicolon"); } } - else - { - Parser_PushErrorF(P, "String doesn't begin correctly"); - } return Result; } +internal bool +Parser_ReadStringValue(parser* P, u32 IdentIndex, gs_string* Result, bool ShouldNullTerminate = false) +{ + gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); + return Parser_ReadStringValue(P, Ident, Result, ShouldNullTerminate); +} + +internal gs_string +Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false) +{ + gs_string Result = {0}; + Parser_ReadStringValue(P, Ident, &Result, ShouldNullTerminate); + return Result; +} + internal gs_string Parser_ReadStringValue(parser* P, u32 IdentIndex, bool ShouldNullTerminate = false) { @@ -346,42 +371,66 @@ Parser_ReadCloseStruct(parser* P) return Result; } +internal bool +Parser_ReadNumberString(parser* P, gs_const_string* Output) +{ + Assert(Output != 0); + + bool Success = false; + + if (IsNumericExtended(P->At[0])) + { + char* NumStart = P->At; + while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0])) + { + Parser_AdvanceChar(P); + } + + Output->Str = NumStart; + Output->Length = P->At - NumStart; + Success = true; + } + + return Success; +} + internal gs_const_string Parser_ReadNumberString(parser* P) { - gs_const_string Result = {}; - Result.Str = P->At; - while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0])) - { - Parser_AdvanceChar(P); - } - Result.Length = P->At - Result.Str; + gs_const_string Result = {0}; + Parser_ReadNumberString(P, &Result); return Result; } -internal u32 -Parser_ReadU32Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadU32Value(parser* P, gs_const_string Ident, u32* Result) { // ident: value; - u32 Result = 0; + bool Success = false; + if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":"))) { gs_const_string NumStr = Parser_ReadNumberString(P); if (Parser_AdvanceIfLineEnd(P)) { - Result = (u32)ParseInt(NumStr); + *Result = (u32)ParseInt(NumStr); + Success = true; } else { Parser_PushErrorF(P, "U32 Value doesn't end with semicolon"); } } - else - { - Parser_PushErrorF(P, "U32 value doesn't begin properly"); - } + return Success; +} + +internal u32 +Parser_ReadU32Value(parser* P, gs_const_string Ident) +{ + u32 Result = 0; + Parser_ReadU32Value(P, Ident, &Result); return Result; } @@ -392,52 +441,72 @@ Parser_ReadU32Value(parser* P, u32 IdentIndex) return Parser_ReadU32Value(P, Ident); } +internal bool +Parser_ReadR32(parser* P, r32* Result) +{ + bool Success = false; + gs_const_string NumStr = {0}; + if (Parser_ReadNumberString(P, &NumStr)) + { + *Result = (r32)ParseFloat(NumStr); + Success = true; + } + return Success; +} + internal r32 Parser_ReadR32(parser* P) { r32 Result = 0; - gs_const_string NumStr = Parser_ReadNumberString(P); - Result = (r32)ParseFloat(NumStr); + Parser_ReadR32(P, &Result); return Result; } -internal r32 -Parser_ReadR32Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadR32Value(parser* P, gs_const_string Ident, r32* Result) { // ident: value; - r32 Result = 0; + bool Success = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":"))) { r32 Value = Parser_ReadR32(P); if (Parser_AdvanceIfLineEnd(P)) { - Result = Value; + *Result = Value; + Success = true; } else { Parser_PushErrorF(P, "R32 Value doesn't end with semicolon"); } } - else - { - Parser_PushErrorF(P, "R32 value doesn't begin properly"); - } + return Success; +} + +internal r32 +Parser_ReadR32Value(parser* P, gs_const_string Ident) +{ + r32 Result = 0; + Parser_ReadR32Value(P, Ident, &Result); return Result; } -internal u32 +internal r32 Parser_ReadR32Value(parser* P, u32 IdentIndex) { + r32 Result = 0; gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); - return Parser_ReadR32Value(P, Ident); + Parser_ReadR32Value(P, Ident, &Result); + return Result; } -internal v3 -Parser_ReadV3Value(parser* P, gs_const_string Ident) +internal bool +Parser_ReadV3Value(parser* P, gs_const_string Ident, v3* Result) { - v3 Result = {0}; + Assert(Result != 0); + bool Success = false; if (Parser_AdvanceIfTokenEquals(P, Ident) && Parser_AdvanceIfTokenEquals(P, ConstString(":")) && Parser_AdvanceIfTokenEquals(P, ConstString("("))) @@ -458,27 +527,35 @@ Parser_ReadV3Value(parser* P, gs_const_string Ident) if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) && Parser_AdvanceIfLineEnd(P)) { - Result.x = X; - Result.y = Y; - Result.z = Z; + Result->x = X; + Result->y = Y; + Result->z = Z; + Success = true; } else { Parser_PushErrorF(P, "V3 Value doesn't end correctly"); } } - else - { - Parser_PushErrorF(P, "V3 Value doesn't begin correctly"); - } + + return Success; +} + +internal v3 +Parser_ReadV3Value(parser* P, gs_const_string Ident) +{ + v3 Result = {0}; + Parser_ReadV3Value(P, Ident, &Result); return Result; } internal v3 Parser_ReadV3Value(parser* P, u32 IdentIndex) { + v3 Result = {0}; gs_const_string Ident = Parser_GetIdent(*P, IdentIndex); - return Parser_ReadV3Value(P, Ident); + Parser_ReadV3Value(P, Ident, &Result); + return Result; } diff --git a/src/app/engine/uart/foldhaus_uart.cpp b/src/app/engine/uart/foldhaus_uart.cpp index 1e7f635..d523f6d 100644 --- a/src/app/engine/uart/foldhaus_uart.cpp +++ b/src/app/engine/uart/foldhaus_uart.cpp @@ -76,7 +76,7 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize); - AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort); + AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort.ConstString); gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data); for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5644aa3..86fb097 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -123,7 +123,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128); #if 1 - gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold"); + gs_const_string SculpturePath = ConstString("data/blumen_lumen_silver_spring.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); #endif diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index d11e851..653dbe6 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -389,14 +389,21 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_ case AddressType_ComPort: { - HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); - if (SerialPort != INVALID_HANDLE_VALUE) + if (BufferAt->ComPort.Length > 0) { - if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); + if (SerialPort != INVALID_HANDLE_VALUE) { - BuffersSent += 1; + if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) + { + BuffersSent += 1; + } } } + else + { + OutputDebugStringA("Skipping data buffer because its COM Port isn't set"); + } }break; InvalidDefaultCase;