dvander@773: /**
dvander@773: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@773: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1231: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1231: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1231: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@773: *
dvander@773: * Version: $Id$
dvander@773: */
dvander@773:
dvander@877: #include
dvander@769: #include
dvander@877: #include
dvander@769: #include "MenuManager.h"
dvander@1269: #include "MenuVoting.h"
dvander@769: #include "sm_stringutil.h"
dvander@769: #include "sourcemm_api.h"
dvander@769: #include "PlayerManager.h"
dvander@769: #include "MenuStyle_Valve.h"
dvander@781: #include "ShareSys.h"
dvander@790: #include "HandleSys.h"
dvander@1220: #include "sourcemm_api.h"
dvander@2042: #include "Translator.h"
dvander@769:
dvander@769: MenuManager g_Menus;
dvander@1269: VoteMenuHandler s_VoteHandler;
dvander@769:
dvander@1220: ConVar sm_menu_sounds("sm_menu_sounds", "1", 0, "Sets whether SourceMod menus play trigger sounds");
dvander@1220:
dvander@769: MenuManager::MenuManager()
dvander@769: {
dvander@780: m_Styles.push_back(&g_ValveMenuStyle);
dvander@780: SetDefaultStyle(&g_ValveMenuStyle);
dvander@769: }
dvander@769:
dvander@769: void MenuManager::OnSourceModAllInitialized()
dvander@769: {
dvander@781: g_ShareSys.AddInterface(NULL, this);
dvander@790:
dvander@790: HandleAccess access;
dvander@790: g_HandleSys.InitAccessDefaults(NULL, &access);
dvander@790:
dvander@790: /* Deny cloning to menus */
dvander@790: access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
dvander@790: m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
dvander@790:
dvander@790: /* Also deny deletion to styles */
dvander@790: access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
dvander@790: m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
dvander@769: }
dvander@769:
dvander@769: void MenuManager::OnSourceModAllShutdown()
dvander@769: {
dvander@790: g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
dvander@790: g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
dvander@769: }
dvander@769:
dvander@790: void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
dvander@790: {
dvander@790: if (type == m_MenuType)
dvander@790: {
dvander@790: IBaseMenu *menu = (IBaseMenu *)object;
dvander@790: menu->Destroy(false);
dvander@1766: }
dvander@1766: else if (type == m_StyleType)
dvander@1766: {
dvander@790: /* Do nothing */
dvander@790: }
dvander@790: }
dvander@790:
dvander@1766: bool MenuManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1766: {
dvander@1766: if (type == m_MenuType)
dvander@1766: {
dvander@1766: *pSize = ((IBaseMenu *)object)->GetApproxMemUsage();
dvander@1766: return true;
dvander@1766: }
dvander@1766: else
dvander@1766: {
dvander@1766: *pSize = ((IMenuStyle *)object)->GetApproxMemUsage();
dvander@1766: return true;
dvander@1766: }
dvander@1766:
dvander@1766: return false;
dvander@1766: }
dvander@1766:
dvander@790: Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
dvander@790: {
dvander@790: if (m_MenuType == NO_HANDLE_TYPE)
dvander@790: {
dvander@790: return BAD_HANDLE;
dvander@790: }
dvander@790:
dvander@790: return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
dvander@790: }
dvander@790:
dvander@790: Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
dvander@790: {
dvander@790: if (m_StyleType == NO_HANDLE_TYPE)
dvander@790: {
dvander@790: return BAD_HANDLE;
dvander@790: }
dvander@790:
dvander@790: return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
dvander@790: }
dvander@790:
dvander@790: HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
dvander@790: {
dvander@790: HandleSecurity sec;
dvander@790:
dvander@790: sec.pIdentity = g_pCoreIdent;
dvander@790: sec.pOwner = NULL;
dvander@790:
dvander@790: return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
dvander@790: }
dvander@790:
dvander@790: HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
dvander@790: {
dvander@790: HandleSecurity sec;
dvander@790:
dvander@790: sec.pIdentity = g_pCoreIdent;
dvander@790: sec.pOwner = g_pCoreIdent;
dvander@790:
dvander@790: return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
dvander@790: }
dvander@790:
dvander@769: bool MenuManager::SetDefaultStyle(IMenuStyle *style)
dvander@769: {
dvander@769: if (!style)
dvander@769: {
dvander@769: return false;
dvander@769: }
dvander@769:
dvander@769: m_pDefaultStyle = style;
dvander@769:
dvander@769: return true;
dvander@769: }
dvander@769:
dvander@769: IMenuStyle *MenuManager::GetStyle(unsigned int index)
dvander@769: {
dvander@769: if (index >= GetStyleCount())
dvander@769: {
dvander@769: return NULL;
dvander@769: }
dvander@769:
dvander@769: return m_Styles[index];
dvander@769: }
dvander@769:
dvander@780: void MenuManager::AddStyle(IMenuStyle *style)
dvander@780: {
dvander@780: m_Styles.push_back(style);
dvander@780: }
dvander@780:
dvander@769: unsigned int MenuManager::GetStyleCount()
dvander@769: {
dvander@769: return (unsigned int)m_Styles.size();
dvander@769: }
dvander@769:
dvander@769: IMenuStyle *MenuManager::FindStyleByName(const char *name)
dvander@769: {
dvander@769: unsigned int count = GetStyleCount();
dvander@769: for (unsigned int i=0; iGetStyleName(), name) == 0)
dvander@769: {
dvander@769: return ptr;
dvander@769: }
dvander@769: }
dvander@769:
dvander@769: return NULL;
dvander@769: }
dvander@769:
dvander@787: inline bool IsSlotItem(IMenuPanel *display,
dvander@769: unsigned int style)
dvander@769: {
dvander@769: if (!display->CanDrawItem(style))
dvander@769: {
dvander@769: return false;
dvander@769: }
dvander@769: if ((style & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
dvander@769: {
dvander@769: return false;
dvander@769: }
dvander@769: if (style & ITEMDRAW_RAWLINE)
dvander@769: {
dvander@769: return false;
dvander@769: }
dvander@769:
dvander@769: return true;
dvander@769: }
dvander@769:
dvander@787: IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder order)
dvander@769: {
dvander@769: IBaseMenu *menu = md.menu;
dvander@769:
dvander@769: if (!menu)
dvander@769: {
dvander@769: return NULL;
dvander@769: }
dvander@769:
dvander@769: struct
dvander@769: {
dvander@769: unsigned int position;
dvander@769: ItemDrawInfo draw;
dvander@769: } drawItems[10];
dvander@769:
dvander@769: /* Figure out how many items to draw */
dvander@769: IMenuStyle *style = menu->GetDrawStyle();
dvander@769: unsigned int pgn = menu->GetPagination();
dvander@769: unsigned int maxItems = style->GetMaxPageItems();
dvander@1653: bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
dvander@1653:
dvander@769: if (pgn != MENU_NO_PAGINATION)
dvander@769: {
dvander@769: maxItems = pgn;
dvander@769: }
dvander@1653: else if (exitButton)
dvander@1653: {
dvander@1653: maxItems--;
dvander@1653: }
dvander@1653:
dvander@1653: /* This is very not allowed! */
dvander@1653: if (maxItems < 2)
dvander@1653: {
dvander@1653: return NULL;
dvander@1653: }
dvander@769:
dvander@769: unsigned int totalItems = menu->GetItemCount();
dvander@769: unsigned int startItem = 0;
dvander@769:
dvander@769: /* For pagination, find the starting point. */
dvander@769: if (pgn != MENU_NO_PAGINATION)
dvander@769: {
dvander@769: if (order == ItemOrder_Ascending)
dvander@769: {
dvander@769: startItem = md.lastItem;
dvander@769: /* This shouldn't happen with well-coded menus.
dvander@769: * If the item is out of bounds, switch the order to
dvander@769: * Items_Descending and make us start from the top.
dvander@769: */
dvander@769: if (startItem >= totalItems)
dvander@769: {
dvander@769: startItem = totalItems - 1;
dvander@769: order = ItemOrder_Descending;
dvander@769: }
dvander@1653: }
dvander@1653: else if (order == ItemOrder_Descending)
dvander@1653: {
dvander@769: startItem = md.firstItem;
dvander@769: /* This shouldn't happen with well-coded menus.
dvander@769: * If searching backwards doesn't give us enough room,
dvander@769: * start from the beginning and change to ascending.
dvander@769: */
dvander@769: if (startItem <= maxItems)
dvander@769: {
dvander@769: startItem = 0;
dvander@769: order = ItemOrder_Ascending;
dvander@769: }
dvander@769: }
dvander@769: }
dvander@769:
dvander@769: /* Get our Display pointer and initialize some crap */
dvander@1653: IMenuPanel *panel = menu->CreatePanel();
dvander@769: IMenuHandler *mh = md.mh;
dvander@769: bool foundExtra = false;
dvander@769: unsigned int extraItem = 0;
dvander@769:
dvander@1653: if (panel == NULL)
dvander@1653: {
dvander@1653: return NULL;
dvander@1653: }
dvander@1653:
dvander@769: /**
dvander@769: * We keep searching until:
dvander@769: * 1) There are no more items
dvander@769: * 2) We reach one OVER the maximum number of slot items
dvander@769: * 3) We have reached maxItems and pagination is MENU_NO_PAGINATION
dvander@769: */
dvander@769: unsigned int i = startItem;
dvander@769: unsigned int foundItems = 0;
dvander@1345: while (totalItems)
dvander@769: {
dvander@769: ItemDrawInfo &dr = drawItems[foundItems].draw;
dvander@769: /* Is the item valid? */
dvander@769: if (menu->GetItemInfo(i, &dr) != NULL)
dvander@769: {
dvander@769: /* Ask the user to change the style, if necessary */
dvander@769: mh->OnMenuDrawItem(menu, client, i, dr.style);
dvander@769: /* Check if it's renderable */
dvander@1653: if (IsSlotItem(panel, dr.style))
dvander@769: {
dvander@769: /* If we've already found the max number of items,
dvander@769: * This means we should just cancel out and log our
dvander@769: * "last item."
dvander@769: */
dvander@769: if (foundItems >= maxItems)
dvander@769: {
dvander@769: foundExtra = true;
dvander@769: extraItem = i;
dvander@769: break;
dvander@769: }
dvander@769: drawItems[foundItems++].position = i;
dvander@769: }
dvander@769: }
dvander@769: /* If there's no pagination, stop once the menu is full. */
dvander@769: if (pgn == MENU_NO_PAGINATION)
dvander@769: {
dvander@769: /* If we've filled up, then stop */
dvander@769: if (foundItems >= maxItems)
dvander@769: {
dvander@769: break;
dvander@769: }
dvander@769: }
dvander@769: /* If we're descending and this is the first item, stop */
dvander@769: if (order == ItemOrder_Descending)
dvander@769: {
dvander@769: if (i == 0)
dvander@769: {
dvander@769: break;
dvander@769: }
dvander@769: i--;
dvander@769: }
dvander@769: /* If we're ascending and this is the last item, stop */
dvander@769: else if (order == ItemOrder_Ascending)
dvander@769: {
dvander@769: if (i >= totalItems - 1)
dvander@769: {
dvander@769: break;
dvander@769: }
dvander@769: i++;
dvander@769: }
dvander@769: }
dvander@769:
dvander@769: /* There were no items to draw! */
dvander@769: if (!foundItems)
dvander@769: {
dvander@1653: panel->DeleteThis();
dvander@769: return NULL;
dvander@769: }
dvander@769:
dvander@769: bool displayPrev = false;
dvander@769: bool displayNext = false;
dvander@769:
dvander@1653: /* This is an annoying process.
dvander@1653: * Skip it for non-paginated menus, which get special treatment.
dvander@769: */
dvander@769: if (pgn != MENU_NO_PAGINATION)
dvander@769: {
dvander@1653: if (foundExtra)
dvander@1653: {
dvander@1653: if (order == ItemOrder_Descending)
dvander@1653: {
dvander@1653: displayPrev = true;
dvander@1653: md.firstItem = extraItem;
dvander@1653: }
dvander@1653: else if (order == ItemOrder_Ascending)
dvander@1653: {
dvander@1653: displayNext = true;
dvander@1653: md.lastItem = extraItem;
dvander@1653: }
dvander@1653: }
dvander@1653:
dvander@769: unsigned int lastItem = 0;
dvander@769: ItemDrawInfo dr;
dvander@769: /* Find the last feasible item to search from. */
dvander@769: if (order == ItemOrder_Descending)
dvander@769: {
dvander@769: lastItem = drawItems[0].position;
dvander@769: if (lastItem >= totalItems - 1)
dvander@769: {
dvander@769: goto skip_search;
dvander@769: }
dvander@769: while (++lastItem < totalItems)
dvander@769: {
dvander@769: if (menu->GetItemInfo(lastItem, &dr) != NULL)
dvander@769: {
dvander@769: mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
dvander@1653: if (IsSlotItem(panel, dr.style))
dvander@769: {
dvander@769: displayNext = true;
dvander@769: md.lastItem = lastItem;
dvander@769: break;
dvander@769: }
dvander@769: }
dvander@769: }
dvander@1653: }
dvander@1653: else if (order == ItemOrder_Ascending)
dvander@1653: {
dvander@769: lastItem = drawItems[0].position;
dvander@769: if (lastItem == 0)
dvander@769: {
dvander@769: goto skip_search;
dvander@769: }
dvander@769: lastItem--;
dvander@1004: while (lastItem != 0)
dvander@769: {
dvander@769: if (menu->GetItemInfo(lastItem, &dr) != NULL)
dvander@769: {
dvander@769: mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
dvander@1653: if (IsSlotItem(panel, dr.style))
dvander@769: {
dvander@769: displayPrev = true;
dvander@769: md.firstItem = lastItem;
dvander@769: break;
dvander@769: }
dvander@769: }
dvander@1004: lastItem--;
dvander@769: }
dvander@769: }
dvander@769: }
dvander@1653:
dvander@769: skip_search:
dvander@769:
dvander@769: /* Draw the item according to the order */
dvander@769: menu_slots_t *slots = md.slots;
dvander@769: unsigned int position = 0; /* Keep track of the last position */
dvander@769: if (order == ItemOrder_Ascending)
dvander@769: {
dvander@1476: md.item_on_page = drawItems[0].position;
dvander@1476: for (unsigned int i = 0; i < foundItems; i++)
dvander@769: {
dvander@769: ItemDrawInfo &dr = drawItems[i].draw;
dvander@1653: if ((position = mh->OnMenuDisplayItem(menu, client, panel, drawItems[i].position, dr)) == 0)
dvander@1163: {
dvander@1653: position = panel->DrawItem(dr);
dvander@1163: }
dvander@1163: if (position != 0)
dvander@769: {
dvander@769: slots[position].item = drawItems[i].position;
dvander@1873: if ((dr.style & ITEMDRAW_DISABLED) == ITEMDRAW_DISABLED)
dvander@1873: {
dvander@1873: slots[position].type = ItemSel_None;
dvander@1873: }
dvander@1873: else
dvander@1873: {
dvander@1873: slots[position].type = ItemSel_Item;
dvander@1873: }
dvander@769: }
dvander@769: }
dvander@1476: }
dvander@1476: else if (order == ItemOrder_Descending)
dvander@1476: {
dvander@769: unsigned int i = foundItems;
dvander@769: /* NOTE: There will always be at least one item because
dvander@769: * of the check earlier.
dvander@769: */
dvander@1476: md.item_on_page = drawItems[foundItems - 1].position;
dvander@769: while (i--)
dvander@769: {
dvander@769: ItemDrawInfo &dr = drawItems[i].draw;
dvander@1653: if ((position = mh->OnMenuDisplayItem(menu, client, panel, drawItems[i].position, dr)) == 0)
dvander@1163: {
dvander@1653: position = panel->DrawItem(dr);
dvander@1163: }
dvander@1257: if (position != 0)
dvander@769: {
dvander@769: slots[position].item = drawItems[i].position;
dvander@1873: if ((dr.style & ITEMDRAW_DISABLED) == ITEMDRAW_DISABLED)
dvander@1873: {
dvander@1873: slots[position].type = ItemSel_None;
dvander@1873: }
dvander@1873: else
dvander@1873: {
dvander@1873: slots[position].type = ItemSel_Item;
dvander@1873: }
dvander@769: }
dvander@769: }
dvander@769: }
dvander@769:
dvander@769: /* Now, we need to check if we need to add anything extra */
dvander@1653: if (pgn != MENU_NO_PAGINATION || exitButton)
dvander@769: {
dvander@1653: bool canDrawDisabled = panel->CanDrawItem(ITEMDRAW_DISABLED|ITEMDRAW_CONTROL);
dvander@1653: bool exitBackButton = false;
dvander@769: char text[50];
dvander@769:
dvander@1653: if (pgn != MENU_NO_PAGINATION
dvander@1653: && (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXITBACK)
dvander@1653: {
dvander@1653: exitBackButton = true;
dvander@1653: }
dvander@1653:
dvander@769: /* Calculate how many items we are allowed for control stuff */
dvander@769: unsigned int padding = style->GetMaxPageItems() - maxItems;
dvander@769:
dvander@769: /* Add the number of available slots */
dvander@769: padding += (maxItems - foundItems);
dvander@769:
dvander@769: /* Someday, if we are able to re-enable this, we will be very lucky men. */
dvander@769: #if 0
dvander@769: if (!style->FeatureExists(MenuStyleFeature_ImplicitExit))
dvander@769: {
dvander@769: #endif
dvander@769: /* Even if we don't draw an exit button, we invalidate the slot. */
dvander@769: padding--;
dvander@769: #if 0
dvander@769: } else {
dvander@769: /* Otherwise, we don't draw anything and leave the slot available */
dvander@769: exitButton = false;
dvander@769: }
dvander@769: #endif
dvander@769:
dvander@1653: if (pgn != MENU_NO_PAGINATION)
dvander@1653: {
dvander@1653: /* Subtract two slots for the displayNext/displayPrev padding */
dvander@1653: padding -= 2;
dvander@1653: }
dvander@769:
dvander@1005: /* If we have an "Exit Back" button and the space to draw it, do so. */
dvander@1005: if (exitBackButton)
dvander@1005: {
dvander@1005: if (!displayPrev)
dvander@1005: {
dvander@1005: displayPrev = true;
dvander@1653: }
dvander@1653: else
dvander@1653: {
dvander@1005: exitBackButton = false;
dvander@1005: }
dvander@1005: }
dvander@1005:
dvander@769: /**
dvander@769: * We allow next/prev to be undrawn if neither exists.
dvander@769: * Thus, we only need padding if one of them will be drawn,
dvander@769: * or the exit button will be drawn.
dvander@769: */
dvander@769: ItemDrawInfo padItem(NULL, ITEMDRAW_SPACER);
dvander@769: if (exitButton || (displayNext || displayPrev))
dvander@769: {
dvander@790: /* If there are no control options,
dvander@790: * Instead just pad with invisible slots.
dvander@790: */
dvander@790: if (!displayPrev && !displayPrev)
dvander@790: {
dvander@790: padItem.style = ITEMDRAW_NOTEXT;
dvander@790: }
dvander@769: /* Add spacers so we can pad to the end */
dvander@769: for (unsigned int i=0; iDrawItem(padItem);
dvander@769: slots[position].type = ItemSel_None;
dvander@769: }
dvander@769: }
dvander@776:
dvander@776: /* Put a fake spacer before control stuff, if possible */
dvander@797: if ((displayPrev || displayNext) || exitButton)
dvander@776: {
dvander@776: ItemDrawInfo draw("", ITEMDRAW_RAWLINE|ITEMDRAW_SPACER);
dvander@1653: panel->DrawItem(draw);
dvander@776: }
dvander@769:
dvander@776: ItemDrawInfo dr(text, 0);
dvander@1653:
dvander@785: /**
dvander@785: * If we have one or the other, we need to have spacers for both.
dvander@785: */
dvander@1653: if (pgn != MENU_NO_PAGINATION)
dvander@769: {
dvander@1653: if (displayPrev || displayNext)
dvander@785: {
dvander@1653: /* PREVIOUS */
dvander@1653: ItemDrawInfo padCtrlItem(NULL, ITEMDRAW_SPACER|ITEMDRAW_CONTROL);
dvander@1653: if (displayPrev || canDrawDisabled)
dvander@1653: {
dvander@1653: if (exitBackButton)
dvander@1653: {
dvander@2042: if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
dvander@2042: {
dvander@2042: UTIL_Format(text, sizeof(text), "Back");
dvander@2042: }
dvander@1653: dr.style = ITEMDRAW_CONTROL;
dvander@1653: position = panel->DrawItem(dr);
dvander@1653: slots[position].type = ItemSel_ExitBack;
dvander@1653: }
dvander@1653: else
dvander@1653: {
dvander@2042: if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
dvander@2042: {
dvander@2042: UTIL_Format(text, sizeof(text), "Previous");
dvander@2042: }
dvander@1653: dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
dvander@1653: position = panel->DrawItem(dr);
dvander@1653: slots[position].type = ItemSel_Back;
dvander@1653: }
dvander@1653: }
dvander@1653: else if (displayNext || exitButton)
dvander@1005: {
dvander@1653: /* If we can't display this, and there is an exit button,
dvander@1653: * we need to pad!
dvander@1653: */
dvander@1653: position = panel->DrawItem(padCtrlItem);
dvander@1653: slots[position].type = ItemSel_None;
dvander@1653: }
dvander@1653:
dvander@1653: /* NEXT */
dvander@1653: if (displayNext || canDrawDisabled)
dvander@1653: {
dvander@2042: if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
dvander@2042: {
dvander@2042: UTIL_Format(text, sizeof(text), "Next");
dvander@2042: }
dvander@1653: dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
dvander@1653: position = panel->DrawItem(dr);
dvander@1653: slots[position].type = ItemSel_Next;
dvander@1005: }
dvander@1653: else if (exitButton)
dvander@1653: {
dvander@1653: /* If we can't display this,
dvander@1653: * but there is an "exit" button, we need to pad!
dvander@1653: */
dvander@1653: position = panel->DrawItem(padCtrlItem);
dvander@1653: slots[position].type = ItemSel_None;
dvander@1653: }
dvander@1653: }
dvander@1653: else
dvander@1653: {
dvander@1653: /* Otherwise, bump to two slots! */
dvander@1653: ItemDrawInfo numBump(NULL, ITEMDRAW_NOTEXT);
dvander@1653: position = panel->DrawItem(numBump);
dvander@1653: slots[position].type = ItemSel_None;
dvander@1653: position = panel->DrawItem(numBump);
dvander@785: slots[position].type = ItemSel_None;
dvander@785: }
dvander@769: }
dvander@769:
dvander@769: /* EXIT */
dvander@769: if (exitButton)
dvander@769: {
dvander@2042: if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
dvander@2042: {
dvander@2042: UTIL_Format(text, sizeof(text), "Exit");
dvander@2042: }
dvander@785: dr.style = ITEMDRAW_CONTROL;
dvander@1653: position = panel->DrawItem(dr);
dvander@769: slots[position].type = ItemSel_Exit;
dvander@769: }
dvander@769: }
dvander@769:
dvander@769: /* Lastly, fill in any slots we could have missed */
dvander@769: for (unsigned int i = position + 1; i < 10; i++)
dvander@769: {
dvander@769: slots[i].type = ItemSel_None;
dvander@769: }
dvander@769:
dvander@769: /* Do title stuff */
dvander@1653: mh->OnMenuDisplay(menu, client, panel);
dvander@1653: panel->DrawTitle(menu->GetDefaultTitle(), true);
dvander@769:
dvander@1653: return panel;
dvander@769: }
dvander@769:
dvander@769: IMenuStyle *MenuManager::GetDefaultStyle()
dvander@769: {
dvander@769: return m_pDefaultStyle;
dvander@769: }
dvander@769:
dvander@1220: bool MenuManager::MenuSoundsEnabled()
dvander@1220: {
dvander@1220: return (sm_menu_sounds.GetInt() != 0);
dvander@1220: }
dvander@1220:
dvander@1220: ConfigResult MenuManager::OnSourceModConfigChanged(const char *key,
dvander@1220: const char *value,
dvander@1220: ConfigSource source,
dvander@1220: char *error,
dvander@1220: size_t maxlength)
dvander@1220: {
dvander@1220: if (strcmp(key, "MenuItemSound") == 0)
dvander@1220: {
dvander@1220: m_SelectSound.assign(value);
dvander@1220: return ConfigResult_Accept;
dvander@1220: } else if (strcmp(key, "MenuExitBackSound") == 0) {
dvander@1220: m_ExitBackSound.assign(value);
dvander@1220: return ConfigResult_Accept;
dvander@1243: } else if (strcmp(key, "MenuExitSound") == 0) {
dvander@1243: m_ExitSound.assign(value);
dvander@1243: return ConfigResult_Accept;
dvander@1220: }
dvander@1220:
dvander@1220: return ConfigResult_Ignore;
dvander@1220: }
dvander@1220:
dvander@1220: const char *MenuManager::GetMenuSound(ItemSelection sel)
dvander@1220: {
dvander@1220: const char *sound = NULL;
dvander@1220:
dvander@1220: switch (sel)
dvander@1220: {
dvander@1220: case ItemSel_Back:
dvander@1220: case ItemSel_Next:
dvander@1220: case ItemSel_Item:
dvander@1220: {
dvander@1220: if (m_SelectSound.size() > 0)
dvander@1220: {
dvander@1220: sound = m_SelectSound.c_str();
dvander@1220: }
dvander@1220: break;
dvander@1220: }
dvander@1220: case ItemSel_ExitBack:
dvander@1220: {
dvander@1220: if (m_ExitBackSound.size() > 0)
dvander@1220: {
dvander@1220: sound = m_ExitBackSound.c_str();
dvander@1220: }
dvander@1220: break;
dvander@1220: }
dvander@1243: case ItemSel_Exit:
dvander@1243: {
dvander@1243: if (m_ExitSound.size() > 0)
dvander@1243: {
dvander@1269: sound = m_ExitSound.c_str();
dvander@1243: }
dvander@1243: break;
dvander@1243: }
dvander@1220: default:
dvander@1220: {
dvander@1220: break;
dvander@1220: }
dvander@1220: }
dvander@1220:
dvander@1220: return sound;
dvander@1220: }
dvander@1258:
dvander@1258: void MenuManager::OnSourceModLevelChange(const char *mapName)
dvander@1258: {
dvander@1258: if (m_SelectSound.size() > 0)
dvander@1258: {
dvander@1258: enginesound->PrecacheSound(m_SelectSound.c_str(), true);
dvander@1258: }
dvander@1258: if (m_ExitBackSound.size() > 0)
dvander@1258: {
dvander@1258: enginesound->PrecacheSound(m_ExitBackSound.c_str(), true);
dvander@1258: }
dvander@1258: if (m_ExitSound.size() > 0)
dvander@1258: {
dvander@1258: enginesound->PrecacheSound(m_ExitSound.c_str(), true);
dvander@1258: }
dvander@1258: }
dvander@1269:
dvander@1269: void MenuManager::CancelMenu(IBaseMenu *menu)
dvander@1269: {
dvander@1269: if (s_VoteHandler.GetCurrentMenu() == menu
dvander@1269: && !s_VoteHandler.IsCancelling())
dvander@1269: {
dvander@1269: s_VoteHandler.CancelVoting();
dvander@1269: return;
dvander@1269: }
dvander@1269:
dvander@1269: menu->Cancel();
dvander@1269: }
dvander@1269:
dvander@1269: bool MenuManager::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags)
dvander@1269: {
dvander@1269: return s_VoteHandler.StartVote(menu, num_clients, clients, max_time, flags);
dvander@1269: }
dvander@1269:
dvander@1269: bool MenuManager::IsVoteInProgress()
dvander@1269: {
dvander@1269: return s_VoteHandler.IsVoteInProgress();
dvander@1269: }
dvander@1269:
dvander@1269: void MenuManager::CancelVoting()
dvander@1269: {
dvander@1269: s_VoteHandler.CancelVoting();
dvander@1269: }
dvander@1291:
dvander@1291: unsigned int MenuManager::GetRemainingVoteDelay()
dvander@1291: {
dvander@1291: return s_VoteHandler.GetRemainingVoteDelay();
dvander@1291: }
dvander@2056:
dvander@2056: bool MenuManager::IsClientInVotePool(int client)
dvander@2056: {
dvander@2056: return s_VoteHandler.IsClientInVotePool(client);
dvander@2056: }
dvander@2056:
dvander@2056: bool MenuManager::RedrawClientVoteMenu(int client)
dvander@2056: {
dvander@2056: return s_VoteHandler.RedrawToClient(client);
dvander@2056: }