summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/ui_gameinfo.c2
-rw-r--r--src/ui/ui_local.h3
-rw-r--r--src/ui/ui_main.c708
-rw-r--r--src/ui/ui_shared.c1444
-rw-r--r--src/ui/ui_shared.h27
5 files changed, 1252 insertions, 932 deletions
diff --git a/src/ui/ui_gameinfo.c b/src/ui/ui_gameinfo.c
index 43639e56..ad31218e 100644
--- a/src/ui/ui_gameinfo.c
+++ b/src/ui/ui_gameinfo.c
@@ -303,7 +303,7 @@ char *UI_GetBotNameByNumber( int num ) {
if (info) {
return Info_ValueForKey( info, "name" );
}
- return "Sarge";
+ return "";
}
void UI_ServerInfo( void )
diff --git a/src/ui/ui_local.h b/src/ui/ui_local.h
index ff8367ba..5f5ea862 100644
--- a/src/ui/ui_local.h
+++ b/src/ui/ui_local.h
@@ -865,6 +865,9 @@ typedef struct {
int humanBuildCount;
int humanBuildIndex;
+ int weapons;
+ int upgrades;
+
serverStatus_t serverStatus;
// for the showing the status of a server
diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
index 768008f6..edecd280 100644
--- a/src/ui/ui_main.c
+++ b/src/ui/ui_main.c
@@ -250,7 +250,7 @@ void _UI_DrawRect( float x, float y, float width, float height, float size, cons
-int Text_Width(const char *text, float scale, int limit) {
+float Text_Width(const char *text, float scale, int limit) {
int count,len;
float out;
glyphInfo_t *glyph;
@@ -265,7 +265,7 @@ int Text_Width(const char *text, float scale, int limit) {
useScale = scale * font->glyphScale;
out = 0;
if (text) {
- len = strlen(text);
+ len = Q_PrintStrlen( text );
if (limit > 0 && len > limit) {
len = limit;
}
@@ -285,7 +285,7 @@ int Text_Width(const char *text, float scale, int limit) {
return out * useScale;
}
-int Text_Height(const char *text, float scale, int limit) {
+float Text_Height(const char *text, float scale, int limit) {
int len, count;
float max;
glyphInfo_t *glyph;
@@ -322,6 +322,16 @@ int Text_Height(const char *text, float scale, int limit) {
return max * useScale;
}
+float Text_EmWidth( float scale )
+{
+ return Text_Width( "M", scale, 0 );
+}
+
+float Text_EmHeight( float scale )
+{
+ return Text_Height( "M", scale, 0 );
+}
+
void Text_PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, qhandle_t hShader) {
float w, h;
w = width * scale;
@@ -353,8 +363,6 @@ void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, f
count = 0;
while (s && *s && count < len) {
glyph = &font->glyphs[(int)*s];
- //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top;
- //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height);
if ( Q_IsColorString( s ) ) {
memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
newColor[3] = color[3];
@@ -455,6 +463,7 @@ void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, f
}
}
+//FIXME: merge this with Text_Paint, somehow
void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style) {
int len, count;
vec4_t newColor;
@@ -480,88 +489,12 @@ void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const cha
glyph2 = &font->glyphs[ (int) cursor];
while (s && *s && count < len) {
glyph = &font->glyphs[(int)*s];
- if ( Q_IsColorString( s ) ) {
- memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
- newColor[3] = color[3];
- trap_R_SetColor( newColor );
- s += 2;
- continue;
- } else {
- yadj = useScale * glyph->top;
- if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
- int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
- colorBlack[3] = newColor[3];
- trap_R_SetColor( colorBlack );
- Text_PaintChar(x + ofs, y - yadj + ofs,
- glyph->imageWidth,
- glyph->imageHeight,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph);
- colorBlack[3] = 1.0;
- trap_R_SetColor( newColor );
- }
- else if( style == ITEM_TEXTSTYLE_NEON )
- {
- vec4_t glow, outer, inner, white;
-
- glow[ 0 ] = newColor[ 0 ] * 0.5;
- glow[ 1 ] = newColor[ 1 ] * 0.5;
- glow[ 2 ] = newColor[ 2 ] * 0.5;
- glow[ 3 ] = newColor[ 3 ] * 0.2;
-
- outer[ 0 ] = newColor[ 0 ];
- outer[ 1 ] = newColor[ 1 ];
- outer[ 2 ] = newColor[ 2 ];
- outer[ 3 ] = newColor[ 3 ];
-
- inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5;
- inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5;
- inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5;
- inner[ 3 ] = newColor[ 3 ];
-
- white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f;
-
- trap_R_SetColor( glow );
- Text_PaintChar( x - 1.5, y - yadj - 1.5,
- glyph->imageWidth + 3,
- glyph->imageHeight + 3,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( outer );
- Text_PaintChar( x - 1, y - yadj - 1,
- glyph->imageWidth + 2,
- glyph->imageHeight + 2,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( inner );
- Text_PaintChar( x - 0.5, y - yadj - 0.5,
- glyph->imageWidth + 1,
- glyph->imageHeight + 1,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( white );
- }
-
- Text_PaintChar(x, y - yadj,
+ yadj = useScale * glyph->top;
+ if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
+ int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
+ colorBlack[3] = newColor[3];
+ trap_R_SetColor( colorBlack );
+ Text_PaintChar(x + ofs, y - yadj + ofs,
glyph->imageWidth,
glyph->imageHeight,
useScale,
@@ -570,25 +503,92 @@ void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const cha
glyph->s2,
glyph->t2,
glyph->glyph);
+ colorBlack[3] = 1.0;
+ trap_R_SetColor( newColor );
+ }
+ else if( style == ITEM_TEXTSTYLE_NEON )
+ {
+ vec4_t glow, outer, inner, white;
+
+ glow[ 0 ] = newColor[ 0 ] * 0.5;
+ glow[ 1 ] = newColor[ 1 ] * 0.5;
+ glow[ 2 ] = newColor[ 2 ] * 0.5;
+ glow[ 3 ] = newColor[ 3 ] * 0.2;
+
+ outer[ 0 ] = newColor[ 0 ];
+ outer[ 1 ] = newColor[ 1 ];
+ outer[ 2 ] = newColor[ 2 ];
+ outer[ 3 ] = newColor[ 3 ];
+
+ inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5;
+ inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5;
+ inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5;
+ inner[ 3 ] = newColor[ 3 ];
+
+ white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f;
+
+ trap_R_SetColor( glow );
+ Text_PaintChar( x - 1.5, y - yadj - 1.5,
+ glyph->imageWidth + 3,
+ glyph->imageHeight + 3,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ trap_R_SetColor( outer );
+ Text_PaintChar( x - 1, y - yadj - 1,
+ glyph->imageWidth + 2,
+ glyph->imageHeight + 2,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ trap_R_SetColor( inner );
+ Text_PaintChar( x - 0.5, y - yadj - 0.5,
+ glyph->imageWidth + 1,
+ glyph->imageHeight + 1,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ trap_R_SetColor( white );
+ }
- // CG_DrawPic(x, y - yadj, scale * uiDC.Assets.textFont.glyphs[text[i]].imageWidth, scale * uiDC.Assets.textFont.glyphs[text[i]].imageHeight, uiDC.Assets.textFont.glyphs[text[i]].glyph);
- yadj = useScale * glyph2->top;
- if (count == cursorPos && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
- Text_PaintChar(x, y - yadj,
- glyph2->imageWidth,
- glyph2->imageHeight,
- useScale,
- glyph2->s,
- glyph2->t,
- glyph2->s2,
- glyph2->t2,
- glyph2->glyph);
- }
-
- x += (glyph->xSkip * useScale);
- s++;
- count++;
+ Text_PaintChar(x, y - yadj,
+ glyph->imageWidth,
+ glyph->imageHeight,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph);
+
+ yadj = useScale * glyph2->top;
+ if (count == cursorPos && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
+ Text_PaintChar(x, y - yadj,
+ glyph2->imageWidth,
+ glyph2->imageHeight,
+ useScale,
+ glyph2->s,
+ glyph2->t,
+ glyph2->s2,
+ glyph2->t2,
+ glyph2->glyph);
}
+
+ x += (glyph->xSkip * useScale);
+ s++;
+ count++;
}
// need to paint cursor at end of text
if (cursorPos == len && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
@@ -611,62 +611,6 @@ void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const cha
}
-static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
- int len, count;
- vec4_t newColor;
- glyphInfo_t *glyph;
- if (text) {
- const char *s = text;
- float max = *maxX;
- float useScale;
- fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
- if (scale <= ui_smallFont.value) {
- font = &uiInfo.uiDC.Assets.smallFont;
- } else if (scale > ui_bigFont.value) {
- font = &uiInfo.uiDC.Assets.bigFont;
- }
- useScale = scale * font->glyphScale;
- trap_R_SetColor( color );
- len = strlen(text);
- if (limit > 0 && len > limit) {
- len = limit;
- }
- count = 0;
- while (s && *s && count < len) {
- glyph = &font->glyphs[(int)*s];
- if ( Q_IsColorString( s ) ) {
- memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
- newColor[3] = color[3];
- trap_R_SetColor( newColor );
- s += 2;
- continue;
- } else {
- float yadj = useScale * glyph->top;
- if (Text_Width(s, useScale, 1) + x > max) {
- *maxX = 0;
- break;
- }
- Text_PaintChar(x, y - yadj,
- glyph->imageWidth,
- glyph->imageHeight,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph);
- x += (glyph->xSkip * useScale) + adjust;
- *maxX = x;
- count++;
- s++;
- }
- }
- trap_R_SetColor( NULL );
- }
-
-}
-
-
void UI_ShowPostGame(qboolean newHigh) {
trap_Cvar_Set ("cg_cameraOrbit", "0");
trap_Cvar_Set("cg_thirdPerson", "0");
@@ -1079,6 +1023,8 @@ void UI_Load( void ) {
String_Init();
UI_LoadMenus("ui/menus.txt", qtrue);
+ UI_LoadMenus("ui/ingame.txt", qfalse);
+ UI_LoadMenus("ui/tremulous.txt", qfalse);
Menus_CloseAll();
Menus_ActivateByName(lastName);
@@ -1214,44 +1160,34 @@ UI_DrawInfoPane
===============
*/
static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, float text_y,
- float scale, vec4_t color, int textStyle )
+ float scale, int textalign, int textvalign, vec4_t color, int textStyle )
{
- float maxLeft = 0, maxTop = 0;
- float maxRight = 0, maxBottom = 0;
- float x = rect->x - text_x, y = rect->y - text_y, w, h;
- menuDef_t dummyParent;
- itemDef_t textItem;
- int value = 0;
- char *string = "";
- int class, credits;
- char ui_currentClass[ MAX_STRING_CHARS ];
+ int value = 0;
+ const char *s = "";
+ char *string = "";
+ int class, credits;
+ char ui_currentClass[ MAX_STRING_CHARS ];
trap_Cvar_VariableStringBuffer( "ui_currentClass", ui_currentClass, MAX_STRING_CHARS );
sscanf( ui_currentClass, "%d %d", &class, &credits );
- //offset the text
- x = rect->x + maxLeft;
- y = rect->y + maxTop;
- w = rect->w - ( maxLeft + maxRight + 16 + ( 2 * text_x ) ); //16 to ensure text within frame
- h = rect->h - ( maxTop + maxBottom );
-
switch( item->type )
{
case INFOTYPE_TEXT:
- textItem.text = item->v.text;
+ s = item->v.text;
break;
case INFOTYPE_CLASS:
value = BG_ClassCanEvolveFromTo( class, item->v.pclass, credits, 0 );
if( value < 1 )
{
- textItem.text = va( "%s\n\n%s",
+ s = va( "%s\n\n%s",
BG_FindHumanNameForClassNum( item->v.pclass ),
BG_FindInfoForClassNum( item->v.pclass ) );
}
else
{
- textItem.text = va( "%s\n\n%s\n\nKills: %d",
+ s = va( "%s\n\n%s\n\nKills: %d",
BG_FindHumanNameForClassNum( item->v.pclass ),
BG_FindInfoForClassNum( item->v.pclass ),
value );
@@ -1262,13 +1198,13 @@ static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, fl
value = BG_FindPriceForWeapon( item->v.weapon );
if( value == 0 )
{
- textItem.text = va( "%s\n\n%s\n\nCredits: Free",
+ s = va( "%s\n\n%s\n\nCredits: Free",
BG_FindHumanNameForWeapon( item->v.weapon ),
BG_FindInfoForWeapon( item->v.weapon ) );
}
else
{
- textItem.text = va( "%s\n\n%s\n\nCredits: %d",
+ s = va( "%s\n\n%s\n\nCredits: %d",
BG_FindHumanNameForWeapon( item->v.weapon ),
BG_FindInfoForWeapon( item->v.weapon ),
value );
@@ -1279,13 +1215,13 @@ static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, fl
value = BG_FindPriceForUpgrade( item->v.upgrade );
if( value == 0 )
{
- textItem.text = va( "%s\n\n%s\n\nCredits: Free",
+ s = va( "%s\n\n%s\n\nCredits: Free",
BG_FindHumanNameForUpgrade( item->v.upgrade ),
BG_FindInfoForUpgrade( item->v.upgrade ) );
}
else
{
- textItem.text = va( "%s\n\n%s\n\nCredits: %d",
+ s = va( "%s\n\n%s\n\nCredits: %d",
BG_FindHumanNameForUpgrade( item->v.upgrade ),
BG_FindInfoForUpgrade( item->v.upgrade ),
value );
@@ -1303,13 +1239,13 @@ static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, fl
if( value == 0 )
{
- textItem.text = va( "%s\n\n%s",
+ s = va( "%s\n\n%s",
BG_FindHumanNameForBuildable( item->v.buildable ),
BG_FindInfoForBuildable( item->v.buildable ) );
}
else
{
- textItem.text = va( "%s\n\n%s\n\n%s: %d",
+ s = va( "%s\n\n%s\n\n%s: %d",
BG_FindHumanNameForBuildable( item->v.buildable ),
BG_FindInfoForBuildable( item->v.buildable ),
string, value );
@@ -1317,30 +1253,8 @@ static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, fl
break;
}
- textItem.parent = &dummyParent;
- memcpy( textItem.window.foreColor, color, sizeof( vec4_t ) );
- textItem.window.flags = 0;
-
- textItem.window.rect.x = x;
- textItem.window.rect.y = y;
- textItem.window.rect.w = w;
- textItem.window.rect.h = h;
- textItem.window.borderSize = 0;
- textItem.textRect.x = 0;
- textItem.textRect.y = 0;
- textItem.textRect.w = 0;
- textItem.textRect.h = 0;
- textItem.textalignment = ITEM_ALIGN_LEFT;
- textItem.textalignx = text_x;
- textItem.textaligny = text_y;
- textItem.textscale = scale;
- textItem.textStyle = textStyle;
-
- textItem.enableCvar = NULL;
- textItem.cvarTest = NULL;
-
- //hack to utilise existing autowrap code
- Item_Text_AutoWrapped_Paint( &textItem );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale,
+ textalign, textvalign, textStyle, s );
}
@@ -1502,13 +1416,6 @@ static void UI_DrawPlayerModel(rectDef_t *rect) {
}
-static void UI_DrawNetSource(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
- if (ui_netSource.integer < 0 || ui_netSource.integer > numNetSources) {
- ui_netSource.integer = 0;
- }
- Text_Paint(rect->x, rect->y, scale, color, va("Source: %s", netSources[ui_netSource.integer]), 0, 0, textStyle);
-}
-
static void UI_DrawNetMapPreview(rectDef_t *rect, float scale, vec4_t color) {
if (uiInfo.serverStatus.currentServerPreview > 0) {
@@ -1535,14 +1442,6 @@ static void UI_DrawNetMapCinematic(rectDef_t *rect, float scale, vec4_t color) {
-static void UI_DrawNetFilter(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
- if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
- ui_serverFilterType.integer = 0;
- }
- Text_Paint(rect->x, rect->y, scale, color, va("Filter: %s", serverFilters[ui_serverFilterType.integer].description), 0, 0, textStyle);
-}
-
-
static void UI_DrawTier(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
int i;
i = trap_Cvar_VariableValue( "ui_currentTier" );
@@ -1789,6 +1688,63 @@ static void UI_DrawOpponentName(rectDef_t *rect, float scale, vec4_t color, int
Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_opponentName"), 0, 0, textStyle);
}
+static const char *UI_OwnerDrawText(int ownerDraw) {
+ const char *s = NULL;
+
+ switch( ownerDraw )
+ {
+ case UI_NETSOURCE:
+ if (ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources) {
+ ui_netSource.integer = 0;
+ }
+ s = netSources[ui_netSource.integer];
+ break;
+
+ case UI_NETFILTER:
+ if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
+ ui_serverFilterType.integer = 0;
+ }
+ s = serverFilters[ui_serverFilterType.integer].description;
+ break;
+
+ case UI_KEYBINDSTATUS:
+ if (Display_KeyBindPending()) {
+ s = "Waiting for new key... Press ESCAPE to cancel";
+ } else {
+ s = "Press ENTER or CLICK to change, Press BACKSPACE to clear";
+ }
+ break;
+
+ case UI_SERVERREFRESHDATE:
+ if (uiInfo.serverStatus.refreshActive) {
+#define MAX_DOTS 5
+ int numServers = trap_LAN_GetServerCount( ui_netSource.integer );
+ int numDots = ( uiInfo.uiDC.realTime / 500 ) % ( MAX_DOTS + 1 );
+ char dots[ MAX_DOTS + 1 ];
+ int i;
+
+ for( i = 0; i < numDots; i++ )
+ dots[ i ] = '.';
+
+ dots[ i ] = '\0';
+
+ s = numServers < 0 ? va( "Waiting for response%s", dots ) :
+ va("Getting info for %d servers (ESC to cancel)%s", numServers, dots );
+ } else {
+ s = va("Refresh Time: %s", UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)));
+ }
+ break;
+
+ case UI_SERVERMOTD:
+ s = uiInfo.serverStatus.motd;
+ break;
+
+ default:
+ break;
+ }
+
+ return s;
+}
static int UI_OwnerDrawWidth(int ownerDraw, float scale) {
int i, h, value;
@@ -1866,16 +1822,11 @@ static int UI_OwnerDrawWidth(int ownerDraw, float scale) {
s = va("%i. %s", ownerDraw-UI_REDTEAM1 + 1, text);
break;
case UI_NETSOURCE:
- if (ui_netSource.integer < 0 || ui_netSource.integer > uiInfo.numJoinGameTypes) {
- ui_netSource.integer = 0;
- }
- s = va("Source: %s", netSources[ui_netSource.integer]);
- break;
case UI_NETFILTER:
- if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
- ui_serverFilterType.integer = 0;
- }
- s = va("Filter: %s", serverFilters[ui_serverFilterType.integer].description );
+ case UI_KEYBINDSTATUS:
+ case UI_SERVERREFRESHDATE:
+ case UI_SERVERMOTD:
+ s = UI_OwnerDrawText( ownerDraw );
break;
case UI_TIER:
break;
@@ -1891,16 +1842,6 @@ static int UI_OwnerDrawWidth(int ownerDraw, float scale) {
break;
case UI_OPPONENT_NAME:
break;
- case UI_KEYBINDSTATUS:
- if (Display_KeyBindPending()) {
- s = "Waiting for new key... Press ESCAPE to cancel";
- } else {
- s = "Press ENTER or CLICK to change, Press BACKSPACE to clear";
- }
- break;
- case UI_SERVERREFRESHDATE:
- s = UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer));
- break;
default:
break;
}
@@ -2015,193 +1956,75 @@ static void UI_DrawSelectedPlayer(rectDef_t *rect, float scale, vec4_t color, in
Text_Paint(rect->x, rect->y, scale, color, name, 0, 0, textStyle);
}
-static void UI_DrawServerRefreshDate(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
- if (uiInfo.serverStatus.refreshActive) {
- vec4_t lowLight, newColor;
- int numServers = trap_LAN_GetServerCount( ui_netSource.integer );
-
- lowLight[0] = 0.8 * color[0];
- lowLight[1] = 0.8 * color[1];
- lowLight[2] = 0.8 * color[2];
- lowLight[3] = 0.8 * color[3];
- LerpColor(color,lowLight,newColor,0.5+0.5*sin(uiInfo.uiDC.realTime / PULSE_DIVISOR));
- Text_Paint(rect->x, rect->y, scale, newColor,
- numServers < 0 ? "Waiting for response..." :
- va("Getting info for %d servers (ESC to cancel)", numServers), 0, 0, textStyle);
- } else {
- char buff[64];
- Q_strncpyz(buff, UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)), 64);
- Text_Paint(rect->x, rect->y, scale, color, va("Refresh Time: %s", buff), 0, 0, textStyle);
- }
-}
-
-static void UI_DrawServerMOTD(rectDef_t *rect, float scale, vec4_t color) {
- if (uiInfo.serverStatus.motdLen) {
- float maxX;
-
- if (uiInfo.serverStatus.motdWidth == -1) {
- uiInfo.serverStatus.motdWidth = 0;
- uiInfo.serverStatus.motdPaintX = rect->x + 1;
- uiInfo.serverStatus.motdPaintX2 = -1;
- }
-
- if (uiInfo.serverStatus.motdOffset > uiInfo.serverStatus.motdLen) {
- uiInfo.serverStatus.motdOffset = 0;
- uiInfo.serverStatus.motdPaintX = rect->x + 1;
- uiInfo.serverStatus.motdPaintX2 = -1;
- }
-
- if (uiInfo.uiDC.realTime > uiInfo.serverStatus.motdTime) {
- uiInfo.serverStatus.motdTime = uiInfo.uiDC.realTime + 10;
- if (uiInfo.serverStatus.motdPaintX <= rect->x + 2) {
- if (uiInfo.serverStatus.motdOffset < uiInfo.serverStatus.motdLen) {
- uiInfo.serverStatus.motdPaintX += Text_Width(&uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], scale, 1) - 1;
- uiInfo.serverStatus.motdOffset++;
- } else {
- uiInfo.serverStatus.motdOffset = 0;
- if (uiInfo.serverStatus.motdPaintX2 >= 0) {
- uiInfo.serverStatus.motdPaintX = uiInfo.serverStatus.motdPaintX2;
- } else {
- uiInfo.serverStatus.motdPaintX = rect->x + rect->w - 2;
- }
- uiInfo.serverStatus.motdPaintX2 = -1;
- }
- } else {
- //serverStatus.motdPaintX--;
- uiInfo.serverStatus.motdPaintX -= 2;
- if (uiInfo.serverStatus.motdPaintX2 >= 0) {
- //serverStatus.motdPaintX2--;
- uiInfo.serverStatus.motdPaintX2 -= 2;
- }
- }
- }
-
- maxX = rect->x + rect->w - 2;
- Text_Paint_Limit(&maxX, uiInfo.serverStatus.motdPaintX, rect->y + rect->h - 3, scale, color, &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], 0, 0);
- if (uiInfo.serverStatus.motdPaintX2 >= 0) {
- float maxX2 = rect->x + rect->w - 2;
- Text_Paint_Limit(&maxX2, uiInfo.serverStatus.motdPaintX2, rect->y + rect->h - 3, scale, color, uiInfo.serverStatus.motd, 0, uiInfo.serverStatus.motdOffset);
- }
- if (uiInfo.serverStatus.motdOffset && maxX > 0) {
- // if we have an offset ( we are skipping the first part of the string ) and we fit the string
- if (uiInfo.serverStatus.motdPaintX2 == -1) {
- uiInfo.serverStatus.motdPaintX2 = rect->x + rect->w - 2;
- }
- } else {
- uiInfo.serverStatus.motdPaintX2 = -1;
- }
-
- }
-}
-
-static void UI_DrawKeyBindStatus(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
- if (Display_KeyBindPending()) {
- Text_Paint(rect->x, rect->y, scale, color, "Waiting for new key... Press ESCAPE to cancel", 0, 0, textStyle);
- } else {
- Text_Paint(rect->x, rect->y, scale, color, "Press ENTER or CLICK to change, Press BACKSPACE to clear", 0, 0, textStyle);
- }
-}
-
-static void UI_DrawGLInfo(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
- char * eptr;
- char buff[1024];
- const char *lines[64];
- int y, numLines, i;
-
- Text_Paint(rect->x + 2, rect->y, scale, color, va("VENDOR: %s", uiInfo.uiDC.glconfig.vendor_string), 0, 30, textStyle);
- Text_Paint(rect->x + 2, rect->y + 15, scale, color, va("VERSION: %s: %s", uiInfo.uiDC.glconfig.version_string,uiInfo.uiDC.glconfig.renderer_string), 0, 30, textStyle);
- Text_Paint(rect->x + 2, rect->y + 30, scale, color, va ("PIXELFORMAT: color(%d-bits) Z(%d-bits) stencil(%d-bits)", uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits, uiInfo.uiDC.glconfig.stencilBits), 0, 30, textStyle);
-
- // build null terminated extension strings
- // in TA this was not directly crashing, but displaying a nasty broken shader right in the middle
- // brought down the string size to 1024, there's not much that can be shown on the screen anyway
- Q_strncpyz(buff, uiInfo.uiDC.glconfig.extensions_string, 1024);
- eptr = buff;
- y = rect->y + 45;
- numLines = 0;
- while ( y < rect->y + rect->h && *eptr )
- {
- while ( *eptr && *eptr == ' ' )
- *eptr++ = '\0';
-
- // track start of valid string
- if (*eptr && *eptr != ' ') {
- lines[numLines++] = eptr;
- }
-
- while ( *eptr && *eptr != ' ' )
- eptr++;
- }
-
- i = 0;
- while (i < numLines) {
- Text_Paint(rect->x + 2, y, scale, color, lines[i++], 0, 20, textStyle);
- if (i < numLines) {
- Text_Paint(rect->x + rect->w / 2, y, scale, color, lines[i++], 0, 20, textStyle);
- }
- y += 10;
- if (y > rect->y + rect->h - 11) {
- break;
- }
- }
+static void UI_DrawGLInfo( rectDef_t *rect, float scale, int textalign, int textvalign,
+ vec4_t color, int textStyle, float text_x, float text_y) {
+ char buffer[ 4096 ];
+ Com_sprintf( buffer, sizeof( buffer ), "VENDOR: %s\nVERSION: %s\n"
+ "PIXELFORMAT: color(%d-bits) Z(%d-bits) stencil(%d-bits)\n%s",
+ uiInfo.uiDC.glconfig.vendor_string, uiInfo.uiDC.glconfig.renderer_string,
+ uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits,
+ uiInfo.uiDC.glconfig.stencilBits, uiInfo.uiDC.glconfig.extensions_string );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale,
+ textalign, textvalign, textStyle, buffer );
}
// FIXME: table drive
//
static void UI_OwnerDraw( float x, float y, float w, float h,
float text_x, float text_y, int ownerDraw,
- int ownerDrawFlags, int align, float special,
+ int ownerDrawFlags, int align,
+ int textalign, int textvalign, float special,
float scale, vec4_t color, qhandle_t shader, int textStyle )
{
rectDef_t rect;
- rect.x = x + text_x;
- rect.y = y + text_y;
+ rect.x = x;
+ rect.y = y;
rect.w = w;
rect.h = h;
switch( ownerDraw )
{
case UI_TEAMINFOPANE:
- UI_DrawInfoPane( &uiInfo.tremTeamList[ uiInfo.tremTeamIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.tremTeamList[ uiInfo.tremTeamIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_ACLASSINFOPANE:
- UI_DrawInfoPane( &uiInfo.alienClassList[ uiInfo.alienClassIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.alienClassList[ uiInfo.alienClassIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_AUPGRADEINFOPANE:
- UI_DrawInfoPane( &uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_HITEMINFOPANE:
- UI_DrawInfoPane( &uiInfo.humanItemList[ uiInfo.humanItemIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.humanItemList[ uiInfo.humanItemIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_HBUYINFOPANE:
- UI_DrawInfoPane( &uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_HSELLINFOPANE:
- UI_DrawInfoPane( &uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_ABUILDINFOPANE:
- UI_DrawInfoPane( &uiInfo.alienBuildList[ uiInfo.alienBuildIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.alienBuildList[ uiInfo.alienBuildIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_HBUILDINFOPANE:
- UI_DrawInfoPane( &uiInfo.humanBuildList[ uiInfo.humanBuildIndex ],
- &rect, text_x, text_y, scale, color, textStyle );
+ UI_DrawInfoPane( &uiInfo.humanBuildList[ uiInfo.humanBuildIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
case UI_HANDICAP:
@@ -2229,7 +2052,7 @@ static void UI_OwnerDraw( float x, float y, float w, float h,
UI_DrawNetGameType(&rect, scale, color, textStyle);
break;
case UI_JOINGAMETYPE:
- UI_DrawJoinGameType(&rect, scale, color, textStyle);
+ UI_DrawJoinGameType(&rect, scale, color, textStyle);
break;
case UI_MAPPREVIEW:
UI_DrawMapPreview(&rect, scale, color, qtrue);
@@ -2266,18 +2089,12 @@ static void UI_OwnerDraw( float x, float y, float w, float h,
case UI_REDTEAM5:
UI_DrawTeamMember(&rect, scale, color, qfalse, ownerDraw - UI_REDTEAM1 + 1, textStyle);
break;
- case UI_NETSOURCE:
- UI_DrawNetSource(&rect, scale, color, textStyle);
- break;
case UI_NETMAPPREVIEW:
UI_DrawNetMapPreview(&rect, scale, color);
break;
case UI_NETMAPCINEMATIC:
UI_DrawNetMapCinematic(&rect, scale, color);
break;
- case UI_NETFILTER:
- UI_DrawNetFilter(&rect, scale, color, textStyle);
- break;
case UI_TIER:
UI_DrawTier(&rect, scale, color, textStyle);
break;
@@ -2344,17 +2161,8 @@ static void UI_OwnerDraw( float x, float y, float w, float h,
case UI_SELECTEDPLAYER:
UI_DrawSelectedPlayer(&rect, scale, color, textStyle);
break;
- case UI_SERVERREFRESHDATE:
- UI_DrawServerRefreshDate(&rect, scale, color, textStyle);
- break;
- case UI_SERVERMOTD:
- UI_DrawServerMOTD(&rect, scale, color);
- break;
case UI_GLINFO:
- UI_DrawGLInfo(&rect,scale, color, textStyle);
- break;
- case UI_KEYBINDSTATUS:
- UI_DrawKeyBindStatus(&rect,scale, color, textStyle);
+ UI_DrawGLInfo(&rect, scale, textalign, textvalign, color, textStyle, text_x, text_y);
break;
default:
break;
@@ -3096,7 +2904,7 @@ static void UI_LoadHumanItems( void )
UI_ParseCarriageList
===============
*/
-static void UI_ParseCarriageList( int *weapons, int *upgrades )
+static void UI_ParseCarriageList( void )
{
int i;
char carriageCvar[ MAX_TOKEN_CHARS ];
@@ -3107,11 +2915,8 @@ static void UI_ParseCarriageList( int *weapons, int *upgrades )
trap_Cvar_VariableStringBuffer( "ui_carriage", carriageCvar, sizeof( carriageCvar ) );
iterator = carriageCvar;
- if( weapons )
- *weapons = 0;
-
- if( upgrades )
- *upgrades = 0;
+ uiInfo.weapons = 0;
+ uiInfo.upgrades = 0;
//simple parser to give rise to weapon/upgrade list
while( iterator && iterator[ 0 ] != '$' )
@@ -3129,8 +2934,7 @@ static void UI_ParseCarriageList( int *weapons, int *upgrades )
i = atoi( buffer );
- if( weapons )
- *weapons |= ( 1 << i );
+ uiInfo.weapons |= ( 1 << i );
}
else if( iterator[ 0 ] == 'U' )
{
@@ -3143,8 +2947,7 @@ static void UI_ParseCarriageList( int *weapons, int *upgrades )
i = atoi( buffer );
- if( upgrades )
- *upgrades |= ( 1 << i );
+ uiInfo.upgrades |= ( 1 << i );
}
iterator++;
@@ -3160,20 +2963,19 @@ static void UI_LoadHumanArmouryBuys( void )
{
int i, j = 0;
stage_t stage = UI_GetCurrentHumanStage( );
- int weapons, upgrades;
int slots = 0;
- UI_ParseCarriageList( &weapons, &upgrades );
+ UI_ParseCarriageList( );
for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
{
- if( weapons & ( 1 << i ) )
+ if( uiInfo.weapons & ( 1 << i ) )
slots |= BG_FindSlotsForWeapon( i );
}
for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
{
- if( upgrades & ( 1 << i ) )
+ if( uiInfo.upgrades & ( 1 << i ) )
slots |= BG_FindSlotsForUpgrade( i );
}
@@ -3186,12 +2988,12 @@ static void UI_LoadHumanArmouryBuys( void )
BG_FindStagesForWeapon( i, stage ) &&
BG_WeaponIsAllowed( i ) &&
!( BG_FindSlotsForWeapon( i ) & slots ) &&
- !( weapons & ( 1 << i ) ) )
+ !( uiInfo.weapons & ( 1 << i ) ) )
{
uiInfo.humanArmouryBuyList[ j ].text =
String_Alloc( BG_FindHumanNameForWeapon( i ) );
uiInfo.humanArmouryBuyList[ j ].cmd =
- String_Alloc( va( "cmd buy %s retrigger\n", BG_FindNameForWeapon( i ) ) );
+ String_Alloc( va( "cmd buy %s\n", BG_FindNameForWeapon( i ) ) );
uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_WEAPON;
uiInfo.humanArmouryBuyList[ j ].v.weapon = i;
@@ -3208,12 +3010,12 @@ static void UI_LoadHumanArmouryBuys( void )
BG_FindStagesForUpgrade( i, stage ) &&
BG_UpgradeIsAllowed( i ) &&
!( BG_FindSlotsForUpgrade( i ) & slots ) &&
- !( upgrades & ( 1 << i ) ) )
+ !( uiInfo.upgrades & ( 1 << i ) ) )
{
uiInfo.humanArmouryBuyList[ j ].text =
String_Alloc( BG_FindHumanNameForUpgrade( i ) );
uiInfo.humanArmouryBuyList[ j ].cmd =
- String_Alloc( va( "cmd buy %s retrigger\n", BG_FindNameForUpgrade( i ) ) );
+ String_Alloc( va( "cmd buy %s\n", BG_FindNameForUpgrade( i ) ) );
uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_UPGRADE;
uiInfo.humanArmouryBuyList[ j ].v.upgrade = i;
@@ -3231,19 +3033,18 @@ UI_LoadHumanArmourySells
*/
static void UI_LoadHumanArmourySells( void )
{
- int weapons, upgrades;
int i, j = 0;
uiInfo.humanArmourySellCount = 0;
- UI_ParseCarriageList( &weapons, &upgrades );
+ UI_ParseCarriageList( );
for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
{
- if( weapons & ( 1 << i ) )
+ if( uiInfo.weapons & ( 1 << i ) )
{
uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForWeapon( i ) );
uiInfo.humanArmourySellList[ j ].cmd =
- String_Alloc( va( "cmd sell %s retrigger\n", BG_FindNameForWeapon( i ) ) );
+ String_Alloc( va( "cmd sell %s\n", BG_FindNameForWeapon( i ) ) );
uiInfo.humanArmourySellList[ j ].type = INFOTYPE_WEAPON;
uiInfo.humanArmourySellList[ j ].v.weapon = i;
@@ -3255,11 +3056,11 @@ static void UI_LoadHumanArmourySells( void )
for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
{
- if( upgrades & ( 1 << i ) )
+ if( uiInfo.upgrades & ( 1 << i ) )
{
uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForUpgrade( i ) );
uiInfo.humanArmourySellList[ j ].cmd =
- String_Alloc( va( "cmd sell %s retrigger\n", BG_FindNameForUpgrade( i ) ) );
+ String_Alloc( va( "cmd sell %s\n", BG_FindNameForUpgrade( i ) ) );
uiInfo.humanArmourySellList[ j ].type = INFOTYPE_UPGRADE;
uiInfo.humanArmourySellList[ j ].v.upgrade = i;
@@ -3272,6 +3073,26 @@ static void UI_LoadHumanArmourySells( void )
/*
===============
+UI_ArmouryRefreshCb
+===============
+*/
+static void UI_ArmouryRefreshCb( void *data )
+{
+ int oldWeapons = uiInfo.weapons;
+ int oldUpgrades = uiInfo.upgrades;
+
+ UI_ParseCarriageList( );
+
+ if( uiInfo.weapons != oldWeapons || uiInfo.upgrades != oldUpgrades )
+ {
+ UI_LoadHumanArmouryBuys( );
+ UI_LoadHumanArmourySells( );
+ UI_RemoveCaptureFunc( );
+ }
+}
+
+/*
+===============
UI_LoadAlienUpgrades
===============
*/
@@ -3313,19 +3134,18 @@ UI_LoadAlienBuilds
*/
static void UI_LoadAlienBuilds( void )
{
- int weapons;
int i, j = 0;
stage_t stage;
- UI_ParseCarriageList( &weapons, NULL );
+ UI_ParseCarriageList( );
stage = UI_GetCurrentAlienStage( );
uiInfo.alienBuildCount = 0;
- for( i = BA_NONE +1; i < BA_NUM_BUILDABLES; i++ )
+ for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ )
{
if( BG_FindTeamForBuildable( i ) == BIT_ALIENS &&
- BG_FindBuildWeaponForBuildable( i ) & weapons &&
+ BG_FindBuildWeaponForBuildable( i ) & uiInfo.weapons &&
BG_FindStagesForBuildable( i, stage ) &&
BG_BuildableIsAllowed( i ) )
{
@@ -3350,19 +3170,18 @@ UI_LoadHumanBuilds
*/
static void UI_LoadHumanBuilds( void )
{
- int weapons;
int i, j = 0;
stage_t stage;
- UI_ParseCarriageList( &weapons, NULL );
+ UI_ParseCarriageList( );
stage = UI_GetCurrentHumanStage( );
uiInfo.humanBuildCount = 0;
- for( i = BA_NONE +1; i < BA_NUM_BUILDABLES; i++ )
+ for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ )
{
if( BG_FindTeamForBuildable( i ) == BIT_HUMANS &&
- BG_FindBuildWeaponForBuildable( i ) & weapons &&
+ BG_FindBuildWeaponForBuildable( i ) & uiInfo.weapons &&
BG_FindStagesForBuildable( i, stage ) &&
BG_BuildableIsAllowed( i ) )
{
@@ -3848,6 +3667,8 @@ static void UI_RunMenuScript(char **args) {
{
if( ( cmd = uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ].cmd ) )
trap_Cmd_ExecuteText( EXEC_APPEND, cmd );
+
+ UI_InstallCaptureFunc( UI_ArmouryRefreshCb, NULL, 1000 );
}
else if( Q_stricmp( name, "LoadHumanArmourySells" ) == 0 )
UI_LoadHumanArmourySells( );
@@ -3855,6 +3676,8 @@ static void UI_RunMenuScript(char **args) {
{
if( ( cmd = uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ].cmd ) )
trap_Cmd_ExecuteText( EXEC_APPEND, cmd );
+
+ UI_InstallCaptureFunc( UI_ArmouryRefreshCb, NULL, 1000 );
}
else if( Q_stricmp( name, "LoadAlienUpgrades" ) == 0 )
{
@@ -5366,6 +5189,8 @@ void _UI_Init( qboolean inGameLoad ) {
uiInfo.uiDC.drawText = &Text_Paint;
uiInfo.uiDC.textWidth = &Text_Width;
uiInfo.uiDC.textHeight = &Text_Height;
+ uiInfo.uiDC.textEmWidth = &Text_EmWidth;
+ uiInfo.uiDC.textEmHeight = &Text_EmHeight;
uiInfo.uiDC.registerModel = &trap_R_RegisterModel;
uiInfo.uiDC.modelBounds = &trap_R_ModelBounds;
uiInfo.uiDC.fillRect = &UI_FillRect;
@@ -5402,6 +5227,7 @@ void _UI_Init( qboolean inGameLoad ) {
uiInfo.uiDC.Print = &Com_Printf;
uiInfo.uiDC.Pause = &UI_Pause;
uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth;
+ uiInfo.uiDC.ownerDrawText = &UI_OwnerDrawText;
uiInfo.uiDC.registerSound = &trap_S_RegisterSound;
uiInfo.uiDC.startBackgroundTrack = &trap_S_StartBackgroundTrack;
uiInfo.uiDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack;
@@ -5974,6 +5800,7 @@ vmCvar_t ui_recordSPDemo;
vmCvar_t ui_realCaptureLimit;
vmCvar_t ui_realWarmUp;
vmCvar_t ui_serverStatusTimeOut;
+vmCvar_t ui_textWrapCache;
vmCvar_t ui_winner;
@@ -6100,6 +5927,7 @@ static cvarTable_t cvarTable[] = {
{ &ui_realWarmUp, "g_warmup", "20", CVAR_ARCHIVE},
{ &ui_realCaptureLimit, "capturelimit", "8", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART},
{ &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
+ { &ui_textWrapCache, "ui_textWrapCache", "1", CVAR_ARCHIVE },
};
static int cvarTableSize = sizeof(cvarTable) / sizeof(cvarTable[0]);
diff --git a/src/ui/ui_shared.c b/src/ui/ui_shared.c
index 0a8a3c25..3224b697 100644
--- a/src/ui/ui_shared.c
+++ b/src/ui/ui_shared.c
@@ -45,7 +45,8 @@ static scrollInfo_t scrollInfo;
void voidFunction( void *var ) { return; }
qboolean voidFunction2( itemDef_t *var1, int var2 ) { return qfalse; }
-static void (*captureFunc) (void *p) = voidFunction;
+static CaptureFunc *captureFunc = voidFunction;
+static int captureFuncExpiry = 0;
static void *captureData = NULL;
static itemDef_t *itemCapture = NULL; // item that has the mouse captured ( if any )
@@ -77,6 +78,34 @@ itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
+/*
+===============
+UI_InstallCaptureFunc
+===============
+*/
+void UI_InstallCaptureFunc( CaptureFunc *f, void *data, int timeout )
+{
+ captureFunc = f;
+ captureData = data;
+
+ if( timeout > 0 )
+ captureFuncExpiry = DC->realTime + timeout;
+ else
+ captureFuncExpiry = 0;
+}
+
+/*
+===============
+UI_RemoveCaptureFunc
+===============
+*/
+void UI_RemoveCaptureFunc( void )
+{
+ captureFunc = voidFunction;
+ captureData = NULL;
+ captureFuncExpiry = 0;
+}
+
#ifdef CGAME
#define MEM_POOL_SIZE 128 * 1024
#else
@@ -333,6 +362,238 @@ qboolean Float_Parse(char **p, float *f) {
}
}
+#define MAX_EXPR_ELEMENTS 32
+
+typedef enum
+{
+ EXPR_OPERATOR,
+ EXPR_VALUE
+} exprType_t;
+
+typedef struct exprToken_s
+{
+ exprType_t type;
+ union
+ {
+ char op;
+ float val;
+ } u;
+} exprToken_t;
+
+typedef struct exprList_s
+{
+ exprToken_t l[ MAX_EXPR_ELEMENTS ];
+ int f, b;
+} exprList_t;
+
+/*
+=================
+OpPrec
+
+Return a value reflecting operator precedence
+=================
+*/
+static ID_INLINE int OpPrec( char op )
+{
+ switch( op )
+ {
+ case '*': return 4;
+ case '/': return 3;
+ case '+': return 2;
+ case '-': return 1;
+ case '(': return 0;
+ default: return -1;
+ }
+}
+
+/*
+=================
+PC_Expression_Parse
+=================
+*/
+static qboolean PC_Expression_Parse( int handle, float *f )
+{
+ pc_token_t token;
+ int unmatchedParentheses = 0;
+ exprList_t stack, fifo;
+ exprToken_t value;
+ qboolean expectingNumber = qtrue;
+
+#define FULL( a ) ( a.b >= ( MAX_EXPR_ELEMENTS - 1 ) )
+#define EMPTY( a ) ( a.f > a.b )
+
+#define PUSH_VAL( a, v ) \
+ { \
+ if( FULL( a ) ) \
+ return qfalse; \
+ a.b++; \
+ a.l[ a.b ].type = EXPR_VALUE; \
+ a.l[ a.b ].u.val = v; \
+ }
+
+#define PUSH_OP( a, o ) \
+ { \
+ if( FULL( a ) ) \
+ return qfalse; \
+ a.b++; \
+ a.l[ a.b ].type = EXPR_OPERATOR; \
+ a.l[ a.b ].u.op = o; \
+ }
+
+#define POP_STACK( a ) \
+ { \
+ if( EMPTY( a ) ) \
+ return qfalse; \
+ value = a.l[ a.b ]; \
+ a.b--; \
+ }
+
+#define PEEK_STACK_OP( a ) ( a.l[ a.b ].u.op )
+#define PEEK_STACK_VAL( a ) ( a.l[ a.b ].u.val )
+
+#define POP_FIFO( a ) \
+ { \
+ if( EMPTY( a ) ) \
+ return qfalse; \
+ value = a.l[ a.f ]; \
+ a.f++; \
+ }
+
+ stack.f = fifo.f = 0;
+ stack.b = fifo.b = -1;
+
+ while( trap_Parse_ReadToken( handle, &token ) )
+ {
+ if( !unmatchedParentheses && token.string[ 0 ] == ')' )
+ break;
+
+ // Special case to catch negative numbers
+ if( expectingNumber && token.string[ 0 ] == '-' )
+ {
+ if( !trap_Parse_ReadToken( handle, &token ) )
+ return qfalse;
+
+ token.floatvalue = -token.floatvalue;
+ }
+
+ if( token.type == TT_NUMBER )
+ {
+ if( !expectingNumber )
+ return qfalse;
+ expectingNumber = !expectingNumber;
+
+ PUSH_VAL( fifo, token.floatvalue );
+ }
+ else
+ {
+ switch( token.string[ 0 ] )
+ {
+ case '(':
+ unmatchedParentheses++;
+ PUSH_OP( stack, '(' );
+ break;
+
+ case ')':
+ unmatchedParentheses--;
+ if( unmatchedParentheses < 0 )
+ return qfalse;
+
+ while( !EMPTY( stack ) && PEEK_STACK_OP( stack ) != '(' )
+ {
+ POP_STACK( stack );
+ PUSH_OP( fifo, value.u.op );
+ }
+
+ // Pop the '('
+ POP_STACK( stack );
+ break;
+
+ case '*':
+ case '/':
+ case '+':
+ case '-':
+ if( expectingNumber )
+ return qfalse;
+ expectingNumber = !expectingNumber;
+
+ if( EMPTY( stack ) )
+ {
+ PUSH_OP( stack, token.string[ 0 ] );
+ }
+ else
+ {
+ while( !EMPTY( stack ) && OpPrec( token.string[ 0 ] ) < OpPrec( PEEK_STACK_OP( stack ) ) )
+ {
+ POP_STACK( stack );
+ PUSH_OP( fifo, value.u.op );
+ }
+
+ PUSH_OP( stack, token.string[ 0 ] );
+ }
+ break;
+
+ default:
+ // Unknown token
+ return qfalse;
+ }
+ }
+ }
+
+ while( !EMPTY( stack ) )
+ {
+ POP_STACK( stack );
+ PUSH_OP( fifo, value.u.op );
+ }
+
+ while( !EMPTY( fifo ) )
+ {
+ POP_FIFO( fifo );
+
+ if( value.type == EXPR_VALUE )
+ {
+ PUSH_VAL( stack, value.u.val );
+ }
+ else if( value.type == EXPR_OPERATOR )
+ {
+ char op = value.u.op;
+ float operand1, operand2, result;
+
+ POP_STACK( stack );
+ operand2 = value.u.val;
+ POP_STACK( stack );
+ operand1 = value.u.val;
+
+ switch( op )
+ {
+ case '*': result = operand1 * operand2; break;
+ case '/': result = operand1 / operand2; break;
+ case '+': result = operand1 + operand2; break;
+ case '-': result = operand1 - operand2; break;
+ default:
+ Com_Error( ERR_FATAL, "Unknown operator '%c' in postfix string", op );
+ return qfalse;
+ }
+
+ PUSH_VAL( stack, result );
+ }
+ }
+
+ POP_STACK( stack );
+
+ *f = value.u.val;
+
+ return qtrue;
+
+#undef FULL
+#undef EMPTY
+#undef PUSH_VAL
+#undef PUSH_OP
+#undef POP_STACK
+#undef PEEK_STACK_OP
+#undef PEEK_STACK_VAL
+#undef POP_FIFO
+}
+
/*
=================
PC_Float_Parse
@@ -344,6 +605,10 @@ qboolean PC_Float_Parse(int handle, float *f) {
if (!trap_Parse_ReadToken(handle, &token))
return qfalse;
+
+ if( token.string[ 0 ] == '(' )
+ return PC_Expression_Parse( handle, f );
+
if (token.string[0] == '-') {
if (!trap_Parse_ReadToken(handle, &token))
return qfalse;
@@ -424,6 +689,20 @@ qboolean PC_Int_Parse(int handle, int *i) {
if (!trap_Parse_ReadToken(handle, &token))
return qfalse;
+
+ if( token.string[ 0 ] == '(' )
+ {
+ float f;
+
+ if( PC_Expression_Parse( handle, &f ) )
+ {
+ *i = (int)f;
+ return qtrue;
+ }
+ else
+ return qfalse;
+ }
+
if (token.string[0] == '-') {
if (!trap_Parse_ReadToken(handle, &token))
return qfalse;
@@ -611,8 +890,7 @@ void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboo
-void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) {
- //float bordersize = 0;
+static void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) {
vec4_t color;
rectDef_t fillRect = w->rect;
@@ -669,6 +947,14 @@ void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle)
DC->drawCinematic(w->cinematic, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
}
}
+}
+
+static void Border_Paint(Window *w) {
+ vec4_t color;
+
+ if (w == NULL || (w->style == 0 && w->border == 0)) {
+ return;
+ }
if (w->border == WINDOW_BORDER_FULL) {
// full
@@ -706,7 +992,6 @@ void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle)
r.y = w->rect.y + w->rect.h - 1;
GradientBar_Paint(&r, w->borderColor);
}
-
}
@@ -1490,7 +1775,7 @@ float Item_Slider_ThumbPosition(itemDef_t *item) {
editFieldDef_t *editDef = item->typeData;
if (item->text) {
- x = item->textRect.x + item->textRect.w + 8;
+ x = item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET;
} else {
x = item->window.rect.x;
}
@@ -1510,21 +1795,29 @@ float Item_Slider_ThumbPosition(itemDef_t *item) {
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;
}
+static float Item_Slider_VScale( itemDef_t *item )
+{
+ if( SLIDER_THUMB_HEIGHT > item->window.rect.h )
+ return item->window.rect.h / SLIDER_THUMB_HEIGHT;
+ else
+ return 1.0f;
+}
+
int Item_Slider_OverSlider(itemDef_t *item, float x, float y) {
rectDef_t r;
+ float vScale = Item_Slider_VScale( item );
r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
- r.y = item->window.rect.y - 2;
+ r.y = item->textRect.y - item->textRect.h +
+ ( ( item->textRect.h - ( SLIDER_THUMB_HEIGHT * vScale ) ) / 2.0f );
r.w = SLIDER_THUMB_WIDTH;
- r.h = SLIDER_THUMB_HEIGHT;
+ r.h = SLIDER_THUMB_HEIGHT * vScale;
if (Rect_ContainsPoint(&r, x, y)) {
return WINDOW_LB_THUMB;
@@ -2058,148 +2351,182 @@ qboolean Item_Multi_HandleKey(itemDef_t *item, int key) {
return qfalse;
}
-qboolean Item_TextField_HandleKey(itemDef_t *item, int key) {
+#define MIN_FIELD_WIDTH 10
+#define EDIT_CURSOR_WIDTH 10
+
+static void Item_TextField_CalcPaintOffset( itemDef_t *item, char *buff )
+{
+ editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
+
+ if( item->cursorPos < editPtr->paintOffset )
+ {
+ editPtr->paintOffset = item->cursorPos;
+ }
+ else
+ {
+ // If there is a maximum field width
+ if( editPtr->maxFieldWidth > 0 )
+ {
+ // If the cursor is at the end of the string, maximise the amount of the
+ // string that's visible
+ if( buff[ item->cursorPos + 1 ] == '\0' )
+ {
+ while( DC->textWidth( &buff[ editPtr->paintOffset ], item->textscale, 0 ) <=
+ ( editPtr->maxFieldWidth - EDIT_CURSOR_WIDTH ) && editPtr->paintOffset > 0 )
+ editPtr->paintOffset--;
+ }
+
+ buff[ item->cursorPos + 1 ] = '\0';
+
+ // Shift paintOffset so that the cursor is visible
+ while( DC->textWidth( &buff[ editPtr->paintOffset ], item->textscale, 0 ) >
+ ( editPtr->maxFieldWidth - EDIT_CURSOR_WIDTH ) )
+ editPtr->paintOffset++;
+ }
+ }
+}
+
+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;
+ qboolean releaseFocus = qtrue;
- if (item->cvar) {
+ if( item->cvar )
+ {
+ Com_Memset( buff, 0, sizeof( buff ) );
+ DC->getCVarString( item->cvar, buff, sizeof( buff ) );
+ len = strlen( buff );
- memset(buff, 0, sizeof(buff));
- DC->getCVarString(item->cvar, buff, sizeof(buff));
- len = strlen(buff);
- if (editPtr->maxChars && len > editPtr->maxChars) {
+ if( editPtr->maxChars && len > editPtr->maxChars )
len = editPtr->maxChars;
- }
- if ( key & K_CHAR_FLAG ) {
- key &= ~K_CHAR_FLAG;
+ if( key & K_CHAR_FLAG )
+ {
+ key &= ~K_CHAR_FLAG;
- if (key == 'h' - 'a' + 1 ) { // ctrl-h is backspace
- if ( item->cursorPos > 0 ) {
+ 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;
- }
+ else if( key < 32 || !item->cvar )
+ {
+ // Ignore any non printable chars
+ releaseFocus = qfalse;
+ goto exit;
+ }
+ else if( item->type == ITEM_TYPE_NUMERICFIELD && ( key < '0' || key > '9' ) )
+ {
+ // Ignore non-numeric characters
+ releaseFocus = qfalse;
+ goto exit;
}
+ else
+ {
+ if (!DC->getOverstrikeMode())
+ {
+ if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars))
+ {
+ // Reached maximum field length
+ releaseFocus = qfalse;
+ goto exit;
+ }
- 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 );
}
- memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
- } else {
- if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars) {
- return qtrue;
+ else
+ {
+ // Reached maximum field length
+ if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars)
+ releaseFocus = qfalse;
+ goto exit;
}
- }
- buff[item->cursorPos] = key;
+ buff[ item->cursorPos ] = key;
- DC->setCVar(item->cvar, buff);
+ DC->setCVar( item->cvar, buff );
- if (item->cursorPos < len + 1) {
- item->cursorPos++;
- if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars) {
- editPtr->paintOffset++;
- }
+ if( item->cursorPos < len + 1 )
+ item->cursorPos++;
}
+ }
+ else
+ {
+ switch( key )
+ {
+ case K_DEL:
+ case K_KP_DEL:
+ if( item->cursorPos < len )
+ {
+ memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
+ DC->setCVar(item->cvar, buff);
+ }
+ break;
- } else {
-
- if ( key == K_DEL || key == K_KP_DEL ) {
- if ( item->cursorPos < len ) {
- memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
- DC->setCVar(item->cvar, buff);
- }
- return qtrue;
- }
+ case K_RIGHTARROW:
+ case K_KP_RIGHTARROW:
+ if( item->cursorPos < len )
+ item->cursorPos++;
+ break;
- if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW )
- {
- if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len) {
- item->cursorPos++;
- editPtr->paintOffset++;
- return qtrue;
- }
- if (item->cursorPos < len) {
- item->cursorPos++;
- }
- return qtrue;
- }
+ case K_LEFTARROW:
+ case K_KP_LEFTARROW:
+ if( item->cursorPos > 0 )
+ item->cursorPos--;
+ break;
- if ( key == K_LEFTARROW || key == K_KP_LEFTARROW )
- {
- if ( item->cursorPos > 0 ) {
- item->cursorPos--;
- }
- if (item->cursorPos < editPtr->paintOffset) {
- editPtr->paintOffset--;
- }
- return qtrue;
- }
+ case K_HOME:
+ case K_KP_HOME:
+ item->cursorPos = 0;
+ break;
- if ( key == K_HOME || key == K_KP_HOME) {// || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) {
- item->cursorPos = 0;
- editPtr->paintOffset = 0;
- return qtrue;
- }
+ case K_END:
+ case K_KP_END:
+ item->cursorPos = len;
+ break;
- if ( key == K_END || key == K_KP_END) {// ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) {
- item->cursorPos = len;
- if(item->cursorPos > editPtr->maxPaintChars) {
- editPtr->paintOffset = len - editPtr->maxPaintChars;
- }
- return qtrue;
- }
+ case K_INS:
+ case K_KP_INS:
+ DC->setOverstrikeMode(!DC->getOverstrikeMode());
+ break;
- if ( key == K_INS || key == K_KP_INS ) {
- DC->setOverstrikeMode(!DC->getOverstrikeMode());
- return qtrue;
- }
- }
+ case K_TAB:
+ case K_DOWNARROW:
+ case K_KP_DOWNARROW:
+ case K_UPARROW:
+ case K_KP_UPARROW:
+ newItem = Menu_SetNextCursorItem(item->parent);
+ if( newItem && ( newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD ) )
+ g_editItem = newItem;
+ break;
- if (key == K_TAB || key == K_DOWNARROW || key == K_KP_DOWNARROW) {
- newItem = Menu_SetNextCursorItem(item->parent);
- if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
- g_editItem = newItem;
- }
- }
+ case K_ENTER:
+ case K_KP_ENTER:
+ case K_ESCAPE:
+ releaseFocus = qtrue;
+ goto exit;
- if (key == K_UPARROW || key == K_KP_UPARROW) {
- newItem = Menu_SetPrevCursorItem(item->parent);
- if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
- g_editItem = newItem;
+ default:
+ break;
}
}
- if ( key == K_ENTER || key == K_KP_ENTER || key == K_ESCAPE) {
- return qfalse;
- }
-
- return qtrue;
+ releaseFocus = qfalse;
}
- return qfalse;
+exit:
+ Item_TextField_CalcPaintOffset( item, buff );
+
+ return !releaseFocus;
}
static void Scroll_ListBox_AutoFunc(void *p) {
@@ -2287,7 +2614,7 @@ static void Scroll_Slider_ThumbFunc(void *p) {
editFieldDef_t *editDef = si->item->typeData;
if (si->item->text) {
- x = si->item->textRect.x + si->item->textRect.w + 8;
+ x = si->item->textRect.x + si->item->textRect.w + ITEM_VALUE_OFFSET;
} else {
x = si->item->window.rect.x;
}
@@ -2308,6 +2635,11 @@ static void Scroll_Slider_ThumbFunc(void *p) {
void Item_StartCapture(itemDef_t *item, int key) {
int flags;
+
+ // Don't allow captureFunc to be overridden
+ if( captureFunc != voidFunction )
+ return;
+
switch (item->type) {
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
@@ -2322,16 +2654,14 @@ void Item_StartCapture(itemDef_t *item, int key) {
scrollInfo.scrollKey = key;
scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
scrollInfo.item = item;
- captureData = &scrollInfo;
- captureFunc = &Scroll_ListBox_AutoFunc;
+ UI_InstallCaptureFunc( Scroll_ListBox_AutoFunc, &scrollInfo, 0 );
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;
+ UI_InstallCaptureFunc( Scroll_ListBox_ThumbFunc, &scrollInfo, 0 );
itemCapture = item;
}
break;
@@ -2344,8 +2674,7 @@ void Item_StartCapture(itemDef_t *item, int key) {
scrollInfo.item = item;
scrollInfo.xStart = DC->cursorx;
scrollInfo.yStart = DC->cursory;
- captureData = &scrollInfo;
- captureFunc = &Scroll_Slider_ThumbFunc;
+ UI_InstallCaptureFunc( Scroll_Slider_ThumbFunc, &scrollInfo, 0 );
itemCapture = item;
}
break;
@@ -2367,7 +2696,7 @@ qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down) {
rectDef_t testRect;
width = SLIDER_WIDTH;
if (item->text) {
- x = item->textRect.x + item->textRect.w + 8;
+ x = item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET;
} else {
x = item->window.rect.x;
}
@@ -2399,8 +2728,7 @@ qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) {
if (itemCapture) {
Item_StopCapture(itemCapture);
itemCapture = NULL;
- captureFunc = voidFunction;
- captureData = NULL;
+ UI_RemoveCaptureFunc( );
} else {
if ( down && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
Item_StartCapture(item, key);
@@ -2750,10 +3078,15 @@ void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
}
} 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;
+ char buffer[ MAX_STRING_CHARS ] = { 0 };
+
+ if( item->cvar )
+ DC->getCVarString( item->cvar, buffer, sizeof( buffer ) );
+
+ item->cursorPos = strlen( buffer );
+ Item_TextField_CalcPaintOffset( item, buffer );
g_editingField = qtrue;
g_editItem = item;
- DC->setOverstrikeMode(qtrue);
}
} else {
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
@@ -2788,10 +3121,15 @@ void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
case K_ENTER:
if (item) {
if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
- item->cursorPos = 0;
+ char buffer[ MAX_STRING_CHARS ] = { 0 };
+
+ if( item->cvar )
+ DC->getCVarString( item->cvar, buffer, sizeof( buffer ) );
+
+ item->cursorPos = strlen( buffer );
+ Item_TextField_CalcPaintOffset( item, buffer );
g_editingField = qtrue;
g_editItem = item;
- DC->setOverstrikeMode(qtrue);
} else {
Item_Action(item);
}
@@ -2826,26 +3164,37 @@ void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *t
// keeps us from computing the widths and heights more than once
if (*width == 0 || (item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER)) {
- int originalWidth = DC->textWidth(item->text, item->textscale, 0);
+ int originalWidth;
- 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) {
+ if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar) {
+ //FIXME: this will only be called once?
char buff[256];
DC->getCVarString(item->cvar, buff, 256);
- originalWidth += DC->textWidth(buff, item->textscale, 0);
+ originalWidth = DC->textWidth(item->text, item->textscale, 0) +
+ DC->textWidth(buff, item->textscale, 0);
+ } else {
+ originalWidth = DC->textWidth(item->text, item->textscale, 0);
}
*width = DC->textWidth(textPtr, item->textscale, 0);
*height = DC->textHeight(textPtr, item->textscale, 0);
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;
+
+ if (item->textvalignment == ITEM_VALIGN_BOTTOM) {
+ item->textRect.y = item->textaligny + item->window.rect.h;
+ } else if (item->textvalignment == ITEM_VALIGN_CENTER) {
+ item->textRect.y = item->textaligny + ( ( *height + item->window.rect.h ) / 2.0f );
+ } else if (item->textvalignment == ITEM_VALIGN_TOP) {
+ item->textRect.y = item->textaligny + *height;
+ }
+
+ if (item->textalignment == ITEM_ALIGN_LEFT) {
+ item->textRect.x = item->textalignx;
} else if (item->textalignment == ITEM_ALIGN_CENTER) {
- item->textRect.x = item->textalignx - originalWidth / 2;
+ item->textRect.x = item->textalignx + ( ( item->window.rect.w - originalWidth ) / 2.0f );
+ } else if (item->textalignment == ITEM_ALIGN_RIGHT) {
+ item->textRect.x = item->textalignx + item->window.rect.w - originalWidth;
}
ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
@@ -2878,140 +3227,215 @@ void Item_TextColor(itemDef_t *item, vec4_t *newColor) {
}
}
-int Item_Text_AutoWrapped_Lines( itemDef_t *item )
+static const char *Item_Text_Wrap( const char *text, float scale, float width )
{
- char text[ 1024 ];
- const char *p, *textPtr, *newLinePtr;
- char buff[ 1024 ];
- int len, textWidth, newLine;
- int lines = 0;
+ static char out[ 8192 ];
+ char *paint = out;
+ char c[ 3 ];
+ const char *p = text;
+ const char *eol;
+ const char *q = NULL, *qMinus1 = NULL;
+ unsigned int testLength;
+ unsigned int i;
- textWidth = 0;
- newLinePtr = NULL;
+ if( strlen( text ) >= sizeof( out ) )
+ return NULL;
- if( item->text == NULL )
+ *paint = '\0';
+
+ while( *p )
{
- if( item->cvar == NULL )
- return 0;
- else
+ Com_Memset( c, 0, sizeof( c ) );
+
+ // Skip leading whitespace
+ while( *p )
{
- DC->getCVarString( item->cvar, text, sizeof( text ) );
- textPtr = text;
+ if( Q_IsColorString( p ) )
+ {
+ c[ 0 ] = p[ 0 ];
+ c[ 1 ] = p[ 1 ];
+ p += 2;
+ }
+ else if( *p != '\n' && isspace( *p ) )
+ p++;
+ else
+ break;
}
- }
- else
- textPtr = item->text;
- if( *textPtr == '\0' )
- return 0;
-
- len = 0;
- buff[ 0 ] = '\0';
- newLine = 0;
- p = textPtr;
+ if( !*p )
+ break;
- while( p )
- {
- textWidth = DC->textWidth( buff, item->textscale, 0 );
+ testLength = 1;
+ eol = p;
- if( *p == ' ' || *p == '\t' || *p == '\n' || *p == '\0' )
+ while( DC->textWidth( p, scale, testLength ) < width )
{
- newLine = len;
- newLinePtr = p + 1;
- }
+ if( testLength >= strlen( p ) )
+ {
+ eol = p + strlen( p );
+ break;
+ }
- // forceably split lines that are too long (where normal splitage has failed)
- if( textWidth > item->window.rect.w && newLine == 0 && *p != '\n' )
- {
- newLine = len;
- newLinePtr = p;
- }
+ // Point q at the end of the current testLength
+ q = p;
+ for( i = 0; i < testLength; )
+ {
+ // Skip color escapes
+ while( Q_IsColorString( q ) )
+ {
+ q += 2;
+ continue;
+ }
- if( ( newLine && textWidth > item->window.rect.w ) || *p == '\n' || *p == '\0' )
- {
- if( len )
- buff[ newLine ] = '\0';
+ qMinus1 = q;
+ q++;
+ i++;
+ }
- if( !( *p == '\n' && !*( p + 1 ) ) )
- lines++;
+ // Some color escapes might still be present
+ while( Q_IsColorString( q ) )
+ q += 2;
- if( *p == '\0' )
+ // Manual line break
+ if( *q == '\n' )
+ {
+ eol = q + 1;
break;
+ }
- //
- p = newLinePtr;
- len = 0;
- newLine = 0;
+ if( !isspace( *qMinus1 ) && isspace( *q ) )
+ eol = q;
- continue;
+ testLength++;
}
- buff[ len++ ] = *p++;
- buff[ len ] = '\0';
+ // No split has taken place, so just split mid-word
+ if( eol == p )
+ eol = q;
+
+ // Add colour code (might be empty)
+ Q_strcat( out, sizeof( out ), c );
+ paint = out + strlen( out );
+
+ // Copy text
+ strncpy( paint, p, eol - p );
+ paint[ eol - p ] = '\0';
+
+ // Add a \n if it's not there already
+ if( out[ strlen( out ) - 1 ] != '\n' )
+ Q_strcat( out, sizeof( out ), "\n" );
+
+ paint = out + strlen( out );
+ p = eol;
}
- return lines;
+ return out;
}
-#define MAX_AUTOWRAP_CACHE 16
-#define MAX_AUTOWRAP_LINES 32
-#define MAX_AUTOWRAP_TEXT 512
+#define MAX_WRAP_CACHE 16
+#define MAX_WRAP_LINES 32
+#define MAX_WRAP_TEXT 512
typedef struct
{
- //this is used purely for checking for cache hits
- char text[ MAX_AUTOWRAP_TEXT * MAX_AUTOWRAP_LINES ];
+ char text[ MAX_WRAP_TEXT * MAX_WRAP_LINES ]; //FIXME: augment with hash?
rectDef_t rect;
- int textWidth, textHeight;
- char lines[ MAX_AUTOWRAP_LINES ][ MAX_AUTOWRAP_TEXT ];
- int lineOffsets[ MAX_AUTOWRAP_LINES ][ 2 ];
+ float scale;
+ char lines[ MAX_WRAP_LINES ][ MAX_WRAP_TEXT ];
+ float lineCoords[ MAX_WRAP_LINES ][ 2 ];
int numLines;
-} autoWrapCache_t;
+} wrapCache_t;
-static int cacheIndex = 0;
-static autoWrapCache_t awc[ MAX_AUTOWRAP_CACHE ];
+static wrapCache_t wrapCache[ MAX_WRAP_CACHE ];
+static int cacheWriteIndex = 0;
+static int cacheReadIndex = 0;
+static int cacheReadLineNum = 0;
-static int checkCache( const char *text, rectDef_t *rect, int width, int height )
+static void UI_CreateCacheEntry( const char *text, rectDef_t *rect, float scale )
+{
+ wrapCache_t *cacheEntry = &wrapCache[ cacheWriteIndex ];
+
+ Q_strncpyz( cacheEntry->text, text, sizeof( cacheEntry->text ) );
+ cacheEntry->rect.x = rect->x;
+ cacheEntry->rect.y = rect->y;
+ cacheEntry->rect.w = rect->w;
+ cacheEntry->rect.h = rect->h;
+ cacheEntry->scale = scale;
+ cacheEntry->numLines = 0;
+}
+
+static void UI_AddCacheEntryLine( const char *text, float x, float y )
+{
+ wrapCache_t *cacheEntry = &wrapCache[ cacheWriteIndex ];
+
+ if( cacheEntry->numLines >= MAX_WRAP_LINES )
+ return;
+
+ Q_strncpyz( cacheEntry->lines[ cacheEntry->numLines ], text,
+ sizeof( cacheEntry->lines[ 0 ] ) );
+ cacheEntry->lineCoords[ cacheEntry->numLines ][ 0 ] = x;
+ cacheEntry->lineCoords[ cacheEntry->numLines ][ 1 ] = y;
+
+ cacheEntry->numLines++;
+}
+
+static void UI_FinishCacheEntry( void )
+{
+ cacheWriteIndex = ( cacheWriteIndex + 1 ) % MAX_WRAP_CACHE;
+}
+
+static qboolean UI_CheckWrapCache( const char *text, rectDef_t *rect, float scale )
{
int i;
- for( i = 0; i < MAX_AUTOWRAP_CACHE; i++ )
+ for( i = 0; i < MAX_WRAP_CACHE; i++ )
{
- if( Q_stricmp( text, awc[ i ].text ) )
+ wrapCache_t *cacheEntry = &wrapCache[ i ];
+
+ if( Q_stricmp( text, cacheEntry->text ) )
continue;
- if( rect->x != awc[ i ].rect.x ||
- rect->y != awc[ i ].rect.y ||
- rect->w != awc[ i ].rect.w ||
- rect->h != awc[ i ].rect.h )
+ if( rect->x != cacheEntry->rect.x ||
+ rect->y != cacheEntry->rect.y ||
+ rect->w != cacheEntry->rect.w ||
+ rect->h != cacheEntry->rect.h )
continue;
- if( awc[ i ].textWidth != width || awc[ i ].textHeight != height )
+ if( cacheEntry->scale != scale )
continue;
- //this is a match
- return i;
+ // This is a match
+ cacheReadIndex = i;
+ cacheReadLineNum = 0;
+ return qtrue;
}
- //no match - autowrap isn't cached
- return -1;
+ // No match - wrap isn't cached
+ return qfalse;
}
-void Item_Text_AutoWrapped_Paint( itemDef_t *item )
+static qboolean UI_NextWrapLine( const char **text, float *x, float *y )
+{
+ wrapCache_t *cacheEntry = &wrapCache[ cacheReadIndex ];
+
+ if( cacheReadLineNum >= cacheEntry->numLines )
+ return qfalse;
+
+ *text = cacheEntry->lines[ cacheReadLineNum ];
+ *x = cacheEntry->lineCoords[ cacheReadLineNum ][ 0 ];
+ *y = cacheEntry->lineCoords[ cacheReadLineNum ][ 1 ];
+
+ cacheReadLineNum++;
+
+ return qtrue;
+}
+
+void Item_Text_Wrapped_Paint( itemDef_t *item )
{
char text[ 1024 ];
- const char *p, *textPtr, *newLinePtr;
- char buff[ 1024 ];
- char lastCMod[ 2 ] = { 0, 0 };
- qboolean forwardColor = qfalse;
- int width, height, len, textWidth, newLine, newLineWidth;
- int skipLines, totalLines, lineNum = 0;
- float y, totalY, diffY;
+ const char *p, *textPtr;
+ float x, y, w, h;
vec4_t color;
- int cache, i;
-
- textWidth = 0;
- newLinePtr = NULL;
if( item->text == NULL )
{
@@ -3030,192 +3454,164 @@ void Item_Text_AutoWrapped_Paint( itemDef_t *item )
return;
Item_TextColor( item, &color );
- Item_SetTextExtents( item, &width, &height, textPtr );
- //check if this block is cached
- cache = checkCache( textPtr, &item->window.rect, width, height );
- if( cache >= 0 )
+ // Check if this block is cached
+ if( (qboolean)DC->getCVarValue( "ui_textWrapCache" ) &&
+ UI_CheckWrapCache( textPtr, &item->window.rect, item->textscale ) )
{
- lineNum = awc[ cache ].numLines;
-
- for( i = 0; i < lineNum; i++ )
+ while( UI_NextWrapLine( &p, &x, &y ) )
{
- item->textRect.x = awc[ cache ].lineOffsets[ i ][ 0 ];
- item->textRect.y = awc[ cache ].lineOffsets[ i ][ 1 ];
-
- DC->drawText( item->textRect.x, item->textRect.y, item->textscale, color,
- awc[ cache ].lines[ i ], 0, 0, item->textStyle );
+ DC->drawText( x, y, item->textscale, color,
+ p, 0, 0, item->textStyle );
}
}
else
{
- y = item->textaligny;
- len = 0;
- buff[ 0 ] = '\0';
- newLine = 0;
- newLineWidth = 0;
- p = textPtr;
+ char buff[ 1024 ];
+ float fontHeight = DC->textEmHeight( item->textscale );
+ const float lineSpacing = fontHeight * 0.4f;
+ float lineHeight = fontHeight + lineSpacing;
+ float textHeight;
+ int textLength;
+ int paintLines, totalLines, lineNum = 0;
+ float paintY;
+ int i;
+
+ UI_CreateCacheEntry( textPtr, &item->window.rect, item->textscale );
+
+ x = item->window.rect.x + item->textalignx;
+ y = item->window.rect.y + item->textaligny;
+ w = item->window.rect.w - ( 2.0f * item->textalignx );
+ h = item->window.rect.h - ( 2.0f * item->textaligny );
+
+ textPtr = Item_Text_Wrap( textPtr, item->textscale, w );
+ textLength = strlen( textPtr );
+
+ // Count lines
+ totalLines = 0;
+ for( i = 0; i < textLength; i++ )
+ {
+ if( textPtr[ i ] == '\n' )
+ totalLines++;
+ }
- totalLines = Item_Text_AutoWrapped_Lines( item );
+ paintLines = (int)floor( ( h + lineSpacing ) / lineHeight );
+ if( paintLines > totalLines )
+ paintLines = totalLines;
- totalY = totalLines * ( height + 5 );
- diffY = totalY - item->window.rect.h;
+ textHeight = ( paintLines * lineHeight ) - lineSpacing;
- if( diffY > 0.0f )
- skipLines = (int)( diffY / ( (float)height + 5.0f ) );
- else
- skipLines = 0;
-
- //set up a cache entry
- strcpy( awc[ cacheIndex ].text, textPtr );
- awc[ cacheIndex ].rect.x = item->window.rect.x;
- awc[ cacheIndex ].rect.y = item->window.rect.y;
- awc[ cacheIndex ].rect.w = item->window.rect.w;
- awc[ cacheIndex ].rect.h = item->window.rect.h;
- awc[ cacheIndex ].textWidth = width;
- awc[ cacheIndex ].textHeight = height;
-
- while( p )
+ switch( item->textvalignment )
{
- textWidth = DC->textWidth( buff, item->textscale, 0 );
-
- if( *p == '^' )
- {
- lastCMod[ 0 ] = p[ 0 ];
- lastCMod[ 1 ] = p[ 1 ];
- }
+ default:
+ case ITEM_VALIGN_BOTTOM:
+ paintY = y + ( h - textHeight );
+ break;
- if( *p == ' ' || *p == '\t' || *p == '\n' || *p == '\0' )
- {
- newLine = len;
- newLinePtr = p+1;
- newLineWidth = textWidth;
+ case ITEM_VALIGN_CENTER:
+ paintY = y + ( ( h - textHeight ) / 2.0f );
+ break;
- if( *p == '\n' ) //don't forward colours past deilberate \n's
- lastCMod[ 0 ] = lastCMod[ 1 ] = 0;
- else
- forwardColor = qtrue;
- }
+ case ITEM_VALIGN_TOP:
+ paintY = y;
+ break;
+ }
- // forceably split lines that are too long (where normal splitage has failed)
- if( textWidth > item->window.rect.w && newLine == 0 && *p != '\n' )
- {
- newLine = len;
- newLinePtr = p;
- newLineWidth = textWidth;
+ p = textPtr;
+ for( i = 0, lineNum = 0; i < textLength && lineNum < paintLines; i++ )
+ {
+ int lineLength = &textPtr[ i ] - p;
- forwardColor = qtrue;
- }
+ if( lineLength >= sizeof( buff ) - 1 )
+ break;
- if( ( newLine && textWidth > item->window.rect.w ) || *p == '\n' || *p == '\0' )
+ if( textPtr[ i ] == '\n' || textPtr[ i ] == '\0' )
{
- if( len )
+ itemDef_t lineItem;
+ int width, height;
+
+ strncpy( buff, p, lineLength );
+ buff[ lineLength ] = '\0';
+ p = &textPtr[ i + 1 ];
+
+ lineItem.type = ITEM_TYPE_TEXT;
+ lineItem.textscale = item->textscale;
+ lineItem.textStyle = item->textStyle;
+ lineItem.text = buff;
+ lineItem.textalignment = item->textalignment;
+ lineItem.textvalignment = ITEM_VALIGN_TOP;
+ lineItem.textalignx = 0.0f;
+ lineItem.textaligny = 0.0f;
+
+ lineItem.textRect.w = 0.0f;
+ lineItem.textRect.h = 0.0f;
+ lineItem.window.rect.x = x;
+ lineItem.window.rect.y = paintY + ( lineNum * lineHeight );
+ lineItem.window.rect.w = w;
+ lineItem.window.rect.h = lineHeight;
+ lineItem.window.border = item->window.border;
+ lineItem.window.borderSize = item->window.borderSize;
+
+ if( debugMode )
{
- 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( !skipLines )
- {
- DC->drawText( item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, 0, item->textStyle );
-
- strcpy( awc[ cacheIndex ].lines[ lineNum ], buff );
- awc[ cacheIndex ].lineOffsets[ lineNum ][ 0 ] = item->textRect.x;
- awc[ cacheIndex ].lineOffsets[ lineNum ][ 1 ] = item->textRect.y;
-
- lineNum++;
- }
+ vec4_t color;
+ color[ 0 ] = color[ 2 ] = color[ 3 ] = 1.0f;
+ color[ 1 ] = 0.0f;
+ DC->drawRect( lineItem.window.rect.x, lineItem.window.rect.y,
+ lineItem.window.rect.w, lineItem.window.rect.h, 1, color );
}
- if( *p == '\0' )
- break;
- //
- if( !skipLines )
- y += height + 5;
-
- if( skipLines )
- skipLines--;
-
- p = newLinePtr;
- len = 0;
- newLine = 0;
- newLineWidth = 0;
-
- if( forwardColor && lastCMod[ 0 ] != 0 )
- {
- buff[ len++ ] = lastCMod[ 0 ];
- buff[ len++ ] = lastCMod[ 1 ];
- buff[ len ] = '\0';
+ Item_SetTextExtents( &lineItem, &width, &height, buff );
+ DC->drawText( lineItem.textRect.x, lineItem.textRect.y,
+ lineItem.textscale, color, buff, 0, 0,
+ lineItem.textStyle );
+ UI_AddCacheEntryLine( buff, lineItem.textRect.x, lineItem.textRect.y );
- forwardColor = qfalse;
- }
-
- continue;
+ lineNum++;
}
-
- buff[ len++ ] = *p++;
- buff[ len ] = '\0';
}
- //mark the end of the lines list
- awc[ cacheIndex ].numLines = lineNum;
-
- //increment cacheIndex
- cacheIndex = ( cacheIndex + 1 ) % MAX_AUTOWRAP_CACHE;
+ UI_FinishCacheEntry( );
}
}
-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 == '\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, 0, item->textStyle);
- y += height + 5;
- start += p - start + 1;
- p = strchr(p+1, '\r');
- }
- DC->drawText(x, y, item->textscale, color, start, 0, 0, item->textStyle);
+/*
+==============
+UI_DrawTextBlock
+==============
+*/
+void UI_DrawTextBlock( rectDef_t *rect, float text_x, float text_y, vec4_t color,
+ float scale, int textalign, int textvalign,
+ int textStyle, const char *text )
+{
+ static menuDef_t dummyParent;
+ static itemDef_t textItem;
+
+ textItem.text = text;
+
+ textItem.parent = &dummyParent;
+ memcpy( textItem.window.foreColor, color, sizeof( vec4_t ) );
+ textItem.window.flags = 0;
+
+ textItem.window.rect.x = rect->x;
+ textItem.window.rect.y = rect->y;
+ textItem.window.rect.w = rect->w;
+ textItem.window.rect.h = rect->h;
+ textItem.window.border = 0;
+ textItem.window.borderSize = 0.0f;
+ textItem.textRect.x = 0.0f;
+ textItem.textRect.y = 0.0f;
+ textItem.textRect.w = 0.0f;
+ textItem.textRect.h = 0.0f;
+ textItem.textalignment = textalign;
+ textItem.textvalignment = textvalign;
+ textItem.textalignx = text_x;
+ textItem.textaligny = text_y;
+ textItem.textscale = scale;
+ textItem.textStyle = textStyle;
+
+ // Utilise existing wrap code
+ Item_Text_Wrapped_Paint( &textItem );
}
void Item_Text_Paint(itemDef_t *item) {
@@ -3228,10 +3624,6 @@ void Item_Text_Paint(itemDef_t *item) {
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) {
@@ -3290,38 +3682,64 @@ void Item_Text_Paint(itemDef_t *item) {
-//float trap_Cvar_VariableValue( const char *var_name );
-//void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
-
-void Item_TextField_Paint(itemDef_t *item) {
- char buff[1024];
- vec4_t newColor;
- int offset;
- menuDef_t *parent = (menuDef_t*)item->parent;
- editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
-
+void Item_TextField_Paint(itemDef_t *item)
+{
+ char buff[1024];
+ vec4_t newColor;
+ int offset = (item->text && *item->text) ? ITEM_VALUE_OFFSET : 0;
+ menuDef_t *parent = (menuDef_t*)item->parent;
+ editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
+ char cursor = DC->getOverstrikeMode() ? '|' : '_';
+ qboolean editing = ( item->window.flags & WINDOW_HASFOCUS && g_editingField );
+ const int cursorWidth = editing ? EDIT_CURSOR_WIDTH : 0;
+
+ //FIXME: causes duplicate printing if item->text is not set (NULL)
Item_Text_Paint(item);
buff[0] = '\0';
- if (item->cvar) {
+ if (item->cvar)
DC->getCVarString(item->cvar, buff, sizeof(buff));
+
+ // maxFieldWidth hasn't been set, so use the item's rect
+ if( editPtr->maxFieldWidth == 0 )
+ {
+ editPtr->maxFieldWidth = item->window.rect.w -
+ ( item->textRect.w + offset + ( item->textRect.x - item->window.rect.x ) );
+
+ if( editPtr->maxFieldWidth < MIN_FIELD_WIDTH )
+ editPtr->maxFieldWidth = MIN_FIELD_WIDTH;
}
+ if( !editing )
+ editPtr->paintOffset = 0;
+
+ // Shorten string to max viewable
+ while( DC->textWidth( buff + editPtr->paintOffset, item->textscale, 0 ) >
+ ( editPtr->maxFieldWidth - cursorWidth ) && strlen( buff ) > 0 )
+ buff[ strlen( buff ) - 1 ] = '\0';
+
parent = (menuDef_t*)item->parent;
- if (item->window.flags & WINDOW_HASFOCUS) {
+ if (item->window.flags & WINDOW_HASFOCUS)
memcpy(newColor, &parent->focusColor, sizeof(vec4_t));
- } else {
+ else
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
- }
- offset = (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->textStyle);
- } else {
- DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, 0, editPtr->maxPaintChars, item->textStyle);
+ if( editing )
+ {
+ 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->textStyle );
+ }
+ else
+ {
+ DC->drawText( item->textRect.x + item->textRect.w + offset,
+ item->textRect.y, item->textscale, newColor,
+ buff + editPtr->paintOffset, 0,
+ editPtr->maxPaintChars, item->textStyle );
}
}
@@ -3329,6 +3747,7 @@ void Item_TextField_Paint(itemDef_t *item) {
void Item_YesNo_Paint(itemDef_t *item) {
vec4_t newColor;
float value;
+ int offset;
menuDef_t *parent = (menuDef_t*)item->parent;
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
@@ -3339,9 +3758,10 @@ void Item_YesNo_Paint(itemDef_t *item) {
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
}
+ offset = (item->text && *item->text) ? ITEM_VALUE_OFFSET : 0;
if (item->text) {
Item_Text_Paint(item);
- DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
+ DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
} else {
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
}
@@ -3362,7 +3782,7 @@ void Item_Multi_Paint(itemDef_t *item) {
if (item->text) {
Item_Text_Paint(item);
- DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
+ DC->drawText(item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
} else {
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
}
@@ -3614,6 +4034,7 @@ void Item_Slider_Paint(itemDef_t *item) {
vec4_t newColor;
float x, y, value;
menuDef_t *parent = (menuDef_t*)item->parent;
+ float vScale = Item_Slider_VScale( item );
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
@@ -3623,18 +4044,25 @@ void Item_Slider_Paint(itemDef_t *item) {
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;
+ x = item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET;
+ y = item->textRect.y - item->textRect.h +
+ ( ( item->textRect.h - ( SLIDER_HEIGHT * vScale ) ) / 2.0f );
} else {
x = item->window.rect.x;
+ y = item->window.rect.y;
}
+
DC->setColor(newColor);
- DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
+ DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT * vScale, DC->Assets.sliderBar );
+
+ y = item->textRect.y - item->textRect.h +
+ ( ( item->textRect.h - ( SLIDER_THUMB_HEIGHT * vScale ) ) / 2.0f );
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,
+ SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT * vScale, DC->Assets.sliderThumb );
}
@@ -3671,7 +4099,7 @@ void Item_Bind_Paint(itemDef_t *item) {
if (item->text) {
Item_Text_Paint(item);
BindingFromName(item->cvar);
- DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, g_nameBind1, 0, maxChars, item->textStyle);
+ DC->drawText(item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET, item->textRect.y, item->textscale, newColor, g_nameBind1, 0, maxChars, item->textStyle);
} else {
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME" : "FIXME", 0, maxChars, item->textStyle);
}
@@ -3891,24 +4319,28 @@ void Item_ListBox_Paint(itemDef_t *item) {
count = DC->feederCount(item->special);
// default is vertical if horizontal flag is not here
if (item->window.flags & WINDOW_HORIZONTAL) {
- // draw scrollbar in bottom of the window
- // bar
- 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);
- //
- listPtr->endPos = listPtr->startPos;
+ if( !listPtr->notselectable )
+ {
+ // draw scrollbar in bottom of the window
+ // bar
+ 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);
+ //
+ listPtr->endPos = listPtr->startPos;
+ }
+
size = item->window.rect.w - 2;
// items
// size contains max available space
@@ -3941,23 +4373,26 @@ void Item_ListBox_Paint(itemDef_t *item) {
//
}
} else {
- // 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);
+ if( !listPtr->notselectable )
+ {
+ // 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);
+ }
// adjust size for item painting
size = item->window.rect.h - 2;
@@ -3987,6 +4422,7 @@ void Item_ListBox_Paint(itemDef_t *item) {
// fit++;
}
} else {
+ float m = DC->textEmHeight( item->textscale );
x = item->window.rect.x + 1;
y = item->window.rect.y + 1;
for (i = listPtr->startPos; i < count; i++) {
@@ -3999,14 +4435,16 @@ void Item_ListBox_Paint(itemDef_t *item) {
for (j = 0; j < listPtr->numColumns; j++) {
Q_strncpyz( text, DC->feederItemText(item->special, i, j, &optionalImage), sizeof( text ) );
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);
+ DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos,
+ y + ( ( listPtr->elementHeight - listPtr->columnInfo[ j ].width ) / 2.0f ),
+ listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
} else if (text) {
int alignOffset = 0.0f, tw;
tw = DC->textWidth( text, item->textscale, 0 );
// Shorten the string if it's too long
- while( tw > listPtr->columnInfo[ j ].width )
+ while( tw > listPtr->columnInfo[ j ].width && strlen( text ) > 0 )
{
text[ strlen( text ) - 1 ] = '\0';
tw = DC->textWidth( text, item->textscale, 0 );
@@ -4030,7 +4468,8 @@ void Item_ListBox_Paint(itemDef_t *item) {
alignOffset = 0.0f;
}
- DC->drawText( x + 4 + listPtr->columnInfo[j].pos + alignOffset, y + listPtr->elementHeight,
+ DC->drawText( x + 4 + listPtr->columnInfo[j].pos + alignOffset,
+ y + m + ( ( listPtr->elementHeight - m ) / 2.0f ),
item->textscale, item->window.foreColor, text, 0,
0, item->textStyle );
}
@@ -4038,14 +4477,17 @@ void Item_ListBox_Paint(itemDef_t *item) {
} else {
Q_strncpyz( text, DC->feederItemText(item->special, i, 0, &optionalImage), sizeof( text ) );
if (optionalImage >= 0) {
- //DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
+ DC->drawHandlePic(x + 4, y, listPtr->elementHeight, listPtr->elementHeight, optionalImage);
} else if (text) {
- DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle);
+ DC->drawText( x + 4, y + m + ( ( listPtr->elementHeight - m ) / 2.0f ),
+ item->textscale, item->window.foreColor, text, 0,
+ 0, item->textStyle );
}
}
if (i == item->cursorPos) {
- DC->fillRect(x + 2, y + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight, item->window.outlineColor);
+ DC->fillRect( x, y, item->window.rect.w - SCROLLBAR_SIZE - ( 2 * item->window.borderSize ),
+ listPtr->elementHeight, item->window.outlineColor);
}
listPtr->endPos++;
@@ -4067,6 +4509,7 @@ void Item_ListBox_Paint(itemDef_t *item) {
void Item_OwnerDraw_Paint(itemDef_t *item) {
menuDef_t *parent;
+ const char *text;
if (item == NULL) {
return;
@@ -4104,16 +4547,26 @@ void Item_OwnerDraw_Paint(itemDef_t *item) {
Com_Memcpy(color, parent->disableColor, sizeof(vec4_t));
}
- if (item->text) {
- Item_Text_Paint(item);
- if (item->text[0]) {
- // +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 );
- } else {
- DC->ownerDrawItem(item->textRect.x + item->textRect.w, 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 );
- }
+ if( DC->ownerDrawText && ( text = DC->ownerDrawText( item->window.ownerDraw ) ) ) {
+ if (item->text && *item->text) {
+ Item_Text_Paint(item);
+
+ DC->drawText(item->textRect.x + item->textRect.w + ITEM_VALUE_OFFSET,
+ item->textRect.y, item->textscale,
+ color, text, 0, 0, item->textStyle);
} 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->text = text;
+ Item_Text_Paint(item);
+ item->text = NULL;
+ }
+ } 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->textalignment, item->textvalignment,
+ item->special, item->textscale, color,
+ item->window.background, item->textStyle );
}
}
}
@@ -4255,7 +4708,6 @@ void Item_Paint(itemDef_t *item) {
return;
}
- // paint the rect first..
Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
if (debugMode) {
@@ -4266,8 +4718,6 @@ void Item_Paint(itemDef_t *item) {
DC->drawRect(r->x, r->y, r->w, r->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);
@@ -4311,6 +4761,7 @@ void Item_Paint(itemDef_t *item) {
break;
}
+ Border_Paint(&item->window);
}
void Menu_Init(menuDef_t *menu) {
@@ -4521,13 +4972,11 @@ void Menu_Paint(menuDef_t *menu, qboolean forcePaint) {
// implies a background shader
// FIXME: make sure we have a default shader if fullscreen is set with no background
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 );
+ Border_Paint(&menu->window);
for (i = 0; i < menu->itemCount; i++) {
Item_Paint(menu->items[i]);
@@ -4788,18 +5237,12 @@ qboolean ItemParse_notselectable( itemDef_t *item, int handle ) {
return qtrue;
}
-// manually wrapped
+// auto wrapped
qboolean ItemParse_wrapped( itemDef_t *item, int handle ) {
item->window.flags |= WINDOW_WRAPPED;
return qtrue;
}
-// auto wrapped
-qboolean ItemParse_autowrapped( itemDef_t *item, int handle ) {
- item->window.flags |= WINDOW_AUTOWRAPPED;
- return qtrue;
-}
-
// horizontalscroll
qboolean ItemParse_horizontalscroll( itemDef_t *item, int handle ) {
@@ -4947,6 +5390,13 @@ qboolean ItemParse_textalign( itemDef_t *item, int handle ) {
return qtrue;
}
+qboolean ItemParse_textvalign( itemDef_t *item, int handle ) {
+ if (!PC_Int_Parse(handle, &item->textvalignment)) {
+ return qfalse;
+ }
+ return qtrue;
+}
+
qboolean ItemParse_textalignx( itemDef_t *item, int handle ) {
if (!PC_Float_Parse(handle, &item->textalignx)) {
return qfalse;
@@ -5166,6 +5616,27 @@ qboolean ItemParse_maxPaintChars( itemDef_t *item, int handle ) {
return qtrue;
}
+qboolean ItemParse_maxFieldWidth( itemDef_t *item, int handle ) {
+ editFieldDef_t *editPtr;
+ int maxFieldWidth;
+
+ Item_ValidateTypeData(item);
+ if (!item->typeData)
+ return qfalse;
+
+ if (!PC_Int_Parse(handle, &maxFieldWidth)) {
+ return qfalse;
+ }
+ editPtr = (editFieldDef_t*)item->typeData;
+
+ if( maxFieldWidth < MIN_FIELD_WIDTH )
+ editPtr->maxFieldWidth = MIN_FIELD_WIDTH;
+ else
+ editPtr->maxFieldWidth = maxFieldWidth;
+
+ return qtrue;
+}
+
qboolean ItemParse_cvarFloat( itemDef_t *item, int handle ) {
@@ -5353,7 +5824,6 @@ keywordHash_t itemParseKeywords[] = {
{"decoration", ItemParse_decoration, NULL},
{"notselectable", ItemParse_notselectable, NULL},
{"wrapped", ItemParse_wrapped, NULL},
- {"autowrapped", ItemParse_autowrapped, NULL},
{"horizontalscroll", ItemParse_horizontalscroll, NULL},
{"type", ItemParse_type, NULL},
{"elementwidth", ItemParse_elementwidth, NULL},
@@ -5367,6 +5837,7 @@ keywordHash_t itemParseKeywords[] = {
{"ownerdraw", ItemParse_ownerdraw, NULL},
{"align", ItemParse_align, NULL},
{"textalign", ItemParse_textalign, NULL},
+ {"textvalign", ItemParse_textvalign, NULL},
{"textalignx", ItemParse_textalignx, NULL},
{"textaligny", ItemParse_textaligny, NULL},
{"textscale", ItemParse_textscale, NULL},
@@ -5387,6 +5858,7 @@ keywordHash_t itemParseKeywords[] = {
{"cvar", ItemParse_cvar, NULL},
{"maxChars", ItemParse_maxChars, NULL},
{"maxPaintChars", ItemParse_maxPaintChars, NULL},
+ {"maxFieldWidth", ItemParse_maxFieldWidth, NULL},
{"focusSound", ItemParse_focusSound, NULL},
{"cvarFloat", ItemParse_cvarFloat, NULL},
{"cvarStrList", ItemParse_cvarStrList, NULL},
@@ -5885,8 +6357,12 @@ int Menu_Count( void ) {
void Menu_PaintAll( void ) {
int i;
- if (captureFunc) {
- captureFunc(captureData);
+ if ( captureFunc != voidFunction ) {
+ if( captureFuncExpiry > 0 && DC->realTime > captureFuncExpiry ) {
+ UI_RemoveCaptureFunc( );
+ } else {
+ captureFunc(captureData);
+ }
}
for (i = 0; i < Menu_Count(); i++) {
diff --git a/src/ui/ui_shared.h b/src/ui/ui_shared.h
index 2fd396d0..28b24482 100644
--- a/src/ui/ui_shared.h
+++ b/src/ui/ui_shared.h
@@ -59,8 +59,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define WINDOW_LB_PGDN 0x00008000 // mouse is over page down
#define WINDOW_ORBITING 0x00010000 // item is in orbit
#define WINDOW_OOB_CLICK 0x00020000 // close on out of bounds click
-#define WINDOW_WRAPPED 0x00040000 // manually wrap text
-#define WINDOW_AUTOWRAPPED 0x00080000 // auto wrap text
+#define WINDOW_WRAPPED 0x00080000 // wrap text
#define WINDOW_FORCED 0x00100000 // forced open
#define WINDOW_POPUP 0x00200000 // popup
#define WINDOW_BACKCOLORSET 0x00400000 // backcolor was explicitly set
@@ -81,6 +80,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_SCRIPT_ARGS 12
#define MAX_EDITFIELD 256
+#define ITEM_VALUE_OFFSET 8
#define ART_FX_BASE "menu/art/fx_base"
#define ART_FX_BLUE "menu/art/fx_blue"
@@ -105,7 +105,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define SLIDER_HEIGHT 16.0
#define SLIDER_THUMB_WIDTH 12.0
#define SLIDER_THUMB_HEIGHT 20.0
-#define NUM_CROSSHAIRS 10
+#define NUM_CROSSHAIRS 10
typedef struct {
const char *command;
@@ -194,6 +194,7 @@ typedef struct editFieldDef_s {
float range; //
int maxChars; // for edit fields
int maxPaintChars; // for edit fields
+ int maxFieldWidth; // for edit fields
int paintOffset; //
} editFieldDef_t;
@@ -226,6 +227,7 @@ typedef struct itemDef_s {
int type; // text, button, radiobutton, checkbox, textfield, listbox, combo
int alignment; // left center right
int textalignment; // ( optional ) alignment for text within rect based on text width
+ int textvalignment; // ( optional ) alignment for text within rect based on text width
float textalignx; // ( optional ) text alignment x coord
float textaligny; // ( optional ) text alignment x coord
float textscale; // scale percentage from 72pts
@@ -318,8 +320,10 @@ typedef struct {
void (*drawHandlePic) (float x, float y, float w, float h, qhandle_t asset);
void (*drawStretchPic) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader );
void (*drawText) (float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style );
- int (*textWidth) (const char *text, float scale, int limit);
- int (*textHeight) (const char *text, float scale, int limit);
+ float (*textWidth) (const char *text, float scale, int limit);
+ float (*textHeight) (const char *text, float scale, int limit);
+ float (*textEmWidth) (float scale);
+ float (*textEmHeight) (float scale);
qhandle_t (*registerModel) (const char *p);
void (*modelBounds) (qhandle_t model, vec3_t min, vec3_t max);
void (*fillRect) ( float x, float y, float w, float h, const vec4_t color);
@@ -330,7 +334,7 @@ typedef struct {
void (*addRefEntityToScene) (const refEntity_t *re );
void (*renderScene) ( const refdef_t *fd );
void (*registerFont) (const char *pFontname, int pointSize, fontInfo_t *font);
- void (*ownerDrawItem) (float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle);
+ void (*ownerDrawItem) (float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, int textalign, int textvalign, float special, float scale, vec4_t color, qhandle_t shader, int textStyle);
float (*getValue) (int ownerDraw);
qboolean (*ownerDrawVisible) (int flags);
void (*runScript)(char **p);
@@ -355,6 +359,7 @@ typedef struct {
void (*Print)(const char *msg, ...);
void (*Pause)(qboolean b);
int (*ownerDrawWidth)(int ownerDraw, float scale);
+ const char *(*ownerDrawText)(int ownerDraw);
sfxHandle_t (*registerSound)(const char *name, qboolean compressed);
void (*startBackgroundTrack)( const char *intro, const char *loop);
void (*stopBackgroundTrack)( void );
@@ -428,6 +433,11 @@ void Menu_Paint(menuDef_t *menu, qboolean forcePaint);
void Menu_SetFeederSelection(menuDef_t *menu, int feeder, int index, const char *name);
void Display_CacheAll( void );
+typedef void (CaptureFunc) (void *p);
+
+void UI_InstallCaptureFunc( CaptureFunc *f, void *data, int timeout );
+void UI_RemoveCaptureFunc( void );
+
void *UI_Alloc( int size );
void UI_InitMemory( void );
qboolean UI_OutOfMemory( void );
@@ -437,7 +447,10 @@ void Controls_SetConfig(qboolean restart);
void Controls_SetDefaults( void );
//for cg_draw.c
-void Item_Text_AutoWrapped_Paint( itemDef_t *item );
+void Item_Text_Wrapped_Paint( itemDef_t *item );
+void UI_DrawTextBlock( rectDef_t *rect, float text_x, float text_y, vec4_t color,
+ float scale, int textalign, int textvalign,
+ int textStyle, const char *text );
int trap_Parse_AddGlobalDefine( char *define );
int trap_Parse_LoadSource( const char *filename );