Finished parsing the new assembly file format
This commit is contained in:
parent
c2f3b9193d
commit
bfd9d6671c
|
@ -5,440 +5,386 @@
|
|||
//
|
||||
#ifndef ASSEMBLY_PARSER_CPP
|
||||
|
||||
internal assembly_token
|
||||
ParseToken (tokenizer* Tokenizer)
|
||||
enum assembly_field
|
||||
{
|
||||
assembly_token Result = {};
|
||||
Result.Token = Tokenizer->At;
|
||||
Result.Length = 1;
|
||||
EatChar(Tokenizer);
|
||||
AssemblyField_AssemblyName,
|
||||
AssemblyField_AssemblyScale,
|
||||
AssemblyField_LedStripCount,
|
||||
|
||||
if (*Result.Token == ':'){ Result.Type = AssemblyToken_Colon; }
|
||||
else if (*Result.Token == ';'){ Result.Type = AssemblyToken_SemiColon; }
|
||||
else if (*Result.Token =='{'){ Result.Type = AssemblyToken_LeftCurlyBrace; }
|
||||
else if (*Result.Token =='}'){ Result.Type = AssemblyToken_RightCurlyBrace; }
|
||||
else if (*Result.Token ==','){ Result.Type = AssemblyToken_Comma; }
|
||||
else if (IsNumericExtended(*Result.Token))
|
||||
{
|
||||
while(*Tokenizer->At && IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
Result.Type = AssemblyToken_Number;
|
||||
Result.Length = Tokenizer->At - Result.Token;
|
||||
}
|
||||
else if (*Result.Token =='\"')
|
||||
{
|
||||
while(*Tokenizer->At && *Tokenizer->At != '\"') { EatChar(Tokenizer); }
|
||||
Result.Token++; // Skip the quote
|
||||
Result.Type = AssemblyToken_String;
|
||||
Result.Length = (Tokenizer->At - Result.Token) - 1;
|
||||
}
|
||||
else if (*Result.Token == '(')
|
||||
{
|
||||
while(*Tokenizer->At && *Tokenizer->At != ')') { EatChar(Tokenizer); }
|
||||
Result.Token++; // Skip the paren
|
||||
Result.Type = AssemblyToken_Vector;
|
||||
Result.Length = (Tokenizer->At - Result.Token) - 1;
|
||||
}
|
||||
else if (CharArraysEqualUpToLength(Result.Token, LED_STRIP_IDENTIFIER, CharArrayLength(LED_STRIP_IDENTIFIER)))
|
||||
{
|
||||
Result.Type = AssemblyToken_LEDStrip;
|
||||
Result.Length = CharArrayLength(LED_STRIP_IDENTIFIER);
|
||||
Tokenizer->At += Result.Length - 1;
|
||||
}
|
||||
else if (CharArraysEqualUpToLength(Result.Token, END_ASSEMBLY_FILE_IDENTIFIER, CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER)))
|
||||
{
|
||||
Result.Type = AssemblyToken_EndOfFile;
|
||||
Result.Length = CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER);
|
||||
Tokenizer->At += Result.Length - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Type = AssemblyToken_Identifier;
|
||||
while(*Tokenizer->At && !IsWhitespace(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
}
|
||||
AssemblyField_LedStrip,
|
||||
AssemblyField_ControlBoxId,
|
||||
AssemblyField_StartUniverse,
|
||||
AssemblyField_StartChannel,
|
||||
AssemblyField_PointPlacementType,
|
||||
AssemblyField_InterpolatePoints,
|
||||
AssemblyField_Start,
|
||||
AssemblyField_End,
|
||||
AssemblyField_LedCount,
|
||||
AssemblyField_TagsCount,
|
||||
AssemblyField_Tag,
|
||||
AssemblyField_Name,
|
||||
AssemblyField_Value,
|
||||
|
||||
return Result;
|
||||
}
|
||||
AssemblyField_Count,
|
||||
};
|
||||
|
||||
internal v3
|
||||
ParseAssemblyVector (char* String)
|
||||
global_variable char* AssemblyFieldIdentifiers[] = {
|
||||
"assembly_name", // AssemblyField_AssemblyName
|
||||
"assembly_scale", // AssemblyField_AssemblyScale
|
||||
"led_strip_count", // AssemblyField_LedStripCount
|
||||
|
||||
"led_strip", // AssemblyField_LedStrip
|
||||
|
||||
"control_box_id", // AssemblyField_ControlBoxId
|
||||
"start_universe", // AssemblyField_StartUniverse
|
||||
"start_channel", // AssemblyField_StartChannel
|
||||
|
||||
"point_placement_type", // AssemblyField_PointPlacementType
|
||||
"interpolate_points", // AssemblyField_InterpolatePoints
|
||||
"start", // AssemblyField_Start
|
||||
"end", // AssemblyField_End
|
||||
|
||||
"led_count", // AssemblyField_LedCount
|
||||
|
||||
"tags_count", // AssemblyField_TagCount
|
||||
"tag", // AssemblyField_Tag
|
||||
"name", // AssemblyField_Name
|
||||
"value", // AssemblyField_Value
|
||||
};
|
||||
|
||||
struct assembly_tokenizer
|
||||
{
|
||||
v3 Result = {};
|
||||
string Text;
|
||||
char* At;
|
||||
|
||||
tokenizer Tokenizer = {};
|
||||
Tokenizer.At = String;
|
||||
u32 LineNumber;
|
||||
};
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.x = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.y = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.z = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseAssemblyFileHeader (assembly_definition* Assembly, tokenizer* Tokenizer)
|
||||
internal bool
|
||||
AtValidPosition(assembly_tokenizer* T)
|
||||
{
|
||||
b32 HeaderIsValid = false;
|
||||
|
||||
if (CharArraysEqualUpToLength(Tokenizer->At, LED_STRIP_COUNT_IDENTIFIER, CharArrayLength(LED_STRIP_COUNT_IDENTIFIER)))
|
||||
{
|
||||
Tokenizer->At += CharArrayLength(LED_STRIP_COUNT_IDENTIFIER);
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token CountToken = ParseToken(Tokenizer);
|
||||
if (CountToken.Type == AssemblyToken_Number)
|
||||
{
|
||||
Assembly->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
|
||||
HeaderIsValid = true;
|
||||
}
|
||||
EatWhitespace(Tokenizer);
|
||||
}
|
||||
return HeaderIsValid;
|
||||
}
|
||||
|
||||
internal led_strip_definition
|
||||
ParseLEDStrip (tokenizer* Tokenizer)
|
||||
{
|
||||
led_strip_definition Result = {};
|
||||
|
||||
// Control Box Index
|
||||
while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
assembly_token BoxIDToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
Result.ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token).SignedIntValue;
|
||||
|
||||
// Start Universe
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token StartUniverseToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
Result.StartUniverse = ParseSignedIntUnsafe(StartUniverseToken.Token).SignedIntValue;
|
||||
|
||||
// Start Channel
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token StartChannelToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
Result.StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token).SignedIntValue;
|
||||
|
||||
// Strip Type
|
||||
// TODO(Peter): This is unused for now, and would be a branch point for parsing
|
||||
// the rest of the info. Fix this.
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
if (CharArraysEqualUpToLength(Tokenizer->At, INTERPOLATE_POINTS_IDENTIFIER, CharArrayLength(INTERPOLATE_POINTS_IDENTIFIER)))
|
||||
{
|
||||
Result.InterpolationType = StripInterpolate_Points;
|
||||
|
||||
// Start Position
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token StartPositionToken = ParseToken(Tokenizer);
|
||||
Assert(StartPositionToken.Type == AssemblyToken_Vector);
|
||||
Result.InterpolatePositionStart = ParseAssemblyVector(StartPositionToken.Token);
|
||||
|
||||
// End Position
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token EndPositionToken = ParseToken(Tokenizer);
|
||||
Assert(EndPositionToken.Type == AssemblyToken_Vector);
|
||||
Result.InterpolatePositionEnd = ParseAssemblyVector(EndPositionToken.Token);
|
||||
|
||||
// LEDs Per Strip
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token LEDsPerStripToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
Result.LEDsPerStrip = ParseSignedIntUnsafe(LEDsPerStripToken.Token).SignedIntValue;
|
||||
}
|
||||
|
||||
EatPastCharacter(Tokenizer, '}');
|
||||
EatWhitespace(Tokenizer);
|
||||
|
||||
bool Result = ((T->At - T->Text.Memory) < T->Text.Length);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ParseAssemblyFileBody (assembly_definition* Assembly, tokenizer* Tokenizer)
|
||||
AdvanceChar(assembly_tokenizer* T)
|
||||
{
|
||||
EatWhitespace(Tokenizer);
|
||||
|
||||
while(*Tokenizer->At)
|
||||
if (IsNewline(T->At[0]))
|
||||
{
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token Token = ParseToken(Tokenizer);
|
||||
|
||||
if (Token.Type != AssemblyToken_EndOfFile)
|
||||
{
|
||||
switch (Token.Type)
|
||||
{
|
||||
case AssemblyToken_LEDStrip:
|
||||
{
|
||||
led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount;
|
||||
Assert(Assembly->LEDStripCount < Assembly->LEDStripSize);
|
||||
|
||||
*LEDStripDef = ParseLEDStrip(Tokenizer);
|
||||
Assembly->TotalLEDCount += LEDStripDef->LEDsPerStrip;
|
||||
|
||||
Assembly->LEDStripCount++;
|
||||
} break;
|
||||
|
||||
// TODO(Peter): Other cases? What else would need to be in the assembly body?
|
||||
|
||||
InvalidDefaultCase;
|
||||
T->LineNumber += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(Peter): Ensure the validity of the assembly file. We probably don't want an assert here,
|
||||
// more likely we want to load a valid assembly anyways, and just raise this as an error to the user
|
||||
// so they can fix it.
|
||||
Assert(Assembly->LEDStripCount == Assembly->LEDStripSize);
|
||||
T->At++;
|
||||
}
|
||||
|
||||
inline b32
|
||||
ParseTokenEquals (tokenizer* T, char* Validate)
|
||||
internal void
|
||||
EatWhitespace(assembly_tokenizer* T)
|
||||
{
|
||||
b32 Result = true;
|
||||
while(AtValidPosition(T) && IsNewlineOrWhitespace(T->At[0]))
|
||||
{
|
||||
AdvanceChar(T);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool
|
||||
AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value)
|
||||
{
|
||||
bool Result = true;
|
||||
|
||||
char* TAt = T->At;
|
||||
char* VAt = Validate;
|
||||
while (((TAt - T->Memory) < T->MemoryLength) && *VAt)
|
||||
char* VAt = Value;
|
||||
while (*VAt != 0)
|
||||
{
|
||||
if (*VAt != *TAt)
|
||||
if (*TAt != *VAt)
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
TAt++;
|
||||
*VAt++;
|
||||
TAt += 1;
|
||||
VAt += 1;
|
||||
}
|
||||
|
||||
// TODO(Peter): What if the token is a subset of Value? ie. this would return true for
|
||||
// T->At = hello_world and Value = hello_
|
||||
// But the next token we read would fail
|
||||
|
||||
if (Result)
|
||||
{
|
||||
T->At = TAt;
|
||||
EatWhitespace(T);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseComma(tokenizer* T)
|
||||
internal bool
|
||||
ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T)
|
||||
{
|
||||
b32 Result = ParseTokenEquals(T, ",");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseOpenCurlyBrace(tokenizer* T)
|
||||
{
|
||||
b32 Result = ParseTokenEquals(T, "{");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseCloseCurlyBrace(tokenizer* T)
|
||||
{
|
||||
b32 Result = ParseTokenEquals(T, "}");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseOpenParen(tokenizer* T)
|
||||
{
|
||||
b32 Result = ParseTokenEquals(T, "(");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseCloseParen(tokenizer* T)
|
||||
{
|
||||
b32 Result = ParseTokenEquals(T, ")");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseUnsignedInteger(tokenizer* T, u32* Value)
|
||||
{
|
||||
parse_result Result = ParseUnsignedIntUnsafe(T->At);
|
||||
*Value = Result.UnsignedIntValue;
|
||||
T->At = Result.OnePastLast;
|
||||
|
||||
// TODO(Peter): Parse functions in gs_string don't actually check for errors or
|
||||
// whether or not they actually parsed an int.
|
||||
// :GSStringParseErrors
|
||||
return true;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseFloat(tokenizer* T, r32* Value)
|
||||
{
|
||||
parse_result ParseResult = ParseFloatUnsafe(T->At);
|
||||
*Value = ParseResult.FloatValue;
|
||||
T->At = ParseResult.OnePastLast;
|
||||
|
||||
// TODO(Peter):
|
||||
// :GSStringParseErrors
|
||||
return true;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseVector(tokenizer* T, v3* Value)
|
||||
{
|
||||
b32 Result = true;
|
||||
|
||||
if (ParseOpenParen(T))
|
||||
bool Result = false;
|
||||
if (AdvanceIfTokenEquals(T, AssemblyFieldIdentifiers[Field]))
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
if (AdvanceIfTokenEquals(T, ":"))
|
||||
{
|
||||
b32 ValueSuccess = ParseFloat(T, &(Value->E[i]));
|
||||
if (!ValueSuccess)
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
Result = true;
|
||||
}
|
||||
|
||||
b32 CommaSuccess = ParseComma(T);
|
||||
if (!CommaSuccess)
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParseCloseParen(T))
|
||||
{
|
||||
Result = false;
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = false;
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// TODO(Peter): :ErrorLogging
|
||||
#define ParseLEDStripToken(tokenizer, parse_expr, error_msg) \
|
||||
(parse_expr) && (ParseComma(tokenizer))
|
||||
|
||||
internal b32
|
||||
ParseLEDStripCount (tokenizer* T, u32* Value)
|
||||
internal bool
|
||||
ReadFieldEnd(assembly_tokenizer* T)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
if (ParseTokenEquals(T, LED_STRIP_COUNT_IDENTIFIER))
|
||||
bool Result = AdvanceIfTokenEquals(T, ";");
|
||||
if (Result)
|
||||
{
|
||||
EatWhitespace(T);
|
||||
if (ParseUnsignedInteger(T, Value))
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal string
|
||||
ReadString(assembly_tokenizer* T)
|
||||
{
|
||||
string Result = {};
|
||||
if (AdvanceIfTokenEquals(T, "\""))
|
||||
{
|
||||
char* StringStart = T->At;
|
||||
while(AtValidPosition(T) && T->At[0] != '\"')
|
||||
{
|
||||
T->At++;
|
||||
}
|
||||
Result.Memory = StringStart;
|
||||
Result.Max = T->At - StringStart;
|
||||
Result.Length = Result.Max;
|
||||
if (AdvanceIfTokenEquals(T, "\""))
|
||||
{
|
||||
// Success
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal string
|
||||
GetNumberString(assembly_tokenizer* T)
|
||||
{
|
||||
string Result = {};
|
||||
Result.Memory = T->At;
|
||||
while(AtValidPosition(T) && IsNumericExtended(T->At[0]))
|
||||
{
|
||||
AdvanceChar(T);
|
||||
}
|
||||
Result.Length = T->At - Result.Memory;
|
||||
Result.Max = Result.Length;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal r32
|
||||
ReadFloat(assembly_tokenizer* T)
|
||||
{
|
||||
r32 Result = 0;
|
||||
string NumberString = GetNumberString(T);
|
||||
parse_result ParsedFloat = ParseFloat(StringExpand(NumberString));
|
||||
Result = ParsedFloat.FloatValue;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
ReadInt(assembly_tokenizer* T)
|
||||
{
|
||||
s32 Result = 0;
|
||||
string NumberString = GetNumberString(T);
|
||||
parse_result ParsedInt = ParseSignedInt(StringExpand(NumberString));
|
||||
Result = ParsedInt.SignedIntValue;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal string
|
||||
ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena)
|
||||
{
|
||||
string Result = {};
|
||||
if (ReadFieldIdentifier(Field, T))
|
||||
{
|
||||
string ExistingString = ReadString(T);
|
||||
if (ReadFieldEnd(T))
|
||||
{
|
||||
// Success
|
||||
Result = PushString(Arena, ExistingString.Length);
|
||||
CopyStringTo(ExistingString, &Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal r32
|
||||
ReadFloatField(assembly_field Field, assembly_tokenizer* T)
|
||||
{
|
||||
r32 Result = 0.0f;
|
||||
if (ReadFieldIdentifier(Field, T))
|
||||
{
|
||||
Result = ReadFloat(T);
|
||||
if (!ReadFieldEnd(T))
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
ReadIntField(assembly_field Field, assembly_tokenizer* T)
|
||||
{
|
||||
r32 Result = 0.0f;
|
||||
if (ReadFieldIdentifier(Field, T))
|
||||
{
|
||||
Result = ReadInt(T);
|
||||
if (!ReadFieldEnd(T))
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal v3
|
||||
ReadV3Field(assembly_field Field, assembly_tokenizer* T)
|
||||
{
|
||||
v3 Result = {};
|
||||
if (ReadFieldIdentifier(Field, T))
|
||||
{
|
||||
if (AdvanceIfTokenEquals(T, "("))
|
||||
{
|
||||
Result.x = ReadFloat(T);
|
||||
if (AdvanceIfTokenEquals(T, ","))
|
||||
{
|
||||
Result.y = ReadFloat(T);
|
||||
if (AdvanceIfTokenEquals(T, ","))
|
||||
{
|
||||
Result.z = ReadFloat(T);
|
||||
|
||||
if (AdvanceIfTokenEquals(T, ")"))
|
||||
{
|
||||
if (!ReadFieldEnd(T))
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
ReadStructOpening(assembly_field Field, assembly_tokenizer* T)
|
||||
{
|
||||
bool Result = false;
|
||||
if (ReadFieldIdentifier(Field, T))
|
||||
{
|
||||
if (AdvanceIfTokenEquals(T, "{"))
|
||||
{
|
||||
Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
ParseLEDStrip (led_strip_definition* Strip, tokenizer* T, memory_arena* Arena)
|
||||
internal bool
|
||||
ReadStructClosing(assembly_tokenizer* T)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
if (ParseTokenEquals(T, LED_STRIP_IDENTIFIER) &&
|
||||
ParseOpenCurlyBrace(T))
|
||||
{
|
||||
Result = true;
|
||||
|
||||
u32 ControlBoxIndex, StartUniverse, StartChannel;
|
||||
ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->ControlBoxID), "Control Box Error");
|
||||
ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->StartUniverse), "Start Universe Error");
|
||||
ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->StartChannel), "Start Channel Error");
|
||||
|
||||
if (ParseTokenEquals(T, INTERPOLATE_POINTS_IDENTIFIER) &&
|
||||
ParseComma(T))
|
||||
{
|
||||
Strip->InterpolationType = StripInterpolate_Points;
|
||||
|
||||
ParseLEDStripToken(T, ParseVector(T, &Strip->InterpolatePositionStart), "Position Start Error");
|
||||
ParseLEDStripToken(T, ParseVector(T, &Strip->InterpolatePositionEnd), "Position End Error");
|
||||
}
|
||||
|
||||
ParseLEDStripToken(T, ParseUnsignedInteger(T, &Strip->LEDsPerStrip), "LEDs Per Strip Error");
|
||||
|
||||
EatWhitespace(T);
|
||||
if (!ParseCloseCurlyBrace(T))
|
||||
{
|
||||
Result = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Result = AdvanceIfTokenEquals(T, "};");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal assembly_definition
|
||||
ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena, event_log* EventLog)
|
||||
internal void
|
||||
ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
|
||||
{
|
||||
assembly_definition Assembly = {};
|
||||
Assert(Assembly->Arena.Alloc != 0);
|
||||
Assembly->LedCountTotal = 0;
|
||||
|
||||
tokenizer Tokenizer = {};
|
||||
Tokenizer.At = (char*)FileBase;
|
||||
Tokenizer.Memory = (char*)FileBase;
|
||||
Tokenizer.MemoryLength = FileSize;
|
||||
assembly_tokenizer Tokenizer = {};
|
||||
Tokenizer.Text = FileText;
|
||||
Tokenizer.At = Tokenizer.Text.Memory;
|
||||
|
||||
if (ParseLEDStripCount(&Tokenizer, &Assembly.LEDStripSize))
|
||||
{
|
||||
Assembly.LEDStrips = PushArray(Arena, led_strip_definition, Assembly.LEDStripSize);
|
||||
Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena);
|
||||
Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer);
|
||||
|
||||
while (AtValidPosition(Tokenizer))
|
||||
{
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assembly->StripCount = ReadIntField(AssemblyField_LedStripCount, &Tokenizer);
|
||||
Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount);
|
||||
|
||||
if (Assembly.LEDStripCount < Assembly.LEDStripSize)
|
||||
for (u32 i = 0; i < Assembly->StripCount; i++)
|
||||
{
|
||||
led_strip_definition* LEDStrip = Assembly.LEDStrips + Assembly.LEDStripCount++;
|
||||
v2_strip* StripAt = Assembly->Strips + i;
|
||||
if (ReadStructOpening(AssemblyField_LedStrip, &Tokenizer))
|
||||
{
|
||||
StripAt->ControlBoxID = ReadIntField(AssemblyField_ControlBoxId, &Tokenizer);
|
||||
StripAt->StartUniverse = ReadIntField(AssemblyField_StartUniverse, &Tokenizer);
|
||||
StripAt->StartChannel = ReadIntField(AssemblyField_StartChannel, &Tokenizer);
|
||||
|
||||
if (ParseLEDStrip(LEDStrip, &Tokenizer, Arena))
|
||||
// TODO(Peter): Need to store this
|
||||
string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena);
|
||||
// TODO(Peter): Switch on value of PointPlacementType
|
||||
if (ReadStructOpening(AssemblyField_InterpolatePoints, &Tokenizer))
|
||||
{
|
||||
Assembly.TotalLEDCount += LEDStrip->LEDsPerStrip;
|
||||
}
|
||||
else
|
||||
StripAt->StartPosition = ReadV3Field(AssemblyField_Start, &Tokenizer);
|
||||
StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer);
|
||||
if (!ReadStructClosing(&Tokenizer))
|
||||
{
|
||||
LogError(EventLog, "Unable to parse LED strip in assembly file");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ParseTokenEquals(&Tokenizer, END_ASSEMBLY_FILE_IDENTIFIER))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError(EventLog, "Did not find ent of file identifier in assembly file");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): :ErrorLoggong
|
||||
// TODO(Peter): Error
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
|
||||
return Assembly;
|
||||
StripAt->LedCount = ReadIntField(AssemblyField_LedCount, &Tokenizer);
|
||||
Assembly->LedCountTotal += StripAt->LedCount;
|
||||
|
||||
StripAt->TagsCount = ReadIntField(AssemblyField_TagsCount, &Tokenizer);
|
||||
StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount);
|
||||
for (u32 Tag = 0; Tag < StripAt->TagsCount; Tag++)
|
||||
{
|
||||
v2_tag* TagAt = StripAt->Tags + Tag;
|
||||
if (ReadStructOpening(AssemblyField_Tag, &Tokenizer))
|
||||
{
|
||||
// TODO(Peter): Need to store the string somewhere we can look it up for display in the interface
|
||||
// right now they are stored in temp memory and won't persist
|
||||
string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient);
|
||||
string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient);
|
||||
TagAt->NameHash = HashString(TagName);
|
||||
TagAt->ValueHash = HashString(TagValue);
|
||||
if (!ReadStructClosing(&Tokenizer))
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReadStructClosing(&Tokenizer))
|
||||
{
|
||||
// TODO(Peter): Error
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ASSEMBLY_PARSER_CPP
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
//
|
||||
// File: assembly_parser.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef ASSEMBLY_PARSER_H
|
||||
|
||||
#define LED_STRIP_COUNT_IDENTIFIER "led_strip_count"
|
||||
|
||||
#define LED_STRIP_IDENTIFIER "led_strip"
|
||||
|
||||
#define INTERPOLATE_POINTS_IDENTIFIER "INTERPOLATE_POINTS"
|
||||
|
||||
#define END_ASSEMBLY_FILE_IDENTIFIER "END_OF_ASSEMBLY_FILE"
|
||||
|
||||
enum assembly_token_type
|
||||
{
|
||||
AssemblyToken_Colon,
|
||||
AssemblyToken_SemiColon,
|
||||
AssemblyToken_LeftCurlyBrace,
|
||||
AssemblyToken_RightCurlyBrace,
|
||||
AssemblyToken_Comma,
|
||||
|
||||
AssemblyToken_Number,
|
||||
AssemblyToken_String,
|
||||
AssemblyToken_Vector,
|
||||
|
||||
AssemblyToken_LEDStrip,
|
||||
|
||||
AssemblyToken_Identifier,
|
||||
|
||||
AssemblyToken_EndOfFile
|
||||
};
|
||||
|
||||
struct assembly_token
|
||||
{
|
||||
char* Token;
|
||||
s32 Length;
|
||||
assembly_token_type Type;
|
||||
};
|
||||
|
||||
enum strip_interpolation_type
|
||||
{
|
||||
StripInterpolate_Boxes,
|
||||
StripInterpolate_Points,
|
||||
};
|
||||
|
||||
struct led_strip_definition
|
||||
{
|
||||
u32 ControlBoxID;
|
||||
u32 StartUniverse;
|
||||
u32 StartChannel;
|
||||
|
||||
strip_interpolation_type InterpolationType;
|
||||
// Interpolate Boxes
|
||||
u32 StartBoxIndex;
|
||||
u32 EndBoxIndex;
|
||||
|
||||
// Interpolate Positions
|
||||
v3 InterpolatePositionStart;
|
||||
v3 InterpolatePositionEnd;
|
||||
|
||||
// Universal Interpolation
|
||||
u32 LEDsPerStrip;
|
||||
};
|
||||
|
||||
struct assembly_definition
|
||||
{
|
||||
u32 LEDStripSize;
|
||||
u32 LEDStripCount;
|
||||
u32 TotalLEDCount;
|
||||
led_strip_definition* LEDStrips;
|
||||
};
|
||||
|
||||
#define ASSEMBLY_PARSER_H
|
||||
#endif // ASSEMBLY_PARSER_H
|
|
@ -176,7 +176,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Camera.LookAt = v3{0, 0, 0};
|
||||
|
||||
#if 1
|
||||
string SculpturePath = MakeStringLiteral("data/blumen_lumen.fold");
|
||||
string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold");
|
||||
LoadAssembly(State, Context, SculpturePath);
|
||||
#endif
|
||||
|
||||
|
@ -208,7 +208,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
|
||||
InitializePanelSystem(&State->PanelSystem);
|
||||
panel* Panel = TakeNewPanel(&State->PanelSystem);
|
||||
SetPanelDefinition(Panel, PanelType_SculptureView, State);
|
||||
SplitPanelVertically(Panel, .5f, &State->PanelSystem);
|
||||
SetPanelDefinition(&Panel->Left->Panel, PanelType_ProfilerView, State);
|
||||
SetPanelDefinition(&Panel->Right->Panel, PanelType_SculptureView, State);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -462,6 +464,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
|
||||
s32 HeaderSize = State->NetworkProtocolHeaderSize;
|
||||
dmx_buffer_list* DMXBuffers = 0;
|
||||
// TODO(Peter): Come back and re add this in. It was tanking frame rate after
|
||||
// updates to the assembly file format
|
||||
#if 0
|
||||
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
||||
{
|
||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
||||
|
@ -469,6 +474,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient);
|
||||
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
|
||||
}
|
||||
#endif
|
||||
|
||||
//DEBUG_IF(GlobalDebugServices->Interface.SendSACNData)
|
||||
{
|
||||
|
|
|
@ -18,17 +18,13 @@
|
|||
#include "sacn/sacn.h"
|
||||
|
||||
#include "foldhaus_assembly.h"
|
||||
#include "assembly_parser.cpp"
|
||||
|
||||
#include "assembly_parser.h"
|
||||
|
||||
#include "foldhaus_node.h"
|
||||
|
||||
// TODO(Peter): TEMPORARY
|
||||
//u32 NodeSpecificationsCount = 0;
|
||||
//node_specification* NodeSpecifications = 0;
|
||||
typedef struct app_state app_state;
|
||||
|
||||
|
||||
#include "assembly_parser.cpp"
|
||||
#include "test_patterns.h"
|
||||
|
||||
// TODO(Peter): something we can do later is to remove all reliance on app_state and context
|
||||
|
@ -36,8 +32,6 @@
|
|||
// perform operations on, like panel_draw_requests = { bounds, panel* } etc.
|
||||
#include "foldhaus_panel.h"
|
||||
|
||||
typedef struct app_state app_state;
|
||||
|
||||
#include "foldhaus_command_dispatch.h"
|
||||
#include "foldhaus_operation_mode.h"
|
||||
|
||||
|
@ -55,6 +49,13 @@ enum network_protocol
|
|||
NetworkProtocol_Count,
|
||||
};
|
||||
|
||||
struct led_buffer
|
||||
{
|
||||
led* Leds;
|
||||
pixel* Colors;
|
||||
led_buffer* Next;
|
||||
};
|
||||
|
||||
struct app_state
|
||||
{
|
||||
rect WindowBounds;
|
||||
|
|
|
@ -5,60 +5,40 @@
|
|||
//
|
||||
#ifndef FOLDHAUS_ASSEMBLY_CPP
|
||||
|
||||
internal assembly
|
||||
ConstructAssemblyFromDefinition (assembly_definition Definition,
|
||||
string AssemblyName,
|
||||
v4 RootPosition,
|
||||
r32 Scale,
|
||||
memory_arena Arena)
|
||||
internal void
|
||||
ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition)
|
||||
{
|
||||
assembly Assembly = {};
|
||||
Assembly.Arena = Arena;
|
||||
|
||||
Assembly.Name = MakeString(PushArray(&Assembly.Arena, char, AssemblyName.Length), AssemblyName.Length);
|
||||
CopyStringTo(AssemblyName, &Assembly.Name);
|
||||
|
||||
// NOTE(Peter): Setting this to zero so we can check at the end of the loop that creates leds
|
||||
// and make sure we created to correct number. By the time this function returns it should be
|
||||
// the case that: (Assembly.LEDCount == Definition.TotalLEDCount)
|
||||
Assembly.LEDBuffer.LEDCount = 0;
|
||||
Assembly.LEDBuffer.Colors = PushArray(&Assembly.Arena, pixel, Definition.TotalLEDCount);
|
||||
Assembly.LEDBuffer.LEDs = PushArray(&Assembly.Arena, led, Definition.TotalLEDCount);
|
||||
Assembly.LEDUniverseMapCount = Definition.LEDStripCount;
|
||||
Assembly.LEDUniverseMap = PushArray(&Assembly.Arena, leds_in_universe_range, Definition.LEDStripCount);
|
||||
Assembly->LEDBuffer.LEDCount = 0;
|
||||
Assembly->LEDBuffer.Colors = PushArray(&Assembly->Arena, pixel, Assembly->LedCountTotal);
|
||||
Assembly->LEDBuffer.LEDs = PushArray(&Assembly->Arena, led, Assembly->LedCountTotal);
|
||||
Assembly->LEDUniverseMapCount = Assembly->LedCountTotal;
|
||||
Assembly->LEDUniverseMap = PushArray(&Assembly->Arena, leds_in_universe_range, Assembly->LedCountTotal);
|
||||
|
||||
// Add LEDs
|
||||
for (u32 StripIdx = 0; StripIdx < Definition.LEDStripCount; StripIdx++)
|
||||
for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++)
|
||||
{
|
||||
led_strip_definition StripDef = Definition.LEDStrips[StripIdx];
|
||||
//led_strip_definition StripDef = Definition.LEDStrips[StripIdx];
|
||||
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
||||
|
||||
leds_in_universe_range* LEDUniverseRange = Assembly.LEDUniverseMap + StripIdx;
|
||||
LEDUniverseRange->Universe = StripDef.StartUniverse;
|
||||
LEDUniverseRange->RangeStart = Assembly.LEDBuffer.LEDCount;
|
||||
LEDUniverseRange->RangeOnePastLast = Assembly.LEDBuffer.LEDCount + StripDef.LEDsPerStrip;
|
||||
leds_in_universe_range* LEDUniverseRange = &Assembly->LEDUniverseMap[StripIdx];
|
||||
|
||||
// NOTE(Peter): this should be a switch on the type, but we only have one for
|
||||
// now. The assert is to remind you to create more cases when necessary
|
||||
Assert(StripDef.InterpolationType == StripInterpolate_Points);
|
||||
LEDUniverseRange->Universe = StripAt->StartUniverse;
|
||||
LEDUniverseRange->RangeStart = Assembly->LEDBuffer.LEDCount;
|
||||
LEDUniverseRange->RangeOnePastLast = Assembly->LEDBuffer.LEDCount + StripAt->LedCount;
|
||||
|
||||
v4 WS_StripStart = RootPosition + V4(StripDef.InterpolatePositionStart * Scale, 1);
|
||||
v4 WS_StripEnd = RootPosition + V4(StripDef.InterpolatePositionEnd * Scale, 1);
|
||||
s32 LEDsInStripCount = StripDef.LEDsPerStrip;
|
||||
|
||||
Assert(Assembly.LEDBuffer.LEDCount + LEDsInStripCount <= Definition.TotalLEDCount);
|
||||
v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1);
|
||||
v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1);
|
||||
s32 LEDsInStripCount = StripAt->LedCount;
|
||||
|
||||
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount;
|
||||
for (s32 Step = 0; Step < LEDsInStripCount; Step++)
|
||||
{
|
||||
s32 LEDIndex = Assembly.LEDBuffer.LEDCount++;
|
||||
Assembly.LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
|
||||
Assembly.LEDBuffer.LEDs[LEDIndex].Index = LEDIndex;
|
||||
s32 LEDIndex = Assembly->LEDBuffer.LEDCount;
|
||||
Assembly->LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
|
||||
Assembly->LEDBuffer.LEDs[LEDIndex].Index = LEDIndex;
|
||||
Assembly->LEDBuffer.LEDCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(Peter): Did we create the correct number of LEDs?
|
||||
Assert(Assembly.LEDBuffer.LEDCount == Definition.TotalLEDCount);
|
||||
return Assembly;
|
||||
}
|
||||
|
||||
// NOTE(Peter): These are here so that if we load 2+ sculptures, they don't all
|
||||
|
@ -73,18 +53,18 @@ LoadAssembly (app_state* State, context Context, string Path)
|
|||
platform_memory_result AssemblyFile = ReadEntireFile(Context, Path);
|
||||
if (AssemblyFile.Error == PlatformMemory_NoError)
|
||||
{
|
||||
assembly_definition AssemblyDefinition = ParseAssemblyFile(AssemblyFile.Base, AssemblyFile.Size, &State->Transient, State->GlobalLog);
|
||||
string AssemblyFileText = MakeString((char*)AssemblyFile.Base);
|
||||
|
||||
s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\');
|
||||
string FileName = Substring(Path, IndexOfLastSlash + 1);
|
||||
|
||||
memory_arena AssemblyArena = {};
|
||||
AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
assembly NewAssembly = {};
|
||||
NewAssembly.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
NewAssembly.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
ParseAssemblyFile(&NewAssembly, AssemblyFileText, &State->Transient);
|
||||
|
||||
v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount];
|
||||
r32 Scale = 100;
|
||||
assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, Offset, Scale, AssemblyArena);
|
||||
ConstructAssemblyFromDefinition(&NewAssembly, FileName, Offset);
|
||||
gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly);
|
||||
|
||||
State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
|
||||
|
|
|
@ -40,6 +40,30 @@ struct assembly_led_buffer
|
|||
led* LEDs;
|
||||
};
|
||||
|
||||
struct v2_tag
|
||||
{
|
||||
u64 NameHash;
|
||||
u64 ValueHash;
|
||||
};
|
||||
|
||||
struct v2_strip
|
||||
{
|
||||
s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore
|
||||
s32 StartUniverse;
|
||||
s32 StartChannel;
|
||||
|
||||
// TODO(Peter): When we create more ways to calculate points, this needs to become
|
||||
// a type enum and a union
|
||||
v3 StartPosition;
|
||||
v3 EndPosition;
|
||||
|
||||
u32 LedCount;
|
||||
u32* LedLUT;
|
||||
|
||||
u32 TagsCount;
|
||||
v2_tag* Tags;
|
||||
};
|
||||
|
||||
struct assembly
|
||||
{
|
||||
memory_arena Arena;
|
||||
|
@ -47,13 +71,13 @@ struct assembly
|
|||
string Name;
|
||||
string FilePath;
|
||||
|
||||
assembly_led_buffer LEDBuffer;
|
||||
r32 Scale;
|
||||
|
||||
#if 0
|
||||
u32 LEDCount;
|
||||
pixel* Colors;
|
||||
led* LEDs;
|
||||
#endif
|
||||
u32 StripCount;
|
||||
v2_strip* Strips;
|
||||
|
||||
s32 LedCountTotal;
|
||||
assembly_led_buffer LEDBuffer;
|
||||
|
||||
u32 LEDUniverseMapCount;
|
||||
leds_in_universe_range* LEDUniverseMap;
|
||||
|
|
|
@ -242,12 +242,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation)
|
|||
if (XDistance > YDistance)
|
||||
{
|
||||
r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / gs_Width(PanelBounds);
|
||||
SplitPanelVertically(Panel, XPercent, PanelBounds, &State->PanelSystem);
|
||||
SplitPanelVertically(Panel, XPercent, &State->PanelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / gs_Height(PanelBounds);
|
||||
SplitPanelHorizontally(Panel, YPercent, PanelBounds, &State->PanelSystem);
|
||||
SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem);
|
||||
}
|
||||
|
||||
Panel->Left->Panel.PanelDefinitionIndex = Panel->PanelDefinitionIndex;
|
||||
|
|
|
@ -154,10 +154,9 @@ FreePanelAtIndex(s32 Index, panel_system* PanelSystem)
|
|||
}
|
||||
|
||||
internal void
|
||||
SplitPanelVertically(panel* Parent, r32 Percent, rect ParentBounds, panel_system* PanelSystem)
|
||||
SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem)
|
||||
{
|
||||
r32 SplitX = GSLerp(ParentBounds.Min.x, ParentBounds.Max.x, Percent);
|
||||
if (SplitX > ParentBounds.Min.x && SplitX < ParentBounds.Max.x)
|
||||
if (Percent >= 0.0f && Percent <= 1.0f)
|
||||
{
|
||||
Parent->SplitDirection = PanelSplit_Vertical;
|
||||
Parent->SplitPercent = Percent;
|
||||
|
@ -171,10 +170,9 @@ SplitPanelVertically(panel* Parent, r32 Percent, rect ParentBounds, panel_system
|
|||
}
|
||||
|
||||
internal void
|
||||
SplitPanelHorizontally(panel* Parent, r32 Percent, rect ParentBounds, panel_system* PanelSystem)
|
||||
SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem)
|
||||
{
|
||||
r32 SplitY = GSLerp(ParentBounds.Min.y, ParentBounds.Max.y, Percent);
|
||||
if (SplitY > ParentBounds.Min.y && SplitY < ParentBounds.Max.y)
|
||||
if (Percent >= 0.0f && Percent <= 1.0f)
|
||||
{
|
||||
Parent->SplitDirection = PanelSplit_Horizontal;
|
||||
Parent->SplitPercent = Percent;
|
||||
|
|
Loading…
Reference in New Issue