Implemented text input into float fields. Small fixes to the node search bar, beginning to pull it out into a standalone piece.

This commit is contained in:
Peter Slattery 2019-09-01 23:03:38 -07:00
parent 8040479379
commit 594e4257e0
11 changed files with 232 additions and 128 deletions

View File

@ -348,7 +348,7 @@ RELOAD_STATIC_DATA(ReloadStaticData)
CameraMouseControl);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, false, KeyCode_Invalid, ToggleUniverseDebugView);
RegisterMouseWheelCommand(&State->InputCommandRegistry, CameraMouseZoom);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, AddNode);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, OpenNodeLister);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Tab, false, KeyCode_Invalid, ToggleNodeDisplay);
InitializeTextInputCommands(&State->TextEntryCommandRegistry, State->Permanent);
@ -370,6 +370,8 @@ INITIALIZE_APPLICATION(InitializeApplication)
InitializeInputCommandRegistry(&State->TextEntryCommandRegistry, 32, State->Permanent);
State->ActiveCommands = &State->InputCommandRegistry;
State->ActiveTextEntry.Buffer = MakeString(PushArray(State->Permanent, char, 256), 0, 256);
// TODO(Peter): put in InitializeInterface?
r32 FontSize = 14;
{
@ -451,10 +453,6 @@ INITIALIZE_APPLICATION(InitializeApplication)
LoadAssembly(State, Context, Path);
#endif
State->InterfaceState.AddingPattern = false;
State->InterfaceState.PatternSelectorStart = 0;
State->InterfaceState.ChannelSelected = -1;
State->InterfaceYMax = 200;
State->PixelsToWorldScale = .01f;
State->Camera_StartDragPos = {};
@ -466,7 +464,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->NodeList = AllocateNodeList(State->Permanent, Kilobytes(64));
State->NodeInteraction = NewNodeInteraction();
State->NodeInteraction = NewEmptyNodeInteraction();
State->NodeRenderSettings.PortDim = v2{20, 15};
State->NodeRenderSettings.PortStep = State->NodeRenderSettings.PortDim.y + 10;
State->NodeRenderSettings.PortColors[MemberType_r32] = RedV4;
@ -476,8 +474,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Permanent);
State->GeneralPurposeSearch.Backbuffer = PushArray(State->Permanent, char, 256);
InitializeEmptyString(&State->GeneralPurposeSearch.Buffer, State->GeneralPurposeSearch.Backbuffer, 256);
InitializeEmptyString(&State->GeneralPurposeSearchString, PushArray(State->Permanent, char, 256), 256);
ReloadStaticData(Context, GlobalDebugServices);
}
@ -494,7 +491,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
if (State->ActiveCommands == &State->TextEntryCommandRegistry)
{
AppendInputToEntryString(State->ActiveTextEntry, Input.New->StringInput, Input.New->StringInputUsed);
AppendInputToEntryString(&State->ActiveTextEntry, Input.New->StringInput, Input.New->StringInputUsed);
}
ExecuteAllRegisteredCommands(State->ActiveCommands, Input, State);
@ -736,40 +733,78 @@ UPDATE_AND_RENDER(UpdateAndRender)
///////////////////////////////////////
// Figuring Out Nodes
//////////////////////////////////////
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
v2 LastFrameMousePos = v2{(r32)Input.Old->MouseX, (r32)Input.Old->MouseY};
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton))
{
node_offset Node = GetNodeUnderPoint(State->NodeList, MousePos, State->NodeRenderSettings);
if (Node.Node)
{
State->NodeInteraction = GetNodeInteractionType(Node.Node, Node.Offset, MousePos, State->NodeRenderSettings);
}
}
else if (KeyTransitionedUp(Input, KeyCode_MouseLeftButton))
{
if (IsDraggingNodePort(State->NodeInteraction))
{
TryConnectNodes(State->NodeInteraction, MousePos, State->NodeList, State->NodeRenderSettings);
State->NodeInteraction = NewEmptyNodeInteraction();
}
else if(IsDraggingNodeValue(State->NodeInteraction))
{
v2 MouseDelta = MousePos - LastFrameMousePos;
// This is just a click
if (Mag(MouseDelta) < 10)
{
node_interaction Interaction = State->NodeInteraction;
interface_node* Node = GetNodeAtOffset(State->NodeList, Interaction.NodeOffset);
node_connection* Connection = Node->Connections + Interaction.InputValue;
struct_member_type InputType = Connection->Type;
if (InputType == MemberType_r32)
{
SetTextInputDestinationToFloat(&State->ActiveTextEntry, &Connection->R32Value);
}
State->NodeInteraction = NewEmptyNodeInteraction();
State->ActiveCommands = &State->TextEntryCommandRegistry;
}
else // This is the case where you dragged the value
{
State->NodeInteraction = NewEmptyNodeInteraction();
}
}
else
{
State->NodeInteraction = NewEmptyNodeInteraction();
}
}
UpdateDraggingNode(MousePos, State->NodeInteraction, State->NodeList,
State->NodeRenderSettings);
UpdateDraggingNodePort(MousePos, State->NodeInteraction, State->NodeList,
State->NodeRenderSettings, RenderBuffer);
UpdateDraggingNodeValue(MousePos, LastFrameMousePos, State->NodeInteraction, State->NodeList, State->NodeRenderSettings, State);
ResetNodesUpdateState(State->NodeList);
if (State->NodeRenderSettings.Display)
{
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
v2 LastFrameMousePos = v2{(r32)Input.Old->MouseX, (r32)Input.Old->MouseY};
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton))
{
node_offset Node = GetNodeUnderPoint(State->NodeList, MousePos, State->NodeRenderSettings);
if (Node.Node)
{
State->NodeInteraction = GetNodeInteractionType(Node.Node, Node.Offset, MousePos, State->NodeRenderSettings);
}
}
else if (KeyTransitionedUp(Input, KeyCode_MouseLeftButton))
{
if (IsDraggingNodePort(State->NodeInteraction))
{
TryConnectNodes(State->NodeInteraction, MousePos, State->NodeList, State->NodeRenderSettings);
}
State->NodeInteraction = NewNodeInteraction();
}
UpdateDraggingNode(MousePos, State->NodeInteraction, State->NodeList,
State->NodeRenderSettings);
UpdateDraggingNodePort(MousePos, State->NodeInteraction, State->NodeList,
State->NodeRenderSettings, RenderBuffer);
UpdateDraggingNodeValue(MousePos, LastFrameMousePos, State->NodeInteraction, State->NodeList, State->NodeRenderSettings, State);
RenderNodeList(State->NodeList, State->NodeRenderSettings, RenderBuffer);
ResetNodesUpdateState(State->NodeList);
if (State->InterfaceShowNodeList)
{
if (KeyTransitionedDown(Input, KeyCode_DownArrow))
{
SearchListerNextItem(State, Input);
}
if (KeyTransitionedDown(Input, KeyCode_UpArrow))
{
SearchListerPrevItem(State, Input);
}
v2 TopLeft = State->NodeListMenuPosition;
v2 Dimension = v2{300, 30};
@ -778,28 +813,27 @@ UPDATE_AND_RENDER(UpdateAndRender)
NodeSpecificationsCount, (u8*)NodeSpecifications,
State->GeneralPurposeSearchHotItem,
NodeListerGetNodeName,
&State->GeneralPurposeSearch.Buffer,
State->GeneralPurposeSearch.CursorPosition,
&State->ActiveTextEntry.Buffer,
State->ActiveTextEntry.CursorPosition,
State->Font, State->Interface, Input);
State->GeneralPurposeSearchHotItem = NodeListResult.HotItem;
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) ||
KeyTransitionedDown(Input, KeyCode_Esc))
{
State->InterfaceShowNodeList = false;
DeactivateTextEntry(State);
}
if (KeyTransitionedDown(Input, KeyCode_Enter))
{
State->InterfaceShowNodeList = false;
if (NodeListResult.HotItem > 0)
{
PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[NodeListResult.HotItem],
MousePos, State->NodeRenderSettings, State->Permanent);
}
NodeListResult.SelectedItem = NodeListResult.HotItem;
}
if (NodeListResult.SelectedItem >= 0)
{
PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[NodeListResult.SelectedItem],
MousePos, State->NodeRenderSettings, State->Permanent);
CloseSearchLister(State, Input);
}
else if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) ||
KeyTransitionedDown(Input, KeyCode_Esc))
{
CloseSearchLister(State, Input);
}
}
}

