Fixed input handling for events that need to be held. Added support for events that only get called on a button release

This commit is contained in:
Peter Slattery 2019-11-01 09:09:05 -07:00
parent 10cc9a4e95
commit 22e15858e5
8 changed files with 103 additions and 76 deletions

View File

@ -350,18 +350,18 @@ RELOAD_STATIC_DATA(ReloadStaticData)
if (State->InputCommandRegistry.Size > 0)
{
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_MouseLeftButton, true, KeyCode_Invalid,
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_MouseLeftButton, Command_Began | Command_Held | Command_Ended, KeyCode_Invalid,
CameraMouseControl);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, false, KeyCode_Invalid, OpenUniverseView);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, OpenNodeLister);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Tab, false, KeyCode_Invalid, OpenNodeView);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, Command_Began, KeyCode_Invalid, OpenUniverseView);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, Command_Began, KeyCode_Invalid, OpenNodeLister);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Tab, Command_Began, KeyCode_Invalid, OpenNodeView);
// Node Lister
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);
RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_DownArrow, Command_Began, KeyCode_Invalid, NodeListerNextItem);
RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_UpArrow, Command_Began, KeyCode_Invalid, NodeListerPrevItem);
RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Enter, Command_Began, KeyCode_Invalid, SelectAndCloseNodeLister);
RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, CloseNodeLister);
RegisterKeyPressCommand(&State->NodeListerCommandRegistry, KeyCode_Esc, Command_Began, KeyCode_Invalid, CloseNodeLister);
InitializeTextInputCommands(&State->NodeListerCommandRegistry, State->Permanent);
}
}
@ -511,12 +511,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
ActivateQueuedCommandRegistry(State);
// CommandQueue holds the list of commands, generated from the current InputCommandRegistry
// Every command entry in the queue should be executed.
// For every Input Event, attempt to add an entry to the CommandQueue if an appropriate command
// exists in ActiveCommands
RemoveNonPersistantCommandsFromQueueAndUpdatePersistentEvents(&State->CommandQueue);
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{
input_entry Event = InputQueue.Entries[EventIdx];
@ -524,13 +518,23 @@ UPDATE_AND_RENDER(UpdateAndRender)
input_command* Command = FindExistingCommand(ActiveCommands, Event.Key, (key_code)0);
if (Command)
{
if (KeyTransitionedDown(Event))
if ((KeyTransitionedDown(Event) && ((Command->Flags & Command_Began) > 0)))
{
PushCommandOnQueue(&State->CommandQueue, *Command, Event);
PushCommandOnQueue(&State->CommandQueue,
*Command,
Event,
(Command->Flags & Command_Held) == 0);
}
else if (Command->PersistsUntilReleased && KeyTransitionedUp(Event))
else if (KeyTransitionedUp(Event) && ((Command->Flags & Command_Ended) > 0))
{
RemoveCommandFromQueue(&State->CommandQueue, *Command, Event);
if ((Command->Flags & Command_Held) == 0)
{
PushCommandOnQueue(&State->CommandQueue, *Command, Event, true);
}
else
{
FlagCommandForRemoval(&State->CommandQueue, *Command, Event);
}
}
}
@ -552,11 +556,13 @@ UPDATE_AND_RENDER(UpdateAndRender)
}
// Execute all commands in CommandQueue
for (s32 CommandIdx = 0; CommandIdx < State->CommandQueue.Used; CommandIdx++)
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
{
command_queue_entry Entry = State->CommandQueue.Commands[CommandIdx];
Entry.Command.Proc(State, Entry.Event, Mouse);
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
Entry->Command.Proc(State, Entry->Event, Mouse);
}
RemoveNonPersistantCommandsFromQueueAndUpdatePersistentEvents(&State->CommandQueue);
}
if (State->LEDBufferList)
@ -746,9 +752,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
// Figuring Out Nodes
//////////////////////////////////////
//NodeViewMousePickNode(State, {}, Mouse);
//RenderNodeView(State, RenderBuffer, {}, Mouse);
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
{
operation_mode OperationMode = State->Modes.ActiveModes[m];

View File

@ -29,7 +29,7 @@ FindExistingCommand (input_command_registry* CommandRegistry, key_code Key, key_
internal void
RegisterKeyPressCommand (input_command_registry* CommandRegistry,
key_code Key,
b32 PersistsUntilReleased,
b32 Flags,
key_code Mdfr,
input_command_proc* Proc)
{
@ -44,7 +44,7 @@ RegisterKeyPressCommand (input_command_registry* CommandRegistry,
}
Command->Key = Key;
Command->PersistsUntilReleased = PersistsUntilReleased;
Command->Flags = Flags;
Command->Mdfr = Mdfr;
Command->Proc = Proc;
}
@ -56,6 +56,22 @@ RegisterMouseWheelCommand (input_command_registry* CommandRegistry,
CommandRegistry->MouseWheelCommand = Proc;
}
internal s32
GetCommandIndexInQueue(input_command_queue* Queue, input_command Command, input_entry Event)
{
s32 Result = -1;
for (s32 CommandIndex = 0; CommandIndex < Queue->Used; CommandIndex++)
{
command_queue_entry* Entry = Queue->Commands + CommandIndex;
if(Entry->Event.Key == Event.Key)
{
Result = CommandIndex;
break;
}
}
return Result;
}
internal input_command_queue
InitializeCommandQueue(command_queue_entry* Memory, s32 MemorySize)
{
@ -73,7 +89,7 @@ RemoveNonPersistantCommandsFromQueueAndUpdatePersistentEvents(input_command_queu
for (s32 i = 0; i < Queue->Used; i++)
{
command_queue_entry* Entry = Queue->Commands + i;
if (Entry->Command.PersistsUntilReleased)
if (!Entry->RemoveOnExecute)
{
Entry->Event.State |= KeyState_WasDown;
// NOTE(Peter): If i == PersistantCommandsCount, then we don't need to copy the
@ -89,27 +105,42 @@ RemoveNonPersistantCommandsFromQueueAndUpdatePersistentEvents(input_command_queu
}
internal void
PushCommandOnQueue(input_command_queue* Queue, input_command Command, input_entry Event)
PushCommandOnQueue(input_command_queue* Queue, input_command Command, input_entry Event, b32 RemoveOnExecute)
{
Assert(Queue->Used < Queue->Size);
command_queue_entry Entry = {};
Entry.Command = Command;
Entry.Event = Event;
Entry.RemoveOnExecute = RemoveOnExecute;
Queue->Commands[Queue->Used++] = Entry;
}
internal void
FlagCommandForRemoval(input_command_queue* Queue, input_command Command, input_entry Event)
{
s32 CommandIndex = GetCommandIndexInQueue(Queue, Command, Event);
Queue->Commands[CommandIndex].RemoveOnExecute = true;
}
internal void
RemoveCommandFromQueue(input_command_queue* Queue, s32 Index)
{
s32 CommandIndex = Index;
if (CommandIndex < Queue->Used)
{
Queue->Used -= 1;
for (; CommandIndex < Queue->Used; CommandIndex++)
{
Queue->Commands[CommandIndex] = Queue->Commands[CommandIndex + 1];
}
}
}
internal void
RemoveCommandFromQueue(input_command_queue* Queue, input_command Command, input_entry Event)
{
s32 CommandIndex = 0;
for (CommandIndex = 0; CommandIndex < Queue->Used; CommandIndex++)
{
command_queue_entry* Entry = Queue->Commands + CommandIndex;
if(Entry->Event.Key == Event.Key)
{
break;
}
}
s32 CommandIndex = GetCommandIndexInQueue(Queue, Command, Event);
// NOTE(Peter): If we made it through the queue without finding an event, there wasn't one
// to remove. This happens when we've changed command registries as a result of an input command,
@ -121,15 +152,7 @@ RemoveCommandFromQueue(input_command_queue* Queue, input_command Command, input_
// For this reason, I'm allowing the case where we try and remove a command where non exists
// I don't think this is a great solution but Im not super familiar with the codebase right now
// so leaving it as is. revisit if it becomes a problem.
if (CommandIndex < Queue->Used)
{
Queue->Used -= 1;
for (; CommandIndex < Queue->Used; CommandIndex++)
{
Queue->Commands[CommandIndex] = Queue->Commands[CommandIndex + 1];
}
}
RemoveCommandFromQueue(Queue, CommandIndex);
}
internal void

View File

@ -1,21 +1,19 @@
#if USAGE_CODE
RegisterInputCommand(KeyCode_UpArrow, SACNView_DrawNextUniverse, Context);
RegisterInputCommand(KeyCode_MouseLeftButton, PanCamera, Context);
ExecuteRegisteredCommands(Context, Input);
#endif // USAGE_CODE
#define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse)
typedef FOLDHAUS_INPUT_COMMAND_PROC(input_command_proc);
enum input_command_flags
{
Command_Began = 1 << 0,
Command_Held = 1 << 1,
Command_Ended = 1 << 2,
};
// TODO(Peter): At the moment these are all key press commands. Need a way to differentiate between
// press and hold. Probably add a second array to input_command_Registry
struct input_command
{
key_code Key;
b32 PersistsUntilReleased;
b32 Flags;
key_code Mdfr;
input_command_proc* Proc;
};
@ -33,6 +31,7 @@ struct command_queue_entry
{
input_command Command;
input_entry Event;
b32 RemoveOnExecute;
};
struct input_command_queue

View File

@ -20,12 +20,13 @@ 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",
PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d",
5, DeltaTime,
(u32)FramesPerSecond,
State->Modes.ActiveModesCount,
State->Modes.Arena.CurrentRegion->Used,
State->Modes.Arena.CurrentRegion->Size);
State->Modes.Arena.CurrentRegion->Size,
State->CommandQueue.Used);
DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, WhiteV4);
v2 ButtonDim = v2{200, (r32)NewLineYOffset(*Interface.Font) + 10};

View File

@ -109,8 +109,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenUniverseView)
{ // Mode Commands
InitializeInputCommandRegistry(&UniverseViewMode->Commands, 3, &State->Modes.Arena);
RegisterKeyPressCommand(&UniverseViewMode->Commands, KeyCode_MouseLeftButton, true, KeyCode_Invalid, UniverseViewPan);
RegisterKeyPressCommand(&UniverseViewMode->Commands, KeyCode_U, false, KeyCode_Invalid, CloseUniverseView);
RegisterKeyPressCommand(&UniverseViewMode->Commands, KeyCode_MouseLeftButton, Command_Began | Command_Ended, KeyCode_Invalid, UniverseViewPan);
RegisterKeyPressCommand(&UniverseViewMode->Commands, KeyCode_U, Command_Began, KeyCode_Invalid, CloseUniverseView);
RegisterMouseWheelCommand(&UniverseViewMode->Commands, UniverseZoom);
}
@ -198,11 +198,11 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister)
{ // 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);
RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_DownArrow, Command_Began, KeyCode_Invalid, NodeListerNextItem);
RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_UpArrow, Command_Began, KeyCode_Invalid, NodeListerPrevItem);
RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_Enter, Command_Began, KeyCode_Invalid, SelectAndCloseNodeLister);
RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_MouseLeftButton, Command_Began, KeyCode_Invalid, CloseNodeLister);
RegisterKeyPressCommand(&AddNodeOperation->Commands, KeyCode_Esc, Command_Began, KeyCode_Invalid, CloseNodeLister);
InitializeTextInputCommands(&AddNodeOperation->Commands, &State->Modes.Arena);
}
@ -373,9 +373,9 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView)
{ // Mode Commands
InitializeInputCommandRegistry(&NodeViewMode->Commands, 3, &State->Modes.Arena);
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_Tab, false, KeyCode_Invalid, CloseNodeView);
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_A, false, KeyCode_Invalid, OpenNodeLister);
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_MouseLeftButton, true, KeyCode_Invalid,
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_Tab, Command_Began, KeyCode_Invalid, CloseNodeView);
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_A, Command_Began, KeyCode_Invalid, OpenNodeLister);
RegisterKeyPressCommand(&NodeViewMode->Commands, KeyCode_MouseLeftButton, Command_Began | Command_Ended, KeyCode_Invalid,
NodeViewMousePickNode);
}

