Began drawing nodes, laying them out, and am working on node interface functionality
This commit is contained in:
parent
e3705842dc
commit
c5404e3296
|
@ -1,16 +1,6 @@
|
||||||
#include "foldhaus_platform.h"
|
#include "foldhaus_platform.h"
|
||||||
#include "foldhaus_app.h"
|
#include "foldhaus_app.h"
|
||||||
|
|
||||||
internal void
|
|
||||||
SetPanelDefinitionExternal(panel* Panel, s32 OldPanelDefinitionIndex, s32 NewPanelDefinitionIndex)
|
|
||||||
{
|
|
||||||
if(OldPanelDefinitionIndex >= 0)
|
|
||||||
{
|
|
||||||
GlobalPanelDefs[OldPanelDefinitionIndex].Cleanup(Panel);
|
|
||||||
}
|
|
||||||
GlobalPanelDefs[NewPanelDefinitionIndex].Init(Panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal v4
|
internal v4
|
||||||
MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds)
|
MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +193,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
|
|
||||||
InitializePanelSystem(&State->PanelSystem);
|
InitializePanelSystem(&State->PanelSystem);
|
||||||
panel* Panel = TakeNewPanel(&State->PanelSystem);
|
panel* Panel = TakeNewPanel(&State->PanelSystem);
|
||||||
SetPanelDefinition(Panel, 0);
|
SetPanelDefinition(Panel, 0, State);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -223,6 +213,7 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_
|
||||||
{
|
{
|
||||||
panel_and_bounds PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, WindowBounds);
|
panel_and_bounds PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, WindowBounds);
|
||||||
if (!PanelWithMouseOverIt.Panel) { return; }
|
if (!PanelWithMouseOverIt.Panel) { return; }
|
||||||
|
State->HotPanel = PanelWithMouseOverIt.Panel;
|
||||||
|
|
||||||
panel_definition PanelDefinition = GlobalPanelDefs[PanelWithMouseOverIt.Panel->PanelDefinitionIndex];
|
panel_definition PanelDefinition = GlobalPanelDefs[PanelWithMouseOverIt.Panel->PanelDefinitionIndex];
|
||||||
if (!PanelDefinition.InputCommands) { return; }
|
if (!PanelDefinition.InputCommands) { return; }
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
#include "foldhaus_assembly.h"
|
#include "foldhaus_assembly.h"
|
||||||
|
|
||||||
#include "assembly_parser.h"
|
#include "assembly_parser.h"
|
||||||
|
|
||||||
#include "foldhaus_node.h"
|
#include "foldhaus_node.h"
|
||||||
|
|
||||||
#include "assembly_parser.cpp"
|
#include "assembly_parser.cpp"
|
||||||
#include "test_patterns.h"
|
#include "test_patterns.h"
|
||||||
|
|
||||||
|
@ -67,6 +69,7 @@ struct app_state
|
||||||
animation_block_handle SelectedAnimationBlockHandle;
|
animation_block_handle SelectedAnimationBlockHandle;
|
||||||
|
|
||||||
panel_system PanelSystem;
|
panel_system PanelSystem;
|
||||||
|
panel* HotPanel;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal void OpenColorPicker(app_state* State, v4* Address);
|
internal void OpenColorPicker(app_state* State, v4* Address);
|
||||||
|
@ -198,10 +201,19 @@ TestPatternThree(assembly* Assembly, r32 Time)
|
||||||
#include "foldhaus_text_entry.cpp"
|
#include "foldhaus_text_entry.cpp"
|
||||||
#include "foldhaus_search_lister.cpp"
|
#include "foldhaus_search_lister.cpp"
|
||||||
|
|
||||||
#define PANEL_INIT_PROC(name) void name(panel* Panel)
|
#include "foldhaus_default_nodes.h"
|
||||||
|
#include "generated/foldhaus_nodes_generated.cpp"
|
||||||
|
#include "foldhaus_node.cpp"
|
||||||
|
|
||||||
|
FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode)
|
||||||
|
{
|
||||||
|
DeactivateCurrentOperationMode(&State->Modes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State)
|
||||||
typedef PANEL_INIT_PROC(panel_init_proc);
|
typedef PANEL_INIT_PROC(panel_init_proc);
|
||||||
|
|
||||||
#define PANEL_CLEANUP_PROC(name) void name(panel* Panel)
|
#define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State)
|
||||||
typedef PANEL_CLEANUP_PROC(panel_cleanup_proc);
|
typedef PANEL_CLEANUP_PROC(panel_cleanup_proc);
|
||||||
|
|
||||||
#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
||||||
|
@ -212,6 +224,7 @@ typedef PANEL_RENDER_PROC(panel_render_proc);
|
||||||
#include "panels/foldhaus_panel_dmx_view.h"
|
#include "panels/foldhaus_panel_dmx_view.h"
|
||||||
#include "panels/foldhaus_panel_animation_timeline.h"
|
#include "panels/foldhaus_panel_animation_timeline.h"
|
||||||
#include "panels/foldhaus_panel_hierarchy.h"
|
#include "panels/foldhaus_panel_hierarchy.h"
|
||||||
|
#include "panels/foldhaus_panel_node_graph.h"
|
||||||
|
|
||||||
#include "generated/foldhaus_panels_generated.h"
|
#include "generated/foldhaus_panels_generated.h"
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,19 @@ enum panel_edit_mode
|
||||||
PanelEdit_Count,
|
PanelEdit_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal void
|
||||||
|
SetPanelDefinition(panel* Panel, s32 NewPanelDefinitionIndex, app_state* State)
|
||||||
|
{
|
||||||
|
s32 OldPanelDefinitionIndex = Panel->PanelDefinitionIndex;
|
||||||
|
Panel->PanelDefinitionIndex = NewPanelDefinitionIndex;
|
||||||
|
|
||||||
|
if(OldPanelDefinitionIndex >= 0)
|
||||||
|
{
|
||||||
|
GlobalPanelDefs[OldPanelDefinitionIndex].Cleanup(Panel, State);
|
||||||
|
}
|
||||||
|
GlobalPanelDefs[NewPanelDefinitionIndex].Init(Panel, State);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Drag Panel Border Operation Mode
|
// Drag Panel Border Operation Mode
|
||||||
|
|
||||||
|
@ -359,6 +372,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation)
|
||||||
SplitPanelHorizontally(Panel, YPercent, PanelBounds, &State->PanelSystem);
|
SplitPanelHorizontally(Panel, YPercent, PanelBounds, &State->PanelSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Panel->Left->Panel.PanelDefinitionIndex = Panel->PanelDefinitionIndex;
|
||||||
|
Panel->Left->Panel.PanelStateMemory = Panel->PanelStateMemory;
|
||||||
|
Panel->Left->Panel.PanelStateMemorySize = Panel->PanelStateMemorySize;
|
||||||
|
|
||||||
|
SetPanelDefinition(&Panel->Right->Panel, Panel->PanelDefinitionIndex, State);
|
||||||
|
|
||||||
DeactivateCurrentOperationMode(&State->Modes);
|
DeactivateCurrentOperationMode(&State->Modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +516,7 @@ DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state Mou
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBounds, interface_config Interface, mouse_state Mouse)
|
DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBounds, mouse_state Mouse, app_state* State)
|
||||||
{
|
{
|
||||||
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f});
|
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f});
|
||||||
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4);
|
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4);
|
||||||
|
@ -525,10 +544,10 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo
|
||||||
string DefName = MakeString(Def.PanelName, Def.PanelNameLength);
|
string DefName = MakeString(Def.PanelName, Def.PanelNameLength);
|
||||||
button_result DefinitionButton = EvaluateButton(RenderBuffer,
|
button_result DefinitionButton = EvaluateButton(RenderBuffer,
|
||||||
ButtonMin, ButtonMin + ButtonDimension,
|
ButtonMin, ButtonMin + ButtonDimension,
|
||||||
DefName, Interface, Mouse);
|
DefName, State->Interface, Mouse);
|
||||||
if (DefinitionButton.Pressed)
|
if (DefinitionButton.Pressed)
|
||||||
{
|
{
|
||||||
SetPanelDefinition(Panel, i);
|
SetPanelDefinition(Panel, i, State);
|
||||||
Panel->PanelSelectionMenuOpen = false;
|
Panel->PanelSelectionMenuOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +558,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo
|
||||||
button_result ButtonResult = EvaluateButton(RenderBuffer,
|
button_result ButtonResult = EvaluateButton(RenderBuffer,
|
||||||
PanelSelectButtonMin,
|
PanelSelectButtonMin,
|
||||||
PanelSelectButtonMax,
|
PanelSelectButtonMax,
|
||||||
MakeStringLiteral("Select"), Interface, Mouse);
|
MakeStringLiteral("Select"), State->Interface, Mouse);
|
||||||
if (ButtonResult.Pressed)
|
if (ButtonResult.Pressed)
|
||||||
{
|
{
|
||||||
Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen;
|
Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen;
|
||||||
|
@ -565,7 +584,7 @@ RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_bu
|
||||||
Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context, Mouse);
|
Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context, Mouse);
|
||||||
|
|
||||||
PushRenderOrthographic(RenderBuffer, WindowBounds.Min.x, WindowBounds.Min.y, WindowBounds.Max.x, WindowBounds.Max.y);
|
PushRenderOrthographic(RenderBuffer, WindowBounds.Min.x, WindowBounds.Min.y, WindowBounds.Max.x, WindowBounds.Max.y);
|
||||||
DrawPanelFooter(Panel, RenderBuffer, FooterBounds, State->Interface, Mouse);
|
DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
|
|
@ -189,7 +189,7 @@ PushNodeOnListFromSpecification (node_list* List, node_type Type, v2 Min, memory
|
||||||
Node->PersistentData = PushArray(Storage, u8, Spec.DataStructSize);
|
Node->PersistentData = PushArray(Storage, u8, Spec.DataStructSize);
|
||||||
|
|
||||||
node_struct_member* MemberList = Spec.MemberList;
|
node_struct_member* MemberList = Spec.MemberList;
|
||||||
for (s32 MemberIdx = 0; MemberIdx < Spec.MemberListLength; MemberIdx++)
|
for (u32 MemberIdx = 0; MemberIdx < Spec.MemberListLength; MemberIdx++)
|
||||||
{
|
{
|
||||||
node_struct_member Member = MemberList[MemberIdx];
|
node_struct_member Member = MemberList[MemberIdx];
|
||||||
InitializeNodeConnection(Node->Connections + MemberIdx, Member, Node);
|
InitializeNodeConnection(Node->Connections + MemberIdx, Member, Node);
|
||||||
|
|
|
@ -169,9 +169,9 @@ struct node_specification
|
||||||
s32 NameLength;
|
s32 NameLength;
|
||||||
|
|
||||||
node_struct_member* MemberList;
|
node_struct_member* MemberList;
|
||||||
s32 DataStructSize;
|
u32 DataStructSize;
|
||||||
|
|
||||||
s32 MemberListLength;
|
u32 MemberListLength;
|
||||||
b32 IsPattern;
|
b32 IsPattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,9 @@ struct panel
|
||||||
// Probably belongs in a more generalized PanelInterfaceState or something
|
// Probably belongs in a more generalized PanelInterfaceState or something
|
||||||
b32 PanelSelectionMenuOpen;
|
b32 PanelSelectionMenuOpen;
|
||||||
|
|
||||||
|
u8* PanelStateMemory;
|
||||||
|
u32 PanelStateMemorySize;
|
||||||
|
|
||||||
union{
|
union{
|
||||||
panel_entry* Left;
|
panel_entry* Left;
|
||||||
panel_entry* Top;
|
panel_entry* Top;
|
||||||
|
@ -80,8 +83,6 @@ struct panel_layout
|
||||||
u32 PanelsMax;
|
u32 PanelsMax;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal void SetPanelDefinitionExternal(panel* Panel, s32 OldPanelDefinitionIndex, s32 NewPanelDefinitionIndex);
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
//
|
//
|
||||||
// Book-Keeping
|
// Book-Keeping
|
||||||
|
@ -201,14 +202,6 @@ ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_sys
|
||||||
FreePanelEntryRecursive(PanelEntryToDestroy, PanelSystem);
|
FreePanelEntryRecursive(PanelEntryToDestroy, PanelSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
|
||||||
SetPanelDefinition(panel* Panel, s32 NewDefinitionIndex)
|
|
||||||
{
|
|
||||||
s32 OldDefinitionIndex = Panel->PanelDefinitionIndex;
|
|
||||||
Panel->PanelDefinitionIndex = NewDefinitionIndex;
|
|
||||||
SetPanelDefinitionExternal(Panel, OldDefinitionIndex, NewDefinitionIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
//
|
//
|
||||||
// Rendering And Interaction
|
// Rendering And Interaction
|
||||||
|
|
|
@ -8,11 +8,12 @@ struct panel_definition
|
||||||
input_command* InputCommands;
|
input_command* InputCommands;
|
||||||
};
|
};
|
||||||
|
|
||||||
global_variable s32 GlobalPanelDefsCount = 5;
|
global_variable s32 GlobalPanelDefsCount = 6;
|
||||||
global_variable panel_definition GlobalPanelDefs[] = {
|
global_variable panel_definition GlobalPanelDefs[] = {
|
||||||
{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands},
|
{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands},
|
||||||
{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands },
|
{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands },
|
||||||
{ "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, 0 },
|
{ "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, 0 },
|
||||||
{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, 0 },
|
{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, 0 },
|
||||||
{ "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, 0 },
|
{ "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, 0 },
|
||||||
|
{ "Node Graph", 10, NodeGraph_Init, NodeGraph_Cleanup, NodeGraph_Render, NodeGraph_Commands },
|
||||||
};
|
};
|
|
@ -0,0 +1,309 @@
|
||||||
|
struct node_graph_state
|
||||||
|
{
|
||||||
|
v2 ViewOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pan Node Graph
|
||||||
|
//
|
||||||
|
|
||||||
|
OPERATION_STATE_DEF(pan_node_graph_operation_state)
|
||||||
|
{
|
||||||
|
v2 InitialViewOffset;
|
||||||
|
|
||||||
|
// TODO(Peter): I DON"T LIKE THIS!!!!
|
||||||
|
// We should have a way to access the panel that created an operation mode or something
|
||||||
|
v2* ViewOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
OPERATION_RENDER_PROC(UpdatePanNodeGraph)
|
||||||
|
{
|
||||||
|
pan_node_graph_operation_state* OpState = (pan_node_graph_operation_state*)Operation.OpStateMemory;
|
||||||
|
v2 MouseDelta = Mouse.Pos - Mouse.DownPos;
|
||||||
|
*OpState->ViewOffset = MouseDelta + OpState->InitialViewOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_command PanNodeGraphCommands[] = {
|
||||||
|
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndCurrentOperationMode },
|
||||||
|
};
|
||||||
|
|
||||||
|
FOLDHAUS_INPUT_COMMAND_PROC(BeginPanNodeGraph)
|
||||||
|
{
|
||||||
|
operation_mode* PanNodeGraph = ActivateOperationModeWithCommands(&State->Modes, PanNodeGraphCommands, UpdatePanNodeGraph);
|
||||||
|
pan_node_graph_operation_state* OpState = CreateOperationState(PanNodeGraph, &State->Modes, pan_node_graph_operation_state);
|
||||||
|
|
||||||
|
panel* NodeGraphPanel = State->HotPanel;
|
||||||
|
node_graph_state* NodeGraphState = (node_graph_state*)NodeGraphPanel->PanelStateMemory;
|
||||||
|
OpState->InitialViewOffset = NodeGraphState->ViewOffset;
|
||||||
|
OpState->ViewOffset = &NodeGraphState->ViewOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Node Graph Panel
|
||||||
|
//
|
||||||
|
|
||||||
|
input_command NodeGraph_Commands[] = {
|
||||||
|
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, BeginPanNodeGraph }
|
||||||
|
};
|
||||||
|
|
||||||
|
PANEL_INIT_PROC(NodeGraph_Init)
|
||||||
|
{
|
||||||
|
// TODO(Peter): We aren't able to free this memory. We need a system for
|
||||||
|
// taking fixed size chunks off the Memory stack and then reusing them. THis
|
||||||
|
// should probably live outside the paneling system.
|
||||||
|
Panel->PanelStateMemory = (u8*)PushStruct(&State->Permanent, node_graph_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_CLEANUP_PROC(NodeGraph_Cleanup)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* RenderBuffer)
|
||||||
|
{
|
||||||
|
r32 LineValue = .16f;
|
||||||
|
v4 LineColor = v4{LineValue, LineValue, LineValue, 1.f};
|
||||||
|
|
||||||
|
v2 GridSquareOffset = v2{
|
||||||
|
GSModF(Offset.x, GridSquareDim.x),
|
||||||
|
GSModF(Offset.y, GridSquareDim.y),
|
||||||
|
};
|
||||||
|
v2 GridOrigin = PanelBounds.Min + GridSquareOffset;
|
||||||
|
|
||||||
|
// Draw Vertical Lines
|
||||||
|
r32 XOffset = 0;
|
||||||
|
while (GridOrigin.x + XOffset < PanelBounds.Max.x)
|
||||||
|
{
|
||||||
|
v2 LineMin = v2{ GridOrigin.x + XOffset, PanelBounds.Min.y };
|
||||||
|
v2 LineMax = v2{ LineMin.x + 1, PanelBounds.Max.y };
|
||||||
|
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, LineColor);
|
||||||
|
|
||||||
|
XOffset += GridSquareDim.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Horizontal Lines
|
||||||
|
r32 YOffset = 0;
|
||||||
|
while (GridOrigin.y + YOffset < PanelBounds.Max.y)
|
||||||
|
{
|
||||||
|
v2 LineMin = v2{ PanelBounds.Min.x, GridOrigin.y + YOffset };
|
||||||
|
v2 LineMax = v2{ PanelBounds.Max.x, LineMin.y + 1, };
|
||||||
|
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, LineColor);
|
||||||
|
|
||||||
|
YOffset += GridSquareDim.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawNodePorts(node_specification Spec, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer)
|
||||||
|
{
|
||||||
|
v2 LinePosition = Position;
|
||||||
|
for (u32 i = 0; i < Spec.MemberListLength; i++)
|
||||||
|
{
|
||||||
|
node_struct_member Member = Spec.MemberList[i];
|
||||||
|
if ((Member.IsInput & InputMask) > 0)
|
||||||
|
{
|
||||||
|
string MemberName = MakeString(Member.Name, CharArrayLength(Member.Name));
|
||||||
|
DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign);
|
||||||
|
|
||||||
|
LinePosition.y -= LineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawNode (v2 Position, node_specification NodeSpecification, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer)
|
||||||
|
{
|
||||||
|
u32 InputMembers = 0;
|
||||||
|
u32 OutputMembers = 0;
|
||||||
|
for (u32 i = 0; i < NodeSpecification.MemberListLength; i++)
|
||||||
|
{
|
||||||
|
node_struct_member Member = NodeSpecification.MemberList[i];
|
||||||
|
if ((Member.IsInput & IsOutputMember) > 0) { OutputMembers++; }
|
||||||
|
if ((Member.IsInput & IsInputMember) > 0) { InputMembers++; }
|
||||||
|
}
|
||||||
|
u32 LineCount = 1 + GSMax(InputMembers, OutputMembers);
|
||||||
|
|
||||||
|
v2 NodeDim = v2{
|
||||||
|
NodeWidth,
|
||||||
|
(LineHeight * LineCount) + Interface.Margin.y,
|
||||||
|
};
|
||||||
|
rect NodeBounds = rect{
|
||||||
|
v2{ Position.x, Position.y - NodeDim.y },
|
||||||
|
v2{ Position.x + NodeDim.x, Position.y },
|
||||||
|
};
|
||||||
|
|
||||||
|
PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.16f, .16f, .16f, 1.f});
|
||||||
|
|
||||||
|
v2 LinePosition = v2{ NodeBounds.Min.x, NodeBounds.Max.y - LineHeight };
|
||||||
|
v2 TextOffset = v2{Interface.Margin.x, 0};
|
||||||
|
|
||||||
|
PushRenderQuad2D(RenderBuffer, LinePosition, LinePosition + v2{NodeWidth, LineHeight}, v4{1.f, .24f, .39f, 1.f});
|
||||||
|
string NodeName = MakeString(NodeSpecification.Name, NodeSpecification.NameLength);
|
||||||
|
DrawString(RenderBuffer, NodeName, Interface.Font, LinePosition + TextOffset, WhiteV4);
|
||||||
|
LinePosition.y -= LineHeight;
|
||||||
|
|
||||||
|
// Draw Ports
|
||||||
|
DrawNodePorts(NodeSpecification, IsInputMember, LinePosition, LineHeight, Align_Left, TextOffset, Interface, RenderBuffer);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 visual_node*
|
||||||
|
ArrangeNodes(node_specification* NodeList, u32 NodesCount, temp_node_connection* ConnectionList, u32 ConnectionsCount, r32 NodeWidth, r32 LayerDistance, memory_arena* Storage)
|
||||||
|
{
|
||||||
|
// Figure out how to arrange nodes
|
||||||
|
u32 LayerCount = 1;
|
||||||
|
|
||||||
|
u32* NodeLayers = PushArray(Storage, u32, NodesCount);
|
||||||
|
GSZeroMemory((u8*)NodeLayers, sizeof(u32) * NodesCount);
|
||||||
|
|
||||||
|
for (u32 c = 0; c < ConnectionsCount; c++)
|
||||||
|
{
|
||||||
|
temp_node_connection Connection = TEMP_NodeConnections[c];
|
||||||
|
|
||||||
|
u32 UpstreamNodeInitialLayer = NodeLayers[Connection.UpstreamNodeIndex];
|
||||||
|
u32 DownstreamNodeLayer = NodeLayers[Connection.DownstreamNodeIndex];
|
||||||
|
|
||||||
|
NodeLayers[Connection.UpstreamNodeIndex] = GSMax(UpstreamNodeInitialLayer, DownstreamNodeLayer + 1);
|
||||||
|
LayerCount = GSMax(NodeLayers[Connection.UpstreamNodeIndex] + 1, LayerCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place Layer Columns
|
||||||
|
v2* LayerPositions = PushArray(Storage, v2, LayerCount);
|
||||||
|
for (u32 l = 0; l < LayerCount; l++)
|
||||||
|
{
|
||||||
|
u32 FromRight = LayerCount - l;
|
||||||
|
LayerPositions[l] = v2{ (NodeWidth + LayerDistance) * FromRight, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place nodes
|
||||||
|
visual_node* VisualNodes = PushArray(Storage, visual_node, NodesCount);
|
||||||
|
for (u32 n = 0; n < NodesCount; n++)
|
||||||
|
{
|
||||||
|
VisualNodes[n].Spec = TEMP_NodeList[n];
|
||||||
|
|
||||||
|
u32 NodeLayer = NodeLayers[n];
|
||||||
|
VisualNodes[n].Position = LayerPositions[NodeLayer];
|
||||||
|
LayerPositions[NodeLayer].y -= 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VisualNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
PANEL_RENDER_PROC(NodeGraph_Render)
|
||||||
|
{
|
||||||
|
node_graph_state* GraphState = (node_graph_state*)Panel.PanelStateMemory;
|
||||||
|
|
||||||
|
rect NodeSelectionWindowBounds = rect{
|
||||||
|
PanelBounds.Min,
|
||||||
|
v2{PanelBounds.Min.x + 300, PanelBounds.Max.y},
|
||||||
|
};
|
||||||
|
rect GraphBounds = rect{
|
||||||
|
v2{NodeSelectionWindowBounds.Max.x, PanelBounds.Min.y},
|
||||||
|
PanelBounds.Max,
|
||||||
|
};
|
||||||
|
|
||||||
|
r32 NodeWidth = 150;
|
||||||
|
r32 LayerDistance = 100;
|
||||||
|
r32 LineHeight = (State->Interface.Font->PixelHeight + (2 * State->Interface.Margin.y));
|
||||||
|
|
||||||
|
visual_node* VisualNodes = ArrangeNodes(&TEMP_NodeList[0], TEMP_NodeListUsed,
|
||||||
|
&TEMP_NodeConnections[0], TEMP_NodeConnectionsUsed,
|
||||||
|
NodeWidth, LayerDistance,
|
||||||
|
&State->Transient);
|
||||||
|
|
||||||
|
DrawGrid(GraphState->ViewOffset, v2{100, 100}, GraphBounds, RenderBuffer);
|
||||||
|
|
||||||
|
render_quad_batch_constructor ConnectionsLayer = PushRenderQuad2DBatch(RenderBuffer, TEMP_NodeConnectionsUsed);
|
||||||
|
for (u32 i = 0; i < TEMP_NodeConnectionsUsed; i++)
|
||||||
|
{
|
||||||
|
temp_node_connection Connection = TEMP_NodeConnections[i];
|
||||||
|
visual_node UpstreamNode = VisualNodes[Connection.UpstreamNodeIndex];
|
||||||
|
visual_node DownstreamNode = VisualNodes[Connection.DownstreamNodeIndex];
|
||||||
|
|
||||||
|
v2 LineStart = GraphState->ViewOffset + UpstreamNode.Position + v2{NodeWidth, 0} - (v2{0, LineHeight} * (Connection.UpstreamNodePort + 2)) + v2{0, LineHeight / 3};
|
||||||
|
v2 LineEnd = GraphState->ViewOffset + DownstreamNode.Position - (v2{0, LineHeight} * (Connection.DownstreamNodePort + 2)) + v2{0, LineHeight / 3};
|
||||||
|
|
||||||
|
PushLine2DOnBatch(&ConnectionsLayer, LineStart, LineEnd, 1.5f, WhiteV4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Selection Panel
|
||||||
|
v4 LineBGColors[] = {
|
||||||
|
{ .16f, .16f, .16f, 1.f },
|
||||||
|
{ .18f, .18f, .18f, 1.f },
|
||||||
|
};
|
||||||
|
|
||||||
|
interface_list List = {};
|
||||||
|
List.LineBGColors = LineBGColors;
|
||||||
|
List.LineBGColorsCount = sizeof(LineBGColors) / sizeof(LineBGColors[0]);
|
||||||
|
List.LineBGHoverColor = v4{ .22f, .22f, .22f, 1.f };
|
||||||
|
List.TextColor = WhiteV4;
|
||||||
|
List.ListBounds = NodeSelectionWindowBounds;
|
||||||
|
List.ListElementDimensions = v2{
|
||||||
|
Width(NodeSelectionWindowBounds),
|
||||||
|
(r32)(State->Interface.Font->PixelHeight + 8),
|
||||||
|
};
|
||||||
|
List.ElementLabelIndent = v2{10, 4};
|
||||||
|
|
||||||
|
string TitleString = MakeStringLiteral("Available Nodes");
|
||||||
|
DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface);
|
||||||
|
|
||||||
|
for (s32 i = 0; i < NodeSpecificationsCount; i++)
|
||||||
|
{
|
||||||
|
node_specification Spec = NodeSpecifications[i];
|
||||||
|
string NodeName = MakeString(Spec.Name, Spec.NameLength);
|
||||||
|
rect ElementBounds = DrawListElement(NodeName, &List, Mouse, RenderBuffer, State->Interface);
|
||||||
|
|
||||||
|
if (MouseButtonTransitionedDown(Mouse.LeftButtonState)
|
||||||
|
&& PointIsInRect(Mouse.DownPos, ElementBounds))
|
||||||
|
{
|
||||||
|
PushNodeOnNodeList(Spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue