Quickly got the search lister to use the correct index when filtering the list.

This commit is contained in:
Peter Slattery 2019-10-30 09:10:15 -07:00
parent 21d6c1740e
commit e00e90f2fd
13 changed files with 230 additions and 142 deletions

View File

@ -21,6 +21,6 @@ del *.pdb > NUL 2> NUL
REM cl %CommonCompilerFlags% ..\meta\main_meta.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib -incremental:no REM cl %CommonCompilerFlags% ..\meta\main_meta.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib -incremental:no
cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags% cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags%
C:\programs\ctime\ctime.exe -end C:\projects\foldhaus\build\win32_gs_meta_build_time.ctm %LastError% C:\programs\ctime\ctime.exe -end C:\projects\foldhaus_meta\build\win32_gs_meta_build_time.ctm %LastError%
C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_gs_meta_build_time.ctm C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_gs_meta_build_time.ctm
popd popd

View File

@ -25,7 +25,7 @@ load_paths = {
command_list = { command_list = {
{ .name = "build_application", { .name = "build_application",
.out = "*app compilation*", .footer_panel = false, .save_dirty_files = true, .out = "*app compilation*", .footer_panel = false, .save_dirty_files = true,
.cmd = { { "src\\build.bat" , .os = "win" }, .cmd = { { "build.bat" , .os = "win" },
{ "./build.sh", .os = "linux" }, { "./build.sh", .os = "linux" },
{ "./build.sh", .os = "mac" }, }, }, { "./build.sh", .os = "mac" }, }, },
{ .name = "build_meta", { .name = "build_meta",

View File

@ -405,7 +405,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel;
GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight); GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight);
platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", FontSize); platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", FontSize, FontWeight_Normal, false, false, false);
Font->PixelHeight = FontInfo.PixelHeight; Font->PixelHeight = FontInfo.PixelHeight;
Font->Ascent = FontInfo.Ascent; Font->Ascent = FontInfo.Ascent;
Font->Descent = FontInfo.Descent; Font->Descent = FontInfo.Descent;
@ -524,6 +524,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++) for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{ {
input_entry Event = InputQueue.Entries[EventIdx]; input_entry Event = InputQueue.Entries[EventIdx];
input_command* Command = FindExistingCommand(State->ActiveCommands, Event.Key, (key_code)0); input_command* Command = FindExistingCommand(State->ActiveCommands, Event.Key, (key_code)0);
if (Command) if (Command)
{ {
@ -857,12 +858,12 @@ UPDATE_AND_RENDER(UpdateAndRender)
{ {
RenderNodeList(State->NodeList, State->NodeRenderSettings, RenderBuffer); RenderNodeList(State->NodeList, State->NodeRenderSettings, RenderBuffer);
if (State->InterfaceShowNodeList) if (State->InterfaceShowNodeLister)
{ {
v2 TopLeft = State->NodeListMenuPosition; v2 TopLeft = State->NodeListMenuPosition;
v2 Dimension = v2{300, 30}; v2 Dimension = v2{300, 30};
search_lister_result NodeListResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension, search_lister_result NodeListerResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension,
MakeStringLiteral("Nodes List"), MakeStringLiteral("Nodes List"),
NodeSpecificationsCount, (u8*)NodeSpecifications, NodeSpecificationsCount, (u8*)NodeSpecifications,
State->GeneralPurposeSearchHotItem, State->GeneralPurposeSearchHotItem,
@ -870,7 +871,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
&State->ActiveTextEntry.Buffer, &State->ActiveTextEntry.Buffer,
State->ActiveTextEntry.CursorPosition, State->ActiveTextEntry.CursorPosition,
State->Font, State->Interface, GuiMouse); State->Font, State->Interface, GuiMouse);
State->GeneralPurposeSearchHotItem = NodeListResult.HotItem; State->GeneralPurposeSearchHotItem = NodeListerResult.HotItem;
} }
} }

View File

@ -98,7 +98,7 @@ struct app_state
v2 UniverseOutputDisplayOffset; v2 UniverseOutputDisplayOffset;
r32 UniverseOutputDisplayZoom; r32 UniverseOutputDisplayZoom;
b32 InterfaceShowNodeList; b32 InterfaceShowNodeLister;
v2 NodeListMenuPosition; v2 NodeListMenuPosition;
node_list* NodeList; node_list* NodeList;

View File

@ -41,7 +41,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(ToggleUniverseDebugView)
FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister)
{ {
State->InterfaceShowNodeList = true; State->InterfaceShowNodeLister = true;
State->NodeListMenuPosition = Mouse.Pos; State->NodeListMenuPosition = Mouse.Pos;
SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString); SetTextInputDestinationToString(&State->ActiveTextEntry, &State->GeneralPurposeSearchString);
State->ActiveCommands = &State->NodeListerCommandRegistry; State->ActiveCommands = &State->NodeListerCommandRegistry;

View File

@ -1124,11 +1124,60 @@ ResetNodesUpdateState (node_list* NodeList)
} }
} }
internal b32
internal char* SpecificationPassesFilter(string SpecificationName, string SearchString)
NodeListerGetNodeName (u8* NodeSpecificationsList, s32 NodeSpecificationsListCount, s32 Offset)
{ {
node_specification* Specifications = (node_specification*)NodeSpecificationsList + Offset; return (SearchString.Length == 0 || StringContainsStringCaseInsensitive(SpecificationName, SearchString));
char* Result = Specifications->Name; }
internal s32
NodeListerConvertHotItemToListIndex (s32 HotItem, u8* NodeSpecificationsList, s32 NodeSpecificationsListCount,
string SearchString)
{
s32 ListIndex = 0;
s32 FilteredItemsCount = 0;
for (s32 i = 0; i < NodeSpecificationsListCount; i++)
{
node_specification* Specification = (node_specification*)NodeSpecificationsList + i;
string ItemName = MakeString(Specification->Name);
b32 PassesFilter = SpecificationPassesFilter(ItemName, SearchString);
if (PassesFilter)
{
if (FilteredItemsCount == HotItem)
{
break;
}
FilteredItemsCount++;
}
ListIndex++;
}
return ListIndex;
}
internal string
NodeListerGetNodeName (u8* NodeSpecificationsList, s32 NodeSpecificationsListCount, string SearchString, s32 Offset)
{
s32 FilteredItemsCount = 0;
node_specification* Specification = (node_specification*)NodeSpecificationsList;
string Result = {};
for (s32 i = 0; i < NodeSpecificationsListCount; i++)
{
string ItemName = MakeString(Specification->Name);
b32 PassesFilter = SpecificationPassesFilter(ItemName, SearchString);
if (PassesFilter)
{
if (FilteredItemsCount == Offset)
{
Result = ItemName;
break;
}
FilteredItemsCount++;
}
Specification++;
}
return Result; return Result;
} }

