extensions/topmenus/smn_topmenus.cpp
author Scott Ehlert <ds@alliedmods.net>
Thu Mar 27 04:54:56 2008 +0000 (2008-03-27)
changeset 1947 e73a1e51833b
parent 1766 d30c252089be
child 2289 44045ead61cd
permissions -rw-r--r--
Updated copyright year
dvander@1699
     1
/**
dvander@1699
     2
 * vim: set ts=4 :
dvander@1699
     3
 * =============================================================================
dvander@1699
     4
 * SourceMod Sample Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@1699
     6
 * =============================================================================
dvander@1699
     7
 *
dvander@1699
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@1699
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@1699
    10
 * Free Software Foundation.
dvander@1699
    11
 * 
dvander@1699
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@1699
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@1699
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@1699
    15
 * details.
dvander@1699
    16
 *
dvander@1699
    17
 * You should have received a copy of the GNU General Public License along with
dvander@1699
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1699
    19
 *
dvander@1699
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@1699
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@1699
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@1699
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@1699
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@1699
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@1699
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@1699
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@1699
    28
 *
dvander@1699
    29
 * Version: $Id$
dvander@1699
    30
 */
dvander@1699
    31
dvander@1699
    32
#include "extension.h"
dvander@1699
    33
#include "TopMenuManager.h"
dvander@1699
    34
#include "TopMenu.h"
dvander@1699
    35
dvander@1699
    36
HandleType_t hTopMenuType;
dvander@1699
    37
dvander@1699
    38
class TopMenuHandle : public IHandleTypeDispatch
dvander@1699
    39
{
dvander@1699
    40
public: 
dvander@1699
    41
	void OnHandleDestroy(HandleType_t type, void *object)
dvander@1699
    42
	{
dvander@1699
    43
		ITopMenu *pTopMenu = (ITopMenu *)object;
dvander@1699
    44
		g_TopMenus.DestroyTopMenu(pTopMenu);
dvander@1699
    45
	}
dvander@1766
    46
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1766
    47
	{
dvander@1766
    48
		*pSize = ((TopMenu *)object)->CalcMemUsage();
dvander@1766
    49
		return true;
dvander@1766
    50
	}
dvander@1699
    51
} s_TopMenuHandle;
dvander@1699
    52
dvander@1699
    53
void Initialize_Natives()
dvander@1699
    54
{
dvander@1699
    55
	hTopMenuType = handlesys->CreateType("ITopMenu",
dvander@1699
    56
		&s_TopMenuHandle,
dvander@1699
    57
		0,
dvander@1699
    58
		NULL,
dvander@1699
    59
		NULL,
dvander@1699
    60
		myself->GetIdentity(),
dvander@1699
    61
		NULL);
dvander@1699
    62
}
dvander@1699
    63
dvander@1699
    64
void Shutdown_Natives()
dvander@1699
    65
{
dvander@1699
    66
	handlesys->RemoveType(hTopMenuType, myself->GetIdentity());
dvander@1699
    67
}
dvander@1699
    68
dvander@1699
    69
enum TopMenuAction
dvander@1699
    70
{
dvander@1699
    71
	TopMenuAction_DisplayOption = 0,
dvander@1699
    72
	TopMenuAction_DisplayTitle = 1,
dvander@1699
    73
	TopMenuAction_SelectOption = 2,
dvander@1699
    74
	TopMenuAction_DrawOption = 3,
dvander@1699
    75
	TopMenuAction_RemoveObject = 4,
dvander@1699
    76
};
dvander@1699
    77
dvander@1699
    78
