- 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
This commit is contained in:
David Anderson 2007-09-26 21:44:12 +00:00
parent 035d646dfd
commit 61ac102fe2
4 changed files with 123 additions and 22 deletions

View File

@ -225,6 +225,14 @@ unsigned int TopMenu::AddToMenu(const char *name,
parent_cat->obj_list.push_back(obj); parent_cat->obj_list.push_back(obj);
parent_cat->reorder = true; parent_cat->reorder = true;
parent_cat->serial++; 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); m_ObjLookup.insert(name, obj);
@ -295,6 +303,14 @@ void TopMenu::RemoveFromMenu(unsigned int object_id)
if (parent_cat->obj_list[i] == obj) if (parent_cat->obj_list[i] == obj)
{ {
parent_cat->obj_list.erase(parent_cat->obj_list.iterAt(i)); 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; break;
} }
} }
@ -552,6 +568,10 @@ void TopMenu::UpdateClientRoot(int client, IGamePlayer *pGamePlayer)
/* Add the sorted items */ /* Add the sorted items */
for (size_t i = 0; i < m_SortedCats.size(); i++) 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("")); 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 */ /* Add the new sorted categories */
for (size_t i = 0; i < m_SortedCats.size(); i++) 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("")); root_menu->AppendItem(m_Categories[item_list[i].obj_index]->obj->name, ItemDrawInfo(""));
} }

View File

@ -62,7 +62,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
OutputFile="$(OutDir)\sample.ext.dll" OutputFile="$(OutDir)\topmenus.ext.dll"
LinkIncremental="2" LinkIncremental="2"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"
@ -118,7 +118,7 @@
/> />
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\sourcepawn" AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\sourcepawn;..\..\..\public\extensions"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
RuntimeLibrary="0" RuntimeLibrary="0"
RuntimeTypeInfo="false" RuntimeTypeInfo="false"
@ -138,7 +138,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
OutputFile="$(OutDir)\sample.ext.dll" OutputFile="$(OutDir)\topmenus.ext.dll"
LinkIncremental="1" LinkIncremental="1"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"

View File

