From da76bb46f5c7a27ced795fc2d652a25002c0cc18 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 23 Nov 2019 03:05:25 -0800 Subject: [PATCH 01/19] Removed nodes from the project --- src/foldhaus_app.cpp | 22 +- src/foldhaus_app.h | 8 +- src/foldhaus_debug_visuals.h | 7 - src/foldhaus_interface.cpp | 498 --------------------------- src/foldhaus_search_lister.cpp | 8 +- src/node/foldhaus_node_interface.cpp | 498 +++++++++++++++++++++++++++ 6 files changed, 507 insertions(+), 534 deletions(-) create mode 100644 src/node/foldhaus_node_interface.cpp diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index a9f3f2b..b54eb35 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -186,7 +186,6 @@ RELOAD_STATIC_DATA(ReloadStaticData) RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, Begin3DViewMouseRotate); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_U, Command_Began, KeyCode_Invalid, OpenUniverseView); - RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_Tab, Command_Began, KeyCode_Invalid, OpenNodeView); } } @@ -297,14 +296,6 @@ INITIALIZE_APPLICATION(InitializeApplication) GlobalDebugServices->Interface.RenderSculpture = true; - State->NodeList = AllocateNodeList(State->Permanent, 128); - State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Permanent); - { - State->NodeRenderSettings.PortColors[MemberType_r32] = RedV4; - State->NodeRenderSettings.PortColors[MemberType_s32] = GreenV4; - State->NodeRenderSettings.PortColors[MemberType_v4] = BlueV4; - State->NodeRenderSettings.Font = State->Font; - } ReloadStaticData(Context, GlobalDebugServices, Alloc, Free); { // MODES PLAYGROUND @@ -414,18 +405,7 @@ UPDATE_AND_RENDER(UpdateAndRender) HandleInput(State, InputQueue, Mouse); - for (s32 AssemblyIndex = 0; AssemblyIndex < State->AssembliesCount; AssemblyIndex++) - { - assembly Assembly = State->AssemblyList[AssemblyIndex]; - UpdateOutputNodeCalculations(State->OutputNode, State->NodeList, - State->Permanent, State->Transient, - Assembly.LEDs, - Assembly.Colors, - Assembly.LEDCount, - Context.DeltaTime); - ResetNodesUpdateState(State->NodeList); - } - ClearTransientNodeColorBuffers(State->NodeList); + // Update Visuals Here s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index b8a723b..1874697 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -23,8 +23,6 @@ typedef struct app_state app_state; #include "foldhaus_text_entry.h" -#include "foldhaus_default_nodes.h" -#include "generated/foldhaus_nodes_generated.cpp" #include "foldhaus_search_lister.h" enum network_protocol @@ -63,10 +61,6 @@ struct app_state input_command_queue CommandQueue; text_entry ActiveTextEntry; - node_list* NodeList; - node_header* OutputNode; - - node_render_settings NodeRenderSettings; bitmap_font* Font; interface_config Interface; }; @@ -74,7 +68,7 @@ struct app_state internal void OpenColorPicker(app_state* State, v4* Address); #include "foldhaus_assembly.cpp" -#include "foldhaus_node.cpp" + #include "foldhaus_debug_visuals.h" //#include "foldhaus_sacn_view.cpp" #include "foldhaus_text_entry.cpp" diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index e9e313a..a98770e 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -298,13 +298,6 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c TopOfScreenLinePos, WhiteV4); TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); - PrintF(&DebugString, "Nodes Memory: %d / %d", - State->NodeList->TotalUsed, - State->NodeList->TotalMax); - DrawString(RenderBuffer, DebugString, Interface.Font, - TopOfScreenLinePos, WhiteV4); - TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); - PrintF(&DebugString, "Render Buffer: %d / %d (at this point)", RenderBuffer->CommandMemoryUsed, RenderBuffer->CommandMemorySize); diff --git a/src/foldhaus_interface.cpp b/src/foldhaus_interface.cpp index cc1c53a..efb720b 100644 --- a/src/foldhaus_interface.cpp +++ b/src/foldhaus_interface.cpp @@ -128,504 +128,6 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenUniverseView) OpState->Zoom = 1.0f; } -//////////////////////////////////////// -// -// Node Lister -// -/////////////////////////////////////// - -struct node_lister_operation_state -{ - search_lister SearchLister; - v2 ListPosition; -}; - -OPERATION_RENDER_PROC(RenderNodeLister) -{ - node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory; - - v2 TopLeft = OpState->ListPosition; - v2 Dimension = v2{300, 30}; - - // Filter the lister - OpState->SearchLister.Filter = State->ActiveTextEntry.Buffer; - FilterSearchLister(&OpState->SearchLister); - - // Display Search Lister - search_lister_result NodeListerResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension, - MakeStringLiteral("Nodes List"), - OpState->SearchLister.SourceList, - OpState->SearchLister.FilteredIndexLUT, - OpState->SearchLister.FilteredListCount, - OpState->SearchLister.HotItem, - &State->ActiveTextEntry.Buffer, - State->ActiveTextEntry.CursorPosition, - State->Font, State->Interface, Mouse); -} - -FOLDHAUS_INPUT_COMMAND_PROC(NodeListerNextItem) -{ - node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); - OpState->SearchLister.HotItem = GetNextFilteredItem(OpState->SearchLister); -} - -FOLDHAUS_INPUT_COMMAND_PROC(NodeListerPrevItem) -{ - node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); - OpState->SearchLister.HotItem = GetPrevFilteredItem(OpState->SearchLister); -} - -FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeLister) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - -FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseNodeLister) -{ - node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); - s32 FilteredNodeIndex = OpState->SearchLister.HotItem; - if (FilteredNodeIndex >= 0) - { - s32 NodeIndex = OpState->SearchLister.FilteredIndexLUT[FilteredNodeIndex]; - PushNodeOnListFromSpecification(State->NodeList, (node_type)NodeIndex, - Mouse.Pos, State->Permanent); - } - CloseNodeLister(State, Event, Mouse); -} - -input_command UniverseViewCommads [] = { - { KeyCode_DownArrow, KeyCode_Invalid, Command_Began, NodeListerNextItem }, - { KeyCode_UpArrow, KeyCode_Invalid, Command_Began, NodeListerPrevItem }, - { KeyCode_Enter, KeyCode_Invalid, Command_Began, SelectAndCloseNodeLister }, - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, CloseNodeLister }, - { KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseNodeLister }, - DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY, -}; - -FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) -{ - operation_mode* AddNodeOperation = ActivateOperationModeWithCommands(&State->Modes, UniverseViewCommads); - - AddNodeOperation->Render = RenderNodeLister; - - node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, - &State->Modes, - node_lister_operation_state); - { - OpState->SearchLister.SourceListCount = NodeSpecificationsCount; - OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, string, OpState->SearchLister.SourceListCount); - { - for (s32 i = 0; i < OpState->SearchLister.SourceListCount; i++) - { - OpState->SearchLister.SourceList[i] = MakeString( - NodeSpecifications[i].Name, - NodeSpecifications[i].NameLength); - } - } - OpState->SearchLister.Filter = MakeString(PushArray(&State->Modes.Arena, char, 64), 0, 64); - - OpState->SearchLister.FilteredListMax = OpState->SearchLister.SourceListCount; - OpState->SearchLister.FilteredListCount = 0; - OpState->SearchLister.FilteredIndexLUT = PushArray(&State->Modes.Arena, s32, OpState->SearchLister.SourceListCount); - } - - OpState->ListPosition = Mouse.Pos; - SetTextInputDestinationToString(&State->ActiveTextEntry, &OpState->SearchLister.Filter); -} - -//////////////////////////////////////// -// -// Node Color Picker -// -/////////////////////////////////////// - -struct color_picker_operation_state -{ - v4* ValueAddr; -}; - -internal void -CloseColorPicker(app_state* State) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - -FOLDHAUS_INPUT_COMMAND_PROC(CloseColorPickerCommand) -{ - CloseColorPicker(State); -} - -OPERATION_RENDER_PROC(RenderColorPicker) -{ - color_picker_operation_state* OpState = (color_picker_operation_state*)Operation.OpStateMemory; - - - b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, - v2{200, 200}, State->Interface, Mouse); - - if (ShouldClose) - { - CloseColorPicker(State); - } -} - -input_command ColorPickerCommands [] = { - { KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseColorPickerCommand }, -}; - -internal void -OpenColorPicker(app_state* State, node_connection* Connection) -{ - operation_mode* ColorPickerMode = ActivateOperationModeWithCommands(&State->Modes, ColorPickerCommands); - ColorPickerMode->Render = RenderColorPicker; - - color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, - &State->Modes, - color_picker_operation_state); - OpState->ValueAddr = Connection->V4ValuePtr; -} - - -//////////////////////////////////////// -// -// Node Field Text Edit -// -/////////////////////////////////////// - -FOLDHAUS_INPUT_COMMAND_PROC(EndNodeFieldTextEdit) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - -input_command NodeFieldTextEditCommands [] = { - { KeyCode_Enter, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit }, - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit }, - DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY, -}; - -internal void -BeginNodeFieldTextEdit(app_state* State, node_connection* Connection) -{ - operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, - NodeFieldTextEditCommands); - - SetTextInputDestinationToFloat(&State->ActiveTextEntry, Connection->R32ValuePtr); -} - -//////////////////////////////////////// -// -// Node Port Mouse Drag -// -/////////////////////////////////////// - -struct drag_node_port_operation_state -{ - node_interaction Interaction; -}; - -OPERATION_RENDER_PROC(RenderDraggingNodePort) -{ - drag_node_port_operation_state* OpState = (drag_node_port_operation_state*)Operation.OpStateMemory; - UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, - State->NodeRenderSettings, RenderBuffer); -} - -FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNodePort) -{ - drag_node_port_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_port_operation_state); - - TryConnectNodes(OpState->Interaction, Mouse.Pos, State->NodeList, State->NodeRenderSettings); - DeactivateCurrentOperationMode(&State->Modes); -} - -input_command DragNodePortInputCommands[] = { - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNodePort }, -}; - -internal void -BeginDraggingNodePort(app_state* State, node_interaction Interaction) -{ - operation_mode* DragNodePortMode = ActivateOperationModeWithCommands( - &State->Modes, - DragNodePortInputCommands); - DragNodePortMode->Render = RenderDraggingNodePort; - - drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, - &State->Modes, - drag_node_port_operation_state); - OpState->Interaction = Interaction; -} - -//////////////////////////////////////// -// -// Node Field Mouse Drag -// -/////////////////////////////////////// - -OPERATION_RENDER_PROC(RenderDragNodeField) -{ - // TODO(Peter): - //UpdateDraggingNodeValue(Mouse.Pos, Mouse.OldPos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, State); -} - -internal void -BeginInteractWithNodeField(app_state* State, node_interaction Interaction) -{ - // TODO(Peter): -} - -//////////////////////////////////////// -// -// Node Mouse Drag -// -/////////////////////////////////////// - -struct drag_node_operation_state -{ - node_interaction Interaction; -}; - -OPERATION_RENDER_PROC(RenderDraggingNode) -{ - drag_node_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_operation_state); - UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, - State->NodeRenderSettings); -} - -FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNode) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - -input_command DragNodeInputCommands[] = { - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNode }, -}; - -internal void -BeginDraggingNode(app_state* State, node_interaction Interaction) -{ - operation_mode* DragNodeMode = ActivateOperationModeWithCommands( - &State->Modes, - DragNodeInputCommands); - DragNodeMode->Render = RenderDraggingNode; - - drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, - &State->Modes, - drag_node_operation_state); - OpState->Interaction = Interaction; -} - -//////////////////////////////////////// -// -// Node View -// -/////////////////////////////////////// - -struct node_view_operation_state -{ - s32 SelectedNodeHandle; -}; - -FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) -{ - node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); - - node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.DownPos, State->NodeRenderSettings); - if (Node) - { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, - State->NodeRenderSettings); - if (IsDraggingNodePort(NewInteraction)) - { - BeginDraggingNodePort(State, NewInteraction); - } - else if(IsDraggingNodeValue(NewInteraction)) - { - // TODO(Peter): This probably wants to live in a mouse held action - // the first frame we realize we're held over a field, just transition to - // drag node field - //BeginInteractWithNodeField(State, NewInteraction, State->NodeRenderSettings); - } - else // IsDraggingNode - { - OpState->SelectedNodeHandle = Node->Handle; - BeginDraggingNode(State, NewInteraction); - } - } - else - { - OpState->SelectedNodeHandle = 0; - } -} - -FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) -{ - node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); - - node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.Pos, State->NodeRenderSettings); - if (Node) - { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, - State->NodeRenderSettings); - if(IsDraggingNodeValue(NewInteraction)) - { - node_connection* Connection = Node->Connections + NewInteraction.InputValue; - struct_member_type InputType = Connection->Type; - - if (InputType == MemberType_r32) - { - BeginNodeFieldTextEdit(State, Connection); - } - else if (InputType == MemberType_v4) - { - OpenColorPicker(State, Connection); - } - } - } -} - -OPERATION_RENDER_PROC(RenderNodeView) -{ - node_view_operation_state* OpState = (node_view_operation_state*)Operation.OpStateMemory; - - DEBUG_TRACK_FUNCTION; - - MakeStringBuffer(NodeHeaderBuffer, 128); - - node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle); - - node_list_iterator NodeIter = GetNodeListIterator(*State->NodeList); - while (NodeIteratorIsValid(NodeIter)) - { - node_header* Node = NodeIter.At; - - rect NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); - b32 DrawFields = PointIsInRect(Mouse.Pos, NodeBounds); - - if (Node == SelectedNode) - { - PushRenderQuad2D(RenderBuffer, NodeBounds.Min - v2{2, 2}, NodeBounds.Max + v2{2, 2}, WhiteV4); - } - - PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.5f, .5f, .5f, 1.f}); - - // TODO(Peter): This is just for debug purposes. We can remove and go back to just having - // Node->Name in DrawString - string NodeName = GetNodeName(*Node); - PrintF(&NodeHeaderBuffer, "%.*s: %d", NodeName.Length, NodeName.Memory, Node->Handle); - DrawString(RenderBuffer, NodeHeaderBuffer, State->NodeRenderSettings.Font, - v2{NodeBounds.Min.x + 5, NodeBounds.Max.y - (State->NodeRenderSettings.Font->PixelHeight + NODE_HEADER_HEIGHT + 5)}, - WhiteV4); - - for (s32 Connection = 0; Connection < Node->ConnectionsCount; Connection++) - { - v4 PortColor = State->NodeRenderSettings.PortColors[Node->Connections[Connection].Type]; - - // Inputs - if (ConnectionIsInput(Node, Connection)) - { - rect PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); - DrawPort(RenderBuffer, PortBounds, PortColor); - - // - // TODO(Peter): I don't like excluding OutputNode, feels too much like a special case - // but I don't want to get in to the meta programming right now. - // We should just generate a spec and struct member types for NodeType_OutputNode - // - // :ExcludingOutputNodeSpecialCase - // - if (Node->Type != NodeType_OutputNode && DrawFields) - { - node_specification Spec = NodeSpecifications[Node->Type]; - node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), - State->NodeRenderSettings.Font, - v2{PortBounds.Min.x - 8, PortBounds.Min.y}, WhiteV4, Align_Right); - } - - rect ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); - DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); - - // NOTE(Peter): its way easier to draw the connection on the input port b/c its a 1:1 relationship, - // whereas output ports might have many connections, they really only know about the most recent one - // Not sure if this is a problem. We mostly do everything backwards here, starting at the - // most downstream node and working back up to find dependencies. - if (ConnectionHasUpstreamConnection(Node, Connection)) - { - rect ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); - v2 InputCenter = CalculateRectCenter(PortBounds); - v2 OutputCenter = CalculateRectCenter(ConnectedPortBounds); - PushRenderLine2D(RenderBuffer, OutputCenter, InputCenter, 1, WhiteV4); - } - } - - // Outputs - if (ConnectionIsOutput(Node, Connection)) - { - rect PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); - DrawPort(RenderBuffer, PortBounds, PortColor); - - if (DrawFields) - { - node_specification Spec = NodeSpecifications[Node->Type]; - node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), - State->NodeRenderSettings.Font, - v2{PortBounds.Max.x + 8, PortBounds.Min.y}, WhiteV4); - } - - rect ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); - DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); - } - - for (s32 Button = 0; Button < 3; Button++) - { - rect ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); - PushRenderQuad2D(RenderBuffer, ButtonRect.Min, ButtonRect.Max, DragButtonColors[Button]); - } - } - - Next(&NodeIter); - } -} - -FOLDHAUS_INPUT_COMMAND_PROC(NodeViewDeleteNode) -{ - node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); - if (OpState->SelectedNodeHandle > 0) - { - node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle); - FreeNodeOnList(State->NodeList, SelectedNode); - } -} - -FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeView) -{ - DeactivateCurrentOperationMode(&State->Modes); -} - -input_command NodeViewCommands [] = { - { KeyCode_Tab, KeyCode_Invalid, Command_Began, CloseNodeView}, - { KeyCode_A, KeyCode_Invalid, Command_Began, OpenNodeLister}, - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, NodeViewBeginMouseDragInteraction}, - { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, NodeViewBeginMouseSelectInteraction}, - { KeyCode_X, KeyCode_Invalid, Command_Began, NodeViewDeleteNode}, -}; - -FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView) -{ - operation_mode* NodeViewMode = ActivateOperationModeWithCommands(&State->Modes, NodeViewCommands); - NodeViewMode->Render = RenderNodeView; - - node_view_operation_state* OpState = CreateOperationState(NodeViewMode, - &State->Modes, - node_view_operation_state); - - OpState->SelectedNodeHandle = 0; -} - //////////////////////////////////////// // // 3D View Mouse Rotate diff --git a/src/foldhaus_search_lister.cpp b/src/foldhaus_search_lister.cpp index 6e7ca98..ee42843 100644 --- a/src/foldhaus_search_lister.cpp +++ b/src/foldhaus_search_lister.cpp @@ -1,3 +1,9 @@ +internal b32 +NamePassesFilter (string Target, string Filter) +{ + return (Filter.Length == 0 || StringContainsStringCaseInsensitive(Target, Filter)); +} + internal void FilterSearchLister (search_lister* SearchLister) { @@ -9,7 +15,7 @@ FilterSearchLister (search_lister* SearchLister) for (s32 i = 0; i < SearchLister->SourceListCount; i++) { string* NameString = SearchLister->SourceList + i; - if (SpecificationPassesFilter(*NameString, SearchLister->Filter)) + if (NamePassesFilter(*NameString, SearchLister->Filter)) { SearchLister->FilteredIndexLUT[SearchLister->FilteredListCount++] = i; } diff --git a/src/node/foldhaus_node_interface.cpp b/src/node/foldhaus_node_interface.cpp new file mode 100644 index 0000000..2e44c67 --- /dev/null +++ b/src/node/foldhaus_node_interface.cpp @@ -0,0 +1,498 @@ + +//////////////////////////////////////// +// +// Node Lister +// +/////////////////////////////////////// + +struct node_lister_operation_state +{ + search_lister SearchLister; + v2 ListPosition; +}; + +OPERATION_RENDER_PROC(RenderNodeLister) +{ + node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory; + + v2 TopLeft = OpState->ListPosition; + v2 Dimension = v2{300, 30}; + + // Filter the lister + OpState->SearchLister.Filter = State->ActiveTextEntry.Buffer; + FilterSearchLister(&OpState->SearchLister); + + // Display Search Lister + search_lister_result NodeListerResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension, + MakeStringLiteral("Nodes List"), + OpState->SearchLister.SourceList, + OpState->SearchLister.FilteredIndexLUT, + OpState->SearchLister.FilteredListCount, + OpState->SearchLister.HotItem, + &State->ActiveTextEntry.Buffer, + State->ActiveTextEntry.CursorPosition, + State->Font, State->Interface, Mouse); +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeListerNextItem) +{ + node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); + OpState->SearchLister.HotItem = GetNextFilteredItem(OpState->SearchLister); +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeListerPrevItem) +{ + node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); + OpState->SearchLister.HotItem = GetPrevFilteredItem(OpState->SearchLister); +} + +FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeLister) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseNodeLister) +{ + node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state); + s32 FilteredNodeIndex = OpState->SearchLister.HotItem; + if (FilteredNodeIndex >= 0) + { + s32 NodeIndex = OpState->SearchLister.FilteredIndexLUT[FilteredNodeIndex]; + PushNodeOnListFromSpecification(State->NodeList, (node_type)NodeIndex, + Mouse.Pos, State->Permanent); + } + CloseNodeLister(State, Event, Mouse); +} + +input_command UniverseViewCommads [] = { + { KeyCode_DownArrow, KeyCode_Invalid, Command_Began, NodeListerNextItem }, + { KeyCode_UpArrow, KeyCode_Invalid, Command_Began, NodeListerPrevItem }, + { KeyCode_Enter, KeyCode_Invalid, Command_Began, SelectAndCloseNodeLister }, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, CloseNodeLister }, + { KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseNodeLister }, + DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY, +}; + +FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) +{ + operation_mode* AddNodeOperation = ActivateOperationModeWithCommands(&State->Modes, UniverseViewCommads); + + AddNodeOperation->Render = RenderNodeLister; + + node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, + &State->Modes, + node_lister_operation_state); + { + OpState->SearchLister.SourceListCount = NodeSpecificationsCount; + OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, string, OpState->SearchLister.SourceListCount); + { + for (s32 i = 0; i < OpState->SearchLister.SourceListCount; i++) + { + OpState->SearchLister.SourceList[i] = MakeString( + NodeSpecifications[i].Name, + NodeSpecifications[i].NameLength); + } + } + OpState->SearchLister.Filter = MakeString(PushArray(&State->Modes.Arena, char, 64), 0, 64); + + OpState->SearchLister.FilteredListMax = OpState->SearchLister.SourceListCount; + OpState->SearchLister.FilteredListCount = 0; + OpState->SearchLister.FilteredIndexLUT = PushArray(&State->Modes.Arena, s32, OpState->SearchLister.SourceListCount); + } + + OpState->ListPosition = Mouse.Pos; + SetTextInputDestinationToString(&State->ActiveTextEntry, &OpState->SearchLister.Filter); +} + +//////////////////////////////////////// +// +// Node Color Picker +// +/////////////////////////////////////// + +struct color_picker_operation_state +{ + v4* ValueAddr; +}; + +internal void +CloseColorPicker(app_state* State) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +FOLDHAUS_INPUT_COMMAND_PROC(CloseColorPickerCommand) +{ + CloseColorPicker(State); +} + +OPERATION_RENDER_PROC(RenderColorPicker) +{ + color_picker_operation_state* OpState = (color_picker_operation_state*)Operation.OpStateMemory; + + + b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, + v2{200, 200}, State->Interface, Mouse); + + if (ShouldClose) + { + CloseColorPicker(State); + } +} + +input_command ColorPickerCommands [] = { + { KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseColorPickerCommand }, +}; + +internal void +OpenColorPicker(app_state* State, node_connection* Connection) +{ + operation_mode* ColorPickerMode = ActivateOperationModeWithCommands(&State->Modes, ColorPickerCommands); + ColorPickerMode->Render = RenderColorPicker; + + color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, + &State->Modes, + color_picker_operation_state); + OpState->ValueAddr = Connection->V4ValuePtr; +} + + +//////////////////////////////////////// +// +// Node Field Text Edit +// +/////////////////////////////////////// + +FOLDHAUS_INPUT_COMMAND_PROC(EndNodeFieldTextEdit) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +input_command NodeFieldTextEditCommands [] = { + { KeyCode_Enter, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit }, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit }, + DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY, +}; + +internal void +BeginNodeFieldTextEdit(app_state* State, node_connection* Connection) +{ + operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, + NodeFieldTextEditCommands); + + SetTextInputDestinationToFloat(&State->ActiveTextEntry, Connection->R32ValuePtr); +} + +//////////////////////////////////////// +// +// Node Port Mouse Drag +// +/////////////////////////////////////// + +struct drag_node_port_operation_state +{ + node_interaction Interaction; +}; + +OPERATION_RENDER_PROC(RenderDraggingNodePort) +{ + drag_node_port_operation_state* OpState = (drag_node_port_operation_state*)Operation.OpStateMemory; + UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, + State->NodeRenderSettings, RenderBuffer); +} + +FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNodePort) +{ + drag_node_port_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_port_operation_state); + + TryConnectNodes(OpState->Interaction, Mouse.Pos, State->NodeList, State->NodeRenderSettings); + DeactivateCurrentOperationMode(&State->Modes); +} + +input_command DragNodePortInputCommands[] = { + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNodePort }, +}; + +internal void +BeginDraggingNodePort(app_state* State, node_interaction Interaction) +{ + operation_mode* DragNodePortMode = ActivateOperationModeWithCommands( + &State->Modes, + DragNodePortInputCommands); + DragNodePortMode->Render = RenderDraggingNodePort; + + drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, + &State->Modes, + drag_node_port_operation_state); + OpState->Interaction = Interaction; +} + +//////////////////////////////////////// +// +// Node Field Mouse Drag +// +/////////////////////////////////////// + +OPERATION_RENDER_PROC(RenderDragNodeField) +{ + // TODO(Peter): + //UpdateDraggingNodeValue(Mouse.Pos, Mouse.OldPos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, State); +} + +internal void +BeginInteractWithNodeField(app_state* State, node_interaction Interaction) +{ + // TODO(Peter): +} + +//////////////////////////////////////// +// +// Node Mouse Drag +// +/////////////////////////////////////// + +struct drag_node_operation_state +{ + node_interaction Interaction; +}; + +OPERATION_RENDER_PROC(RenderDraggingNode) +{ + drag_node_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_operation_state); + UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, + State->NodeRenderSettings); +} + +FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNode) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +input_command DragNodeInputCommands[] = { + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNode }, +}; + +internal void +BeginDraggingNode(app_state* State, node_interaction Interaction) +{ + operation_mode* DragNodeMode = ActivateOperationModeWithCommands( + &State->Modes, + DragNodeInputCommands); + DragNodeMode->Render = RenderDraggingNode; + + drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, + &State->Modes, + drag_node_operation_state); + OpState->Interaction = Interaction; +} + +//////////////////////////////////////// +// +// Node View +// +/////////////////////////////////////// + +struct node_view_operation_state +{ + s32 SelectedNodeHandle; +}; + +FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) +{ + node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); + + node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.DownPos, State->NodeRenderSettings); + if (Node) + { + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, + State->NodeRenderSettings); + if (IsDraggingNodePort(NewInteraction)) + { + BeginDraggingNodePort(State, NewInteraction); + } + else if(IsDraggingNodeValue(NewInteraction)) + { + // TODO(Peter): This probably wants to live in a mouse held action + // the first frame we realize we're held over a field, just transition to + // drag node field + //BeginInteractWithNodeField(State, NewInteraction, State->NodeRenderSettings); + } + else // IsDraggingNode + { + OpState->SelectedNodeHandle = Node->Handle; + BeginDraggingNode(State, NewInteraction); + } + } + else + { + OpState->SelectedNodeHandle = 0; + } +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) +{ + node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); + + node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.Pos, State->NodeRenderSettings); + if (Node) + { + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, + State->NodeRenderSettings); + if(IsDraggingNodeValue(NewInteraction)) + { + node_connection* Connection = Node->Connections + NewInteraction.InputValue; + struct_member_type InputType = Connection->Type; + + if (InputType == MemberType_r32) + { + BeginNodeFieldTextEdit(State, Connection); + } + else if (InputType == MemberType_v4) + { + OpenColorPicker(State, Connection); + } + } + } +} + +OPERATION_RENDER_PROC(RenderNodeView) +{ + node_view_operation_state* OpState = (node_view_operation_state*)Operation.OpStateMemory; + + DEBUG_TRACK_FUNCTION; + + MakeStringBuffer(NodeHeaderBuffer, 128); + + node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle); + + node_list_iterator NodeIter = GetNodeListIterator(*State->NodeList); + while (NodeIteratorIsValid(NodeIter)) + { + node_header* Node = NodeIter.At; + + rect NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); + b32 DrawFields = PointIsInRect(Mouse.Pos, NodeBounds); + + if (Node == SelectedNode) + { + PushRenderQuad2D(RenderBuffer, NodeBounds.Min - v2{2, 2}, NodeBounds.Max + v2{2, 2}, WhiteV4); + } + + PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.5f, .5f, .5f, 1.f}); + + // TODO(Peter): This is just for debug purposes. We can remove and go back to just having + // Node->Name in DrawString + string NodeName = GetNodeName(*Node); + PrintF(&NodeHeaderBuffer, "%.*s: %d", NodeName.Length, NodeName.Memory, Node->Handle); + DrawString(RenderBuffer, NodeHeaderBuffer, State->NodeRenderSettings.Font, + v2{NodeBounds.Min.x + 5, NodeBounds.Max.y - (State->NodeRenderSettings.Font->PixelHeight + NODE_HEADER_HEIGHT + 5)}, + WhiteV4); + + for (s32 Connection = 0; Connection < Node->ConnectionsCount; Connection++) + { + v4 PortColor = State->NodeRenderSettings.PortColors[Node->Connections[Connection].Type]; + + // Inputs + if (ConnectionIsInput(Node, Connection)) + { + rect PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); + DrawPort(RenderBuffer, PortBounds, PortColor); + + // + // TODO(Peter): I don't like excluding OutputNode, feels too much like a special case + // but I don't want to get in to the meta programming right now. + // We should just generate a spec and struct member types for NodeType_OutputNode + // + // :ExcludingOutputNodeSpecialCase + // + if (Node->Type != NodeType_OutputNode && DrawFields) + { + node_specification Spec = NodeSpecifications[Node->Type]; + node_struct_member Member = Spec.MemberList[Connection]; + DrawString(RenderBuffer, MakeString(Member.Name), + State->NodeRenderSettings.Font, + v2{PortBounds.Min.x - 8, PortBounds.Min.y}, WhiteV4, Align_Right); + } + + rect ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); + DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); + + // NOTE(Peter): its way easier to draw the connection on the input port b/c its a 1:1 relationship, + // whereas output ports might have many connections, they really only know about the most recent one + // Not sure if this is a problem. We mostly do everything backwards here, starting at the + // most downstream node and working back up to find dependencies. + if (ConnectionHasUpstreamConnection(Node, Connection)) + { + rect ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); + v2 InputCenter = CalculateRectCenter(PortBounds); + v2 OutputCenter = CalculateRectCenter(ConnectedPortBounds); + PushRenderLine2D(RenderBuffer, OutputCenter, InputCenter, 1, WhiteV4); + } + } + + // Outputs + if (ConnectionIsOutput(Node, Connection)) + { + rect PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); + DrawPort(RenderBuffer, PortBounds, PortColor); + + if (DrawFields) + { + node_specification Spec = NodeSpecifications[Node->Type]; + node_struct_member Member = Spec.MemberList[Connection]; + DrawString(RenderBuffer, MakeString(Member.Name), + State->NodeRenderSettings.Font, + v2{PortBounds.Max.x + 8, PortBounds.Min.y}, WhiteV4); + } + + rect ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); + DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); + } + + for (s32 Button = 0; Button < 3; Button++) + { + rect ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); + PushRenderQuad2D(RenderBuffer, ButtonRect.Min, ButtonRect.Max, DragButtonColors[Button]); + } + } + + Next(&NodeIter); + } +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeViewDeleteNode) +{ + node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state); + if (OpState->SelectedNodeHandle > 0) + { + node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle); + FreeNodeOnList(State->NodeList, SelectedNode); + } +} + +FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeView) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +input_command NodeViewCommands [] = { + { KeyCode_Tab, KeyCode_Invalid, Command_Began, CloseNodeView}, + { KeyCode_A, KeyCode_Invalid, Command_Began, OpenNodeLister}, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, NodeViewBeginMouseDragInteraction}, + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, NodeViewBeginMouseSelectInteraction}, + { KeyCode_X, KeyCode_Invalid, Command_Began, NodeViewDeleteNode}, +}; + +FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView) +{ + operation_mode* NodeViewMode = ActivateOperationModeWithCommands(&State->Modes, NodeViewCommands); + NodeViewMode->Render = RenderNodeView; + + node_view_operation_state* OpState = CreateOperationState(NodeViewMode, + &State->Modes, + node_view_operation_state); + + OpState->SelectedNodeHandle = 0; +} From a77d97a31f6075063e7529419b65b87e49575fcc Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 28 Nov 2019 21:12:57 -0800 Subject: [PATCH 02/19] Created an initial version of a standard array template and swapped it in for the assembly array structure. --- src/animation/foldhaus_animation.h | 11 ++ src/foldhaus_app.cpp | 41 ++++-- src/foldhaus_app.h | 8 +- src/foldhaus_assembly.h | 2 + src/foldhaus_debug_visuals.h | 2 +- src/foldhaus_platform.h | 1 + src/gs_array.h | 226 +++++++++++++++++++++++++++++ 7 files changed, 268 insertions(+), 23 deletions(-) create mode 100644 src/animation/foldhaus_animation.h create mode 100644 src/gs_array.h diff --git a/src/animation/foldhaus_animation.h b/src/animation/foldhaus_animation.h new file mode 100644 index 0000000..3b00f99 --- /dev/null +++ b/src/animation/foldhaus_animation.h @@ -0,0 +1,11 @@ +struct animation_block +{ + r32 StartTime; + r32 EndTime; + animation_block* Next; +}; + +struct animation_layer +{ + animation_block* Blocks; +}; \ No newline at end of file diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index b54eb35..8b0858c 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -137,7 +137,6 @@ LoadAssembly (app_state* State, context Context, char* Path) string FileName = Substring(PathString, IndexOfLastSlash + 1); r32 Scale = 100; - Assert(State->AssembliesCount < ASSEMBLY_LIST_LENGTH); s32 AssemblyMemorySize = GetAssemblyMemorySizeFromDefinition(AssemblyDefinition, FileName); u8* AssemblyMemory = Context.PlatformAlloc(AssemblyMemorySize); @@ -147,7 +146,9 @@ LoadAssembly (app_state* State, context Context, char* Path) Scale, AssemblyMemory, AssemblyMemorySize); - State->AssemblyList[State->AssembliesCount++] = NewAssembly; + array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); + PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); + State->TotalLEDsCount += NewAssembly.LEDCount; ClearArenaToSnapshot(State->Transient, TempMemorySnapshot); @@ -156,19 +157,20 @@ LoadAssembly (app_state* State, context Context, char* Path) internal void UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) { - assembly* Assembly = State->AssemblyList + AssemblyIndex; + assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); State->TotalLEDsCount -= Assembly->LEDCount; Context.PlatformFree(Assembly->Arena.Base, Assembly->Arena.Size); - if (AssemblyIndex != (State->AssembliesCount - 1)) + RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - State->AssemblyList[AssemblyIndex] = State->AssemblyList[State->AssembliesCount - 1]; + array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + if (Handle.Index == AssemblyIndex) + { + RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); + break; + } } - else - { - *Assembly = {}; - } - State->AssembliesCount -= 1; } //////////////////////////////////////////////////////////////////////// @@ -287,6 +289,9 @@ 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); @@ -409,9 +414,10 @@ UPDATE_AND_RENDER(UpdateAndRender) s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; - for (s32 i = 0; i < State->AssembliesCount; i++) + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - assembly Assembly = State->AssemblyList[i]; + array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } @@ -475,9 +481,10 @@ UPDATE_AND_RENDER(UpdateAndRender) s32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); - for (s32 AssemblyIdx = 0; AssemblyIdx < State->AssembliesCount; AssemblyIdx++) + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - assembly Assembly = State->AssemblyList[AssemblyIdx]; + array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); for (s32 Job = 0; Job < JobsNeeded; Job++) @@ -529,9 +536,11 @@ UPDATE_AND_RENDER(UpdateAndRender) State->Interface, Mouse); string InterfaceString = MakeString(PushArray(State->Transient, char, 256), 256); - for (int i = 0; i < State->AssembliesCount; i++) + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - PrintF(&InterfaceString, "Unload %.*s", State->AssemblyList[i].Name.Length, State->AssemblyList[i].Name.Memory); + array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + PrintF(&InterfaceString, "Unload %.*s", Assembly.Name.Length, Assembly.Name.Memory); ButtonPos.x += ButtonDim.x + 10; button_result UnloadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 1874697..2b354f4 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -46,12 +46,8 @@ struct app_state s32 TotalLEDsCount; - // TODO(Peter): Make this dynamic. We want them contiguous in memory since we'll be accessing them - // mostly by looping through them. On the other hand, I don't expect there to ever be more than 100 - // of them at once. -#define ASSEMBLY_LIST_LENGTH 32 - assembly AssemblyList[ASSEMBLY_LIST_LENGTH]; - s32 AssembliesCount; + assembly_array AssemblyList; + array_entry_handle_contiguous_array ActiveAssemblyIndecies; camera Camera; r32 PixelsToWorldScale; diff --git a/src/foldhaus_assembly.h b/src/foldhaus_assembly.h index ea945f7..e413bbe 100644 --- a/src/foldhaus_assembly.h +++ b/src/foldhaus_assembly.h @@ -36,3 +36,5 @@ struct assembly s32 LEDUniverseMapCount; leds_in_universe_range* LEDUniverseMap; }; + +TYPEDEF_ARRAY(assembly); diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index a98770e..8ce9557 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -211,7 +211,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c r32 FramesPerSecond = 1.0f / DeltaTime; - PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d", + PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d | HI SAM!!!! ", 5, DeltaTime, (u32)FramesPerSecond, State->Modes.ActiveModesCount, diff --git a/src/foldhaus_platform.h b/src/foldhaus_platform.h index f927a2a..79d8c88 100644 --- a/src/foldhaus_platform.h +++ b/src/foldhaus_platform.h @@ -1,5 +1,6 @@ #include "gs_language.h" #include "gs_platform.h" +#include "gs_array.h" #include "foldhaus_memory.h" #include "gs_string.h" diff --git a/src/gs_array.h b/src/gs_array.h new file mode 100644 index 0000000..6fd0b47 --- /dev/null +++ b/src/gs_array.h @@ -0,0 +1,226 @@ +struct free_list +{ + free_list* Next; + s32 Index; +}; + +struct bucket_index +{ + s32 Bucket; + s32 IndexInBucket; +}; + +inline bucket_index +GetBucketIndexForIndex (s32 Index, s32 BucketSize) +{ + bucket_index Result = {}; + Result.Bucket = Index / BucketSize; + Result.IndexInBucket = Index % BucketSize; + return Result; +}; + +struct array_entry_handle +{ + s32 Generation; + s32 Index; +}; + +// NOTE(Peter): This is a total bastardization of the preprocessor but it works and is +// easier than writing a metaprogramming system at the moment. +// TODO(Peter): Write a metaprogramming version of this that is actually easy to debug + +#define TYPEDEF_ARRAY(element_type) \ +struct element_type##_array_entry { \ + s32 Generation; \ + union \ + { \ + element_type Entry; \ + free_list Free; \ + }; \ +}; \ +\ +struct element_type##_array \ +{ \ + element_type##_array_entry** Buckets; \ + s32 BucketSize; \ + s32 BucketCount; \ + s32 Used; \ + free_list FreeList; \ +}; \ +\ +internal void \ +GrowBuffer(element_type##_array* Buffer) \ +{ \ + s32 NewBucketSize = sizeof(element_type##_array_entry) * Buffer->BucketSize; \ + element_type##_array_entry* NewBucket = (element_type##_array_entry*)malloc(NewBucketSize); \ + GSZeroMemory((u8*)NewBucket, NewBucketSize); \ + \ + s32 NewBucketIndex = Buffer->BucketCount++; \ + if (!Buffer->Buckets) \ + { \ + Buffer->Buckets = (element_type##_array_entry**)malloc(sizeof(element_type##_array_entry*)); \ + } \ + else \ + { \ + Buffer->Buckets = (element_type##_array_entry**)realloc(Buffer->Buckets, sizeof(element_type##_array_entry*) * Buffer->BucketCount); \ + } \ + Buffer->Buckets[NewBucketIndex] = NewBucket; \ +} \ +\ +internal element_type##_array_entry* \ +GetEntryAtIndex (s32 Index, element_type##_array Buffer) \ +{ \ + bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \ + element_type##_array_entry* Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \ + return Entry; \ +} \ +\ +internal array_entry_handle \ +PushElement (element_type Data, element_type##_array* Buffer) \ +{ \ + array_entry_handle Result = {}; \ + \ + if (Buffer->FreeList.Next != &Buffer->FreeList) \ + { \ + free_list* FreeList = Buffer->FreeList.Next; \ + element_type##_array_entry* Entry = GetEntryAtIndex(FreeList->Index, *Buffer); \ + Buffer->FreeList.Next = Entry->Free.Next; \ + \ + Result.Index = Entry->Free.Index; \ + Result.Generation = Entry->Generation; \ + Entry->Entry = Data; \ + \ + ++Buffer->Used; \ + } \ + else \ + { \ + if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount) \ + { \ + GrowBuffer(Buffer); \ + } \ + \ + s32 Index = Buffer->Used++; \ + s32 BucketIndex = Index / Buffer->BucketSize; \ + s32 IndexInBucket = Index % Buffer->BucketSize; \ + \ + Buffer->Buckets[BucketIndex][IndexInBucket].Entry = Data; \ + Result.Index = Index; \ + Result.Generation = Buffer->Buckets[BucketIndex][IndexInBucket].Generation; \ + } \ + \ + return Result; \ +} \ +\ +internal element_type* \ +GetElementAtIndex (s32 Index, element_type##_array Buffer) \ +{ \ + Assert(Index < Buffer.Used); \ + element_type##_array_entry* Entry = GetEntryAtIndex(Index, Buffer); \ + element_type* Result = &Entry->Entry; \ + return Result; \ +} \ +\ +internal element_type* \ +GetElementWithHandle (array_entry_handle Handle, element_type##_array Buffer) \ +{ \ + element_type* Result = 0; \ + \ + element_type##_array_entry* Entry = GetEntryAtIndex(Handle.Index, Buffer); \ + \ + if (Entry->Generation == Handle.Generation) \ + { \ + Result = &Entry->Entry; \ + } \ + \ + return Result; \ +} \ +\ +internal void \ +RemoveElementAtIndex (s32 Index, element_type##_array* Buffer) \ +{ \ + Assert(Index < Buffer->Used); \ + \ + element_type##_array_entry* Entry = GetEntryAtIndex(Index, *Buffer); \ + ++Entry->Generation; \ + Entry->Free.Index = Index; \ + \ + Entry->Free.Next = Buffer->FreeList.Next; \ + Buffer->FreeList.Next = &Entry->Free; \ + \ + --Buffer->Used; \ +} \ + +// END OF CRAZY MACRO + + +#define TYPEDEF_CONTIGUOUS_ARRAY(element_type) \ +struct element_type##_contiguous_array \ +{ \ + element_type** Buckets; \ + s32 BucketSize; \ + s32 BucketCount; \ + s32 Used; \ +}; \ +\ +internal void \ +GrowBuffer(element_type##_contiguous_array* Buffer) \ +{ \ + s32 NewBucketSize = sizeof(element_type) * Buffer->BucketSize; \ + element_type* NewBucket = (element_type*)malloc(NewBucketSize); \ + GSZeroMemory((u8*)NewBucket, NewBucketSize); \ + \ + s32 NewBucketIndex = Buffer->BucketCount++; \ + if (!Buffer->Buckets) \ + { \ + Buffer->Buckets = (element_type**)malloc(sizeof(element_type*)); \ + } \ + else \ + { \ + Buffer->Buckets = (element_type**)realloc(Buffer->Buckets, sizeof(element_type*) * Buffer->BucketCount); \ + } \ + Buffer->Buckets[NewBucketIndex] = NewBucket; \ +} \ +\ +internal element_type* \ +GetElementAtIndex (s32 Index, element_type##_contiguous_array Buffer) \ +{ \ + bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \ + element_type* Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \ + return Entry; \ +} \ +\ +internal s32 \ +PushElement (element_type Data, element_type##_contiguous_array* Buffer) \ +{ \ + s32 Result = -1; \ + \ + if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount) \ + { \ + GrowBuffer(Buffer); \ + } \ + \ + s32 Index = Buffer->Used++; \ + s32 BucketIndex = Index / Buffer->BucketSize; \ + s32 IndexInBucket = Index % Buffer->BucketSize; \ + \ + Buffer->Buckets[BucketIndex][IndexInBucket] = Data; \ + Result = Index; \ + return Result; \ +} \ +\ +internal void \ +RemoveElementAtIndex (s32 Index, element_type##_contiguous_array* Buffer) \ +{ \ + Assert(Index < Buffer->Used); \ + \ + bucket_index IndexToRemove = GetBucketIndexForIndex(Index, Buffer->BucketSize); \ + bucket_index LastIndex = GetBucketIndexForIndex(Buffer->Used - 1, Buffer->BucketSize); \ + element_type ValueAtLastIndex = Buffer->Buckets[LastIndex.Bucket][LastIndex.IndexInBucket]; \ + Buffer->Buckets[IndexToRemove.Bucket][IndexToRemove.IndexInBucket] = ValueAtLastIndex; \ + --Buffer->Used; \ +} \ + +// END OF CRAZY MACRO + +TYPEDEF_ARRAY(array_entry_handle); +TYPEDEF_CONTIGUOUS_ARRAY(array_entry_handle); \ No newline at end of file From 4d9f28dc6ed327046522a66c95c4a187a59b7f1c Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Tue, 3 Dec 2019 22:40:22 -0800 Subject: [PATCH 03/19] Got SACN transmitting over the network and set it up for blumen lumen --- data/blumen_lumen.fold | 15 +++ data/generate_blumen_code.h | 21 ++++ meta/gs_string_builder.h | 99 +++++++++++++++++ src/foldhaus_app.cpp | 123 ++++++++++++++++++--- src/foldhaus_app.h | 5 + src/foldhaus_platform.h | 1 - src/generated/foldhaus_nodes_generated.cpp | 15 ++- src/gs_hashtable.h | 1 + src/gs_platform.h | 9 +- src/sacn/sacn.h | 4 +- src/win32_foldhaus.cpp | 45 +------- 11 files changed, 272 insertions(+), 66 deletions(-) create mode 100644 data/blumen_lumen.fold create mode 100644 data/generate_blumen_code.h create mode 100644 meta/gs_string_builder.h create mode 100644 src/gs_hashtable.h diff --git a/data/blumen_lumen.fold b/data/blumen_lumen.fold new file mode 100644 index 0000000..6340e2d --- /dev/null +++ b/data/blumen_lumen.fold @@ -0,0 +1,15 @@ +led_strip_count 12 + +led_strip { 0, 0, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.000000, 0.050000, 1.000000), 70 } +led_strip { 0, 1, 0, INTERPOLATE_POINTS, (0.500000, 0.866025, 0.000000), (0.025000, 0.043301, 1.000000), 70 } +led_strip { 0, 2, 0, INTERPOLATE_POINTS, (0.866025, 0.499999, 0.000000), (0.043301, 0.024999, 1.000000), 70 } +led_strip { 0, 3, 0, INTERPOLATE_POINTS, (1.000000, -0.000000, 0.000000), (0.050000, -0.000000, 1.000000), 70 } +led_strip { 0, 4, 0, INTERPOLATE_POINTS, (0.866025, -0.500000, 0.000000), (0.043301, -0.025000, 1.000000), 70 } +led_strip { 0, 5, 0, INTERPOLATE_POINTS, (0.500000, -0.866025, 0.000000), (0.025000, -0.043301, 1.000000), 70 } +led_strip { 0, 6, 0, INTERPOLATE_POINTS, (-0.000000, -1.000000, 0.000000), (-0.000000, -0.050000, 1.000000), 70 } +led_strip { 0, 7, 0, INTERPOLATE_POINTS, (-0.500000, -0.866025, 0.000000), (-0.025000, -0.043301, 1.000000), 70 } +led_strip { 0, 8, 0, INTERPOLATE_POINTS, (-0.866025, -0.499999, 0.000000), (-0.043301, -0.024999, 1.000000), 70 } +led_strip { 0, 9, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.050000, 0.000000, 1.000000), 70 } +led_strip { 0, 10, 0, INTERPOLATE_POINTS, (-0.866025, 0.499999, 0.000000), (-0.043301, 0.024999, 1.000000), 70 } +led_strip { 0, 11, 0, INTERPOLATE_POINTS, (-0.499999, 0.866025, 0.000000), (-0.024999, 0.043301, 1.000000), 70 } +END_OF_ASSEMBLY_FILE \ No newline at end of file diff --git a/data/generate_blumen_code.h b/data/generate_blumen_code.h new file mode 100644 index 0000000..e4acd76 --- /dev/null +++ b/data/generate_blumen_code.h @@ -0,0 +1,21 @@ +// NOTE(Peter): stuff this in a function and itll print out the code needed to generate a blumen +// TODO(Peter): Modify this when you get actual blumen measurements +MakeStringBuffer(Buffer, 256); +v3 InnerVectors[12]; +v3 OuterVectors[12]; +for (s32 i = 0; i < 12; i++) +{ + r32 Theta = ((r32)i / 12.0f) * 2 * PI; + + v3 Direction = v3{GSSin(Theta), GSCos(Theta), 0}; + + InnerVectors[i] = Direction; + OuterVectors[i] = v3{Direction.x * 0.05f, Direction.y * 0.05f, 1}; + + PrintF(&Buffer, "led_strip { 0, %d, 0, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 70 }\n", + i, + InnerVectors[i].x, InnerVectors[i].y, InnerVectors[i].z, + OuterVectors[i].x, OuterVectors[i].y, OuterVectors[i].z); + NullTerminate(&Buffer); + OutputDebugStringA(Buffer.Memory); +} diff --git a/meta/gs_string_builder.h b/meta/gs_string_builder.h new file mode 100644 index 0000000..519ed0c --- /dev/null +++ b/meta/gs_string_builder.h @@ -0,0 +1,99 @@ +#define STRING_BUILDER_ARRAY_BUFFER_SIZE 32 + +struct string_array +{ + string** Buckets; + s32 BucketSize; + s32 BucketCount; + s32 Used; + free_list FreeList; +}; + +internal string* +GetEntryAtIndex (s32 Index, string_array Buffer) +{ + string* Result = 0; + if (Buffer.Buckets) + { + bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); + Result = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; + } + return Result; +} + +internal s32 +PushElement (string Data, string_array* Buffer) +{ + s32 Result = -1; + + if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount) + { + Buffer->Buckets = (string**)GrowBuffer(Buffer->BucketSize, sizeof(string), &Buffer->BucketCount, (void**)Buffer->Buckets); + } + + s32 Index = Buffer->Used++; + s32 BucketIndex = Index / Buffer->BucketSize; + s32 IndexInBucket = Index % Buffer->BucketSize; + + Buffer->Buckets[BucketIndex][IndexInBucket] = Data; + Result = Index; + return Result; +} + +struct string_builder +{ + string_array Buffer; + s32 BufferElementSize; +}; + +internal string_builder +InitStringBuilder(s32 BufferSize) +{ + string_builder Result = {}; + Result.BufferElementSize = BufferSize; + Result.Buffer.BucketSize = STRING_BUILDER_ARRAY_BUFFER_SIZE; + Result.Buffer.FreeList.Next = &Result.Buffer.FreeList; + return Result; +} + +internal void +GrowStringBuilder (string_builder* StringBuilder) +{ + string NewSegment = {}; + NewSegment.Memory = (char*)malloc(StringBuilder->BufferElementSize * sizeof(char)); + NewSegment.Max = StringBuilder->BufferElementSize; + + PushElement(NewSegment, &StringBuilder->Buffer); +} + +internal void +StringBuilderPrintF (string_builder* StringBuilder, char* Format, ...) +{ + string Addition = {}; + Addition.Max = 2048; + Addition.Memory = (char*)malloc(Addition.Max * sizeof(char)); + + va_list Args; + va_start(Args, Format); + Addition.Length = PrintFArgsList(Addition.Memory, Addition.Max, Format, Args); + + s32 CharsCopied = 0; + while (CharsCopied < Addition.Length) + { + s32 StringBuilderTailIndex = StringBuilder->Buffer.Used - 1; + string* LastString = GetEntryAtIndex(StringBuilderTailIndex, StringBuilder->Buffer); + if (!LastString || LastString->Length >= LastString->Max) + { + GrowStringBuilder(StringBuilder); + StringBuilderTailIndex = StringBuilder->Buffer.Used - 1; + LastString = GetEntryAtIndex(StringBuilderTailIndex, StringBuilder->Buffer); + } + + while (CharsCopied < Addition.Length && LastString->Length < LastString->Max) + { + LastString->Memory[LastString->Length++] = Addition.Memory[CharsCopied++]; + } + } + + free(Addition.Memory); +} \ No newline at end of file diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 8b0858c..3c5591b 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -88,7 +88,6 @@ struct send_sacn_job_data { platform_socket_handle SendSocket; - platform_get_send_address* GetSendAddress; platform_send_to* SendTo; dmx_buffer_list* DMXBuffers; }; @@ -99,7 +98,6 @@ SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) DEBUG_TRACK_FUNCTION; send_sacn_job_data* Data = (send_sacn_job_data*)JobData; - platform_get_send_address* GetSendAddress = Data->GetSendAddress; platform_socket_handle SendSocket = Data->SendSocket; platform_send_to* SendTo = Data->SendTo; @@ -109,10 +107,11 @@ SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) dmx_buffer Buffer = DMXBufferAt->Buffer; u_long V4SendAddress = SACNGetUniverseSendAddress(Buffer.Universe); - platform_network_address_handle SendAddress = GetSendAddress( - AF_INET, - HostToNetU16(DEFAULT_STREAMING_ACN_PORT), - HostToNetU32(V4SendAddress)); + + platform_network_address SendAddress = {}; + SendAddress.Family = AF_INET; + SendAddress.Port = DEFAULT_STREAMING_ACN_PORT; + SendAddress.Address = V4SendAddress; SendTo(SendSocket, SendAddress, (const char*)Buffer.Base, Buffer.TotalSize, 0); @@ -195,10 +194,14 @@ INITIALIZE_APPLICATION(InitializeApplication) { app_state* State = (app_state*)Context.MemoryBase; u8* MemoryCursor = Context.MemoryBase + sizeof(app_state); - s32 PermanentStorageSize = Megabytes(32); - s32 TransientStorageSize = Context.MemorySize - PermanentStorageSize; + s32 PermanentStorageSize = Context.MemorySize; //Megabytes(32); + //s32 TransientStorageSize = Context.MemorySize - PermanentStorageSize; State->Permanent = BootstrapArenaIntoMemory(MemoryCursor, PermanentStorageSize); - State->Transient = BootstrapArenaIntoMemory(MemoryCursor + PermanentStorageSize, TransientStorageSize); + //State->Transient = BootstrapArenaIntoMemory(MemoryCursor + PermanentStorageSize, TransientStorageSize); + + u8* TransientMemory = Context.PlatformAlloc(Megabytes(32)); + InitMemoryArena(&State->TransientMemory, TransientMemory, Megabytes(32), Context.PlatformAlloc); + State->Transient = &State->TransientMemory; InitMemoryArena(&State->SACNMemory, 0, 0, Context.PlatformAlloc); @@ -293,7 +296,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AssemblyList.FreeList.Next = &State->AssemblyList.FreeList; State->ActiveAssemblyIndecies.BucketSize = 32; #if 1 - char Path[] = "radialumia.fold"; + char Path[] = "blumen_lumen.fold"; LoadAssembly(State, Context, Path); #endif @@ -382,6 +385,7 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) Head->Next = NewBuffer; Head = NewBuffer; + u8* DestChannel = Head->Buffer.Base + BufferHeaderSize; for (s32 LEDIdx = LEDUniverseRange.RangeStart; LEDIdx < LEDUniverseRange.RangeOnePastLast; LEDIdx++) @@ -389,8 +393,11 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) led LED = Assembly.LEDs[LEDIdx]; pixel Color = Assembly.Colors[LED.Index]; - s32 DestinationStartChannel = LEDIdx * 3; - *((pixel*)(Head->Buffer.Base + DestinationStartChannel)) = Color; + + DestChannel[0] = Color.R; + DestChannel[1] = Color.G; + DestChannel[2] = Color.B; + DestChannel += 3; } } @@ -410,6 +417,96 @@ UPDATE_AND_RENDER(UpdateAndRender) HandleInput(State, InputQueue, Mouse); + r32 GreenSize = 20.0f; + r32 BlueSize = 25.0f; + r32 RedSize = 25.0f; + + State->GreenIter += Context.DeltaTime * 45; + State->BlueIter += Context.DeltaTime * 25; + State->RedIter += Context.DeltaTime * -35; + + + +#define PATTERN_THREE + +#ifdef PATTERN_ONE + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + TestAssembly.Colors[LED.Index].R = 255; + TestAssembly.Colors[LED.Index].B = 255; + TestAssembly.Colors[LED.Index].G = 255; + } + } +#endif + +#ifdef PATTERN_TWO + if (State->GreenIter > 2 * PI * 100) { State->GreenIter = 0; } + r32 SinAdjusted = 0.5f + (GSSin(State->GreenIter * 0.01f) * .5f); + u8 Brightness = (u8)(GSClamp01(SinAdjusted) * 255); + + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + TestAssembly.Colors[LED.Index].R = Brightness; + TestAssembly.Colors[LED.Index].B = Brightness; + TestAssembly.Colors[LED.Index].G = Brightness; + } + } +#endif + +#ifdef PATTERN_THREE + if(State->GreenIter > 100 + GreenSize) { State->GreenIter = -GreenSize; } + if(State->BlueIter > 100 + BlueSize) { State->BlueIter = -BlueSize; } + if(State->RedIter < 0 - RedSize) { State->RedIter = 100 + RedSize; } + + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + u8 Red = 0; + u8 Green = 0; + u8 Blue = 0; + + r32 GreenDistance = GSAbs(LED.Position.z - State->GreenIter); + r32 GreenBrightness = GSClamp(0.0f, GreenSize - GreenDistance, GreenSize) / GreenSize; + Green = (u8)(GreenBrightness * 255); + + r32 BlueDistance = GSAbs(LED.Position.z - State->BlueIter); + r32 BlueBrightness = GSClamp(0.0f, BlueSize - BlueDistance, BlueSize) / BlueSize; + Blue = (u8)(BlueBrightness * 255); + + r32 RedDistance = GSAbs(LED.Position.z - State->RedIter); + r32 RedBrightness = GSClamp(0.0f, RedSize - RedDistance, RedSize) / RedSize; + Red = (u8)(RedBrightness * 255); + + TestAssembly.Colors[LED.Index].R = Red; + TestAssembly.Colors[LED.Index].B = Blue; + TestAssembly.Colors[LED.Index].G = Green; + } + } +#endif + // Update Visuals Here s32 HeaderSize = State->NetworkProtocolHeaderSize; @@ -424,7 +521,6 @@ UPDATE_AND_RENDER(UpdateAndRender) DEBUG_IF(GlobalDebugServices->Interface.SendSACNData) { - switch (State->NetworkProtocol) { case NetworkProtocol_SACN: @@ -441,7 +537,6 @@ UPDATE_AND_RENDER(UpdateAndRender) send_sacn_job_data* Job = PushStruct(State->Transient, send_sacn_job_data); Job->SendSocket = State->SACN.SendSocket; - Job->GetSendAddress = Context.PlatformGetSendAddress; Job->SendTo = Context.PlatformSendTo; Job->DMXBuffers = DMXBuffers; diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 2b354f4..32d7e10 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -36,6 +36,7 @@ enum network_protocol struct app_state { memory_arena* Permanent; + memory_arena TransientMemory; memory_arena* Transient; memory_arena SACNMemory; @@ -59,6 +60,10 @@ struct app_state bitmap_font* Font; interface_config Interface; + + r32 GreenIter; + r32 BlueIter; + r32 RedIter; }; internal void OpenColorPicker(app_state* State, v4* Address); diff --git a/src/foldhaus_platform.h b/src/foldhaus_platform.h index 79d8c88..1532634 100644 --- a/src/foldhaus_platform.h +++ b/src/foldhaus_platform.h @@ -140,7 +140,6 @@ struct context platform_get_font_info* PlatformGetFontInfo; platform_draw_font_codepoint* PlatformDrawFontCodepoint; platform_get_socket_handle* PlatformGetSocketHandle; - platform_get_send_address* PlatformGetSendAddress; platform_set_socket_option* PlatformSetSocketOption; platform_send_to* PlatformSendTo; platform_close_socket* PlatformCloseSocket; diff --git a/src/generated/foldhaus_nodes_generated.cpp b/src/generated/foldhaus_nodes_generated.cpp index 25fa0d0..2543f5b 100644 --- a/src/generated/foldhaus_nodes_generated.cpp +++ b/src/generated/foldhaus_nodes_generated.cpp @@ -47,7 +47,6 @@ node_struct_member MemberList_sin_wave_data[] = { node_struct_member MemberList_multiply_patterns_data[] = { { MemberType_NODE_COLOR_BUFFER, "ALEDs", (u64)&((multiply_patterns_data*)0)->ALEDs, IsInputMember }, -{ MemberType_NODE_COLOR_BUFFER, "BLEDs", (u64)&((multiply_patterns_data*)0)->BLEDs, IsInputMember }, { MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((multiply_patterns_data*)0)->ResultLEDs, IsOutputMember}, }; @@ -83,8 +82,8 @@ node_specification NodeSpecifications[] = { { NodeType_VectorValue, "VectorValue", 11, MemberList_vector_data, 32, 5, false}, { NodeType_MultiplyNodeProc, "MultiplyNodeProc", 16, MemberList_multiply_data, 12, 3, false}, { NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, false}, -{ NodeType_SinWave, "SinWave", 7, MemberList_sin_wave_data, 20, 4, false}, -{ NodeType_MultiplyPatterns, "MultiplyPatterns", 16, MemberList_multiply_patterns_data, 60, 3, false}, +{ NodeType_SinWave, "SinWave", 7, MemberList_sin_wave_data, 16, 4, false}, +{ NodeType_MultiplyPatterns, "MultiplyPatterns", 16, MemberList_multiply_patterns_data, 40, 2, false}, { NodeType_OutputNode, "OutputNode", 10, MemberList_output_node_data, 20, 1, false}, { NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false}, { NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 44, 4, false}, @@ -93,11 +92,11 @@ node_specification NodeSpecifications[] = { s32 NodeSpecificationsCount = 10; internal void CallNodeProc(node_header* Node, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime) -{ -node_specification Spec = NodeSpecifications[Node->Type]; -switch (Spec.Type) -{ -case NodeType_FloatValue: { FloatValue((float_value_data*)Data, DeltaTime); } break; + { + node_specification Spec = NodeSpecifications[Node->Type]; + switch (Spec.Type) + { + case NodeType_FloatValue: { FloatValue((float_value_data*)Data, DeltaTime); } break; case NodeType_VectorValue: { VectorValue((vector_data*)Data, DeltaTime); } break; case NodeType_MultiplyNodeProc: { MultiplyNodeProc((multiply_data*)Data, DeltaTime); } break; case NodeType_AddNodeProc: { AddNodeProc((add_data*)Data, DeltaTime); } break; diff --git a/src/gs_hashtable.h b/src/gs_hashtable.h new file mode 100644 index 0000000..ab0c014 --- /dev/null +++ b/src/gs_hashtable.h @@ -0,0 +1 @@ +// \ No newline at end of file diff --git a/src/gs_platform.h b/src/gs_platform.h index 332d349..190c89e 100644 --- a/src/gs_platform.h +++ b/src/gs_platform.h @@ -87,6 +87,13 @@ typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle); +struct platform_network_address +{ + s32 Family; + u16 Port; + u32 Address; +}; + typedef s32 platform_socket_handle; typedef s32 platform_network_address_handle; @@ -99,7 +106,7 @@ typedef PLATFORM_GET_SEND_ADDRESS_HANDLE(platform_get_send_address); #define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option); -#define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, platform_network_address_handle AddressHandle, const char* Buffer, s32 BufferLength, s32 Flags) +#define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, platform_network_address Address, const char* Buffer, s32 BufferLength, s32 Flags) typedef PLATFORM_SEND_TO(platform_send_to); #define PLATFORM_CLOSE_SOCKET(name) void name(platform_socket_handle SocketHandle) diff --git a/src/sacn/sacn.h b/src/sacn/sacn.h index cb18e0e..7e406dc 100644 --- a/src/sacn/sacn.h +++ b/src/sacn/sacn.h @@ -330,8 +330,8 @@ SACNGetUniverseSendAddress(s32 Universe) u8 MulticastAddressBuffer[4] = {}; MulticastAddressBuffer[0] = 239; MulticastAddressBuffer[1] = 255; - MulticastAddressBuffer[2] = (u8)(Universe & 0xff00); // high bit - MulticastAddressBuffer[3] = (u8)((Universe & 0x00ff) >> 8); // low bit + MulticastAddressBuffer[2] = (u8)((Universe & 0xff00) >> 8); // high bit + MulticastAddressBuffer[3] = (u8)((Universe & 0x00ff)); // low bit u_long V4Address = (u_long)UpackB4(MulticastAddressBuffer); return V4Address; diff --git a/src/win32_foldhaus.cpp b/src/win32_foldhaus.cpp index e3d53d1..e11a349 100644 --- a/src/win32_foldhaus.cpp +++ b/src/win32_foldhaus.cpp @@ -158,41 +158,6 @@ PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) return (platform_socket_handle)NewSocketIndex; } -#define NETWORK_ADDRESS_DICTIONARY_GROW_SIZE 32 -s32 Win32NetworkAddressHandleMax; -s32 Win32NetworkAddressHandleCount; -sockaddr_in* NetworkAddressValues; - -PLATFORM_GET_SEND_ADDRESS_HANDLE(Win32GetSendAddress) -{ - if (Win32NetworkAddressHandleCount >= Win32NetworkAddressHandleMax) - { - s32 NewDictionaryMax = Win32NetworkAddressHandleMax + NETWORK_ADDRESS_DICTIONARY_GROW_SIZE; - s32 NewDictionaryDataSize = NewDictionaryMax * sizeof(sockaddr_in); - u8* DictionaryMemory = Win32Alloc(NewDictionaryDataSize); - Assert(DictionaryMemory); - - sockaddr_in* NewValues = (sockaddr_in*)(DictionaryMemory); - if (NetworkAddressValues) - { - GSMemCopy(NetworkAddressValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); - Win32Free((u8*)NetworkAddressValues, sizeof(win32_socket) * Win32NetworkAddressHandleCount); - } - NetworkAddressValues = NewValues; - - Win32NetworkAddressHandleMax = NewDictionaryMax; - } - - Assert(Win32NetworkAddressHandleCount < Win32NetworkAddressHandleMax); - s32 NewAddressIndex = Win32NetworkAddressHandleCount++; - - NetworkAddressValues[NewAddressIndex].sin_family = AddressFamily; - NetworkAddressValues[NewAddressIndex].sin_port = HostToNetU16(Port); - NetworkAddressValues[NewAddressIndex].sin_addr.s_addr = HostToNetU32(Address); - - return (platform_network_address_handle)NewAddressIndex; -} - PLATFORM_SET_SOCKET_OPTION(Win32SetSocketOption) { s32 SocketIndex = (s32)SocketHandle; @@ -211,10 +176,12 @@ PLATFORM_SEND_TO(Win32SendTo) s32 SocketIndex = (s32)SocketHandle; Assert(SocketIndex < Win32SocketHandleCount); - s32 AddressIndex = (s32)AddressHandle; - Assert(AddressIndex < Win32NetworkAddressHandleCount); + sockaddr_in SockAddress = {}; + SockAddress.sin_family = Address.Family; + SockAddress.sin_port = HostToNetU16(Address.Port); + SockAddress.sin_addr.s_addr = HostToNetU32(Address.Address); - s32 LengthSent = sendto(SocketValues[SocketIndex].Socket, Buffer, BufferLength, Flags, (sockaddr*)&NetworkAddressValues[AddressIndex], sizeof(sockaddr_in)); + s32 LengthSent = sendto(SocketValues[SocketIndex].Socket, Buffer, BufferLength, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); if (LengthSent == SOCKET_ERROR) { @@ -233,7 +200,6 @@ PLATFORM_CLOSE_SOCKET(Win32CloseSocket) closesocket(SocketValues[SocketIndex].Socket); } - HDC FontDrawingDC; HBITMAP FontBitmap; HFONT CurrentFont; @@ -606,7 +572,6 @@ INT NCmdShow Context.PlatformGetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; - Context.PlatformGetSendAddress = Win32GetSendAddress; Context.PlatformSetSocketOption = Win32SetSocketOption; Context.PlatformSendTo = Win32SendTo; Context.PlatformCloseSocket = Win32CloseSocket; From dbc3886e9179ffedb408c8e215ce62020ba68fd0 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 22 Dec 2019 17:47:26 -0800 Subject: [PATCH 04/19] imported gs_memory_arena.h which is an improved rewrite of gs_memory.h. Integrated this new library in place of gs_memory.h --- src/foldhaus_app.cpp | 80 ++--- src/foldhaus_app.h | 6 +- src/foldhaus_assembly.cpp | 5 +- src/foldhaus_assembly.h | 2 +- src/foldhaus_debug_visuals.h | 9 +- src/foldhaus_memory.h | 78 +---- src/foldhaus_operation_mode.h | 2 +- src/foldhaus_platform.h | 6 + src/gs_memory.h | 461 ------------------------- src/gs_memory_arena.h | 613 ++++++++++++++++++++++++++++++++++ src/gs_platform.h | 3 + src/gs_win32.cpp | 12 + src/win32_foldhaus.cpp | 3 +- 13 files changed, 689 insertions(+), 591 deletions(-) delete mode 100644 src/gs_memory.h create mode 100644 src/gs_memory_arena.h diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 3c5591b..b8edca6 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -122,12 +122,10 @@ SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) internal void LoadAssembly (app_state* State, context Context, char* Path) { - arena_snapshot TempMemorySnapshot = TakeSnapshotOfArena(*State->Transient); - platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); Assert(TestAssemblyFile.Size > 0); - assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, State->Transient); + assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient); Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size); @@ -136,21 +134,19 @@ LoadAssembly (app_state* State, context Context, char* Path) string FileName = Substring(PathString, IndexOfLastSlash + 1); r32 Scale = 100; - s32 AssemblyMemorySize = GetAssemblyMemorySizeFromDefinition(AssemblyDefinition, FileName); - u8* AssemblyMemory = Context.PlatformAlloc(AssemblyMemorySize); + memory_arena AssemblyArena = {}; + AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, v3{0, 0, 0}, Scale, - AssemblyMemory, - AssemblyMemorySize); + AssemblyArena); array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); State->TotalLEDsCount += NewAssembly.LEDCount; - - ClearArenaToSnapshot(State->Transient, TempMemorySnapshot); } internal void @@ -158,7 +154,7 @@ UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) { assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); State->TotalLEDsCount -= Assembly->LEDCount; - Context.PlatformFree(Assembly->Arena.Base, Assembly->Arena.Size); + FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree); RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList); for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) @@ -193,27 +189,22 @@ RELOAD_STATIC_DATA(ReloadStaticData) INITIALIZE_APPLICATION(InitializeApplication) { app_state* State = (app_state*)Context.MemoryBase; - u8* MemoryCursor = Context.MemoryBase + sizeof(app_state); - s32 PermanentStorageSize = Context.MemorySize; //Megabytes(32); - //s32 TransientStorageSize = Context.MemorySize - PermanentStorageSize; - State->Permanent = BootstrapArenaIntoMemory(MemoryCursor, PermanentStorageSize); - //State->Transient = BootstrapArenaIntoMemory(MemoryCursor + PermanentStorageSize, TransientStorageSize); + State->Permanent = {}; + State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Transient = {}; +State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; - u8* TransientMemory = Context.PlatformAlloc(Megabytes(32)); - InitMemoryArena(&State->TransientMemory, TransientMemory, Megabytes(32), Context.PlatformAlloc); - State->Transient = &State->TransientMemory; - - InitMemoryArena(&State->SACNMemory, 0, 0, Context.PlatformAlloc); - - InitializeInputCommandRegistry(&State->DefaultInputCommandRegistry, 32, State->Permanent); + InitializeInputCommandRegistry(&State->DefaultInputCommandRegistry, 32, &State->Permanent); s32 CommandQueueSize = 32; - command_queue_entry* CommandQueueMemory = PushArray(State->Permanent, + command_queue_entry* CommandQueueMemory = PushArray(&State->Permanent, command_queue_entry, CommandQueueSize); State->CommandQueue = InitializeCommandQueue(CommandQueueMemory, CommandQueueSize); - State->ActiveTextEntry.Buffer = MakeString(PushArray(State->Permanent, char, 256), 0, 256); + State->ActiveTextEntry.Buffer = MakeString(PushArray(&State->Permanent, char, 256), 0, 256); // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; @@ -221,12 +212,12 @@ INITIALIZE_APPLICATION(InitializeApplication) platform_memory_result FontFile = Context.PlatformReadEntireFile("Anonymous Pro.ttf"); if (FontFile.Size) { - bitmap_font* Font = PushStruct(State->Permanent, bitmap_font); + bitmap_font* Font = PushStruct(&State->Permanent, bitmap_font); Font->BitmapWidth = 512; Font->BitmapHeight = 512; Font->BitmapBytesPerPixel = 4; - Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel); + Font->BitmapMemory = PushArray(&State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel); Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight); @@ -239,8 +230,8 @@ INITIALIZE_APPLICATION(InitializeApplication) Font->CodepointDictionarySize = (FontInfo.CodepointOnePastLast - FontInfo.CodepointStart); Font->CodepointDictionaryCount = 0; - Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize); - Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize); + Font->CodepointKeys = PushArray(&State->Permanent, char, Font->CodepointDictionarySize); + Font->CodepointValues = PushArray(&State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize); for (s32 Codepoint = FontInfo.CodepointStart; Codepoint < FontInfo.CodepointOnePastLast; @@ -296,7 +287,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AssemblyList.FreeList.Next = &State->AssemblyList.FreeList; State->ActiveAssemblyIndecies.BucketSize = 32; #if 1 - char Path[] = "blumen_lumen.fold"; + char Path[] = "radialumia.fold"; LoadAssembly(State, Context, Path); #endif @@ -308,10 +299,10 @@ INITIALIZE_APPLICATION(InitializeApplication) { // MODES PLAYGROUND State->Modes.ActiveModesCount = 0; - - s32 ModesMemorySize = Kilobytes(32); - u8* ModesMemory = PushSize(State->Permanent, ModesMemorySize); - InitMemoryArena(&State->Modes.Arena, ModesMemory, ModesMemorySize, 0); + State->Modes.Arena = {}; + State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; } } @@ -413,7 +404,7 @@ UPDATE_AND_RENDER(UpdateAndRender) // and need to persist beyond the end of the UpdateAndRender call. In the release version, we won't // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically // incorrect to clear the arena, and then access the memory later. - ClearArena(State->Transient); + ClearArena(&State->Transient); HandleInput(State, InputQueue, Mouse); @@ -515,7 +506,7 @@ UPDATE_AND_RENDER(UpdateAndRender) { array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); - dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, State->Transient); + dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, &State->Transient); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } @@ -535,7 +526,7 @@ UPDATE_AND_RENDER(UpdateAndRender) CurrentDMXBuffer = CurrentDMXBuffer->Next; } - send_sacn_job_data* Job = PushStruct(State->Transient, send_sacn_job_data); + send_sacn_job_data* Job = PushStruct(&State->Transient, send_sacn_job_data); Job->SendSocket = State->SACN.SendSocket; Job->SendTo = Context.PlatformSendTo; Job->DMXBuffers = DMXBuffers; @@ -584,7 +575,7 @@ UPDATE_AND_RENDER(UpdateAndRender) for (s32 Job = 0; Job < JobsNeeded; Job++) { - draw_leds_job_data* JobData = PushStruct(State->Transient, draw_leds_job_data); + draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); JobData->LEDs = Assembly.LEDs; JobData->Colors = Assembly.Colors; JobData->StartIndex = Job * MaxLEDsPerJob; @@ -630,7 +621,7 @@ UPDATE_AND_RENDER(UpdateAndRender) MakeStringLiteral("Load Assembly"), State->Interface, Mouse); - string InterfaceString = MakeString(PushArray(State->Transient, char, 256), 256); + string InterfaceString = MakeString(PushArray(&State->Transient, char, 256), 256); for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); @@ -669,7 +660,18 @@ UPDATE_AND_RENDER(UpdateAndRender) DrawDebugInterface(RenderBuffer, 25, State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, - Context.DeltaTime, State, State->Camera, Mouse, State->Transient); + Context.DeltaTime, State, State->Camera, Mouse, &State->Transient); + } + + // Checking for overflows + { + DEBUG_TRACK_SCOPE(OverflowChecks); + AssertAllocationsNoOverflow(State->Permanent); + for (s32 i = 0; i < State->AssemblyList.Used; i++) + { + assembly* Assembly = GetElementAtIndex(i, State->AssemblyList); + AssertAllocationsNoOverflow(Assembly->Arena); + } } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 32d7e10..037895b 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -35,10 +35,8 @@ enum network_protocol struct app_state { - memory_arena* Permanent; - memory_arena TransientMemory; - memory_arena* Transient; - memory_arena SACNMemory; + memory_arena Permanent; + memory_arena Transient; s32 NetworkProtocolHeaderSize; network_protocol NetworkProtocol; diff --git a/src/foldhaus_assembly.cpp b/src/foldhaus_assembly.cpp index 418b169..8d59332 100644 --- a/src/foldhaus_assembly.cpp +++ b/src/foldhaus_assembly.cpp @@ -12,11 +12,10 @@ ConstructAssemblyFromDefinition (assembly_definition Definition, string AssemblyName, v3 RootPosition, r32 Scale, - u8* MemoryBase, - s32 MemorySize) + memory_arena Arena) { assembly Assembly = {}; - Assembly.Arena = CreateMemoryArena(MemoryBase, MemorySize); + Assembly.Arena = Arena; Assembly.Name = MakeString(PushArray(&Assembly.Arena, char, AssemblyName.Length), AssemblyName.Length); CopyStringTo(AssemblyName, &Assembly.Name); diff --git a/src/foldhaus_assembly.h b/src/foldhaus_assembly.h index e413bbe..637ae5f 100644 --- a/src/foldhaus_assembly.h +++ b/src/foldhaus_assembly.h @@ -24,7 +24,7 @@ struct leds_in_universe_range struct assembly { - static_memory_arena Arena; + memory_arena Arena; string Name; string FilePath; diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index 8ce9557..4454460 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -197,7 +197,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c v2 TopOfDebugView = v2{StartX, WindowHeight - (NewLineYOffset(*Interface.Font) + 5)}; v2 TopOfScreenLinePos = TopOfDebugView; - arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient); + //arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient); string DebugString = InitializeEmptyString(PushArray(Transient, char, 256), 256); @@ -215,8 +215,8 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c 5, DeltaTime, (u32)FramesPerSecond, State->Modes.ActiveModesCount, - State->Modes.Arena.CurrentRegion->Used, - State->Modes.Arena.CurrentRegion->Size, + State->Modes.Arena.TotalUsed, + State->Modes.Arena.TotalSize, State->CommandQueue.Used); DrawString(RenderBuffer, DebugString, Interface.Font, TopOfScreenLinePos, WhiteV4); @@ -356,7 +356,4 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c } #endif } - - ZeroArenaToSnapshot(Transient, StartTempMemory); - ClearArenaToSnapshot(Transient, StartTempMemory); } diff --git a/src/foldhaus_memory.h b/src/foldhaus_memory.h index 16e2378..cdbc2db 100644 --- a/src/foldhaus_memory.h +++ b/src/foldhaus_memory.h @@ -1,5 +1,6 @@ #ifndef GS_MEMORY_H +#if 0 #ifndef GS_LANGUAGE_H typedef uint8_t u8; @@ -230,6 +231,7 @@ ClearArenaToSnapshot (memory_arena* Arena, arena_snapshot Snapshot) Assert(RegionCursor == Snapshot.CurrentRegion); RegionCursor->Used = Snapshot.UsedAtSnapshot; } +#endif // // Basic Memory Arena @@ -253,6 +255,7 @@ CreateMemoryArena (u8* Base, u32 Size) return Result; } +#define PushArrayOnStaticArena(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length) static u8* PushSize_ (static_memory_arena* Arena, u32 Size) { @@ -262,80 +265,5 @@ PushSize_ (static_memory_arena* Arena, u32 Size) return Result; } -// -// Tracked Array Implementation -// - -#define ARRAY_CHECKSUM 0x51bada7b -struct array_header_ -{ - u32 Size; - s32 ElementMax; - s32 ElementCount; - s32 ElementSize; - u32 Checksum; -}; - -#define gs_PushArray(arena, type, size) (type*)gs_PushArray_(arena, sizeof(type), size) - -static u8* -gs_PushArray_ (memory_arena* Arena, u32 StepSize, u32 Count) -{ - u32 ArrayFootprint = sizeof(array_header_) + (StepSize * Count); - array_header_* Header = (array_header_*)PushSize_(Arena, ArrayFootprint); - - array_header_* Body = Header + 1; - u8* Result = (u8*)(Body); - - Header->Size = Count * StepSize; - Header->ElementMax = Count; - Header->ElementSize = StepSize; - Header->ElementCount = 0; - Header->Checksum = ARRAY_CHECKSUM; - - return Result; -} - -#define gs_ArrayHeader_(array) (((array_header_*)array) - 1) - -#ifdef DEBUG -#define gs_ArrayCheck(array) Assert(!array || gs_ArrayHeader_(array)->Checksum == ARRAY_CHECKSUM) -#else -#define gs_ArrayCheck(array) -#endif - -#define gs_ArrayCount(array) gs_ArrayCount_((u8*)array) -static s32 -gs_ArrayCount_ (u8* Base) -{ - gs_ArrayCheck(Base); - return gs_ArrayHeader_(Base)->ElementCount; -} - -#define gs_ArrayMax(array) gs_ArrayMax_((u8*)array) -static s32 -gs_ArrayMax_ (u8* Base) -{ - gs_ArrayCheck(Base); - return gs_ArrayHeader_(Base)->ElementMax; -} - -#define gs_ArrayAdd(array) ( gs_PushArrayElement_((u8*)array), (array) + (gs_ArrayCount(array) - 1) ) -#define gs_ArrayPush(array, ele) *( gs_ArrayAdd(array) ) = (ele) - -static void* -gs_PushArrayElement_ (u8* Base) -{ - gs_ArrayCheck(Base); - Assert(gs_ArrayHeader_(Base)->ElementCount + 1 <= gs_ArrayHeader_(Base)->ElementMax); - - void* Result = (void*)(Base + (gs_ArrayHeader_(Base)->ElementCount * gs_ArrayHeader_(Base)->ElementSize)); - gs_ArrayHeader_(Base)->ElementCount++; - - return Result; -} - - - #define GS_MEMORY_H #endif // GS_MEMORY_H \ No newline at end of file diff --git a/src/foldhaus_operation_mode.h b/src/foldhaus_operation_mode.h index ef7d043..37f464b 100644 --- a/src/foldhaus_operation_mode.h +++ b/src/foldhaus_operation_mode.h @@ -28,7 +28,7 @@ ActivateOperationMode (operation_mode_system* System) Assert(System->ActiveModesCount < OPERATION_MODES_MAX); s32 ModeIndex = System->ActiveModesCount++; - System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(System->Arena); + System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); operation_mode NewMode = {}; System->ActiveModes[ModeIndex] = NewMode; diff --git a/src/foldhaus_platform.h b/src/foldhaus_platform.h index 1532634..5e3a4e5 100644 --- a/src/foldhaus_platform.h +++ b/src/foldhaus_platform.h @@ -3,6 +3,11 @@ #include "gs_array.h" #include "foldhaus_memory.h" + +#define GS_MEMORY_TRACK_ALLOCATIONS +#define GS_MEMORY_NO_STD_LIBS +#include "gs_memory_arena.h" + #include "gs_string.h" #include "foldhaus_debug.h" @@ -133,6 +138,7 @@ struct context platform_alloc* PlatformAlloc; platform_free* PlatformFree; + platform_realloc* PlatformRealloc; platform_read_entire_file* PlatformReadEntireFile; platform_write_entire_file* PlatformWriteEntireFile; platform_get_file_path* PlatformGetFilePath; diff --git a/src/gs_memory.h b/src/gs_memory.h deleted file mode 100644 index 9d1541d..0000000 --- a/src/gs_memory.h +++ /dev/null @@ -1,461 +0,0 @@ -#ifndef GS_MEMORY_H - -#define ArenaZeroStruct(data_ptr) ArenaZeroStruct_((u8*)data_ptr, sizeof(*data_ptr)) -inline void -ArenaZeroStruct_ (u8* Base, s32 Size) -{ - u8* Iter = Base; - for (s32 i = 0; i < Size; i++) { *Iter++ = 0; } -} - -struct grow_arena_result -{ - u8* Base; - s32 Size; -}; - -#define GROW_ARENA_MEMORY(name) grow_arena_result name(s32 Size) -typedef GROW_ARENA_MEMORY(grow_arena_memory); - -#define FREE_ARENA_MEMORY(name) b32 name(u8* Base, s32 Size) -typedef FREE_ARENA_MEMORY(free_arena_memory); - -struct memory_region_header -{ - memory_region_header* Prev; - s32 Size; - s32 Used; - u8* Base; -}; - -inline b32 -RegionCanFitSize (memory_region_header* Header, s32 Size) -{ - b32 Result = (Header->Used + Size) <= Header->Size; - return Result; -} - -inline b32 -AddressIsInRegion (memory_region_header* Header, u8* Address) -{ - b32 Result = (Header->Base <= Address) && (Header->Base + Header->Used > Address); - return Result; -} - -#ifndef DEFAULT_MEMORY_ALIGNMENT -#define DEFAULT_MEMORY_ALIGNMENT (2 * sizeof(void*)) -#endif - -b32 GSMemIsPowerOfTwo (u64 Address) -{ - return (Address & (Address - 1)) == 0; -} - -u64 AlignForward (u64 Base, u64 Align) -{ - u64 P, A, Modulo; - - Assert(GSMemIsPowerOfTwo(Align)); - - P = Base; - A = Align; - Modulo = P & (A - 1); - - if (Modulo != 0) - { - P = P + (A - Modulo); - } - - return P; -} - -////////////////////////////// -// Heap Memory -////////////////////////////// - -// heap_memory_arena -// a growable memory arena that has two ways to interact with it: push and clear. -// Push: returns a free region of continguous memory. If the arenas GrowArenaProc function is set, this may -// get called in order to obtain enough free memory to fulfil the push request -// Clear: clears the entire memory arena. If the arena has been grown at any point, those subsequent -// regions of memory will be freed back to the system. -struct heap_memory_arena -{ - memory_region_header* CurrentRegion; - - s32 RegionMemorySize; - grow_arena_memory* GrowArenaProc; - free_arena_memory* FreeArenaMemoryProc; -}; - -static void -GrowHeapArena (heap_memory_arena* Arena, s32 RequestedSize) -{ - if (Arena->GrowArenaProc) - { - Assert(Arena->RegionMemorySize > 0); - - s32 GrowthSize = GSMax(RequestedSize, Arena->RegionMemorySize); - grow_arena_result NewMemory = Arena->GrowArenaProc(GrowthSize + sizeof(memory_region_header)); - Assert(NewMemory.Size > 0); - - memory_region_header* Header = (memory_region_header*)NewMemory.Base; - Header->Base = (u8*)NewMemory.Base + sizeof(memory_region_header); - Header->Size = NewMemory.Size - sizeof(memory_region_header); - Header->Used = 0; - Header->Prev = Arena->CurrentRegion; - Arena->CurrentRegion = Header; - } - else - { - InvalidCodePath; - } -} - -#define PushStruct(arena, type) (type*)PushSize_(arena, sizeof(type)) -#define PushArray(arena, type, count) (type*)PushSize_(arena, sizeof(type)*count) -static u8* -PushSize_ (heap_memory_arena* Arena, s32 Size) -{ - if (!Arena->CurrentRegion) { GrowHeapArena(Arena, Size); } - - u8* CurrPointer = Arena->CurrentRegion->Base + Arena->CurrentRegion->Used; - u64 Offset = AlignForward((u64)CurrPointer, DEFAULT_MEMORY_ALIGNMENT); - Offset -= (u64)(Arena->CurrentRegion->Base + Arena->CurrentRegion->Used); - - if (!RegionCanFitSize(Arena->CurrentRegion, Size + Offset)) - { - // TODO(Peter): There might be empty space in the current region, its just not big enough for the - // requested size. We should search backwards to see if there is enough space in a previous region - // before growing the arena. - - GrowHeapArena(Arena, Size + Offset); - } - - u8* Result = Arena->CurrentRegion->Base + Arena->CurrentRegion->Used + Offset; - Arena->CurrentRegion->Used += Size + Offset; - - GSZeroMemory(Result, Size); - - return Result; -} - -static void -InitHeapMemoryArena (heap_memory_arena* Arena, s32 RegionMemorySize, - grow_arena_memory* GrowProc, free_arena_memory* FreeProc) -{ - ArenaZeroStruct(Arena); - Arena->RegionMemorySize = RegionMemorySize; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -static void -InitHeapMemoryArena (heap_memory_arena* Arena, u8* Base, s32 Size, - s32 RegionMemorySize = 0, - grow_arena_memory* GrowProc = 0, - free_arena_memory* FreeProc = 0) -{ - Assert(Size > sizeof(memory_region_header)); - - Arena->CurrentRegion = (memory_region_header*)Base; - Arena->CurrentRegion->Base = Base + sizeof(memory_region_header); - Arena->CurrentRegion->Size = Size - sizeof(memory_region_header); - Arena->CurrentRegion->Used = 0; - Arena->CurrentRegion->Prev = 0; - - Arena->RegionMemorySize = RegionMemorySize; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -static void -ClearHeapMemoryArena (heap_memory_arena* Arena) -{ - if (!Arena->CurrentRegion) { return; } - - memory_region_header* CurrentHead = Arena->CurrentRegion; - - if (CurrentHead->Prev) - { - Assert(Arena->FreeArenaMemoryProc); - while(CurrentHead->Prev) - { - memory_region_header* PrevHead = CurrentHead->Prev; - Arena->FreeArenaMemoryProc((u8*)CurrentHead, CurrentHead->Size + sizeof(memory_region_header)); - CurrentHead = PrevHead; - } - - Arena->CurrentRegion = CurrentHead; - } - - Arena->CurrentRegion->Used = 0; -} - - -////////////////////////////// -// Stack Memory -////////////////////////////// - -struct stack_memory_region -{ - stack_memory_region* Prev; -}; - -// stack_memory_arena -// Push: returns a free region of continguous memory. If the arenas GrowArenaProc function is set, this may -// get called in order to obtain enough free memory to fulfil the push request -// Pop: frees the last region allocated on the stack, returning it to the region of memory available to -// be used. -// Clear: clears the entire memory arena. If the arena has been grown at any point, those subsequent -// regions of memory will be freed back to the system. -struct stack_memory_arena -{ - memory_region_header* CurrentRegion; - stack_memory_region* UsedList; - - s32 RegionMemorySize; - grow_arena_memory* GrowArenaProc; - free_arena_memory* FreeArenaMemoryProc; -}; - -static u8* -PushSize_ (stack_memory_arena* Arena, s32 Size) -{ - if (!Arena->CurrentRegion || - !RegionCanFitSize(Arena->CurrentRegion, Size)) - { - if (Arena->GrowArenaProc) - { - Assert(Arena->RegionMemorySize > 0); - - grow_arena_result NewMemory = Arena->GrowArenaProc(Arena->RegionMemorySize + sizeof(memory_region_header)); - Assert(NewMemory.Size > 0); - - memory_region_header* Header = (memory_region_header*)NewMemory.Base; - Header->Base = (u8*)NewMemory.Base + sizeof(memory_region_header); - Header->Size = NewMemory.Size - sizeof(memory_region_header); - Header->Used = 0; - Header->Prev = Arena->CurrentRegion; - Arena->CurrentRegion = Header; - } - else - { - InvalidCodePath; - } - } - - u8* Region = Arena->CurrentRegion->Base + Arena->CurrentRegion->Used; - stack_memory_region* UsedListHeader = (stack_memory_region*)Region; - UsedListHeader->Prev = Arena->UsedList; - Arena->UsedList = UsedListHeader; - - u8* Result = Region + sizeof(stack_memory_region); - Arena->CurrentRegion->Used += Size + sizeof(stack_memory_region); - - return Result; -} - -// NOTE(Peter): Returns size available after the Pop operation -static s32 -PopLast (stack_memory_arena* Arena) -{ - s32 Result = Arena->CurrentRegion->Size - Arena->CurrentRegion->Used; - - if (Arena->UsedList) - { - u8* LastHead = (u8*)Arena->UsedList; - - if (!AddressIsInRegion(Arena->CurrentRegion, LastHead) && - Arena->FreeArenaMemoryProc) - { - memory_region_header* PrevHeader = Arena->CurrentRegion->Prev; - Arena->FreeArenaMemoryProc((u8*)Arena->CurrentRegion, - Arena->CurrentRegion->Size + sizeof(memory_region_header)); - Arena->CurrentRegion = PrevHeader; - - } - - Assert(LastHead >= Arena->CurrentRegion->Base && - LastHead <= Arena->CurrentRegion->Base + Arena->CurrentRegion->Size); - - stack_memory_region* PrevAlloc = Arena->UsedList->Prev; - - s32 SizeUsed = LastHead - Arena->CurrentRegion->Base; - Arena->CurrentRegion->Used = SizeUsed; - Result = Arena->CurrentRegion->Size - Arena->CurrentRegion->Used; - - Arena->UsedList = PrevAlloc; - } - - return Result; -} - -static void -InitStackMemoryArena (stack_memory_arena* Arena, s32 RegionMemorySize, - grow_arena_memory* GrowProc, free_arena_memory* FreeProc) -{ - ArenaZeroStruct(Arena); - Arena->RegionMemorySize = RegionMemorySize; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -static void -InitStackMemoryArena (stack_memory_arena* Arena, u8* Base, s32 Size, - s32 RegionMemorySize = 0, - grow_arena_memory* GrowProc = 0, - free_arena_memory* FreeProc = 0) -{ - Assert(Size > sizeof(memory_region_header)); - - Arena->CurrentRegion = (memory_region_header*)Base; - Arena->CurrentRegion->Base = Base + sizeof(memory_region_header); - Arena->CurrentRegion->Size = Size - sizeof(memory_region_header); - Arena->CurrentRegion->Used = 0; - Arena->CurrentRegion->Prev = 0; - - Arena->RegionMemorySize = RegionMemorySize; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -static void -ClearStackMemoryArena (stack_memory_arena* Arena) -{ - if (!Arena->CurrentRegion) { return; } - - memory_region_header* CurrentHead = Arena->CurrentRegion; - - if (CurrentHead->Prev) - { - Assert(Arena->FreeArenaMemoryProc); - while(CurrentHead->Prev) - { - memory_region_header* PrevHead = CurrentHead->Prev; - Arena->FreeArenaMemoryProc((u8*)CurrentHead, CurrentHead->Size + sizeof(memory_region_header)); - CurrentHead = PrevHead; - } - - Arena->CurrentRegion = CurrentHead; - } - - Arena->CurrentRegion->Used = 0; - Arena->UsedList = 0; -} - -////////////////////////////// -// Pool Memory -////////////////////////////// - -struct chunk_header -{ - chunk_header* Prev; -}; - -struct pool_memory_arena -{ - memory_region_header* CurrentRegion; - s32 ChunkSize; - chunk_header* FreeList; - - s32 RegionMemorySize; - grow_arena_memory* GrowArenaProc; - free_arena_memory* FreeArenaMemoryProc; -}; - -struct chunk_result -{ - s32 Size; - u8* Base; -}; - -static chunk_result -PushChunk (pool_memory_arena* Arena) -{ - chunk_result Result = {}; - - if (Arena->FreeList) - { - Result.Base = (u8*)Arena->FreeList; - Result.Size = Arena->ChunkSize; - - Arena->FreeList = Arena->FreeList->Prev; - } - else - { - if (!RegionCanFitSize(Arena->CurrentRegion, Arena->ChunkSize)) - { - if (Arena->GrowArenaProc) - { - grow_arena_result NewMemory = Arena->GrowArenaProc(Arena->RegionMemorySize + sizeof(memory_region_header)); - Assert(NewMemory.Size > 0); - - memory_region_header* Header = (memory_region_header*)NewMemory.Base; - Header->Base = (u8*)NewMemory.Base + sizeof(memory_region_header); - Header->Size = NewMemory.Size - sizeof(memory_region_header); - Header->Used = 0; - Header->Prev = Arena->CurrentRegion; - Arena->CurrentRegion = Header; - } - else - { - InvalidCodePath; - } - } - - Result.Base = Arena->CurrentRegion->Base + Arena->CurrentRegion->Used; - Result.Size = Arena->ChunkSize; - - Arena->CurrentRegion->Used += Arena->ChunkSize; - } - - return Result; -} - -static void -FreeChunk (pool_memory_arena* Arena, u8* Base, s32 Size) -{ - Assert(Arena->ChunkSize == Size); - - chunk_header* Header = (chunk_header*)Base; - Header->Prev = Arena->FreeList; - Arena->FreeList = Header; -} - -static void -InitPoolMemoryArena (pool_memory_arena* Arena, s32 ChunkSize, s32 ChunksPerRegion, - grow_arena_memory* GrowProc, free_arena_memory* FreeProc) -{ - Assert(ChunkSize > sizeof(chunk_header)); - - ArenaZeroStruct(Arena); - Arena->ChunkSize = ChunkSize; - Arena->RegionMemorySize = ChunkSize * ChunksPerRegion; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -static void -InitStackMemoryArena (pool_memory_arena* Arena, u8* Base, s32 Size, - s32 ChunkSize, s32 ChunksPerRegion, - grow_arena_memory* GrowProc = 0, - free_arena_memory* FreeProc = 0) -{ - Assert(Size > sizeof(memory_region_header)); - Assert(Size % ChunkSize == ChunksPerRegion); - - Arena->CurrentRegion = (memory_region_header*)Base; - Arena->CurrentRegion->Base = Base + sizeof(memory_region_header); - Arena->CurrentRegion->Size = Size - sizeof(memory_region_header); - Arena->CurrentRegion->Used = 0; - Arena->CurrentRegion->Prev = 0; - - Arena->ChunkSize = ChunkSize; - Arena->RegionMemorySize = ChunkSize * ChunksPerRegion; - Arena->GrowArenaProc = GrowProc; - Arena->FreeArenaMemoryProc = FreeProc; -} - -#define GS_MEMORY_H -#endif // GS_MEMORY_H diff --git a/src/gs_memory_arena.h b/src/gs_memory_arena.h new file mode 100644 index 0000000..bcf4746 --- /dev/null +++ b/src/gs_memory_arena.h @@ -0,0 +1,613 @@ +// File: gs_memory_arena.h +// Description: Single header file library that defines a push-only memory arena +// Author: Peter Slattery +// Date Created: 2019-12-22 +// +// +// ----------------- +// Set Up +// ----------------- +// +// Include 'gs_memory_arena.h' in a file and start using it! (Simple! Nice!) +// +// ----------------- +// Usage +// ----------------- +// Simply create a memory_arena and use PushSize, PushStruct, or PushArray +// to allocate out of it. +// See Example Program below. +// +// While there are options you can set (see Options below), the library adheres +// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to +// zero, under all default options, will 'just work'. +// +// Alignment: +// By default, the Push functions use 4 byte alignment +// If you need to control the alignment of an allocation, there are variants of the +// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned +// These functions simply take a final parameter which specifies the alignment. +// Note: Alignment must be a power of two +// +// ----------------- +// Options +// ----------------- +// +// DEBUG: +// Define DEBUG for debug functionality. +// +// To override the default assert function define GSMem_Assert(expression) +// before inluding this file. +// +// GS_MEMORY_NO_STD_LIBS: +// if you don't want stdlib.h to be included, define GS_MEMORY_NO_STD_LIBS +// before including this file. +// Note that if you do this, zero-is-initialization will no longer work for +// memory_arenas. You must either: +// 1. Set each memory_arena's Alloc and Realloc so they can grow fields +// 2. Set each memory_arena's ExpansionRule to ExpansionRule_Disallowed +// If DEBUG is defined, the program will assert if one of the 2 rules above +// aren't followed. +// +// memory_arena.Alloc and memory_arena.Realloc +// By default, memory_arena's will use malloc and realloc to grow. +// You can override this by setting the Alloc and Realloc function pointers +// of a memory_arena. See the example program below for an implementation of this. +// +// GS_MEMORY_BUFFER_SIZE: +// This defines the minimum buffer size for memory_arena's. If an arena doesn't have +// room to fit an allocation, it will allocate a new buffer no smaller than GS_MEMORY_BUFFER_SIZE +// and place the allocation in the new buffer. +// By default this is 4096 bytes. To override, define GS_MEMORY_BUFFER_SIZE before including +// this file +// +// GS_MEMORY_TRACK_ALLOCATIONS: +// If you want to keep records of each allocation performed in every arena, define +// GS_MEMORY_TRACK_ALLOCATIONS before including this file. +// When defined, memory arenas gain fields that allow them to keep a list of every +// allocation they contain. It also adds a footer on the end of each allocation that +// can be checked to ensure there are no writes to allocations that overflow their bounds +// Note that calling ClearArena also clears this list +// You can then call AssertAllocationsNoOverflow occasionally throughout your program +// to check that no allocations have been written beyond their boundaries +// +// +// Example Program +// (this compiles - copy it into its own file though) +#if 0 +#include "gs_memory_arena.h" + +// Places the characters 'gs' at the end of each allocation. This would allow for an external +// function to check that we haven't written past the end of an allocation +void* MallocWrapper(gs_mem_u32 Size) +{ + int SizeWithFooter = Size + (sizeof(char) * 2); + void* Result = malloc(SizeWithFooter); + char* Footer = (char*)(Result + Size); + Footer[0] = 'g'; + Footer[1] = 's'; + return Result; +} + +void* ReallocWrapper(void* Address, gs_mem_u32 Size) +{ + return realloc(Address, Size); +} + +int +main(int ArgCount, char** Args) +{ + memory_arena Arena = {}; +// Uncomment these lines for an example of how you can implement custom allocation functions + // Arena.Alloc = MallocWrapper; + // Arena.Realloc = ReallocWrapper; + + int ArrayLength = 10; + +int* A = PushArray(&Arena, int, ArrayLength); + int* B = PushArray(&Arena, int, ArrayLength); + int* C = PushArray(&Arena, int, ArrayLength); + int* D = PushArrayAligned(&Arena, int, ArrayLength, 8); + int* E = PushArrayAligned(&Arena, int, ArrayLength, 16); + + // Just ensure that we can actually write to each address of each array + for (s32 i = 0; i < ArrayLength; i++) + { + A[i] = i; + B[i] = i; + C[i] = i; + D[i] = i; + E[i] = i; + } + + ClearArena(&Arena); + + A = PushArray(&Arena, int, ArrayLength); +for (s32 i = 0; i < ArrayLength; i++) + { + A[i] = i; + } + + return 0; +} +#endif + +// ------------------- +// Begin Library +// ------------------- +#ifndef GS_MEMORY_ARENA_H + +#ifndef GS_MEMORY_NO_STD_LIBS + +// NOTE(Peter): We use this so that we can fall back on malloc and realloc +// in the event that a memory_arena needs to grow but doesn't have a +// alloc or realloc function pointer assigned to it. +// +// See GrowArena to see where this is used +// +#include + +#endif + +typedef unsigned char gs_mem_u8; +typedef unsigned int gs_mem_u32; +typedef unsigned long long int gs_mem_u64; + +#ifdef DEBUG +#if !defined(GSMem_Assert) +#define GSMem_Assert(expression) \ +if(!(expression)) { \ +*((int *)0) = 5; \ +} + +#endif +#else +#define GSMem_Assert(expression) +#endif + +enum gs_memory_expansion_rule +{ + MemoryExpansion_Allowed, // Zero is initialization lets the memory grow on its own + MemoryExpansion_OnlyIfFunctionsProvided, + MemoryExpansion_Disallowed, + MemoryExpansion_Count, +}; + +// NOTE(Peter): +// This rule is only here to allow for taking arena snapshots. The problem this solves +// is if you take a snapshot while there are 'holes' in memory_buffers behind the +// most recently added memory_buffer, take a snapshot of that arena, then push something +// on that fits in one of those holes, we will fill the hole and be unable to track/free +// that addition via the snapshot construct. +// +// By requiring that allocations in a buffer only come from the most recent memory_buffer +// we can very easily rewind the buffer to the correct location. +// Hence FindAddress_InLastBufferOnly +enum gs_memory_find_address_rule +{ + FindAddress_InAnyBuffer, + FindAddress_InLastBufferOnly, + FindAddress_Count, +}; + +typedef void* gs_memory_alloc(gs_mem_u32 Size); +typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize); +typedef void gs_memory_free(void* Address, gs_mem_u32 Size); + +#ifndef GS_MEMORY_BUFFER_SIZE +#define GS_MEMORY_BUFFER_SIZE 1024 +#endif + +#define GS_MEMORY_FOOTER_SIZE 4 +#define GS_MEMORY_FOOTER_0 'g' +#define GS_MEMORY_FOOTER_1 's' +#define GS_MEMORY_FOOTER_2 'p' +#define GS_MEMORY_FOOTER_3 's' + +struct tracked_allocation +{ +gs_mem_u8* Head; + gs_mem_u8* Footer; + char* File; + gs_mem_u32 LineNumber; +}; + +#define GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE 512 +struct tracked_allocation_buffer +{ + tracked_allocation Buffer[GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE]; +}; + +struct memory_buffer +{ + gs_mem_u8* Buffer; + gs_mem_u32 Size; + gs_mem_u32 Used; +}; + +struct memory_arena +{ + memory_buffer* Buffers; + gs_mem_u32 BuffersCount; + + gs_mem_u32 TotalUsed; + gs_mem_u32 TotalSize; + + gs_memory_find_address_rule FindAddressRule; + gs_memory_expansion_rule ExpansionRule; + gs_memory_alloc* Alloc; + gs_memory_realloc* Realloc; + +#ifdef GS_MEMORY_TRACK_ALLOCATIONS + tracked_allocation_buffer** AllocationBuffers; + gs_mem_u32 AllocationBuffersCount; + gs_mem_u32 AllocationsUsed; + #endif +}; + +struct address_and_buffer +{ + memory_buffer* Buffer; + gs_mem_u64 Address; + gs_mem_u32 SizeWithAlignment; +}; + +struct arena_snapshot +{ + gs_mem_u32 ArenaUsedAtSnapshot; + gs_mem_u32 HeadBufferUsedAtSnapshot; + gs_mem_u32 HeadBufferAtSnapshot; + memory_arena* Arena; + +#ifdef GS_MEMORY_TRACK_ALLOCATIONS + gs_mem_u32 AllocationsUsedAtSnapshot; + #endif +}; + +static void +FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free) +{ + if (Free) + { +for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + { + memory_buffer* Buffer = Arena->Buffers + i; + Free(Buffer->Buffer, Buffer->Size); + } + Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); + } + else + { +#ifdef GS_MEMORY_NO_STD_LIBS + GSMem_Assert(0); +#else + for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + { + memory_buffer* Buffer = Arena->Buffers + i; + free(Buffer->Buffer); + } + free(Arena->Buffers); + #endif + } +} + +#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) + +inline gs_mem_u32 +GetAlignmentOffset (gs_mem_u64 Address, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) +{ + gs_mem_u32 AlignmentOffset = 0; +if (Address & AlignmentMask) + { + AlignmentOffset = Alignment - (Address & AlignmentMask); + } + return AlignmentOffset; +} + +static address_and_buffer +GetAlignedAddressInBuffer(memory_buffer* Buffer, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) +{ + address_and_buffer Result = {}; + + gs_mem_u64 HeadAddress = (gs_mem_u64)Buffer->Buffer + Buffer->Used; + gs_mem_u32 AlignmentOffset = GetAlignmentOffset(HeadAddress, Alignment, AlignmentMask); + gs_mem_u64 AlignedAddress = HeadAddress + AlignmentOffset; + +if (Buffer->Used + AlignmentOffset + Size <= Buffer->Size) + { + Result.Buffer = Buffer; + Result.Address = AlignedAddress; + Result.SizeWithAlignment = Size + AlignmentOffset; + } + + return Result; +} + +static address_and_buffer +FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) +{ +address_and_buffer Result = {}; + for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + { + memory_buffer* At = Arena->Buffers + i; + GSMem_Assert(At); + + address_and_buffer AddressInCurrentBuffer = GetAlignedAddressInBuffer(At, Size, Alignment, AlignmentMask); + if (AddressInCurrentBuffer.Address != 0) + { + Result = AddressInCurrentBuffer; + break; + } + } + return Result; +} + +static gs_mem_u8* +ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size) +{ + gs_mem_u8* Result = 0; + +if (Arena->Alloc) + { + Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size); + } + else + { +#ifdef GS_MEMORY_NO_STD_LIBS + // NOTE(Peter): If you specify no std libs AND don't supply a allocation function + // we should assert as this is an invalid codepath + GSMem_Assert(0); +#else + Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size); + #endif + } + + return Result; +} + +static gs_mem_u8* +ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize) +{ + gs_mem_u8* Result = 0; + + if (Arena->Realloc != 0) + { + Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize); + } + else + { +#ifdef GS_MEMORY_NO_STD_LIBS + // NOTE(Peter): If you specify no std libs AND don't supply a reallocation function + // we should assert as this is an invalid codepath + GSMem_Assert(0); + #else + Result = (gs_mem_u8*)realloc(Head, NewSize); + #endif + } + + return Result; +} + +static memory_buffer* +GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded) +{ + GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed); + if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided) + { + GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0)); + } + + gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1); + gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount; + gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount; + Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize); + Arena->BuffersCount = NewBuffersCount; + + memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1); + NewBuffer->Size = GS_MEMORY_BUFFER_SIZE; + if (SizeNeeded > NewBuffer->Size) + { + NewBuffer->Size = SizeNeeded; + } + + NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size); + NewBuffer->Used = 0; + + Arena->TotalSize += NewBuffer->Size; + return NewBuffer; +} + +#ifdef GS_MEMORY_TRACK_ALLOCATIONS + +#define DetermineAllocationSize(size) (size) + GS_MEMORY_FOOTER_SIZE +#define ClearAllocationsUsed(arena) (arena)->AllocationsUsed = 0 +#define ClearAllocationsUsedToSnapshot(arena, snapshot) \ +(arena)->AllocationsUsed = (snapshot).AllocationsUsedAtSnapshot; + +static void +TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Filename, gs_mem_u32 LineNumber) +{ +gs_mem_u32 AllocationsMax = Arena->AllocationBuffersCount * GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; + if (Arena->AllocationsUsed >= AllocationsMax) + { + gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1; + Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena, + (gs_mem_u8*)Arena->AllocationBuffers, + Arena->AllocationBuffersCount * sizeof(void*), +NewAllocationBuffersCount * sizeof(void*)); + Arena->AllocationBuffersCount = NewAllocationBuffersCount; + + gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1; + Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer)); + } + + gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++; + gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; + gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; + tracked_allocation_buffer* Buffer = Arena->AllocationBuffers[BufferIndex]; + tracked_allocation* NewAllocationTracker = Buffer->Buffer + IndexInBuffer; + + NewAllocationTracker->Head = Head; + +NewAllocationTracker->Footer = Head + Size - GS_MEMORY_FOOTER_SIZE; + NewAllocationTracker->Footer[0] = GS_MEMORY_FOOTER_0; +NewAllocationTracker->Footer[1] = GS_MEMORY_FOOTER_1; +NewAllocationTracker->Footer[2] = GS_MEMORY_FOOTER_2; +NewAllocationTracker->Footer[3] = GS_MEMORY_FOOTER_3; + + NewAllocationTracker->File = Filename; + NewAllocationTracker->LineNumber = LineNumber; +} + + inline bool +VerifyAllocationNoOverflow (tracked_allocation Allocation) +{ + bool Result = ((Allocation.Footer[0] == GS_MEMORY_FOOTER_0) && +(Allocation.Footer[1] == GS_MEMORY_FOOTER_1) && +(Allocation.Footer[2] == GS_MEMORY_FOOTER_2) && + (Allocation.Footer[3] == GS_MEMORY_FOOTER_3)); + return Result; +} + + static void +AssertAllocationsNoOverflow (memory_arena Arena) +{ + for (gs_mem_u32 AllocationIndex = 0; + AllocationIndex< Arena.AllocationsUsed; + AllocationIndex++) + { + gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; + gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; + + tracked_allocation_buffer* Buffer = Arena.AllocationBuffers[BufferIndex]; + tracked_allocation Allocation = Buffer->Buffer[IndexInBuffer]; + +GSMem_Assert(VerifyAllocationNoOverflow(Allocation)); + } +} + +#define PushSize(arena, size) PushSize_((arena), (size), 4, __FILE__, __LINE__) +#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length, 4, __FILE__, __LINE__) +#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type), 4, __FILE__, __LINE__) +#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment), __FILE__, __LINE__) +#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment), __FILE__, __LINE__) +#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment), __FILE__, __LINE__) + +#else // GS_MEMORY_TRACK_ALLOCATIONS + +#define AssertAllocationsNoOverflow(arena) +#define DetermineAllocationSize(size) size +#define ClearAllocationsUsed(arena) +#define ClearAllocationsUsedToSnapshot(arena, snapshot) + +#define TrackAllocation(arena, head, size, filename, linenumber) + +#define PushSize(arena, size) PushSize_((arena), (size)) +#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length) +#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type)) +#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment)) +#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment)) +#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment)) + +#endif // GS_MEMORY_TRACK_ALLOCATIONS + +static gs_mem_u8* +PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0) +{ + // ie. Alignment = 4 = 100 (binary) + // 4 - 1 = 3 + // 100 - 1 = 011 which is a mask of the bits we don't want set in the start address + GSMem_Assert(IsPowerOfTwo(Alignment)); +gs_mem_u32 AlignmentMask = Alignment - 1; + + gs_mem_u32 AllocationSize = DetermineAllocationSize(Size); + + address_and_buffer ResultAddress = {}; + if (Arena->FindAddressRule == FindAddress_InAnyBuffer) + { + ResultAddress = FindAlignedAddressInBufferWithRoom(Arena, AllocationSize, Alignment, AlignmentMask); + } + else if (Arena->FindAddressRule == FindAddress_InLastBufferOnly + && Arena->BuffersCount > 0) + { + memory_buffer* LastBuffer = Arena->Buffers + Arena->BuffersCount - 1; + ResultAddress = GetAlignedAddressInBuffer(LastBuffer, Size, Alignment, AlignmentMask); + } + + if (ResultAddress.Address == 0) + { + memory_buffer* Buffer = GrowArena(Arena, AllocationSize); + ResultAddress = GetAlignedAddressInBuffer(Buffer, AllocationSize, Alignment, AlignmentMask); + } + GSMem_Assert(ResultAddress.Address != 0); +GSMem_Assert((ResultAddress.Address & AlignmentMask) == 0); + + gs_mem_u8* Result = (gs_mem_u8*)ResultAddress.Address; + ResultAddress.Buffer->Used += ResultAddress.SizeWithAlignment; + Arena->TotalUsed += ResultAddress.SizeWithAlignment; + + TrackAllocation(Arena, Result, AllocationSize, Filename, LineNumber); + + return Result; +} + +static void +ClearArena(memory_arena* Arena) +{ + for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) + { + memory_buffer* At = Arena->Buffers + i; + At->Used = 0; + } + + Arena->TotalUsed = 0; + ClearAllocationsUsed(Arena); +} + +static arena_snapshot +TakeSnapshotOfArena(memory_arena* Arena) +{ + Assert(Arena->FindAddressRule == FindAddress_InLastBufferOnly); + +arena_snapshot Result = {}; + Result.Arena = Arena; + Result.ArenaUsedAtSnapshot = Arena->TotalUsed; + if (Arena->BuffersCount > 0) + { + Result.HeadBufferAtSnapshot = Arena->BuffersCount - 1; + } + else + { + Result.HeadBufferAtSnapshot = 0; + } + + memory_buffer* HeadBuffer = Arena->Buffers + Result.HeadBufferAtSnapshot; + if (HeadBuffer) + { + Result.HeadBufferUsedAtSnapshot = HeadBuffer->Used; + } + +return Result; +} + +static void +ClearArenaToSnapshot(memory_arena* Arena, arena_snapshot Snapshot) +{ + Assert(Arena == Snapshot.Arena); + + memory_buffer* HeadBufferAtSnapshot = Arena->Buffers + Snapshot.HeadBufferAtSnapshot; + if (HeadBufferAtSnapshot) + { + HeadBufferAtSnapshot->Used = Snapshot.HeadBufferUsedAtSnapshot; + + for (gs_mem_u32 i = Snapshot.HeadBufferAtSnapshot + 1; i < Arena->BuffersCount; i++) + { + memory_buffer* Buffer = Arena->Buffers + i; + Buffer->Used = 0; + } + } + + Arena->TotalUsed = Snapshot.ArenaUsedAtSnapshot; + ClearAllocationsUsedToSnapshot(Arena, Snapshot); +} +#define GS_MEMORY_ARENA_H +#endif // GS_MEMORY_ARENA_H \ No newline at end of file diff --git a/src/gs_platform.h b/src/gs_platform.h index 190c89e..9f1b5a7 100644 --- a/src/gs_platform.h +++ b/src/gs_platform.h @@ -75,6 +75,9 @@ typedef PLATFORM_ALLOC(platform_alloc); #define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size) typedef PLATFORM_FREE(platform_free); +#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize) +typedef PLATFORM_REALLOC(platform_realloc); + #define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(char* Path) typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); diff --git a/src/gs_win32.cpp b/src/gs_win32.cpp index 277b1aa..fd89867 100644 --- a/src/gs_win32.cpp +++ b/src/gs_win32.cpp @@ -61,6 +61,7 @@ internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer internal PLATFORM_ALLOC(Win32Alloc); internal PLATFORM_FREE(Win32Free); +internal PLATFORM_REALLOC(Win32Realloc); // File IO internal PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile); @@ -610,6 +611,17 @@ PLATFORM_FREE(Win32Free) return Result; } +PLATFORM_REALLOC(Win32Realloc) +{ + u8* NewMemory = Win32BasicAlloc(NewSize); + if (Base) + { + GSMemCopy(Base, NewMemory, OldSize); + Win32Free(Base, OldSize); + } + return NewMemory; +} + // File IO PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) { diff --git a/src/win32_foldhaus.cpp b/src/win32_foldhaus.cpp index e11a349..154a2c3 100644 --- a/src/win32_foldhaus.cpp +++ b/src/win32_foldhaus.cpp @@ -567,7 +567,8 @@ INT NCmdShow Context.GeneralWorkQueue = &WorkQueue; Context.PlatformAlloc = Win32Alloc; Context.PlatformFree = Win32Free; - Context.PlatformReadEntireFile = Win32ReadEntireFile; + Context.PlatformRealloc = Win32Realloc; +Context.PlatformReadEntireFile = Win32ReadEntireFile; Context.PlatformWriteEntireFile = Win32WriteEntireFile; Context.PlatformGetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; From f491988c9043e5c095ed0bd2b6505d4ff561df8e Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 08:11:48 -0800 Subject: [PATCH 05/19] Began experimenting with animation timelines. This is making it obvious that I need to revamp my interface system --- build.bat | 2 +- src/animation/foldhaus_animation.h | 119 +++++++++++++- src/animation/foldhaus_animation_interface.h | 161 +++++++++++++++++++ src/foldhaus_app.cpp | 136 ++++++---------- src/foldhaus_app.h | 100 +++++++++++- src/foldhaus_platform.h | 11 +- todo.txt | 2 +- 7 files changed, 428 insertions(+), 103 deletions(-) create mode 100644 src/animation/foldhaus_animation_interface.h diff --git a/build.bat b/build.bat index 514d5e8..744f502 100644 --- a/build.bat +++ b/build.bat @@ -10,7 +10,7 @@ IF NOT EXIST .\build\ mkdir .\build C:\programs\ctime\ctime.exe -begin %ProjectDevPath%\build\win32_foldhaus_build_time.ctm -set CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- +set CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- -IC:\programs-dev\gs_libs\src set CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -O2 %CommonCompilerFlags% set CommonLinkerFlags= -opt:ref diff --git a/src/animation/foldhaus_animation.h b/src/animation/foldhaus_animation.h index 3b00f99..2967b2c 100644 --- a/src/animation/foldhaus_animation.h +++ b/src/animation/foldhaus_animation.h @@ -1,11 +1,122 @@ +// TODO +// [] - animation system start and end time +// [] - animation blending +// [] - delete a layer +// [] - will need a way to create an empty layer +// [] - get a list of all animation procs + +#define ANIMATION_PROC(name) void name(app_state* State, r32 Time) +typedef ANIMATION_PROC(animation_proc); + struct animation_block { r32 StartTime; r32 EndTime; - animation_block* Next; + animation_proc* Proc; + + u32 Layer; }; -struct animation_layer +struct animation_block_handle { - animation_block* Blocks; -}; \ No newline at end of file + 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; + +r32 Time; + b32 TimelineShouldAdvance; +// :Temporary + 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_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++; + } + + Result.Generation = ++System->Blocks[Result.Index].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 = System->Blocks + Handle.Index; + + // 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; +} + + \ No newline at end of file diff --git a/src/animation/foldhaus_animation_interface.h b/src/animation/foldhaus_animation_interface.h new file mode 100644 index 0000000..a2e26a1 --- /dev/null +++ b/src/animation/foldhaus_animation_interface.h @@ -0,0 +1,161 @@ +// TODO +// [] - Moving animation blocks +// [] - dragging beginning and end of time blocks +// [] - creating a timeblock with a specific animation +// [x] - play, pause, stop, +// [] - setting the start and end of the animation system +// [] - displaying multiple layers +// [] - + +FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlock) +{ + if (AnimationBlockHandleIsValid(State->SelectedAnimationBlockHandle)) + { + RemoveAnimationBlock(State->SelectedAnimationBlockHandle, &State->AnimationSystem); + State->SelectedAnimationBlockHandle = {0}; + } +} + +internal animation_block_handle +DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse) +{ + animation_block_handle Result = SelectedBlockHandle; + +r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; + r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; + panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax, + 0, Interface); + + b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); + + for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) + { + animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; + if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } + + animation_block_handle CurrentBlockHandle = {}; + CurrentBlockHandle.Index = i; + CurrentBlockHandle.Generation = AnimationBlockEntry.Generation; + + animation_block AnimationBlockAt = AnimationBlockEntry.Block; + +r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd; + r32 StartPosition = AnimationPanelWidth * StartTimePercent; + +r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd; + r32 EndPosition = AnimationPanelWidth * EndTimePercent; + + v2 Min = v2{StartPosition, 25}; + v2 Max = v2{EndPosition, 75}; + + v4 BlockColor = BlackV4; + if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + { + BlockColor = PinkV4; + } + + PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); + PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4); + + if (PointIsInRange(Mouse.Pos, Min, Max) + && MouseButtonTransitionedDown(Mouse.LeftButtonState)) + { + MouseDownAndNotHandled = false; +if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + { +// If the block is already selected, deselect it. + Result = {0}; + } + else + { +Result = CurrentBlockHandle; + } + } + } + + r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd; + r32 SliderPosition = AnimationPanelWidth * TimePercent; + PushRenderQuad2D(RenderBuffer, v2{SliderPosition, AnimationPanelHeight}, + v2{SliderPosition + 1, 0}, WhiteV4); + + if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + { + r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth; + r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd; +#define NEW_BLOCK_DURATION 1 + r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION; + + animation_block Block = {0}; + Block.StartTime = NewBlockTimeStart; + Block.EndTime = NewBlockTimeEnd; + Block.Proc = TestPatternThree; + + animation_block_handle NewBlockHandle = AddAnimationBlock(Block, AnimationSystem); + Result = NewBlockHandle; + } + return Result; + } + +internal animation_block_handle +DrawAnimationPanel (animation_system* AnimationSystem, +v2 PanelMin, v2 PanelMax, +animation_block_handle SelectedBlockHandle, +render_command_buffer* RenderBuffer, +interface_config Interface, mouse_state Mouse) +{ + animation_block_handle Result = SelectedBlockHandle; + +r32 OptionsRowHeight = 25; + v2 TimelineMin = PanelMin; + v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight}; + if (TimelineMax.y - TimelineMin.y > 0) + { + Result = DrawAnimationTimeline(AnimationSystem, +TimelineMin, TimelineMax, + SelectedBlockHandle, + RenderBuffer, Interface, Mouse); + } + + v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y }; + v2 OptionsRowMax = PanelMax; + panel_result AnimationPanel = EvaluatePanel(RenderBuffer, OptionsRowMin, OptionsRowMax, + 0, Interface); + + r32 ButtonWidth = 35; + v2 ButtonMin = v2{0, 0}; + v2 ButtonMax = v2{35, OptionsRowHeight - 2}; + v2 ButtonAt = v2{OptionsRowMin.x + 1, OptionsRowMin.y + 1}; + + button_result PauseResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Pause"), + Interface, Mouse); + ButtonAt.x += ButtonWidth + 2; +button_result PlayResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Play"), + Interface, Mouse); + ButtonAt.x += ButtonWidth + 2; +button_result StopResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Stop"), + Interface, Mouse); + + if (PauseResult.Pressed) + { + AnimationSystem->TimelineShouldAdvance = false; + } + + if (PlayResult.Pressed) + { + AnimationSystem->TimelineShouldAdvance = true; + } + + if (StopResult.Pressed) + { + AnimationSystem->TimelineShouldAdvance = false; + AnimationSystem->Time = 0; + } + + return Result; +} \ No newline at end of file diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index b8edca6..6337b14 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -183,6 +183,7 @@ RELOAD_STATIC_DATA(ReloadStaticData) RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, Begin3DViewMouseRotate); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_U, Command_Began, KeyCode_Invalid, OpenUniverseView); + RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_X, Command_Ended, KeyCode_Invalid, DeleteAnimationBlock); } } @@ -297,13 +298,36 @@ State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; ReloadStaticData(Context, GlobalDebugServices, Alloc, Free); - { // MODES PLAYGROUND + // Setup Operation Modes State->Modes.ActiveModesCount = 0; State->Modes.Arena = {}; State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; - } + + { // MODES PLAYGROUND + InitializeAnimationSystem(&State->AnimationSystem); + + animation_block BlockZero = {0}; + BlockZero.StartTime = 0; + BlockZero.EndTime = 2; + BlockZero.Proc = TestPatternOne; + AddAnimationBlock(BlockZero, &State->AnimationSystem); + +animation_block BlockOne = {0}; +BlockOne.StartTime = 3; + BlockOne.EndTime = 5; + BlockOne.Proc = TestPatternTwo; + AddAnimationBlock(BlockOne, &State->AnimationSystem); + +animation_block BlockTwo = {0}; +BlockTwo.StartTime = 5; + BlockTwo.EndTime = 8; + BlockTwo.Proc = TestPatternThree; + AddAnimationBlock(BlockTwo, &State->AnimationSystem); + + State->AnimationSystem.AnimationEnd = 10; + } // End Animation Playground } internal void @@ -408,97 +432,27 @@ UPDATE_AND_RENDER(UpdateAndRender) HandleInput(State, InputQueue, Mouse); - r32 GreenSize = 20.0f; - r32 BlueSize = 25.0f; - r32 RedSize = 25.0f; - - State->GreenIter += Context.DeltaTime * 45; - State->BlueIter += Context.DeltaTime * 25; - State->RedIter += Context.DeltaTime * -35; - - - -#define PATTERN_THREE - -#ifdef PATTERN_ONE - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + if (State->AnimationSystem.TimelineShouldAdvance) { + State->AnimationSystem.Time += Context.DeltaTime; + if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd) { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; - for (s32 LEDIdx = LEDUniverseRange.RangeStart; - LEDIdx < LEDUniverseRange.RangeOnePastLast; - LEDIdx++) - { - led LED = TestAssembly.LEDs[LEDIdx]; - TestAssembly.Colors[LED.Index].R = 255; - TestAssembly.Colors[LED.Index].B = 255; - TestAssembly.Colors[LED.Index].G = 255; - } + State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd; } -#endif -#ifdef PATTERN_TWO - if (State->GreenIter > 2 * PI * 100) { State->GreenIter = 0; } - r32 SinAdjusted = 0.5f + (GSSin(State->GreenIter * 0.01f) * .5f); - u8 Brightness = (u8)(GSClamp01(SinAdjusted) * 255); - - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) - { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; - for (s32 LEDIdx = LEDUniverseRange.RangeStart; - LEDIdx < LEDUniverseRange.RangeOnePastLast; - LEDIdx++) + for (u32 i = 0; i < State->AnimationSystem.BlocksCount; i++) { - led LED = TestAssembly.LEDs[LEDIdx]; - TestAssembly.Colors[LED.Index].R = Brightness; - TestAssembly.Colors[LED.Index].B = Brightness; - TestAssembly.Colors[LED.Index].G = Brightness; - } - } -#endif - -#ifdef PATTERN_THREE - if(State->GreenIter > 100 + GreenSize) { State->GreenIter = -GreenSize; } - if(State->BlueIter > 100 + BlueSize) { State->BlueIter = -BlueSize; } - if(State->RedIter < 0 - RedSize) { State->RedIter = 100 + RedSize; } - - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) - { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; - for (s32 LEDIdx = LEDUniverseRange.RangeStart; - LEDIdx < LEDUniverseRange.RangeOnePastLast; - LEDIdx++) + animation_block_entry BlockEntry = State->AnimationSystem.Blocks[i]; + if (!AnimationBlockIsFree(BlockEntry)) + { + animation_block Block = BlockEntry.Block; + if (State->AnimationSystem.Time >= Block.StartTime + && State->AnimationSystem.Time <= Block.EndTime) { - led LED = TestAssembly.LEDs[LEDIdx]; - u8 Red = 0; - u8 Green = 0; - u8 Blue = 0; - - r32 GreenDistance = GSAbs(LED.Position.z - State->GreenIter); - r32 GreenBrightness = GSClamp(0.0f, GreenSize - GreenDistance, GreenSize) / GreenSize; - Green = (u8)(GreenBrightness * 255); - - r32 BlueDistance = GSAbs(LED.Position.z - State->BlueIter); - r32 BlueBrightness = GSClamp(0.0f, BlueSize - BlueDistance, BlueSize) / BlueSize; - Blue = (u8)(BlueBrightness * 255); - - r32 RedDistance = GSAbs(LED.Position.z - State->RedIter); - r32 RedBrightness = GSClamp(0.0f, RedSize - RedDistance, RedSize) / RedSize; - Red = (u8)(RedBrightness * 255); - - TestAssembly.Colors[LED.Index].R = Red; - TestAssembly.Colors[LED.Index].B = Blue; - TestAssembly.Colors[LED.Index].G = Green; - } + Block.Proc(State, State->AnimationSystem.Time - Block.StartTime); + } + } + } } -#endif - - // Update Visuals Here s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; @@ -649,6 +603,14 @@ UPDATE_AND_RENDER(UpdateAndRender) } } + v2 TimelineMin = v2{0, 0}; + v2 TimelineMax = v2{Context.WindowWidth, 125}; + animation_block_handle NewSelection = DrawAnimationPanel(&State->AnimationSystem, +TimelineMin, TimelineMax, +State->SelectedAnimationBlockHandle, + RenderBuffer, State->Interface, Mouse); + State->SelectedAnimationBlockHandle = NewSelection; + for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) { operation_mode OperationMode = State->Modes.ActiveModes[m]; diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 037895b..87d2c4e 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -21,6 +21,8 @@ typedef struct app_state app_state; #include "foldhaus_command_dispatch.cpp" #include "foldhaus_operation_mode.h" +#include "animation/foldhaus_animation.h" + #include "foldhaus_text_entry.h" #include "foldhaus_search_lister.h" @@ -59,13 +61,102 @@ struct app_state bitmap_font* Font; interface_config Interface; - r32 GreenIter; - r32 BlueIter; - r32 RedIter; + animation_system AnimationSystem; + animation_block_handle SelectedAnimationBlockHandle; }; internal void OpenColorPicker(app_state* State, v4* Address); +// BEGIN TEMPORARY PATTERNS +internal void +TestPatternOne(app_state* State, r32 Time) +{ + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + TestAssembly.Colors[LED.Index].R = 255; + TestAssembly.Colors[LED.Index].B = 255; + TestAssembly.Colors[LED.Index].G = 255; + } + } +} + +internal void +TestPatternTwo(app_state* State, r32 Time) +{ + if (Time > 2 * PI * 100) { Time = 0; } + r32 SinAdjusted = 0.5f + (GSSin(Time * 0.01f) * .5f); + u8 Brightness = (u8)(GSClamp01(SinAdjusted) * 255); + + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + TestAssembly.Colors[LED.Index].R = Brightness; + TestAssembly.Colors[LED.Index].B = 0; + TestAssembly.Colors[LED.Index].G = Brightness; + } + } +} + +internal void +TestPatternThree(app_state* State, r32 Time) +{ +r32 GreenSize = 20.0f; + r32 BlueSize = 25.0f; + r32 RedSize = 25.0f; + + r32 GreenPosition = -GreenSize + (Time * 45); + r32 BluePosition = -BlueSize + (Time * 25); + r32 RedPosition = (100 + RedSize) + (Time * -35); + + array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); + assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); + for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + { + leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + for (s32 LEDIdx = LEDUniverseRange.RangeStart; + LEDIdx < LEDUniverseRange.RangeOnePastLast; + LEDIdx++) + { + led LED = TestAssembly.LEDs[LEDIdx]; + u8 Red = 0; + u8 Green = 0; + u8 Blue = 0; + + r32 GreenDistance = GSAbs(LED.Position.z - GreenPosition); + r32 GreenBrightness = GSClamp(0.0f, GreenSize - GreenDistance, GreenSize) / GreenSize; + Green = (u8)(GreenBrightness * 255); + + r32 BlueDistance = GSAbs(LED.Position.z - BluePosition); + r32 BlueBrightness = GSClamp(0.0f, BlueSize - BlueDistance, BlueSize) / BlueSize; + Blue = (u8)(BlueBrightness * 255); + + r32 RedDistance = GSAbs(LED.Position.z - RedPosition); + r32 RedBrightness = GSClamp(0.0f, RedSize - RedDistance, RedSize) / RedSize; + Red = (u8)(RedBrightness * 255); + + TestAssembly.Colors[LED.Index].R = Red; + TestAssembly.Colors[LED.Index].B = Blue; + TestAssembly.Colors[LED.Index].G = Green; + } + } +} +// END TEMPORARY PATTERNS + #include "foldhaus_assembly.cpp" #include "foldhaus_debug_visuals.h" @@ -73,4 +164,5 @@ internal void OpenColorPicker(app_state* State, v4* Address); #include "foldhaus_text_entry.cpp" #include "foldhaus_search_lister.cpp" -#include "foldhaus_interface.cpp" \ No newline at end of file +#include "foldhaus_interface.cpp" +#include "animation/foldhaus_animation_interface.h" \ No newline at end of file diff --git a/src/foldhaus_platform.h b/src/foldhaus_platform.h index 5e3a4e5..3cdb841 100644 --- a/src/foldhaus_platform.h +++ b/src/foldhaus_platform.h @@ -1,14 +1,13 @@ -#include "gs_language.h" +#define GS_LANGUAGE_NO_PROFILER_DEFINES +#include #include "gs_platform.h" #include "gs_array.h" -#include "foldhaus_memory.h" - #define GS_MEMORY_TRACK_ALLOCATIONS #define GS_MEMORY_NO_STD_LIBS -#include "gs_memory_arena.h" +#include -#include "gs_string.h" +#include #include "foldhaus_debug.h" global_variable debug_services* GlobalDebugServices; @@ -16,7 +15,7 @@ global_variable debug_services* GlobalDebugServices; global_variable platform_alloc* GSAlloc; global_variable platform_free* GSFree; -#include "gs_vector_matrix.h" +#include #include "gs_input.h" diff --git a/todo.txt b/todo.txt index d48682e..900f6a9 100644 --- a/todo.txt +++ b/todo.txt @@ -40,7 +40,7 @@ Hardening - Then we want to think about separating out mode render functions from mode update functions. Not sure its necessary but having something that operates like an update funciton but is called render is weird. Might want some sort of coroutine functionality in place, where modes can add and remove optional, parallel update functions - memory visualization -- - Log memory allocations +- x Log memory allocations - separate rendering thread - cache led positions. Only update if they are moving - :HotCodeReloading From 9b9fe2f5e1d8356aca552ab9d48850c49059993b Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 12:42:55 -0800 Subject: [PATCH 06/19] Created a panel system and began moving everything over to it. --- src/animation/foldhaus_animation_interface.h | 144 -------- src/foldhaus_app.cpp | 187 ++++------- src/foldhaus_app.h | 16 +- src/foldhaus_debug_visuals.h | 5 +- src/foldhaus_panel.cpp | 313 ++++++++++++++++++ src/foldhaus_panel.h | 73 ++++ src/generated/foldhaus_panels_generated.h | 7 + src/gs_memory_arena.h | 2 +- .../foldhaus_panel_animation_timeline.h | 149 +++++++++ src/panels/foldhaus_panel_dmx_view.h | 77 +++++ src/panels/foldhaus_panel_profiler.h | 199 +++++++++++ src/panels/foldhaus_panel_sculpture_view.h | 123 +++++++ 12 files changed, 1030 insertions(+), 265 deletions(-) create mode 100644 src/foldhaus_panel.cpp create mode 100644 src/foldhaus_panel.h create mode 100644 src/generated/foldhaus_panels_generated.h create mode 100644 src/panels/foldhaus_panel_animation_timeline.h create mode 100644 src/panels/foldhaus_panel_dmx_view.h create mode 100644 src/panels/foldhaus_panel_profiler.h create mode 100644 src/panels/foldhaus_panel_sculpture_view.h diff --git a/src/animation/foldhaus_animation_interface.h b/src/animation/foldhaus_animation_interface.h index a2e26a1..a6b6726 100644 --- a/src/animation/foldhaus_animation_interface.h +++ b/src/animation/foldhaus_animation_interface.h @@ -15,147 +15,3 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlock) State->SelectedAnimationBlockHandle = {0}; } } - -internal animation_block_handle -DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse) -{ - animation_block_handle Result = SelectedBlockHandle; - -r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; - r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; - panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax, - 0, Interface); - - b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); - - for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) - { - animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; - if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } - - animation_block_handle CurrentBlockHandle = {}; - CurrentBlockHandle.Index = i; - CurrentBlockHandle.Generation = AnimationBlockEntry.Generation; - - animation_block AnimationBlockAt = AnimationBlockEntry.Block; - -r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd; - r32 StartPosition = AnimationPanelWidth * StartTimePercent; - -r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd; - r32 EndPosition = AnimationPanelWidth * EndTimePercent; - - v2 Min = v2{StartPosition, 25}; - v2 Max = v2{EndPosition, 75}; - - v4 BlockColor = BlackV4; - if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) - { - BlockColor = PinkV4; - } - - PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); - PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4); - - if (PointIsInRange(Mouse.Pos, Min, Max) - && MouseButtonTransitionedDown(Mouse.LeftButtonState)) - { - MouseDownAndNotHandled = false; -if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) - { -// If the block is already selected, deselect it. - Result = {0}; - } - else - { -Result = CurrentBlockHandle; - } - } - } - - r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd; - r32 SliderPosition = AnimationPanelWidth * TimePercent; - PushRenderQuad2D(RenderBuffer, v2{SliderPosition, AnimationPanelHeight}, - v2{SliderPosition + 1, 0}, WhiteV4); - - if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) - { - r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth; - r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd; -#define NEW_BLOCK_DURATION 1 - r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION; - - animation_block Block = {0}; - Block.StartTime = NewBlockTimeStart; - Block.EndTime = NewBlockTimeEnd; - Block.Proc = TestPatternThree; - - animation_block_handle NewBlockHandle = AddAnimationBlock(Block, AnimationSystem); - Result = NewBlockHandle; - } - return Result; - } - -internal animation_block_handle -DrawAnimationPanel (animation_system* AnimationSystem, -v2 PanelMin, v2 PanelMax, -animation_block_handle SelectedBlockHandle, -render_command_buffer* RenderBuffer, -interface_config Interface, mouse_state Mouse) -{ - animation_block_handle Result = SelectedBlockHandle; - -r32 OptionsRowHeight = 25; - v2 TimelineMin = PanelMin; - v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight}; - if (TimelineMax.y - TimelineMin.y > 0) - { - Result = DrawAnimationTimeline(AnimationSystem, -TimelineMin, TimelineMax, - SelectedBlockHandle, - RenderBuffer, Interface, Mouse); - } - - v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y }; - v2 OptionsRowMax = PanelMax; - panel_result AnimationPanel = EvaluatePanel(RenderBuffer, OptionsRowMin, OptionsRowMax, - 0, Interface); - - r32 ButtonWidth = 35; - v2 ButtonMin = v2{0, 0}; - v2 ButtonMax = v2{35, OptionsRowHeight - 2}; - v2 ButtonAt = v2{OptionsRowMin.x + 1, OptionsRowMin.y + 1}; - - button_result PauseResult = EvaluateButton(RenderBuffer, - ButtonAt + ButtonMin, ButtonAt + ButtonMax, - MakeStringLiteral("Pause"), - Interface, Mouse); - ButtonAt.x += ButtonWidth + 2; -button_result PlayResult = EvaluateButton(RenderBuffer, - ButtonAt + ButtonMin, ButtonAt + ButtonMax, - MakeStringLiteral("Play"), - Interface, Mouse); - ButtonAt.x += ButtonWidth + 2; -button_result StopResult = EvaluateButton(RenderBuffer, - ButtonAt + ButtonMin, ButtonAt + ButtonMax, - MakeStringLiteral("Stop"), - Interface, Mouse); - - if (PauseResult.Pressed) - { - AnimationSystem->TimelineShouldAdvance = false; - } - - if (PlayResult.Pressed) - { - AnimationSystem->TimelineShouldAdvance = true; - } - - if (StopResult.Pressed) - { - AnimationSystem->TimelineShouldAdvance = false; - AnimationSystem->Time = 0; - } - - return Result; -} \ No newline at end of file diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 6337b14..0ee0504 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -22,68 +22,6 @@ MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, r32 WindowWidth, r32 Win return WorldPosition; } -struct draw_leds_job_data -{ - led* LEDs; - pixel* Colors; - s32 StartIndex; - s32 OnePastLastIndex; - - render_quad_batch_constructor* Batch; - - m44 FaceCameraMatrix; - m44 ModelViewMatrix; - r32 LEDHalfWidth; -}; - -internal void -DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) -{ - DEBUG_TRACK_FUNCTION; - - draw_leds_job_data* Data = (draw_leds_job_data*)JobData; - - s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; - - quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); - s32 TrisUsed = 0; - - r32 HalfWidth = Data->LEDHalfWidth; - - v4 P0_In = v4{-HalfWidth, -HalfWidth, 0, 1}; - v4 P1_In = v4{HalfWidth, -HalfWidth, 0, 1}; - v4 P2_In = v4{HalfWidth, HalfWidth, 0, 1}; - v4 P3_In = v4{-HalfWidth, HalfWidth, 0, 1}; - - v2 UV0 = v2{0, 0}; - v2 UV1 = v2{1, 0}; - v2 UV2 = v2{1, 1}; - v2 UV3 = v2{0, 1}; - - led* LED = Data->LEDs + Data->StartIndex; - for (s32 LEDIdx = 0; - LEDIdx < LEDCount; - LEDIdx++) - { - pixel PixelColor = Data->Colors[LED->Index]; - v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; - - v4 V4Position = LED->Position; - V4Position.w = 0; - v4 P0 = P0_In + V4Position; - v4 P1 = P1_In + V4Position; - v4 P2 = P2_In + V4Position; - v4 P3 = P3_In + V4Position; - - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, - P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, - P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); - - LED++; - } -} - struct send_sacn_job_data { @@ -194,7 +132,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; State->Transient = {}; -State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; InitializeInputCommandRegistry(&State->DefaultInputCommandRegistry, 32, &State->Permanent); @@ -244,12 +182,12 @@ State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; u32 CodepointW, CodepointH; Context.PlatformDrawFontCodepoint( - Font->BitmapMemory, - Font->BitmapWidth, - Font->BitmapHeight, - CodepointX, CodepointY, - Codepoint, FontInfo, - &CodepointW, &CodepointH); + Font->BitmapMemory, + Font->BitmapWidth, + Font->BitmapHeight, + CodepointX, CodepointY, + Codepoint, FontInfo, + &CodepointW, &CodepointH); AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); } @@ -299,35 +237,44 @@ State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; ReloadStaticData(Context, GlobalDebugServices, Alloc, Free); // Setup Operation Modes - State->Modes.ActiveModesCount = 0; - State->Modes.Arena = {}; - State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; - State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; + State->Modes.ActiveModesCount = 0; + State->Modes.Arena = {}; + State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; { // MODES PLAYGROUND InitializeAnimationSystem(&State->AnimationSystem); - + animation_block BlockZero = {0}; BlockZero.StartTime = 0; - BlockZero.EndTime = 2; - BlockZero.Proc = TestPatternOne; - AddAnimationBlock(BlockZero, &State->AnimationSystem); - -animation_block BlockOne = {0}; -BlockOne.StartTime = 3; - BlockOne.EndTime = 5; + BlockZero.EndTime = 2; + BlockZero.Proc = TestPatternOne; + AddAnimationBlock(BlockZero, &State->AnimationSystem); + + animation_block BlockOne = {0}; + BlockOne.StartTime = 3; + BlockOne.EndTime = 5; BlockOne.Proc = TestPatternTwo; - AddAnimationBlock(BlockOne, &State->AnimationSystem); - -animation_block BlockTwo = {0}; -BlockTwo.StartTime = 5; - BlockTwo.EndTime = 8; - BlockTwo.Proc = TestPatternThree; + AddAnimationBlock(BlockOne, &State->AnimationSystem); + + animation_block BlockTwo = {0}; + BlockTwo.StartTime = 5; + BlockTwo.EndTime = 8; + BlockTwo.Proc = TestPatternThree; AddAnimationBlock(BlockTwo, &State->AnimationSystem); State->AnimationSystem.AnimationEnd = 10; } // End Animation Playground + + + { // Panels Playground + InitializePanelLayout(&State->PanelLayout); +panel* Panel = TakeNewPanel(&State->PanelLayout); + SetPanelDefinition(Panel, GlobalPanelDefs[0]); + SplitPanelVertically(Panel, .5f, v2{0, 0}, v2{Context.WindowWidth, Context.WindowHeight}, &State->PanelLayout); + SetPanelDefinition(&Panel->Right->Panel, GlobalPanelDefs[1]); + } // End Panels Playground } internal void @@ -433,25 +380,25 @@ UPDATE_AND_RENDER(UpdateAndRender) HandleInput(State, InputQueue, Mouse); if (State->AnimationSystem.TimelineShouldAdvance) { - State->AnimationSystem.Time += Context.DeltaTime; - if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd) - { - State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd; - } - + State->AnimationSystem.Time += Context.DeltaTime; + if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd) + { + State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd; + } + for (u32 i = 0; i < State->AnimationSystem.BlocksCount; i++) { animation_block_entry BlockEntry = State->AnimationSystem.Blocks[i]; if (!AnimationBlockIsFree(BlockEntry)) { animation_block Block = BlockEntry.Block; - if (State->AnimationSystem.Time >= Block.StartTime - && State->AnimationSystem.Time <= Block.EndTime) - { - Block.Proc(State, State->AnimationSystem.Time - Block.StartTime); + if (State->AnimationSystem.Time >= Block.StartTime + && State->AnimationSystem.Time <= Block.EndTime) + { + Block.Proc(State, State->AnimationSystem.Time - Block.StartTime); } } - } + } } s32 HeaderSize = State->NetworkProtocolHeaderSize; @@ -486,20 +433,28 @@ UPDATE_AND_RENDER(UpdateAndRender) Job->DMXBuffers = DMXBuffers; Context.GeneralWorkQueue->PushWorkOnQueue( - Context.GeneralWorkQueue, - SACNSendDMXBufferListJob, - Job); + Context.GeneralWorkQueue, + SACNSendDMXBufferListJob, + Job); }break; InvalidDefaultCase; } } +PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight); + PushRenderClearScreen(RenderBuffer); + v2 WindowMin = v2{0, 0}; + v2 WindowMax = v2{Context.WindowWidth, Context.WindowHeight}; + HandleMousePanelInteraction(&State->PanelLayout, WindowMin, WindowMax, Mouse); + DrawAllPanels(State->PanelLayout, WindowMin, WindowMax, RenderBuffer, State->Interface, Mouse, State, Context); + //////////////////////////////// // Render Assembly /////////////////////////////// if (Context.WindowIsVisible) { + #if 0 State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight; m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); @@ -507,7 +462,7 @@ UPDATE_AND_RENDER(UpdateAndRender) r32 LEDHalfWidth = .5f; - PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight, State->Camera); + PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth / 2, Context.WindowHeight, State->Camera); PushRenderClearScreen(RenderBuffer); // TODO(Peter): Pretty sure this isn't working right now @@ -540,9 +495,9 @@ UPDATE_AND_RENDER(UpdateAndRender) JobData->LEDHalfWidth = LEDHalfWidth; Context.GeneralWorkQueue->PushWorkOnQueue( - Context.GeneralWorkQueue, - DrawLEDsInBufferRangeJob, - JobData); + Context.GeneralWorkQueue, + DrawLEDsInBufferRangeJob, + JobData); } } @@ -561,7 +516,6 @@ UPDATE_AND_RENDER(UpdateAndRender) /////////////////////////////////////// // Menu Bar ////////////////////////////////////// - r32 TopBarHeight = 40; { panel_result TopBarPanel = EvaluatePanel(RenderBuffer, @@ -606,11 +560,11 @@ UPDATE_AND_RENDER(UpdateAndRender) v2 TimelineMin = v2{0, 0}; v2 TimelineMax = v2{Context.WindowWidth, 125}; animation_block_handle NewSelection = DrawAnimationPanel(&State->AnimationSystem, -TimelineMin, TimelineMax, -State->SelectedAnimationBlockHandle, - RenderBuffer, State->Interface, Mouse); + TimelineMin, TimelineMax, + State->SelectedAnimationBlockHandle, + RenderBuffer, State->Interface, Mouse); State->SelectedAnimationBlockHandle = NewSelection; - + for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) { operation_mode OperationMode = State->Modes.ActiveModes[m]; @@ -623,16 +577,17 @@ State->SelectedAnimationBlockHandle, DrawDebugInterface(RenderBuffer, 25, State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, Context.DeltaTime, State, State->Camera, Mouse, &State->Transient); +#endif } // Checking for overflows { DEBUG_TRACK_SCOPE(OverflowChecks); - AssertAllocationsNoOverflow(State->Permanent); - for (s32 i = 0; i < State->AssemblyList.Used; i++) - { - assembly* Assembly = GetElementAtIndex(i, State->AssemblyList); - AssertAllocationsNoOverflow(Assembly->Arena); + AssertAllocationsNoOverflow(State->Permanent); + for (s32 i = 0; i < State->AssemblyList.Used; i++) + { + assembly* Assembly = GetElementAtIndex(i, State->AssemblyList); + AssertAllocationsNoOverflow(Assembly->Arena); } } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 87d2c4e..62004fa 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -17,6 +17,8 @@ typedef struct app_state app_state; +#include "foldhaus_panel.h" + #include "foldhaus_command_dispatch.h" #include "foldhaus_command_dispatch.cpp" #include "foldhaus_operation_mode.h" @@ -40,7 +42,7 @@ struct app_state memory_arena Permanent; memory_arena Transient; - s32 NetworkProtocolHeaderSize; +s32 NetworkProtocolHeaderSize; network_protocol NetworkProtocol; streaming_acn SACN; @@ -63,6 +65,8 @@ struct app_state animation_system AnimationSystem; animation_block_handle SelectedAnimationBlockHandle; + + panel_layout PanelLayout; }; internal void OpenColorPicker(app_state* State, v4* Address); @@ -165,4 +169,12 @@ r32 GreenSize = 20.0f; #include "foldhaus_search_lister.cpp" #include "foldhaus_interface.cpp" -#include "animation/foldhaus_animation_interface.h" \ No newline at end of file +#include "animation/foldhaus_animation_interface.h" + +#include "panels/foldhaus_panel_sculpture_view.h" +#include "panels/foldhaus_panel_profiler.h" +#include "panels/foldhaus_panel_dmx_view.h" +#include "panels/foldhaus_panel_animation_timeline.h" + +#include "generated/foldhaus_panels_generated.h" +#include "foldhaus_panel.cpp" diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index 4454460..f5e6641 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -1,4 +1,4 @@ - +#if 0 internal void RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, @@ -188,6 +188,7 @@ DrawDebugFrameList (render_command_buffer* RenderBuffer, interface_config Interf VisibleFrame, Memory); } } +#endif internal void DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_config Interface, r32 WindowWidth, r32 WindowHeight, r32 DeltaTime, app_state* State, camera Camera, mouse_state Mouse, memory_arena* Transient) @@ -311,7 +312,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c v2 ProfilerMin = v2{TopOfDebugView.x, TopOfDebugView.y - 500}; v2 ProfilerMax = v2{TopOfDebugView.x + 700, TopOfDebugView.y - 64}; PushRenderQuad2D(RenderBuffer, ProfilerMin, ProfilerMax, v4{0, 0, 0, .8f}); - DrawDebugFrameList(RenderBuffer, Interface, Mouse, ProfilerMin, ProfilerMax, Transient); + //DrawDebugFrameList(RenderBuffer, Interface, Mouse, ProfilerMin, ProfilerMax, Transient); #if 0 r32 ColumnsStartX = TopOfScreenLinePos.x; diff --git a/src/foldhaus_panel.cpp b/src/foldhaus_panel.cpp new file mode 100644 index 0000000..579ce8e --- /dev/null +++ b/src/foldhaus_panel.cpp @@ -0,0 +1,313 @@ + +///////////////////////////////// +// +// Book-Keeping +// +///////////////////////////////// + +internal void +InitializePanelLayout(panel_layout* Layout) +{ + Layout->FreeList.Free.Next = &Layout->FreeList; +} + +internal panel_entry* +TakeNewPanelEntry(panel_layout* Layout) +{ + panel_entry* FreeEntry = 0; + if (Layout->FreeList.Free.Next != &Layout->FreeList) + { + FreeEntry = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = FreeEntry->Free.Next; + } + else + { + Assert(Layout->PanelsUsed < PANELS_MAX); + FreeEntry = Layout->Panels + Layout->PanelsUsed++; + } + return FreeEntry; +} + +internal panel* +TakeNewPanel(panel_layout* Layout) +{ + panel* Result = 0; + panel_entry* FreeEntry = TakeNewPanelEntry(Layout); +Result = &FreeEntry->Panel; + *Result = {0}; + return Result; +} + +internal void +FreePanelEntry(panel_entry* Entry, panel_layout* Layout) +{ + Assert(Entry >= Layout->Panels && Entry <= Layout->Panels + PANELS_MAX); + Entry->Panel = {0}; + Entry->Free.Next = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = Entry; +} + +internal void +FreePanelAtIndex(s32 Index, panel_layout* Layout) +{ + Assert(Index > 0 && Index < (s32)Layout->PanelsUsed); + panel_entry* EntryToFree = Layout->Panels + Index; + EntryToFree->Free.Next = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = EntryToFree; +} + +internal void +SplitPanelVertically(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) +{ + r32 SplitX = GSLerp(ParentMin.x, ParentMax.x, Percent); + if (SplitX > ParentMin.x && SplitX < ParentMax.x) + { +Parent->SplitDirection = PanelSplit_Vertical; + Parent->SplitPercent = Percent; + + Parent->Left = TakeNewPanelEntry(Layout); + Parent->Left->Panel.Render = Parent->Render; + +Parent->Right = TakeNewPanelEntry(Layout); + Parent->Right->Panel.Render = Parent->Render; + } +} + +internal void +SplitPanelHorizontally(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) +{ + r32 SplitY = GSLerp(ParentMin.y, ParentMax.y, Percent); + if (SplitY > ParentMin.y && SplitY < ParentMax.y) + { +Parent->SplitDirection = PanelSplit_Horizontal; + Parent->SplitPercent = Percent; + + Parent->Bottom = TakeNewPanelEntry(Layout); + Parent->Bottom->Panel.Render = Parent->Render; + +Parent->Top = TakeNewPanelEntry(Layout); + Parent->Top->Panel.Render = Parent->Render; + } +} + +internal void +ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_layout* Layout) +{ + panel_entry* LeftChild = Parent->Left; + panel_entry* RightChild = Parent->Right; + + *Parent = PanelEntryToKeep->Panel; + Parent->SplitDirection = PanelSplit_NoSplit; + + FreePanelEntry(LeftChild, Layout); + FreePanelEntry(RightChild, Layout); +} + +internal void +SetPanelDefinition(panel* Panel, panel_definition Def) +{ + if(Panel->Cleanup) + { + Panel->Cleanup(Panel); + } + +Panel->Cleanup = Def.Cleanup; + Panel->Render = Def.Render; + Def.Init(Panel); +} + +///////////////////////////////// +// +// Rendering And Interaction +// +///////////////////////////////// + +internal void +HandleMousePanelInteractionOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, panel_layout* PanelLayout, mouse_state Mouse) +{ + r32 PanelEdgeClickMaxDistance = 4; + + // TODO(Peter): Need a way to calculate this button's position more systemically + if (Panel->SplitDirection == PanelSplit_NoSplit + && PointIsInRange(Mouse.DownPos, PanelMin, PanelMin + v2{25, 25})) + { + r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); + r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + + if (XDistance > YDistance) + { + r32 XPercent = (Mouse.Pos.x - PanelMin.x) / (PanelMax.x - PanelMin.x); + SplitPanelVertically(Panel, XPercent, PanelMin, PanelMax, PanelLayout); + } + else + { + r32 YPercent = (Mouse.Pos.y - PanelMin.y) / (PanelMax.y - PanelMin.y); + SplitPanelHorizontally(Panel, YPercent, PanelMin, PanelMax, PanelLayout); + } + } + else if (Panel->SplitDirection == PanelSplit_Horizontal) + { + r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); + r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY); + if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) + { + r32 NewSplitY = Mouse.Pos.y; + if (NewSplitY <= PanelMin.y) + { + ConsolidatePanelsKeepOne(Panel, Panel->Top, PanelLayout); + } + else if (NewSplitY >= PanelMax.y) + { + ConsolidatePanelsKeepOne(Panel, Panel->Bottom, PanelLayout); + } + else + { + Panel->SplitPercent = (NewSplitY - PanelMin.y) / (PanelMax.y - PanelMin.y); + } + } + else + { + HandleMousePanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, PanelLayout, Mouse); + HandleMousePanelInteractionOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, PanelLayout, Mouse); + } + } + else if (Panel->SplitDirection == PanelSplit_Vertical) + { + r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); + r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX); + if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) + { + r32 NewSplitX = Mouse.Pos.x; + if (NewSplitX <= PanelMin.x) + { + ConsolidatePanelsKeepOne(Panel, Panel->Right, PanelLayout); + } + else if (NewSplitX >= PanelMax.x) + { + ConsolidatePanelsKeepOne(Panel, Panel->Left, PanelLayout); + } + else + { + Panel->SplitPercent = (NewSplitX - PanelMin.x) / (PanelMax.x - PanelMin.x); + } + } + else + { + HandleMousePanelInteractionOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, PanelLayout, Mouse); + HandleMousePanelInteractionOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, PanelLayout, Mouse); + } + } +} + +internal void +HandleMousePanelInteraction(panel_layout* PanelLayout, v2 WindowMin, v2 WindowMax, mouse_state Mouse) +{ + r32 PanelEdgeClickMaxDistance = 4; + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState)) + { + Assert(PanelLayout->PanelsUsed > 0); + panel* FirstPanel = &PanelLayout->Panels[0].Panel; + HandleMousePanelInteractionOrRecurse(FirstPanel, WindowMin, WindowMax, PanelLayout, Mouse); + } +} + +internal void +DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, v2 FooterMin, v2 FooterMax, interface_config Interface, mouse_state Mouse) +{ + PushRenderQuad2D(RenderBuffer, FooterMin, v2{FooterMax.x, FooterMin.y + 25}, v4{.5f, .5f, .5f, 1.f}); + PushRenderQuad2D(RenderBuffer, FooterMin, FooterMin + v2{25, 25}, WhiteV4); + + v2 PanelSelectButtonMin = FooterMin + v2{30, 1}; + v2 PanelSelectButtonMax = PanelSelectButtonMin + v2{100, 23}; + + if (Panel->PanelSelectionMenuOpen) + { + v2 ButtonDimension = v2{100, 25}; + v2 ButtonMin = v2{PanelSelectButtonMin.x, FooterMax.y}; + + v2 MenuMin = ButtonMin; + v2 MenuMax = v2{ButtonMin.x + ButtonDimension.x, ButtonMin.y + (ButtonDimension.y * GlobalPanelDefsCount)}; + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) + && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) + { + Panel->PanelSelectionMenuOpen = false; + } + + +for (s32 i = 0; i < GlobalPanelDefsCount; i++) + { + panel_definition Def = GlobalPanelDefs[i]; + string DefName = MakeString(Def.PanelName, Def.PanelNameLength); + button_result DefinitionButton = EvaluateButton(RenderBuffer, + ButtonMin, ButtonMin + ButtonDimension, + DefName, Interface, Mouse); + if (DefinitionButton.Pressed) + { + SetPanelDefinition(Panel, Def); + Panel->PanelSelectionMenuOpen = false; + } + + ButtonMin.y += ButtonDimension.y; + } + } + +button_result ButtonResult = EvaluateButton(RenderBuffer, + PanelSelectButtonMin, +PanelSelectButtonMax, + MakeStringLiteral("Select"), Interface, Mouse); + if (ButtonResult.Pressed) + { + Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; + } + +} + +internal void +DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, render_command_buffer* RenderBuffer) +{ + PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color); +} + +internal void +DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) +{ + if (Panel->SplitDirection == PanelSplit_NoSplit) + { + v2 FooterMin = PanelMin; + v2 FooterMax = v2{PanelMax.x, PanelMin.y + 25}; + v2 PanelViewMin = v2{PanelMin.x, FooterMax.y}; + v2 PanelViewMax = PanelMax; + + Panel->Render(*Panel, PanelViewMin, PanelViewMax, RenderBuffer, State, Context, Mouse); + v4 BorderColor = v4{0, 1, 1, 1}; + if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + { + BorderColor = v4{1, 0, 1, 1}; + } + +PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); +DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer); +DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, Interface, Mouse); + } + else if (Panel->SplitDirection == PanelSplit_Horizontal) + { + r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); + DrawPanelOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + DrawPanelOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + } + else if (Panel->SplitDirection == PanelSplit_Vertical) + { + r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); + DrawPanelOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + DrawPanelOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + } +} + +internal void +DrawAllPanels(panel_layout PanelLayout, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) +{ + Assert(PanelLayout.PanelsUsed > 0); + panel* FirstPanel = &PanelLayout.Panels[0].Panel; + DrawPanelOrRecurse(FirstPanel, WindowMin, WindowMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); +} diff --git a/src/foldhaus_panel.h b/src/foldhaus_panel.h new file mode 100644 index 0000000..90a06bd --- /dev/null +++ b/src/foldhaus_panel.h @@ -0,0 +1,73 @@ + +typedef struct panel panel; + +#define PANEL_INIT_PROC(name) void name(panel* Panel) +typedef PANEL_INIT_PROC(panel_init_proc); + +#define PANEL_CLEANUP_PROC(name) void name(panel* Panel) +typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); + +#define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +typedef PANEL_RENDER_PROC(panel_render_proc); + +enum panel_split_direction +{ + PanelSplit_NoSplit, +PanelSplit_Horizontal, + PanelSplit_Vertical, + + PanelSplit_Count, +}; + +typedef struct panel_entry panel_entry; + +struct panel +{ +panel_render_proc* Render; +panel_cleanup_proc* Cleanup; + + panel_split_direction SplitDirection; + r32 SplitPercent; + + // TODO(Peter): This REALLY doesn't want to live here + // Probably belongs in a more generalized PanelInterfaceState or something + b32 PanelSelectionMenuOpen; + + union{ + panel_entry* Left; + panel_entry* Top; + }; + union{ + panel_entry* Right; + panel_entry* Bottom; + }; +}; + +struct free_panel +{ + panel_entry* Next; +}; + +struct panel_entry +{ + panel Panel; + free_panel Free; +}; + +#define PANELS_MAX 16 +struct panel_layout +{ +panel_entry Panels[PANELS_MAX]; + u32 PanelsUsed; + + panel_entry FreeList; +}; + +struct panel_definition +{ + char* PanelName; + s32 PanelNameLength; + panel_init_proc* Init; + panel_cleanup_proc* Cleanup; + panel_render_proc* Render; +}; \ No newline at end of file diff --git a/src/generated/foldhaus_panels_generated.h b/src/generated/foldhaus_panels_generated.h new file mode 100644 index 0000000..fc7847a --- /dev/null +++ b/src/generated/foldhaus_panels_generated.h @@ -0,0 +1,7 @@ +global_variable s32 GlobalPanelDefsCount = 4; +global_variable panel_definition GlobalPanelDefs[] = { + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render }, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render }, + { "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render }, +}; \ No newline at end of file diff --git a/src/gs_memory_arena.h b/src/gs_memory_arena.h index bcf4746..7cf08f3 100644 --- a/src/gs_memory_arena.h +++ b/src/gs_memory_arena.h @@ -191,7 +191,7 @@ enum gs_memory_find_address_rule typedef void* gs_memory_alloc(gs_mem_u32 Size); typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize); -typedef void gs_memory_free(void* Address, gs_mem_u32 Size); +typedef void gs_memory_free(void* Address, gs_mem_u32 Size); #ifndef GS_MEMORY_BUFFER_SIZE #define GS_MEMORY_BUFFER_SIZE 1024 diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h new file mode 100644 index 0000000..9d965e0 --- /dev/null +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -0,0 +1,149 @@ +PANEL_INIT_PROC(AnimationTimeline_Init) +{ + +} + +PANEL_CLEANUP_PROC(AnimationTimeline_Cleanup) +{ + +} + +internal animation_block_handle +DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse) +{ + animation_block_handle Result = SelectedBlockHandle; + +r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; + r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; + panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax, + 0, Interface); + + b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); + + for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) + { + animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; + if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } + + animation_block_handle CurrentBlockHandle = {}; + CurrentBlockHandle.Index = i; + CurrentBlockHandle.Generation = AnimationBlockEntry.Generation; + + animation_block AnimationBlockAt = AnimationBlockEntry.Block; + +r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd; + r32 StartPosition = AnimationPanelWidth * StartTimePercent; + +r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd; + r32 EndPosition = AnimationPanelWidth * EndTimePercent; + + v2 Min = PanelMin + v2{StartPosition, 25}; + v2 Max = PanelMin + v2{EndPosition, 75}; + + v4 BlockColor = BlackV4; + if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + { + BlockColor = PinkV4; + } + + PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); + PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4); + + if (PointIsInRange(Mouse.Pos, Min, Max) + && MouseButtonTransitionedDown(Mouse.LeftButtonState)) + { + MouseDownAndNotHandled = false; +if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + { +// If the block is already selected, deselect it. + Result = {0}; + } + else + { +Result = CurrentBlockHandle; + } + } + } + + r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd; + r32 SliderX = PanelMin.x + (AnimationPanelWidth * TimePercent); + v2 SliderMin = v2{SliderX, PanelMin.y}; + v2 SliderMax = v2{SliderX + 1, PanelMax.y - 25}; + PushRenderQuad2D(RenderBuffer, SliderMin, SliderMax, WhiteV4); + + if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + { + r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth; + r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd; +#define NEW_BLOCK_DURATION 1 + r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION; + + animation_block Block = {0}; + Block.StartTime = NewBlockTimeStart; + Block.EndTime = NewBlockTimeEnd; + Block.Proc = TestPatternThree; + + animation_block_handle NewBlockHandle = AddAnimationBlock(Block, AnimationSystem); + Result = NewBlockHandle; + } + return Result; + } + +PANEL_RENDER_PROC(AnimationTimeline_Render) +{ + animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; + +r32 OptionsRowHeight = 25; + v2 TimelineMin = PanelMin; + v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight}; + if (TimelineMax.y - TimelineMin.y > 0) + { + SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem, +TimelineMin, TimelineMax, + SelectedBlockHandle, + RenderBuffer, State->Interface, Mouse); + } + + v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y }; + v2 OptionsRowMax = PanelMax; + panel_result AnimationPanel = EvaluatePanel(RenderBuffer, OptionsRowMin, OptionsRowMax, + 0, State->Interface); + + r32 ButtonWidth = 35; + v2 ButtonMin = v2{0, 0}; + v2 ButtonMax = v2{35, OptionsRowHeight - 2}; + v2 ButtonAt = v2{OptionsRowMin.x + 1, OptionsRowMin.y + 1}; + + button_result PauseResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Pause"), + State->Interface, Mouse); + ButtonAt.x += ButtonWidth + 2; +button_result PlayResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Play"), + State->Interface, Mouse); + ButtonAt.x += ButtonWidth + 2; +button_result StopResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Stop"), + State->Interface, Mouse); + + if (PauseResult.Pressed) + { + State->AnimationSystem.TimelineShouldAdvance = false; + } + + if (PlayResult.Pressed) + { + State->AnimationSystem.TimelineShouldAdvance = true; + } + + if (StopResult.Pressed) + { + State->AnimationSystem.TimelineShouldAdvance = false; + State->AnimationSystem.Time = 0; + } + +State->SelectedAnimationBlockHandle = SelectedBlockHandle; +} diff --git a/src/panels/foldhaus_panel_dmx_view.h b/src/panels/foldhaus_panel_dmx_view.h new file mode 100644 index 0000000..1986403 --- /dev/null +++ b/src/panels/foldhaus_panel_dmx_view.h @@ -0,0 +1,77 @@ +PANEL_INIT_PROC(DMXView_Init) +{ + +} + +PANEL_CLEANUP_PROC(DMXView_Cleanup) +{ + +} + +PANEL_RENDER_PROC(DMXView_Render) +{ +#if 0 + DEBUG_TRACK_SCOPE(DrawUniverseOutputDisplay); + + universe_view_operation_state* OpState = (universe_view_operation_state*)Operation.OpStateMemory; + + string TitleBarString = InitializeEmptyString(PushArray(State->Transient, char, 64), 64); + + v2 DisplayArea_Dimension = v2{600, 600}; + + v2 DisplayContents_Offset = OpState->DisplayOffset; + + // + // TODO(Peter): I don't like this. Dragging the Universe view should be an operation mode, just + // like rotating the 3D view, but modes don't have access to the state of modes above them in the stack + // (and attempting to cast those states to the appropriate type seems risky) + // + // :NeedToPassStateDownModeChain + // + if (OpState->MouseDown) + { + DisplayContents_Offset += (Mouse.Pos - Mouse.DownPos); + } + + v2 DisplayArea_TopLeft = v2{300, (r32)RenderBuffer->ViewHeight - 50} + DisplayContents_Offset; + v2 UniverseDisplayDimension = v2{100, 100} * OpState->Zoom; + v2 Padding = v2{25, 50} * OpState->Zoom; + + v2 UniverseDisplayTopLeft = DisplayArea_TopLeft; + + sacn_universe_buffer* UniverseList = State->SACN.UniverseBuffer; + while(UniverseList) + { + for (s32 UniverseIdx = 0; + UniverseIdx < UniverseList->Used; + UniverseIdx++) + { + sacn_universe* Universe = UniverseList->Universes + UniverseIdx; + DrawSACNUniversePixels(RenderBuffer, Universe, UniverseDisplayTopLeft, UniverseDisplayDimension); + + + if (OpState->Zoom > .5f) + { + v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12}; + PrintF(&TitleBarString, "Universe %d", Universe->Universe); + DrawString(RenderBuffer, TitleBarString, State->Interface.Font, + TitleDisplayStart, WhiteV4); + } + + UniverseDisplayTopLeft.x += UniverseDisplayDimension.x + Padding.x; + if (UniverseDisplayTopLeft.x > DisplayArea_TopLeft.x + DisplayArea_Dimension.x) + { + UniverseDisplayTopLeft.x = DisplayArea_TopLeft.x; + UniverseDisplayTopLeft.y -= UniverseDisplayDimension.y + Padding.y; + } + + if (UniverseDisplayTopLeft.y < DisplayArea_TopLeft.y - DisplayArea_Dimension.y) + { + break; + } + + } + UniverseList = UniverseList->Next; + } +#endif +} \ No newline at end of file diff --git a/src/panels/foldhaus_panel_profiler.h b/src/panels/foldhaus_panel_profiler.h new file mode 100644 index 0000000..3f4e789 --- /dev/null +++ b/src/panels/foldhaus_panel_profiler.h @@ -0,0 +1,199 @@ +PANEL_INIT_PROC(ProfilerView_Init) +{ + +} + +PANEL_CLEANUP_PROC(ProfilerView_Cleanup) +{ + +} + +internal void +RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, + interface_config Interface, mouse_state Mouse, + v2 Min, v2 Max, + debug_frame* VisibleFrame, memory_arena* Memory) +{ + v4 ThreadColors[] = { + v4{.73f, .33f, .83f, 1}, + v4{0, .50f, .50f, 1}, + v4{.83f, 0, 0, 1}, + v4{.33f, .49f, .83f, 1}, + v4{.74f, .40f, .25f, 1}, + }; + + r32 Width = Max.x - Min.x; + r32 DepthHeight = 64; + + s64 FrameStartCycles = VisibleFrame->FrameStartCycles; + s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; + + debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices, + VisibleFrame); + + MakeStringBuffer(String, 256); + for (s32 i = 0; i < ThreadScopeCalls->Count; i++) + { + scope_record* Record = ThreadScopeCalls->Calls + i; + scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash); + r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles; + r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles; + + v2 ScopeMin = v2{Min.x + (Width * PercentStart), Max.y - ((Record->CallDepth + 1) * DepthHeight)}; + v2 ScopeMax = v2{Min.x + (Width * PercentEnd), ScopeMin.y + (DepthHeight - 4)}; + + if ((ScopeMax.x - ScopeMin.x) >= 1) + { + v4 Color = ThreadColors[0]; + if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax)) + { + Color = GreenV4; + } + + PushRenderQuad2D(RenderBuffer, ScopeMin, ScopeMax, Color); + PushRenderBoundingBox2D(RenderBuffer, ScopeMin, ScopeMax, 1, BlackV4); + + if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax)) + { + PushRenderQuad2D(RenderBuffer, Mouse.Pos, Mouse.Pos + v2{256, 32}, BlackV4); + PrintF(&String, "%.*s : %d - %d", Name->Name.Length, Name->Name.Memory, Record->StartCycles, Record->EndCycles); + DrawString(RenderBuffer, String, Interface.Font, Mouse.Pos, WhiteV4); + } + } + } +} + +internal void +RenderProfiler_ListVisualization(render_command_buffer* RenderBuffer, + interface_config Interface, mouse_state Mouse, + v2 Min, v2 Max, + debug_frame* VisibleFrame, memory_arena* Memory) +{ + MakeStringBuffer(String, 256); + + r32 YAt = Max.y - Interface.Font->PixelHeight; + r32 Column0X = Min.x; + r32 Column1X = Column0X + 256; + r32 Column2X = Column1X + 128; + r32 Column3X = Column2X + 128; + r32 Column4X = Column3X + 100; + + for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) + { + scope_name NameEntry = VisibleFrame->ScopeNamesHash[n]; + if (NameEntry.Hash != 0) + { + collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n; + + PrintF(&String, "%.*s", NameEntry.Name.Length, NameEntry.Name.Memory); + DrawString(RenderBuffer, String, Interface.Font, v2{Column0X, YAt}, WhiteV4); + + PrintF(&String, "%f", CollatedRecord->PercentFrameTime); + DrawString(RenderBuffer, String, Interface.Font, v2{Column1X, YAt}, WhiteV4); + + PrintF(&String, "%fs", CollatedRecord->TotalSeconds); + DrawString(RenderBuffer, String, Interface.Font, v2{Column2X, YAt}, WhiteV4); + + PrintF(&String, "%dcy", CollatedRecord->TotalCycles); + DrawString(RenderBuffer, String, Interface.Font, v2{Column3X, YAt}, WhiteV4); + + PrintF(&String, "%d calls", CollatedRecord->CallCount); + DrawString(RenderBuffer, String, Interface.Font, v2{Column4X, YAt}, WhiteV4); + + YAt -= Interface.Font->PixelHeight + 4; + + if (YAt < Min.y) { break; } + } + } +} + +PANEL_RENDER_PROC(ProfilerView_Render) +{ + memory_arena* Memory = &State->Transient; +string String = InitializeEmptyString(PushArray(Memory, char, 256), 256); + + v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; + + r32 FrameListHeight = 64; + v2 FrameListMin = v2{PanelMin.x + 16, PanelMax.y - (16 + FrameListHeight)}; + v2 FrameListMax = v2{PanelMax.x - 16, PanelMax.y - 16}; + + r32 FrameListPadding = 4; + r32 FrameListInnerWidth = (FrameListMax.x - FrameListMin.x) - (FrameListPadding * 2); + + r32 SingleFrameStep = FrameListInnerWidth / DEBUG_FRAME_COUNT; + r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); + + PushRenderBoundingBox2D(RenderBuffer, FrameListMin, FrameListMax, 2, WhiteV4); + + if (PointIsInRange(Mouse.Pos, FrameListMin, FrameListMax) && + MouseButtonHeldDown(Mouse.LeftButtonState)) + { + r32 LocalMouseX = (Mouse.Pos.x - FrameListMin.x) + FrameListPadding; + s32 ClosestFrameIndex = (LocalMouseX / SingleFrameStep); + + if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) + { + GlobalDebugServices->RecordFrames = false; + GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; + } + } + + for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) + { + v2 Min = v2{FrameListMin.x + FrameListPadding + (F * SingleFrameStep), FrameListMin.y + 4}; + v2 Max = v2{Min.x + SingleFrameWidth, FrameListMax.y - 4}; + + s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); + if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } + v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)]; + PushRenderQuad2D(RenderBuffer, Min, Max, Color); + } + + debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices); + s64 FrameStartCycles = VisibleFrame->FrameStartCycles; + s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; + + PrintF(&String, "Frame %d - Total Cycles: %lld", + GlobalDebugServices->CurrentDebugFrame - 1, + FrameTotalCycles); + DrawString(RenderBuffer, String, State->Interface.Font, FrameListMin - v2{0, 32}, WhiteV4); + + v2 ButtonMin = v2{FrameListMax.x - 128, FrameListMin.y - 32}; + v2 ButtonMax = ButtonMin + v2{128, 28}; + button_result ShouldResumeRecording = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax, + MakeString("Resume Recording"), State->Interface, Mouse); + if (ShouldResumeRecording.Pressed) + { + GlobalDebugServices->RecordFrames = true; + } + + ButtonMin = v2{FrameListMin.x, FrameListMin.y - 60}; + ButtonMax = v2{FrameListMin.x + 128, FrameListMin.y - 42}; + button_result ActivateScopeView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax, + MakeString("Scope View"), State->Interface, Mouse); + + ButtonMin.x += 152; + ButtonMax.x += 152; + button_result ActivateListView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax, + MakeString("List View"), State->Interface, Mouse); + + if (ActivateScopeView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; } + if (ActivateListView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; } + + v2 ViewModeMin = v2{FrameListMin.x, PanelMin.y}; + v2 ViewModeMax = v2{FrameListMax.x, FrameListMin.y - 96}; + + if (GlobalDebugServices->Interface.FrameView == FRAME_VIEW_PROFILER) + { + RenderProfiler_ScopeVisualization(RenderBuffer, State->Interface, Mouse, + ViewModeMin, ViewModeMax, + VisibleFrame, Memory); + } + else + { + RenderProfiler_ListVisualization(RenderBuffer, State->Interface, Mouse, + ViewModeMin, ViewModeMax, + VisibleFrame, Memory); + } +} \ No newline at end of file diff --git a/src/panels/foldhaus_panel_sculpture_view.h b/src/panels/foldhaus_panel_sculpture_view.h new file mode 100644 index 0000000..1200313 --- /dev/null +++ b/src/panels/foldhaus_panel_sculpture_view.h @@ -0,0 +1,123 @@ +PANEL_INIT_PROC(SculptureView_Init) +{ + +} + +PANEL_CLEANUP_PROC(SculptureView_Cleanup) +{ + +} + + +struct draw_leds_job_data +{ + led* LEDs; + pixel* Colors; + s32 StartIndex; + s32 OnePastLastIndex; + + render_quad_batch_constructor* Batch; + + m44 FaceCameraMatrix; + m44 ModelViewMatrix; + r32 LEDHalfWidth; +}; + +internal void +DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) +{ + DEBUG_TRACK_FUNCTION; + + draw_leds_job_data* Data = (draw_leds_job_data*)JobData; + + s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; + + quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); + s32 TrisUsed = 0; + + r32 HalfWidth = Data->LEDHalfWidth; + + v4 P0_In = v4{-HalfWidth, -HalfWidth, 0, 1}; + v4 P1_In = v4{HalfWidth, -HalfWidth, 0, 1}; + v4 P2_In = v4{HalfWidth, HalfWidth, 0, 1}; + v4 P3_In = v4{-HalfWidth, HalfWidth, 0, 1}; + + v2 UV0 = v2{0, 0}; + v2 UV1 = v2{1, 0}; + v2 UV2 = v2{1, 1}; + v2 UV3 = v2{0, 1}; + + led* LED = Data->LEDs + Data->StartIndex; + for (s32 LEDIdx = 0; + LEDIdx < LEDCount; + LEDIdx++) + { + pixel PixelColor = Data->Colors[LED->Index]; + v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; + + v4 V4Position = LED->Position; + V4Position.w = 0; + v4 P0 = P0_In + V4Position; + v4 P1 = P1_In + V4Position; + v4 P2 = P2_In + V4Position; + v4 P3 = P3_In + V4Position; + + SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); + SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); + + LED++; + } +} + +PANEL_RENDER_PROC(SculptureView_Render) +{ + DEBUG_TRACK_SCOPE(RenderSculpture); + +r32 PanelWidth = PanelMax.x - PanelMin.x; + r32 PanelHeight = PanelMax.y - PanelMin.y; + State->Camera.AspectRatio = PanelWidth / PanelHeight; + + m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); + m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); + + r32 LEDHalfWidth = .5f; + + PushRenderPerspective(RenderBuffer, PanelMin.x, PanelMin.y, PanelWidth, PanelHeight, State->Camera); + + // TODO(Peter): Pretty sure this isn't working right now + m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); + FaceCameraMatrix = FaceCameraMatrix; + + s32 MaxLEDsPerJob = 2048; + render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); + + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) + { + array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); + + for (s32 Job = 0; Job < JobsNeeded; Job++) + { + draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); + JobData->LEDs = Assembly.LEDs; + JobData->Colors = Assembly.Colors; + JobData->StartIndex = Job * MaxLEDsPerJob; + JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDCount); + JobData->Batch = &RenderLEDsBatch; + JobData->FaceCameraMatrix; + JobData->ModelViewMatrix = ModelViewMatrix; + JobData->LEDHalfWidth = LEDHalfWidth; + + Context.GeneralWorkQueue->PushWorkOnQueue( + Context.GeneralWorkQueue, + DrawLEDsInBufferRangeJob, + JobData); + } + } + + Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); + Context.GeneralWorkQueue->ResetWorkQueue(Context.GeneralWorkQueue); +} From b83d718d37a27ae5bcd5782295d61aa3d7f7fb2c Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 13:14:00 -0800 Subject: [PATCH 07/19] Consolidated all panel code in one file, and removed all external dependencies. ITS A LIBRARY NOW (still needs refinement) --- src/animation/foldhaus_animation_interface.h | 8 - src/foldhaus_app.cpp | 103 +++++- src/foldhaus_app.h | 20 +- src/foldhaus_panel.cpp | 313 ------------------ src/foldhaus_panel.h | 287 ++++++++++++++-- .../foldhaus_panel_animation_timeline.h | 9 + 6 files changed, 384 insertions(+), 356 deletions(-) diff --git a/src/animation/foldhaus_animation_interface.h b/src/animation/foldhaus_animation_interface.h index a6b6726..059c91a 100644 --- a/src/animation/foldhaus_animation_interface.h +++ b/src/animation/foldhaus_animation_interface.h @@ -1,11 +1,3 @@ -// TODO -// [] - Moving animation blocks -// [] - dragging beginning and end of time blocks -// [] - creating a timeblock with a specific animation -// [x] - play, pause, stop, -// [] - setting the start and end of the animation system -// [] - displaying multiple layers -// [] - FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlock) { diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 0ee0504..446d871 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -1,6 +1,85 @@ #include "foldhaus_platform.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 void +DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, v2 FooterMin, v2 FooterMax, interface_config Interface, mouse_state Mouse) +{ + PushRenderQuad2D(RenderBuffer, FooterMin, v2{FooterMax.x, FooterMin.y + 25}, v4{.5f, .5f, .5f, 1.f}); + PushRenderQuad2D(RenderBuffer, FooterMin, FooterMin + v2{25, 25}, WhiteV4); + + v2 PanelSelectButtonMin = FooterMin + v2{30, 1}; + v2 PanelSelectButtonMax = PanelSelectButtonMin + v2{100, 23}; + + if (Panel->PanelSelectionMenuOpen) + { + v2 ButtonDimension = v2{100, 25}; + v2 ButtonMin = v2{PanelSelectButtonMin.x, FooterMax.y}; + + v2 MenuMin = ButtonMin; + v2 MenuMax = v2{ButtonMin.x + ButtonDimension.x, ButtonMin.y + (ButtonDimension.y * GlobalPanelDefsCount)}; + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) + && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) + { + Panel->PanelSelectionMenuOpen = false; + } + + +for (s32 i = 0; i < GlobalPanelDefsCount; i++) + { + panel_definition Def = GlobalPanelDefs[i]; + string DefName = MakeString(Def.PanelName, Def.PanelNameLength); + button_result DefinitionButton = EvaluateButton(RenderBuffer, + ButtonMin, ButtonMin + ButtonDimension, + DefName, Interface, Mouse); + if (DefinitionButton.Pressed) + { + SetPanelDefinition(Panel, i); + Panel->PanelSelectionMenuOpen = false; + } + + ButtonMin.y += ButtonDimension.y; + } + } + +button_result ButtonResult = EvaluateButton(RenderBuffer, + PanelSelectButtonMin, +PanelSelectButtonMax, + MakeStringLiteral("Select"), Interface, Mouse); + if (ButtonResult.Pressed) + { + Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; + } + +} + +internal void +RenderPanel(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +{ + Assert(Panel->PanelDefinitionIndex >= 0); + +v2 FooterMin = PanelMin; + v2 FooterMax = v2{PanelMax.x, PanelMin.y + 25}; + v2 PanelViewMin = v2{PanelMin.x, FooterMax.y}; + v2 PanelViewMax = PanelMax; + +panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; + Definition.Render(*Panel, PanelMin, PanelMax, RenderBuffer, State, Context, Mouse); + +PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); +DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, State->Interface, Mouse); +} + internal v4 MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, r32 WindowWidth, r32 WindowHeight) { @@ -271,9 +350,9 @@ INITIALIZE_APPLICATION(InitializeApplication) { // Panels Playground InitializePanelLayout(&State->PanelLayout); panel* Panel = TakeNewPanel(&State->PanelLayout); - SetPanelDefinition(Panel, GlobalPanelDefs[0]); + SetPanelDefinition(Panel, 0); SplitPanelVertically(Panel, .5f, v2{0, 0}, v2{Context.WindowWidth, Context.WindowHeight}, &State->PanelLayout); - SetPanelDefinition(&Panel->Right->Panel, GlobalPanelDefs[1]); + SetPanelDefinition(&Panel->Right->Panel, 1); } // End Panels Playground } @@ -557,14 +636,13 @@ PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHe } } - v2 TimelineMin = v2{0, 0}; - v2 TimelineMax = v2{Context.WindowWidth, 125}; - animation_block_handle NewSelection = DrawAnimationPanel(&State->AnimationSystem, - TimelineMin, TimelineMax, - State->SelectedAnimationBlockHandle, - RenderBuffer, State->Interface, Mouse); - State->SelectedAnimationBlockHandle = NewSelection; - + DrawDebugInterface(RenderBuffer, 25, + State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, + Context.DeltaTime, State, State->Camera, Mouse, &State->Transient); +#endif + } + + for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) { operation_mode OperationMode = State->Modes.ActiveModes[m]; @@ -574,11 +652,6 @@ PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHe } } - DrawDebugInterface(RenderBuffer, 25, - State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, - Context.DeltaTime, State, State->Camera, Mouse, &State->Transient); -#endif - } // Checking for overflows { diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 62004fa..bfad4dd 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -17,6 +17,7 @@ typedef struct app_state app_state; + #include "foldhaus_panel.h" #include "foldhaus_command_dispatch.h" @@ -171,10 +172,27 @@ r32 GreenSize = 20.0f; #include "foldhaus_interface.cpp" #include "animation/foldhaus_animation_interface.h" +#define PANEL_INIT_PROC(name) void name(panel* Panel) +typedef PANEL_INIT_PROC(panel_init_proc); + +#define PANEL_CLEANUP_PROC(name) void name(panel* Panel) +typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); + +#define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +typedef PANEL_RENDER_PROC(panel_render_proc); + +struct panel_definition +{ + char* PanelName; + s32 PanelNameLength; + panel_init_proc* Init; + panel_cleanup_proc* Cleanup; + panel_render_proc* Render; +}; + #include "panels/foldhaus_panel_sculpture_view.h" #include "panels/foldhaus_panel_profiler.h" #include "panels/foldhaus_panel_dmx_view.h" #include "panels/foldhaus_panel_animation_timeline.h" #include "generated/foldhaus_panels_generated.h" -#include "foldhaus_panel.cpp" diff --git a/src/foldhaus_panel.cpp b/src/foldhaus_panel.cpp index 579ce8e..e69de29 100644 --- a/src/foldhaus_panel.cpp +++ b/src/foldhaus_panel.cpp @@ -1,313 +0,0 @@ - -///////////////////////////////// -// -// Book-Keeping -// -///////////////////////////////// - -internal void -InitializePanelLayout(panel_layout* Layout) -{ - Layout->FreeList.Free.Next = &Layout->FreeList; -} - -internal panel_entry* -TakeNewPanelEntry(panel_layout* Layout) -{ - panel_entry* FreeEntry = 0; - if (Layout->FreeList.Free.Next != &Layout->FreeList) - { - FreeEntry = Layout->FreeList.Free.Next; - Layout->FreeList.Free.Next = FreeEntry->Free.Next; - } - else - { - Assert(Layout->PanelsUsed < PANELS_MAX); - FreeEntry = Layout->Panels + Layout->PanelsUsed++; - } - return FreeEntry; -} - -internal panel* -TakeNewPanel(panel_layout* Layout) -{ - panel* Result = 0; - panel_entry* FreeEntry = TakeNewPanelEntry(Layout); -Result = &FreeEntry->Panel; - *Result = {0}; - return Result; -} - -internal void -FreePanelEntry(panel_entry* Entry, panel_layout* Layout) -{ - Assert(Entry >= Layout->Panels && Entry <= Layout->Panels + PANELS_MAX); - Entry->Panel = {0}; - Entry->Free.Next = Layout->FreeList.Free.Next; - Layout->FreeList.Free.Next = Entry; -} - -internal void -FreePanelAtIndex(s32 Index, panel_layout* Layout) -{ - Assert(Index > 0 && Index < (s32)Layout->PanelsUsed); - panel_entry* EntryToFree = Layout->Panels + Index; - EntryToFree->Free.Next = Layout->FreeList.Free.Next; - Layout->FreeList.Free.Next = EntryToFree; -} - -internal void -SplitPanelVertically(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) -{ - r32 SplitX = GSLerp(ParentMin.x, ParentMax.x, Percent); - if (SplitX > ParentMin.x && SplitX < ParentMax.x) - { -Parent->SplitDirection = PanelSplit_Vertical; - Parent->SplitPercent = Percent; - - Parent->Left = TakeNewPanelEntry(Layout); - Parent->Left->Panel.Render = Parent->Render; - -Parent->Right = TakeNewPanelEntry(Layout); - Parent->Right->Panel.Render = Parent->Render; - } -} - -internal void -SplitPanelHorizontally(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) -{ - r32 SplitY = GSLerp(ParentMin.y, ParentMax.y, Percent); - if (SplitY > ParentMin.y && SplitY < ParentMax.y) - { -Parent->SplitDirection = PanelSplit_Horizontal; - Parent->SplitPercent = Percent; - - Parent->Bottom = TakeNewPanelEntry(Layout); - Parent->Bottom->Panel.Render = Parent->Render; - -Parent->Top = TakeNewPanelEntry(Layout); - Parent->Top->Panel.Render = Parent->Render; - } -} - -internal void -ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_layout* Layout) -{ - panel_entry* LeftChild = Parent->Left; - panel_entry* RightChild = Parent->Right; - - *Parent = PanelEntryToKeep->Panel; - Parent->SplitDirection = PanelSplit_NoSplit; - - FreePanelEntry(LeftChild, Layout); - FreePanelEntry(RightChild, Layout); -} - -internal void -SetPanelDefinition(panel* Panel, panel_definition Def) -{ - if(Panel->Cleanup) - { - Panel->Cleanup(Panel); - } - -Panel->Cleanup = Def.Cleanup; - Panel->Render = Def.Render; - Def.Init(Panel); -} - -///////////////////////////////// -// -// Rendering And Interaction -// -///////////////////////////////// - -internal void -HandleMousePanelInteractionOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, panel_layout* PanelLayout, mouse_state Mouse) -{ - r32 PanelEdgeClickMaxDistance = 4; - - // TODO(Peter): Need a way to calculate this button's position more systemically - if (Panel->SplitDirection == PanelSplit_NoSplit - && PointIsInRange(Mouse.DownPos, PanelMin, PanelMin + v2{25, 25})) - { - r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); - r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); - - if (XDistance > YDistance) - { - r32 XPercent = (Mouse.Pos.x - PanelMin.x) / (PanelMax.x - PanelMin.x); - SplitPanelVertically(Panel, XPercent, PanelMin, PanelMax, PanelLayout); - } - else - { - r32 YPercent = (Mouse.Pos.y - PanelMin.y) / (PanelMax.y - PanelMin.y); - SplitPanelHorizontally(Panel, YPercent, PanelMin, PanelMax, PanelLayout); - } - } - else if (Panel->SplitDirection == PanelSplit_Horizontal) - { - r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY); - if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) - { - r32 NewSplitY = Mouse.Pos.y; - if (NewSplitY <= PanelMin.y) - { - ConsolidatePanelsKeepOne(Panel, Panel->Top, PanelLayout); - } - else if (NewSplitY >= PanelMax.y) - { - ConsolidatePanelsKeepOne(Panel, Panel->Bottom, PanelLayout); - } - else - { - Panel->SplitPercent = (NewSplitY - PanelMin.y) / (PanelMax.y - PanelMin.y); - } - } - else - { - HandleMousePanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, PanelLayout, Mouse); - HandleMousePanelInteractionOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, PanelLayout, Mouse); - } - } - else if (Panel->SplitDirection == PanelSplit_Vertical) - { - r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX); - if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) - { - r32 NewSplitX = Mouse.Pos.x; - if (NewSplitX <= PanelMin.x) - { - ConsolidatePanelsKeepOne(Panel, Panel->Right, PanelLayout); - } - else if (NewSplitX >= PanelMax.x) - { - ConsolidatePanelsKeepOne(Panel, Panel->Left, PanelLayout); - } - else - { - Panel->SplitPercent = (NewSplitX - PanelMin.x) / (PanelMax.x - PanelMin.x); - } - } - else - { - HandleMousePanelInteractionOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, PanelLayout, Mouse); - HandleMousePanelInteractionOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, PanelLayout, Mouse); - } - } -} - -internal void -HandleMousePanelInteraction(panel_layout* PanelLayout, v2 WindowMin, v2 WindowMax, mouse_state Mouse) -{ - r32 PanelEdgeClickMaxDistance = 4; - - if (MouseButtonTransitionedUp(Mouse.LeftButtonState)) - { - Assert(PanelLayout->PanelsUsed > 0); - panel* FirstPanel = &PanelLayout->Panels[0].Panel; - HandleMousePanelInteractionOrRecurse(FirstPanel, WindowMin, WindowMax, PanelLayout, Mouse); - } -} - -internal void -DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, v2 FooterMin, v2 FooterMax, interface_config Interface, mouse_state Mouse) -{ - PushRenderQuad2D(RenderBuffer, FooterMin, v2{FooterMax.x, FooterMin.y + 25}, v4{.5f, .5f, .5f, 1.f}); - PushRenderQuad2D(RenderBuffer, FooterMin, FooterMin + v2{25, 25}, WhiteV4); - - v2 PanelSelectButtonMin = FooterMin + v2{30, 1}; - v2 PanelSelectButtonMax = PanelSelectButtonMin + v2{100, 23}; - - if (Panel->PanelSelectionMenuOpen) - { - v2 ButtonDimension = v2{100, 25}; - v2 ButtonMin = v2{PanelSelectButtonMin.x, FooterMax.y}; - - v2 MenuMin = ButtonMin; - v2 MenuMax = v2{ButtonMin.x + ButtonDimension.x, ButtonMin.y + (ButtonDimension.y * GlobalPanelDefsCount)}; - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) - && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) - { - Panel->PanelSelectionMenuOpen = false; - } - - -for (s32 i = 0; i < GlobalPanelDefsCount; i++) - { - panel_definition Def = GlobalPanelDefs[i]; - string DefName = MakeString(Def.PanelName, Def.PanelNameLength); - button_result DefinitionButton = EvaluateButton(RenderBuffer, - ButtonMin, ButtonMin + ButtonDimension, - DefName, Interface, Mouse); - if (DefinitionButton.Pressed) - { - SetPanelDefinition(Panel, Def); - Panel->PanelSelectionMenuOpen = false; - } - - ButtonMin.y += ButtonDimension.y; - } - } - -button_result ButtonResult = EvaluateButton(RenderBuffer, - PanelSelectButtonMin, -PanelSelectButtonMax, - MakeStringLiteral("Select"), Interface, Mouse); - if (ButtonResult.Pressed) - { - Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; - } - -} - -internal void -DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, render_command_buffer* RenderBuffer) -{ - PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color); -} - -internal void -DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) -{ - if (Panel->SplitDirection == PanelSplit_NoSplit) - { - v2 FooterMin = PanelMin; - v2 FooterMax = v2{PanelMax.x, PanelMin.y + 25}; - v2 PanelViewMin = v2{PanelMin.x, FooterMax.y}; - v2 PanelViewMax = PanelMax; - - Panel->Render(*Panel, PanelViewMin, PanelViewMax, RenderBuffer, State, Context, Mouse); - v4 BorderColor = v4{0, 1, 1, 1}; - if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) - { - BorderColor = v4{1, 0, 1, 1}; - } - -PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); -DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer); -DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, Interface, Mouse); - } - else if (Panel->SplitDirection == PanelSplit_Horizontal) - { - r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); - DrawPanelOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); - DrawPanelOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); - } - else if (Panel->SplitDirection == PanelSplit_Vertical) - { - r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); - DrawPanelOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); - DrawPanelOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); - } -} - -internal void -DrawAllPanels(panel_layout PanelLayout, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) -{ - Assert(PanelLayout.PanelsUsed > 0); - panel* FirstPanel = &PanelLayout.Panels[0].Panel; - DrawPanelOrRecurse(FirstPanel, WindowMin, WindowMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); -} diff --git a/src/foldhaus_panel.h b/src/foldhaus_panel.h index 90a06bd..ee56081 100644 --- a/src/foldhaus_panel.h +++ b/src/foldhaus_panel.h @@ -1,15 +1,17 @@ +/* +File: foldhaus_panel.cpp +Description: a system for laying out panels on a screen +Author: Peter Slattery +Creation Date: 2019-12-26 + +Usage: +Include this file in ONE file in your project. +Define both RenderPanel and SetPanelDefinitionExternal + +*/ typedef struct panel panel; -#define PANEL_INIT_PROC(name) void name(panel* Panel) -typedef PANEL_INIT_PROC(panel_init_proc); - -#define PANEL_CLEANUP_PROC(name) void name(panel* Panel) -typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); - -#define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) -typedef PANEL_RENDER_PROC(panel_render_proc); - enum panel_split_direction { PanelSplit_NoSplit, @@ -23,9 +25,8 @@ typedef struct panel_entry panel_entry; struct panel { -panel_render_proc* Render; -panel_cleanup_proc* Cleanup; - + s32 PanelDefinitionIndex; + panel_split_direction SplitDirection; r32 SplitPercent; @@ -63,11 +64,259 @@ panel_entry Panels[PANELS_MAX]; panel_entry FreeList; }; -struct panel_definition +internal void SetPanelDefinitionExternal(panel* Panel, s32 OldPanelDefinitionIndex, s32 NewPanelDefinitionIndex); +internal void RenderPanel(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse); + + +///////////////////////////////// +// +// Book-Keeping +// +///////////////////////////////// + +internal void +InitializePanelLayout(panel_layout* Layout) { - char* PanelName; - s32 PanelNameLength; - panel_init_proc* Init; - panel_cleanup_proc* Cleanup; - panel_render_proc* Render; -}; \ No newline at end of file + Layout->FreeList.Free.Next = &Layout->FreeList; +} + +internal panel_entry* +TakeNewPanelEntry(panel_layout* Layout) +{ + panel_entry* FreeEntry = 0; + if (Layout->FreeList.Free.Next != &Layout->FreeList) + { + FreeEntry = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = FreeEntry->Free.Next; + } + else + { + Assert(Layout->PanelsUsed < PANELS_MAX); + FreeEntry = Layout->Panels + Layout->PanelsUsed++; + } + return FreeEntry; +} + +internal panel* +TakeNewPanel(panel_layout* Layout) +{ + panel* Result = 0; + panel_entry* FreeEntry = TakeNewPanelEntry(Layout); +Result = &FreeEntry->Panel; + +*Result = {0}; + Result->PanelDefinitionIndex = -1; + + return Result; +} + +internal void +FreePanelEntry(panel_entry* Entry, panel_layout* Layout) +{ + Assert(Entry >= Layout->Panels && Entry <= Layout->Panels + PANELS_MAX); + Entry->Panel = {0}; + Entry->Free.Next = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = Entry; +} + +internal void +FreePanelAtIndex(s32 Index, panel_layout* Layout) +{ + Assert(Index > 0 && Index < (s32)Layout->PanelsUsed); + panel_entry* EntryToFree = Layout->Panels + Index; + EntryToFree->Free.Next = Layout->FreeList.Free.Next; + Layout->FreeList.Free.Next = EntryToFree; +} + +internal void +SplitPanelVertically(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) +{ + r32 SplitX = GSLerp(ParentMin.x, ParentMax.x, Percent); + if (SplitX > ParentMin.x && SplitX < ParentMax.x) + { +Parent->SplitDirection = PanelSplit_Vertical; + Parent->SplitPercent = Percent; + + Parent->Left = TakeNewPanelEntry(Layout); + Parent->Left->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + +Parent->Right = TakeNewPanelEntry(Layout); + Parent->Right->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + } +} + +internal void +SplitPanelHorizontally(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout) +{ + r32 SplitY = GSLerp(ParentMin.y, ParentMax.y, Percent); + if (SplitY > ParentMin.y && SplitY < ParentMax.y) + { +Parent->SplitDirection = PanelSplit_Horizontal; + Parent->SplitPercent = Percent; + + Parent->Bottom = TakeNewPanelEntry(Layout); + Parent->Bottom->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + +Parent->Top = TakeNewPanelEntry(Layout); + Parent->Top->Panel.PanelDefinitionIndex = Parent->PanelDefinitionIndex; + } +} + +internal void +ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_layout* Layout) +{ + panel_entry* LeftChild = Parent->Left; + panel_entry* RightChild = Parent->Right; + + *Parent = PanelEntryToKeep->Panel; + Parent->SplitDirection = PanelSplit_NoSplit; + + FreePanelEntry(LeftChild, Layout); + FreePanelEntry(RightChild, Layout); +} + +internal void +SetPanelDefinition(panel* Panel, s32 NewDefinitionIndex) +{ + s32 OldDefinitionIndex = Panel->PanelDefinitionIndex; + Panel->PanelDefinitionIndex = NewDefinitionIndex; + SetPanelDefinitionExternal(Panel, OldDefinitionIndex, NewDefinitionIndex); +} +///////////////////////////////// +// +// Rendering And Interaction +// +///////////////////////////////// + +internal void +HandleMousePanelInteractionOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, panel_layout* PanelLayout, mouse_state Mouse) +{ + r32 PanelEdgeClickMaxDistance = 4; + + // TODO(Peter): Need a way to calculate this button's position more systemically + if (Panel->SplitDirection == PanelSplit_NoSplit + && PointIsInRange(Mouse.DownPos, PanelMin, PanelMin + v2{25, 25})) + { + r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); + r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + + if (XDistance > YDistance) + { + r32 XPercent = (Mouse.Pos.x - PanelMin.x) / (PanelMax.x - PanelMin.x); + SplitPanelVertically(Panel, XPercent, PanelMin, PanelMax, PanelLayout); + } + else + { + r32 YPercent = (Mouse.Pos.y - PanelMin.y) / (PanelMax.y - PanelMin.y); + SplitPanelHorizontally(Panel, YPercent, PanelMin, PanelMax, PanelLayout); + } + } + else if (Panel->SplitDirection == PanelSplit_Horizontal) + { + r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); + r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY); + if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) + { + r32 NewSplitY = Mouse.Pos.y; + if (NewSplitY <= PanelMin.y) + { + ConsolidatePanelsKeepOne(Panel, Panel->Top, PanelLayout); + } + else if (NewSplitY >= PanelMax.y) + { + ConsolidatePanelsKeepOne(Panel, Panel->Bottom, PanelLayout); + } + else + { + Panel->SplitPercent = (NewSplitY - PanelMin.y) / (PanelMax.y - PanelMin.y); + } + } + else + { + HandleMousePanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, PanelLayout, Mouse); + HandleMousePanelInteractionOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, PanelLayout, Mouse); + } + } + else if (Panel->SplitDirection == PanelSplit_Vertical) + { + r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); + r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX); + if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance) + { + r32 NewSplitX = Mouse.Pos.x; + if (NewSplitX <= PanelMin.x) + { + ConsolidatePanelsKeepOne(Panel, Panel->Right, PanelLayout); + } + else if (NewSplitX >= PanelMax.x) + { + ConsolidatePanelsKeepOne(Panel, Panel->Left, PanelLayout); + } + else + { + Panel->SplitPercent = (NewSplitX - PanelMin.x) / (PanelMax.x - PanelMin.x); + } + } + else + { + HandleMousePanelInteractionOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, PanelLayout, Mouse); + HandleMousePanelInteractionOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, PanelLayout, Mouse); + } + } +} + +internal void +HandleMousePanelInteraction(panel_layout* PanelLayout, v2 WindowMin, v2 WindowMax, mouse_state Mouse) +{ + r32 PanelEdgeClickMaxDistance = 4; + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState)) + { + Assert(PanelLayout->PanelsUsed > 0); + panel* FirstPanel = &PanelLayout->Panels[0].Panel; + HandleMousePanelInteractionOrRecurse(FirstPanel, WindowMin, WindowMax, PanelLayout, Mouse); + } +} + +internal void +DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, render_command_buffer* RenderBuffer) +{ + PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color); +} + +internal void +DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) +{ + if (Panel->SplitDirection == PanelSplit_NoSplit) + { + RenderPanel(Panel, PanelMin, PanelMax, WindowMin, WindowMax, RenderBuffer, State, Context, Mouse); + v4 BorderColor = v4{0, 1, 1, 1}; + if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + { + BorderColor = v4{1, 0, 1, 1}; + } + +PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); +DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer); + } + else if (Panel->SplitDirection == PanelSplit_Horizontal) + { + r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent); + DrawPanelOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + DrawPanelOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + } + else if (Panel->SplitDirection == PanelSplit_Vertical) + { + r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent); + DrawPanelOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + DrawPanelOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); + } +} + +internal void +DrawAllPanels(panel_layout PanelLayout, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context) +{ + Assert(PanelLayout.PanelsUsed > 0); + panel* FirstPanel = &PanelLayout.Panels[0].Panel; + DrawPanelOrRecurse(FirstPanel, WindowMin, WindowMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context); +} diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h index 9d965e0..45957aa 100644 --- a/src/panels/foldhaus_panel_animation_timeline.h +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -1,3 +1,12 @@ +// TODO +// [] - Moving animation blocks +// [] - dragging beginning and end of time blocks +// [] - creating a timeblock with a specific animation +// [x] - play, pause, stop, +// [] - setting the start and end of the animation system +// [] - displaying multiple layers +// [] - + PANEL_INIT_PROC(AnimationTimeline_Init) { From d9af0c6a368adbf25f7b35b5f3e93406462da548 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 14:45:27 -0800 Subject: [PATCH 08/19] Created a hierarchy view --- src/foldhaus_app.cpp | 105 +- src/foldhaus_app.h | 10 +- src/foldhaus_assembly.cpp | 49 + src/foldhaus_panel.cpp | 0 src/foldhaus_panel.h | 5 +- src/generated/foldhaus_panels_generated.h | 21 +- src/gs_language.h | 423 ---- src/gs_memory_arena.h | 613 ------ src/gs_string.h | 2206 -------------------- src/gs_vector_matrix.h | 1466 ------------- src/panels/foldhaus_panel_hierarchy.h | 78 + src/panels/foldhaus_panel_sculpture_view.h | 4 + 12 files changed, 155 insertions(+), 4825 deletions(-) delete mode 100644 src/foldhaus_panel.cpp delete mode 100644 src/gs_language.h delete mode 100644 src/gs_memory_arena.h delete mode 100644 src/gs_string.h delete mode 100644 src/gs_vector_matrix.h create mode 100644 src/panels/foldhaus_panel_hierarchy.h diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 446d871..55eb6a2 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -74,7 +74,9 @@ v2 FooterMin = PanelMin; v2 PanelViewMax = PanelMax; panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; - Definition.Render(*Panel, PanelMin, PanelMax, RenderBuffer, State, Context, Mouse); + + +Definition.Render(*Panel, PanelMin, PanelMax, RenderBuffer, State, Context, Mouse); PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, State->Interface, Mouse); @@ -136,55 +138,6 @@ SACNSendDMXBufferListJob (s32 ThreadID, void* JobData) } } -internal void -LoadAssembly (app_state* State, context Context, char* Path) -{ - platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); - Assert(TestAssemblyFile.Size > 0); - - assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient); - - Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size); - - string PathString = MakeStringLiteral(Path); - s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\'); - string FileName = Substring(PathString, IndexOfLastSlash + 1); - - r32 Scale = 100; - memory_arena AssemblyArena = {}; - AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; - AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; - - assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, - FileName, - v3{0, 0, 0}, - Scale, - AssemblyArena); - array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); - PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); - - State->TotalLEDsCount += NewAssembly.LEDCount; -} - -internal void -UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) -{ - assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); - 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++) - { - array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - if (Handle.Index == AssemblyIndex) - { - RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); - break; - } - } -} - //////////////////////////////////////////////////////////////////////// RELOAD_STATIC_DATA(ReloadStaticData) @@ -197,8 +150,6 @@ RELOAD_STATIC_DATA(ReloadStaticData) if (State->DefaultInputCommandRegistry.Size > 0) { - RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, - Begin3DViewMouseRotate); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_U, Command_Began, KeyCode_Invalid, OpenUniverseView); RegisterKeyPressCommand(&State->DefaultInputCommandRegistry, KeyCode_X, Command_Ended, KeyCode_Invalid, DeleteAnimationBlock); } @@ -534,56 +485,6 @@ PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHe if (Context.WindowIsVisible) { #if 0 - State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight; - - m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); - m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); - - r32 LEDHalfWidth = .5f; - - PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth / 2, Context.WindowHeight, State->Camera); - PushRenderClearScreen(RenderBuffer); - - // TODO(Peter): Pretty sure this isn't working right now - m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); - FaceCameraMatrix = FaceCameraMatrix; - - DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle - { - DEBUG_TRACK_SCOPE(RenderSculpture); - - s32 MaxLEDsPerJob = 2048; - render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); - - for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) - { - array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); - s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); - - for (s32 Job = 0; Job < JobsNeeded; Job++) - { - draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); - JobData->LEDs = Assembly.LEDs; - JobData->Colors = Assembly.Colors; - JobData->StartIndex = Job * MaxLEDsPerJob; - JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDCount); - JobData->Batch = &RenderLEDsBatch; - JobData->FaceCameraMatrix; - JobData->ModelViewMatrix = ModelViewMatrix; - JobData->LEDHalfWidth = LEDHalfWidth; - - Context.GeneralWorkQueue->PushWorkOnQueue( - Context.GeneralWorkQueue, - DrawLEDsInBufferRangeJob, - JobData); - } - } - - Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); - Context.GeneralWorkQueue->ResetWorkQueue(Context.GeneralWorkQueue); - } - /////////////////////////////////////// // Interface ////////////////////////////////////// diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index bfad4dd..1318f21 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -181,18 +181,10 @@ typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); #define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) typedef PANEL_RENDER_PROC(panel_render_proc); -struct panel_definition -{ - char* PanelName; - s32 PanelNameLength; - panel_init_proc* Init; - panel_cleanup_proc* Cleanup; - panel_render_proc* Render; -}; - #include "panels/foldhaus_panel_sculpture_view.h" #include "panels/foldhaus_panel_profiler.h" #include "panels/foldhaus_panel_dmx_view.h" #include "panels/foldhaus_panel_animation_timeline.h" +#include "panels/foldhaus_panel_hierarchy.h" #include "generated/foldhaus_panels_generated.h" diff --git a/src/foldhaus_assembly.cpp b/src/foldhaus_assembly.cpp index 8d59332..f9c700f 100644 --- a/src/foldhaus_assembly.cpp +++ b/src/foldhaus_assembly.cpp @@ -62,3 +62,52 @@ ConstructAssemblyFromDefinition (assembly_definition Definition, Assert(Assembly.LEDCount == Definition.TotalLEDCount); return Assembly; } + +internal void +LoadAssembly (app_state* State, context Context, char* Path) +{ + platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); + Assert(TestAssemblyFile.Size > 0); + + assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient); + + Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size); + + string PathString = MakeStringLiteral(Path); + s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\'); + string FileName = Substring(PathString, IndexOfLastSlash + 1); + + r32 Scale = 100; + memory_arena AssemblyArena = {}; + AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; + AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + + assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, + FileName, + v3{0, 0, 0}, + Scale, + AssemblyArena); + array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); + PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies); + + State->TotalLEDsCount += NewAssembly.LEDCount; +} + +internal void +UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) +{ + assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList); + 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++) + { + array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + if (Handle.Index == AssemblyIndex) + { + RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies); + break; + } + } +} diff --git a/src/foldhaus_panel.cpp b/src/foldhaus_panel.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/foldhaus_panel.h b/src/foldhaus_panel.h index ee56081..10dd69c 100644 --- a/src/foldhaus_panel.h +++ b/src/foldhaus_panel.h @@ -290,11 +290,14 @@ DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 Wind if (Panel->SplitDirection == PanelSplit_NoSplit) { RenderPanel(Panel, PanelMin, PanelMax, WindowMin, WindowMax, RenderBuffer, State, Context, Mouse); - v4 BorderColor = v4{0, 1, 1, 1}; + v4 BorderColor = v4{0, 0, 0, 1}; + + #if 0 if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) { BorderColor = v4{1, 0, 1, 1}; } +#endif PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y); DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer); diff --git a/src/generated/foldhaus_panels_generated.h b/src/generated/foldhaus_panels_generated.h index fc7847a..6679244 100644 --- a/src/generated/foldhaus_panels_generated.h +++ b/src/generated/foldhaus_panels_generated.h @@ -1,7 +1,18 @@ -global_variable s32 GlobalPanelDefsCount = 4; +struct panel_definition +{ + char* PanelName; + s32 PanelNameLength; + panel_init_proc* Init; + panel_cleanup_proc* Cleanup; + panel_render_proc* Render; + input_command* InputCommands; +}; + +global_variable s32 GlobalPanelDefsCount = 5; global_variable panel_definition GlobalPanelDefs[] = { - { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render }, - { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render }, - { "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render }, - { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render }, + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands}, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, 0 }, + { "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, 0 }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, 0 }, + { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, 0 }, }; \ No newline at end of file diff --git a/src/gs_language.h b/src/gs_language.h deleted file mode 100644 index d1b233a..0000000 --- a/src/gs_language.h +++ /dev/null @@ -1,423 +0,0 @@ -#ifndef GS_LANGUAGE_H - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) -#include -#include - -// TODO(Peter): Get rid of stdio and math.h -#include -#include - -#elif defined(__APPLE__) && defined(__MAC__) -// TODO(Peter): - -#else // Std lib -#include - -#endif - -#define internal static -#define local_persist static -#define global_variable static - - -#if !defined(GS_TYPES) - -#define GSINT64(s) (s) ## L -#define GSUINT64(s) (s) ## UL - -typedef signed char b8; -typedef short int b16; -typedef int b32; -typedef long long int b64; - -typedef unsigned char u8; -typedef unsigned short int u16; -typedef unsigned int u32; -typedef unsigned long long int u64; - -typedef signed char s8; -typedef short int s16; -typedef int s32; -typedef long long int s64; - -typedef float r32; -typedef double r64; - -#define INT8_MIN (-128) -#define INT16_MIN (-32767-1) -#define INT32_MIN (-2147483647-1) -#define INT64_MIN (-GSINT64(9223372036854775807)-1) - -#define INT8_MAX (127) -#define INT16_MAX (32767) -#define INT32_MAX (2147483647) -#define INT64_MAX (GSINT64(9223372036854775807)) - -#define UINT8_MAX (255) -#define UINT16_MAX (65535) -#define UINT32_MAX (4294967295U) -#define UINT64_MAX (GSUINT64(18446744073709551615)) - -#define FLOAT_MIN (1.175494351e-38F) -#define FLOAT_MAX (3.402823466e+38F) -#define DOUBLE_MIN (2.2250738585072014e-308) -#define DOUBLE_MAX (1.7976931348623158e+308) - -#define Kilobytes(Value) ((Value) * 1024) -#define Megabytes(Value) (Kilobytes(Value) * 1024) -#define Gigabytes(Value) (Megabytes(Value) * 1024) -#define Terabytes(Value) (Gigabytes(Value) * 1024) - -#define PI 3.14159265359 -#define PI_OVER_180 0.01745329251f - -#define GS_TYPES -#endif - - -#ifdef DEBUG - -static void DebugPrint(char* Format, ...); - -#if !defined(Assert) -// NOTE(peter): this writes to address 0 which is always illegal and will cause a crash -#define Assert(expression) if(!(expression)){ *((int *)0) = 5; } -#endif - -#define DEBUG_IF(condition) if (condition) - -#define InvalidCodePath Assert(0) -#define InvalidDefaultCase default: { Assert(0); } -#define DebugBreak __debugbreak() - -#define STBI_ASSERT(x) Assert(x) - -#ifdef GS_TEST_SUTE -#define TestClean(v, c) SuccessCount += Test(v, c, &TestCount) -internal s32 -Test(b32 Result, char* Description, s32* Count) -{ - char* Passed = (Result ? "Success" : "Failed"); - if (!Result) - DebugPrint("%s:\n................................................%s\n\n", Description, Passed); - - *Count = *Count + 1; - return (Result ? 1 : 0); -} -#endif // GS_TEST_SUTE - -#else - -#define Assert(expression) -#define InvalidCodePath -#define DEBUG_IF(condition) - -//#define DEBUG_TRACK_SCOPE(a) - -#endif // DEBUG - -#ifndef GS_LANGUAGE_MATH - -#define GSZeroStruct(data) GSZeroMemory_((u8*)(&(data)), sizeof(data)) -#define GSZeroMemory(mem, size) GSZeroMemory_((u8*)(mem), (size)) -static void -GSZeroMemory_ (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -#define GSMemCopy(from, to, size) GSMemCopy_((u8*)from, (u8*)to, size) -static void -GSMemCopy_ (u8* From, u8* To, s32 Size) -{ - for (int i = 0; i < Size; i++) { To[i] = From[i]; } -} - -#define GSMemSet(buffer, value, size) GSMemSet_((u8*)buffer, value, size) -internal void -GSMemSet_ (u8* Buffer, u8 Value, s32 Length) -{ - u8* Cursor = Buffer; - for (s32 i = 0; i < Length; i++) - { - *Cursor++ = Value; - } -} - -#define GSMinDef(type) static type GSMin(type A, type B) { return (A < B ? A : B); } -GSMinDef(s8) -GSMinDef(s16) -GSMinDef(s32) -GSMinDef(s64) -GSMinDef(u8) -GSMinDef(u16) -GSMinDef(u32) -GSMinDef(u64) -GSMinDef(r32) -GSMinDef(r64) -#undef GSMinDef - -#define GSMaxDef(type) static type GSMax(type A, type B) { return (A > B ? A : B); } -GSMaxDef(s8) -GSMaxDef(s16) -GSMaxDef(s32) -GSMaxDef(s64) -GSMaxDef(u8) -GSMaxDef(u16) -GSMaxDef(u32) -GSMaxDef(u64) -GSMaxDef(r32) -GSMaxDef(r64) -#undef GSMaxDef - -inline b32 XOR(b32 A, b32 B) -{ - b32 Result = (A == !B); - return Result; -} -#define GSClampDef(type) static type GSClamp(type Min, type V, type Max) { \ - type Result = V; \ - if (V < Min) { Result = Min; } \ - if (V > Max) { Result = Max; } \ - return Result; \ -} -GSClampDef(s8) -GSClampDef(s16) -GSClampDef(s32) -GSClampDef(s64) -GSClampDef(u8) -GSClampDef(u16) -GSClampDef(u32) -GSClampDef(u64) -GSClampDef(r32) -GSClampDef(r64) -#undef GSClampDef - -#define GSClamp01Def(type) static type GSClamp01(type V) { \ - type Min = 0; type Max = 1; \ - type Result = V; \ - if (V < Min) { Result = Min; } \ - if (V > Max) { Result = Max; } \ - return Result; \ -} -GSClamp01Def(r32) -GSClamp01Def(r64) -#undef GSClamp01Def - -#define GSAbsDef(type) static type GSAbs(type A) { return (A < 0 ? -A : A); } -GSAbsDef(s8) -GSAbsDef(s16) -GSAbsDef(s32) -GSAbsDef(s64) -GSAbsDef(r32) -GSAbsDef(r64) -#undef GSAbsDef - -#define GSPowDef(type) static type GSPow(type N, s32 Power) { \ - type Result = N; \ - for(s32 i = 1; i < Power; i++) { Result *= N; } \ - return Result; \ -} -GSPowDef(s8) -GSPowDef(s16) -GSPowDef(s32) -GSPowDef(s64) -GSPowDef(u8) -GSPowDef(u16) -GSPowDef(u32) -GSPowDef(u64) -GSPowDef(r32) -GSPowDef(r64) -#undef GSPowDef - - -#define GSLerpDef(type) type GSLerp(type A, type B, type Percent) { return (A * (1.0f - Percent))+(B * Percent);} -GSLerpDef(r32) -GSLerpDef(r64) -#undef GSLerpDef - -static r32 GSSqrt(r32 V) -{ - r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; -} -#if 0 -// TODO(Peter): Need a way to split the input into two f32's to supply to _mm_sqrt_sd -static r64 GSSqrt(r64 V) -{ - r64 Result = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_set_sd(V))); - return Result; -} -#endif - -static r32 DegreesToRadians (r32 Degrees) { return Degrees * PI_OVER_180; } -static r64 DegreesToRadians (r64 Degrees) { return Degrees * PI_OVER_180; } - -#define GSIsPowerOfTwoDef(type) static type IsPowerOfTwo(type V) { return (V & (V - 1)) == 0; } -GSIsPowerOfTwoDef(u8); -GSIsPowerOfTwoDef(u16); -GSIsPowerOfTwoDef(u32); -GSIsPowerOfTwoDef(u64); -#undef GSIsPowerOfTwoDef - -#define GSIsOddDef(type) inline type IsOdd(type V) { return (V & 1); } -GSIsOddDef(u8); -GSIsOddDef(u16); -GSIsOddDef(u32); -GSIsOddDef(u64); -GSIsOddDef(s8); -GSIsOddDef(s16); -GSIsOddDef(s32); -GSIsOddDef(s64); -#undef GSIsOddDef - -#define GSIntDivideRoundUpDef(type) static type IntegerDivideRoundUp (type A, type B) { r32 Result = (r32)A / (r32)B; Result += .99999f; return (type)Result; } -GSIntDivideRoundUpDef(u8); -GSIntDivideRoundUpDef(u16); -GSIntDivideRoundUpDef(u32); -GSIntDivideRoundUpDef(u64); -GSIntDivideRoundUpDef(s8); -GSIntDivideRoundUpDef(s16); -GSIntDivideRoundUpDef(s32); -GSIntDivideRoundUpDef(s64); -#undef GSIntDivideRoundUpDef - -#define GSRemapDef(type) \ -static type GSRemap(type Value, type OldMin, type OldMax, type NewMin, type NewMax) { \ - type Result = (Value - OldMin) / (OldMax - OldMin); \ - Result = (Result * (NewMax - NewMin)) + NewMin; \ - return Result; \ -} -GSRemapDef(u8); -GSRemapDef(u16); -GSRemapDef(u32); -GSRemapDef(u64); -GSRemapDef(s8); -GSRemapDef(s16); -GSRemapDef(s32); -GSRemapDef(s64); -GSRemapDef(r32); -GSRemapDef(r64); -#undef GSRemapDef - -#define GSTrigFunctionDef(name, type, func) static type name(type V) { return func(V); } -GSTrigFunctionDef(GSSin, r32, sinf); -GSTrigFunctionDef(GSSin, r64, sin); -GSTrigFunctionDef(GSCos, r32, cosf); -GSTrigFunctionDef(GSCos, r64, cos); -GSTrigFunctionDef(GSTan, r32, tanf); -GSTrigFunctionDef(GSTan, r64, tan); -#undef GSTrigFunctionDef - -static u8 -RoundToNearestPowerOfTwo (u8 V) -{ - u8 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result += 1; - } - - return Result; -} - -static u16 -RoundToNearestPowerOfTwo (u16 V) -{ - u16 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result += 1; - } - - return Result; -} - -static u32 -RoundToNearestPowerOfTwo (u32 V) -{ - u32 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result += 1; - } - - return Result; -} - -static u64 -RoundToNearestPowerOfTwo (u64 V) -{ - u64 Result = 0; - - if (IsPowerOfTwo(V)) - { - Result = V; - } - else - { - Result = V - 1; - Result |= Result >> 1; - Result |= Result >> 2; - Result |= Result >> 4; - Result |= Result >> 8; - Result |= Result >> 16; - Result |= Result >> 32; - Result += 1; - } - - return Result; -} - -#define GS_LANGUAGE_MATH -#endif // GS_LANGUAGE_MATH - -static u32 -HostToNetU32(u32 In) -{ - unsigned char *s = (unsigned char *)&In; - u32 Result = (u32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); - return Result; -} - -static u16 -HostToNetU16(u16 In) -{ - unsigned char *s = (unsigned char *)&In; - u16 Result = (u16)(s[0] << 8 | s[1]); - return Result; -} - -#define GS_LANGUAGE_H -#endif diff --git a/src/gs_memory_arena.h b/src/gs_memory_arena.h deleted file mode 100644 index 7cf08f3..0000000 --- a/src/gs_memory_arena.h +++ /dev/null @@ -1,613 +0,0 @@ -// File: gs_memory_arena.h -// Description: Single header file library that defines a push-only memory arena -// Author: Peter Slattery -// Date Created: 2019-12-22 -// -// -// ----------------- -// Set Up -// ----------------- -// -// Include 'gs_memory_arena.h' in a file and start using it! (Simple! Nice!) -// -// ----------------- -// Usage -// ----------------- -// Simply create a memory_arena and use PushSize, PushStruct, or PushArray -// to allocate out of it. -// See Example Program below. -// -// While there are options you can set (see Options below), the library adheres -// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to -// zero, under all default options, will 'just work'. -// -// Alignment: -// By default, the Push functions use 4 byte alignment -// If you need to control the alignment of an allocation, there are variants of the -// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned -// These functions simply take a final parameter which specifies the alignment. -// Note: Alignment must be a power of two -// -// ----------------- -// Options -// ----------------- -// -// DEBUG: -// Define DEBUG for debug functionality. -// -// To override the default assert function define GSMem_Assert(expression) -// before inluding this file. -// -// GS_MEMORY_NO_STD_LIBS: -// if you don't want stdlib.h to be included, define GS_MEMORY_NO_STD_LIBS -// before including this file. -// Note that if you do this, zero-is-initialization will no longer work for -// memory_arenas. You must either: -// 1. Set each memory_arena's Alloc and Realloc so they can grow fields -// 2. Set each memory_arena's ExpansionRule to ExpansionRule_Disallowed -// If DEBUG is defined, the program will assert if one of the 2 rules above -// aren't followed. -// -// memory_arena.Alloc and memory_arena.Realloc -// By default, memory_arena's will use malloc and realloc to grow. -// You can override this by setting the Alloc and Realloc function pointers -// of a memory_arena. See the example program below for an implementation of this. -// -// GS_MEMORY_BUFFER_SIZE: -// This defines the minimum buffer size for memory_arena's. If an arena doesn't have -// room to fit an allocation, it will allocate a new buffer no smaller than GS_MEMORY_BUFFER_SIZE -// and place the allocation in the new buffer. -// By default this is 4096 bytes. To override, define GS_MEMORY_BUFFER_SIZE before including -// this file -// -// GS_MEMORY_TRACK_ALLOCATIONS: -// If you want to keep records of each allocation performed in every arena, define -// GS_MEMORY_TRACK_ALLOCATIONS before including this file. -// When defined, memory arenas gain fields that allow them to keep a list of every -// allocation they contain. It also adds a footer on the end of each allocation that -// can be checked to ensure there are no writes to allocations that overflow their bounds -// Note that calling ClearArena also clears this list -// You can then call AssertAllocationsNoOverflow occasionally throughout your program -// to check that no allocations have been written beyond their boundaries -// -// -// Example Program -// (this compiles - copy it into its own file though) -#if 0 -#include "gs_memory_arena.h" - -// Places the characters 'gs' at the end of each allocation. This would allow for an external -// function to check that we haven't written past the end of an allocation -void* MallocWrapper(gs_mem_u32 Size) -{ - int SizeWithFooter = Size + (sizeof(char) * 2); - void* Result = malloc(SizeWithFooter); - char* Footer = (char*)(Result + Size); - Footer[0] = 'g'; - Footer[1] = 's'; - return Result; -} - -void* ReallocWrapper(void* Address, gs_mem_u32 Size) -{ - return realloc(Address, Size); -} - -int -main(int ArgCount, char** Args) -{ - memory_arena Arena = {}; -// Uncomment these lines for an example of how you can implement custom allocation functions - // Arena.Alloc = MallocWrapper; - // Arena.Realloc = ReallocWrapper; - - int ArrayLength = 10; - -int* A = PushArray(&Arena, int, ArrayLength); - int* B = PushArray(&Arena, int, ArrayLength); - int* C = PushArray(&Arena, int, ArrayLength); - int* D = PushArrayAligned(&Arena, int, ArrayLength, 8); - int* E = PushArrayAligned(&Arena, int, ArrayLength, 16); - - // Just ensure that we can actually write to each address of each array - for (s32 i = 0; i < ArrayLength; i++) - { - A[i] = i; - B[i] = i; - C[i] = i; - D[i] = i; - E[i] = i; - } - - ClearArena(&Arena); - - A = PushArray(&Arena, int, ArrayLength); -for (s32 i = 0; i < ArrayLength; i++) - { - A[i] = i; - } - - return 0; -} -#endif - -// ------------------- -// Begin Library -// ------------------- -#ifndef GS_MEMORY_ARENA_H - -#ifndef GS_MEMORY_NO_STD_LIBS - -// NOTE(Peter): We use this so that we can fall back on malloc and realloc -// in the event that a memory_arena needs to grow but doesn't have a -// alloc or realloc function pointer assigned to it. -// -// See GrowArena to see where this is used -// -#include - -#endif - -typedef unsigned char gs_mem_u8; -typedef unsigned int gs_mem_u32; -typedef unsigned long long int gs_mem_u64; - -#ifdef DEBUG -#if !defined(GSMem_Assert) -#define GSMem_Assert(expression) \ -if(!(expression)) { \ -*((int *)0) = 5; \ -} - -#endif -#else -#define GSMem_Assert(expression) -#endif - -enum gs_memory_expansion_rule -{ - MemoryExpansion_Allowed, // Zero is initialization lets the memory grow on its own - MemoryExpansion_OnlyIfFunctionsProvided, - MemoryExpansion_Disallowed, - MemoryExpansion_Count, -}; - -// NOTE(Peter): -// This rule is only here to allow for taking arena snapshots. The problem this solves -// is if you take a snapshot while there are 'holes' in memory_buffers behind the -// most recently added memory_buffer, take a snapshot of that arena, then push something -// on that fits in one of those holes, we will fill the hole and be unable to track/free -// that addition via the snapshot construct. -// -// By requiring that allocations in a buffer only come from the most recent memory_buffer -// we can very easily rewind the buffer to the correct location. -// Hence FindAddress_InLastBufferOnly -enum gs_memory_find_address_rule -{ - FindAddress_InAnyBuffer, - FindAddress_InLastBufferOnly, - FindAddress_Count, -}; - -typedef void* gs_memory_alloc(gs_mem_u32 Size); -typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize); -typedef void gs_memory_free(void* Address, gs_mem_u32 Size); - -#ifndef GS_MEMORY_BUFFER_SIZE -#define GS_MEMORY_BUFFER_SIZE 1024 -#endif - -#define GS_MEMORY_FOOTER_SIZE 4 -#define GS_MEMORY_FOOTER_0 'g' -#define GS_MEMORY_FOOTER_1 's' -#define GS_MEMORY_FOOTER_2 'p' -#define GS_MEMORY_FOOTER_3 's' - -struct tracked_allocation -{ -gs_mem_u8* Head; - gs_mem_u8* Footer; - char* File; - gs_mem_u32 LineNumber; -}; - -#define GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE 512 -struct tracked_allocation_buffer -{ - tracked_allocation Buffer[GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE]; -}; - -struct memory_buffer -{ - gs_mem_u8* Buffer; - gs_mem_u32 Size; - gs_mem_u32 Used; -}; - -struct memory_arena -{ - memory_buffer* Buffers; - gs_mem_u32 BuffersCount; - - gs_mem_u32 TotalUsed; - gs_mem_u32 TotalSize; - - gs_memory_find_address_rule FindAddressRule; - gs_memory_expansion_rule ExpansionRule; - gs_memory_alloc* Alloc; - gs_memory_realloc* Realloc; - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - tracked_allocation_buffer** AllocationBuffers; - gs_mem_u32 AllocationBuffersCount; - gs_mem_u32 AllocationsUsed; - #endif -}; - -struct address_and_buffer -{ - memory_buffer* Buffer; - gs_mem_u64 Address; - gs_mem_u32 SizeWithAlignment; -}; - -struct arena_snapshot -{ - gs_mem_u32 ArenaUsedAtSnapshot; - gs_mem_u32 HeadBufferUsedAtSnapshot; - gs_mem_u32 HeadBufferAtSnapshot; - memory_arena* Arena; - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - gs_mem_u32 AllocationsUsedAtSnapshot; - #endif -}; - -static void -FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free) -{ - if (Free) - { -for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - Free(Buffer->Buffer, Buffer->Size); - } - Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - GSMem_Assert(0); -#else - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - free(Buffer->Buffer); - } - free(Arena->Buffers); - #endif - } -} - -#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) - -inline gs_mem_u32 -GetAlignmentOffset (gs_mem_u64 Address, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ - gs_mem_u32 AlignmentOffset = 0; -if (Address & AlignmentMask) - { - AlignmentOffset = Alignment - (Address & AlignmentMask); - } - return AlignmentOffset; -} - -static address_and_buffer -GetAlignedAddressInBuffer(memory_buffer* Buffer, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ - address_and_buffer Result = {}; - - gs_mem_u64 HeadAddress = (gs_mem_u64)Buffer->Buffer + Buffer->Used; - gs_mem_u32 AlignmentOffset = GetAlignmentOffset(HeadAddress, Alignment, AlignmentMask); - gs_mem_u64 AlignedAddress = HeadAddress + AlignmentOffset; - -if (Buffer->Used + AlignmentOffset + Size <= Buffer->Size) - { - Result.Buffer = Buffer; - Result.Address = AlignedAddress; - Result.SizeWithAlignment = Size + AlignmentOffset; - } - - return Result; -} - -static address_and_buffer -FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) -{ -address_and_buffer Result = {}; - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* At = Arena->Buffers + i; - GSMem_Assert(At); - - address_and_buffer AddressInCurrentBuffer = GetAlignedAddressInBuffer(At, Size, Alignment, AlignmentMask); - if (AddressInCurrentBuffer.Address != 0) - { - Result = AddressInCurrentBuffer; - break; - } - } - return Result; -} - -static gs_mem_u8* -ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size) -{ - gs_mem_u8* Result = 0; - -if (Arena->Alloc) - { - Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a allocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); -#else - Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size); - #endif - } - - return Result; -} - -static gs_mem_u8* -ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize) -{ - gs_mem_u8* Result = 0; - - if (Arena->Realloc != 0) - { - Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize); - } - else - { -#ifdef GS_MEMORY_NO_STD_LIBS - // NOTE(Peter): If you specify no std libs AND don't supply a reallocation function - // we should assert as this is an invalid codepath - GSMem_Assert(0); - #else - Result = (gs_mem_u8*)realloc(Head, NewSize); - #endif - } - - return Result; -} - -static memory_buffer* -GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded) -{ - GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed); - if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided) - { - GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0)); - } - - gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1); - gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount; - gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount; - Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize); - Arena->BuffersCount = NewBuffersCount; - - memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1); - NewBuffer->Size = GS_MEMORY_BUFFER_SIZE; - if (SizeNeeded > NewBuffer->Size) - { - NewBuffer->Size = SizeNeeded; - } - - NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size); - NewBuffer->Used = 0; - - Arena->TotalSize += NewBuffer->Size; - return NewBuffer; -} - -#ifdef GS_MEMORY_TRACK_ALLOCATIONS - -#define DetermineAllocationSize(size) (size) + GS_MEMORY_FOOTER_SIZE -#define ClearAllocationsUsed(arena) (arena)->AllocationsUsed = 0 -#define ClearAllocationsUsedToSnapshot(arena, snapshot) \ -(arena)->AllocationsUsed = (snapshot).AllocationsUsedAtSnapshot; - -static void -TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Filename, gs_mem_u32 LineNumber) -{ -gs_mem_u32 AllocationsMax = Arena->AllocationBuffersCount * GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - if (Arena->AllocationsUsed >= AllocationsMax) - { - gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1; - Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena, - (gs_mem_u8*)Arena->AllocationBuffers, - Arena->AllocationBuffersCount * sizeof(void*), -NewAllocationBuffersCount * sizeof(void*)); - Arena->AllocationBuffersCount = NewAllocationBuffersCount; - - gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1; - Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer)); - } - - gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++; - gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - tracked_allocation_buffer* Buffer = Arena->AllocationBuffers[BufferIndex]; - tracked_allocation* NewAllocationTracker = Buffer->Buffer + IndexInBuffer; - - NewAllocationTracker->Head = Head; - -NewAllocationTracker->Footer = Head + Size - GS_MEMORY_FOOTER_SIZE; - NewAllocationTracker->Footer[0] = GS_MEMORY_FOOTER_0; -NewAllocationTracker->Footer[1] = GS_MEMORY_FOOTER_1; -NewAllocationTracker->Footer[2] = GS_MEMORY_FOOTER_2; -NewAllocationTracker->Footer[3] = GS_MEMORY_FOOTER_3; - - NewAllocationTracker->File = Filename; - NewAllocationTracker->LineNumber = LineNumber; -} - - inline bool -VerifyAllocationNoOverflow (tracked_allocation Allocation) -{ - bool Result = ((Allocation.Footer[0] == GS_MEMORY_FOOTER_0) && -(Allocation.Footer[1] == GS_MEMORY_FOOTER_1) && -(Allocation.Footer[2] == GS_MEMORY_FOOTER_2) && - (Allocation.Footer[3] == GS_MEMORY_FOOTER_3)); - return Result; -} - - static void -AssertAllocationsNoOverflow (memory_arena Arena) -{ - for (gs_mem_u32 AllocationIndex = 0; - AllocationIndex< Arena.AllocationsUsed; - AllocationIndex++) - { - gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - gs_mem_u32 IndexInBuffer = AllocationIndex % GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE; - - tracked_allocation_buffer* Buffer = Arena.AllocationBuffers[BufferIndex]; - tracked_allocation Allocation = Buffer->Buffer[IndexInBuffer]; - -GSMem_Assert(VerifyAllocationNoOverflow(Allocation)); - } -} - -#define PushSize(arena, size) PushSize_((arena), (size), 4, __FILE__, __LINE__) -#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length, 4, __FILE__, __LINE__) -#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type), 4, __FILE__, __LINE__) -#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment), __FILE__, __LINE__) -#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment), __FILE__, __LINE__) -#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment), __FILE__, __LINE__) - -#else // GS_MEMORY_TRACK_ALLOCATIONS - -#define AssertAllocationsNoOverflow(arena) -#define DetermineAllocationSize(size) size -#define ClearAllocationsUsed(arena) -#define ClearAllocationsUsedToSnapshot(arena, snapshot) - -#define TrackAllocation(arena, head, size, filename, linenumber) - -#define PushSize(arena, size) PushSize_((arena), (size)) -#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length) -#define PushStruct(arena, type) (type*)PushSize_((arena), sizeof(type)) -#define PushSizeAligned(arena, size, alignment) PushSize_((arena), (size), (alignment)) -#define PushArrayAligned(arena, type, length, alignment) (type*)PushSize_((arena), sizeof(type) * length, (alignment)) -#define PushStructAligned(arena, type, alignment) (type*)PushSize_((arena), sizeof(type), (alignment)) - -#endif // GS_MEMORY_TRACK_ALLOCATIONS - -static gs_mem_u8* -PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0) -{ - // ie. Alignment = 4 = 100 (binary) - // 4 - 1 = 3 - // 100 - 1 = 011 which is a mask of the bits we don't want set in the start address - GSMem_Assert(IsPowerOfTwo(Alignment)); -gs_mem_u32 AlignmentMask = Alignment - 1; - - gs_mem_u32 AllocationSize = DetermineAllocationSize(Size); - - address_and_buffer ResultAddress = {}; - if (Arena->FindAddressRule == FindAddress_InAnyBuffer) - { - ResultAddress = FindAlignedAddressInBufferWithRoom(Arena, AllocationSize, Alignment, AlignmentMask); - } - else if (Arena->FindAddressRule == FindAddress_InLastBufferOnly - && Arena->BuffersCount > 0) - { - memory_buffer* LastBuffer = Arena->Buffers + Arena->BuffersCount - 1; - ResultAddress = GetAlignedAddressInBuffer(LastBuffer, Size, Alignment, AlignmentMask); - } - - if (ResultAddress.Address == 0) - { - memory_buffer* Buffer = GrowArena(Arena, AllocationSize); - ResultAddress = GetAlignedAddressInBuffer(Buffer, AllocationSize, Alignment, AlignmentMask); - } - GSMem_Assert(ResultAddress.Address != 0); -GSMem_Assert((ResultAddress.Address & AlignmentMask) == 0); - - gs_mem_u8* Result = (gs_mem_u8*)ResultAddress.Address; - ResultAddress.Buffer->Used += ResultAddress.SizeWithAlignment; - Arena->TotalUsed += ResultAddress.SizeWithAlignment; - - TrackAllocation(Arena, Result, AllocationSize, Filename, LineNumber); - - return Result; -} - -static void -ClearArena(memory_arena* Arena) -{ - for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++) - { - memory_buffer* At = Arena->Buffers + i; - At->Used = 0; - } - - Arena->TotalUsed = 0; - ClearAllocationsUsed(Arena); -} - -static arena_snapshot -TakeSnapshotOfArena(memory_arena* Arena) -{ - Assert(Arena->FindAddressRule == FindAddress_InLastBufferOnly); - -arena_snapshot Result = {}; - Result.Arena = Arena; - Result.ArenaUsedAtSnapshot = Arena->TotalUsed; - if (Arena->BuffersCount > 0) - { - Result.HeadBufferAtSnapshot = Arena->BuffersCount - 1; - } - else - { - Result.HeadBufferAtSnapshot = 0; - } - - memory_buffer* HeadBuffer = Arena->Buffers + Result.HeadBufferAtSnapshot; - if (HeadBuffer) - { - Result.HeadBufferUsedAtSnapshot = HeadBuffer->Used; - } - -return Result; -} - -static void -ClearArenaToSnapshot(memory_arena* Arena, arena_snapshot Snapshot) -{ - Assert(Arena == Snapshot.Arena); - - memory_buffer* HeadBufferAtSnapshot = Arena->Buffers + Snapshot.HeadBufferAtSnapshot; - if (HeadBufferAtSnapshot) - { - HeadBufferAtSnapshot->Used = Snapshot.HeadBufferUsedAtSnapshot; - - for (gs_mem_u32 i = Snapshot.HeadBufferAtSnapshot + 1; i < Arena->BuffersCount; i++) - { - memory_buffer* Buffer = Arena->Buffers + i; - Buffer->Used = 0; - } - } - - Arena->TotalUsed = Snapshot.ArenaUsedAtSnapshot; - ClearAllocationsUsedToSnapshot(Arena, Snapshot); -} -#define GS_MEMORY_ARENA_H -#endif // GS_MEMORY_ARENA_H \ No newline at end of file diff --git a/src/gs_string.h b/src/gs_string.h deleted file mode 100644 index 2cd8158..0000000 --- a/src/gs_string.h +++ /dev/null @@ -1,2206 +0,0 @@ -#ifndef GS_STRING_H -//////////////////////////////////////////////////////////////// -// String -//////////////////////////////////////////////////////////////// - -struct string -{ - char* Memory; - s32 Length; - s32 Max; -}; - -//////////////////////////////////////////////////////////////// -// String Tokenizing -//////////////////////////////////////////////////////////////// - -struct tokenizer -{ - char* At; - char* Memory; - s32 MemoryLength; -}; - - -enum token_type -{ - Token_Error, - - Token_LeftParen, - Token_RightParen, - Token_LeftSquareBracket, - Token_RightSquareBracket, - Token_LeftCurlyBracket, - Token_RightCurlyBracket, - Token_Semicolon, - Token_Operator, - Token_Comma, - Token_Period, - Token_PointerReference, - - Token_PoundDefine, - Token_PoundUndef, - Token_PoundInclude, - Token_PoundIfDef, - Token_PoundIfNDef, - Token_PoundIf, - Token_PoundElif, - Token_PoundElse, - Token_PoundEndif, - Token_PoundError, - Token_PoundPragma, - - Token_Number, - Token_Char, - Token_String, - Token_Identifier, - - Token_Comment, - Token_MultilineComment, - - Token_Unknown, - Token_EndOfStream, -}; - -char* TokenNames[] = { - "Token_Error ", - "Token_LeftParen ", - "Token_RightParen ", - "Token_LeftSquareBracket ", - "Token_RightSquareBracket ", - "Token_LeftCurlyBracket ", - "Token_RightCurlyBracket ", - "Token_Semicolon ", - "Token_Operator ", - "Token_Comma ", - "Token_Period ", - "Token_PointerReference ", - "Token_PoundDefine ", - "Token_PoundUndef ", - "Token_PoundInclude ", - "Token_PoundIfDef ", - "Token_PoundIfNDef ", - "Token_PoundIf ", - "Token_PoundElif ", - "Token_PoundElse ", - "Token_PoundEndif ", - "Token_PoundError ", - "Token_PoundPragma ", - "Token_Number ", - "Token_Char ", - "Token_String ", - "Token_Identifier ", - "Token_Comment ", - "Token_MultilineComment ", - "Token_Unknown ", - "Token_EndOfStream ", -}; - -struct token -{ - token_type Type; - string Text; - token* Next; -}; - -//////////////////////////////////////////////////////////////// -// String Memory -//////////////////////////////////////////////////////////////// - -struct slot_header -{ - slot_header* Next; - s32 Size; -}; - -struct slot_arena -{ - u8* Memory; - s32 SlotSize; - s32 SlotCount; - slot_header* FreeList; -}; - -struct contiguous_slot_count_result -{ - s32 Count; - slot_header* LastContiguousSlot; -}; - - -//////////////////////////////////////////////////////////////// -// String Function Declarations -//////////////////////////////////////////////////////////////// - -// Utility -#if !defined GS_LANGUAGE_H - -static void GSZeroMemory (u8* Memory, s32 Size); -static s32 GSMin (s32 A, s32 B); -static s32 GSAbs (s32 A); -static float GSAbsF (float A); -static float GSPowF (float N, s32 Power); - -#endif - -// Setup - -#ifdef GS_MEMORY_H -#define PushString(str, arena, size) (str)->Memory = PushArray(arena, char, size); (str)->Length = 0; (str)->Max = size; -#endif - -static void InitializeEmptyString (string* String, char* Data, s32 DataSize); -static void InitializeString(string* String, char* Data, s32 Used, s32 Max); -static string InitializeEmptyString (char* Data, s32 DataSize); -static string InitializeString (char* Data, s32 Used, s32 Max); -static void ClearString (string* String); - -// Character Values -static bool IsSlash (char C); -static bool IsNewline (char C); -static bool IsWhitespace (char C); -static bool IsAlpha (char C); -static bool IsUpper (char C); -static bool IsLower (char C); -static char ToUpper (char C); -static char ToLower (char C); -static bool IsNumeric (char C); -static bool IsNumericExtended (char C); -static bool IsAlphaNumeric (char C); -static bool IsOperator (char C); -static bool CharsEqualCaseInsensitive(char A, char B); - -// Tokenizing -static b32 AtValidPosition(tokenizer Tokenizer); -static b32 AtValidToken(tokenizer Tokenizer); -static char* EatToNewLine(char* C); -static void EatToNewLine(tokenizer* T); -static char* EatWhitespace(char* C); -static void EatWhitespace(tokenizer* T); -static char* EatToWhitespace(char* C); -static void EatToWhitespace(tokenizer* T); -static char* EatToCharacter(char* C, char Char); -static void EatToCharacter(tokenizer* T, char Char); -static char* EatPastCharacter(char* C, char Char); -static void EatPastCharacter(tokenizer* T, char Char); -static char* EatNumber(char* C); -static void EatNumber(tokenizer* T); - -// Char/Char Array -static u32 CharToUInt (char C); -static s32 CharArrayLength (char* CharArray); -static bool CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength); -static bool CharArraysEqualUnsafe (char* A, char* B); -static void ReverseCharArray (char* Array, s32 Length); -#define FirstIndexOfCharInCharArray(array, find) IndexOfChar(array, 0, find) -static s32 IndexOfChar (char* Array, s32 Start, char Find); -#define FastLastIndexOfCharInCharArray(array, len, find) FastReverseIndexOfChar(array, len, 0, find) -static s32 FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find); -#define LastIndexOfCharInCharArray(array, find) ReverseIndexOfChar(array, 0, find) -static s32 ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find); -static b32 CharArrayContains(char* Array, char* CheckFor); -static b32 CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength); - -// String - -#define MakeStringBuffer(name, size) \ -char name##Backbuffer[(size)]; \ -string name = MakeString(name##Backbuffer, size); - -static string MakeString (char* Array, s32 Length, s32 Max); -static string MakeString (char* Array, s32 Length); -static string MakeString (char* Array); -static string MakeStringLiteral(char* Data); - -static bool StringsEqual (string A, string B); -static bool StringEqualsCharArray (string String, char* CharArray); -static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); -static s32 FindFirstChar (string String, char C); - -static void SetStringToChar (string* Dest, char C, s32 Count); -static void SetStringToCharArray (string* Dest, char* Source); - -static void ConcatString (string Source, string* Dest); -static void ConcatString (string Source, s32 Length, string* Dest); -static void ConcatCharToString(string* Dest, char C); -static void ConcatCharArrayToString (char* Source, string* Dest); -static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); - -static void CopyStringTo (string Source, string* Dest); -static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); -static void CopyCharArrayToString (char* Src, string* Dest); -static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); -static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); -static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); - -static void InsertChar (string* String, char Char, s32 Index); -static void InsertStringAt (string* Dest, string Source, s32 At); -static void RemoveCharAt (string* String, s32 Index); - -static s32 IndexOfChar(string String, char C); -static s32 LastIndexOfChar(string String, char C); -static string Substring (string* String, s32 Start, s32 End); -static string Substring (string* String, s32 Start); - -static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsString(string SearchIn, string SearchFor); -static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); - -static void NullTerminate (string* String); - - -// Parsing -enum parse_type -{ - ParseType_UnsignedInt, - ParseType_SignedInt, - ParseType_Float, -}; - -struct parse_result -{ - parse_type Type; - char* OnePastLast; - union - { - u32 UnsignedIntValue; - s32 SignedIntValue; - r32 FloatValue; - }; -}; - -enum format_flags -{ - FormatFlags_LeftJustify = 0x1, - FormatFlags_ForceSign = 0x2, - FormatFlags_ForceSpaceInsteadOfSign = 0x4, - FormatFlags_ForceDecimalOrPrependOx = 0x8, - FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, -}; - -static parse_result ParseUnsignedInt (char* String, s32 Length); -static parse_result ParseSignedInt (char* String, s32 Length); -static parse_result ParseFloat (char* String, s32 Length); - -// PrintF -static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); -static void PrintF(string* String, char* Format, ...); - -//////////////////////////////////////////////////////////////// -// String Memory Function Declarations -//////////////////////////////////////////////////////////////// - -static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); -static bool SlotsAreContiguous (slot_header* First, slot_header* Second); -static contiguous_slot_count_result CountContiguousSlots (slot_header* First); -static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); -static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); -static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); -static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); -static void FreeToStringArena (string* String, slot_arena* Storage); -static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); - -//////////////////////////////////////////////////////////////// -// String Utility Functions -//////////////////////////////////////////////////////////////// - -#if !defined GS_LANGUAGE_H - -static void -GSZeroMemory (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -static s32 -GSMin (s32 A, s32 B) -{ - return (A < B ? A : B); -} - -static s32 -GSAbs (s32 A) -{ - return (A < 0 ? -A : A); -} - -static float -GSAbs (float A) -{ - return (A < 0 ? -A : A); -} - -static float -GSPow (float N, s32 Power) -{ - float Result = N; - for(s32 i = 1; i < Power; i++) { Result *= N; } - return Result; -} - -#endif - -//////////////////////////////////////////////////////////////// -// Init and Clear -//////////////////////////////////////////////////////////////// - -static void -InitializeEmptyString (string* String, char* Data, s32 DataSize) -{ - String->Memory = Data; - String->Max = DataSize; - String->Length = 0; -} - -static void -InitializeString(string* String, char* Data, s32 Used, s32 Max) -{ - String->Memory = Data; - String->Max = Max; - String->Length = Used; -} - -static string -InitializeEmptyString (char* Data, s32 DataSize) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = DataSize; - Result.Length = 0; - return Result; -} - -static string -InitializeString (char* Data, s32 Used, s32 Max) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = Max; - Result.Length = Used; - return Result; -} - -static void -ClearString (string* String) -{ - String->Memory = 0; - String->Max = 0; - String->Length = 0; -} - -//////////////////////////////////////////////////////////////// -// Char Value Types -//////////////////////////////////////////////////////////////// - -static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } -static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } -static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t') || IsNewline(C); } -static bool IsAlpha (char C) -{ - // TODO(Peter): support UTF8 chars - return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); -} -static bool IsUpper (char C) -{ - return ((C >= 'A') && (C <= 'Z')); -} -static bool IsLower (char C) -{ - return ((C >= 'a') && (C <= 'z')); -} -static bool IsNumeric (char C) -{ - return (C >= '0') && (C <= '9'); -} -static bool IsNumericExtended (char C) -{ - return (IsNumeric(C) || (C == 'x') || (C == 'f') || (C == '.')); -} -static bool IsAlphaNumeric (char C) -{ - return IsAlpha(C) || IsNumeric(C); -} -static bool IsOperator (char C) -{ - return ((C == '+') || - (C == '-') || - (C == '*') || - (C == '/') || - (C == '=') || - (C == '%') || - (C == '<') || - (C == '>')); -} -static char ToUpper (char A) -{ - char Result = A; - if (IsLower(A)) - { - Result += 'A' - 'a'; - } - return Result; -} -static char ToLower (char A) -{ - char Result = A; - if (IsUpper(A)) - { - Result -= 'A' - 'a'; - } - return Result; -} -static bool CharsEqualCaseInsensitive (char A, char B) -{ - b32 Result = (ToLower(A) == ToLower(B)); - return Result; -} - -//////////////////////////////////////////////////////////////// -// Tokenizing -//////////////////////////////////////////////////////////////// - -static b32 -AtValidPosition (tokenizer Tokenizer) -{ - b32 Result = (Tokenizer.At - Tokenizer.Memory) <= Tokenizer.MemoryLength; - return Result; -} - -static b32 -AtValidToken(tokenizer Tokenizer) -{ - b32 Result = *Tokenizer.At && Tokenizer.At < (Tokenizer.Memory + Tokenizer.MemoryLength); - return Result; -} - -static char* -EatToNewLine(char* C) -{ - char* Result = C; - while (*Result && !IsNewline(*Result)) { Result++; } - if (*Result) { Result++; } // NOTE(Peter): eat past the newline character - return Result; -} - -static void -EatToNewLine(tokenizer* T) -{ - while (*T->At && !IsNewline(*T->At)) { T->At++; } - if (*T->At) { T->At++; } // NOTE(Peter): eat past the newline character -} - -static char* -EatWhitespace(char* C) -{ - char* Result = C; - while (*Result && IsWhitespace(*Result)) { Result++; } - return Result; -} - -static void -EatWhitespace(tokenizer* T) -{ - while (*T->At && IsWhitespace(*T->At)) { T->At++; } -} - -static char* -EatToWhitespace(char* C) -{ - char* Result = C; - while (*Result && !IsWhitespace(*Result)) { Result++; } - return Result; -} - -static void -EatToWhitespace(tokenizer* T) -{ - while (*T->At && !IsWhitespace(*T->At)) { T->At++; } -} - -static char* -EatToCharacter(char* C, char Char) -{ - char* Result = C; - while (*Result && *Result != Char) { Result++; } - return Result; -} - -static void -EatToCharacter(tokenizer* T, char Char) -{ - while (*T->At && *T->At != Char) { T->At++; } -} - -static char* -EatPastCharacter(char* C, char Char) -{ - char* Result = EatToCharacter(C, Char); - if (*Result && *Result == Char) { Result++; } - return Result; -} - -static void -EatPastCharacter(tokenizer* T, char Char) -{ - EatToCharacter(T, Char); - if (*T->At && *T->At == Char) { T->At++; } -} - -static char* -EatNumber(char* C) -{ - char* Result = C; - while (*Result && IsNumericExtended(*Result)) { Result++; } - return Result; -} - -static void -EatNumber(tokenizer* T) -{ - while (*T->At && IsNumericExtended(*T->At)) { T->At++; } -} - -//////////////////////////////////////////////////////////////// -// Basic Char Operations -//////////////////////////////////////////////////////////////// - -static u32 CharToUInt (char C) { - u32 Result = (C - '0'); - return Result; -} - -static s32 -CharArrayLength (char* Array) -{ - char* C = Array; - s32 Result = 0; - while (*C) - { - *C++; - Result++; - } - return Result; -} - -static s32 -NullTerminatedCharArrayLength (char* CharArray) -{ - char* Iter = CharArray; - while (*Iter) - { - *Iter++; - } - return (Iter - CharArray); -} - -static bool -CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) -{ - bool Result = false; - if (ALength == BLength) - { - Result = true; - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < ALength; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - return Result; -} - -static bool -CharArraysEqualUnsafe (char* A, char* B) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - while(*AIter && *BIter) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - if((*AIter && !*BIter) || (!*AIter && *BIter)) - { - Result = false; - } - - return Result; -} - -static bool -CharArraysEqualUpToLength (char* A, char* B, s32 Length) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < Length; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - return Result; -} - -static void -ReverseCharArray (char* Array, s32 Length) -{ - char* ForwardIter = Array; - char* BackwardIter = Array + Length - 1; - for (s32 i = 0; i < (Length / 2); i++) - { - char F = *ForwardIter; - char B = *BackwardIter; - *ForwardIter++ = B; - *BackwardIter-- = F; - } -} - -static s32 -IndexOfChar (char* Array, s32 After, char Find) -{ - s32 Result = -1; - - s32 Counter = After; - char* Iter = Array + After; - while (*Iter) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - Counter++; - *Iter++; - } - - return Result; -} - -static s32 -FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) -{ - s32 Result = -1; - - s32 Counter = Length - OffsetFromEnd; - char* Iter = Array + Length - OffsetFromEnd; - for (int i = 0; i < (Length - OffsetFromEnd); i++) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - - *Iter--; - Counter--; - } - - return Result; -} - -static s32 -ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) -{ - s32 StringLength = NullTerminatedCharArrayLength(Array); - return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); -} - -static b32 -CharArrayContains(char* Array, char* CheckFor) -{ - b32 Result = false; - - char* Src = Array; - while (*Src) - { - if (*Src == *CheckFor) - { - char* A = CheckFor; - char* B = Src; - while (*B && *A && *A == *B) - { - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - - return Result; -} - -static b32 -CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) -{ - b32 Result = false; - - if (ArrayLength >= CheckForLength) - { - char* Src = Array; - for (s32 s = 0; s < ArrayLength; s++) - { - if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) - { - char* A = CheckFor; - char* B = Src; - for (s32 d = 0; d < CheckForLength; d++) - { - if (*B != *A) { break; } - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - } - - return Result; -} - -//////////////////////////////////////////////////////////////// -// Basic String Operations -//////////////////////////////////////////////////////////////// - -static bool -StringsEqual (string A, string B) -{ - bool Result = false; - - if (A.Length == B.Length) - { - Result = true; - char* AIter = A.Memory; - char* BIter = B.Memory; - for (s32 i = 0; i < A.Length; i++) - { - if (*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static string -MakeString (char* Array, s32 Length, s32 Max) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Max; - return Result; -} - -static string -MakeString (char* Array, s32 Length) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Length; - return Result; -} - -static string -MakeString (char* Array) -{ - s32 Length = CharArrayLength (Array); - return MakeString(Array, Length); -} - -static string -MakeStringLiteral (char* String) -{ - string Result = {}; - Result.Memory = String; - Result.Max = CharArrayLength(String); - Result.Length = Result.Max; - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray) -{ - bool Result = true; - - char* S = String.Memory; - char* C = CharArray; - - s32 Count = 0; - while (*C && Count < String.Length) - { - if (*C++ != *S++) - { - Result = false; - break; - } - Count++; - } - - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) -{ - bool Result = false; - - if (CharArrayLength == String.Length) - { - Result = true; - - char* S = String.Memory; - char* C = CharArray; - for (s32 i = 0; i < String.Length; i++) - { - if (*C++ != *S++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static s32 -FindFirstChar (string String, char C) -{ - s32 Result = -1; - - char* Iter = String.Memory; - for (int i = 0; i < String.Length; i++) - { - if (*Iter++ == C) - { - Result = i; - break; - } - } - - return Result; -} - -static void -SetStringToChar (string* Dest, char C, s32 Count) -{ - Assert(Count <= Dest->Max); - - char* Iter = Dest->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = C; - } - Dest->Length = Count; -} - -static void -SetStringToCharArray (string* Dest, char* Source) -{ - Dest->Length = 0; - - char* Src = Source; - char* Dst = Dest->Memory; - while (*Src && Dest->Length < Dest->Max) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, string* Dest) -{ - Assert((Dest->Length + Source.Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Source.Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, s32 Length, string* Dest) -{ - Assert(Length < Source.Length); - Assert((Dest->Length + Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharToString (string* Dest, char C) -{ - Assert(Dest->Length + 1 <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - *Dst = C; - Dest->Length++; -} - -static void -ConcatCharArrayToString (char* Source, string* Dest) -{ - Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - while (Dest->Length < Dest->Max && - *Src) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -CopyStringTo (string Source, string* Dest) -{ - char* Src = Source.Memory; - char* Dst = Dest->Memory; - s32 CopyLength = GSMin(Source.Length, Dest->Max); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - Dest->Length = Source.Length; -} - -static s32 -CopyStringToCharArray (string Source, char* Dest, s32 DestLength) -{ - char* Src = Source.Memory; - char* Dst = Dest; - s32 CopyLength = GSMin(Source.Length, DestLength); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - return CopyLength; -} - -static void -CopyCharArrayToString (char* Source, string* Dest) -{ - char* Src = Source; - char* Dst = Dest->Memory; - s32 Copied = 0; - while (*Src && Copied < Dest->Max) - { - *Dst++ = *Src++; - Copied++; - } - *Dst++ = 0; - Dest->Length = Copied; -} - -static void -CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength <= Dest->Max); - - char* Src = Source; - char* Dst = Dest->Memory; - for (s32 i = 0; i < SourceLength; i++) - { - *Dst++ = *Src++; - } - *Dst++ = 0; - Dest->Length = SourceLength; -} - -static s32 -CopyCharArray (char* Source, char* Dest, s32 DestLength) -{ - char* Src = Source; - char* Dst = Dest; - s32 i = 0; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i; -} - -static s32 -CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) -{ - Assert(Offset < DestLength); - - char* Src = Source; - char* Dst = Dest + Offset; - s32 i = Offset; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i - Offset; -} - -static void -InsertChar (string* String, char Char, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - Assert(String->Length < String->Max); - - char* Src = String->Memory + String->Length - 1; - char* Dst = Src + 1; - for (int i = String->Length - 1; i >= Index; i--) - { - *Dst-- = *Src--; - } - - *(String->Memory + Index) = Char; - String->Length++; -} - -static void -RemoveCharAt (string* String, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - - char* Dst = String->Memory + Index; - char* Src = Dst + 1; - for (int i = Index; i < String->Length; i++) - { - *Dst++ = *Src++; - } - *Dst = 0; - String->Length--; -} - -static s32 -IndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = i; - break; - } - At++; - } - return Result; -} - -static s32 -LastIndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory + String.Length - 1; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = String.Length - i; - break; - } - At--; - } - return Result; -} - -static string -Substring (string String, s32 Start, s32 End) -{ - Assert(Start >= 0 && End > Start && End <= String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = End - Start; - return Result; -} - -static string -Substring (string String, s32 Start) -{ - Assert(Start >= 0 && Start < String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = String.Length - Start; - return Result; -} - -static b32 -StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (*InAt == *ForAt) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsString(string SearchIn, string SearchFor) -{ - return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static b32 -StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (CharsEqualCaseInsensitive(*InAt, *ForAt)) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) -{ - return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static void -NullTerminate (string* String) -{ - Assert(String->Length + 1 <= String->Max); - *(String->Memory + String->Length) = 0; - String->Length++; -} - -static void -InsertStringAt (string* Dest, string Source, s32 At) -{ - Assert(At + Source.Length < Dest->Max); - Assert(At < Dest->Length); - - char* Src = Dest->Memory + Dest->Length; - char* Dst = Dest->Memory + Source.Length + Dest->Length; - for (s32 i = Dest->Length - 1; i >= At; i--) - { - *--Dst = *--Src; - } - - Src = Source.Memory; - Dst = Dest->Memory + At; - for (s32 j = 0; j < Source.Length; j++) - { - *Dst++ = *Src++; - } - - Dest->Length += Source.Length; -} - -//////////////////////////////////////////////////////////////// -// String Parsing -//////////////////////////////////////////////////////////////// - -static parse_result -ParseUnsignedInt (char* String, s32 Length) -{ - Assert(IsNumeric(*String)); - parse_result Result = {}; - Result.Type = ParseType_UnsignedInt; - - char* Iter = String; - u32 ResultValue = 0; - for (s32 i = 0; i < Length; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - Result.UnsignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseUnsignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseUnsignedInt(String, End - Start); -} - -static parse_result -ParseSignedInt (char* String, s32 Length) -{ - Assert(Length > 0); - parse_result Result = {}; - Result.Type = ParseType_SignedInt; - - s32 Negative = 1; - s32 LengthRemaining = Length; - s32 ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - ResultValue *= Negative; - - Result.SignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseSignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseSignedInt(String, End - Start); -} - -static parse_result -ParseFloat (char* String, s32 Length) -{ - parse_result Result = {}; - Result.Type = ParseType_Float; - - s32 Negative = 1; - s32 LengthRemaining = Length; - float ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); - } - else if (*Iter == '.' || *Iter == 0) - { - LengthRemaining -= i; - break; - } - } - - if (*Iter == '.') - { - *Iter++; - float AfterPoint = 0; - s32 PlacesAfterPoint = 0; - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); - PlacesAfterPoint++; - } - else - { - break; - } - } - - AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); - ResultValue += AfterPoint; - } - - ResultValue *= Negative; - - Result.FloatValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseFloatUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseFloat(String, End - Start); -} - -static s32 -UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - char* Iter = String; - while (Remaining > 0 && (Iter - String) < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - } - s32 CharsCopied = Iter - String; - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - s32 CharsCopied = 0; - - char* Iter = String; - - bool Negative = Remaining < 0; - Remaining = GSAbs(Remaining); - - if (Remaining > 0) - { - while (Remaining > 0 && CharsCopied < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - CharsCopied++; - } - } - else if (Remaining == 0) - { - *Iter++ = '0'; - } - - if (Negative) - { - *Iter++ = '-'; - CharsCopied++; - } - - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - char* StringStart = String + Offset; - s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); - return LengthWritten; -} - -static s32 -FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - s32 IPart = (s32)Float; - float FPart = GSAbs(Float - (float)IPart); - - s32 i = IntToString(IPart, String, MaxLength); - - if (AfterPoint > 1) - { - String[i++] = '.'; - - s32 FPartInt = FPart * GSPow(10, AfterPoint); - i += IntToString(FPartInt, String, MaxLength, i, 0, 0); - } - - return i; -} - -//////////////////////////////////////////////////////////////// -// PrintF -//////////////////////////////////////////////////////////////// - -static void -OutChar (string* String, char C) -{ - if (String->Length < String->Max) - { - String->Memory[String->Length] = C; - String->Length++; - } -} - -char OctalDigits[] = "01234567"; -char DecimalDigits[] = "0123456789"; -char HexDigits[] = "0123456789ABCDEF"; - -static void -U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) -{ - u64 ValueRemaining = Value; - char* Start = String->Memory + String->Length; - do { - s32 DigitsIndex = ValueRemaining % Base; - char Digit = Digits[DigitsIndex]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while (ValueRemaining); - char* End = String->Memory + String->Length; - - while (Start < End) - { - End--; - char Temp = *End; - *End = *Start; - *Start = Temp; - *Start++; - } -} - -static void -F64ToASCII (string* String, r64 Value, s32 Precision) -{ - if (Value < 0) - { - OutChar(String, '-'); - Value = -Value; - } - - u64 IntegerPart = (u64)Value; - Value -= IntegerPart; - - U64ToASCII(String, IntegerPart, 10, DecimalDigits); - - OutChar(String, '.'); - - for (s32 i = 0; i < Precision; i++) - { - Value *= 10.f; - u32 DecimalPlace = Value; - Value -= DecimalPlace; - OutChar(String, DecimalDigits[DecimalPlace]); - } -} - -internal s64 -ReadVarArgsSignedInteger (s32 Width, va_list* Args) -{ - s64 Result = 0; - switch (Width) - { - case 1: { Result = (s64)va_arg(*Args, s8); } break; - case 2: { Result = (s64)va_arg(*Args, s16); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) -{ - u64 Result = 0; - switch (Width) - { - case 1: { Result = (u64)va_arg(*Args, u8); } break; - case 2: { Result = (u64)va_arg(*Args, u16); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsFloat (s32 Width, va_list* Args) -{ - r64 Result = 0; - switch (Width) - { - case 4: { Result = (r64)va_arg(*Args, r64); } break; - case 8: { Result = (r64)va_arg(*Args, r64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal s32 -PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) -{ - char* DestAt = Dest; - - char* FormatAt = Format; - while (*FormatAt) - { - if (FormatAt[0] != '%') - { - *DestAt++ = *FormatAt++; - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - *DestAt++ = *FormatAt++; - } - else - { - FormatAt++; - - // Flags - if (FormatAt[0] == '-') - { - FormatAt++; - } - else if (FormatAt[0] == '+') - { - FormatAt++; - } - else if (FormatAt[0] == ' ') - { - FormatAt++; - } - else if (FormatAt[0] == '#') - { - FormatAt++; - } - else if (FormatAt[0] == '0') - { - FormatAt++; - } - - // Width - b32 WidthSpecified = false; - s32 Width = 0; - - if (IsNumeric(FormatAt[0])) - { - WidthSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Width = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - WidthSpecified = true; - Width = va_arg(Args, s32); - Assert(Width >= 0); - FormatAt++; - } - - // Precision - b32 PrecisionSpecified = false; - s32 Precision = 0; - - if (FormatAt[0] == '.') - { - FormatAt++; - if (IsNumeric(FormatAt[0])) - { - PrecisionSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Precision = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - PrecisionSpecified = true; - Precision = va_arg(Args, s32); - Assert(Precision >= 0); - FormatAt++; - } - } - - // Length - b32 LengthSpecified = false; - s32 Length = 4; - - if (FormatAt[0] == 'h' && FormatAt[1] == 'h') - { - LengthSpecified = true; - LengthSpecified = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - LengthSpecified = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - LengthSpecified = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifier - s32 DestLengthRemaining = DestMax - (DestAt - Dest); - - char Temp[64]; - string TempDest = MakeString(Temp, 0, 64); - - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&TempDest, '-'); - SignedInt *= -1; - } - U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - F64ToASCII(&TempDest, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, char); - OutChar(&TempDest, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CharArrayLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = GSMin(InsertStringLength, Precision); - } - InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&TempDest, *InsertString++); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - for (s32 i = 0; i < TempDest.Length; i++) - { - *DestAt++ = TempDest.Memory[i]; - } - - *FormatAt++; - } - } - - s32 FormattedLength = DestAt - Dest; - return FormattedLength; -} - -internal void -PrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length = PrintFArgsList(String->Memory, String->Max, Format, Args); - va_end(Args); -} - - -//////////////////////////////////////////////////////////////// -// String Memory Function Definitions -//////////////////////////////////////////////////////////////// - -static s32 -CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) -{ - s32 SlotCount = RequestedSize / SlotSize; - if (SlotCount * SlotSize < RequestedSize) - { - SlotCount += 1; - } - return SlotCount; -} - -static bool -SlotsAreContiguous (slot_header* First, slot_header* Second) -{ - bool Result = false; - u8* FirstSlotNextAddress = (u8*)First + First->Size; - u8* SecondAddress = (u8*)Second; - Result = FirstSlotNextAddress == SecondAddress; - return Result; -} - -static contiguous_slot_count_result -CountContiguousSlots (slot_header* First) -{ - Assert(First != 0); - - contiguous_slot_count_result Result = {}; - Result.Count = 1; - - slot_header* IterPrev = First; - slot_header* Iter = First->Next; - while (Iter && SlotsAreContiguous(IterPrev, Iter)) - { - Result.Count++; - IterPrev = Iter; - Iter = Iter->Next; - } - - Result.LastContiguousSlot = IterPrev; - return Result; -} - -static slot_header* -GetSlotAtOffset(slot_header* First, s32 Offset) -{ - slot_header* Iter = First; - s32 Count = 0; - while (Count < Offset && Iter) - { - Iter = Iter->Next; - Count++; - } - return Iter; -} - -static slot_header* -InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) -{ - slot_header* List = ListStart; - if (NewSlot < List) - { - NewSlot->Next = List; - List = NewSlot; - } - else - { - slot_header* PrevIter = List; - slot_header* Iter = List->Next; - while (Iter && NewSlot > Iter) - { - PrevIter = Iter; - Iter = Iter->Next; - } - - Assert(PrevIter); - if (PrevIter) - { - PrevIter->Next = NewSlot; - } - - if (Iter) - { - NewSlot->Next = Iter; - } - } - return List; -} - -static void -AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) -{ - s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); - slot_header* Slot = Storage->FreeList; - slot_header* PrevSlot = 0; - while (Slot) - { - contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); - if (ContiguousSlots.Count >= SlotCount) - { - slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); - if (PrevSlot) - { - PrevSlot->Next = NextStartSlot; - } - else - { - Storage->FreeList = NextStartSlot; - } - break; - } - else - { - PrevSlot = Slot; - Slot = Slot->Next; - } - } - - if (Slot) - { - String->Memory = (char*)Slot; - GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); - String->Max = SlotCount * Storage->SlotSize; - String->Length = 0; - } -} - -static string -AllocStringFromStringArena (s32 Size, slot_arena* Storage) -{ - string Result = {0}; - AllocStringFromStringArena(&Result, Size, Storage); - return Result; -} - -static void -FreeToStringArena (string* String, slot_arena* Storage) -{ - u8* Base = (u8*)(String->Memory); - u8* End = Base + String->Max - 1; - u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); - Assert((Base >= Storage->Memory) && (End < MemoryEnd)); - Assert((String->Max % Storage->SlotSize) == 0); - - s32 SizeReclaimed = 0; - slot_header* Slot = (slot_header*)Base; - while (SizeReclaimed < String->Max) - { - Slot->Size = Storage->SlotSize; - Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); - SizeReclaimed += Storage->SlotSize; - Slot = (slot_header*)(Base + SizeReclaimed); - } - - String->Memory = 0; - String->Length = 0; - String->Max = 0; -} - -static void -ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) -{ - string NewString = AllocStringFromStringArena(NewSize, Storage); - CopyStringTo(*String, &NewString); - FreeToStringArena(String, Storage); - *String = NewString; -} - -#if defined(DEBUG) - -void DEBUGPrintChars (string* String, s32 Count) -{ - char* Iter = String->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = (char)('A' + i); - } - String->Length = Count; -} - -#ifdef DEBUG_GS_STRING - -#include - -static void -TestStrings() -{ - - slot_arena StringArena = {}; - - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); - - //////////////////////////////////////////////////////////////// - // Char Functions - - char ForwardArray[] = "Hello, Sailor"; - char BackwardArray[] = "roliaS ,olleH"; - TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); - TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); - - TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); - TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); - TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); - TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); - - ReverseCharArray(ForwardArray, 13); - TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); - - char UIntString[] = "1234"; - u32 UIntValue = 1234; - u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); - TestClean((ParsedUInt == UIntValue), "String To U32"); - char StringifiedUInt[4] = {}; - UIntToString(UIntValue, StringifiedUInt, 4); - TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); - - char IntString[] = "-1234"; - s32 IntValue = -1234; - s32 ParsedInt = ParseSignedInt(IntString, 5); - TestClean((ParsedInt == IntValue), "String To S32"); - char StringifiedInt[5] = {}; - IntToString(IntValue, StringifiedInt, 5); - TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); - - char FloatString[] = "-1234.125"; - float FloatValue = -1234.125f; - float ParsedFloat = ParseFloat(FloatString, 8); - TestClean((ParsedFloat == FloatValue), "String To Float"); - char StringifiedFloat[10] = {}; - FloatToString(FloatValue, StringifiedFloat, 10, 3); - TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); - - - //////////////////////////////////////////////////////////////// - // - - StringArena.SlotSize = 256; - StringArena.SlotCount = 32; - StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); - slot_header* PrevSlotHeader = 0; - for (int i = StringArena.SlotCount - 1; i >= 0; i--) - { - u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); - slot_header* SlotHeader = (slot_header*)SlotBase; - SlotHeader->Size = StringArena.SlotSize; - SlotHeader->Next = PrevSlotHeader; - - // TEST(peter): Should be true always, except on the first iteration, when there is no next slot - bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); - TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); - - PrevSlotHeader = SlotHeader; - } - StringArena.FreeList = PrevSlotHeader; - - // TEST(peter): Count Should equal StringArena.SlotCount - s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; - TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); - - // TEST(peter): Should be false - bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); - Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); - TestClean(!Contiguity, "Non Contiguous Arenas"); - - s32 Slots = CalculateSlotCountFromSize(10, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(256, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(345, 256); - TestClean(Slots == 2, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(1024, 256); - TestClean(Slots == 4, "Slot Sizing"); - - slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); - slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); - slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); - - string StringA = AllocStringFromStringArena(10, &StringArena); - string StringB = AllocStringFromStringArena(345, &StringArena); - -#if 0 - // TEST(peter): Should TestClean - u8* RandomMemory = (u8*)malloc(256); - string RandomMemString = {}; - RandomMemString.Memory = (char*)RandomMemory; - RandomMemString.Max = 256; - FreeToStringArena(&RandomMemString, &StringArena); -#endif - FreeToStringArena(&StringA, &StringArena); - FreeToStringArena(&StringB, &StringArena); - // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal - s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; - TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); - - // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately - // sized block - // The slots will look list [256][used][256][256][256] etc.. - StringA = AllocStringFromStringArena(256, &StringArena); - StringB = AllocStringFromStringArena(256, &StringArena); - FreeToStringArena(&StringA, &StringArena); - u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; - string StringC = AllocStringFromStringArena(512, &StringArena); - slot_header* HeaderC = (slot_header*)(StringC.Memory); - - string ReallocTestString = AllocStringFromStringArena(256, &StringArena); - DEBUGPrintChars(&ReallocTestString, 24); - ReallocFromStringArena(&ReallocTestString, 512, &StringArena); - - - string TestString = AllocStringFromStringArena(10, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 20, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 10, &StringArena); - FreeToStringArena(&TestString, &StringArena); - - string EqualityStringA = AllocStringFromStringArena(345, &StringArena); - string EqualityStringB = AllocStringFromStringArena(415, &StringArena); - // Equality should succeed despite length differences - string EqualityStringC = AllocStringFromStringArena(256, &StringArena); - string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail - string EqualityStringEmpty = {}; - - DEBUGPrintChars(&EqualityStringA, 24); - DEBUGPrintChars(&EqualityStringB, 24); - DEBUGPrintChars(&EqualityStringC, 24); - DEBUGPrintChars(&EqualityStringD, 12); - - bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed - bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed - bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail - bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail - - TestClean(ABEquality, "String Equality"); - TestClean(ACEquality, "String Equality"); - TestClean(!ADEquality, "String Equality"); - TestClean(!AEEquality, "String Equality"); - - string CatStringA = AllocStringFromStringArena(256, &StringArena); - SetStringToCharArray(&CatStringA, "Hello "); - string CatStringB = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringB, "Sailor!"); - string CatStringResult = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringResult, "Hello Sailor!"); - ConcatString(&CatStringA, CatStringB); - TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); - - s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); - TestClean(FirstSpaceIndex == 5, "First Index"); - - SetStringToChar(&CatStringB, 'B', 5); - TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); - - - DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); -} -#endif // DEBUG_GS_STRING - -#endif // DEBUG - -#define GS_STRING_H -#endif // GS_STRING_H \ No newline at end of file diff --git a/src/gs_vector_matrix.h b/src/gs_vector_matrix.h deleted file mode 100644 index 6e9ec29..0000000 --- a/src/gs_vector_matrix.h +++ /dev/null @@ -1,1466 +0,0 @@ -#ifndef GS_VECTOR_MATRIX_H - -#ifndef GS_LANGUAGE_H - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) - -#include -#include -#include - -static r32 GSCos (r32 Theta) { return sin(Theta); } -static r32 GSSin (r32 Theta) { return cos(Theta); } - -static r32 GSSqrt(r32 V) -{ - r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; -} - -#else // Linux and MacOS -#include - -#endif // Platforms - -#endif // GS_LANGUAGE_H -////////////////////////////////////// -// VECTOR -///////////////////////////////////// - -union v2 -{ - struct - { - r32 x, y; - }; - r32 E[2]; -}; - -union v3 -{ - struct - { - r32 x, y, z; - }; - - struct - { - r32 R, G, B; - }; - - r32 E[3]; -}; - -union v4 -{ - struct - { - r32 x, y, z, w; - }; - - struct - { - r32 r, g, b, a; - }; - - r32 E[4]; -}; - -#define WhiteV4 v4{1, 1, 1, 1} -#define BlackV4 v4{0, 0, 0, 1} -#define RedV4 v4{1, 0, 0, 1} -#define GreenV4 v4{0, 1, 0, 1} -#define BlueV4 v4{0, 0, 1, 1} -#define YellowV4 v4{1, 1, 0, 1} -#define TealV4 v4{0, 1, 1, 1} -#define PinkV4 v4{1, 0, 1, 1} - -////////////////////////////////////// -// MATRIX -///////////////////////////////////// - -union m33 -{ - struct - { - float a, b, c; - float d, e, f; - float g, h, i; - }; - float E[9]; -}; - -union m44 -{ - struct - { - float a, b, c, d; - float e, f, g, h; - float i, j, k, l; - float m, n, o, p; - }; - float E[16]; -}; - -////////////////////////////////////// -// RECT -///////////////////////////////////// - -struct rect -{ - v2 Min; - v2 Max; -}; - - -////////////////////////////////////// -// VECTOR -////////////////////////////////////// - - -// -// -// Operators -// -// - -v2 V2 (v3 V) -{ - return v2{V.x, V.y}; -} - -v3 V3 (v2 XY, r32 Z) -{ - return v3{XY.x, XY.y, Z}; -} - -v3 V3 (v4 V) -{ - return v3{V.x, V.y, V.z}; -} - -v4 V4 (v3 XYZ, r32 W) -{ - return v4{XYZ.x, XYZ.y, XYZ.z, W}; -} - -v2 operator- (v2 A) -{ - v2 Result; - - Result.x = -A.x; - Result.y = -A.y; - - return Result; -} - -v3 operator- (v3 A) -{ - v3 Result; - - Result.x = -A.x; - Result.y = -A.y; - Result.z = -A.z; - - return Result; -} - -v4 operator- (v4 A) -{ - v4 Result; - - Result.x = -A.x; - Result.y = -A.y; - Result.z = -A.z; - Result.w = -A.w; - - return Result; -} - -#define V2OpV2Def(op) v2 operator##op (v2 A, v2 B) { return v2{ A.x op B.x, A.y op B.y };} -#define V3OpV3Def(op) v3 operator##op (v3 A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };} -#define V4OpV4Def(op) v4 operator##op (v4 A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };} -V2OpV2Def(+) -V2OpV2Def(-) -V2OpV2Def(/) -V2OpV2Def(*) -V3OpV3Def(+) -V3OpV3Def(-) -V3OpV3Def(/) -V3OpV3Def(*) -V4OpV4Def(+) -V4OpV4Def(-) -V4OpV4Def(/) -V4OpV4Def(*) -#undef V2OpV2Def -#undef V3OpV3Def -#undef V4OpV4Def - -#define V2RefOpV2Def(op) v2 operator##op (v2& A, v2 B) { return v2{ A.x op B.x, A.y op B.y };} -#define V3RefOpV3Def(op) v3 operator##op (v3& A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };} -#define V4RefOpScalarDef(op) v4 operator##op (v4& A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };} -V2RefOpV2Def(+=) -V2RefOpV2Def(-=) -V3RefOpV3Def(+=) -V3RefOpV3Def(-=) -V4RefOpScalarDef(+=) -V4RefOpScalarDef(-=) -#undef V2RefOpV2Def -#undef V3RefOpV3Def -#undef V4RefOpV4Def - -#define V2OpScalarDef(op) v2 operator##op (v2 A, r32 B) { return v2{ A.x op B, A.y op B };} -#define V3OpScalarDef(op) v3 operator##op (v3 A, r32 B) { return v3{ A.x op B, A.y op B, A.z op B };} -#define V4OpScalarDef(op) v4 operator##op (v4 A, r32 B) { return v4{ A.x op B, A.y op B, A.z op B, A.w op B };} -V2OpScalarDef(*) -V2OpScalarDef(/) -V3OpScalarDef(*) -V3OpScalarDef(/) -V4OpScalarDef(*) -V4OpScalarDef(/) -#undef V2POpScalarDef -#undef V3POpScalarDef -#undef V4POpScalarDef - - -#define V2POpScalarDef(op) v2 operator##op (v2& A, r32 B) { return v2{ A->x op B, A->y op B };} -#define V3POpScalarDef(op) v3 operator##op (v3& A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };} -#define V4POpScalarDef(op) v4 operator##op (v4& A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };} -V2OpScalarDef(*=) -V2OpScalarDef(/=) -V3OpScalarDef(*=) -V3OpScalarDef(/=) -V4OpScalarDef(*=) -V4OpScalarDef(/=) -#undef V2POpScalarDef -#undef V3POpScalarDef -#undef V4POpScalarDef - -bool operator== (v2 A, v2 B) -{ - b32 Result = true; - for (s32 i = 0; i < 2; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - - -bool operator== (v3 A, v3 B) -{ - b32 Result = true; - for (s32 i = 0; i < 3; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - -bool operator== (v4 A, v4 B) -{ - b32 Result = true; - for (s32 i = 0; i < 4; i++) - { - if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } - } - return Result; -} - -// -// Operations -// - -static v3 -ToV3(v4 V) -{ - v3 R = {}; - R.x = V.x; - R.y = V.y; - R.z = V.z; - return R; -} - -static v4 -ToV4(v3 V, r32 W) -{ - v4 R = {}; - R.x = V.x; - R.y = V.y; - R.z = V.z; - R.w = W; - return R; -} - -inline r32 -MagSqr( -v2 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y); - return Result; -} - -inline r32 -MagSqr( -v3 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y) + (_A.z * _A.z); - return Result; -} - -inline r32 -MagSqr( -v4 _A -) -{ - r32 Result = (_A.x * _A.x) + (_A.y * _A.y) + (_A.z * _A.z) + (_A.w * _A.w); - return Result; -} - -#define MagDef(type) inline r32 Mag(type A) { r32 Result = MagSqr(A); return GSSqrt(Result); } -MagDef(v2) -MagDef(v3) -MagDef(v4) -#undef MagDef - -#define DistanceDef(type) inline r32 Distance (type A, type B) { type Diff = A - B; return Mag(Diff); } -DistanceDef(v2) -DistanceDef(v3) -DistanceDef(v4) -#undef DistanceDef - -#define DistanceSqDef(type) inline r32 DistanceSq (type A, type B) { type Diff = A - B; return MagSqr(Diff); } -DistanceSqDef(v2) -DistanceSqDef(v3) -DistanceSqDef(v4) -#undef DistanceSqDef - -inline v2 -Normalize( -v2 _A -) -{ - v2 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - - return Result; -} - -inline v3 -Normalize( -v3 _A -) -{ - v3 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - Result.z = _A.z / Magnitude; - - return Result; -} - -inline v4 -Normalize( -v4 _A -) -{ - v4 Result; - - r32 Magnitude = Mag(_A); - - Result.x = _A.x / Magnitude; - Result.y = _A.y / Magnitude; - Result.z = _A.z / Magnitude; - Result.w = _A.w / Magnitude; - - return Result; -} - -inline r32 -Dot( -v2 _A, -v2 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y; - return Result; -} - -inline r32 -Dot ( -v3 _A, -v3 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y + _A.z * _B.z; - return Result; -} - -inline r32 -Dot ( -v4 _A, -v4 _B -) -{ - r32 Result = _A.x * _B.x + _A.y * _B.y + _A.z * _B.z + _A.w * _B.w; - return Result; -} - -inline v2 -PerpendicularCW (v2 A) -{ - v2 Result = v2{A.y, -A.x}; - return Result; -} - -inline v2 -PerpendicularCCW (v2 A) -{ - v2 Result = v2{A.y, A.x}; - return Result; -} - -inline v3 -Cross( -v3 _A, -v3 _B -) -{ - v3 Result = {}; - - Result.x = (_A.y * _B.z) - (_A.z * _B.y); - Result.y = (_A.z * _B.x) - (_A.x * _B.z); - Result.z = (_A.x * _B.y) - (_A.y * _B.x); - - return Result; -} - -inline v4 -Cross( -v4 _A, -v4 _B -) -{ - v4 Result = {}; - - Result.x = (_A.y * _B.z) - (_A.z * _B.y); - Result.y = (_A.z * _B.x) - (_A.x * _B.z); - Result.z = (_A.x * _B.y) - (_A.y * _B.x); - Result.w = 0; - - return Result; -} - -inline v2 -ClampVector01 (v2 V) -{ - v2 Result = {}; - Result.x = GSClamp(0.0f, V.x, 1.f); - Result.y = GSClamp(0.0f, V.y, 1.f); - return Result; -} - -inline v3 -ClampVector01 (v3 V) -{ - v3 Result = {}; - Result.x = GSClamp(0.f, V.x, 1.f); - Result.y = GSClamp(0.f, V.y, 1.f); - Result.z = GSClamp(0.f, V.z, 1.f); - return Result; -} - -inline v4 -ClampVector01 (v4 V) -{ - v4 Result = {}; - Result.x = GSClamp(0.f, V.x, 1.f); - Result.y = GSClamp(0.f, V.y, 1.f); - Result.z = GSClamp(0.f, V.z, 1.f); - Result.w = GSClamp(0.f, V.w, 1.f); - return Result; -} - -inline v2 -Lerp( -v2 _A, -v2 _B, -r32 _Percent -) -{ - v2 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - - return Result; -} - -inline v3 -Lerp( -v3 _A, -v3 _B, -r32 _Percent -) -{ - v3 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - Result.z = GSLerp(_A.z, _B.z, _Percent); - - return Result; -} - -inline v4 -Lerp( -v4 _A, -v4 _B, -r32 _Percent -) -{ - v4 Result; - - Result.x = GSLerp(_A.x, _B.x, _Percent); - Result.y = GSLerp(_A.y, _B.y, _Percent); - Result.z = GSLerp(_A.z, _B.z, _Percent); - Result.w = GSLerp(_A.w, _B.w, _Percent); - - return Result; -} - -v4 HSVToRGB (v4 In) -{ - r32 Hue = In.x; - while (Hue > 360.0f) { Hue -= 360.0f; } - while (Hue < 0.0f) { Hue += 360.0f; } - - r32 Sat = In.y; - r32 Value = In.z; - - r32 hh, p, q, t, ff; - long i; - v4 Result = {}; - Result.a = In.a; - - if(Sat <= 0.0f) { // < is bogus, just shuts up warnings - Result.r = Value; - Result.g = Value; - Result.b = Value; - return Result; - } - hh = Hue; - if(hh >= 360.0f) hh = 0.0f; - hh /= 60.0f; - i = (long)hh; - ff = hh - i; - p = Value * (1.0f - Sat); - q = Value * (1.0f - (Sat * ff)); - t = Value * (1.0f - (Sat * (1.0f - ff))); - - switch(i) { - case 0: - {Result.r = Value; - Result.g = t; - Result.b = p; - }break; - - case 1: - { - Result.r = q; - Result.g = Value; - Result.b = p; - }break; - - case 2: - { - Result.r = p; - Result.g = Value; - Result.b = t; - }break; - - case 3: - { - Result.r = p; - Result.g = q; - Result.b = Value; - }break; - - case 4: - { - Result.r = t; - Result.g = p; - Result.b = Value; - }break; - - case 5: - default: - { - Result.r = Value; - Result.g = p; - Result.b = q; - }break; - } - - return Result; -} - -static bool -PointIsInRange ( -v2 _P, -v2 _Min, v2 _Max -) -{ - return (_P.x >= _Min.x && _P.x <= _Max.x && - _P.y >= _Min.y && _P.y <= _Max.y); -} - -static bool -PointIsInRangeSafe ( -v2 _P, -v2 _Min, v2 _Max -) -{ - s32 MinX = GSMin(_Min.x, _Max.x); - s32 MinY = GSMin(_Min.y, _Max.y); - s32 MaxX = GSMax(_Min.x, _Max.x); - s32 MaxY = GSMax(_Min.y, _Max.y); - - return (_P.x >= MinX && _P.x <= MaxX && - _P.y >= MinY && _P.y <= MaxY); -} - -inline v2 -PointToPercentRange (v2 P, v2 Min, v2 Max) -{ - v2 Result = {}; - - Result.x = GSClamp(0.f, (P.x - Min.x) / (Max.x - Min.x), 1.f); - Result.y = GSClamp(0.f, (P.y - Min.y) / (Max.y - Min.y), 1.f); - - return Result; -} - -////////////////////////////////////// -// RECT -////////////////////////////////////// - -inline r32 -Width (rect Rect) -{ - s32 Result = Rect.Max.x - Rect.Min.x; - return Result; -} - -inline r32 -Height (rect Rect) -{ - s32 Result = Rect.Max.y - Rect.Min.y; - return Result; -} - -inline v2 -CalculateRectCenter (rect Rect) -{ - v2 Result = (Rect.Min + Rect.Max) / 2.0f; - return Result; -} - -inline b32 -PointIsInRect (v2 Point, rect Rect) -{ - b32 Result = ((Point.x >= Rect.Min.x && Point.x <= Rect.Max.x) && - (Point.y >= Rect.Min.y && Point.y <= Rect.Max.y)); - return Result; -} - -////////////////////////////////////// -// MATRIX -////////////////////////////////////// - -static m33 -M33(r32 a, r32 b, r32 c, - r32 d, r32 e, r32 f, - r32 g, r32 h, r32 i) -{ - m33 M = {}; - M.a = a; M.b = b; M.c = c; - M.d = d; M.e = e; M.f = f; - M.g = g; M.h = h; M.i = i; - return M; -} - -static m44 -M44(r32 a, r32 b, r32 c, r32 d, - r32 e, r32 f, r32 g, r32 h, - r32 i, r32 j, r32 k, r32 l, - r32 m, r32 n, r32 o, r32 p) -{ - m44 M = {}; - M.a = a; M.b = b; M.c = c; M.d = d; - M.e = e; M.f = f; M.g = g; M.h = h; - M.i = i; M.j = j; M.k = k; M.l = l; - M.m = m; M.n = n; M.o = o; M.p = p; - return M; -} - -static m33 -M33Empty () -{ - m33 M = {}; - M.a = 0; M.b = 0; M.c = 0; - M.d = 0; M.e = 0; M.f = 0; - M.g = 0; M.h = 0; M.i = 0; - return M; -} - -static m44 -M44Empty() -{ - m44 M = {}; - M.a = 0; M.b = 0; M.c = 0; M.d = 0; - M.e = 0; M.f = 0; M.g = 0; M.h = 0; - M.i = 0; M.j = 0; M.k = 0; M.l = 0; - M.m = 0; M.n = 0; M.o = 0; M.p = 0; - return M; -} - -static m33 -M33Identity () -{ - m33 M = {}; - M.a = 1; M.b = 0; M.c = 0; - M.d = 0; M.e = 1; M.f = 0; - M.g = 0; M.h = 0; M.i = 1; - return M; -} - -static m44 -M44Identity() -{ - m44 M = {}; - M.a = 1; M.b = 0; M.c = 0; M.d = 0; - M.e = 0; M.f = 1; M.g = 0; M.h = 0; - M.i = 0; M.j = 0; M.k = 1; M.l = 0; - M.m = 0; M.n = 0; M.o = 0; M.p = 1; - return M; -} - -static m44 -GetXRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - 1, 0, 0, 0, - 0, CosAngle, SinAngle, 0, - 0, -SinAngle, CosAngle, 0, - 0, 0, 0, 1 - }; - return M; -} - - -static m44 -GetYRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - CosAngle, 0, -SinAngle, 0, - 0, 1, 0, 0, - SinAngle, 0, CosAngle, 0, - 0, 0, 0, 1 - }; - return M; -} - -static m44 -GetZRotation (r32 Angle) -{ - r32 CosAngle = GSCos(Angle); - r32 SinAngle = GSSin(Angle); - m44 M = { - CosAngle, SinAngle, 0, 0, - -SinAngle, CosAngle, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - return M; -} - - -static m33 -Transpose (m33 M) -{ - m33 Result = {}; - - for (s32 x = 0; x < 3; x++) - { - for (s32 y = 0; y < 3; y++) - { - Result.E[x + (y * 3)] = M.E[y + (x * 3)]; - } - } - - return Result; -} - -inline m44 -Transpose (m44 M) -{ - DEBUG_TRACK_SCOPE(Transpose); - - m44 Result = {}; - - Result.E[0] = M.E[0]; - Result.E[1] = M.E[4]; - Result.E[2] = M.E[8]; - Result.E[3] = M.E[12]; - - Result.E[4] = M.E[1]; - Result.E[5] = M.E[5]; - Result.E[6] = M.E[9]; - Result.E[7] = M.E[13]; - - Result.E[8] = M.E[2]; - Result.E[9] = M.E[6]; - Result.E[10] = M.E[10]; - Result.E[11] = M.E[14]; - - Result.E[12] = M.E[3]; - Result.E[13] = M.E[7]; - Result.E[14] = M.E[11]; - Result.E[15] = M.E[15]; - - return Result; -} - -static m44 -GetPositionM44 (v4 Position) -{ -#if 1 - return m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - Position.x, Position.y, Position.z, Position.w - }; -#else - return m44{ - 1, 0, 0, Position.x, - 0, 1, 0, Position.y, - 0, 0, 1, Position.z, - 0, 0, 0, Position.w}; -#endif -} - -static m44 -GetLookAtMatrix (v4 Position, v4 Target) -{ - // Forward - v4 Forward = Normalize(Target - Position); - // Right - v4 Right = Normalize(Cross(v4{0, 1, 0, 0}, Forward)); - // Up - v4 Up = Normalize(Cross(Forward, Right)); - - m44 RotationMatrix = M44( - Right.x, Up.x, Forward.x, 0, - Right.y, Up.y, Forward.y, 0, - Right.z, Up.z, Forward.z, 0, - 0, 0, 0, 1); - - return RotationMatrix; -} - -b32 operator== (m33 A, m33 B) -{ - b32 Result = true; - for (int e = 0; e < 9; e++) { if (GSAbs(A.E[e] - B.E[e]) > 0.0001f) { Result = false; break; } } - return Result; -} - -b32 operator== (m44 A, m44 B) -{ - b32 Result = true; - for (int e = 0; e < 16; e++) { if (GSAbs(A.E[e] - B.E[e]) > 0.0001f) { Result = false; break; } } - return Result; -} - -m33 operator+ (m33 A, m33 B) -{ - m33 M = {}; - for (int e = 0; e < 9; e++) { M.E[e] = A.E[e] + B.E[e]; } - return M; -} - -m44 operator+ (m44 A, m44 B) -{ - m44 M = {}; - for (int e = 0; e < 16; e++) { M.E[e] = A.E[e] + B.E[e]; } - return M; -} - -m33 operator- (m33 A, m33 B) -{ - m33 M = {}; - for (int e = 0; e < 9; e++) { M.E[e] = A.E[e] - B.E[e]; } - return M; -} - -m44 operator- (m44 A, m44 B) -{ - m44 M = {}; - for (int e = 0; e < 16; e++) { M.E[e] = A.E[e] - B.E[e]; } - return M; -} - -m33 operator* (m33 A, m33 B) -{ - m33 M = {}; - for (int rx = 0; rx < 3; rx++) - { - for (int ry = 0; ry < 3; ry++) - { - int RIndex = (ry * 3) + rx; - M.E[RIndex] = 0; - for (int i = 0; i < 3; i++) - { - M.E[RIndex] += B.E[(ry * 3) + i] * A.E[(i * 3) + rx]; - } - } - } - return M; -} - -m44 operator* (m44 A, m44 B) -{ - m44 M = {}; - - r32 A00=A.E[0+4*0]; - r32 A01=A.E[0+4*1]; - r32 A02=A.E[0+4*2]; - r32 A03=A.E[0+4*3]; - - r32 A10=A.E[1+4*0]; - r32 A11=A.E[1+4*1]; - r32 A12=A.E[1+4*2]; - r32 A13=A.E[1+4*3]; - - r32 A20=A.E[2+4*0]; - r32 A21=A.E[2+4*1]; - r32 A22=A.E[2+4*2]; - r32 A23=A.E[2+4*3]; - - r32 A30=A.E[3+4*0]; - r32 A31=A.E[3+4*1]; - r32 A32=A.E[3+4*2]; - r32 A33=A.E[3+4*3]; - - r32 B00=B.E[0+4*0]; - r32 B01=B.E[0+4*1]; - r32 B02=B.E[0+4*2]; - r32 B03=B.E[0+4*3]; - - r32 B10=B.E[1+4*0]; - r32 B11=B.E[1+4*1]; - r32 B12=B.E[1+4*2]; - r32 B13=B.E[1+4*3]; - - r32 B20=B.E[2+4*0]; - r32 B21=B.E[2+4*1]; - r32 B22=B.E[2+4*2]; - r32 B23=B.E[2+4*3]; - - r32 B30=B.E[3+4*0]; - r32 B31=B.E[3+4*1]; - r32 B32=B.E[3+4*2]; - r32 B33=B.E[3+4*3]; - - M.E[0+4*0] = A00*B00+A10*B01+A20*B02+A30*B03; - M.E[0+4*1] = A01*B00+A11*B01+A21*B02+A31*B03; - M.E[0+4*2] = A02*B00+A12*B01+A22*B02+A32*B03; - M.E[0+4*3] = A03*B00+A13*B01+A23*B02+A33*B03; - - M.E[1+4*0] = A00*B10+A10*B11+A20*B12+A30*B13; - M.E[1+4*1] = A01*B10+A11*B11+A21*B12+A31*B13; - M.E[1+4*2] = A02*B10+A12*B11+A22*B12+A32*B13; - M.E[1+4*3] = A03*B10+A13*B11+A23*B12+A33*B13; - - M.E[2+4*0] = A00*B20+A10*B21+A20*B22+A30*B23; - M.E[2+4*1] = A01*B20+A11*B21+A21*B22+A31*B23; - M.E[2+4*2] = A02*B20+A12*B21+A22*B22+A32*B23; - M.E[2+4*3] = A03*B20+A13*B21+A23*B22+A33*B23; - - M.E[3+4*0] = A00*B30+A10*B31+A20*B32+A30*B33; - M.E[3+4*1] = A01*B30+A11*B31+A21*B32+A31*B33; - M.E[3+4*2] = A02*B30+A12*B31+A22*B32+A32*B33; - M.E[3+4*3] = A03*B30+A13*B31+A23*B32+A33*B33; - - return M; -} - -v3 operator* (m33 M, v3 V) -{ - v3 Result = {}; - int i = 0; - for (int y = 0; y < 3; y++) - { - Result.E[y] = 0; - for (int x = 0; x < 3; x++) - { - Result.E[y] += M.E[(y * 3) + x] * V.E[x]; - } - } - return Result; -} - -v4 operator* (m44 M, v4 V) -{ - v4 Result = {}; -#if 1 - Result.x = V.x*M.a + V.y*M.e + V.z*M.i + V.w*M.m; - Result.y = V.x*M.b + V.y*M.f + V.z*M.j + V.w*M.n; - Result.z = V.x*M.c + V.y*M.g + V.z*M.k + V.w*M.o; - Result.w = V.x*M.d + V.y*M.h + V.z*M.l + V.w*M.p; -#else - for (int y = 0; y < 4; y++) - { - Result.E[y] = 0; - for (int x = 0; x < 4; x++) - { - Result.E[y] += M.E[(y * 4) + x] * V.E[x]; - } - } -#endif - return Result; -} - -b32 Inverse(m44 M_In, m44* M_Out) -{ - b32 Result = false; - - r32 det; - s32 i; - - - M_Out->E[0] = M_In.E[5] * M_In.E[10] * M_In.E[15] - - M_In.E[5] * M_In.E[11] * M_In.E[14] - - M_In.E[9] * M_In.E[6] * M_In.E[15] + - M_In.E[9] * M_In.E[7] * M_In.E[14] + - M_In.E[13] * M_In.E[6] * M_In.E[11] - - M_In.E[13] * M_In.E[7] * M_In.E[10]; - - M_Out->E[4] = -M_In.E[4] * M_In.E[10] * M_In.E[15] + - M_In.E[4] * M_In.E[11] * M_In.E[14] + - M_In.E[8] * M_In.E[6] * M_In.E[15] - - M_In.E[8] * M_In.E[7] * M_In.E[14] - - M_In.E[12] * M_In.E[6] * M_In.E[11] + - M_In.E[12] * M_In.E[7] * M_In.E[10]; - - M_Out->E[8] = M_In.E[4] * M_In.E[9] * M_In.E[15] - - M_In.E[4] * M_In.E[11] * M_In.E[13] - - M_In.E[8] * M_In.E[5] * M_In.E[15] + - M_In.E[8] * M_In.E[7] * M_In.E[13] + - M_In.E[12] * M_In.E[5] * M_In.E[11] - - M_In.E[12] * M_In.E[7] * M_In.E[9]; - - M_Out->E[12] = -M_In.E[4] * M_In.E[9] * M_In.E[14] + - M_In.E[4] * M_In.E[10] * M_In.E[13] + - M_In.E[8] * M_In.E[5] * M_In.E[14] - - M_In.E[8] * M_In.E[6] * M_In.E[13] - - M_In.E[12] * M_In.E[5] * M_In.E[10] + - M_In.E[12] * M_In.E[6] * M_In.E[9]; - - M_Out->E[1] = -M_In.E[1] * M_In.E[10] * M_In.E[15] + - M_In.E[1] * M_In.E[11] * M_In.E[14] + - M_In.E[9] * M_In.E[2] * M_In.E[15] - - M_In.E[9] * M_In.E[3] * M_In.E[14] - - M_In.E[13] * M_In.E[2] * M_In.E[11] + - M_In.E[13] * M_In.E[3] * M_In.E[10]; - - M_Out->E[5] = M_In.E[0] * M_In.E[10] * M_In.E[15] - - M_In.E[0] * M_In.E[11] * M_In.E[14] - - M_In.E[8] * M_In.E[2] * M_In.E[15] + - M_In.E[8] * M_In.E[3] * M_In.E[14] + - M_In.E[12] * M_In.E[2] * M_In.E[11] - - M_In.E[12] * M_In.E[3] * M_In.E[10]; - - M_Out->E[9] = -M_In.E[0] * M_In.E[9] * M_In.E[15] + - M_In.E[0] * M_In.E[11] * M_In.E[13] + - M_In.E[8] * M_In.E[1] * M_In.E[15] - - M_In.E[8] * M_In.E[3] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[11] + - M_In.E[12] * M_In.E[3] * M_In.E[9]; - - M_Out->E[13] = M_In.E[0] * M_In.E[9] * M_In.E[14] - - M_In.E[0] * M_In.E[10] * M_In.E[13] - - M_In.E[8] * M_In.E[1] * M_In.E[14] + - M_In.E[8] * M_In.E[2] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[10] - - M_In.E[12] * M_In.E[2] * M_In.E[9]; - - M_Out->E[2] = M_In.E[1] * M_In.E[6] * M_In.E[15] - - M_In.E[1] * M_In.E[7] * M_In.E[14] - - M_In.E[5] * M_In.E[2] * M_In.E[15] + - M_In.E[5] * M_In.E[3] * M_In.E[14] + - M_In.E[13] * M_In.E[2] * M_In.E[7] - - M_In.E[13] * M_In.E[3] * M_In.E[6]; - - M_Out->E[6] = -M_In.E[0] * M_In.E[6] * M_In.E[15] + - M_In.E[0] * M_In.E[7] * M_In.E[14] + - M_In.E[4] * M_In.E[2] * M_In.E[15] - - M_In.E[4] * M_In.E[3] * M_In.E[14] - - M_In.E[12] * M_In.E[2] * M_In.E[7] + - M_In.E[12] * M_In.E[3] * M_In.E[6]; - - M_Out->E[10] = M_In.E[0] * M_In.E[5] * M_In.E[15] - - M_In.E[0] * M_In.E[7] * M_In.E[13] - - M_In.E[4] * M_In.E[1] * M_In.E[15] + - M_In.E[4] * M_In.E[3] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[7] - - M_In.E[12] * M_In.E[3] * M_In.E[5]; - - M_Out->E[14] = -M_In.E[0] * M_In.E[5] * M_In.E[14] + - M_In.E[0] * M_In.E[6] * M_In.E[13] + - M_In.E[4] * M_In.E[1] * M_In.E[14] - - M_In.E[4] * M_In.E[2] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[6] + - M_In.E[12] * M_In.E[2] * M_In.E[5]; - - M_Out->E[3] = -M_In.E[1] * M_In.E[6] * M_In.E[11] + - M_In.E[1] * M_In.E[7] * M_In.E[10] + - M_In.E[5] * M_In.E[2] * M_In.E[11] - - M_In.E[5] * M_In.E[3] * M_In.E[10] - - M_In.E[9] * M_In.E[2] * M_In.E[7] + - M_In.E[9] * M_In.E[3] * M_In.E[6]; - - M_Out->E[7] = M_In.E[0] * M_In.E[6] * M_In.E[11] - - M_In.E[0] * M_In.E[7] * M_In.E[10] - - M_In.E[4] * M_In.E[2] * M_In.E[11] + - M_In.E[4] * M_In.E[3] * M_In.E[10] + - M_In.E[8] * M_In.E[2] * M_In.E[7] - - M_In.E[8] * M_In.E[3] * M_In.E[6]; - - M_Out->E[11] = -M_In.E[0] * M_In.E[5] * M_In.E[11] + - M_In.E[0] * M_In.E[7] * M_In.E[9] + - M_In.E[4] * M_In.E[1] * M_In.E[11] - - M_In.E[4] * M_In.E[3] * M_In.E[9] - - M_In.E[8] * M_In.E[1] * M_In.E[7] + - M_In.E[8] * M_In.E[3] * M_In.E[5]; - - M_Out->E[15] = M_In.E[0] * M_In.E[5] * M_In.E[10] - - M_In.E[0] * M_In.E[6] * M_In.E[9] - - M_In.E[4] * M_In.E[1] * M_In.E[10] + - M_In.E[4] * M_In.E[2] * M_In.E[9] + - M_In.E[8] * M_In.E[1] * M_In.E[6] - - M_In.E[8] * M_In.E[2] * M_In.E[5]; - - det = M_In.E[0] * M_Out->E[0] + M_In.E[1] * M_Out->E[4] + M_In.E[2] * M_Out->E[8] + M_In.E[3] * M_Out->E[12]; - - if (det == 0) - { - return false; - } - - det = 1.0 / det; - - for (i = 0; i < 16; i++) - { - M_Out->E[i] = M_Out->E[i] * det; - } - - return true; -} - -#if defined(VECTOR_MATRIX_TEST_SUITE) - -void TestVectorMatrixMultiplication () -{ - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Vector/Matrix\n\n\n"); - - // Utility Functions - TestClean((GSSqrt(4.f) == 2.f), "Vector Square Root"); - TestClean((GSLerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); - TestClean((GSMin(-.25f, 5.f) == -.25f), "Vector Min"); - TestClean((GSMax(-.25f, 5.f) == 5.f), "Vector Max"); - TestClean((GSClamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); - TestClean((GSClamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); - - ////////////////////////////// - // Vector Functions - ///////////////////////////// - - v2 V2Unit = v2{1, 0}; - v3 V3Unit = v3{1, 0, 0}; - v4 V4Unit = v4{1, 0, 0, 0}; - - v2 TestV2 = v2{1, 2}; - r32 TestV2MagSq = (TestV2.x * TestV2.x) + (TestV2.y * TestV2.y); - r32 TestV2Mag = GSSqrt(TestV2MagSq); - v2 TestV2Norm = v2{TestV2.x / TestV2Mag, TestV2.y / TestV2Mag}; - r32 TestV2DotR = (TestV2.x * V2Unit.x) + (TestV2.y * V2Unit.y); - - v3 TestV3 = v3{1, 2, 3}; - r32 TestV3MagSq = (TestV3.x * TestV3.x) + (TestV3.y * TestV3.y) + (TestV3.z * TestV3.z); - r32 TestV3Mag = GSSqrt(TestV3MagSq); - v3 TestV3Norm = v3{TestV3.x / TestV3Mag, TestV3.y / TestV3Mag, TestV3.z / TestV3Mag}; - r32 TestV3DotR = (TestV3.x * V3Unit.x) + (TestV3.y * V3Unit.y) + (TestV3.z * V3Unit.z); - - v4 TestV4 = v4{1, 2, 3, 4}; - r32 TestV4MagSq = (TestV4.x * TestV4.x) + (TestV4.y * TestV4.y) + (TestV4.z * TestV4.z) + (TestV4.w * TestV4.w); - r32 TestV4Mag = GSSqrt(TestV4MagSq); - v4 TestV4Norm = v4{ - TestV4.x / TestV4Mag, TestV4.y / TestV4Mag, TestV4.z / TestV4Mag, TestV4.w / TestV4Mag - }; - r32 TestV4DotR = (TestV4.x * V4Unit.x) + (TestV4.y * V4Unit.y) + (TestV4.z * V4Unit.z) + (TestV4.w * V4Unit.w); - - v2 DownCastV3 = V2(TestV3); - v3 DownCastV4 = V3(TestV4); - - v2 EqualityV2 = v2{TestV2.x, TestV2.y}; - v2 ZeroV2 = v2{0, 0}; - v3 EqualityV3 = v3{TestV3.x, TestV3.y, TestV3.z}; - v3 ZeroV3 = v3{0, 0, 0}; - v4 EqualityV4 = v4{TestV4.x, TestV4.y, TestV4.z, TestV4.w}; - v4 ZeroV4 = v4{0, 0, 0, 0}; - - TestClean((TestV2.x == 1 && TestV2.y == 2), "V2 Assignment"); - TestClean((TestV3.x == 1 && TestV3.y == 2 && TestV3.z == 3), "V3 Assignment"); - TestClean((TestV4.x == 1 && TestV4.y == 2 && TestV4.z == 3 && TestV4.w == 4), "V3 Assignment"); - - TestClean((DownCastV3.x == 1 && DownCastV3.y == 2), "V3 -> V2 Downcast"); - TestClean((DownCastV4.x == 1 && DownCastV4.y == 2 && DownCastV4.z == 3), "V4 -> V3 Downcast"); - - // Vector Operators - - TestClean((TestV2 == EqualityV2 && !(TestV2 == ZeroV2)), "V2 Equality"); - TestClean((TestV3 == EqualityV3 && !(TestV3 == ZeroV3)), "V3 Equality"); - TestClean((TestV4 == EqualityV4 && !(TestV4 == ZeroV4)), "V4 Equality"); - - TestClean(((TestV2 - TestV2) == ZeroV2), "V2 Subtraction"); - TestClean(((TestV3 - TestV3) == ZeroV3), "V3 Subtraction"); - TestClean(((TestV4 - TestV4) == ZeroV4), "V4 Subtraction"); - - TestClean(((TestV2 + TestV2) == v2{TestV2.x * 2, TestV2.y * 2}), "V2 Addition"); - TestClean(((TestV3 + TestV3) == v3{TestV3.x * 2, TestV3.y * 2, TestV3.z * 2}), "V3 Addition"); - TestClean(((TestV4 + TestV4) == v4{TestV4.x * 2, TestV4.y * 2, TestV4.z * 2, TestV4.w * 2}), "V4 Addition"); - - TestClean(((TestV2 * 2.0f) == v2{TestV2.x * 2, TestV2.y * 2}), "V2 Multiplication"); - TestClean(((TestV3 * 2.0f) == v3{TestV3.x * 2, TestV3.y * 2, TestV3.z * 2}), "V3 Multiplication"); - TestClean(((TestV4 * 2.0f) == v4{TestV4.x * 2, TestV4.y * 2, TestV4.z * 2, TestV4.w * 2}), "V4 Multiplication"); - - TestClean(((TestV2 * TestV2) == v2{TestV2.x * TestV2.x, TestV2.y * TestV2.y}), "V2 Piecewise Mult"); - TestClean(((TestV3 * TestV3) == v3{ - TestV3.x * TestV3.x, - TestV3.y * TestV3.y, - TestV3.z * TestV3.z}), "V3 Piecewise Mult"); - TestClean(((TestV4 * TestV4) == v4{ - TestV4.x * TestV4.x, - TestV4.y * TestV4.y, - TestV4.z * TestV4.z, - TestV4.w * TestV4.w}), "V4 Piecewise Mult"); - - - TestClean(((TestV2 / 2.0f) == v2{TestV2.x / 2, TestV2.y / 2}), "V2 Division"); - TestClean(((TestV3 / 2.0f) == v3{TestV3.x / 2, TestV3.y / 2, TestV3.z / 2}), "V3 Division"); - TestClean(((TestV4 / 2.0f) == v4{TestV4.x / 2, TestV4.y / 2, TestV4.z / 2, TestV4.w / 2}), "V4 Division"); - - TestClean(((TestV2 / TestV2) == v2{TestV2.x / TestV2.x, TestV2.y / TestV2.y}), "V2 Piecewise Div"); - TestClean(((TestV3 / TestV3) == v3{ - TestV3.x / TestV3.x, - TestV3.y / TestV3.y, - TestV3.z / TestV3.z}), "V3 Piecewise Div"); - TestClean(((TestV4 / TestV4) == v4{ - TestV4.x / TestV4.x, - TestV4.y / TestV4.y, - TestV4.z / TestV4.z, - TestV4.w / TestV4.w}), "V4 Piecewise Div"); - - TestClean(((MagSqr(V2Unit) == 1) && (MagSqr(TestV2) == TestV2MagSq)), "V2 Square Mag"); - TestClean(((MagSqr(V3Unit) == 1) && (MagSqr(TestV3) == TestV3MagSq)), "V3 Square Mag"); - TestClean(((MagSqr(V4Unit) == 1) && (MagSqr(TestV4) == TestV4MagSq)), "V4 Square Mag"); - TestClean(((Mag(V2Unit) == 1) && (Mag(TestV2) == TestV2Mag)), "V2 Mag"); - TestClean(((Mag(V3Unit) == 1) && (Mag(TestV3) == TestV3Mag)), "V3 Mag"); - TestClean(((Mag(V4Unit) == 1) && (Mag(TestV4) == TestV4Mag)), "V4 Mag"); - - TestClean((DistanceSq(ZeroV2, TestV2) == TestV2MagSq), "V2 Distance Sq"); - TestClean((DistanceSq(ZeroV3, TestV3) == TestV3MagSq), "V3 Distance Sq"); - TestClean((DistanceSq(ZeroV4, TestV4) == TestV4MagSq), "V4 Distance Sq"); - TestClean((Distance(ZeroV2, TestV2) == TestV2Mag), "V2 Distance"); - TestClean((Distance(ZeroV3, TestV3) == TestV3Mag), "V3 Distance"); - TestClean((Distance(ZeroV4, TestV4) == TestV4Mag), "V4 Distance"); - - TestClean((Normalize(TestV2) == TestV2Norm), "V2 Normalize"); - TestClean((Normalize(TestV3) == TestV3Norm), "V3 Normalize"); - TestClean((Normalize(TestV4) == TestV4Norm), "V4 Normalize"); - - TestClean(((Dot(V2Unit, V2Unit) == 1) && (Dot(TestV2, V2Unit) == TestV2DotR)), "V2 Dot"); - TestClean(((Dot(V3Unit, V3Unit) == 1) && (Dot(TestV3, V3Unit) == TestV3DotR)), "V3 Dot"); - TestClean(((Dot(V4Unit, V4Unit) == 1) && (Dot(TestV4, V4Unit) == TestV4DotR)), "V4 Dot"); - - // Skipping Cross For Now - - TestClean((Lerp(v2{0, 0}, v2{1, 1}, .5f) == v2{.5f, .5f}), "V2 Lerp"); - TestClean((Lerp(v3{0, 0, 0}, v3{1, 1, 1}, .5f) == v3{.5f, .5f, .5f}), "V3 Lerp"); - TestClean((Lerp(v4{0, 0, 0, 0}, v4{1, 1, 1, 1}, .5f) == v4{.5f, .5f, .5f, .5f}), "V4 Lerp"); - - ///////////////////////////// - // Matrix - //////////////////////////// - - m33 TestM33 = m33{ - 0, 1, 2, - 3, 4, 5, - 6, 7, 8}; - - m33 EqualityM33 = {}; - for (s32 i = 0; i < 16; i++) { EqualityM33.E[i] = TestM33.E[i]; } - - m33 TransposeM33 = m33{ - 0, 3, 6, - 1, 4, 7, - 2, 5, 8}; - - m33 IdentityM33 = m33{ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1}; - - m33 TestM33Squared = m33{ - 15, 18, 21, - 42, 54, 66, - 69, 90, 111 - }; - - m44 TestM44 = m44{ - 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15 - }; - - m44 EqualityM44 = {}; - for (s32 i = 0; i < 16; i++) { EqualityM44.E[i] = TestM44.E[i]; } - - m44 TransposeM44 = m44{ - 0, 4, 8, 12, - 1, 5, 9, 13, - 2, 6, 10, 14, - 3, 7, 11, 15 - }; - - m44 IdentityM44 = m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - m44 TestM44Squared = m44{ - 56, 62, 68, 74, - 152, 174, 196, 218, - 248, 286, 324, 362, - 344, 398, 452, 506, - }; - - TestClean(((IdentityM33 == IdentityM33) && (TestM33 == EqualityM33)), "M33 Equality"); - TestClean(((IdentityM44 == IdentityM44) && (TestM44 == EqualityM44)), "M44 Equality"); - - TestClean(((Transpose(IdentityM33) == IdentityM33) && - (Transpose(TestM33) == TransposeM33)), "M33 Transpose"); - TestClean(((Transpose(IdentityM44) == IdentityM44) && - (Transpose(TestM44) == TransposeM44)), "M44 Transpose"); - - TestClean(((TestM33 * IdentityM33) == TestM33), "M33 Identity Mult"); - TestClean(((TestM44 * IdentityM44) == TestM44), "M44 Identity Mult"); - TestClean(((TestM33 * TestM33) == TestM33Squared), "M33 Mult"); - TestClean(((TestM44 * TestM44) == TestM44Squared), "M44 Mult"); - - - // Useful Tests - v4 Right = v4{1, 0, 0, 0}; - v4 Forward = v4{0, 0, 1, 0}; - v4 Up = v4{0, 1, 0, 0}; - v4 Left = v4{-1, 0, 0, 0}; - v4 Back = v4{0, 0, -1, 0}; - v4 Down = v4{0, -1, 0, 0}; - - m44 NinetyDegreesAboutX = GetXRotation(M_PI / 2); - v4 Rotated = NinetyDegreesAboutX * Forward; - TestClean((Rotated == Up), "Rotation About X"); - - m44 NinetyDegreesAboutY = GetYRotation(M_PI / 2); - Rotated = NinetyDegreesAboutY * Right; - TestClean((Rotated == Forward), "Rotation About Y"); - - m44 NinetyDegreesAboutZ = GetZRotation(M_PI / 2); - Rotated = NinetyDegreesAboutZ * Right; - TestClean((Rotated == Down), "Rotation About Z"); - - - v4 A = v4{1, 2, 3, 4}; - m44 B = m44{ - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 1, 2, 3, - 4, 5, 6, 7}; - v4 VTest = v4{30, 70, 29, 60}; - TestClean(((B * A) == VTest), "V4 M44 Multiplication"); - - m44 C = m44{ - 9, 8, 7, 6, - 5, 4, 3, 2, - 1, 0, 9, 8, - 7, 6, 5, 4 - }; - m44 MResult = B * C; - m44 MTest = m44{ - 50, 40, 60, 50, - 138, 112, 156, 130, - 109, 94, 99, 84, - 116, 94, 132, 110 - }; - TestClean(((B * C) == MTest), "M44 Mult Test 2"); - - m44 Identity = M44Identity(); - m44 InvIdentity = {}; - Inverse(Identity, &InvIdentity); - TestClean((Identity == InvIdentity), "Inverse Identity"); - - m44 Test = m44{ - 2, 4, 6, 7, - 5, 1, 8, 8, - 1, 7, 3, 1, - 3, 9, 2, 4 - }; - m44 PreCalcTestInv = m44{ - -0.3904761904761904762f, 0.26190476190476190475f, -0.02857142857142857139f, 0.16666666666666666668f, - 0.022222222222222222212f, -0.055555555555555555549f, 0.06666666666666666667f, 0.055555555555555555547f, - -0.00317460317460317458f, 0.07936507936507936506f, 0.27619047619047619045f, -0.2222222222222222222f, - 0.24444444444444444444f, -0.1111111111111111111f, -0.26666666666666666667f, 0.1111111111111111111f - }; - m44 InvTest = {}; - Inverse(Test, &InvTest); - //TestClean((PreCalcTestInv == InvTest), "Inverse M44"); - - DebugPrint("Results: Passed %d / %d\n\n\no", SuccessCount, TestCount); -} - -#endif - -#define GS_VECTOR_MATRIX_H -#endif \ No newline at end of file diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h new file mode 100644 index 0000000..4adc49b --- /dev/null +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -0,0 +1,78 @@ +PANEL_INIT_PROC(HierarchyView_Init) +{ + +} + +PANEL_CLEANUP_PROC(HierarchyView_Cleanup) +{ + +} + +PANEL_RENDER_PROC(HierarchyView_Render) +{ + r32 PanelWidth = PanelMax.x - PanelMin.x; + r32 PanelHeight = PanelMax.y - PanelMin.y; + + s32 LineBGColorsCount = 2; +v4 LineBGColors[] = { + { .16f, .16f, .16f, 1.f }, + { .18f, .18f, .18f, 1.f }, + }; + v4 LineBGHoverColor = { .22f, .22f, .22f, 1.f }; + + r32 LineHeight = State->Interface.Font->PixelHeight + 8; + v2 LineMin = v2{PanelMin.x + State->Interface.Margin.x, PanelMax.y - LineHeight}; + v2 LineMax = LineMin + v2{PanelWidth, LineHeight}; + v2 TextOffset = v2{10, 4}; + string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); + + s32 LineCount = (s32)(PanelHeight / LineHeight) + 1; + for (s32 i = 0; i < LineCount; i++) + { + v4 Color = LineBGColors[i % LineBGColorsCount]; + if (PointIsInRange(Mouse.Pos, LineMin, LineMax)) + { + Color = LineBGHoverColor; + } +PushRenderQuad2D(RenderBuffer, LineMin, LineMax, Color); + if (i < State->ActiveAssemblyIndecies.Used) + { +array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); + PrintF(&TempString, "%S", Assembly.Name); + + DrawString(RenderBuffer, TempString, State->Interface.Font, LineMin + TextOffset, WhiteV4); + + PrintF(&TempString, "X"); + + v2 XLowerRight = v2{LineMax.x - 25, LineMin.y + TextOffset.y}; + v2 XLowerLeft = DrawString(RenderBuffer, TempString, State->Interface.Font, XLowerRight, WhiteV4, Align_Right); + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState) + && PointIsInRange(Mouse.Pos, XLowerLeft, LineMax)) + { + UnloadAssembly(i, State, Context); + } + } + else if (i == State->ActiveAssemblyIndecies.Used) + { + PrintF(&TempString, "+ Add Assembly"); + v2 TextMinX = LineMin + TextOffset; + DrawString(RenderBuffer, TempString, State->Interface.Font, TextMinX, WhiteV4); + + if (MouseButtonTransitionedUp(Mouse.LeftButtonState) + && PointIsInRange(Mouse.Pos, LineMin, LineMax)) + { + char FilePath[256]; + b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0"); + if (Success) + { + LoadAssembly(State, Context, FilePath); + } + } + } + + LineMin.y = GSMax(PanelMin.y, LineMin.y - LineHeight); + LineMax.y = GSMax(PanelMin.y, LineMax.y - LineHeight); + } +} \ No newline at end of file diff --git a/src/panels/foldhaus_panel_sculpture_view.h b/src/panels/foldhaus_panel_sculpture_view.h index 1200313..3c6d72e 100644 --- a/src/panels/foldhaus_panel_sculpture_view.h +++ b/src/panels/foldhaus_panel_sculpture_view.h @@ -1,3 +1,7 @@ +input_command SculptureView_Commands[] = { + { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, +}; + PANEL_INIT_PROC(SculptureView_Init) { From 2c6adaeda2061fbb181cbca434fbe99375134e10 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 16:23:43 -0800 Subject: [PATCH 09/19] Improved the visuals of the hierarchy panel and the timeline panel --- src/animation/foldhaus_animation.h | 8 +- src/foldhaus_app.cpp | 14 +- src/gs_input.h | 4 +- src/interface.h | 10 +- .../foldhaus_panel_animation_timeline.h | 135 ++++++++++++------ src/panels/foldhaus_panel_hierarchy.h | 2 +- 6 files changed, 121 insertions(+), 52 deletions(-) diff --git a/src/animation/foldhaus_animation.h b/src/animation/foldhaus_animation.h index 2967b2c..73aedeb 100644 --- a/src/animation/foldhaus_animation.h +++ b/src/animation/foldhaus_animation.h @@ -39,8 +39,12 @@ struct animation_system free_list FreeList; u32 BlocksCount; -r32 Time; - b32 TimelineShouldAdvance; + r32 Time; + s32 LastUpdatedFrame; + r32 SecondsPerFrame; + +b32 TimelineShouldAdvance; + // :Temporary r32 AnimationEnd; }; diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 55eb6a2..8148b2c 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -275,6 +275,7 @@ INITIALIZE_APPLICATION(InitializeApplication) { // MODES PLAYGROUND InitializeAnimationSystem(&State->AnimationSystem); + State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; animation_block BlockZero = {0}; BlockZero.StartTime = 0; @@ -415,7 +416,14 @@ UPDATE_AND_RENDER(UpdateAndRender) { State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd; } - + } + +s32 CurrentFrame = (s32)(State->AnimationSystem.Time / State->AnimationSystem.SecondsPerFrame); + if (CurrentFrame != State->AnimationSystem.LastUpdatedFrame) + { + State->AnimationSystem.LastUpdatedFrame = CurrentFrame; + r32 FrameTime = CurrentFrame * State->AnimationSystem.SecondsPerFrame; + for (u32 i = 0; i < State->AnimationSystem.BlocksCount; i++) { animation_block_entry BlockEntry = State->AnimationSystem.Blocks[i]; @@ -425,11 +433,11 @@ UPDATE_AND_RENDER(UpdateAndRender) if (State->AnimationSystem.Time >= Block.StartTime && State->AnimationSystem.Time <= Block.EndTime) { - Block.Proc(State, State->AnimationSystem.Time - Block.StartTime); + Block.Proc(State, FrameTime - Block.StartTime); } } + } } - } s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; diff --git a/src/gs_input.h b/src/gs_input.h index d77d12a..30bebb5 100644 --- a/src/gs_input.h +++ b/src/gs_input.h @@ -105,5 +105,7 @@ MouseButtonTransitionedUp (b32 MouseButtonState) internal b32 MouseButtonHeldDown (b32 MouseButtonState) { - return (KeyWasDown(MouseButtonState) && KeyIsDown(MouseButtonState)); + b32 WasDown = KeyWasDown(MouseButtonState); + b32 IsDown = KeyIsDown(MouseButtonState); + return (WasDown && IsDown); } \ No newline at end of file diff --git a/src/interface.h b/src/interface.h index 32acbae..e3631aa 100644 --- a/src/interface.h +++ b/src/interface.h @@ -8,12 +8,14 @@ enum string_alignment internal void DrawCharacter_ (render_quad_batch_constructor* BatchConstructor, r32 MinX, r32 MinY, codepoint_bitmap CodepointInfo, v4 Color) { - r32 MaxX = MinX + (CodepointInfo.Width); - r32 MaxY = MinY + (CodepointInfo.Height); + s32 AlignedMinX = (s32)(MinX); + s32 AlignedMinY = (s32)(MinY); +s32 AlignedMaxX = AlignedMinX + (CodepointInfo.Width); + s32 AlignedMaxY = AlignedMinY + (CodepointInfo.Height); PushQuad2DOnBatch(BatchConstructor, - v2{MinX, MinY}, v2{MaxX, MinY}, - v2{MaxX, MaxY}, v2{MinX, MaxY}, + v2{(r32)AlignedMinX, (r32)AlignedMinY}, v2{(r32)AlignedMaxX, (r32)AlignedMinY}, + v2{(r32)AlignedMaxX, (r32)AlignedMaxY}, v2{(r32)AlignedMinX, (r32)AlignedMaxY}, CodepointInfo.UVMin, CodepointInfo.UVMax, Color); } diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h index 45957aa..829e1a6 100644 --- a/src/panels/foldhaus_panel_animation_timeline.h +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -18,36 +18,75 @@ PANEL_CLEANUP_PROC(AnimationTimeline_Cleanup) } internal animation_block_handle -DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse) +DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, v2 PanelMin, v2 PanelMax, animation_block_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; -r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; - r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; - panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax, - 0, Interface); + r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; + r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; + PushRenderQuad2D(RenderBuffer, PanelMin, PanelMax, v4{.22f, .22f, .22f, 1.f}); + // Frame Bar + r32 FrameBarHeight = 24; + v2 FrameBarMin = v2{PanelMin.x, PanelMax.y - FrameBarHeight}; + v2 FrameBarMax = PanelMax; + PushRenderQuad2D(RenderBuffer, FrameBarMin, FrameBarMax, v4{.16f, .16f, .16f, 1.f}); + +// Mouse clicked inside frame nubmer bar -> change current frame on timeline + if (MouseButtonHeldDown(Mouse.LeftButtonState) + && PointIsInRange(Mouse.DownPos, FrameBarMin, FrameBarMax)) + { + r32 MouseX = Mouse.DownPos.x; + r32 MousePercentX = (MouseX - FrameBarMin.x) / (FrameBarMax.x - FrameBarMin.y); + s32 MouseFrame = (s32)((MousePercentX * FrameCount) + StartFrame); + r32 MouseFrameTime = (r32)MouseFrame * AnimationSystem->SecondsPerFrame; + AnimationSystem->Time = MouseFrameTime; + } + + for (s32 f = 0; f < FrameCount; f += 10) + { + s32 Frame = StartFrame + f; + PrintF(&TempString, "%d", Frame); + + r32 FramePercent = (r32)f / (r32)FrameCount; + r32 FrameX = GSLerp(PanelMin.x, PanelMax.x, FramePercent); + v2 FrameTextPos = v2{FrameX, FrameBarMin.y + 2}; + DrawString(RenderBuffer, TempString, State->Interface.Font, FrameTextPos, WhiteV4); + + // Frame Vertical Slices + v2 LineTop = v2{FrameX, FrameBarMin.y}; + v2 LineBottom = v2{FrameX + 1, PanelMin.y}; + PushRenderQuad2D(RenderBuffer, LineTop, LineBottom, v4{.16f, .16f, .16f, 1.f}); + } + + // Animation Blocks + v2 TimelineMin = PanelMin; + v2 TimelineMax = v2{PanelMax.x, FrameBarMin.y}; b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); - - for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) - { - animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; - if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } +for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) + { + animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; + if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } animation_block_handle CurrentBlockHandle = {}; CurrentBlockHandle.Index = i; CurrentBlockHandle.Generation = AnimationBlockEntry.Generation; - animation_block AnimationBlockAt = AnimationBlockEntry.Block; - -r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd; - r32 StartPosition = AnimationPanelWidth * StartTimePercent; - -r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd; - r32 EndPosition = AnimationPanelWidth * EndTimePercent; - - v2 Min = PanelMin + v2{StartPosition, 25}; - v2 Max = PanelMin + v2{EndPosition, 75}; + animation_block AnimationBlockAt = AnimationBlockEntry.Block; + + s32 BlockStartFrame = AnimationBlockAt.StartTime / AnimationSystem->SecondsPerFrame; + r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount; + r32 StartPosition = AnimationPanelWidth * StartFramePercent; + + s32 BlockEndFrame = AnimationBlockAt.EndTime / AnimationSystem->SecondsPerFrame; + r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount; + r32 EndPosition = AnimationPanelWidth * EndFramePercent; + + v2 Min = TimelineMin + v2{StartPosition, 25}; + v2 Max = TimelineMin + v2{EndPosition, 75}; v4 BlockColor = BlackV4; if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) @@ -55,32 +94,44 @@ r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd; BlockColor = PinkV4; } - PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); + PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4); if (PointIsInRange(Mouse.Pos, Min, Max) && MouseButtonTransitionedDown(Mouse.LeftButtonState)) { MouseDownAndNotHandled = false; -if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) + if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) { -// If the block is already selected, deselect it. + // If the block is already selected, deselect it. Result = {0}; } else { -Result = CurrentBlockHandle; + Result = CurrentBlockHandle; } } - } + } - r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd; + // Time Slider +s32 SliderFrame = AnimationSystem->Time / AnimationSystem->SecondsPerFrame; + r32 TimePercent = (r32)SliderFrame / (r32)EndFrame; r32 SliderX = PanelMin.x + (AnimationPanelWidth * TimePercent); v2 SliderMin = v2{SliderX, PanelMin.y}; v2 SliderMax = v2{SliderX + 1, PanelMax.y - 25}; - PushRenderQuad2D(RenderBuffer, SliderMin, SliderMax, WhiteV4); + v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; - if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + PushRenderQuad2D(RenderBuffer, SliderMin, SliderMax, TimeSliderColor); + + r32 SliderHalfWidth = 10; + v2 HeadMin = v2{SliderX - SliderHalfWidth, SliderMax.y}; + v2 HeadMax = v2{SliderX + SliderHalfWidth, SliderMax.y + FrameBarHeight}; + PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); + + PrintF(&TempString, "%d", SliderFrame); + DrawString(RenderBuffer, TempString, State->Interface.Font, HeadMin + v2{4, 4}, WhiteV4); + + if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, TimelineMin, TimelineMax)) { r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth; r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd; @@ -96,21 +147,23 @@ Result = CurrentBlockHandle; Result = NewBlockHandle; } return Result; - } +} PANEL_RENDER_PROC(AnimationTimeline_Render) { animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; -r32 OptionsRowHeight = 25; + r32 OptionsRowHeight = 25; v2 TimelineMin = PanelMin; v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight}; if (TimelineMax.y - TimelineMin.y > 0) { + s32 FrameEnd = (s32)(State->AnimationSystem.AnimationEnd / State->AnimationSystem.SecondsPerFrame); SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem, -TimelineMin, TimelineMax, - SelectedBlockHandle, - RenderBuffer, State->Interface, Mouse); + 0, FrameEnd, + TimelineMin, TimelineMax, + SelectedBlockHandle, + RenderBuffer, State, Mouse); } v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y }; @@ -128,14 +181,14 @@ TimelineMin, TimelineMax, MakeStringLiteral("Pause"), State->Interface, Mouse); ButtonAt.x += ButtonWidth + 2; -button_result PlayResult = EvaluateButton(RenderBuffer, - ButtonAt + ButtonMin, ButtonAt + ButtonMax, - MakeStringLiteral("Play"), + button_result PlayResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Play"), State->Interface, Mouse); ButtonAt.x += ButtonWidth + 2; -button_result StopResult = EvaluateButton(RenderBuffer, - ButtonAt + ButtonMin, ButtonAt + ButtonMax, - MakeStringLiteral("Stop"), + button_result StopResult = EvaluateButton(RenderBuffer, + ButtonAt + ButtonMin, ButtonAt + ButtonMax, + MakeStringLiteral("Stop"), State->Interface, Mouse); if (PauseResult.Pressed) @@ -153,6 +206,6 @@ button_result StopResult = EvaluateButton(RenderBuffer, State->AnimationSystem.TimelineShouldAdvance = false; State->AnimationSystem.Time = 0; } - -State->SelectedAnimationBlockHandle = SelectedBlockHandle; + + State->SelectedAnimationBlockHandle = SelectedBlockHandle; } diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h index 4adc49b..db23770 100644 --- a/src/panels/foldhaus_panel_hierarchy.h +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -21,7 +21,7 @@ v4 LineBGColors[] = { v4 LineBGHoverColor = { .22f, .22f, .22f, 1.f }; r32 LineHeight = State->Interface.Font->PixelHeight + 8; - v2 LineMin = v2{PanelMin.x + State->Interface.Margin.x, PanelMax.y - LineHeight}; + v2 LineMin = v2{PanelMin.x, PanelMax.y - LineHeight}; v2 LineMax = LineMin + v2{PanelWidth, LineHeight}; v2 TextOffset = v2{10, 4}; string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); From 76d27e3b5794544d585ccb1f75de89eec772f33a Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Thu, 26 Dec 2019 18:40:14 -0800 Subject: [PATCH 10/19] Fixed a bug where unloading assemblies caused a crash in the test patterns. Fixed another bug caused by not initializing dmx buffers linked lists to zero. --- src/animation/foldhaus_animation.h | 5 +- src/foldhaus_app.cpp | 49 ++++---- src/foldhaus_app.h | 96 ++++++++++----- src/foldhaus_assembly.cpp | 12 +- src/gs_array.h | 11 +- .../foldhaus_panel_animation_timeline.h | 111 ++++++++++++------ src/panels/foldhaus_panel_hierarchy.h | 2 +- 7 files changed, 185 insertions(+), 101 deletions(-) diff --git a/src/animation/foldhaus_animation.h b/src/animation/foldhaus_animation.h index 73aedeb..003ef2d 100644 --- a/src/animation/foldhaus_animation.h +++ b/src/animation/foldhaus_animation.h @@ -5,7 +5,7 @@ // [] - will need a way to create an empty layer // [] - get a list of all animation procs -#define ANIMATION_PROC(name) void name(app_state* State, r32 Time) +#define ANIMATION_PROC(name) void name(assembly* Assembly, r32 Time) typedef ANIMATION_PROC(animation_proc); struct animation_block @@ -46,7 +46,8 @@ u32 BlocksCount; b32 TimelineShouldAdvance; // :Temporary - r32 AnimationEnd; + r32 AnimationStart; +r32 AnimationEnd; }; internal b32 diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 8148b2c..c0e8161 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -275,27 +275,22 @@ INITIALIZE_APPLICATION(InitializeApplication) { // MODES PLAYGROUND InitializeAnimationSystem(&State->AnimationSystem); - State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; - - animation_block BlockZero = {0}; - BlockZero.StartTime = 0; - BlockZero.EndTime = 2; - BlockZero.Proc = TestPatternOne; - AddAnimationBlock(BlockZero, &State->AnimationSystem); +State->AnimationSystem.SecondsPerFrame = 1.f / 24.f; animation_block BlockOne = {0}; - BlockOne.StartTime = 3; - BlockOne.EndTime = 5; + BlockOne.StartTime = 0; + BlockOne.EndTime = 8; BlockOne.Proc = TestPatternTwo; AddAnimationBlock(BlockOne, &State->AnimationSystem); animation_block BlockTwo = {0}; - BlockTwo.StartTime = 5; - BlockTwo.EndTime = 8; + BlockTwo.StartTime = 8; + BlockTwo.EndTime = 15; BlockTwo.Proc = TestPatternThree; AddAnimationBlock(BlockTwo, &State->AnimationSystem); - State->AnimationSystem.AnimationEnd = 10; + State->AnimationSystem.AnimationStart = 0; + State->AnimationSystem.AnimationEnd = 15; } // End Animation Playground @@ -303,8 +298,6 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializePanelLayout(&State->PanelLayout); panel* Panel = TakeNewPanel(&State->PanelLayout); SetPanelDefinition(Panel, 0); - SplitPanelVertically(Panel, .5f, v2{0, 0}, v2{Context.WindowWidth, Context.WindowHeight}, &State->PanelLayout); - SetPanelDefinition(&Panel->Right->Panel, 1); } // End Panels Playground } @@ -365,10 +358,11 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) leds_in_universe_range LEDUniverseRange = Assembly.LEDUniverseMap[Range]; dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list); - NewBuffer->Buffer.Universe = LEDUniverseRange.Universe; +NewBuffer->Buffer.Universe = LEDUniverseRange.Universe; NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize); NewBuffer->Buffer.TotalSize = BufferSize; NewBuffer->Buffer.HeaderSize = BufferHeaderSize; + NewBuffer->Next = 0; // Append if (!Result) { @@ -433,7 +427,12 @@ s32 CurrentFrame = (s32)(State->AnimationSystem.Time / State->AnimationSystem.Se if (State->AnimationSystem.Time >= Block.StartTime && State->AnimationSystem.Time <= Block.EndTime) { - Block.Proc(State, FrameTime - Block.StartTime); + for (s32 j = 0; j < State->ActiveAssemblyIndecies.Used; j++) + { + array_entry_handle* AssemblyHandle = GetElementAtIndex(j, State->ActiveAssemblyIndecies); + assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); + Block.Proc(Assembly, FrameTime - Block.StartTime); + } } } } @@ -441,12 +440,17 @@ s32 CurrentFrame = (s32)(State->AnimationSystem.Time / State->AnimationSystem.Se s32 HeaderSize = State->NetworkProtocolHeaderSize; dmx_buffer_list* DMXBuffers = 0; + if (State->ActiveAssemblyIndecies.Used > 1) + { + s32 f = 4; + } + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies); - assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList); - dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, &State->Transient); - DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); + array_entry_handle* AssemblyHandle = GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); + dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient); + DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); } DEBUG_IF(GlobalDebugServices->Interface.SendSACNData) @@ -566,9 +570,10 @@ PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHe { DEBUG_TRACK_SCOPE(OverflowChecks); AssertAllocationsNoOverflow(State->Permanent); - for (s32 i = 0; i < State->AssemblyList.Used; i++) + for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++) { - assembly* Assembly = GetElementAtIndex(i, State->AssemblyList); + array_entry_handle* AssemblyHandle = GetElementAtIndex(i, State->ActiveAssemblyIndecies); + assembly* Assembly = GetElementWithHandle(*AssemblyHandle, State->AssemblyList); AssertAllocationsNoOverflow(Assembly->Arena); } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 1318f21..d27a06f 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -74,51 +74,85 @@ internal void OpenColorPicker(app_state* State, v4* Address); // BEGIN TEMPORARY PATTERNS internal void -TestPatternOne(app_state* State, r32 Time) +TestPatternOne(assembly* Assembly, r32 Time) { - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + for (s32 Range = 0; Range < Assembly->LEDUniverseMapCount; Range++) { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + leds_in_universe_range LEDUniverseRange = Assembly->LEDUniverseMap[Range]; for (s32 LEDIdx = LEDUniverseRange.RangeStart; LEDIdx < LEDUniverseRange.RangeOnePastLast; LEDIdx++) { - led LED = TestAssembly.LEDs[LEDIdx]; - TestAssembly.Colors[LED.Index].R = 255; - TestAssembly.Colors[LED.Index].B = 255; - TestAssembly.Colors[LED.Index].G = 255; + led LED = Assembly->LEDs[LEDIdx]; + Assembly->Colors[LED.Index].R = 255; + Assembly->Colors[LED.Index].B = 255; + Assembly->Colors[LED.Index].G = 255; + } } - } } internal void -TestPatternTwo(app_state* State, r32 Time) +TestPatternTwo(assembly* Assembly, r32 Time) { - if (Time > 2 * PI * 100) { Time = 0; } - r32 SinAdjusted = 0.5f + (GSSin(Time * 0.01f) * .5f); - u8 Brightness = (u8)(GSClamp01(SinAdjusted) * 255); + r32 PeriodicTime = (Time / PI) * 2; + + r32 ZeroOneSin = (GSSin(PeriodicTime) * .5f) + .5f; +r32 ZeroOneCos = (GSCos(PeriodicTime) * .5f) + .5f; + pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + v4 Center = v4{0, 0, 0, 1}; + r32 ThetaZ = Time / 2; + v4 Normal = v4{GSCos(ThetaZ), 0, GSSin(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = Cross(Normal, v4{0, 1, 0, 0}); + + v4 FrontCenter = Center + (Normal * 25); + v4 BackCenter = Center - (Normal * 25); + + r32 OuterRadiusSquared = 1000000; + r32 InnerRadiusSquared = 0; + +for (s32 Range = 0; Range < Assembly->LEDUniverseMapCount; Range++) { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; - for (s32 LEDIdx = LEDUniverseRange.RangeStart; + leds_in_universe_range LEDUniverseRange = Assembly->LEDUniverseMap[Range]; +for (s32 LEDIdx = LEDUniverseRange.RangeStart; LEDIdx < LEDUniverseRange.RangeOnePastLast; LEDIdx++) { - led LED = TestAssembly.LEDs[LEDIdx]; - TestAssembly.Colors[LED.Index].R = Brightness; - TestAssembly.Colors[LED.Index].B = 0; - TestAssembly.Colors[LED.Index].G = Brightness; + led LED = Assembly->LEDs[LEDIdx]; + + v4 Position = LED.Position; + + v4 ToFront = Position + FrontCenter; + v4 ToBack = Position + BackCenter; + + r32 ToFrontDotNormal = Dot(ToFront, Normal); + r32 ToBackDotNormal = Dot(ToBack, Normal); + + ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); + + r32 SqDistToCenter = MagSqr(Position); + if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) + { + if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) + { + Assembly->Colors[LED.Index] = Color; + } + else + { + Assembly->Colors[LED.Index] = {}; + } + } +else + { + Assembly->Colors[LED.Index] = {}; + } } } } internal void -TestPatternThree(app_state* State, r32 Time) +TestPatternThree(assembly* Assembly, r32 Time) { r32 GreenSize = 20.0f; r32 BlueSize = 25.0f; @@ -128,16 +162,14 @@ r32 GreenSize = 20.0f; r32 BluePosition = -BlueSize + (Time * 25); r32 RedPosition = (100 + RedSize) + (Time * -35); - array_entry_handle TestAssemblyHandle = *GetElementAtIndex(0, State->ActiveAssemblyIndecies); - assembly TestAssembly = *GetElementWithHandle(TestAssemblyHandle, State->AssemblyList); - for (s32 Range = 0; Range < TestAssembly.LEDUniverseMapCount; Range++) + for (s32 Range = 0; Range < Assembly->LEDUniverseMapCount; Range++) { - leds_in_universe_range LEDUniverseRange = TestAssembly.LEDUniverseMap[Range]; + leds_in_universe_range LEDUniverseRange = Assembly->LEDUniverseMap[Range]; for (s32 LEDIdx = LEDUniverseRange.RangeStart; LEDIdx < LEDUniverseRange.RangeOnePastLast; LEDIdx++) { - led LED = TestAssembly.LEDs[LEDIdx]; + led LED = Assembly->LEDs[LEDIdx]; u8 Red = 0; u8 Green = 0; u8 Blue = 0; @@ -154,9 +186,9 @@ r32 GreenSize = 20.0f; r32 RedBrightness = GSClamp(0.0f, RedSize - RedDistance, RedSize) / RedSize; Red = (u8)(RedBrightness * 255); - TestAssembly.Colors[LED.Index].R = Red; - TestAssembly.Colors[LED.Index].B = Blue; - TestAssembly.Colors[LED.Index].G = Green; + Assembly->Colors[LED.Index].R = Red; + Assembly->Colors[LED.Index].B = Blue; + Assembly->Colors[LED.Index].G = Green; } } } diff --git a/src/foldhaus_assembly.cpp b/src/foldhaus_assembly.cpp index f9c700f..4a39d04 100644 --- a/src/foldhaus_assembly.cpp +++ b/src/foldhaus_assembly.cpp @@ -10,7 +10,7 @@ GetAssemblyMemorySizeFromDefinition(assembly_definition Definition, string Name) internal assembly ConstructAssemblyFromDefinition (assembly_definition Definition, string AssemblyName, - v3 RootPosition, + v4 RootPosition, r32 Scale, memory_arena Arena) { @@ -43,8 +43,8 @@ ConstructAssemblyFromDefinition (assembly_definition Definition, // now. The assert is to remind you to create more cases when necessary Assert(StripDef.InterpolationType == StripInterpolate_Points); - v4 WS_StripStart = V4(StripDef.InterpolatePositionStart * Scale, 1); - v4 WS_StripEnd = V4(StripDef.InterpolatePositionEnd * Scale, 1); + v4 WS_StripStart = RootPosition + V4(StripDef.InterpolatePositionStart * Scale, 1); + v4 WS_StripEnd = RootPosition + V4(StripDef.InterpolatePositionEnd * Scale, 1); s32 LEDsInStripCount = StripDef.LEDsPerStrip; Assert(Assembly.LEDCount + LEDsInStripCount <= Definition.TotalLEDCount); @@ -63,6 +63,9 @@ ConstructAssemblyFromDefinition (assembly_definition Definition, return Assembly; } +static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} }; +s32 TempAssemblyOffsetsCount = 3; + internal void LoadAssembly (app_state* State, context Context, char* Path) { @@ -82,9 +85,10 @@ LoadAssembly (app_state* State, context Context, char* Path) AssemblyArena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc; AssemblyArena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc; + v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount]; assembly NewAssembly = ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, - v3{0, 0, 0}, + Offset, Scale, AssemblyArena); array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList); diff --git a/src/gs_array.h b/src/gs_array.h index 6fd0b47..37c9855 100644 --- a/src/gs_array.h +++ b/src/gs_array.h @@ -147,7 +147,6 @@ RemoveElementAtIndex (s32 Index, element_type##_array* Buffer) \ Entry->Free.Next = Buffer->FreeList.Next; \ Buffer->FreeList.Next = &Entry->Free; \ \ - --Buffer->Used; \ } \ // END OF CRAZY MACRO @@ -183,9 +182,13 @@ GrowBuffer(element_type##_contiguous_array* Buffer) \ \ internal element_type* \ GetElementAtIndex (s32 Index, element_type##_contiguous_array Buffer) \ -{ \ - bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \ - element_type* Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \ + { \ + element_type* Entry = 0; \ + if (Index <= Buffer.Used) \ + { \ +bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \ + Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \ + } \ return Entry; \ } \ \ diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h index 829e1a6..5217815 100644 --- a/src/panels/foldhaus_panel_animation_timeline.h +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -17,35 +17,31 @@ PANEL_CLEANUP_PROC(AnimationTimeline_Cleanup) } -internal animation_block_handle -DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) +internal r32 +DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, s32 StartFrame, s32 EndFrame, v2 PanelMin, v2 PanelMax, interface_config Interface, mouse_state Mouse) { - string TempString = MakeString(PushArray(&State->Transient, char, 256), 256); -s32 FrameCount = EndFrame - StartFrame; - - animation_block_handle Result = SelectedBlockHandle; + MakeStringBuffer(TempString, 256); - r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; - r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; - PushRenderQuad2D(RenderBuffer, PanelMin, PanelMax, v4{.22f, .22f, .22f, 1.f}); + s32 FrameCount = EndFrame - StartFrame; - // Frame Bar r32 FrameBarHeight = 24; v2 FrameBarMin = v2{PanelMin.x, PanelMax.y - FrameBarHeight}; v2 FrameBarMax = PanelMax; + PushRenderQuad2D(RenderBuffer, FrameBarMin, FrameBarMax, v4{.16f, .16f, .16f, 1.f}); -// Mouse clicked inside frame nubmer bar -> change current frame on timeline + // Mouse clicked inside frame nubmer bar -> change current frame on timeline if (MouseButtonHeldDown(Mouse.LeftButtonState) && PointIsInRange(Mouse.DownPos, FrameBarMin, FrameBarMax)) { r32 MouseX = Mouse.DownPos.x; - r32 MousePercentX = (MouseX - FrameBarMin.x) / (FrameBarMax.x - FrameBarMin.y); - s32 MouseFrame = (s32)((MousePercentX * FrameCount) + StartFrame); - r32 MouseFrameTime = (r32)MouseFrame * AnimationSystem->SecondsPerFrame; - AnimationSystem->Time = MouseFrameTime; + r32 StartFrameTime = (r32)StartFrame * AnimationSystem->SecondsPerFrame; + r32 EndFrameTime = (r32)EndFrame * AnimationSystem->SecondsPerFrame; + r32 MouseTime = GSRemap(MouseX, FrameBarMin.x, FrameBarMax.x, StartFrameTime, EndFrameTime); + AnimationSystem->Time = MouseTime; } + // Frame Ticks for (s32 f = 0; f < FrameCount; f += 10) { s32 Frame = StartFrame + f; @@ -54,7 +50,7 @@ s32 FrameCount = EndFrame - StartFrame; r32 FramePercent = (r32)f / (r32)FrameCount; r32 FrameX = GSLerp(PanelMin.x, PanelMax.x, FramePercent); v2 FrameTextPos = v2{FrameX, FrameBarMin.y + 2}; - DrawString(RenderBuffer, TempString, State->Interface.Font, FrameTextPos, WhiteV4); + DrawString(RenderBuffer, TempString, Interface.Font, FrameTextPos, WhiteV4); // Frame Vertical Slices v2 LineTop = v2{FrameX, FrameBarMin.y}; @@ -62,11 +58,65 @@ s32 FrameCount = EndFrame - StartFrame; PushRenderQuad2D(RenderBuffer, LineTop, LineBottom, v4{.16f, .16f, .16f, 1.f}); } + return FrameBarMin.y; +} + +internal rect +DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, r32 SecondsPerFrame, s32 FrameCount, s32 StartFrame, v2 TimelineMin, v2 TimelineMax, render_command_buffer* RenderBuffer) +{ + rect BlockBounds = {}; + + r32 TimelineWidth = TimelineMax.x - TimelineMin.x; + + s32 BlockStartFrame = AnimationBlock.StartTime / SecondsPerFrame; + r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount; + r32 StartPosition = TimelineWidth * StartFramePercent; + + s32 BlockEndFrame = AnimationBlock.EndTime / SecondsPerFrame; + r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount; + r32 EndPosition = TimelineWidth * EndFramePercent; + + BlockBounds.Min = TimelineMin + v2{StartPosition, 25}; + BlockBounds.Max = TimelineMin + v2{EndPosition, 75}; + + PushRenderQuad2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, BlockColor); + PushRenderBoundingBox2D(RenderBuffer, BlockBounds.Min, BlockBounds.Max, 1, WhiteV4); + + return BlockBounds; +} + +internal animation_block_handle +DrawAnimationTimeline (animation_system* AnimationSystem, s32 StartFrame, s32 EndFrame, v2 PanelMin, v2 PanelMax, animation_block_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; + + r32 AnimationPanelHeight = PanelMax.y - PanelMin.y; + r32 AnimationPanelWidth = PanelMax.x - PanelMin.x; + + { + s32 FirstPlayableFrame = (AnimationSystem->AnimationStart / AnimationSystem->SecondsPerFrame); + s32 LastPlayableFrame = (AnimationSystem->AnimationEnd / AnimationSystem->SecondsPerFrame); + + r32 FirstPlayablePercentX = ((r32)(FirstPlayableFrame - StartFrame) / (r32)FrameCount); + r32 LastPlayablePercentX = ((r32)(LastPlayableFrame - StartFrame) / (r32)FrameCount); + + v2 PlayableMin = v2{(FirstPlayablePercentX * AnimationPanelWidth) + PanelMin.x, PanelMin.y }; + v2 PlayableMax = v2{(LastPlayablePercentX * AnimationPanelWidth) + PanelMin.x, PanelMax.y }; + + PushRenderQuad2D(RenderBuffer, PanelMin, PanelMax, v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(RenderBuffer, PlayableMin, PlayableMax, v4{.22f, .22f, .22f, 1.f}); + } + + r32 FrameBarBottom = DrawFrameBar(AnimationSystem, RenderBuffer, StartFrame, EndFrame, PanelMin, PanelMax, State->Interface, Mouse); + // Animation Blocks v2 TimelineMin = PanelMin; - v2 TimelineMax = v2{PanelMax.x, FrameBarMin.y}; + v2 TimelineMax = v2{PanelMax.x, FrameBarBottom}; b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState); -for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) + for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) { animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i]; if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; } @@ -77,27 +127,15 @@ for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) animation_block AnimationBlockAt = AnimationBlockEntry.Block; - s32 BlockStartFrame = AnimationBlockAt.StartTime / AnimationSystem->SecondsPerFrame; - r32 StartFramePercent = (r32)(BlockStartFrame - StartFrame) / (r32)FrameCount; - r32 StartPosition = AnimationPanelWidth * StartFramePercent; - - s32 BlockEndFrame = AnimationBlockAt.EndTime / AnimationSystem->SecondsPerFrame; - r32 EndFramePercent = (r32)(BlockEndFrame - StartFrame) / (r32)FrameCount; - r32 EndPosition = AnimationPanelWidth * EndFramePercent; - - v2 Min = TimelineMin + v2{StartPosition, 25}; - v2 Max = TimelineMin + v2{EndPosition, 75}; - v4 BlockColor = BlackV4; if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle)) { BlockColor = PinkV4; } - PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor); - PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4); + rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AnimationSystem->SecondsPerFrame, FrameCount, StartFrame, TimelineMin, TimelineMax, RenderBuffer); - if (PointIsInRange(Mouse.Pos, Min, Max) + if (PointIsInRange(Mouse.Pos, BlockBounds.Min, BlockBounds.Max) && MouseButtonTransitionedDown(Mouse.LeftButtonState)) { MouseDownAndNotHandled = false; @@ -114,8 +152,8 @@ for (u32 i = 0; i < AnimationSystem->BlocksCount; i++) } // Time Slider -s32 SliderFrame = AnimationSystem->Time / AnimationSystem->SecondsPerFrame; - r32 TimePercent = (r32)SliderFrame / (r32)EndFrame; + s32 SliderFrame = AnimationSystem->Time / AnimationSystem->SecondsPerFrame; + r32 TimePercent = (r32)(SliderFrame - StartFrame) / (r32)FrameCount; r32 SliderX = PanelMin.x + (AnimationPanelWidth * TimePercent); v2 SliderMin = v2{SliderX, PanelMin.y}; v2 SliderMax = v2{SliderX + 1, PanelMax.y - 25}; @@ -125,7 +163,7 @@ s32 SliderFrame = AnimationSystem->Time / AnimationSystem->SecondsPerFrame; r32 SliderHalfWidth = 10; v2 HeadMin = v2{SliderX - SliderHalfWidth, SliderMax.y}; - v2 HeadMax = v2{SliderX + SliderHalfWidth, SliderMax.y + FrameBarHeight}; + v2 HeadMax = v2{SliderX + SliderHalfWidth, PanelMax.y}; PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); PrintF(&TempString, "%d", SliderFrame); @@ -158,9 +196,10 @@ PANEL_RENDER_PROC(AnimationTimeline_Render) v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight}; if (TimelineMax.y - TimelineMin.y > 0) { + s32 FrameStart = (s32)(State->AnimationSystem.AnimationStart / State->AnimationSystem.SecondsPerFrame); s32 FrameEnd = (s32)(State->AnimationSystem.AnimationEnd / State->AnimationSystem.SecondsPerFrame); SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem, - 0, FrameEnd, + FrameStart - 20, FrameEnd + 20, TimelineMin, TimelineMax, SelectedBlockHandle, RenderBuffer, State, Mouse); diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h index db23770..08d8b87 100644 --- a/src/panels/foldhaus_panel_hierarchy.h +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -51,7 +51,7 @@ array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyI if (MouseButtonTransitionedUp(Mouse.LeftButtonState) && PointIsInRange(Mouse.Pos, XLowerLeft, LineMax)) { - UnloadAssembly(i, State, Context); + UnloadAssembly(AssemblyHandle.Index, State, Context); } } else if (i == State->ActiveAssemblyIndecies.Used) From d112b01e793be5708fa3861bf44150bf05dead22 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 28 Dec 2019 10:51:47 -0800 Subject: [PATCH 11/19] Lotta work on panels geting animation and sculpture view more up to scratch. Deleted a bunch of now obsolete files. --- data/splash.png | Bin 1157515 -> 1153384 bytes src/animation/foldhaus_animation_interface.h | 9 - src/foldhaus_app.cpp | 189 +++++--------- src/foldhaus_app.h | 74 +++--- src/foldhaus_command_dispatch.cpp | 149 ----------- src/foldhaus_command_dispatch.h | 152 ++++++++++- src/foldhaus_debug_visuals.h | 245 ------------------ src/foldhaus_interface.cpp | 44 ---- src/foldhaus_interface.h | 0 src/foldhaus_panel.h | 242 ++++++++++++----- src/foldhaus_platform.h | 3 +- src/generated/foldhaus_panels_generated.h | 2 +- .../foldhaus_panel_animation_timeline.h | 81 ++++-- src/panels/foldhaus_panel_sculpture_view.h | 45 +++- src/win32_foldhaus.cpp | 21 +- todo.txt | 14 +- 16 files changed, 547 insertions(+), 723 deletions(-) delete mode 100644 src/animation/foldhaus_animation_interface.h delete mode 100644 src/foldhaus_command_dispatch.cpp delete mode 100644 src/foldhaus_interface.h diff --git a/data/splash.png b/data/splash.png index 02bb10a2c5e0d36070399b3426ad64e91f799c8c..689248ba1a253c75cda9fa0d89593814d945646e 100644 GIT binary patch delta 667789 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

ycu2 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⁡#L}*N^icdjgV;urN{>N{dpSHhfr)OM^&(CU_ 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%0Asa@LZZpiu$H zk#HS9>s6@sJtke{^m(HD2;=(gE-GGVMPq}AUz6?wd*Wo&OJ`xRM}-MyFHTLffwAzifj!U@I| z7vFFy_QB?5+B2QBKb1{WDWA({tbbvYN&{|-Khy$!$MXf1)uUZM)%H9_HvIty@uJ06 zd8LoluRwmx+tp!OCfcR2;H6a8pUjt|g+uQ+c9;7*{pDrJp7hi-&AOU8zxQCr{lk

8`57#^gi|aHK3;R|tE~dKYm#oz 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

Tnae=oXM+}YauJMg<&Geu4b4Y~Cf3F$N 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