diff --git a/src/app/editor/foldhaus_editor.cpp b/src/app/editor/foldhaus_editor.cpp index d6abf2e..3764b25 100644 --- a/src/app/editor/foldhaus_editor.cpp +++ b/src/app/editor/foldhaus_editor.cpp @@ -149,8 +149,6 @@ Editor_Render(app_state* State, context* Context, render_command_buffer* RenderB } Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext); - ResetWorkQueue(Context->GeneralWorkQueue); - } diff --git a/src/app/editor/interface.h b/src/app/editor/interface.h index 54a956e..ee3c9d6 100644 --- a/src/app/editor/interface.h +++ b/src/app/editor/interface.h @@ -1534,7 +1534,10 @@ ui_BeginList(ui_interface* Interface, gs_string Text, u32 ViewportRows, u32 Elem s32 ScrollableElements = Max(0, ElementCount - ViewportRows); ui_widget_retained_state* ViewportState = ui_GetOrCreateRetainedState(Interface, ViewportLayout); ViewportState->ChildrenDrawOffset.x = 0; - ViewportState->ChildrenDrawOffset.y = ((1.0f - State->InitialValueR32) * (r32)(ScrollableElements + 1)) * ViewportLayout->RowHeight; + r32 BaseOffset = Rect2Height(ViewportLayout->Bounds) - ViewportLayout->RowHeight; + r32 ScrollPct = 1.0 - State->InitialValueR32; + r32 ScrollOffset = ScrollPct * ViewportLayout->RowHeight * ScrollableElements; + ViewportState->ChildrenDrawOffset.y = BaseOffset + ScrollOffset; } internal void diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index e1dd6b6..822cf58 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -19,6 +19,12 @@ struct animation_timeline_state animation_handle NextActiveAnim; }; +internal void +AnimationTimeline_SelectLayer(animation_timeline_state* TLState, s32 Layer) +{ + TLState->SelectedAnimationLayer = Layer; +} + inline u32 GetFrameFromPointInAnimationPanel(v2 Point, rect2 PanelBounds, frame_range VisibleRange) { @@ -266,6 +272,11 @@ AnimationTimeline_AddAnimationBlockCommand(animation_timeline_state* TimelineSta { animation_pattern_handle PatternHandle = Patterns_IndexToHandle(0); s32 Layer = TimelineState->SelectedAnimationLayer; + if (Layer < 0) + { + Layer = Animation_AddLayer(ActiveAnim, MakeString("[New Layer]"), BlendMode_Add, &State->AnimationSystem); + AnimationTimeline_SelectLayer(TimelineState, Layer); + } Assert(Layer >= 0); handle NewBlockHandle = Animation_AddBlock(ActiveAnim, StartFrame, EndFrame, PatternHandle, Layer); @@ -472,33 +483,6 @@ DrawLayerMenu(animation_system* AnimationSystem, animation ActiveAnim, ui_interf } } -internal rect2 -DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect2 TimelineBounds, render_command_buffer* RenderBuffer) -{ - rect2 BlockBounds = {}; - - r32 TimelineWidth = Rect2Width(TimelineBounds); - - u32 ClampedBlockStartFrame = ClampFrameToRange(AnimationBlock.Range.Min, VisibleFrames); - r32 StartFramePercent = FrameToPercentRange(ClampedBlockStartFrame, VisibleFrames); - r32 StartPosition = TimelineWidth * StartFramePercent; - - u32 ClampedBlockEndFrame = ClampFrameToRange(AnimationBlock.Range.Max, VisibleFrames); - r32 EndFramePercent = FrameToPercentRange(ClampedBlockEndFrame, VisibleFrames); - r32 EndPosition = TimelineWidth * EndFramePercent; - - r32 LayerYOffset = LAYER_HEIGHT * AnimationBlock.Layer; - BlockBounds.Min = TimelineBounds.Min + v2{StartPosition, LayerYOffset}; - BlockBounds.Max = TimelineBounds.Min + v2{EndPosition, LayerYOffset + LAYER_HEIGHT}; - - PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor); - PushRenderBoundingBox2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, 1, WhiteV4); - - // TODO(pjs): If mouse is on one of the border hot spots, render an off colored square to signal the region is hot - - return BlockBounds; -} - PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback) { Assert(ReturningFrom->TypeIndex == PanelType_FileView); @@ -518,6 +502,8 @@ PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback) internal void PlayBar_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; + animation_system* AnimSystem = &State->AnimationSystem; ui_interface* Interface = &State->Interface; ui_PushLayout(Interface, Bounds, LayoutDirection_TopDown, MakeString("PlayBar Layout")); @@ -548,6 +534,8 @@ PlayBar_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Pan internal void FrameCount_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, rect2 Bounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; + ui_interface* Interface = &State->Interface; gs_string TempString = PushString(State->Transient, 256); @@ -627,6 +615,7 @@ LayerList_DrawLayerButton (ui_interface* Interface, gs_string Name, rect2 Bounds internal void LayerList_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; ui_interface* Interface = &State->Interface; ui_FillRect(Interface, Bounds, Interface->Style.PanelBG); @@ -658,9 +647,49 @@ LayerList_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, } } +internal void +TimeRange_RenderBlock (rect2 BlockBounds, u32 BlockIndex, animation* ActiveAnim, handle SelectedBlockHandle, ui_interface* Interface, render_command_buffer* RenderBuffer) +{ + v4 BlockColor = BlackV4; + if (SelectedBlockHandle.Index == BlockIndex && SelectedBlockHandle.Generation == ActiveAnim->Blocks_.Generations[BlockIndex]) + { + BlockColor = TealV4; + } + + PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor); + PushRenderBoundingBox2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, 1, WhiteV4); +} + +struct block_bounds_lut_entry +{ + rect2 Bounds; + u32 Index; +}; + +internal void +TimeRange_RenderBlockArray(block_bounds_lut_entry* Blocks, u32* LUT, u32 LUTCount, r32 HeightOffset, animation* ActiveAnim, handle SelectedBlockHandle, handle* DragBlockHandle, ui_interface* Interface, render_command_buffer* RenderBuffer) +{ + for (u32 i = 0; i < LUTCount; i++) + { + u32 BlockBoundsIndex = LUT[i]; + block_bounds_lut_entry Block = Blocks[BlockBoundsIndex]; + Block.Bounds.Max.y += HeightOffset; + + TimeRange_RenderBlock(Block.Bounds, Block.Index, ActiveAnim, SelectedBlockHandle, Interface, RenderBuffer); + + if (PointIsInRect(Block.Bounds, Interface->Mouse.Pos)) + { + DragBlockHandle->Index = Block.Index; + DragBlockHandle->Generation = ActiveAnim->Blocks_.Generations[Block.Index]; + } + } +} + internal void TimeRange_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, rect2 Bounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; + ui_interface* Interface = &State->Interface; // TODO(pjs): setting the timeline to show the entire range @@ -682,32 +711,108 @@ TimeRange_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, handle DragBlockHandle = {0}; if (ActiveAnim) { - for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) + u32 BlocksCountMax = ActiveAnim->Blocks_.Count; + u32 BlocksCount = 0; + block_bounds_lut_entry* Blocks = PushArray(State->Transient, block_bounds_lut_entry, BlocksCountMax); + + u32 FrontBlocksCount = 0; + u32* FrontBlocks = PushArray(State->Transient, u32, BlocksCountMax); + u32 BackBlocksCount = 0; + u32* BackBlocks = PushArray(State->Transient, u32, BlocksCountMax); + + for (u32 l = 0; l < ActiveAnim->Layers.Count; l++) { - animation_block* AnimationBlockAt = ActiveAnim->Blocks_.Values + i; + BlocksCount = 0; + FrontBlocksCount = 0; + BackBlocksCount = 0; - // If either end is in the range, we should draw it - b32 RangeIsVisible = (FrameIsInRange(ViewRange, AnimationBlockAt->Range.Min) || - FrameIsInRange(ViewRange, AnimationBlockAt->Range.Max)); - // If neither end is in the range, but the ends surround the visible range, - // we should still draw it. - RangeIsVisible |= (AnimationBlockAt->Range.Min <= ViewRange.Min && - AnimationBlockAt->Range.Max>= ViewRange.Max); - if (RangeIsVisible) + for (u32 i = 0; i < ActiveAnim->Blocks_.Count; i++) { - v4 BlockColor = BlackV4; - if (SelectedBlockHandle.Index == i && SelectedBlockHandle.Generation == ActiveAnim->Blocks_.Generations[i]) - { - BlockColor = PinkV4; - } - rect2 BlockBounds = DrawAnimationBlock(*AnimationBlockAt, BlockColor, ViewRange, Bounds, Interface->RenderBuffer); + animation_block* AnimationBlockAt = ActiveAnim->Blocks_.Values + i; + if (AnimationBlockAt->Layer != l) continue; - if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) + // If either end is in the range, we should draw it + b32 RangeIsVisible = (FrameIsInRange(ViewRange, AnimationBlockAt->Range.Min) || + FrameIsInRange(ViewRange, AnimationBlockAt->Range.Max)); + // If neither end is in the range, but the ends surround the visible range, + // we should still draw it. + RangeIsVisible |= (AnimationBlockAt->Range.Min <= ViewRange.Min && + AnimationBlockAt->Range.Max>= ViewRange.Max); + if (!RangeIsVisible) continue; + + r32 TimelineWidth = Rect2Width(Bounds); + + frame_range BlockAtRange = AnimationBlockAt->Range; + u32 ClampedBlockStartFrame = ClampFrameToRange(BlockAtRange.Min, ViewRange); + r32 StartFramePercent = FrameToPercentRange(ClampedBlockStartFrame, ViewRange); + r32 StartPosition = TimelineWidth * StartFramePercent; + + u32 ClampedBlockEndFrame = ClampFrameToRange(BlockAtRange.Max, ViewRange); + r32 EndFramePercent = FrameToPercentRange(ClampedBlockEndFrame, ViewRange); + r32 EndPosition = TimelineWidth * EndFramePercent; + + r32 LayerYOffset = LAYER_HEIGHT * AnimationBlockAt->Layer; + + rect2 NewBlockBounds = {}; + NewBlockBounds.Min = Bounds.Min + v2{StartPosition, LayerYOffset}; + NewBlockBounds.Max = Bounds.Min + v2{EndPosition, LayerYOffset + LAYER_HEIGHT}; + + block_bounds_lut_entry NewBlock = {}; + NewBlock.Bounds = NewBlockBounds; + NewBlock.Index = i; + + // fast (implementation-wise) insert sort. + // TODO(PS): probably not great + for (u32 j = 0; j < BlocksCount; j++) { - DragBlockHandle.Index = i; - DragBlockHandle.Generation = ActiveAnim->Blocks_.Generations[i]; + if (Blocks[j].Bounds.Min.x > NewBlock.Bounds.Min.x) + { + block_bounds_lut_entry Old = Blocks[j]; + Blocks[j] = NewBlock; + NewBlock = Old; + } + } + Blocks[BlocksCount++] = NewBlock; + } + + // BlockBounds are sorted by their render bounds from left to right + // This iterates over them to see if any on the same layer overlap, and if + // so, shrinks one of them, putting it in a new list + for (u32 i = 0; i < BlocksCount; i++) + { + if (i % 2 == 0) + { + BackBlocks[BackBlocksCount++] = i; + continue; + } + + bool ShortCandidate = false; + block_bounds_lut_entry Block = Blocks[i]; + if (i > 0) + { + block_bounds_lut_entry PrevBlock = Blocks[i - 1]; + rect2 Union = Rect2Union(PrevBlock.Bounds, Block.Bounds); + ShortCandidate |= Rect2Width(Union) > 0; + } + if (i < BlocksCount - 1) + { + block_bounds_lut_entry NextBlock = Blocks[i + 1]; + rect2 Union = Rect2Union(NextBlock.Bounds, Block.Bounds); + ShortCandidate |= Rect2Width(Union) > 0; + } + + if (ShortCandidate) + { + FrontBlocks[FrontBlocksCount++] = i; + } + else + { + BackBlocks[BackBlocksCount++] = i; } } + + TimeRange_RenderBlockArray(Blocks, BackBlocks, BackBlocksCount, 0, ActiveAnim, SelectedBlockHandle, &DragBlockHandle, Interface, RenderBuffer); + TimeRange_RenderBlockArray(Blocks, FrontBlocks, FrontBlocksCount, -15, ActiveAnim, SelectedBlockHandle, &DragBlockHandle, Interface, RenderBuffer); } } @@ -770,6 +875,7 @@ AnimationTimeline_SetActiveAnimation (animation_handle Handle, animation_timelin internal void AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAnim, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; animation_system* AnimSystem = &State->AnimationSystem; animation_handle ActiveAnimHandle = State->AnimationSystem.ActiveFadeGroup.From; @@ -884,9 +990,8 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, animation* ActiveAn { animation_pattern BlockPattern = Patterns_GetPattern(State->Patterns, SelectedBlock->AnimationProcHandle); - ui_BeginRow(Interface, 3); + ui_BeginRow(Interface, 2); ui_Label(Interface, MakeString("Selected Pattern")); - //if (ui_BeginLabeledDropdown(Interface, MakeString("Selected Pattern"), MakeString(BlockPattern.Name, BlockPattern.NameLength))) if (ui_BeginDropdown(Interface, MakeString(BlockPattern.Name, BlockPattern.NameLength))) { Interface->ActiveLayout->Bounds.Max.x += 128.0f; @@ -925,6 +1030,8 @@ GSMetaTag(panel_type_animation_timeline); internal void AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { + DEBUG_TRACK_FUNCTION; + animation_timeline_state* TimelineState = Panel_GetStateStruct(Panel, animation_timeline_state); animation* ActiveAnim = 0; diff --git a/src/app/engine/animation/foldhaus_animation.h b/src/app/engine/animation/foldhaus_animation.h index adac56e..4bcad4a 100644 --- a/src/app/engine/animation/foldhaus_animation.h +++ b/src/app/engine/animation/foldhaus_animation.h @@ -291,6 +291,13 @@ Patterns_IndexToHandle(s32 Index) return Result; } +internal bool +IsValid(animation_pattern_handle Handle) +{ + bool Result = Handle.IndexPlusOne > 0; + return Result; +} + internal animation_pattern Patterns_GetPattern(animation_pattern_array Patterns, animation_pattern_handle Handle) { @@ -312,7 +319,7 @@ internal animation_block_array AnimBlockArray_Create(gs_memory_arena* Storage, u32 CountMax) { animation_block_array Result = {0}; - Result.CountMax = CountMax; + Result.CountMax = Max(CountMax, 32); Result.Values = PushArray(Storage, animation_block, Result.CountMax); Result.Generations = PushArray(Storage, u32, Result.CountMax); return Result; @@ -359,7 +366,7 @@ internal anim_layer_array AnimLayerArray_Create(gs_memory_arena* Storage, u32 CountMax) { anim_layer_array Result = {0}; - Result.CountMax = CountMax; + Result.CountMax = Max(CountMax, 32); Result.Values = PushArray(Storage, anim_layer, Result.CountMax); return Result; } @@ -409,6 +416,8 @@ AnimationArray_Push(animation_array* Array, animation Value) internal animation* AnimationArray_Get(animation_array Array, animation_handle Handle) { + DEBUG_TRACK_FUNCTION; + animation* Result = 0; if (IsValid(Handle) && Handle.Index < (s32)Array.Count) { @@ -541,6 +550,13 @@ SecondsToFrames(r32 Seconds, animation_system System) return Result; } +inline frame_range +FrameRange_Overlap(frame_range A, frame_range B) +{ + frame_range Result = {}; + +} + inline bool FrameIsInRange(frame_range Range, s32 Frame) { @@ -679,6 +695,8 @@ AnimationSystem_CalculateAnimationFrame(animation_system* System, animation* Animation, gs_memory_arena* Arena) { + DEBUG_TRACK_FUNCTION; + animation_frame Result = {0}; Result.LayersCount = Animation->Layers.Count; Result.Layers = PushArray(Arena, animation_layer_frame, Result.LayersCount); @@ -793,5 +811,12 @@ AnimationSystem_NeedsRender(animation_system System) return Result; } +inline r32 +AnimationSystem_GetCurrentTime(animation_system System) +{ + r32 Result = System.CurrentFrame * System.SecondsPerFrame; + return Result; +} + #define FOLDHAUS_ANIMATION #endif // FOLDHAUS_ANIMATION \ No newline at end of file diff --git a/src/app/engine/animation/foldhaus_animation_renderer.cpp b/src/app/engine/animation/foldhaus_animation_renderer.cpp index f43184b..208c87a 100644 --- a/src/app/engine/animation/foldhaus_animation_renderer.cpp +++ b/src/app/engine/animation/foldhaus_animation_renderer.cpp @@ -122,6 +122,7 @@ AnimationSystem_BeginRenderBlockToLedBuffer(animation_system* System, animation_ r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); + Assert(Pattern.Proc); if (System->Multithreaded && Pattern.Multithreaded) { @@ -182,6 +183,8 @@ RenderAnimationToLedBuffer (animation_system* System, gs_memory_arena* Transient, context Context) { + DEBUG_TRACK_FUNCTION; + led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); // Create the LayerLEDBuffers @@ -266,8 +269,7 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse { DEBUG_TRACK_FUNCTION; - s32 CurrentFrame = System->CurrentFrame; - r32 FrameTime = CurrentFrame * System->SecondsPerFrame; + r32 FrameTime = AnimationSystem_GetCurrentTime(*System); #if 1 animation_array Animations = System->Animations; diff --git a/src/app/engine/animation/foldhaus_animation_serializer.cpp b/src/app/engine/animation/foldhaus_animation_serializer.cpp index 577e84b..55a4422 100644 --- a/src/app/engine/animation/foldhaus_animation_serializer.cpp +++ b/src/app/engine/animation/foldhaus_animation_serializer.cpp @@ -82,12 +82,10 @@ AnimParser_Parse(gs_string File, gs_memory_arena* Arena, animation_pattern_array { 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); - - Result.Blocks_.CountMax = Parser_ReadU32Value(&Parser, AnimField_BlocksCount); - Result.Blocks_.Generations = PushArray(Arena, u32, Result.Blocks_.CountMax); - Result.Blocks_.Values = PushArray(Arena, animation_block, Result.Blocks_.CountMax); + u32 LayersNeeded = Parser_ReadU32Value(&Parser, AnimField_LayersCount); + u32 BlocksNeeded = Parser_ReadU32Value(&Parser, AnimField_BlocksCount); + Result.Layers = AnimLayerArray_Create(Arena, LayersNeeded); + Result.Blocks_ = AnimBlockArray_Create(Arena, BlocksNeeded); if (Parser_ReadOpenStruct(&Parser, AnimField_PlayableRange)) { @@ -169,7 +167,7 @@ AnimParser_Parse(gs_string File, gs_memory_arena* Arena, animation_pattern_array break; } } - + Assert(IsValid(Block.AnimationProcHandle)); if (Parser_ReadCloseStruct(&Parser)) { AnimBlockArray_Push(&Result.Blocks_, Block); @@ -200,6 +198,7 @@ AnimationSystem_LoadAnimationFromFile(animation_system* System, animation_patter { animation NewAnim = AnimParser_Parse(AnimFile.Data, System->Storage, AnimPatterns); NewAnim.FileInfo = AnimFile.FileInfo; + NewAnim.FileInfo.Path = PushStringF(System->Storage, AnimFile.FileInfo.Path.Length, "%S", AnimFile.FileInfo.Path).ConstString; NewAnimHandle = AnimationArray_Push(&System->Animations, NewAnim); } return NewAnimHandle; diff --git a/src/app/engine/assembly/foldhaus_assembly_parser.cpp b/src/app/engine/assembly/foldhaus_assembly_parser.cpp index 5024fb6..dbeb890 100644 --- a/src/app/engine/assembly/foldhaus_assembly_parser.cpp +++ b/src/app/engine/assembly/foldhaus_assembly_parser.cpp @@ -276,7 +276,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName); Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale); - Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter); + Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter) * Assembly->Scale; Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount); Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount); diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 13852a5..dc19ab6 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -10,13 +10,22 @@ RELOAD_STATIC_DATA(ReloadStaticData) { - app_state* State = (app_state*)Context.MemoryBase; - GlobalDebugServices = DebugServices; - State->PanelSystem.PanelDefs = GlobalPanelDefs; - State->PanelSystem.PanelDefsCount = GlobalPanelDefsCount; - US_LoadPatterns(&State->UserSpaceDesc, State, Context); + if (AppReady) + { + app_state* State = (app_state*)Context.MemoryBase; + State->PanelSystem.PanelDefs = GlobalPanelDefs; + State->PanelSystem.PanelDefsCount = GlobalPanelDefsCount; + + gs_data UserData = State->UserSpaceDesc.UserData; + State->UserSpaceDesc = BlumenLumen_UserSpaceCreate(); + if (UserData.Memory && !State->UserSpaceDesc.UserData.Memory) + { + State->UserSpaceDesc.UserData = UserData; + } + US_LoadPatterns(&State->UserSpaceDesc, State, Context); + } } INITIALIZE_APPLICATION(InitializeApplication) @@ -38,19 +47,25 @@ INITIALIZE_APPLICATION(InitializeApplication) AnimSysDesc.SecondsPerFrame = 1.0f / 24.0f; State->AnimationSystem = AnimationSystem_Init(AnimSysDesc); - interface_config IConfig = {0}; - IConfig.FontSize = 14; - IConfig.PanelBG = v4{ .3f, .3f, .3f, 1.f }; - IConfig.ButtonColor_Inactive = BlackV4; - IConfig.ButtonColor_Active = v4{ .1f, .1f, .1f, 1.f }; - IConfig.ButtonColor_Selected = v4{ .3f, .3f, .3f, 1.f }; - IConfig.TextColor = WhiteV4; - IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; - IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; - IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; - IConfig.ListBGSelected = v4{ .44f, .44f, .44f, 1.f }; - IConfig.Margin = v2{5, 5}; - State->Interface = ui_InterfaceCreate(Context, IConfig, &State->Permanent); + if (!Context.Headless) + { + interface_config IConfig = {0}; + IConfig.FontSize = 14; + IConfig.PanelBG = v4{ .3f, .3f, .3f, 1.f }; + IConfig.ButtonColor_Inactive = BlackV4; + IConfig.ButtonColor_Active = v4{ .1f, .1f, .1f, 1.f }; + IConfig.ButtonColor_Selected = v4{ .3f, .3f, .3f, 1.f }; + IConfig.TextColor = WhiteV4; + IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; + IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; + IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; + IConfig.ListBGSelected = v4{ .44f, .44f, .44f, 1.f }; + IConfig.Margin = v2{5, 5}; + State->Interface = ui_InterfaceCreate(Context, IConfig, &State->Permanent); + + PanelSystem_Init(&State->PanelSystem, GlobalPanelDefs, GlobalPanelDefsCount, &State->Permanent); + + } State->SACN = SACN_Initialize(Context); @@ -59,17 +74,14 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AssemblyDebugState.Brightness = 255; State->AssemblyDebugState.Override = ADS_Override_None; - GlobalDebugServices->Interface.RenderSculpture = true; - - PanelSystem_Init(&State->PanelSystem, GlobalPanelDefs, GlobalPanelDefsCount, &State->Permanent); - State->Modes = OperationModeSystemInit(&State->Permanent, Context.ThreadContext); - State->UserSpaceDesc = BlumenLumen_UserSpaceCreate(); - - ReloadStaticData(Context, GlobalDebugServices); + ReloadStaticData(Context, GlobalDebugServices, true); US_CustomInit(&State->UserSpaceDesc, State, Context); + GlobalDebugServices->Interface.RenderSculpture = true; + + if (!Context.Headless) { // NOTE(pjs): This just sets up the default panel layout panel* RootPanel = PanelSystem_PushPanel(&State->PanelSystem, PanelType_SculptureView, State, Context); @@ -92,7 +104,7 @@ INITIALIZE_APPLICATION(InitializeApplication) } - State->RunEditor = true; + State->RunEditor = !Context.Headless; } internal void @@ -152,6 +164,7 @@ UPDATE_AND_RENDER(UpdateAndRender) { Editor_Render(State, Context, RenderBuffer); } + ResetWorkQueue(Context->GeneralWorkQueue); Assert(State->UserSpaceDesc.UserData.Memory != 0); BuildAssemblyData(State, *Context, OutputData); diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index f9813fe..565b797 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -95,6 +95,7 @@ LoadAssembly(gs_const_string Path, app_state* State, context Context) #include "engine/user_space.cpp" +#include "ss_blumen_lumen/sdf.h" #include "patterns/blumen_patterns.h" #include "ss_blumen_lumen/blumen_lumen.cpp" diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index dcfafc8..1009001 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -74,7 +74,7 @@ typedef INITIALIZE_APPLICATION(initialize_application); #define UPDATE_AND_RENDER(name) void name(context* Context, input_queue InputQueue, render_command_buffer* RenderBuffer, addressed_data_buffer_list* OutputData) typedef UPDATE_AND_RENDER(update_and_render); -#define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices) +#define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices, bool AppReady) typedef RELOAD_STATIC_DATA(reload_static_data); #define CLEANUP_APPLICATION(name) void name(context Context, addressed_data_buffer_list* OutputData) @@ -213,6 +213,7 @@ struct context b32 WindowIsVisible; rect2 WindowBounds; + r64 TotalTime; r32 DeltaTime; mouse_state Mouse; @@ -236,6 +237,9 @@ struct context system_time SystemTime_Last; system_time SystemTime_Current; + + // + bool Headless; }; #define FOLDHAUS_PLATFORM_H diff --git a/src/app/patterns/blumen_patterns.h b/src/app/patterns/blumen_patterns.h index 4fe9588..62b913f 100644 --- a/src/app/patterns/blumen_patterns.h +++ b/src/app/patterns/blumen_patterns.h @@ -286,9 +286,9 @@ Fbm3D(v3 P, r32 T) F += 0.500000f * Noise3D(Pp + Tt); Pp = Pp * 2.02; F += 0.031250f * Noise3D(Pp); Pp = Pp * 2.01; - F += 0.250000f * Noise3D(Pp); Pp = Pp * 2.03; + F += 0.250000f * Noise3D(Pp - Tt); Pp = Pp * 2.03; F += 0.125000f * Noise3D(Pp); Pp = Pp * 2.01; - F += 0.062500f * Noise3D(Pp); Pp = Pp * 2.04; + F += 0.062500f * Noise3D(Pp + Tt); Pp = Pp * 2.04; F += 0.015625f * Noise3D(Pp + Tv); F = F / 0.984375f; @@ -319,49 +319,6 @@ Voronoise(v2 P, r32 U, r32 V) return A.x / A.y; } -v4 FlowerAColors[FLOWER_COLORS_COUNT] = { - { 232 / 255.f, 219 / 255.f, 88 / 255.f }, - { 232 / 255.f, 219 / 255.f, 88 / 255.f }, - { 232 / 255.f, 219 / 255.f, 88 / 255.f }, - { 147 / 255.f, 75 / 255.f, 176 / 255.f }, - { 193 / 255.f, 187 / 255.f, 197 / 255.f }, - { 223 / 255.f, 190 / 255.f, 49 / 255.f }, - { 198 / 255.f, 76 / 255.f, 65 / 255.f }, - { 198 / 255.f, 76 / 255.f, 65 / 255.f }, - { 198 / 255.f, 76 / 255.f, 65 / 255.f }, - { 226 / 255.f, 200 / 255.f, 17 / 255.f }, - { 116 / 255.f, 126 / 255.f, 39 / 255.f }, - { 61 / 255.f, 62 / 255.f, 31 / 255.f } -}; -v4 FlowerBColors[FLOWER_COLORS_COUNT] = { - { 62 / 255.f, 56 / 255.f, 139 / 255.f }, - { 93 / 255.f, 87 / 255.f, 164 / 255.f }, - { 93 / 255.f, 87 / 255.f, 164 / 255.f }, - { 93 / 255.f, 87 / 255.f, 164 / 255.f }, - { 155 / 255.f, 140 / 255.f, 184 / 255.f }, - { 191 / 255.f, 201 / 255.f, 204 / 255.f }, - { 45 / 255.f, 31 / 255.f, 116 / 255.f }, - { 201 / 255.f, 196 / 255.f, 156 / 255.f }, - { 191 / 255.f, 175 / 255.f, 109 / 255.f }, - { 186 / 255.f, 176 / 255.f, 107 / 255.f }, - { 89 / 255.f, 77 / 255.f, 17 / 255.f }, - { 47 / 255.f, 49 / 255.f, 18 / 255.f }, -}; -v4 FlowerCColors[FLOWER_COLORS_COUNT] = { - { 220 / 255.f, 217 / 255.f, 210 / 255.f }, - { 220 / 255.f, 217 / 255.f, 210 / 255.f }, - { 220 / 255.f, 217 / 255.f, 210 / 255.f }, - { 225 / 255.f, 193 / 255.f, 110 / 255.f }, - { 225 / 255.f, 193 / 255.f, 110 / 255.f }, - { 227 / 255.f, 221 / 255.f, 214 / 255.f }, - { 227 / 255.f, 221 / 255.f, 214 / 255.f }, - { 230 / 255.f, 218 / 255.f, 187 / 255.f }, - { 230 / 255.f, 218 / 255.f, 187 / 255.f }, - { 172 / 255.f, 190 / 255.f, 211 / 255.f }, - { 172 / 255.f, 190 / 255.f, 211 / 255.f }, - { 172 / 255.f, 190 / 255.f, 211 / 255.f }, -}; - internal pixel V4ToRGBPixel(v4 C) { @@ -410,166 +367,6 @@ GetColor(v4* Colors, u32 ColorsCount, r32 Percent) return Result; } -internal void -SolidColorPattern(led_buffer* Leds, led_buffer_range Range, pixel Color) -{ - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - Leds->Colors[LedIndex] = Color; - } -} - -internal void -Pattern_Blue(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - pixel Blue = pixel{0, 0, 255}; - SolidColorPattern(Leds, Range, Blue); -} - -internal void -Pattern_Green(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - pixel Green = pixel{0, 255, 0}; - SolidColorPattern(Leds, Range, Green); -} - -internal void -Pattern_FlowerColors(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 CycleTime = 10; - r32 CyclePercent = ModR32(Time, CycleTime) / CycleTime; - - v4 CA = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, CyclePercent); - v4 CB = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, 1.0f - CyclePercent); - - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - v4 P = Leds->Positions[LedIndex]; - r32 Pct = (Abs(ModR32(P.y, 150) / 150) + CycleTime) * PiR32; - - r32 APct = RemapR32(SinR32(Pct), -1, 1, 0, 1); - Leds->Colors[LedIndex] = PixelMix(APct, CA, CB); - } -} - -internal void -TestPatternOne(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient); - led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient); - - for (u32 i = 0; i < BlumenStrips.Count; i++) - { - u32 StripIndex = BlumenStrips.StripIndices[i]; - v2_strip StripAt = Assembly.Strips[StripIndex]; - - for (u32 j = 0; j < StripAt.LedCount; j++) - { - u32 LedIndex = StripAt.LedLUT[j]; - Leds->Colors[LedIndex] = { 255, 0, 0 }; - - } - } - - for (u32 i = 0; i < RadiaStrips.Count; i++) - { - u32 StripIndex = RadiaStrips.StripIndices[i]; - v2_strip StripAt = Assembly.Strips[StripIndex]; - - for (u32 j = 0; j < StripAt.LedCount; j++) - { - u32 LedIndex = StripAt.LedLUT[j]; - Leds->Colors[LedIndex] = { 0, 255, 0 }; - } - } -} - -internal void -TestPatternTwo(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 PeriodicTime = (Time / PiR32) * 2; - - r32 ZeroOneSin = (SinR32(PeriodicTime) * .5f) + .5f; - r32 ZeroOneCos = (CosR32(PeriodicTime) * .5f) + .5f; - pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; - - v4 Center = v4{0, 0, 0, 1}; - r32 ThetaZ = Time / 2; - v4 Normal = v4{CosR32(ThetaZ), 0, SinR32(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); - - v4 FrontCenter = Center + (Normal * 25); - v4 BackCenter = Center - (Normal * 25); - - r32 OuterRadiusSquared = 1000000; - r32 InnerRadiusSquared = 0; - - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - v4 Position = Leds->Positions[LedIndex]; - - v4 ToFront = Position + FrontCenter; - v4 ToBack = Position + BackCenter; - - r32 ToFrontDotNormal = V4Dot(ToFront, Normal); - r32 ToBackDotNormal = V4Dot(ToBack, Normal); - - ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - - r32 SqDistToCenter = V4MagSquared(Position); - if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) - { - if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) - { - Leds->Colors[LedIndex] = Color; - } - else - { - //Leds->Colors[LedIndex] = {}; - } - } - else - { - //Leds->Colors[LedIndex] = {}; - } - } -} - -internal void -TestPatternThree(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - v4 GreenCenter = v4{0, 0, 150, 1}; - r32 GreenRadius = Abs(SinR32(Time)) * 200; - - v4 TealCenter = v4{0, 0, 150, 1}; - r32 TealRadius = Abs(SinR32(Time + 1.5)) * 200; - - r32 FadeDist = 35; - - - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - v4 LedPosition = Leds->Positions[LedIndex]; - u8 Red = 0; - u8 Green = 0; - u8 Blue = 0; - - r32 GreenDist = Abs(V4Mag(LedPosition - GreenCenter) - GreenRadius); - r32 GreenBrightness = Clamp(0.f, FadeDist - Abs(GreenDist), FadeDist); - Green = (u8)(GreenBrightness * 255); - - r32 TealDist = Abs(V4Mag(LedPosition - TealCenter) - TealRadius); - r32 TealBrightness = Clamp(0.f, FadeDist - Abs(TealDist), FadeDist); - Red = (u8)(TealBrightness * 255); - Blue = (u8)(TealBrightness * 255); - - Leds->Colors[LedIndex].R = Red; - Leds->Colors[LedIndex].B = Green; - Leds->Colors[LedIndex].G = Green; - } -} - v4 RGBToHSV(v4 In) { v4 Result = {}; @@ -697,6 +494,22 @@ while (Hue > 360.0f) { Hue -= 360.0f; } return Result; } +internal void +Pattern_AltBloomMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + v3 SphereCenter = Assembly.Center - v3{0, -150, 0}; + r32 SphereRadius = Time; + r32 SphereBrightness = 1; + + for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) + { + v3 P = Leds->Positions[LedIndex].xyz; + r32 Sphere = SDF_SphereNormalized(P, SphereCenter, SphereRadius); + Sphere = Clamp01(-Sphere); + Leds->Colors[LedIndex] = V4ToRGBPixel(WhiteV4 * Sphere); + } +} + internal void Pattern_HueShift(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { @@ -728,7 +541,7 @@ Pattern_HueShift(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r3 } internal void -Pattern_HueFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +Pattern_Rainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { r32 HueBase = ModR32(Time * 50, 360); @@ -748,49 +561,7 @@ Pattern_HueFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 } internal void -Pattern_AllGreen(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - u32 I = LedIndex + 1; - Leds->Colors[LedIndex] = {0, 255, 0}; - } -} - -internal r32 -PatternHash(r32 Seed) -{ - return FractR32(Seed * 17.0 * FractR32(Seed * 0.3183099)); -} - -internal void -Pattern_Spots(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - pixel ColorA = { 0, 255, 255 }; - pixel ColorB = { 255, 0, 255 }; - - r32 Speed = .5f; - Time *= Speed; - r32 ScaleA = 2 * SinR32(Time / 5); - r32 ScaleB = 2.4f * CosR32(Time / 2.5f); - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - v4 P = Leds->Positions[LedIndex]; - r32 V = P.y; - r32 Noise = .3f * PatternHash(V); - r32 ThetaY = (Leds->Positions[LedIndex].y / 10) + Time + Noise; - r32 ThetaX = (Leds->Positions[LedIndex].x / 13) + Time + Noise; - r32 Fade = (ScaleA * SinR32(ThetaY)) + (ScaleB * CosR32(3 * ThetaX)); - Fade = RemapClampedR32(Fade, -1, 1, 0, 1); - - Leds->Colors[LedIndex].R = (u8)LerpR32(Fade, ColorA.R, ColorB.R); - Leds->Colors[LedIndex].G = (u8)LerpR32(Fade, ColorA.G, ColorB.G); - Leds->Colors[LedIndex].B = (u8)LerpR32(Fade, ColorA.B, ColorB.B); - } -} - -internal void -Pattern_LighthouseRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +Pattern_RadialRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) }); for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) @@ -803,196 +574,16 @@ Pattern_LighthouseRainbow(led_buffer* Leds, led_buffer_range Range, assembly Ass r32 Angle = V2Dot(RefVector, Vector); - v4 HSV = { (Angle * 30) + (Time * 10) + Leds->Positions[LedIndex].y, 1, 1, 1 }; + v4 HSV = { (Angle * 30) + (Time * 10), 1, 1, 1 }; v4 RGB = HSVToRGB(HSV); Leds->Colors[LedIndex] = V4ToRGBPixel(RGB); } } -internal void -Pattern_SmoothGrowRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f; - r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f; - - v4 HSV = { 0, 1, 1, 1 }; - for (u32 s = 0; s < Assembly.StripCount; s++) - { - v2_strip Strip = Assembly.Strips[s]; - - v4 RGB0 = HSVToRGB(HSV); - for (u32 l = 0; l < Strip.LedCount; l++) - { - u32 LedIndex = Strip.LedLUT[l]; - Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0); - } - - HSV.x += 15; - } -} - -internal void -Pattern_GrowAndFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 PercentCycle = ModR32(Time, 10) / 10; - v4 HSV = { PercentCycle * 360, 1, 1, 1 }; - v4 RGB = HSVToRGB(HSV); - - r32 RefHeight = -100 + (Smoothstep(PercentCycle * 1.4f) * 400); - r32 RefBrightness = 1.0f - Smoothstep(PercentCycle); - - for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) - { - v4 P = Leds->Positions[LedIndex]; - - v4 RgbFaded = v4{}; - if (P.y < RefHeight) - { - RgbFaded = RGB * RefBrightness; - } - Leds->Colors[LedIndex] = V4ToRGBPixel(RgbFaded); - } -} - -internal void -Pattern_ColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 FadeBottomBase = 50; - r32 FadeTop = 125; - - for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) - { - v2_strip Strip = Assembly.Strips[StripIndex]; - - r32 FlowerSpread = .8f; - r32 FlowerOffset = 0; - if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "center")) - { - FlowerOffset = 1; - } - else if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "right")) - { - FlowerOffset = 2; - } - FlowerOffset *= FlowerSpread; - - r32 PercentCycle = ModR32(Time + FlowerOffset, 10) / 10; - - r32 FadeBottom = FadeBottomBase + RemapR32(SinR32((PercentCycle * 4) * TauR32), -1, 1, -50, 50); - - v4 TopRGB = WhiteV4; - pixel TopColor = V4ToRGBPixel(TopRGB); - - for (u32 i = 0; i < Strip.LedCount; i++) - { - u32 LedIndex = Strip.LedLUT[i]; - v4 P = Leds->Positions[LedIndex]; - - pixel FinalColor = {}; - if (P.y > FadeTop) - { - FinalColor = TopColor; - } - else - { - r32 B = RemapR32(SinR32((P.y / 15.f) + (PercentCycle * TauR32)), -1, 1, .5f, 1.f); - r32 HNoise = RemapR32(SinR32((P.y / 31.f) + (PercentCycle * TauR32)), -1, 1, -32.f, 32.f); - v4 BottomRGB = HSVToRGB(v4{ (PercentCycle * 360) + HNoise, 1, B, 1 }); - - if (P.y < FadeBottom) - { - FinalColor = V4ToRGBPixel(BottomRGB); - } - else if (P.y >= FadeBottom && P.y <= FadeTop) - { - r32 FadePct = RemapR32(P.y, FadeBottom, FadeTop, 0, 1); - v4 MixRGB = V4Lerp(FadePct, BottomRGB, TopRGB); - FinalColor = V4ToRGBPixel(MixRGB); - } - } - - Leds->Colors[LedIndex] = FinalColor; - } - } -} - -internal void -Pattern_FlowerColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) -{ - r32 FadeBottomBase = 50; - r32 FadeTop = 125; - - for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) - { - v2_strip Strip = Assembly.Strips[StripIndex]; - -#if 0 - // All flowers same flower type - pixel* Colors = &FlowerAColors[0]; - r32 FlowerSpread = .8f; - r32 FlowerOffset = 0; - if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "center")) - { - FlowerOffset = 1; - } - else if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "right")) - { - FlowerOffset = 2; - } - FlowerOffset *= FlowerSpread; -#else - // Each flower different - v4* Colors = &FlowerAColors[0]; - r32 FlowerOffset = 0; - if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "center")) - { - Colors = &FlowerBColors[0]; - } - else if (AssemblyStrip_HasTagValueSLOW(Strip, "flower", "right")) - { - Colors = &FlowerCColors[0]; - } -#endif - r32 PercentCycle = ModR32(Time + FlowerOffset, 10) / 10; - - r32 FadeBottom = FadeBottomBase + RemapR32(SinR32((PercentCycle * 4) * TauR32), -1, 1, -50, 50); - - for (u32 i = 0; i < Strip.LedCount; i++) - { - u32 LedIndex = Strip.LedLUT[i]; - v4 P = Leds->Positions[LedIndex]; - - v4 FinalColor = {}; - r32 B = RemapR32(SinR32((P.y / 15.f) + (PercentCycle * TauR32)), -1, 1, .5f, 1.f); - r32 HNoise = RemapR32(SinR32((P.y / 31.f) + (PercentCycle * TauR32)), -1, 1, 0.f, 1.f); - - v4 BottomColor = GetColor(Colors, FLOWER_COLORS_COUNT, (PercentCycle + HNoise) / 2); - - FinalColor = BottomColor; - - Leds->Colors[LedIndex] = V4ToRGBPixel(FinalColor); - } - } -} - -r32 TLastFrame = 0; -v4* FAC = &FlowerAColors[0]; -v4* FBC = &FlowerBColors[0]; -v4* FCC = &FlowerCColors[0]; - internal void Pattern_BasicFlowers(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { - if (TLastFrame > Time) - { - v4 * Temp = FAC; - FAC = FBC; - FBC = FCC; - FCC = Temp; - } - TLastFrame = Time; - blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); @@ -1032,30 +623,58 @@ Pattern_Wavy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Ti DEBUG_TRACK_FUNCTION; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; - phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; + phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly); v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); + v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1}); + r32 Top = 120 + (SinR32(Time) * 10); + r32 Mid = 70 + (CosR32(Time * 2.13) * 20); + r32 Bot = 0; + + r32 TopD = Top - Mid; + r32 BotD = Mid - Bot; + r32 MidD = Min(TopD, BotD); + + //r32 MaxFadeDistance = 10; for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) { - v4 P = Leds->Positions[LedIndex]; + v3 P = Leds->Positions[LedIndex].xyz; - v3 Pp = P.xyz; + r32 PercentTop = Clamp01(1.0f - ((Top - P.y) / TopD)); - r32 Noise = Fbm3D((Pp / 1000) + (v3{Time, -Time, Time} * 0.01f)); - Noise = RemapR32(Noise, -1, 1, 0, 1); - Noise = Smoothstep(Noise, 0, 1); - u8 NV = (u8)(Noise * 255); + r32 PercentMid = Clamp01(1.0f - Abs(P.y - Mid) / MidD); + r32 N = Noise3D((P / 17) + v3{Time, -Time, 0}); + N = Clamp01(N) * 2; + N = Smoothstep(N); + N *= N; + N = Smoothstep(N); + N *= 1.0f - PowR32(1.0f - PercentMid, 4); + PercentMid = Clamp01(PercentMid + N); - v3 BSeed = v3{P.z, P.x, P.y}; - r32 BNoise = 1.0f; //Fbm3D(BSeed / 50); + r32 PercentBot = Clamp01(1.0f - ((P.y - Bot) / BotD)); - v4 C = V4Lerp(BNoise, C0, C1); - C = C * BNoise; + v4 TopC = (C0 * PercentTop); + v4 MidC = (C1 * PercentMid); + v4 BotC = (C2 * PercentBot); - //Leds->Colors[LedIndex] = V4ToRGBPixel(v4{Noise, Noise, Noise, 1}); + v4 C = {}; + if (PercentTop > PercentMid && PercentTop > PercentBot) + { + C = C0; + } + else if (PercentMid > PercentBot) + { + C = C1; + } + else + { + C = C2; + } + + r32 ScaleFactor = PercentTop + PercentMid + PercentBot; + C = (TopC + MidC + BotC) / ScaleFactor; Leds->Colors[LedIndex] = V4ToRGBPixel(C); - //Leds->Colors[LedIndex] = pixel{NV, NV, NV}; } } @@ -1065,7 +684,7 @@ Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 DEBUG_TRACK_FUNCTION; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; - phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % BL_FLOWER_COUNT]; + phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly); v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); @@ -1086,70 +705,71 @@ Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 NoiseB = Smoothstep(NoiseB); v4 CB = C1 * NoiseB; - v4 C = CA + CB; + v4 C = (C0 * NoiseA) + (C1 * NoiseB); + C /= (NoiseA + NoiseB); Leds->Colors[LedIndex] = V4ToRGBPixel(C); } } +internal r32 +Leafy_BandSDF(v3 P, gs_random_series* Random, r32 Time) +{ + r32 MinBandThickness = 5; + r32 MaxBandThickness = 10; + r32 MaxTransitionPeriod = 120.0f; + + r32 BandTransitionPeriod = NextRandomUnilateral(Random) * MaxTransitionPeriod; + r32 BandTransitionBias = (1 - Clamp(0, (Time / (MaxTransitionPeriod / 2)), 0.7f)); // approaches 0.5 over time + BandTransitionPeriod *= BandTransitionBias; + + r32 BandPercent = ModR32(Time, BandTransitionPeriod) / BandTransitionPeriod; + BandPercent = Smoothstep(BandPercent); + r32 BandY = -150 + (BandPercent * 290); + + r32 ThickRand = NextRandomUnilateral(Random); + // 1 - 4((ThickRand - .5)^2) - distribution curve + ThickRand = 1.0f - ((4 * PowR32(ThickRand, 2)) - (4 * ThickRand) + 1); + r32 BandThickness = MinBandThickness + (ThickRand * (MaxBandThickness - MinBandThickness)); + + // BandBrightness = 1 - ((2x - 1) ^ 8) where x is BandPercent + r32 BandBrightness = 1.0f - PowR32((2 * BandPercent) - 1, 8); + BandBrightness *= RemapR32(NextRandomUnilateral(Random), 0, 1, .25f, 1); + r32 Result = 1 - Clamp01(Abs(P.y - BandY) / BandThickness); + Result *= BandBrightness; + return Result; +} + internal void Pattern_Leafy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { DEBUG_TRACK_FUNCTION; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; - phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; + phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly); v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); + v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1}); for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) { v4 P = Leds->Positions[LedIndex]; -#if 0 - r32 RefPos = P.y + Noise2D(v2{P.x, P.z} * 10); - v4 C = {}; r32 B = 0; - r32 BandWidth = 5; - r32 TransitionPeriod = 30.0f; - u32 BandCount = 10; + // NOTE(PS): initializing the Random seed inside the Led Loop + // so that the bands are consistently calculated for each led + // ie. each time you calculate a band, the random numbers requested + // will always be the same + gs_random_series Random = InitRandomSeries(24601); + u32 BandCount = 25; for (u32 Band = 0; Band < BandCount; Band++) { - r32 BandSeed = Hash1((r32)Band); - r32 BandSeedPos = RemapR32(BandSeed, -1, 1, 0, 1); - r32 BandDelay = BandSeedPos * TransitionPeriod; - r32 BandTransitionPeriod = RemapR32(Hash1((r32)Band * 3.413f), -1, 1, 0, 1) * TransitionPeriod; - r32 BandOffset = Time + BandDelay; - r32 BandPercent = ModR32(BandOffset, BandTransitionPeriod) / BandTransitionPeriod; - r32 BandSmoothed = Smoothstep(BandPercent, 0, 1); - - r32 BandHeight = -125 + BandPercent * 250; - - r32 BandDist = Abs(RefPos - BandHeight); - - B += Max(0, (BandWidth + BandSeed * 2.5) - BandDist); + B += Leafy_BandSDF(P.xyz, &Random, Time); } - B = Clamp(0, B, 1); + B = Clamp01(B); - r32 BandCP = (P.y + 100) / 200; - BandCP = 0.8f; - v4 BandC = GetColor(&FlowerBColors[0], FLOWER_COLORS_COUNT, BandCP); - - v4 GradientC = GetColor(&FlowerBColors[0], FLOWER_COLORS_COUNT, 0); - r32 GradientB = RemapR32(P.y, 200, 0, 1, 0); - GradientB = Clamp(0, GradientB, 1); - - C = (GradientC * GradientB) + (BandC * B); -#endif - //v4 C = GetColor(&FlowerBColors[0], FLOWER_COLORS_COUNT, 0); - v4 C = v4{ 255, 100, 3 }; - C /= 255.f; - //r32 B = Fbm3D(P.xyz / 200); - //C *= B; - if (P.y < 75) { - C = v4{ 139 / 255.f, 69 / 255.f, 19 / 255.f, 1.0f} * .25f; - } + C = WhiteV4 * B; Leds->Colors[LedIndex] = V4ToRGBPixel(C); } } @@ -1159,33 +779,44 @@ Pattern_LeafyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, { DEBUG_TRACK_FUNCTION; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; - phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; + + phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly); v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1}); v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1}); + v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1}); + for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) { v4 P = Leds->Positions[LedIndex]; - r32 LedRange = 300.0f; - r32 ScaleFactor = 1.0f / LedRange; v3 Pp = P.xyz + v3{150, 100, 0}; - r32 NoiseA = Fbm3D((Pp / 35), Time * 0.5f); - //NoiseA = PowR32(NoiseA, 3); + r32 NoiseA = Fbm3D((Pp / 18), Time * 0.25f); NoiseA = Smoothstep(NoiseA); - v4 CA = C0 * NoiseA; - r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 5}); + r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 0.5f}); NoiseB = PowR32(NoiseB, 3); NoiseB = Smoothstep(NoiseB); - v4 CB = C1; - v4 C = V4Lerp(NoiseB, CA, CB); + r32 NoiseC = Noise3D((Pp / 25) + v3{0, 0, Time * 4}); + r32 CPresence = SinR32((P.y / 50) - Time) + (0.8f * SinR32((P.y / 25) - (Time * 5.0f))); + CPresence = RemapR32(CPresence, -1.8, 1.8, 0, 1); + CPresence = PowR32(CPresence, 4); + NoiseC *= CPresence; + + v4 C = (C0 * NoiseA * 0.5f) + (C1 * NoiseB) + (C2 * NoiseC); + C *= 1.0f / (NoiseA + NoiseB + NoiseC); Leds->Colors[LedIndex] = V4ToRGBPixel(C); } } internal void Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + +} + +internal void +Pattern_VerticalLines(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) { DEBUG_TRACK_FUNCTION; blumen_lumen_state* BLState = (blumen_lumen_state*)UserData; @@ -1194,22 +825,11 @@ Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 LightSpeedMin = 1; r32 LightSpeedMax = 5; -#if 0 - r32 LightHueMin = (ModR32(Time, 10) / 10) * 360; - r32 LightHueMax = ModR32((LightHueMin + 45), 360) ; -#else - r32 CenterHue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3].Hue0; - r32 LightHueMin = ModR32(CenterHue + 30, 360);; - r32 LightHueMax = ModR32(CenterHue - 30, 360) ; -#endif s32 LightTailLength = 10; for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++) { v2_strip Strip = Assembly.Strips[StripIndex]; - r32 LightHue = LerpR32(NextRandomUnilateral(&Random), - LightHueMin, - LightHueMax); r32 LightStartHeight = NextRandomUnilateral(&Random); r32 LightSpeed = LerpR32(NextRandomUnilateral(&Random), LightSpeedMin, @@ -1224,11 +844,99 @@ Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, u32 LedIndex = Strip.LedLUT[StripLedIndex]; r32 PctTail = ((r32)i / (r32)LightTailLength); - v4 C = HSVToRGB(v4{LightHue, 1, 1, 1}) * PctTail; + v4 C = WhiteV4 * PctTail; Leds->Colors[LedIndex] = V4ToRGBPixel(C); } } } +internal void +Pattern_Rotary(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + gs_random_series Random = InitRandomSeries(24601); + +#define SphereCount 32 + v3 SphereCenter[SphereCount]; + + r32 MaxHeightOffset = 150; + r32 MaxSpeed = 10; + r32 SphereRadius = 2.0f; + for (u32 i = 0; i < SphereCount; i++) + { + r32 SphereSeedA = NextRandomBilateral(&Random); + r32 SphereSeedB = NextRandomBilateral(&Random); + r32 SphereSpeed = NextRandomUnilateral(&Random) * MaxSpeed; + + r32 SphereTime = Time + SphereSpeed; + r32 HeightOffset = SphereTime + (SphereSeedA * MaxHeightOffset); + r32 RotationOffset = SphereTime + SphereSeedB * TauR32; + r32 SphereRotationDir = NextRandomBilateral(&Random) < 0 ? -1 : 1; + v3 SpherePosOffset = v3{ + SinR32(RotationOffset * SphereRotationDir) * (SphereRadius * 2), + HeightOffset, + CosR32(RotationOffset * SphereRotationDir) * (SphereRadius * 2) + }; + SphereCenter[i] = Assembly.Center + SpherePosOffset; + } + + for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) + { + v3 P = Leds->Positions[LedIndex].xyz; + + r32 Dist = 10000000; + for (u32 i = 0; i < SphereCount; i++) + { + r32 SphereSDF = Abs(SDF_Sphere(P, SphereCenter[i], SphereRadius)); + SphereSDF = SphereSDF / SphereRadius; + Dist = Min(Dist, SphereSDF); + } + + v4 C = BlackV4; + if (Dist <= 1) + { + r32 Brightness = Clamp01(SphereRadius - Dist); + C = WhiteV4 * Brightness; + } + + Leds->Colors[LedIndex] = V4ToRGBPixel(C); + } +} + +internal void +Pattern_AllOnMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + pixel White = V4ToRGBPixel(WhiteV4); + for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) + { + v3 P = Leds->Positions[LedIndex].xyz; + Leds->Colors[LedIndex] = White; + } +} + +internal void +Pattern_BulbMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) +{ + r32 Top = 141; + r32 BulbRange = 50; + + pixel White = V4ToRGBPixel(WhiteV4); + for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++) + { + v3 P = Leds->Positions[LedIndex].xyz; + + r32 BulbSDF = 1 - Clamp01(((Top - P.y) - BulbRange) / BulbRange); + r32 N = Noise3D((P / 17) + v3{Time, -Time, 0}); + N = Clamp01(N) * 2; + N = Smoothstep(N); + N *= N; + N = Smoothstep(N); + N *= 1.0f - PowR32(1.0f - BulbSDF, 4); + BulbSDF += N; + BulbSDF = Clamp01(BulbSDF); + v4 C = WhiteV4 * BulbSDF; + Leds->Colors[LedIndex] = V4ToRGBPixel(C); + } +} + #define BLUMEN_PATTERNS_H #endif // BLUMEN_PATTERNS_H \ No newline at end of file diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index 82a98ff..3957f03 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -430,14 +430,15 @@ Win32_SendAddressedDataBuffer_Job(gs_thread_context Context, gs_data Arg) } internal bool -ReloadAndLinkDLL(win32_dll_refresh* DLL, context* Context, gs_work_queue* WorkQueue, bool ShouldError) +ReloadAndLinkDLL(win32_dll_refresh* DLL, context* Context, gs_work_queue* WorkQueue, bool ShouldError, bool AppReady) { bool Success = false; if (HotLoadDLL(DLL)) { SetApplicationLinks(Context, *DLL, WorkQueue); - Context->ReloadStaticData(*Context, GlobalDebugServices); + Context->ReloadStaticData(*Context, GlobalDebugServices, AppReady); Success = true; + OutputDebugStringA("Reloaded DLL\n"); } else if(ShouldError) { @@ -609,20 +610,30 @@ WinMain ( if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1; - MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); - Win32UpdateWindowDimension(&MainWindow); - - win32_opengl_window_info OpenGLWindowInfo = {}; - OpenGLWindowInfo.ColorBits = 32; - OpenGLWindowInfo.AlphaBits = 8; - OpenGLWindowInfo.DepthBits = 0; - CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); - context Context = {}; Context.ThreadContext = ThreadContext; Context.MemorySize = MB(64); Context.MemoryBase = (u8*)Win32Alloc(Context.MemorySize, 0); + gs_const_string Args = ConstString((char*)CmdLineArgs); + if (StringsEqual(Args, ConstString("-headless"))) + { + OutputDebugStringA("Running Headless\n"); + Context.Headless = true; + } + + if (!Context.Headless) + { + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); + Win32UpdateWindowDimension(&MainWindow); + + win32_opengl_window_info OpenGLWindowInfo = {}; + OpenGLWindowInfo.ColorBits = 32; + OpenGLWindowInfo.AlphaBits = 8; + OpenGLWindowInfo.DepthBits = 0; + CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); + } + gs_memory_arena PlatformPermanent = CreateMemoryArena(Context.ThreadContext.Allocator, "Platform Memory"); s64 PerformanceCountFrequency = GetPerformanceFrequency(); @@ -657,7 +668,7 @@ WinMain ( *Context.SocketManager = CreatePlatformSocketManager(Win32ConnectSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend); win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); - if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true)) { return -1; } + if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true, false)) { return -1; } Mouse_Init(); @@ -708,42 +719,43 @@ WinMain ( ResetInputQueue(&InputQueue); - ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, false); + ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, false, true); AddressedDataBufferList_Clear(&OutputData); - Mouse_Update(MainWindow, &Context); - - MSG Message; - while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE)) + if (!Context.Headless) { - DEBUG_TRACK_SCOPE(PeekWindowsMessages); - HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); + Mouse_Update(MainWindow, &Context); + MSG Message; + while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE)) + { + DEBUG_TRACK_SCOPE(PeekWindowsMessages); + HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); + } + + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + RenderBuffer.ViewWidth = MainWindow.Width; + RenderBuffer.ViewHeight = MainWindow.Height; } - Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; - RenderBuffer.ViewWidth = MainWindow.Width; - RenderBuffer.ViewHeight = MainWindow.Height; Context.DeltaTime = LastFrameSecondsElapsed; - -#if 0 - gs_string T = PushStringF(Context.ThreadContext.Transient, 256, "%f\n", Context.DeltaTime); - NullTerminate(&T); - OutputDebugStringA(T.Str); -#endif + Context.TotalTime += (r64)Context.DeltaTime; Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); Win32_SendOutputData(ThreadContext, OutputData); - RenderCommandBuffer(RenderBuffer); - ClearRenderBuffer(&RenderBuffer); - - Mouse_Advance(&Context); - - HDC DeviceContext = GetDC(MainWindow.Handle); - SwapBuffers(DeviceContext); - ReleaseDC(MainWindow.Handle, DeviceContext); + if (!Context.Headless) + { + RenderCommandBuffer(RenderBuffer); + ClearRenderBuffer(&RenderBuffer); + + Mouse_Advance(&Context); + + HDC DeviceContext = GetDC(MainWindow.Handle); + SwapBuffers(DeviceContext); + ReleaseDC(MainWindow.Handle, DeviceContext); + } Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); @@ -767,8 +779,6 @@ WinMain ( Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext); Win32WorkQueue_Cleanup(); - //Win32_TestCode_SocketReading_Cleanup(); - Win32SocketSystem_Cleanup(); return 0; diff --git a/src/app/ss_blumen_lumen/blumen_lumen.cpp b/src/app/ss_blumen_lumen/blumen_lumen.cpp index 4b4d224..ee55776 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.cpp +++ b/src/app/ss_blumen_lumen/blumen_lumen.cpp @@ -194,28 +194,18 @@ BlumenLumen_LoadPatterns(app_state* State) } Patterns->Count = 0; - Patterns_PushPattern(Patterns, TestPatternOne, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, TestPatternTwo, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, TestPatternThree, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_AllGreen, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_HueShift, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_HueFade, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Spots, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_GrowAndFade, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_ColorToWhite, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Blue, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_Green, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_FlowerColors, PATTERN_MULTITHREADED); - Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Rainbow, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_BasicFlowers, PATTERN_MULTITHREADED); - // 15 Patterns_PushPattern(Patterns, Pattern_Wavy, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_Patchy, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_Leafy, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_LeafyPatchy, PATTERN_MULTITHREADED); Patterns_PushPattern(Patterns, Pattern_WavyPatchy, PATTERN_SINGLETHREADED); + Patterns_PushPattern(Patterns, Pattern_VerticalLines, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_Rotary, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_AllOnMask, PATTERN_MULTITHREADED); + Patterns_PushPattern(Patterns, Pattern_BulbMask, PATTERN_MULTITHREADED); } internal gs_data @@ -240,6 +230,8 @@ BlumenLumen_CustomInit(app_state* State, context Context) BLState->MicListenJobData.IncomingMsgQueue = &BLState->IncomingMsgQueue; BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue; + BLState->PatternSpeed = GlobalAnimSpeed; + #if 1 BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData); #endif @@ -267,38 +259,6 @@ BlumenLumen_CustomInit(app_state* State, context Context) &State->Permanent); #if 0 - { // Animation PLAYGROUND - animation_desc Desc = {}; - Desc.NameSize = 256; - Desc.LayersCount = 8; - Desc.BlocksCount = 8; - Desc.MinFrames = 0; - Desc.MaxFrames = SecondsToFrames(15, State->AnimationSystem); - - animation_desc Desc0 = Desc; - Desc.Name = "test_anim_zero"; - animation Anim0 = Animation_Create(Desc0, &State->AnimationSystem); - Animation_AddLayer(&Anim0, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); - Animation_AddBlock(&Anim0, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(15), 0); - BLState->AnimHandles[0] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim0); - - animation_desc Desc1 = Desc; - Desc1.Name = "test_anim_one"; - animation Anim1 = Animation_Create(Desc1, &State->AnimationSystem); - Animation_AddLayer(&Anim1, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); - Animation_AddBlock(&Anim1, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(12), 0); - BLState->AnimHandles[1] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim1); - - animation_desc Desc2 = Desc; - Desc2.Name = "i_love_you"; - animation Anim2 = Animation_Create(Desc2, &State->AnimationSystem);; - Animation_AddLayer(&Anim2, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem); - Animation_AddBlock(&Anim2, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(20), 0); - BLState->AnimHandles[2] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim2); - - State->AnimationSystem.ActiveFadeGroup.From = BLState->AnimHandles[2]; - } // End Animation Playground -#elif 0 animation_handle DemoPatternsAnim = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, @@ -307,6 +267,7 @@ BlumenLumen_CustomInit(app_state* State, context Context) #else BLState->ModeAnimations[BlumenPattern_Standard] = LoadAllAnimationsInDir(AmbientPatternFolder, BLState, State, Context); BLState->ModeAnimations[BlumenPattern_VoiceCommand] = LoadAllAnimationsInDir(VoicePatternFolder, BLState, State, Context); + AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem, State->Patterns, Context, ConstString("data/blumen_animations/anim_demo.foldanim")); BlumenLumen_SetPatternMode(BlumenPattern_Standard, 5, &State->AnimationSystem, BLState); #endif @@ -402,6 +363,20 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) } } + // Update next frames Hues + r32 AnimTime = AnimationSystem_GetCurrentTime(State->AnimationSystem); + AnimTime = (r32)Context->TotalTime; + r32 BaseTime = AnimTime * BLState->PatternSpeed; + + r32 ColorSpeed = 1; //.001; + r32 ColorOscSpeed = .05 * ColorSpeed; + r32 ColorRelOscSpeed = 1 * ColorSpeed;; + r32 ColorOscillation = (SinR32(BaseTime * ColorOscSpeed) + 1) / 2; + r32 ColorRelationship = 30 + (((1 + SinR32(BaseTime * ColorRelOscSpeed)) / 2) * 300); + BLState->StandardPatternHues.Hue0 = ModR32(ColorOscillation * 360, 360); + BLState->StandardPatternHues.Hue1 = ModR32(BaseTime + ColorRelationship, 360); + BLState->StandardPatternHues.Hue2 = LerpR32(.3f, BLState->StandardPatternHues.Hue0, BLState->StandardPatternHues.Hue1); + // Transition back to standard mode after some time if (BLState->PatternMode == BlumenPattern_VoiceCommand) { diff --git a/src/app/ss_blumen_lumen/blumen_lumen.h b/src/app/ss_blumen_lumen/blumen_lumen.h index 21d42c3..6dd55ac 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen.h +++ b/src/app/ss_blumen_lumen/blumen_lumen.h @@ -155,6 +155,7 @@ struct blumen_lumen_state system_time LastSendTime; + phrase_hue StandardPatternHues; phrase_hue AssemblyColors[BL_FLOWER_COUNT]; u32 LastAssemblyColorSet; @@ -172,6 +173,7 @@ struct blumen_lumen_state phrase_hue_map PhraseHueMap; system_time TimeLastSetToVoiceMode; + r32 PatternSpeed; // Debug motor_packet DEBUG_PendingMotorPacket; bool DEBUG_IgnoreWeatherDimmingLeds; @@ -179,6 +181,26 @@ struct blumen_lumen_state #include "message_queue.cpp" +internal phrase_hue +BlumenLumen_GetCurrentHue(blumen_lumen_state* BLState, assembly Assembly) +{ + phrase_hue Result = {}; + + switch (BLState->PatternMode) + { + case BlumenPattern_Standard: + { + Result = BLState->StandardPatternHues; + }break; + + case BlumenPattern_VoiceCommand: + { + Result = BLState->AssemblyColors[Assembly.AssemblyIndex % 3]; + }break; + } + + return Result; +} diff --git a/src/app/ss_blumen_lumen/blumen_lumen_settings.h b/src/app/ss_blumen_lumen/blumen_lumen_settings.h index 8fb514d..97b6686 100644 --- a/src/app/ss_blumen_lumen/blumen_lumen_settings.h +++ b/src/app/ss_blumen_lumen/blumen_lumen_settings.h @@ -126,4 +126,8 @@ r32 HighTemperatureBrightnessPercent = .25f; // lower it for heat reasons? r32 FullBrightnessPercent = 1.0f; +// A global modifier so Joerg can just slow all the patterns right down +// XD +r32 GlobalAnimSpeed = 1.0f; + #endif //BLUMEN_LUMEN_SETTINGS_H diff --git a/src/app/ss_blumen_lumen/sdf.h b/src/app/ss_blumen_lumen/sdf.h new file mode 100644 index 0000000..58e40e9 --- /dev/null +++ b/src/app/ss_blumen_lumen/sdf.h @@ -0,0 +1,20 @@ +/* date = March 29th 2021 10:41 pm */ + +#ifndef SDF_H +#define SDF_H + +internal r32 +SDF_Sphere(v3 Point, v3 Center, r32 Radius) +{ + r32 Result = V3Mag(Point - Center) - Radius; + return Result; +} + +internal r32 +SDF_SphereNormalized(v3 Point, v3 Center, r32 Radius) +{ + r32 Result = SDF_Sphere(Point, Center, Radius) / Radius; + return Result; +} + +#endif //SDF_H diff --git a/src/sculpture_gen/gen_blumen_lumen.cpp b/src/sculpture_gen/gen_blumen_lumen.cpp index 4555311..a93f79d 100644 --- a/src/sculpture_gen/gen_blumen_lumen.cpp +++ b/src/sculpture_gen/gen_blumen_lumen.cpp @@ -106,8 +106,8 @@ BuildFlower(gs_string* OutputBuffer, flower_desc Desc) #if 1 // the bloom stem inner loop_desc BloomStemInner = {}; - BloomStemInner.CenterStart = v3{0, 1.4f, 0} + Desc.Pos; - BloomStemInner.CenterEnd = v3{0, .9f, 0} + Desc.Pos; + BloomStemInner.CenterStart = v3{0, 1.4f, 0}; + BloomStemInner.CenterEnd = v3{0, .9f, 0}; BloomStemInner.Radius = .05f; BloomStemInner.SegmentsCount = 6; BloomStemInner.SubsegmentsCount = 3; @@ -120,8 +120,8 @@ BuildFlower(gs_string* OutputBuffer, flower_desc Desc) // the bloom stem outer loop_desc BloomStemOuter = {}; - BloomStemOuter.CenterStart = v3{0, .5f, 0} + Desc.Pos; - BloomStemOuter.CenterEnd = v3{0, .9f, 0} + Desc.Pos; + BloomStemOuter.CenterStart = v3{0, .5f, 0}; + BloomStemOuter.CenterEnd = v3{0, .9f, 0}; BloomStemOuter.Radius = .07f; BloomStemOuter.SegmentsCount = 9; BloomStemOuter.SubsegmentsCount = 3; @@ -136,8 +136,8 @@ BuildFlower(gs_string* OutputBuffer, flower_desc Desc) #if 1 // the flower stem loop_desc FlowerStem = {}; - FlowerStem.CenterStart = v3{0, -1.5f, 0} + Desc.Pos; - FlowerStem.CenterEnd = v3{0, .5f, 0} + Desc.Pos; + FlowerStem.CenterStart = v3{0, -1.5f, 0}; + FlowerStem.CenterEnd = v3{0, .5f, 0}; FlowerStem.Radius = .05f; FlowerStem.SegmentsCount = 6; FlowerStem.SubsegmentsCount = 1; @@ -182,7 +182,7 @@ int main(int ArgCount, char** Args) WriteAssemblyUARTOpen(&OutputBuffer0, "Blumen Lumen - Silver Spring - 00", 100, - v3{0, 0, 0}, + v3{-1, 0, 0}, 21, ""); WriteAssemblyUARTOpen(&OutputBuffer1, @@ -194,7 +194,7 @@ int main(int ArgCount, char** Args) WriteAssemblyUARTOpen(&OutputBuffer2, "Blumen Lumen - Silver Spring - 02", 100, - v3{0, 0, 0}, + v3{1, 0, 0}, 21, ""); @@ -204,7 +204,7 @@ int main(int ArgCount, char** Args) u32 BloomOuterChannels[] = { FSC(1, 0), FSC(1, 1), FSC(1, 2), FSC(1, 3), FSC(1, 4), FSC(1, 5), FSC(1, 6), FSC(1, 7), FSC(2, 0) }; u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) }; flower_desc F0 = {}; - F0.Pos = v3{-1, 0, 0}; + F0.Pos = v3{0, 0, 0}; F0.ComPort = "\\\\.\\COM11"; F0.FlowerTagValue = "left"; F0.StemChannels = StemChannels; @@ -222,7 +222,7 @@ int main(int ArgCount, char** Args) StripCount += BuildFlower(&OutputBuffer1, F1); flower_desc F2 = {}; - F2.Pos = v3{1, 0, 0}; + F2.Pos = v3{0, 0, 0}; F2.ComPort = "\\\\.\\COM6"; F2.FlowerTagValue = "right"; F2.StemChannels = StemChannels;