diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 3c2140b..016ff00 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -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) { diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index 8da6b92..840f314 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -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 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 diff --git a/src/app/engine/animation/foldhaus_animation_parser.cpp b/src/app/engine/animation/foldhaus_animation_parser.cpp new file mode 100644 index 0000000..16233e6 --- /dev/null +++ b/src/app/engine/animation/foldhaus_animation_parser.cpp @@ -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 \ No newline at end of file diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp index 481b248..d66f3ee 100644 --- a/src/app/engine/animation/foldhaus_animation_serializer.cpp +++ b/src/app/engine/animation/foldhaus_animation_serializer.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* 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 \ No newline at end of file diff --git a/src/app/engine/foldhaus_parser.h b/src/app/engine/foldhaus_parser.h new file mode 100644 index 0000000..709f375 --- /dev/null +++ b/src/app/engine/foldhaus_parser.h @@ -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 \ No newline at end of file diff --git a/src/app/engine/foldhaus_serializer.h b/src/app/engine/foldhaus_serializer.h new file mode 100644 index 0000000..b82ee62 --- /dev/null +++ b/src/app/engine/foldhaus_serializer.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 \ No newline at end of file diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index e2b4756..7dd6042 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -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); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 51938b4..1675b20 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -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"