From e51400c3132b34b3bb0ee30008c21595d198b03e Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Fri, 1 Nov 2019 05:46:40 -0700 Subject: [PATCH] Got modes working for the node lister --- src/foldhaus_app.cpp | 88 +++++++--------------- src/foldhaus_app.h | 10 +-- src/foldhaus_debug_visuals.h | 17 +---- src/foldhaus_interface.cpp | 134 ++++++++++++++++++++++++++++++--- src/foldhaus_operation_mode.h | 24 +++++- src/foldhaus_search_lister.cpp | 29 ------- todo.txt | 14 ++-- 7 files changed, 187 insertions(+), 129 deletions(-) diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 9f9adc8..2746c5c 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -357,12 +357,13 @@ RELOAD_STATIC_DATA(ReloadStaticData) RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, OpenNodeLister); RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Tab, false, KeyCode_Invalid, ToggleNodeDisplay); + // Node Lister - RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_DownArrow, false, KeyCode_Invalid, SearchListerNextItem); - RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_UpArrow, false, KeyCode_Invalid, SearchListerPrevItem); - RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Enter, false, KeyCode_Invalid, SelectAndCloseSearchLister); - RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_MouseLeftButton, false, KeyCode_Invalid, CloseSearchLister); - RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Esc, false, KeyCode_Invalid, CloseSearchLister); + RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_DownArrow, false, KeyCode_Invalid, NodeListerNextItem); + RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_UpArrow, false, KeyCode_Invalid, NodeListerPrevItem); + RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Enter, false, KeyCode_Invalid, SelectAndCloseNodeLister); + RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_MouseLeftButton, false, KeyCode_Invalid, CloseNodeLister); + RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Esc, false, KeyCode_Invalid, CloseNodeLister); InitializeTextInputCommands(&State->NodeListerCommandRegistry, State->Permanent); } } @@ -378,10 +379,6 @@ 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; @@ -394,30 +391,6 @@ 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; { @@ -522,6 +495,14 @@ INITIALIZE_APPLICATION(InitializeApplication) InitializeEmptyString(&State->GeneralPurposeSearchString, PushArray(State->Permanent, char, 256), 256); ReloadStaticData(Context, GlobalDebugServices); + + { // MODES PLAYGROUND + State->Modes.ActiveModesCount = 0; + + s32 ModesMemorySize = Kilobytes(32); + u8* ModesMemory = PushSize(State->Permanent, ModesMemorySize); + InitMemoryArena(&State->Modes.Arena, ModesMemory, ModesMemorySize, 0); + } } UPDATE_AND_RENDER(UpdateAndRender) @@ -540,7 +521,14 @@ UPDATE_AND_RENDER(UpdateAndRender) GuiMouse.OldPos = Mouse.OldPos; GuiMouse.DeltaPos = Mouse.DeltaPos; GuiMouse.DownPos = Mouse.DownPos; + { + input_command_registry* ActiveCommands = State->ActiveCommands; + if (State->Modes.ActiveModesCount > 0) + { + ActiveCommands = &State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands; + } + ActivateQueuedCommandRegistry(State); // CommandQueue holds the list of commands, generated from the current InputCommandRegistry @@ -553,7 +541,7 @@ UPDATE_AND_RENDER(UpdateAndRender) { input_entry Event = InputQueue.Entries[EventIdx]; - input_command* Command = FindExistingCommand(State->ActiveCommands, Event.Key, (key_code)0); + input_command* Command = FindExistingCommand(ActiveCommands, Event.Key, (key_code)0); if (Command) { if (KeyTransitionedDown(Event)) @@ -885,32 +873,6 @@ UPDATE_AND_RENDER(UpdateAndRender) if (State->NodeRenderSettings.Display) { RenderNodeList(State->NodeList, State->NodeRenderSettings, RenderBuffer); - - if (State->InterfaceShowNodeLister) - { - 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"), - State->SearchLister.SourceList, - State->SearchLister.FilteredIndexLUT, - State->SearchLister.FilteredListCount, - State->SearchLister.HotItem, - &State->ActiveTextEntry.Buffer, - State->ActiveTextEntry.CursorPosition, - State->Font, State->Interface, GuiMouse); - } } if (State->ColorPickerEditValue != 0) @@ -924,6 +886,12 @@ UPDATE_AND_RENDER(UpdateAndRender) } } + for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) + { + operation_mode OperationMode = State->Modes.ActiveModes[m]; + OperationMode.Render(State, RenderBuffer, OperationMode, GuiMouse); + } + DrawDebugInterface(RenderBuffer, 25, State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, Context.DeltaTime, State, State->Camera, GuiMouse, State->Transient); diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index eca10df..8e36416 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -65,10 +65,11 @@ struct app_state camera Camera; - operation_mode Operation_AddNode; operation_mode_system Modes; input_command_registry InputCommandRegistry; + // TODO(Peter): At the moment this is only still here because text input into nodes utilizes it. + // Get rid of this once Modes are working and you can switch all text input over to various modes input_command_registry NodeListerCommandRegistry; // NOTE(Peter): stores the address of the command registry to be activated next frame. // was having a problem where switching command registry's in the middle of the loop trying to @@ -78,7 +79,6 @@ struct app_state input_command_queue CommandQueue; text_entry ActiveTextEntry; - search_lister SearchLister; streaming_acn SACN; s32 TotalLEDsCount; @@ -101,7 +101,6 @@ struct app_state v2 UniverseOutputDisplayOffset; r32 UniverseOutputDisplayZoom; - b32 InterfaceShowNodeLister; v2 NodeListMenuPosition; node_list* NodeList; @@ -119,5 +118,6 @@ struct app_state #include "foldhaus_command_dispatch.cpp" #include "foldhaus_node.cpp" #include "foldhaus_text_entry.cpp" -#include "foldhaus_interface.cpp" -#include "foldhaus_search_lister.cpp" \ No newline at end of file +#include "foldhaus_search_lister.cpp" + +#include "foldhaus_interface.cpp" \ No newline at end of file diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index 70cf10e..82afb02 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -20,21 +20,12 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c r32 FramesPerSecond = 1.0f / DeltaTime; - string InputCommands = MakeStringLiteral("Default Input Registry"); - string NodeListerCommands = MakeStringLiteral("Node Lister Input Registry"); - string ActiveInputRegistry = {}; - if (State->ActiveCommands == &State->InputCommandRegistry) - { - ActiveInputRegistry = InputCommands; - } - else if (State->ActiveCommands == &State->NodeListerCommandRegistry) - { - ActiveInputRegistry = NodeListerCommands; - } - PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d", + PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d", 5, DeltaTime, (u32)FramesPerSecond, - State->Modes.ActiveModesCount); + State->Modes.ActiveModesCount, + State->Modes.Arena.CurrentRegion->Used, + State->Modes.Arena.CurrentRegion->Size); 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 781242c..64a631c 100644 --- a/src/foldhaus_interface.cpp +++ b/src/foldhaus_interface.cpp @@ -38,18 +38,128 @@ FOLDHAUS_INPUT_COMMAND_PROC(ToggleUniverseDebugView) State->DrawUniverseOutputDisplay = !State->DrawUniverseOutputDisplay; } - -FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) -{ - ActivateOperationMode(State->Operation_AddNode, &State->Modes); - - State->InterfaceShowNodeLister = true; - State->NodeListMenuPosition = Mouse.Pos; - SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString); - State->ActiveCommands = &State->NodeListerCommandRegistry; -} - FOLDHAUS_INPUT_COMMAND_PROC(ToggleNodeDisplay) { State->NodeRenderSettings.Display = !State->NodeRenderSettings.Display; -} \ No newline at end of file +} + +//////////////////////////////////////// +// +// Universe View +// +/////////////////////////////////////// + +OPERATION_RENDER_PROC(RenderUniverseView) +{ + +} + +//////////////////////////////////////// +// +// Node Lister +// +/////////////////////////////////////// + +struct node_lister_operation_state +{ + search_lister SearchLister; +}; + +OPERATION_RENDER_PROC(RenderNodeLister) +{ + node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory; + + v2 TopLeft = State->NodeListMenuPosition; + 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, GuiMouse); +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeListerNextItem) +{ + // TODO(Peter): Pass this in as a parameter + operation_mode Mode = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1]; + node_lister_operation_state* OpState = (node_lister_operation_state*)Mode.OpStateMemory; + OpState->SearchLister.HotItem = GetNextFilteredItem(OpState->SearchLister); +} + +FOLDHAUS_INPUT_COMMAND_PROC(NodeListerPrevItem) +{ + // TODO(Peter): Pass this in as a parameter + operation_mode Mode = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1]; + node_lister_operation_state* OpState = (node_lister_operation_state*)Mode.OpStateMemory; + OpState->SearchLister.HotItem = GetPrevFilteredItem(OpState->SearchLister); +} + +FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeLister) +{ + DeactivateCurrentOperationMode(&State->Modes); +} + +FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseNodeLister) +{ + // TODO(Peter): Pass this in as a parameter + operation_mode Mode = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1]; + node_lister_operation_state* OpState = (node_lister_operation_state*)Mode.OpStateMemory; + + s32 FilteredNodeIndex = OpState->SearchLister.HotItem; + s32 NodeIndex = OpState->SearchLister.FilteredIndexLUT[FilteredNodeIndex]; + PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[NodeIndex], + Mouse.Pos, State->NodeRenderSettings, State->Permanent); + CloseNodeLister(State, Event, Mouse); +} + +FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) +{ + // TODO(Peter): This won't work with hot code reloading + operation_mode* AddNodeOperation = ActivateOperationMode(&State->Modes); + + { // Mode Commands + InitializeInputCommandRegistry(&AddNodeOperation->Commands, 128, &State->Modes.Arena); + RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_DownArrow, false, KeyCode_Invalid, NodeListerNextItem); + RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_UpArrow, false, KeyCode_Invalid, NodeListerPrevItem); + RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_Enter, false, KeyCode_Invalid, SelectAndCloseNodeLister); + RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_MouseLeftButton, false, KeyCode_Invalid, CloseNodeLister); + RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_Esc, false, KeyCode_Invalid, CloseNodeLister); + InitializeTextInputCommands(&AddNodeOperation->Commands, &State->Modes.Arena); + } + + AddNodeOperation->Render = RenderNodeLister; + + node_lister_operation_state* OpState = PushStruct(&State->Modes.Arena, node_lister_operation_state); + AddNodeOperation->OpStateMemory = (u8*)OpState; + { + 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 = State->ActiveTextEntry.Buffer; + + + OpState->SearchLister.FilteredListMax = OpState->SearchLister.SourceListCount; + OpState->SearchLister.FilteredListCount = 0; + OpState->SearchLister.FilteredIndexLUT = PushArray(&State->Modes.Arena, s32, OpState->SearchLister.SourceListCount); + } + + State->NodeListMenuPosition = Mouse.Pos; + SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString); +} diff --git a/src/foldhaus_operation_mode.h b/src/foldhaus_operation_mode.h index cd2ce5c..15535dc 100644 --- a/src/foldhaus_operation_mode.h +++ b/src/foldhaus_operation_mode.h @@ -1,6 +1,13 @@ +typedef struct operation_mode operation_mode; + +#define OPERATION_RENDER_PROC(name) void name(app_state* State, render_command_buffer* RenderBuffer, operation_mode Operation, gui_mouse GuiMouse) +typedef OPERATION_RENDER_PROC(operation_render_proc); + struct operation_mode { input_command_registry Commands; + operation_render_proc* Render; + u8* OpStateMemory; }; #define OPERATION_MODES_MAX 32 @@ -8,18 +15,27 @@ struct operation_mode_system { s32 ActiveModesCount; operation_mode ActiveModes[OPERATION_MODES_MAX]; + arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX]; + + // NOTE(Peter): This acts as mode scoped memory. When a mode gets activated, it can allocate + // temporary memory which then gets freed when the mode is deactivated + memory_arena Arena; }; -internal void -ActivateOperationMode (operation_mode Mode, operation_mode_system* System) +internal operation_mode* +ActivateOperationMode (operation_mode_system* System) { Assert(System->ActiveModesCount < OPERATION_MODES_MAX); - System->ActiveModes[System->ActiveModesCount++] = Mode; + s32 ModeIndex = System->ActiveModesCount++; + System->ActiveModes[ModeIndex] = {}; + System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(System->Arena); + return &System->ActiveModes[ModeIndex]; } internal void DeactivateCurrentOperationMode (operation_mode_system* System) { Assert(System->ActiveModesCount > 0); - System->ActiveModesCount--; + s32 ModeIndex = --System->ActiveModesCount; + ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); } \ No newline at end of file diff --git a/src/foldhaus_search_lister.cpp b/src/foldhaus_search_lister.cpp index 14f455a..0a7db7f 100644 --- a/src/foldhaus_search_lister.cpp +++ b/src/foldhaus_search_lister.cpp @@ -29,32 +29,3 @@ GetPrevFilteredItem (search_lister SearchLister) s32 Result = GSMax(SearchLister.HotItem - 1, 0); return Result; } - -FOLDHAUS_INPUT_COMMAND_PROC(SearchListerNextItem) -{ - State->SearchLister.HotItem = GetNextFilteredItem(State->SearchLister); -} - -FOLDHAUS_INPUT_COMMAND_PROC(SearchListerPrevItem) -{ - 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); -} - -FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseSearchLister) -{ - 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/todo.txt b/todo.txt index 7e062d5..7c8e92d 100644 --- a/todo.txt +++ b/todo.txt @@ -12,13 +12,15 @@ Intermediate Lifetime Memory & Operations - - Add Node (needs nesting) - - View SACN +- Why does backspacing in text entry not save when you close and reopen the node lister? + 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 +x start with adding nodes +x push/pop an operation +x create operation structure +x static size of operations list +x move command registry out of search lister and text entry into operation +x initialize/cleanup add node operation - extend to other operations Hardening