2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 void SCR_DrawTextLeftAlign( float &y, const char *text, ... ) id_attribute((format(printf,2,3)));
33 void SCR_DrawTextRightAlign( float &y, const char *text, ... ) id_attribute((format(printf,2,3)));
36 #define NUM_CON_TIMES 4
37 #define CON_TEXTSIZE 0x30000
38 #define TOTAL_LINES (CON_TEXTSIZE / LINE_WIDTH)
39 #define CONSOLE_FIRSTREPEAT 200
40 #define CONSOLE_REPEAT 100
42 #define COMMAND_HISTORY 64
44 // the console will query the cvar and command systems for
45 // command completion information
47 class idConsoleLocal : public idConsole {
49 virtual void Init( void );
50 virtual void Shutdown( void );
51 virtual void LoadGraphics( void );
52 virtual bool ProcessEvent( const sysEvent_t *event, bool forceAccept );
53 virtual bool Active( void );
54 virtual void ClearNotifyLines( void );
55 virtual void Close( void );
56 virtual void Print( const char *text );
57 virtual void Draw( bool forceFullScreen );
59 void Dump( const char *toFile );
62 //============================
64 const idMaterial * charSetShader;
67 void KeyDownEvent( int key );
78 void DrawSolidConsole( float frac );
81 void SetDisplayFraction( float frac );
82 void UpdateDisplayFraction( void );
84 //============================
88 short text[CON_TEXTSIZE];
89 int current; // line where next message will be printed
90 int x; // offset in current line for next print
91 int display; // bottom of console displays this line
92 int lastKeyEvent; // time of last key event for scroll delay
93 int nextKeyEvent; // keyboard repeat rate
95 float displayFrac; // approaches finalFrac at scr_conspeed
96 float finalFrac; // 0.0 to 1.0 lines of console to display
97 int fracTime; // time of last displayFrac update
99 int vislines; // in scanlines
101 int times[NUM_CON_TIMES]; // cls.realtime time the line was generated
102 // for transparent notify lines
105 idEditField historyEditLines[COMMAND_HISTORY];
107 int nextHistoryLine;// the last line in the history buffer, not masked
108 int historyLine; // the line being displayed from history buffer
109 // will be <= nextHistoryLine
111 idEditField consoleField;
113 static idCVar con_speed;
114 static idCVar con_notifyTime;
115 static idCVar con_noPrint;
117 const idMaterial * whiteShader;
118 const idMaterial * consoleShader;
121 static idConsoleLocal localConsole;
122 idConsole *console = &localConsole;
124 idCVar idConsoleLocal::con_speed( "con_speed", "3", CVAR_SYSTEM, "speed at which the console moves up and down" );
125 idCVar idConsoleLocal::con_notifyTime( "con_notifyTime", "3", CVAR_SYSTEM, "time messages are displayed onscreen when console is pulled up" );
127 idCVar idConsoleLocal::con_noPrint( "con_noPrint", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "print on the console but not onscreen when console is pulled up" );
129 idCVar idConsoleLocal::con_noPrint( "con_noPrint", "1", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "print on the console but not onscreen when console is pulled up" );
135 =============================================================================
139 =============================================================================
144 SCR_DrawTextLeftAlign
147 void SCR_DrawTextLeftAlign( float &y, const char *text, ... ) {
148 char string[MAX_STRING_CHARS];
150 va_start( argptr, text );
151 idStr::vsnPrintf( string, sizeof( string ), text, argptr );
153 renderSystem->DrawSmallStringExt( 0, y + 2, string, colorWhite, true, localConsole.charSetShader );
154 y += SMALLCHAR_HEIGHT + 4;
159 SCR_DrawTextRightAlign
162 void SCR_DrawTextRightAlign( float &y, const char *text, ... ) {
163 char string[MAX_STRING_CHARS];
165 va_start( argptr, text );
166 int i = idStr::vsnPrintf( string, sizeof( string ), text, argptr );
168 renderSystem->DrawSmallStringExt( 635 - i * SMALLCHAR_WIDTH, y + 2, string, colorWhite, true, localConsole.charSetShader );
169 y += SMALLCHAR_HEIGHT + 4;
181 float SCR_DrawFPS( float y ) {
184 static int previousTimes[FPS_FRAMES];
191 // don't use serverTime, because that will be drifting to
192 // correct for internet lag changes, timescales, timedemos, etc
193 t = Sys_Milliseconds();
194 frameTime = t - previous;
197 previousTimes[index % FPS_FRAMES] = frameTime;
199 if ( index > FPS_FRAMES ) {
200 // average multiple frames together to smooth changes out a bit
202 for ( i = 0 ; i < FPS_FRAMES ; i++ ) {
203 total += previousTimes[i];
208 fps = 10000 * FPS_FRAMES / total;
211 s = va( "%ifps", fps );
212 w = strlen( s ) * BIGCHAR_WIDTH;
214 renderSystem->DrawBigStringExt( 635 - w, idMath::FtoiFast( y ) + 2, s, colorWhite, true, localConsole.charSetShader);
217 return y + BIGCHAR_HEIGHT + 4;
225 float SCR_DrawMemoryUsage( float y ) {
226 memoryStats_t allocs, frees;
228 Mem_GetStats( allocs );
229 SCR_DrawTextRightAlign( y, "total allocated memory: %4d, %4dkB", allocs.num, allocs.totalSize>>10 );
231 Mem_GetFrameStats( allocs, frees );
232 SCR_DrawTextRightAlign( y, "frame alloc: %4d, %4dkB frame free: %4d, %4dkB", allocs.num, allocs.totalSize>>10, frees.num, frees.totalSize>>10 );
234 Mem_ClearFrameStats();
244 float SCR_DrawAsyncStats( float y ) {
245 int i, outgoingRate, incomingRate;
246 float outgoingCompression, incomingCompression;
248 if ( idAsyncNetwork::server.IsActive() ) {
250 SCR_DrawTextRightAlign( y, "server delay = %d msec", idAsyncNetwork::server.GetDelay() );
251 SCR_DrawTextRightAlign( y, "total outgoing rate = %d KB/s", idAsyncNetwork::server.GetOutgoingRate() >> 10 );
252 SCR_DrawTextRightAlign( y, "total incoming rate = %d KB/s", idAsyncNetwork::server.GetIncomingRate() >> 10 );
254 for ( i = 0; i < MAX_ASYNC_CLIENTS; i++ ) {
256 outgoingRate = idAsyncNetwork::server.GetClientOutgoingRate( i );
257 incomingRate = idAsyncNetwork::server.GetClientIncomingRate( i );
258 outgoingCompression = idAsyncNetwork::server.GetClientOutgoingCompression( i );
259 incomingCompression = idAsyncNetwork::server.GetClientIncomingCompression( i );
261 if ( outgoingRate != -1 && incomingRate != -1 ) {
262 SCR_DrawTextRightAlign( y, "client %d: out rate = %d B/s (% -2.1f%%), in rate = %d B/s (% -2.1f%%)",
263 i, outgoingRate, outgoingCompression, incomingRate, incomingCompression );
268 idAsyncNetwork::server.GetAsyncStatsAvgMsg( msg );
269 SCR_DrawTextRightAlign( y, msg.c_str() );
271 } else if ( idAsyncNetwork::client.IsActive() ) {
273 outgoingRate = idAsyncNetwork::client.GetOutgoingRate();
274 incomingRate = idAsyncNetwork::client.GetIncomingRate();
275 outgoingCompression = idAsyncNetwork::client.GetOutgoingCompression();
276 incomingCompression = idAsyncNetwork::client.GetIncomingCompression();
278 if ( outgoingRate != -1 && incomingRate != -1 ) {
279 SCR_DrawTextRightAlign( y, "out rate = %d B/s (% -2.1f%%), in rate = %d B/s (% -2.1f%%)",
280 outgoingRate, outgoingCompression, incomingRate, incomingCompression );
283 SCR_DrawTextRightAlign( y, "packet loss = %d%%, client prediction = %d",
284 (int)idAsyncNetwork::client.GetIncomingPacketLoss(), idAsyncNetwork::client.GetPrediction() );
286 SCR_DrawTextRightAlign( y, "predicted frames: %d", idAsyncNetwork::client.GetPredictedFrames() );
295 SCR_DrawSoundDecoders
298 float SCR_DrawSoundDecoders( float y ) {
299 int index, numActiveDecoders;
300 soundDecoderInfo_t decoderInfo;
303 numActiveDecoders = 0;
304 while( ( index = soundSystem->GetSoundDecoderInfo( index, decoderInfo ) ) != -1 ) {
305 int localTime = decoderInfo.current44kHzTime - decoderInfo.start44kHzTime;
306 int sampleTime = decoderInfo.num44kHzSamples / decoderInfo.numChannels;
308 if ( localTime > sampleTime ) {
309 if ( decoderInfo.looping ) {
310 percent = ( localTime % sampleTime ) * 100 / sampleTime;
315 percent = localTime * 100 / sampleTime;
317 SCR_DrawTextLeftAlign( y, "%3d: %3d%% (%1.2f) %s: %s (%dkB)", numActiveDecoders, percent, decoderInfo.lastVolume, decoderInfo.format.c_str(), decoderInfo.name.c_str(), decoderInfo.numBytes >> 10 );
323 //=========================================================================
330 static void Con_Clear_f( const idCmdArgs &args ) {
331 localConsole.Clear();
339 static void Con_Dump_f( const idCmdArgs &args ) {
340 if ( args.Argc() != 2 ) {
341 common->Printf( "usage: conDump <filename>\n" );
345 idStr fileName = args.Argv(1);
346 fileName.DefaultFileExtension(".txt");
348 common->Printf( "Dumped console text to %s.\n", fileName.c_str() );
350 localConsole.Dump( fileName.c_str() );
358 void idConsoleLocal::Init( void ) {
364 nextKeyEvent = CONSOLE_FIRSTREPEAT;
366 consoleField.Clear();
368 consoleField.SetWidthInChars( LINE_WIDTH );
370 for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
371 historyEditLines[i].Clear();
372 historyEditLines[i].SetWidthInChars( LINE_WIDTH );
375 cmdSystem->AddCommand( "clear", Con_Clear_f, CMD_FL_SYSTEM, "clears the console" );
376 cmdSystem->AddCommand( "conDump", Con_Dump_f, CMD_FL_SYSTEM, "dumps the console text to a file" );
381 idConsoleLocal::Shutdown
384 void idConsoleLocal::Shutdown( void ) {
385 cmdSystem->RemoveCommand( "clear" );
386 cmdSystem->RemoveCommand( "conDump" );
393 Can't be combined with init, because init happens before
394 the renderSystem is initialized
397 void idConsoleLocal::LoadGraphics() {
398 charSetShader = declManager->FindMaterial( "textures/bigchars" );
399 whiteShader = declManager->FindMaterial( "_white" );
400 consoleShader = declManager->FindMaterial( "console" );
405 idConsoleLocal::Active
408 bool idConsoleLocal::Active( void ) {
414 idConsoleLocal::ClearNotifyLines
417 void idConsoleLocal::ClearNotifyLines() {
420 for ( i = 0 ; i < NUM_CON_TIMES ; i++ ) {
427 idConsoleLocal::Close
430 void idConsoleLocal::Close() {
432 SetDisplayFraction( 0 );
433 displayFrac = 0; // don't scroll to that point, go immediately
439 idConsoleLocal::Clear
442 void idConsoleLocal::Clear() {
445 for ( i = 0 ; i < CON_TEXTSIZE ; i++ ) {
446 text[i] = (idStr::ColorIndex(C_COLOR_CYAN)<<8) | ' ';
449 Bottom(); // go to end
456 Save the console contents out to a file
459 void idConsoleLocal::Dump( const char *fileName ) {
463 char buffer[LINE_WIDTH + 3];
465 f = fileSystem->OpenFileWrite( fileName );
467 common->Warning( "couldn't open %s", fileName );
472 l = current - TOTAL_LINES + 1;
476 for ( ; l <= current ; l++ )
478 line = text + ( l % TOTAL_LINES ) * LINE_WIDTH;
479 for ( x = 0; x < LINE_WIDTH; x++ )
480 if ( ( line[x] & 0xff ) > ' ' )
482 if ( x != LINE_WIDTH )
486 // write the remaining lines
487 for ( ; l <= current; l++ ) {
488 line = text + ( l % TOTAL_LINES ) * LINE_WIDTH;
489 for( i = 0; i < LINE_WIDTH; i++ ) {
490 buffer[i] = line[i] & 0xff;
492 for ( x = LINE_WIDTH-1; x >= 0; x-- ) {
493 if ( buffer[x] <= ' ' ) {
502 f->Write( buffer, strlen( buffer ) );
505 fileSystem->CloseFile( f );
510 idConsoleLocal::PageUp
513 void idConsoleLocal::PageUp( void ) {
515 if ( current - display >= TOTAL_LINES ) {
516 display = current - TOTAL_LINES + 1;
522 idConsoleLocal::PageDown
525 void idConsoleLocal::PageDown( void ) {
527 if ( display > current ) {
537 void idConsoleLocal::Top( void ) {
543 idConsoleLocal::Bottom
546 void idConsoleLocal::Bottom( void ) {
552 =============================================================================
556 ==============================================================================
563 Handles history and console scrollback
566 void idConsoleLocal::KeyDownEvent( int key ) {
568 // Execute F key bindings
569 if ( key >= K_F1 && key <= K_F12 ) {
570 idKeyInput::ExecKeyBinding( key );
574 // ctrl-L clears screen
575 if ( key == 'l' && idKeyInput::IsDown( K_CTRL ) ) {
580 // enter finishes the line
581 if ( key == K_ENTER || key == K_KP_ENTER ) {
583 common->Printf ( "]%s\n", consoleField.GetBuffer() );
585 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, consoleField.GetBuffer() ); // valid command
586 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
588 // copy line to history buffer
589 historyEditLines[nextHistoryLine % COMMAND_HISTORY] = consoleField;
591 historyLine = nextHistoryLine;
593 consoleField.Clear();
594 consoleField.SetWidthInChars( LINE_WIDTH );
596 session->UpdateScreen();// force an update, because the command
597 // may take some time
601 // command completion
603 if ( key == K_TAB ) {
604 consoleField.AutoComplete();
608 // command history (ctrl-p ctrl-n for unix style)
610 if ( ( key == K_UPARROW ) ||
611 ( ( tolower(key) == 'p' ) && idKeyInput::IsDown( K_CTRL ) ) ) {
612 if ( nextHistoryLine - historyLine < COMMAND_HISTORY && historyLine > 0 ) {
615 consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ];
619 if ( ( key == K_DOWNARROW ) ||
620 ( ( tolower( key ) == 'n' ) && idKeyInput::IsDown( K_CTRL ) ) ) {
621 if ( historyLine == nextHistoryLine ) {
625 consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ];
630 if ( key == K_PGUP ) {
632 lastKeyEvent = eventLoop->Milliseconds();
633 nextKeyEvent = CONSOLE_FIRSTREPEAT;
637 if ( key == K_PGDN ) {
639 lastKeyEvent = eventLoop->Milliseconds();
640 nextKeyEvent = CONSOLE_FIRSTREPEAT;
644 if ( key == K_MWHEELUP ) {
649 if ( key == K_MWHEELDOWN ) {
654 // ctrl-home = top of console
655 if ( key == K_HOME && idKeyInput::IsDown( K_CTRL ) ) {
660 // ctrl-end = bottom of console
661 if ( key == K_END && idKeyInput::IsDown( K_CTRL ) ) {
666 // pass to the normal editline routine
667 consoleField.KeyDownEvent( key );
673 deals with scrolling text because we don't have key repeat
676 void idConsoleLocal::Scroll( ) {
677 if (lastKeyEvent == -1 || (lastKeyEvent+200) > eventLoop->Milliseconds()) {
681 if ( idKeyInput::IsDown( K_PGUP ) ) {
683 nextKeyEvent = CONSOLE_REPEAT;
687 if ( idKeyInput::IsDown( K_PGDN ) ) {
689 nextKeyEvent = CONSOLE_REPEAT;
698 Causes the console to start opening the desired amount.
701 void idConsoleLocal::SetDisplayFraction( float frac ) {
703 fracTime = com_frameTime;
708 UpdateDisplayFraction
710 Scrolls the console up or down based on conspeed
713 void idConsoleLocal::UpdateDisplayFraction( void ) {
714 if ( con_speed.GetFloat() <= 0.1f ) {
715 fracTime = com_frameTime;
716 displayFrac = finalFrac;
720 // scroll towards the destination height
721 if ( finalFrac < displayFrac ) {
722 displayFrac -= con_speed.GetFloat() * ( com_frameTime - fracTime ) * 0.001f;
723 if ( finalFrac > displayFrac ) {
724 displayFrac = finalFrac;
726 fracTime = com_frameTime;
727 } else if ( finalFrac > displayFrac ) {
728 displayFrac += con_speed.GetFloat() * ( com_frameTime - fracTime ) * 0.001f;
729 if ( finalFrac < displayFrac ) {
730 displayFrac = finalFrac;
732 fracTime = com_frameTime;
741 bool idConsoleLocal::ProcessEvent( const sysEvent_t *event, bool forceAccept ) {
743 consoleKey = event->evType == SE_KEY && ( event->evValue == Sys_GetConsoleKey( false ) || event->evValue == Sys_GetConsoleKey( true ) );
746 // If the console's not already down, and we have it turned off, check for ctrl+alt
747 if ( !keyCatching && !com_allowConsole.GetBool() ) {
748 if ( !idKeyInput::IsDown( K_CTRL ) || !idKeyInput::IsDown( K_ALT ) ) {
754 // we always catch the console key event
755 if ( !forceAccept && consoleKey ) {
757 if ( event->evValue2 == 0 ) {
761 consoleField.ClearAutoComplete();
763 // a down event will toggle the destination lines
766 Sys_GrabMouseCursor( true );
767 cvarSystem->SetCVarBool( "ui_chat", false );
769 consoleField.Clear();
771 if ( idKeyInput::IsDown( K_SHIFT ) ) {
772 // if the shift key is down, don't open the console as much
773 SetDisplayFraction( 0.2f );
775 SetDisplayFraction( 0.5f );
777 cvarSystem->SetCVarBool( "ui_chat", true );
782 // if we aren't key catching, dump all the other events
783 if ( !forceAccept && !keyCatching ) {
787 // handle key and character events
788 if ( event->evType == SE_CHAR ) {
789 // never send the console key as a character
790 if ( event->evValue != Sys_GetConsoleKey( false ) && event->evValue != Sys_GetConsoleKey( true ) ) {
791 consoleField.CharEvent( event->evValue );
796 if ( event->evType == SE_KEY ) {
797 // ignore up key events
798 if ( event->evValue2 == 0 ) {
802 KeyDownEvent( event->evValue );
806 // we don't handle things like mouse, joystick, and network packets
811 ==============================================================================
815 ==============================================================================
823 void idConsoleLocal::Linefeed() {
826 // mark time for transparent overlay
827 if ( current >= 0 ) {
828 times[current % NUM_CON_TIMES] = com_frameTime;
832 if ( display == current ) {
836 for ( i = 0; i < LINE_WIDTH; i++ ) {
837 text[(current%TOTAL_LINES)*LINE_WIDTH+i] = (idStr::ColorIndex(C_COLOR_CYAN)<<8) | ' ';
846 Handles cursor positioning, line wrapping, etc
849 void idConsoleLocal::Print( const char *txt ) {
854 #ifdef ID_ALLOW_TOOLS
857 if( com_editors & EDITOR_MATERIAL ) {
858 MaterialEditorPrintConsole(txt);
862 color = idStr::ColorIndex( C_COLOR_CYAN );
864 while ( (c = *(const unsigned char*)txt) != 0 ) {
865 if ( idStr::IsColor( txt ) ) {
866 if ( *(txt+1) == C_COLOR_DEFAULT ) {
867 color = idStr::ColorIndex( C_COLOR_CYAN );
869 color = idStr::ColorIndex( *(txt+1) );
875 y = current % TOTAL_LINES;
877 // if we are about to print a new word, check to see
878 // if we should wrap to the new line
879 if ( c > ' ' && ( x == 0 || text[y*LINE_WIDTH+x-1] <= ' ' ) ) {
881 for (l=0 ; l< LINE_WIDTH ; l++) {
882 if ( txt[l] <= ' ') {
888 if (l != LINE_WIDTH && (x + l >= LINE_WIDTH) ) {
901 text[y*LINE_WIDTH+x] = (color << 8) | ' ';
903 if ( x >= LINE_WIDTH ) {
912 default: // display character and advance
913 text[y*LINE_WIDTH+x] = (color << 8) | c;
915 if ( x >= LINE_WIDTH ) {
924 // mark time for transparent overlay
925 if ( current >= 0 ) {
926 times[current % NUM_CON_TIMES] = com_frameTime;
932 ==============================================================================
936 ==============================================================================
944 Draw the editline after a ] prompt
947 void idConsoleLocal::DrawInput() {
948 int y, autoCompleteLength;
950 y = vislines - ( SMALLCHAR_HEIGHT * 2 );
952 if ( consoleField.GetAutoCompleteLength() != 0 ) {
953 autoCompleteLength = strlen( consoleField.GetBuffer() ) - consoleField.GetAutoCompleteLength();
955 if ( autoCompleteLength > 0 ) {
956 renderSystem->SetColor4( .8f, .2f, .2f, .45f );
958 renderSystem->DrawStretchPic( 2 * SMALLCHAR_WIDTH + consoleField.GetAutoCompleteLength() * SMALLCHAR_WIDTH,
959 y + 2, autoCompleteLength * SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT - 2, 0, 0, 0, 0, whiteShader );
964 renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
966 renderSystem->DrawSmallChar( 1 * SMALLCHAR_WIDTH, y, ']', localConsole.charSetShader );
968 consoleField.Draw(2 * SMALLCHAR_WIDTH, y, SCREEN_WIDTH - 3 * SMALLCHAR_WIDTH, true, charSetShader );
976 Draws the last few lines of output transparently over the game top
979 void idConsoleLocal::DrawNotify() {
986 if ( con_noPrint.GetBool() ) {
990 currentColor = idStr::ColorIndex( C_COLOR_WHITE );
991 renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
994 for ( i = current-NUM_CON_TIMES+1; i <= current; i++ ) {
998 time = times[i % NUM_CON_TIMES];
1002 time = com_frameTime - time;
1003 if ( time > con_notifyTime.GetFloat() * 1000 ) {
1006 text_p = text + (i % TOTAL_LINES)*LINE_WIDTH;
1008 for ( x = 0; x < LINE_WIDTH; x++ ) {
1009 if ( ( text_p[x] & 0xff ) == ' ' ) {
1012 if ( idStr::ColorIndex(text_p[x]>>8) != currentColor ) {
1013 currentColor = idStr::ColorIndex(text_p[x]>>8);
1014 renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
1016 renderSystem->DrawSmallChar( (x+1)*SMALLCHAR_WIDTH, v, text_p[x] & 0xff, localConsole.charSetShader );
1019 v += SMALLCHAR_HEIGHT;
1022 renderSystem->SetColor( colorCyan );
1029 Draws the console with the solid background
1032 void idConsoleLocal::DrawSolidConsole( float frac ) {
1041 lines = idMath::FtoiFast( SCREEN_HEIGHT * frac );
1046 if ( lines > SCREEN_HEIGHT ) {
1047 lines = SCREEN_HEIGHT;
1050 // draw the background
1051 y = frac * SCREEN_HEIGHT - 2;
1055 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, y, 0, 1.0f - displayFrac, 1, 1, consoleShader );
1058 renderSystem->SetColor( colorCyan );
1059 renderSystem->DrawStretchPic( 0, y, SCREEN_WIDTH, 2, 0, 0, 0, 0, whiteShader );
1060 renderSystem->SetColor( colorWhite );
1062 // draw the version number
1064 renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
1066 idStr version = va("%s.%i", ENGINE_VERSION, BUILD_NUMBER);
1067 i = version.Length();
1069 for ( x = 0; x < i; x++ ) {
1070 renderSystem->DrawSmallChar( SCREEN_WIDTH - ( i - x ) * SMALLCHAR_WIDTH,
1071 (lines-(SMALLCHAR_HEIGHT+SMALLCHAR_HEIGHT/2)), version[x], localConsole.charSetShader );
1078 rows = (lines-SMALLCHAR_WIDTH)/SMALLCHAR_WIDTH; // rows of text to draw
1080 y = lines - (SMALLCHAR_HEIGHT*3);
1082 // draw from the bottom up
1083 if ( display != current ) {
1084 // draw arrows to show the buffer is backscrolled
1085 renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
1086 for ( x = 0; x < LINE_WIDTH; x += 4 ) {
1087 renderSystem->DrawSmallChar( (x+1)*SMALLCHAR_WIDTH, idMath::FtoiFast( y ), '^', localConsole.charSetShader );
1089 y -= SMALLCHAR_HEIGHT;
1099 currentColor = idStr::ColorIndex( C_COLOR_WHITE );
1100 renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
1102 for ( i = 0; i < rows; i++, y -= SMALLCHAR_HEIGHT, row-- ) {
1106 if ( current - row >= TOTAL_LINES ) {
1107 // past scrollback wrap point
1111 text_p = text + (row % TOTAL_LINES)*LINE_WIDTH;
1113 for ( x = 0; x < LINE_WIDTH; x++ ) {
1114 if ( ( text_p[x] & 0xff ) == ' ' ) {
1118 if ( idStr::ColorIndex(text_p[x]>>8) != currentColor ) {
1119 currentColor = idStr::ColorIndex(text_p[x]>>8);
1120 renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
1122 renderSystem->DrawSmallChar( (x+1)*SMALLCHAR_WIDTH, idMath::FtoiFast( y ), text_p[x] & 0xff, localConsole.charSetShader );
1126 // draw the input prompt, user text, and cursor if desired
1129 renderSystem->SetColor( colorCyan );
1137 ForceFullScreen is used by the editor
1140 void idConsoleLocal::Draw( bool forceFullScreen ) {
1143 if ( !charSetShader ) {
1147 if ( forceFullScreen ) {
1148 // if we are forced full screen because of a disconnect,
1149 // we want the console closed when we go back to a session state
1151 // we are however catching keyboard input
1157 UpdateDisplayFraction();
1159 if ( forceFullScreen ) {
1160 DrawSolidConsole( 1.0f );
1161 } else if ( displayFrac ) {
1162 DrawSolidConsole( displayFrac );
1164 // only draw the notify lines if the developer cvar is set,
1165 // or we are a debug build
1166 if ( !con_noPrint.GetBool() ) {
1171 if ( com_showFPS.GetBool() ) {
1172 y = SCR_DrawFPS( 0 );
1175 if ( com_showMemoryUsage.GetBool() ) {
1176 y = SCR_DrawMemoryUsage( y );
1179 if ( com_showAsyncStats.GetBool() ) {
1180 y = SCR_DrawAsyncStats( y );
1183 if ( com_showSoundDecoders.GetBool() ) {
1184 y = SCR_DrawSoundDecoders( y );