View File

@ -107,13 +107,13 @@ InitializeTextInputCommands (input_command_registry* Commands, memory_arena* Per
{
if (Commands->Size > 0)
{
RegisterKeyPressCommand(Commands, KeyCode_Backspace, false, KeyCode_Invalid, RemoveCharacterFromEntryString);
RegisterKeyPressCommand(Commands, KeyCode_LeftArrow, false, KeyCode_Invalid, TextEntryMoveCursorLeft);
RegisterKeyPressCommand(Commands, KeyCode_RightArrow, false, KeyCode_Invalid, TextEntryMoveCursorRight);
RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began, KeyCode_Invalid, RemoveCharacterFromEntryString);
RegisterKeyPressCommand(Commands, KeyCode_LeftArrow, Command_Began, KeyCode_Invalid, TextEntryMoveCursorLeft);
RegisterKeyPressCommand(Commands, KeyCode_RightArrow, Command_Began, KeyCode_Invalid, TextEntryMoveCursorRight);
for (s32 i = KeyCode_a; i < KeyCode_UpArrow; i++)
{
RegisterKeyPressCommand(Commands, (key_code)i, false, KeyCode_Invalid, TextEntryInsertChar);
RegisterKeyPressCommand(Commands, (key_code)i, Command_Began, KeyCode_Invalid, TextEntryInsertChar);
}
}

View File

@ -379,6 +379,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true,
ShiftDown, AltDown, CtrlDown, false);
Mouse->DownPos = Mouse->Pos;
}break;

View File

@ -8,7 +8,7 @@ x Allow one operation at a time at first
x Push/pop operations on a list?
- Current Operations:
- - View Sculpture (this might be an exception since its so central)
- - View/Edit Nodes
x - View/Edit Nodes
- x Add Node (needs nesting)
- x View SACN