Incorporated a new *shudders* c++ template based list implementation. Hopefully I can stop writing list implementations now

This commit is contained in:
Peter Slattery 2019-12-30 20:26:28 -08:00
parent c5404e3296
commit 9973cf4ed9
10 changed files with 182 additions and 212 deletions

View File

@ -17,27 +17,11 @@ struct animation_block
u32 Layer; 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_LAYERS_MAX 128
#define ANIMATION_SYSTEM_BLOCKS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128
struct animation_system struct animation_system
{ {
animation_block_entry Blocks[ANIMATION_SYSTEM_BLOCKS_MAX]; gs_list<animation_block> Blocks;
free_list FreeList;
u32 BlocksCount;
r32 Time; r32 Time;
s32 LastUpdatedFrame; s32 LastUpdatedFrame;
@ -50,98 +34,8 @@ struct animation_system
r32 AnimationEnd; 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 internal void
InitializeAnimationSystem(animation_system* System) InitializeAnimationSystem(animation_system* System)
{ {
*System = {0}; *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;
} }

View File

@ -162,9 +162,6 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->Camera.Position = v3{0, 0, -250}; State->Camera.Position = v3{0, 0, -250};
State->Camera.LookAt = v3{0, 0, 0}; State->Camera.LookAt = v3{0, 0, 0};
State->AssemblyList.BucketSize = 32;
State->AssemblyList.FreeList.Next = &State->AssemblyList.FreeList;
State->ActiveAssemblyIndecies.BucketSize = 32;
#if 1 #if 1
char Path[] = "radialumia.fold"; char Path[] = "radialumia.fold";
LoadAssembly(State, Context, Path); LoadAssembly(State, Context, Path);
@ -331,19 +328,19 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->AnimationSystem.LastUpdatedFrame = CurrentFrame; State->AnimationSystem.LastUpdatedFrame = CurrentFrame;
r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; 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]; gs_list_entry<animation_block>* BlockEntry = State->AnimationSystem.Blocks.GetEntryAtIndex(i);
if (!AnimationBlockIsFree(BlockEntry)) if (!EntryIsFree(BlockEntry))
{ {
animation_block Block = BlockEntry.Block; animation_block Block = BlockEntry->Value;
if (State->AnimationSystem.Time >= Block.StartTime if (State->AnimationSystem.Time >= Block.StartTime
&& State->AnimationSystem.Time <= Block.EndTime) && 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); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(j);
assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
Block.Proc(Assembly, FrameTime - Block.StartTime); Block.Proc(Assembly, FrameTime - Block.StartTime);
} }
} }
@ -353,10 +350,10 @@ UPDATE_AND_RENDER(UpdateAndRender)
s32 HeaderSize = State->NetworkProtocolHeaderSize; s32 HeaderSize = State->NetworkProtocolHeaderSize;
dmx_buffer_list* DMXBuffers = 0; 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); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient); dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient);
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
} }
@ -411,10 +408,10 @@ UPDATE_AND_RENDER(UpdateAndRender)
{ {
DEBUG_TRACK_SCOPE(OverflowChecks); DEBUG_TRACK_SCOPE(OverflowChecks);
AssertAllocationsNoOverflow(State->Permanent); 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); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
AssertAllocationsNoOverflow(Assembly->Arena); AssertAllocationsNoOverflow(Assembly->Arena);
} }
} }

View File

@ -53,8 +53,8 @@ struct app_state
streaming_acn SACN; streaming_acn SACN;
s32 TotalLEDsCount; s32 TotalLEDsCount;
assembly_array AssemblyList; gs_list<assembly> AssemblyList;
array_entry_handle_contiguous_array ActiveAssemblyIndecies; gs_list<gs_list_handle> ActiveAssemblyIndecies;
camera Camera; camera Camera;
r32 PixelsToWorldScale; r32 PixelsToWorldScale;
@ -66,7 +66,7 @@ struct app_state
interface_config Interface; interface_config Interface;
animation_system AnimationSystem; animation_system AnimationSystem;
animation_block_handle SelectedAnimationBlockHandle; gs_list_handle SelectedAnimationBlockHandle;
panel_system PanelSystem; panel_system PanelSystem;
panel* HotPanel; panel* HotPanel;

View File

@ -91,26 +91,26 @@ LoadAssembly (app_state* State, context Context, char* Path)
Offset, Offset,
Scale, Scale,
AssemblyArena); AssemblyArena);
array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly);
PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
State->TotalLEDsCount += NewAssembly.LEDCount; State->TotalLEDsCount += NewAssembly.LEDCount;
} }
internal void 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; State->TotalLEDsCount -= Assembly->LEDCount;
FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree);
RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); State->AssemblyList.FreeElementAtIndex(AssemblyIndex);
for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) 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) if (Handle.Index == AssemblyIndex)
{ {
RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); State->ActiveAssemblyIndecies.FreeElementAtIndex(i);
break; break;
} }
} }

View File

@ -36,5 +36,3 @@ struct assembly
s32 LEDUniverseMapCount; s32 LEDUniverseMapCount;
leds_in_universe_range* LEDUniverseMap; leds_in_universe_range* LEDUniverseMap;
}; };
TYPEDEF_ARRAY(assembly);

