core/MenuStyle_Base.cpp
author Scott Ehlert <ds@alliedmods.net>
Mon Jul 23 19:38:02 2007 +0000 (2007-07-23)
changeset 1149 70d171906c7e
parent 1131 d109d9e33ee5
child 1163 0bb03cb6277b
permissions -rw-r--r--
No comment worth mentioning for this one :x
dvander@769
     1
/**
dvander@769
     2
 * vim: set ts=4 :
dvander@769
     3
 * ===============================================================
dvander@769
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@769
     5
 * ===============================================================
dvander@769
     6
 *
dvander@769
     7
 * This file is not open source and may not be copied without explicit
dvander@769
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@769
     9
 * in whole or significant part.
dvander@769
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@769
    11
 *
dvander@769
    12
 * Version: $Id$
dvander@769
    13
 */
dvander@771
    14
dvander@769
    15
#include <stdarg.h>
dvander@769
    16
#include "sm_stringutil.h"
dvander@769
    17
#include "MenuStyle_Base.h"
dvander@775
    18
#include "PlayerManager.h"
dvander@775
    19
#include "MenuManager.h"
dvander@790
    20
#include "HandleSys.h"
dvander@970
    21
#if defined MENU_DEBUG
dvander@970
    22
#include "Logger.h"
dvander@970
    23
#endif
dvander@775
    24
dvander@790
    25
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
dvander@790
    26
{
dvander@790
    27
}
dvander@790
    28
dvander@790
    29
Handle_t BaseMenuStyle::GetHandle()
dvander@775
    30
{
dvander@790
    31
	/* Don't create the handle until we need it */
dvander@790
    32
	if (m_hHandle == BAD_HANDLE)
dvander@790
    33
	{
dvander@790
    34
		m_hHandle = g_Menus.CreateStyleHandle(this);
dvander@790
    35
	}
dvander@790
    36
dvander@790
    37
	return m_hHandle;
dvander@775
    38
}
dvander@775
    39
dvander@775
    40
void BaseMenuStyle::AddClientToWatch(int client)
dvander@775
    41
{
dvander@970
    42
#if defined MENU_DEBUG
dvander@970
    43
	g_Logger.LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
dvander@970
    44
#endif
dvander@775
    45
	m_WatchList.push_back(client);
dvander@775
    46
}
dvander@775
    47
dvander@775
    48
void BaseMenuStyle::RemoveClientFromWatch(int client)
dvander@775
    49
{
dvander@970
    50
#if defined MENU_DEBUG
dvander@970
    51
	g_Logger.LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
dvander@970
    52
#endif
dvander@775
    53
	m_WatchList.remove(client);
dvander@775
    54
}
dvander@775
    55
dvander@1005
    56
void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore/* =false */)
dvander@775
    57
{
dvander@970
    58
#if defined MENU_DEBUG
dvander@970
    59
	g_Logger.LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
dvander@970
    60
#endif
dvander@775
    61
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
    62
	menu_states_t &states = player->states;
dvander@775
    63
dvander@775
    64
	bool bOldIgnore = player->bAutoIgnore;
dvander@775
    65
	if (bAutoIgnore)
dvander@775
    66
	{
dvander@775
    67
		player->bAutoIgnore = true;
dvander@775
    68
	}
dvander@775
    69
dvander@775
    70
	/* Save states */
dvander@775
    71
	IMenuHandler *mh = states.mh;
dvander@775
    72
	IBaseMenu *menu = states.menu;
dvander@775
    73
dvander@775
    74
	/* Clear menu */
dvander@775
    75
	player->bInMenu = false;
dvander@775
    76
	if (player->menuHoldTime)
dvander@775
    77
	{
dvander@775
    78
		RemoveClientFromWatch(client);
dvander@775
    79
	}
dvander@775
    80
dvander@775
    81
	/* Fire callbacks */
dvander@775
    82
	mh->OnMenuCancel(menu, client, reason);
dvander@790
    83
	
dvander@790
    84
	/* Only fire end if there's a valid menu */
dvander@790
    85
	if (menu)
dvander@790
    86
	{
dvander@997
    87
		mh->OnMenuEnd(menu, MenuEnd_Cancelled);
dvander@790
    88
	}
dvander@775
    89
dvander@775
    90
	if (bAutoIgnore)
dvander@775
    91
	{
dvander@775
    92
		player->bAutoIgnore = bOldIgnore;
dvander@775
    93
	}
dvander@775
    94
}
dvander@775
    95
dvander@775
    96
