14
14
#include " StdInc.h"
15
15
#include < game/CGame.h>
16
16
17
+ using std::vector;
18
+
17
19
extern CCore* g_pCore;
18
20
19
21
CChat * g_pChat = NULL ;
@@ -57,19 +59,19 @@ CChat::CChat ( CGUI* pManager, const CVector2D & vecPosition )
57
59
m_iReportCount = 0 ;
58
60
59
61
// Background area
60
- m_pBackground. reset ( m_pManager->CreateStaticImage () );
61
- m_pBackgroundTexture. reset ( m_pManager->CreateTexture () );
62
- m_pBackground->LoadFromTexture ( m_pBackgroundTexture. get () );
62
+ m_pBackground = m_pManager->CreateStaticImage ();
63
+ m_pBackgroundTexture = m_pManager->CreateTexture ();
64
+ m_pBackground->LoadFromTexture ( m_pBackgroundTexture );
63
65
m_pBackground->MoveToBack ();
64
66
m_pBackground->SetPosition ( m_vecBackgroundPosition );
65
67
m_pBackground->SetSize ( m_vecBackgroundSize );
66
68
m_pBackground->SetEnabled ( false );
67
69
m_pBackground->SetVisible ( false );
68
70
69
71
// Input area
70
- m_pInput. reset ( m_pManager->CreateStaticImage () );
71
- m_pInputTexture. reset ( m_pManager->CreateTexture () );
72
- m_pInput->LoadFromTexture ( m_pInputTexture. get () );
72
+ m_pInput = m_pManager->CreateStaticImage ();
73
+ m_pInputTexture = m_pManager->CreateTexture ();
74
+ m_pInput->LoadFromTexture ( m_pInputTexture );
73
75
m_pInput->MoveToBack ();
74
76
m_pInput->SetPosition ( m_vecInputPosition );
75
77
m_pInput->SetSize ( m_vecInputSize );
@@ -89,6 +91,10 @@ CChat::~CChat ( void )
89
91
ClearInput ();
90
92
91
93
SetDxFont ( NULL );
94
+ SAFE_DELETE ( m_pBackground );
95
+ SAFE_DELETE ( m_pBackgroundTexture );
96
+ SAFE_DELETE ( m_pInput );
97
+ SAFE_DELETE ( m_pInputTexture );
92
98
93
99
if ( g_pChat == this )
94
100
g_pChat = NULL ;
@@ -694,7 +700,7 @@ bool CChat::CharacterKeyHandler ( CGUIKeyEventArgs KeyboardArgs )
694
700
else // we have any char from Extended ASCII, any ANSI code page or UNICODE range
695
701
{
696
702
// Generate a null-terminating string for our character
697
- wchar_t wUNICODE[2 ] = { ( wchar_t ) uiCharacter, ' \0 ' };
703
+ wchar_t wUNICODE[2 ] = { uiCharacter, ' \0 ' };
698
704
699
705
// Convert our UTF character into an ANSI string
700
706
std::string strANSI = UTF16ToMbUTF8 (wUNICODE);
@@ -832,7 +838,7 @@ void CChat::SetColor ( const CColor& Color )
832
838
unsigned long ulBackgroundColor = COLOR_ARGB ( Color.A , Color.R , Color.G , Color.B );
833
839
834
840
m_pBackgroundTexture->LoadFromMemory ( &ulBackgroundColor, 1 , 1 );
835
- m_pBackground->LoadFromTexture ( m_pBackgroundTexture. get () );
841
+ m_pBackground->LoadFromTexture ( m_pBackgroundTexture );
836
842
}
837
843
838
844
@@ -844,7 +850,7 @@ void CChat::SetInputColor ( const CColor& Color )
844
850
m_pInputTexture->LoadFromMemory ( &ulInputColor, 1 , 1 );
845
851
846
852
if ( m_pInput )
847
- m_pInput->LoadFromTexture ( m_pInputTexture. get () );
853
+ m_pInput->LoadFromTexture ( m_pInputTexture );
848
854
}
849
855
850
856
@@ -979,3 +985,220 @@ void CChat::DrawTextString ( const char * szText, CRect2D DrawArea, float fZ, CR
979
985
}
980
986
}
981
987
988
+
989
+ CChatLine::CChatLine ( void )
990
+ {
991
+ m_bActive = false ;
992
+ UpdateCreationTime ();
993
+ }
994
+
995
+ void CChatLine::UpdateCreationTime ()
996
+ {
997
+ m_ulCreationTime = GetTickCount32 ();
998
+ }
999
+
1000
+
1001
+ //
1002
+ // Calculate the equivalent ansi string pointer of szPosition.
1003
+ //
1004
+ const char * CalcAnsiPtr ( const char * szStringAnsi, const wchar_t * szPosition )
1005
+ {
1006
+ int iOrigSize = strlen ( szStringAnsi );
1007
+ int iEndSize = UTF16ToMbUTF8 ( szPosition ).length ();
1008
+ int iOffset = iOrigSize - iEndSize;
1009
+ return szStringAnsi + iOffset;
1010
+ }
1011
+
1012
+
1013
+ const char * CChatLine::Format ( const char * szStringAnsi, float fWidth , CColor& color, bool bColorCoded )
1014
+ {
1015
+ std::wstring wString = MbUTF8ToUTF16 ( szStringAnsi );
1016
+ const wchar_t * szString = wString.c_str ();
1017
+
1018
+ float fPrevSectionsWidth = 0 .0f ;
1019
+ m_Sections.clear ();
1020
+
1021
+ const wchar_t * szSectionStart = szString;
1022
+ const wchar_t * szSectionEnd = szString;
1023
+ const wchar_t * szLastWrapPoint = szString;
1024
+ bool bLastSection = false ;
1025
+ while ( !bLastSection ) // iterate over sections
1026
+ {
1027
+ m_Sections.resize ( m_Sections.size () + 1 );
1028
+ CChatLineSection& section = *(m_Sections.end () - 1 );
1029
+ section.SetColor ( color );
1030
+
1031
+ if ( m_Sections.size () > 1 && bColorCoded) // If we've processed sections before
1032
+ szSectionEnd += 7 ; // skip the color code
1033
+
1034
+ szSectionStart = szSectionEnd;
1035
+ szLastWrapPoint = szSectionStart;
1036
+ unsigned int uiSeekPos = 0 ;
1037
+ std::wstring strSectionStart = szSectionStart;
1038
+
1039
+ while ( true ) // find end of this section
1040
+ {
1041
+ float fSectionWidth = CChat::GetTextExtent ( UTF16ToMbUTF8 ( strSectionStart.substr ( 0 , uiSeekPos ) ).c_str (), g_pChat->m_vecScale .fX );
1042
+
1043
+ if ( *szSectionEnd == ' \0 ' || *szSectionEnd == ' \n ' || fPrevSectionsWidth + fSectionWidth > fWidth )
1044
+ {
1045
+ bLastSection = true ;
1046
+ break ;
1047
+ }
1048
+ if ( bColorCoded && IsColorCode ( UTF16ToMbUTF8 ( szSectionEnd ).c_str () ) )
1049
+ {
1050
+ unsigned long ulColor = 0 ;
1051
+ sscanf ( UTF16ToMbUTF8 ( szSectionEnd ).c_str () + 1 , " %06x" , &ulColor );
1052
+ color = ulColor;
1053
+ fPrevSectionsWidth += fSectionWidth ;
1054
+ break ;
1055
+ }
1056
+ if ( isspace ( (unsigned char )*szSectionEnd ) || ispunct ( (unsigned char )*szSectionEnd ) )
1057
+ {
1058
+ szLastWrapPoint = szSectionEnd;
1059
+ }
1060
+ szSectionEnd++;
1061
+ uiSeekPos++;
1062
+ }
1063
+ section.m_strText = UTF16ToMbUTF8 ( strSectionStart.substr ( 0 , uiSeekPos ) );
1064
+ }
1065
+
1066
+ if ( *szSectionEnd == ' \0 ' )
1067
+ {
1068
+ return NULL ;
1069
+ }
1070
+ else if ( *szSectionEnd == ' \n ' )
1071
+ {
1072
+ return CalcAnsiPtr ( szStringAnsi, szSectionEnd + 1 );
1073
+ }
1074
+ else
1075
+ {
1076
+ // Do word wrap
1077
+ if ( szLastWrapPoint == szSectionStart )
1078
+ {
1079
+ // Wrapping point coincides with the start of a section.
1080
+ if ( szLastWrapPoint == szString )
1081
+ {
1082
+ // The line consists of one huge word. Leave the one section we created as it
1083
+ // is (with the huge word cut off) and return szRemaining as the rest of the word
1084
+ return CalcAnsiPtr ( szStringAnsi, szSectionEnd );
1085
+ }
1086
+ else
1087
+ {
1088
+ // There's more than one section, remove the last one (where our wrap point is)
1089
+ m_Sections.pop_back ();
1090
+ }
1091
+ }
1092
+ else
1093
+ {
1094
+ // Wrapping point is in the middle of a section, truncate
1095
+ CChatLineSection& last = *( m_Sections.end () - 1 );
1096
+ std::wstring wstrTemp = MbUTF8ToUTF16 ( last.m_strText );
1097
+ wstrTemp.resize ( szLastWrapPoint - szSectionStart );
1098
+ last.m_strText = UTF16ToMbUTF8 ( wstrTemp );
1099
+ }
1100
+ return CalcAnsiPtr ( szStringAnsi, szLastWrapPoint );
1101
+ }
1102
+ }
1103
+
1104
+
1105
+ void CChatLine::Draw ( const CVector2D& vecPosition, unsigned char ucAlpha, bool bShadow, const CRect2D& RenderBounds )
1106
+ {
1107
+ float fCurrentX = vecPosition.fX ;
1108
+ std::vector < CChatLineSection >::iterator iter = m_Sections.begin ();
1109
+ for ( ; iter != m_Sections.end () ; iter++ )
1110
+ {
1111
+ (*iter).Draw ( CVector2D ( fCurrentX , vecPosition.fY ), ucAlpha, bShadow, RenderBounds );
1112
+ fCurrentX += (*iter).GetWidth ();
1113
+ }
1114
+ }
1115
+
1116
+
1117
+ float CChatLine::GetWidth ()
1118
+ {
1119
+ float fWidth = 0 .0f ;
1120
+ std::vector < CChatLineSection >::iterator it;
1121
+ for ( it = m_Sections.begin (); it != m_Sections.end (); it++ )
1122
+ {
1123
+ fWidth += (*it).GetWidth ();
1124
+ }
1125
+ return fWidth ;
1126
+ }
1127
+
1128
+
1129
+ void CChatInputLine::Draw ( CVector2D& vecPosition, unsigned char ucAlpha, bool bShadow )
1130
+ {
1131
+ CRect2D RenderBounds ( 0 , 0 , 9999 , 9999 );
1132
+
1133
+ CColor colPrefix;
1134
+ m_Prefix.GetColor ( colPrefix );
1135
+ if ( colPrefix.A > 0 )
1136
+ m_Prefix.Draw ( vecPosition, colPrefix.A , bShadow, RenderBounds );
1137
+
1138
+ if ( g_pChat->m_InputTextColor .A > 0 && m_Sections.size () > 0 )
1139
+ {
1140
+ m_Sections [ 0 ].Draw ( CVector2D ( vecPosition.fX + m_Prefix.GetWidth (), vecPosition.fY ),
1141
+ g_pChat->m_InputTextColor .A , bShadow, RenderBounds );
1142
+
1143
+ float fLineDifference = CChat::GetFontHeight ( g_pChat->m_vecScale .fY );
1144
+
1145
+ vector < CChatLine >::iterator iter = m_ExtraLines.begin ();
1146
+ for ( ; iter != m_ExtraLines.end () ; iter++ )
1147
+ {
1148
+ vecPosition.fY += fLineDifference ;
1149
+ (*iter).Draw ( vecPosition, g_pChat->m_InputTextColor .A , bShadow, RenderBounds );
1150
+ }
1151
+ }
1152
+ }
1153
+
1154
+
1155
+ void CChatInputLine::Clear ( void )
1156
+ {
1157
+ m_Sections.clear ();
1158
+ m_ExtraLines.clear ();
1159
+ }
1160
+
1161
+ CChatLineSection::CChatLineSection ()
1162
+ {
1163
+ m_fCachedWidth = -1 .0f ;
1164
+ m_uiCachedLength = 0 ;
1165
+ }
1166
+
1167
+ CChatLineSection::CChatLineSection ( const CChatLineSection& other )
1168
+ {
1169
+ *this = other;
1170
+ }
1171
+
1172
+ CChatLineSection& CChatLineSection::operator = ( const CChatLineSection& other )
1173
+ {
1174
+ m_strText = other.m_strText ;
1175
+ m_Color = other.m_Color ;
1176
+ m_fCachedWidth = other.m_fCachedWidth ;
1177
+ m_uiCachedLength = other.m_uiCachedLength ;
1178
+ return *this ;
1179
+ }
1180
+
1181
+ void CChatLineSection::Draw ( const CVector2D& vecPosition, unsigned char ucAlpha, bool bShadow, const CRect2D& RenderBounds )
1182
+ {
1183
+ if ( !m_strText.empty () && ucAlpha > 0 )
1184
+ {
1185
+ if ( bShadow )
1186
+ {
1187
+ CRect2D drawShadowAt ( vecPosition.fX + 1 .0f , vecPosition.fY + 1 .0f , vecPosition.fX + 1000 .0f , vecPosition.fY + 1000 .0f );
1188
+ CChat::DrawTextString ( m_strText.c_str (), drawShadowAt, 0 .0f , drawShadowAt, 0 , COLOR_ARGB ( ucAlpha, 0 , 0 , 0 ), g_pChat->m_vecScale .fX , g_pChat->m_vecScale .fY , RenderBounds );
1189
+ }
1190
+ CRect2D drawAt ( vecPosition.fX , vecPosition.fY , vecPosition.fX + 1000 .0f , vecPosition.fY + 1000 .0f );
1191
+ CChat::DrawTextString ( m_strText.c_str (), drawAt, 0 .0f , drawAt, 0 , COLOR_ARGB ( ucAlpha, m_Color.R , m_Color.G , m_Color.B ), g_pChat->m_vecScale .fX , g_pChat->m_vecScale .fY , RenderBounds );
1192
+ }
1193
+ }
1194
+
1195
+
1196
+ float CChatLineSection::GetWidth ()
1197
+ {
1198
+ if ( m_fCachedWidth < 0 .0f || m_strText.size () != m_uiCachedLength )
1199
+ {
1200
+ m_fCachedWidth = CChat::GetTextExtent ( m_strText.c_str (), g_pChat->m_vecScale .fX ) / Max ( 0 .01f , g_pChat->m_vecScale .fX );
1201
+ m_uiCachedLength = m_strText.size ();
1202
+ }
1203
+ return m_fCachedWidth * g_pChat->m_vecScale .fX ;
1204
+ }
0 commit comments