core/MenuStyle_Radio.cpp
author David Anderson <dvander@alliedmods.net>
Mon May 21 01:11:37 2007 +0000 (2007-05-21)
changeset 819 a2f2353049b9
parent 790 9b1474d03470
child 820 958de63aa9f5
permissions -rw-r--r--
added key selection setting
fixed amb309
     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 
    20 extern const char *g_RadioNumTable[];
    21 CRadioStyle g_RadioMenuStyle;
    22 int g_ShowMenuId = -1;
    23 bool g_bRadioInit = false;
    24 
    25 CRadioStyle::CRadioStyle() : m_players(new CBaseMenuPlayer[256+1])
    26 {
    27 }
    28 
    29 void CRadioStyle::OnSourceModLevelChange(const char *mapName)
    30 {
    31 	if (g_bRadioInit)
    32 	{
    33 		return;
    34 	}
    35 
    36 	g_bRadioInit = true;
    37 	const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
    38 	if (!msg || msg[0] == '\0')
    39 	{
    40 		return;
    41 	}
    42 
    43 	g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
    44 
    45 	if (!IsSupported())
    46 	{
    47 		return;
    48 	}
    49 
    50 	g_Menus.AddStyle(this);
    51 	g_Menus.SetDefaultStyle(this);
    52 
    53 	g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
    54 }
    55 
    56 void CRadioStyle::OnSourceModShutdown()
    57 {
    58 	g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
    59 
    60 	while (!m_FreeDisplays.empty())
    61 	{
    62 		delete m_FreeDisplays.front();
    63 		m_FreeDisplays.pop();
    64 	}
    65 }
    66 
    67 bool CRadioStyle::IsSupported()
    68 {
    69 	return (g_ShowMenuId != -1);
    70 }
    71 
    72 bool CRadioStyle::OnClientCommand(int client)
    73 {
    74 	const char *cmd = engine->Cmd_Argv(0);
    75 
    76 	if (strcmp(cmd, "menuselect") == 0)
    77 	{
    78 		if (!m_players[client].bInMenu)
    79 		{
    80 			return false;
    81 		}
    82 
    83 		int arg = atoi(engine->Cmd_Argv(1));
    84 		ClientPressedKey(client, arg);
    85 		return true;
    86 	}
    87 
    88 	return false;
    89 }
    90 
    91 static unsigned int g_last_holdtime = 0;
    92 static unsigned int g_last_client_count = 0;
    93 static int g_last_clients[256];
    94 
    95 void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
    96 {
    97 	int count = pFilter->GetRecipientCount();
    98 	bf_read br(bf->GetBasePointer(), 2);
    99 
   100 	br.ReadWord();
   101 	int c = br.ReadChar();
   102 
   103 	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
   104 
   105 	for (int i=0; i<count; i++)
   106 	{
   107 		g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
   108 	}
   109 }
   110 
   111 void CRadioStyle::OnUserMessageSent(int msg_id)
   112 {
   113 	for (unsigned int i=0; i<g_last_client_count; i++)
   114 	{
   115 		int client = g_last_clients[i];
   116 		if (m_players[client].bInMenu)
   117 		{
   118 			_CancelClientMenu(client, true);
   119 		}
   120 		m_players[client].bInExternMenu = true;
   121 		m_players[client].menuHoldTime = g_last_holdtime;
   122 	}
   123 	g_last_client_count = 0;
   124 }
   125 
   126 void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
   127 {
   128 	CRadioDisplay *rDisplay = (CRadioDisplay *)display;
   129 	rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
   130 }
   131 
   132 IMenuPanel *CRadioStyle::CreatePanel()
   133 {
   134 	return g_RadioMenuStyle.MakeRadioDisplay();
   135 }
   136 
   137 IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   138 {
   139 	return new CRadioMenu(pHandler, pOwner);
   140 }
   141 
   142 unsigned int CRadioStyle::GetMaxPageItems()
   143 {
   144 	return 10;
   145 }
   146 
   147 const char *CRadioStyle::GetStyleName()
   148 {
   149 	return "radio";
   150 }
   151 
   152 CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
   153 {
   154 	return &m_players[client];
   155 }
   156 
   157 CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
   158 {
   159 	CRadioDisplay *display;
   160 	if (m_FreeDisplays.empty())
   161 	{
   162 		display = new CRadioDisplay();
   163 	} else {
   164 		display = m_FreeDisplays.front();
   165 		m_FreeDisplays.pop();
   166 		display->Reset();
   167 	}
   168 	return display;
   169 }
   170 
   171 void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
   172 {
   173 	m_FreeDisplays.push(display);
   174 }
   175 
   176 CRadioDisplay::CRadioDisplay()
   177 {
   178 	Reset();
   179 }
   180 
   181 CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
   182 {
   183 	Reset();
   184 }
   185 
   186 bool CRadioDisplay::DrawRawLine(const char *rawline)
   187 {
   188 	m_BufferText.append(rawline);
   189 	m_BufferText.append("\n");
   190 	return true;
   191 }
   192 
   193 void CRadioDisplay::Reset()
   194 {
   195 	m_BufferText.assign("");
   196 	m_Title.assign("");
   197 	m_NextPos = 1;
   198 	keys = 0;
   199 }
   200 
   201 bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   202 {
   203 	return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
   204 }
   205 
   206 bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   207 {
   208 	return false;
   209 }
   210 
   211 IMenuStyle *CRadioDisplay::GetParentStyle()
   212 {
   213 	return &g_RadioMenuStyle;
   214 }
   215 
   216 void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   217 {
   218 	if (m_Title.size() != 0 && onlyIfEmpty)
   219 	{
   220 		return;
   221 	}
   222 	m_Title.assign(text);
   223 }
   224 
   225 unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
   226 {
   227 	if (m_NextPos > 10 || !CanDrawItem(item.style))
   228 	{
   229 		return 0;
   230 	}
   231 
   232 	if (item.style & ITEMDRAW_RAWLINE)
   233 	{
   234 		if (item.style & ITEMDRAW_SPACER)
   235 		{
   236 			m_BufferText.append(" \n");
   237 		} else {
   238 			m_BufferText.append(item.display);
   239 			m_BufferText.append("\n");
   240 		}
   241 		return 0;
   242 	} else if (item.style & ITEMDRAW_SPACER) {
   243 		m_BufferText.append(" \n");
   244 		return m_NextPos++;
   245 	} else if (item.style & ITEMDRAW_NOTEXT) {
   246 		return m_NextPos++;
   247 	}
   248 
   249 	if (item.style & ITEMDRAW_DISABLED)
   250 	{
   251 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   252 		m_BufferText.append(item.display);
   253 		m_BufferText.append("\n");
   254 	} else {
   255 		m_BufferText.append("->");
   256 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   257 		m_BufferText.append(item.display);
   258 		m_BufferText.append("\n");
   259 		keys |= (1<<(m_NextPos-1));
   260 	}
   261 
   262 	return m_NextPos++;
   263 }
   264 
   265 bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
   266 {
   267 	if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
   268 	{
   269 		return false;
   270 	}
   271 
   272 	if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
   273 	{
   274 		return false;
   275 	}
   276 
   277 	return true;
   278 }
   279 
   280 void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
   281 {
   282 	char buffer[4096];
   283 	size_t len;
   284 
   285 	len = UTIL_Format(buffer, sizeof(buffer), "%s\n%s", m_Title.c_str(), m_BufferText.c_str());
   286 
   287 	cell_t players[1] = {client};
   288 
   289 	int _sel_keys = (keys == 0) ? (1<<9) : keys;
   290 
   291 	char *ptr = buffer;
   292 	char save = 0;
   293 	while (true)
   294 	{
   295 		if (len > 240)
   296 		{
   297 			save = ptr[240];
   298 			ptr[240] = '\0';
   299 		}
   300 		bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, 0);
   301 		buffer->WriteWord(_sel_keys);
   302 		buffer->WriteChar(time ? time : -1);
   303 		buffer->WriteByte( (len > 240) ? 1 : 0 );
   304 		buffer->WriteString(ptr);
   305 		g_UserMsgs.EndMessage();
   306 		if (len > 240)
   307 		{
   308 			ptr[240] = save;
   309 			ptr = &ptr[240];
   310 			len -= 240;
   311 		} else {
   312 			break;
   313 		}
   314 	}
   315 }
   316 
   317 void CRadioDisplay::DeleteThis()
   318 {
   319 	delete this;
   320 }
   321 
   322 bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
   323 {
   324 	keys = (signed)keymap;
   325 }
   326 
   327 CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   328 CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
   329 {
   330 }
   331 
   332 bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
   333 {
   334 	return false;
   335 }
   336 
   337 IMenuPanel *CRadioMenu::CreatePanel()
   338 {
   339 	return g_RadioMenuStyle.MakeRadioDisplay(this);
   340 }
   341 
   342 bool CRadioMenu::Display(int client, unsigned int time)
   343 {
   344 	return g_RadioMenuStyle.DoClientMenu(client, this, m_pHandler, time);
   345 }
   346 
   347 void CRadioMenu::Cancel_Finally()
   348 {
   349 	g_RadioMenuStyle.CancelMenu(this);
   350 }
   351 
   352 const char *g_RadioNumTable[11] = 
   353 {
   354 	"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
   355 };