void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
dvander@775
    97
{
dvander@970
    98
#if defined MENU_DEBUG
dvander@970
    99
	g_Logger.LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
dvander@970
   100
#endif
dvander@775
   101
	int maxClients = g_Players.GetMaxClients();
dvander@775
   102
	for (int i=1; i<=maxClients; i++)
dvander@775
   103
	{
dvander@775
   104
		CBaseMenuPlayer *player = GetMenuPlayer(i);
dvander@775
   105
		if (player->bInMenu)
dvander@775
   106
		{
dvander@775
   107
			menu_states_t &states = player->states;
dvander@775
   108
			if (states.menu == menu)
dvander@775
   109
			{
dvander@1005
   110
				_CancelClientMenu(i, MenuCancel_Interrupted);
dvander@775
   111
			}
dvander@775
   112
		}
dvander@775
   113
	}
dvander@775
   114
}
dvander@775
   115
dvander@775
   116
bool BaseMenuStyle::CancelClientMenu(int client, bool autoIgnore)
dvander@775
   117
{
dvander@970
   118
#if defined MENU_DEBUG
dvander@970
   119
	g_Logger.LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
dvander@970
   120
#endif
dvander@775
   121
	if (client < 1 || client > g_Players.MaxClients())
dvander@775
   122
	{
dvander@775
   123
		return false;
dvander@775
   124
	}
dvander@775
   125
dvander@775
   126
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   127
	if (!player->bInMenu)
dvander@775
   128
	{
dvander@775
   129
		return false;
dvander@775
   130
	}
dvander@775
   131
dvander@1005
   132
	_CancelClientMenu(client, MenuCancel_Interrupted, autoIgnore);
dvander@775
   133
dvander@775
   134
	return true;
dvander@775
   135
}
dvander@775
   136
dvander@775
   137
MenuSource BaseMenuStyle::GetClientMenu(int client, void **object)
dvander@775
   138
{
dvander@775
   139
	if (client < 1 || client > g_Players.GetMaxClients())
dvander@775
   140
	{
dvander@775
   141
		return MenuSource_None;
dvander@775
   142
	}
dvander@775
   143
dvander@775
   144
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   145
dvander@775
   146
	if (player->bInMenu)
dvander@775
   147
	{
dvander@775
   148
		IBaseMenu *menu;
dvander@775
   149
		if ((menu=player->states.menu) != NULL)
dvander@775
   150
		{
dvander@775
   151
			if (object)
dvander@775
   152
			{
dvander@775
   153
				*object = menu;
dvander@775
   154
			}
dvander@775
   155
			return MenuSource_BaseMenu;
dvander@775
   156
		}
dvander@775
   157
dvander@775
   158
		return MenuSource_Display;
dvander@780
   159
	} else if (player->bInExternMenu) {
dvander@782
   160
		if (player->menuHoldTime != 0
dvander@782
   161
			&& (gpGlobals->curtime > player->menuStartTime + player->menuHoldTime))
dvander@782
   162
		{
dvander@782
   163
			player->bInExternMenu = false;
dvander@782
   164
			return MenuSource_None;
dvander@782
   165
		}
dvander@780
   166
		return MenuSource_External;
dvander@775
   167
	}
dvander@775
   168
dvander@775
   169
	return MenuSource_None;
dvander@775
   170
}
dvander@775
   171
dvander@775
   172
void BaseMenuStyle::OnClientDisconnected(int client)
dvander@775
   173
{
dvander@970
   174
#if defined MENU_DEBUG
dvander@970
   175
	g_Logger.LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
dvander@970
   176
#endif
dvander@775
   177
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   178
	if (!player->bInMenu)
dvander@775
   179
	{
dvander@775
   180
		return;
dvander@775
   181
	}
dvander@775
   182
dvander@1005
   183
	_CancelClientMenu(client, MenuCancel_Disconnected, true);
dvander@775
   184
dvander@775
   185
	player->bInMenu = false;
dvander@790
   186
	player->bInExternMenu = false;
dvander@775
   187
}
dvander@775
   188
dvander@775
   189
static int do_lookup[256];
dvander@775
   190
void BaseMenuStyle::ProcessWatchList()
dvander@775
   191
{
dvander@775
   192
	if (!m_WatchList.size())
dvander@775
   193
	{
dvander@775
   194
		return;
dvander@775
   195
	}
dvander@775
   196
dvander@1131
   197
#if defined MENU_DEBUG
dvander@1131
   198
	g_Logger.LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)", 
dvander@1131
   199
		m_WatchList.m_Size,
dvander@1131
   200
		m_WatchList.m_FirstLink,
dvander@1131
   201
		m_WatchList.m_FreeNodes,
dvander@1131
   202
		m_WatchList.m_LastLink,
dvander@1131
   203
		m_WatchList.m_MaxSize,
