// Console.cpp : implementation file
//
#include "Console.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/* List of commands the console supports. */
/* Commands are of the form : <Command text><Help text (optional)><handler function> */
struct console CommandList[] =
{
{"CullBackFaces","...[0/1]", ConsoleCullBackFaces},
{"Gamma","...........[0..100]", ConsoleGamma},
{NULL,NULL,NULL}
};
//-----------------------------------------------------------------------------
// Function handler for the gamma command
void ConsoleGamma(char *command)
{
if ( command == NULL )
{
/* Just display the current value on the console */
theApp.m_console.FormatLine("gamma=%d",theApp.m_GammaVal);
return;
}
/* Set the new gamma value */
theApp.m_GammaVal = atol(command);
theApp.SetGammaCorrection((float)theApp.m_GammaVal / 100.0f );
}
//-----------------------------------------------------------------------------
void ConsoleCullBackFaces(char * command)
{
if ( command != NULL )
{
switch ( command[0] )
{
case '0':
theApp.m_dwFlags &= ~CULL_BACK_FACES;
theApp.SetOptions();
return;
case '1':
theApp.m_dwFlags |= CULL_BACK_FACES;
theApp.SetOptions();
return;
}
}
/* Toggle */
theApp.m_dwFlags ^= CULL_BACK_FACES;
theApp.SetOptions();
}
/////////////////////////////////////////////////////////////////////////////
// CConsole
CConsole::CConsole()
{
m_initialised = false;
m_FontName = "font4.bmp";
m_BackgroundName = "console2.bmp";
m_mode = DOWN;
m_HistoryPos = NULL;
m_TabCount = 0;
}
CConsole::~CConsole()
{
m_initialised = false;
D3DTextr_DestroyTexture(m_FontName);
D3DTextr_DestroyTexture(m_BackgroundName);
}
//-----------------------------------------------------------------------
// Initialize the console. Call before use or after the render device has changed
//-----------------------------------------------------------------------
void CConsole::Initialize()
{
DDSURFACEDESC2 ddsd;
HDC hdc;
if ( !g_pFramework || !g_pFramework->GetD3DDevice() || !g_pFramework->GetDirect3D())
return; // Just in case...
m_FontSz.cy = DISPLAY_FONT_HEIGHT;
m_FontSz.cx = DISPLAY_FONT_WIDTH;
/* Calculate the size of the cosoole ( when fully visible ) */
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
g_pFramework->GetBackBuffer()->GetSurfaceDesc(&ddsd);
m_size.SetRect(0,0,ddsd.dwWidth,ddsd.dwHeight / 2);
/* The vertices of the quad that will be uses for the background */
m_v[0] = D3DTLVERTEX(D3DVECTOR(0,0,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),0,0);
m_v[1] = D3DTLVERTEX(D3DVECTOR(0,0,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),0,1);
m_v[2] = D3DTLVERTEX(D3DVECTOR((float)ddsd.dwWidth,0,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),1,1);
m_v[3] = D3DTLVERTEX(D3DVECTOR((float)ddsd.dwWidth,0,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),1,0);
m_v[0].color = m_v[1].color= m_v[2].color = m_v[3].color = D3DRGBA(1,1,1,0.8);
/* Load the font "texture" to an off-screen surface*/
D3DTextr_CreateTexture( m_FontName , 0, 0 );
D3DTextr_Restore(m_FontName,g_pFramework->GetD3DDevice());
m_font = D3DTextr_GetTexture(m_FontName);
DDSetColorKey(D3DTextr_GetSurface(m_FontName),RGB(0,0,0));
/* Load the background image to an off-screen surface */
D3DTextr_CreateTexture( m_BackgroundName , 0, 0 );
D3DTextr_Restore( m_BackgroundName,g_pFramework->GetD3DDevice());
m_background = D3DTextr_GetTexture( m_BackgroundName);
/* Number of visible lines */
m_nLines = (int)(((float)((ddsd.dwHeight) / 2.0) - YOFF - YOFF ) / m_FontSz.cy ) - 1;
/* Create a blank empty text buffer */
for ( int i = m_text.GetCount(); i < m_nLines; i++ )
m_text.AddHead("");
/* Initialize some other member variables */
m_bCursor = true;
m_FlashCounter = 0;
m_yOffset = 0;
m_mode = DOWN;
m_CursorPos = 0;
m_initialised = true;
}
//-----------------------------------------------------------------------
// Render the console. Call this every frame.
//-----------------------------------------------------------------------
void CConsole::Render()
{
POSITION pos;
int top;
CString str;
char *p;
int x,
y,
c,
len;
D3DTLVERTEX v[4];
ULONG lOldZFunc,
loldColor,
loldAlpha,
loldSrc,
loldDest;
float uoffset,
voffset,
usize = (1 / ( 256.0 / FONT_WIDTH)),
vsize = (1 / ( 256.0 / FONT_HEIGHT));
bool done = false;
static DWORD LastTime = timeGetTime();
DWORD ThisTime = timeGetTime();
DWORD elapsed = ThisTime - LastTime;
HDC hdc = NULL;
CDC dc;
CFont *old;
if ( !m_initialised )
return;
/* 'Animation' stuff */
m_FlashCounter += elapsed;
if ( m_FlashCounter > FLASH_SPEED )
{
m_FlashCounter = 0;
m_bCursor = m_bCursor ? false : true;
}
if ( m_yOffset == 0 )
elapsed = 1;
LastTime = ThisTime;
switch ( m_mode )
{
case DOWN: // The console is scrolling down
m_yOffset += (float)elapsed / 2.0;
if ( m_yOffset > m_size.bottom )
{
m_yOffset = m_size.bottom;
m_mode = STATIC;
}
/* fade in the console as is scrolls down */
alpha = m_yOffset / m_size.bottom;
if ( alpha < 0.8f )
m_v[0].color = m_v[1].color= m_v[2].color = m_v[3].color = D3DRGBA(1,1,1,alpha);
break;
case UP: // The console is scrolling up
m_yOffset -= elapsed;
if ( m_yOffset < 0 )
{
m_yOffset = 0;
m_mode = DOWN;
}
/* fade out the console as is scrolls up */
alpha = m_yOffset / m_size.bottom;
if ( alpha >= 0 )
m_v[0].color = m_v[1].color= m_v[2].color = m_v[3].color = D3DRGBA(1,1,1,alpha);
break;
case STATIC: // The console is fully visible
break;
}
/* Setup some render states */
LPDIRECT3DDEVICE3 pDevice = g_pFramework->GetD3DDevice();
pDevice->GetRenderState( D3DRENDERSTATE_ZFUNC, &lOldZFunc );
pDevice->SetRenderState( D3DRENDERSTATE_ZFUNC, D3DCMP_ALWAYS );
pDevice->GetTextureStageState( 1, D3DTSS_COLOROP,&loldColor );
pDevice->SetTextureStageState( 1, D3DTSS_COLOROP,D3DTOP_DISABLE );
pDevice->GetTextureStageState( 1, D3DTSS_ALPHAOP,&loldAlpha );
pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,D3DTOP_DISABLE );
pDevice->GetRenderState( D3DRENDERSTATE_SRCBLEND,&loldSrc);
pDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA);
pDevice->GetRenderState( D3DRENDERSTATE_DESTBLEND,&loldDest );
pDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
pDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
pDevice->SetTexture(0, m_background);
/* Draw the background (Transparent quad) */
m_v[0].sy = m_yOffset - m_size.bottom;
m_v[1].sy = m_yOffset;
m_v[2].sy = m_yOffset;
m_v[3].sy = m_yOffset - m_size.bottom;
pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,D3DFVF_TLVERTEX ,(LPVOID)m_v,4,NULL);
/* Draw the text. This should be done using a vertex buffer & DrawIndexedPrimitiveVB()!!! */
pDevice->SetTexture(0, m_font);
top = m_text.GetCount() - m_nLines;
pos = m_text.FindIndex(top);
x = XOFF;
y = (m_yOffset - m_size.bottom) + YOFF;
while ( !done )
{
if ( pos == NULL )
{
str = m_InputBuffer;
done = true;
}
else
str = m_text.GetNext(pos);
len = str.GetLength();
p = str.GetBuffer(0);
for ( c = 0, x = XOFF; c < len; c++, x += DISPLAY_FONT_WIDTH,p++ )
{
uoffset = (*p % UMAX ) * usize;
voffset = (*p / UMAX ) * vsize;
v[0] = D3DTLVERTEX(D3DVECTOR(x,y,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + COMP,voffset + COMP);
v[1] = D3DTLVERTEX(D3DVECTOR(x,y + DISPLAY_FONT_HEIGHT ,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + COMP,voffset + vsize - COMP - COMP);
v[2] = D3DTLVERTEX(D3DVECTOR(x + DISPLAY_FONT_WIDTH,y + DISPLAY_FONT_HEIGHT,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + usize - COMP - COMP ,voffset + vsize - COMP - COMP);
v[3] = D3DTLVERTEX(D3DVECTOR(x + DISPLAY_FONT_WIDTH,y,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + usize - COMP - COMP,voffset + COMP);
pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,D3DFVF_TLVERTEX ,(LPVOID)v,4,NULL);
}
y += m_FontSz.cy;
}
/* Draw the cursor */
if ( m_bCursor )
{
y -= m_FontSz.cy;
x = (m_FontSz.cx * m_CursorPos) + XOFF;
uoffset = ('I' % UMAX ) * usize;
voffset = ('I' / UMAX ) * vsize;
v[0] = D3DTLVERTEX(D3DVECTOR(x,y,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + COMP,voffset + COMP);
v[1] = D3DTLVERTEX(D3DVECTOR(x,y + DISPLAY_FONT_HEIGHT ,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + COMP,voffset + vsize - COMP - COMP);
v[2] = D3DTLVERTEX(D3DVECTOR(x + DISPLAY_FONT_WIDTH,y + DISPLAY_FONT_HEIGHT,0),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + usize - COMP - COMP ,voffset + vsize - COMP - COMP);
v[3] = D3DTLVERTEX(D3DVECTOR(x + DISPLAY_FONT_WIDTH,y,1),1,D3DRGB(1,1,1),D3DRGB(1,1,1),uoffset + usize - COMP - COMP,voffset + COMP);
pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,D3DFVF_TLVERTEX ,(LPVOID)v,4,NULL);
}
/* restore the device render states */
pDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,loldSrc);
pDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND,loldDest);
pDevice->SetTextureStageState( 1, D3DTSS_COLOROP,loldColor);
pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,loldAlpha);
pDevice->SetRenderState( D3DRENDERSTATE_ZFUNC,lOldZFunc);
}
//-----------------------------------------------------------------------
// Call this when the device nees to be restored
void CConsole::Restore()
{
D3DTextr_Restore(m_FontName,g_pFramework->GetD3DDevice());
m_font = D3DTextr_GetTexture(m_FontName);
DDSetColorKey(D3DTextr_GetSurface(m_FontName),RGB(0,0,0));
D3DTextr_Restore( m_BackgroundName,g_pFramework->GetD3DDevice());
m_background = D3DTextr_GetTexture( m_BackgroundName);
}
//-----------------------------------------------------------------------
// Function to add a line to the console. Use in the same way as printf
// eg "console.FormatLine("Loaded texture %s",texturename)";
void CConsole::FormatLine(char *format, ...)
{
va_list arg;
char buffer[256];
va_start(arg, format);
vsprintf(buffer, format, arg);
va_end(arg);
DisplayLine(buffer);
}
//-----------------------------------------------------------------------
// Function to display a line of text
void CConsole::DisplayLine(char *text)
{
m_text.AddTail(text);
if ( m_text.GetCount() > MAX_SIZE )
m_text.RemoveHead();
}
//-----------------------------------------------------------------------
// Function to handle a key press
void CConsole::OnChar(char character)
{
if ( character != VK_TAB)
m_TabCount = 0;
switch ( character )
{
case '`':
case '~':
if ( m_mode == STATIC )
{
m_InputBuffer.Empty();
m_CursorPos = 0;
m_mode = UP;
}
break;
case VK_ESCAPE:
if ( m_InputBuffer.IsEmpty() )
m_mode = UP;
else
{
m_InputBuffer.Empty();
m_CursorPos = 0;
}
break;
case VK_BACK:
if ( !m_InputBuffer.IsEmpty())
{
m_InputBuffer.Delete(m_CursorPos - 1);
m_CursorPos--;
}
break;
case VK_RETURN:
ProccessCommand();
break;
case VK_TAB:
ProccessTab();
break;
default:
if ( m_CursorPos < m_InputBuffer.GetLength() )
{
m_InputBuffer.Insert(m_CursorPos,character);
}
else
m_InputBuffer += character;
m_CursorPos++;
}
}
//-----------------------------------------------------------------------
// Function to handle a key press
void CConsole::OnKeyUp(int key)
{
POSITION pos = NULL;
if ( key != VK_TAB )
m_TabCount = 0;
switch ( key )
{
case VK_UP:
if ( m_HistoryPos == NULL )
m_HistoryPos = m_CommandHistory.GetHeadPosition();
else
m_CommandHistory.GetNext(m_HistoryPos);
if ( m_HistoryPos )
m_InputBuffer = m_CommandHistory.GetAt(m_HistoryPos);
else
m_HistoryPos = m_CommandHistory.GetTailPosition();
m_CursorPos = m_InputBuffer.GetLength();
break;
case VK_DOWN:
if ( m_HistoryPos )
{
m_CommandHistory.GetPrev(m_HistoryPos);
if ( m_HistoryPos == NULL )
m_HistoryPos = m_CommandHistory.GetHeadPosition();
m_InputBuffer = m_CommandHistory.GetAt(m_HistoryPos);
}
m_CursorPos = m_InputBuffer.GetLength();
break;
case VK_LEFT:
if ( m_CursorPos > 0 )
m_CursorPos--;
break;
case VK_RIGHT:
if ( m_CursorPos < m_InputBuffer.GetLength() )
m_CursorPos++;
break;
case VK_DELETE:
if ( m_CursorPos < m_InputBuffer.GetLength() )
{
m_InputBuffer.Delete(m_CursorPos,1);
}
break;
case VK_HOME:
m_CursorPos = 0;
break;
case VK_END:
m_CursorPos = m_InputBuffer.GetLength();
break;
}
}
//-----------------------------------------------------------------------
// The main part of the console!! This examines the keyed input and
// calls the appropriate function handler
void CConsole::ProccessCommand()
{
struct console *pCommand = CommandList;
char CommandLine[128],
*p;
int n = m_InputBuffer.Find(' ');
if ( m_InputBuffer.IsEmpty() )
{
DisplayLine("");
return ;
}
m_InputBuffer.TrimRight();
/* Update history */
m_CommandHistory.AddHead(m_InputBuffer);
if ( m_CommandHistory.GetCount() > MAX_SIZE )
m_CommandHistory.RemoveHead();
m_HistoryPos = NULL;
strcpy(CommandLine,m_InputBuffer);
m_InputBuffer.Empty();
m_CursorPos = 0;
while ( pCommand->command && pCommand->handler )
{
if ( strnicmp(CommandLine,pCommand->command,n) == 0)
{
/* Display the command */
DisplayLine(CommandLine);
/* Get the option */
p = strtok(CommandLine," ");
p = strtok(NULL," ");
/* Handle the command */
pCommand->handler(p);
return;
}
pCommand++;
}
/* Not found a match in the command list */
FormatLine("Unknown command :\"%s\".",CommandLine);
DisplayLine( "Type HELP for list ");
}
//-----------------------------------------------------------------------
// Enable the TAB key to complete the current command
void CConsole::ProccessTab()
{
struct console *pCommand = CommandList;
int match = 0;
if ( m_TabCount == 0 )
m_PrevInput = m_InputBuffer;
while ( pCommand->command && pCommand->handler )
{
if ( strnicmp(m_PrevInput,pCommand->command,m_PrevInput.GetLength()) == 0)
{
m_InputBuffer = pCommand->command;
m_CursorPos = m_InputBuffer.GetLength();
if ( m_TabCount <= match )
{
m_TabCount = match + 1;
return;
}
match++;
}
pCommand++;
}
}
//-----------------------------------------------------------------------
// Close the console
void CConsole::Close()
{
m_yOffset = 0;
m_mode = DOWN;
}
|