the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 503 lines 17 kB view raw
1#include "stdafx.h" 2#include "..\..\Tesselator.h" 3#include "XUI_FontData.h" 4#include "XUI_Font.h" 5 6extern IDirect3DDevice9 *g_pD3DDevice; 7 8//-------------------------------------------------------------------------------------- 9// Name: XUI_Font() 10// Desc: Constructor 11//-------------------------------------------------------------------------------------- 12XUI_Font::XUI_Font(int iFontData, float scaleFactor, XUI_FontData *fontData) 13 : m_iFontData(iFontData), m_fScaleFactor(scaleFactor) 14{ 15 m_fontData = fontData; 16 refCount = 0; 17 18 m_fCursorX = 0.0f; 19 m_fCursorY = 0.0f; 20 21 m_fXScaleFactor = m_fYScaleFactor = scaleFactor; 22 23 m_fSlantFactor = 0.0f; 24 m_bRotate = FALSE; 25 m_dRotCos = cos( 0.0 ); 26 m_dRotSin = sin( 0.0 ); 27 28 m_dwNestedBeginCount = 0L; 29 30 // Initialize the window 31 D3DDISPLAYMODE DisplayMode; 32 g_pD3DDevice->GetDisplayMode( 0, &DisplayMode ); 33 m_rcWindow.x1 = 0; 34 m_rcWindow.y1 = 0; 35 m_rcWindow.x2 = DisplayMode.Width; 36 m_rcWindow.y2 = DisplayMode.Height; 37} 38 39 40//-------------------------------------------------------------------------------------- 41// Name: ~XUI_Font() 42// Desc: Destructor 43//-------------------------------------------------------------------------------------- 44XUI_Font::~XUI_Font() 45{ 46} 47 48//-------------------------------------------------------------------------------------- 49// Name: GetTextExtent() 50// Desc: Get the dimensions of a text string 51//-------------------------------------------------------------------------------------- 52 53VOID XUI_Font::GetTextExtent( const WCHAR* strText, FLOAT* pWidth, 54 FLOAT* pHeight, BOOL bFirstLineOnly ) const 55{ 56 assert( pWidth != NULL ); 57 assert( pHeight != NULL ); 58 59 // Set default text extent in output parameters 60 int iWidth = 0; 61 FLOAT fHeight = 0.0f; 62 63 if( strText ) 64 { 65 // Initialize counters that keep track of text extent 66 int ix = 0; 67 FLOAT fy = m_fontData->getFontHeight(); // One character high to start 68 if( fy > fHeight ) 69 fHeight = fy; 70 71 // Loop through each character and update text extent 72 DWORD letter; 73 while( (letter = *strText) != 0 ) 74 { 75 ++strText; 76 77 // Handle newline character 78 if( letter == L'\n' ) 79 { 80 if( bFirstLineOnly ) 81 break; 82 ix = 0; 83 fy += m_fontData->getFontYAdvance(); 84 // since the height has changed, test against the height extent 85 if( fy > fHeight ) 86 fHeight = fy; 87 } 88 89 // Handle carriage return characters by ignoring them. This helps when 90 // displaying text from a file. 91 if( letter == L'\r' ) 92 continue; 93 94 // Translate unprintable characters 95 XUI_FontData::SChar sChar = m_fontData->getChar(letter); 96 97 // Get text extent for this character's glyph 98 ix += sChar.getOffset(); 99 ix += sChar.getWAdvance(); 100 101 // Since the x widened, test against the x extent 102 if (ix > iWidth) iWidth = ix; 103 } 104 } 105 106 // Convert the width to a float here, load/hit/store. :( 107 FLOAT fWidth = static_cast<FLOAT>(iWidth); // Delay the use if fWidth to reduce LHS pain 108 // Apply the scale factor to the result 109 fHeight *= m_fYScaleFactor; 110 // Store the final results 111 *pHeight = fHeight; 112 113 fWidth *= m_fXScaleFactor; 114 *pWidth = fWidth; 115} 116 117//-------------------------------------------------------------------------------------- 118// Name: GetTextWidth() 119// Desc: Returns the width in pixels of a text string 120//-------------------------------------------------------------------------------------- 121FLOAT XUI_Font::GetTextWidth( const WCHAR* strText ) const 122{ 123 FLOAT fTextWidth; 124 FLOAT fTextHeight; 125 GetTextExtent( strText, &fTextWidth, &fTextHeight ); 126 return fTextWidth; 127} 128 129//-------------------------------------------------------------------------------------- 130// Name: Begin() 131// Desc: Prepares the font vertex buffers for rendering. 132//-------------------------------------------------------------------------------------- 133VOID XUI_Font::Begin() 134{ 135 PIXBeginNamedEvent( 0, "Text Rendering" ); 136 137 // Set state on the first call 138 if( 0 == m_dwNestedBeginCount ) 139 { 140 // Cache the global pointer into a register 141 IDirect3DDevice9 *pD3dDevice = g_pD3DDevice; 142 assert( pD3dDevice ); 143 144 // Set the texture scaling factor as a vertex shader constant 145 //D3DSURFACE_DESC TextureDesc; 146 //m_pFontTexture->GetLevelDesc( 0, &TextureDesc ); // Get the description 147 148 // Set render state 149 assert(m_fontData->m_pFontTexture != NULL || m_fontData->m_iFontTexture > 0); 150 if(m_fontData->m_pFontTexture != NULL) 151 { 152 pD3dDevice->SetTexture( 0, m_fontData->m_pFontTexture ); 153 } 154 else 155 { 156 glBindTexture(GL_TEXTURE_2D, m_fontData->m_iFontTexture); 157 } 158 159 //// Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc() 160 //FLOAT vTexScale[4]; 161 //vTexScale[0] = 1.0f / TextureDesc.Width; // LHS due to int->float conversion 162 //vTexScale[1] = 1.0f / TextureDesc.Height; 163 //vTexScale[2] = 0.0f; 164 //vTexScale[3] = 0.0f; 165 // 166 //pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); 167 //pD3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); 168 //pD3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); 169 //pD3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); 170 //pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); 171 //pD3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 ); 172 //pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); 173 //pD3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); 174 //pD3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); 175 //pD3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); 176 //pD3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); 177 //pD3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, FALSE ); 178 //pD3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 179 //pD3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 180 //pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); 181 //pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); 182 } 183 184 // Keep track of the nested begin/end calls. 185 m_dwNestedBeginCount++; 186} 187 188 189//-------------------------------------------------------------------------------------- 190// Name: DrawText() 191// Desc: Draws text as textured polygons 192//-------------------------------------------------------------------------------------- 193VOID XUI_Font::DrawText( DWORD dwColor, const WCHAR* strText, DWORD dwFlags, 194 FLOAT fMaxPixelWidth ) 195{ 196 DrawText( m_fCursorX, m_fCursorY, dwColor, strText, dwFlags, fMaxPixelWidth ); 197} 198 199//-------------------------------------------------------------------------------------- 200// Name: DrawShadowText() 201// Desc: Draws text as textured polygons 202//-------------------------------------------------------------------------------------- 203VOID XUI_Font::DrawShadowText( FLOAT fOriginX, FLOAT fOriginY, DWORD dwColor, DWORD dwShadowColor, 204 const WCHAR* strText, DWORD dwFlags, FLOAT fMaxPixelWidth) 205{ 206 float fXShadow=1.0f, fYShadow=1.0f; 207 // 4J Stu - Don't move the drop shadow as much 208 //DrawText( fOriginX + (1*m_fXScaleFactor), fOriginY + (1*m_fYScaleFactor), dwColor, strText, dwFlags, fMaxPixelWidth, true ); 209 210 // 4J-PB - if we're in 480 widescreen, we need to draw the drop shadow at +2 pixels, so that when the scene is halved, it's at +1 211 if(!RenderManager.IsHiDef()) 212 { 213 if(RenderManager.IsWidescreen()) 214 { 215 fXShadow=2.0f; 216 fYShadow=2.0f; 217 } 218 //else 219 //{ 220 // 480 SD mode - the draw text call will reposition the y 221 //} 222 } 223 DrawText( fOriginX + fXShadow, fOriginY + fYShadow, dwColor, strText, dwFlags, fMaxPixelWidth, true ); 224 DrawText( fOriginX, fOriginY, dwColor, strText, dwFlags, fMaxPixelWidth ); 225 226 //DrawText( fOriginX + 1, fOriginY + 1, dwShadowColor, strText, dwFlags, fMaxPixelWidth); 227 //DrawText( fOriginX, fOriginY, dwColor, strText, dwFlags, fMaxPixelWidth ); 228} 229 230//-------------------------------------------------------------------------------------- 231// Name: DrawText() 232// Desc: Draws text as textured polygons 233// TODO: This function should use the Begin/SetVertexData/End() API when it 234// becomes available. 235//-------------------------------------------------------------------------------------- 236VOID XUI_Font::DrawText( FLOAT fOriginX, FLOAT fOriginY, DWORD dwColor, 237 const WCHAR* strText, DWORD dwFlags, FLOAT fMaxPixelWidth, bool darken /*= false*/ ) 238{ 239 if( NULL == strText ) return; 240 if( L'\0' == strText[0] ) return; 241 242 // 4J-PB - if we're in 480 widescreen mode, we need to ensure that the font characters are aligned on an even boundary if they are a 2x multiple 243 if(!RenderManager.IsHiDef()) 244 { 245 if(RenderManager.IsWidescreen()) 246 { 247 int iScaleX=(int)m_fXScaleFactor; 248 int iOriginX; 249 if(iScaleX%2==0) 250 { 251 iOriginX=(int)fOriginX; 252 if(iOriginX%2==1) 253 { 254 fOriginX+=1.0f; 255 } 256 } 257 int iScaleY=(int)m_fYScaleFactor; 258 int iOriginY; 259 if(iScaleY%2==0) 260 { 261 iOriginY=(int)fOriginY; 262 if(iOriginY%2==1) 263 { 264 fOriginY+=1.0f; 265 } 266 } 267 } 268 else 269 { 270 // 480 SD mode - y needs to be on a pixel boundary when multiplied by 1.5, so if it's an odd number, subtract 1/3 from it 271 int iOriginY=(int)fOriginY; 272 if(iOriginY%2==1) 273 { 274 fOriginY-=1.0f/3.0f; 275 } 276 } 277 } 278 // Create a PIX user-defined event that encapsulates all of the text draw calls. 279 // This makes DrawText calls easier to recognize in PIX captures, and it makes 280 // them take up fewer entries in the event list. 281 PIXBeginNamedEvent( dwColor, "DrawText: %S", strText ); 282 283 // Set up stuff to prepare for drawing text 284 Begin(); 285 286 if (darken) 287 { 288 int oldAlpha = dwColor & 0xff000000; 289 dwColor = (dwColor & 0xfcfcfc) >> 2; 290 dwColor += oldAlpha; 291 } 292 293 float r = ((dwColor >> 16) & 0xff) / 255.0f; 294 float g = ((dwColor >> 8) & 0xff) / 255.0f; 295 float b = ((dwColor) & 0xff) / 255.0f; 296 float a = ((dwColor >> 24) & 0xff) / 255.0f; 297 if (a == 0) a = 1; 298 // a = 1; 299 glColor4f(r, g, b, a); 300 301 // Set the starting screen position 302 if( ( fOriginX < 0.0f ) || ( ( dwFlags & ATGFONT_RIGHT ) && ( fOriginX <= 0.0f ) ) ) 303 { 304 fOriginX += ( m_rcWindow.x2 - m_rcWindow.x1 ); 305 } 306 // 4J-PB - not sure what this code was intending to do, but it removed a line of text that is slightly off the top of the control, rather than having it partially render 307// if( fOriginY < 0.0f ) 308// { 309// fOriginY += ( m_rcWindow.y2 - m_rcWindow.y1 ); 310// } 311 312 m_fCursorX = floorf( fOriginX ); 313 m_fCursorY = floorf( fOriginY ); 314 315 // Adjust for padding 316 fOriginY -= m_fontData->getFontTopPadding(); 317 318 XUI_FontData::SChar sChar = m_fontData->getChar(L'.'); 319 FLOAT fEllipsesPixelWidth = m_fXScaleFactor * 3.0f * (sChar.getOffset() + sChar.getWAdvance()); 320 321 if( dwFlags & ATGFONT_TRUNCATED ) 322 { 323 // Check if we will really need to truncate the string 324 if( fMaxPixelWidth <= 0.0f ) 325 { 326 dwFlags &= ( ~ATGFONT_TRUNCATED ); 327 } 328 else 329 { 330 FLOAT w, h; 331 GetTextExtent( strText, &w, &h, TRUE ); 332 333 // If not, then clear the flag 334 if( w <= fMaxPixelWidth ) 335 dwFlags &= ( ~ATGFONT_TRUNCATED ); 336 } 337 } 338 339 // If vertically centered, offset the starting m_fCursorY value 340 if( dwFlags & ATGFONT_CENTER_Y ) 341 { 342 FLOAT w, h; 343 GetTextExtent( strText, &w, &h ); 344 m_fCursorY = floorf( m_fCursorY - (h * 0.5f) ); 345 } 346 347 // Add window offsets 348 FLOAT Winx = static_cast<FLOAT>(m_rcWindow.x1); 349 FLOAT Winy = static_cast<FLOAT>(m_rcWindow.y1); 350 fOriginX += Winx; 351 fOriginY += Winy; 352 m_fCursorX += Winx; 353 m_fCursorY += Winy; 354 355 // Set a flag so we can determine initial justification effects 356 BOOL bStartingNewLine = TRUE; 357 358 DWORD dwNumEllipsesToDraw = 0; 359 360 // Begin drawing the vertices 361 362 363 DWORD dwNumChars = wcslen( strText ) + ( dwFlags & ATGFONT_TRUNCATED ? 3 : 0 ); 364 365 bStartingNewLine = TRUE; 366 367 // Draw four vertices for each glyph 368 while( *strText ) 369 { 370 WCHAR letter; 371 372 if( dwNumEllipsesToDraw ) 373 { 374 letter = L'.'; 375 } 376 else 377 { 378 // If starting text on a new line, determine justification effects 379 if( bStartingNewLine ) 380 { 381 if( dwFlags & ( ATGFONT_RIGHT | ATGFONT_CENTER_X ) ) 382 { 383 // Get the extent of this line 384 FLOAT w, h; 385 GetTextExtent( strText, &w, &h, TRUE ); 386 387 // Offset this line's starting m_fCursorX value 388 if( dwFlags & ATGFONT_RIGHT ) 389 m_fCursorX = floorf( fOriginX - w ); 390 if( dwFlags & ATGFONT_CENTER_X ) 391 m_fCursorX = floorf( fOriginX - w * 0.5f ); 392 } 393 bStartingNewLine = FALSE; 394 } 395 396 // Get the current letter in the string 397 letter = *strText++; 398 399 // Handle the newline character 400 if( letter == L'\n' ) 401 { 402 m_fCursorX = fOriginX; 403 m_fCursorY += m_fontData->getFontYAdvance() * m_fYScaleFactor; 404 bStartingNewLine = TRUE; 405 406 continue; 407 } 408 409 // Handle carriage return characters by ignoring them. This helps when 410 // displaying text from a file. 411 if( letter == L'\r' ) 412 continue; 413 } 414 415 // Translate unprintable characters 416 XUI_FontData::SChar sChar = m_fontData->getChar( letter ); 417 418 FLOAT fOffset = m_fXScaleFactor * ( FLOAT )sChar.getOffset(); 419 FLOAT fAdvance = m_fXScaleFactor * ( FLOAT )sChar.getWAdvance(); 420 // 4J Use the font max width otherwise scaling doesnt look right 421 FLOAT fWidth = m_fXScaleFactor * (sChar.tu2() - sChar.tu1());//( FLOAT )pGlyph->wWidth; 422 FLOAT fHeight = m_fYScaleFactor * m_fontData->getFontHeight(); 423 424 if( 0 == dwNumEllipsesToDraw ) 425 { 426 if( dwFlags & ATGFONT_TRUNCATED ) 427 { 428 // Check if we will be exceeded the max allowed width 429 if( m_fCursorX + fOffset + fWidth + fEllipsesPixelWidth + m_fSlantFactor > fOriginX + fMaxPixelWidth ) 430 { 431 // Yup, draw the three ellipses dots instead 432 dwNumEllipsesToDraw = 3; 433 continue; 434 } 435 } 436 } 437 438 // Setup the screen coordinates 439 m_fCursorX += fOffset; 440 FLOAT X4 = m_fCursorX; 441 FLOAT X1 = X4 + m_fSlantFactor; 442 FLOAT X3 = X4 + fWidth; 443 FLOAT X2 = X1 + fWidth; 444 FLOAT Y1 = m_fCursorY; 445 FLOAT Y3 = Y1 + fHeight; 446 FLOAT Y2 = Y1; 447 FLOAT Y4 = Y3; 448 449 m_fCursorX += fAdvance; 450 451 // Add the vertices to draw this glyph 452 453 FLOAT tu1 = sChar.tu1() / (float)m_fontData->getImageWidth(); 454 FLOAT tv1 = sChar.tv1() / (float)m_fontData->getImageHeight(); 455 FLOAT tu2 = sChar.tu2() / (float)m_fontData->getImageWidth(); 456 FLOAT tv2 = sChar.tv2() / (float)m_fontData->getImageHeight(); 457 458 Tesselator *t = Tesselator::getInstance(); 459 t->begin(); 460 t->vertexUV(X1, Y1, 0.0f, tu1, tv1); 461 t->vertexUV(X2, Y2, 0.0f, tu2, tv1); 462 t->vertexUV(X3, Y3, 0.0f, tu2, tv2); 463 t->vertexUV(X4, Y4, 0.0f, tu1, tv2); 464 t->end(); 465 466 467 // If drawing ellipses, exit when they're all drawn 468 if( dwNumEllipsesToDraw ) 469 { 470 if( --dwNumEllipsesToDraw == 0 ) 471 break; 472 } 473 474 dwNumChars--; 475 } 476 477 // Undo window offsets 478 m_fCursorX -= Winx; 479 m_fCursorY -= Winy; 480 481 // Call End() to complete the begin/end pair for drawing text 482 End(); 483 484 // Close off the user-defined event opened with PIXBeginNamedEvent. 485 PIXEndNamedEvent(); 486} 487 488 489//-------------------------------------------------------------------------------------- 490// Name: End() 491// Desc: Paired call that restores state set in the Begin() call. 492//-------------------------------------------------------------------------------------- 493VOID XUI_Font::End() 494{ 495 assert( m_dwNestedBeginCount > 0 ); 496 if( --m_dwNestedBeginCount > 0 ) 497 { 498 PIXEndNamedEvent(); 499 return; 500 } 501 502 PIXEndNamedEvent(); 503}