View File

@ -1,7 +1,9 @@
#include <windows.h>
#define GS_LANGUAGE_NO_PROFILER_DEFINES #define GS_LANGUAGE_NO_PROFILER_DEFINES
#include <gs_language.h> #include <gs_language.h>
#include "gs_platform.h" #include "gs_platform.h"
#include "gs_array.h" #include <gs_list.h>
#define GS_MEMORY_TRACK_ALLOCATIONS #define GS_MEMORY_TRACK_ALLOCATIONS
#define GS_MEMORY_NO_STD_LIBS #define GS_MEMORY_NO_STD_LIBS

View File

@ -39,7 +39,7 @@ AddAnimationBlock(r32 StartTime, r32 EndTime, animation_proc* Proc, animation_sy
NewBlock.StartTime = StartTime; NewBlock.StartTime = StartTime;
NewBlock.EndTime = EndTime; NewBlock.EndTime = EndTime;
NewBlock.Proc = Proc; NewBlock.Proc = Proc;
AddAnimationBlock(NewBlock, AnimationSystem); AnimationSystem->Blocks.PushElementOnList(NewBlock);
} }
#define NEW_ANIMATION_BLOCK_DURATION 3 #define NEW_ANIMATION_BLOCK_DURATION 3
@ -51,14 +51,14 @@ AddAnimationBlockAtCurrentTime (animation_proc* Proc, animation_system* System)
} }
internal void 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}; State->SelectedAnimationBlockHandle = {0};
} }
internal void internal void
SelectAnimationBlock(animation_block_handle BlockHandle, app_state* State) SelectAnimationBlock(gs_list_handle BlockHandle, app_state* State)
{ {
State->SelectedAnimationBlockHandle = BlockHandle; State->SelectedAnimationBlockHandle = BlockHandle;
} }
@ -71,10 +71,7 @@ DeselectCurrentAnimationBlock(app_state* State)
FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) 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 TimeAtMouseX = GetTimeFromPointInAnimationPanel(Mouse.Pos, OpState->TimelineBounds, OpState->AnimationPanel_StartFrame, OpState->AnimationPanel_EndFrame, State->AnimationSystem.SecondsPerFrame);
r32 TimeOffset = TimeAtMouseX - TimeAtMouseDownX; 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) 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 [] = { input_command DragAnimationClipCommands [] = {
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDragAnimationClip }, { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndCurrentOperationMode },
}; };
internal void 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); SelectAnimationBlock(BlockHandle, State);
@ -185,7 +177,7 @@ SelectAndBeginDragAnimationBlock(animation_block_handle BlockHandle, s32 PanelSt
OpState->AnimationPanel_StartFrame = PanelStartFrame; OpState->AnimationPanel_StartFrame = PanelStartFrame;
OpState->AnimationPanel_EndFrame = PanelEndFrame ; 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_InitialStartTime = SelectedBlock->StartTime;
OpState->SelectedClip_InitialEndTime = SelectedBlock->EndTime; OpState->SelectedClip_InitialEndTime = SelectedBlock->EndTime;
} }
@ -205,7 +197,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
Block.EndTime = NewBlockTimeEnd; Block.EndTime = NewBlockTimeEnd;
Block.Proc = TestPatternThree; Block.Proc = TestPatternThree;
animation_block_handle NewBlockHandle = AddAnimationBlock(Block, &State->AnimationSystem); gs_list_handle NewBlockHandle = State->AnimationSystem.Blocks.PushElementOnList(Block);
SelectAnimationBlock(NewBlockHandle, State); SelectAnimationBlock(NewBlockHandle, State);
} }
@ -288,13 +280,13 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPe
return BlockBounds; return BlockBounds;
} }
internal animation_block_handle internal gs_list_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) 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); string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
s32 FrameCount = EndFrame - StartFrame; s32 FrameCount = EndFrame - StartFrame;
animation_block_handle Result = SelectedBlockHandle; gs_list_handle Result = SelectedBlockHandle;
r32 AnimationPanelHeight = PanelBounds.Max.y - PanelBounds.Min.y; r32 AnimationPanelHeight = PanelBounds.Max.y - PanelBounds.Min.y;
r32 AnimationPanelWidth = PanelBounds.Max.x - PanelBounds.Min.x; r32 AnimationPanelWidth = PanelBounds.Max.x - PanelBounds.Min.x;
@ -318,19 +310,16 @@ DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 En
// Animation Blocks // Animation Blocks
rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} }; rect TimelineBounds = rect{ PanelBounds.Min, v2{PanelBounds.Max.x, FrameBarBottom} };
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); 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); gs_list_entry<animation_block>* AnimationBlockEntry = AnimationSystem->Blocks.GetEntryAtIndex(i);
if (AnimationBlockIsFree(*AnimationBlockEntry)) { continue; } if (AnimationBlockEntry->Free.NextFreeEntry != 0) { continue; }
animation_block_handle CurrentBlockHandle = {}; gs_list_handle CurrentBlockHandle = AnimationBlockEntry->Handle;
CurrentBlockHandle.Index = i; animation_block AnimationBlockAt = AnimationBlockEntry->Value;
CurrentBlockHandle.Generation = AnimationBlockEntry->Generation;
animation_block AnimationBlockAt = AnimationBlockEntry->Block;
v4 BlockColor = BlackV4; v4 BlockColor = BlackV4;
if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) if (GSListHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
{ {
BlockColor = PinkV4; BlockColor = PinkV4;
} }
@ -425,7 +414,7 @@ DrawAnimationClipsList(rect PanelBounds, mouse_state Mouse, render_command_buffe
PANEL_RENDER_PROC(AnimationTimeline_Render) PANEL_RENDER_PROC(AnimationTimeline_Render)
{ {
animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
r32 OptionsRowHeight = 25; r32 OptionsRowHeight = 25;
rect AnimationClipListBounds = rect{ rect AnimationClipListBounds = rect{

View File

@ -31,15 +31,15 @@ PANEL_RENDER_PROC(HierarchyView_Render)
v2 TextOffset = v2{10, 4}; v2 TextOffset = v2{10, 4};
string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); string TempString = MakeString(PushArray(&State->Transient, char, 256), 256);
s32 LineCount = (s32)(PanelHeight / List.ListElementDimensions.y) + 1; u32 LineCount = (u32)(PanelHeight / List.ListElementDimensions.y) + 1;
for (s32 i = 0; i < LineCount; i++) for (u32 i = 0; i < LineCount; i++)
{ {
rect ElementBounds = DrawListElementBackground(&List, Mouse, RenderBuffer); rect ElementBounds = DrawListElementBackground(&List, Mouse, RenderBuffer);
if (i < State->ActiveAssemblyIndecies.Used) if (i < State->ActiveAssemblyIndecies.Used)
{ {
array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
PrintF(&TempString, "%S", Assembly.Name); PrintF(&TempString, "%S", Assembly.Name);
DrawString(RenderBuffer, TempString, State->Interface.Font, ElementBounds.Min + TextOffset, WhiteV4); DrawString(RenderBuffer, TempString, State->Interface.Font, ElementBounds.Min + TextOffset, WhiteV4);

View File

@ -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 // Pan Node Graph
// //
@ -39,6 +86,41 @@ FOLDHAUS_INPUT_COMMAND_PROC(BeginPanNodeGraph)
OpState->ViewOffset = &NodeGraphState->ViewOffset; 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 // Node Graph Panel
// //
@ -96,9 +178,13 @@ DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer*
} }
internal void internal s32
DrawNodePorts(node_specification Spec, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer) 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; v2 LinePosition = Position;
for (u32 i = 0; i < Spec.MemberListLength; i++) 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)); string MemberName = MakeString(Member.Name, CharArrayLength(Member.Name));
DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign); 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; LinePosition.y -= LineHeight;
} }
} }
return PortClicked;
} }
internal void internal s32
DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer) 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 InputMembers = 0;
u32 OutputMembers = 0; u32 OutputMembers = 0;
for (u32 i = 0; i < NodeSpecification.MemberListLength; i++) for (u32 i = 0; i < NodeSpecification.MemberListLength; i++)
@ -147,44 +254,23 @@ DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32
LinePosition.y -= LineHeight; LinePosition.y -= LineHeight;
// Draw Ports // 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 OutputLinePosition = v2{LinePosition.x + NodeDim.x, LinePosition.y };
v2 OutputTextOffset = v2{-TextOffset.x, TextOffset.y}; v2 OutputTextOffset = v2{-TextOffset.x, TextOffset.y};
DrawNodePorts(NodeSpecification, IsOutputMember, OutputLinePosition, LineHeight, Align_Right, OutputTextOffset, Interface, RenderBuffer); s32 OutputPortClicked = DrawNodePorts(NodeSpecification, IsOutputMember, OutputLinePosition, LineHeight, Align_Right, OutputTextOffset, Interface, RenderBuffer, Mouse);
}
struct temp_node_connection
{
u32 DownstreamNodeIndex;
u32 DownstreamNodePort;
u32 UpstreamNodeIndex; if (InputPortClicked >= 0)
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++; PortClicked = InputPortClicked;
TEMP_NodeList[Index] = Spec;
} }
else if (OutputPortClicked >= 0)
{
PortClicked = OutputPortClicked;
}
return PortClicked;
} }
internal visual_node* internal visual_node*
@ -270,7 +356,11 @@ PANEL_RENDER_PROC(NodeGraph_Render)
for (u32 i = 0; i < TEMP_NodeListUsed; i++) for (u32 i = 0; i < TEMP_NodeListUsed; i++)
{ {
visual_node VisualNode = VisualNodes[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 // Node Selection Panel

View File

@ -138,10 +138,10 @@ PANEL_RENDER_PROC(SculptureView_Render)
s32 MaxLEDsPerJob = 2048; s32 MaxLEDsPerJob = 2048;
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); 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); gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob);
for (s32 Job = 0; Job < JobsNeeded; Job++) for (s32 Job = 0; Job < JobsNeeded; Job++)