dvander@1131
   204
		m_WatchList.m_Nodes);
dvander@1131
   205
#endif
dvander@1131
   206
dvander@775
   207
	unsigned int total = 0;
dvander@775
   208
	for (FastLink<int>::iterator iter=m_WatchList.begin(); iter!=m_WatchList.end(); ++iter)
dvander@775
   209
	{
dvander@775
   210
		do_lookup[total++] = (*iter);
dvander@775
   211
	}
dvander@775
   212
dvander@970
   213
#if defined MENU_DEBUG
dvander@970
   214
	if (total)
dvander@970
   215
	{
dvander@970
   216
		g_Logger.LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
dvander@970
   217
	}
dvander@970
   218
#endif
dvander@970
   219
dvander@775
   220
	int client;
dvander@775
   221
	CBaseMenuPlayer *player;
dvander@775
   222
	float curTime = gpGlobals->curtime;
dvander@775
   223
	for (unsigned int i=0; i<total; i++)
dvander@775
   224
	{
dvander@775
   225
		client = do_lookup[i];
dvander@775
   226
		player = GetMenuPlayer(client);
dvander@970
   227
#if defined MENU_DEBUG
dvander@970
   228
		g_Logger.LogMessage("[SM_MENU] ProcessWatchList() (client %d) (bInMenu %d) (menuHoldTime %d) (curTime %f) (menuStartTime %f)",
dvander@970
   229
			client,
dvander@970
   230
			player->bInMenu,
dvander@970
   231
			player->menuHoldTime,
dvander@970
   232
			curTime,
dvander@970
   233
			player->menuStartTime);
dvander@970
   234
#endif
dvander@775
   235
		if (!player->bInMenu || !player->menuHoldTime)
dvander@775
   236
		{
dvander@970
   237
#if defined MENU_DEBUG
dvander@970
   238
			g_Logger.LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
dvander@970
   239
#endif
dvander@825
   240
			m_WatchList.remove(client);
dvander@775
   241
			continue;
dvander@775
   242
		}
dvander@775
   243
		if (curTime > player->menuStartTime + player->menuHoldTime)
dvander@775
   244
		{
dvander@1005
   245
			_CancelClientMenu(client, MenuCancel_Timeout, false);
dvander@775
   246
		}
dvander@775
   247
	}
dvander@775
   248
}
dvander@775
   249
dvander@775
   250
void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
dvander@775
   251
{
dvander@970
   252
#if defined MENU_DEBUG
dvander@970
   253
	g_Logger.LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
dvander@970
   254
#endif
dvander@775
   255
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   256
dvander@775
   257
	/* First question: Are we in a menu? */
dvander@775
   258
	if (!player->bInMenu)
dvander@775
   259
	{
dvander@775
   260
		return;
dvander@775
   261
	}
dvander@775
   262
dvander@775
   263
	bool cancel = false;
dvander@775
   264
	unsigned int item = 0;
dvander@775
   265
	MenuCancelReason reason = MenuCancel_Exit;
dvander@1005
   266
	MenuEndReason end_reason = MenuEnd_Selected;
dvander@775
   267
	menu_states_t &states = player->states;
dvander@775
   268
dvander@775
   269
	assert(states.mh != NULL);
dvander@775
   270
dvander@775
   271
	if (states.menu == NULL)
dvander@775
   272
	{
dvander@775
   273
		item = key_press;
dvander@785
   274
	} else if (key_press < 1 || key_press > GetMaxPageItems()) {
dvander@775
   275
		cancel = true;
dvander@775
   276
	} else {
dvander@775
   277
		ItemSelection type = states.slots[key_press].type;
dvander@775
   278
dvander@775
   279
		/* For navigational items, we're going to redisplay */
dvander@775
   280
		if (type == ItemSel_Back)
dvander@775
   281
		{
dvander@775
   282
			if (!RedoClientMenu(client, ItemOrder_Descending))
dvander@775
   283
			{
dvander@775
   284
				cancel = true;
dvander@775
   285
				reason = MenuCancel_NoDisplay;
dvander@1005
   286
				end_reason = MenuEnd_Cancelled;
dvander@775
   287
			} else {
dvander@775
   288
				return;
dvander@775
   289
			}
dvander@775
   290
		} else if (type == ItemSel_Next) {
dvander@775
   291
			if (!RedoClientMenu(client, ItemOrder_Ascending))
dvander@775
   292
			{
dvander@775
   293
				cancel = true;						/* I like Saltines. */
dvander@775
   294
				reason = MenuCancel_NoDisplay;
dvander@1005
   295
				end_reason = MenuEnd_Cancelled;
dvander@775
   296
			} else {
dvander@775
   297
				return;
dvander@775
   298
			}
dvander@775
   299
		} else if (type == ItemSel_Exit || type == ItemSel_None) {
dvander@775
   300
			cancel = true;
dvander@1005
   301
			reason = MenuCancel_Exit;
dvander@1005
   302
			end_reason = MenuEnd_Exit;
dvander@1005
   303
		} else if (type == ItemSel_ExitBack) {
dvander@1005
   304
			cancel = true;
dvander@1005
   305
			reason = MenuCancel_ExitBack;
dvander@1005
   306
			end_reason = MenuEnd_ExitBack;
dvander@775
   307
		} else {
dvander@775
   308
			item = states.slots[key_press].item;
dvander@775
   309
		}
dvander@775
   310
	}
dvander@775
   311
dvander@775
   312
	/* Save variables */
dvander@775
   313
	IMenuHandler *mh = states.mh;
dvander@775
   314
	IBaseMenu *menu = states.menu;
dvander@775
   315
dvander@775
   316
	/* Clear states */
dvander@775
   317
	player->bInMenu = false;
dvander@775
   318
	if (player->menuHoldTime)
dvander@775
   319
	{
dvander@883
   320
		RemoveClientFromWatch(client);
dvander@775
   321
	}
dvander@775
   322
dvander@775
   323
	if (cancel)
dvander@775
   324
	{
dvander@775
   325
		mh->OnMenuCancel(menu, client, reason);
dvander@775
   326
	} else {
dvander@775
   327
		mh->OnMenuSelect(menu, client, item);
dvander@775
   328
	}
dvander@775
   329
dvander@790
   330
	/* Only fire end for valid menus */
dvander@790
   331
	if (menu)
dvander@790
   332
	{
dvander@997
   333
		mh->OnMenuEnd(menu, end_reason);
dvander@790
   334
	}
dvander@775
   335
}
dvander@775
   336
