From 9973cf4ed9976ddae8f1b161ee8179edbf984aa5 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 30 Dec 2019 20:26:28 -0800 Subject: [PATCH] Incorporated a new *shudders* c++ template based list implementation. Hopefully I can stop writing list implementations now --- src/animation/foldhaus_animation.h | 108 +----------- src/foldhaus_app.cpp | 29 ++-- src/foldhaus_app.h | 6 +- src/foldhaus_assembly.cpp | 16 +- src/foldhaus_assembly.h | 2 - src/foldhaus_platform.h | 4 +- .../foldhaus_panel_animation_timeline.h | 51 +++--- src/panels/foldhaus_panel_hierarchy.h | 8 +- src/panels/foldhaus_panel_node_graph.h | 164 ++++++++++++++---- src/panels/foldhaus_panel_sculpture_view.h | 6 +- 10 files changed, 182 insertions(+), 212 deletions(-) diff --git a/src/animation/foldhaus_animation.h b/src/animation/foldhaus_animation.h index 064402b..3044ef0 100644 --- a/src/animation/foldhaus_animation.h +++ b/src/animation/foldhaus_animation.h @@ -17,27 +17,11 @@ struct animation_block u32 Layer; }; -struct animation_block_handle -{ - s32 Index; - // NOTE(Peter): Zero is invalid - u32 Generation; -}; - -struct animation_block_entry -{ - u32 Generation; - animation_block Block; - free_list Free; -}; - #define ANIMATION_SYSTEM_LAYERS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system { - animation_block_entry Blocks[ANIMATION_SYSTEM_BLOCKS_MAX]; - free_list FreeList; - u32 BlocksCount; + gs_list Blocks; r32 Time; s32 LastUpdatedFrame; @@ -50,98 +34,8 @@ struct animation_system r32 AnimationEnd; }; -internal b32 -AnimationBlockHandlesAreEqual(animation_block_handle A, animation_block_handle B) -{ - b32 Result = ((A.Index == B.Index) && (A.Generation == B.Generation)); - return Result; -} - -internal b32 -AnimationBlockHandleIsValid(animation_block_handle Handle) -{ - b32 Result = Handle.Generation != 0; - return Result; -} - internal void InitializeAnimationSystem(animation_system* System) { *System = {0}; - System->FreeList.Next = &System->FreeList; -} - -inline b32 -AnimationBlockIsFree(animation_block_entry Entry) -{ - // NOTE(Peter): If we've set Free.Next to zero, we've removed it from the - // free list. - b32 Result = Entry.Free.Next != 0; - return Result; -} - -internal animation_block_entry* -GetEntryAtIndex(u32 Index, animation_system* System) -{ - Assert(Index < System->BlocksCount); - animation_block_entry* Result = System->Blocks + Index; - return Result; -} - -internal animation_block* -GetAnimationBlockWithHandle(animation_block_handle Handle, animation_system* System) -{ - animation_block* Result = 0; - animation_block_entry* Entry = GetEntryAtIndex(Handle.Index, System); - if (Entry && Entry->Generation == Handle.Generation) - { - Result = &Entry->Block; - } - return Result; -} - -internal animation_block_handle -AddAnimationBlock(animation_block Block, animation_system* System) -{ - animation_block_handle Result = {0}; - - if (System->FreeList.Next != 0 - && System->FreeList.Next != &System->FreeList) - { - free_list* FreeEntry = System->FreeList.Next; - Result.Index = FreeEntry->Index; - System->FreeList.Next = FreeEntry->Next; - } - else - { - Assert(System->BlocksCount < ANIMATION_SYSTEM_BLOCKS_MAX); - Result.Index = System->BlocksCount++; - } - - animation_block_entry* Entry = GetEntryAtIndex(Result.Index, System); - Entry->Generation += 1; - Result.Generation = Entry->Generation; - System->Blocks[Result.Index].Block = Block; - System->Blocks[Result.Index].Free.Next = 0; - - return Result; -} - -internal void -RemoveAnimationBlock(animation_block_handle Handle, animation_system* System) -{ - animation_block_entry* Entry = GetEntryAtIndex(Handle.Index, System); - - // NOTE(Peter): I'm pretty sure this doesn't need to be an assert but at the moment, there - // is no reason why we shouldn't always be able to remove an entry when we request it. - // For now, I'm putting this assert here so we deal with this intentionally when the first - // case comes up. - // TODO: When we do deal with the above note, I'm guessing we want to return true or false - // to signal if we were able to remove the entry or not so that the calling site can deal - // with the removed reference - Assert(Handle.Generation == Entry->Generation); - - Entry->Free.Index = Handle.Index; - Entry->Free.Next = System->FreeList.Next; - System->FreeList.Next = &Entry->Free; } diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 7300131..9e5c584 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -162,9 +162,6 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Camera.Position = v3{0, 0, -250}; State->Camera.LookAt = v3{0, 0, 0}; - State->AssemblyList.BucketSize = 32; - State->AssemblyList.FreeList.Next = &State->AssemblyList.FreeList; - State->ActiveAssemblyIndecies.BucketSize = 32; #if 1 char Path[] = "radialumia.fold"; LoadAssembly(State, Context, Path); @@ -331,19 +328,19 @@ UPDATE_AND_RENDER(UpdateAndRender) State->AnimationSystem.LastUpdatedFrame = CurrentFrame; r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; - for (u32 i = 0; i < State->AnimationSystem.BlocksCount; i++) + for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) { - animation_block_entry BlockEntry = State->AnimationSystem.Blocks[i]; - if (!AnimationBlockIsFree(BlockEntry)) + gs_list_entry* BlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i); + if (!EntryIsFree(BlockEntry)) { - animation_block Block = BlockEntry.Block; + animation_block Block = BlockEntry->Value; if (State->AnimationSystem.Time >= Block.StartTime && State->AnimationSystem.Time <= Block.EndTime) { - for (s32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++) + for (u32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++) { - array_entry_handle* AssemblyHandle = GetElementAtIndex(j, State->ActiveAssemblyIndecies); - assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); + gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j); + assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); Block.Proc(Assembly, FrameTime - Block.StartTime); } } @@ -353,10 +350,10 @@ UPDATE_AND_RENDER(UpdateAndRender) s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - array_entry_handle* AssemblyHandle = GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); + gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); + assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } @@ -411,10 +408,10 @@ UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_SCOPE(OverflowChecks); AssertAllocationsNoOverflow(State->Permanent); - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - array_entry_handle* AssemblyHandle = GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); + gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); + assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle); AssertAllocationsNoOverflow(Assembly->Arena); } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index c535528..e5be6f4 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -53,8 +53,8 @@ struct app_state streaming_acn SACN; s32 TotalLEDsCount; - assembly_array AssemblyList; - array_entry_handle_contiguous_array ActiveAssemblyIndecies; + gs_list AssemblyList; + gs_list ActiveAssemblyIndecies; camera Camera; r32 PixelsToWorldScale; @@ -66,7 +66,7 @@ struct app_state interface_config Interface; animation_system AnimationSystem; - animation_block_handle SelectedAnimationBlockHandle; + gs_list_handle SelectedAnimationBlockHandle; panel_system PanelSystem; panel* HotPanel; diff --git a/src/foldhaus_assembly.cpp b/src/foldhaus_assembly.cpp index 4a39d04..282b0f1 100644 --- a/src/foldhaus_assembly.cpp +++ b/src/foldhaus_assembly.cpp @@ -91,26 +91,26 @@ LoadAssembly (app_state* State, context Context, char* Path) Offset, Scale, AssemblyArena); - array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); - PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); + gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly); + State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle); State->TotalLEDsCount += NewAssembly.LEDCount; } internal void -UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) +UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context) { - assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); + assembly* Assembly = State->AssemblyList.GetElementAtIndex(AssemblyIndex); State->TotalLEDsCount -= Assembly->LEDCount; FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); - RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + State->AssemblyList.FreeElementAtIndex(AssemblyIndex); + for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + gs_list_handle Handle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); if (Handle.Index == AssemblyIndex) { - RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); + State->ActiveAssemblyIndecies.FreeElementAtIndex(i); break; } } diff --git a/src/foldhaus_assembly.h b/src/foldhaus_assembly.h index 637ae5f..62ac818 100644 --- a/src/foldhaus_assembly.h +++ b/src/foldhaus_assembly.h @@ -36,5 +36,3 @@ struct assembly s32 LEDUniverseMapCount; leds_in_universe_range* LEDUniverseMap; }; - -TYPEDEF_ARRAY(assembly); diff --git a/src/foldhaus_platform.h b/src/foldhaus_platform.h index 58e4d16..fab1f86 100644 --- a/src/foldhaus_platform.h +++ b/src/foldhaus_platform.h @@ -1,7 +1,9 @@ +#include + #define GS_LANGUAGE_NO_PROFILER_DEFINES #include #include "gs_platform.h" -#include "gs_array.h" +#include #define GS_MEMORY_TRACK_ALLOCATIONS #define GS_MEMORY_NO_STD_LIBS diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h index 1e496b0..73cbc55 100644 --- a/src/panels/foldhaus_panel_animation_timeline.h +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -39,7 +39,7 @@ AddAnimationBlock(r32 StartTime, r32 EndTime, animation_proc* Proc, animation_sy NewBlock.StartTime = StartTime; NewBlock.EndTime = EndTime; NewBlock.Proc = Proc; - AddAnimationBlock(NewBlock, AnimationSystem); + AnimationSystem->Blocks.PushElementOnList(NewBlock); } #define NEW_ANIMATION_BLOCK_DURATION 3 @@ -51,14 +51,14 @@ AddAnimationBlockAtCurrentTime (animation_proc* Proc, animation_system* System) } internal void -DeleteAnimationBlock(animation_block_handle AnimationBlockHandle, app_state* State) +DeleteAnimationBlock(gs_list_handle AnimationBlockHandle, app_state* State) { - RemoveAnimationBlock(State->SelectedAnimationBlockHandle, &State->AnimationSystem); + State->AnimationSystem.Blocks.FreeElementWithHandle(AnimationBlockHandle); State->SelectedAnimationBlockHandle = {0}; } internal void -SelectAnimationBlock(animation_block_handle BlockHandle, app_state* State) +SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State) { State->SelectedAnimationBlockHandle = BlockHandle; } @@ -71,10 +71,7 @@ DeselectCurrentAnimationBlock(app_state* State) FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) { - if (AnimationBlockHandleIsValid(State->SelectedAnimationBlockHandle)) - { - DeleteAnimationBlock(State->SelectedAnimationBlockHandle, State); - } + DeleteAnimationBlock(State->SelectedAnimationBlockHandle, State); } // @@ -145,7 +142,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) r32 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame); r32 TimeOffset = TimeAtMouseX - TimeAtMouseDownX; - animation_block* AnimationBlock = GetAnimationBlockWithHandle(State->SelectedAnimationBlockHandle, &State->AnimationSystem); + animation_block* AnimationBlock = State->AnimationSystem.Blocks.GetElementWithHandle(State->SelectedAnimationBlockHandle); if (GSAbs(Mouse.DownPos.x - ClipInitialStartTimeXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) { @@ -162,17 +159,12 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) } } -FOLDHAUS_INPUT_COMMAND_PROC(EndDragAnimationClip) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - input_command DragAnimationClipCommands [] = { - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDragAnimationClip }, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndCurrentOperationMode }, }; internal void -SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelStartFrame, s32 PanelEndFrame, rect TimelineBounds, app_state* State) +SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, s32 PanelStartFrame, s32 PanelEndFrame, rect TimelineBounds, app_state* State) { SelectAnimationBlock(BlockHandle, State); @@ -185,7 +177,7 @@ SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelSt OpState->AnimationPanel_StartFrame = PanelStartFrame; OpState->AnimationPanel_EndFrame = PanelEndFrame ; - animation_block* SelectedBlock = GetAnimationBlockWithHandle(BlockHandle, &State->AnimationSystem); + animation_block* SelectedBlock = State->AnimationSystem.Blocks.GetElementWithHandle(BlockHandle); OpState->SelectedClip_InitialStartTime = SelectedBlock->StartTime; OpState->SelectedClip_InitialEndTime = SelectedBlock->EndTime; } @@ -205,7 +197,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand) Block.EndTime = NewBlockTimeEnd; Block.Proc = TestPatternThree; - animation_block_handle NewBlockHandle = AddAnimationBlock(Block, &State->AnimationSystem); + gs_list_handle NewBlockHandle = State->AnimationSystem.Blocks.PushElementOnList(Block); SelectAnimationBlock(NewBlockHandle, State); } @@ -288,13 +280,13 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPe return BlockBounds; } -internal animation_block_handle -DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, rect PanelBounds, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) +internal gs_list_handle +DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, rect PanelBounds, gs_list_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) { string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); s32 FrameCount = EndFrame - StartFrame; - animation_block_handle Result = SelectedBlockHandle; + gs_list_handle Result = SelectedBlockHandle; r32 AnimationPanelHeight = PanelBounds.Max.y - PanelBounds.Min.y; r32 AnimationPanelWidth = PanelBounds.Max.x - PanelBounds.Min.x; @@ -318,19 +310,16 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En // Animation Blocks rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} }; b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); - for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) + for (u32 i = 0; i < AnimationSystem->Blocks.Used; i++) { - animation_block_entry* AnimationBlockEntry = GetEntryAtIndex(i, AnimationSystem); - if (AnimationBlockIsFree(*AnimationBlockEntry)) { continue; } + gs_list_entry* AnimationBlockEntry = AnimationSystem->Blocks.GetEntryAtIndex(i); + if (AnimationBlockEntry->Free.NextFreeEntry != 0) { continue; } - animation_block_handle CurrentBlockHandle = {}; - CurrentBlockHandle.Index = i; - CurrentBlockHandle.Generation = AnimationBlockEntry->Generation; - - animation_block AnimationBlockAt = AnimationBlockEntry->Block; + gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle; + animation_block AnimationBlockAt = AnimationBlockEntry->Value; v4 BlockColor = BlackV4; - if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + if (GSListHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) { BlockColor = PinkV4; } @@ -425,7 +414,7 @@ DrawAnimationClipsList(rect PanelBounds, mouse_state Mouse, render_command_buffe PANEL_RENDER_PROC(AnimationTimeline_Render) { - animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; + gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; r32 OptionsRowHeight = 25; rect AnimationClipListBounds = rect{ diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h index 529d3c7..d659461 100644 --- a/src/panels/foldhaus_panel_hierarchy.h +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -31,15 +31,15 @@ PANEL_RENDER_PROC(HierarchyView_Render) v2 TextOffset = v2{10, 4}; string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); - s32 LineCount = (s32)(PanelHeight / List.ListElementDimensions.y) + 1; - for (s32 i = 0; i < LineCount; i++) + u32 LineCount = (u32)(PanelHeight / List.ListElementDimensions.y) + 1; + for (u32 i = 0; i < LineCount; i++) { rect ElementBounds = DrawListElementBackground(&List, Mouse, RenderBuffer); if (i < State->ActiveAssemblyIndecies.Used) { - array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); + assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle); PrintF(&TempString, "%S", Assembly.Name); DrawString(RenderBuffer, TempString, State->Interface.Font, ElementBounds.Min + TextOffset, WhiteV4); diff --git a/src/panels/foldhaus_panel_node_graph.h b/src/panels/foldhaus_panel_node_graph.h index 102e74b..2a8b24e 100644 --- a/src/panels/foldhaus_panel_node_graph.h +++ b/src/panels/foldhaus_panel_node_graph.h @@ -4,6 +4,53 @@ struct node_graph_state }; +struct temp_node_connection +{ + u32 DownstreamNodeIndex; + u32 DownstreamNodePort; + + u32 UpstreamNodeIndex; + u32 UpstreamNodePort; +}; + +struct visual_node +{ + node_specification Spec; + v2 Position; +}; + +#define TEMP_NODE_LIST_MAX 10 +global_variable u32 TEMP_NodeListUsed = 0; +global_variable node_specification TEMP_NodeList[TEMP_NODE_LIST_MAX]; + +#define TEMP_CONNECTIONS_LIST_MAX 10 +global_variable u32 TEMP_NodeConnectionsUsed = 0; +global_variable temp_node_connection TEMP_NodeConnections[TEMP_CONNECTIONS_LIST_MAX]; + +internal void +PushNodeOnNodeList(node_specification Spec) +{ + if (TEMP_NodeListUsed < TEMP_NODE_LIST_MAX) + { + u32 Index = TEMP_NodeListUsed++; + TEMP_NodeList[Index] = Spec; + } +} + +internal void +PushConnectionOnConnectionsList(u32 UpstreamNodeIndex, u32 UpstreamNodePort, u32 DownstreamNodeIndex, u32 DownstreamNodePort) +{ + if (TEMP_NodeConnectionsUsed < TEMP_CONNECTIONS_LIST_MAX) + { + u32 Index = TEMP_NodeConnectionsUsed++; + TEMP_NodeConnections[Index].DownstreamNodeIndex = DownstreamNodeIndex; + TEMP_NodeConnections[Index].DownstreamNodePort = DownstreamNodePort; + TEMP_NodeConnections[Index].UpstreamNodeIndex = UpstreamNodeIndex; + TEMP_NodeConnections[Index].UpstreamNodePort = UpstreamNodePort;; + } +} + + // // Pan Node Graph // @@ -39,6 +86,41 @@ FOLDHAUS_INPUT_COMMAND_PROC(BeginPanNodeGraph) OpState->ViewOffset = &NodeGraphState->ViewOffset; } +// +// Connect Nodes +// + +OPERATION_STATE_DEF(connect_nodes_operation_state) +{ + u32 NodeIndex; + u32 PortIndex; +}; + +OPERATION_RENDER_PROC(UpdateConnectNodeOperation) +{ + +} + +FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation) +{ + connect_nodes_operation_state* OpState = GetCurrentOperationState(State->Modes, connect_nodes_operation_state); + + EndCurrentOperationMode(State, Event, Mouse); +} + +input_command ConnectNodesOperationCommands[] = { + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, EndConnectNodesOperation }, +}; + +internal void +BeginConnectNodesOperation(u32 NodeIndex, u32 PortIndex, app_state* State) +{ + operation_mode* ConnectNodesOperation = ActivateOperationModeWithCommands(&State->Modes, ConnectNodesOperationCommands, UpdateConnectNodeOperation); + connect_nodes_operation_state* OpState = CreateOperationState(ConnectNodesOperation, &State->Modes, connect_nodes_operation_state); + OpState->NodeIndex = NodeIndex; + OpState->PortIndex = PortIndex; +} + // // Node Graph Panel // @@ -96,9 +178,13 @@ DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* } -internal void -DrawNodePorts(node_specification Spec, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer) +internal s32 +DrawNodePorts(node_specification Spec, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) { + s32 PortClicked = -1; + + rect PortBounds = rect{v2{0, 0}, v2{6, 6}}; + v2 LinePosition = Position; for (u32 i = 0; i < Spec.MemberListLength; i++) { @@ -108,15 +194,36 @@ DrawNodePorts(node_specification Spec, b32 InputMask, v2 Position, r32 LineHeigh string MemberName = MakeString(Member.Name, CharArrayLength(Member.Name)); DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign); + rect PositionedPortBounds = PortBounds; + PositionedPortBounds.Min += LinePosition + v2{0, LineHeight / 4}; + PositionedPortBounds.Max += LinePosition + v2{0, LineHeight / 4}; + if (TextAlign == Align_Left) + { + PositionedPortBounds.Min -= v2{PortBounds.Max.x, 0}; + PositionedPortBounds.Max -= v2{PortBounds.Max.x, 0}; + } + + + PushRenderQuad2D(RenderBuffer, PositionedPortBounds.Min, PositionedPortBounds.Max, WhiteV4); + + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) + && PointIsInRect(Mouse.DownPos, PositionedPortBounds)) + { + PortClicked = i; + } + LinePosition.y -= LineHeight; } } + return PortClicked; } -internal void -DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer) +internal s32 +DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) { + s32 PortClicked = -1; + u32 InputMembers = 0; u32 OutputMembers = 0; for (u32 i = 0; i < NodeSpecification.MemberListLength; i++) @@ -147,44 +254,23 @@ DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32 LinePosition.y -= LineHeight; // Draw Ports - DrawNodePorts(NodeSpecification, IsInputMember, LinePosition, LineHeight, Align_Left, TextOffset, Interface, RenderBuffer); + s32 InputPortClicked = DrawNodePorts(NodeSpecification, IsInputMember, LinePosition, LineHeight, Align_Left, TextOffset, Interface, RenderBuffer, Mouse); v2 OutputLinePosition = v2{LinePosition.x + NodeDim.x, LinePosition.y }; v2 OutputTextOffset = v2{-TextOffset.x, TextOffset.y}; - DrawNodePorts(NodeSpecification, IsOutputMember, OutputLinePosition, LineHeight, Align_Right, OutputTextOffset, Interface, RenderBuffer); -} - -struct temp_node_connection -{ - u32 DownstreamNodeIndex; - u32 DownstreamNodePort; + s32 OutputPortClicked = DrawNodePorts(NodeSpecification, IsOutputMember, OutputLinePosition, LineHeight, Align_Right, OutputTextOffset, Interface, RenderBuffer, Mouse); - u32 UpstreamNodeIndex; - u32 UpstreamNodePort; -}; - -struct visual_node -{ - node_specification Spec; - v2 Position; -}; - -#define TEMP_NODE_LIST_MAX 10 -global_variable u32 TEMP_NodeListUsed = 0; -global_variable node_specification TEMP_NodeList[TEMP_NODE_LIST_MAX]; - -#define TEMP_CONNECTIONS_LIST_MAX 10 -global_variable u32 TEMP_NodeConnectionsUsed = 0; -global_variable temp_node_connection TEMP_NodeConnections[TEMP_CONNECTIONS_LIST_MAX]; - -internal void -PushNodeOnNodeList(node_specification Spec) -{ - if (TEMP_NodeListUsed < TEMP_NODE_LIST_MAX) + + if (InputPortClicked >= 0) { - u32 Index = TEMP_NodeListUsed++; - TEMP_NodeList[Index] = Spec; + PortClicked = InputPortClicked; } + else if (OutputPortClicked >= 0) + { + PortClicked = OutputPortClicked; + } + + return PortClicked; } internal visual_node* @@ -270,7 +356,11 @@ PANEL_RENDER_PROC(NodeGraph_Render) for (u32 i = 0; i < TEMP_NodeListUsed; i++) { visual_node VisualNode = VisualNodes[i]; - DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeWidth, LineHeight, State->Interface, RenderBuffer); + s32 PortClicked = DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeWidth, LineHeight, State->Interface, RenderBuffer, Mouse); + if (PortClicked >= 0) + { + BeginConnectNodesOperation(i, PortClicked, State); + } } // Node Selection Panel diff --git a/src/panels/foldhaus_panel_sculpture_view.h b/src/panels/foldhaus_panel_sculpture_view.h index c9dc032..b9f7809 100644 --- a/src/panels/foldhaus_panel_sculpture_view.h +++ b/src/panels/foldhaus_panel_sculpture_view.h @@ -138,10 +138,10 @@ PANEL_RENDER_PROC(SculptureView_Render) s32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i); + assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle); s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); for (s32 Job = 0; Job < JobsNeeded; Job++)