View File

@ -51,6 +51,7 @@ typedef struct app_state app_state;
#include "foldhaus_debug_visuals.h"
#include "foldhaus_command_dispatch.h"
#include "foldhaus_text_entry.h"
#include "foldhaus_default_nodes.h"
@ -62,18 +63,12 @@ struct app_state
memory_arena* Transient;
memory_arena SACNMemory;
/*
render_texture* LoadedTextures;
s32 LoadedTexturesSize;
s32 LoadedTexturesUsed;
*/
camera Camera;
input_command_registry InputCommandRegistry;
input_command_registry TextEntryCommandRegistry;
input_command_registry* ActiveCommands;
text_input* ActiveTextEntry;
text_input ActiveTextEntry;
streaming_acn SACN;
s32 TotalLEDsCount;
@ -87,7 +82,6 @@ struct app_state
s32 AssembliesUsed;
bitmap_font* Font;
interface_state InterfaceState;
interface_config Interface;
r32 InterfaceYMax;
@ -108,11 +102,12 @@ struct app_state
v4* ColorPickerEditValue;
text_input GeneralPurposeSearch;
string GeneralPurposeSearchString;
s32 GeneralPurposeSearchHotItem;
};
#include "foldhaus_search_lister.h"
#include "foldhaus_sacn_view.cpp"
#include "foldhaus_command_dispatch.cpp"
#include "foldhaus_node.cpp"

