Serious-Engine/Sources/SeriousSam/GUI/Menus/GameMenu.cpp

351 lines
7.9 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "SeriousSam/StdH.h"
#include <Engine/CurrentVersion.h>
#include "SeriousSam/GUI/Menus/MenuPrinting.h"
#include "SeriousSam/GUI/Menus/GameMenu.h"
CGameMenu::CGameMenu(void)
{
gm_pgmParentMenu = NULL;
gm_pmgSelectedByDefault = NULL;
gm_pmgArrowUp = NULL;
gm_pmgArrowDn = NULL;
gm_pmgListTop = NULL;
gm_pmgListBottom = NULL;
gm_iListOffset = 0;
gm_ctListVisible = 0;
gm_ctListTotal = 0;
gm_bPopup = FALSE;
}
void CGameMenu::Initialize_t(void)
{
}
void CGameMenu::Destroy(void)
{
}
void CGameMenu::FillListItems(void)
{
ASSERT(FALSE); // must be implemented to scroll up/down
}
void CGameMenu::KillAllFocuses(void)
{
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg) {
itmg->mg_bFocused = FALSE;
}
}
void CGameMenu::Think(void)
{
}
// +-1 -> hit top/bottom when pressing up/down on keyboard
// +-2 -> pressed pageup/pagedown on keyboard
// +-3 -> pressed arrow up/down button in menu
// +-4 -> scrolling with mouse wheel
void CGameMenu::ScrollList(INDEX iDir)
{
// if not valid for scrolling
if (gm_ctListTotal <= 0
|| gm_pmgArrowUp == NULL || gm_pmgArrowDn == NULL
|| gm_pmgListTop == NULL || gm_pmgListBottom == NULL) {
// do nothing
return;
}
INDEX iOldTopKey = gm_iListOffset;
// change offset
switch (iDir) {
case -1:
gm_iListOffset -= 1;
break;
case -4:
gm_iListOffset -= 3;
break;
case -2:
case -3:
gm_iListOffset -= gm_ctListVisible;
break;
case +1:
gm_iListOffset += 1;
break;
case +4:
gm_iListOffset += 3;
break;
case +2:
case +3:
gm_iListOffset += gm_ctListVisible;
break;
default:
ASSERT(FALSE);
return;
}
if (gm_ctListTotal <= gm_ctListVisible) {
gm_iListOffset = 0;
}
else {
gm_iListOffset = Clamp(gm_iListOffset, INDEX(0), INDEX(gm_ctListTotal - gm_ctListVisible));
}
// set new names
FillListItems();
// if scroling with wheel
if (iDir == +4 || iDir == -4) {
// no focus changing
return;
}
// delete all focuses
FOREACHINLIST(CMenuGadget, mg_lnNode, pgmCurrentMenu->gm_lhGadgets, itmg) {
itmg->OnKillFocus();
}
// set new focus
const INDEX iFirst = 0;
const INDEX iLast = gm_ctListVisible - 1;
switch (iDir) {
case +1:
gm_pmgListBottom->OnSetFocus();
break;
case +2:
if (gm_iListOffset != iOldTopKey) {
gm_pmgListTop->OnSetFocus();
}
else {
gm_pmgListBottom->OnSetFocus();
}
break;
case +3:
gm_pmgArrowDn->OnSetFocus();
break;
case -1:
gm_pmgListTop->OnSetFocus();
break;
case -2:
gm_pmgListTop->OnSetFocus();
break;
case -3:
gm_pmgArrowUp->OnSetFocus();
break;
}
}
BOOL CGameMenu::OnChar(MSG msg)
{
// find curently active gadget
CMenuGadget *pmgActive = NULL;
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, pgmCurrentMenu->gm_lhGadgets, itmg) {
// if focused
if (itmg->mg_bFocused) {
// remember as active
pmgActive = &itmg.Current();
}
}
// if none focused
if (pmgActive == NULL) {
// do nothing
return FALSE;
}
// if active gadget handles it
if (pmgActive->OnChar(msg)) {
// key is handled
return TRUE;
}
// key is not handled
return FALSE;
}
// return TRUE if handled
BOOL CGameMenu::OnKeyDown(int iVKey)
{
// find curently active gadget
CMenuGadget *pmgActive = NULL;
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, pgmCurrentMenu->gm_lhGadgets, itmg) {
// if focused
if (itmg->mg_bFocused) {
// remember as active
pmgActive = &itmg.Current();
}
}
// if none focused
if (pmgActive == NULL) {
// do nothing
return FALSE;
}
// if active gadget handles it
if (pmgActive->OnKeyDown(iVKey)) {
// key is handled
return TRUE;
}
// process normal in menu movement
switch (iVKey) {
case VK_PRIOR:
ScrollList(-2);
return TRUE;
case VK_NEXT:
ScrollList(+2);
return TRUE;
case 11:
ScrollList(-4);
return TRUE;
case 10:
ScrollList(+4);
return TRUE;
case VK_UP:
// if this is top button in list
if (pmgActive == gm_pmgListTop) {
// scroll list up
ScrollList(-1);
// key is handled
return TRUE;
}
// if we can go up
if (pmgActive->mg_pmgUp != NULL && pmgActive->mg_pmgUp->mg_bVisible) {
// call lose focus to still active gadget and
pmgActive->OnKillFocus();
// set focus to new one
pmgActive = pmgActive->mg_pmgUp;
pmgActive->OnSetFocus();
// key is handled
return TRUE;
}
break;
case VK_DOWN:
// if this is bottom button in list
if (pmgActive == gm_pmgListBottom) {
// scroll list down
ScrollList(+1);
// key is handled
return TRUE;
}
// if we can go down
if (pmgActive->mg_pmgDown != NULL && pmgActive->mg_pmgDown->mg_bVisible) {
// call lose focus to still active gadget and
pmgActive->OnKillFocus();
// set focus to new one
pmgActive = pmgActive->mg_pmgDown;
pmgActive->OnSetFocus();
// key is handled
return TRUE;
}
break;
case VK_LEFT:
// if we can go left
if (pmgActive->mg_pmgLeft != NULL) {
// call lose focus to still active gadget and
pmgActive->OnKillFocus();
// set focus to new one
if (!pmgActive->mg_pmgLeft->mg_bVisible && gm_pmgSelectedByDefault != NULL) {
pmgActive = gm_pmgSelectedByDefault;
}
else {
pmgActive = pmgActive->mg_pmgLeft;
}
pmgActive->OnSetFocus();
// key is handled
return TRUE;
}
break;
case VK_RIGHT:
// if we can go right
if (pmgActive->mg_pmgRight != NULL) {
// call lose focus to still active gadget and
pmgActive->OnKillFocus();
// set focus to new one
if (!pmgActive->mg_pmgRight->mg_bVisible && gm_pmgSelectedByDefault != NULL) {
pmgActive = gm_pmgSelectedByDefault;
}
else {
pmgActive = pmgActive->mg_pmgRight;
}
pmgActive->OnSetFocus();
// key is handled
return TRUE;
}
break;
}
// key is not handled
return FALSE;
}
void CGameMenu::StartMenu(void)
{
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg)
{
itmg->mg_bFocused = FALSE;
// call appear
itmg->Appear();
}
// if there is a list
if (gm_pmgListTop != NULL) {
// scroll it so that the wanted tem is centered
gm_iListOffset = gm_iListWantedItem - gm_ctListVisible / 2;
// clamp the scrolling
gm_iListOffset = Clamp(gm_iListOffset, 0L, Max(0L, gm_ctListTotal - gm_ctListVisible));
// fill the list
FillListItems();
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg) {
// if in list, but disabled
if (itmg->mg_iInList == -2) {
// hide it
itmg->mg_bVisible = FALSE;
// if in list
} else if (itmg->mg_iInList >= 0) {
// show it
itmg->mg_bVisible = TRUE;
}
// if wanted
if (itmg->mg_iInList == gm_iListWantedItem) {
// focus it
itmg->OnSetFocus();
gm_pmgSelectedByDefault = itmg;
}
}
}
}
void CGameMenu::EndMenu(void)
{
// for each menu gadget in menu
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg)
{
// call disappear
itmg->Disappear();
}
}