View File

@ -35,7 +35,21 @@ typedef CLEANUP_APPLICATION(cleanup_application);
typedef struct platform_font_info platform_font_info; typedef struct platform_font_info platform_font_info;
#define GET_FONT_INFO(name) platform_font_info name(char* FontName, s32 PixelHeight) enum font_weight
{
FontWeight_Invalid = 0,
FontWeight_Thin = 100,
FontWeight_ExtraLight = 200,
FontWeight_Light = 300,
FontWeight_Normal = 400,
FontWeight_Medium = 500,
FontWeight_SemiBold = 600,
FontWeight_Bold = 700,
FontWeight_ExtraBold = 800,
FontWeight_Heavy = 900,
};
#define GET_FONT_INFO(name) platform_font_info name(char* FontName, s32 PixelHeight, font_weight FontWeight, b32 Italic, b32 Underline, b32 Strikeout)
typedef GET_FONT_INFO(platform_get_font_info); typedef GET_FONT_INFO(platform_get_font_info);
#define DRAW_FONT_CODEPOINT(name) void name(u8* DestBuffer, s32 DestBufferWidth, s32 DestBufferHeight, u32 XOffset, u32 YOffset, char Codepoint, platform_font_info FontInfo, u32* OutWidth, u32* OutHeight) #define DRAW_FONT_CODEPOINT(name) void name(u8* DestBuffer, s32 DestBufferWidth, s32 DestBufferHeight, u32 XOffset, u32 YOffset, char Codepoint, platform_font_info FontInfo, u32* OutWidth, u32* OutHeight)

View File