dvander@787
   337
bool BaseMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
dvander@775
   338
{
dvander@970
   339
#if defined MENU_DEBUG
dvander@970
   340
	g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
dvander@970
   341
		client,
dvander@970
   342
		menu,
dvander@970
   343
		mh,
dvander@970
   344
		time);
dvander@970
   345
#endif
dvander@775
   346
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
dvander@775
   347
	if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
dvander@775
   348
	{
dvander@775
   349
		return false;
dvander@775
   350
	}
dvander@775
   351
dvander@775
   352
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   353
	if (player->bAutoIgnore)
dvander@775
   354
	{
dvander@775
   355
		return false;
dvander@775
   356
	}
dvander@775
   357
dvander@775
   358
	/* For the duration of this, we are going to totally ignore whether
dvander@775
   359
	* the player is already in a menu or not (except to cancel the old one).
dvander@775
   360
	* Instead, we are simply going to ignore any further menu displays, so
dvander@775
   361
	* this display can't be interrupted.
dvander@775
   362
	*/
dvander@775
   363
	player->bAutoIgnore = true;
dvander@775
   364
dvander@775
   365
	/* Cancel any old menus */
dvander@775
   366
	menu_states_t &states = player->states;
dvander@775
   367
	if (player->bInMenu)
dvander@775
   368
	{
dvander@1005
   369
		_CancelClientMenu(client, MenuCancel_Interrupted, true);
dvander@775
   370
	}
dvander@775
   371
dvander@775
   372
	states.firstItem = 0;
dvander@775
   373
	states.lastItem = 0;
dvander@775
   374
	states.menu = NULL;
dvander@775
   375
	states.mh = mh;
dvander@775
   376
	states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
dvander@775
   377
	player->bInMenu = true;
dvander@790
   378
	player->bInExternMenu = false;
dvander@775
   379
	player->menuStartTime = gpGlobals->curtime;
dvander@775
   380
	player->menuHoldTime = time;
dvander@775
   381
dvander@775
   382
	if (time)
dvander@775
   383
	{
dvander@775
   384
		AddClientToWatch(client);
dvander@775
   385
	}
dvander@775
   386
dvander@775
   387
	/* Draw the display */
dvander@775
   388
	SendDisplay(client, menu);
dvander@775
   389
dvander@775
   390
	/* We can be interrupted again! */
dvander@775
   391
	player->bAutoIgnore = false;
dvander@775
   392
dvander@775
   393
	return true;
dvander@775
   394
}
dvander@775
   395
dvander@775
   396