View File

@ -50,11 +50,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(ToggleUniverseDebugView)
}
FOLDHAUS_INPUT_COMMAND_PROC(AddNode)
FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister)
{
State->InterfaceShowNodeList = true;
State->NodeListMenuPosition = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
ActivateTextEntry(&State->GeneralPurposeSearch, State);
SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString);
State->ActiveCommands = &State->TextEntryCommandRegistry;
}
FOLDHAUS_INPUT_COMMAND_PROC(ToggleNodeDisplay)

View File

@ -1,23 +0,0 @@
enum interface_selection_type
{
InterfaceSelection_None,
InterfaceSelection_Channel,
InterfaceSelection_Pattern,
};
struct interface_state
{
b32 AddingPattern;
s32 ChannelSelectorStart;
s32 ChannelSelected;
s32 ActiveChannelPatternSelectorStart;
s32 ActiveChannelPatternSelected;
s32 PatternSelectorStart;
b32 ChooseOperationPanelOpen;
interface_selection_type SelectionType;
};

View File

@ -271,7 +271,7 @@ CalculateNodeDragHandleBounds (rect NodeBounds, s32 Index, node_render_settings
}
internal node_interaction
NewNodeInteraction ()
NewEmptyNodeInteraction ()
{
node_interaction Result = {};
Result.NodeOffset = -1;
@ -282,6 +282,19 @@ NewNodeInteraction ()
return Result;
}
internal node_interaction
NewNodeInteraction (s32 NodeOffset, v2 MouseOffset)
{
node_interaction Result = {};
Result.NodeOffset = NodeOffset;
Result.MouseOffset = MouseOffset;
Result.InputPort = -1;
Result.InputValue = -1;
Result.OutputPort = -1;
Result.OutputValue = -1;
return Result;
}
internal b32
IsDraggingNode (node_interaction Interaction)
{
@ -431,7 +444,6 @@ ConnectionIsOutput (interface_node* Node, s32 ConnectionIdx)
return ConnectionIsOutput(Node->Connections[ConnectionIdx]);
}
internal b32
CheckForRecursion (node_list* NodeList, s32 LookForNode, interface_node* StartNode)
{
@ -535,10 +547,7 @@ GetNodeInteractionType (interface_node* ActiveNode, s32 NodeOffset, v2 MousePos,
{
DEBUG_TRACK_FUNCTION;
node_interaction Interaction = NewNodeInteraction();
Interaction.NodeOffset = NodeOffset;
Interaction.MouseOffset = ActiveNode->Min - MousePos;
node_interaction Interaction = NewNodeInteraction(NodeOffset, ActiveNode->Min - MousePos);
rect NodeBounds = CalculateNodeBounds(ActiveNode, RenderSettings);

View File

@ -21,10 +21,10 @@ s32 name##LEDCount;
enum mouse_node_interaction
{
MouseNodeInteraction_None,
MouseNodeInteraction_DragNode,
MouseNodeInteraction_DragInput,
NodeInteraction_None,
NodeInteraction_MouseDragNode,
NodeInteraction_MouseDragInput,
NodeInteraction_KeyboardEnterPortValue,
MouseNodeInteraction_Count,
};
@ -37,6 +37,7 @@ enum node_port_direction
// TODO(Peter): Generate this
enum struct_member_type
{
MemberType_Invalid,
MemberType_s32,
MemberType_r32,
MemberType_v4,
@ -121,6 +122,8 @@ struct node_interaction
v2 MouseOffset;
b32 Flags;
// TODO(Peter): Inputs and outputs are all stored in the same array. Should this just be flags,
// and we store the Port and Value?
s32 InputPort;
s32 InputValue;
s32 OutputPort;

33
foldhaus_search_lister.h Normal file
View File

@ -0,0 +1,33 @@
internal s32
GetNextHotItem (s32 CurrentHotItem, s32 ListLength)
{
s32 Result = GSMin(CurrentHotItem + 1, ListLength - 1);
return Result;
}
internal s32
GetPrevHotItem (s32 CurrentHotItem)
{
s32 Result = GSMax(0, CurrentHotItem - 1);
return Result;
}
FOLDHAUS_INPUT_COMMAND_PROC(SearchListerNextItem)
{
State->GeneralPurposeSearchHotItem = GetNextHotItem(State->GeneralPurposeSearchHotItem, NodeSpecificationsCount);
}
FOLDHAUS_INPUT_COMMAND_PROC(SearchListerPrevItem)
{
State->GeneralPurposeSearchHotItem = GetPrevHotItem(State->GeneralPurposeSearchHotItem);
}
FOLDHAUS_INPUT_COMMAND_PROC(CloseSearchLister)
{
// TODO(Peter): This is to show the node list. Generalize to just a lister
State->InterfaceShowNodeList = false;
// TODO(Peter): This also assumes we know where we came from. Probably need to implement
// push/pop functionality for the activecommands.
State->ActiveCommands = &State->InputCommandRegistry;
State->GeneralPurposeSearchHotItem = -1;
}

View File

@ -1,28 +1,60 @@
internal void
ResetTextInput (text_input* Input)
{
Input->CursorPosition = 0;
Input->Buffer.Length = 0;
}
internal void
PipeSearchStringToDestination (text_input* Input)
{
switch (Input->Destination.Type)
{
case TextTranslateTo_String:
{
CopyStringTo(Input->Buffer, Input->Destination.StringDest);
}break;
case TextTranslateTo_R32:
{
parse_result FloatParseResult = ParseFloat(Input->Buffer.Memory, Input->Buffer.Length);
*Input->Destination.FloatDest = FloatParseResult.FloatValue;
}break;
InvalidDefaultCase;
}
}
FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntryString)
{
if (State->GeneralPurposeSearch.CursorPosition > 0)
if (State->ActiveTextEntry.CursorPosition > 0)
{
RemoveCharAt(&State->GeneralPurposeSearch.Buffer,
State->GeneralPurposeSearch.CursorPosition - 1);
State->GeneralPurposeSearch.CursorPosition--;
RemoveCharAt(&State->ActiveTextEntry.Buffer,
State->ActiveTextEntry.CursorPosition - 1);
State->ActiveTextEntry.CursorPosition--;
}
}
internal void
ActivateTextEntry(text_input* ActiveEntryString, app_state* State)
SetTextInputDestinationToString (text_input* TextInput, string* DestinationString)
{
State->ActiveTextEntry = ActiveEntryString;
State->ActiveTextEntry->PreviousCommandRegistry = State->ActiveCommands;
State->ActiveCommands = &State->TextEntryCommandRegistry;
ResetTextInput(TextInput);
TextInput->Destination.Type = TextTranslateTo_String;
TextInput->Destination.StringDest = DestinationString;
CopyStringTo(*DestinationString, &TextInput->Buffer);
}
internal void
DeactivateTextEntry(app_state* State)
internal void
SetTextInputDestinationToFloat (text_input* TextInput, r32* DestinationFloat)
{
if (State->ActiveTextEntry->PreviousCommandRegistry != 0)
ResetTextInput(TextInput);
TextInput->Destination.Type = TextTranslateTo_R32;
TextInput->Destination.FloatDest = DestinationFloat;
PrintF(&TextInput->Buffer, "%f", *DestinationFloat);
if (*DestinationFloat == 0.0f)
{
State->ActiveCommands = State->ActiveTextEntry->PreviousCommandRegistry;
State->ActiveTextEntry = 0;
TextInput->CursorPosition = 1;
}
}
@ -37,18 +69,25 @@ AppendInputToEntryString (text_input* EntryString, char* InputString, s32 InputS
EntryString->CursorPosition++;
}
}
PipeSearchStringToDestination(EntryString);
}
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorRight)
{
State->ActiveTextEntry->CursorPosition = GSMin(State->ActiveTextEntry->Buffer.Length,
State->ActiveTextEntry->CursorPosition + 1);
State->ActiveTextEntry.CursorPosition = GSMin(State->ActiveTextEntry.Buffer.Length,
State->ActiveTextEntry.CursorPosition + 1);
}
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorLeft)
{
State->ActiveTextEntry->CursorPosition = GSMax(0,
State->ActiveTextEntry->CursorPosition - 1);
State->ActiveTextEntry.CursorPosition = GSMax(0,
State->ActiveTextEntry.CursorPosition - 1);
}
FOLDHAUS_INPUT_COMMAND_PROC(LeaveTextEntryMode)
{
// TODO(Peter): Make this more flexible. Should return to whatever came before
State->ActiveCommands = &State->InputCommandRegistry;
}
internal void
@ -59,5 +98,7 @@ InitializeTextInputCommands (input_command_registry* SearchCommands, memory_aren
RegisterKeyPressCommand(SearchCommands, KeyCode_Backspace, false, KeyCode_Invalid, RemoveCharacterFromEntryString);
RegisterKeyPressCommand(SearchCommands, KeyCode_LeftArrow, false, KeyCode_Invalid, TextEntryMoveCursorLeft);
RegisterKeyPressCommand(SearchCommands, KeyCode_RightArrow, false, KeyCode_Invalid, TextEntryMoveCursorRight);
RegisterKeyPressCommand(SearchCommands, KeyCode_Enter, false, KeyCode_Invalid,
LeaveTextEntryMode);
}
}