@ -57,7 +57,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(SearchListerPrevItem)
FOLDHAUS_INPUT_COMMAND_PROC(CloseSearchLister) FOLDHAUS_INPUT_COMMAND_PROC(CloseSearchLister)
{ {
// TODO(Peter): This is to show the node list. Generalize to just a lister // TODO(Peter): This is to show the node list. Generalize to just a lister
State->InterfaceShowNodeList = false; State->InterfaceShowNodeLister = false;
// TODO(Peter): This also assumes we know where we came from. Probably need to implement // TODO(Peter): This also assumes we know where we came from. Probably need to implement
// push/pop functionality for the activecommands. // push/pop functionality for the activecommands.
QueueNextFrameCommandRegistry(&State->InputCommandRegistry, State); QueueNextFrameCommandRegistry(&State->InputCommandRegistry, State);
@ -67,7 +67,11 @@ FOLDHAUS_INPUT_COMMAND_PROC(CloseSearchLister)
FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseSearchLister) FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseSearchLister)
{ {
s32 HotItem = State->GeneralPurposeSearchHotItem; s32 HotItem = State->GeneralPurposeSearchHotItem;
PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[HotItem], s32 ListIndexFromHotItem = NodeListerConvertHotItemToListIndex(HotItem,
(u8*)NodeSpecifications,
NodeSpecificationsCount,
State->ActiveTextEntry.Buffer);
PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[ListIndexFromHotItem],
Mouse.Pos, State->NodeRenderSettings, State->Permanent); Mouse.Pos, State->NodeRenderSettings, State->Permanent);
CloseSearchLister(State, Event, Mouse); CloseSearchLister(State, Event, Mouse);
} }

View File

@ -575,7 +575,7 @@ struct search_lister_result
b32 ShouldRemainOpen; b32 ShouldRemainOpen;
}; };
typedef char* search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, s32 Offset); typedef string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, string SearchString, s32 Offset);
internal search_lister_result internal search_lister_result
EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimension, string Title, EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimension, string Title,
@ -600,14 +600,9 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens
TopLeft.y -= 30; TopLeft.y -= 30;
s32 VisibleItemIndex = 0; s32 VisibleItemIndex = 0;
for (s32 i = 0; i < ListLength; i++)
{
char* ListItemText = GetListItem(ListMemory, ListLength, i);
Assert(ListItemText);
string ListItemString = MakeStringLiteral(ListItemText);
if (SearchString->Length == 0 || string ListItemText = GetListItem(ListMemory, ListLength, *SearchString, VisibleItemIndex);
StringContainsStringCaseInsensitive(ListItemString, *SearchString)) while(ListItemText.Length > 0)
{ {
v2 Min = v2{TopLeft.x, TopLeft.y - 30}; v2 Min = v2{TopLeft.x, TopLeft.y - 30};
v2 Max = Min + Dimension - v2{0, Config.Margin.y}; v2 Max = Min + Dimension - v2{0, Config.Margin.y};
@ -618,17 +613,16 @@ EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimens
ButtonColor = Config.ButtonColor_Active; ButtonColor = Config.ButtonColor_Active;
} }
button_result Button = EvaluateButton(RenderBuffer, Min, Max, Config.Margin, ListItemString, button_result Button = EvaluateButton(RenderBuffer, Min, Max, Config.Margin, ListItemText,
ButtonColor, ButtonColor, Config.TextColor, Config.TextColor, ButtonColor, ButtonColor, Config.TextColor, Config.TextColor,
Config.Font, Mouse); Config.Font, Mouse);
if (Button.Pressed) if (Button.Pressed)
{ {
Result.SelectedItem = i; Result.SelectedItem = VisibleItemIndex;
} }
TopLeft.y -= 30; TopLeft.y -= 30;
VisibleItemIndex++; ListItemText = GetListItem(ListMemory, ListLength, *SearchString, ++VisibleItemIndex);
}
} }
return Result; return Result;

View File

@ -1,78 +0,0 @@
TODO FOLDHAUS
Hardening
- memory visualization
- separate rendering thread
- cache led positions. Only update if they are moving
- input context changes
- - shift drag to 10x drag speed
- select nodes -> delete nodes
- remove node connections
Name
- Splash screen (like blender) (thisll be fun)
- - Image importer (stb image? or find a png > bmp converter for the image you have)
- - Display on startup
/Debug
x Make debug scope tracking thread safe - was throwing an error in stringsequal but that stopped.
x Keep an eye out.
Application
- More efficient HSV <-> RGB
- Save and load a session
- - Serialize Nodes
- Don't render if the window isn't visible
Development
- Fix your scope time tracker to account for threads.
- Nest scope times so you can see totals/dig in
- Log memory allocations
Interface
- fullscreen
- In world interface elements
- - Handles for Patterns
- - UI Popups
- - Value modifiers
- Scroll view
- Update the text system - use system fonts
Switch To Nodes
x basic node elements
- - evaluation step (one node at a time)
- - selector node (has a list of connections that it can switch between)
- serialize
- delete nodes
Structure
- motion
Renderer
- Mouse Picking - point at a led and see info about it
- Camera: pan
- Camera: zoom
- Camera: leds always face camera
Resource Management
- TODO: Need to figure out which textures are currently in graphics memory and which need to be resubmitted
- Icons
Animation
- timeline
- create clips that play
- clips can have parameters that drive them?
- clips should have prerequesites
- - channels active
- - patterns active in the channel
- - when a clip is playing, it should just take over the whole structure
Command Line
- select a channel/pattern
Optimization
- patterns are asking to be multithreaded
- probably want to convert as much color functions to use u32 Packed Colors
- - Probably want to think about this more. What about supporting different color depths
- for different output devices?