bool BaseMenuStyle::DoClientMenu(int client, CBaseMenu *menu, IMenuHandler *mh, unsigned int time)
dvander@775
   397
{
dvander@970
   398
#if defined MENU_DEBUG
dvander@970
   399
	g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
dvander@970
   400
		client,
dvander@970
   401
		menu,
dvander@970
   402
		mh,
dvander@970
   403
		time);
dvander@970
   404
#endif
dvander@775
   405
	mh->OnMenuStart(menu);
dvander@775
   406
dvander@775
   407
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
dvander@775
   408
	if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
dvander@775
   409
	{
dvander@970
   410
#if defined MENU_DEBUG
dvander@970
   411
		g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
dvander@970
   412
#endif
dvander@775
   413
		mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
dvander@997
   414
		mh->OnMenuEnd(menu, MenuEnd_Cancelled);
dvander@775
   415
		return false;
dvander@775
   416
	}
dvander@775
   417
dvander@775
   418
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   419
	if (player->bAutoIgnore)
dvander@775
   420
	{
dvander@970
   421
#if defined MENU_DEBUG
dvander@970
   422
		g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
dvander@970
   423
#endif
dvander@775
   424
		mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
dvander@997
   425
		mh->OnMenuEnd(menu, MenuEnd_Cancelled);
dvander@775
   426
		return false;
dvander@775
   427
	}
dvander@775
   428
dvander@775
   429
	/* For the duration of this, we are going to totally ignore whether
dvander@775
   430
	* the player is already in a menu or not (except to cancel the old one).
dvander@775
   431
	* Instead, we are simply going to ignore any further menu displays, so
dvander@775
   432
	* this display can't be interrupted.
dvander@775
   433
	*/
dvander@775
   434
	player->bAutoIgnore = true;
dvander@775
   435
dvander@775
   436
	/* Cancel any old menus */
dvander@775
   437
	menu_states_t &states = player->states;
dvander@775
   438
	if (player->bInMenu)
dvander@775
   439
	{
dvander@970
   440
#if defined MENU_DEBUG
dvander@970
   441
		g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
dvander@970
   442
#endif
dvander@1005
   443
		_CancelClientMenu(client, MenuCancel_Interrupted, true);
dvander@775
   444
	}
dvander@775
   445
dvander@775
   446
	states.firstItem = 0;
dvander@775
   447
	states.lastItem = 0;
dvander@775
   448
	states.menu = menu;
dvander@775
   449
	states.mh = mh;
dvander@775
   450
	states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
dvander@775
   451
dvander@787
   452
	IMenuPanel *display = g_Menus.RenderMenu(client, states, ItemOrder_Ascending);
dvander@775
   453
	if (!display)
dvander@775
   454
	{
dvander@970
   455
#if defined MENU_DEBUG
dvander@970
   456
		g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
dvander@970
   457
#endif
dvander@775
   458
		player->bAutoIgnore = false;
dvander@775
   459
		player->bInMenu = false;
dvander@775
   460
		mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
dvander@997
   461
		mh->OnMenuEnd(menu, MenuEnd_Cancelled);
dvander@775
   462
		return false;
dvander@775
   463
	}
dvander@775
   464
dvander@775
   465
	/* Finally, set our states */
dvander@775
   466
	player->bInMenu = true;
dvander@790
   467
	player->bInExternMenu = false;
dvander@775
   468
	player->menuStartTime = gpGlobals->curtime;
dvander@775
   469
	player->menuHoldTime = time;
dvander@775
   470
dvander@775
   471
	if (time)
dvander@775
   472
	{
dvander@775
   473
		AddClientToWatch(client);
dvander@775
   474
	}
dvander@775
   475
dvander@775
   476
	/* Draw the display */
dvander@775
   477
	SendDisplay(client, display);
dvander@775
   478
dvander@775
   479
	/* Free the display pointer */
dvander@776
   480
	display->DeleteThis();
dvander@775
   481
dvander@775
   482
	/* We can be interrupted again! */
dvander@775
   483
	player->bAutoIgnore = false;
dvander@775
   484
dvander@970
   485
#if defined MENU_DEBUG
dvander@970
   486
	g_Logger.LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
dvander@970
   487
#endif
dvander@970
   488
dvander@775
   489
	return true;
dvander@775
   490
}
dvander@775
   491
dvander@775
   492
bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
dvander@775
   493
{
dvander@970
   494
#if defined MENU_DEBUG
dvander@970
   495
	g_Logger.LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
dvander@970
   496
#endif
dvander@775
   497
	CBaseMenuPlayer *player = GetMenuPlayer(client);
dvander@775
   498
	menu_states_t &states = player->states;
dvander@775
   499
dvander@775
   500
	player->bAutoIgnore = true;
dvander@787
   501
	IMenuPanel *display = g_Menus.RenderMenu(client, states, order);
dvander@775
   502
	if (!display)
dvander@775
   503
	{
dvander@970
   504
#if defined MENU_DEBUG
dvander@970
   505
		g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
dvander@970
   506
#endif
dvander@775
   507
		if (player->menuHoldTime)
dvander@775
   508
		{
dvander@883
   509
			RemoveClientFromWatch(client);
dvander@775
   510
		}
dvander@775
   511
		player->bAutoIgnore = false;
dvander@775
   512
		return false;
dvander@775
   513
	}
dvander@775
   514
dvander@775
   515
	SendDisplay(client, display);
dvander@775
   516
dvander@776
   517
	display->DeleteThis();
dvander@775
   518
dvander@775
   519
	player->bAutoIgnore = false;
dvander@775
   520
dvander@970
   521
#if defined MENU_DEBUG
dvander@970
   522
	g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
dvander@970
   523
#endif
dvander@970
   524
dvander@775
   525
	return true;
dvander@775
   526
}
dvander@769
   527
dvander@790
   528
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : 
dvander@790
   529
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_ExitButton(true), 
dvander@790
   530
m_bShouldDelete(false), m_bCancelling(false), m_pOwner(pOwner ? pOwner : g_pCoreIdent), 
dvander@877
   531
m_bDeleting(false), m_bWillFreeHandle(false), m_hHandle(BAD_HANDLE), m_pHandler(pHandler),
dvander@1005
   532
m_pVoteHandler(NULL), m_ExitBackButton(false)
dvander@769
   533
{
dvander@769
   534
}
dvander@769
   535
dvander@769
   536
CBaseMenu::~CBaseMenu()
dvander@769
   537
{
dvander@877
   538
	g_Menus.ReleaseVoteWrapper(m_pVoteHandler);
dvander@769
   539
}
dvander@769
   540
dvander@790
   541
Handle_t CBaseMenu::GetHandle()
dvander@790
   542
{
dvander@790
   543
	if (!m_hHandle)
dvander@790
   544
	{
dvander@790
   545
		m_hHandle = g_Menus.CreateMenuHandle(this, m_pOwner);
dvander@790
   546
	}
dvander@790
   547
dvander@790
   548
	return m_hHandle;
dvander@790
   549
}
dvander@790
   550
dvander@769
   551
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
dvander@769
   552
{
dvander@778
   553
	if (m_Pagination == (unsigned)MENU_NO_PAGINATION
dvander@769
   554
		&& m_items.size() >= m_pStyle->GetMaxPageItems())
dvander@769
   555
	{
dvander@769
   556
		return false;
dvander@769
   557
	}
dvander@769
   558
dvander@769
   559
	CItem item;
dvander@769
   560
dvander@769
   561
	item.infoString = m_Strings.AddString(info);
dvander@769
   562
	if (draw.display)
dvander@769
   563
	{
dvander@769
   564
		item.displayString = m_Strings.AddString(draw.display);
dvander@769
   565
	}
dvander@769
   566
	item.style = draw.style;
dvander@769
   567
dvander@769
   568
dvander@769
   569
	m_items.push_back(item);
dvander@769
   570
dvander@769
   571
	return true;
dvander@769
   572
}
dvander@769
   573
dvander@769
   574
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
dvander@769
   575
{
dvander@778
   576
	if (m_Pagination == (unsigned)MENU_NO_PAGINATION
dvander@769
   577
		&& m_items.size() >= m_pStyle->GetMaxPageItems())
dvander@769
   578
	{
dvander@769
   579
		return false;
dvander@769
   580
	}
dvander@769
   581
dvander@769
   582
	if (position >= m_items.size())
dvander@769
   583
	{
dvander@769
   584
		return false;
dvander@769
   585
	}
dvander@769
   586
dvander@769
   587
	CItem item;
dvander@769
   588
	item.infoString = m_Strings.AddString(info);
dvander@769
   589
	if (draw.display)
dvander@769
   590
	{
dvander@769
   591
		item.displayString = m_Strings.AddString(draw.display);
dvander@769
   592
	}
dvander@769
   593
	item.style = draw.style;
dvander@769
   594
dvander@769
   595
	CVector<CItem>::iterator iter = m_items.iterAt(position);
dvander@769
   596
	m_items.insert(iter, item);
dvander@769
   597
dvander@769
   598
	return true;
dvander@769
   599
}
dvander@769
   600
dvander@769
   601