@ -84,8 +84,9 @@ public:
cell_t result = ITEMDRAW_DEFAULT; cell_t result = ITEMDRAW_DEFAULT;
m_pFunction->PushCell(m_hMenuHandle); m_pFunction->PushCell(m_hMenuHandle);
m_pFunction->PushCell(client); m_pFunction->PushCell(TopMenuAction_DrawOption);
m_pFunction->PushCell(object_id); m_pFunction->PushCell(object_id);
m_pFunction->PushCell(client);
m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK); m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
m_pFunction->PushCell(maxlength); m_pFunction->PushCell(maxlength);
m_pFunction->Execute(&result); m_pFunction->Execute(&result);
@ -100,8 +101,9 @@ public:
size_t maxlength) size_t maxlength)
{ {
m_pFunction->PushCell(m_hMenuHandle); m_pFunction->PushCell(m_hMenuHandle);
m_pFunction->PushCell(client); m_pFunction->PushCell(TopMenuAction_DrawTitle);
m_pFunction->PushCell(object_id); m_pFunction->PushCell(object_id);
m_pFunction->PushCell(client);
m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK); m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
m_pFunction->PushCell(maxlength); m_pFunction->PushCell(maxlength);
m_pFunction->Execute(NULL); m_pFunction->Execute(NULL);
@ -112,8 +114,9 @@ public:
unsigned int object_id) unsigned int object_id)
{ {
m_pFunction->PushCell(m_hMenuHandle); m_pFunction->PushCell(m_hMenuHandle);
m_pFunction->PushCell(client); m_pFunction->PushCell(TopMenuAction_SelectOption);
m_pFunction->PushCell(object_id); m_pFunction->PushCell(object_id);
m_pFunction->PushCell(client);
m_pFunction->PushString(""); m_pFunction->PushString("");
m_pFunction->PushCell(0); m_pFunction->PushCell(0);
m_pFunction->Execute(NULL); m_pFunction->Execute(NULL);
@ -157,6 +160,8 @@ static cell_t CreateTopMenu(IPluginContext *pContext, const cell_t *params)
return BAD_HANDLE; return BAD_HANDLE;
} }
cb->m_hMenuHandle = hndl;
return hndl; return hndl;
} }
@ -204,7 +209,7 @@ static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params)
char *name, *cmdname; char *name, *cmdname;
pContext->LocalToString(params[2], &name); pContext->LocalToString(params[2], &name);
pContext->LocalToString(params[5], &cmdname); pContext->LocalToString(params[6], &cmdname);
TopMenuObjectType obj_type = (TopMenuObjectType)params[3]; TopMenuObjectType obj_type = (TopMenuObjectType)params[3];
@ -213,8 +218,9 @@ static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params)
obj_type, obj_type,
cb, cb,
pContext->GetIdentity(), pContext->GetIdentity(),
cmdname,params[6], cmdname,
params[7])) == 0) params[7],
params[5])) == 0)
{ {
delete cb; delete cb;
return 0; return 0;
@ -258,10 +264,37 @@ static cell_t FindTopMenuCategory(IPluginContext *pContext, const cell_t *params
return pMenu->FindCategory(name); 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[] = sp_nativeinfo_t g_TopMenuNatives[] =
{ {
{"AddToTopMenu", AddToTopMenu}, {"AddToTopMenu", AddToTopMenu},
{"CreateTopMenu", CreateTopMenu}, {"CreateTopMenu", CreateTopMenu},
{"DisplayTopMenu", DisplayTopMenu},
{"LoadTopMenuConfig", LoadTopMenuConfig}, {"LoadTopMenuConfig", LoadTopMenuConfig},
{"RemoveFromTopMenu", RemoveFromTopMenu}, {"RemoveFromTopMenu", RemoveFromTopMenu},
{"FindTopMenuCategory", FindTopMenuCategory}, {"FindTopMenuCategory", FindTopMenuCategory},

View File

@ -45,7 +45,7 @@ enum TopMenuAction
/** /**
* An option is being drawn for a menu (or for sorting purposes). * 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: Buffer for rendering, maxlength of buffer.
* OUTPUT: Must return an ITEMDRAW constant. * OUTPUT: Must return an ITEMDRAW constant.
*/ */
@ -54,9 +54,10 @@ enum TopMenuAction
/** /**
* The title of a menu is being drawn for a given object. * 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. * OUTPUT: Buffer for rendering, maxlength of buffer.
*/ */
TopMenuAction_DrawTitle = 1, TopMenuAction_DrawTitle = 1,
@ -64,7 +65,9 @@ enum TopMenuAction
/** /**
* A menu option has been selected. * 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, TopMenuAction_SelectOption = 2,
}; };
@ -78,6 +81,16 @@ enum TopMenuObjectType
TopMenuObject_Item = 1 /**< Item on a sub-menu */ 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. * Top menu object tag for type checking.
*/ */
@ -91,16 +104,16 @@ enum TopMenuObject
* *
* @param topmenu Handle to the TopMenu. * @param topmenu Handle to the TopMenu.
* @param action TopMenuAction being performed. * @param action TopMenuAction being performed.
* @param param1 First parameter (dependent on action). * @param object_id The object ID (if used).
* @param param2 Second parameter (dependent on action). * @param param Extra parameter (if used).
* @param buffer Output buffer (not always used). * @param buffer Output buffer (if used).
* @param maxlength Output buffer (not always used). * @param maxlength Output buffer (if used).
* @noreturn * @noreturn
*/ */
functag TopMenuHandler public(Handle:topmenu, functag TopMenuHandler public(Handle:topmenu,
TopMenuAction:action, TopMenuAction:action,
param1, TopMenuObject:object_id,
param2, param,
String:buffer[], String:buffer[],
maxlength); maxlength);
@ -161,9 +174,9 @@ native TopMenuObject:AddToTopMenu(Handle:topmenu,
const String:name[], const String:name[],
TopMenuObjectType:type, TopMenuObjectType:type,
TopMenuHandler:handler, TopMenuHandler:handler,
const String:cmdname[], TopMenuObject:parent,
flags, const String:cmdname[]="",
TopMenuObject:parent); flags=0);
/** /**
* Removes an object from a TopMenu. * Removes an object from a TopMenu.
@ -178,6 +191,17 @@ native TopMenuObject:AddToTopMenu(Handle:topmenu,
*/ */
native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object); 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. * Finds a category's object ID in a TopMenu.
* *
@ -188,3 +212,23 @@ native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object);
* @error Invalid TopMenu Handle. * @error Invalid TopMenu Handle.
*/ */
native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]); 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
};