class TopMenuCallbacks : public ITopMenuObjectCallbacks
dvander@1699
    79
{
dvander@1699
    80
public:
dvander@1699
    81
	TopMenuCallbacks(IPluginFunction *pFunction) : m_pFunction(pFunction)
dvander@1699
    82
	{		
dvander@1699
    83
	}
dvander@1699
    84
dvander@1699
    85
	unsigned int OnTopMenuDrawOption(ITopMenu *menu,
dvander@1699
    86
		int client,
dvander@1699
    87
		unsigned int object_id)
dvander@1699
    88
	{
dvander@1699
    89
		char buffer[2] = {ITEMDRAW_DEFAULT, 0x0};
dvander@1699
    90
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1699
    91
		m_pFunction->PushCell(TopMenuAction_DrawOption);
dvander@1699
    92
		m_pFunction->PushCell(object_id);
dvander@1699
    93
		m_pFunction->PushCell(client);
dvander@1699
    94
		m_pFunction->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
dvander@1699
    95
		m_pFunction->PushCell(sizeof(buffer));
dvander@1699
    96
		m_pFunction->Execute(NULL);
dvander@1699
    97
		return (unsigned int)buffer[0];
dvander@1699
    98
	}
dvander@1699
    99
dvander@1699
   100
	void OnTopMenuDisplayOption(ITopMenu *menu,
dvander@1699
   101
		int client, 
dvander@1699
   102
		unsigned int object_id,
dvander@1699
   103
		char buffer[], 
dvander@1699
   104
		size_t maxlength)
dvander@1699
   105
	{
dvander@1699
   106
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1699
   107
		m_pFunction->PushCell(TopMenuAction_DisplayOption);
dvander@1699
   108
		m_pFunction->PushCell(object_id);
dvander@1699
   109
		m_pFunction->PushCell(client);
dvander@1699
   110
		m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
dvander@1699
   111
		m_pFunction->PushCell(maxlength);
dvander@1699
   112
		m_pFunction->Execute(NULL);
dvander@1699
   113
	}
dvander@1699
   114
dvander@1699
   115
	void OnTopMenuDisplayTitle(ITopMenu *menu,
dvander@1699
   116
		int client,
dvander@1699
   117
		unsigned int object_id,
dvander@1699
   118
		char buffer[],
dvander@1699
   119
		size_t maxlength)
dvander@1699
   120
	{
dvander@1699
   121
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1699
   122
		m_pFunction->PushCell(TopMenuAction_DisplayTitle);
dvander@1699
   123
		m_pFunction->PushCell(object_id);
dvander@1699
   124
		m_pFunction->PushCell(client);
dvander@1699
   125
		m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
dvander@1699
   126
		m_pFunction->PushCell(maxlength);
dvander@1699
   127
		m_pFunction->Execute(NULL);
dvander@1699
   128
	}
dvander@1699
   129
dvander@1699
   130
	void OnTopMenuSelectOption(ITopMenu *menu, 
dvander@1699
   131
		int client, 
dvander@1699
   132
		unsigned int object_id)
dvander@1699
   133
	{
dvander@1699
   134
		unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
dvander@1699
   135
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1699
   136
		m_pFunction->PushCell(TopMenuAction_SelectOption);
dvander@1699
   137
		m_pFunction->PushCell(object_id);
dvander@1699
   138
		m_pFunction->PushCell(client);
dvander@1699
   139
		m_pFunction->PushString("");
dvander@1699
   140
		m_pFunction->PushCell(0);
dvander@1699
   141
		m_pFunction->Execute(NULL);
dvander@1699
   142
		playerhelpers->SetReplyTo(old_reply);
dvander@1699
   143
	}
dvander@1699
   144
dvander@1699
   145
	void OnTopMenuObjectRemoved(ITopMenu *menu, unsigned int object_id)
dvander@1699
   146
	{
dvander@1699
   147
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1699
   148
		m_pFunction->PushCell(TopMenuAction_RemoveObject);
dvander@1699
   149
		m_pFunction->PushCell(object_id);
dvander@1699
   150
		m_pFunction->PushCell(0);
dvander@1699
   151
		m_pFunction->PushString("");
dvander@1699
   152
		m_pFunction->PushCell(0);
dvander@1699
   153
		m_pFunction->Execute(NULL);
dvander@1699
   154
dvander@1699
   155
		delete this;
dvander@1699
   156
	}
dvander@1699
   157
dvander@1699
   158
	Handle_t m_hMenuHandle;
dvander@1699
   159
	IPluginFunction *m_pFunction;
dvander@1699
   160
};
dvander@1699
   161
dvander@1699
   162
static cell_t CreateTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1699
   163
{
dvander@1699
   164
	IPluginFunction *func = pContext->GetFunctionById(params[1]);
dvander@1699
   165
	if (func == NULL)
dvander@1699
   166
	{
dvander@1699
   167
		return pContext	->ThrowNativeError("Invalid function specified");
dvander@1699
   168
	}
dvander@1699
   169
dvander@1699
   170
	TopMenuCallbacks *cb = new TopMenuCallbacks(func);
dvander@1699
   171
dvander@1699
   172
	ITopMenu *pMenu = g_TopMenus.CreateTopMenu(cb);
dvander@1699
   173
dvander@1699
   174
	if (!pMenu)
dvander@1699
   175
	{
dvander@1699
   176
		delete cb;
dvander@1699
   177
		return BAD_HANDLE;
dvander@1699
   178
	}
dvander@1699
   179
dvander@1699
   180
	Handle_t hndl = handlesys->CreateHandle(hTopMenuType, 
dvander@1699
   181
		pMenu,
dvander@1699
   182
		pContext->GetIdentity(),
dvander@1699
   183
		myself->GetIdentity(),
dvander@1699
   184
		NULL);
dvander@1699
   185
	if (hndl == 0)
dvander@1699
   186
	{
dvander@1699
   187
		g_TopMenus.DestroyTopMenu(pMenu);
dvander@1699
   188
		return BAD_HANDLE;
dvander@1699
   189
	}
dvander@1699
   190
dvander@1699
   191
	cb->m_hMenuHandle = hndl;
dvander@1699
   192
dvander@1699
   193
	return hndl;
dvander@1699
   194
}
dvander@1699
   195
