From 61ac102fe25dab7060e25e9d8a9a349ece3e47ee Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 26 Sep 2007 21:44:12 +0000 Subject: [PATCH] - various improvements to the plugin-level topmenu api - categories are no longer displayed if they have no items --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401502 --- extensions/topmenus/TopMenu.cpp | 24 ++++++++ extensions/topmenus/msvc8/topmenus.vcproj | 6 +- extensions/topmenus/smn_topmenus.cpp | 45 +++++++++++++-- plugins/include/topmenus.inc | 70 ++++++++++++++++++----- 4 files changed, 123 insertions(+), 22 deletions(-) diff --git a/extensions/topmenus/TopMenu.cpp b/extensions/topmenus/TopMenu.cpp index 9b2803e3..50aef2ea 100644 --- a/extensions/topmenus/TopMenu.cpp +++ b/extensions/topmenus/TopMenu.cpp @@ -225,6 +225,14 @@ unsigned int TopMenu::AddToMenu(const char *name, parent_cat->obj_list.push_back(obj); parent_cat->reorder = true; parent_cat->serial++; + + /* If the category just went from 0 to 1 items, mark it as + * changed, so clients get the category drawn. + */ + if (parent_cat->obj_list.size() == 1) + { + m_SerialNo++; + } } m_ObjLookup.insert(name, obj); @@ -295,6 +303,14 @@ void TopMenu::RemoveFromMenu(unsigned int object_id) if (parent_cat->obj_list[i] == obj) { parent_cat->obj_list.erase(parent_cat->obj_list.iterAt(i)); + + /* If this category now has no items, mark root as changed + * so clients won't get the category drawn anymore. + */ + if (parent_cat->obj_list.size() == 0) + { + m_SerialNo++; + } break; } } @@ -552,6 +568,10 @@ void TopMenu::UpdateClientRoot(int client, IGamePlayer *pGamePlayer) /* Add the sorted items */ for (size_t i = 0; i < m_SortedCats.size(); i++) { + if (m_Categories[m_SortedCats[i]]->obj_list.size() == 0) + { + continue; + } root_menu->AppendItem(m_Categories[m_SortedCats[i]]->obj->name, ItemDrawInfo("")); } @@ -579,6 +599,10 @@ void TopMenu::UpdateClientRoot(int client, IGamePlayer *pGamePlayer) /* Add the new sorted categories */ for (size_t i = 0; i < m_SortedCats.size(); i++) { + if (m_Categories[item_list[i].obj_index]->obj_list.size() == 0) + { + continue; + } root_menu->AppendItem(m_Categories[item_list[i].obj_index]->obj->name, ItemDrawInfo("")); } diff --git a/extensions/topmenus/msvc8/topmenus.vcproj b/extensions/topmenus/msvc8/topmenus.vcproj index 48f95937..09e7a4c0 100644 --- a/extensions/topmenus/msvc8/topmenus.vcproj +++ b/extensions/topmenus/msvc8/topmenus.vcproj @@ -62,7 +62,7 @@ /> PushCell(m_hMenuHandle); - m_pFunction->PushCell(client); + m_pFunction->PushCell(TopMenuAction_DrawOption); m_pFunction->PushCell(object_id); + m_pFunction->PushCell(client); m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK); m_pFunction->PushCell(maxlength); m_pFunction->Execute(&result); @@ -100,8 +101,9 @@ public: size_t maxlength) { m_pFunction->PushCell(m_hMenuHandle); - m_pFunction->PushCell(client); + m_pFunction->PushCell(TopMenuAction_DrawTitle); m_pFunction->PushCell(object_id); + m_pFunction->PushCell(client); m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK); m_pFunction->PushCell(maxlength); m_pFunction->Execute(NULL); @@ -112,8 +114,9 @@ public: unsigned int object_id) { m_pFunction->PushCell(m_hMenuHandle); - m_pFunction->PushCell(client); + m_pFunction->PushCell(TopMenuAction_SelectOption); m_pFunction->PushCell(object_id); + m_pFunction->PushCell(client); m_pFunction->PushString(""); m_pFunction->PushCell(0); m_pFunction->Execute(NULL); @@ -157,6 +160,8 @@ static cell_t CreateTopMenu(IPluginContext *pContext, const cell_t *params) return BAD_HANDLE; } + cb->m_hMenuHandle = hndl; + return hndl; } @@ -204,7 +209,7 @@ static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params) char *name, *cmdname; pContext->LocalToString(params[2], &name); - pContext->LocalToString(params[5], &cmdname); + pContext->LocalToString(params[6], &cmdname); TopMenuObjectType obj_type = (TopMenuObjectType)params[3]; @@ -213,8 +218,9 @@ static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params) obj_type, cb, pContext->GetIdentity(), - cmdname,params[6], - params[7])) == 0) + cmdname, + params[7], + params[5])) == 0) { delete cb; return 0; @@ -258,10 +264,37 @@ static cell_t FindTopMenuCategory(IPluginContext *pContext, const cell_t *params return pMenu->FindCategory(name); } +static cell_t DisplayTopMenu(IPluginContext *pContext, const cell_t *params) +{ + HandleError err; + ITopMenu *pMenu; + HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); + + if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + int client = params[2]; + IGamePlayer *player = playerhelpers->GetGamePlayer(client); + if (!player) + { + return pContext->ThrowNativeError("Invalid client index %d", client); + } + else if (!player->IsInGame()) + { + return pContext->ThrowNativeError("Client %d is not in game", client); + } + + return pMenu->DisplayMenu(client, 0, (TopMenuPosition)params[3]); +} + sp_nativeinfo_t g_TopMenuNatives[] = { {"AddToTopMenu", AddToTopMenu}, {"CreateTopMenu", CreateTopMenu}, + {"DisplayTopMenu", DisplayTopMenu}, {"LoadTopMenuConfig", LoadTopMenuConfig}, {"RemoveFromTopMenu", RemoveFromTopMenu}, {"FindTopMenuCategory", FindTopMenuCategory}, diff --git a/plugins/include/topmenus.inc b/plugins/include/topmenus.inc index 24d3b383..3e6115b6 100644 --- a/plugins/include/topmenus.inc +++ b/plugins/include/topmenus.inc @@ -45,7 +45,7 @@ enum TopMenuAction /** * An option is being drawn for a menu (or for sorting purposes). * - * INPUT : TopMenu Handle, (param1) Client index, (param2) object ID. + * INPUT : TopMenu Handle, object ID, client index in extra parameter. * OUTPUT: Buffer for rendering, maxlength of buffer. * OUTPUT: Must return an ITEMDRAW constant. */ @@ -54,9 +54,10 @@ enum TopMenuAction /** * The title of a menu is being drawn for a given object. * - * Note: The Object ID will be 0 if drawing the root title. + * Note: The Object ID will be INVALID_TOPMENUOBJECT if drawing the + * root title. Otherwise, the Object ID is a category. * - * INPUT : TopMenu Handle, (param1) Client index, (param2) object ID. + * INPUT : TopMenu Handle, object ID, client index in extra parameter. * OUTPUT: Buffer for rendering, maxlength of buffer. */ TopMenuAction_DrawTitle = 1, @@ -64,7 +65,9 @@ enum TopMenuAction /** * A menu option has been selected. * - * INPUT : TopMenu Handle, (param1) Client index, (param2) object ID. + * The Object ID will always be an item (not a category). + * + * INPUT : TopMenu Handle, object ID, client index in extra parameter. */ TopMenuAction_SelectOption = 2, }; @@ -78,6 +81,16 @@ enum TopMenuObjectType TopMenuObject_Item = 1 /**< Item on a sub-menu */ }; +/** + * Top menu starting positions for display. + */ +enum TopMenuPosition +{ + TopMenuPosition_Start = 0, /**< Start/root of the menu */ + TopMenuPosition_LastRoot = 1, /**< Last position in the root menu */ + TopMenuPosition_LastCategory = 3, /**< Last position in their last category */ +}; + /** * Top menu object tag for type checking. */ @@ -91,16 +104,16 @@ enum TopMenuObject * * @param topmenu Handle to the TopMenu. * @param action TopMenuAction being performed. - * @param param1 First parameter (dependent on action). - * @param param2 Second parameter (dependent on action). - * @param buffer Output buffer (not always used). - * @param maxlength Output buffer (not always used). + * @param object_id The object ID (if used). + * @param param Extra parameter (if used). + * @param buffer Output buffer (if used). + * @param maxlength Output buffer (if used). * @noreturn */ functag TopMenuHandler public(Handle:topmenu, TopMenuAction:action, - param1, - param2, + TopMenuObject:object_id, + param, String:buffer[], maxlength); @@ -161,9 +174,9 @@ native TopMenuObject:AddToTopMenu(Handle:topmenu, const String:name[], TopMenuObjectType:type, TopMenuHandler:handler, - const String:cmdname[], - flags, - TopMenuObject:parent); + TopMenuObject:parent, + const String:cmdname[]="", + flags=0); /** * Removes an object from a TopMenu. @@ -178,6 +191,17 @@ native TopMenuObject:AddToTopMenu(Handle:topmenu, */ native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object); +/** + * Displays a TopMenu to a client. + * + * @param topmenu TopMenu Handle. + * @param client Client index. + * @param position Position to display from. + * @return True on success, false on failure. + * @error Invalid TopMenu Handle or client not in game. + */ +native DisplayTopMenu(Handle:topmenu, client, TopMenuPosition:position); + /** * Finds a category's object ID in a TopMenu. * @@ -188,3 +212,23 @@ native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object); * @error Invalid TopMenu Handle. */ native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]); + +/** + * Do not edit below this line! + */ +public Extension:__ext_cstrike = +{ + name = "TopMenus", + file = "topmenus.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; +