2016-03-31 02:38:57 +02:00
|
|
|
/* 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. */
|
2016-03-16 19:43:05 +01:00
|
|
|
|
|
|
|
#include "StdH.h"
|
|
|
|
#include <Engine/CurrentVersion.h>
|
|
|
|
#include "MenuPrinting.h"
|
|
|
|
#include "GameMenu.h"
|
|
|
|
|
|
|
|
|
|
|
|
CGameMenu::CGameMenu(void)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
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;
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::Initialize_t(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::Destroy(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::FillListItems(void)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
ASSERT(FALSE); // must be implemented to scroll up/down
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::KillAllFocuses(void)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// for each menu gadget in menu
|
|
|
|
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg) {
|
|
|
|
itmg->mg_bFocused = FALSE;
|
|
|
|
}
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// 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;
|
|
|
|
}
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CGameMenu::OnChar(MSG msg)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// 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;
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// return TRUE if handled
|
|
|
|
BOOL CGameMenu::OnKeyDown(int iVKey)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// 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;
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::StartMenu(void)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CGameMenu::EndMenu(void)
|
|
|
|
{
|
2016-03-31 22:27:11 +02:00
|
|
|
// for each menu gadget in menu
|
|
|
|
FOREACHINLIST(CMenuGadget, mg_lnNode, gm_lhGadgets, itmg)
|
|
|
|
{
|
|
|
|
// call disappear
|
|
|
|
itmg->Disappear();
|
|
|
|
}
|
2016-03-16 19:43:05 +01:00
|
|
|
}
|