dvander@1699
   196
static cell_t LoadTopMenuConfig(IPluginContext *pContext, const cell_t *params)
dvander@1699
   197
{
dvander@1699
   198
	HandleError err;
dvander@1699
   199
	ITopMenu *pMenu;
dvander@1699
   200
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   201
dvander@1699
   202
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   203
		!= HandleError_None)
dvander@1699
   204
	{
dvander@1699
   205
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   206
	}
dvander@1699
   207
dvander@1699
   208
	char *file, *err_buf;
dvander@1699
   209
	pContext->LocalToString(params[2], &file);
dvander@1699
   210
	pContext->LocalToString(params[3], &err_buf);
dvander@1699
   211
dvander@1699
   212
	char path[PLATFORM_MAX_PATH];
dvander@1699
   213
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
dvander@1699
   214
dvander@1699
   215
	return pMenu->LoadConfiguration(path, err_buf, params[4]) ? 1 : 0;
dvander@1699
   216
}
dvander@1699
   217
dvander@1699
   218
static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1699
   219
{
dvander@1699
   220
	HandleError err;
dvander@1699
   221
	ITopMenu *pMenu;
dvander@1699
   222
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   223
dvander@1699
   224
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   225
		!= HandleError_None)
dvander@1699
   226
	{
dvander@1699
   227
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   228
	}
dvander@1699
   229
dvander@1699
   230
	IPluginFunction *func = pContext->GetFunctionById(params[4]);
dvander@1699
   231
	if (func == NULL)
dvander@1699
   232
	{
dvander@1699
   233
		return pContext	->ThrowNativeError("Invalid function specified");
dvander@1699
   234
	}
dvander@1699
   235
dvander@1699
   236
	TopMenuCallbacks *cb = new TopMenuCallbacks(func);
dvander@1699
   237
dvander@1699
   238
	char *name, *cmdname, *info_string = NULL;
dvander@1699
   239
	pContext->LocalToString(params[2], &name);
dvander@1699
   240
	pContext->LocalToString(params[6], &cmdname);
dvander@1699
   241
dvander@1699
   242
	if (params[0] >= 8)
dvander@1699
   243
	{
dvander@1699
   244
		pContext->LocalToString(params[8], &info_string);
dvander@1699
   245
	}
dvander@1699
   246
dvander@1699
   247
	TopMenuObjectType obj_type = (TopMenuObjectType)params[3];
dvander@1699
   248
	
dvander@1699
   249
	unsigned int object_id;
dvander@1699
   250
	if ((object_id = pMenu->AddToMenu2(name,
dvander@1699
   251
		obj_type,
dvander@1699
   252
		cb,
dvander@1699
   253
		pContext->GetIdentity(),
dvander@1699
   254
		cmdname,
dvander@1699
   255
		params[7], 
dvander@1699
   256
		params[5],
dvander@1699
   257
		info_string)) == 0)
dvander@1699
   258
	{
dvander@1699
   259
		delete cb;
dvander@1699
   260
		return 0;
dvander@1699
   261
	}
dvander@1699
   262
dvander@1699
   263
	cb->m_hMenuHandle = params[1];
dvander@1699
   264
dvander@1699
   265
	return object_id;
dvander@1699
   266
}
dvander@1699
   267
dvander@1699
   268
static cell_t RemoveFromTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1699
   269
{
dvander@1699
   270
	HandleError err;
dvander@1699
   271
	ITopMenu *pMenu;
dvander@1699
   272
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   273
dvander@1699
   274
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   275
		!= HandleError_None)
dvander@1699
   276
	{
dvander@1699
   277
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   278
	}
dvander@1699
   279
dvander@1699
   280
	pMenu->RemoveFromMenu(params[2]);
dvander@1699
   281
dvander@1699
   282
	return 1;
dvander@1699
   283
}
dvander@1699
   284
dvander@1699
   285
static cell_t FindTopMenuCategory(IPluginContext *pContext, const cell_t *params)
dvander@1699
   286
{
dvander@1699
   287
	HandleError err;
dvander@1699
   288
	ITopMenu *pMenu;
dvander@1699
   289
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   290
dvander@1699
   291
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   292
		!= HandleError_None)
