1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- 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.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "ConsoleHistory.h"
- #include "../renderer/ResolutionScale.h"
- #include "Common_local.h"
- #define CON_TEXTSIZE 0x30000
- #define NUM_CON_TIMES 4
- #define CONSOLE_FIRSTREPEAT 200
- #define CONSOLE_REPEAT 100
- #define COMMAND_HISTORY 64
- struct overlayText_t {
- idStr text;
- justify_t justify;
- int time;
- };
- // the console will query the cvar and command systems for
- // command completion information
- class idConsoleLocal : public idConsole {
- public:
- virtual void Init();
- virtual void Shutdown();
- virtual bool ProcessEvent( const sysEvent_t * event, bool forceAccept );
- virtual bool Active();
- virtual void ClearNotifyLines();
- virtual void Close();
- virtual void Print( const char *text );
- virtual void Draw( bool forceFullScreen );
- virtual void PrintOverlay( idOverlayHandle &handle, justify_t justify, const char *text, ... );
- virtual idDebugGraph * CreateGraph( int numItems );
- virtual void DestroyGraph( idDebugGraph * graph );
- void Dump( const char *toFile );
- void Clear();
- private:
- void KeyDownEvent( int key );
- void Linefeed();
- void PageUp();
- void PageDown();
- void Top();
- void Bottom();
- void DrawInput();
- void DrawNotify();
- void DrawSolidConsole( float frac );
- void Scroll();
- void SetDisplayFraction( float frac );
- void UpdateDisplayFraction();
- void DrawTextLeftAlign( float x, float &y, const char *text, ... );
- void DrawTextRightAlign( float x, float &y, const char *text, ... );
- float DrawFPS( float y );
- float DrawMemoryUsage( float y );
- void DrawOverlayText( float & leftY, float & rightY, float & centerY );
- void DrawDebugGraphs();
- //============================
- // allow these constants to be adjusted for HMD
- int LOCALSAFE_LEFT;
- int LOCALSAFE_RIGHT;
- int LOCALSAFE_TOP;
- int LOCALSAFE_BOTTOM;
- int LOCALSAFE_WIDTH;
- int LOCALSAFE_HEIGHT;
- int LINE_WIDTH;
- int TOTAL_LINES;
- bool keyCatching;
- short text[CON_TEXTSIZE];
- int current; // line where next message will be printed
- int x; // offset in current line for next print
- int display; // bottom of console displays this line
- int lastKeyEvent; // time of last key event for scroll delay
- int nextKeyEvent; // keyboard repeat rate
- float displayFrac; // approaches finalFrac at con_speed
- float finalFrac; // 0.0 to 1.0 lines of console to display
- int fracTime; // time of last displayFrac update
- int vislines; // in scanlines
- int times[NUM_CON_TIMES]; // cls.realtime time the line was generated
- // for transparent notify lines
- idVec4 color;
- idEditField historyEditLines[COMMAND_HISTORY];
- int nextHistoryLine;// the last line in the history buffer, not masked
- int historyLine; // the line being displayed from history buffer
- // will be <= nextHistoryLine
- idEditField consoleField;
- idList< overlayText_t > overlayText;
- idList< idDebugGraph *> debugGraphs;
- static idCVar con_speed;
- static idCVar con_notifyTime;
- static idCVar con_noPrint;
- };
- static idConsoleLocal localConsole;
- idConsole * console = &localConsole;
- idCVar idConsoleLocal::con_speed( "con_speed", "3", CVAR_SYSTEM, "speed at which the console moves up and down" );
- idCVar idConsoleLocal::con_notifyTime( "con_notifyTime", "3", CVAR_SYSTEM, "time messages are displayed onscreen when console is pulled up" );
- #ifdef DEBUG
- 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" );
- #else
- 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" );
- #endif
- /*
- =============================================================================
- Misc stats
- =============================================================================
- */
- /*
- ==================
- idConsoleLocal::DrawTextLeftAlign
- ==================
- */
- void idConsoleLocal::DrawTextLeftAlign( float x, float &y, const char *text, ... ) {
- char string[MAX_STRING_CHARS];
- va_list argptr;
- va_start( argptr, text );
- idStr::vsnPrintf( string, sizeof( string ), text, argptr );
- va_end( argptr );
- renderSystem->DrawSmallStringExt( x, y + 2, string, colorWhite, true );
- y += SMALLCHAR_HEIGHT + 4;
- }
- /*
- ==================
- idConsoleLocal::DrawTextRightAlign
- ==================
- */
- void idConsoleLocal::DrawTextRightAlign( float x, float &y, const char *text, ... ) {
- char string[MAX_STRING_CHARS];
- va_list argptr;
- va_start( argptr, text );
- int i = idStr::vsnPrintf( string, sizeof( string ), text, argptr );
- va_end( argptr );
- renderSystem->DrawSmallStringExt( x - i * SMALLCHAR_WIDTH, y + 2, string, colorWhite, true );
- y += SMALLCHAR_HEIGHT + 4;
- }
- /*
- ==================
- idConsoleLocal::DrawFPS
- ==================
- */
- #define FPS_FRAMES 6
- float idConsoleLocal::DrawFPS( float y ) {
- static int previousTimes[FPS_FRAMES];
- static int index;
- static int previous;
- // don't use serverTime, because that will be drifting to
- // correct for internet lag changes, timescales, timedemos, etc
- int t = Sys_Milliseconds();
- int frameTime = t - previous;
- previous = t;
- previousTimes[index % FPS_FRAMES] = frameTime;
- index++;
- if ( index > FPS_FRAMES ) {
- // average multiple frames together to smooth changes out a bit
- int total = 0;
- for ( int i = 0 ; i < FPS_FRAMES ; i++ ) {
- total += previousTimes[i];
- }
- if ( !total ) {
- total = 1;
- }
- int fps = 1000000 * FPS_FRAMES / total;
- fps = ( fps + 500 ) / 1000;
- const char * s = va( "%ifps", fps );
- int w = strlen( s ) * BIGCHAR_WIDTH;
- renderSystem->DrawBigStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, s, colorWhite, true );
- }
- y += BIGCHAR_HEIGHT + 4;
- // print the resolution scale so we can tell when we are at reduced resolution
- idStr resolutionText;
- resolutionScale.GetConsoleText( resolutionText );
- int w = resolutionText.Length() * BIGCHAR_WIDTH;
- renderSystem->DrawBigStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, resolutionText.c_str(), colorWhite, true );
- const int gameThreadTotalTime = commonLocal.GetGameThreadTotalTime();
- const int gameThreadGameTime = commonLocal.GetGameThreadGameTime();
- const int gameThreadRenderTime = commonLocal.GetGameThreadRenderTime();
- const int rendererBackEndTime = commonLocal.GetRendererBackEndMicroseconds();
- const int rendererShadowsTime = commonLocal.GetRendererShadowsMicroseconds();
- const int rendererGPUIdleTime = commonLocal.GetRendererIdleMicroseconds();
- const int rendererGPUTime = commonLocal.GetRendererGPUMicroseconds();
- const int maxTime = 16;
- y += SMALLCHAR_HEIGHT + 4;
- idStr timeStr;
- timeStr.Format( "%sG+RF: %4d", gameThreadTotalTime > maxTime ? S_COLOR_RED : "", gameThreadTotalTime );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sG: %4d", gameThreadGameTime > maxTime ? S_COLOR_RED : "", gameThreadGameTime );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sRF: %4d", gameThreadRenderTime > maxTime ? S_COLOR_RED : "", gameThreadRenderTime );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sRB: %4.1f", rendererBackEndTime > maxTime * 1000 ? S_COLOR_RED : "", rendererBackEndTime / 1000.0f );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sSV: %4.1f", rendererShadowsTime > maxTime * 1000 ? S_COLOR_RED : "", rendererShadowsTime / 1000.0f );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sIDLE: %4.1f", rendererGPUIdleTime > maxTime * 1000 ? S_COLOR_RED : "", rendererGPUIdleTime / 1000.0f );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- y += SMALLCHAR_HEIGHT + 4;
- timeStr.Format( "%sGPU: %4.1f", rendererGPUTime > maxTime * 1000 ? S_COLOR_RED : "", rendererGPUTime / 1000.0f );
- w = timeStr.LengthWithoutColors() * SMALLCHAR_WIDTH;
- renderSystem->DrawSmallStringExt( LOCALSAFE_RIGHT - w, idMath::Ftoi( y ) + 2, timeStr.c_str(), colorWhite, false );
- return y + BIGCHAR_HEIGHT + 4;
- }
- /*
- ==================
- idConsoleLocal::DrawMemoryUsage
- ==================
- */
- float idConsoleLocal::DrawMemoryUsage( float y ) {
- return y;
- }
- //=========================================================================
- /*
- ==============
- Con_Clear_f
- ==============
- */
- static void Con_Clear_f( const idCmdArgs &args ) {
- localConsole.Clear();
- }
- /*
- ==============
- Con_Dump_f
- ==============
- */
- static void Con_Dump_f( const idCmdArgs &args ) {
- if ( args.Argc() != 2 ) {
- common->Printf( "usage: conDump <filename>\n" );
- return;
- }
- idStr fileName = args.Argv(1);
- fileName.DefaultFileExtension(".txt");
- common->Printf( "Dumped console text to %s.\n", fileName.c_str() );
- localConsole.Dump( fileName.c_str() );
- }
- /*
- ==============
- idConsoleLocal::Init
- ==============
- */
- void idConsoleLocal::Init() {
- int i;
- keyCatching = false;
- LOCALSAFE_LEFT = 32;
- LOCALSAFE_RIGHT = 608;
- LOCALSAFE_TOP = 24;
- LOCALSAFE_BOTTOM = 456;
- LOCALSAFE_WIDTH = LOCALSAFE_RIGHT - LOCALSAFE_LEFT;
- LOCALSAFE_HEIGHT = LOCALSAFE_BOTTOM - LOCALSAFE_TOP;
- LINE_WIDTH = ( ( LOCALSAFE_WIDTH / SMALLCHAR_WIDTH ) - 2 );
- TOTAL_LINES = (CON_TEXTSIZE / LINE_WIDTH);
- lastKeyEvent = -1;
- nextKeyEvent = CONSOLE_FIRSTREPEAT;
- consoleField.Clear();
- consoleField.SetWidthInChars( LINE_WIDTH );
- for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
- historyEditLines[i].Clear();
- historyEditLines[i].SetWidthInChars( LINE_WIDTH );
- }
- cmdSystem->AddCommand( "clear", Con_Clear_f, CMD_FL_SYSTEM, "clears the console" );
- cmdSystem->AddCommand( "conDump", Con_Dump_f, CMD_FL_SYSTEM, "dumps the console text to a file" );
- }
- /*
- ==============
- idConsoleLocal::Shutdown
- ==============
- */
- void idConsoleLocal::Shutdown() {
- cmdSystem->RemoveCommand( "clear" );
- cmdSystem->RemoveCommand( "conDump" );
- debugGraphs.DeleteContents( true );
- }
- /*
- ================
- idConsoleLocal::Active
- ================
- */
- bool idConsoleLocal::Active() {
- return keyCatching;
- }
- /*
- ================
- idConsoleLocal::ClearNotifyLines
- ================
- */
- void idConsoleLocal::ClearNotifyLines() {
- int i;
- for ( i = 0 ; i < NUM_CON_TIMES ; i++ ) {
- times[i] = 0;
- }
- }
- /*
- ================
- idConsoleLocal::Close
- ================
- */
- void idConsoleLocal::Close() {
- keyCatching = false;
- SetDisplayFraction( 0 );
- displayFrac = 0; // don't scroll to that point, go immediately
- ClearNotifyLines();
- }
- /*
- ================
- idConsoleLocal::Clear
- ================
- */
- void idConsoleLocal::Clear() {
- int i;
- for ( i = 0 ; i < CON_TEXTSIZE ; i++ ) {
- text[i] = (idStr::ColorIndex(C_COLOR_CYAN)<<8) | ' ';
- }
- Bottom(); // go to end
- }
- /*
- ================
- idConsoleLocal::Dump
- Save the console contents out to a file
- ================
- */
- void idConsoleLocal::Dump( const char *fileName ) {
- int l, x, i;
- short * line;
- idFile *f;
- char * buffer = (char *)alloca( LINE_WIDTH + 3 );
- f = fileSystem->OpenFileWrite( fileName );
- if ( !f ) {
- common->Warning( "couldn't open %s", fileName );
- return;
- }
- // skip empty lines
- l = current - TOTAL_LINES + 1;
- if ( l < 0 ) {
- l = 0;
- }
- for ( ; l <= current ; l++ )
- {
- line = text + ( l % TOTAL_LINES ) * LINE_WIDTH;
- for ( x = 0; x < LINE_WIDTH; x++ )
- if ( ( line[x] & 0xff ) > ' ' )
- break;
- if ( x != LINE_WIDTH )
- break;
- }
- // write the remaining lines
- for ( ; l <= current; l++ ) {
- line = text + ( l % TOTAL_LINES ) * LINE_WIDTH;
- for( i = 0; i < LINE_WIDTH; i++ ) {
- buffer[i] = line[i] & 0xff;
- }
- for ( x = LINE_WIDTH-1; x >= 0; x-- ) {
- if ( buffer[x] <= ' ' ) {
- buffer[x] = 0;
- } else {
- break;
- }
- }
- buffer[x+1] = '\r';
- buffer[x+2] = '\n';
- buffer[x+3] = 0;
- f->Write( buffer, strlen( buffer ) );
- }
- fileSystem->CloseFile( f );
- }
- /*
- ================
- idConsoleLocal::PageUp
- ================
- */
- void idConsoleLocal::PageUp() {
- display -= 2;
- if ( current - display >= TOTAL_LINES ) {
- display = current - TOTAL_LINES + 1;
- }
- }
- /*
- ================
- idConsoleLocal::PageDown
- ================
- */
- void idConsoleLocal::PageDown() {
- display += 2;
- if ( display > current ) {
- display = current;
- }
- }
- /*
- ================
- idConsoleLocal::Top
- ================
- */
- void idConsoleLocal::Top() {
- display = 0;
- }
- /*
- ================
- idConsoleLocal::Bottom
- ================
- */
- void idConsoleLocal::Bottom() {
- display = current;
- }
- /*
- =============================================================================
- CONSOLE LINE EDITING
- ==============================================================================
- */
- /*
- ====================
- KeyDownEvent
- Handles history and console scrollback
- ====================
- */
- void idConsoleLocal::KeyDownEvent( int key ) {
-
- // Execute F key bindings
- if ( key >= K_F1 && key <= K_F12 ) {
- idKeyInput::ExecKeyBinding( key );
- return;
- }
- // ctrl-L clears screen
- if ( key == K_L && ( idKeyInput::IsDown( K_LCTRL ) || idKeyInput::IsDown( K_RCTRL ) ) ) {
- Clear();
- return;
- }
- // enter finishes the line
- if ( key == K_ENTER || key == K_KP_ENTER ) {
- common->Printf ( "]%s\n", consoleField.GetBuffer() );
- cmdSystem->BufferCommandText( CMD_EXEC_APPEND, consoleField.GetBuffer() ); // valid command
- cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
- // copy line to history buffer
- if ( consoleField.GetBuffer()[ 0 ] != '\n' && consoleField.GetBuffer()[ 0 ] != '\0' ) {
- consoleHistory.AddToHistory( consoleField.GetBuffer() );
- }
- consoleField.Clear();
- consoleField.SetWidthInChars( LINE_WIDTH );
- const bool captureToImage = false;
- common->UpdateScreen( captureToImage );// force an update, because the command
- // may take some time
- return;
- }
- // command completion
- if ( key == K_TAB ) {
- consoleField.AutoComplete();
- return;
- }
- // command history (ctrl-p ctrl-n for unix style)
- if ( ( key == K_UPARROW ) ||
- ( key == K_P && ( idKeyInput::IsDown( K_LCTRL ) || idKeyInput::IsDown( K_RCTRL ) ) ) ) {
- idStr hist = consoleHistory.RetrieveFromHistory( true );
- if ( !hist.IsEmpty() ) {
- consoleField.SetBuffer( hist );
- }
- return;
- }
- if ( ( key == K_DOWNARROW ) ||
- ( key == K_N && ( idKeyInput::IsDown( K_LCTRL ) || idKeyInput::IsDown( K_RCTRL ) ) ) ) {
- idStr hist = consoleHistory.RetrieveFromHistory( false );
- if ( !hist.IsEmpty() ) {
- consoleField.SetBuffer( hist );
- }
- return;
- }
- // console scrolling
- if ( key == K_PGUP ) {
- PageUp();
- lastKeyEvent = eventLoop->Milliseconds();
- nextKeyEvent = CONSOLE_FIRSTREPEAT;
- return;
- }
- if ( key == K_PGDN ) {
- PageDown();
- lastKeyEvent = eventLoop->Milliseconds();
- nextKeyEvent = CONSOLE_FIRSTREPEAT;
- return;
- }
- if ( key == K_MWHEELUP ) {
- PageUp();
- return;
- }
- if ( key == K_MWHEELDOWN ) {
- PageDown();
- return;
- }
- // ctrl-home = top of console
- if ( key == K_HOME && ( idKeyInput::IsDown( K_LCTRL ) || idKeyInput::IsDown( K_RCTRL ) ) ) {
- Top();
- return;
- }
- // ctrl-end = bottom of console
- if ( key == K_END && ( idKeyInput::IsDown( K_LCTRL ) || idKeyInput::IsDown( K_RCTRL ) ) ) {
- Bottom();
- return;
- }
- // pass to the normal editline routine
- consoleField.KeyDownEvent( key );
- }
- /*
- ==============
- Scroll
- deals with scrolling text because we don't have key repeat
- ==============
- */
- void idConsoleLocal::Scroll( ) {
- if (lastKeyEvent == -1 || (lastKeyEvent+200) > eventLoop->Milliseconds()) {
- return;
- }
- // console scrolling
- if ( idKeyInput::IsDown( K_PGUP ) ) {
- PageUp();
- nextKeyEvent = CONSOLE_REPEAT;
- return;
- }
- if ( idKeyInput::IsDown( K_PGDN ) ) {
- PageDown();
- nextKeyEvent = CONSOLE_REPEAT;
- return;
- }
- }
- /*
- ==============
- SetDisplayFraction
- Causes the console to start opening the desired amount.
- ==============
- */
- void idConsoleLocal::SetDisplayFraction( float frac ) {
- finalFrac = frac;
- fracTime = Sys_Milliseconds();
- }
- /*
- ==============
- UpdateDisplayFraction
- Scrolls the console up or down based on conspeed
- ==============
- */
- void idConsoleLocal::UpdateDisplayFraction() {
- if ( con_speed.GetFloat() <= 0.1f ) {
- fracTime = Sys_Milliseconds();
- displayFrac = finalFrac;
- return;
- }
- // scroll towards the destination height
- if ( finalFrac < displayFrac ) {
- displayFrac -= con_speed.GetFloat() * ( Sys_Milliseconds() - fracTime ) * 0.001f;
- if ( finalFrac > displayFrac ) {
- displayFrac = finalFrac;
- }
- fracTime = Sys_Milliseconds();
- } else if ( finalFrac > displayFrac ) {
- displayFrac += con_speed.GetFloat() * ( Sys_Milliseconds() - fracTime ) * 0.001f;
- if ( finalFrac < displayFrac ) {
- displayFrac = finalFrac;
- }
- fracTime = Sys_Milliseconds();
- }
- }
- /*
- ==============
- ProcessEvent
- ==============
- */
- bool idConsoleLocal::ProcessEvent( const sysEvent_t *event, bool forceAccept ) {
- const bool consoleKey = event->evType == SE_KEY && event->evValue == K_GRAVE && com_allowConsole.GetBool();
- // we always catch the console key event
- if ( !forceAccept && consoleKey ) {
- // ignore up events
- if ( event->evValue2 == 0 ) {
- return true;
- }
- consoleField.ClearAutoComplete();
- // a down event will toggle the destination lines
- if ( keyCatching ) {
- Close();
- Sys_GrabMouseCursor( true );
- } else {
- consoleField.Clear();
- keyCatching = true;
- if ( idKeyInput::IsDown( K_LSHIFT ) || idKeyInput::IsDown( K_RSHIFT ) ) {
- // if the shift key is down, don't open the console as much
- SetDisplayFraction( 0.2f );
- } else {
- SetDisplayFraction( 0.5f );
- }
- }
- return true;
- }
- // if we aren't key catching, dump all the other events
- if ( !forceAccept && !keyCatching ) {
- return false;
- }
- // handle key and character events
- if ( event->evType == SE_CHAR ) {
- // never send the console key as a character
- if ( event->evValue != '`' && event->evValue != '~' ) {
- consoleField.CharEvent( event->evValue );
- }
- return true;
- }
- if ( event->evType == SE_KEY ) {
- // ignore up key events
- if ( event->evValue2 == 0 ) {
- return true;
- }
- KeyDownEvent( event->evValue );
- return true;
- }
- // we don't handle things like mouse, joystick, and network packets
- return false;
- }
- /*
- ==============================================================================
- PRINTING
- ==============================================================================
- */
- /*
- ===============
- Linefeed
- ===============
- */
- void idConsoleLocal::Linefeed() {
- int i;
- // mark time for transparent overlay
- if ( current >= 0 ) {
- times[current % NUM_CON_TIMES] = Sys_Milliseconds();
- }
- x = 0;
- if ( display == current ) {
- display++;
- }
- current++;
- for ( i = 0; i < LINE_WIDTH; i++ ) {
- int offset = ( (unsigned int)current % TOTAL_LINES ) * LINE_WIDTH + i;
- text[offset] = (idStr::ColorIndex(C_COLOR_CYAN)<<8) | ' ';
- }
- }
- /*
- ================
- Print
- Handles cursor positioning, line wrapping, etc
- ================
- */
- void idConsoleLocal::Print( const char *txt ) {
- int y;
- int c, l;
- int color;
- if ( TOTAL_LINES == 0 ) {
- // not yet initialized
- return;
- }
- color = idStr::ColorIndex( C_COLOR_CYAN );
- while ( (c = *(const unsigned char*)txt) != 0 ) {
- if ( idStr::IsColor( txt ) ) {
- if ( *(txt+1) == C_COLOR_DEFAULT ) {
- color = idStr::ColorIndex( C_COLOR_CYAN );
- } else {
- color = idStr::ColorIndex( *(txt+1) );
- }
- txt += 2;
- continue;
- }
- y = current % TOTAL_LINES;
- // if we are about to print a new word, check to see
- // if we should wrap to the new line
- if ( c > ' ' && ( x == 0 || text[y*LINE_WIDTH+x-1] <= ' ' ) ) {
- // count word length
- for (l=0 ; l< LINE_WIDTH ; l++) {
- if ( txt[l] <= ' ') {
- break;
- }
- }
- // word wrap
- if (l != LINE_WIDTH && (x + l >= LINE_WIDTH) ) {
- Linefeed();
- }
- }
- txt++;
- switch( c ) {
- case '\n':
- Linefeed ();
- break;
- case '\t':
- do {
- text[y*LINE_WIDTH+x] = (color << 8) | ' ';
- x++;
- if ( x >= LINE_WIDTH ) {
- Linefeed();
- x = 0;
- }
- } while ( x & 3 );
- break;
- case '\r':
- x = 0;
- break;
- default: // display character and advance
- text[y*LINE_WIDTH+x] = (color << 8) | c;
- x++;
- if ( x >= LINE_WIDTH ) {
- Linefeed();
- x = 0;
- }
- break;
- }
- }
- // mark time for transparent overlay
- if ( current >= 0 ) {
- times[current % NUM_CON_TIMES] = Sys_Milliseconds();
- }
- }
- /*
- ==============================================================================
- DRAWING
- ==============================================================================
- */
- /*
- ================
- DrawInput
- Draw the editline after a ] prompt
- ================
- */
- void idConsoleLocal::DrawInput() {
- int y, autoCompleteLength;
- y = vislines - ( SMALLCHAR_HEIGHT * 2 );
- if ( consoleField.GetAutoCompleteLength() != 0 ) {
- autoCompleteLength = strlen( consoleField.GetBuffer() ) - consoleField.GetAutoCompleteLength();
- if ( autoCompleteLength > 0 ) {
- renderSystem->DrawFilled( idVec4( 0.8f, 0.2f, 0.2f, 0.45f ),
- LOCALSAFE_LEFT + 2 * SMALLCHAR_WIDTH + consoleField.GetAutoCompleteLength() * SMALLCHAR_WIDTH,
- y + 2, autoCompleteLength * SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT - 2 );
- }
- }
- renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
- renderSystem->DrawSmallChar( LOCALSAFE_LEFT + 1 * SMALLCHAR_WIDTH, y, ']' );
- consoleField.Draw( LOCALSAFE_LEFT + 2 * SMALLCHAR_WIDTH, y, SCREEN_WIDTH - 3 * SMALLCHAR_WIDTH, true );
- }
- /*
- ================
- DrawNotify
- Draws the last few lines of output transparently over the game top
- ================
- */
- void idConsoleLocal::DrawNotify() {
- int x, v;
- short *text_p;
- int i;
- int time;
- int currentColor;
- if ( con_noPrint.GetBool() ) {
- return;
- }
- currentColor = idStr::ColorIndex( C_COLOR_WHITE );
- renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
- v = 0;
- for ( i = current-NUM_CON_TIMES+1; i <= current; i++ ) {
- if ( i < 0 ) {
- continue;
- }
- time = times[i % NUM_CON_TIMES];
- if ( time == 0 ) {
- continue;
- }
- time = Sys_Milliseconds() - time;
- if ( time > con_notifyTime.GetFloat() * 1000 ) {
- continue;
- }
- text_p = text + (i % TOTAL_LINES)*LINE_WIDTH;
-
- for ( x = 0; x < LINE_WIDTH; x++ ) {
- if ( ( text_p[x] & 0xff ) == ' ' ) {
- continue;
- }
- if ( idStr::ColorIndex(text_p[x]>>8) != currentColor ) {
- currentColor = idStr::ColorIndex(text_p[x]>>8);
- renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
- }
- renderSystem->DrawSmallChar( LOCALSAFE_LEFT + (x+1)*SMALLCHAR_WIDTH, v, text_p[x] & 0xff );
- }
- v += SMALLCHAR_HEIGHT;
- }
- renderSystem->SetColor( colorCyan );
- }
- /*
- ================
- DrawSolidConsole
- Draws the console with the solid background
- ================
- */
- void idConsoleLocal::DrawSolidConsole( float frac ) {
- int i, x;
- float y;
- int rows;
- short *text_p;
- int row;
- int lines;
- int currentColor;
- lines = idMath::Ftoi( SCREEN_HEIGHT * frac );
- if ( lines <= 0 ) {
- return;
- }
- if ( lines > SCREEN_HEIGHT ) {
- lines = SCREEN_HEIGHT;
- }
- // draw the background
- y = frac * SCREEN_HEIGHT - 2;
- if ( y < 1.0f ) {
- y = 0.0f;
- } else {
- renderSystem->DrawFilled( idVec4( 0.0f, 0.0f, 0.0f, 0.75f ), 0, 0, SCREEN_WIDTH, y );
- }
- renderSystem->DrawFilled( colorCyan, 0, y, SCREEN_WIDTH, 2 );
- // draw the version number
- renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
- idStr version = va( "%s.%i.%i", ENGINE_VERSION, BUILD_NUMBER, BUILD_NUMBER_MINOR );
- i = version.Length();
- for ( x = 0; x < i; x++ ) {
- renderSystem->DrawSmallChar( LOCALSAFE_WIDTH - ( i - x ) * SMALLCHAR_WIDTH,
- (lines-(SMALLCHAR_HEIGHT+SMALLCHAR_HEIGHT/4)), version[x] );
- }
- // draw the text
- vislines = lines;
- rows = (lines-SMALLCHAR_WIDTH)/SMALLCHAR_WIDTH; // rows of text to draw
- y = lines - (SMALLCHAR_HEIGHT*3);
- // draw from the bottom up
- if ( display != current ) {
- // draw arrows to show the buffer is backscrolled
- renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) );
- for ( x = 0; x < LINE_WIDTH; x += 4 ) {
- renderSystem->DrawSmallChar( LOCALSAFE_LEFT + (x+1)*SMALLCHAR_WIDTH, idMath::Ftoi( y ), '^' );
- }
- y -= SMALLCHAR_HEIGHT;
- rows--;
- }
-
- row = display;
- if ( x == 0 ) {
- row--;
- }
- currentColor = idStr::ColorIndex( C_COLOR_WHITE );
- renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
- for ( i = 0; i < rows; i++, y -= SMALLCHAR_HEIGHT, row-- ) {
- if ( row < 0 ) {
- break;
- }
- if ( current - row >= TOTAL_LINES ) {
- // past scrollback wrap point
- continue;
- }
- text_p = text + (row % TOTAL_LINES)*LINE_WIDTH;
- for ( x = 0; x < LINE_WIDTH; x++ ) {
- if ( ( text_p[x] & 0xff ) == ' ' ) {
- continue;
- }
- if ( idStr::ColorIndex(text_p[x]>>8) != currentColor ) {
- currentColor = idStr::ColorIndex(text_p[x]>>8);
- renderSystem->SetColor( idStr::ColorForIndex( currentColor ) );
- }
- renderSystem->DrawSmallChar( LOCALSAFE_LEFT + (x+1)*SMALLCHAR_WIDTH, idMath::Ftoi( y ), text_p[x] & 0xff );
- }
- }
- // draw the input prompt, user text, and cursor if desired
- DrawInput();
- renderSystem->SetColor( colorCyan );
- }
- /*
- ==============
- Draw
- ForceFullScreen is used by the editor
- ==============
- */
- void idConsoleLocal::Draw( bool forceFullScreen ) {
- if ( forceFullScreen ) {
- // if we are forced full screen because of a disconnect,
- // we want the console closed when we go back to a session state
- Close();
- // we are however catching keyboard input
- keyCatching = true;
- }
- Scroll();
- UpdateDisplayFraction();
- if ( forceFullScreen ) {
- DrawSolidConsole( 1.0f );
- } else if ( displayFrac ) {
- DrawSolidConsole( displayFrac );
- } else {
- // only draw the notify lines if the developer cvar is set,
- // or we are a debug build
- if ( !con_noPrint.GetBool() ) {
- DrawNotify();
- }
- }
- float lefty = LOCALSAFE_TOP;
- float righty = LOCALSAFE_TOP;
- float centery = LOCALSAFE_TOP;
- if ( com_showFPS.GetBool() ) {
- righty = DrawFPS( righty );
- }
- if ( com_showMemoryUsage.GetBool() ) {
- righty = DrawMemoryUsage( righty );
- }
- DrawOverlayText( lefty, righty, centery );
- DrawDebugGraphs();
- }
- /*
- ========================
- idConsoleLocal::PrintOverlay
- ========================
- */
- void idConsoleLocal::PrintOverlay( idOverlayHandle &handle, justify_t justify, const char *text, ... ) {
- if ( handle.index >= 0 && handle.index < overlayText.Num() ) {
- if ( overlayText[handle.index].time == handle.time ) {
- return;
- }
- }
- char string[MAX_PRINT_MSG];
- va_list argptr;
- va_start( argptr, text );
- idStr::vsnPrintf( string, sizeof( string ), text, argptr );
- va_end( argptr );
- overlayText_t &overlay = overlayText.Alloc();
- overlay.text = string;
- overlay.justify = justify;
- overlay.time = Sys_Milliseconds();
- handle.index = overlayText.Num() - 1;
- handle.time = overlay.time;
- }
- /*
- ========================
- idConsoleLocal::DrawOverlayText
- ========================
- */
- void idConsoleLocal::DrawOverlayText( float & leftY, float & rightY, float & centerY ) {
- for ( int i = 0; i < overlayText.Num(); i++ ) {
- const idStr & text = overlayText[i].text;
- int maxWidth = 0;
- int numLines = 0;
- for ( int j = 0; j < text.Length(); j++ ) {
- int width = 1;
- for (; j < text.Length() && text[j] != '\n'; j++ ) {
- width++;
- }
- numLines++;
- if ( width > maxWidth ) {
- maxWidth = width;
- }
- }
- idVec4 bgColor( 0.0f, 0.0f, 0.0f, 0.75f );
- const float width = maxWidth * SMALLCHAR_WIDTH;
- const float height = numLines * ( SMALLCHAR_HEIGHT + 4 );
- const float bgAdjust = - 0.5f * SMALLCHAR_WIDTH;
- if ( overlayText[i].justify == JUSTIFY_LEFT ) {
- renderSystem->DrawFilled( bgColor, LOCALSAFE_LEFT + bgAdjust, leftY, width, height );
- } else if ( overlayText[i].justify == JUSTIFY_RIGHT ) {
- renderSystem->DrawFilled( bgColor, LOCALSAFE_RIGHT - width + bgAdjust, rightY, width, height );
- } else if ( overlayText[i].justify == JUSTIFY_CENTER_LEFT || overlayText[i].justify == JUSTIFY_CENTER_RIGHT ) {
- renderSystem->DrawFilled( bgColor, LOCALSAFE_LEFT + ( LOCALSAFE_WIDTH - width + bgAdjust ) * 0.5f, centerY, width, height );
- } else {
- assert( false );
- }
- idStr singleLine;
- for ( int j = 0; j < text.Length(); j += singleLine.Length() + 1 ) {
- singleLine = "";
- for ( int k = j; k < text.Length() && text[k] != '\n'; k++ ) {
- singleLine.Append( text[k] );
- }
- if ( overlayText[i].justify == JUSTIFY_LEFT ) {
- DrawTextLeftAlign( LOCALSAFE_LEFT, leftY, "%s", singleLine.c_str() );
- } else if ( overlayText[i].justify == JUSTIFY_RIGHT ) {
- DrawTextRightAlign( LOCALSAFE_RIGHT, rightY, "%s", singleLine.c_str() );
- } else if ( overlayText[i].justify == JUSTIFY_CENTER_LEFT ) {
- DrawTextLeftAlign( LOCALSAFE_LEFT + ( LOCALSAFE_WIDTH - width ) * 0.5f, centerY, "%s", singleLine.c_str() );
- } else if ( overlayText[i].justify == JUSTIFY_CENTER_RIGHT ) {
- DrawTextRightAlign( LOCALSAFE_LEFT + ( LOCALSAFE_WIDTH + width ) * 0.5f, centerY, "%s", singleLine.c_str() );
- } else {
- assert( false );
- }
- }
- }
- overlayText.SetNum( 0 );
- }
- /*
- ========================
- idConsoleLocal::CreateGraph
- ========================
- */
- idDebugGraph * idConsoleLocal::CreateGraph( int numItems ) {
- idDebugGraph * graph = new (TAG_SYSTEM) idDebugGraph( numItems );
- debugGraphs.Append( graph );
- return graph;
- }
- /*
- ========================
- idConsoleLocal::DestroyGraph
- ========================
- */
- void idConsoleLocal::DestroyGraph( idDebugGraph * graph ) {
- debugGraphs.Remove( graph );
- delete graph;
- }
- /*
- ========================
- idConsoleLocal::DrawDebugGraphs
- ========================
- */
- void idConsoleLocal::DrawDebugGraphs() {
- for ( int i = 0; i < debugGraphs.Num(); i++ ) {
- debugGraphs[i]->Render( renderSystem );
- }
- }
|