diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index e2823d4..9f9adc8 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -378,6 +378,10 @@ INITIALIZE_APPLICATION(InitializeApplication) InitMemoryArena(&State->SACNMemory, 0, 0, Context.PlatformAlloc); + { // MODES PLAYGROUND + State->Modes.ActiveModesCount = 0; + } + InitializeInputCommandRegistry(&State->InputCommandRegistry, 32, State->Permanent); InitializeInputCommandRegistry(&State->NodeListerCommandRegistry, 128, State->Permanent); State->ActiveCommands = &State->InputCommandRegistry; @@ -390,6 +394,30 @@ INITIALIZE_APPLICATION(InitializeApplication) State->ActiveTextEntry.Buffer = MakeString(PushArray(State->Permanent, char, 256), 0, 256); + { // Search Lister + State->SearchLister.SourceListCount = NodeSpecificationsCount; + State->SearchLister.SourceList = PushArray(State->Permanent, string, State->SearchLister.SourceListCount); + { + for (s32 i = 0; i < State->SearchLister.SourceListCount; i++) + { + State->SearchLister.SourceList[i] = MakeString( + NodeSpecifications[i].Name, + NodeSpecifications[i].NameLength); + } + } + State->SearchLister.Filter = State->ActiveTextEntry.Buffer; + + // TODO(Peter): This doesn't allow for using this search lister on different sources + // + // TODO(Peter): In general right now we support memory lifetimes of 1 frame, and permanent + // we need to support some intermediate lifetimes like + // temporary multiframe operation like searching. + // + State->SearchLister.FilteredListMax = State->SearchLister.SourceListCount; + State->SearchLister.FilteredListCount = 0; + State->SearchLister.FilteredIndexLUT = PushArray(State->Permanent, s32, State->SearchLister.SourceListCount); + } + // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; { @@ -863,15 +891,25 @@ UPDATE_AND_RENDER(UpdateAndRender) v2 TopLeft = State->NodeListMenuPosition; v2 Dimension = v2{300, 30}; + if (State->ActiveTextEntry.Buffer.Length > 0) + { + s32 x = 5; + } + + // Filter the lister + State->SearchLister.Filter = State->ActiveTextEntry.Buffer; + FilterSearchLister(&State->SearchLister); + + // Display Search Lister search_lister_result NodeListerResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension, MakeStringLiteral("Nodes List"), - NodeSpecificationsCount, (u8*)NodeSpecifications, - State->GeneralPurposeSearchHotItem, - NodeListerGetNodeName, + State->SearchLister.SourceList, + State->SearchLister.FilteredIndexLUT, + State->SearchLister.FilteredListCount, + State->SearchLister.HotItem, &State->ActiveTextEntry.Buffer, State->ActiveTextEntry.CursorPosition, State->Font, State->Interface, GuiMouse); - State->GeneralPurposeSearchHotItem = NodeListerResult.HotItem; } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 4fcb97e..eca10df 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -48,9 +48,8 @@ struct assembly typedef struct app_state app_state; - #include "foldhaus_command_dispatch.h" - +#include "foldhaus_operation_mode.h" #include "foldhaus_text_entry.h" @@ -66,6 +65,9 @@ struct app_state camera Camera; + operation_mode Operation_AddNode; + operation_mode_system Modes; + input_command_registry InputCommandRegistry; input_command_registry NodeListerCommandRegistry; // NOTE(Peter): stores the address of the command registry to be activated next frame. @@ -76,6 +78,7 @@ struct app_state input_command_queue CommandQueue; text_entry ActiveTextEntry; + search_lister SearchLister; streaming_acn SACN; s32 TotalLEDsCount; @@ -109,8 +112,6 @@ struct app_state v4* ColorPickerEditValue; string GeneralPurposeSearchString; - s32 GeneralPurposeSearchHotItem; - }; #include "foldhaus_debug_visuals.h" diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index 8454ddc..70cf10e 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -20,7 +20,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c r32 FramesPerSecond = 1.0f / DeltaTime; - string InputCommands = MakeStringLiteral("Default Input Registry - HELLO DAVID"); + string InputCommands = MakeStringLiteral("Default Input Registry"); string NodeListerCommands = MakeStringLiteral("Node Lister Input Registry"); string ActiveInputRegistry = {}; if (State->ActiveCommands == &State->InputCommandRegistry) @@ -31,10 +31,10 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c { ActiveInputRegistry = NodeListerCommands; } - PrintF(&DebugString, "Framerate: %.*f s %d fps | Input: %s", + PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d", 5, DeltaTime, (u32)FramesPerSecond, - ActiveInputRegistry.Memory); + State->Modes.ActiveModesCount); DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, WhiteV4); v2 ButtonDim = v2{200, (r32)NewLineYOffset(*Interface.Font) + 10}; diff --git a/src/foldhaus_interface.cpp b/src/foldhaus_interface.cpp index 22517da..781242c 100644 --- a/src/foldhaus_interface.cpp +++ b/src/foldhaus_interface.cpp @@ -41,6 +41,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(ToggleUniverseDebugView) FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) { + ActivateOperationMode(State->Operation_AddNode, &State->Modes); + State->InterfaceShowNodeLister = true; State->NodeListMenuPosition = Mouse.Pos; SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString); diff --git a/src/foldhaus_operation_mode.h b/src/foldhaus_operation_mode.h new file mode 100644 index 0000000..cd2ce5c --- /dev/null +++ b/src/foldhaus_operation_mode.h @@ -0,0 +1,25 @@ +struct operation_mode +{ + input_command_registry Commands; +}; + +#define OPERATION_MODES_MAX 32 +struct operation_mode_system +{ + s32 ActiveModesCount; + operation_mode ActiveModes[OPERATION_MODES_MAX]; +}; + +internal void +ActivateOperationMode (operation_mode Mode, operation_mode_system* System) +{ + Assert(System->ActiveModesCount < OPERATION_MODES_MAX); + System->ActiveModes[System->ActiveModesCount++] = Mode; +} + +internal void +DeactivateCurrentOperationMode (operation_mode_system* System) +{ + Assert(System->ActiveModesCount > 0); + System->ActiveModesCount--; +} \ No newline at end of file diff --git a/src/foldhaus_search_lister.cpp b/src/foldhaus_search_lister.cpp index 7224922..14f455a 100644 --- a/src/foldhaus_search_lister.cpp +++ b/src/foldhaus_search_lister.cpp @@ -1,77 +1,60 @@ -internal string* -GetStringAtIndex (search_lister Lister, s32 Index) -{ - string* Result = 0; - Assert(Index >= 0 && Index < Lister.ListLength); - - u8* Element = Lister.ListMemory + (Lister.ElementStride * Index); - Result = (string*)(Element + Lister.OffsetToStringInElement); - - return Result; -} - -#define InitializeSearchLister(SearchLister, List, ListLength, StringFieldName) \ -s32 ElementStride = (u8*)(List + 1) - (u8*)(List); \ -s32 OffsetToString = (u8*)(List->#StringFieldName) - (u8*)(List); \ -InitializeSearchLister_((u8*)List, ListLength, ElementStride, OffsetToString); \ - internal void -InitializeSearchLister_(search_lister* Lister, - u8* ListMemory, - s32 ListLength, - s32 ElementStride, - s32 OffsetToString) +FilterSearchLister (search_lister* SearchLister) { - Lister->ListLength = ListLength; - Lister->ListMemory = ListMemory; - Lister->OffsetToStringInElement = OffsetToString; - Lister->ElementStride = ElementStride; - Lister->Filter.Length = 0; + Assert(SearchLister->FilteredIndexLUT != 0); + Assert(SearchLister->FilteredListMax == SearchLister->SourceListCount); + SearchLister->FilteredListCount = 0; + + for (s32 i = 0; i < SearchLister->SourceListCount; i++) + { + string* NameString = SearchLister->SourceList + i; + if (SpecificationPassesFilter(*NameString, SearchLister->Filter)) + { + SearchLister->FilteredIndexLUT[SearchLister->FilteredListCount++] = i; + } + } } internal s32 -GetNextHotItemIndex (s32 CurrentHotItem, s32 ListLength) +GetNextFilteredItem (search_lister SearchLister) { - s32 Result = GSMin(CurrentHotItem + 1, ListLength - 1); + s32 Result = GSMin(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1); return Result; } internal s32 -GetPrevHotItemIndex (s32 CurrentHotItem) +GetPrevFilteredItem (search_lister SearchLister) { - s32 Result = GSMax(0, CurrentHotItem - 1); + s32 Result = GSMax(SearchLister.HotItem - 1, 0); return Result; } FOLDHAUS_INPUT_COMMAND_PROC(SearchListerNextItem) { - State->GeneralPurposeSearchHotItem = GetNextHotItemIndex(State->GeneralPurposeSearchHotItem, NodeSpecificationsCount); + State->SearchLister.HotItem = GetNextFilteredItem(State->SearchLister); } FOLDHAUS_INPUT_COMMAND_PROC(SearchListerPrevItem) { - State->GeneralPurposeSearchHotItem = GetPrevHotItemIndex(State->GeneralPurposeSearchHotItem); + State->SearchLister.HotItem = GetPrevFilteredItem(State->SearchLister); } FOLDHAUS_INPUT_COMMAND_PROC(CloseSearchLister) { + DeactivateCurrentOperationMode(&State->Modes); // TODO(Peter): This is to show the node list. Generalize to just a lister State->InterfaceShowNodeLister = false; // TODO(Peter): This also assumes we know where we came from. Probably need to implement // push/pop functionality for the activecommands. QueueNextFrameCommandRegistry(&State->InputCommandRegistry, State); - State->GeneralPurposeSearchHotItem = -1; } FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseSearchLister) { - s32 HotItem = State->GeneralPurposeSearchHotItem; - s32 ListIndexFromHotItem = NodeListerConvertHotItemToListIndex(HotItem, - (u8*)NodeSpecifications, - NodeSpecificationsCount, - State->ActiveTextEntry.Buffer); - PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[ListIndexFromHotItem], + s32 FilteredNodeIndex = State->SearchLister.HotItem; + s32 NodeIndex = State->SearchLister.FilteredIndexLUT[FilteredNodeIndex]; + PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[NodeIndex], Mouse.Pos, State->NodeRenderSettings, State->Permanent); CloseSearchLister(State, Event, Mouse); } diff --git a/src/foldhaus_search_lister.h b/src/foldhaus_search_lister.h index bb0af8e..0f3ed1d 100644 --- a/src/foldhaus_search_lister.h +++ b/src/foldhaus_search_lister.h @@ -1,9 +1,20 @@ struct search_lister { - s32 ListLength; - u8* ListMemory; - s32 OffsetToStringInElement; - s32 ElementStride; + // TODO(Peter): Giving up trying to just use the source list for now. At the moment + // we are copying the strings you want to filter from and storing them here. Come back + // once its working and make the memory efficient version (ie store the existing memory + // location, the element stride and the offset to the char*) + s32 SourceListCount; + string* SourceList; + + // NOTE(Peter): stores the source indecies of each filtered item + // For example: + // Index 0 in this array contains 3. This means the first item that passes the filter + // is index 3 in ListMemory + s32 FilteredListMax; + s32 FilteredListCount; + s32* FilteredIndexLUT; + s32 HotItem; string Filter; -}; \ No newline at end of file +}; diff --git a/src/gs_string.h b/src/gs_string.h index 9548c29..d7986f5 100644 --- a/src/gs_string.h +++ b/src/gs_string.h @@ -1749,6 +1749,7 @@ PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) if (SignedInt < 0) { OutChar(&TempDest, '-'); + SignedInt *= -1; } U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); } diff --git a/src/interface.h b/src/interface.h index b67bf2d..f730079 100644 --- a/src/interface.h +++ b/src/interface.h @@ -579,12 +579,11 @@ typedef string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLen internal search_lister_result EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimension, string Title, - s32 ListLength, u8* ListMemory, s32 HotItem, search_lister_get_list_item_at_offset* GetListItem, + string* ItemList, s32* ListLUT, s32 ListLength, + s32 HotItem, string* SearchString, s32 SearchStringCursorPosition, bitmap_font* Font, interface_config Config, gui_mouse Mouse) { - Assert(GetListItem != 0); - search_lister_result Result = {}; Result.ShouldRemainOpen = true; Result.HotItem = HotItem; @@ -592,6 +591,10 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens // Title Bar PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, v4{.3f, .3f, .3f, 1.f}); DrawString(RenderBuffer, Title, Font, 14, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4); + + MakeStringBuffer(DebugString, 256); + PrintF(&DebugString, "Hot Item: %d", HotItem); + DrawString(RenderBuffer, DebugString, Font, 14, v2{TopLeft.x + 256, TopLeft.y - 25}, WhiteV4); TopLeft.y -= 30; // Search Bar @@ -599,30 +602,29 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens DrawStringWithCursor(RenderBuffer, *SearchString, SearchStringCursorPosition, Font, 14, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4); TopLeft.y -= 30; - s32 VisibleItemIndex = 0; - - string ListItemText = GetListItem(ListMemory, ListLength, *SearchString, VisibleItemIndex); - while(ListItemText.Length > 0) + for (s32 i = 0; i < ListLength; i++) { + s32 FilteredIndex = ListLUT[i]; + string ListItemString = ItemList[FilteredIndex]; + v2 Min = v2{TopLeft.x, TopLeft.y - 30}; v2 Max = Min + Dimension - v2{0, Config.Margin.y}; v4 ButtonColor = Config.ButtonColor_Inactive; - if (VisibleItemIndex == HotItem) + if (i == HotItem) { ButtonColor = Config.ButtonColor_Active; } - button_result Button = EvaluateButton(RenderBuffer, Min, Max, Config.Margin, ListItemText, - ButtonColor, ButtonColor, Config.TextColor, Config.TextColor, + button_result Button = EvaluateButton(RenderBuffer, Min, Max, Config.Margin, ListItemString, + ButtonColor, ButtonColor, Config.TextColor, Config.TextColor, Config.Font, Mouse); if (Button.Pressed) { - Result.SelectedItem = VisibleItemIndex; + Result.SelectedItem = i; } TopLeft.y -= 30; - ListItemText = GetListItem(ListMemory, ListLength, *SearchString, ++VisibleItemIndex); } return Result; diff --git a/todo.txt b/todo.txt index 1460261..7e062d5 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,26 @@ TODO FOLDHAUS +Intermediate Lifetime Memory & Operations +- Intermediate lifetime memory arena +- Temporary memory region = a multi frame operation +- Concept of an operation - temporary memory + interface command registry +- Allow one operation at a time at first +- Push/pop operations on a list? +- Current Operations: +- - View Sculpture +- - View/Edit Nodes +- - Add Node (needs nesting) +- - View SACN + +Plan +- start with adding nodes +- push/pop an operation +- create operation structure +- static size of operations list +- move command registry out of search lister and text entry into operation +- initialize/cleanup add node operation +- extend to other operations + Hardening - memory visualization - separate rendering thread