diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index f0c4a29ad1..43e7180185 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3607,4 +3607,7 @@ STR_5270 :{SMALLFONT}{BLACK}Miscellaneous STR_5271 :{SMALLFONT}{BLACK}Twitch STR_5272 :{SMALLFONT}{BLACK}Small Scenery STR_5273 :{SMALLFONT}{BLACK}Large Scenery -STR_5274 :{SMALLFONT}{BLACK}Footpaths \ No newline at end of file +STR_5274 :{SMALLFONT}{BLACK}Footpath +STR_5275 :Search for Objects +STR_5276 :Enter the name of an object to search for +STR_5277 :Clear \ No newline at end of file diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 27cad6559a..d71eda159a 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -44,6 +44,8 @@ enum { uint32 _filter_flags; uint16 _filter_object_counts[11]; +char _filter_string[41]; + #define _FILTER_ALL ((_filter_flags & FILTER_ALL) == FILTER_ALL) #define _FILTER_RCT2 (_filter_flags & FILTER_RCT2) #define _FILTER_WW (_filter_flags & FILTER_WW) @@ -88,6 +90,8 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX { WIDX_PREVIEW, // 17, 20000 WIDX_DROPDOWN2, // 18, 40000 WIDX_FILTER_DROPDOWN, // 19, 80000 + WIDX_FILTER_STRING_BUTTON, // 20, 100000 + WIDX_FILTER_CLEAR_BUTTON // 21, 200000 }; static rct_widget window_editor_object_selection_widgets[] = { @@ -107,10 +111,12 @@ static rct_widget window_editor_object_selection_widgets[] = { { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, 1812 }, { WWT_TAB, 1, 313, 343, 17, 43, 0x2000144E, 1812 }, { WWT_DROPDOWN_BUTTON, 0, 470, 591, 23, 34, STR_OBJECT_SELECTION_ADVANCED, STR_OBJECT_SELECTION_ADVANCED_TIP }, - { WWT_SCROLL, 1, 4, 291, 46, 386, 2, STR_NONE }, + { WWT_SCROLL, 1, 4, 291, 60, 386, 2, STR_NONE }, { WWT_FLATBTN, 1, 391, 504, 46, 159, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 0, 384, 595, 24, 35, STR_INSTALL_NEW_TRACK_DESIGN, STR_INSTALL_NEW_TRACK_DESIGN_TIP }, { WWT_DROPDOWN_BUTTON, 0, 350, 463, 23, 34, 5261, 5265 }, + { WWT_DROPDOWN_BUTTON, 1, 4, 214, 46, 57, STR_NONE, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 218, 287, 46, 57, 5277, STR_NONE }, { WIDGETS_END } }; @@ -131,6 +137,7 @@ static void window_editor_object_selection_tooltip(); static void window_editor_object_selection_invalidate(); static void window_editor_object_selection_paint(); static void window_editor_object_selection_scrollpaint(); +static void window_editor_object_selection_textinput(); static void* window_editor_object_selection_events[] = { window_editor_object_selection_close, @@ -152,7 +159,7 @@ static void* window_editor_object_selection_events[] = { (void*)window_editor_object_selection_scroll_mousedown, (void*)window_editor_object_selection_emptysub, (void*)window_editor_object_selection_scroll_mouseover, - (void*)window_editor_object_selection_emptysub, + (void*)window_editor_object_selection_textinput, (void*)window_editor_object_selection_emptysub, (void*)window_editor_object_selection_emptysub, (void*)window_editor_object_selection_tooltip, @@ -172,6 +179,9 @@ static int window_editor_object_selection_select_object(int flags, rct_object_en static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry); static void window_editor_object_selection_manage_tracks(); static void editor_load_selected_objects(); +static bool filter_string(rct_object_entry *entry); +static bool filter_source(rct_object_entry *entry); +static void filter_update_counts(); static rct_object_entry DefaultSelectedObjects[] = { // Objects that are always required @@ -246,9 +256,12 @@ void window_editor_object_selection_open() (1 << WIDX_DROPDOWN1) | (1 << WIDX_DROPDOWN2) | (1 << WIDX_FILTER_DROPDOWN) | + (1 << WIDX_FILTER_STRING_BUTTON) | + (1 << WIDX_FILTER_CLEAR_BUTTON) | (1 << WIDX_CLOSE); _filter_flags = FILTER_ALL; + memset(_filter_string, 0, sizeof(_filter_string)); for (int i = WIDX_TAB_1; i <= WIDX_TAB_11; i++) window->enabled_widgets |= (1LL << i); @@ -342,6 +355,16 @@ static void window_editor_object_selection_mouseup() window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK); break; + case WIDX_FILTER_STRING_BUTTON: + window_text_input_open(w, widgetIndex, 5275, 5276, 1170, (uint32)_filter_string, 40); + break; + case WIDX_FILTER_CLEAR_BUTTON: + memset(_filter_string, 0, sizeof(_filter_string)); + + w->scrolls->v_top = 0; + + window_invalidate(w); + break; } } @@ -376,8 +399,6 @@ void window_editor_object_selection_mousedown(int widgetIndex, rct_window*w, rct gDropdownItemsChecked = _filter_flags; break; } - - } static void window_editor_object_selection_dropdown() @@ -395,21 +416,7 @@ static void window_editor_object_selection_dropdown() _filter_flags ^= (1 << dropdownIndex); - if (!_FILTER_ALL) { - rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - uint8 type, source; - for (int i = 0; i < 11; i++) { - _filter_object_counts[i] = 0; - } - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i) { - type = installed_entry->flags & 0xF; - source = (installed_entry->flags & 0xF0) >> 4; - if ((_FILTER_RCT2 && source == 8) || (_FILTER_WW && source == 1) || (_FILTER_TT && source == 2) || (_FILTER_CUSTOM && source != 8 && source != 1 && source != 2)) { - _filter_object_counts[type]++; - } - installed_entry = object_get_next(installed_entry); - } - } + filter_update_counts(); w->scrolls->v_top = 0; window_invalidate(w); @@ -431,7 +438,7 @@ static void window_editor_object_selection_scrollgetsize() numItems = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER) ? RCT2_GLOBAL(0x00F43412, uint16) : - (_FILTER_ALL ? + ((_FILTER_ALL && _filter_string[0] == 0) ? RCT2_ADDRESS(0x00F433E1, uint16)[w->selected_tab] : _filter_object_counts[w->selected_tab]); @@ -691,6 +698,26 @@ static void window_editor_object_selection_paint() rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); + gfx_fill_rect_inset(dpi, + w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].left, + w->y + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].top, + w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].right, + w->y + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].bottom, + w->colours[1], + 0x30 + ); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&_filter_string; + gfx_draw_string_left_clipped( + dpi, + 1170, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, + w->colours[1], + w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].left + 1, + w->y + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].top, + w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].right + ); + if (w->selected_list_item == -1 || stex_entry == NULL) return; @@ -812,7 +839,7 @@ static void window_editor_object_selection_scrollpaint() for (i = 0; i < numObjects; i++) { type = entry->flags & 0x0F; source = (entry->flags & 0xF0) >> 4; - if (type == w->selected_tab && !(*itemFlags & 0x20) && ((_FILTER_RCT2 && source == 8) || (_FILTER_WW && source == 1) || (_FILTER_TT && source == 2) || (_FILTER_CUSTOM && source != 8 && source != 1 && source != 2))) { + if (type == w->selected_tab && !(*itemFlags & 0x20) && filter_source(entry) && filter_string(entry)) { if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) { // Draw checkbox if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && !(*itemFlags & 0x20)) @@ -926,7 +953,7 @@ static int get_object_from_object_selection(uint8 object_type, int y, uint8 *obj int object_count = 0; for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ source = ((*installed_entry)->flags & 0xF0) >> 4; - if (((*installed_entry)->flags & 0xF) == object_type && ((_FILTER_RCT2 && source == 8) || (_FILTER_WW && source == 1) || (_FILTER_TT && source == 2) || (_FILTER_CUSTOM && source != 8 && source != 1 && source != 2))){ + if (((*installed_entry)->flags & 0xF) == object_type && filter_source(*installed_entry) && filter_string(*installed_entry)){ if (!(*selection_flags & 0x20)){ y -= 12; *object_selection_flags = *selection_flags; @@ -1006,3 +1033,78 @@ static void editor_load_selected_objects() installed_entry = object_get_next(installed_entry); } } + +static void window_editor_object_selection_textinput() +{ + uint8 result; + short widgetIndex; + rct_window *w; + char *text; + + window_textinput_get_registers(w, widgetIndex, result, text); + + if (widgetIndex != WIDX_FILTER_STRING_BUTTON || !result) + return; + if (strlen(text) == 0) { + memset(_filter_string, 0, sizeof(_filter_string)); + } + else { + memset(_filter_string, 0, sizeof(_filter_string)); + strcpy(_filter_string, text); + } + + filter_update_counts(); + + w->scrolls->v_top = 0; + + window_invalidate(w); +} + +static bool filter_string(rct_object_entry *entry) +{ + if (_filter_string[0] == 0) + return true; + + char *name = object_get_name(entry); + if (name[0] == 0) + return false; + + char name_lower[MAX_PATH]; + char filter_lower[sizeof(_filter_string)]; + strcpy(name_lower, name); + strcpy(filter_lower, _filter_string); + + for (int i = 0; i < (int)strlen(name_lower); i++) + name_lower[i] = (char)tolower(name_lower[i]); + for (int i = 0; i < (int)strlen(filter_lower); i++) + filter_lower[i] = (char)tolower(filter_lower[i]); + + return strstr(name_lower, filter_lower) != NULL; +} + +static bool filter_source(rct_object_entry *entry) +{ + if (_FILTER_ALL) + return true; + + uint8 source = (entry->flags & 0xF0) >> 4; + return (_FILTER_RCT2 && source == 8) || (_FILTER_WW && source == 1) || (_FILTER_TT && source == 2) || (_FILTER_CUSTOM && source != 8 && source != 1 && source != 2); +} + +static void filter_update_counts() +{ + if (!_FILTER_ALL || strlen(_filter_string) > 0) { + rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + uint8 type; + for (int i = 0; i < 11; i++) { + _filter_object_counts[i] = 0; + } + for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i) { + type = installed_entry->flags & 0xF; + if (filter_source(installed_entry) && filter_string(installed_entry)) { + _filter_object_counts[type]++; + } + installed_entry = object_get_next(installed_entry); + } + } +}