Implement menu_create "ml" param to allow menu title/item to be looked up as multilingual key (#593)
* Clean up menu_create() internal code No code changes. Just modernizing code a little and tidying up things. * Implement menu_create() "ml" param * Include newmenu.inc to VS project files * Adjust documentation * Put back the quote in the log error message.
This commit is contained in:
parent
b4768a3d1d
commit
8717ffe07c
|
@ -457,6 +457,7 @@ md -p JIT 2>NUL
|
||||||
<None Include="..\..\plugins\include\cvars.inc" />
|
<None Include="..\..\plugins\include\cvars.inc" />
|
||||||
<None Include="..\..\plugins\include\datapack.inc" />
|
<None Include="..\..\plugins\include\datapack.inc" />
|
||||||
<None Include="..\..\plugins\include\gameconfig.inc" />
|
<None Include="..\..\plugins\include\gameconfig.inc" />
|
||||||
|
<None Include="..\..\plugins\include\newmenus.inc" />
|
||||||
<None Include="..\..\plugins\include\string_const.inc" />
|
<None Include="..\..\plugins\include\string_const.inc" />
|
||||||
<None Include="..\..\plugins\include\string_stocks.inc" />
|
<None Include="..\..\plugins\include\string_stocks.inc" />
|
||||||
<None Include="..\..\plugins\include\textparse_ini.inc" />
|
<None Include="..\..\plugins\include\textparse_ini.inc" />
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="ReSDK\engine">
|
<Filter Include="ReSDK\engine">
|
||||||
<UniqueIdentifier>{04fab577-6f56-40d0-8f69-7ce1b8bf3bb9}</UniqueIdentifier>
|
<UniqueIdentifier>{04fab577-6f56-40d0-8f69-7ce1b8bf3bb9}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Third Party\UTF8Rewind">
|
<Filter Include="Third Party\UTF8Rewind">
|
||||||
<UniqueIdentifier>{270f3524-564f-4154-bb35-242a6faac09e}</UniqueIdentifier>
|
<UniqueIdentifier>{270f3524-564f-4154-bb35-242a6faac09e}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@ -693,6 +693,9 @@
|
||||||
<None Include="..\..\plugins\include\string_stocks.inc">
|
<None Include="..\..\plugins\include\string_stocks.inc">
|
||||||
<Filter>Pawn Includes</Filter>
|
<Filter>Pawn Includes</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\plugins\include\newmenus.inc">
|
||||||
|
<Filter>Pawn Includes</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Object Include="..\Jit\helpers-x86.obj">
|
<Object Include="..\Jit\helpers-x86.obj">
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include "CMenu.h"
|
#include "CMenu.h"
|
||||||
#include "newmenus.h"
|
#include "newmenus.h"
|
||||||
|
#include "format.h"
|
||||||
|
|
||||||
ke::Vector<Menu *> g_NewMenus;
|
ke::Vector<Menu *> g_NewMenus;
|
||||||
CStack<int> g_MenuFreeStack;
|
CStack<int> g_MenuFreeStack;
|
||||||
|
@ -90,9 +91,9 @@ bool CloseNewMenus(CPlayer *pPlayer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::Menu(const char *title, AMX *amx, int fid) : m_Title(title), m_ItemColor("\\r"),
|
Menu::Menu(const char *title, AMX *amx, int fid, bool use_ml) : m_Title(title), m_ItemColor("\\r"),
|
||||||
m_NeverExit(false), m_AutoColors(g_coloredmenus), thisId(0), func(fid),
|
m_NeverExit(false), m_AutoColors(g_coloredmenus), thisId(0), func(fid),
|
||||||
isDestroying(false), pageCallback(-1), showPageNumber(true), items_per_page(7)
|
isDestroying(false), pageCallback(-1), showPageNumber(true), useMultilingual(use_ml), amx(amx), items_per_page(7)
|
||||||
{
|
{
|
||||||
CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx);
|
CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx);
|
||||||
menuId = g_menucmds.registerMenuId(title, amx);
|
menuId = g_menucmds.registerMenuId(title, amx);
|
||||||
|
@ -356,18 +357,32 @@ const char *Menu::GetTextString(int player, page_t page, int &keys)
|
||||||
|
|
||||||
m_Text = nullptr;
|
m_Text = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
auto title = m_Title.chars();
|
||||||
|
|
||||||
|
if (this->useMultilingual)
|
||||||
|
{
|
||||||
|
const auto language = playerlang(player);
|
||||||
|
const auto definition = translate(this->amx, language, title);
|
||||||
|
|
||||||
|
if (definition)
|
||||||
|
{
|
||||||
|
title = definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
if (showPageNumber && items_per_page && (pages != 1))
|
if (showPageNumber && items_per_page && (pages != 1))
|
||||||
{
|
{
|
||||||
if (m_AutoColors)
|
if (m_AutoColors)
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s %d/%d\n\\w\n", m_Title.chars(), page + 1, pages);
|
ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s %d/%d\n\\w\n", title, page + 1, pages);
|
||||||
else
|
else
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s %d/%d\n\n", m_Title.chars(), page + 1, pages);
|
ke::SafeSprintf(buffer, sizeof(buffer), "%s %d/%d\n\n", title, page + 1, pages);
|
||||||
} else {
|
} else {
|
||||||
if (m_AutoColors)
|
if (m_AutoColors)
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s\n\\w\n", m_Title.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s\n\\w\n", title);
|
||||||
else
|
else
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s\n\n", m_Title.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "%s\n\n", title);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Text = m_Text + buffer;
|
m_Text = m_Text + buffer;
|
||||||
|
@ -462,24 +477,37 @@ const char *Menu::GetTextString(int player, page_t page, int &keys)
|
||||||
option_display = 0;
|
option_display = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto itemName = pItem->name.chars();
|
||||||
|
|
||||||
|
if (this->useMultilingual)
|
||||||
|
{
|
||||||
|
const auto language = playerlang(player);
|
||||||
|
const auto definition = translate(this->amx, language, itemName);
|
||||||
|
|
||||||
|
if (definition)
|
||||||
|
{
|
||||||
|
itemName = definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pItem->isBlank)
|
if (pItem->isBlank)
|
||||||
{
|
{
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s\n", pItem->name.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "%s\n", itemName);
|
||||||
}
|
}
|
||||||
else if (enabled)
|
else if (enabled)
|
||||||
{
|
{
|
||||||
if (m_AutoColors)
|
if (m_AutoColors)
|
||||||
{
|
{
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s%d.\\w %s\n", m_ItemColor.chars(),option_display, pItem->name.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "%s%d.\\w %s\n", m_ItemColor.chars(),option_display, itemName);
|
||||||
} else {
|
} else {
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s\n", option_display, pItem->name.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s\n", option_display, itemName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m_AutoColors)
|
if (m_AutoColors)
|
||||||
{
|
{
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "\\d%d. %s\n\\w", option_display, pItem->name.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "\\d%d. %s\n\\w", option_display, itemName);
|
||||||
} else {
|
} else {
|
||||||
ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", pItem->name.chars());
|
ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", itemName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slots++;
|
slots++;
|
||||||
|
@ -620,38 +648,45 @@ const char *Menu::GetTextString(int player, page_t page, int &keys)
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid menu id %d(%d)", p, g_NewMenus.length()); \
|
LogError(amx, AMX_ERR_NATIVE, "Invalid menu id %d(%d)", p, g_NewMenus.length()); \
|
||||||
return 0; }
|
return 0; }
|
||||||
|
|
||||||
//Makes a new menu handle (-1 for failure)
|
// native menu_create(const title[], const handler[], bool:ml = false);
|
||||||
//native csdm_makemenu(title[]);
|
|
||||||
static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
int len;
|
enum args { arg_count, arg_title, arg_handler, arg_ml };
|
||||||
char *title = get_amxstring(amx, params[1], 0, len);
|
|
||||||
validate_menu_text(title);
|
|
||||||
char *handler = get_amxstring(amx, params[2], 1, len);
|
|
||||||
|
|
||||||
int func = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
int length;
|
||||||
|
const auto title = get_amxstring(amx, params[arg_title], 0, length);
|
||||||
|
const auto handler = get_amxstring(amx, params[arg_handler], 1, length);
|
||||||
|
const auto callback = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||||
|
|
||||||
if (func == -1)
|
if (callback == -1)
|
||||||
{
|
{
|
||||||
LogError(amx, AMX_ERR_NOTFOUND, "Invalid function \"%s\"", handler);
|
LogError(amx, AMX_ERR_NOTFOUND, R"(Invalid function "%s")", handler);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu *pMenu = new Menu(title, amx, func);
|
validate_menu_text(title);
|
||||||
|
|
||||||
|
auto pMenu = new Menu(title, amx, callback, params[arg_ml] != 0);
|
||||||
|
|
||||||
if (g_MenuFreeStack.empty())
|
if (g_MenuFreeStack.empty())
|
||||||
{
|
{
|
||||||
g_NewMenus.append(pMenu);
|
g_NewMenus.append(pMenu);
|
||||||
pMenu->thisId = (int)g_NewMenus.length() - 1;
|
|
||||||
} else {
|
pMenu->thisId = static_cast<int>(g_NewMenus.length()) - 1;
|
||||||
int pos = g_MenuFreeStack.front();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto position = g_MenuFreeStack.front();
|
||||||
|
|
||||||
g_MenuFreeStack.pop();
|
g_MenuFreeStack.pop();
|
||||||
g_NewMenus[pos] = pMenu;
|
g_NewMenus[position] = pMenu;
|
||||||
pMenu->thisId = pos;
|
|
||||||
|
pMenu->thisId = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pMenu->thisId;
|
return pMenu->thisId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL menu_addblank(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL menu_addblank(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
GETMENU(params[1]);
|
GETMENU(params[1]);
|
||||||
|
|
|
@ -95,7 +95,7 @@ typedef unsigned int page_t;
|
||||||
class Menu
|
class Menu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Menu(const char *title, AMX *amx, int fid);
|
Menu(const char *title, AMX *amx, int fid, bool use_ml);
|
||||||
~Menu();
|
~Menu();
|
||||||
|
|
||||||
menuitem *GetMenuItem(item_t item);
|
menuitem *GetMenuItem(item_t item);
|
||||||
|
@ -127,6 +127,8 @@ public:
|
||||||
bool isDestroying;
|
bool isDestroying;
|
||||||
int pageCallback;
|
int pageCallback;
|
||||||
bool showPageNumber;
|
bool showPageNumber;
|
||||||
|
bool useMultilingual;
|
||||||
|
AMX *amx;
|
||||||
public:
|
public:
|
||||||
unsigned int items_per_page;
|
unsigned int items_per_page;
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,13 +117,14 @@
|
||||||
* @param title Title the menu should use.
|
* @param title Title the menu should use.
|
||||||
* @param handler Name of the handler function. The function will be invoked
|
* @param handler Name of the handler function. The function will be invoked
|
||||||
* once and only once to every menu_display() call.
|
* once and only once to every menu_display() call.
|
||||||
* @param ml Unused (should be 0).
|
* @param ml If true, the menu title and items will be looked up as multilingual keys
|
||||||
|
* when the menu displays.
|
||||||
* @return Menu resource identifier which must be destroyed via
|
* @return Menu resource identifier which must be destroyed via
|
||||||
* menu_destroy(). All menus are destroyed when the plugin
|
* menu_destroy(). All menus are destroyed when the plugin
|
||||||
* unloads.
|
* unloads.
|
||||||
* @error Function name not found.
|
* @error Function name not found.
|
||||||
*/
|
*/
|
||||||
native menu_create(const title[], const handler[], ml=0);
|
native menu_create(const title[], const handler[], bool:ml = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a menu item callback handler.
|
* Creates a menu item callback handler.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user