core/MenuStyle_Radio.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 06 06:27:47 2007 +0000 (2007-06-06)
changeset 884 a5f3239cef1a
parent 877 898c39fbfde9
child 970 b47becc0083d
permissions -rw-r--r--
- vote menus now get cancelled properly (and get a new callback with it)
- added api for seeing if a menu is in a VoteDisplay
- fixed another item count bug
- removed some cruft from the vote handler header
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "MenuStyle_Radio.h"
    16 #include "sm_stringutil.h"
    17 #include "UserMessages.h"
    18 #include "GameConfigs.h"
    19 #include "PlayerManager.h"
    20 
    21 extern const char *g_RadioNumTable[];
    22 CRadioStyle g_RadioMenuStyle;
    23 int g_ShowMenuId = -1;
    24 bool g_bRadioInit = false;
    25 
    26 CRadioStyle::CRadioStyle() : m_players(new CBaseMenuPlayer[256+1])
    27 {
    28 }
    29 
    30 void CRadioStyle::OnSourceModAllInitialized()
    31 {
    32 	g_Players.AddClientListener(this);
    33 }
    34 
    35 void CRadioStyle::OnSourceModLevelChange(const char *mapName)
    36 {
    37 	if (g_bRadioInit)
    38 	{
    39 		return;
    40 	}
    41 
    42 	g_bRadioInit = true;
    43 	const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
    44 	if (!msg || msg[0] == '\0')
    45 	{
    46 		return;
    47 	}
    48 
    49 	g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
    50 
    51 	if (!IsSupported())
    52 	{
    53 		return;
    54 	}
    55 
    56 	g_Menus.AddStyle(this);
    57 	g_Menus.SetDefaultStyle(this);
    58 
    59 	g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
    60 }
    61 
    62 void CRadioStyle::OnSourceModShutdown()
    63 {
    64 	g_Players.RemoveClientListener(this);
    65 	g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
    66 
    67 	while (!m_FreeDisplays.empty())
    68 	{
    69 		delete m_FreeDisplays.front();
    70 		m_FreeDisplays.pop();
    71 	}
    72 }
    73 
    74 bool CRadioStyle::IsSupported()
    75 {
    76 	return (g_ShowMenuId != -1);
    77 }
    78 
    79 bool CRadioStyle::OnClientCommand(int client)
    80 {
    81 	const char *cmd = engine->Cmd_Argv(0);
    82 
    83 	if (strcmp(cmd, "menuselect") == 0)
    84 	{
    85 		if (!m_players[client].bInMenu)
    86 		{
    87 			return false;
    88 		}
    89 
    90 		int arg = atoi(engine->Cmd_Argv(1));
    91 		ClientPressedKey(client, arg);
    92 		return true;
    93 	}
    94 
    95 	return false;
    96 }
    97 
    98 static unsigned int g_last_holdtime = 0;
    99 static unsigned int g_last_client_count = 0;
   100 static int g_last_clients[256];
   101 
   102 void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   103 {
   104 	int count = pFilter->GetRecipientCount();
   105 	bf_read br(bf->GetBasePointer(), 2);
   106 
   107 	br.ReadWord();
   108 	int c = br.ReadChar();
   109 
   110 	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
   111 
   112 	for (int i=0; i<count; i++)
   113 	{
   114 		g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
   115 	}
   116 }
   117 
   118 void CRadioStyle::OnUserMessageSent(int msg_id)
   119 {
   120 	for (unsigned int i=0; i<g_last_client_count; i++)
   121 	{
   122 		int client = g_last_clients[i];
   123 		if (m_players[client].bInMenu)
   124 		{
   125 			_CancelClientMenu(client, true);
   126 		}
   127 		m_players[client].bInExternMenu = true;
   128 		m_players[client].menuHoldTime = g_last_holdtime;
   129 	}
   130 	g_last_client_count = 0;
   131 }
   132 
   133 void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
   134 {
   135 	CRadioDisplay *rDisplay = (CRadioDisplay *)display;
   136 	rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
   137 }
   138 
   139 IMenuPanel *CRadioStyle::CreatePanel()
   140 {
   141 	return g_RadioMenuStyle.MakeRadioDisplay();
   142 }
   143 
   144 IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   145 {
   146 	return new CRadioMenu(pHandler, pOwner);
   147 }
   148 
   149 unsigned int CRadioStyle::GetMaxPageItems()
   150 {
   151 	return 10;
   152 }
   153 
   154 const char *CRadioStyle::GetStyleName()
   155 {
   156 	return "radio";
   157 }
   158 
   159 CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
   160 {
   161 	return &m_players[client];
   162 }
   163 
   164 CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
   165 {
   166 	CRadioDisplay *display;
   167 	if (m_FreeDisplays.empty())
   168 	{
   169 		display = new CRadioDisplay();
   170 	} else {
   171 		display = m_FreeDisplays.front();
   172 		m_FreeDisplays.pop();
   173 		display->Reset();
   174 	}
   175 	return display;
   176 }
   177 
   178 void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
   179 {
   180 	m_FreeDisplays.push(display);
   181 }
   182 
   183 CRadioDisplay::CRadioDisplay()
   184 {
   185 	Reset();
   186 }
   187 
   188 CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
   189 {
   190 	Reset();
   191 }
   192 
   193 bool CRadioDisplay::DrawRawLine(const char *rawline)
   194 {
   195 	m_BufferText.append(rawline);
   196 	m_BufferText.append("\n");
   197 	return true;
   198 }
   199 
   200 void CRadioDisplay::Reset()
   201 {
   202 	m_BufferText.assign("");
   203 	m_Title.assign("");
   204 	m_NextPos = 1;
   205 	keys = 0;
   206 }
   207 
   208 unsigned int CRadioDisplay::GetCurrentKey()
   209 {
   210 	return m_NextPos;
   211 }
   212 
   213 bool CRadioDisplay::SetCurrentKey(unsigned int key)
   214 {
   215 	if (key < m_NextPos || m_NextPos > 10)
   216 	{
   217 		return false;
   218 	}
   219 
   220 	m_NextPos = key;
   221 
   222 	return true;
   223 }
   224 
   225 bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   226 {
   227 	return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
   228 }
   229 
   230 bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   231 {
   232 	return false;
   233 }
   234 
   235 IMenuStyle *CRadioDisplay::GetParentStyle()
   236 {
   237 	return &g_RadioMenuStyle;
   238 }
   239 
   240 void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   241 {
   242 	if (m_Title.size() != 0 && onlyIfEmpty)
   243 	{
   244 		return;
   245 	}
   246 	m_Title.assign(text);
   247 }
   248 
   249 unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
   250 {
   251 	if (m_NextPos > 10 || !CanDrawItem(item.style))
   252 	{
   253 		return 0;
   254 	}
   255 
   256 	if (item.style & ITEMDRAW_RAWLINE)
   257 	{
   258 		if (item.style & ITEMDRAW_SPACER)
   259 		{
   260 			m_BufferText.append(" \n");
   261 		} else {
   262 			m_BufferText.append(item.display);
   263 			m_BufferText.append("\n");
   264 		}
   265 		return 0;
   266 	} else if (item.style & ITEMDRAW_SPACER) {
   267 		m_BufferText.append(" \n");
   268 		return m_NextPos++;
   269 	} else if (item.style & ITEMDRAW_NOTEXT) {
   270 		return m_NextPos++;
   271 	}
   272 
   273 	if (item.style & ITEMDRAW_DISABLED)
   274 	{
   275 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   276 		m_BufferText.append(item.display);
   277 		m_BufferText.append("\n");
   278 	} else {
   279 		m_BufferText.append("->");
   280 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   281 		m_BufferText.append(item.display);
   282 		m_BufferText.append("\n");
   283 		keys |= (1<<(m_NextPos-1));
   284 	}
   285 
   286 	return m_NextPos++;
   287 }
   288 
   289 bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
   290 {
   291 	if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
   292 	{
   293 		return false;
   294 	}
   295 
   296 	if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
   297 	{
   298 		return false;
   299 	}
   300 
   301 	return true;
   302 }
   303 
   304 void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
   305 {
   306 	char buffer[4096];
   307 	size_t len;
   308 
   309 	len = UTIL_Format(buffer, sizeof(buffer), "%s\n%s", m_Title.c_str(), m_BufferText.c_str());
   310 
   311 	cell_t players[1] = {client};
   312 
   313 	int _sel_keys = (keys == 0) ? (1<<9) : keys;
   314 
   315 	char *ptr = buffer;
   316 	char save = 0;
   317 	while (true)
   318 	{
   319 		if (len > 240)
   320 		{
   321 			save = ptr[240];
   322 			ptr[240] = '\0';
   323 		}
   324 		bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, 0);
   325 		buffer->WriteWord(_sel_keys);
   326 		buffer->WriteChar(time ? time : -1);
   327 		buffer->WriteByte( (len > 240) ? 1 : 0 );
   328 		buffer->WriteString(ptr);
   329 		g_UserMsgs.EndMessage();
   330 		if (len > 240)
   331 		{
   332 			ptr[240] = save;
   333 			ptr = &ptr[240];
   334 			len -= 240;
   335 		} else {
   336 			break;
   337 		}
   338 	}
   339 }
   340 
   341 void CRadioDisplay::DeleteThis()
   342 {
   343 	delete this;
   344 }
   345 
   346 bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
   347 {
   348 	keys = (signed)keymap;
   349 	return true;
   350 }
   351 
   352 CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   353 CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
   354 {
   355 }
   356 
   357 bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
   358 {
   359 	return false;
   360 }
   361 
   362 IMenuPanel *CRadioMenu::CreatePanel()
   363 {
   364 	return g_RadioMenuStyle.MakeRadioDisplay(this);
   365 }
   366 
   367 bool CRadioMenu::Display(int client, unsigned int time)
   368 {
   369 	if (m_bCancelling)
   370 	{
   371 		return false;
   372 	}
   373 
   374 	return g_RadioMenuStyle.DoClientMenu(client, this, m_pHandler, time);
   375 }
   376 
   377 void CRadioMenu::VoteDisplay(int client, unsigned int maxTime)
   378 {
   379 	if (m_bCancelling)
   380 	{
   381 		return;
   382 	}
   383 
   384 	g_RadioMenuStyle.DoClientMenu(client, this, m_pVoteHandler, maxTime);
   385 }
   386 
   387 void CRadioMenu::Cancel_Finally()
   388 {
   389 	g_RadioMenuStyle.CancelMenu(this);
   390 }
   391 
   392 const char *g_RadioNumTable[11] = 
   393 {
   394 	"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
   395 };