diff -r 7602d7fb60d9 -r 026da5437111 core/MenuStyle_Base.cpp
--- a/core/MenuStyle_Base.cpp Fri Jul 11 06:51:21 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,837 +0,0 @@
-/**
- * vim: set ts=4 :
- * =============================================================================
- * SourceMod
- * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- *
- * As a special exception, AlliedModders LLC gives you permission to link the
- * code of this program (as well as its derivative works) to "Half-Life 2," the
- * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
- * by the Valve Corporation. You must obey the GNU General Public License in
- * all respects for all other code used. Additionally, AlliedModders LLC grants
- * this exception to all derivative works. AlliedModders LLC defines further
- * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
- * or .
- *
- * Version: $Id$
- */
-
-#include
-#include "sm_stringutil.h"
-#include "MenuStyle_Base.h"
-#include "PlayerManager.h"
-#include "MenuManager.h"
-#include "HandleSys.h"
-#include "CellRecipientFilter.h"
-#if defined MENU_DEBUG
-#include "Logger.h"
-#endif
-
-BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
-{
-}
-
-Handle_t BaseMenuStyle::GetHandle()
-{
- /* Don't create the handle until we need it */
- if (m_hHandle == BAD_HANDLE)
- {
- m_hHandle = g_Menus.CreateStyleHandle(this);
- }
-
- return m_hHandle;
-}
-
-void BaseMenuStyle::AddClientToWatch(int client)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
-#endif
- m_WatchList.push_back(client);
-}
-
-void BaseMenuStyle::RemoveClientFromWatch(int client)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
-#endif
- m_WatchList.remove(client);
-}
-
-void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore/* =false */)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
-#endif
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- menu_states_t &states = player->states;
-
- bool bOldIgnore = player->bAutoIgnore;
- if (bAutoIgnore)
- {
- player->bAutoIgnore = true;
- }
-
- /* Save states */
- IMenuHandler *mh = states.mh;
- IBaseMenu *menu = states.menu;
-
- /* Clear menu */
- player->bInMenu = false;
- if (player->menuHoldTime)
- {
- RemoveClientFromWatch(client);
- }
-
- /* Fire callbacks */
- mh->OnMenuCancel(menu, client, reason);
-
- /* Only fire end if there's a valid menu */
- if (menu)
- {
- mh->OnMenuEnd(menu, MenuEnd_Cancelled);
- }
-
- if (bAutoIgnore)
- {
- player->bAutoIgnore = bOldIgnore;
- }
-}
-
-void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
-#endif
- int maxClients = g_Players.GetMaxClients();
- for (int i=1; i<=maxClients; i++)
- {
- CBaseMenuPlayer *player = GetMenuPlayer(i);
- if (player->bInMenu)
- {
- menu_states_t &states = player->states;
- if (states.menu == menu)
- {
- _CancelClientMenu(i, MenuCancel_Interrupted);
- }
- }
- }
-}
-
-bool BaseMenuStyle::CancelClientMenu(int client, bool autoIgnore)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
-#endif
- if (client < 1 || client > g_Players.MaxClients())
- {
- return false;
- }
-
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- if (!player->bInMenu)
- {
- return false;
- }
-
- _CancelClientMenu(client, MenuCancel_Interrupted, autoIgnore);
-
- return true;
-}
-
-MenuSource BaseMenuStyle::GetClientMenu(int client, void **object)
-{
- if (client < 1 || client > g_Players.GetMaxClients())
- {
- return MenuSource_None;
- }
-
- CBaseMenuPlayer *player = GetMenuPlayer(client);
-
- if (player->bInMenu)
- {
- IBaseMenu *menu;
- if ((menu=player->states.menu) != NULL)
- {
- if (object)
- {
- *object = menu;
- }
- return MenuSource_BaseMenu;
- }
-
- return MenuSource_Display;
- } else if (player->bInExternMenu) {
- if (player->menuHoldTime != 0
- && (gpGlobals->curtime > player->menuStartTime + player->menuHoldTime))
- {
- player->bInExternMenu = false;
- return MenuSource_None;
- }
- return MenuSource_External;
- }
-
- return MenuSource_None;
-}
-
-void BaseMenuStyle::OnClientDisconnected(int client)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
-#endif
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- if (!player->bInMenu)
- {
- return;
- }
-
- _CancelClientMenu(client, MenuCancel_Disconnected, true);
-
- player->bInMenu = false;
- player->bInExternMenu = false;
-}
-
-static int do_lookup[256];
-void BaseMenuStyle::ProcessWatchList()
-{
- if (!m_WatchList.size())
- {
- return;
- }
-
-#if defined MENU_DEBUG
- g_Logger.LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)",
- m_WatchList.m_Size,
- m_WatchList.m_FirstLink,
- m_WatchList.m_FreeNodes,
- m_WatchList.m_LastLink,
- m_WatchList.m_MaxSize,
- m_WatchList.m_Nodes);
-#endif
-
- unsigned int total = 0;
- for (FastLink::iterator iter=m_WatchList.begin(); iter!=m_WatchList.end(); ++iter)
- {
- do_lookup[total++] = (*iter);
- }
-
-#if defined MENU_DEBUG
- if (total)
- {
- g_Logger.LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
- }
-#endif
-
- int client;
- CBaseMenuPlayer *player;
- float curTime = gpGlobals->curtime;
- for (unsigned int i=0; ibInMenu,
- player->menuHoldTime,
- curTime,
- player->menuStartTime);
-#endif
- if (!player->bInMenu || !player->menuHoldTime)
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
-#endif
- m_WatchList.remove(client);
- continue;
- }
- if (curTime > player->menuStartTime + player->menuHoldTime)
- {
- _CancelClientMenu(client, MenuCancel_Timeout, false);
- }
- }
-}
-
-void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
-#endif
- CBaseMenuPlayer *player = GetMenuPlayer(client);
-
- /* First question: Are we in a menu? */
- if (!player->bInMenu)
- {
- return;
- }
-
- bool cancel = false;
- unsigned int item = 0;
- MenuCancelReason reason = MenuCancel_Exit;
- MenuEndReason end_reason = MenuEnd_Selected;
- menu_states_t &states = player->states;
-
- /* Save variables */
- IMenuHandler *mh = states.mh;
- IBaseMenu *menu = states.menu;
-
- unsigned int item_on_page = states.item_on_page;
-
- assert(mh != NULL);
-
- if (menu == NULL)
- {
- item = key_press;
- } else if (key_press < 1 || key_press > GetMaxPageItems()) {
- cancel = true;
- } else {
- ItemSelection type = states.slots[key_press].type;
-
- /* Check if we should play a sound about the type */
- if (g_Menus.MenuSoundsEnabled() &&
- (!menu || (menu->GetMenuOptionFlags() & MENUFLAG_NO_SOUND) != MENUFLAG_NO_SOUND))
- {
- CellRecipientFilter filter;
- cell_t clients[1];
-
- clients[0] = client;
- filter.Initialize(clients, 1);
-
- const char *sound = g_Menus.GetMenuSound(type);
-
- if (sound != NULL)
- {
- edict_t *pEdict = engine->PEntityOfEntIndex(client);
- if (pEdict)
- {
- ICollideable *pCollideable = pEdict->GetCollideable();
-
- if (pCollideable)
- {
- const Vector & pos = pCollideable->GetCollisionOrigin();
-
- enginesound->EmitSound(filter,
- client,
- CHAN_AUTO,
- sound,
- VOL_NORM,
- ATTN_NORM,
- 0,
- PITCH_NORM,
- &pos);
- }
- }
- }
- }
-
- /* For navigational items, we're going to redisplay */
- if (type == ItemSel_Back)
- {
- if (!RedoClientMenu(client, ItemOrder_Descending))
- {
- cancel = true;
- reason = MenuCancel_NoDisplay;
- end_reason = MenuEnd_Cancelled;
- } else {
- return;
- }
- } else if (type == ItemSel_Next) {
- if (!RedoClientMenu(client, ItemOrder_Ascending))
- {
- cancel = true; /* I like Saltines. */
- reason = MenuCancel_NoDisplay;
- end_reason = MenuEnd_Cancelled;
- } else {
- return;
- }
- } else if (type == ItemSel_Exit || type == ItemSel_None) {
- cancel = true;
- reason = MenuCancel_Exit;
- end_reason = MenuEnd_Exit;
- } else if (type == ItemSel_ExitBack) {
- cancel = true;
- reason = MenuCancel_ExitBack;
- end_reason = MenuEnd_ExitBack;
- } else {
- item = states.slots[key_press].item;
- }
- }
-
- /* Clear states */
- player->bInMenu = false;
- if (player->menuHoldTime)
- {
- RemoveClientFromWatch(client);
- }
-
- if (cancel)
- {
- mh->OnMenuCancel(menu, client, reason);
- } else {
- mh->OnMenuSelect(menu, client, item);
- if (mh->GetMenuAPIVersion2() >= 13)
- {
- mh->OnMenuSelect2(menu, client, item, item_on_page);
- }
- }
-
- /* Only fire end for valid menus */
- if (menu)
- {
- mh->OnMenuEnd(menu, end_reason);
- }
-}
-
-bool BaseMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
- client,
- menu,
- mh,
- time);
-#endif
- CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
- if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
- {
- return false;
- }
-
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- if (player->bAutoIgnore)
- {
- return false;
- }
-
- /* For the duration of this, we are going to totally ignore whether
- * the player is already in a menu or not (except to cancel the old one).
- * Instead, we are simply going to ignore any further menu displays, so
- * this display can't be interrupted.
- */
- player->bAutoIgnore = true;
-
- /* Cancel any old menus */
- menu_states_t &states = player->states;
- if (player->bInMenu)
- {
- _CancelClientMenu(client, MenuCancel_Interrupted, true);
- }
-
- states.firstItem = 0;
- states.lastItem = 0;
- states.menu = NULL;
- states.mh = mh;
- states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
- player->bInMenu = true;
- player->bInExternMenu = false;
- player->menuStartTime = gpGlobals->curtime;
- player->menuHoldTime = time;
-
- if (time)
- {
- AddClientToWatch(client);
- }
-
- /* Draw the display */
- SendDisplay(client, menu);
-
- /* We can be interrupted again! */
- player->bAutoIgnore = false;
-
- return true;
-}
-
-bool BaseMenuStyle::DoClientMenu(int client,
- CBaseMenu *menu,
- unsigned int first_item,
- IMenuHandler *mh,
- unsigned int time)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
- client,
- menu,
- mh,
- time);
-#endif
- mh->OnMenuStart(menu);
-
- CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
- if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
-#endif
- mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
- mh->OnMenuEnd(menu, MenuEnd_Cancelled);
- return false;
- }
-
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- if (player->bAutoIgnore)
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
-#endif
- mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
- mh->OnMenuEnd(menu, MenuEnd_Cancelled);
- return false;
- }
-
- /* For the duration of this, we are going to totally ignore whether
- * the player is already in a menu or not (except to cancel the old one).
- * Instead, we are simply going to ignore any further menu displays, so
- * this display can't be interrupted.
- */
- player->bAutoIgnore = true;
-
- /* Cancel any old menus */
- menu_states_t &states = player->states;
- if (player->bInMenu)
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
-#endif
- _CancelClientMenu(client, MenuCancel_Interrupted, true);
- }
-
- states.firstItem = 0;
- states.lastItem = first_item;
- states.menu = menu;
- states.mh = mh;
- states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
-
- IMenuPanel *display = g_Menus.RenderMenu(client, states, ItemOrder_Ascending);
- if (!display)
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
-#endif
- player->bAutoIgnore = false;
- player->bInMenu = false;
- mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
- mh->OnMenuEnd(menu, MenuEnd_Cancelled);
- return false;
- }
-
- /* Finally, set our states */
- player->bInMenu = true;
- player->bInExternMenu = false;
- player->menuStartTime = gpGlobals->curtime;
- player->menuHoldTime = time;
-
- if (time)
- {
- AddClientToWatch(client);
- }
-
- /* Draw the display */
- SendDisplay(client, display);
-
- /* Free the display pointer */
- display->DeleteThis();
-
- /* We can be interrupted again! */
- player->bAutoIgnore = false;
-
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
-#endif
-
- return true;
-}
-
-bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
-{
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
-#endif
- CBaseMenuPlayer *player = GetMenuPlayer(client);
- menu_states_t &states = player->states;
-
- player->bAutoIgnore = true;
- IMenuPanel *display = g_Menus.RenderMenu(client, states, order);
- if (!display)
- {
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
-#endif
- if (player->menuHoldTime)
- {
- RemoveClientFromWatch(client);
- }
- player->bAutoIgnore = false;
- return false;
- }
-
- SendDisplay(client, display);
-
- display->DeleteThis();
-
- player->bAutoIgnore = false;
-
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
-#endif
-
- return true;
-}
-
-CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
-m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
-m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
-m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
-{
-}
-
-CBaseMenu::~CBaseMenu()
-{
-}
-
-Handle_t CBaseMenu::GetHandle()
-{
- if (!m_hHandle)
- {
- m_hHandle = g_Menus.CreateMenuHandle(this, m_pOwner);
- }
-
- return m_hHandle;
-}
-
-bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
-{
- if (m_Pagination == (unsigned)MENU_NO_PAGINATION
- && m_items.size() >= m_pStyle->GetMaxPageItems())
- {
- return false;
- }
-
- CItem item;
-
- item.infoString = m_Strings.AddString(info);
- if (draw.display)
- {
- item.displayString = m_Strings.AddString(draw.display);
- }
- item.style = draw.style;
-
- m_items.push_back(item);
-
- return true;
-}
-
-bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
-{
- if (m_Pagination == (unsigned)MENU_NO_PAGINATION
- && m_items.size() >= m_pStyle->GetMaxPageItems())
- {
- return false;
- }
-
- if (position >= m_items.size())
- {
- return false;
- }
-
- CItem item;
- item.infoString = m_Strings.AddString(info);
- if (draw.display)
- {
- item.displayString = m_Strings.AddString(draw.display);
- }
- item.style = draw.style;
-
- CVector::iterator iter = m_items.iterAt(position);
- m_items.insert(iter, item);
-
- return true;
-}
-
-bool CBaseMenu::RemoveItem(unsigned int position)
-{
- if (position >= m_items.size())
- {
- return false;
- }
-
- m_items.erase(m_items.iterAt(position));
-
- if (m_items.size() == 0)
- {
- m_Strings.Reset();
- }
-
- return true;
-}
-
-void CBaseMenu::RemoveAllItems()
-{
- m_items.clear();
- m_Strings.Reset();
-}
-
-const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
-{
- if (position >= m_items.size())
- {
- return NULL;
- }
-
- if (draw)
- {
- draw->display = m_Strings.GetString(m_items[position].displayString);
- draw->style = m_items[position].style;
- }
-
- return m_Strings.GetString(m_items[position].infoString);
-}
-
-unsigned int CBaseMenu::GetItemCount()
-{
- return m_items.size();
-}
-
-bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
-{
- if (itemsPerPage > 7 || itemsPerPage == 1)
- {
- return false;
- }
-
- if (itemsPerPage == MENU_NO_PAGINATION
- && m_Pagination != MENU_NO_PAGINATION)
- {
- m_nFlags &= ~MENUFLAG_BUTTON_EXIT;
- }
-
- m_Pagination = itemsPerPage;
-
- return true;
-}
-
-unsigned int CBaseMenu::GetPagination()
-{
- return m_Pagination;
-}
-
-IMenuStyle *CBaseMenu::GetDrawStyle()
-{
- return m_pStyle;
-}
-
-void CBaseMenu::SetDefaultTitle(const char *message)
-{
- m_Title.assign(message);
-}
-
-const char *CBaseMenu::GetDefaultTitle()
-{
- return m_Title.c_str();
-}
-
-void CBaseMenu::Cancel()
-{
- if (m_bCancelling)
- {
- return;
- }
-
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_bShouldDelete %d)",
- this,
- m_bShouldDelete);
-#endif
-
- m_bCancelling = true;
- Cancel_Finally();
- m_bCancelling = false;
-
- if (m_bShouldDelete)
- {
- InternalDelete();
- }
-}
-
-void CBaseMenu::Destroy(bool releaseHandle)
-{
- /* Check if we shouldn't be here */
- if (m_bDeleting)
- {
- return;
- }
-
-#if defined MENU_DEBUG
- g_Logger.LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
- this,
- releaseHandle,
- m_bCancelling,
- m_bShouldDelete);
-#endif
-
- /* Save the destruction hint about our handle */
- m_bWillFreeHandle = releaseHandle;
-
- /* Now actually do stuff */
- if (!m_bCancelling || m_bShouldDelete)
- {
- Cancel();
- InternalDelete();
- } else {
- m_bShouldDelete = true;
- }
-}
-
-void CBaseMenu::InternalDelete()
-{
- if (m_bWillFreeHandle && m_hHandle != BAD_HANDLE)
- {
- Handle_t hndl = m_hHandle;
- HandleSecurity sec;
-
- sec.pOwner = m_pOwner;
- sec.pIdentity = g_pCoreIdent;
-
- m_hHandle = BAD_HANDLE;
- m_bDeleting = true;
- g_HandleSys.FreeHandle(hndl, &sec);
- }
-
- m_pHandler->OnMenuDestroy(this);
-
- delete this;
-}
-
-unsigned int CBaseMenu::GetMenuOptionFlags()
-{
- return m_nFlags;
-}
-
-void CBaseMenu::SetMenuOptionFlags(unsigned int flags)
-{
- m_nFlags = flags;
-}
-
-IMenuHandler *CBaseMenu::GetHandler()
-{
- return m_pHandler;
-}
-
-unsigned int CBaseMenu::GetBaseMemUsage()
-{
- return m_Title.size()
- + m_Strings.GetMemTable()->GetMemUsage()
- + (m_items.size() * sizeof(CItem));
-}