dvander@1699
   293
	{
dvander@1699
   294
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   295
	}
dvander@1699
   296
dvander@1699
   297
	char *name;
dvander@1699
   298
	pContext->LocalToString(params[2], &name);
dvander@1699
   299
dvander@1699
   300
	return pMenu->FindCategory(name);
dvander@1699
   301
}
dvander@1699
   302
dvander@1699
   303
static cell_t DisplayTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1699
   304
{
dvander@1699
   305
	HandleError err;
dvander@1699
   306
	ITopMenu *pMenu;
dvander@1699
   307
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   308
dvander@1699
   309
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   310
		!= HandleError_None)
dvander@1699
   311
	{
dvander@1699
   312
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   313
	}
dvander@1699
   314
dvander@1699
   315
	int client = params[2];
dvander@1699
   316
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
dvander@1699
   317
	if (!player)
dvander@1699
   318
	{
dvander@1699
   319
		return pContext->ThrowNativeError("Invalid client index %d", client);
dvander@1699
   320
	}
dvander@1699
   321
	else if (!player->IsInGame())
dvander@1699
   322
	{
dvander@1699
   323
		return pContext->ThrowNativeError("Client %d is not in game", client);
dvander@1699
   324
	}
dvander@1699
   325
dvander@1699
   326
	return pMenu->DisplayMenu(client, 0, (TopMenuPosition)params[3]);
dvander@1699
   327
}
dvander@1699
   328
dvander@1699
   329
static cell_t GetTopMenuInfoString(IPluginContext *pContext, const cell_t *params)
dvander@1699
   330
{
dvander@1699
   331
	HandleError err;
dvander@1699
   332
	ITopMenu *pMenu;
dvander@1699
   333
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   334
dvander@1699
   335
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   336
		!= HandleError_None)
dvander@1699
   337
	{
dvander@1699
   338
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   339
	}
dvander@1699
   340
dvander@1699
   341
	const char *str;
dvander@1699
   342
	if ((str = pMenu->GetObjectInfoString(params[2])) == NULL)
dvander@1699
   343
	{
dvander@1699
   344
		return pContext->ThrowNativeError("Invalid menu object %d", params[2]);
dvander@1699
   345
	}
dvander@1699
   346
dvander@1699
   347
	char *buffer;
dvander@1699
   348
	pContext->LocalToString(params[3], &buffer);
dvander@1699
   349
dvander@1699
   350
	return strncopy(buffer, str, params[4]);
dvander@1699
   351
}
dvander@1699
   352
dvander@1699
   353
static cell_t GetTopMenuName(IPluginContext *pContext, const cell_t *params)
dvander@1699
   354
{
dvander@1699
   355
	HandleError err;
dvander@1699
   356
	ITopMenu *pMenu;
dvander@1699
   357
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1699
   358
dvander@1699
   359
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1699
   360
		!= HandleError_None)
dvander@1699
   361
	{
dvander@1699
   362
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1699
   363
	}
dvander@1699
   364
dvander@1699
   365
	const char *str;
dvander@1699
   366
	if ((str = pMenu->GetObjectName(params[2])) == NULL)
dvander@1699
   367
	{
dvander@1699
   368
		return pContext->ThrowNativeError("Invalid menu object %d", params[2]);
dvander@1699
   369
	}
dvander@1699
   370
dvander@1699
   371
	char *buffer;
dvander@1699
   372
	pContext->LocalToString(params[3], &buffer);
dvander@1699
   373
dvander@1699
   374
	return strncopy(buffer, str, params[4]);
dvander@1699
   375
}
dvander@1699
   376
dvander@1699
   377
sp_nativeinfo_t g_TopMenuNatives[] = 
dvander@1699
   378
{
dvander@1699
   379
	{"AddToTopMenu",			AddToTopMenu},
dvander@1699
   380
	{"CreateTopMenu",			CreateTopMenu},
dvander@1699
   381
	{"DisplayTopMenu",			DisplayTopMenu},
dvander@1699
   382
	{"LoadTopMenuConfig",		LoadTopMenuConfig},
dvander@1699
   383
	{"RemoveFromTopMenu",		RemoveFromTopMenu},
dvander@1699
   384
	{"FindTopMenuCategory",		FindTopMenuCategory},
dvander@1699
   385
	{"GetTopMenuInfoString",	GetTopMenuInfoString},
dvander@1700
   386
	{"GetTopMenuObjName",		GetTopMenuName},
dvander@1699
   387
	{NULL,					NULL},
dvander@1699
   388
};