summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cgame/cg_local.h2
-rw-r--r--src/cgame/cg_main.c19
-rw-r--r--src/game/bg_misc.c61
-rw-r--r--src/game/bg_public.h1
-rw-r--r--src/game/g_client.c57
-rw-r--r--src/game/g_local.h5
-rw-r--r--src/game/g_main.c6
-rw-r--r--src/qcommon/q_shared.h3
-rw-r--r--src/ui/ui_main.c16
-rw-r--r--src/ui/ui_shared.c353
-rw-r--r--src/ui/ui_shared.h4
11 files changed, 412 insertions, 115 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index f090e928..9bdcb3b9 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1533,6 +1533,8 @@ extern vmCvar_t cg_projectileNudge;
extern vmCvar_t cg_voice;
+extern vmCvar_t cg_emoticons;
+
//
// cg_main.c
//
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index b239236d..9a40a5c3 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -214,6 +214,8 @@ vmCvar_t cg_projectileNudge;
vmCvar_t cg_voice;
+vmCvar_t cg_emoticons;
+
typedef struct
{
@@ -336,7 +338,9 @@ static cvarTable_t cvarTable[ ] =
{ &pmove_msec, "pmove_msec", "8", 0},
{ &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE},
- { &cg_voice, "voice", "default", CVAR_USERINFO|CVAR_ARCHIVE}
+ { &cg_voice, "voice", "default", CVAR_USERINFO|CVAR_ARCHIVE},
+
+ { &cg_emoticons, "cg_emoticons", "1", CVAR_LATCH|CVAR_ARCHIVE}
};
static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] );
@@ -1663,6 +1667,8 @@ void CG_LoadHudMenu( void )
void CG_AssetCache( void )
{
+ int i;
+
cgDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
cgDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
cgDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
@@ -1672,6 +1678,17 @@ void CG_AssetCache( void )
cgDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
cgDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
cgDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
+
+ if( cg_emoticons.integer )
+ cgDC.Assets.emoticonCount = BG_LoadEmoticons( cgDC.Assets.emoticons );
+ else
+ cgDC.Assets.emoticonCount = 0;
+
+ for( i = 0; i < cgDC.Assets.emoticonCount; i++ )
+ {
+ cgDC.Assets.emoticonShaders[ i ] = trap_R_RegisterShaderNoMip(
+ va( "emoticons/%s.tga", cgDC.Assets.emoticons[ i ] ) );
+ }
}
/*
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 9f8ce9e4..244ee482 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -31,6 +31,7 @@ void trap_FS_Read( void *buffer, int len, fileHandle_t f );
void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
void trap_FS_FCloseFile( fileHandle_t f );
void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t
+int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
static const buildableAttributes_t bg_buildableList[ ] =
{
@@ -3855,3 +3856,63 @@ weapon_t BG_PrimaryWeapon( int stats[ ] )
return WP_NONE;
}
+/*
+============
+BG_LoadEmoticons
+============
+*/
+int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ] )
+{
+ int numFiles;
+ char fileList[ MAX_EMOTICONS * ( MAX_EMOTICON_NAME_LEN + 5 ) ] = {""};
+ int i;
+ char *filePtr;
+ int fileLen;
+ char emoticon[ MAX_EMOTICON_NAME_LEN + 5 ] = {""};
+ int loaded = 0;
+ int count;
+
+ numFiles = trap_FS_GetFileList( "emoticons", ".tga", fileList,
+ sizeof( fileList ) );
+
+ if( numFiles < 1 )
+ return 0;
+
+ filePtr = fileList;
+ fileLen = 0;
+ count = 0;
+ for( i = 0; i < numFiles; i++, filePtr += fileLen + 1 )
+ {
+ if( count >= MAX_EMOTICONS )
+ {
+ count++;
+ continue;
+ }
+
+ fileLen = strlen( filePtr );
+ if( fileLen > MAX_EMOTICON_NAME_LEN + 5 )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: MAX_EMOTICON_NAME_LEN is %d. "
+ "skipping \"%s\", filename too long", MAX_EMOTICON_NAME_LEN, filePtr );
+ continue;
+ }
+ if( !trap_FS_FOpenFile( va( "emoticons/%s", filePtr ), NULL, FS_READ ) )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: BG_LoadEmoticons(): detected "
+ " an unreadable .tga file name \"emoticons/%s\" in emoticon detection",
+ filePtr );
+ break;
+ }
+ Q_strncpyz( emoticon, filePtr, sizeof( emoticon ) );
+ emoticon[ fileLen - 4 ] = '\0';
+
+ Q_strncpyz( names[ count ], emoticon, sizeof( names[ count ] ) );
+ count++;
+ loaded = count;
+ }
+
+ Com_Printf( "Loaded %d of %d emoticons (MAX_EMOTICONS is %d)\n",
+ loaded, count, MAX_EMOTICONS );
+ return loaded;
+}
+
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 1e1c98ac..2a6f1874 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -1298,3 +1298,4 @@ voiceTrack_t *BG_VoiceTrackFind( voiceTrack_t *head, team_t team,
class_t class, weapon_t weapon,
int enthusiasm, int *trackNum );
+int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ] );
diff --git a/src/game/g_client.c b/src/game/g_client.c
index 0e8051b8..4d674905 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -764,16 +764,54 @@ void respawn( gentity_t *ent )
}
}
+static qboolean G_IsEmoticon( const char *s, qboolean *escaped )
+{
+ int i, j;
+ const char *p = s;
+ char emoticon[ MAX_EMOTICON_NAME_LEN ] = {""};
+ qboolean escape = qfalse;
+
+ if( *p != '[' )
+ return qfalse;
+ p++;
+ if( *p == '[' )
+ {
+ escape = qtrue;
+ p++;
+ }
+ i = 0;
+ while( *p && i < ( MAX_EMOTICON_NAME_LEN - 1 ) )
+ {
+ if( *p == ']' )
+ {
+ for( j = 0; j < level.emoticonCount; j++ )
+ {
+ if( !Q_stricmp( emoticon, level.emoticons[ j ] ) )
+ {
+ *escaped = escape;
+ return qtrue;
+ }
+ }
+ return qfalse;
+ }
+ emoticon[ i++ ] = *p;
+ emoticon[ i ] = '\0';
+ p++;
+ }
+ return qfalse;
+}
+
/*
===========
-ClientCleanName
+G_ClientCleanName
============
*/
-static void ClientCleanName( const char *in, char *out, int outSize )
+static void G_ClientCleanName( const char *in, char *out, int outSize )
{
int len, colorlessLen;
char *p;
int spaces;
+ qboolean escaped;
//save room for trailing null byte
outSize--;
@@ -808,6 +846,19 @@ static void ClientCleanName( const char *in, char *out, int outSize )
len += 2;
continue;
}
+ else if( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) )
+ {
+ // make sure room in dest for both chars
+ if( len > outSize - 2 )
+ break;
+
+ *out++ = '[';
+ *out++ = '[';
+ len += 2;
+ if( escaped )
+ in++;
+ continue;
+ }
// don't allow too many consecutive spaces
if( *in == ' ' )
@@ -942,7 +993,7 @@ void ClientUserinfoChanged( int clientNum )
// set name
Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) );
s = Info_ValueForKey( userinfo, "name" );
- ClientCleanName( s, newname, sizeof( newname ) );
+ G_ClientCleanName( s, newname, sizeof( newname ) );
if( strcmp( oldname, newname ) )
{
diff --git a/src/game/g_local.h b/src/game/g_local.h
index db15d208..05f1fe21 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -619,6 +619,9 @@ typedef struct
team_t surrenderTeam;
voice_t *voices;
+
+ char emoticons[ MAX_EMOTICONS ][ MAX_EMOTICON_NAME_LEN ];
+ int emoticonCount;
} level_locals_t;
#define CMD_CHEAT 0x01
@@ -1142,6 +1145,8 @@ extern vmCvar_t g_mapConfigs;
extern vmCvar_t g_layouts;
extern vmCvar_t g_layoutAuto;
+extern vmCvar_t g_emoticonsAllowedInNames;
+
extern vmCvar_t g_admin;
extern vmCvar_t g_adminLog;
extern vmCvar_t g_adminParseSay;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 34793cb2..e3db3c23 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -124,6 +124,8 @@ vmCvar_t g_chatTeamPrefix;
vmCvar_t g_layouts;
vmCvar_t g_layoutAuto;
+vmCvar_t g_emoticonsAllowedInNames;
+
vmCvar_t g_admin;
vmCvar_t g_adminLog;
vmCvar_t g_adminParseSay;
@@ -244,6 +246,8 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_layouts, "g_layouts", "", CVAR_LATCH, 0, qfalse },
{ &g_layoutAuto, "g_layoutAuto", "1", CVAR_ARCHIVE, 0, qfalse },
+
+ { &g_emoticonsAllowedInNames, "g_emoticonsAllowedInNames", "1", CVAR_LATCH|CVAR_ARCHIVE, 0, qfalse },
{ &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse },
{ &g_adminLog, "g_adminLog", "admin.log", CVAR_ARCHIVE, 0, qfalse },
@@ -603,6 +607,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ),
&level.clients[ 0 ].ps, sizeof( level.clients[ 0 ] ) );
+ level.emoticonCount = BG_LoadEmoticons( level.emoticons );
+
trap_SetConfigstring( CS_INTERMISSION, "0" );
// test to see if a custom buildable layout will be loaded
diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
index 232982f5..84e2c2b4 100644
--- a/src/qcommon/q_shared.h
+++ b/src/qcommon/q_shared.h
@@ -1326,4 +1326,7 @@ typedef enum {
#define SAY_TEAM 1
#define SAY_TELL 2
+#define MAX_EMOTICON_NAME_LEN 16
+#define MAX_EMOTICONS 64
+
#endif // __Q_SHARED_H
diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
index d8389c66..8d18372d 100644
--- a/src/ui/ui_main.c
+++ b/src/ui/ui_main.c
@@ -98,6 +98,8 @@ vmCvar_t ui_developer;
vmCvar_t ui_winner;
+vmCvar_t ui_emoticons;
+
static cvarTable_t cvarTable[ ] =
{
{ &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE },
@@ -120,6 +122,7 @@ static cvarTable_t cvarTable[ ] =
{ &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
{ &ui_textWrapCache, "ui_textWrapCache", "1", CVAR_ARCHIVE },
{ &ui_developer, "ui_developer", "0", CVAR_ARCHIVE | CVAR_CHEAT },
+ { &ui_emoticons, "ui_emoticons", "1", CVAR_LATCH | CVAR_ARCHIVE },
};
static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] );
@@ -190,6 +193,8 @@ intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3,
void AssetCache( void )
{
+ int i;
+
uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
uiInfo.uiDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
uiInfo.uiDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
@@ -199,6 +204,17 @@ void AssetCache( void )
uiInfo.uiDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
uiInfo.uiDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
uiInfo.uiDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
+
+ if( ui_emoticons.integer )
+ uiInfo.uiDC.Assets.emoticonCount = BG_LoadEmoticons( uiInfo.uiDC.Assets.emoticons );
+ else
+ uiInfo.uiDC.Assets.emoticonCount = 0;
+
+ for( i = 0; i < uiInfo.uiDC.Assets.emoticonCount; i++ )
+ {
+ uiInfo.uiDC.Assets.emoticonShaders[ i ] = trap_R_RegisterShaderNoMip(
+ va( "emoticons/%s.tga", uiInfo.uiDC.Assets.emoticons[ i ] ) );
+ }
}
void UI_DrawSides( float x, float y, float w, float h, float size )
diff --git a/src/ui/ui_shared.c b/src/ui/ui_shared.c
index 84c31e4e..f2fe9b28 100644
--- a/src/ui/ui_shared.c
+++ b/src/ui/ui_shared.c
@@ -1834,6 +1834,53 @@ void Script_playLooped( itemDef_t *item, char **args )
}
}
+static qboolean UI_Text_Emoticon( const char *s, qboolean *escaped, int *length, qhandle_t *h )
+{
+ char name[ MAX_EMOTICON_NAME_LEN ] = {""};
+ const char *p = s;
+ int i = 0;
+ int j = 0;
+
+ if( *p != '[' )
+ return qfalse;
+ p++;
+
+ *escaped = qfalse;
+ if( *p == '[' )
+ {
+ *escaped = qtrue;
+ p++;
+ }
+
+ while( *p && i < ( MAX_EMOTICON_NAME_LEN - 1 ) )
+ {
+ if( *p == ']' )
+ {
+ for( j = 0; j < DC->Assets.emoticonCount; j++ )
+ {
+ if( !Q_stricmp( DC->Assets.emoticons[ j ], name ) )
+ {
+ if( *escaped )
+ {
+ *length = 1;
+ return qtrue;
+ }
+ if( h )
+ *h = DC->Assets.emoticonShaders[ j ];
+ *length = i + 2;
+ return qtrue;
+ }
+ }
+ return qfalse;
+ }
+ name[ i++ ] = *p;
+ name[ i ] = '\0';
+ p++;
+ }
+ return qfalse;
+}
+
+
float UI_Text_Width( const char *text, float scale, int limit )
{
int count, len;
@@ -1842,6 +1889,10 @@ float UI_Text_Width( const char *text, float scale, int limit )
float useScale;
const char *s = text;
fontInfo_t *font = &DC->Assets.textFont;
+ int emoticonLen;
+ qboolean emoticonEscaped;
+ float emoticonWidth;
+ int emoticons = 0;
if( scale <= DC->getCVarValue( "ui_smallFont" ) )
font = &DC->Assets.smallFont;
@@ -1849,6 +1900,7 @@ float UI_Text_Width( const char *text, float scale, int limit )
font = &DC->Assets.bigFont;
useScale = scale * font->glyphScale;
+ emoticonWidth = UI_Text_Height( "[", scale, 0 ) * DC->aspectScale;
out = 0;
if( text )
@@ -1862,22 +1914,33 @@ float UI_Text_Width( const char *text, float scale, int limit )
while( s && *s && count < len )
{
+ glyph = &font->glyphs[( int )*s];
+
if( Q_IsColorString( s ) )
{
s += 2;
continue;
}
- else
+ else if ( UI_Text_Emoticon( s, &emoticonEscaped, &emoticonLen, NULL ) )
{
- glyph = &font->glyphs[( int )*s];
- out += ( glyph->xSkip * DC->aspectScale );
- s++;
- count++;
+ if( emoticonEscaped )
+ {
+ s++;
+ }
+ else
+ {
+ s += emoticonLen;
+ emoticons++;
+ continue;
+ }
}
+ out += ( glyph->xSkip * DC->aspectScale );
+ s++;
+ count++;
}
}
- return out * useScale;
+ return ( out * useScale ) + ( emoticons * emoticonWidth );
}
float UI_Text_Height( const char *text, float scale, int limit )
@@ -1971,6 +2034,13 @@ void UI_Text_Paint_Limit( float *maxX, float x, float y, float scale,
int len, count;
vec4_t newColor;
glyphInfo_t *glyph;
+ int emoticonLen = 0;
+ qhandle_t emoticonHandle = 0;
+ float emoticonH, emoticonW;
+ qboolean emoticonEscaped;
+
+ emoticonH = UI_Text_Height( "[", scale, 0 );
+ emoticonW = emoticonH * DC->aspectScale;
if( text )
{
@@ -1979,6 +2049,8 @@ void UI_Text_Paint_Limit( float *maxX, float x, float y, float scale,
float useScale;
fontInfo_t *font = &DC->Assets.textFont;
+ memcpy( &newColor[0], &color[0], sizeof( vec4_t ) );
+
if( scale <= DC->getCVarValue( "ui_smallFont" ) )
font = &DC->Assets.smallFont;
else if( scale > DC->getCVarValue( "ui_bigFont" ) )
@@ -1997,11 +2069,13 @@ void UI_Text_Paint_Limit( float *maxX, float x, float y, float scale,
while( s && *s && count < len )
{
- float width, height, skip;
+ float width, height, skip, yadj;
+
glyph = &font->glyphs[ ( int )*s ];
width = glyph->imageWidth * DC->aspectScale;
height = glyph->imageHeight;
skip = glyph->xSkip * DC->aspectScale;
+ yadj = useScale * glyph->top;
if( Q_IsColorString( s ) )
{
@@ -2011,30 +2085,42 @@ void UI_Text_Paint_Limit( float *maxX, float x, float y, float scale,
s += 2;
continue;
}
- else
+ else if( UI_Text_Emoticon( s, &emoticonEscaped, &emoticonLen, &emoticonHandle ) )
{
- float yadj = useScale * glyph->top;
-
- if( UI_Text_Width( s, useScale, 1 ) + x > max )
+ if( emoticonEscaped )
{
- *maxX = 0;
- break;
+ s++;
}
+ else
+ {
+ s += emoticonLen;
+ DC->setColor( NULL );
+ DC->drawHandlePic( x, y - yadj, emoticonW, emoticonH, emoticonHandle );
+ DC->setColor( newColor );
+ x += emoticonW;
+ continue;
+ }
+ }
- UI_Text_PaintChar( x, y - yadj,
- width,
- height,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
- x += ( skip * useScale ) + adjust;
- *maxX = x;
- count++;
- s++;
+ if( UI_Text_Width( s, useScale, 1 ) + x > max )
+ {
+ *maxX = 0;
+ break;
}
+
+ UI_Text_PaintChar( x, y - yadj,
+ width,
+ height,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+ x += ( skip * useScale ) + adjust;
+ *maxX = x;
+ count++;
+ s++;
}
DC->setColor( NULL );
@@ -2049,12 +2135,18 @@ void UI_Text_Paint( float x, float y, float scale, vec4_t color, const char *tex
glyphInfo_t *glyph;
float useScale;
fontInfo_t *font = &DC->Assets.textFont;
+ int emoticonLen = 0;
+ qhandle_t emoticonHandle = 0;
+ float emoticonH, emoticonW;
+ qboolean emoticonEscaped;
if( scale <= DC->getCVarValue( "ui_smallFont" ) )
font = &DC->Assets.smallFont;
else if( scale >= DC->getCVarValue( "ui_bigFont" ) )
font = &DC->Assets.bigFont;
+ emoticonH = UI_Text_Height( "[", scale, 0 );
+ emoticonW = emoticonH * DC->aspectScale;
useScale = scale * font->glyphScale;
if( text )
@@ -2071,11 +2163,13 @@ void UI_Text_Paint( float x, float y, float scale, vec4_t color, const char *tex
while( s && *s && count < len )
{
- float width, height, skip;
+ float width, height, skip, yadj;
+
glyph = &font->glyphs[( int )*s];
width = glyph->imageWidth * DC->aspectScale;
height = glyph->imageHeight;
skip = glyph->xSkip * DC->aspectScale;
+ yadj = useScale * glyph->top;
if( Q_IsColorString( s ) )
{
@@ -2085,85 +2179,29 @@ void UI_Text_Paint( float x, float y, float scale, vec4_t color, const char *tex
s += 2;
continue;
}
- else
+ else if( UI_Text_Emoticon( s, &emoticonEscaped, &emoticonLen, &emoticonHandle ) )
{
- float yadj = useScale * glyph->top;
-
- if( style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE )
+ if( emoticonEscaped )
{
- int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
- colorBlack[3] = newColor[3];
- DC->setColor( colorBlack );
- UI_Text_PaintChar( x + ofs, y - yadj + ofs,
- width,
- height,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
- DC->setColor( newColor );
- colorBlack[3] = 1.0;
+ s++;
}
- else if( style == ITEM_TEXTSTYLE_NEON )
+ else
{
- 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;
-
- DC->setColor( glow );
- UI_Text_PaintChar( x - 1.5, y - yadj - 1.5,
- width + 3,
- height + 3,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- DC->setColor( outer );
- UI_Text_PaintChar( x - 1, y - yadj - 1,
- width + 2,
- height + 2,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- DC->setColor( inner );
- UI_Text_PaintChar( x - 0.5, y - yadj - 0.5,
- width + 1,
- height + 1,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- DC->setColor( white );
+ DC->setColor( NULL );
+ DC->drawHandlePic( x, y - yadj, emoticonW, emoticonH, emoticonHandle );
+ DC->setColor( newColor );
+ x += emoticonW;
+ s += emoticonLen;
+ continue;
}
+ }
- UI_Text_PaintChar( x, y - yadj,
+ if( style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE )
+ {
+ int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
+ colorBlack[3] = newColor[3];
+ DC->setColor( colorBlack );
+ UI_Text_PaintChar( x + ofs, y - yadj + ofs,
width,
height,
useScale,
@@ -2172,13 +2210,80 @@ void UI_Text_Paint( float x, float y, float scale, vec4_t color, const char *tex
glyph->s2,
glyph->t2,
glyph->glyph );
+ DC->setColor( newColor );
+ colorBlack[3] = 1.0;
+ }
+ else if( style == ITEM_TEXTSTYLE_NEON )
+ {
+ vec4_t glow, outer, inner, white;
- x += ( skip * useScale ) + adjust;
- s++;
- count++;
+ 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;
+
+ DC->setColor( glow );
+ UI_Text_PaintChar( x - 1.5, y - yadj - 1.5,
+ width + 3,
+ height + 3,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ DC->setColor( outer );
+ UI_Text_PaintChar( x - 1, y - yadj - 1,
+ width + 2,
+ height + 2,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ DC->setColor( inner );
+ UI_Text_PaintChar( x - 0.5, y - yadj - 0.5,
+ width + 1,
+ height + 1,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ DC->setColor( white );
}
- }
+ UI_Text_PaintChar( x, y - yadj,
+ width,
+ height,
+ useScale,
+ glyph->s,
+ glyph->t,
+ glyph->s2,
+ glyph->t2,
+ glyph->glyph );
+
+ x += ( skip * useScale ) + adjust;
+ s++;
+ count++;
+ }
DC->setColor( NULL );
}
}
@@ -4433,6 +4538,8 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
const char *q = NULL, *qMinus1 = NULL;
unsigned int testLength;
unsigned int i;
+ int emoticonLen;
+ qboolean emoticonEscaped;
if( strlen( text ) >= sizeof( out ) )
return NULL;
@@ -4469,12 +4576,20 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
q = p;
while( Q_IsColorString( q ) )
+ {
+ c[ 0 ] = q[ 0 ];
+ c[ 1 ] = q[ 1 ];
q += 2;
+ }
q++;
while( Q_IsColorString( q ) )
+ {
+ c[ 0 ] = q[ 0 ];
+ c[ 1 ] = q[ 1 ];
q += 2;
+ }
while( UI_Text_Width( p, scale, testLength ) < width )
{
@@ -4490,11 +4605,18 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
for( i = 0; i < testLength; )
{
// Skip color escapes
-
while( Q_IsColorString( q ) )
{
+ c[ 0 ] = q[ 0 ];
+ c[ 1 ] = q[ 1 ];
q += 2;
- continue;
+ }
+ while( UI_Text_Emoticon( q, &emoticonEscaped, &emoticonLen, NULL ) )
+ {
+ if( emoticonEscaped )
+ q++;
+ else
+ q += emoticonLen;
}
qMinus1 = q;
@@ -4504,7 +4626,18 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
// Some color escapes might still be present
while( Q_IsColorString( q ) )
+ {
+ c[ 0 ] = q[ 0 ];
+ c[ 1 ] = q[ 1 ];
q += 2;
+ }
+ while( UI_Text_Emoticon( q, &emoticonEscaped, &emoticonLen, NULL ) )
+ {
+ if( emoticonEscaped )
+ q++;
+ else
+ q += emoticonLen;
+ }
// Manual line break
if( *q == '\n' )
@@ -4523,9 +4656,6 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
if( eol == p )
eol = q;
- // Add colour code (might be empty)
- Q_strcat( out, sizeof( out ), c );
-
paint = out + strlen( out );
// Copy text
@@ -4535,7 +4665,10 @@ static const char *Item_Text_Wrap( const char *text, float scale, float width )
// Add a \n if it's not there already
if( out[ strlen( out ) - 1 ] != '\n' )
- Q_strcat( out, sizeof( out ), "\n" );
+ {
+ Q_strcat( out, sizeof( out ), "\n " );
+ Q_strcat( out, sizeof( out ), c );
+ }
paint = out + strlen( out );
diff --git a/src/ui/ui_shared.h b/src/ui/ui_shared.h
index a33d9ae6..fe9b03fe 100644
--- a/src/ui/ui_shared.h
+++ b/src/ui/ui_shared.h
@@ -341,7 +341,9 @@ typedef struct
vec4_t shadowColor;
float shadowFadeClamp;
qboolean fontRegistered;
-
+ char emoticons[ MAX_EMOTICONS ][ MAX_EMOTICON_NAME_LEN ];
+ qhandle_t emoticonShaders[ MAX_EMOTICONS ];
+ int emoticonCount;
}
cachedAssets_t;