bool CBaseMenu::RemoveItem(unsigned int position)
dvander@769
   602
{
dvander@769
   603
	if (position >= m_items.size())
dvander@769
   604
	{
dvander@769
   605
		return false;
dvander@769
   606
	}
dvander@769
   607
dvander@769
   608
	m_items.erase(m_items.iterAt(position));
dvander@769
   609
dvander@769
   610
	if (m_items.size() == 0)
dvander@769
   611
	{
dvander@769
   612
		m_Strings.Reset();
dvander@769
   613
	}
dvander@769
   614
dvander@769
   615
	return true;
dvander@769
   616
}
dvander@769
   617
dvander@769
   618
void CBaseMenu::RemoveAllItems()
dvander@769
   619
{
dvander@769
   620
	m_items.clear();
dvander@769
   621
	m_Strings.Reset();
dvander@769
   622
}
dvander@769
   623
dvander@769
   624
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
dvander@769
   625
{
dvander@769
   626
	if (position >= m_items.size())
dvander@769
   627
	{
dvander@769
   628
		return NULL;
dvander@769
   629
	}
dvander@769
   630
dvander@769
   631
	if (draw)
dvander@769
   632
	{
dvander@769
   633
		draw->display = m_Strings.GetString(m_items[position].displayString);
dvander@769
   634
		draw->style = m_items[position].style;
dvander@769
   635
	}
dvander@769
   636
dvander@769
   637
	return m_Strings.GetString(m_items[position].infoString);
dvander@769
   638
}
dvander@769
   639
dvander@769
   640
unsigned int CBaseMenu::GetItemCount()
dvander@769
   641
{
dvander@769
   642
	return m_items.size();
dvander@769
   643
}
dvander@769
   644
dvander@769
   645
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
dvander@769
   646
{
dvander@820
   647
	if (itemsPerPage > 7 || itemsPerPage == 1)
dvander@769
   648
	{
dvander@769
   649
		return false;
dvander@769
   650
	}
dvander@769
   651
dvander@769
   652
	m_Pagination = itemsPerPage;
dvander@769
   653
dvander@769
   654
	return true;
dvander@769
   655
}
dvander@769
   656
dvander@769
   657
unsigned int CBaseMenu::GetPagination()
dvander@769
   658
{
dvander@769
   659
	return m_Pagination;
dvander@769
   660
}
dvander@769
   661
dvander@769
   662
IMenuStyle *CBaseMenu::GetDrawStyle()
dvander@769
   663
{
dvander@769
   664
	return m_pStyle;
dvander@769
   665
}
dvander@769
   666
dvander@769
   667
void CBaseMenu::SetDefaultTitle(const char *message)
dvander@769
   668
{
dvander@769
   669
	m_Title.assign(message);
dvander@769
   670
}
dvander@769
   671
dvander@769
   672
const char *CBaseMenu::GetDefaultTitle()
dvander@769
   673
{
dvander@769
   674
	return m_Title.c_str();
dvander@769
   675
}
dvander@769
   676
dvander@769
   677
bool CBaseMenu::GetExitButton()
dvander@769
   678
{
dvander@769
   679
	return m_ExitButton;
dvander@769
   680
}
dvander@769
   681
dvander@769
   682
bool CBaseMenu::SetExitButton(bool set)
dvander@769
   683
{
dvander@769
   684
	m_ExitButton = set;
dvander@769
   685
	return true;
dvander@769
   686
}
dvander@775
   687
dvander@775
   688
void CBaseMenu::Cancel()
dvander@775
   689
{
dvander@775
   690
	if (m_bCancelling)
dvander@775
   691
	{
dvander@775
   692
		return;
dvander@775
   693
	}
dvander@775
   694
dvander@970
   695
#if defined MENU_DEBUG
dvander@970
   696
	g_Logger.LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_pVote %p) (inVote %d) (m_bShouldDelete %d)",
dvander@970
   697
		this,
dvander@970
   698
		m_pVoteHandler,
dvander@970
   699
		m_pVoteHandler ? m_pVoteHandler->IsVoteInProgress() : false,
dvander@970
   700
		m_bShouldDelete);
dvander@970
   701
#endif
dvander@970
   702
dvander@959
   703
	if (m_pVoteHandler && m_pVoteHandler->IsVoteInProgress())
dvander@959
   704
	{
dvander@959
   705
		m_pVoteHandler->CancelVoting();
dvander@959
   706
	}
dvander@959
   707
dvander@775
   708
	m_bCancelling = true;
dvander@775
   709
	Cancel_Finally();
dvander@775
   710
	m_bCancelling = false;
dvander@775
   711
dvander@775
   712
	if (m_bShouldDelete)
dvander@775
   713
	{
dvander@790
   714
		InternalDelete();
dvander@775
   715
	}
dvander@775
   716
}
dvander@775
   717
dvander@790
   718
