Wrote a file serializer and parser for animations
This commit is contained in:
parent
b816474dd5
commit
1940483620
|
@ -577,20 +577,6 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta
|
|||
return Result;
|
||||
}
|
||||
|
||||
struct animation_clip
|
||||
{
|
||||
char* Name;
|
||||
s32 NameLength;
|
||||
animation_proc* Proc;
|
||||
};
|
||||
|
||||
s32 GlobalAnimationClipsCount = 3;
|
||||
animation_clip GlobalAnimationClips[] = {
|
||||
{ "Test Pattern One", 16, TestPatternOne },
|
||||
{ "Test Pattern Two", 16, TestPatternTwo },
|
||||
{ "Test Pattern Three", 18, TestPatternThree },
|
||||
};
|
||||
|
||||
internal void
|
||||
DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,13 @@ enum blend_mode
|
|||
BlendMode_Count,
|
||||
};
|
||||
|
||||
global gs_const_string BlendModeStrings[] = {
|
||||
ConstString("Overwrite"),
|
||||
ConstString("Add"),
|
||||
ConstString("Multiply"),
|
||||
ConstString("Count"),
|
||||
};
|
||||
|
||||
struct anim_layer
|
||||
{
|
||||
gs_string Name;
|
||||
|
@ -44,6 +51,8 @@ struct anim_layer_array
|
|||
|
||||
struct animation
|
||||
{
|
||||
gs_string Name;
|
||||
|
||||
anim_layer_array Layers;
|
||||
gs_list<animation_block> Blocks;
|
||||
|
||||
|
@ -87,6 +96,67 @@ struct animation_system
|
|||
|
||||
};
|
||||
|
||||
// TODO(pjs): Better name - something like animation_prototype
|
||||
struct animation_clip
|
||||
{
|
||||
char* Name;
|
||||
s32 NameLength;
|
||||
animation_proc* Proc;
|
||||
};
|
||||
|
||||
// Serialization
|
||||
|
||||
enum animation_field
|
||||
{
|
||||
AnimField_FileIdent,
|
||||
AnimField_AnimName,
|
||||
AnimField_LayersCount,
|
||||
AnimField_BlocksCount,
|
||||
|
||||
AnimField_PlayableRange,
|
||||
AnimField_PlayableRangeMin,
|
||||
AnimField_PlayableRangeMax,
|
||||
|
||||
AnimField_LayersArray,
|
||||
AnimField_Layer,
|
||||
AnimField_LayerName,
|
||||
AnimField_LayerBlendMode,
|
||||
|
||||
AnimField_BlocksArray,
|
||||
AnimField_Block,
|
||||
AnimField_BlockFrameRange,
|
||||
AnimField_BlockFrameRangeMin,
|
||||
AnimField_BlockFrameRangeMax,
|
||||
AnimField_BlockLayerIndex,
|
||||
AnimField_BlockAnimName,
|
||||
|
||||
AnimField_Count,
|
||||
};
|
||||
|
||||
global gs_const_string AnimationFieldStrings[] = {
|
||||
ConstString("lumenarium_animation_file"), // AnimField_FileIdent
|
||||
ConstString("animation_name"),// AnimField_AnimName
|
||||
ConstString("layers_count"),// AnimField_LayersCount
|
||||
ConstString("blocks_count"),// AnimField_BlocksCount
|
||||
|
||||
ConstString("playable_range"),// AnimField_PlayableRange
|
||||
ConstString("min"),// AnimField_PlayableRangeMin
|
||||
ConstString("max"),// AnimField_PlayableRangeMax
|
||||
|
||||
ConstString("layers"),// AnimField_LayersArray
|
||||
ConstString("layer"),// AnimField_Layer
|
||||
ConstString("name"),// AnimField_LayerName
|
||||
ConstString("blend"),// AnimField_LayerBlendMode
|
||||
|
||||
ConstString("blocks"),// AnimField_BlocksArray
|
||||
ConstString("block"),// AnimField_Block
|
||||
ConstString("frame_range"),// AnimField_BlockFrameRange
|
||||
ConstString("min"),// AnimField_BlockFrameRangeMin
|
||||
ConstString("max"),// AnimField_BlockFrameRangeMax
|
||||
ConstString("layer_index"),// AnimField_BlockLayerIndex
|
||||
ConstString("animation_name"),// AnimField_BlockAnimName
|
||||
};
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Anim Layers Array
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
//
|
||||
// File: foldhaus_animation_parser.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-09
|
||||
//
|
||||
#ifndef FOLDHAUS_ANIMATION_PARSER_CPP
|
||||
|
||||
|
||||
#define FOLDHAUS_ANIMATION_PARSER_CPP
|
||||
#endif // FOLDHAUS_ANIMATION_PARSER_CPP
|
|
@ -5,6 +5,185 @@
|
|||
//
|
||||
#ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
||||
|
||||
internal gs_string
|
||||
AnimSerializer_Serialize(animation Anim, animation_clip* GlobalClips, gs_memory_arena* Arena)
|
||||
{
|
||||
serializer Serializer = {0};
|
||||
Serializer.String = PushString(Arena, 4096);
|
||||
Serializer.Identifiers = AnimationFieldStrings;
|
||||
Serializer.IdentifiersCount = AnimField_Count;
|
||||
|
||||
Serializer_WriteF(&Serializer, "%S;\n", AnimationFieldStrings[AnimField_FileIdent]);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_AnimName, Anim.Name.ConstString);
|
||||
Serializer_WriteValue(&Serializer, AnimField_LayersCount, Anim.Layers.Count);
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlocksCount, Anim.Blocks.Used);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_PlayableRange);
|
||||
{
|
||||
Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMin, (u32)Anim.PlayableRange.Min);
|
||||
Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMax, (u32)Anim.PlayableRange.Max);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_LayersArray);
|
||||
for (u32 i = 0; i < Anim.Layers.Count; i++)
|
||||
{
|
||||
anim_layer LayerAt = Anim.Layers.Values[i];
|
||||
Serializer_OpenStruct(&Serializer, AnimField_Layer);
|
||||
{
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_LayerName, LayerAt.Name.ConstString);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_LayerBlendMode, BlendModeStrings[LayerAt.BlendMode]);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_BlocksArray);
|
||||
for (u32 i = 0; i < Anim.Blocks.Used; i++)
|
||||
{
|
||||
gs_list_entry<animation_block>* AnimationBlockEntry = Anim.Blocks.GetEntryAtIndex(i);
|
||||
if (EntryIsFree(AnimationBlockEntry)) { continue; }
|
||||
gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle;
|
||||
animation_block AnimationBlockAt = AnimationBlockEntry->Value;
|
||||
|
||||
// TODO(pjs): Systematize the AnimationProcHandle
|
||||
// :AnimProcHandle
|
||||
u32 AnimationProcIndex = AnimationBlockAt.AnimationProcHandle - 1;
|
||||
animation_clip Animation = GlobalClips[AnimationProcIndex];
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_Block);
|
||||
{
|
||||
Serializer_OpenStruct(&Serializer, AnimField_BlockFrameRange);
|
||||
{
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMin, (u32)AnimationBlockAt.Range.Min);
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMax, (u32)AnimationBlockAt.Range.Max);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockLayerIndex, AnimationBlockAt.Layer);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_BlockAnimName, ConstString(Animation.Name));
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
return Serializer.String;
|
||||
}
|
||||
|
||||
internal animation
|
||||
AnimParser_Parse(gs_string File, animation_clip* GlobalClips, gs_memory_arena* Arena, u32 AnimClipsCount, animation_clip* AnimClips)
|
||||
{
|
||||
animation Result = {0};
|
||||
|
||||
parser Parser = {0};
|
||||
Parser.String = File;
|
||||
Parser.At = Parser.String.Str;
|
||||
Parser.Identifiers = AnimationFieldStrings;
|
||||
Parser.IdentifiersCount = AnimField_Count;
|
||||
Parser.Arena = Arena;
|
||||
|
||||
if (Parser_ReadString(&Parser, AnimationFieldStrings[AnimField_FileIdent]))
|
||||
{
|
||||
Result.Name = Parser_ReadStringValue(&Parser, AnimField_AnimName);
|
||||
|
||||
Result.Layers.CountMax = Parser_ReadU32Value(&Parser, AnimField_LayersCount);
|
||||
Result.Layers.Values = PushArray(Arena, anim_layer, Result.Layers.CountMax);
|
||||
|
||||
// TODO(pjs): We're not using this now because Blocks are built on gs_list or something,
|
||||
// but I want to replace that eventually, so this is here to preallocate the blocks we need
|
||||
u32 BlocksCount = Parser_ReadU32Value(&Parser, AnimField_BlocksCount);
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_PlayableRange))
|
||||
{
|
||||
Result.PlayableRange.Min = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMin);
|
||||
Result.PlayableRange.Max = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_LayersArray))
|
||||
{
|
||||
while (!Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
anim_layer Layer = {0};
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_Layer))
|
||||
{
|
||||
Layer.Name = Parser_ReadStringValue(&Parser, AnimField_LayerName);
|
||||
|
||||
gs_string BlendModeName = Parser_ReadStringValue(&Parser, AnimField_LayerBlendMode);
|
||||
for (u32 i = 0; i < BlendMode_Count; i++)
|
||||
{
|
||||
if (StringsEqual(BlendModeName.ConstString, BlendModeStrings[i]))
|
||||
{
|
||||
Layer.BlendMode = (blend_mode)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
Animation_AddLayer(&Result, Layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_BlocksArray))
|
||||
{
|
||||
while(!Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
animation_block Block = {0};
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_Block))
|
||||
{
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_BlockFrameRange))
|
||||
{
|
||||
Block.Range.Min = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMin);
|
||||
Block.Range.Max = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMax);
|
||||
|
||||
Parser_ReadCloseStruct(&Parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
|
||||
Block.Layer = Parser_ReadU32Value(&Parser, AnimField_BlockLayerIndex);
|
||||
|
||||
// TODO(pjs): AnimName -> Animation Proc Handle
|
||||
gs_string AnimName = Parser_ReadStringValue(&Parser, AnimField_BlockAnimName);
|
||||
Block.AnimationProcHandle = 0;
|
||||
for (u32 i = 0; i < AnimClipsCount; i++)
|
||||
{
|
||||
if (StringEqualsCharArray(AnimName.ConstString, AnimClips[i].Name, CStringLength(AnimClips[i].Name)))
|
||||
{
|
||||
Block.AnimationProcHandle = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
Result.Blocks.PushElementOnList(Block);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
||||
#endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// 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
|
|
@ -0,0 +1,384 @@
|
|||
//
|
||||
// File: foldhaus_serializer.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-09
|
||||
//
|
||||
#ifndef FOLDHAUS_SERIALIZER_H
|
||||
|
||||
struct serializer
|
||||
{
|
||||
gs_string String;
|
||||
u32 Indent;
|
||||
gs_const_string* Identifiers;
|
||||
u32 IdentifiersCount;
|
||||
};
|
||||
|
||||
internal gs_const_string
|
||||
Serializer_GetIdent(serializer* Serializer, u32 Index)
|
||||
{
|
||||
gs_const_string Result = Serializer->Identifiers[Index];
|
||||
return Result;
|
||||
}
|
||||
|
||||
// Serializing
|
||||
|
||||
internal void
|
||||
Serializer_WriteIndent(serializer* Serializer)
|
||||
{
|
||||
for (u32 i = 0; i < Serializer->Indent; i++)
|
||||
{
|
||||
AppendPrintF(&Serializer->String, " ");
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteF(serializer* Serializer, char* Format, ...)
|
||||
{
|
||||
Serializer_WriteIndent(Serializer);
|
||||
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
PrintFArgsList(&Serializer->String, Format, Args);
|
||||
va_end(Args);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_OpenStruct(serializer* Serializer, gs_const_string StructName)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S:{\n", StructName);
|
||||
Serializer->Indent++;
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_OpenStruct(serializer* Serializer, u32 StructIdentifier)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, StructIdentifier);
|
||||
Serializer_WriteF(Serializer, "%S:{\n", Ident);
|
||||
Serializer->Indent++;
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_CloseStruct(serializer* Serializer)
|
||||
{
|
||||
Serializer->Indent--;
|
||||
Serializer_WriteF(Serializer, "};\n");
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S: %S;\n", Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||||
Serializer_WriteValue(Serializer, Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, u32 Value)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S: %d;\n", Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, u32 Value)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||||
Serializer_WriteValue(Serializer, Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, r32 Value)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S: %f;\n", Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, r32 Value)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||||
Serializer_WriteValue(Serializer, Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteStringValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S: \"%S\";\n", Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteStringValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||||
Serializer_WriteStringValue(Serializer, Ident, Value);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteV3Value(serializer* Serializer, gs_const_string Ident, v3 Value)
|
||||
{
|
||||
Serializer_WriteF(Serializer, "%S: (%f, %f, %f);\n", Ident, Value.x, Value.y, Value.z);
|
||||
}
|
||||
|
||||
internal void
|
||||
Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value)
|
||||
{
|
||||
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||||
Serializer_WriteV3Value(Serializer, Ident, Value);
|
||||
}
|
||||
|
||||
// Parsing
|
||||
|
||||
struct parser
|
||||
{
|
||||
gs_string String;
|
||||
|
||||
gs_const_string* Identifiers;
|
||||
u32 IdentifiersCount;
|
||||
|
||||
u32 Line;
|
||||
|
||||
char* LineStart;
|
||||
char* At;
|
||||
|
||||
gs_memory_arena* Arena;
|
||||
};
|
||||
|
||||
internal gs_const_string
|
||||
Parser_GetIdent(parser Parser, u32 Index)
|
||||
{
|
||||
gs_const_string Result = Parser.Identifiers[Index];
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_AtValidPosition(parser Parser)
|
||||
{
|
||||
u64 Offset = Parser.At - Parser.String.Str;
|
||||
bool Result = (Offset < Parser.String.Length);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Parser_AdvanceChar(parser* P)
|
||||
{
|
||||
if (IsNewline(P->At[0]))
|
||||
{
|
||||
P->Line += 1;
|
||||
P->LineStart = P->At + 1;
|
||||
}
|
||||
P->At++;
|
||||
}
|
||||
|
||||
internal void
|
||||
Parser_EatWhitespace(parser* P)
|
||||
{
|
||||
while(Parser_AtValidPosition(*P) && IsNewlineOrWhitespace(P->At[0]))
|
||||
{
|
||||
Parser_AdvanceChar(P);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
Parser_EatToNewLine(parser* P)
|
||||
{
|
||||
while(Parser_AtValidPosition(*P) && !IsNewline(P->At[0]))
|
||||
{
|
||||
Parser_AdvanceChar(P);
|
||||
}
|
||||
Parser_EatWhitespace(P);
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_AdvanceIfTokenEquals(parser* P, gs_const_string Value)
|
||||
{
|
||||
bool Result = true;
|
||||
|
||||
char* PAt = P->At;
|
||||
char* VAt = Value.Str;
|
||||
while (*VAt != 0)
|
||||
{
|
||||
if (*PAt != *VAt)
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
PAt += 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)
|
||||
{
|
||||
P->At = PAt;
|
||||
Parser_EatWhitespace(P);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_AdvanceIfLineEnd(parser* P)
|
||||
{
|
||||
bool Result = Parser_AdvanceIfTokenEquals(P, ConstString(";"));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_ReadString(parser* P, gs_const_string String)
|
||||
{
|
||||
// string;
|
||||
bool Result = Parser_AdvanceIfTokenEquals(P, String);
|
||||
Result &= Parser_AdvanceIfLineEnd(P);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_ReadString(parser* P, u32 IdentIndex)
|
||||
{
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadString(P, Ident);
|
||||
}
|
||||
|
||||
internal gs_string
|
||||
Parser_ReadStringValue(parser* P, gs_const_string Ident)
|
||||
{
|
||||
// ident: "value";
|
||||
gs_string Result = {};
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString("\"")))
|
||||
{
|
||||
gs_const_string FileString = {0};
|
||||
FileString.Str = P->At;
|
||||
|
||||
while (Parser_AtValidPosition(*P) && P->At[0] != '"')
|
||||
{
|
||||
Parser_AdvanceChar(P);
|
||||
}
|
||||
|
||||
FileString.Length = P->At - FileString.Str;
|
||||
if (Parser_AdvanceIfTokenEquals(P, ConstString("\"")) &&
|
||||
Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result = PushStringF(P->Arena, FileString.Length, "%S", FileString);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal gs_string
|
||||
Parser_ReadStringValue(parser* P, u32 IdentIndex)
|
||||
{
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadStringValue(P, Ident);
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_ReadOpenStruct(parser* P, gs_const_string Ident)
|
||||
{
|
||||
// ident: {
|
||||
bool Result = Parser_AdvanceIfTokenEquals(P, Ident);
|
||||
Result &= Parser_AdvanceIfTokenEquals(P, ConstString(":"));
|
||||
Result &= Parser_AdvanceIfTokenEquals(P, ConstString("{"));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_ReadOpenStruct(parser* P, u32 IdentIndex)
|
||||
{
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadOpenStruct(P, Ident);
|
||||
}
|
||||
|
||||
internal bool
|
||||
Parser_ReadCloseStruct(parser* P)
|
||||
{
|
||||
// }
|
||||
bool Result = Parser_AdvanceIfTokenEquals(P, ConstString("}"));
|
||||
Result &= Parser_AdvanceIfLineEnd(P);
|
||||
return Result;
|
||||
}
|
||||
|
||||
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;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Parser_ReadU32Value(parser* P, gs_const_string Ident)
|
||||
{
|
||||
// ident: value;
|
||||
u32 Result = 0;
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||
{
|
||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||||
if (Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result = (u32)ParseInt(NumStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Parser_ReadU32Value(parser* P, u32 IdentIndex)
|
||||
{
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadU32Value(P, Ident);
|
||||
}
|
||||
|
||||
internal r32
|
||||
Parser_ReadR32Value(parser* P, gs_const_string Ident)
|
||||
{
|
||||
// ident: value;
|
||||
r32 Result = 0;
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||
{
|
||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||||
if (Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result = (r32)ParseFloat(NumStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Parser_ReadR32Value(parser* P, u32 IdentIndex)
|
||||
{
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadR32Value(P, Ident);
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_SERIALIZER_H
|
||||
#endif // FOLDHAUS_SERIALIZER_H
|
|
@ -144,6 +144,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
|
||||
|
||||
animation Anim = {0};
|
||||
Anim.Name = PushStringF(&State->Permanent, 256, "test_anim_one");
|
||||
Anim.Layers.CountMax = 8;
|
||||
Anim.Layers.Values = PushArray(State->AnimationSystem.Storage, anim_layer, Anim.Layers.CountMax);
|
||||
Anim.PlayableRange.Min = 0;
|
||||
|
@ -152,9 +153,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
Animation_AddLayer(&Anim, MakeString("Color Layer"), BlendMode_Multiply, &State->AnimationSystem);
|
||||
Animation_AddLayer(&Anim, MakeString("Sparkles"), BlendMode_Add, &State->AnimationSystem);
|
||||
|
||||
Animation_AddBlock(&Anim, 22, 123, 2, 1);
|
||||
|
||||
AnimationArray_Push(&State->AnimationSystem.Animations, Anim);
|
||||
|
||||
|
||||
} // End Animation Playground
|
||||
|
||||
|
||||
|
@ -280,6 +281,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
||||
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||
|
||||
// :AnimProcHandle
|
||||
u32 AnimationProcIndex = Block.AnimationProcHandle - 1;
|
||||
animation_proc* AnimationProc = GlobalAnimationClips[AnimationProcIndex].Proc;
|
||||
AnimationProc(&LayerLEDBuffers[Layer], *Assembly, SecondsIntoBlock, State->Transient);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "../meta/gs_meta_include.h"
|
||||
#include "../meta/gs_meta_lexer.h"
|
||||
|
||||
#include "engine/foldhaus_serializer.h"
|
||||
|
||||
#include "../gs_libs/gs_font.h"
|
||||
#include "foldhaus_log.h"
|
||||
|
||||
|
@ -32,6 +34,7 @@ typedef struct app_state app_state;
|
|||
#include "editor/foldhaus_operation_mode.h"
|
||||
|
||||
#include "engine/animation/foldhaus_animation.h"
|
||||
#include "engine/animation/foldhaus_animation_serializer.cpp"
|
||||
|
||||
struct app_state
|
||||
{
|
||||
|
@ -226,6 +229,13 @@ struct panel_definition
|
|||
s32 InputCommandsCount;
|
||||
};
|
||||
|
||||
s32 GlobalAnimationClipsCount = 3;
|
||||
animation_clip GlobalAnimationClips[] = {
|
||||
{ "Test Pattern One", 16, TestPatternOne },
|
||||
{ "Test Pattern Two", 16, TestPatternTwo },
|
||||
{ "Test Pattern Three", 18, TestPatternThree },
|
||||
};
|
||||
|
||||
#include "editor/panels/foldhaus_panel_sculpture_view.h"
|
||||
#include "editor/panels/foldhaus_panel_profiler.h"
|
||||
#include "editor/panels/foldhaus_panel_dmx_view.h"
|
||||
|
|
Loading…
Reference in New Issue