From 1027d151e5ab4206377f739aa203a630d5490ae5 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 25 Jul 2007 01:18:11 +0000 Subject: [PATCH] - added MenuAction_DisplayItem callback for plugins - fixed various bugs in MenuAction_Display - added an "access" parameter for IMenuManager. better to do this now than later, even though it's not used yet - hard bumped menu api to change the OnMenuDisplayItem callback. sorry! --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401169 --- core/MenuManager.cpp | 16 +++++--- core/MenuManager.h | 2 +- core/MenuStyle_Base.cpp | 10 +++-- core/MenuStyle_Base.h | 2 + core/smn_menus.cpp | 79 +++++++++++++++++++++++++++++++++++++-- plugins/include/menus.inc | 15 +++++++- public/IMenuManager.h | 29 ++++++++------ 7 files changed, 127 insertions(+), 26 deletions(-) diff --git a/core/MenuManager.cpp b/core/MenuManager.cpp index fa0114ad..d6e5f207 100644 --- a/core/MenuManager.cpp +++ b/core/MenuManager.cpp @@ -187,9 +187,9 @@ void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *dis m_pHandler->OnMenuDisplay(menu, client, display); } -void VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display) +unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr) { - m_pHandler->OnMenuDisplayItem(menu, client, item, display); + return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr); } void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style) @@ -594,8 +594,11 @@ skip_search: for (unsigned int i=0; iOnMenuDisplayItem(menu, client, drawItems[i].position, &(dr.display)); - if ((position = display->DrawItem(dr)) != 0) + if ((position = mh->OnMenuDisplayItem(menu, client, display, drawItems[i].position, dr)) == 0) + { + position = display->DrawItem(dr); + } + if (position != 0) { slots[position].item = drawItems[i].position; slots[position].type = ItemSel_Item; @@ -609,7 +612,10 @@ skip_search: while (i--) { ItemDrawInfo &dr = drawItems[i].draw; - mh->OnMenuDisplayItem(menu, client, drawItems[i].position, &(dr.display)); + if ((position = mh->OnMenuDisplayItem(menu, client, display, drawItems[i].position, dr)) == 0) + { + position = display->DrawItem(dr); + } if ((position = display->DrawItem(dr)) != 0) { slots[position].item = drawItems[i].position; diff --git a/core/MenuManager.h b/core/MenuManager.h index 12a51670..a79e4e6a 100644 --- a/core/MenuManager.h +++ b/core/MenuManager.h @@ -35,7 +35,7 @@ public: //IMenuHandler void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason); void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason); void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); - void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display); + unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr); public: //IVoteMenuHandler bool IsVoteInProgress(); void InitializeVoting(IBaseMenu *menu); diff --git a/core/MenuStyle_Base.cpp b/core/MenuStyle_Base.cpp index d8341641..477b036a 100644 --- a/core/MenuStyle_Base.cpp +++ b/core/MenuStyle_Base.cpp @@ -427,10 +427,10 @@ bool BaseMenuStyle::DoClientMenu(int client, CBaseMenu *menu, IMenuHandler *mh, } /* For the duration of this, we are going to totally ignore whether - * the player is already in a menu or not (except to cancel the old one). - * Instead, we are simply going to ignore any further menu displays, so - * this display can't be interrupted. - */ + * the player is already in a menu or not (except to cancel the old one). + * Instead, we are simply going to ignore any further menu displays, so + * this display can't be interrupted. + */ player->bAutoIgnore = true; /* Cancel any old menus */ @@ -564,6 +564,7 @@ bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw) item.displayString = m_Strings.AddString(draw.display); } item.style = draw.style; + item.access = draw.access; m_items.push_back(item); @@ -591,6 +592,7 @@ bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDr item.displayString = m_Strings.AddString(draw.display); } item.style = draw.style; + item.access = draw.access; CVector::iterator iter = m_items.iterAt(position); m_items.insert(iter, item); diff --git a/core/MenuStyle_Base.h b/core/MenuStyle_Base.h index 08bcd608..3d5d3f74 100644 --- a/core/MenuStyle_Base.h +++ b/core/MenuStyle_Base.h @@ -33,11 +33,13 @@ public: infoString = -1; displayString = -1; style = 0; + access = 0; } public: int infoString; int displayString; unsigned int style; + unsigned int access; }; class CBaseMenuPlayer diff --git a/core/smn_menus.cpp b/core/smn_menus.cpp index f2ba8334..c8e600f6 100644 --- a/core/smn_menus.cpp +++ b/core/smn_menus.cpp @@ -45,6 +45,7 @@ enum MenuAction MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started */ MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */ MenuAction_DrawItem = (1<<8), /**< A style is being drawn; return the new style (param1=client, param2=item) */ + MenuAction_DisplayItem = (1<<9), /**< the odd duck */ }; class CPanelHandler : public IMenuHandler @@ -80,6 +81,7 @@ public: unsigned int totalVotes); void OnMenuVoteCancel(IBaseMenu *menu); void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); + unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr); #if 0 void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display); @@ -104,11 +106,13 @@ public: virtual void OnSourceModAllInitialized() { m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL); + m_TempPanelType = g_HandleSys.CreateType("TempIMenuPanel", this, m_PanelType, NULL, NULL, g_pCoreIdent, NULL); g_PluginSys.AddPluginsListener(this); } virtual void OnSourceModShutdown() { + g_HandleSys.RemoveType(m_TempPanelType, g_pCoreIdent); g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent); while (!m_FreePanelHandlers.empty()) @@ -126,6 +130,11 @@ public: virtual void OnHandleDestroy(HandleType_t type, void *object) { + if (type == m_TempPanelType) + { + return; + } + IMenuPanel *panel = (IMenuPanel *)object; panel->DeleteThis(); } @@ -155,6 +164,11 @@ public: return m_PanelType; } + inline HandleType_t GetTempPanelType() + { + return m_TempPanelType; + } + CPanelHandler *GetPanelHandler(IPluginFunction *pFunction) { CPanelHandler *handler; @@ -200,6 +214,7 @@ public: private: HandleType_t m_PanelType; + HandleType_t m_TempPanelType; CStack m_FreePanelHandlers; CStack m_FreeMenuHandlers; CVector m_PanelHandlers; @@ -235,6 +250,10 @@ void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) g_MenuHelpers.FreePanelHandler(this); } +static IMenuPanel *s_pCurPanel = NULL; +static unsigned int s_CurPanelReturn = 0; +static const ItemDrawInfo *s_CurDrawInfo = NULL; + /** * MENU HANDLER WRAPPER */ @@ -257,14 +276,14 @@ void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel) if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display) { HandleSecurity sec; - sec.pIdentity = m_pBasic->GetParentContext()->GetIdentity(); - sec.pOwner = g_pCoreIdent; + sec.pIdentity = g_pCoreIdent; + sec.pOwner = m_pBasic->GetParentContext()->GetIdentity(); HandleAccess access; g_HandleSys.InitAccessDefaults(NULL, &access); access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER; - Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetPanelType(), panel, &sec, &access, NULL); + Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetTempPanelType(), panel, &sec, &access, NULL); DoAction(menu, MenuAction_Display, client, hndl); @@ -319,6 +338,38 @@ void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item } } +unsigned int CMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, + int client, + IMenuPanel *panel, + unsigned int item, + const ItemDrawInfo &dr) +{ + if ((m_Flags & (int)MenuAction_DisplayItem) == (int)MenuAction_DisplayItem) + { + IMenuPanel *oldpanel = s_pCurPanel; + unsigned int oldret = s_CurPanelReturn; + const ItemDrawInfo *oldinfo = s_CurDrawInfo; + s_pCurPanel = panel; + s_CurPanelReturn = 0; + s_CurDrawInfo = &dr; + + cell_t res = DoAction(menu, MenuAction_DisplayItem, client, item, 0); + + if (!res) + { + res = s_CurPanelReturn; + } + + s_pCurPanel = oldpanel; + s_CurPanelReturn = oldret; + s_CurDrawInfo = oldinfo; + + return res; + } + + return 0; +} + cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res) { #if defined MENU_DEBUG @@ -1002,6 +1053,27 @@ static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params) return panel->SetCurrentKey(params[2]) ? 1 : 0; } +static cell_t RedrawMenuItem(IPluginContext *pContext, const cell_t *params) +{ + if (!s_pCurPanel) + { + return pContext->ThrowNativeError("You can only call this once from a MenuAction_DisplayItem callback"); + } + + char *str; + pContext->LocalToString(params[1], &str); + + ItemDrawInfo dr = *s_CurDrawInfo; + dr.display = str; + + if ((s_CurPanelReturn = s_pCurPanel->DrawItem(dr)) != 0) + { + s_pCurPanel = NULL; + } + + return s_CurPanelReturn; +} + REGISTER_NATIVES(menuNatives) { {"AddMenuItem", AddMenuItem}, @@ -1028,6 +1100,7 @@ REGISTER_NATIVES(menuNatives) {"GetPanelStyle", GetPanelStyle}, {"InsertMenuItem", InsertMenuItem}, {"IsVoteInProgress", IsVoteInProgress}, + {"RedrawMenuItem", RedrawMenuItem}, {"RemoveAllMenuItems", RemoveAllMenuItems}, {"RemoveMenuItem", RemoveMenuItem}, {"SendPanelToClient", SendPanelToClient}, diff --git a/plugins/include/menus.inc b/plugins/include/menus.inc index f133fc54..dde6a96a 100644 --- a/plugins/include/menus.inc +++ b/plugins/include/menus.inc @@ -42,6 +42,10 @@ enum MenuAction MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started (nothing passed) */ MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */ MenuAction_DrawItem = (1<<8), /**< An item is being drawn; return the new style (param1=client, param2=item) */ + MenuAction_DisplayItem = (1<<9) /**< Item text is being drawn to the display (param1=client, param2=item) + To change the text, use RedrawMenuItem(). + If you do so, return its return value. Otherwise, return 0. + */ }; /** Default menu actions */ @@ -475,7 +479,8 @@ native DrawPanelItem(Handle:panel, const String:text[], style=ITEMDRAW_DEFAULT); /** * Draws a raw line of text on a panel, without any markup other than a newline. * - * @param panel A MenuPanel Handle. + * @param panel A MenuPanel Handle, or INVALID_HANDLE if inside a + * MenuAction_DisplayItem callback. * @param text Display text to use. * @return True on success, false if raw lines are not supported. * @error Invalid Handle. @@ -545,6 +550,14 @@ native GetPanelCurrentKey(Handle:panel); */ native bool:SetPanelCurrentKey(Handle:panel, key); +/** + * @brief Redraws menu text from inside a MenuAction_DisplayItem callback. + * + * @param text Menu text to draw. + * @return Item position; must be returned via the callback. + */ +native RedrawMenuItem(const String:text[]); + /** * Retrieves voting information from MenuAction_VoteEnd. * diff --git a/public/IMenuManager.h b/public/IMenuManager.h index f2d9b708..9784d84b 100644 --- a/public/IMenuManager.h +++ b/public/IMenuManager.h @@ -23,7 +23,7 @@ #include #define SMINTERFACE_MENUMANAGER_NAME "IMenuManager" -#define SMINTERFACE_MENUMANAGER_VERSION 6 +#define SMINTERFACE_MENUMANAGER_VERSION 7 /** * @file IMenuManager.h @@ -93,17 +93,14 @@ namespace SourceMod */ struct ItemDrawInfo { - ItemDrawInfo() - { - style = 0; - display = NULL; - } - ItemDrawInfo(const char *DISPLAY, unsigned int STYLE=ITEMDRAW_DEFAULT) - : display(DISPLAY), style(STYLE) + ItemDrawInfo(const char *DISPLAY=NULL, unsigned int STYLE=ITEMDRAW_DEFAULT, + unsigned int FLAGS=0, const char *HELPTEXT=NULL) + : display(DISPLAY), style(STYLE), access(FLAGS) { } const char *display; /**< Display text (NULL for none) */ unsigned int style; /**< ITEMDRAW style flags */ + unsigned int access; /**< Access flags required to see */ }; /** @@ -648,15 +645,23 @@ namespace SourceMod } /** - * @brief Called when requesting how to draw an item's text. + * @brief Called when drawing item text. * * @param menu Menu pointer. * @param client Client index receiving the menu. + * @param panel Panel being used to draw the menu. * @param item Item number in the menu. - * @param display Pointer to the display text string (changeable). + * @param dr Item draw information. + * @return 0 to let the render algorithm decide how to draw, otherwise, + * the return value from panel->DrawItem should be returned. */ - virtual void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display) + virtual unsigned int OnMenuDisplayItem(IBaseMenu *menu, + int client, + IMenuPanel *panel, + unsigned int item, + const ItemDrawInfo &dr) { + return 0; } /** @@ -755,7 +760,7 @@ namespace SourceMod } virtual bool IsVersionCompatible(unsigned int version) { - if (version < 5 || version > GetInterfaceVersion()) + if (version < 7 || version > GetInterfaceVersion()) { return false; }