void CBaseMenu::Destroy(bool releaseHandle)
dvander@775
   719
{
dvander@790
   720
	/* Check if we shouldn't be here */
dvander@790
   721
	if (m_bDeleting)
dvander@790
   722
	{
dvander@790
   723
		return;
dvander@790
   724
	}
dvander@790
   725
dvander@970
   726
#if defined MENU_DEBUG
dvander@970
   727
	g_Logger.LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
dvander@970
   728
		this,
dvander@970
   729
		releaseHandle,
dvander@970
   730
		m_bCancelling,
dvander@970
   731
		m_bShouldDelete);
dvander@970
   732
#endif
dvander@970
   733
dvander@790
   734
	/* Save the destruction hint about our handle */
dvander@790
   735
	m_bWillFreeHandle = releaseHandle;
dvander@790
   736
dvander@790
   737
	/* Now actually do stuff */
dvander@775
   738
	if (!m_bCancelling || m_bShouldDelete)
dvander@775
   739
	{
dvander@775
   740
		Cancel();
dvander@790
   741
		InternalDelete();
dvander@775
   742
	} else {
dvander@775
   743
		m_bShouldDelete = true;
dvander@775
   744
	}
dvander@775
   745
}
dvander@775
   746
dvander@790
   747
void CBaseMenu::InternalDelete()
dvander@790
   748
{
dvander@790
   749
	if (m_bWillFreeHandle && m_hHandle != BAD_HANDLE)
dvander@790
   750
	{
dvander@790
   751
		Handle_t hndl = m_hHandle;
dvander@790
   752
		HandleSecurity sec;
dvander@790
   753
dvander@790
   754
		sec.pOwner = m_pOwner;
dvander@790
   755
		sec.pIdentity = g_pCoreIdent;
dvander@790
   756
dvander@790
   757
		m_hHandle = BAD_HANDLE;
dvander@790
   758
		m_bDeleting = true;
dvander@790
   759
		g_HandleSys.FreeHandle(hndl, &sec);
dvander@790
   760
	}
dvander@790
   761
dvander@790
   762
	m_pHandler->OnMenuDestroy(this);
dvander@790
   763
dvander@790
   764
	delete this;
dvander@790
   765
}
dvander@790
   766
dvander@877
   767
bool CBaseMenu::BroadcastVote(int clients[], 
dvander@877
   768
							  unsigned int numClients, 
dvander@877
   769
							  unsigned int maxTime,
dvander@877
   770
							  unsigned int flags)
dvander@877
   771
{
dvander@970
   772
#if defined MENU_DEBUG
dvander@970
   773
	g_Logger.LogMessage("[SM_MENU] CBaseMenu::BroadcastVote(%p) (maxTime %d) (numClients %d) (m_pVote %p) (inVote %d)",
dvander@970
   774
		this,
dvander@970
   775
		maxTime,
dvander@970
   776
		numClients,
dvander@970
   777
		m_pVoteHandler,
dvander@970
   778
		m_pVoteHandler ? m_pVoteHandler->IsVoteInProgress() : false);
dvander@970
   779
#endif
dvander@877
   780
	if (!m_pVoteHandler)
dvander@877
   781
	{
dvander@877
   782
		m_pVoteHandler = g_Menus.CreateVoteWrapper(m_pHandler);
dvander@877
   783
	} else if (m_pVoteHandler->IsVoteInProgress()) {
dvander@877
   784
		return false;
dvander@877
   785
	}
dvander@877
   786
dvander@877
   787
	m_pVoteHandler->InitializeVoting(this);
dvander@877
   788
dvander@877
   789
	for (unsigned int i=0; i<numClients; i++)
dvander@877
   790
	{
dvander@877
   791
		VoteDisplay(clients[i], maxTime);
dvander@877
   792
	}
dvander@877
   793
dvander@877
   794
	m_pVoteHandler->StartVoting();
dvander@879
   795
dvander@879
   796
	return true;
dvander@877
   797
}
dvander@879
   798
dvander@884
   799
bool CBaseMenu::IsVoteInProgress()
dvander@884
   800
{
dvander@884
   801
	return (m_pVoteHandler && m_pVoteHandler->IsVoteInProgress());
dvander@884
   802
}
dvander@1005
   803
dvander@1005
   804
bool CBaseMenu::GetExitBackButton()
dvander@1005
   805
{
dvander@1005
   806
	return m_ExitBackButton;
dvander@1005
   807
}
dvander@1005
   808
dvander@1005
   809
void CBaseMenu::SetExitBackButton(bool set)
dvander@1005
   810
{
dvander@1005
   811
	m_ExitBackButton = set;
dvander@1005
   812
}