mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 14:51:46 +00:00
added option search menu
This commit is contained in:
parent
540e180fb1
commit
73d81d3983
6 changed files with 368 additions and 1 deletions
|
@ -51,6 +51,9 @@ CVAR(Int, developer, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
// [RH] Feature control cvars
|
// [RH] Feature control cvars
|
||||||
CVAR(Bool, var_friction, true, CVAR_SERVERINFO);
|
CVAR(Bool, var_friction, true, CVAR_SERVERINFO);
|
||||||
|
|
||||||
|
// Option Search
|
||||||
|
CVAR(Bool, os_isanyof, true, CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,4 +141,3 @@ CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOB
|
||||||
if (Level->info != nullptr) Level->LevelName = Level->info->LookupLevelName();
|
if (Level->info != nullptr) Level->LevelName = Level->info->LookupLevelName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -378,6 +378,8 @@ OptionMenu "OptionsMenu" protected
|
||||||
Submenu "$OPTMNU_DISPLAY", "VideoOptions"
|
Submenu "$OPTMNU_DISPLAY", "VideoOptions"
|
||||||
Submenu "$OPTMNU_VIDEO", "VideoModeMenu"
|
Submenu "$OPTMNU_VIDEO", "VideoModeMenu"
|
||||||
StaticText " "
|
StaticText " "
|
||||||
|
Submenu "$OS_TITLE", "os_Menu"
|
||||||
|
StaticText " "
|
||||||
SafeCommand "$OPTMNU_DEFAULTS", "reset2defaults"
|
SafeCommand "$OPTMNU_DEFAULTS", "reset2defaults"
|
||||||
SafeCommand "$OPTMNU_RESETTOSAVED", "reset2saved"
|
SafeCommand "$OPTMNU_RESETTOSAVED", "reset2saved"
|
||||||
Command "$OPTMNU_CONSOLE", "menuconsole"
|
Command "$OPTMNU_CONSOLE", "menuconsole"
|
||||||
|
@ -2606,3 +2608,21 @@ OptionString "LanguageOptions"
|
||||||
"ptb", "Português do Brasil (PTB)"
|
"ptb", "Português do Brasil (PTB)"
|
||||||
"rus", "Русский (RU)"
|
"rus", "Русский (RU)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*=======================================
|
||||||
|
*
|
||||||
|
* Option Search menu
|
||||||
|
*
|
||||||
|
*=======================================*/
|
||||||
|
|
||||||
|
OptionMenu "os_Menu"
|
||||||
|
{
|
||||||
|
Class "os_Menu"
|
||||||
|
Title "$OS_TITLE"
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionValue "os_isanyof_values"
|
||||||
|
{
|
||||||
|
0, "$OS_ALL"
|
||||||
|
1, "$OS_ANY"
|
||||||
|
}
|
||||||
|
|
|
@ -253,6 +253,10 @@ version "3.8"
|
||||||
#include "zscript/ui/menu/reverbedit.zs"
|
#include "zscript/ui/menu/reverbedit.zs"
|
||||||
#include "zscript/ui/menu/textentermenu.zs"
|
#include "zscript/ui/menu/textentermenu.zs"
|
||||||
|
|
||||||
|
#include "zscript/ui/menu/search/menu.zs"
|
||||||
|
#include "zscript/ui/menu/search/searchfield.zs"
|
||||||
|
#include "zscript/ui/menu/search/query.zs"
|
||||||
|
|
||||||
#include "zscript/ui/statscreen/statscreen.zs"
|
#include "zscript/ui/statscreen/statscreen.zs"
|
||||||
#include "zscript/ui/statscreen/statscreen_coop.zs"
|
#include "zscript/ui/statscreen/statscreen_coop.zs"
|
||||||
#include "zscript/ui/statscreen/statscreen_dm.zs"
|
#include "zscript/ui/statscreen/statscreen_dm.zs"
|
||||||
|
|
212
wadsrc/static/zscript/ui/menu/search/menu.zs
Normal file
212
wadsrc/static/zscript/ui/menu/search/menu.zs
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Option Search Menu class.
|
||||||
|
// This menu contains search field, and is dynamically filled with search
|
||||||
|
// results.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class os_Menu : OptionMenu
|
||||||
|
{
|
||||||
|
override void Init(Menu parent, OptionMenuDescriptor desc)
|
||||||
|
{
|
||||||
|
Super.Init(parent, desc);
|
||||||
|
|
||||||
|
mDesc.mItems.clear();
|
||||||
|
|
||||||
|
addSearchField();
|
||||||
|
|
||||||
|
mDesc.mScrollPos = 0;
|
||||||
|
mDesc.mSelectedItem = 0;
|
||||||
|
mDesc.CalcIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void search(os_Query query)
|
||||||
|
{
|
||||||
|
mDesc.mItems.clear();
|
||||||
|
|
||||||
|
addSearchField(query.getText());
|
||||||
|
|
||||||
|
string path = StringTable.Localize("$OPTMNU_TITLE");
|
||||||
|
bool isAnyTermMatches = mIsAnyOfItem.mCVar.GetBool();
|
||||||
|
bool found = listOptions(mDesc, "MainMenu", query, path, isAnyTermMatches);
|
||||||
|
|
||||||
|
if (!found) { addNoResultsItem(mDesc); }
|
||||||
|
|
||||||
|
mDesc.CalcIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSearchField(string query = "")
|
||||||
|
{
|
||||||
|
string searchLabel = StringTable.Localize("$OS_LABEL");
|
||||||
|
let searchField = new("os_SearchField").Init(searchLabel, self, query);
|
||||||
|
|
||||||
|
mIsAnyOfItem = new("OptionMenuItemOption").Init("", "os_isanyof", "os_isanyof_values");
|
||||||
|
|
||||||
|
mDesc.mItems.push(searchField);
|
||||||
|
mDesc.mItems.push(mIsAnyOfItem);
|
||||||
|
addEmptyLine(mDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool listOptions(OptionMenuDescriptor targetDesc,
|
||||||
|
string menuName,
|
||||||
|
os_Query query,
|
||||||
|
string path,
|
||||||
|
bool isAnyTermMatches)
|
||||||
|
{
|
||||||
|
let desc = MenuDescriptor.GetDescriptor(menuName);
|
||||||
|
let listMenuDesc = ListMenuDescriptor(desc);
|
||||||
|
|
||||||
|
if (listMenuDesc)
|
||||||
|
{
|
||||||
|
return listOptionsListMenu(listMenuDesc, targetDesc, query, path, isAnyTermMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
let optionMenuDesc = OptionMenuDescriptor(desc);
|
||||||
|
|
||||||
|
if (optionMenuDesc)
|
||||||
|
{
|
||||||
|
return listOptionsOptionMenu(optionMenuDesc, targetDesc, query, path, isAnyTermMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool listOptionsListMenu(ListMenuDescriptor sourceDesc,
|
||||||
|
OptionMenuDescriptor targetDesc,
|
||||||
|
os_Query query,
|
||||||
|
string path,
|
||||||
|
bool isAnyTermMatches)
|
||||||
|
{
|
||||||
|
int nItems = sourceDesc.mItems.size();
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < nItems; ++i)
|
||||||
|
{
|
||||||
|
let item = sourceDesc.mItems[i];
|
||||||
|
string actionN = item.GetAction();
|
||||||
|
string newPath = (actionN == "Optionsmenu")
|
||||||
|
? StringTable.Localize("$OPTMNU_TITLE")
|
||||||
|
: StringTable.Localize("$OS_MAIN");
|
||||||
|
|
||||||
|
found |= listOptions(targetDesc, actionN, query, newPath, isAnyTermMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool listOptionsOptionMenu(OptionMenuDescriptor sourceDesc,
|
||||||
|
OptionMenuDescriptor targetDesc,
|
||||||
|
os_Query query,
|
||||||
|
string path,
|
||||||
|
bool isAnyTermMatches)
|
||||||
|
{
|
||||||
|
if (sourceDesc == targetDesc) { return false; }
|
||||||
|
|
||||||
|
int nItems = sourceDesc.mItems.size();
|
||||||
|
bool first = true;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < nItems; ++i)
|
||||||
|
{
|
||||||
|
let item = sourceDesc.mItems[i];
|
||||||
|
|
||||||
|
if (item is "OptionMenuItemStaticText") { continue; }
|
||||||
|
|
||||||
|
string label = StringTable.Localize(item.mLabel);
|
||||||
|
|
||||||
|
if (!query.matches(label, isAnyTermMatches)) { continue; }
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
addEmptyLine(targetDesc);
|
||||||
|
addPathItem(targetDesc, path);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let itemOptionBase = OptionMenuItemOptionBase(item);
|
||||||
|
|
||||||
|
if (itemOptionBase)
|
||||||
|
{
|
||||||
|
itemOptionBase.mCenter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetDesc.mItems.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nItems; ++i)
|
||||||
|
{
|
||||||
|
let item = sourceDesc.mItems[i];
|
||||||
|
string label = StringTable.Localize(item.mLabel);
|
||||||
|
string optionSearchTitle = StringTable.Localize("$OS_TITLE");
|
||||||
|
|
||||||
|
if (label == optionSearchTitle) { continue; }
|
||||||
|
|
||||||
|
if (item is "OptionMenuItemSubMenu")
|
||||||
|
{
|
||||||
|
string newPath = makePath(path, label);
|
||||||
|
|
||||||
|
found |= listOptions(targetDesc, item.GetAction(), query, newPath, isAnyTermMatches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string makePath(string path, string label)
|
||||||
|
{
|
||||||
|
int pathWidth = SmallFont.StringWidth(path .. "/" .. label);
|
||||||
|
int screenWidth = Screen.GetWidth();
|
||||||
|
bool isTooWide = (pathWidth > screenWidth / 3);
|
||||||
|
string newPath = isTooWide
|
||||||
|
? path .. "/" .. "\n" .. label
|
||||||
|
: path .. "/" .. label;
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addPathItem(OptionMenuDescriptor desc, string path)
|
||||||
|
{
|
||||||
|
Array<String> lines;
|
||||||
|
path.split(lines, "\n");
|
||||||
|
|
||||||
|
int nLines = lines.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < nLines; ++i)
|
||||||
|
{
|
||||||
|
OptionMenuItemStaticText text = new("OptionMenuItemStaticText").Init(lines[i], 1);
|
||||||
|
|
||||||
|
desc.mItems.push(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addEmptyLine(OptionMenuDescriptor desc)
|
||||||
|
{
|
||||||
|
int nItems = desc.mItems.size();
|
||||||
|
|
||||||
|
if (nItems > 0)
|
||||||
|
{
|
||||||
|
let staticText = OptionMenuItemStaticText(desc.mItems[nItems - 1]);
|
||||||
|
|
||||||
|
if (staticText != null && staticText.mLabel == "") { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = new("OptionMenuItemStaticText").Init("");
|
||||||
|
|
||||||
|
desc.mItems.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addNoResultsItem(OptionMenuDescriptor desc)
|
||||||
|
{
|
||||||
|
string noResults = StringTable.Localize("$OS_NO_RESULTS");
|
||||||
|
let text = new("OptionMenuItemStaticText").Init(noResults, 0);
|
||||||
|
|
||||||
|
addEmptyLine(desc);
|
||||||
|
desc.mItems.push(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OptionMenuItemOption mIsAnyOfItem;
|
||||||
|
}
|
78
wadsrc/static/zscript/ui/menu/search/query.zs
Normal file
78
wadsrc/static/zscript/ui/menu/search/query.zs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Option Search Query class represents a search query.
|
||||||
|
// A search query consists constists of one or more terms (words).
|
||||||
|
//
|
||||||
|
// Query matching deponds on "os_is_any_of" variable.
|
||||||
|
// If this variable is "true", the text matches the query if any of the terms
|
||||||
|
// matches the query.
|
||||||
|
// If this variable is "false", the text matches the query only if all the
|
||||||
|
// terms match the query.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class os_Query
|
||||||
|
{
|
||||||
|
static os_Query fromString(string str)
|
||||||
|
{
|
||||||
|
let query = new("os_Query");
|
||||||
|
|
||||||
|
str.Split(query.mQueryParts, " ", TOK_SKIPEMPTY);
|
||||||
|
|
||||||
|
query.mText = str;
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(string text, bool isSearchForAny)
|
||||||
|
{
|
||||||
|
return isSearchForAny
|
||||||
|
? matchesAny(text)
|
||||||
|
: matchesAll(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
string getText() { return mText; }
|
||||||
|
|
||||||
|
// private: //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private bool matchesAny(string text)
|
||||||
|
{
|
||||||
|
int nParts = mQueryParts.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < nParts; ++i)
|
||||||
|
{
|
||||||
|
string queryPart = mQueryParts[i];
|
||||||
|
|
||||||
|
if (contains(text, queryPart)) { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool matchesAll(string text)
|
||||||
|
{
|
||||||
|
int nParts = mQueryParts.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < nParts; ++i)
|
||||||
|
{
|
||||||
|
string queryPart = mQueryParts[i];
|
||||||
|
|
||||||
|
if (!contains(text, queryPart)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool contains(string str, string substr)
|
||||||
|
{
|
||||||
|
str .toLower();
|
||||||
|
substr.toLower();
|
||||||
|
|
||||||
|
bool contains = (str.IndexOf(substr) != -1);
|
||||||
|
|
||||||
|
return contains;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string mText;
|
||||||
|
private Array<String> mQueryParts;
|
||||||
|
}
|
51
wadsrc/static/zscript/ui/menu/search/searchfield.zs
Normal file
51
wadsrc/static/zscript/ui/menu/search/searchfield.zs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Option Search Field class.
|
||||||
|
//
|
||||||
|
// When the search query is entered, makes Search Menu perform a search.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class os_SearchField : OptionMenuItemTextField
|
||||||
|
{
|
||||||
|
os_SearchField Init(String label, os_Menu menu, string query)
|
||||||
|
{
|
||||||
|
Super.Init(label, "");
|
||||||
|
|
||||||
|
mMenu = menu;
|
||||||
|
|
||||||
|
mText = query;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||||
|
{
|
||||||
|
if (mkey == Menu.MKEY_Enter)
|
||||||
|
{
|
||||||
|
Menu.MenuSound("menu/choose");
|
||||||
|
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), SmallFont, mText, -1, fromcontroller);
|
||||||
|
mEnter.ActivateMenu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mkey == Menu.MKEY_Input)
|
||||||
|
{
|
||||||
|
string text = mEnter.GetText();
|
||||||
|
let query = os_Query.fromString(text);
|
||||||
|
|
||||||
|
mMenu.search(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Super.MenuEvent(mkey, fromcontroller);
|
||||||
|
}
|
||||||
|
|
||||||
|
override String Represent()
|
||||||
|
{
|
||||||
|
return mEnter
|
||||||
|
? mEnter.GetText() .. SmallFont.GetCursor()
|
||||||
|
: mText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private os_Menu mMenu;
|
||||||
|
private string mText;
|
||||||
|
}
|
Loading…
Reference in a new issue