// maxX param is initially an X limit, but is also used as feedback. 0 = text was clipped to fit within, else maxX = next pos void CG_Text_Paint_Limit( float *maxX, float x, float y, float scale, const vector4 *color, const char *text, float adjust, int limit, int iMenuFont ) { qboolean bIsTrailingPunctuation; // this is kinda dirty, but... qhandle_t iFontIndex = MenuFontToHandle( iMenuFont ); //float fMax = *maxX; float iPixelLen = trap->R_Font_StrLenPixels( text, iFontIndex, scale ); if ( x + iPixelLen > *maxX ) { // whole text won't fit, so we need to print just the amount that does... // Ok, this is slow and tacky, but only called occasionally, and it works... char sTemp[4096] = { 0 }; // lazy assumption const char *psText = text; char *psOut = &sTemp[0]; char *psOutLastGood = psOut; unsigned int uiLetter; while ( *psText && (x + trap->R_Font_StrLenPixels( sTemp, iFontIndex, scale ) <= *maxX) && psOut < &sTemp[sizeof(sTemp)-1] ) { int iAdvanceCount; psOutLastGood = psOut; uiLetter = trap->R_AnyLanguage_ReadCharFromString( psText, &iAdvanceCount, &bIsTrailingPunctuation ); psText += iAdvanceCount; if ( uiLetter > 255 ) { *psOut++ = uiLetter >> 8; *psOut++ = uiLetter & 0xFF; } else
static void DrawPlayerCount_Free( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPLARGE ); const float fontScale = 0.5f, width = SCREEN_WIDTH / 2.0f, lineHeight = 14.0f; float y = 108.0f; const char *tmp = NULL; vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f }; int i, freeCount = 0, specCount = 0, botCount = 0; colour.a = fade; for ( i = 0; i < cg.numScores; i++ ) { clientInfo_t *ci = &cgs.clientinfo[cg.scores[i].client]; if ( ci->team == TEAM_FREE ) freeCount++; else if ( ci->team == TEAM_SPECTATOR ) specCount++; if ( ci->botSkill != -1 ) botCount++; } // player count if ( botCount ) tmp = va( "%i players / %i bots", freeCount - botCount, botCount ); else tmp = va( "%i players", freeCount ); trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour, fontHandle, -1, fontScale ); // spectator count tmp = va( "%2i spectators", specCount ); trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y + lineHeight * 20, tmp, &colour, fontHandle, -1, fontScale ); }
void CG_DrawFlagCarrierName( void ) { int fontHandle = MenuFontToHandle( FONT_Q3PLARGE ); float fontScale = 0.137f; vector4 color = { 1.0f, 1.0f, 1.0f, 1.0f }; vector3 worldPos = { 0.0f, 0.0f, 0.0f }; vector2 screenPos = { 0.0f, 0.0f }; char text[] = "FLAG CARRIER"; if ( (cgs.gametype < GT_FLAGS || !cg_drawFlagCarrier.boolean || cg.q3p.flagCarrierEntityNum == ENTITYNUM_NONE) && !cg_debugHUD->integer ) return; VectorCopy( cg_entities[cg.q3p.flagCarrierEntityNum].lerpOrigin, worldPos ); worldPos[2] += 64.0f; //FIXME: skews position on non 4:3 ratios // fix is in modbase/ja++ CG_WorldCoordToScreenCoordFloat( worldPos, &screenPos[0], &screenPos[1] ); trap->R_Font_DrawString( screenPos[0] - trap->R_Font_StrLenPixels( text, fontHandle, fontScale )/2.0f, screenPos[1], text, color, fontHandle|STYLE_DROPSHADOW, -1, fontScale ); //already drawn it this frame, reset ent num so we can scan again next frame cg.q3p.flagCarrierEntityNum = ENTITYNUM_NONE; trap->R_SetColor( NULL ); }
// shows current date and JA++ version static void DrawClientInfo( float fade ) { struct tm *timeinfo; time_t tm; char buf[256]; const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPMONO ); const float fontScale = 0.5f; const float lineHeight = trap->R_Font_HeightPixels( fontHandle, fontScale ); float y = SCREEN_HEIGHT - lineHeight - 4.0f; vector4 colour; VectorCopy4( &g_color_table[ColorIndex( COLOR_ORANGE )], &colour ); colour.a = fade; #ifdef REVISION // JA++ version trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( REVISION, fontHandle, fontScale ) - 21.0f, y, REVISION, &colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale ); y -= lineHeight; #endif // date time( &tm ); timeinfo = localtime( &tm ); Com_sprintf( buf, sizeof(buf), "%s %i%s %04i, %02i:%02i:%02i", months[timeinfo->tm_mon], timeinfo->tm_mday, GetDateSuffix( timeinfo->tm_mday ), 1900 + timeinfo->tm_year, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec ); trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( buf, fontHandle, fontScale ) - 12.0f, y, buf, &colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale ); }
void JKG_Slice_DrawGridSummary(int slot, float x, float y, float w, float h) { static const vec4_t topcol = {.2, 1, .2, 0.2f}; static const vec4_t botcol = {1, 0.2, 0.2, 0.2f}; int orientation = (slot >> 3) & 1; // 0 = Columns, 1 = Rows int index = slot & 7; vec4_t color; const char *text; float w2; if ((orientation == 0 && index >= sliceData.width) || (orientation == 1 && index >= sliceData.height) ) { UI_DrawRect(x, y, w, h, disabled); return; } else { UI_FillRect(x, y, w, h/2, topcol); UI_FillRect(x, y + (0.5f * h), w, h/2, botcol); if (sliceData.inputState == INPUTSTATE_AWAITINGLINE) { float phase = 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f; MAKERGBA(color, phase, phase, phase, 1.0f); UI_DrawRect(x, y, w, h, color); } else { UI_DrawRect(x, y, w, h, black); } } if (sliceData.summariesKnown) { text = va("%i", sliceData.summaries[slot].value); w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 ); text = va("%i", sliceData.summaries[slot].alarms); w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y+(h*0.5f)-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 ); } else { text = "?"; w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 ); w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y+(h*0.5f)-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 ); } }
void JKG_Slice_DrawDialog(int line, float x, float y, float w, float h) { float width; const char *text; if (!sliceData.dlgActive) { return; } if (line == 1) { text = sliceData.dlgText1; } else if (line == 2) { text = sliceData.dlgText2; } else { text = sliceData.dlgText3; } width = (float)trap->R_Font_StrLenPixels(text, MenuFontToHandle(1), 1) * 0.5f; x = x + ((w / 2) - (width / 2)); trap->R_Font_DrawString( x, y, text, colorWhite, MenuFontToHandle(1) | 0x80000000 , -1, 0.5f); }
static void DrawPlayers_Free( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() ); const float fontScale = 0.45f, lineHeight = 14.0f; float x = 0, y = 128.0f; const int playerCount = PlayerCount( TEAM_FREE ); // dirty hack, 7 players means 4 on left, so +1 then /2 (8/2==4) will give a good number (4 left, 3 right) // similarly, 8 players means 4 on left, so +1 then /2 (9/2==4) will give a good number (4 left, 4 right) ListPlayers_Free( fade, x, y, fontScale, fontHandle, lineHeight, 0, (playerCount + 1) / 2 ); ListPlayers_Free( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, (playerCount + 1) / 2, playerCount / 2 ); DrawSpectators( fade ); }
void JKG_PartyMngt_DrawDialog(int line, float x, float y, float w, float h) { float width; const char *text; //vec4_t shadow; if (!PDlgData.InUse) { return; } if (line == 1) { text = PDlgData.line1; } else if (line == 2) { text = PDlgData.line2; } else { text = PDlgData.line3; } width = (float)trap->R_Font_StrLenPixels(text, MenuFontToHandle(1), 1) * 0.5f; x = x + ((w / 2) - (width / 2)); //MAKERGBA(shadow,0,0,0,0.2f); //trap->R_Font_DrawString( x+1, y+1, text, shadow, MenuFontToHandle(1), -1, 0.5f); trap->R_Font_DrawString( x, y, text, colorWhite, MenuFontToHandle(1) | 0x80000000 , -1, 0.5f); }
void DrawPlayerCount_Team( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPLARGE ); const float fontScale = 0.5f, width = SCREEN_WIDTH / 2.0f, lineHeight = 14.0f; float y = 108.0f; const char *tmp = NULL; vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f }; int i, redCount = 0, blueCount = 0, specCount = 0, pingAccumRed = 0, pingAvgRed = 0, pingAccumBlue = 0, pingAvgBlue = 0; colour.a = fade; for ( i = 0; i < cg.numScores; i++ ) { if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_RED ) { pingAccumRed += cg.scores[i].ping; redCount++; } else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_BLUE ) { blueCount++; pingAccumBlue += cg.scores[i].ping; } else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR ) specCount++; } if ( redCount ) pingAvgRed = ceilf( pingAccumRed / redCount ); if ( blueCount ) pingAvgBlue = ceilf( pingAccumBlue / blueCount ); if ( cgs.scores1 >= cgs.scores2 ) { // red team tmp = va( S_COLOR_RED "%i players " S_COLOR_WHITE "(%3i avg ping)", redCount, pingAvgRed ); trap->R_Font_DrawString( width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour, fontHandle, -1, fontScale ); // blue team tmp = va( S_COLOR_CYAN "%i players " S_COLOR_WHITE "(%3i avg ping)", blueCount, pingAvgBlue ); trap->R_Font_DrawString( width + width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour, fontHandle, -1, fontScale ); } else { tmp = va( S_COLOR_CYAN "%i players " S_COLOR_WHITE "(%i avg ping)", blueCount, pingAvgBlue ); trap->R_Font_DrawString( width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour, fontHandle, -1, fontScale ); tmp = va( S_COLOR_RED "%i players " S_COLOR_WHITE "(%i avg ping)", redCount, pingAvgRed ); trap->R_Font_DrawString( width + width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour, fontHandle, -1, fontScale ); } tmp = va( "%2i spectators", specCount ); trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y + lineHeight * 20, tmp, &colour, fontHandle, -1, fontScale ); }
static void DrawPlayers_Team( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() ); const float fontScale = 0.5f, lineHeight = 14.0f; float x = 0, y = 128.0f; if ( cgs.scores1 >= cgs.scores2 ) { ListPlayers_Team( fade, x, y, fontScale, fontHandle, lineHeight, TEAM_RED ); ListPlayers_Team( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, TEAM_BLUE ); } else { ListPlayers_Team( fade, x, y, fontScale, fontHandle, lineHeight, TEAM_BLUE ); ListPlayers_Team( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, TEAM_RED ); } DrawSpectators( fade ); }
static void DrawSpectators( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() ); const float fontScale = 0.5f, lineHeight = 14.0f; float y = 128.0f; vector4 white = { 1.0f, 1.0f, 1.0f, 1.0f }; white.a = fade; CG_BuildSpectatorString(); cg.scoreboard.spectatorWidth = CG_Text_Width( cg.scoreboard.spectatorList, fontScale, fontHandle ); if ( cg.scoreboard.spectatorLen ) { const float dt = (cg.time - cg.scoreboard.spectatorResetTime)*0.0625f; cg.scoreboard.spectatorX = SCREEN_WIDTH - (1.0f)*dt; if ( cg.scoreboard.spectatorX < 0 - cg.scoreboard.spectatorWidth ) { cg.scoreboard.spectatorX = SCREEN_WIDTH; cg.scoreboard.spectatorResetTime = cg.time; } CG_Text_Paint( cg.scoreboard.spectatorX, (y + lineHeight * 20) - 3, fontScale, &white, cg.scoreboard.spectatorList, 0, 0, ITEM_TEXTSTYLE_SHADOWED, fontHandle ); } }
void JKG_Slice_DrawSecurityClearance(int slot, float x, float y, float w, float h) { const char *text; float w2; if (slot >= sliceData.securityLevels) { UI_DrawRect(x, y, w, h, disabled); return; } else { switch (sliceData.securityState[slot]) { case 0: UI_FillRect(x, y, w, h, red); break; case 1: UI_FillRect(x, y, w, h, orange); break; case 2: UI_FillRect(x, y, w, h, yellow); break; case 3: UI_FillRect(x, y, w, h, green); break; } UI_DrawRect(x, y, w, h, black); } text = va("%i", slot + 1); w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.5f; DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.5f, const_cast<float *>(white), text, 0, 0, 0, 0 ); }
void CG_DrawObituary( void ) { linkedList_t *node = NULL; float x = SCREEN_WIDTH/2.0f, y = 0.0f; float lineHeight = 20.0f; float iconSize = lineHeight*2.0f; int fontHandle = MenuFontToHandle( FONT_Q3PSMALL ); float fontScale = 0.8f;//0.2175f; if ( !cg_newObituary->integer ) return; trap->R_SetColor( NULL ); if ( cg_debugHUD.boolean ) { char *attackerName = "AttackerName"; char *targetName = "TargetName"; float attackerWidth = trap->R_Font_StrLenPixels( attackerName, fontHandle, fontScale ); float iconWidth = 2.0f + iconSize + 2.0f; float victimWidth = trap->R_Font_StrLenPixels( targetName, fontHandle, fontScale ); float totalWidth = attackerWidth + iconWidth + victimWidth; float startX = x - totalWidth/2.0f; trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += attackerWidth; CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_QUANTIZER] ].weaponIcon ); startX += iconWidth; trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += victimWidth; startX = x - totalWidth/2.0f; y += lineHeight; trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += attackerWidth; CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_MORTAR] ].weaponIcon ); startX += iconWidth; trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += victimWidth; startX = x - totalWidth/2.0f; y += lineHeight; trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += attackerWidth; CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_DIVERGENCE] ].weaponIcon ); startX += iconWidth; trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += victimWidth; startX = x - totalWidth/2.0f; y += lineHeight; } else { for ( node=cg.q3p.obituaryRoot; node; node=LinkedList_Traverse( node ) ) { obituary_t *obituary = (obituary_t*)node->data; if ( obituary->deathTime < cg.time - cg_obituaryTime->integer ) {//Free this object free( obituary ); LinkedList_RemoveObject( &cg.q3p.obituaryRoot, node ); node = cg.q3p.obituaryRoot;//HACK: Return to start of list continue; } else { float attackerWidth = trap->R_Font_StrLenPixels( obituary->attackerName, fontHandle, fontScale ); float iconWidth = 2.0f + iconSize + 2.0f; float victimWidth = trap->R_Font_StrLenPixels( obituary->targetName, fontHandle, fontScale ); float totalWidth = attackerWidth + iconWidth + victimWidth; float startX = x - totalWidth/2.0f; trap->R_Font_DrawString( startX, y, obituary->attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += attackerWidth; CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[obituary->mod] ].weaponIcon ); startX += iconWidth; trap->R_Font_DrawString( startX, y, obituary->targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale ); startX += victimWidth; y += lineHeight; } } } }
static void DrawServerInfo( float fade ) { const qhandle_t fontLarge = MenuFontToHandle( FONT_JAPPLARGE ), fontSmall = MenuFontToHandle( FONT_JAPPMONO ); const float fontScale = 0.5f, lineHeightBig = 14.0f, lineHeightSmall = trap->R_Font_HeightPixels( fontSmall, fontScale ); const char *tmp = NULL; float y = SCREEN_HEIGHT - lineHeightSmall - 4.0f; vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f }; colour.a = fade; // map name tmp = va( "%s (%s)", (char *)CG_ConfigString( CS_MESSAGE ), cgs.mapname ); trap->R_Font_DrawString( 0.0f, y, tmp, &colour, fontSmall | STYLE_DROPSHADOW, -1, fontScale ); y -= lineHeightSmall; // server name trap->R_Font_DrawString( 0.0f, y, cgs.japp.serverName, &colour, fontSmall | STYLE_DROPSHADOW, -1, fontScale ); y -= lineHeightSmall; y = 42.0f; // gametype tmp = BG_GetGametypeString( cgs.gametype ); trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); y += lineHeightBig; switch ( cgs.gametype ) { case GT_FFA: if ( cgs.timelimit && cgs.fraglimit ) { tmp = va( "Until " S_COLOR_YELLOW "%i " S_COLOR_WHITE "frags or " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i minutes", cgs.fraglimit, (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit ); } else if ( cgs.timelimit ) { tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "minutes", (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit ); } else if ( cgs.fraglimit ) tmp = va( "Until " S_COLOR_YELLOW "%i " S_COLOR_WHITE "frags", cgs.fraglimit ); else tmp = "Playing forever!"; trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); break; case GT_CTF: case GT_CTY: if ( cgs.timelimit && cgs.capturelimit ) { tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "captures or " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i minutes", max( cgs.scores1, cgs.scores2 ), cgs.capturelimit, (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit ); } else if ( cgs.timelimit ) { tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "minutes", (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit ); } else if ( cgs.capturelimit ) { tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "captures", max( cgs.scores1, cgs.scores2 ), cgs.capturelimit ); } else tmp = "Playing forever!"; trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); y += lineHeightBig * 2; //FALL THROUGH TO GENERIC TEAM GAME INFO! case GT_TEAM: if ( cgs.scores1 == cgs.scores2 ) { tmp = S_COLOR_YELLOW"Teams are tied"; trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); y += lineHeightBig; tmp = va( S_COLOR_RED"%i "S_COLOR_WHITE"/ "S_COLOR_CYAN"%i", cgs.scores1, cgs.scores2 ); trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); } else if ( cgs.scores1 > cgs.scores2 ) { tmp = S_COLOR_RED"Red "S_COLOR_WHITE"leads"; trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); y += lineHeightBig; tmp = va( S_COLOR_RED"%i "S_COLOR_WHITE"/ "S_COLOR_CYAN"%i", cgs.scores1, cgs.scores2 ); trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); } else { tmp = S_COLOR_CYAN"Blue "S_COLOR_WHITE"leads"; trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); y += lineHeightBig; tmp = va( S_COLOR_CYAN"%i "S_COLOR_WHITE"/ "S_COLOR_RED"%i", cgs.scores2, cgs.scores1 ); trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale ); } //TODO: playing until x/y break; default: break; } }
void JKG_Slice_DrawGridSlot(int slot, float x, float y, float w, float h) { vec4_t color; vec4_t color2; int row = slot >> 3; int col = slot & 7; const char *text = NULL; float w2; if (row >= sliceData.height || col >= sliceData.width) { UI_DrawRect(x, y, w, h, disabled); } else { if (sliceData.grid[row][col].active) { // Determine the color to show switch (sliceData.grid[row][col].type) { case 0: // Alarm node VectorCopy4M(red, color2); text = NULL; break; case 1: // Relay node VectorCopy4M(orange, color2); text = NULL; break; case 2: // Reset node VectorCopy4M(yellow, color2); text = "R"; break; case 3: // Access level 1 case 4: // Access level 2 case 5: // Access level 3 case 6: // Access level 4 case 7: // Access level 5 VectorCopy4M(green, color2); text = va("%i", sliceData.grid[row][col].type - 2); break; } if (sliceData.grid[row][col].revealTime) { float phase = (float)(trap->Milliseconds() - sliceData.grid[row][col].revealTime) / 250.0f; if (phase > 1.0f) phase = 1.0f; if (trap->Milliseconds() > sliceData.grid[row][col].revealTime + 250) { sliceData.grid[row][col].revealTime = 0; } LerpColor((float *)white, color2, color, phase); UI_FillRect(x, y, w, h, color); if (text) { color[0] = color[1] = color[2] = 1.0f; color[3] = phase; w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.4f, color, text, 0, 0, 0, 0 ); } } else { UI_FillRect(x, y, w, h, color2); if (text) { w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f; DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.4f, (float *)(white), text, 0, 0, 0, 0 ); } } } else { if (sliceData.grid[row][col].blinkTime) { int delta = trap->Milliseconds() - sliceData.grid[row][col].blinkTime; float phase; if (delta > 2350) { // ~(7.5 * PI)*100, so the node blinks 4 times and stops when faded out sliceData.grid[row][col].blinkTime = 0; } phase = 0.5f + (sin((float)delta / 100.0f) * 0.5); if (sliceData.grid[row][col].blinkColor) { LerpColor((float *)offcolor, (float *)green, color, phase); } else { LerpColor((float *)offcolor, (float *)red, color, phase); } UI_FillRect(x, y, w, h, color); } else { if (sliceData.grid[row][col].marked) { if (sliceData.grid[row][col].marked == 1) { MAKERGBA(color, 0.3f, 0.3f, 1.0f, 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f); } else { MAKERGBA(color, 1.0f, 0.3f, .3f, 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f); } UI_FillRect(x, y, w, h, color); } else { UI_FillRect(x, y, w, h, offcolor); } } } if (sliceData.inputState == INPUTSTATE_AWAITINGNODE || (sliceData.inputState == INPUTSTATE_AWAITINGINACTIVENODE && !sliceData.grid[row][col].active)) { float phase = 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f; MAKERGBA(color, phase, phase, phase, 1.0f); UI_DrawRect(x, y, w, h, color); } else { UI_DrawRect(x, y, w, h, black); } } }