diff --git a/core/MenuManager.cpp b/core/MenuManager.cpp index aade116b..43e809db 100644 --- a/core/MenuManager.cpp +++ b/core/MenuManager.cpp @@ -366,9 +366,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord } } } - } - else if (order == ItemOrder_Ascending) - { + } else if (order == ItemOrder_Ascending) { lastItem = drawItems[0].position; if (lastItem == 0) { @@ -398,7 +396,8 @@ skip_search: unsigned int position = 0; /* Keep track of the last position */ if (order == ItemOrder_Ascending) { - for (unsigned int i=0; iOnMenuDisplayItem(menu, client, display, drawItems[i].position, dr)) == 0) @@ -411,11 +410,14 @@ skip_search: slots[position].type = ItemSel_Item; } } - } else if (order == ItemOrder_Descending) { + } + else if (order == ItemOrder_Descending) + { unsigned int i = foundItems; /* NOTE: There will always be at least one item because * of the check earlier. */ + md.item_on_page = drawItems[foundItems - 1].position; while (i--) { ItemDrawInfo &dr = drawItems[i].draw; diff --git a/core/MenuStyle_Base.cpp b/core/MenuStyle_Base.cpp index ec9e58c7..4c236c44 100644 --- a/core/MenuStyle_Base.cpp +++ b/core/MenuStyle_Base.cpp @@ -288,7 +288,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press) IMenuHandler *mh = states.mh; IBaseMenu *menu = states.menu; - unsigned int item_on_page = states.firstItem; + unsigned int item_on_page = states.item_on_page; assert(mh != NULL); @@ -508,8 +508,8 @@ bool BaseMenuStyle::DoClientMenu(int client, _CancelClientMenu(client, MenuCancel_Interrupted, true); } - states.firstItem = first_item; - states.lastItem = 0; + states.firstItem = 0; + states.lastItem = first_item; states.menu = menu; states.mh = mh; states.apiVers = SMINTERFACE_MENUMANAGER_VERSION; diff --git a/core/smn_menus.cpp b/core/smn_menus.cpp index 80a87630..358d8b36 100644 --- a/core/smn_menus.cpp +++ b/core/smn_menus.cpp @@ -89,7 +89,7 @@ public: public: void OnMenuStart(IBaseMenu *menu); void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display); - void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item); + void OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page); void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason); void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason); void OnMenuDestroy(IBaseMenu *menu); @@ -273,6 +273,7 @@ void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) static IMenuPanel *s_pCurPanel = NULL; static unsigned int s_CurPanelReturn = 0; static const ItemDrawInfo *s_CurDrawInfo = NULL; +static unsigned int *s_CurSelectPosition = NULL; /** * MENU HANDLER WRAPPER @@ -311,9 +312,17 @@ void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel) } } -void CMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) +void CMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page) { + /* Save old position first. */ + unsigned int first_item = item_on_page; + unsigned int *old_pos = s_CurSelectPosition; + + s_CurSelectPosition = &first_item; + DoAction(menu, MenuAction_Select, client, item); + + s_CurSelectPosition = old_pos; } void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason) @@ -620,6 +629,20 @@ static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params) return menu->Display(params[2], params[3]) ? 1 : 0; } +static cell_t DisplayMenuAtItem(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = (Handle_t)params[1]; + HandleError err; + IBaseMenu *menu; + + if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None) + { + return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err); + } + + return menu->DisplayAtItem(params[2], params[4], params[3]) ? 1 : 0; +} + static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params) { if (g_Menus.IsVoteInProgress()) @@ -1358,6 +1381,16 @@ static cell_t CheckVoteDelay(IPluginContext *pContext, const cell_t *params) return g_Menus.GetRemainingVoteDelay(); } +static cell_t GetMenuSelectionPosition(IPluginContext *pContext, const cell_t *params) +{ + if (!s_CurSelectPosition) + { + return pContext->ThrowNativeError("Can only be called from inside a MenuAction_Select callback"); + } + + return *s_CurSelectPosition; +} + REGISTER_NATIVES(menuNatives) { {"AddMenuItem", AddMenuItem}, @@ -1371,6 +1404,7 @@ REGISTER_NATIVES(menuNatives) {"CreatePanel", CreatePanel}, {"CreatePanelFromMenu", CreatePanelFromMenu}, {"DisplayMenu", DisplayMenu}, + {"DisplayMenuAtItem", DisplayMenuAtItem}, {"DrawPanelItem", DrawPanelItem}, {"DrawPanelText", DrawPanelText}, {"GetClientMenu", GetClientMenu}, @@ -1381,6 +1415,7 @@ REGISTER_NATIVES(menuNatives) {"GetMenuItemCount", GetMenuItemCount}, {"GetMenuOptionFlags", GetMenuOptionFlags}, {"GetMenuPagination", GetMenuPagination}, + {"GetMenuSelectionPosition",GetMenuSelectionPosition}, {"GetMenuStyle", GetMenuStyle}, {"GetMenuStyleHandle", GetMenuStyleHandle}, {"GetMenuTitle", GetMenuTitle}, diff --git a/public/IMenuManager.h b/public/IMenuManager.h index 11e17fb8..5c8e9aa9 100644 --- a/public/IMenuManager.h +++ b/public/IMenuManager.h @@ -90,6 +90,7 @@ namespace SourceMod IMenuHandler *mh; /**< Menu callbacks handler */ unsigned int firstItem; /**< MENU ONLY: First item displayed on the last page */ unsigned int lastItem; /**< MENU ONLY: Last item displayed on the last page */ + unsigned int item_on_page; /**< MENU ONLY: First item on page */ menu_slots_t slots[11]; /**< MENU ONLY: Item selection table (first index is 1) */ };