jkxr/Projects/Android/jni/OpenJK/code/ui/ui_shared.cpp

11541 lines
234 KiB
C++

/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 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 <http://www.gnu.org/licenses/>.
===========================================================================
*/
//
// string allocation/managment
// leave this at the top of all UI_xxxx files for PCH reasons...
//
#include "../server/exe_headers.h"
#include "ui_local.h"
//rww - added for ui ghoul2 models
#define UI_SHARED_CPP
#include "../game/anims.h"
#include "../cgame/animtable.h"
#include "ui_shared.h"
#include "menudef.h"
#include "qcommon/stringed_ingame.h"
#include <JKXR/VrClientInfo.h>
extern vr_client_info_t vr;
void UI_LoadMenus(const char *menuFile, qboolean reset);
extern vmCvar_t ui_char_color_red;
extern vmCvar_t ui_char_color_green;
extern vmCvar_t ui_char_color_blue;
void *UI_Alloc( int size );
void Controls_GetConfig( void );
void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount);
void Item_Init(itemDef_t *item);
void Item_InitControls(itemDef_t *item);
qboolean Item_Parse(itemDef_t *item);
void Item_RunScript(itemDef_t *item, const char *s);
void Item_SetupKeywordHash(void);
void Item_Text_AutoWrapped_Paint(itemDef_t *item);
void Item_UpdatePosition(itemDef_t *item);
void Item_ValidateTypeData(itemDef_t *item);
void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t);
itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p);
itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name);
void Menu_Paint(menuDef_t *menu, qboolean forcePaint);
void Menu_SetupKeywordHash(void);
void Menus_ShowItems(const char *menuName);
qboolean ParseRect(const char **p, rectDef_t *r);
const char *String_Alloc(const char *p);
void ToWindowCoords(float *x, float *y, windowDef_t *window);
void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle);
int Item_ListBox_ThumbDrawPosition(itemDef_t *item);
int Item_ListBox_ThumbPosition(itemDef_t *item);
int Item_ListBox_MaxScroll(itemDef_t *item);
static qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y) ;
static qboolean Item_Paint(itemDef_t *item, qboolean bDraw);
int Item_TextScroll_ThumbDrawPosition ( itemDef_t *item );
static void Item_TextScroll_BuildLines ( itemDef_t* item );
//static qboolean debugMode = qfalse;
static qboolean g_waitingForKey = qfalse;
static qboolean g_editingField = qfalse;
static itemDef_t *g_bindItem = NULL;
static itemDef_t *g_editItem = NULL;
static itemDef_t *itemCapture = NULL; // item that has the mouse captured ( if any )
#define DOUBLE_CLICK_DELAY 300
static int lastListBoxClickTime = 0;
static void (*captureFunc) (void *p) = NULL;
static void *captureData = NULL;
//const char defaultString[10] = {"default"};
#ifdef CGAME
#define MEM_POOL_SIZE (128 * 1024)
#else
#define MEM_POOL_SIZE (4 * 1024 * 1024)
#endif
#define SCROLL_TIME_START 500
#define SCROLL_TIME_ADJUST 150
#define SCROLL_TIME_ADJUSTOFFSET 40
#define SCROLL_TIME_FLOOR 20
typedef struct scrollInfo_s {
int nextScrollTime;
int nextAdjustTime;
int adjustValue;
int scrollKey;
float xStart;
float yStart;
itemDef_t *item;
qboolean scrollDir;
} scrollInfo_t;
static scrollInfo_t scrollInfo;
static char memoryPool[MEM_POOL_SIZE];
static int allocPoint, outOfMemory;
displayContextDef_t *DC = NULL;
menuDef_t Menus[MAX_MENUS]; // defined menus
int menuCount = 0; // how many
menuDef_t *menuStack[MAX_OPEN_MENUS];
int openMenuCount = 0;
static int strPoolIndex = 0;
static char strPool[STRING_POOL_SIZE];
typedef struct stringDef_s {
struct stringDef_s *next;
const char *str;
} stringDef_t;
#define HASH_TABLE_SIZE 2048
static int strHandleCount = 0;
static stringDef_t *strHandle[HASH_TABLE_SIZE];
typedef struct itemFlagsDef_s {
const char *string;
int value;
} itemFlagsDef_t;
itemFlagsDef_t itemFlags [] = {
{ "WINDOW_INACTIVE", WINDOW_INACTIVE },
{ NULL, 0 }
};
const char *styles [] = {
"WINDOW_STYLE_EMPTY",
"WINDOW_STYLE_FILLED",
"WINDOW_STYLE_GRADIENT",
"WINDOW_STYLE_SHADER",
"WINDOW_STYLE_TEAMCOLOR",
"WINDOW_STYLE_CINEMATIC",
NULL
};
const char *types [] = {
"ITEM_TYPE_TEXT",
"ITEM_TYPE_BUTTON",
"ITEM_TYPE_RADIOBUTTON",
"ITEM_TYPE_CHECKBOX",
"ITEM_TYPE_EDITFIELD",
"ITEM_TYPE_COMBO",
"ITEM_TYPE_LISTBOX",
"ITEM_TYPE_MODEL",
"ITEM_TYPE_OWNERDRAW",
"ITEM_TYPE_NUMERICFIELD",
"ITEM_TYPE_SLIDER",
"ITEM_TYPE_YESNO",
"ITEM_TYPE_MULTI",
"ITEM_TYPE_BIND",
"ITEM_TYPE_TEXTSCROLL",
NULL
};
const char *alignment [] = {
"ITEM_ALIGN_LEFT",
"ITEM_ALIGN_CENTER",
"ITEM_ALIGN_RIGHT",
NULL
};
/*
==================
Init_Display
Initializes the display with a structure to all the drawing routines
==================
*/
void Init_Display(displayContextDef_t *dc)
{
DC = dc;
}
/*
==================
Window_Init
Initializes a window structure ( windowDef_t ) with defaults
==================
*/
void Window_Init(Window *w)
{
memset(w, 0, sizeof(windowDef_t));
w->borderSize = 1;
w->foreColor[0] = w->foreColor[1] = w->foreColor[2] = w->foreColor[3] = 1.0;
w->cinematic = -1;
}
/*
=================
PC_SourceError
=================
*/
void PC_SourceError(int handle, char *format, ...)
{
int line;
char filename[128];
va_list argptr;
static char string[4096];
va_start (argptr, format);
Q_vsnprintf (string, sizeof(string), format, argptr);
va_end (argptr);
filename[0] = '\0';
line = 0;
Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
}
/*
=================
PC_ParseStringMem
=================
*/
qboolean PC_ParseStringMem(const char **out)
{
const char *temp;
if (PC_ParseString(&temp))
{
return qfalse;
}
*(out) = String_Alloc(temp);
return qtrue;
}
/*
=================
PC_ParseRect
=================
*/
qboolean PC_ParseRect(rectDef_t *r)
{
if (!PC_ParseFloat(&r->x))
{
if (!PC_ParseFloat(&r->y))
{
if (!PC_ParseFloat(&r->w))
{
if (!PC_ParseFloat(&r->h))
{
return qtrue;
}
}
}
}
return qfalse;
}
/*
=================
PC_Script_Parse
=================
*/
qboolean PC_Script_Parse(const char **out)
{
char script[4096];
// pc_token_t token;
char *token2;
script[0]=0;
// scripts start with { and have ; separated command lists.. commands are command, arg..
// basically we want everything between the { } as it will be interpreted at run time
token2 = PC_ParseExt();
if (!token2)
{
return qfalse;
}
if (*token2 !='{')
{
return qfalse;
}
while ( 1 )
{
token2 = PC_ParseExt();
if (!token2)
{
return qfalse;
}
if (*token2 =='}') // End of the script?
{
*out = String_Alloc(script);
return qtrue;
}
if (*(token2 +1) != '\0')
{
Q_strcat(script, sizeof(script), va("\"%s\"", token2));
}
else
{
Q_strcat(script, sizeof(script), token2);
}
Q_strcat(script, sizeof(script), " ");
}
}
//--------------------------------------------------------------------------------------------
// Menu Keyword Parse functions
//--------------------------------------------------------------------------------------------
/*
=================
MenuParse_font
=================
*/
qboolean MenuParse_font( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_ParseStringMem(&menu->font))
{
return qfalse;
}
if (!DC->Assets.fontRegistered)
{
DC->Assets.qhMediumFont = DC->registerFont(menu->font);
DC->Assets.fontRegistered = qtrue;
}
return qtrue;
}
/*
=================
MenuParse_name
=================
*/
qboolean MenuParse_name(itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_ParseStringMem((const char **) &menu->window.name))
{
return qfalse;
}
// if (Q_stricmp(menu->window.name, "main") == 0)
// {
// default main as having focus
// menu->window.flags |= WINDOW_HASFOCUS;
// }
return qtrue;
}
/*
=================
MenuParse_fullscreen
=================
*/
qboolean MenuParse_fullscreen( itemDef_t *item )
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt((int *) &menu->fullScreen))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_rect
=================
*/
qboolean MenuParse_rect( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_ParseRect(&menu->window.rect))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_style
=================
*/
qboolean MenuParse_style( itemDef_t *item)
{
int i;
const char *tempStr;
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (styles[i])
{
if (Q_stricmp(tempStr,styles[i])==0)
{
menu->window.style = i;
break;
}
i++;
}
if (styles[i] == NULL)
{
PC_ParseWarning(va("Unknown menu style value '%s'",tempStr));
}
return qtrue;
}
/*
=================
MenuParse_visible
=================
*/
qboolean MenuParse_visible( itemDef_t *item )
{
int i;
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&i))
{
return qfalse;
}
if (i)
{
menu->window.flags |= WINDOW_VISIBLE;
}
return qtrue;
}
/*
=================
MenuParse_ignoreescape
=================
*/
qboolean MenuParse_ignoreescape( itemDef_t *item )
{
int i;
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&i))
{
return qfalse;
}
if (i)
{
menu->window.flags |= WINDOW_IGNORE_ESCAPE;
}
return qtrue;
}
/*
=================
MenuParse_onOpen
=================
*/
qboolean MenuParse_onOpen( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_Script_Parse(&menu->onOpen))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_onClose
=================
*/
qboolean MenuParse_onClose( itemDef_t *item )
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_Script_Parse(&menu->onClose))
{
return qfalse;
}
return qtrue;
}
//JLFACCEPT MPMOVED
/*
=================
MenuParse_onAccept
=================
*/
qboolean MenuParse_onAccept( itemDef_t *item )
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_Script_Parse(&menu->onAccept))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_onESC
=================
*/
qboolean MenuParse_onESC( itemDef_t *item )
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_Script_Parse(&menu->onESC))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_border
=================
*/
qboolean MenuParse_border( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->window.border))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_borderSize
=================
*/
qboolean MenuParse_borderSize( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseFloat(&menu->window.borderSize))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_backcolor
=================
*/
qboolean MenuParse_backcolor( itemDef_t *item )
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
menu->window.backColor[i] = f;
}
return qtrue;
}
/*
=================
MenuParse_forecolor
=================
*/
qboolean MenuParse_forecolor( itemDef_t *item)
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
if (f < 0)
{ //special case for player color
menu->window.flags |= WINDOW_PLAYERCOLOR;
return qtrue;
}
menu->window.foreColor[i] = f;
menu->window.flags |= WINDOW_FORECOLORSET;
}
return qtrue;
}
/*
=================
MenuParse_bordercolor
=================
*/
qboolean MenuParse_bordercolor( itemDef_t *item )
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
menu->window.borderColor[i] = f;
}
return qtrue;
}
/*
=================
MenuParse_focuscolor
=================
*/
qboolean MenuParse_focuscolor( itemDef_t *item)
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
menu->focusColor[i] = f;
}
return qtrue;
}
/*
=================
MenuParse_focuscolor
=================
*/
qboolean MenuParse_appearanceIncrement( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseFloat(&menu->appearanceIncrement))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_descAlignment
=================
*/
qboolean MenuParse_descAlignment( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
const char *tempStr;
int i;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (alignment[i])
{
if (Q_stricmp(tempStr,alignment[i])==0)
{
menu->descAlignment = i;
break;
}
i++;
}
if (alignment[i] == NULL)
{
PC_ParseWarning(va("Unknown desc alignment value '%s'",tempStr));
}
return qtrue;
}
/*
=================
MenuParse_descTextStyle
=================
*/
qboolean MenuParse_descTextStyle( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->descTextStyle))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_descX
=================
*/
qboolean MenuParse_descX( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->descX))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_descY
=================
*/
qboolean MenuParse_descY( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->descY))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_descScale
=================
*/
qboolean MenuParse_descScale( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseFloat(&menu->descScale))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_descColor
=================
*/
qboolean MenuParse_descColor( itemDef_t *item)
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
menu->descColor[i] = f;
}
return qtrue;
}
/*
=================
MenuParse_disablecolor
=================
*/
qboolean MenuParse_disablecolor( itemDef_t *item)
{
int i;
float f;
menuDef_t *menu = (menuDef_t*)item;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
menu->disableColor[i] = f;
}
return qtrue;
}
/*
=================
MenuParse_outlinecolor
=================
*/
qboolean MenuParse_outlinecolor( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseColor(&menu->window.outlineColor))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_background
=================
*/
qboolean MenuParse_background( itemDef_t *item)
{
const char *buff;
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseString(&buff))
{
return qfalse;
}
menu->window.background = ui.R_RegisterShaderNoMip(buff);
return qtrue;
}
/*
=================
MenuParse_cinematic
=================
*/
qboolean MenuParse_cinematic( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_ParseStringMem((const char **) &menu->window.cinematicName))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_ownerdrawFlag
=================
*/
qboolean MenuParse_ownerdrawFlag( itemDef_t *item)
{
int i;
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&i))
{
return qfalse;
}
menu->window.ownerDrawFlags |= i;
return qtrue;
}
/*
=================
MenuParse_ownerdraw
=================
*/
qboolean MenuParse_ownerdraw( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->window.ownerDraw))
{
return qfalse;
}
return qtrue;
}
/*
=================
MenuParse_popup
=================
*/
qboolean MenuParse_popup( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
menu->window.flags |= WINDOW_POPUP;
return qtrue;
}
/*
=================
MenuParse_outOfBounds
=================
*/
qboolean MenuParse_outOfBounds( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
menu->window.flags |= WINDOW_OOB_CLICK;
return qtrue;
}
/*
=================
MenuParse_soundLoop
=================
*/
qboolean MenuParse_soundLoop( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (!PC_ParseStringMem((const char **) &menu->soundName))
{
return qfalse;
}
return qtrue;
}
/*
================
MenuParse_fadeClamp
================
*/
qboolean MenuParse_fadeClamp( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseFloat(&menu->fadeClamp))
{
return qfalse;
}
return qtrue;
}
/*
================
MenuParse_fadeAmount
================
*/
qboolean MenuParse_fadeAmount( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseFloat(&menu->fadeAmount))
{
return qfalse;
}
return qtrue;
}
/*
================
MenuParse_fadeCycle
================
*/
qboolean MenuParse_fadeCycle( itemDef_t *item)
{
menuDef_t *menu = (menuDef_t*)item;
if (PC_ParseInt(&menu->fadeCycle))
{
return qfalse;
}
return qtrue;
}
/*
===============
Item_ApplyHacks
Hacks to fix issues with Team Arena menu scripts
===============
*/
static void Item_ApplyHacks( itemDef_t *item ) {
#if !defined(_WIN32) || ( defined(_WIN32) && defined(idx64) )
// Fix length of favorite address in createfavorite.menu
if ( item->type == ITEM_TYPE_MULTI && item->cvar && !Q_stricmp( item->cvar, "s_UseOpenAL" ) ) {
if( item->parent )
{
menuDef_t *parent = (menuDef_t *)item->parent;
VectorSet4( parent->disableColor, 0.5f, 0.5f, 0.5f, 1.0f );
item->disabled = qtrue;
// Just in case it had focus
item->window.flags &= ~WINDOW_MOUSEOVER;
Com_Printf( "Disabling eax field because current platform does not support EAX.\n");
}
}
if ( item->type == ITEM_TYPE_TEXT && item->window.name && !Q_stricmp( item->window.name, "eax_icon") && item->cvarTest && !Q_stricmp( item->cvarTest, "s_UseOpenAL" ) && item->enableCvar && (item->cvarFlags & CVAR_HIDE) ) {
if( item->parent )
{
menuDef_t *parent = (menuDef_t *)item->parent;
VectorSet4( parent->disableColor, 0.5f, 0.5f, 0.5f, 1.0f );
item->disabled = item->disabledHidden = qtrue;
// Just in case it had focus
item->window.flags &= ~WINDOW_MOUSEOVER;
Com_Printf( "Hiding eax_icon object because current platform does not support EAX.\n");
}
}
#endif
if ( item->type == ITEM_TYPE_MULTI && item->window.name && !Q_stricmp( item->window.name, "sound_quality") ) {
multiDef_t *multiPtr = (multiDef_t *)item->typeData;
int i;
qboolean found = qfalse;
for( i = 0; i < multiPtr->count; i++ )
{
if ( multiPtr->cvarValue[i] == 44 )
{
found = qtrue;
break;
}
}
if ( !found && multiPtr->count < MAX_MULTI_CVARS )
{
#ifdef JK2_MODE
multiPtr->cvarList[multiPtr->count] = String_Alloc("@MENUS0_VERY_HIGH");
#else
multiPtr->cvarList[multiPtr->count] = String_Alloc("@MENUS_VERY_HIGH");
#endif
multiPtr->cvarValue[multiPtr->count] = 44;
multiPtr->count++;
Com_Printf( "Extended sound quality field to contain very high option.\n");
}
}
if ( item->type == ITEM_TYPE_MULTI && item->window.name && !Q_stricmp( item->window.name, "voice") && item->cvar && !Q_stricmp( item->cvar, "g_subtitles" ) ) {
multiDef_t *multiPtr = (multiDef_t *)item->typeData;
int i;
qboolean found = qfalse;
for( i = 0; i < multiPtr->count; i++ )
{
if ( multiPtr->cvarValue[i] == 1 )
{
found = qtrue;
break;
}
}
if ( !found && multiPtr->count < MAX_MULTI_CVARS )
{
#ifdef JK2_MODE
multiPtr->cvarList[multiPtr->count] = String_Alloc("@MENUS3_ALL_VOICEOVERS");
#else
multiPtr->cvarList[multiPtr->count] = String_Alloc("@MENUS_ALL_VOICEOVERS");
#endif
multiPtr->cvarValue[multiPtr->count] = 1;
multiPtr->count++;
Com_Printf( "Extended subtitles field to contain all voiceovers option.\n");
}
}
#ifdef JK2_MODE
if ( item->type == ITEM_TYPE_MULTI && item->window.name && !Q_stricmp( item->window.name, "video_mode") && item->cvar && !Q_stricmp( item->cvar, "r_ext_texture_filter_anisotropic" ) ) {
{
memset(item->typeData, 0, sizeof(multiDef_t));
}
editFieldDef_t *editPtr = NULL;
item->cvarFlags = CVAR_DISABLE;
item->type = ITEM_TYPE_SLIDER;
Item_ValidateTypeData(item);
editPtr = (editFieldDef_t *)item->typeData;
editPtr->minVal = 0.5f;
editPtr->maxVal = cls.glconfig.maxTextureFilterAnisotropy;
editPtr->defVal = 1.0f;
Com_Printf( "Converted anisotropic filter field to slider.\n");
}
#endif
}
/*
================
MenuParse_itemDef
================
*/
qboolean MenuParse_itemDef( itemDef_t *item )
{
menuDef_t *menu = (menuDef_t*)item;
if (menu->itemCount < MAX_MENUITEMS)
{
itemDef_t *newItem = menu->items[menu->itemCount] = (struct itemDef_s *) UI_Alloc(sizeof(itemDef_t));
Item_Init(newItem);
if (!Item_Parse(newItem))
{
return qfalse;
}
Item_InitControls( newItem );
newItem->parent = menu->items[menu->itemCount]->parent = menu;
menu->itemCount++;
Item_ApplyHacks( newItem );
}
else
{
PC_ParseWarning(va("Exceeded item/menu max of %d", MAX_MENUITEMS));
}
return qtrue;
}
#define KEYWORDHASH_SIZE 512
typedef struct keywordHash_s
{
const char *keyword;
qboolean (*func)(itemDef_t *item);
struct keywordHash_s *next;
} keywordHash_t;
keywordHash_t menuParseKeywords[] = {
{"appearanceIncrement", MenuParse_appearanceIncrement},
{"backcolor", MenuParse_backcolor, },
{"background", MenuParse_background, },
{"border", MenuParse_border, },
{"bordercolor", MenuParse_bordercolor, },
{"borderSize", MenuParse_borderSize, },
{"cinematic", MenuParse_cinematic, },
{"descAlignment", MenuParse_descAlignment },
{"descTextStyle", MenuParse_descTextStyle },
{"desccolor", MenuParse_descColor },
{"descX", MenuParse_descX },
{"descY", MenuParse_descY },
{"descScale", MenuParse_descScale },
{"disablecolor", MenuParse_disablecolor, },
{"fadeClamp", MenuParse_fadeClamp, },
{"fadeCycle", MenuParse_fadeCycle, },
{"fadeAmount", MenuParse_fadeAmount, },
{"focuscolor", MenuParse_focuscolor, },
{"font", MenuParse_font, },
{"forecolor", MenuParse_forecolor, },
{"fullscreen", MenuParse_fullscreen, },
{"itemDef", MenuParse_itemDef, },
{"name", MenuParse_name, },
{"onClose", MenuParse_onClose, },
//JLFACCEPT MPMOVED
{"onAccept", MenuParse_onAccept, },
{"onESC", MenuParse_onESC, },
{"onOpen", MenuParse_onOpen, },
{"outlinecolor", MenuParse_outlinecolor, },
{"outOfBoundsClick", MenuParse_outOfBounds, },
{"ownerdraw", MenuParse_ownerdraw, },
{"ownerdrawFlag", MenuParse_ownerdrawFlag,},
{"popup", MenuParse_popup, },
{"rect", MenuParse_rect, },
{"soundLoop", MenuParse_soundLoop, },
{"style", MenuParse_style, },
{"visible", MenuParse_visible, },
{"ignoreescape", MenuParse_ignoreescape, },
{NULL, NULL, }
};
keywordHash_t *menuParseKeywordHash[KEYWORDHASH_SIZE];
/*
================
KeywordHash_Key
================
*/
int KeywordHash_Key(const char *keyword)
{
int hash, i;
hash = 0;
for (i = 0; keyword[i] != '\0'; i++) {
if (keyword[i] >= 'A' && keyword[i] <= 'Z')
hash += (keyword[i] + ('a' - 'A')) * (119 + i);
else
hash += keyword[i] * (119 + i);
}
hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1);
return hash;
}
/*
================
KeywordHash_Add
================
*/
void KeywordHash_Add(keywordHash_t *table[], keywordHash_t *key)
{
int hash;
hash = KeywordHash_Key(key->keyword);
key->next = table[hash];
table[hash] = key;
}
/*
===============
KeywordHash_Find
===============
*/
keywordHash_t *KeywordHash_Find(keywordHash_t *table[], const char *keyword)
{
keywordHash_t *key;
int hash;
hash = KeywordHash_Key(keyword);
for (key = table[hash]; key; key = key->next)
{
if (!Q_stricmp(key->keyword, keyword))
return key;
}
return NULL;
}
/*
================
hashForString
return a hash value for the string
================
*/
static unsigned hashForString(const char *str)
{
int i;
unsigned hash;
char letter;
hash = 0;
i = 0;
while (str[i] != '\0')
{
letter = tolower((unsigned char)str[i]);
hash += (unsigned)(letter)*(i + 119);
i++;
}
hash &= (HASH_TABLE_SIZE-1);
return hash;
}
/*
=================
String_Alloc
=================
*/
const char *String_Alloc(const char *p)
{
int len;
unsigned hash;
stringDef_t *str, *last;
static const char *staticNULL = "";
if (p == NULL)
{
return NULL;
}
if (*p == 0)
{
return staticNULL;
}
hash = hashForString(p);
str = strHandle[hash];
while (str)
{
if (strcmp(p, str->str) == 0)
{
return str->str;
}
str = str->next;
}
len = strlen(p);
if (len + strPoolIndex + 1 < STRING_POOL_SIZE)
{
int ph = strPoolIndex;
strcpy(&strPool[strPoolIndex], p);
strPoolIndex += len + 1;
str = strHandle[hash];
last = str;
while (last && last->next)
{
last = last->next;
}
str = (stringDef_s *) UI_Alloc( sizeof(stringDef_t));
str->next = NULL;
str->str = &strPool[ph];
if (last)
{
last->next = str;
}
else
{
strHandle[hash] = str;
}
return &strPool[ph];
}
else
{
Com_Printf("WARNING: Ran out of strPool space\n");
}
return NULL;
}
/*
=================
String_Report
=================
*/
void String_Report(void)
{
float f;
Com_Printf("Memory/String Pool Info\n");
Com_Printf("----------------\n");
f = strPoolIndex;
f /= STRING_POOL_SIZE;
f *= 100;
Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
f = allocPoint;
f /= MEM_POOL_SIZE;
f *= 100;
Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
}
/*
=================
String_Init
=================
*/
void String_Init(void)
{
int i;
for (i = 0; i < HASH_TABLE_SIZE; i++)
{
strHandle[i] = 0;
}
strHandleCount = 0;
strPoolIndex = 0;
UI_InitMemory();
Item_SetupKeywordHash();
Menu_SetupKeywordHash();
if (DC && DC->getBindingBuf)
{
Controls_GetConfig();
}
}
//---------------------------------------------------------------------------------------------------------
// Memory
//---------------------------------------------------------------------------------------------------------
/*
===============
UI_Alloc
===============
*/
void *UI_Alloc( int size )
{
char *p;
if ( allocPoint + size > MEM_POOL_SIZE )
{
outOfMemory = qtrue;
if (DC->Print)
{
DC->Print("UI_Alloc: Failure. Out of memory!\n");
}
return NULL;
}
p = &memoryPool[allocPoint];
allocPoint += ( size + 15 ) & ~15;
return p;
}
/*
===============
UI_InitMemory
===============
*/
void UI_InitMemory( void )
{
allocPoint = 0;
outOfMemory = qfalse;
}
/*
===============
Menu_ItemsMatchingGroup
===============
*/
int Menu_ItemsMatchingGroup(menuDef_t *menu, const char *name)
{
int i;
int count = 0;
for (i = 0; i < menu->itemCount; i++)
{
if ((!menu->items[i]->window.name) && (!menu->items[i]->window.group))
{
Com_Printf(S_COLOR_YELLOW"WARNING: item has neither name or group\n");
continue;
}
if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0))
{
count++;
}
}
return count;
}
/*
===============
Menu_GetMatchingItemByNumber
===============
*/
itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name)
{
int i;
int count = 0;
for (i = 0; i < menu->itemCount; i++)
{
if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0))
{
if (count == index)
{
return menu->items[i];
}
count++;
}
}
return NULL;
}
/*
===============
Menu_FadeItemByName
===============
*/
void Menu_FadeItemByName(menuDef_t *menu, const char *p, qboolean fadeOut)
{
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
for (i = 0; i < count; i++)
{
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL)
{
if (fadeOut)
{
item->window.flags |= (WINDOW_FADINGOUT | WINDOW_VISIBLE);
item->window.flags &= ~WINDOW_FADINGIN;
}
else
{
item->window.flags |= (WINDOW_VISIBLE | WINDOW_FADINGIN);
item->window.flags &= ~WINDOW_FADINGOUT;
}
}
}
}
/*
===============
Menu_ShowItemByName
===============
*/
void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow)
{
itemDef_t *item;
int i;
int count;
count = Menu_ItemsMatchingGroup(menu, p);
if (!count)
{
Com_Printf(S_COLOR_YELLOW"WARNING: Menu_ShowItemByName - unable to locate any items named: \"%s\"\n",p);
}
for (i = 0; i < count; i++)
{
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL)
{
if (bShow)
{
item->window.flags |= WINDOW_VISIBLE;
}
else
{
item->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
// stop cinematics playing in the window
if (item->window.cinematic >= 0)
{
DC->stopCinematic(item->window.cinematic);
item->window.cinematic = -1;
}
}
}
}
}
/*
===============
Menu_GetFocused
===============
*/
menuDef_t *Menu_GetFocused(void)
{
int i;
for (i = 0; i < menuCount; i++)
{
if ((Menus[i].window.flags & WINDOW_HASFOCUS) && (Menus[i].window.flags & WINDOW_VISIBLE))
{
return &Menus[i];
}
}
return NULL;
}
/*
===============
Menus_OpenByName
===============
*/
void Menus_OpenByName(const char *p)
{
Menus_ActivateByName(p);
}
/*
===============
Menus_FindByName
===============
*/
menuDef_t *Menus_FindByName(const char *p)
{
int i;
for (i = 0; i < menuCount; i++)
{
if (Q_stricmp(Menus[i].window.name, p) == 0)
{
return &Menus[i];
}
}
return NULL;
}
/*
===============
Menu_RunCloseScript
===============
*/
static void Menu_RunCloseScript(menuDef_t *menu)
{
if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose)
{
itemDef_t item;
item.parent = menu;
Item_RunScript(&item, menu->onClose);
}
}
/*
===============
Item_ActivateByName
===============
*/
void Item_ActivateByName(const char *menuName,const char *itemName)
{
itemDef_t *item;
menuDef_t *menu;
menu = Menus_FindByName(menuName);
item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, itemName);
if (item != NULL)
{
item->window.flags &= ~WINDOW_INACTIVE;
}
}
/*
===============
Menus_CloseByName
===============
*/
void Menus_CloseByName(const char *p)
{
menuDef_t *menu = Menus_FindByName(p);
// If the menu wasnt found just exit
if (menu == NULL)
{
return;
}
// Run the close script for the menu
Menu_RunCloseScript(menu);
// If this window had the focus then take it away
if ( menu->window.flags & WINDOW_HASFOCUS )
{
// If there is something still in the open menu list then
// set it to have focus now
if ( openMenuCount )
{
// Subtract one from the open menu count to prepare to
// remove the top menu from the list
openMenuCount -= 1;
// Set the top menu to have focus now
menuStack[openMenuCount]->window.flags |= WINDOW_HASFOCUS;
// Remove the top menu from the list
menuStack[openMenuCount] = NULL;
}
}
// Window is now invisible and doenst have focus
menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
}
/*
===============
Menu_FindItemByName
===============
*/
itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p)
{
int i;
if (menu == NULL || p == NULL)
{
return NULL;
}
for (i = 0; i < menu->itemCount; i++)
{
if (Q_stricmp(p, menu->items[i]->window.name) == 0)
{
return menu->items[i];
}
}
return NULL;
}
/*
=================
Menu_ClearFocus
=================
*/
itemDef_t *Menu_ClearFocus(menuDef_t *menu)
{
int i;
itemDef_t *ret = NULL;
if (menu == NULL)
{
return NULL;
}
for (i = 0; i < menu->itemCount; i++)
{
if (menu->items[i]->window.flags & WINDOW_HASFOCUS)
{
ret = menu->items[i];
menu->items[i]->window.flags &= ~WINDOW_HASFOCUS;
if (menu->items[i]->leaveFocus)
{
Item_RunScript(menu->items[i], menu->items[i]->leaveFocus);
}
}
}
return ret;
}
// Set all the items within a given menu, with the given itemName, to the given shader
void Menu_SetItemBackground(const menuDef_t *menu,const char *itemName, const char *background)
{
itemDef_t *item;
int j, count;
if (!menu) // No menu???
{
return;
}
count = Menu_ItemsMatchingGroup( (menuDef_t *) menu, itemName);
for (j = 0; j < count; j++)
{
item = Menu_GetMatchingItemByNumber( (menuDef_t *) menu, j, itemName);
if (item != NULL)
{
// item->window.background = DC->registerShaderNoMip(background);
item->window.background = ui.R_RegisterShaderNoMip(background);
}
}
}
// Set all the items within a given menu, with the given itemName, to the given text
void Menu_SetItemText(const menuDef_t *menu,const char *itemName, const char *text)
{
itemDef_t *item;
int j, count;
if (!menu) // No menu???
{
return;
}
count = Menu_ItemsMatchingGroup( (menuDef_t *) menu, itemName);
for (j = 0; j < count; j++)
{
item = Menu_GetMatchingItemByNumber( (menuDef_t *) menu, j, itemName);
if (item != NULL)
{
if (text[0] == '*')
{
item->cvar = text+1;
// Just copying what was in ItemParse_cvar()
if ( item->typeData)
{
editFieldDef_t *editPtr;
editPtr = (editFieldDef_t*)item->typeData;
editPtr->minVal = -1;
editPtr->maxVal = -1;
editPtr->defVal = -1;
}
}
else
{
if (item->type == ITEM_TYPE_TEXTSCROLL )
{
char cvartext[1024];
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
if ( scrollPtr )
{
scrollPtr->startPos = 0;
scrollPtr->endPos = 0;
}
if (item->cvar)
{
DC->getCVarString(item->cvar, cvartext, sizeof(cvartext));
item->text = cvartext;
}
else
{
item->text = (char *) text;
}
Item_TextScroll_BuildLines ( item );
}
else
{
item->text = (char *) text;
}
}
}
}
}
/*
=================
Menu_TransitionItemByName
=================
*/
void Menu_TransitionItemByName(menuDef_t *menu, const char *p, const rectDef_t *rectFrom, const rectDef_t *rectTo, int time, float amt)
{
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
for (i = 0; i < count; i++)
{
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL)
{
if (!rectFrom)
{
rectFrom = &item->window.rect; //if there are more than one of these with the same name, they'll all use the FIRST one's FROM.
}
item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
item->window.offsetTime = time;
memcpy(&item->window.rectClient, rectFrom, sizeof(rectDef_t));
memcpy(&item->window.rectEffects, rectTo, sizeof(rectDef_t));
item->window.rectEffects2.x = abs(rectTo->x - rectFrom->x) / amt;
item->window.rectEffects2.y = abs(rectTo->y - rectFrom->y) / amt;
item->window.rectEffects2.w = abs(rectTo->w - rectFrom->w) / amt;
item->window.rectEffects2.h = abs(rectTo->h - rectFrom->h) / amt;
Item_UpdatePosition(item);
}
}
}
/*
=================
Menu_TransitionItemByName
=================
*/
//JLF MOVED
#define _TRANS3
#ifdef _TRANS3
void Menu_Transition3ItemByName(menuDef_t *menu, const char *p, const float minx, const float miny, const float minz,
const float maxx, const float maxy, const float maxz, const float fovtx, const float fovty,
const int time, const float amt)
{
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
modelDef_t * modelptr;
for (i = 0; i < count; i++)
{
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL)
{
if ( item->type == ITEM_TYPE_MODEL)
{
modelptr = (modelDef_t*)item->typeData;
item->window.flags |= (WINDOW_INTRANSITIONMODEL | WINDOW_VISIBLE);
item->window.offsetTime = time;
modelptr->fov_x2 = fovtx;
modelptr->fov_y2 = fovty;
VectorSet(modelptr->g2maxs2, maxx, maxy, maxz);
VectorSet(modelptr->g2mins2, minx, miny, minz);
// //modelptr->g2maxs2.x= maxx;
// modelptr->g2maxs2.y= maxy;
// modelptr->g2maxs2.z= maxz;
// modelptr->g2mins2.x= minx;
// modelptr->g2mins2.y= miny;
// modelptr->g2mins2.z= minz;
// VectorSet(modelptr->g2maxs2, maxx, maxy, maxz);
modelptr->g2maxsEffect[0] = abs(modelptr->g2maxs2[0] - modelptr->g2maxs[0]) / amt;
modelptr->g2maxsEffect[1] = abs(modelptr->g2maxs2[1] - modelptr->g2maxs[1]) / amt;
modelptr->g2maxsEffect[2] = abs(modelptr->g2maxs2[2] - modelptr->g2maxs[2]) / amt;
modelptr->g2minsEffect[0] = abs(modelptr->g2mins2[0] - modelptr->g2mins[0]) / amt;
modelptr->g2minsEffect[1] = abs(modelptr->g2mins2[1] - modelptr->g2mins[1]) / amt;
modelptr->g2minsEffect[2] = abs(modelptr->g2mins2[2] - modelptr->g2mins[2]) / amt;
modelptr->fov_Effectx = abs(modelptr->fov_x2 - modelptr->fov_x) / amt;
modelptr->fov_Effecty = abs(modelptr->fov_y2 - modelptr->fov_y) / amt;
}
}
}
}
#endif
/*
=================
Menu_OrbitItemByName
=================
*/
void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time)
{
itemDef_t *item;
int i;
int count = Menu_ItemsMatchingGroup(menu, p);
for (i = 0; i < count; i++)
{
item = Menu_GetMatchingItemByNumber(menu, i, p);
if (item != NULL)
{
item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
item->window.offsetTime = time;
item->window.rectEffects.x = cx;
item->window.rectEffects.y = cy;
item->window.rectClient.x = x;
item->window.rectClient.y = y;
Item_UpdatePosition(item);
}
}
}
void Menu_ItemDisable(menuDef_t *menu, const char *name, qboolean disableFlag)
{
int j,count;
itemDef_t *itemFound;
count = Menu_ItemsMatchingGroup(menu, name);
// Loop through all items that have this name
for (j = 0; j < count; j++)
{
itemFound = Menu_GetMatchingItemByNumber( menu, j, name);
if (itemFound != NULL)
{
itemFound->disabled = disableFlag;
// Just in case it had focus
itemFound->window.flags &= ~WINDOW_MOUSEOVER;
}
}
}
/*
=================
Rect_Parse
=================
*/
qboolean Rect_Parse(const char **p, rectDef_t *r)
{
if (!COM_ParseFloat(p, &r->x))
{
if (!COM_ParseFloat(p, &r->y))
{
if (!COM_ParseFloat(p, &r->w))
{
if (!COM_ParseFloat(p, &r->h))
{
return qtrue;
}
}
}
}
return qfalse;
}
qboolean Script_SetItemRect(itemDef_t *item, const char **args)
{
const char *itemname;
rectDef_t *out;
rectDef_t rect;
// expecting type of color to set and 4 args for the color
if (String_Parse(args, &itemname))
{
itemDef_t *item2;
int j;
int count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, itemname);
if (!Rect_Parse(args, &rect))
{
return qtrue;
}
for (j = 0; j < count; j++)
{
item2 = Menu_GetMatchingItemByNumber((menuDef_t *) item->parent, j, itemname);
if (item2 != NULL)
{
out = &item2->window.rect;
if (out)
{
item2->window.rect.x = rect.x;
item2->window.rect.y = rect.y;
item2->window.rect.w = rect.w;
item2->window.rect.h = rect.h;
}
}
}
}
return qtrue;
}
/*
=================
Script_SetItemBackground
=================
*/
qboolean Script_SetItemBackground(itemDef_t *item, const char **args)
{
const char *itemName;
const char *name;
// expecting name of shader
if (String_Parse(args, &itemName) && String_Parse(args, &name))
{
Menu_SetItemBackground((menuDef_t *) item->parent, itemName, name);
}
return qtrue;
}
/*
=================
Script_SetItemText
=================
*/
qboolean Script_SetItemText(itemDef_t *item, const char **args)
{
const char *itemName;
const char *text;
// expecting text
if (String_Parse(args, &itemName) && String_Parse(args, &text))
{
Menu_SetItemText((menuDef_t *) item->parent, itemName, text);
}
return qtrue;
}
/*
=================
Script_FadeIn
=================
*/
qboolean Script_FadeIn(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menu_FadeItemByName((menuDef_t *) item->parent, name, qfalse);
}
return qtrue;
}
/*
=================
Script_FadeOut
=================
*/
qboolean Script_FadeOut(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menu_FadeItemByName((menuDef_t *) item->parent, name, qtrue);
}
return qtrue;
}
/*
=================
Script_Show
=================
*/
qboolean Script_Show(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menu_ShowItemByName((menuDef_t *) item->parent, name, qtrue);
}
return qtrue;
}
/*
=================
Script_ShowMenu
=================
*/
qboolean Script_ShowMenu(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menus_ShowItems(name);
}
return qtrue;
}
/*
=================
Script_Hide
=================
*/
qboolean Script_Hide(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menu_ShowItemByName((menuDef_t *) item->parent, name, qfalse);
}
return qtrue;
}
/*
=================
Script_SetColor
=================
*/
qboolean Script_SetColor(itemDef_t *item, const char **args)
{
const char *name;
int i;
float f;
vec4_t *out;
// expecting type of color to set and 4 args for the color
if (String_Parse(args, &name))
{
out = NULL;
if (Q_stricmp(name, "backcolor") == 0)
{
out = &item->window.backColor;
item->window.flags |= WINDOW_BACKCOLORSET;
}
else if (Q_stricmp(name, "forecolor") == 0)
{
out = &item->window.foreColor;
item->window.flags |= WINDOW_FORECOLORSET;
}
else if (Q_stricmp(name, "bordercolor") == 0)
{
out = &item->window.borderColor;
}
if (out)
{
for (i = 0; i < 4; i++)
{
// if (!Float_Parse(args, &f))
if (COM_ParseFloat( args, &f))
{
return qtrue;
}
(*out)[i] = f;
}
}
}
return qtrue;
}
/*
=================
Script_Open
=================
*/
qboolean Script_Open(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
Menus_OpenByName(name);
}
return qtrue;
}
qboolean Script_OpenGoToMenu(itemDef_t *item, const char **args)
{
Menus_OpenByName(GoToMenu); // Give warning
return qtrue;
}
/*
=================
Script_Close
=================
*/
qboolean Script_Close(itemDef_t *item, const char **args)
{
const char *name;
if (String_Parse(args, &name))
{
if (Q_stricmp(name, "all") == 0)
{
Menus_CloseAll();
}
else
{
Menus_CloseByName(name);
}
}
return qtrue;
}
/*
=================
Script_Activate
=================
*/
qboolean Script_Activate(itemDef_t *item, const char **args)
{
const char *name, *menu;
if (String_Parse(args, &menu))
{
if (String_Parse(args, &name))
{
Item_ActivateByName(menu,name);
}
}
return qtrue;
}
/*
=================
Script_SetBackground
=================
*/
qboolean Script_SetBackground(itemDef_t *item, const char **args)
{
const char *name;
// expecting name to set asset to
if (String_Parse(args, &name))
{
item->window.background = DC->registerShaderNoMip(name);
}
return qtrue;
}
/*
=================
Script_SetAsset
=================
*/
qboolean Script_SetAsset(itemDef_t *item, const char **args)
{
const char *name;
// expecting name to set asset to
if (String_Parse(args, &name))
{
// check for a model
if (item->type == ITEM_TYPE_MODEL)
{
}
}
return qtrue;
}
/*
=================
Script_SetFocus
=================
*/
qboolean Script_SetFocus(itemDef_t *item, const char **args)
{
const char *name;
itemDef_t *focusItem;
if (String_Parse(args, &name))
{
focusItem = (itemDef_s *) Menu_FindItemByName((menuDef_t *) item->parent, name);
if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS))
{
Menu_ClearFocus((menuDef_t *) item->parent);
//JLF
focusItem->window.flags |= WINDOW_HASFOCUS;
//END JLF
if (focusItem->onFocus)
{
Item_RunScript(focusItem, focusItem->onFocus);
}
if (DC->Assets.itemFocusSound)
{
DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
}
}
}
return qtrue;
}
/*
=================
Script_SetItemFlag
=================
*/
qboolean Script_SetItemFlag(itemDef_t *item, const char **args)
{
const char *itemName,*number;
if (String_Parse(args, &itemName))
{
item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) item->parent, itemName);
if (String_Parse(args, &number))
{
int amount = atoi(number);
item->window.flags |= amount;
}
}
return qtrue;
}
void UI_SetItemVisible(menuDef_t *menu,const char *itemname,qboolean visible)
{
itemDef_t *item;
int j;
int count = Menu_ItemsMatchingGroup(menu, itemname);
for (j = 0; j < count; j++)
{
item = Menu_GetMatchingItemByNumber(menu, j, itemname);
if (item != NULL)
{
if (visible==qtrue)
{
item->window.flags |= WINDOW_VISIBLE;
}
else
{
item->window.flags &= ~WINDOW_VISIBLE;
}
}
}
}
void UI_SetItemColor(itemDef_t *item,const char *itemname,const char *name,vec4_t color)
{
itemDef_t *item2;
int i,j;
vec4_t *out;
int count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, itemname);
for (j = 0; j < count; j++)
{
item2 = Menu_GetMatchingItemByNumber((menuDef_t *) item->parent, j, itemname);
if (item2 != NULL)
{
out = NULL;
if (Q_stricmp(name, "backcolor") == 0)
{
out = &item2->window.backColor;
}
else if (Q_stricmp(name, "forecolor") == 0)
{
out = &item2->window.foreColor;
item2->window.flags |= WINDOW_FORECOLORSET;
}
else if (Q_stricmp(name, "bordercolor") == 0)
{
out = &item2->window.borderColor;
}
if (out)
{
for (i = 0; i < 4; i++)
{
(*out)[i] = color[i];
}
}
}
}
}
/*
=================
Script_SetItemColor
=================
*/
qboolean Script_SetItemColor(itemDef_t *item, const char **args)
{
const char *itemname;
const char *name;
vec4_t color;
// expecting type of color to set and 4 args for the color
if (String_Parse(args, &itemname) && String_Parse(args, &name))
{
if (COM_ParseVec4(args, &color))
{
return qtrue;
}
UI_SetItemColor(item,itemname,name,color);
}
return qtrue;
}
/*
=================
Script_Defer
Defers the rest of the script based on the defer condition. The deferred
portion of the script can later be run with the "rundeferred"
=================
*/
qboolean Script_Defer ( itemDef_t* item, const char **args )
{
// Should the script be deferred?
if ( DC->deferScript ( args ) )
{
// Need the item the script was being run on
uiInfo.deferredScriptItem = item;
// Save the rest of the script
Q_strncpyz ( uiInfo.deferredScript, *args, MAX_DEFERRED_SCRIPT );
// No more running
return qfalse;
}
// Keep running the script, its ok
return qtrue;
}
/*
=================
Script_RunDeferred
Runs the last deferred script, there can only be one script deferred at a
time so be careful of recursion
=================
*/
qboolean Script_RunDeferred ( itemDef_t* item, const char **args )
{
// Make sure there is something to run.
if ( !uiInfo.deferredScript[0] || !uiInfo.deferredScriptItem )
{
return qtrue;
}
// Run the deferred script now
Item_RunScript ( uiInfo.deferredScriptItem, uiInfo.deferredScript );
return qtrue;
}
/*
=================
Script_Delay
Delays the rest of the script for the specified amount of time
=================
*/
qboolean Script_Delay ( itemDef_t* item, const char **args )
{
int time;
if (Int_Parse(args, &time))
{
item->window.flags |= WINDOW_SCRIPTWAITING;
item->window.delayTime = DC->realTime + time; // Flag to set delay time on next paint
item->window.delayedScript = (char *)*args; // Copy current location, we'll resume executing here later
}
else
{
Com_Printf(S_COLOR_YELLOW"WARNING: Script_Delay: error parsing\n" );
}
// Stop running
return qfalse;
}
/*
=================
Script_Transition
transition rtvscr 321 0 202 264 415 0 202 264 20 25
=================
*/
qboolean Script_Transition(itemDef_t *item, const char **args)
{
const char *name;
rectDef_t rectFrom, rectTo;
int time;
float amt;
if (String_Parse(args, &name))
{
if ( ParseRect(args, &rectFrom) && ParseRect(args, &rectTo) && Int_Parse(args, &time) && !COM_ParseFloat(args, &amt))
{
Menu_TransitionItemByName((menuDef_t *) item->parent, name, &rectFrom, &rectTo, time, amt);
}
else
{
Com_Printf(S_COLOR_YELLOW"WARNING: Script_Transition: error parsing '%s'\n", name );
}
}
return qtrue;
}
/*
=================
Script_Transition2
uses current origin instead of specifing a starting origin
transition2 lfvscr 25 0 202 264 20 25
=================
*/
qboolean Script_Transition2(itemDef_t *item, const char **args)
{
const char *name;
rectDef_t rectTo;
int time;
float amt;
if (String_Parse(args, &name))
{
if ( ParseRect(args, &rectTo) && Int_Parse(args, &time) && !COM_ParseFloat(args, &amt))
{
Menu_TransitionItemByName((menuDef_t *) item->parent, name, 0, &rectTo, time, amt);
}
else
{
Com_Printf(S_COLOR_YELLOW"WARNING: Script_Transition2: error parsing '%s'\n", name );
}
}
return qtrue;
}
#ifdef _TRANS3
/*
JLF MPMOVED
=================
Script_Transition3
used exclusively with model views
uses current origin instead of specifing a starting origin
transition3 lfvscr (min extent) (max extent) (fovx,y) 20 25
=================
*/
qboolean Script_Transition3(itemDef_t *item, const char **args)
{
const char *name = NULL;
const char *value = NULL;
float minx, miny, minz, maxx, maxy, maxz, fovtx, fovty;
int time;
float amt;
if (String_Parse(args, &name))
{
if (String_Parse( args, &value))
{
minx = atof(value);
if (String_Parse( args, &value))
{
miny = atof(value);
if (String_Parse( args, &value))
{
minz = atof(value);
if (String_Parse( args, &value))
{
maxx = atof(value);
if (String_Parse( args, &value))
{
maxy = atof(value);
if (String_Parse( args, &value))
{
maxz = atof(value);
if (String_Parse( args, &value))
{
fovtx = atof(value);
if (String_Parse( args, &value))
{
fovty = atof(value);
if (String_Parse( args, &value))
{
time = atoi(value);
if (String_Parse( args, &value))
{
amt = atof(value);
//set up the variables
Menu_Transition3ItemByName((menuDef_t *) item->parent,
name,
minx, miny, minz,
maxx, maxy, maxz,
fovtx, fovty,
time, amt);
return qtrue;
}
}
}
}
}
}
}
}
}
}
}
if ( name ) {
Com_Printf( S_COLOR_YELLOW "WARNING: Script_Transition2: error parsing '%s'\n", name );
}
return qtrue;
}
#endif
//only works on some feeders
int GetCurrentFeederIndex(itemDef_t * item)
{
float feederID = item->special;
const char * name;
int i, max;
if (feederID == FEEDER_PLAYER_SPECIES)
{
return uiInfo.playerSpeciesIndex;
}
if (feederID == FEEDER_PLAYER_SKIN_HEAD)
{
name = Cvar_VariableString("ui_char_skin_head");
max = uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadCount;
for ( i = 0; i < max ; i++)
{
if (!Q_stricmp(name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHead[i].name))
{
return i;
}
// Cvar_Set("ui_char_skin_head", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadNames[index]);
}
return -1;
}
else if (feederID == FEEDER_PLAYER_SKIN_TORSO)
{
name = Cvar_VariableString("ui_char_skin_torso");
max = uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorsoCount;
for ( i = 0; i < max ; i++)
{
if (!Q_stricmp(name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorso[i].name))
{
return i;
}
// Cvar_Set("ui_char_skin_head", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadNames[index]);
}
return -1;
}
else if (feederID == FEEDER_PLAYER_SKIN_LEGS)
{
name = Cvar_VariableString("ui_char_skin_legs");
max = uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegCount;
for ( i = 0; i < max ; i++)
{
if (!Q_stricmp(name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLeg[i].name))
{
return i;
}
// Cvar_Set("ui_char_skin_head", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadNames[index]);
}
return -1;
// if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegCount)
// {
// Cvar_Set("ui_char_skin_legs", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegNames[index]);
// }
}
else if (feederID == FEEDER_COLORCHOICES)
{
extern void Item_RunScript(itemDef_t *item, const char *s); //from ui_shared;
int currR, currG, currB, newR, newG, newB;
currR = Cvar_VariableIntegerValue( "ui_char_color_red");
currG = Cvar_VariableIntegerValue( "ui_char_color_green");
currB = Cvar_VariableIntegerValue( "ui_char_color_blue");
max = uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount;
for ( i = 0; i < max ; i++)
{
Item_RunScript(item, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Color[i].actionText);
newR = Cvar_VariableIntegerValue( "ui_char_color_red");
newG = Cvar_VariableIntegerValue( "ui_char_color_green");
newB = Cvar_VariableIntegerValue( "ui_char_color_blue");
if ( currR == newR && currG == newG && currB == newB)
return i;
}
return -1;
//JLF junk copied code
/*
extern void Item_RunScript(itemDef_t *item, const char *s); //from ui_shared;
name = Cvar_VariableString("ui_char_skin_legs");
max = uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount;
for ( i = 0; i < max ; i++)
if (!qstrcmp(name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegNames[i]))
{
return i;
// Cvar_Set("ui_char_skin_head", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadNames[index]);
}
return -1;
if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount)
{
Item_RunScript(item, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorActionText[index]);
}
*/
}
return -1;
}
qboolean Script_IncrementFeeder(itemDef_t * item, const char ** args)
{
int feedercount = uiInfo.uiDC.feederCount(item->special);
int value = GetCurrentFeederIndex(item);
value++;
if ( value >= feedercount)
value = 0;
DC->feederSelection(item->special, value, item);
return qtrue;
}
qboolean Script_DecrementFeeder(itemDef_t * item, const char ** args)
{
int feedercount = uiInfo.uiDC.feederCount(item->special);
int value = GetCurrentFeederIndex(item);
value--;
if ( value < 0)
value = feedercount-1;
DC->feederSelection(item->special, value, item);
return qtrue;
}
/*
=================
Script_SetCvar
=================
*/
qboolean Script_SetCvar(itemDef_t *item, const char **args)
{
const char *cvar, *val;
if (String_Parse(args, &cvar) && String_Parse(args, &val))
{
if(!Q_stricmp(val,"(NULL)"))
{
DC->setCVar(cvar, "");
}
else {
DC->setCVar(cvar, val);
}
}
return qtrue;
}
/*
=================
Script_Exec
=================
*/
qboolean Script_Exec ( itemDef_t *item, const char **args)
{
const char *val;
if (String_Parse(args, &val))
{
DC->executeText(EXEC_APPEND, va("%s ; ", val));
}
return qtrue;
}
/*
=================
Script_Play
=================
*/
static qboolean Script_Play(itemDef_t *item, const char **args)
{
const char *val;
if (String_Parse(args, &val))
{
DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_AUTO );
}
return qtrue;
}
/*
=================
Script_PlayVoice
=================
*/
static qboolean Script_PlayVoice(itemDef_t *item, const char **args)
{
const char *val;
if (String_Parse(args, &val))
{
DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_VOICE );
}
return qtrue;
}
/*
=================
Script_StopVoice
=================
*/
static qboolean Script_StopVoice(itemDef_t *item, const char **args)
{
DC->startLocalSound(uiInfo.uiDC.Assets.nullSound, CHAN_VOICE );
return qtrue;
}
/*
=================
Script_playLooped
=================
*/
/*
qboolean Script_playLooped(itemDef_t *item, const char **args)
{
const char *val;
if (String_Parse(args, &val))
{
// FIXME BOB - is this needed?
DC->stopBackgroundTrack();
DC->startBackgroundTrack(val, val);
}
return qtrue;
}
*/
/*
=================
Script_Orbit
=================
*/
qboolean Script_Orbit(itemDef_t *item, const char **args)
{
const char *name;
float cx, cy, x, y;
int time;
if (String_Parse(args, &name))
{
// if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) )
if ( !COM_ParseFloat(args, &x) && !COM_ParseFloat(args, &y) && !COM_ParseFloat(args, &cx) && !COM_ParseFloat(args, &cy) && Int_Parse(args, &time) )
{
Menu_OrbitItemByName((menuDef_t *) item->parent, name, x, y, cx, cy, time);
}
}
return qtrue;
}
commandDef_t commandList[] =
{
{"activate", &Script_Activate}, // menu
{"close", &Script_Close}, // menu
{"exec", &Script_Exec}, // group/name
{"fadein", &Script_FadeIn}, // group/name
{"fadeout", &Script_FadeOut}, // group/name
{"hide", &Script_Hide}, // group/name
{"open", &Script_Open}, // menu
{"openGoToMenu", &Script_OpenGoToMenu}, //
{"orbit", &Script_Orbit}, // group/name
{"play", &Script_Play}, // group/name
{"playVoice", &Script_PlayVoice}, // group/name
{"stopVoice", &Script_StopVoice}, // group/name
// {"playlooped", &Script_playLooped}, // group/name
{"setasset", &Script_SetAsset}, // works on this
{"setbackground", &Script_SetBackground}, // works on this
{"setcolor", &Script_SetColor}, // works on this
{"setcvar", &Script_SetCvar}, // group/name
{"setfocus", &Script_SetFocus}, // sets this background color to team color
{"setitemcolor", &Script_SetItemColor}, // group/name
{"setitemflag", &Script_SetItemFlag}, // name
{"show", &Script_Show}, // group/name
{"showMenu", &Script_ShowMenu}, // menu
{"transition", &Script_Transition}, // group/name
{"transition2", &Script_Transition2}, // group/name
{"setitembackground", &Script_SetItemBackground}, // group/name
{"setitemtext", &Script_SetItemText}, // group/name
{"setitemrect", &Script_SetItemRect}, // group/name
{"defer", &Script_Defer}, //
{"rundeferred", &Script_RunDeferred}, //
{"delay", &Script_Delay}, // works on this (script)
{"transition3", &Script_Transition3}, // model exclusive transition
{"incrementfeeder", &Script_IncrementFeeder},
{"decrementfeeder", &Script_DecrementFeeder}
};
int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
/*
===============
Item_Init
===============
*/
void Item_Init(itemDef_t *item)
{
memset(item, 0, sizeof(itemDef_t));
item->textscale = 0.55f;
Window_Init(&item->window);
}
/*
===============
Item_Multi_Setting
===============
*/
const char *Item_Multi_Setting(itemDef_t *item)
{
char buff[1024];
float value = 0;
int i;
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
if (multiPtr)
{
if (multiPtr->strDef)
{
if (item->cvar)
{
DC->getCVarString(item->cvar, buff, sizeof(buff));
}
else
{
}
}
else
{
if (item->cvar) // Was a cvar given?
{
value = DC->getCVarValue(item->cvar);
}
else
{
value = item->value;
}
}
for (i = 0; i < multiPtr->count; i++)
{
if (multiPtr->strDef)
{
if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0)
{
return multiPtr->cvarList[i];
}
}
else
{
if (multiPtr->cvarValue[i] == value)
{
return multiPtr->cvarList[i];
}
}
}
}
#ifdef JK2_MODE
return "@MENUS1_CUSTOM";
#else
return "@MENUS_CUSTOM";
#endif
}
//---------------------------------------------------------------------------------------------------------
// Item Keyword Parse functions
//---------------------------------------------------------------------------------------------------------
/*
===============
ItemParse_name
name <string>
===============
*/
qboolean ItemParse_name( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **)&item->window.name))
{
return qfalse;
}
return qtrue;
}
qboolean ItemParse_font( itemDef_t *item )
{
if (PC_ParseInt(&item->font))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_focusSound
name <string>
===============
*/
qboolean ItemParse_focusSound( itemDef_t *item)
{
const char *temp;
if (PC_ParseString(&temp))
{
return qfalse;
}
item->focusSound = DC->registerSound(temp, qfalse);
return qtrue;
}
/*
===============
ItemParse_text
text <string>
===============
*/
qboolean ItemParse_text( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **) &item->text))
{
return qfalse;
}
//#ifdef _DEBUG
// UI_Debug_EnterReference("TEXT", item->text);
//#endif
return qtrue;
}
/*
===============
ItemParse_descText
text <string>
===============
*/
qboolean ItemParse_descText( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **) &item->descText))
{
return qfalse;
}
//#ifdef _DEBUG
// UI_Debug_EnterReference("DESC", item->descText);
//#endif
return qtrue;
}
/*
===============
ItemParse_text
text <string>
===============
*/
qboolean ItemParse_text2( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **) &item->text2))
{
return qfalse;
}
//#ifdef _DEBUG
// UI_Debug_EnterReference("TXT2", item->text2);
//#endif
return qtrue;
}
/*
===============
ItemParse_group
group <string>
===============
*/
qboolean ItemParse_group( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **)&item->window.group))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_asset_model
asset_model <string>
===============
*/
qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name )
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (!Q_stricmp(&name[strlen(name) - 4], ".glm"))
{ //it's a ghoul2 model then
if ( item->ghoul2.size() && item->ghoul2[0].mModelindex >= 0)
{
DC->g2_RemoveGhoul2Model( item->ghoul2, 0 );
item->flags &= ~ITF_G2VALID;
}
int g2Model = DC->g2_InitGhoul2Model(item->ghoul2, name, 0, 0, 0, 0, 0);
if (g2Model >= 0)
{
item->flags |= ITF_G2VALID;
if (modelPtr->g2anim)
{ //does the menu request this model be playing an animation?
DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qfalse);
}
if ( modelPtr->g2skin )
{
DC->g2_SetSkin( &item->ghoul2[0], 0, modelPtr->g2skin );//this is going to set the surfs on/off matching the skin file
}
}
}
else if(!(item->asset))
{ //guess it's just an md3
item->asset = DC->registerModel(name);
item->flags &= ~ITF_G2VALID;
}
return qtrue;
}
qboolean ItemParse_asset_model( itemDef_t *item )
{
const char *temp;
Item_ValidateTypeData(item);
if (PC_ParseString(&temp))
{
return qfalse;
}
char modelPath[MAX_QPATH];
if (!Q_stricmp(temp,"ui_char_model") )
{
Com_sprintf( modelPath, sizeof( modelPath ), "models/players/%s/model.glm", Cvar_VariableString ( "g_char_model" ) );
}
else
{
Com_sprintf( modelPath, sizeof( modelPath ), temp);
}
return (ItemParse_asset_model_go( item, modelPath ));
}
/*
===============
ItemParse_asset_model
asset_shader <string>
===============
*/
qboolean ItemParse_asset_shader( itemDef_t *item)
{
const char *temp;
if (PC_ParseString(&temp))
{
return qfalse;
}
item->asset = DC->registerShaderNoMip(temp);
return qtrue;
}
/*
===============
ItemParse_asset_model
model_origin <number> <number> <number>
===============
*/
qboolean ItemParse_model_origin( itemDef_t *item)
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (PC_ParseFloat(&modelPtr->origin[0]))
{
if (PC_ParseFloat(&modelPtr->origin[1]))
{
if (PC_ParseFloat(&modelPtr->origin[2]))
{
return qtrue;
}
}
}
return qfalse;
}
/*
===============
ItemParse_model_fovx
model_fovx <number>
===============
*/
qboolean ItemParse_model_fovx( itemDef_t *item)
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (PC_ParseFloat(&modelPtr->fov_x))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_model_fovy
model_fovy <number>
===============
*/
qboolean ItemParse_model_fovy( itemDef_t *item)
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (PC_ParseFloat(&modelPtr->fov_y))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_model_rotation
model_rotation <integer>
===============
*/
qboolean ItemParse_model_rotation( itemDef_t *item)
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (PC_ParseInt(&modelPtr->rotationSpeed))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_model_angle
model_angle <integer>
===============
*/
qboolean ItemParse_model_angle( itemDef_t *item)
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (PC_ParseInt(&modelPtr->angle))
{
return qfalse;
}
return qtrue;
}
// model_g2mins <number> <number> <number>
qboolean ItemParse_model_g2mins( itemDef_t *item ) {
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (!PC_ParseFloat(&modelPtr->g2mins[0])) {
if (!PC_ParseFloat(&modelPtr->g2mins[1])) {
if (!PC_ParseFloat(&modelPtr->g2mins[2])) {
return qtrue;
}
}
}
return qfalse;
}
// model_g2maxs <number> <number> <number>
qboolean ItemParse_model_g2maxs( itemDef_t *item ) {
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (!PC_ParseFloat(&modelPtr->g2maxs[0])) {
if (!PC_ParseFloat(&modelPtr->g2maxs[1])) {
if (!PC_ParseFloat(&modelPtr->g2maxs[2])) {
return qtrue;
}
}
}
return qfalse;
}
// model_g2skin <string>
qboolean ItemParse_model_g2skin_go( itemDef_t *item, const char *skinName )
{
modelDef_t *modelPtr;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (!skinName || !skinName[0])
{ //it was parsed cor~rectly so still return true.
modelPtr->g2skin = 0;
DC->g2_SetSkin( &item->ghoul2[0], -1, 0 );//turn off custom skin
return qtrue;
}
modelPtr->g2skin = DC->registerSkin(skinName);
if ( item->ghoul2.IsValid() )
{
DC->g2_SetSkin( &item->ghoul2[0], 0, modelPtr->g2skin );//this is going to set the surfs on/off matching the skin file
}
return qtrue;
}
qboolean ItemParse_model_g2skin( itemDef_t *item )
{
const char *skinName;
if (PC_ParseString(&skinName)) {
return qfalse;
}
return (ItemParse_model_g2skin_go( item, skinName ));
}
// model_g2anim <number>
qboolean ItemParse_model_g2anim_go( itemDef_t *item, const char *animName )
{
modelDef_t *modelPtr;
int i = 0;
Item_ValidateTypeData(item);
modelPtr = (modelDef_t*)item->typeData;
if (!animName || !animName[0])
{ //it was parsed correctly so still return true.
return qtrue;
}
while (i < MAX_ANIMATIONS)
{
if (!Q_stricmp(animName, animTable[i].name))
{ //found it
modelPtr->g2anim = animTable[i].id;
return qtrue;
}
i++;
}
Com_Printf("Could not find '%s' in the anim table\n", animName);
return qtrue;
}
qboolean ItemParse_model_g2anim( itemDef_t *item ) {
const char *animName;
if (PC_ParseString(&animName)) {
return qfalse;
}
return ItemParse_model_g2anim_go( item, animName );
}
/*
===============
ItemParse_rect
rect <rectangle>
===============
*/
qboolean ItemParse_rect( itemDef_t *item)
{
if (!PC_ParseRect(&item->window.rectClient))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_flag
flag <integer>
===============
*/
qboolean ItemParse_flag( itemDef_t *item)
{
int i;
const char *tempStr;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (itemFlags[i].string)
{
if (Q_stricmp(tempStr,itemFlags[i].string)==0)
{
item->window.flags |= itemFlags[i].value;
break;
}
i++;
}
if (itemFlags[i].string == NULL)
{
PC_ParseWarning(va("Unknown item flag value '%s'",tempStr));
}
return qtrue;
}
/*
===============
ItemParse_style
style <integer>
===============
*/
qboolean ItemParse_style( itemDef_t *item)
{
int i;
const char *tempStr;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (styles[i])
{
if (Q_stricmp(tempStr,styles[i])==0)
{
item->window.style = i;
break;
}
i++;
}
if (styles[i] == NULL)
{
PC_ParseWarning(va("Unknown item style value '%s'",tempStr));
}
return qtrue;
}
/*
===============
ItemParse_decoration
decoration
===============
*/
qboolean ItemParse_decoration( itemDef_t *item )
{
item->window.flags |= WINDOW_DECORATION;
return qtrue;
}
/*
===============
ItemParse_notselectable
notselectable
===============
*/
qboolean ItemParse_notselectable( itemDef_t *item )
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
listPtr = (listBoxDef_t*)item->typeData;
if (item->type == ITEM_TYPE_LISTBOX && listPtr)
{
listPtr->notselectable = qtrue;
}
return qtrue;
}
/*
===============
ItemParse_scrollhidden
scrollhidden
===============
*/
qboolean ItemParse_scrollhidden( itemDef_t *item )
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
listPtr = (listBoxDef_t*)item->typeData;
if (item->type == ITEM_TYPE_LISTBOX && listPtr)
{
listPtr->scrollhidden = qtrue;
}
return qtrue;
}
/*
===============
ItemParse_wrapped
manually wrapped
===============
*/
qboolean ItemParse_wrapped( itemDef_t *item )
{
item->window.flags |= WINDOW_WRAPPED;
return qtrue;
}
/*
===============
ItemParse_autowrapped
auto wrapped
===============
*/
qboolean ItemParse_autowrapped( itemDef_t *item)
{
item->window.flags |= WINDOW_AUTOWRAPPED;
return qtrue;
}
/*
===============
ItemParse_horizontalscroll
horizontalscroll
===============
*/
qboolean ItemParse_horizontalscroll( itemDef_t *item )
{
item->window.flags |= WINDOW_HORIZONTAL;
return qtrue;
}
/*
===============
ItemParse_type
type <integer>
===============
*/
qboolean ItemParse_type( itemDef_t *item )
{
int i;
const char *tempStr;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (types[i])
{
if (Q_stricmp(tempStr,types[i])==0)
{
item->type = i;
break;
}
i++;
}
if (types[i] == NULL)
{
PC_ParseWarning(va("Unknown item type value '%s'",tempStr));
}
else
{
Item_ValidateTypeData(item);
}
return qtrue;
}
/*
===============
ItemParse_elementwidth
elementwidth, used for listbox image elements
uses textalignx for storage
===============
*/
qboolean ItemParse_elementwidth( itemDef_t *item )
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
listPtr = (listBoxDef_t*)item->typeData;
if (PC_ParseFloat(&listPtr->elementWidth))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_elementheight
elementheight, used for listbox image elements
uses textaligny for storage
===============
*/
qboolean ItemParse_elementheight( itemDef_t *item )
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
listPtr = (listBoxDef_t*)item->typeData;
if (PC_ParseFloat(&listPtr->elementHeight))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_feeder
feeder <float>
===============
*/
qboolean ItemParse_feeder( itemDef_t *item )
{
if (PC_ParseFloat( &item->special))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_elementtype
elementtype, used to specify what type of elements a listbox contains
uses textstyle for storage
===============
*/
qboolean ItemParse_elementtype( itemDef_t *item )
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
listPtr = (listBoxDef_t*)item->typeData;
if (PC_ParseInt(&listPtr->elementStyle))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_columns
columns sets a number of columns and an x pos and width per..
===============
*/
qboolean ItemParse_columns( itemDef_t *item)
{
int num, i;
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
listPtr = (listBoxDef_t*)item->typeData;
if (!PC_ParseInt(&num))
{
if (num > MAX_LB_COLUMNS)
{
num = MAX_LB_COLUMNS;
}
listPtr->numColumns = num;
for (i = 0; i < num; i++)
{
int pos, width, maxChars;
if (!PC_ParseInt(&pos) && !PC_ParseInt(&width) && !PC_ParseInt(&maxChars))
{
listPtr->columnInfo[i].pos = pos;
listPtr->columnInfo[i].width = width;
listPtr->columnInfo[i].maxChars = maxChars;
}
else
{
return qfalse;
}
}
}
else
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_border
===============
*/
qboolean ItemParse_border( itemDef_t *item)
{
if (PC_ParseInt(&item->window.border))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_bordersize
===============
*/
qboolean ItemParse_bordersize( itemDef_t *item )
{
if (PC_ParseFloat(&item->window.borderSize))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_visible
===============
*/
qboolean ItemParse_visible( itemDef_t *item)
{
int i;
if (PC_ParseInt(&i))
{
return qfalse;
}
if (i)
{
item->window.flags |= WINDOW_VISIBLE;
}
return qtrue;
}
/*
===============
ItemParse_ownerdraw
===============
*/
qboolean ItemParse_ownerdraw( itemDef_t *item)
{
if (PC_ParseInt(&item->window.ownerDraw))
{
return qfalse;
}
item->type = ITEM_TYPE_OWNERDRAW;
return qtrue;
}
/*
===============
ItemParse_align
===============
*/
qboolean ItemParse_align( itemDef_t *item)
{
if (PC_ParseInt(&item->alignment))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_align
===============
*/
qboolean ItemParse_Appearance_slot( itemDef_t *item)
{
if (PC_ParseInt(&item->appearanceSlot))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_textalign
===============
*/
qboolean ItemParse_textalign( itemDef_t *item )
{
const char *tempStr;
int i;
if (PC_ParseString(&tempStr))
{
return qfalse;
}
i=0;
while (alignment[i])
{
if (Q_stricmp(tempStr,alignment[i])==0)
{
item->textalignment = i;
break;
}
i++;
}
if (alignment[i] == NULL)
{
PC_ParseWarning(va("Unknown text alignment value '%s'",tempStr));
}
return qtrue;
}
/*
===============
ItemParse_text2alignx
===============
*/
qboolean ItemParse_text2alignx( itemDef_t *item)
{
if (PC_ParseFloat(&item->text2alignx))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_text2aligny
===============
*/
qboolean ItemParse_text2aligny( itemDef_t *item)
{
if (PC_ParseFloat(&item->text2aligny))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_textalignx
===============
*/
qboolean ItemParse_textalignx( itemDef_t *item)
{
if (PC_ParseFloat(&item->textalignx))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_textaligny
===============
*/
qboolean ItemParse_textaligny( itemDef_t *item)
{
if (PC_ParseFloat(&item->textaligny))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_textscale
===============
*/
qboolean ItemParse_textscale( itemDef_t *item )
{
if (PC_ParseFloat(&item->textscale))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_textstyle
===============
*/
qboolean ItemParse_textstyle( itemDef_t *item)
{
if (PC_ParseInt(&item->textStyle))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_invertyesno
===============
*/
qboolean ItemParse_invertyesno( itemDef_t *item)
{
if (PC_ParseInt(&item->invertYesNo))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_xoffset (used for yes/no and multi)
===============
*/
qboolean ItemParse_xoffset( itemDef_t *item)
{
if (PC_ParseInt(&item->xoffset))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_backcolor
===============
*/
qboolean ItemParse_backcolor( itemDef_t *item)
{
int i;
float f;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
item->window.backColor[i] = f;
}
return qtrue;
}
/*
===============
ItemParse_forecolor
===============
*/
qboolean ItemParse_forecolor( itemDef_t *item)
{
int i;
float f;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
if (f < 0)
{ //special case for player color
item->window.flags |= WINDOW_PLAYERCOLOR;
return qtrue;
}
item->window.foreColor[i] = f;
item->window.flags |= WINDOW_FORECOLORSET;
}
return qtrue;
}
/*
===============
ItemParse_bordercolor
===============
*/
qboolean ItemParse_bordercolor( itemDef_t *item)
{
int i;
float f;
for (i = 0; i < 4; i++)
{
if (PC_ParseFloat(&f))
{
return qfalse;
}
item->window.borderColor[i] = f;
}
return qtrue;
}
/*
===============
ItemParse_outlinecolor
===============
*/
qboolean ItemParse_outlinecolor( itemDef_t *item)
{
if (PC_ParseColor(&item->window.outlineColor))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_background
===============
*/
qboolean ItemParse_background( itemDef_t *item)
{
const char *temp;
if (PC_ParseString(&temp))
{
return qfalse;
}
item->window.background = ui.R_RegisterShaderNoMip(temp);
return qtrue;
}
/*
===============
ItemParse_cinematic
===============
*/
qboolean ItemParse_cinematic( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **) &item->window.cinematicName))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_doubleClick
===============
*/
qboolean ItemParse_doubleClick( itemDef_t *item)
{
listBoxDef_t *listPtr;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
listPtr = (listBoxDef_t*)item->typeData;
if (!PC_Script_Parse(&listPtr->doubleClick))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_onFocus
===============
*/
qboolean ItemParse_onFocus( itemDef_t *item)
{
if (!PC_Script_Parse(&item->onFocus))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_leaveFocus
===============
*/
qboolean ItemParse_leaveFocus( itemDef_t *item )
{
if (!PC_Script_Parse(&item->leaveFocus))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_mouseEnter
===============
*/
qboolean ItemParse_mouseEnter( itemDef_t *item)
{
if (!PC_Script_Parse(&item->mouseEnter))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_mouseExit
===============
*/
qboolean ItemParse_mouseExit( itemDef_t *item)
{
if (!PC_Script_Parse(&item->mouseExit))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_mouseEnterText
===============
*/
qboolean ItemParse_mouseEnterText( itemDef_t *item)
{
if (!PC_Script_Parse(&item->mouseEnterText))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_mouseExitText
===============
*/
qboolean ItemParse_mouseExitText( itemDef_t *item)
{
if (!PC_Script_Parse(&item->mouseExitText))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_accept
===============
*/
qboolean ItemParse_accept( itemDef_t *item)
{
if (!PC_Script_Parse(&item->accept))
{
return qfalse;
}
return qtrue;
}
//JLFDPADSCRIPT
/*
===============
ItemParse_selectionNext
===============
*/
qboolean ItemParse_selectionNext( itemDef_t *item)
{
if (!PC_Script_Parse(&item->selectionNext))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_selectionPrev
===============
*/
qboolean ItemParse_selectionPrev( itemDef_t *item)
{
if (!PC_Script_Parse(&item->selectionPrev))
{
return qfalse;
}
return qtrue;
}
// END JLFDPADSCRIPT
/*
===============
ItemParse_action
===============
*/
qboolean ItemParse_action( itemDef_t *item)
{
if (!PC_Script_Parse(&item->action))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_special
===============
*/
qboolean ItemParse_special( itemDef_t *item)
{
if (PC_ParseFloat(&item->special))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_cvarTest
===============
*/
qboolean ItemParse_cvarTest( itemDef_t *item)
{
if (!PC_ParseStringMem((const char **) &item->cvarTest))
{
return qfalse;
}
return qtrue;
}
/*
===============
ItemParse_cvar
===============
*/
qboolean ItemParse_cvar( itemDef_t *item)
{
editFieldDef_t *editPtr;
Item_ValidateTypeData(item);
if (!PC_ParseStringMem(&item->cvar))
{
return qfalse;
}
if ( item->typeData)
{
switch ( item->type )
{
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
case ITEM_TYPE_YESNO:
case ITEM_TYPE_BIND:
case ITEM_TYPE_SLIDER:
case ITEM_TYPE_TEXT:
case ITEM_TYPE_TEXTSCROLL:
editPtr = (editFieldDef_t*)item->typeData;
editPtr->minVal = -1;
editPtr->maxVal = -1;
editPtr->defVal = -1;
break;
}
}
return qtrue;
}
/*
===============
ItemParse_maxChars
===============
*/
qboolean ItemParse_maxChars( itemDef_t *item)
{
editFieldDef_t *editPtr;
int maxChars;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
if (PC_ParseInt(&maxChars))
{
return qfalse;
}
editPtr = (editFieldDef_t*)item->typeData;
editPtr->maxChars = maxChars;
return qtrue;
}
/*
===============
ItemParse_maxPaintChars
===============
*/
qboolean ItemParse_maxPaintChars( itemDef_t *item)
{
editFieldDef_t *editPtr;
int maxChars;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
if (PC_ParseInt(&maxChars))
{
return qfalse;
}
editPtr = (editFieldDef_t*)item->typeData;
editPtr->maxPaintChars = maxChars;
return qtrue;
}
qboolean ItemParse_lineHeight( itemDef_t *item)
{
textScrollDef_t *scrollPtr;
int height;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
if (PC_ParseInt(&height))
{
return qfalse;
}
scrollPtr = (textScrollDef_t*)item->typeData;
scrollPtr->lineHeight = height;
return qtrue;
}
/*
===============
ItemParse_cvarFloat
===============
*/
qboolean ItemParse_cvarFloat( itemDef_t *item)
{
editFieldDef_t *editPtr;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
editPtr = (editFieldDef_t*)item->typeData;
if (PC_ParseStringMem((const char **) &item->cvar) &&
!PC_ParseFloat(&editPtr->defVal) &&
!PC_ParseFloat(&editPtr->minVal) &&
!PC_ParseFloat(&editPtr->maxVal))
{
if (!Q_stricmp(item->cvar,"r_ext_texture_filter_anisotropic"))
{//hehe, hook up the correct max value here.
editPtr->maxVal=cls.glconfig.maxTextureFilterAnisotropy;
}
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_cvarStrList
===============
*/
qboolean ItemParse_cvarStrList( itemDef_t *item)
{
const char *token;
multiDef_t *multiPtr;
int pass;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
multiPtr = (multiDef_t*)item->typeData;
multiPtr->count = 0;
multiPtr->strDef = qtrue;
if (PC_ParseString(&token))
{
return qfalse;
}
if (!Q_stricmp(token,"feeder") && item->special == FEEDER_PLAYER_SPECIES)
{
for (; multiPtr->count < uiInfo.playerSpeciesCount; multiPtr->count++)
{
multiPtr->cvarList[multiPtr->count] = String_Alloc(Q_strupr(va("@MENUS_%s",uiInfo.playerSpecies[multiPtr->count].Name ))); //look up translation
multiPtr->cvarStr[multiPtr->count] = uiInfo.playerSpecies[multiPtr->count].Name; //value
}
return qtrue;
}
// languages
if (!Q_stricmp(token,"feeder") && item->special == FEEDER_LANGUAGES)
{
for (; multiPtr->count < uiInfo.languageCount; multiPtr->count++)
{
// The displayed text
multiPtr->cvarList[multiPtr->count] = "@MENUS_MYLANGUAGE";
// The cvar value that goes into se_language
#ifndef JK2_MODE // FIXME
multiPtr->cvarStr[multiPtr->count] = SE_GetLanguageName(multiPtr->count);
#endif
}
return qtrue;
}
if (*token != '{')
{
return qfalse;
}
pass = 0;
while ( 1 )
{
if (!PC_ParseStringMem(&token))
{
PC_ParseWarning("end of file inside menu item\n");
return qfalse;
}
if (*token == '}')
{
return qtrue;
}
if (*token == ',' || *token == ';')
{
continue;
}
if (pass == 0)
{
multiPtr->cvarList[multiPtr->count] = token;
pass = 1;
}
else
{
multiPtr->cvarStr[multiPtr->count] = token;
pass = 0;
multiPtr->count++;
if (multiPtr->count >= MAX_MULTI_CVARS)
{
return qfalse;
}
}
}
return qfalse;
}
/*
===============
ItemParse_cvarFloatList
===============
*/
qboolean ItemParse_cvarFloatList( itemDef_t *item)
{
const char *token;
multiDef_t *multiPtr;
Item_ValidateTypeData(item);
if (!item->typeData)
{
return qfalse;
}
multiPtr = (multiDef_t*)item->typeData;
multiPtr->count = 0;
multiPtr->strDef = qfalse;
if (PC_ParseString(&token))
{
return qfalse;
}
if (*token != '{')
{
return qfalse;
}
while ( 1 )
{
if (!PC_ParseStringMem(&token))
{
PC_ParseWarning("end of file inside menu item\n");
return qfalse;
}
if (*token == '}')
{
return qtrue;
}
if (*token == ',' || *token == ';')
{
continue;
}
multiPtr->cvarList[multiPtr->count] = token; //a StringAlloc ptr
if (PC_ParseFloat(&multiPtr->cvarValue[multiPtr->count]))
{
return qfalse;
}
multiPtr->count++;
if (multiPtr->count >= MAX_MULTI_CVARS)
{
return qfalse;
}
}
return qfalse;
}
/*
===============
ItemParse_addColorRange
===============
*/
qboolean ItemParse_addColorRange( itemDef_t *item)
{
colorRangeDef_t color;
if (PC_ParseFloat(&color.low) &&
PC_ParseFloat(&color.high) &&
PC_ParseColor(&color.color) )
{
if (item->numColors < MAX_COLOR_RANGES)
{
memcpy(&item->colorRanges[item->numColors], &color, sizeof(color));
item->numColors++;
}
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_ownerdrawFlag
===============
*/
qboolean ItemParse_ownerdrawFlag( itemDef_t *item )
{
int i;
if (PC_ParseInt(&i))
{
return qfalse;
}
item->window.ownerDrawFlags |= i;
return qtrue;
}
/*
===============
ItemParse_enableCvar
===============
*/
qboolean ItemParse_enableCvar( itemDef_t *item)
{
if (PC_Script_Parse(&item->enableCvar))
{
item->cvarFlags = CVAR_ENABLE;
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_disableCvar
===============
*/
qboolean ItemParse_disableCvar( itemDef_t *item )
{
if (PC_Script_Parse(&item->enableCvar))
{
item->cvarFlags = CVAR_DISABLE;
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_showCvar
===============
*/
qboolean ItemParse_showCvar( itemDef_t *item )
{
if (PC_Script_Parse(&item->enableCvar))
{
item->cvarFlags = CVAR_SHOW;
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_hideCvar
===============
*/
qboolean ItemParse_hideCvar( itemDef_t *item )
{
if (PC_Script_Parse(&item->enableCvar))
{
item->cvarFlags = CVAR_HIDE;
return qtrue;
}
return qfalse;
}
/*
===============
ItemParse_cvarsubstring
===============
*/
qboolean ItemParse_cvarsubstring( itemDef_t *item )
{
assert(item->cvarFlags); //need something set first, then we or in our flag.
item->cvarFlags |= CVAR_SUBSTRING;
return qtrue;
}
/*
===============
Item_ValidateTypeData
===============
*/
void Item_ValidateTypeData(itemDef_t *item)
{
if (item->typeData)
{
return;
}
if (item->type == ITEM_TYPE_LISTBOX)
{
item->typeData = UI_Alloc(sizeof(listBoxDef_t));
memset(item->typeData, 0, sizeof(listBoxDef_t));
}
else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_BIND || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_TEXT)
{
item->typeData = UI_Alloc(sizeof(editFieldDef_t));
memset(item->typeData, 0, sizeof(editFieldDef_t));
if (item->type == ITEM_TYPE_EDITFIELD)
{
if (!((editFieldDef_t *) item->typeData)->maxPaintChars)
{
((editFieldDef_t *) item->typeData)->maxPaintChars = MAX_EDITFIELD;
}
}
}
else if (item->type == ITEM_TYPE_MULTI)
{
item->typeData = UI_Alloc(sizeof(multiDef_t));
}
else if (item->type == ITEM_TYPE_MODEL)
{
item->typeData = UI_Alloc(sizeof(modelDef_t));
memset(item->typeData, 0, sizeof(modelDef_t));
}
else if (item->type == ITEM_TYPE_TEXTSCROLL )
{
item->typeData = UI_Alloc(sizeof(textScrollDef_t));
}
}
qboolean ItemParse_isCharacter( itemDef_t *item )
{
int i;
if ( !PC_ParseInt(&i) )
{
if ( i )
{
item->flags |= ITF_ISCHARACTER;
}
else
{
item->flags &= ~ITF_ISCHARACTER;
}
return qtrue;
}
return qfalse;
}
qboolean ItemParse_isSaber( itemDef_t *item )
{
extern void UI_SaberLoadParms( void );
extern qboolean ui_saber_parms_parsed;
extern void UI_CacheSaberGlowGraphics( void );
int i;
if ( !PC_ParseInt(&i) )
{
if ( i )
{
item->flags |= ITF_ISSABER;
UI_CacheSaberGlowGraphics();
if ( !ui_saber_parms_parsed )
{
UI_SaberLoadParms();
}
}
else
{
item->flags &= ~ITF_ISSABER;
}
return qtrue;
}
return qfalse;
}
qboolean ItemParse_isSaber2( itemDef_t *item )
{
extern void UI_SaberLoadParms( void );
extern qboolean ui_saber_parms_parsed;
extern void UI_CacheSaberGlowGraphics( void );
int i;
if ( !PC_ParseInt(&i) )
{
if ( i )
{
item->flags |= ITF_ISSABER2;
UI_CacheSaberGlowGraphics();
if ( !ui_saber_parms_parsed )
{
UI_SaberLoadParms();
}
}
else
{
item->flags &= ~ITF_ISSABER2;
}
return qtrue;
}
return qfalse;
}
keywordHash_t itemParseKeywords[] = {
{"accept", ItemParse_accept, },
{"selectNext", ItemParse_selectionNext, },
{"selectPrev", ItemParse_selectionPrev, },
{"action", ItemParse_action, },
{"addColorRange", ItemParse_addColorRange, },
{"align", ItemParse_align, },
{"appearance_slot", ItemParse_Appearance_slot, },
{"asset_model", ItemParse_asset_model, },
{"asset_shader", ItemParse_asset_shader, },
{"isCharacter", ItemParse_isCharacter, },
{"isSaber", ItemParse_isSaber, },
{"isSaber2", ItemParse_isSaber2, },
{"autowrapped", ItemParse_autowrapped, },
{"backcolor", ItemParse_backcolor, },
{"background", ItemParse_background, },
{"border", ItemParse_border, },
{"bordercolor", ItemParse_bordercolor, },
{"bordersize", ItemParse_bordersize, },
{"cinematic", ItemParse_cinematic, },
{"columns", ItemParse_columns, },
{"cvar", ItemParse_cvar, },
{"cvarFloat", ItemParse_cvarFloat, },
{"cvarFloatList", ItemParse_cvarFloatList, },
{"cvarSubString", ItemParse_cvarsubstring },
{"cvarStrList", ItemParse_cvarStrList, },
{"cvarTest", ItemParse_cvarTest, },
{"decoration", ItemParse_decoration, },
{"desctext", ItemParse_descText },
{"disableCvar", ItemParse_disableCvar, },
{"doubleclick", ItemParse_doubleClick, },
{"elementheight", ItemParse_elementheight, },
{"elementtype", ItemParse_elementtype, },
{"elementwidth", ItemParse_elementwidth, },
{"enableCvar", ItemParse_enableCvar, },
{"feeder", ItemParse_feeder, },
{"flag", ItemParse_flag, },
{"focusSound", ItemParse_focusSound, },
{"font", ItemParse_font, },
{"forecolor", ItemParse_forecolor, },
{"group", ItemParse_group, },
{"hideCvar", ItemParse_hideCvar, },
{"horizontalscroll",ItemParse_horizontalscroll, },
{"leaveFocus", ItemParse_leaveFocus, },
{"maxChars", ItemParse_maxChars, },
{"maxPaintChars", ItemParse_maxPaintChars, },
{"model_angle", ItemParse_model_angle, },
{"model_fovx", ItemParse_model_fovx, },
{"model_fovy", ItemParse_model_fovy, },
{"model_origin", ItemParse_model_origin, },
{"model_rotation", ItemParse_model_rotation, },
//rww - g2 begin
{"model_g2mins", ItemParse_model_g2mins, },
{"model_g2maxs", ItemParse_model_g2maxs, },
{"model_g2skin", ItemParse_model_g2skin, },
{"model_g2anim", ItemParse_model_g2anim, },
//rww - g2 end
{"mouseEnter", ItemParse_mouseEnter, },
{"mouseEnterText", ItemParse_mouseEnterText, },
{"mouseExit", ItemParse_mouseExit, },
{"mouseExitText", ItemParse_mouseExitText, },
{"name", ItemParse_name },
{"notselectable", ItemParse_notselectable, },
//JLF
{"scrollhidden", ItemParse_scrollhidden, },
//JLF END
{"onFocus", ItemParse_onFocus, },
{"outlinecolor", ItemParse_outlinecolor, },
{"ownerdraw", ItemParse_ownerdraw, },
{"ownerdrawFlag", ItemParse_ownerdrawFlag, },
{"rect", ItemParse_rect, },
{"showCvar", ItemParse_showCvar, },
{"special", ItemParse_special, },
{"style", ItemParse_style, },
{"text", ItemParse_text },
{"text2", ItemParse_text2 },
{"text2alignx", ItemParse_text2alignx, },
{"text2aligny", ItemParse_text2aligny, },
{"textalign", ItemParse_textalign, },
{"textalignx", ItemParse_textalignx, },
{"textaligny", ItemParse_textaligny, },
{"textscale", ItemParse_textscale, },
{"textstyle", ItemParse_textstyle, },
{"type", ItemParse_type, },
{"visible", ItemParse_visible, },
{"wrapped", ItemParse_wrapped, },
{"invertyesno", ItemParse_invertyesno },
{"xoffset", ItemParse_xoffset },//for yes/no and multi
// Text scroll specific
{"lineHeight", ItemParse_lineHeight, NULL },
{NULL, NULL, }
};
keywordHash_t *itemParseKeywordHash[KEYWORDHASH_SIZE];
/*
===============
Item_SetupKeywordHash
===============
*/
void Item_SetupKeywordHash(void)
{
int i;
memset(itemParseKeywordHash, 0, sizeof(itemParseKeywordHash));
for (i = 0; itemParseKeywords[i].keyword; i++)
{
KeywordHash_Add(itemParseKeywordHash, &itemParseKeywords[i]);
}
}
/*
===============
Item_Parse
===============
*/
qboolean Item_Parse(itemDef_t *item)
{
keywordHash_t *key;
const char *token;
if (PC_ParseString(&token))
{
return qfalse;
}
if (*token != '{')
{
return qfalse;
}
while ( 1 )
{
if (PC_ParseString(&token))
{
PC_ParseWarning("End of file inside menu item");
return qfalse;
}
if (*token == '}')
{
/* if (!item->window.name)
{
item->window.name = defaultString;
Com_Printf(S_COLOR_YELLOW"WARNING: Menu item has no name\n");
}
if (!item->window.group)
{
item->window.group = defaultString;
Com_Printf(S_COLOR_YELLOW"WARNING: Menu item has no group\n");
}
*/
return qtrue;
}
key = (keywordHash_s *) KeywordHash_Find(itemParseKeywordHash, token);
if (!key)
{
PC_ParseWarning(va("Unknown item keyword '%s'", token));
continue;
}
if ( !key->func(item) )
{
PC_ParseWarning(va("Couldn't parse item keyword '%s'", token));
return qfalse;
}
}
}
static void Item_TextScroll_BuildLines ( itemDef_t* item )
{
// new asian-aware line breaker... (pasted from elsewhere late @ night, hence aliasing-vars ;-)
//
textScrollDef_t* scrollPtr = (textScrollDef_t*) item->typeData;
const char *psText = item->text; // for copy/paste ease
int iBoxWidth = item->window.rect.w - SCROLLBAR_SIZE - 10;
// this could probably be simplified now, but it was converted from something else I didn't originally write,
// and it works anyway so wtf...
//
const char *psCurrentTextReadPos;
const char *psReadPosAtLineStart;
const char *psBestLineBreakSrcPos;
const char *psLastGood_s; // needed if we get a full screen of chars with no punctuation or space (see usage notes)
qboolean bIsTrailingPunctuation;
unsigned int uiLetter;
if (!psText)
{
return;
}
if (*psText == '@') // string reference
{
// trap_SP_GetStringTextString( &psText[1], text, sizeof(text));
psText = SE_GetString( &psText[1] );
}
psCurrentTextReadPos = psText;
psReadPosAtLineStart = psCurrentTextReadPos;
psBestLineBreakSrcPos = psCurrentTextReadPos;
scrollPtr->iLineCount = 0;
memset((char*)scrollPtr->pLines,0,sizeof(scrollPtr->pLines));
while (*psCurrentTextReadPos && (scrollPtr->iLineCount < MAX_TEXTSCROLL_LINES) )
{
char sLineForDisplay[2048]; // ott
// construct a line...
//
psCurrentTextReadPos = psReadPosAtLineStart;
sLineForDisplay[0] = '\0';
while ( *psCurrentTextReadPos )
{
int iAdvanceCount;
psLastGood_s = psCurrentTextReadPos;
// read letter...
//
uiLetter = ui.AnyLanguage_ReadCharFromString((char *)psCurrentTextReadPos, &iAdvanceCount, &bIsTrailingPunctuation);
psCurrentTextReadPos += iAdvanceCount;
// concat onto string so far...
//
if (uiLetter == 32 && sLineForDisplay[0] == '\0')
{
psReadPosAtLineStart++;
continue; // unless it's a space at the start of a line, in which case ignore it.
}
if (uiLetter > 255)
{
Q_strcat(sLineForDisplay, sizeof(sLineForDisplay),va("%c%c",uiLetter >> 8, uiLetter & 0xFF));
}
else
{
Q_strcat(sLineForDisplay, sizeof(sLineForDisplay),va("%c",uiLetter & 0xFF));
}
if (uiLetter == '\n')
{
// explicit new line...
//
sLineForDisplay[ strlen(sLineForDisplay)-1 ] = '\0'; // kill the CR
psReadPosAtLineStart = psCurrentTextReadPos;
psBestLineBreakSrcPos = psCurrentTextReadPos;
// hack it to fit in with this code...
//
scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc ( sLineForDisplay );
break; // print this line
}
else
if ( DC->textWidth( sLineForDisplay, item->textscale, item->font ) >= iBoxWidth )
{
// reached screen edge, so cap off string at bytepos after last good position...
//
if (uiLetter > 255 && bIsTrailingPunctuation && !ui.Language_UsesSpaces())
{
// Special case, don't consider line breaking if you're on an asian punctuation char of
// a language that doesn't use spaces...
//
}
else
{
if (psBestLineBreakSrcPos == psReadPosAtLineStart)
{
// aarrrggh!!!!! we'll only get here is someone has fed in a (probably) garbage string,
// since it doesn't have a single space or punctuation mark right the way across one line
// of the screen. So far, this has only happened in testing when I hardwired a taiwanese
// string into this function while the game was running in english (which should NEVER happen
// normally). On the other hand I suppose it's entirely possible that some taiwanese string
// might have no punctuation at all, so...
//
psBestLineBreakSrcPos = psLastGood_s; // force a break after last good letter
}
sLineForDisplay[ psBestLineBreakSrcPos - psReadPosAtLineStart ] = '\0';
psReadPosAtLineStart = psCurrentTextReadPos = psBestLineBreakSrcPos;
// hack it to fit in with this code...
//
scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc( sLineForDisplay );
break; // print this line
}
}
// record last-good linebreak pos... (ie if we've just concat'd a punctuation point (western or asian) or space)
//
if (bIsTrailingPunctuation || uiLetter == ' ' || (uiLetter > 255 && !ui.Language_UsesSpaces()))
{
psBestLineBreakSrcPos = psCurrentTextReadPos;
}
}
/// arrgghh, this is gettng horrible now...
//
if (scrollPtr->pLines[ scrollPtr->iLineCount ] == NULL && strlen(sLineForDisplay))
{
// then this is the last line and we've just run out of text, no CR, no overflow etc...
//
scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc( sLineForDisplay );
}
scrollPtr->iLineCount++;
}
}
/*
===============
Item_InitControls
init's special control types
===============
*/
void Item_InitControls(itemDef_t *item)
{
if (item == NULL)
{
return;
}
if (item->type == ITEM_TYPE_LISTBOX)
{
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
item->cursorPos = 0;
if (listPtr)
{
listPtr->cursorPos = 0;
listPtr->startPos = 0;
listPtr->endPos = 0;
listPtr->cursorPos = 0;
}
}
}
/*
=================
Int_Parse
=================
*/
qboolean Int_Parse(const char **p, int *i)
{
char *token;
token = COM_ParseExt(p, qfalse);
if (token && token[0] != 0)
{
*i = atoi(token);
return qtrue;
}
else
{
return qfalse;
}
}
/*
=================
String_Parse
=================
*/
qboolean String_Parse(const char **p, const char **out)
{
char *token;
token = COM_ParseExt(p, qfalse);
if (token && token[0] != 0)
{
*out = String_Alloc(token);
return (qboolean)(*out != NULL);
}
return qfalse;
}
/*
===============
Item_RunScript
===============
*/
void Item_RunScript(itemDef_t *item, const char *s)
{
const char *p;
int i;
qboolean bRan;
uiInfo.runScriptItem = item;
if (item && s && s[0])
{
p = s;
COM_BeginParseSession();
while (1)
{
const char *command;
// expect command then arguments, ; ends command, NULL ends script
if (!String_Parse(&p, &command))
{
break;
}
if (command[0] == ';' && command[1] == '\0')
{
continue;
}
bRan = qfalse;
for (i = 0; i < scriptCommandCount; i++)
{
if (Q_stricmp(command, commandList[i].name) == 0)
{
if ( !(commandList[i].handler(item, &p)) )
{
COM_EndParseSession();
return;
}
bRan = qtrue;
break;
}
}
// not in our auto list, pass to handler
if (!bRan)
{
// Allow any script command to fail
if ( !DC->runScript(&p) )
{
break;
}
}
}
COM_EndParseSession();
}
}
/*
===============
Menu_SetupKeywordHash
===============
*/
void Menu_SetupKeywordHash(void)
{
int i;
memset(menuParseKeywordHash, 0, sizeof(menuParseKeywordHash));
for (i = 0; menuParseKeywords[i].keyword; i++)
{
KeywordHash_Add(menuParseKeywordHash, &menuParseKeywords[i]);
}
}
/*
===============
Menus_ActivateByName
===============
*/
void Menu_HandleMouseMove(menuDef_t *menu, float x, float y);
menuDef_t *Menus_ActivateByName(const char *p)
{
int i;
menuDef_t *m = NULL;
menuDef_t *focus = Menu_GetFocused();
for (i = 0; i < menuCount; i++)
{
// Look for the name in the current list of windows
if (Q_stricmp(Menus[i].window.name, p) == 0)
{
m = &Menus[i];
Menus_Activate(m);
if (openMenuCount < MAX_OPEN_MENUS && focus != NULL)
{
menuStack[openMenuCount++] = focus;
}
}
else
{
Menus[i].window.flags &= ~WINDOW_HASFOCUS;
}
}
if (!m)
{ // A hack so we don't have to load all three mission menus before we know what tier we're on
if (!Q_stricmp( p, "ingameMissionSelect1" ) )
{
UI_LoadMenus("ui/tier1.txt",qfalse);
Menus_CloseAll();
Menus_OpenByName("ingameMissionSelect1");
}
else if (!Q_stricmp( p, "ingameMissionSelect2" ) )
{
UI_LoadMenus("ui/tier2.txt",qfalse);
Menus_CloseAll();
Menus_OpenByName("ingameMissionSelect2");
}
else if (!Q_stricmp( p, "ingameMissionSelect3" ) )
{
UI_LoadMenus("ui/tier3.txt",qfalse);
Menus_CloseAll();
Menus_OpenByName("ingameMissionSelect3");
}
else
{
Com_Printf(S_COLOR_YELLOW"WARNING: Menus_ActivateByName: Unable to find menu \"%s\"\n",p);
}
}
// First time, show force select instructions
if (!Q_stricmp( p, "ingameForceSelect" ) )
{
int tier_storyinfo = Cvar_VariableIntegerValue( "tier_storyinfo" );
if (tier_storyinfo==1)
{
Menus_OpenByName("ingameForceHelp");
}
}
// First time, show weapons select instructions
if (!Q_stricmp( p, "ingameWpnSelect" ) )
{
int tier_storyinfo = Cvar_VariableIntegerValue( "tier_storyinfo" );
if (tier_storyinfo==1)
{
Menus_OpenByName("ingameWpnSelectHelp");
}
}
// Want to handle a mouse move on the new menu in case your already over an item
Menu_HandleMouseMove ( m, DC->cursorx, DC->cursory );
return m;
}
/*
===============
Menus_Activate
===============
*/
void Menus_Activate(menuDef_t *menu)
{
menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
if (menu->onOpen)
{
itemDef_t item;
item.parent = menu;
item.window.flags = 0; //err, item is fake here, but we want a valid flag before calling runscript
Item_RunScript(&item, menu->onOpen);
if (item.window.flags & WINDOW_SCRIPTWAITING) //in case runscript set waiting, copy it up to the menu
{
menu->window.flags |= WINDOW_SCRIPTWAITING;
menu->window.delayedScript = item.window.delayedScript;
menu->window.delayTime = item.window.delayTime;
}
}
// menu->appearanceTime = DC->realTime + 1000;
menu->appearanceTime = 0;
menu->appearanceCnt = 0;
}
static const char *g_bindCommands[] = {
"+altattack",
"+attack",
"+back",
#ifndef JK2_MODE
"+force_drain",
#endif
"+force_grip",
"+force_lightning",
"+forward",
"+left",
"+lookdown",
"+lookup",
"+mlook",
"+movedown",
"+moveleft",
"+moveright",
"+moveup",
"+right",
"+speed",
"+strafe",
"+use",
"+useforce",
"centerview",
"cg_thirdperson !",
"datapad",
"exitview",
#ifndef JK2_MODE
"force_absorb",
#endif
"force_distract",
"force_heal",
#ifndef JK2_MODE
"force_protect",
#endif
"force_pull",
#ifndef JK2_MODE
"force_rage",
"force_sight",
#endif
"force_speed",
"force_throw",
"forcenext",
"forceprev",
"invnext",
"invprev",
"invuse",
"load auto",
#ifdef JK2_MODE
"load quik",
#else
"load quick",
#endif
"saberAttackCycle",
#ifdef JK2_MODE
"save quik*",
#else
"save quick",
#endif
"taunt",
"uimenu ingameloadmenu",
"uimenu ingamesavemenu",
"use_bacta",
"use_electrobinoculars",
"use_lightamp_goggles",
"use_seeker",
"use_sentry",
"weapnext",
"weapon 0",
"weapon 1",
"weapon 10",
"weapon 11",
"weapon 12",
"weapon 13",
"weapon 2",
"weapon 3",
"weapon 4",
"weapon 5",
"weapon 6",
"weapon 7",
"weapon 8",
"weapon 9",
"weapprev",
"zoom"
};
#define g_bindCount ARRAY_LEN(g_bindCommands)
static int g_bindKeys[g_bindCount][2];
/*
=================
Controls_GetKeyAssignment
=================
*/
static void Controls_GetKeyAssignment( const char *command, int *twokeys )
{
int count;
int j;
char b[256];
twokeys[0] = twokeys[1] = -1;
count = 0;
for ( j=0; j<MAX_KEYS; j++ ) {
DC->getBindingBuf( j, b, sizeof( b ) );
if ( *b && !Q_stricmp( b, command ) ) {
twokeys[count] = j;
count++;
if ( count == 2 )
break;
}
}
}
/*
=================
Controls_GetConfig
=================
*/
void Controls_GetConfig( void )
{
size_t i;
// iterate each command, get its numeric binding
for ( i = 0; i < g_bindCount; i++ )
Controls_GetKeyAssignment( g_bindCommands[i], g_bindKeys[i] );
}
/*
===============
Item_SetScreenCoords
===============
*/
void Item_SetScreenCoords(itemDef_t *item, float x, float y)
{
if (item == NULL)
{
return;
}
if (item->window.border != 0)
{
x += item->window.borderSize;
y += item->window.borderSize;
}
item->window.rect.x = x + item->window.rectClient.x;
item->window.rect.y = y + item->window.rectClient.y;
item->window.rect.w = item->window.rectClient.w;
item->window.rect.h = item->window.rectClient.h;
// force the text rects to recompute
item->textRect.w = 0;
item->textRect.h = 0;
switch ( item->type)
{
case ITEM_TYPE_TEXTSCROLL:
{
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
if ( scrollPtr )
{
scrollPtr->startPos = 0;
scrollPtr->endPos = 0;
}
Item_TextScroll_BuildLines ( item );
break;
}
}
}
static void Menu_FreeGhoulItems(menuDef_t *menu)
{
int i,j;
for (i = 0; i < menu->itemCount; i++)
{
for (j=0; j < menu->items[i]->ghoul2.size(); j++)
{
if ( menu->items[i]->ghoul2[j].mModelindex >= 0)
{
DC->g2_RemoveGhoul2Model( menu->items[i]->ghoul2, j );
}
}
(menu->items[i]->ghoul2).clear(); //clear is the public Free so i can actually remove this slot
}
}
/*
===============
Menu_Reset
===============
*/
void Menu_Reset(void)
{
//FIXME iterate menus to destoy G2 assets.
int i;
for (i = 0; i < menuCount; i++)
{
Menu_FreeGhoulItems( &Menus[i] );
}
menuCount = 0;
}
/*
===============
Menu_UpdatePosition
===============
*/
void Menu_UpdatePosition(menuDef_t *menu)
{
int i;
float x, y;
if (menu == NULL)
{
return;
}
x = menu->window.rect.x;
y = menu->window.rect.y;
if (menu->window.border != 0)
{
x += menu->window.borderSize;
y += menu->window.borderSize;
}
for (i = 0; i < menu->itemCount; i++)
{
Item_SetScreenCoords(menu->items[i], x, y);
}
}
/*
===============
Menu_PostParse
===============
*/
void Menu_PostParse(menuDef_t *menu)
{
if (menu == NULL)
{
return;
}
if (menu->fullScreen)
{
menu->window.rect.x = 0;
menu->window.rect.y = 0;
menu->window.rect.w = 640;
menu->window.rect.h = 480;
}
Menu_UpdatePosition(menu);
}
/*
===============
Menu_Init
===============
*/
void Menu_Init(menuDef_t *menu)
{
memset(menu, 0, sizeof(menuDef_t));
menu->cursorItem = -1;
UI_Cursor_Show(qtrue);
if (DC)
{
menu->fadeAmount = DC->Assets.fadeAmount;
menu->fadeClamp = DC->Assets.fadeClamp;
menu->fadeCycle = DC->Assets.fadeCycle;
}
Window_Init(&menu->window);
}
/*
===============
Menu_Parse
===============
*/
qboolean Menu_Parse(char *inbuffer, menuDef_t *menu)
{
// pc_token_t token;
keywordHash_t *key;
char *token2;
char * buffer;
bool nest= false;
buffer = inbuffer;
token2 = PC_ParseExt();
if (!token2)
{
return qfalse;
}
if (*token2 != '{')
{
PC_ParseWarning("Misplaced {");
return qfalse;
}
while ( 1 )
{
token2 = PC_ParseExt();
if (!token2)
{
PC_ParseWarning("End of file inside menu.");
return qfalse;
}
if (*token2 == '}')
{
return qtrue;
}
if (nest && (*token2 == 0))
{
PC_EndParseSession(buffer);
nest = false;
continue;
}
key = KeywordHash_Find(menuParseKeywordHash, token2);
if (!key)
{
PC_ParseWarning(va("Unknown menu keyword %s",token2));
continue;
}
if ( !key->func((itemDef_t*)menu) )
{
PC_ParseWarning(va("Couldn't parse menu keyword %s as %s",token2, key->keyword));
return qfalse;
}
}
}
/*
===============
Menu_New
===============
*/
void Menu_New(char *buffer)
{
menuDef_t *menu = &Menus[menuCount];
if (menuCount < MAX_MENUS)
{
Menu_Init(menu);
if (Menu_Parse(buffer, menu))
{
Menu_PostParse(menu);
menuCount++;
}
}
}
/*
===============
Menus_CloseAll
===============
*/
void Menus_CloseAll(void)
{
int i;
for (i = 0; i < menuCount; i++)
{
Menu_RunCloseScript ( &Menus[i] );
Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
}
// Clear the menu stack
openMenuCount = 0;
}
/*
===============
PC_StartParseSession
===============
*/
int PC_StartParseSession(const char *fileName,char **buffer)
{
int len;
// Try to open file and read it in.
len = ui.FS_ReadFile( fileName,(void **) buffer );
// Not there?
if ( len>0 )
{
COM_BeginParseSession();
Q_strncpyz(parseData[parseDataCount].fileName, fileName, sizeof (parseData[0].fileName));
parseData[parseDataCount].bufferStart = *buffer;
parseData[parseDataCount].bufferCurrent = *buffer;
}
return len;
}
/*
===============
PC_EndParseSession
===============
*/
void PC_EndParseSession(char *buffer)
{
COM_EndParseSession();
ui.FS_FreeFile( buffer ); //let go of the buffer
}
/*
===============
PC_ParseWarning
===============
*/
void PC_ParseWarning(const char *message)
{
ui.Printf(S_COLOR_YELLOW "WARNING: %s Line #%d of File '%s'\n", message,parseData[parseDataCount].com_lines,parseData[parseDataCount].fileName);
}
char *PC_ParseExt(void)
{
if(parseDataCount < 0)
Com_Error(ERR_FATAL, "PC_ParseExt: parseDataCount < 0 (be sure to call PC_StartParseSession!)");
return (COM_ParseExt(&parseData[parseDataCount].bufferCurrent, qtrue));
}
qboolean PC_ParseString(const char **string)
{
int hold;
if(parseDataCount < 0)
Com_Error(ERR_FATAL, "PC_ParseString: parseDataCount < 0 (be sure to call PC_StartParseSession!)");
hold = COM_ParseString(&parseData[parseDataCount].bufferCurrent,string);
while (hold==0 && **string == 0)
{
hold = COM_ParseString(&parseData[parseDataCount].bufferCurrent,string);
}
return (qboolean)(hold != 0);
}
qboolean PC_ParseInt(int *number)
{
if(parseDataCount < 0)
Com_Error(ERR_FATAL, "PC_ParseInt: parseDataCount < 0 (be sure to call PC_StartParseSession!)");
return(COM_ParseInt(&parseData[parseDataCount].bufferCurrent,number));
}
qboolean PC_ParseFloat(float *number)
{
if(parseDataCount < 0)
Com_Error(ERR_FATAL, "PC_ParseFloat: parseDataCount < 0 (be sure to call PC_StartParseSession!)");
return(COM_ParseFloat(&parseData[parseDataCount].bufferCurrent,number));
}
qboolean PC_ParseColor(vec4_t *color)
{
if(parseDataCount < 0)
Com_Error(ERR_FATAL, "PC_ParseColor: parseDataCount < 0 (be sure to call PC_StartParseSession!)");
return(COM_ParseVec4(&parseData[parseDataCount].bufferCurrent, color));
}
/*
=================
Menu_Count
=================
*/
int Menu_Count(void)
{
return menuCount;
}
/*
=================
Menu_PaintAll
=================
*/
void Menu_PaintAll(void)
{
int i;
if (captureFunc)
{
captureFunc(captureData);
}
for (i = 0; i < menuCount; i++)
{
Menu_Paint(&Menus[i], qfalse);
}
if (uis.debugMode)
{
vec4_t v = {1, 1, 1, 1};
DC->drawText(5, 25, .75, v, va("(%d,%d)",DC->cursorx,DC->cursory), 0, 0, DC->Assets.qhMediumFont);
DC->drawText(5, 10, .75, v, va("fps: %f", DC->FPS), 0, 0, DC->Assets.qhMediumFont);
}
}
/*
=================
Menu_Paint
=================
*/
void Menu_Paint(menuDef_t *menu, qboolean forcePaint)
{
int i;
if (menu == NULL)
{
return;
}
if (menu->window.flags & WINDOW_SCRIPTWAITING)
{
if (DC->realTime > menu->window.delayTime)
{ // Time has elapsed, resume running whatever script we saved
itemDef_t item;
item.parent = menu;
item.window.flags = 0; //clear before calling RunScript
menu->window.flags &= ~WINDOW_SCRIPTWAITING;
Item_RunScript(&item, menu->window.delayedScript);
// Could have hit another delay. Need to hoist from fake item
if (item.window.flags & WINDOW_SCRIPTWAITING)
{
menu->window.flags |= WINDOW_SCRIPTWAITING;
menu->window.delayedScript = item.window.delayedScript;
menu->window.delayTime = item.window.delayTime;
}
}
}
if (!(menu->window.flags & WINDOW_VISIBLE) && !forcePaint)
{
return;
}
// if (menu->window.ownerDrawFlags && DC->ownerDrawVisible && !DC->ownerDrawVisible(menu->window.ownerDrawFlags))
// {
// return;
// }
if (forcePaint)
{
menu->window.flags |= WINDOW_FORCED;
}
// draw the background if necessary
if (menu->fullScreen)
{
vec4_t color;
color[0] = menu->window.backColor[0];
color[1] = menu->window.backColor[1];
color[2] = menu->window.backColor[2];
color[3] = menu->window.backColor[3];
ui.R_SetColor( color);
if (menu->window.background==0) // No background shader given? Make it blank
{
menu->window.background = uis.whiteShader;
}
DC->drawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, menu->window.background );
}
else if (menu->window.background)
{
// this allows a background shader without being full screen
//UI_DrawHandlePic(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, menu->backgroundShader);
}
// paint the background and or border
Window_Paint(&menu->window, menu->fadeAmount, menu->fadeClamp, menu->fadeCycle );
// Loop through all items for the menu and paint them
int iSlotsVisible = 0;
for (i = 0; i < menu->itemCount; i++)
{
if (!menu->items[i]->appearanceSlot)
{
Item_Paint(menu->items[i], qtrue);
}
else // Timed order of appearance
{
if (Item_Paint(menu->items[i], qfalse) )
{
iSlotsVisible++; //It would paint
}
if (menu->items[i]->appearanceSlot<=menu->appearanceCnt)
{
Item_Paint(menu->items[i], qtrue);
}
}
}
if (iSlotsVisible && menu->appearanceTime < DC->realTime && menu->appearanceCnt < menu->itemCount) // Time to show another item
{
menu->appearanceTime = DC->realTime + menu->appearanceIncrement;
menu->appearanceCnt++;
}
if (uis.debugMode)
{
vec4_t color;
color[0] = color[2] = color[3] = 1;
color[1] = 0;
DC->drawRect(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, 1, color);
}
}
/*
=================
Item_EnableShowViaCvar
=================
*/
qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag)
{
if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest)
{
char script[1024];
const char *p;
char buff[1024];
if (item->cvarFlags & CVAR_SUBSTRING)
{
const char *val;
p = item->enableCvar;
COM_BeginParseSession();
if (!String_Parse(&p, &val))
{//strip the quotes off
COM_EndParseSession();
return (item->cvarFlags & flag) ? qfalse : qtrue;
}
COM_EndParseSession();
Q_strncpyz(buff, val, sizeof(buff));
DC->getCVarString(item->cvarTest, script, sizeof(script));
p = script;
}
else
{
DC->getCVarString(item->cvarTest, buff, sizeof(buff));
Q_strncpyz(script, item->enableCvar, sizeof(script));
p = script;
}
COM_BeginParseSession();
while (1)
{
const char *val;
// expect value then ; or NULL, NULL ends list
if (!String_Parse(&p, &val))
{
COM_EndParseSession();
return (item->cvarFlags & flag) ? qfalse : qtrue;
}
if (val[0] == ';' && val[1] == '\0')
{
continue;
}
// enable it if any of the values are true
if (item->cvarFlags & flag)
{
if (Q_stricmp(buff, val) == 0)
{
COM_EndParseSession();
return qtrue;
}
}
else
{
// disable it if any of the values are true
if (Q_stricmp(buff, val) == 0)
{
COM_EndParseSession();
return qfalse;
}
}
}
COM_EndParseSession();
return (item->cvarFlags & flag) ? qfalse : qtrue;
}
return qtrue;
}
bool HasStringLanguageChanged ( const itemDef_t *item )
{
if ( !item->text || item->text[0] == '\0' )
{
return false;
}
int modificationCount;
#ifdef JK2_MODE
modificationCount = sp_language->modificationCount;
#else
modificationCount = se_language->modificationCount;
#endif
return item->asset != modificationCount;
}
/*
=================
Item_SetTextExtents
=================
*/
void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *text)
{
const char *textPtr = (text) ? text : item->text;
if (textPtr == NULL )
{
return;
}
*width = item->textRect.w;
*height = item->textRect.h;
// keeps us from computing the widths and heights more than once
if (*width == 0 ||
(item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER) ||
HasStringLanguageChanged (item))
{
int originalWidth;
originalWidth = DC->textWidth(textPtr, item->textscale, item->font);
if (item->type == ITEM_TYPE_OWNERDRAW && (item->textalignment == ITEM_ALIGN_CENTER || item->textalignment == ITEM_ALIGN_RIGHT))
{
originalWidth += DC->ownerDrawWidth(item->window.ownerDraw, item->textscale);
}
else if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar)
{
char buff[256];
DC->getCVarString(item->cvar, buff, 256);
originalWidth += DC->textWidth(buff, item->textscale, item->font);
}
*width = DC->textWidth(textPtr, item->textscale, item->font);
*height = DC->textHeight(textPtr, item->textscale, item->font);
item->textRect.w = *width;
item->textRect.h = *height;
item->textRect.x = item->textalignx;
item->textRect.y = item->textaligny;
if (item->textalignment == ITEM_ALIGN_RIGHT)
{
item->textRect.x = item->textalignx - originalWidth;
}
else if (item->textalignment == ITEM_ALIGN_CENTER)
{
item->textRect.x = item->textalignx - originalWidth / 2;
}
ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
#ifdef JK2_MODE
if(item->text && item->text[0]=='@')
item->asset = sp_language->modificationCount;
#else
if (item->text && item->text[0]=='@' )//string package
item->asset = se_language->modificationCount; //mark language
#endif
}
}
/*
=================
Item_TextColor
=================
*/
void Item_TextColor(itemDef_t *item, vec4_t *newColor)
{
vec4_t lowLight;
const vec4_t greyColor = { .5, .5, .5, 1};
menuDef_t *parent = (menuDef_t*)item->parent;
Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
if ( !(item->type == ITEM_TYPE_TEXT && item->window.flags & WINDOW_AUTOWRAPPED) && item->window.flags & WINDOW_HASFOCUS)
{
lowLight[0] = 0.8 * parent->focusColor[0];
lowLight[1] = 0.8 * parent->focusColor[1];
lowLight[2] = 0.8 * parent->focusColor[2];
lowLight[3] = 0.8 * parent->focusColor[3];
LerpColor(parent->focusColor,lowLight,*newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
/* else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1))
{
lowLight[0] = 0.8 * item->window.foreColor[0];
lowLight[1] = 0.8 * item->window.foreColor[1];
lowLight[2] = 0.8 * item->window.foreColor[2];
lowLight[3] = 0.8 * item->window.foreColor[3];
LerpColor(item->window.foreColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
}
*/ else
{
memcpy(newColor, &item->window.foreColor, sizeof(vec4_t));
}
if (item->disabled)
{
memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
}
// items can be enabled and disabled based on cvars
if (item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest)
{
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE))
{
memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
}
}
if (item->window.flags & WINDOW_INACTIVE)
{
memcpy(newColor, &greyColor, sizeof(vec4_t));
}
}
/*
=================
Item_Text_Wrapped_Paint
=================
*/
void Item_Text_Wrapped_Paint(itemDef_t *item)
{
char text[1024];
const char *p, *start, *textPtr;
char buff[1024];
int width, height;
float x, y;
vec4_t color;
// now paint the text and/or any optional images
// default to left
if (item->text == NULL)
{
if (item->cvar == NULL)
{
return;
}
else
{
DC->getCVarString(item->cvar, text, sizeof(text));
textPtr = text;
}
}
else
{
textPtr = item->text;
}
if (*textPtr == '@') // string reference
{
textPtr = SE_GetString( &textPtr[1] );
}
if (*textPtr == '\0')
{
return;
}
Item_TextColor(item, &color);
Item_SetTextExtents(item, &width, &height, textPtr);
x = item->textRect.x;
y = item->textRect.y;
start = textPtr;
p = strchr(textPtr, '\r');
while (p && *p)
{
strncpy(buff, start, p-start+1);
buff[p-start] = '\0';
DC->drawText(x, y, item->textscale, color, buff, 0, item->textStyle, item->font);
y += height + 5;
start += p - start + 1;
p = strchr(p+1, '\r');
}
DC->drawText(x, y, item->textscale, color, start, 0, item->textStyle, item->font);
}
/*
=================
Menu_Paint
=================
*/
void Item_Text_Paint(itemDef_t *item)
{
char text[1024];
const char *textPtr;
int height, width;
vec4_t color;
if (item->window.flags & WINDOW_WRAPPED)
{
Item_Text_Wrapped_Paint(item);
return;
}
if (item->window.flags & WINDOW_AUTOWRAPPED)
{
Item_Text_AutoWrapped_Paint(item);
return;
}
if (item->text == NULL)
{
if (item->cvar == NULL)
{
return;
}
else
{
DC->getCVarString(item->cvar, text, sizeof(text));
textPtr = text;
}
}
else
{
textPtr = item->text;
}
#ifdef JK2_MODE
if (*textPtr == '@')
{
textPtr = JK2SP_GetStringTextString(&textPtr[1]);
}
#else
if (*textPtr == '@') // string reference
{
textPtr = SE_GetString( &textPtr[1] );
}
#endif
// this needs to go here as it sets extents for cvar types as well
Item_SetTextExtents(item, &width, &height, textPtr);
if (*textPtr == '\0')
{
return;
}
Item_TextColor(item, &color);
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, textPtr, 0, item->textStyle, item->font);
if (item->text2) // Is there a second line of text?
{
textPtr = item->text2;
if (*textPtr == '@') // string reference
{
textPtr = SE_GetString( &textPtr[1] );
}
Item_TextColor(item, &color);
DC->drawText(item->textRect.x + item->text2alignx, item->textRect.y + item->text2aligny, item->textscale, color, textPtr, 0, item->textStyle, item->font);
}
}
/*
=================
Item_UpdatePosition
=================
*/
// FIXME: consolidate this with nearby stuff
void Item_UpdatePosition(itemDef_t *item)
{
float x, y;
menuDef_t *menu;
if (item == NULL || item->parent == NULL)
{
return;
}
menu = (menuDef_t *) item->parent;
x = menu->window.rect.x;
y = menu->window.rect.y;
if (menu->window.border != 0)
{
x += menu->window.borderSize;
y += menu->window.borderSize;
}
Item_SetScreenCoords(item, x, y);
}
/*
=================
Item_TextField_Paint
=================
*/
void Item_TextField_Paint(itemDef_t *item)
{
char buff[1024];
vec4_t newColor, lowLight;
int offset;
menuDef_t *parent = (menuDef_t*)item->parent;
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
Item_Text_Paint(item);
buff[0] = '\0';
if (item->cvar)
{
DC->getCVarString(item->cvar, buff, sizeof(buff));
}
if (item->window.flags & WINDOW_HASFOCUS)
{
lowLight[0] = 0.8 * parent->focusColor[0];
lowLight[1] = 0.8 * parent->focusColor[1];
lowLight[2] = 0.8 * parent->focusColor[2];
lowLight[3] = 0.8 * parent->focusColor[3];
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
else
{
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
}
offset = 8;//(item->text && *item->text) ? 8 : 0;
if (item->window.flags & WINDOW_HASFOCUS && g_editingField)
{
char cursor = DC->getOverstrikeMode() ? '_' : '|';
DC->drawTextWithCursor(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, item->cursorPos - editPtr->paintOffset , cursor, /*editPtr->maxPaintChars*/ item->window.rect.w, item->textStyle, item->font);
}
else
{
DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, /*editPtr->maxPaintChars*/ item->window.rect.w, item->textStyle, item->font);
}
}
void Item_TextScroll_Paint(itemDef_t *item)
{
char cvartext[1024];
float x, y, size, count, thumb;
int i;
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
size = item->window.rect.h - 2;
// Re-arranged this function. Previous version had a plethora of bugs.
// Still a little iffy - BTO (VV)
if (item->cvar)
{
DC->getCVarString(item->cvar, cvartext, sizeof(cvartext));
item->text = cvartext;
}
Item_TextScroll_BuildLines ( item );
count = scrollPtr->iLineCount;
// Draw scroll bar if text goes beyond bottom
if (( scrollPtr->iLineCount * scrollPtr->lineHeight ) > size)
{
// draw scrollbar to right side of the window
x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
y = item->window.rect.y + 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
y += SCROLLBAR_SIZE - 1;
scrollPtr->endPos = scrollPtr->startPos;
size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
y += size - 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
// thumb
thumb = Item_TextScroll_ThumbDrawPosition(item);
if (thumb > y - SCROLLBAR_SIZE - 1)
{
thumb = y - SCROLLBAR_SIZE - 1;
}
DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
}
// adjust size for item painting
size = item->window.rect.h - 2;
x = item->window.rect.x + item->textalignx + 1;
y = item->window.rect.y + item->textaligny + 1;
for (i = scrollPtr->startPos; i < count; i++)
{
const char *text;
text = scrollPtr->pLines[i];
if (!text)
{
continue;
}
DC->drawText(x + 4, y, item->textscale, item->window.foreColor, text, 0, item->textStyle, item->font);
size -= scrollPtr->lineHeight;
if (size < scrollPtr->lineHeight)
{
scrollPtr->drawPadding = scrollPtr->lineHeight - size;
break;
}
scrollPtr->endPos++;
y += scrollPtr->lineHeight;
}
}
/*
=================
Item_ListBox_Paint
=================
*/
void Item_ListBox_Paint(itemDef_t *item)
{
float x, y, size;
int count, i, thumb;
qhandle_t image;
qhandle_t optionalImage;
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
// the listbox is horizontal or vertical and has a fixed size scroll bar going either direction
// elements are enumerated from the DC and either text or image handles are acquired from the DC as well
// textscale is used to size the text, textalignx and textaligny are used to size image elements
// there is no clipping available so only the last completely visible item is painted
count = DC->feederCount(item->special);
if (listPtr->startPos > (count?count-1:count))
{//probably changed feeders, so reset
listPtr->startPos = 0;
}
if (item->cursorPos > (count?count-1:count))
{//probably changed feeders, so reset
item->cursorPos = 0;
}
// default is vertical if horizontal flag is not here
if (item->window.flags & WINDOW_HORIZONTAL)
{
//JLF new variable (code just indented)
if (!listPtr->scrollhidden)
{
// draw scrollbar in bottom of the window
// bar
if (Item_ListBox_MaxScroll(item) > 0)
{
x = item->window.rect.x + 1;
y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE - 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowLeft);
x += SCROLLBAR_SIZE - 1;
size = item->window.rect.w - (SCROLLBAR_SIZE * 2);
DC->drawHandlePic(x, y, size+1, SCROLLBAR_SIZE, DC->Assets.scrollBar);
x += size - 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowRight);
// thumb
thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
if (thumb > x - SCROLLBAR_SIZE - 1)
{
thumb = x - SCROLLBAR_SIZE - 1;
}
DC->drawHandlePic(thumb, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
}
else if (listPtr->startPos > 0)
{
listPtr->startPos = 0;
}
}
//JLF end
//
listPtr->endPos = listPtr->startPos;
size = item->window.rect.w - 2;
// items
// size contains max available space
if (listPtr->elementStyle == LISTBOX_IMAGE)
{
// fit = 0;
x = item->window.rect.x + 1;
y = item->window.rect.y + 1;
for (i = listPtr->startPos; i < count; i++)
{
// always draw at least one
// which may overdraw the box if it is too small for the element
image = DC->feederItemImage(item->special, i);
if (image)
{
if (item->window.flags & WINDOW_PLAYERCOLOR)
{
vec4_t color;
color[0] = ui_char_color_red.integer/255.0f;
color[1] = ui_char_color_green.integer/255.0f;
color[2] = ui_char_color_blue.integer/255.0f;
color[3] = 1;
ui.R_SetColor(color);
}
DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
}
if (i == item->cursorPos)
{
DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
}
size -= listPtr->elementWidth;
if (size < listPtr->elementWidth)
{
listPtr->drawPadding = size; //listPtr->elementWidth - size;
break;
}
x += listPtr->elementWidth;
listPtr->endPos++;
// fit++;
}
}
else
{
//
}
}
else
{
//JLF new variable (code idented with if)
if (!listPtr->scrollhidden)
{
// draw scrollbar to right side of the window
x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
y = item->window.rect.y + 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
y += SCROLLBAR_SIZE - 1;
listPtr->endPos = listPtr->startPos;
size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
y += size - 1;
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
// thumb
thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
if (thumb > y - SCROLLBAR_SIZE - 1)
{
thumb = y - SCROLLBAR_SIZE - 1;
}
DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
}
//JLF end
// adjust size for item painting
size = item->window.rect.h - 2;
if (listPtr->elementStyle == LISTBOX_IMAGE)
{
// fit = 0;
x = item->window.rect.x + 1;
y = item->window.rect.y + 1;
for (i = listPtr->startPos; i < count; i++)
{
// always draw at least one
// which may overdraw the box if it is too small for the element
image = DC->feederItemImage(item->special, i);
if (image)
{
DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
}
if (i == item->cursorPos)
{
DC->drawRect(x, y, listPtr->elementWidth - 1, listPtr->elementHeight - 1, item->window.borderSize, item->window.borderColor);
}
listPtr->endPos++;
size -= listPtr->elementHeight;
if (size < listPtr->elementHeight)
{
listPtr->drawPadding = listPtr->elementHeight - size;
break;
}
y += listPtr->elementHeight;
// fit++;
}
}
else
{
x = item->window.rect.x + 1;
y = item->window.rect.y + 1 - listPtr->elementHeight;
i = listPtr->startPos;
for (; i < count; i++)
{
const char *text;
// always draw at least one
// which may overdraw the box if it is too small for the element
if (listPtr->numColumns > 0)
{
int j;
for (j = 0; j < listPtr->numColumns; j++)
{
text = DC->feederItemText(item->special, i, j, &optionalImage);
if (text[0]=='@')
{
text = SE_GetString( &text[1] );
}
if (optionalImage >= 0)
{
DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos, y - 1 + listPtr->elementHeight / 2, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
}
else if (text)
{
vec4_t *color;
menuDef_t *parent = (menuDef_t*)item->parent;
// Use focus color is it has focus.
if (i == item->cursorPos)
{
color = &parent->focusColor;
}
else
{
color = &item->window.foreColor;
}
int textyOffset;
textyOffset = 0;
DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight+ textyOffset, item->textscale, *color, text, listPtr->columnInfo[j].maxChars, item->textStyle, item->font);
}
}
}
else
{
text = DC->feederItemText(item->special, i, 0, &optionalImage);
if (optionalImage >= 0)
{
//DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
}
else if (text)
{
DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, item->textStyle, item->font);
}
}
// The chosen text
if (i == item->cursorPos)
{
DC->fillRect(x + 2, y + listPtr->elementHeight + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight+2, item->window.outlineColor);
}
size -= listPtr->elementHeight;
if (size < listPtr->elementHeight)
{
listPtr->drawPadding = listPtr->elementHeight - size;
break;
}
listPtr->endPos++;
y += listPtr->elementHeight;
// fit++;
}
}
}
}
/*
=================
BindingIDFromName
=================
*/
int BindingIDFromName( const char *name ) {
size_t i;
// iterate each command, set its default binding
for ( i = 0; i < g_bindCount; i++ ) {
if ( !Q_stricmp( name, g_bindCommands[i] ) )
return i;
}
return -1;
}
char g_nameBind[96];
/*
=================
BindingFromName
=================
*/
void BindingFromName( const char *cvar ) {
size_t i;
int b1, b2;
char sOR[32];
// iterate each command, set its default binding
for ( i=0; i < g_bindCount; i++ ) {
if ( !Q_stricmp(cvar, g_bindCommands[i] ) ) {
b2 = g_bindKeys[i][1];
b1 = g_bindKeys[i][0];
if ( b1 == -1 )
break;
if ( b2 != -1 ) {
char keyname[2][32];
DC->keynumToStringBuf( b1, keyname[0], sizeof( keyname[0] ) );
// do NOT do this or it corrupts asian text!!! Q_strupr(keyname[0]);
DC->keynumToStringBuf( b2, keyname[1], sizeof( keyname[1] ) );
// do NOT do this or it corrupts asian text!!! Q_strupr(keyname[1]);
#ifdef JK2_MODE
Q_strncpyz( sOR, ui.SP_GetStringTextString( "MENUS3_KEYBIND_OR" ), sizeof(sOR) );
#else
Q_strncpyz( sOR, SE_GetString( "MENUS_KEYBIND_OR" ), sizeof(sOR) );
#endif
Com_sprintf( g_nameBind, sizeof( g_nameBind ), "%s %s %s", keyname[0], sOR, keyname[1] );
}
else {
DC->keynumToStringBuf( b1, g_nameBind, sizeof( g_nameBind ) );
// do NOT do this or it corrupts asian text!!! Q_strupr(g_nameBind);
}
return;
}
}
Q_strncpyz( g_nameBind, "???", sizeof( g_nameBind ) );
}
/*
=================
Item_Bind_Paint
=================
*/
void Item_Bind_Paint(itemDef_t *item)
{
vec4_t newColor, lowLight;
float value,textScale,textWidth;
int maxChars = 0, textHeight,yAdj,startingXPos;
menuDef_t *parent = (menuDef_t*)item->parent;
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
if (editPtr)
{
maxChars = editPtr->maxPaintChars;
}
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
if (item->window.flags & WINDOW_HASFOCUS)
{
if (g_bindItem == item)
{
lowLight[0] = 0.8f * 1.0f;
lowLight[1] = 0.8f * 0.0f;
lowLight[2] = 0.8f * 0.0f;
lowLight[3] = 0.8f * 1.0f;
}
else
{
lowLight[0] = 0.8f * parent->focusColor[0];
lowLight[1] = 0.8f * parent->focusColor[1];
lowLight[2] = 0.8f * parent->focusColor[2];
lowLight[3] = 0.8f * parent->focusColor[3];
}
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
else
{
Item_TextColor( item,&newColor);
}
if (item->text)
{
Item_Text_Paint(item);
BindingFromName(item->cvar);
// If the text runs past the limit bring the scale down until it fits.
textScale = item->textscale;
textWidth = DC->textWidth(g_nameBind,(float) textScale, uiInfo.uiDC.Assets.qhMediumFont);
startingXPos = (item->textRect.x + item->textRect.w + 8);
while ((startingXPos + textWidth) >= SCREEN_WIDTH)
{
textScale -= .05f;
textWidth = DC->textWidth(g_nameBind,(float) textScale, uiInfo.uiDC.Assets.qhMediumFont);
}
// Try to adjust it's y placement if the scale has changed.
yAdj = 0;
if (textScale != item->textscale)
{
textHeight = DC->textHeight(g_nameBind, item->textscale, uiInfo.uiDC.Assets.qhMediumFont);
yAdj = textHeight - DC->textHeight(g_nameBind, textScale, uiInfo.uiDC.Assets.qhMediumFont);
}
DC->drawText(startingXPos, item->textRect.y + yAdj, textScale, newColor, g_nameBind, maxChars/*item->textRect.w*/, item->textStyle, item->font);
}
else
{
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME 1" : "FIXME 0", maxChars/*item->textRect.w*/, item->textStyle, item->font);
}
}
void UI_ScaleModelAxis(refEntity_t *ent)
{ // scale the model should we need to
if (ent->modelScale[0] && ent->modelScale[0] != 1.0f)
{
VectorScale( ent->axis[0], ent->modelScale[0] , ent->axis[0] );
ent->nonNormalizedAxes = qtrue;
}
if (ent->modelScale[1] && ent->modelScale[1] != 1.0f)
{
VectorScale( ent->axis[1], ent->modelScale[1] , ent->axis[1] );
ent->nonNormalizedAxes = qtrue;
}
if (ent->modelScale[2] && ent->modelScale[2] != 1.0f)
{
VectorScale( ent->axis[2], ent->modelScale[2] , ent->axis[2] );
ent->nonNormalizedAxes = qtrue;
}
}
/*
=================
Item_Model_Paint
=================
*/
extern int s_entityWavVol[MAX_GENTITIES]; //from snd_dma.cpp
void UI_TalkingHead(itemDef_t *item)
{
// static int facial_blink = DC->realTime + Q_flrand(4000.0, 8000.0);
static int facial_timer = DC->realTime + Q_flrand(10000.0, 30000.0);
// static animNumber_t facial_anim = FACE_ALERT;
int anim = -1;
//are we blinking?
/* if (facial_blink < 0)
{ // yes, check if we are we done blinking ?
if (-(facial_blink) < DC->realTime)
{ // yes, so reset blink timer
facial_blink = DC->realTime + Q_flrand(4000.0, 8000.0);
CG_G2SetHeadBlink( cent, qfalse ); //stop the blink
}
}
else // no we aren't blinking
{
if (facial_blink < DC->realTime)// but should we start ?
{
CG_G2SetHeadBlink( cent, qtrue );
if (facial_blink == 1)
{//requested to stay shut by SET_FACEEYESCLOSED
facial_blink = -(DC->realTime + 99999999.0f);// set blink timer
}
else
{
facial_blink = -(DC->realTime + 300.0f);// set blink timer
}
}
}
*/
if (s_entityWavVol[0] > 0) // if we aren't talking, then it will be 0, -1 for talking but paused
{
anim = FACE_TALK1 + s_entityWavVol[0]-1;
if( anim > FACE_TALK4 )
{
anim = FACE_TALK4;
}
// reset timers so we don't start right away after talking
facial_timer = DC->realTime + Q_flrand(2000.0, 7000.0);
}
else if (s_entityWavVol[0] == -1)
{// talking, but silent
anim = FACE_TALK0;
// reset timers so we don't start right away after talking
facial_timer = DC->realTime + Q_flrand(2000.0, 7000.0);
}
/* else if (s_entityWavVol[0] == 0) //don't anim if in a slient part of speech
{//not talking
if (facial_timer < 0) // are animating ?
{ //yes
if (-(facial_timer) < DC->realTime)// are we done animating ?
{ // yes, reset timer
facial_timer = DC->realTime + Q_flrand(10000.0, 30000.0);
}
else
{ // not yet, so choose anim
anim = facial_anim;
}
}
else // no we aren't animating
{ // but should we start ?
if (facial_timer < DC->realTime)
{//yes
facial_anim = FACE_ALERT + Q_irand(0,2); //alert, smile, frown
// set aux timer
facial_timer = -(DC->realTime + 2000.0);
anim = facial_anim;
}
}
}//talking
*/
if (facial_timer < DC->realTime)
{//restart the base anim
// modelDef_t *modelPtr = (modelDef_t*)item->typeData;
//ItemParse_model_g2anim_go( item, "BOTH_STAND5IDLE1" );
// facial_timer = DC->realTime + Q_flrand(2000.0, 7000.0) + DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
}
if (anim != -1)
{
DC->g2hilev_SetAnim(&item->ghoul2[0], "face", anim, qfalse);
}
}
/*
=================
Item_Model_Paint
=================
*/
extern void UI_SaberDrawBlades( itemDef_t *item, vec3_t origin, float curYaw );
void Item_Model_Paint(itemDef_t *item)
{
float x, y, w, h;
refdef_t refdef;
refEntity_t ent;
vec3_t mins, maxs, origin;
vec3_t angles;
const modelDef_t *modelPtr = (modelDef_t*)item->typeData;
if (modelPtr == NULL)
{
return;
}
// Fuck all the logic --eez
#ifdef JK2_MODE
// setup the refdef
memset( &refdef, 0, sizeof( refdef ) );
refdef.rdflags = RDF_NOWORLDMODEL;
AxisClear( refdef.viewaxis );
x = item->window.rect.x+1;
y = item->window.rect.y+1;
w = item->window.rect.w-2;
h = item->window.rect.h-2;
refdef.x = x * DC->xscale;
refdef.y = y * DC->yscale;
refdef.width = w * DC->xscale;
refdef.height = h * DC->yscale;
DC->modelBounds( item->asset, mins, maxs );
origin[2] = -0.5 * ( mins[2] + maxs[2] );
origin[1] = 0.5 * ( mins[1] + maxs[1] );
// calculate distance so the model nearly fills the box
if (qtrue)
{
float len = 0.5 * ( maxs[2] - mins[2] );
origin[0] = len / 0.268; // len / tan( fov/2 )
//origin[0] = len / tan(w/2);
}
else
{
origin[0] = item->textscale;
}
// WTF..? --eez
//refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : w;
//refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : h;
refdef.override_fov = true;
refdef.fov_x = 45;
refdef.fov_y = 45;
//refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
//xx = refdef.width / tan( refdef.fov_x / 360 * M_PI );
//refdef.fov_y = atan2( refdef.height, xx );
//refdef.fov_y *= ( 360 / M_PI );
DC->clearScene();
refdef.time = DC->realTime;
// add the model
memset( &ent, 0, sizeof(ent) );
//adjust = 5.0 * sin( (float)uis.realtime / 500 );
//adjust = 360 % (int)((float)uis.realtime / 1000);
//VectorSet( angles, 0, 0, 1 );
// use item storage to track
/*
if (modelPtr->rotationSpeed)
{
if (DC->realTime > item->window.nextTime)
{
item->window.nextTime = DC->realTime + modelPtr->rotationSpeed;
modelPtr->angle = (int)(modelPtr->angle + 1) % 360;
}
}
VectorSet( angles, 0, modelPtr->angle, 0 );
*/
VectorSet( angles, 0, (float)(refdef.time/20.0f), 0);
AnglesToAxis( angles, ent.axis );
ent.hModel = item->asset;
VectorCopy( origin, ent.origin );
VectorCopy( ent.origin, ent.oldorigin );
// Set up lighting
VectorCopy( refdef.vieworg, ent.lightingOrigin );
ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
DC->addRefEntityToScene( &ent );
DC->renderScene( &refdef );
#else
// a moves datapad anim is playing
if (uiInfo.moveAnimTime && (uiInfo.moveAnimTime < uiInfo.uiDC.realTime))
{
modelDef_t *modelPtr;
modelPtr = (modelDef_t*)item->typeData;
if (modelPtr)
{
//HACKHACKHACK: check for any multi-part anim sequences, and play the next anim, if needbe
switch( modelPtr->g2anim )
{
case BOTH_FORCEWALLREBOUND_FORWARD:
case BOTH_FORCEJUMP1:
ItemParse_model_g2anim_go( item, animTable[BOTH_FORCEINAIR1].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
if ( !uiInfo.moveAnimTime )
{
uiInfo.moveAnimTime = 500;
}
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_FORCEINAIR1:
ItemParse_model_g2anim_go( item, animTable[BOTH_FORCELAND1].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_FORCEWALLRUNFLIP_START:
ItemParse_model_g2anim_go( item, animTable[BOTH_FORCEWALLRUNFLIP_END].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_FORCELONGLEAP_START:
ItemParse_model_g2anim_go( item, animTable[BOTH_FORCELONGLEAP_LAND].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_KNOCKDOWN3://on front - into force getup
DC->startLocalSound(uiInfo.uiDC.Assets.datapadmoveJumpSound, CHAN_LOCAL );
ItemParse_model_g2anim_go( item, animTable[BOTH_FORCE_GETUP_F1].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_KNOCKDOWN2://on back - kick forward getup
DC->startLocalSound(uiInfo.uiDC.Assets.datapadmoveJumpSound, CHAN_LOCAL );
ItemParse_model_g2anim_go( item, animTable[BOTH_GETUP_BROLL_F].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
case BOTH_KNOCKDOWN1://on back - roll-away
DC->startLocalSound(uiInfo.uiDC.Assets.datapadmoveRollSound, CHAN_LOCAL );
ItemParse_model_g2anim_go( item, animTable[BOTH_GETUP_BROLL_R].name );
uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
break;
default:
ItemParse_model_g2anim_go( item, uiInfo.movesBaseAnim );
DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue);
uiInfo.moveAnimTime = 0;
break;
}
}
}
// setup the refdef
memset( &refdef, 0, sizeof( refdef ) );
refdef.rdflags = RDF_NOWORLDMODEL;
AxisClear( refdef.viewaxis );
x = item->window.rect.x+1;
y = item->window.rect.y+1;
w = item->window.rect.w-2;
h = item->window.rect.h-2;
refdef.x = x * DC->xscale;
refdef.y = y * DC->yscale;
refdef.width = w * DC->xscale;
refdef.height = h * DC->yscale;
if (item->flags&ITF_G2VALID)
{ //ghoul2 models don't have bounds, so we have to parse them.
VectorCopy(modelPtr->g2mins, mins);
VectorCopy(modelPtr->g2maxs, maxs);
if (!mins[0] && !mins[1] && !mins[2] &&
!maxs[0] && !maxs[1] && !maxs[2])
{ //we'll use defaults then I suppose.
VectorSet(mins, -16, -16, -24);
VectorSet(maxs, 16, 16, 32);
}
}
else
{
DC->modelBounds( item->asset, mins, maxs );
}
origin[2] = -0.5 * ( mins[2] + maxs[2] );
origin[1] = 0.5 * ( mins[1] + maxs[1] );
refdef.override_fov = true;
refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : (int)((float)refdef.width / 640.0f * 90.0f);
refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : atan2( refdef.height, refdef.width / tan( refdef.fov_x / 360 * M_PI ) ) * ( 360 / M_PI );
// refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : refdef.width;
// refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : refdef.height;
// calculate distance so the model nearly fills the box
float len = 0.5 * ( maxs[2] - mins[2] );
origin[0] = len / 0.268;
DC->clearScene();
refdef.time = DC->realTime;
// add the model
memset( &ent, 0, sizeof(ent) );
// use item storage to track
float curYaw = modelPtr->angle;
if (modelPtr->rotationSpeed)
{
curYaw += (float)refdef.time/modelPtr->rotationSpeed;
}
if ( item->flags&ITF_ISANYSABER && !(item->flags&ITF_ISCHARACTER) )
{//hack to put saber on it's side
VectorSet( angles, curYaw, 0, 90 );
}
else
{
VectorSet( angles, 0, curYaw, 0 );
}
AnglesToAxis( angles, ent.axis );
if (item->flags&ITF_G2VALID)
{
ent.ghoul2 = &item->ghoul2;
ent.radius = 1000;
ent.customSkin = modelPtr->g2skin;
if ( (item->flags&ITF_ISCHARACTER) )
{
ent.shaderRGBA[0] = ui_char_color_red.integer;
ent.shaderRGBA[1] = ui_char_color_green.integer;
ent.shaderRGBA[2] = ui_char_color_blue.integer;
ent.shaderRGBA[3] = 255;
UI_TalkingHead(item);
}
if ( item->flags&ITF_ISANYSABER )
{//UGH, draw the saber blade!
UI_SaberDrawBlades( item, origin, curYaw );
}
}
else
{
ent.hModel = item->asset;
}
VectorCopy( origin, ent.origin );
VectorCopy( ent.origin, ent.oldorigin );
// Set up lighting
//VectorCopy( refdef.vieworg, ent.lightingOrigin );
ent.renderfx = RF_NOSHADOW;
ui.R_AddLightToScene(refdef.vieworg, 500, 1, 1, 1); //fixme: specify in menu file!
DC->addRefEntityToScene( &ent );
DC->renderScene( &refdef );
#endif
}
/*
=================
Item_OwnerDraw_Paint
=================
*/
void Item_OwnerDraw_Paint(itemDef_t *item)
{
menuDef_t *parent;
if (item == NULL)
{
return;
}
parent = (menuDef_t*)item->parent;
if (DC->ownerDrawItem)
{
vec4_t color, lowLight;
Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
memcpy(&color, &item->window.foreColor, sizeof(color));
if (item->numColors > 0 && DC->getValue)
{
// if the value is within one of the ranges then set color to that, otherwise leave at default
int i;
float f = DC->getValue(item->window.ownerDraw);
for (i = 0; i < item->numColors; i++)
{
if (f >= item->colorRanges[i].low && f <= item->colorRanges[i].high)
{
memcpy(&color, &item->colorRanges[i].color, sizeof(color));
break;
}
}
}
if (item->window.flags & WINDOW_HASFOCUS)
{
lowLight[0] = 0.8 * parent->focusColor[0];
lowLight[1] = 0.8 * parent->focusColor[1];
lowLight[2] = 0.8 * parent->focusColor[2];
lowLight[3] = 0.8 * parent->focusColor[3];
LerpColor(parent->focusColor,lowLight,color,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1))
{
lowLight[0] = 0.8 * item->window.foreColor[0];
lowLight[1] = 0.8 * item->window.foreColor[1];
lowLight[2] = 0.8 * item->window.foreColor[2];
lowLight[3] = 0.8 * item->window.foreColor[3];
LerpColor(item->window.foreColor,lowLight,color,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
if ( item->disabled )
memcpy( color, parent->disableColor, sizeof( vec4_t ) );
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE))
{
memcpy(color, parent->disableColor, sizeof(vec4_t));
}
if (item->text)
{
Item_Text_Paint(item);
// +8 is an offset kludge to properly align owner draw items that have text combined with them
DC->ownerDrawItem(item->textRect.x + item->textRect.w + 8, item->window.rect.y, item->window.rect.w, item->window.rect.h, 0, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle, item->font );
}
else
{
DC->ownerDrawItem(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, item->textalignx, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle, item->font );
}
}
}
void Item_YesNo_Paint(itemDef_t *item)
{
vec4_t color;
float value;
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
#ifdef JK2_MODE
const char *psYes = ui.SP_GetStringTextString( "MENUS0_YES" );
const char *psNo = ui.SP_GetStringTextString( "MENUS0_NO" );
#else
const char *psYes = SE_GetString( "MENUS_YES" );
const char *psNo = SE_GetString( "MENUS_NO" );
#endif
const char *yesnovalue;
if (item->invertYesNo)
yesnovalue = (value == 0) ? psYes : psNo;
else
yesnovalue = (value != 0) ? psYes : psNo;
Item_TextColor(item, &color);
if (item->text)
{
Item_Text_Paint(item);
DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, color, yesnovalue, 0, item->textStyle, item->font);
}
else
{
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, yesnovalue , 0, item->textStyle, item->font);
}
}
/*
=================
Item_Multi_Paint
=================
*/
void Item_Multi_Paint(itemDef_t *item)
{
vec4_t color;
const char *text = "";
text = Item_Multi_Setting(item);
if (*text == '@') // string reference
{
text = SE_GetString( &text[1] );
}
Item_TextColor(item, &color);
if (item->text)
{
Item_Text_Paint(item);
DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, color, text, 0, item->textStyle, item->font);
}
else
{
//JLF added xoffset
DC->drawText(item->textRect.x +item->xoffset, item->textRect.y, item->textscale, color, text, 0, item->textStyle, item->font);
}
}
int Item_TextScroll_MaxScroll ( itemDef_t *item )
{
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
int count = scrollPtr->iLineCount;
int max = count - (int)(item->window.rect.h / scrollPtr->lineHeight) + 1;
if (max < 0)
{
return 0;
}
return max;
}
int Item_TextScroll_ThumbPosition ( itemDef_t *item )
{
float max, pos, size;
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
max = Item_TextScroll_MaxScroll ( item );
size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
if (max > 0)
{
pos = (size-SCROLLBAR_SIZE) / (float) max;
}
else
{
pos = 0;
}
pos *= scrollPtr->startPos;
return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
}
int Item_TextScroll_ThumbDrawPosition ( itemDef_t *item )
{
int min, max;
if (itemCapture == item)
{
min = item->window.rect.y + SCROLLBAR_SIZE + 1;
max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2)
{
return DC->cursory - SCROLLBAR_SIZE/2;
}
return Item_TextScroll_ThumbPosition(item);
}
return Item_TextScroll_ThumbPosition(item);
}
int Item_TextScroll_OverLB ( itemDef_t *item, float x, float y )
{
rectDef_t r;
textScrollDef_t *scrollPtr;
int thumbstart;
scrollPtr = (textScrollDef_t*)item->typeData;
// Scroll bar isn't drawing so ignore this input
if ((( scrollPtr->iLineCount * scrollPtr->lineHeight ) <= (item->window.rect.h - 2)) && (item->type == ITEM_TYPE_TEXTSCROLL))
{
return 0;
}
r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
r.y = item->window.rect.y;
r.h = r.w = SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_LEFTARROW;
}
r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_RIGHTARROW;
}
thumbstart = Item_TextScroll_ThumbPosition(item);
r.y = thumbstart;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_THUMB;
}
r.y = item->window.rect.y + SCROLLBAR_SIZE;
r.h = thumbstart - r.y;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGUP;
}
r.y = thumbstart + SCROLLBAR_SIZE;
r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGDN;
}
return 0;
}
void Item_TextScroll_MouseEnter (itemDef_t *item, float x, float y)
{
item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
item->window.flags |= Item_TextScroll_OverLB(item, x, y);
}
/*
=================
Item_Slider_ThumbPosition
=================
*/
int Item_ListBox_ThumbDrawPosition(itemDef_t *item)
{
int min, max;
if (itemCapture == item)
{
if (item->window.flags & WINDOW_HORIZONTAL)
{
min = item->window.rect.x + SCROLLBAR_SIZE + 1;
max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2)
{
return DC->cursorx - SCROLLBAR_SIZE/2;
}
else
{
return Item_ListBox_ThumbPosition(item);
}
}
else
{
min = item->window.rect.y + SCROLLBAR_SIZE + 1;
max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2)
{
return DC->cursory - SCROLLBAR_SIZE/2;
}
else
{
return Item_ListBox_ThumbPosition(item);
}
}
}
else
{
return Item_ListBox_ThumbPosition(item);
}
}
/*
=================
Item_Slider_ThumbPosition
=================
*/
float Item_Slider_ThumbPosition(itemDef_t *item)
{
float value, range, x;
editFieldDef_t *editDef = (editFieldDef_t *) item->typeData;
if (item->text)
{
x = item->textRect.x + item->textRect.w + 8;
}
else
{
x = item->window.rect.x;
}
if (!editDef || !item->cvar)
{
return x;
}
value = DC->getCVarValue(item->cvar);
if (value < editDef->minVal)
{
value = editDef->minVal;
}
else if (value > editDef->maxVal)
{
value = editDef->maxVal;
}
range = editDef->maxVal - editDef->minVal;
value -= editDef->minVal;
value /= range;
//value /= (editDef->maxVal - editDef->minVal);
value *= SLIDER_WIDTH;
x += value;
// vm fuckage
//x = x + (((float)value / editDef->maxVal) * SLIDER_WIDTH);
return x;
}
/*
=================
Item_Slider_Paint
=================
*/
void Item_Slider_Paint(itemDef_t *item)
{
vec4_t newColor, lowLight;
float x, y;
menuDef_t *parent = (menuDef_t*)item->parent;
if (item->window.flags & WINDOW_HASFOCUS)
{
lowLight[0] = 0.8 * parent->focusColor[0];
lowLight[1] = 0.8 * parent->focusColor[1];
lowLight[2] = 0.8 * parent->focusColor[2];
lowLight[3] = 0.8 * parent->focusColor[3];
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
}
else
{
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
}
y = item->window.rect.y;
if (item->text)
{
Item_Text_Paint(item);
x = item->textRect.x + item->textRect.w + 8;
}
else
{
x = item->window.rect.x;
}
DC->setColor(newColor);
DC->drawHandlePic( x, y+2, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
x = Item_Slider_ThumbPosition(item);
// DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y - 2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y+2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
}
/*
=================
Item_Paint
=================
*/
static qboolean Item_Paint(itemDef_t *item, qboolean bDraw)
{
int xPos,textWidth;
vec4_t red;
menuDef_t *parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (item == NULL)
{
return qfalse;
}
parent = (menuDef_t*)item->parent;
if (item->window.flags & WINDOW_SCRIPTWAITING)
{
if (DC->realTime > item->window.delayTime)
{ // Time has elapsed, resume running whatever script we saved
item->window.flags &= ~WINDOW_SCRIPTWAITING;
Item_RunScript(item, item->window.delayedScript);
}
}
if (item->window.flags & WINDOW_ORBITING)
{
if (DC->realTime > item->window.nextTime)
{
float rx, ry, a, c, s, w, h;
item->window.nextTime = DC->realTime + item->window.offsetTime;
// translate
w = item->window.rectClient.w / 2;
h = item->window.rectClient.h / 2;
rx = item->window.rectClient.x + w - item->window.rectEffects.x;
ry = item->window.rectClient.y + h - item->window.rectEffects.y;
a = (float) (3 * M_PI / 180);
c = cos(a);
s = sin(a);
item->window.rectClient.x = (rx * c - ry * s) + item->window.rectEffects.x - w;
item->window.rectClient.y = (rx * s + ry * c) + item->window.rectEffects.y - h;
Item_UpdatePosition(item);
}
}
if (item->window.flags & WINDOW_INTRANSITION)
{
if (DC->realTime > item->window.nextTime)
{
int done = 0;
item->window.nextTime = DC->realTime + item->window.offsetTime;
// transition the x,y
if (item->window.rectClient.x == item->window.rectEffects.x)
{
done++;
}
else
{
if (item->window.rectClient.x < item->window.rectEffects.x)
{
item->window.rectClient.x += item->window.rectEffects2.x;
if (item->window.rectClient.x > item->window.rectEffects.x)
{
item->window.rectClient.x = item->window.rectEffects.x;
done++;
}
}
else
{
item->window.rectClient.x -= item->window.rectEffects2.x;
if (item->window.rectClient.x < item->window.rectEffects.x)
{
item->window.rectClient.x = item->window.rectEffects.x;
done++;
}
}
}
if (item->window.rectClient.y == item->window.rectEffects.y)
{
done++;
}
else
{
if (item->window.rectClient.y < item->window.rectEffects.y)
{
item->window.rectClient.y += item->window.rectEffects2.y;
if (item->window.rectClient.y > item->window.rectEffects.y)
{
item->window.rectClient.y = item->window.rectEffects.y;
done++;
}
}
else
{
item->window.rectClient.y -= item->window.rectEffects2.y;
if (item->window.rectClient.y < item->window.rectEffects.y)
{
item->window.rectClient.y = item->window.rectEffects.y;
done++;
}
}
}
if (item->window.rectClient.w == item->window.rectEffects.w)
{
done++;
}
else
{
if (item->window.rectClient.w < item->window.rectEffects.w)
{
item->window.rectClient.w += item->window.rectEffects2.w;
if (item->window.rectClient.w > item->window.rectEffects.w)
{
item->window.rectClient.w = item->window.rectEffects.w;
done++;
}
}
else
{
item->window.rectClient.w -= item->window.rectEffects2.w;
if (item->window.rectClient.w < item->window.rectEffects.w)
{
item->window.rectClient.w = item->window.rectEffects.w;
done++;
}
}
}
if (item->window.rectClient.h == item->window.rectEffects.h)
{
done++;
}
else
{
if (item->window.rectClient.h < item->window.rectEffects.h)
{
item->window.rectClient.h += item->window.rectEffects2.h;
if (item->window.rectClient.h > item->window.rectEffects.h)
{
item->window.rectClient.h = item->window.rectEffects.h;
done++;
}
}
else
{
item->window.rectClient.h -= item->window.rectEffects2.h;
if (item->window.rectClient.h < item->window.rectEffects.h)
{
item->window.rectClient.h = item->window.rectEffects.h;
done++;
}
}
}
Item_UpdatePosition(item);
if (done == 4)
{
item->window.flags &= ~WINDOW_INTRANSITION;
}
}
}
#ifdef _TRANS3
//JLF begin model transition stuff
if (item->window.flags & WINDOW_INTRANSITIONMODEL)
{
if ( item->type == ITEM_TYPE_MODEL)
{
//fields ing modelptr
// vec3_t g2mins2, g2maxs2, g2minsEffect, g2maxsEffect;
// float fov_x2, fov_y2, fov_Effectx, fov_Effecty;
modelDef_t * modelptr = (modelDef_t *)item->typeData;
if (DC->realTime > item->window.nextTime)
{
int done = 0;
item->window.nextTime = DC->realTime + item->window.offsetTime;
// transition the x,y,z max
if (modelptr->g2maxs[0] == modelptr->g2maxs2[0])
{
done++;
}
else
{
if (modelptr->g2maxs[0] < modelptr->g2maxs2[0])
{
modelptr->g2maxs[0] += modelptr->g2maxsEffect[0];
if (modelptr->g2maxs[0] > modelptr->g2maxs2[0])
{
modelptr->g2maxs[0] = modelptr->g2maxs2[0];
done++;
}
}
else
{
modelptr->g2maxs[0] -= modelptr->g2maxsEffect[0];
if (modelptr->g2maxs[0] < modelptr->g2maxs2[0])
{
modelptr->g2maxs[0] = modelptr->g2maxs2[0];
done++;
}
}
}
//y
if (modelptr->g2maxs[1] == modelptr->g2maxs2[1])
{
done++;
}
else
{
if (modelptr->g2maxs[1] < modelptr->g2maxs2[1])
{
modelptr->g2maxs[1] += modelptr->g2maxsEffect[1];
if (modelptr->g2maxs[1] > modelptr->g2maxs2[1])
{
modelptr->g2maxs[1] = modelptr->g2maxs2[1];
done++;
}
}
else
{
modelptr->g2maxs[1] -= modelptr->g2maxsEffect[1];
if (modelptr->g2maxs[1] < modelptr->g2maxs2[1])
{
modelptr->g2maxs[1] = modelptr->g2maxs2[1];
done++;
}
}
}
//z
if (modelptr->g2maxs[2] == modelptr->g2maxs2[2])
{
done++;
}
else
{
if (modelptr->g2maxs[2] < modelptr->g2maxs2[2])
{
modelptr->g2maxs[2] += modelptr->g2maxsEffect[2];
if (modelptr->g2maxs[2] > modelptr->g2maxs2[2])
{
modelptr->g2maxs[2] = modelptr->g2maxs2[2];
done++;
}
}
else
{
modelptr->g2maxs[2] -= modelptr->g2maxsEffect[2];
if (modelptr->g2maxs[2] < modelptr->g2maxs2[2])
{
modelptr->g2maxs[2] = modelptr->g2maxs2[2];
done++;
}
}
}
// transition the x,y,z min
if (modelptr->g2mins[0] == modelptr->g2mins2[0])
{
done++;
}
else
{
if (modelptr->g2mins[0] < modelptr->g2mins2[0])
{
modelptr->g2mins[0] += modelptr->g2minsEffect[0];
if (modelptr->g2mins[0] > modelptr->g2mins2[0])
{
modelptr->g2mins[0] = modelptr->g2mins2[0];
done++;
}
}
else
{
modelptr->g2mins[0] -= modelptr->g2minsEffect[0];
if (modelptr->g2mins[0] < modelptr->g2mins2[0])
{
modelptr->g2mins[0] = modelptr->g2mins2[0];
done++;
}
}
}
//y
if (modelptr->g2mins[1] == modelptr->g2mins2[1])
{
done++;
}
else
{
if (modelptr->g2mins[1] < modelptr->g2mins2[1])
{
modelptr->g2mins[1] += modelptr->g2minsEffect[1];
if (modelptr->g2mins[1] > modelptr->g2mins2[1])
{
modelptr->g2mins[1] = modelptr->g2mins2[1];
done++;
}
}
else
{
modelptr->g2mins[1] -= modelptr->g2minsEffect[1];
if (modelptr->g2mins[1] < modelptr->g2mins2[1])
{
modelptr->g2mins[1] = modelptr->g2mins2[1];
done++;
}
}
}
//z
if (modelptr->g2mins[2] == modelptr->g2mins2[2])
{
done++;
}
else
{
if (modelptr->g2mins[2] < modelptr->g2mins2[2])
{
modelptr->g2mins[2] += modelptr->g2minsEffect[2];
if (modelptr->g2mins[2] > modelptr->g2mins2[2])
{
modelptr->g2mins[2] = modelptr->g2mins2[2];
done++;
}
}
else
{
modelptr->g2mins[2] -= modelptr->g2minsEffect[2];
if (modelptr->g2mins[2] < modelptr->g2mins2[2])
{
modelptr->g2mins[2] = modelptr->g2mins2[2];
done++;
}
}
}
//fovx
if (modelptr->fov_x == modelptr->fov_x2)
{
done++;
}
else
{
if (modelptr->fov_x < modelptr->fov_x2)
{
modelptr->fov_x += modelptr->fov_Effectx;
if (modelptr->fov_x > modelptr->fov_x2)
{
modelptr->fov_x = modelptr->fov_x2;
done++;
}
}
else
{
modelptr->fov_x -= modelptr->fov_Effectx;
if (modelptr->fov_x < modelptr->fov_x2)
{
modelptr->fov_x = modelptr->fov_x2;
done++;
}
}
}
//fovy
if (modelptr->fov_y == modelptr->fov_y2)
{
done++;
}
else
{
if (modelptr->fov_y < modelptr->fov_y2)
{
modelptr->fov_y += modelptr->fov_Effecty;
if (modelptr->fov_y > modelptr->fov_y2)
{
modelptr->fov_y = modelptr->fov_y2;
done++;
}
}
else
{
modelptr->fov_y -= modelptr->fov_Effecty;
if (modelptr->fov_y < modelptr->fov_y2)
{
modelptr->fov_y = modelptr->fov_y2;
done++;
}
}
}
if (done == 5)
{
item->window.flags &= ~WINDOW_INTRANSITIONMODEL;
}
}
}
}
#endif
//JLF end transition stuff for models
if (item->window.ownerDrawFlags && DC->ownerDrawVisible)
{
if (!DC->ownerDrawVisible(item->window.ownerDrawFlags))
{
item->window.flags &= ~WINDOW_VISIBLE;
}
else
{
item->window.flags |= WINDOW_VISIBLE;
}
}
if (item->disabled && item->disabledHidden)
{
return qfalse;
}
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE))
{
if (!Item_EnableShowViaCvar(item, CVAR_SHOW))
{
return qfalse;
}
}
if (item->window.flags & WINDOW_TIMEDVISIBLE)
{
}
if (!(item->window.flags & WINDOW_VISIBLE))
{
return qfalse;
}
if (!bDraw)
{
return qtrue;
}
//okay to paint
//JLFMOUSE
if (item->window.flags & WINDOW_MOUSEOVER)
{
if (item->descText && !Display_KeyBindPending())
{
// Make DOUBLY sure that this item should have desctext.
// NOTE : we can't just check the mouse position on this, what if we TABBED
// to the current menu item -- in that case our mouse isn't over the item.
// Removing the WINDOW_MOUSEOVER flag just prevents the item's OnExit script from running
// if (!Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
// { // It isn't something that should, because it isn't live anymore.
// item->window.flags &= ~WINDOW_MOUSEOVER;
// }
// else
//END JLFMOUSE
// items can be enabled and disabled based on cvars
if( !(item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) )
{ // Draw the desctext
const char *textPtr = item->descText;
if (*textPtr == '@') // string reference
{
textPtr = SE_GetString( &textPtr[1] );
}
vec4_t color = {1, 1, 1, 1};
Item_TextColor(item, &color);
float fDescScale = parent->descScale ? parent->descScale : 1;
float fDescScaleCopy = fDescScale;
while (1)
{
// FIXME - add some type of parameter in the menu file like descfont to specify the font for the descriptions for this menu.
textWidth = DC->textWidth(textPtr, fDescScale, 0); // item->font);
if (parent->descAlignment == ITEM_ALIGN_RIGHT)
{
xPos = parent->descX - textWidth; // Right justify
}
else if (parent->descAlignment == ITEM_ALIGN_CENTER)
{
xPos = parent->descX - (textWidth/2); // Center justify
}
else // Left justify
{
xPos = parent->descX;
}
if (parent->descAlignment == ITEM_ALIGN_CENTER)
{
// only this one will auto-shrink the scale until we eventually fit...
//
if (xPos + textWidth > (SCREEN_WIDTH-4)) {
fDescScale -= 0.001f;
continue;
}
}
// Try to adjust it's y placement if the scale has changed...
//
int iYadj = 0;
if (fDescScale != fDescScaleCopy)
{
int iOriginalTextHeight = DC->textHeight(textPtr, fDescScaleCopy, uiInfo.uiDC.Assets.qhMediumFont);
iYadj = iOriginalTextHeight - DC->textHeight(textPtr, fDescScale, uiInfo.uiDC.Assets.qhMediumFont);
}
// FIXME - add some type of parameter in the menu file like descfont to specify the font for the descriptions for this menu.
DC->drawText(xPos, parent->descY + iYadj, fDescScale, parent->descColor, textPtr, 0, parent->descTextStyle, 0); //item->font);
break;
}
}
}
}
// paint the rect first..
Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
// Print a box showing the extents of the rectangle, when in debug mode
if (uis.debugMode)
{
vec4_t color;
color[1] = color[3] = 1;
color[0] = color[2] = 0;
DC->drawRect(
item->window.rect.x,
item->window.rect.y,
item->window.rect.w,
item->window.rect.h,
1,
color);
}
//DC->drawRect(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, 1, red);
switch (item->type)
{
case ITEM_TYPE_OWNERDRAW:
Item_OwnerDraw_Paint(item);
break;
case ITEM_TYPE_TEXT:
case ITEM_TYPE_BUTTON:
Item_Text_Paint(item);
break;
case ITEM_TYPE_RADIOBUTTON:
break;
case ITEM_TYPE_CHECKBOX:
break;
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
Item_TextField_Paint(item);
break;
case ITEM_TYPE_COMBO:
break;
case ITEM_TYPE_LISTBOX:
Item_ListBox_Paint(item);
break;
case ITEM_TYPE_TEXTSCROLL:
Item_TextScroll_Paint ( item );
break;
case ITEM_TYPE_MODEL:
Item_Model_Paint(item);
break;
case ITEM_TYPE_YESNO:
Item_YesNo_Paint(item);
break;
case ITEM_TYPE_MULTI:
Item_Multi_Paint(item);
break;
case ITEM_TYPE_BIND:
Item_Bind_Paint(item);
break;
case ITEM_TYPE_SLIDER:
Item_Slider_Paint(item);
break;
default:
break;
}
return qtrue;
}
/*
=================
LerpColor
=================
*/
void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
{
int i;
// lerp and clamp each component
for (i=0; i<4; i++)
{
c[i] = a[i] + t*(b[i]-a[i]);
if (c[i] < 0)
{
c[i] = 0;
}
else if (c[i] > 1.0)
{
c[i] = 1.0;
}
}
}
/*
=================
Fade
=================
*/
void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount)
{
if (*flags & (WINDOW_FADINGOUT | WINDOW_FADINGIN))
{
if (DC->realTime > *nextTime)
{
*nextTime = DC->realTime + offsetTime;
if (*flags & WINDOW_FADINGOUT)
{
*f -= fadeAmount;
if (bFlags && *f <= 0.0)
{
*flags &= ~(WINDOW_FADINGOUT | WINDOW_VISIBLE);
}
}
else
{
*f += fadeAmount;
if (*f >= clamp)
{
*f = clamp;
if (bFlags)
{
*flags &= ~WINDOW_FADINGIN;
}
}
}
}
}
}
/*
=================
GradientBar_Paint
=================
*/
void GradientBar_Paint(rectDef_t *rect, vec4_t color)
{
// gradient bar takes two paints
DC->setColor( color );
DC->drawHandlePic(rect->x, rect->y, rect->w, rect->h, DC->Assets.gradientBar);
DC->setColor( NULL );
}
/*
=================
Window_Paint
=================
*/
void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle)
{
//float bordersize = 0;
vec4_t color;
rectDef_t fillRect = w->rect;
if (uis.debugMode)
{
color[0] = color[1] = color[2] = color[3] = 1;
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color);
}
if (w == NULL || (w->style == 0 && w->border == 0))
{
return;
}
if (w->border != 0)
{
fillRect.x += w->borderSize;
fillRect.y += w->borderSize;
fillRect.w -= w->borderSize + 1;
fillRect.h -= w->borderSize + 1;
}
if (w->style == WINDOW_STYLE_FILLED)
{
// box, but possible a shader that needs filled
if (w->background)
{
Fade(&w->flags, &w->backColor[3], fadeClamp, &w->nextTime, fadeCycle, qtrue, fadeAmount);
DC->setColor(w->backColor);
DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
DC->setColor(NULL);
}
else
{
DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->backColor);
}
}
else if (w->style == WINDOW_STYLE_GRADIENT)
{
GradientBar_Paint(&fillRect, w->backColor);
// gradient bar
}
else if (w->style == WINDOW_STYLE_SHADER)
{
if (w->flags & WINDOW_PLAYERCOLOR)
{
vec4_t color;
color[0] = ui_char_color_red.integer/255.0f;
color[1] = ui_char_color_green.integer/255.0f;
color[2] = ui_char_color_blue.integer/255.0f;
color[3] = 1;
ui.R_SetColor(color);
}
else if (w->flags & WINDOW_FORECOLORSET)
{
DC->setColor(w->foreColor);
}
DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
DC->setColor(NULL);
}
if (w->border == WINDOW_BORDER_FULL)
{
// full
// HACK HACK HACK
if (w->style == WINDOW_STYLE_TEAMCOLOR)
{
if (color[0] > 0)
{
// red
color[0] = 1;
color[1] = color[2] = .5;
}
else
{
color[2] = 1;
color[0] = color[1] = .5;
}
color[3] = 1;
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, color);
}
else
{
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, w->borderColor);
}
}
else if (w->border == WINDOW_BORDER_HORZ)
{
// top/bottom
DC->setColor(w->borderColor);
DC->drawTopBottom(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
DC->setColor( NULL );
}
else if (w->border == WINDOW_BORDER_VERT)
{
// left right
DC->setColor(w->borderColor);
DC->drawSides(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
DC->setColor( NULL );
}
else if (w->border == WINDOW_BORDER_KCGRADIENT)
{
// this is just two gradient bars along each horz edge
rectDef_t r = w->rect;
r.h = w->borderSize;
GradientBar_Paint(&r, w->borderColor);
r.y = w->rect.y + w->rect.h - 1;
GradientBar_Paint(&r, w->borderColor);
}
}
/*
=================
Display_KeyBindPending
=================
*/
qboolean Display_KeyBindPending(void)
{
return g_waitingForKey;
}
/*
=================
ToWindowCoords
=================
*/
void ToWindowCoords(float *x, float *y, windowDef_t *window)
{
if (window->border != 0)
{
*x += window->borderSize;
*y += window->borderSize;
}
*x += window->rect.x;
*y += window->rect.y;
}
/*
=================
Item_Text_AutoWrapped_Paint
=================
*/
void Item_Text_AutoWrapped_Paint(itemDef_t *item)
{
char text[1024];
const char *p, *textPtr, *newLinePtr;
char buff[1024];
int height, len, textWidth, newLine, newLineWidth;
float y;
vec4_t color;
textWidth = 0;
newLinePtr = NULL;
if (item->text == NULL)
{
if (item->cvar == NULL)
{
return;
}
else
{
DC->getCVarString(item->cvar, text, sizeof(text));
textPtr = text;
}
}
else
{
textPtr = item->text;
}
if (*textPtr == '@') // string reference
{
textPtr = SE_GetString( &textPtr[1] );
}
if (*textPtr == '\0')
{
return;
}
Item_TextColor(item, &color);
//Item_SetTextExtents(item, &width, &height, textPtr);
if (item->value == 0)
{
item->value = (int)(0.5 + (float)DC->textWidth(textPtr, item->textscale, item->font) / item->window.rect.w);
}
height = DC->textHeight(textPtr, item->textscale, item->font);
item->special = 0;
y = item->textaligny;
len = 0;
buff[0] = '\0';
newLine = 0;
newLineWidth = 0;
p = textPtr;
int line = 1;
while (1) //findmeste (this will break widechar languages)!
{
if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0')
{
newLine = len;
newLinePtr = p+1;
newLineWidth = textWidth;
}
textWidth = DC->textWidth(buff, item->textscale, 0);
if ( (newLine && textWidth >= item->window.rect.w - item->textalignx) || *p == '\n' || *p == '\0')
{
if (line > item->cursorPos) //scroll
{
if (len)
{
if (item->textalignment == ITEM_ALIGN_LEFT)
{
item->textRect.x = item->textalignx;
}
else if (item->textalignment == ITEM_ALIGN_RIGHT)
{
item->textRect.x = item->textalignx - newLineWidth;
}
else if (item->textalignment == ITEM_ALIGN_CENTER)
{
item->textRect.x = item->textalignx - newLineWidth / 2;
}
item->textRect.y = y;
ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
//
buff[newLine] = '\0';
if ( *p && y + height + 4 > item->window.rect.h - height)
{
item->special = 1;
strcat(buff,"...");//uhh, let's render some ellipses
}
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, item->textStyle, item->font);
}
y += height + 4;
if ( y > item->window.rect.h - height)
{//reached the bottom of the box, so stop
break;
}
len = 0;
}
else
{
strcpy(buff,"...");
len = 3;
}
if (*p == '\0')
{ //end of string
break;
}
p = newLinePtr;
newLine = 0;
newLineWidth = 0;
line++;
}
buff[len++] = *p++;
buff[len] = '\0';
}
item->textRect = item->window.rect;
}
/*
=================
Rect_ContainsPoint
=================
*/
static qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y)
{
//JLF ignore mouse pointer location
// return true;
// END JLF
if (rect)
{
// if ((x > rect->x) && (x < (rect->x + rect->w)) && (y > rect->y) && (y < (rect->y + rect->h)))
if ((x > rect->x) && (x < (rect->x + rect->w)))
{
if ((y > rect->y) && (y < (rect->y + rect->h)))
{
return qtrue;
}
}
}
return qfalse;
}
qboolean Item_TextScroll_HandleKey ( itemDef_t *item, int key, qboolean down, qboolean force)
{
textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
int max;
int viewmax;
if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS))
{
max = Item_TextScroll_MaxScroll(item);
viewmax = (item->window.rect.h / scrollPtr->lineHeight);
if ( key == A_CURSOR_UP || key == A_KP_8 )
{
scrollPtr->startPos--;
if (scrollPtr->startPos < 0)
{
scrollPtr->startPos = 0;
}
return qtrue;
}
if ( key == A_CURSOR_DOWN || key == A_KP_2 )
{
scrollPtr->startPos++;
if (scrollPtr->startPos > max)
{
scrollPtr->startPos = max;
}
return qtrue;
}
//Raz: Added
if ( key == A_MWHEELUP )
{
scrollPtr->startPos--;
if (scrollPtr->startPos < 0)
{
scrollPtr->startPos = 0;
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qfalse;
}
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qtrue;
}
if ( key == A_MWHEELDOWN )
{
scrollPtr->startPos++;
if (scrollPtr->startPos > max)
{
scrollPtr->startPos = max;
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qfalse;
}
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qtrue;
}
// mouse hit
if (key == A_MOUSE1 || key == A_MOUSE2)
{
if (item->window.flags & WINDOW_LB_LEFTARROW)
{
scrollPtr->startPos--;
if (scrollPtr->startPos < 0)
{
scrollPtr->startPos = 0;
}
}
else if (item->window.flags & WINDOW_LB_RIGHTARROW)
{
// one down
scrollPtr->startPos++;
if (scrollPtr->startPos > max)
{
scrollPtr->startPos = max;
}
}
else if (item->window.flags & WINDOW_LB_PGUP)
{
// page up
scrollPtr->startPos -= viewmax;
if (scrollPtr->startPos < 0)
{
scrollPtr->startPos = 0;
}
}
else if (item->window.flags & WINDOW_LB_PGDN)
{
// page down
scrollPtr->startPos += viewmax;
if (scrollPtr->startPos > max)
{
scrollPtr->startPos = max;
}
}
else if (item->window.flags & WINDOW_LB_THUMB)
{
// Display_SetCaptureItem(item);
}
return qtrue;
}
if ( key == A_HOME || key == A_KP_7)
{
// home
scrollPtr->startPos = 0;
return qtrue;
}
if ( key == A_END || key == A_KP_1)
{
// end
scrollPtr->startPos = max;
return qtrue;
}
if (key == A_PAGE_UP || key == A_KP_9 )
{
scrollPtr->startPos -= viewmax;
if (scrollPtr->startPos < 0)
{
scrollPtr->startPos = 0;
}
return qtrue;
}
if ( key == A_PAGE_DOWN || key == A_KP_3 )
{
scrollPtr->startPos += viewmax;
if (scrollPtr->startPos > max)
{
scrollPtr->startPos = max;
}
return qtrue;
}
}
return qfalse;
}
/*
=================
Item_ListBox_MaxScroll
=================
*/
int Item_ListBox_MaxScroll(itemDef_t *item)
{
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
int count = DC->feederCount(item->special);
int max;
if (item->window.flags & WINDOW_HORIZONTAL)
{
max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
}
else
{
max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
}
if (max < 0)
{
return 0;
}
return max;
}
/*
=================
Item_ListBox_ThumbPosition
=================
*/
int Item_ListBox_ThumbPosition(itemDef_t *item)
{
float max, pos, size;
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
max = Item_ListBox_MaxScroll(item);
if (item->window.flags & WINDOW_HORIZONTAL) {
size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
if (max > 0)
{
pos = (size-SCROLLBAR_SIZE) / (float) max;
}
else
{
pos = 0;
}
pos *= listPtr->startPos;
return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
}
else
{
size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
if (max > 0)
{
pos = (size-SCROLLBAR_SIZE) / (float) max;
}
else
{
pos = 0;
}
pos *= listPtr->startPos;
return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
}
}
/*
=================
Item_ListBox_OverLB
=================
*/
int Item_ListBox_OverLB(itemDef_t *item, float x, float y)
{
rectDef_t r;
int thumbstart;
if (item->window.flags & WINDOW_HORIZONTAL)
{
// check if on left arrow
r.x = item->window.rect.x;
r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
r.h = r.w = SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_LEFTARROW;
}
// check if on right arrow
r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_RIGHTARROW;
}
// check if on thumb
thumbstart = Item_ListBox_ThumbPosition(item);
r.x = thumbstart;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_THUMB;
}
r.x = item->window.rect.x + SCROLLBAR_SIZE;
r.w = thumbstart - r.x;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGUP;
}
r.x = thumbstart + SCROLLBAR_SIZE;
r.w = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGDN;
}
}
else
{
r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
r.y = item->window.rect.y;
r.h = r.w = SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_LEFTARROW;
}
r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_RIGHTARROW;
}
thumbstart = Item_ListBox_ThumbPosition(item);
r.y = thumbstart;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_THUMB;
}
r.y = item->window.rect.y + SCROLLBAR_SIZE;
r.h = thumbstart - r.y;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGUP;
}
r.y = thumbstart + SCROLLBAR_SIZE;
r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_PGDN;
}
}
return 0;
}
/*
=================
Item_ListBox_MouseEnter
=================
*/
void Item_ListBox_MouseEnter(itemDef_t *item, float x, float y)
{
rectDef_t r;
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
item->window.flags |= Item_ListBox_OverLB(item, x, y);
if (item->window.flags & WINDOW_HORIZONTAL)
{
if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN)))
{
// check for selection hit as we have exausted buttons and thumb
if (listPtr->elementStyle == LISTBOX_IMAGE)
{
r.x = item->window.rect.x;
r.y = item->window.rect.y;
r.h = item->window.rect.h - SCROLLBAR_SIZE;
r.w = item->window.rect.w - listPtr->drawPadding;
if (Rect_ContainsPoint(&r, x, y))
{
listPtr->cursorPos = (int)((x - r.x) / listPtr->elementWidth) + listPtr->startPos;
if (listPtr->cursorPos > listPtr->endPos)
{
listPtr->cursorPos = listPtr->endPos;
}
}
}
else
{
// text hit..
}
}
}
else if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN)))
{
r.x = item->window.rect.x;
r.y = item->window.rect.y;
r.w = item->window.rect.w - SCROLLBAR_SIZE;
r.h = item->window.rect.h - listPtr->drawPadding;
if (Rect_ContainsPoint(&r, x, y))
{
listPtr->cursorPos = (int)((y - 2 - r.y) / listPtr->elementHeight) + listPtr->startPos;
if (listPtr->cursorPos > listPtr->endPos)
{
listPtr->cursorPos = listPtr->endPos;
}
}
}
}
/*
=================
Item_MouseEnter
=================
*/
void Item_MouseEnter(itemDef_t *item, float x, float y)
{
rectDef_t r;
//JLFMOUSE
if (item)
{
r = item->textRect;
// r.y -= r.h; // NOt sure why this is here, but I commented it out.
// in the text rect?
// items can be enabled and disabled
if (item->disabled)
{
return;
}
// items can be enabled and disabled based on cvars
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE))
{
return;
}
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW))
{
return;
}
//JLFMOUSE
if (Rect_ContainsPoint(&r, x, y))
{
if (!(item->window.flags & WINDOW_MOUSEOVERTEXT))
{
Item_RunScript(item, item->mouseEnterText);
item->window.flags |= WINDOW_MOUSEOVERTEXT;
}
if (!(item->window.flags & WINDOW_MOUSEOVER))
{
Item_RunScript(item, item->mouseEnter);
item->window.flags |= WINDOW_MOUSEOVER;
}
}
else
{
// not in the text rect
if (item->window.flags & WINDOW_MOUSEOVERTEXT)
{
// if we were
Item_RunScript(item, item->mouseExitText);
item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
}
if (!(item->window.flags & WINDOW_MOUSEOVER))
{
Item_RunScript(item, item->mouseEnter);
item->window.flags |= WINDOW_MOUSEOVER;
}
if (item->type == ITEM_TYPE_LISTBOX)
{
Item_ListBox_MouseEnter(item, x, y);
}
else if ( item->type == ITEM_TYPE_TEXTSCROLL )
{
Item_TextScroll_MouseEnter ( item, x, y );
}
}
}
}
void VR_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight );
/*
=================
Item_SetFocus
=================
*/
// will optionaly set focus to this item
qboolean Item_SetFocus(itemDef_t *item, float x, float y)
{
int i;
itemDef_t *oldFocus;
sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
qboolean playSound = qfalse;
// sanity check, non-null, not a decoration and does not already have the focus
if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE) || (item->window.flags & WINDOW_INACTIVE))
{
return qfalse;
}
menuDef_t *parent = (menuDef_t*)item->parent;
// items can be enabled and disabled
if (item->disabled)
{
return qfalse;
}
// items can be enabled and disabled based on cvars
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE))
{
return qfalse;
}
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW))
{
return qfalse;
}
oldFocus = Menu_ClearFocus((menuDef_t *) item->parent);
if (item->type == ITEM_TYPE_TEXT)
{
rectDef_t r;
r = item->textRect;
//r.y -= r.h;
//JLFMOUSE
if (Rect_ContainsPoint(&r, x, y))
{
item->window.flags |= WINDOW_HASFOCUS;
if (item->focusSound)
{
sfx = &item->focusSound;
}
playSound = qtrue;
}
else
{
if (oldFocus)
{
oldFocus->window.flags |= WINDOW_HASFOCUS;
if (oldFocus->onFocus)
{
Item_RunScript(oldFocus, oldFocus->onFocus);
}
}
}
}
else
{
item->window.flags |= WINDOW_HASFOCUS;
if (item->onFocus)
{
Item_RunScript(item, item->onFocus);
}
if (item->focusSound)
{
sfx = &item->focusSound;
}
playSound = qtrue;
}
if (playSound && sfx)
{
DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
VR_HapticEvent("selector_icon", 0, vr.right_handed ? 1 : 2, 60, 0, 0);
}
for (i = 0; i < parent->itemCount; i++)
{
if (parent->items[i] == item)
{
parent->cursorItem = i;
break;
}
}
return qtrue;
}
/*
=================
IsVisible
=================
*/
qboolean IsVisible(int flags)
{
return (qboolean)((flags & WINDOW_VISIBLE && !(flags & WINDOW_FADINGOUT)) != 0);
}
/*
=================
Item_MouseLeave
=================
*/
void Item_MouseLeave(itemDef_t *item)
{
if (item)
{
if (item->window.flags & WINDOW_MOUSEOVERTEXT)
{
Item_RunScript(item, item->mouseExitText);
item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
}
Item_RunScript(item, item->mouseExit);
item->window.flags &= ~(WINDOW_LB_RIGHTARROW | WINDOW_LB_LEFTARROW);
}
}
/*
=================
Item_SetMouseOver
=================
*/
void Item_SetMouseOver(itemDef_t *item, qboolean focus)
{
if (item)
{
if (focus)
{
item->window.flags |= WINDOW_MOUSEOVER;
}
else
{
item->window.flags &= ~WINDOW_MOUSEOVER;
}
}
}
/*
=================
Menu_HandleMouseMove
=================
*/
void Menu_HandleMouseMove(menuDef_t *menu, float x, float y)
{
int i, pass;
qboolean focusSet = qfalse;
itemDef_t *overItem;
if (menu == NULL)
{
return;
}
if (!(menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)))
{
return;
}
if (itemCapture)
{
//Item_MouseMove(itemCapture, x, y);
return;
}
if (g_waitingForKey || g_editingField)
{
return;
}
// FIXME: this is the whole issue of focus vs. mouse over..
// need a better overall solution as i don't like going through everything twice
for (pass = 0; pass < 2; pass++)
{
for (i = 0; i < menu->itemCount; i++)
{
// turn off focus each item
// menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)))
{
continue;
}
if (menu->items[i]->window.flags & WINDOW_INACTIVE)
{
continue;
}
if (menu->items[i]->disabled)
{
continue;
}
// items can be enabled and disabled based on cvars
if (menu->items[i]->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_ENABLE))
{
continue;
}
if (menu->items[i]->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_SHOW))
{
continue;
}
if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y))
{
if (pass == 1)
{
overItem = menu->items[i];
if (overItem->type == ITEM_TYPE_TEXT && overItem->text)
{
if (!Rect_ContainsPoint(&overItem->window.rect, x, y))
{
continue;
}
}
// if we are over an item
if (IsVisible(overItem->window.flags))
{
// different one
Item_MouseEnter(overItem, x, y);
// Item_SetMouseOver(overItem, qtrue);
// if item is not a decoration see if it can take focus
if (!focusSet)
{
focusSet = Item_SetFocus(overItem, x, y);
}
}
}
} else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER)
{
Item_MouseLeave(menu->items[i]);
Item_SetMouseOver(menu->items[i], qfalse);
}
}
}
}
/*
=================
Display_MouseMove
=================
*/
qboolean Display_MouseMove(void *p, int x, int y)
{
int i;
menuDef_t *menu = (menuDef_t *) p;
if (menu == NULL)
{
menu = Menu_GetFocused();
if (menu)
{
if (menu->window.flags & WINDOW_POPUP)
{
Menu_HandleMouseMove(menu, x, y);
return qtrue;
}
}
for (i = 0; i < menuCount; i++)
{
Menu_HandleMouseMove(&Menus[i], x, y);
}
}
else
{
menu->window.rect.x += x;
menu->window.rect.y += y;
Menu_UpdatePosition(menu);
}
return qtrue;
}
/*
=================
Menus_AnyFullScreenVisible
=================
*/
qboolean Menus_AnyFullScreenVisible(void)
{
int i;
for (i = 0; i < menuCount; i++)
{
if (Menus[i].window.flags & WINDOW_VISIBLE && Menus[i].fullScreen)
{
return qtrue;
}
}
return qfalse;
}
/*
=================
Controls_SetConfig
=================
*/
void Controls_SetConfig( void )
{
size_t i;
// iterate each command, get its numeric binding
for ( i=0; i<g_bindCount; i++ ) {
if ( g_bindKeys[i][0] != -1 ) {
DC->setBinding( g_bindKeys[i][0], g_bindCommands[i] );
if ( g_bindKeys[i][1] != -1 )
DC->setBinding( g_bindKeys[i][1], g_bindCommands[i] );
}
}
}
void Controls_SetDefaults( void )
{
size_t i;
for ( i=0; i<g_bindCount; i++ ) {
g_bindKeys[i][0] = -1;
g_bindKeys[i][1] = -1;
}
}
void Item_Bind_Ungrey(itemDef_t *item)
{
menuDef_t *menu;
int i;
menu = (menuDef_t *) item->parent;
for (i=0;i<menu->itemCount;++i)
{
if (menu->items[i] == item)
{
continue;
}
menu->items[i]->window.flags &= ~WINDOW_INACTIVE;
}
}
/*
=================
Item_Bind_HandleKey
=================
*/
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down)
{
int id;
int i;
menuDef_t *menu;
if (key == A_MOUSE1 && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && !g_waitingForKey)
{
if (down)
{
g_waitingForKey = qtrue;
g_bindItem = item;
// Set all others in the menu to grey
menu = (menuDef_t *) item->parent;
for (i=0;i<menu->itemCount;++i)
{
if (menu->items[i] == item)
{
continue;
}
menu->items[i]->window.flags |= WINDOW_INACTIVE;
}
}
return qtrue;
}
else if (key == A_ENTER && !g_waitingForKey)
{
if (down)
{
g_waitingForKey = qtrue;
g_bindItem = item;
// Set all others in the menu to grey
menu = (menuDef_t *) item->parent;
for (i=0;i<menu->itemCount;++i)
{
if (menu->items[i] == item)
{
continue;
}
menu->items[i]->window.flags |= WINDOW_INACTIVE;
}
}
return qtrue;
}
else
{
if (!g_waitingForKey || g_bindItem == NULL)
{
return qfalse;
}
if (key & K_CHAR_FLAG)
{
return qtrue;
}
switch (key)
{
case A_ESCAPE:
g_waitingForKey = qfalse;
Item_Bind_Ungrey(item);
return qtrue;
case A_BACKSPACE:
id = BindingIDFromName(item->cvar);
if ( id != -1 )
{
if ( g_bindKeys[id][0] != -1 )
DC->setBinding( g_bindKeys[id][0], "" );
if ( g_bindKeys[id][1] != -1 )
DC->setBinding( g_bindKeys[id][1], "" );
g_bindKeys[id][0] = -1;
g_bindKeys[id][1] = -1;
}
Controls_SetConfig();
g_waitingForKey = qfalse;
g_bindItem = NULL;
Item_Bind_Ungrey(item);
return qtrue;
break;
case '`':
return qtrue;
}
}
// Is the same key being bound to something else?
if ( key != -1 ) {
size_t b;
for ( b=0; b<g_bindCount; b++ )
{
if ( g_bindKeys[b][1] == key )
g_bindKeys[b][1] = -1;
if ( g_bindKeys[b][0] == key ) {
g_bindKeys[b][0] = g_bindKeys[b][1];
g_bindKeys[b][1] = -1;
}
}
}
id = BindingIDFromName( item->cvar );
if ( id != -1 ) {
if ( key == -1 ) {
if ( g_bindKeys[id][0] != -1 ) {
DC->setBinding( g_bindKeys[id][0], "" );
g_bindKeys[id][0] = -1;
}
if ( g_bindKeys[id][1] != -1 ) {
DC->setBinding( g_bindKeys[id][1], "" );
g_bindKeys[id][1] = -1;
}
}
else if ( g_bindKeys[id][0] == -1 )
g_bindKeys[id][0] = key;
else if ( g_bindKeys[id][0] != key && g_bindKeys[id][1] == -1 )
g_bindKeys[id][1] = key;
else {
DC->setBinding( g_bindKeys[id][0], "" );
DC->setBinding( g_bindKeys[id][1], "" );
g_bindKeys[id][0] = key;
g_bindKeys[id][1] = -1;
}
}
Controls_SetConfig();
g_waitingForKey = qfalse;
Item_Bind_Ungrey(item);
return qtrue;
}
/*
=================
Menu_SetNextCursorItem
=================
*/
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu)
{
qboolean wrapped = qfalse;
int oldCursor = menu->cursorItem;
if (menu->cursorItem == -1)
{
menu->cursorItem = 0;
wrapped = qtrue;
}
while (menu->cursorItem < menu->itemCount)
{
menu->cursorItem++;
if (menu->cursorItem >= menu->itemCount && !wrapped)
{
wrapped = qtrue;
menu->cursorItem = 0;
}
if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory))
{
Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
return menu->items[menu->cursorItem];
}
}
menu->cursorItem = oldCursor;
return NULL;
}
/*
=================
Menu_SetPrevCursorItem
=================
*/
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu)
{
qboolean wrapped = qfalse;
int oldCursor = menu->cursorItem;
if (menu->cursorItem < 0)
{
menu->cursorItem = menu->itemCount-1;
wrapped = qtrue;
}
while (menu->cursorItem > -1)
{
menu->cursorItem--;
if (menu->cursorItem < 0 )
{
if (wrapped)
{
break;
}
wrapped = qtrue;
menu->cursorItem = menu->itemCount -1;
}
if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory))
{
Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
return menu->items[menu->cursorItem];
}
}
menu->cursorItem = oldCursor;
return NULL;
}
/*
=================
Item_TextField_HandleKey
=================
*/
qboolean Item_TextField_HandleKey(itemDef_t *item, int key)
{
char buff[1024];
int len;
itemDef_t *newItem = NULL;
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
if (item->cvar)
{
memset(buff, 0, sizeof(buff));
DC->getCVarString(item->cvar, buff, sizeof(buff));
len = strlen(buff);
if (editPtr->maxChars && len > editPtr->maxChars)
{
len = editPtr->maxChars;
}
if ( key & K_CHAR_FLAG )
{
key &= ~K_CHAR_FLAG;
if (key == 'h' - 'a' + 1 )
{ // ctrl-h is backspace
if ( item->cursorPos > 0 )
{
memmove( &buff[item->cursorPos - 1], &buff[item->cursorPos], len + 1 - item->cursorPos);
item->cursorPos--;
if (item->cursorPos < editPtr->paintOffset)
{
editPtr->paintOffset--;
}
}
DC->setCVar(item->cvar, buff);
return qtrue;
}
//
// ignore any non printable chars
//
if ( key < 32 || !item->cvar)
{
return qtrue;
}
if (item->type == ITEM_TYPE_NUMERICFIELD)
{
if (key < '0' || key > '9')
{
return qfalse;
}
}
if (!DC->getOverstrikeMode())
{
if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars))
{
return qtrue;
}
memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
}
else
{
if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars)
{
return qtrue;
}
}
buff[item->cursorPos] = key;
DC->setCVar(item->cvar, buff);
if (item->cursorPos < len + 1)
{
item->cursorPos++;
if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars)
{
editPtr->paintOffset++;
}
}
}
else
{
if ( key == A_DELETE || key == A_KP_PERIOD )
{
if ( item->cursorPos < len )
{
memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
DC->setCVar(item->cvar, buff);
}
return qtrue;
}
if ( key == A_CURSOR_RIGHT || key == A_KP_6 )
{
if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len)
{
item->cursorPos++;
editPtr->paintOffset++;
return qtrue;
}
if (item->cursorPos < len)
{
item->cursorPos++;
}
return qtrue;
}
if ( key == A_CURSOR_LEFT|| key == A_KP_4 )
{
if ( item->cursorPos > 0 )
{
item->cursorPos--;
}
if (item->cursorPos < editPtr->paintOffset)
{
editPtr->paintOffset--;
}
return qtrue;
}
if ( key == A_HOME || key == A_KP_7)
{
item->cursorPos = 0;
editPtr->paintOffset = 0;
return qtrue;
}
if ( key == A_END || key == A_KP_1)
{
item->cursorPos = len;
if(item->cursorPos > editPtr->maxPaintChars)
{
editPtr->paintOffset = len - editPtr->maxPaintChars;
}
return qtrue;
}
if ( key == A_INSERT || key == A_KP_0 )
{
DC->setOverstrikeMode((qboolean)(!DC->getOverstrikeMode()));
return qtrue;
}
}
if (key == A_TAB || key == A_CURSOR_DOWN || key == A_KP_2)
{
newItem = Menu_SetNextCursorItem((menuDef_t *) item->parent);
if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD))
{
g_editItem = newItem;
}
}
if (key == A_CURSOR_UP || key == A_KP_8)
{
newItem = Menu_SetPrevCursorItem((menuDef_t *) item->parent);
if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD))
{
g_editItem = newItem;
}
}
if ( key == A_ENTER || key == A_KP_ENTER || key == A_ESCAPE)
{
return qfalse;
}
return qtrue;
}
return qfalse;
}
static void Scroll_TextScroll_AutoFunc (void *p)
{
scrollInfo_t *si = (scrollInfo_t*)p;
if (DC->realTime > si->nextScrollTime)
{
// need to scroll which is done by simulating a click to the item
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
// so it calls it directly
Item_TextScroll_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
si->nextScrollTime = DC->realTime + si->adjustValue;
}
if (DC->realTime > si->nextAdjustTime)
{
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
if (si->adjustValue > SCROLL_TIME_FLOOR)
{
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
}
}
}
static void Scroll_TextScroll_ThumbFunc(void *p)
{
scrollInfo_t *si = (scrollInfo_t*)p;
rectDef_t r;
int pos;
int max;
textScrollDef_t *scrollPtr = (textScrollDef_t*)si->item->typeData;
if (DC->cursory != si->yStart)
{
r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
r.w = SCROLLBAR_SIZE;
max = Item_TextScroll_MaxScroll(si->item);
//
pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
if (pos < 0)
{
pos = 0;
}
else if (pos > max)
{
pos = max;
}
scrollPtr->startPos = pos;
si->yStart = DC->cursory;
}
if (DC->realTime > si->nextScrollTime)
{
// need to scroll which is done by simulating a click to the item
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
// so it calls it directly
Item_TextScroll_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
si->nextScrollTime = DC->realTime + si->adjustValue;
}
if (DC->realTime > si->nextAdjustTime)
{
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
if (si->adjustValue > SCROLL_TIME_FLOOR)
{
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
}
}
}
/*
=================
Menu_OverActiveItem
=================
*/
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y)
{
if (menu && menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))
{
if (Rect_ContainsPoint(&menu->window.rect, x, y))
{
int i;
for (i = 0; i < menu->itemCount; i++)
{
// turn off focus each item
// menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)))
{
continue;
}
if (menu->items[i]->window.flags & WINDOW_DECORATION)
{
continue;
}
if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y))
{
itemDef_t *overItem = menu->items[i];
if (overItem->type == ITEM_TYPE_TEXT && overItem->text)
{
if (Rect_ContainsPoint(&overItem->window.rect, x, y))
{
return qtrue;
}
else
{
continue;
}
}
else
{
return qtrue;
}
}
}
}
}
return qfalse;
}
/*
=================
Display_VisibleMenuCount
=================
*/
int Display_VisibleMenuCount(void)
{
int i, count;
count = 0;
for (i = 0; i < menuCount; i++)
{
if (Menus[i].window.flags & (WINDOW_FORCED | WINDOW_VISIBLE))
{
count++;
}
}
return count;
}
/*
=================
Window_CloseCinematic
=================
*/
static void Window_CloseCinematic(windowDef_t *window)
{
if (window->style == WINDOW_STYLE_CINEMATIC && window->cinematic >= 0)
{
DC->stopCinematic(window->cinematic);
window->cinematic = -1;
}
}
/*
=================
Menu_CloseCinematics
=================
*/
static void Menu_CloseCinematics(menuDef_t *menu)
{
if (menu)
{
int i;
Window_CloseCinematic(&menu->window);
for (i = 0; i < menu->itemCount; i++)
{
Window_CloseCinematic(&menu->items[i]->window);
if (menu->items[i]->type == ITEM_TYPE_OWNERDRAW)
{
DC->stopCinematic(0-menu->items[i]->window.ownerDraw);
}
}
}
}
/*
=================
Display_CloseCinematics
=================
*/
static void Display_CloseCinematics()
{
int i;
for (i = 0; i < menuCount; i++)
{
Menu_CloseCinematics(&Menus[i]);
}
}
/*
=================
Menus_HandleOOBClick
=================
*/
void Menus_HandleOOBClick(menuDef_t *menu, int key, qboolean down)
{
if (menu)
{
int i;
// basically the behaviour we are looking for is if there are windows in the stack.. see if
// the cursor is within any of them.. if not close them otherwise activate them and pass the
// key on.. force a mouse move to activate focus and script stuff
if (down && menu->window.flags & WINDOW_OOB_CLICK)
{
Menu_RunCloseScript(menu);
menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
}
for (i = 0; i < menuCount; i++)
{
if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory))
{
Menu_RunCloseScript(menu);
menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
// Menus_Activate(&Menus[i]);
Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
Menu_HandleKey(&Menus[i], key, down);
}
}
if (Display_VisibleMenuCount() == 0)
{
if (DC->Pause)
{
DC->Pause(qfalse);
}
}
Display_CloseCinematics();
}
}
/*
=================
Item_StopCapture
=================
*/
void Item_StopCapture(itemDef_t *item)
{
}
/*
=================
Item_ListBox_HandleKey
=================
*/
qboolean Item_ListBox_HandleKey(itemDef_t *item, int key, qboolean down, qboolean force)
{
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
int count = DC->feederCount(item->special);
int max, viewmax;
if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS))
{
max = Item_ListBox_MaxScroll(item);
if (item->window.flags & WINDOW_HORIZONTAL)
{
viewmax = (item->window.rect.w / listPtr->elementWidth);
if ( key == A_CURSOR_LEFT || key == A_KP_4 )
{
if (!listPtr->notselectable)
{
listPtr->cursorPos--;
if (listPtr->cursorPos < 0)
{
listPtr->cursorPos = 0;
}
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos--;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
}
}
return qtrue;
}
if ( key == A_CURSOR_RIGHT || key == A_KP_6 )
{
if (!listPtr->notselectable)
{
listPtr->cursorPos++;
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= count)
{
listPtr->cursorPos = count-1;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos++;
if (listPtr->startPos >= count)
{
listPtr->startPos = count-1;
}
}
return qtrue;
}
}
else
{
viewmax = (item->window.rect.h / listPtr->elementHeight);
if ( key == A_CURSOR_UP || key == A_KP_8 )
{
if (!listPtr->notselectable)
{
listPtr->cursorPos--;
if (listPtr->cursorPos < 0)
{
listPtr->cursorPos = 0;
}
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos--;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
}
}
return qtrue;
}
if ( key == A_CURSOR_DOWN || key == A_KP_2 )
{
if (!listPtr->notselectable)
{
listPtr->cursorPos++;
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= count)
{
listPtr->cursorPos = count-1;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos++;
if (listPtr->startPos > max)
{
listPtr->startPos = max;
}
}
return qtrue;
}
//Raz: Added
if ( key == A_MWHEELUP )
{
listPtr->startPos -= ((int)item->special == FEEDER_Q3HEADS) ? viewmax : 1;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qfalse;
}
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qtrue;
}
if ( key == A_MWHEELDOWN )
{
listPtr->startPos += ((int)item->special == FEEDER_Q3HEADS) ? viewmax : 1;
if (listPtr->startPos > max)
{
listPtr->startPos = max;
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qfalse;
}
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
return qtrue;
}
}
// mouse hit
if (key == A_MOUSE1 || key == A_MOUSE2)
{
if (item->window.flags & WINDOW_LB_LEFTARROW)
{
listPtr->startPos--;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
}
}
else if (item->window.flags & WINDOW_LB_RIGHTARROW)
{
// one down
listPtr->startPos++;
if (listPtr->startPos > max)
{
listPtr->startPos = max;
}
}
else if (item->window.flags & WINDOW_LB_PGUP)
{
// page up
listPtr->startPos -= viewmax;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
}
}
else if (item->window.flags & WINDOW_LB_PGDN)
{
// page down
listPtr->startPos += viewmax;
if (listPtr->startPos > max)
{
listPtr->startPos = max;
}
}
else if (item->window.flags & WINDOW_LB_THUMB)
{
// Display_SetCaptureItem(item);
}
else
{
// select an item
if (DC->realTime < lastListBoxClickTime && listPtr->doubleClick)
{
Item_RunScript(item, listPtr->doubleClick);
}
lastListBoxClickTime = DC->realTime + DOUBLE_CLICK_DELAY;
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
return qtrue;
}
if ( key == A_HOME || key == A_KP_7)
{
// home
listPtr->startPos = 0;
return qtrue;
}
if ( key == A_END || key == A_KP_1)
{
// end
listPtr->startPos = max;
return qtrue;
}
if (key == A_PAGE_UP || key == A_KP_9 )
{
// page up
if (!listPtr->notselectable)
{
listPtr->cursorPos -= viewmax;
if (listPtr->cursorPos < 0)
{
listPtr->cursorPos = 0;
}
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos -= viewmax;
if (listPtr->startPos < 0)
{
listPtr->startPos = 0;
}
}
return qtrue;
}
if ( key == A_PAGE_DOWN || key == A_KP_3 )
{
// page down
if (!listPtr->notselectable)
{
listPtr->cursorPos += viewmax;
if (listPtr->cursorPos < listPtr->startPos)
{
listPtr->startPos = listPtr->cursorPos;
}
if (listPtr->cursorPos >= count)
{
listPtr->cursorPos = count-1;
}
if (listPtr->cursorPos >= listPtr->startPos + viewmax)
{
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
}
item->cursorPos = listPtr->cursorPos;
DC->feederSelection(item->special, item->cursorPos, item);
}
else
{
listPtr->startPos += viewmax;
if (listPtr->startPos > max)
{
listPtr->startPos = max;
}
}
return qtrue;
}
}
return qfalse;
}
/*
=================
Scroll_ListBox_AutoFunc
=================
*/
static void Scroll_ListBox_AutoFunc(void *p)
{
scrollInfo_t *si = (scrollInfo_t*)p;
if (DC->realTime > si->nextScrollTime)
{
// need to scroll which is done by simulating a click to the item
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
// so it calls it directly
Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
si->nextScrollTime = DC->realTime + si->adjustValue;
}
if (DC->realTime > si->nextAdjustTime)
{
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
if (si->adjustValue > SCROLL_TIME_FLOOR)
{
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
}
}
}
/*
=================
Scroll_ListBox_ThumbFunc
=================
*/
static void Scroll_ListBox_ThumbFunc(void *p)
{
scrollInfo_t *si = (scrollInfo_t*)p;
rectDef_t r;
int pos, max;
listBoxDef_t *listPtr = (listBoxDef_t*)si->item->typeData;
if (si->item->window.flags & WINDOW_HORIZONTAL)
{
if (DC->cursorx == si->xStart)
{
return;
}
r.x = si->item->window.rect.x + SCROLLBAR_SIZE + 1;
r.y = si->item->window.rect.y + si->item->window.rect.h - SCROLLBAR_SIZE - 1;
r.h = SCROLLBAR_SIZE;
r.w = si->item->window.rect.w - (SCROLLBAR_SIZE*2) - 2;
max = Item_ListBox_MaxScroll(si->item);
//
pos = (DC->cursorx - r.x - SCROLLBAR_SIZE/2) * max / (r.w - SCROLLBAR_SIZE);
if (pos < 0)
{
pos = 0;
}
else if (pos > max)
{
pos = max;
}
listPtr->startPos = pos;
si->xStart = DC->cursorx;
}
else if (DC->cursory != si->yStart)
{
r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
r.w = SCROLLBAR_SIZE;
max = Item_ListBox_MaxScroll(si->item);
//
pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
if (pos < 0)
{
pos = 0;
}
else if (pos > max)
{
pos = max;
}
listPtr->startPos = pos;
si->yStart = DC->cursory;
}
if (DC->realTime > si->nextScrollTime)
{
// need to scroll which is done by simulating a click to the item
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
// so it calls it directly
Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
si->nextScrollTime = DC->realTime + si->adjustValue;
}
if (DC->realTime > si->nextAdjustTime)
{
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
if (si->adjustValue > SCROLL_TIME_FLOOR)
{
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
}
}
}
/*
=================
Item_Slider_OverSlider
=================
*/
int Item_Slider_OverSlider(itemDef_t *item, float x, float y)
{
rectDef_t r;
r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
r.y = item->window.rect.y - 2;
r.w = SLIDER_THUMB_WIDTH;
r.h = SLIDER_THUMB_HEIGHT;
if (Rect_ContainsPoint(&r, x, y))
{
return WINDOW_LB_THUMB;
}
return 0;
}
/*
=================
Scroll_Slider_ThumbFunc
=================
*/
static void Scroll_Slider_ThumbFunc(void *p)
{
float x, value, cursorx;
scrollInfo_t *si = (scrollInfo_t*)p;
editFieldDef_t *editDef = (struct editFieldDef_s *) si->item->typeData;
if (si->item->text)
{
x = si->item->textRect.x + si->item->textRect.w + 8;
}
else
{
x = si->item->window.rect.x;
}
cursorx = DC->cursorx;
if (cursorx < x)
{
cursorx = x;
}
else if (cursorx > x + SLIDER_WIDTH)
{
cursorx = x + SLIDER_WIDTH;
}
value = cursorx - x;
value /= SLIDER_WIDTH;
value *= (editDef->maxVal - editDef->minVal);
value += editDef->minVal;
DC->setCVar(si->item->cvar, va("%f", value));
}
/*
=================
Item_StartCapture
=================
*/
void Item_StartCapture(itemDef_t *item, int key)
{
int flags;
switch (item->type)
{
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
case ITEM_TYPE_LISTBOX:
{
flags = Item_ListBox_OverLB(item, DC->cursorx, DC->cursory);
if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW))
{
scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
scrollInfo.adjustValue = SCROLL_TIME_START;
scrollInfo.scrollKey = key;
scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
scrollInfo.item = item;
captureData = &scrollInfo;
captureFunc = &Scroll_ListBox_AutoFunc;
itemCapture = item;
}
else if (flags & WINDOW_LB_THUMB)
{
scrollInfo.scrollKey = key;
scrollInfo.item = item;
scrollInfo.xStart = DC->cursorx;
scrollInfo.yStart = DC->cursory;
captureData = &scrollInfo;
captureFunc = &Scroll_ListBox_ThumbFunc;
itemCapture = item;
}
break;
}
case ITEM_TYPE_TEXTSCROLL:
flags = Item_TextScroll_OverLB (item, DC->cursorx, DC->cursory);
if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW))
{
scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
scrollInfo.adjustValue = SCROLL_TIME_START;
scrollInfo.scrollKey = key;
scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
scrollInfo.item = item;
captureData = &scrollInfo;
captureFunc = &Scroll_TextScroll_AutoFunc;
itemCapture = item;
}
else if (flags & WINDOW_LB_THUMB)
{
scrollInfo.scrollKey = key;
scrollInfo.item = item;
scrollInfo.xStart = DC->cursorx;
scrollInfo.yStart = DC->cursory;
captureData = &scrollInfo;
captureFunc = &Scroll_TextScroll_ThumbFunc;
itemCapture = item;
}
break;
case ITEM_TYPE_SLIDER:
{
flags = Item_Slider_OverSlider(item, DC->cursorx, DC->cursory);
if (flags & WINDOW_LB_THUMB)
{
scrollInfo.scrollKey = key;
scrollInfo.item = item;
scrollInfo.xStart = DC->cursorx;
scrollInfo.yStart = DC->cursory;
captureData = &scrollInfo;
captureFunc = &Scroll_Slider_ThumbFunc;
itemCapture = item;
}
break;
}
}
}
/*
=================
Item_YesNo_HandleKey
=================
*/
qboolean Item_YesNo_HandleKey(itemDef_t *item, int key)
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar)
{
if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3)
{
DC->setCVar(item->cvar, va("%i", !DC->getCVarValue(item->cvar)));
return qtrue;
}
}
return qfalse;
}
/*
=================
Item_Multi_FindCvarByValue
=================
*/
int Item_Multi_FindCvarByValue(itemDef_t *item)
{
char buff[1024];
float value = 0;
int i;
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
if (multiPtr)
{
if (multiPtr->strDef)
{
DC->getCVarString(item->cvar, buff, sizeof(buff));
}
else
{
value = DC->getCVarValue(item->cvar);
}
for (i = 0; i < multiPtr->count; i++)
{
if (multiPtr->strDef)
{
if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0)
{
return i;
}
}
else
{
if (multiPtr->cvarValue[i] == value)
{
return i;
}
}
}
}
return 0;
}
/*
=================
Item_Multi_CountSettings
=================
*/
int Item_Multi_CountSettings(itemDef_t *item)
{
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
if (multiPtr == NULL)
{
return 0;
}
return multiPtr->count;
}
/*
=================
Item_OwnerDraw_HandleKey
=================
*/
qboolean Item_OwnerDraw_HandleKey(itemDef_t *item, int key)
{
if (item && DC->ownerDrawHandleKey)
{
return DC->ownerDrawHandleKey(item->window.ownerDraw, item->window.ownerDrawFlags, &item->special, key);
}
return qfalse;
}
/*
=================
Item_Text_HandleKey
=================
*/
qboolean Item_Text_HandleKey(itemDef_t *item, int key)
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_AUTOWRAPPED)
{
if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3)
{
if (key == A_MOUSE2)
{
item->cursorPos--;
if ( item->cursorPos < 0 )
{
item->cursorPos = 0;
}
}
else if (item->special)
{
item->cursorPos++;
if ( item->cursorPos >= item->value )
{
item->cursorPos = 0;
}
}
return qtrue;
}
}
return qfalse;
}
/*
=================
Item_Multi_HandleKey
=================
*/
qboolean Item_Multi_HandleKey(itemDef_t *item, int key)
{
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
if (multiPtr)
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS)
{
//Raz: Scroll on multi buttons!
if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3 || key == A_MWHEELDOWN || key == A_MWHEELUP)
//if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3)
{
if (item->cvar)
{
int current = Item_Multi_FindCvarByValue(item);
int max = Item_Multi_CountSettings(item);
if (key == A_MOUSE2 || key == A_MWHEELDOWN)
{
current--;
if ( current < 0 )
{
current = max-1;
}
}
else
{
current++;
if ( current >= max )
{
current = 0;
}
}
if (multiPtr->strDef)
{
DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
}
else
{
float value = multiPtr->cvarValue[current];
if (((float)((int) value)) == value)
{
DC->setCVar(item->cvar, va("%i", (int) value ));
}
else
{
DC->setCVar(item->cvar, va("%f", value ));
}
}
if (item->special)
{//its a feeder?
DC->feederSelection(item->special, current, item);
}
}
else
{
int max = Item_Multi_CountSettings(item);
if (key == A_MOUSE2 || key == A_MWHEELDOWN)
{
item->value--;
if ( item->value < 0 )
{
item->value = max;
}
}
else
{
item->value++;
if ( item->value >= max )
{
item->value = 0;
}
}
if (item->special)
{//its a feeder?
DC->feederSelection(item->special, item->value, item);
}
}
return qtrue;
}
}
}
return qfalse;
}
/*
=================
Item_Slider_HandleKey
=================
*/
qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down)
{
//DC->Print("slider handle key\n");
//JLF MPMOVED
float x, value, width, work;
if (item->window.flags & WINDOW_HASFOCUS && item->cvar && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
{
if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3)
{
editFieldDef_t *editDef = (editFieldDef_s *) item->typeData;
if (editDef)
{
rectDef_t testRect;
width = SLIDER_WIDTH;
if (item->text)
{
x = item->textRect.x + item->textRect.w + 8;
}
else
{
x = item->window.rect.x;
}
testRect = item->window.rect;
testRect.x = x;
value = (float)SLIDER_THUMB_WIDTH / 2;
testRect.x -= value;
//DC->Print("slider x: %f\n", testRect.x);
testRect.w = (SLIDER_WIDTH + (float)SLIDER_THUMB_WIDTH / 2);
//DC->Print("slider w: %f\n", testRect.w);
if (Rect_ContainsPoint(&testRect, DC->cursorx, DC->cursory))
{
work = DC->cursorx - x;
value = work / width;
value *= (editDef->maxVal - editDef->minVal);
// vm fuckage
// value = (((float)(DC->cursorx - x)/ SLIDER_WIDTH) * (editDef->maxVal - editDef->minVal));
value += editDef->minVal;
DC->setCVar(item->cvar, va("%f", value));
return qtrue;
}
}
}
}
//DC->Print("slider handle key exit\n");
return qfalse;
}
/*
=================
Item_HandleKey
=================
*/
qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down)
{
if (itemCapture)
{
Item_StopCapture(itemCapture);
itemCapture = NULL;
captureFunc = NULL;
captureData = NULL;
}
else
{
if (down && (key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3))
{
Item_StartCapture(item, key);
}
}
if (!down)
{
return qfalse;
}
switch (item->type)
{
case ITEM_TYPE_BUTTON:
return qfalse;
break;
case ITEM_TYPE_RADIOBUTTON:
return qfalse;
break;
case ITEM_TYPE_CHECKBOX:
return qfalse;
break;
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
//return Item_TextField_HandleKey(item, key);
return qfalse;
break;
case ITEM_TYPE_COMBO:
return qfalse;
break;
case ITEM_TYPE_LISTBOX:
return Item_ListBox_HandleKey(item, key, down, qfalse);
break;
case ITEM_TYPE_TEXTSCROLL:
return Item_TextScroll_HandleKey(item, key, down, qfalse);
break;
case ITEM_TYPE_YESNO:
return Item_YesNo_HandleKey(item, key);
break;
case ITEM_TYPE_MULTI:
return Item_Multi_HandleKey(item, key);
break;
case ITEM_TYPE_OWNERDRAW:
return Item_OwnerDraw_HandleKey(item, key);
break;
case ITEM_TYPE_BIND:
return Item_Bind_HandleKey(item, key, down);
break;
case ITEM_TYPE_SLIDER:
return Item_Slider_HandleKey(item, key, down);
break;
//JLF MPMOVED
case ITEM_TYPE_TEXT:
return Item_Text_HandleKey(item, key);
break;
default:
return qfalse;
break;
}
//return qfalse;
}
//JLFACCEPT MPMOVED
/*
-----------------------------------------
Item_HandleAccept
If Item has an accept script, run it.
-------------------------------------------
*/
qboolean Item_HandleAccept(itemDef_t * item)
{
if (item->accept)
{
Item_RunScript(item, item->accept);
return qtrue;
}
return qfalse;
}
//JLFDPADSCRIPT MPMOVED
/*
-----------------------------------------
Item_HandleSelectionNext
If Item has an selectionNext script, run it.
-------------------------------------------
*/
qboolean Item_HandleSelectionNext(itemDef_t * item)
{
if (item->selectionNext)
{
Item_RunScript(item, item->selectionNext);
return qtrue;
}
return qfalse;
}
//JLFDPADSCRIPT MPMOVED
/*
-----------------------------------------
Item_HandleSelectionPrev
If Item has an selectionPrev script, run it.
-------------------------------------------
*/
qboolean Item_HandleSelectionPrev(itemDef_t * item)
{
if (item->selectionPrev)
{
Item_RunScript(item, item->selectionPrev);
return qtrue;
}
return qfalse;
}
/*
=================
Item_Action
=================
*/
void Item_Action(itemDef_t *item)
{
if (item)
{
Item_RunScript(item, item->action);
}
}
/*
=================
Menu_HandleKey
=================
*/
void Menu_HandleKey(menuDef_t *menu, int key, qboolean down)
{
int i;
itemDef_t *item = NULL;
qboolean inHandler = qfalse;
if (inHandler)
{
return;
}
inHandler = qtrue;
if (g_waitingForKey && down)
{
Item_Bind_HandleKey(g_bindItem, key, down);
inHandler = qfalse;
return;
}
if (g_editingField && down)
{
if (!Item_TextField_HandleKey(g_editItem, key))
{
g_editingField = qfalse;
g_editItem = NULL;
inHandler = qfalse;
return;
}
else if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3)
{
g_editingField = qfalse;
g_editItem = NULL;
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
}
else if (key == A_TAB || key == A_CURSOR_UP || key == A_CURSOR_DOWN)
{
return;
}
}
if (menu == NULL)
{
inHandler = qfalse;
return;
}
//JLFMOUSE MPMOVED
// see if the mouse is within the window bounds and if so is this a mouse click
if (down && !(menu->window.flags & WINDOW_POPUP) && !Rect_ContainsPoint(&menu->window.rect, DC->cursorx, DC->cursory))
{
static qboolean inHandleKey = qfalse;
if (!inHandleKey && (key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3))
{
inHandleKey = qtrue;
Menus_HandleOOBClick(menu, key, down);
inHandleKey = qfalse;
inHandler = qfalse;
return;
}
}
// get the item with focus
for (i = 0; i < menu->itemCount; i++)
{
if (menu->items[i]->window.flags & WINDOW_HASFOCUS)
{
item = menu->items[i];
break;
}
}
// Ignore if disabled
if (item && item->disabled)
{
return;
}
if (item != NULL)
{
if (Item_HandleKey(item, key, down))
//JLFLISTBOX
{
// It is possible for an item to be disable after Item_HandleKey is run (like in Voice Chat)
if (!item->disabled)
{
Item_Action(item);
}
inHandler = qfalse;
return;
}
}
if (!down)
{
inHandler = qfalse;
return;
}
// Special Data Pad key handling (gotta love the datapad)
if (!(key & K_CHAR_FLAG) )
{ //only check keys not chars
char b[256];
DC->getBindingBuf( key, b, 256 );
if (Q_stricmp(b,"datapad") == 0) // They hit the datapad key again.
{
if (( Q_stricmp(menu->window.name,"datapadMissionMenu") == 0) ||
(Q_stricmp(menu->window.name,"datapadWeaponsMenu") == 0) ||
(Q_stricmp(menu->window.name,"datapadForcePowersMenu") == 0) ||
(Q_stricmp(menu->window.name,"datapadInventoryMenu") == 0))
{
key = A_ESCAPE; //pop on outta here
}
}
}
// default handling
switch ( key )
{
case A_F11:
if (DC->getCVarValue("developer"))
{
uis.debugMode = (qboolean)!uis.debugMode;
}
break;
case A_F12:
if (DC->getCVarValue("developer"))
{
switch ( DC->screenshotFormat )
{
case SSF_JPEG:
DC->executeText(EXEC_APPEND, "screenshot\n");
break;
case SSF_TGA:
DC->executeText(EXEC_APPEND, "screenshot_tga\n");
break;
case SSF_PNG:
DC->executeText(EXEC_APPEND, "screenshot_png\n");
break;
default:
if (DC->Print) {
DC->Print(S_COLOR_YELLOW "Menu_HandleKey[F12]: Unknown screenshot format assigned! This should not happen.\n");
}
break;
}
}
break;
case A_KP_8:
case A_CURSOR_UP:
Menu_SetPrevCursorItem(menu);
break;
case A_ESCAPE:
if (!g_waitingForKey && menu->onESC)
{
itemDef_t it;
it.parent = menu;
Item_RunScript(&it, menu->onESC);
}
break;
case A_TAB:
case A_KP_2:
case A_CURSOR_DOWN:
Menu_SetNextCursorItem(menu);
break;
case A_MOUSE1:
case A_MOUSE2:
if (item)
{
if (item->type == ITEM_TYPE_TEXT)
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
{
if ( item->action )
Item_Action(item);
else
{
if (menu->onAccept)
{
itemDef_t it;
it.parent = menu;
Item_RunScript(&it, menu->onAccept);
}
}
}
}
else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD)
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
{
item->cursorPos = 0;
g_editingField = qtrue;
g_editItem = item;
//DC->setOverstrikeMode(qtrue);
}
}
//JLFACCEPT
// add new types here as needed
/* Notes:
Most controls will use the dpad to move through the selection possibilies. Buttons are the only exception.
Buttons will be assumed to all be on one menu together. If the start or A button is pressed on a control focus, that
means that the menu is accepted and move onto the next menu. If the start or A button is pressed on a button focus it
should just process the action and not support the accept functionality.
*/
//JLFACCEPT
else if ( item->type == ITEM_TYPE_MULTI || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_SLIDER)
{
if (Item_HandleAccept(item))
{
//Item processed it overriding the menu processing
return;
}
else if (menu->onAccept)
{
itemDef_t it;
it.parent = menu;
Item_RunScript(&it, menu->onAccept);
}
}
//END JLFACCEPT
else
{
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
{
Item_Action(item);
}
}
}
else if (menu->onAccept)
{
itemDef_t it;
it.parent = menu;
Item_RunScript(&it, menu->onAccept);
}
break;
case A_JOY0:
case A_JOY1:
case A_JOY2:
case A_JOY3:
case A_JOY4:
case A_AUX0:
case A_AUX1:
case A_AUX2:
case A_AUX3:
case A_AUX4:
case A_AUX5:
case A_AUX6:
case A_AUX7:
case A_AUX8:
case A_AUX9:
case A_AUX10:
case A_AUX11:
case A_AUX12:
case A_AUX13:
case A_AUX14:
case A_AUX15:
case A_AUX16:
break;
case A_KP_ENTER:
case A_ENTER:
if (item)
{
if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD)
{
item->cursorPos = 0;
g_editingField = qtrue;
g_editItem = item;
//DC->setOverstrikeMode(qtrue);
}
else
{
Item_Action(item);
}
}
break;
}
inHandler = qfalse;
}
/*
=================
ParseRect
=================
*/
qboolean ParseRect(const char **p, rectDef_t *r)
{
if (!COM_ParseFloat(p, &r->x))
{
if (!COM_ParseFloat(p, &r->y))
{
if (!COM_ParseFloat(p, &r->w))
{
if (!COM_ParseFloat(p, &r->h))
{
return qtrue;
}
}
}
}
return qfalse;
}
/*
=================
Menus_HideItems
=================
*/
void Menus_HideItems(const char *menuName)
{
menuDef_t *menu;
int i;
menu =Menus_FindByName(menuName); // Get menu
if (!menu)
{
Com_Printf(S_COLOR_YELLOW"WARNING: No menu was found. Could not hide items.\n");
return;
}
menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
for (i = 0; i < menu->itemCount; i++)
{
menu->items[i]->cvarFlags = CVAR_HIDE;
}
}
/*
=================
Menus_ShowItems
=================
*/
void Menus_ShowItems(const char *menuName)
{
menuDef_t *menu;
int i;
menu =Menus_FindByName(menuName); // Get menu
if (!menu)
{
Com_Printf(S_COLOR_YELLOW"WARNING: No menu was found. Could not show items.\n");
return;
}
menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
for (i = 0; i < menu->itemCount; i++)
{
menu->items[i]->cvarFlags = CVAR_SHOW;
}
}
/*
=================
UI_Cursor_Show
=================
*/
void UI_Cursor_Show(qboolean flag)
{
DC->cursorShow = flag;
if ((DC->cursorShow != qtrue) && (DC->cursorShow != qfalse))
{
DC->cursorShow = qtrue;
}
}