View File

@ -1,7 +1,26 @@
enum text_translation_type
{
TextTranslateTo_String,
TextTranslateTo_R32,
TextTranslateTo_S32,
TextTranslateTo_U32,
};
struct text_input_destination
{
text_translation_type Type;
union {
string* StringDest;
r32* FloatDest;
s32* SignedIntDest;
u32* UnsignedIntDest;
};
};
struct text_input
{
char* Backbuffer;
string Buffer;
s32 CursorPosition;
input_command_registry* PreviousCommandRegistry;
text_input_destination Destination;
};

View File

@ -562,6 +562,7 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin
struct search_lister_result
{
s32 HotItem;
s32 SelectedItem;
b32 ShouldRemainOpen;
};
@ -578,17 +579,7 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens
search_lister_result Result = {};
Result.ShouldRemainOpen = true;
Result.HotItem = HotItem;
// NOTE(Peter): These are direction reversed because going up the list in terms of indicies is
// visually displayed as going down.
if (KeyTransitionedDown(Input, KeyCode_DownArrow))
{
Result.HotItem = GSMin(Result.HotItem + 1, ListLength - 1);
}
if (KeyTransitionedDown(Input, KeyCode_UpArrow))
{
Result.HotItem = GSMax(0, Result.HotItem - 1);
}
Result.SelectedItem = -1;
// Title Bar
PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, v4{.3f, .3f, .3f, 1.f});
@ -624,7 +615,7 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens
Config.Font, Input);
if (Button.Pressed)
{
Result.HotItem = i;
Result.SelectedItem = i;
}
TopLeft.y -= 30;

View File

@ -4,9 +4,10 @@ Hardening
- input context changes
- x don't type into the search bar when its not open
- x don't type into the search bar when you press a to open it
- - type into text boxes
- x type into text boxes
- - shift drag to 10x drag speed
- select nodes -> delete nodes
- open add node menu, click off to the side, it still adds a node.
Name
- Splash screen (like blender) (thisll be fun)