mirror of
https://github.com/ProjectDreamland/area51.git
synced 2024-11-01 11:11:47 +01:00
843 lines
24 KiB
C++
843 lines
24 KiB
C++
|
//==============================================================================
|
||
|
//
|
||
|
// hud_TextRenderer.cpp
|
||
|
//
|
||
|
// Copyright (c) 2002-2004 Inevitable Entertainment Inc. All rights reserved.
|
||
|
//
|
||
|
//==============================================================================
|
||
|
|
||
|
//==============================================================================
|
||
|
// INCLUDES
|
||
|
//==============================================================================
|
||
|
|
||
|
#include "hud_Text.hpp"
|
||
|
#include "HudObject.hpp"
|
||
|
|
||
|
#include "Ui/ui_font.hpp"
|
||
|
#include "stringmgr\stringmgr.hpp"
|
||
|
#ifndef X_EDITOR
|
||
|
#include "Ui/ui_manager.hpp"
|
||
|
#endif
|
||
|
|
||
|
#if defined(TARGET_PS2)
|
||
|
#include "Entropy\PS2\ps2_misc.hpp"
|
||
|
#endif
|
||
|
|
||
|
// These must be positive and in increasing order. Shouldn't overlap,
|
||
|
// but there can be gaps if so desired. Units are in seconds.
|
||
|
#define SCROLL_DOWN_START 1.9f
|
||
|
#define SCROLL_DOWN_END 2.0f
|
||
|
|
||
|
#define SLIDE_IN_START 0.0f
|
||
|
#define SLIDE_IN_END 0.0f
|
||
|
|
||
|
#define FLARE_START 2.5f
|
||
|
#define FLARE_END 3.0f
|
||
|
|
||
|
|
||
|
// These must be negative and in decreasing order.
|
||
|
#define SLIDE_OUT_START -0.0f
|
||
|
#define SLIDE_OUT_END -0.0f
|
||
|
|
||
|
#define SCROLL_UP_START -2.0f
|
||
|
#define SCROLL_UP_END -2.1f
|
||
|
|
||
|
#define BASE_MSG_STAY 1.8f
|
||
|
#define MSG_STAY_PER_CHAR 0.04f
|
||
|
#define MAX_MSG_STAY 8.0f
|
||
|
|
||
|
#define MAX_CHARS_SOFT 240 // Point after which to set message time left to SLIDE_OUT_START because we're getting too much to display.
|
||
|
#define MAX_CHARS_HARD 300 // Point after which to set message inuse field to FALSE.
|
||
|
#define MAX_LINES_SOFT 5 // Number of lines after which we start immediately fading.
|
||
|
#define MAX_LINES_HARD 5 // Number of lines after which we make any disappear immediately.
|
||
|
|
||
|
|
||
|
//==============================================================================
|
||
|
// FUNCTIONS
|
||
|
//==============================================================================
|
||
|
|
||
|
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
hud_text::hud_text( void )
|
||
|
{
|
||
|
m_NumDisplay = 5;
|
||
|
m_CursorPos = 0.0f;
|
||
|
m_TopLine = 0;
|
||
|
m_NumGoals = 0;
|
||
|
|
||
|
m_MaxTextWidth = 100;
|
||
|
|
||
|
m_TopGoal = 0;
|
||
|
|
||
|
m_TextBoxRect.l = 0;
|
||
|
m_TextBoxRect.t = 0;
|
||
|
m_TextBoxRect.r = 0;
|
||
|
m_TextBoxRect.b = 0;
|
||
|
|
||
|
m_PosX = 50;
|
||
|
m_PosY = 50;
|
||
|
|
||
|
s32 i;
|
||
|
for( i = 0; i < MAX_QUEUE; i++ )
|
||
|
{
|
||
|
m_Lines[ i ].Reset();
|
||
|
|
||
|
}
|
||
|
|
||
|
for( i = 0; i < MAX_GOALS; i++ )
|
||
|
{
|
||
|
m_Goals[ i ].Reset();
|
||
|
}
|
||
|
|
||
|
m_Bonus.Reset();
|
||
|
m_WeaponInfo.Reset();
|
||
|
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_CLOSED;
|
||
|
m_PercentOpen = 0.0f;
|
||
|
//m_IncomingBmp.SetName(PRELOAD_FILE("HUD_Campaign_incoming.xbmp"));
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
// I'm using this instead of a straight circular queue like the messages use
|
||
|
// because goals can come and go as they please, leaving gaps in any queue.
|
||
|
s32 hud_text::GetIthGoal( s32 Index )
|
||
|
{
|
||
|
s32 Last = -1;
|
||
|
|
||
|
s32 i;
|
||
|
for( i = 0; i <= Index; i++ )
|
||
|
{
|
||
|
s32 Current = -1;
|
||
|
|
||
|
s32 j;
|
||
|
for( j = 0; j < MAX_GOALS; j++ )
|
||
|
{
|
||
|
if( m_Goals[ j ].InUse )
|
||
|
{
|
||
|
|
||
|
if( (Last == -1) || (m_Goals[ j ].SeqNum > m_Goals[ Last ].SeqNum) )
|
||
|
{
|
||
|
if( (Current == -1) || (m_Goals[ j ].SeqNum < m_Goals[ Current ].SeqNum) )
|
||
|
{
|
||
|
Current = j;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
Last = Current;
|
||
|
}
|
||
|
|
||
|
return Last;
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
hud_text::~hud_text( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
s32 s_wi_t = 340;
|
||
|
s32 s_wi_b = 360;
|
||
|
s32 s_wi_l = 400;
|
||
|
s32 s_wi_r = 500;
|
||
|
|
||
|
static xcolor CHAT_RECT_COLOR_GREEN = xcolor( 0,31,0,127 );
|
||
|
static xbool CHAT_DROP_SHADOW = FALSE;
|
||
|
static xcolor TEXT_BOX_BACK_COLOR = xcolor( 0,0,0,80);
|
||
|
#define CHAT_BOX_LINEFEED 17
|
||
|
void hud_text::OnRender( player* pPlayer )
|
||
|
{
|
||
|
#ifndef X_EDITOR
|
||
|
(void)pPlayer;
|
||
|
|
||
|
// Get the hardware resolution for use later
|
||
|
s32 XRes;
|
||
|
s32 YRes;
|
||
|
eng_GetRes( XRes, YRes );
|
||
|
|
||
|
ui_font* pFont = g_UiMgr->GetFont( "small" );
|
||
|
|
||
|
irect iRect;
|
||
|
|
||
|
s32 TopFullLine = (s32)(m_CursorPos);
|
||
|
f32 Offset = m_CursorPos - TopFullLine;
|
||
|
|
||
|
u8 Alpha = 255;
|
||
|
u8 RectAlpha = 180;
|
||
|
|
||
|
s32 i;
|
||
|
|
||
|
f32 CurrentOffset = m_YPos;
|
||
|
|
||
|
//
|
||
|
// Render the goals
|
||
|
//
|
||
|
for( i = 0; i < m_NumGoals; i++ )
|
||
|
{
|
||
|
s32 iGoal = GetIthGoal( i );
|
||
|
|
||
|
if( m_Goals[ iGoal ].InUse )
|
||
|
{
|
||
|
f32 PercentOnScreen = 0.0f;
|
||
|
xwchar* pLine = m_Goals[ iGoal ].Text;
|
||
|
|
||
|
PercentOnScreen = 1.0f;
|
||
|
|
||
|
//Find the ith goal
|
||
|
iRect.t = (s32)CurrentOffset;
|
||
|
iRect.b = (s32)CurrentOffset + pFont->TextHeight(pLine);//CHAT_BOX_LINEFEED;
|
||
|
iRect.l = (s32)0;
|
||
|
iRect.r = (s32)0;
|
||
|
|
||
|
CurrentOffset += pFont->TextHeight(pLine);//CHAT_BOX_LINEFEED;
|
||
|
|
||
|
iRect.l = (s32)m_XPos;
|
||
|
iRect.r = (s32)pFont->TextWidth(pLine)+(s32)m_XPos+8;
|
||
|
|
||
|
if( m_Goals[iGoal].KeyingPos < 400 )
|
||
|
{
|
||
|
m_Goals[iGoal].KeyingPos+=10;
|
||
|
|
||
|
// scissor region
|
||
|
#ifdef TARGET_PS2
|
||
|
gsreg_Begin( 1 );
|
||
|
gsreg_SetScissor(
|
||
|
/*iRect.l*/0,
|
||
|
iRect.t,
|
||
|
iRect.l+(s32)m_Goals[iGoal].KeyingPos,
|
||
|
iRect.b
|
||
|
);
|
||
|
gsreg_End();
|
||
|
#endif
|
||
|
|
||
|
#ifdef TARGET_XBOX
|
||
|
D3DRECT Rects[1];
|
||
|
Rects[0].x1 = /*iRect.l*/0;
|
||
|
Rects[0].y1 = iRect.t;
|
||
|
Rects[0].x2 = iRect.l+(s32)m_Goals[iGoal].KeyingPos;
|
||
|
Rects[0].y2 = iRect.b;
|
||
|
g_pd3dDevice->SetScissors( 1,FALSE,Rects );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
xcolor TextColor = XCOLOR_WHITE;
|
||
|
RectAlpha = CHAT_RECT_COLOR_GREEN.A;
|
||
|
Alpha = (u8)(255 * (m_Goals[ iGoal ].Time > 0.25f ? 1.0f : (m_Goals[ iGoal ].Time * 4.0f)));
|
||
|
RectAlpha = (u8)(CHAT_RECT_COLOR_GREEN.A * (m_Goals[ iGoal ].Time > 0.25f ? 1.0f : (m_Goals[ iGoal ].Time * 4.0f)));
|
||
|
|
||
|
// full rect area
|
||
|
|
||
|
xcolor greenColor;
|
||
|
greenColor = CHAT_RECT_COLOR_GREEN;
|
||
|
greenColor.A = RectAlpha;
|
||
|
|
||
|
draw_Rect( iRect, greenColor, FALSE);
|
||
|
|
||
|
// blended end
|
||
|
irect iFadeOut;
|
||
|
iFadeOut.l = iRect.r;
|
||
|
iFadeOut.r = iFadeOut.l+8;
|
||
|
iFadeOut.t = iRect.t;
|
||
|
iFadeOut.b = iRect.b;
|
||
|
draw_GouraudRect(iFadeOut,greenColor,greenColor,xcolor(0,31,0,0),xcolor(0,31,0,0),FALSE);
|
||
|
|
||
|
// blended start
|
||
|
irect iFadeIn;
|
||
|
iFadeIn.l = iRect.l-8;
|
||
|
iFadeIn.r = iRect.l;
|
||
|
iFadeIn.t = iRect.t;
|
||
|
iFadeIn.b = iRect.b;
|
||
|
draw_GouraudRect(iFadeIn,xcolor(0,180,0,80),xcolor(0,180,0,80),greenColor,greenColor,FALSE);
|
||
|
|
||
|
// Bright side line.
|
||
|
irect rLine;
|
||
|
rLine.Set(iRect.l-8,iRect.t,iRect.l-7,iRect.b);
|
||
|
draw_Rect(rLine,g_HudColor,TRUE);
|
||
|
|
||
|
// text
|
||
|
iRect.t-=1;
|
||
|
iRect.b-=1;
|
||
|
RenderLine( pLine, iRect, Alpha, TextColor, 1, ui_font::h_left|ui_font::v_top, CHAT_DROP_SHADOW );
|
||
|
|
||
|
// restore scissor region
|
||
|
#ifdef TARGET_PS2
|
||
|
gsreg_Begin( 1 );
|
||
|
gsreg_SetScissor( 0, 0, XRes, YRes );
|
||
|
gsreg_End();
|
||
|
#endif
|
||
|
|
||
|
#ifdef TARGET_XBOX
|
||
|
// ensure we're not using a shrunken viewport
|
||
|
g_pd3dDevice->SetViewport( NULL );
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iRect.l = (s32)m_XPos+1;
|
||
|
iRect.r = (s32)300;
|
||
|
|
||
|
CurrentOffset += 0.0f;
|
||
|
|
||
|
i = TopFullLine;
|
||
|
if( Offset > 0.0f )
|
||
|
{
|
||
|
i += 1;
|
||
|
CurrentOffset -= (1.0f - Offset) * pFont->TextHeight( m_Lines[ i % MAX_QUEUE ].Text );
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Render the messages to the display
|
||
|
//
|
||
|
for( ;
|
||
|
(i >= 0) && (i > (TopFullLine - m_NumDisplay));
|
||
|
i-- )
|
||
|
{
|
||
|
s32 QueueIndex = i % MAX_QUEUE;
|
||
|
|
||
|
const xwchar* pLine = m_Lines[ QueueIndex ].Text;
|
||
|
|
||
|
iRect.t = (s32)CurrentOffset;
|
||
|
iRect.b = iRect.t + pFont->TextHeight(pLine);//CHAT_BOX_LINEFEED;
|
||
|
|
||
|
iRect.l = (s32)m_XPos;
|
||
|
iRect.r = (s32)pFont->TextWidth(pLine)+(s32)m_XPos+8;
|
||
|
|
||
|
// Blank line?
|
||
|
if( iRect.r-8 <= iRect.l )
|
||
|
{
|
||
|
iRect.r = iRect.l;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CurrentOffset += pFont->TextHeight(pLine);//CHAT_BOX_LINEFEED;
|
||
|
|
||
|
RectAlpha = CHAT_RECT_COLOR_GREEN.A;
|
||
|
|
||
|
// Alpha for top line as it scrolls in.
|
||
|
if( i == (TopFullLine + 1) )
|
||
|
{
|
||
|
Alpha = (u8)(255 * Offset);
|
||
|
RectAlpha = (u8)(CHAT_RECT_COLOR_GREEN.A * Offset);
|
||
|
}
|
||
|
|
||
|
// Alpha for bottom line that is potentially timing out or scrolling out.
|
||
|
else if( i == (TopFullLine - m_NumDisplay + 1) )
|
||
|
{
|
||
|
u8 Option1 = (u8)(255 * (1.0f - Offset));
|
||
|
u8 Option2 = (u8)(255 * (m_Lines[ QueueIndex ].Time > 0.25f ? 1.0f : (m_Lines[ QueueIndex ].Time * 4.0f)));
|
||
|
|
||
|
Alpha = x_min(Option1, Option2);
|
||
|
|
||
|
Option1 = (u8)(CHAT_RECT_COLOR_GREEN.A * (1.0f - Offset));
|
||
|
Option2 = (u8)(CHAT_RECT_COLOR_GREEN.A * (m_Lines[ QueueIndex ].Time > 0.25f ? 1.0f : (m_Lines[ QueueIndex ].Time * 4.0f)));
|
||
|
|
||
|
RectAlpha = x_min(Option1, Option2);
|
||
|
}
|
||
|
|
||
|
// Alpha for all other lines that could potentially be timing out.
|
||
|
else
|
||
|
{
|
||
|
Alpha = (u8)(255 * (m_Lines[ QueueIndex ].Time > 0.25f ? 1.0f : (m_Lines[ QueueIndex ].Time * 4.0f)));
|
||
|
RectAlpha = (u8)(CHAT_RECT_COLOR_GREEN.A * (m_Lines[ QueueIndex ].Time > 0.25f ? 1.0f : (m_Lines[ QueueIndex ].Time * 4.0f)));
|
||
|
}
|
||
|
|
||
|
xcolor TextColor = XCOLOR_WHITE;
|
||
|
|
||
|
xcolor greenColor = CHAT_RECT_COLOR_GREEN;
|
||
|
greenColor.A = RectAlpha;
|
||
|
|
||
|
// full rect area
|
||
|
draw_Rect( iRect, greenColor, FALSE);
|
||
|
|
||
|
// blended end
|
||
|
irect iFadeOut;
|
||
|
iFadeOut.l = iRect.r;
|
||
|
iFadeOut.r = iFadeOut.l+8;
|
||
|
iFadeOut.t = iRect.t;
|
||
|
iFadeOut.b = iRect.b;
|
||
|
draw_GouraudRect(iFadeOut,greenColor,greenColor,xcolor(0,31,0,0),xcolor(0,31,0,0),FALSE);
|
||
|
|
||
|
// blended Start
|
||
|
irect iFadeIn;
|
||
|
iFadeIn.l = iRect.l-8;
|
||
|
iFadeIn.r = iRect.l;
|
||
|
iFadeIn.t = iRect.t;
|
||
|
iFadeIn.b = iRect.b;
|
||
|
draw_GouraudRect(iFadeIn,xcolor(0,180,0,80),xcolor(0,180,0,80),greenColor,greenColor,FALSE);
|
||
|
|
||
|
// Bright side line.
|
||
|
irect rLine;
|
||
|
rLine.Set(iRect.l-8,iRect.t,iRect.l-7,iRect.b);
|
||
|
draw_Rect(rLine,g_HudColor,TRUE);
|
||
|
|
||
|
// text
|
||
|
iRect.t-=1;
|
||
|
iRect.b-=1;
|
||
|
RenderLine( pLine, iRect, Alpha, TextColor, 1, ui_font::h_left|ui_font::v_top, CHAT_DROP_SHADOW );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Render the bonus text
|
||
|
//
|
||
|
if( m_Bonus.InUse )
|
||
|
{
|
||
|
static irect BonusRect = irect(0,148,512,448);
|
||
|
|
||
|
rect ViewDimensions;
|
||
|
view& rView = pPlayer->GetView();
|
||
|
rView.GetViewport( ViewDimensions );
|
||
|
BonusRect.r = (s32)ViewDimensions.GetWidth();
|
||
|
BonusRect.b = (s32)ViewDimensions.GetHeight();
|
||
|
|
||
|
xcolor TextColor = XCOLOR_YELLOW;
|
||
|
RenderLine( m_Bonus.Text, BonusRect, 255, TextColor, 1, ui_font::h_center|ui_font::v_top, TRUE );
|
||
|
}
|
||
|
|
||
|
// Render Weapon Info Text
|
||
|
if( m_WeaponInfo.InUse )
|
||
|
{
|
||
|
iRect.t = s_wi_t; // 340
|
||
|
iRect.b = s_wi_b; // 360
|
||
|
iRect.l = s_wi_l; // 400
|
||
|
iRect.r = s_wi_r; // 500
|
||
|
|
||
|
xcolor TextColor = XCOLOR_BLUE;
|
||
|
RenderLine( m_WeaponInfo.Text, iRect, 255, TextColor, 0, ui_font::h_left|ui_font::v_bottom, TRUE );
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
inline void hud_text::AddLinesAndChars( s32& NumLines, s32& NumChars, xwchar* pLine )
|
||
|
{
|
||
|
if( *pLine == 0 )
|
||
|
return;
|
||
|
|
||
|
{
|
||
|
NumLines++;
|
||
|
while( *pLine != 0 )
|
||
|
{
|
||
|
// Linebreak?
|
||
|
if( *pLine == '\n' )
|
||
|
{
|
||
|
NumLines++;
|
||
|
}
|
||
|
|
||
|
// Normal character?
|
||
|
else if( (*pLine & 0xFF00) != 0xFF00 )
|
||
|
{
|
||
|
NumChars++;
|
||
|
}
|
||
|
|
||
|
// Skip color codes.
|
||
|
else
|
||
|
{
|
||
|
pLine++;
|
||
|
}
|
||
|
|
||
|
pLine++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
inline void hud_text::ClearAllBelow( s32 MsgIndex )
|
||
|
{
|
||
|
while( (MsgIndex >= 0) && ( (MsgIndex % MAX_QUEUE != m_TopLine % MAX_QUEUE) || (MsgIndex == m_TopLine)) )
|
||
|
{
|
||
|
m_Lines[ MsgIndex % MAX_QUEUE ].Time = 0.0f;
|
||
|
m_Lines[ MsgIndex % MAX_QUEUE ].InUse = FALSE;
|
||
|
|
||
|
m_Lines[ MsgIndex % MAX_QUEUE ].Reset();
|
||
|
|
||
|
MsgIndex--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
static s32 TEXT_BOX_POS_L = 16;
|
||
|
static s32 TEXT_BOX_POS_T = 16;
|
||
|
static s32 TEXT_BOX_POS_R = 350;
|
||
|
static s32 TEXT_BOX_LINE_HEIGHT = CHAT_BOX_LINEFEED;
|
||
|
static f32 TEXT_BOX_OPEN_SPEED = 6.0f;
|
||
|
|
||
|
void hud_text::OnAdvanceLogic( player* pPlayer, f32 DeltaTime )
|
||
|
{
|
||
|
(void)pPlayer;
|
||
|
|
||
|
s32 LinesDisplayed = 0; // How many lines we're potentially displaying on the screen.
|
||
|
s32 CharsDisplayed = 0; // How many characters we're displaying on the screen.
|
||
|
|
||
|
s32 textWidth = 0;
|
||
|
|
||
|
#ifndef X_EDITOR
|
||
|
ui_font* pFont = g_UiMgr->GetFont( "small" );
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Do all goal sliding here
|
||
|
//
|
||
|
for( s32 i = 0; i < MAX_GOALS; i++ )
|
||
|
{
|
||
|
// Is this goal currently active?
|
||
|
if( m_Goals[ i ].InUse )
|
||
|
{
|
||
|
AddLinesAndChars( LinesDisplayed, CharsDisplayed, m_Goals[ i ].Text );
|
||
|
#ifndef X_EDITOR
|
||
|
textWidth = MAX(textWidth, pFont->TextWidth(m_Goals[i].Text));
|
||
|
#endif
|
||
|
m_Goals[ i ].Time -= DeltaTime;
|
||
|
|
||
|
if( m_Goals[ i ].Time <= 0.0f )
|
||
|
{
|
||
|
m_Goals[ i ].Reset();
|
||
|
m_NumGoals--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Do normal message logic here.
|
||
|
//
|
||
|
{
|
||
|
// Scroll the messages some if they need scrolling.
|
||
|
const f32 ScrollSpeed = 0.8f;
|
||
|
if( m_CursorPos < m_TopLine )
|
||
|
{
|
||
|
f32 Scroll = (5.0f + (m_TopLine - m_CursorPos)) * DeltaTime * ScrollSpeed;
|
||
|
|
||
|
m_CursorPos += Scroll;
|
||
|
|
||
|
if( m_CursorPos > m_TopLine )
|
||
|
{
|
||
|
m_CursorPos = (f32)m_TopLine;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This makes sure that only m_NumDisplay messages are ever visible.
|
||
|
// I'm using m_CursorPos because that allows an extra message to be on the screen
|
||
|
// a new one is in the process of scrolling in.
|
||
|
ClearAllBelow( (s32)m_CursorPos - m_NumDisplay );
|
||
|
|
||
|
// Loop through all the messages and make sure we never have too much text
|
||
|
// on the screen or take up too much space, and time out the last visible message.
|
||
|
for( s32 i = m_TopLine; i >= 0; i-- )
|
||
|
{
|
||
|
// Add this line to the current running tally of messages.
|
||
|
AddLinesAndChars( LinesDisplayed, CharsDisplayed, m_Lines[ i % MAX_QUEUE ].Text );
|
||
|
|
||
|
#ifndef X_EDITOR
|
||
|
textWidth = MAX(textWidth, pFont->TextWidth(m_Lines[ i % MAX_QUEUE ].Text));
|
||
|
#endif
|
||
|
|
||
|
// Have we gone over the hard limit? Then immediately remove this line.
|
||
|
if( (LinesDisplayed > MAX_LINES_HARD) ||
|
||
|
(CharsDisplayed > MAX_CHARS_HARD ) )
|
||
|
{
|
||
|
m_Lines[ i % MAX_QUEUE ].Time = 0.0f;
|
||
|
ClearAllBelow( i );
|
||
|
break;
|
||
|
}
|
||
|
// If we've gone over the soft limit, tell this line to hurry up and die.
|
||
|
else if( (LinesDisplayed > MAX_LINES_SOFT) ||
|
||
|
(CharsDisplayed > MAX_CHARS_SOFT) )
|
||
|
{
|
||
|
m_Lines[ i % MAX_QUEUE ].Time = x_min( 0.25f, m_Lines[ i % MAX_QUEUE ].Time );
|
||
|
ClearAllBelow( i - 1 );
|
||
|
}
|
||
|
|
||
|
// If the next one is dead, this one should be dying.
|
||
|
if( (!m_Lines[ (i - 1) % MAX_QUEUE ].InUse) )
|
||
|
{
|
||
|
m_Lines[ i % MAX_QUEUE ].Time -= DeltaTime;
|
||
|
|
||
|
if( m_Lines[ i % MAX_QUEUE ].Time <= 0.0f )
|
||
|
{
|
||
|
ClearAllBelow( i );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Bonus logic
|
||
|
//
|
||
|
if( m_Bonus.InUse )
|
||
|
{
|
||
|
m_Bonus.Time -= DeltaTime;
|
||
|
if( m_Bonus.Time < 0 )
|
||
|
{
|
||
|
m_Bonus.InUse = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( m_WeaponInfo.InUse )
|
||
|
{
|
||
|
m_WeaponInfo.Time -= DeltaTime;
|
||
|
if( m_WeaponInfo.Time < 0 )
|
||
|
{
|
||
|
m_WeaponInfo.InUse = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// setup the text box rect that draws around the text lines.
|
||
|
m_TextBoxRect.l = TEXT_BOX_POS_L;
|
||
|
m_TextBoxRect.t = TEXT_BOX_POS_T;
|
||
|
|
||
|
if( LinesDisplayed )
|
||
|
{
|
||
|
m_TextBoxRect.b = (TEXT_BOX_LINE_HEIGHT * (LinesDisplayed+1));
|
||
|
m_TextBoxRect.r = TEXT_BOX_POS_R;
|
||
|
m_RenderTextBoxRect = TRUE;
|
||
|
|
||
|
switch( m_TextBoxRectState )
|
||
|
{
|
||
|
case TEXT_BOX_STATE_CLOSED:
|
||
|
// Text box is closed so start to open it.
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_OPENING;
|
||
|
m_PercentOpen = 0.0f;
|
||
|
break;
|
||
|
|
||
|
case TEXT_BOX_STATE_OPENING:
|
||
|
// Calc the irect here for opening.
|
||
|
m_PercentOpen += (DeltaTime * TEXT_BOX_OPEN_SPEED);
|
||
|
|
||
|
if( m_PercentOpen >= 1.0f )
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_OPEN;
|
||
|
break;
|
||
|
|
||
|
case TEXT_BOX_STATE_OPEN:
|
||
|
// do nothing but render the box open.
|
||
|
m_PercentOpen = 1.0f;
|
||
|
break;
|
||
|
|
||
|
case TEXT_BOX_STATE_CLOSEING:
|
||
|
// If closeing then set to open again.
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_OPENING;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_RenderTextBoxRect = FALSE;
|
||
|
|
||
|
switch( m_TextBoxRectState )
|
||
|
{
|
||
|
case TEXT_BOX_STATE_OPEN:
|
||
|
case TEXT_BOX_STATE_OPENING:
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_CLOSEING;
|
||
|
break;
|
||
|
|
||
|
case TEXT_BOX_STATE_CLOSEING:
|
||
|
// Start Closing the box
|
||
|
m_PercentOpen -= (DeltaTime * TEXT_BOX_OPEN_SPEED);
|
||
|
if( m_PercentOpen <= 0 )
|
||
|
m_TextBoxRectState = TEXT_BOX_STATE_CLOSED;
|
||
|
break;
|
||
|
|
||
|
case TEXT_BOX_STATE_CLOSED:
|
||
|
// Do nothing we are closed.
|
||
|
m_PercentOpen = 0.0f;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_TextBoxRect.b = MAX( (s32)(m_TextBoxRect.b * m_PercentOpen), TEXT_BOX_POS_T)+8;
|
||
|
m_TextBoxRect.r = (s32)((textWidth+8+16) * m_PercentOpen)+TEXT_BOX_POS_L;
|
||
|
|
||
|
if( m_TextBoxRect.l > m_TextBoxRect.r )
|
||
|
m_TextBoxRect.l = m_TextBoxRect.r;
|
||
|
if( m_TextBoxRect.r < m_TextBoxRect.l )
|
||
|
m_TextBoxRect.r = m_TextBoxRect.l;
|
||
|
if( m_TextBoxRect.t > m_TextBoxRect.b )
|
||
|
m_TextBoxRect.t = m_TextBoxRect.b;
|
||
|
if( m_TextBoxRect.b < m_TextBoxRect.t )
|
||
|
m_TextBoxRect.b = m_TextBoxRect.t;
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
void hud_text::AddLine( const xwchar* pLine )
|
||
|
{
|
||
|
(void)pLine;
|
||
|
#ifndef X_EDITOR
|
||
|
m_TopLine++;
|
||
|
|
||
|
irect iRect(0, 0, m_MaxTextWidth, 400);
|
||
|
|
||
|
ui_font* pFont = g_UiMgr->GetFont( "small" );
|
||
|
xwstring WrappedLine;
|
||
|
pFont->TextWrap( pLine, iRect, WrappedLine );
|
||
|
const xwchar* pWrappedLine = (const xwchar*)WrappedLine;
|
||
|
|
||
|
s32 i = -1;
|
||
|
do {
|
||
|
i++;
|
||
|
m_Lines[ m_TopLine % MAX_QUEUE ].Text[ i ] = pWrappedLine[ i ];
|
||
|
} while( pWrappedLine[ i ] != 0 );
|
||
|
|
||
|
m_Lines[ m_TopLine % MAX_QUEUE ].InUse = FALSE;
|
||
|
|
||
|
f32 StayTime = BASE_MSG_STAY + (i * MSG_STAY_PER_CHAR);
|
||
|
|
||
|
if( StayTime > MAX_MSG_STAY )
|
||
|
{
|
||
|
StayTime = MAX_MSG_STAY;
|
||
|
}
|
||
|
|
||
|
m_Lines[ m_TopLine % MAX_QUEUE ].InUse = TRUE;
|
||
|
m_Lines[ m_TopLine % MAX_QUEUE ].Time = StayTime;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
void hud_text::AddGoal( s32 GoalID, const xwchar* pGoal, f32 Time )
|
||
|
{
|
||
|
(void)GoalID;
|
||
|
(void)pGoal;
|
||
|
(void)Time;
|
||
|
#ifndef X_EDITOR
|
||
|
s32 i;
|
||
|
|
||
|
irect iRect(0, 0, m_MaxTextWidth, 400);
|
||
|
|
||
|
ui_font* pFont = g_UiMgr->GetFont( "small" );
|
||
|
xwstring WrappedLine;
|
||
|
pFont->TextWrap( pGoal, iRect, WrappedLine );
|
||
|
const xwchar* pWrappedLine = (const xwchar*)WrappedLine;
|
||
|
|
||
|
for( i = 0; i < MAX_GOALS; i++ )
|
||
|
{
|
||
|
if( !m_Goals[ i ].InUse )
|
||
|
{
|
||
|
s32 j = -1;
|
||
|
do {
|
||
|
j++;
|
||
|
m_Goals[ i ].Text[ j ] = pWrappedLine[ j ];
|
||
|
} while( pWrappedLine[ j ] != 0 );
|
||
|
|
||
|
// Play Sound here?
|
||
|
g_AudioMgr.Play("HUD_Text_Alert", TRUE );
|
||
|
|
||
|
m_Goals[ i ].ScrollState = 1;
|
||
|
m_Goals[ i ].SeqNum = ++m_TopGoal;
|
||
|
m_Goals[ i ].InUse = TRUE;
|
||
|
m_Goals[ i ].Time = Time;
|
||
|
m_Goals[ i ].GoalID = GoalID;
|
||
|
m_Goals[ i ].KeyingPos = 0;
|
||
|
|
||
|
m_NumGoals++;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
void hud_text::UpdateGoal( s32 GoalID, xbool Enabled, const xwchar* pGoal, f32 Time )
|
||
|
{
|
||
|
s32 i;
|
||
|
for( i = 0; i < MAX_GOALS; i++ )
|
||
|
{
|
||
|
// This means that whoever created this goal does not want to manipulate it
|
||
|
// in the future and are planning on it fading on its own.
|
||
|
if( GoalID == -1 )
|
||
|
{
|
||
|
if( Enabled )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return; // You can't clear a goal created with -1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Updating or deleting:
|
||
|
if( GoalID == m_Goals[ i ].GoalID && m_Goals[ i ].InUse )
|
||
|
{
|
||
|
// If the time has changed, set that
|
||
|
if( Time >= 0 )
|
||
|
{
|
||
|
m_Goals[ i ].Time = Time;
|
||
|
}
|
||
|
|
||
|
// Copy the new text over
|
||
|
s32 j = -1;
|
||
|
do {
|
||
|
j++;
|
||
|
m_Goals[ i ].Text[ j ] = pGoal[ j ];
|
||
|
} while( pGoal[ j ] != 0 );
|
||
|
|
||
|
//if( m_Goals[ i ].ScrollState > FLARE_START )
|
||
|
//{
|
||
|
// m_Goals[ i ].ScrollState = FLARE_START;
|
||
|
//}
|
||
|
//else
|
||
|
//{
|
||
|
// m_Goals[ i ].ScrollState = SCROLL_DOWN_START;
|
||
|
//}
|
||
|
|
||
|
//if( !Enabled )
|
||
|
//{
|
||
|
// m_Goals[ i ].ScrollState = SLIDE_OUT_START;
|
||
|
//}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Creating:
|
||
|
if( Enabled )
|
||
|
{
|
||
|
AddGoal( GoalID, pGoal, Time );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
void hud_text::SetBonus( const xwchar* pBonus, f32 Time )
|
||
|
{
|
||
|
m_Bonus.Time = Time;
|
||
|
m_Bonus.InUse = TRUE;
|
||
|
|
||
|
s32 j = -1;
|
||
|
do {
|
||
|
j++;
|
||
|
m_Bonus.Text[ j ] = pBonus[ j ];
|
||
|
} while( pBonus[ j ] != 0 );
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
|
||
|
void hud_text::SetWeaponInfo( const xwchar* pWeaponInfo, f32 Time )
|
||
|
{
|
||
|
m_WeaponInfo.Time = Time;
|
||
|
m_WeaponInfo.InUse = TRUE;
|
||
|
|
||
|
s32 j = -1;
|
||
|
do {
|
||
|
j++;
|
||
|
m_WeaponInfo.Text[ j ] = pWeaponInfo[ j ];
|
||
|
} while( pWeaponInfo[ j ] != 0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//==============================================================================
|