mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-06-02 01:31:45 +00:00
swf_show debug rendering
This commit is contained in:
parent
6d4a3f107b
commit
d4eb9f8d93
5 changed files with 520 additions and 9 deletions
|
@ -385,6 +385,9 @@ private:
|
||||||
const idMaterial* guiCursor_arrow;
|
const idMaterial* guiCursor_arrow;
|
||||||
const idMaterial* guiCursor_hand;
|
const idMaterial* guiCursor_hand;
|
||||||
const idMaterial* white;
|
const idMaterial* white;
|
||||||
|
// RB begin
|
||||||
|
const idFont* debugFont;
|
||||||
|
// RB end
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class idSWFSprite;
|
friend class idSWFSprite;
|
||||||
|
@ -450,6 +453,13 @@ private:
|
||||||
uint64 GLStateForRenderState( const swfRenderState_t& renderState );
|
uint64 GLStateForRenderState( const swfRenderState_t& renderState );
|
||||||
void FindTooltipIcons( idStr* text );
|
void FindTooltipIcons( idStr* text );
|
||||||
|
|
||||||
|
// RB: debugging tools
|
||||||
|
swfRect_t CalcRect( const idSWFSpriteInstance* sprite, const swfRenderState_t& renderState );
|
||||||
|
void DrawRect( idRenderSystem* gui, const swfRect_t& rect, const idVec4& color );
|
||||||
|
int DrawText( idRenderSystem* gui, float x, float y, float scale, idVec4 color, const char* text, float adjust, int limit, int style );
|
||||||
|
int DrawText( idRenderSystem* gui, const char* text, float textScale, int textAlign, idVec4 color, const swfRect_t& rectDraw, bool wrap, int cursor = -1, bool calcOnly = false, idList<int>* breaks = NULL, int limit = 0 );
|
||||||
|
// RB end
|
||||||
|
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
// SWF_Image.cpp
|
// SWF_Image.cpp
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
|
|
|
@ -900,7 +900,7 @@ void idSWF::WriteJSON( const char* filename )
|
||||||
|
|
||||||
// export fill draws
|
// export fill draws
|
||||||
file->WriteFloatString( "\t\t\t\"fillDraws\":\n\t\t\t[\n" );
|
file->WriteFloatString( "\t\t\t\"fillDraws\":\n\t\t\t[\n" );
|
||||||
|
|
||||||
if( shape->fillDraws.Num() > 1 )
|
if( shape->fillDraws.Num() > 1 )
|
||||||
{
|
{
|
||||||
idLib::Printf( S_COLOR_YELLOW "WARNING: " S_COLOR_RED "%s.Shape%i has %i fill draws\n", filename, i, shape->fillDraws.Num() );
|
idLib::Printf( S_COLOR_YELLOW "WARNING: " S_COLOR_RED "%s.Shape%i has %i fill draws\n", filename, i, shape->fillDraws.Num() );
|
||||||
|
@ -1026,7 +1026,7 @@ void idSWF::WriteJSON( const char* filename )
|
||||||
for( int v = 0; v < fillDraw.startVerts.Num(); v++ )
|
for( int v = 0; v < fillDraw.startVerts.Num(); v++ )
|
||||||
{
|
{
|
||||||
const idVec2& vert = fillDraw.startVerts[v];
|
const idVec2& vert = fillDraw.startVerts[v];
|
||||||
|
|
||||||
file->WriteFloatString( "\t\t\t\t\t\t{ \"v\": [ %f, %f ] }%s\n", vert.x, vert.y, ( v == ( fillDraw.startVerts.Num() - 1 ) ) ? "" : "," );
|
file->WriteFloatString( "\t\t\t\t\t\t{ \"v\": [ %f, %f ] }%s\n", vert.x, vert.y, ( v == ( fillDraw.startVerts.Num() - 1 ) ) ? "" : "," );
|
||||||
}
|
}
|
||||||
file->WriteFloatString( "\t\t\t\t\t]" );
|
file->WriteFloatString( "\t\t\t\t\t]" );
|
||||||
|
@ -1051,7 +1051,7 @@ void idSWF::WriteJSON( const char* filename )
|
||||||
for( int v = 0; v < fillDraw.indices.Num(); v++ )
|
for( int v = 0; v < fillDraw.indices.Num(); v++ )
|
||||||
{
|
{
|
||||||
const uint16& vert = fillDraw.indices[v];
|
const uint16& vert = fillDraw.indices[v];
|
||||||
|
|
||||||
file->WriteFloatString( "%i%s", vert, ( v == fillDraw.indices.Num() - 1 ) ? "" : ", " );
|
file->WriteFloatString( "%i%s", vert, ( v == fillDraw.indices.Num() - 1 ) ? "" : ", " );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1267,15 +1267,19 @@ void idSWF::WriteJSON( const char* filename )
|
||||||
|
|
||||||
if( dictionary[i].type != SWF_DICT_NULL )
|
if( dictionary[i].type != SWF_DICT_NULL )
|
||||||
{
|
{
|
||||||
file->WriteFloatString( "\t\t}%s\n", ( i == ( dictionary.Num() - 1 ) ) ? "" : "," );
|
//file->WriteFloatString( "\t\t}%s\n", ( i == ( dictionary.Num() - 1 ) ) ? "" : "," );
|
||||||
|
file->WriteFloatString( "\t\t},\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file->WriteFloatString( "\t],\n" );
|
file->WriteFloatString( "\t\t{\n" );
|
||||||
|
file->WriteFloatString( "\t\t\t\"type\": \"SPRITE\",\n" );
|
||||||
file->WriteFloatString( "\t\"mainsprite\":\n\t{\n" );
|
file->WriteFloatString( "\t\t\t\"characterID\": %i,\n", dictionary.Num() );
|
||||||
|
file->WriteFloatString( "\t\t\t\"mainsprite\": true,\n" );
|
||||||
mainsprite->WriteJSON( file, dictionary.Num() );
|
mainsprite->WriteJSON( file, dictionary.Num() );
|
||||||
file->WriteFloatString( "\t}\n}\n" );
|
file->WriteFloatString( "\t\t}\n" );
|
||||||
|
file->WriteFloatString( "\t]\n" );
|
||||||
|
file->WriteFloatString( "}\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// RB end
|
// RB end
|
||||||
|
|
|
@ -68,6 +68,9 @@ idSWF::idSWF( const char* filename_, idSoundWorld* soundWorld_ )
|
||||||
guiCursor_hand = declManager->FindMaterial( "ui/assets/guicursor_hand" );
|
guiCursor_hand = declManager->FindMaterial( "ui/assets/guicursor_hand" );
|
||||||
white = declManager->FindMaterial( "_white" );
|
white = declManager->FindMaterial( "_white" );
|
||||||
|
|
||||||
|
// RB:
|
||||||
|
debugFont = renderSystem->RegisterFont( "Arial Narrow" );
|
||||||
|
|
||||||
tooltipButtonImage.Append( keyButtonImages_t( "<JOY1>", "guis/assets/hud/controller/xb360/a", "guis/assets/hud/controller/ps3/cross", 37, 37, 0 ) );
|
tooltipButtonImage.Append( keyButtonImages_t( "<JOY1>", "guis/assets/hud/controller/xb360/a", "guis/assets/hud/controller/ps3/cross", 37, 37, 0 ) );
|
||||||
tooltipButtonImage.Append( keyButtonImages_t( "<JOY2>", "guis/assets/hud/controller/xb360/b", "guis/assets/hud/controller/ps3/circle", 37, 37, 0 ) );
|
tooltipButtonImage.Append( keyButtonImages_t( "<JOY2>", "guis/assets/hud/controller/xb360/b", "guis/assets/hud/controller/ps3/circle", 37, 37, 0 ) );
|
||||||
tooltipButtonImage.Append( keyButtonImages_t( "<JOY3>", "guis/assets/hud/controller/xb360/x", "guis/assets/hud/controller/ps3/square", 37, 37, 0 ) );
|
tooltipButtonImage.Append( keyButtonImages_t( "<JOY3>", "guis/assets/hud/controller/xb360/x", "guis/assets/hud/controller/ps3/square", 37, 37, 0 ) );
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||||
Copyright (C) 2013 Robert Beckebans
|
Copyright (C) 2013-2015 Robert Beckebans
|
||||||
|
|
||||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ idCVar swf_skipSolids( "swf_skipSolids", "0", CVAR_BOOL, "" );
|
||||||
idCVar swf_skipGradients( "swf_skipGradients", "0", CVAR_BOOL, "" );
|
idCVar swf_skipGradients( "swf_skipGradients", "0", CVAR_BOOL, "" );
|
||||||
idCVar swf_skipLineDraws( "swf_skipLineDraws", "0", CVAR_BOOL, "" );
|
idCVar swf_skipLineDraws( "swf_skipLineDraws", "0", CVAR_BOOL, "" );
|
||||||
idCVar swf_skipBitmaps( "swf_skipBitmaps", "0", CVAR_BOOL, "" );
|
idCVar swf_skipBitmaps( "swf_skipBitmaps", "0", CVAR_BOOL, "" );
|
||||||
|
|
||||||
|
idCVar swf_show( "swf_show", "0", CVAR_INTEGER, "" );
|
||||||
// RB end
|
// RB end
|
||||||
|
|
||||||
extern idCVar swf_textStrokeSize;
|
extern idCVar swf_textStrokeSize;
|
||||||
|
@ -462,6 +464,33 @@ void idSWF::RenderSprite( idRenderSystem* gui, idSWFSpriteInstance* spriteInstan
|
||||||
//idLib::Warning( "%s: Tried to render an unrenderable character %d", filename.c_str(), entry->type );
|
//idLib::Warning( "%s: Tried to render an unrenderable character %d", filename.c_str(), entry->type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RB begin
|
||||||
|
if( swf_show.GetInteger() > 0 && !spriteInstance->name.IsEmpty() )//Icmp( "buttonBar" ) == 0 )
|
||||||
|
{
|
||||||
|
swfRect_t rect = CalcRect( spriteInstance, renderState );
|
||||||
|
|
||||||
|
DrawRect( gui, rect, colorRed );
|
||||||
|
|
||||||
|
if( swf_show.GetInteger() > 1 )
|
||||||
|
{
|
||||||
|
idVec4 color = colorWhite;
|
||||||
|
|
||||||
|
if( spriteInstance->parent != NULL && spriteInstance->parent == mainspriteInstance )
|
||||||
|
{
|
||||||
|
color = colorCyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
idStr str;
|
||||||
|
//str = display.spriteInstance->name.c_str();
|
||||||
|
sprintf( str, "%s\n%s", spriteInstance->name.c_str(), GetName() );
|
||||||
|
|
||||||
|
DrawText( gui, str, 0.35f, 0, color, swfRect_t( rect.tl.x, rect.tl.y, 300, 40 ), false );
|
||||||
|
//DrawText( gui, str, 0.25 * 2, 0, colorWhite, swfRect_t( rect.tl.x, rect.tl.y, 300, 40 ), false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// RB end
|
||||||
|
|
||||||
for( int j = 0; j < activeMasks.Num(); j++ )
|
for( int j = 0; j < activeMasks.Num(); j++ )
|
||||||
{
|
{
|
||||||
const swfDisplayEntry_t* mask = activeMasks[ j ];
|
const swfDisplayEntry_t* mask = activeMasks[ j ];
|
||||||
|
@ -1876,4 +1905,434 @@ void idSWF::FindTooltipIcons( idStr* text )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RB begin
|
||||||
|
swfRect_t idSWF::CalcRect( const idSWFSpriteInstance* spriteInstance, const swfRenderState_t& renderState )
|
||||||
|
{
|
||||||
|
swfRect_t bounds;
|
||||||
|
bounds.tl.x = renderState.matrix.tx;
|
||||||
|
bounds.tl.y = renderState.matrix.ty;
|
||||||
|
bounds.br.x = renderState.matrix.tx;
|
||||||
|
bounds.br.y = renderState.matrix.ty;
|
||||||
|
|
||||||
|
if( spriteInstance == NULL )
|
||||||
|
{
|
||||||
|
idLib::Warning( "%s: CalcRect: spriteInstance == NULL", filename.c_str() );
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
for( int i = 0; i < spriteInstance->displayList.Num(); i++ )
|
||||||
|
{
|
||||||
|
const swfDisplayEntry_t& display = spriteInstance->displayList[i];
|
||||||
|
|
||||||
|
idSWFDictionaryEntry* entry = FindDictionaryEntry( display.characterID );
|
||||||
|
if( entry == NULL )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
swfRenderState_t renderState2;
|
||||||
|
renderState2.matrix = display.matrix.Multiply( renderState.matrix );
|
||||||
|
|
||||||
|
if( entry->type == SWF_DICT_SPRITE )
|
||||||
|
{
|
||||||
|
swfRect_t spriteBounds = CalcRect( display.spriteInstance, renderState2 );
|
||||||
|
|
||||||
|
if( spriteBounds.tl.x < bounds.tl.x )
|
||||||
|
{
|
||||||
|
bounds.tl.x = spriteBounds.tl.x;
|
||||||
|
}
|
||||||
|
else if( spriteBounds.br.x > bounds.br.x )
|
||||||
|
{
|
||||||
|
bounds.br.x = spriteBounds.br.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( spriteBounds.tl.y < bounds.tl.y )
|
||||||
|
{
|
||||||
|
bounds.tl.y = spriteBounds.tl.y;
|
||||||
|
}
|
||||||
|
else if( spriteBounds.br.y > bounds.br.y )
|
||||||
|
{
|
||||||
|
bounds.br.y = spriteBounds.br.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( entry->type == SWF_DICT_SHAPE )
|
||||||
|
{
|
||||||
|
const idSWFShape* shape = entry->shape;
|
||||||
|
|
||||||
|
for( int i = 0; i < shape->fillDraws.Num(); i++ )
|
||||||
|
{
|
||||||
|
const idSWFShapeDrawFill& fill = shape->fillDraws[i];
|
||||||
|
|
||||||
|
for( int j = 0; j < fill.startVerts.Num(); j++ )
|
||||||
|
{
|
||||||
|
const idVec2& xy = fill.startVerts[j];
|
||||||
|
|
||||||
|
idVec2 p = renderState.matrix.Transform( xy );//.Scale( scaleToVirtual );
|
||||||
|
|
||||||
|
if( p.x < bounds.tl.x )
|
||||||
|
{
|
||||||
|
bounds.tl.x = p.x;
|
||||||
|
}
|
||||||
|
else if( p.x > bounds.br.x )
|
||||||
|
{
|
||||||
|
bounds.br.x = p.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p.y < bounds.tl.y )
|
||||||
|
{
|
||||||
|
bounds.tl.y = p.y;
|
||||||
|
}
|
||||||
|
else if( p.y > bounds.br.y )
|
||||||
|
{
|
||||||
|
bounds.br.y = p.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( entry->type == SWF_DICT_MORPH )
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
else if( entry->type == SWF_DICT_EDITTEXT )
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//idLib::Warning( "%s: Tried to render an unrenderable character %d", filename.c_str(), entry->type );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idSWF::DrawRect( idRenderSystem* gui, const swfRect_t& rect, const idVec4& color )
|
||||||
|
{
|
||||||
|
renderSystem->SetColor( color );
|
||||||
|
|
||||||
|
float x = rect.tl.x;
|
||||||
|
float y = rect.tl.y;
|
||||||
|
float w = fabs( rect.br.x - rect.tl.x );
|
||||||
|
float h = fabs( rect.br.y - rect.tl.y );
|
||||||
|
|
||||||
|
float size = 1;
|
||||||
|
|
||||||
|
DrawStretchPic( x, y, size, h, 0, 0, 0, 0, white );
|
||||||
|
DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, white );
|
||||||
|
DrawStretchPic( x, y, w, size, 0, 0, 0, 0, white );
|
||||||
|
DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, white );
|
||||||
|
}
|
||||||
|
|
||||||
|
static triIndex_t quadPicIndexes[6] = { 3, 0, 2, 2, 0, 1 };
|
||||||
|
int idSWF::DrawText( idRenderSystem* gui, float x, float y, float scale, idVec4 color, const char* text, float adjust, int limit, int style )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if( !matIsIdentity || cursor != -1 )
|
||||||
|
{
|
||||||
|
// fallback to old code
|
||||||
|
return idDeviceContext::DrawText( x, y, scale, color, text, adjust, limit, style, cursor );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
idStr drawText = text;
|
||||||
|
|
||||||
|
if( drawText.Length() == 0 )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if( color.w == 0.0f )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 currentColor = PackColor( color );
|
||||||
|
uint32 currentColorNativeByteOrder = LittleLong( currentColor );
|
||||||
|
|
||||||
|
int len = drawText.Length();
|
||||||
|
if( limit > 0 && len > limit )
|
||||||
|
{
|
||||||
|
len = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int charIndex = 0;
|
||||||
|
while( charIndex < drawText.Length() )
|
||||||
|
{
|
||||||
|
uint32 textChar = drawText.UTF8Char( charIndex );
|
||||||
|
if( textChar == C_COLOR_ESCAPE )
|
||||||
|
{
|
||||||
|
// I'm not sure if inline text color codes are used anywhere in the game,
|
||||||
|
// they may only be needed for multi-color user names
|
||||||
|
idVec4 newColor;
|
||||||
|
uint32 colorIndex = drawText.UTF8Char( charIndex );
|
||||||
|
if( colorIndex == C_COLOR_DEFAULT )
|
||||||
|
{
|
||||||
|
newColor = color;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newColor = idStr::ColorForIndex( colorIndex );
|
||||||
|
newColor[3] = color[3];
|
||||||
|
}
|
||||||
|
renderSystem->SetColor( newColor );
|
||||||
|
currentColorNativeByteOrder = LittleLong( PackColor( newColor ) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
scaledGlyphInfo_t glyphInfo;
|
||||||
|
debugFont->GetScaledGlyph( scale, textChar, glyphInfo );
|
||||||
|
|
||||||
|
// PaintChar( x, y, glyphInfo );
|
||||||
|
float drawY = y - glyphInfo.top;
|
||||||
|
float drawX = x + glyphInfo.left;
|
||||||
|
float w = glyphInfo.width;
|
||||||
|
float h = glyphInfo.height;
|
||||||
|
float s = glyphInfo.s1;
|
||||||
|
float t = glyphInfo.t1;
|
||||||
|
float s2 = glyphInfo.s2;
|
||||||
|
float t2 = glyphInfo.t2;
|
||||||
|
|
||||||
|
float xOffset = 0;
|
||||||
|
float yOffset = 0;
|
||||||
|
|
||||||
|
//idDrawVert* verts = gui->AllocTris( fill.startVerts.Num(), fill.indices.Ptr(), fill.indices.Num(), material, renderState.stereoDepth );
|
||||||
|
|
||||||
|
//if( !ClippedCoords( &drawX, &drawY, &w, &h, &s, &t, &s2, &t2 ) )
|
||||||
|
{
|
||||||
|
float x1 = xOffset + drawX * scaleToVirtual.x;
|
||||||
|
float x2 = xOffset + ( drawX + w ) * scaleToVirtual.x;
|
||||||
|
float y1 = yOffset + drawY * scaleToVirtual.y;
|
||||||
|
float y2 = yOffset + ( drawY + h ) * scaleToVirtual.y;
|
||||||
|
idDrawVert* verts = gui->AllocTris( 4, quadPicIndexes, 6, glyphInfo.material, STEREO_DEPTH_TYPE_NONE );
|
||||||
|
if( verts != NULL )
|
||||||
|
{
|
||||||
|
verts[0].xyz[0] = x1;
|
||||||
|
verts[0].xyz[1] = y1;
|
||||||
|
verts[0].xyz[2] = 0.0f;
|
||||||
|
verts[0].SetTexCoord( s, t );
|
||||||
|
verts[0].SetNativeOrderColor( currentColorNativeByteOrder );
|
||||||
|
verts[0].ClearColor2();
|
||||||
|
|
||||||
|
verts[1].xyz[0] = x2;
|
||||||
|
verts[1].xyz[1] = y1;
|
||||||
|
verts[1].xyz[2] = 0.0f;
|
||||||
|
verts[1].SetTexCoord( s2, t );
|
||||||
|
verts[1].SetNativeOrderColor( currentColorNativeByteOrder );
|
||||||
|
verts[1].ClearColor2();
|
||||||
|
|
||||||
|
verts[2].xyz[0] = x2;
|
||||||
|
verts[2].xyz[1] = y2;
|
||||||
|
verts[2].xyz[2] = 0.0f;
|
||||||
|
verts[2].SetTexCoord( s2, t2 );
|
||||||
|
verts[2].SetNativeOrderColor( currentColorNativeByteOrder );
|
||||||
|
verts[2].ClearColor2();
|
||||||
|
|
||||||
|
verts[3].xyz[0] = x1;
|
||||||
|
verts[3].xyz[1] = y2;
|
||||||
|
verts[3].xyz[2] = 0.0f;
|
||||||
|
verts[3].SetTexCoord( s, t2 );
|
||||||
|
verts[3].SetNativeOrderColor( currentColorNativeByteOrder );
|
||||||
|
verts[3].ClearColor2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += glyphInfo.xSkip + adjust;
|
||||||
|
}
|
||||||
|
return drawText.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int idSWF::DrawText( idRenderSystem* gui, const char* text, float textScale, int textAlign, idVec4 color, const swfRect_t& rectDraw, bool wrap, int cursor, bool calcOnly, idList<int>* breaks, int limit )
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
int charIndex = 0;
|
||||||
|
int lastBreak = 0;
|
||||||
|
float y = 0.0f;
|
||||||
|
float textWidth = 0.0f;
|
||||||
|
float textWidthAtLastBreak = 0.0f;
|
||||||
|
|
||||||
|
float charSkip = idMath::Ftoi( debugFont->GetMaxCharWidth( textScale ) ) + 1;
|
||||||
|
float lineSkip = idMath::Ftoi( debugFont->GetMaxCharWidth( textScale ) );
|
||||||
|
|
||||||
|
bool lineBreak = false;
|
||||||
|
bool wordBreak = false;
|
||||||
|
|
||||||
|
float rectWidth = fabs( rectDraw.br.x - rectDraw.tl.x );
|
||||||
|
float rectHeight = fabs( rectDraw.br.y - rectDraw.tl.y );
|
||||||
|
|
||||||
|
idStr drawText = text;
|
||||||
|
idStr textBuffer;
|
||||||
|
|
||||||
|
if( !calcOnly && !( text && *text ) )
|
||||||
|
{
|
||||||
|
//if( cursor == 0 )
|
||||||
|
//{
|
||||||
|
// renderSystem->SetColor( color );
|
||||||
|
// DrawEditCursor( rectDraw.tl.x, lineSkip + rectDraw.y, textScale );
|
||||||
|
//}
|
||||||
|
return idMath::Ftoi( rectWidth / charSkip );
|
||||||
|
}
|
||||||
|
|
||||||
|
y = lineSkip + rectDraw.y();
|
||||||
|
|
||||||
|
if( breaks )
|
||||||
|
{
|
||||||
|
breaks->Append( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( charIndex < drawText.Length() )
|
||||||
|
{
|
||||||
|
uint32 textChar = drawText.UTF8Char( charIndex );
|
||||||
|
|
||||||
|
// See if we need to start a new line.
|
||||||
|
if( textChar == '\n' || textChar == '\r' || charIndex == drawText.Length() )
|
||||||
|
{
|
||||||
|
lineBreak = true;
|
||||||
|
if( charIndex < drawText.Length() )
|
||||||
|
{
|
||||||
|
// New line character and we still have more text to read.
|
||||||
|
char nextChar = drawText[ charIndex + 1 ];
|
||||||
|
if( ( textChar == '\n' && nextChar == '\r' ) || ( textChar == '\r' && nextChar == '\n' ) )
|
||||||
|
{
|
||||||
|
// Just absorb extra newlines.
|
||||||
|
textChar = drawText.UTF8Char( charIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for escape colors if not then simply get the glyph width.
|
||||||
|
if( textChar == C_COLOR_ESCAPE && charIndex < drawText.Length() )
|
||||||
|
{
|
||||||
|
textBuffer.AppendUTF8Char( textChar );
|
||||||
|
textChar = drawText.UTF8Char( charIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the character isn't a new line then add it to the text buffer.
|
||||||
|
if( textChar != '\n' && textChar != '\r' )
|
||||||
|
{
|
||||||
|
textWidth += debugFont->GetGlyphWidth( textScale, textChar );
|
||||||
|
textBuffer.AppendUTF8Char( textChar );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !lineBreak && ( textWidth > rectWidth ) )
|
||||||
|
{
|
||||||
|
// The next character will cause us to overflow, if we haven't yet found a suitable
|
||||||
|
// break spot, set it to be this character
|
||||||
|
if( textBuffer.Length() > 0 && lastBreak == 0 )
|
||||||
|
{
|
||||||
|
lastBreak = textBuffer.Length();
|
||||||
|
textWidthAtLastBreak = textWidth;
|
||||||
|
}
|
||||||
|
wordBreak = true;
|
||||||
|
}
|
||||||
|
else if( lineBreak || ( wrap && ( textChar == ' ' || textChar == '\t' ) ) )
|
||||||
|
{
|
||||||
|
// The next character is in view, so if we are a break character, store our position
|
||||||
|
lastBreak = textBuffer.Length();
|
||||||
|
textWidthAtLastBreak = textWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to go to a new line
|
||||||
|
if( lineBreak || wordBreak )
|
||||||
|
{
|
||||||
|
float x = rectDraw.tl.x;
|
||||||
|
|
||||||
|
if( textWidthAtLastBreak > 0 )
|
||||||
|
{
|
||||||
|
textWidth = textWidthAtLastBreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align text if needed
|
||||||
|
#if 0
|
||||||
|
if( textAlign == ALIGN_RIGHT )
|
||||||
|
{
|
||||||
|
x = rectDraw.tl.x + rectWidth - textWidth;
|
||||||
|
}
|
||||||
|
else if( textAlign == ALIGN_CENTER )
|
||||||
|
{
|
||||||
|
x = rectDraw.tl.x + ( rectWidth - textWidth ) / 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( wrap || lastBreak > 0 )
|
||||||
|
{
|
||||||
|
// This is a special case to handle breaking in the middle of a word.
|
||||||
|
// if we didn't do this, the cursor would appear on the end of this line
|
||||||
|
// and the beginning of the next.
|
||||||
|
if( wordBreak && cursor >= lastBreak && lastBreak == textBuffer.Length() )
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw what's in the current text buffer.
|
||||||
|
if( !calcOnly )
|
||||||
|
{
|
||||||
|
if( lastBreak > 0 )
|
||||||
|
{
|
||||||
|
count += DrawText( gui, x, y, textScale, color, textBuffer.Left( lastBreak ).c_str(), 0, 0, 0 );
|
||||||
|
textBuffer = textBuffer.Right( textBuffer.Length() - lastBreak );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count += DrawText( gui, x, y, textScale, color, textBuffer.c_str(), 0, 0, 0 );
|
||||||
|
textBuffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cursor < lastBreak )
|
||||||
|
{
|
||||||
|
cursor = -1;
|
||||||
|
}
|
||||||
|
else if( cursor >= 0 )
|
||||||
|
{
|
||||||
|
cursor -= ( lastBreak + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If wrap is disabled return at this point.
|
||||||
|
if( !wrap )
|
||||||
|
{
|
||||||
|
return lastBreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've hit the allowed character limit then break.
|
||||||
|
if( limit && count > limit )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
y += lineSkip + 5;
|
||||||
|
|
||||||
|
if( !calcOnly && y > rectDraw.Bottom() )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If breaks were requested then make a note of this one.
|
||||||
|
if( breaks )
|
||||||
|
{
|
||||||
|
breaks->Append( drawText.Length() - charIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset necessary parms for next line.
|
||||||
|
lastBreak = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
textWidthAtLastBreak = 0;
|
||||||
|
lineBreak = false;
|
||||||
|
wordBreak = false;
|
||||||
|
|
||||||
|
// Reassess the remaining width
|
||||||
|
for( int i = 0; i < textBuffer.Length(); )
|
||||||
|
{
|
||||||
|
if( textChar != C_COLOR_ESCAPE )
|
||||||
|
{
|
||||||
|
textWidth += debugFont->GetGlyphWidth( textScale, textBuffer.UTF8Char( i ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return idMath::Ftoi( rectWidth / charSkip );
|
||||||
|
}
|
|
@ -67,6 +67,41 @@ struct swfRect_t
|
||||||
swfRect_t();
|
swfRect_t();
|
||||||
idVec2 tl;
|
idVec2 tl;
|
||||||
idVec2 br;
|
idVec2 br;
|
||||||
|
|
||||||
|
// RB: helpers
|
||||||
|
swfRect_t( float x, float y, float w, float h )
|
||||||
|
{
|
||||||
|
tl.x = x;
|
||||||
|
tl.y = y;
|
||||||
|
br.x = x + w;
|
||||||
|
br.y = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float x() const
|
||||||
|
{
|
||||||
|
return tl.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float y() const
|
||||||
|
{
|
||||||
|
return tl.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float w() const
|
||||||
|
{
|
||||||
|
return fabs( br.x - tl.x );
|
||||||
|
}
|
||||||
|
|
||||||
|
float h() const
|
||||||
|
{
|
||||||
|
return fabs( br.y - tl.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Bottom() const
|
||||||
|
{
|
||||||
|
return br.y;
|
||||||
|
}
|
||||||
|
// RB end
|
||||||
};
|
};
|
||||||
struct swfMatrix_t
|
struct swfMatrix_t
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue