mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-20 06:58:20 +00:00
Merge pull request #1590 from LordSk/feature/chat_part1
Improve chat look and feel part 1
This commit is contained in:
commit
a9a013ca87
|
@ -67,6 +67,11 @@ public:
|
||||||
CFontSizeData m_aSizes[NUM_FONT_SIZES];
|
CFontSizeData m_aSizes[NUM_FONT_SIZES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CQuadChar
|
||||||
|
{
|
||||||
|
float m_aUvs[4];
|
||||||
|
IGraphics::CQuadItem m_QuadItem;
|
||||||
|
};
|
||||||
|
|
||||||
class CTextRender : public IEngineTextRender
|
class CTextRender : public IEngineTextRender
|
||||||
{
|
{
|
||||||
|
@ -538,6 +543,227 @@ public:
|
||||||
m_TextOutlineA = a;
|
m_TextOutlineA = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void TextShadowed(CTextCursor *pCursor, const char *pText, int Length, vec2 ShadowOffset,
|
||||||
|
vec4 ShadowColor, vec4 TextColor_)
|
||||||
|
{
|
||||||
|
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||||
|
float FakeToScreenX, FakeToScreenY;
|
||||||
|
|
||||||
|
// to correct coords, convert to screen coords, round, and convert back
|
||||||
|
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||||
|
|
||||||
|
FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0));
|
||||||
|
FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
|
||||||
|
ShadowOffset.x /= FakeToScreenX;
|
||||||
|
ShadowOffset.y /= FakeToScreenX;
|
||||||
|
|
||||||
|
CQuadChar aTextQuads[1024];
|
||||||
|
int TextQuadCount = 0;
|
||||||
|
IGraphics::CTextureHandle FontTexture;
|
||||||
|
|
||||||
|
TextDeferredRenderEx(pCursor, pText, Length, aTextQuads, sizeof(aTextQuads)/sizeof(aTextQuads[0]),
|
||||||
|
&TextQuadCount, &FontTexture);
|
||||||
|
|
||||||
|
Graphics()->TextureSet(FontTexture);
|
||||||
|
|
||||||
|
Graphics()->QuadsBegin();
|
||||||
|
|
||||||
|
// shadow pass
|
||||||
|
Graphics()->SetColor(ShadowColor.r, ShadowColor.g, ShadowColor.b, ShadowColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < TextQuadCount; i++)
|
||||||
|
{
|
||||||
|
const CQuadChar& q = aTextQuads[i];
|
||||||
|
Graphics()->QuadsSetSubset(q.m_aUvs[0], q.m_aUvs[1], q.m_aUvs[2], q.m_aUvs[3]);
|
||||||
|
|
||||||
|
IGraphics::CQuadItem QuadItem = q.m_QuadItem;
|
||||||
|
QuadItem.m_X += ShadowOffset.x;
|
||||||
|
QuadItem.m_Y += ShadowOffset.y;
|
||||||
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// text pass
|
||||||
|
Graphics()->SetColor(TextColor_.r, TextColor_.g, TextColor_.b, TextColor_.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < TextQuadCount; i++)
|
||||||
|
{
|
||||||
|
const CQuadChar& q = aTextQuads[i];
|
||||||
|
Graphics()->QuadsSetSubset(q.m_aUvs[0], q.m_aUvs[1], q.m_aUvs[2], q.m_aUvs[3]);
|
||||||
|
Graphics()->QuadsDrawTL(&q.m_QuadItem, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Graphics()->QuadsEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TextDeferredRenderEx(CTextCursor *pCursor, const char *pText, int Length,
|
||||||
|
CQuadChar* aQuadChar, int QuadCharMaxCount, int* pQuadCharCount,
|
||||||
|
IGraphics::CTextureHandle* pFontTexture)
|
||||||
|
{
|
||||||
|
CFont *pFont = pCursor->m_pFont;
|
||||||
|
CFontSizeData *pSizeData = NULL;
|
||||||
|
|
||||||
|
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||||
|
float FakeToScreenX, FakeToScreenY;
|
||||||
|
int ActualX, ActualY;
|
||||||
|
|
||||||
|
int ActualSize;
|
||||||
|
int GotNewLine = 0;
|
||||||
|
float DrawX = 0.0f, DrawY = 0.0f;
|
||||||
|
int LineCount = 0;
|
||||||
|
float CursorX, CursorY;
|
||||||
|
|
||||||
|
float Size = pCursor->m_FontSize;
|
||||||
|
|
||||||
|
// to correct coords, convert to screen coords, round, and convert back
|
||||||
|
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||||
|
|
||||||
|
FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0));
|
||||||
|
FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
|
||||||
|
ActualX = (int)(pCursor->m_X * FakeToScreenX);
|
||||||
|
ActualY = (int)(pCursor->m_Y * FakeToScreenY);
|
||||||
|
|
||||||
|
CursorX = ActualX / FakeToScreenX;
|
||||||
|
CursorY = ActualY / FakeToScreenY;
|
||||||
|
|
||||||
|
// same with size
|
||||||
|
ActualSize = (int)(Size * FakeToScreenY);
|
||||||
|
Size = ActualSize / FakeToScreenY;
|
||||||
|
|
||||||
|
// fetch pFont data
|
||||||
|
if(!pFont)
|
||||||
|
pFont = m_pDefaultFont;
|
||||||
|
|
||||||
|
if(!pFont)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pSizeData = GetSize(pFont, ActualSize);
|
||||||
|
RenderSetup(pFont, ActualSize);
|
||||||
|
*pFontTexture = pSizeData->m_aTextures[0];
|
||||||
|
|
||||||
|
float Scale = 1.0f/pSizeData->m_FontSize;
|
||||||
|
|
||||||
|
// set length
|
||||||
|
if(Length < 0)
|
||||||
|
Length = str_length(pText);
|
||||||
|
|
||||||
|
|
||||||
|
const char *pCurrent = (char *)pText;
|
||||||
|
const char *pEnd = pCurrent+Length;
|
||||||
|
DrawX = CursorX;
|
||||||
|
DrawY = CursorY;
|
||||||
|
LineCount = pCursor->m_LineCount;
|
||||||
|
|
||||||
|
while(pCurrent < pEnd && (pCursor->m_MaxLines < 1 || LineCount <= pCursor->m_MaxLines))
|
||||||
|
{
|
||||||
|
int NewLine = 0;
|
||||||
|
const char *pBatchEnd = pEnd;
|
||||||
|
if(pCursor->m_LineWidth > 0 && !(pCursor->m_Flags&TEXTFLAG_STOP_AT_END))
|
||||||
|
{
|
||||||
|
int Wlen = min(WordLength((char *)pCurrent), (int)(pEnd-pCurrent));
|
||||||
|
CTextCursor Compare = *pCursor;
|
||||||
|
Compare.m_X = DrawX;
|
||||||
|
Compare.m_Y = DrawY;
|
||||||
|
Compare.m_Flags &= ~TEXTFLAG_RENDER;
|
||||||
|
Compare.m_LineWidth = -1;
|
||||||
|
TextDeferredRenderEx(&Compare, pCurrent, Wlen, aQuadChar, QuadCharMaxCount, pQuadCharCount,
|
||||||
|
pFontTexture);
|
||||||
|
|
||||||
|
if(Compare.m_X-DrawX > pCursor->m_LineWidth)
|
||||||
|
{
|
||||||
|
// word can't be fitted in one line, cut it
|
||||||
|
CTextCursor Cutter = *pCursor;
|
||||||
|
Cutter.m_CharCount = 0;
|
||||||
|
Cutter.m_X = DrawX;
|
||||||
|
Cutter.m_Y = DrawY;
|
||||||
|
Cutter.m_Flags &= ~TEXTFLAG_RENDER;
|
||||||
|
Cutter.m_Flags |= TEXTFLAG_STOP_AT_END;
|
||||||
|
|
||||||
|
TextDeferredRenderEx(&Cutter, (const char *)pCurrent, Wlen, aQuadChar, QuadCharMaxCount,
|
||||||
|
pQuadCharCount, pFontTexture);
|
||||||
|
Wlen = Cutter.m_CharCount;
|
||||||
|
NewLine = 1;
|
||||||
|
|
||||||
|
if(Wlen <= 3) // if we can't place 3 chars of the word on this line, take the next
|
||||||
|
Wlen = 0;
|
||||||
|
}
|
||||||
|
else if(Compare.m_X-pCursor->m_StartX > pCursor->m_LineWidth)
|
||||||
|
{
|
||||||
|
NewLine = 1;
|
||||||
|
Wlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pBatchEnd = pCurrent + Wlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pTmp = pCurrent;
|
||||||
|
int NextCharacter = str_utf8_decode(&pTmp);
|
||||||
|
while(pCurrent < pBatchEnd)
|
||||||
|
{
|
||||||
|
int Character = NextCharacter;
|
||||||
|
pCurrent = pTmp;
|
||||||
|
NextCharacter = str_utf8_decode(&pTmp);
|
||||||
|
|
||||||
|
if(Character == '\n')
|
||||||
|
{
|
||||||
|
DrawX = pCursor->m_StartX;
|
||||||
|
DrawY += Size;
|
||||||
|
DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
|
||||||
|
DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;
|
||||||
|
++LineCount;
|
||||||
|
if(pCursor->m_MaxLines > 0 && LineCount > pCursor->m_MaxLines)
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFontChar *pChr = GetChar(pFont, pSizeData, Character);
|
||||||
|
if(pChr)
|
||||||
|
{
|
||||||
|
float Advance = pChr->m_AdvanceX + Kerning(pFont, Character, NextCharacter)*Scale;
|
||||||
|
if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+Advance*Size-pCursor->m_StartX > pCursor->m_LineWidth)
|
||||||
|
{
|
||||||
|
// we hit the end of the line, no more to render or count
|
||||||
|
pCurrent = pEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pCursor->m_Flags&TEXTFLAG_RENDER)
|
||||||
|
{
|
||||||
|
dbg_assert(*pQuadCharCount < QuadCharMaxCount, "aQuadChar size is too small");
|
||||||
|
|
||||||
|
CQuadChar QuadChar;
|
||||||
|
memmove(QuadChar.m_aUvs, pChr->m_aUvs, sizeof(pChr->m_aUvs));
|
||||||
|
|
||||||
|
IGraphics::CQuadItem QuadItem(DrawX+pChr->m_OffsetX*Size,
|
||||||
|
DrawY+pChr->m_OffsetY*Size,
|
||||||
|
pChr->m_Width*Size,
|
||||||
|
pChr->m_Height*Size);
|
||||||
|
QuadChar.m_QuadItem = QuadItem;
|
||||||
|
aQuadChar[(*pQuadCharCount)++] = QuadChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawX += Advance*Size;
|
||||||
|
pCursor->m_CharCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NewLine)
|
||||||
|
{
|
||||||
|
DrawX = pCursor->m_StartX;
|
||||||
|
DrawY += Size;
|
||||||
|
GotNewLine = 1;
|
||||||
|
DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
|
||||||
|
DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;
|
||||||
|
++LineCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCursor->m_X = DrawX;
|
||||||
|
pCursor->m_LineCount = LineCount;
|
||||||
|
|
||||||
|
if(GotNewLine)
|
||||||
|
pCursor->m_Y = DrawY;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length)
|
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length)
|
||||||
{
|
{
|
||||||
CFont *pFont = pCursor->m_pFont;
|
CFont *pFont = pCursor->m_pFont;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#ifndef ENGINE_TEXTRENDER_H
|
#ifndef ENGINE_TEXTRENDER_H
|
||||||
#define ENGINE_TEXTRENDER_H
|
#define ENGINE_TEXTRENDER_H
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
#include <base/vmath.h>
|
||||||
|
#include <engine/graphics.h>
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -40,6 +42,11 @@ public:
|
||||||
|
|
||||||
//
|
//
|
||||||
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
|
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
|
||||||
|
virtual void TextDeferredRenderEx(CTextCursor *pCursor, const char *pText, int Length,
|
||||||
|
struct CQuadChar* aQuadChar, int QuadCharMaxCount, int* out_pQuadCharCount,
|
||||||
|
IGraphics::CTextureHandle* pFontTexture) = 0;
|
||||||
|
virtual void TextShadowed(CTextCursor *pCursor, const char *pText, int Length, vec2 ShadowOffset,
|
||||||
|
vec4 ShadowColor, vec4 TextColor_) = 0;
|
||||||
|
|
||||||
// old foolish interface
|
// old foolish interface
|
||||||
virtual void TextColor(float r, float g, float b, float a) = 0;
|
virtual void TextColor(float r, float g, float b, float a) = 0;
|
||||||
|
|
|
@ -376,7 +376,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
||||||
const char *pStr = pLine;
|
const char *pStr = pLine;
|
||||||
const char *pEnd = 0;
|
const char *pEnd = 0;
|
||||||
while(*pStr)
|
while(*pStr)
|
||||||
{
|
{
|
||||||
const char *pStrOld = pStr;
|
const char *pStrOld = pStr;
|
||||||
int Code = str_utf8_decode(&pStr);
|
int Code = str_utf8_decode(&pStr);
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
||||||
*(const_cast<char *>(pStr)) = 0;
|
*(const_cast<char *>(pStr)) = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pEnd != 0)
|
if(pEnd != 0)
|
||||||
*(const_cast<char *>(pEnd)) = 0;
|
*(const_cast<char *>(pEnd)) = 0;
|
||||||
|
|
||||||
|
@ -445,8 +445,8 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
||||||
|
|
||||||
if(ClientID == -1) // server message
|
if(ClientID == -1) // server message
|
||||||
{
|
{
|
||||||
str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName));
|
m_aLines[m_CurrentLine].m_aName[0] = 0;
|
||||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
|
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "*** %s", pLine);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -462,7 +462,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "%2d: %s", ClientID, m_pClient->m_aClients[ClientID].m_aName);
|
str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "%2d: %s", ClientID, m_pClient->m_aClients[ClientID].m_aName);
|
||||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine);
|
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
char aBuf[1024];
|
char aBuf[1024];
|
||||||
|
@ -594,63 +594,167 @@ void CChat::OnRender()
|
||||||
float FontSize = 6.0f;
|
float FontSize = 6.0f;
|
||||||
CTextCursor Cursor;
|
CTextCursor Cursor;
|
||||||
int OffsetType = m_pClient->m_pScoreboard->Active() ? 1 : 0;
|
int OffsetType = m_pClient->m_pScoreboard->Active() ? 1 : 0;
|
||||||
|
|
||||||
|
// get the y offset (calculate it if we haven't done that yet)
|
||||||
for(int i = 0; i < MAX_LINES; i++)
|
for(int i = 0; i < MAX_LINES; i++)
|
||||||
{
|
{
|
||||||
int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
|
int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
|
||||||
if(Now > m_aLines[r].m_Time+16*time_freq() && !m_Show)
|
CLine& Line = m_aLines[r];
|
||||||
break;
|
|
||||||
|
|
||||||
// get the y offset (calculate it if we haven't done that yet)
|
if(m_aLines[r].m_aText[0] == 0) break;
|
||||||
if(m_aLines[r].m_YOffset[OffsetType] < 0.0f)
|
|
||||||
|
if(Line.m_YOffset[OffsetType] < 0.0f)
|
||||||
{
|
{
|
||||||
TextRender()->SetCursor(&Cursor, Begin, 0.0f, FontSize, 0);
|
TextRender()->SetCursor(&Cursor, Begin, 0.0f, FontSize, 0);
|
||||||
Cursor.m_LineWidth = LineWidth;
|
Cursor.m_LineWidth = LineWidth;
|
||||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
|
|
||||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
|
char aBuf[48];
|
||||||
m_aLines[r].m_YOffset[OffsetType] = Cursor.m_Y + Cursor.m_FontSize;
|
if(Line.m_Mode == CHAT_TEAM)
|
||||||
|
{
|
||||||
|
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Team"));
|
||||||
|
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||||
|
}
|
||||||
|
else if(Line.m_Mode == CHAT_WHISPER)
|
||||||
|
{
|
||||||
|
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Whisper"));
|
||||||
|
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextRender()->TextEx(&Cursor, Line.m_aName, -1);
|
||||||
|
|
||||||
|
if(Line.m_ClientID != -1)
|
||||||
|
TextRender()->TextEx(&Cursor, ": ", 2);
|
||||||
|
TextRender()->TextEx(&Cursor, Line.m_aText, -1);
|
||||||
|
Line.m_YOffset[OffsetType] = Cursor.m_Y + Cursor.m_FontSize;
|
||||||
}
|
}
|
||||||
y -= m_aLines[r].m_YOffset[OffsetType];
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < MAX_LINES; i++)
|
||||||
|
{
|
||||||
|
int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
|
||||||
|
CLine& Line = m_aLines[r];
|
||||||
|
|
||||||
|
if(m_aLines[r].m_aText[0] == 0) break;
|
||||||
|
|
||||||
|
if(Now > Line.m_Time+16*time_freq() && !m_Show)
|
||||||
|
break;
|
||||||
|
|
||||||
|
y -= Line.m_YOffset[OffsetType];
|
||||||
|
|
||||||
// cut off if msgs waste too much space
|
// cut off if msgs waste too much space
|
||||||
if(y < HeightLimit)
|
if(y < HeightLimit)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
float Blend = Now > m_aLines[r].m_Time+14*time_freq() && !m_Show ? 1.0f-(Now-m_aLines[r].m_Time-14*time_freq())/(2.0f*time_freq()) : 1.0f;
|
float Blend = Now > Line.m_Time+14*time_freq() && !m_Show ? 1.0f-(Now-Line.m_Time-14*time_freq())/(2.0f*time_freq()) : 1.0f;
|
||||||
|
|
||||||
// reset the cursor
|
// reset the cursor
|
||||||
TextRender()->SetCursor(&Cursor, Begin, y, FontSize, TEXTFLAG_RENDER);
|
TextRender()->SetCursor(&Cursor, Begin, y, FontSize, TEXTFLAG_RENDER);
|
||||||
Cursor.m_LineWidth = LineWidth;
|
Cursor.m_LineWidth = LineWidth;
|
||||||
|
|
||||||
// render name
|
|
||||||
if(m_aLines[r].m_ClientID == -1)
|
|
||||||
TextRender()->TextColor(1.0f, 1.0f, 0.5f, Blend); // system
|
|
||||||
else if(m_aLines[r].m_Mode == CHAT_TEAM)
|
|
||||||
TextRender()->TextColor(0.45f, 0.9f, 0.45f, Blend); // team message
|
|
||||||
else if(m_aLines[r].m_NameColor == TEAM_RED)
|
|
||||||
TextRender()->TextColor(1.0f, 0.5f, 0.5f, Blend); // red
|
|
||||||
else if(m_aLines[r].m_NameColor == TEAM_BLUE)
|
|
||||||
TextRender()->TextColor(0.7f, 0.7f, 1.0f, Blend); // blue
|
|
||||||
else if(m_aLines[r].m_NameColor == TEAM_SPECTATORS)
|
|
||||||
TextRender()->TextColor(0.75f, 0.5f, 0.75f, Blend); // spectator
|
|
||||||
else
|
|
||||||
TextRender()->TextColor(0.8f, 0.8f, 0.8f, Blend);
|
|
||||||
|
|
||||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
|
const vec2 ShadowOffset(0.8f, 1.5f);
|
||||||
|
const vec4 ShadowWhisper(0.09f, 0.f, 0.26f, Blend * 0.9f);
|
||||||
|
const vec4 ShadowBlack(0, 0, 0, Blend * 0.9f);
|
||||||
|
vec4 ShadowColor = ShadowBlack;
|
||||||
|
|
||||||
|
if(Line.m_Mode == CHAT_WHISPER)
|
||||||
|
ShadowColor = ShadowWhisper;
|
||||||
|
|
||||||
|
|
||||||
|
const vec4 ColorSystem(1.0f, 1.0f, 0.5f, Blend);
|
||||||
|
const vec4 ColorWhisper(0.4f, 1.0f, 1.0f, Blend);
|
||||||
|
const vec4 ColorRed(1.0f, 0.5f, 0.5f, Blend);
|
||||||
|
const vec4 ColorBlue(0.7f, 0.7f, 1.0f, Blend);
|
||||||
|
const vec4 ColorSpec(0.75f, 0.5f, 0.75f, Blend);
|
||||||
|
const vec4 ColorAllPre(0.8f, 0.8f, 0.8f, Blend);
|
||||||
|
const vec4 ColorAllText(1.0f, 1.0f, 1.0f, Blend);
|
||||||
|
const vec4 ColorTeamPre(0.45f, 0.9f, 0.45f, Blend);
|
||||||
|
const vec4 ColorTeamText(0.6f, 1.0f, 0.6f, Blend);
|
||||||
|
const vec4 ColorHighlightOutline(0.0f, 0.4, 1.0f, Blend);
|
||||||
|
|
||||||
|
vec4 TextColor = ColorAllText;
|
||||||
|
|
||||||
|
char aBuf[48];
|
||||||
|
if(Line.m_Mode == CHAT_TEAM)
|
||||||
|
{
|
||||||
|
TextColor = ColorTeamPre;
|
||||||
|
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Team"));
|
||||||
|
TextRender()->TextShadowed(&Cursor, aBuf, -1, ShadowOffset, ShadowColor, TextColor);
|
||||||
|
}
|
||||||
|
else if(Line.m_Mode == CHAT_WHISPER)
|
||||||
|
{
|
||||||
|
TextColor = ColorWhisper;
|
||||||
|
ShadowColor = ShadowWhisper;
|
||||||
|
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Whisper"));
|
||||||
|
TextRender()->TextShadowed(&Cursor, aBuf, -1, ShadowOffset, ShadowColor, TextColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we have to break protocol to make that work
|
||||||
|
// CNetMsg_Sv_Chat needs a TargetID, like Cl_Chat
|
||||||
|
#if 0
|
||||||
|
if(line.m_Mode == CHAT_WHISPER)
|
||||||
|
{
|
||||||
|
TextColor = vec4(1.0f, 0.5f, 0.9f, Blend);
|
||||||
|
if(line.m_ClientID == m_pClient->m_LocalClientID)
|
||||||
|
TextRender()->TextEx(&Cursor, "To ", -1);
|
||||||
|
else
|
||||||
|
TextRender()->TextEx(&Cursor, "From ", -1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// render name
|
||||||
|
if(Line.m_ClientID == -1)
|
||||||
|
TextColor = ColorSystem;
|
||||||
|
else if(Line.m_Mode == CHAT_WHISPER)
|
||||||
|
TextColor = ColorWhisper;
|
||||||
|
else if(Line.m_Mode == CHAT_TEAM)
|
||||||
|
TextColor = ColorTeamPre;
|
||||||
|
else if(Line.m_NameColor == TEAM_RED)
|
||||||
|
TextColor = ColorRed;
|
||||||
|
else if(Line.m_NameColor == TEAM_BLUE)
|
||||||
|
TextColor = ColorBlue;
|
||||||
|
else if(Line.m_NameColor == TEAM_SPECTATORS)
|
||||||
|
TextColor = ColorSpec;
|
||||||
|
else
|
||||||
|
TextColor = ColorAllPre;
|
||||||
|
|
||||||
|
if(Line.m_ClientID != -1)
|
||||||
|
{
|
||||||
|
TextRender()->TextShadowed(&Cursor, Line.m_aName, -1, ShadowOffset, ShadowColor, TextColor);
|
||||||
|
TextRender()->TextShadowed(&Cursor, ": ", 2, ShadowOffset, ShadowColor, TextColor);
|
||||||
|
}
|
||||||
|
|
||||||
// render line
|
// render line
|
||||||
if(m_aLines[r].m_ClientID == -1)
|
if(Line.m_ClientID == -1)
|
||||||
TextRender()->TextColor(1.0f, 1.0f, 0.5f, Blend); // system
|
TextColor = ColorSystem;
|
||||||
else if(m_aLines[r].m_Highlighted)
|
else if(Line.m_Mode == CHAT_WHISPER)
|
||||||
TextRender()->TextColor(1.0f, 0.5f, 0.5f, Blend); // highlighted
|
TextColor = ColorWhisper;
|
||||||
else if(m_aLines[r].m_Mode == CHAT_TEAM)
|
else if(Line.m_Mode == CHAT_TEAM)
|
||||||
TextRender()->TextColor(0.65f, 1.0f, 0.65f, Blend); // team message
|
TextColor = ColorTeamText;
|
||||||
else
|
else
|
||||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Blend);
|
TextColor = ColorAllText;
|
||||||
|
|
||||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
|
if(Line.m_Highlighted && Line.m_Mode != CHAT_WHISPER && Line.m_ClientID != -1)
|
||||||
|
{
|
||||||
|
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a);
|
||||||
|
float Alpha = 0.3;
|
||||||
|
if(Line.m_Mode == CHAT_TEAM)
|
||||||
|
Alpha = 0.4;
|
||||||
|
|
||||||
|
TextRender()->TextOutlineColor(ColorHighlightOutline.r,
|
||||||
|
ColorHighlightOutline.g,
|
||||||
|
ColorHighlightOutline.b,
|
||||||
|
Alpha * Blend);
|
||||||
|
|
||||||
|
TextRender()->TextEx(&Cursor, Line.m_aText, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TextRender()->TextShadowed(&Cursor, Line.m_aText, -1, ShadowOffset, ShadowColor, TextColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChat::Say(int Mode, const char *pLine)
|
void CChat::Say(int Mode, const char *pLine)
|
||||||
|
|
|
@ -12,7 +12,7 @@ class CChat : public CComponent
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
MAX_LINES = 25,
|
MAX_LINES = 50,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CLine
|
struct CLine
|
||||||
|
|
Loading…
Reference in a new issue