View File

@ -249,11 +249,10 @@ GET_FONT_INFO(Win32GetFontInfo)
HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap); HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap);
CurrentFont = CreateFont(PixelHeight, 0, 0, 0, CurrentFont = CreateFont(PixelHeight, 0, 0, 0,
// TODO(Peter): Font weight, need a platform way to request others FontWeight,
FW_NORMAL, Italic,
FALSE, // Italic Underline,
FALSE, // Underling Strikeout,
FALSE, // Strikeout,
ANSI_CHARSET, ANSI_CHARSET,
OUT_OUTLINE_PRECIS, OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
@ -297,8 +296,7 @@ DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint)
COLORREF PixelColor; COLORREF PixelColor;
for (u32 Y = 0; Y < *OutHeight; Y++) for (u32 Y = 0; Y < *OutHeight; Y++)
{ {
// TODO(Peter): * 4 b/c its 4 bytes per pixel. Switch to our bitmap_texture struct for clarity // NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel.
// and fewer fields to this function
u8* Channel = (u8*)Row + (XOffset * 4); u8* Channel = (u8*)Row + (XOffset * 4);
for (u32 X = 0; X < *OutWidth; X++) for (u32 X = 0; X < *OutWidth; X++)
{ {
@ -375,39 +373,63 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true, AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->DownPos = Mouse->Pos; Mouse->DownPos = Mouse->Pos;
}break; }break;
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
case WM_MBUTTONUP: case WM_MBUTTONUP:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
case WM_RBUTTONUP: case WM_RBUTTONUP:
{ {
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false,
false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
@ -422,9 +444,13 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0; b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0;
b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0; b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0;
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
// New Input Queue // New Input Queue
// TODO(Peter): Come back and add state tracking for the modifier keys AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown,
AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown, false, false, false, false); ShiftDown, AltDown, CtrlDown, false);
}break; }break;
default: default:

View File

@ -0,0 +1,78 @@
TODO FOLDHAUS
Hardening
- memory visualization
- separate rendering thread
- cache led positions. Only update if they are moving
x input context changes
- - shift drag to 10x drag speed
- select nodes -> delete nodes
- remove node connections
Name
- Splash screen (like blender) (thisll be fun)
- - Image importer (stb image? or find a png > bmp converter for the image you have)
- - Display on startup
/Debug
x Make debug scope tracking thread safe - was throwing an error in stringsequal but that stopped.
x Keep an eye out.
Application
- More efficient HSV <-> RGB
- Save and load a session
- - Serialize Nodes
- Don't render if the window isn't visible
Development
- Fix your scope time tracker to account for threads.
- Nest scope times so you can see totals/dig in
- Log memory allocations
Interface
- fullscreen
- In world interface elements
- - Handles for Patterns
- - UI Popups
- - Value modifiers
- Scroll view
- Update the text system - use system fonts
Switch To Nodes
x basic node elements
- - evaluation step (one node at a time)
- - selector node (has a list of connections that it can switch between)
- serialize
- delete nodes
Structure
- motion
Renderer
- Mouse Picking - point at a led and see info about it
- Camera: pan
- Camera: zoom
- Camera: leds always face camera
Resource Management
- TODO: Need to figure out which textures are currently in graphics memory and which need to be resubmitted
- Icons
Animation
- timeline
- create clips that play
- clips can have parameters that drive them?
- clips should have prerequesites
- - channels active
- - patterns active in the channel
- - when a clip is playing, it should just take over the whole structure
Command Line
- select a channel/pattern
Optimization
- patterns are asking to be multithreaded
- probably want to convert as much color functions to use u32 Packed Colors
- - Probably want to think about this more. What about supporting different color depths
- for different output devices?