/* Config.cpp Written by Matthew Fisher Implementation file for the Console class. */ #include "Main.h" Overlay::Overlay() { _Font = NULL; _NullPixelShader = NULL; _Sprite = NULL; } void Overlay::FreeMemory() { if(_Font) { _Font->Release(); _Font = NULL; } if(_Sprite) { _Sprite->Release(); _Sprite = NULL; } if(_NullPixelShader) { _NullPixelShader->Release(); _NullPixelShader = NULL; } } void Overlay::OnLostDevice() { if(_Font) { _Font->OnLostDevice(); } if(_Sprite) { _Sprite->OnLostDevice(); } if(_NullPixelShader) { _NullPixelShader->Release(); _NullPixelShader = NULL; } } void Overlay::OnResetDevice() { if(_Font) { _Font->OnResetDevice(); } if(_Sprite) { _Sprite->OnResetDevice(); } if(_NullPixelShader) { _NullPixelShader->Release(); _NullPixelShader = NULL; } } void Overlay::ClearPanel(UINT PanelIndex) { if(PanelIndex >= ConsolePanelCount) { return; } if(g_Globals.UsingOverlay) { ConsolePanel &CurPanel = _Panels[PanelIndex]; CurPanel.CurHeadPtr = 0; CurPanel.Lines.Allocate(g_Globals.ConsoleLineCount); } } void Overlay::Init(D3D9Base::LPDIRECT3DDEVICE9 Device) { if(g_Globals.UsingOverlay) { _Device = Device; FreeMemory(); HDC hDC = GetDC( NULL ); int nLogPixelsY = GetDeviceCaps(hDC, LOGPIXELSY); ReleaseDC( NULL, hDC ); int FontHeight = -9 * nLogPixelsY / 72; //get the appropriate height of the font HRESULT hr = D3DXCreateFont( Device, FontHeight, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &_Font); Assert(SUCCEEDED(hr), "D3DXCreateFont failed"); for(UINT PanelIndex = 0; PanelIndex < ConsolePanelCount; PanelIndex++) { ClearPanel(PanelIndex); } hr = D3DXCreateSprite(Device, &_Sprite); Assert(SUCCEEDED(hr), "D3DXCreateSprite failed"); WriteLine("Console Start", RGBColor::Yellow, 0); } } void Overlay::CreateNullPixelShader() { HRESULT hr; DWORD dwShaderFlags = 0; D3D9Base::LPD3DXBUFFER pCode = NULL; D3D9Base::LPD3DXBUFFER pErrors = NULL; String ShaderFilename = g_Globals.BaseDirectory + String("\\") + String("Null.psh"); PersistentAssert(Utility::FileExists(ShaderFilename), "Null.psh not found"); // Assemble the vertex shader from the file hr = D3DXCompileShaderFromFile( ShaderFilename.CString(), NULL, NULL, "PShaderEntry", "ps_3_0", dwShaderFlags, &pCode, &pErrors, NULL ); String ErrorString; if(pErrors) { char *ErrorMessage = (char *)pErrors->GetBufferPointer(); DWORD ErrorLength = pErrors->GetBufferSize(); for(UINT i = 0; i < ErrorLength; i++) { g_Globals.ErrorFile() << ErrorMessage[i]; ErrorString += String(ErrorMessage[i]); } } PersistentAssert(!FAILED(hr), String("D3DXCompileShaderFromFile failed: ") + ErrorString); // Create the pixel shader hr = _Device->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), &_NullPixelShader ); if(pErrors) { pErrors->Release(); } if(pCode) { pCode->Release(); } PersistentAssert(!FAILED(hr), "CreatePixelShader failed"); } void Overlay::SetNullPixelShader() { if(_NullPixelShader == NULL) { CreateNullPixelShader(); } HRESULT hr = _Device->SetPixelShader(_NullPixelShader); Assert(SUCCEEDED(hr), "SetPixelShader failed"); } void Overlay::WriteLine(const String &Text, RGBColor Color, UINT PanelIndex) { if(PanelIndex >= ConsolePanelCount) { return; } if(g_Globals.UsingOverlay) { ConsolePanel &CurPanel = _Panels[PanelIndex]; CurPanel.Lines[CurPanel.CurHeadPtr].Text = Text; CurPanel.Lines[CurPanel.CurHeadPtr].Color = Color; CurPanel.CurHeadPtr = Math::Mod(CurPanel.CurHeadPtr + 1, CurPanel.Lines.Length()); } } void Overlay::AddMesh(const Mesh &M) { _Meshes.PushEnd(new Mesh(M)); } void Overlay::SetMeshTransform(const Matrix4 &Transform) { _MeshTransform = Transform; } void Overlay::ClearMeshes() { for(UINT MeshIndex = 0; MeshIndex < _Meshes.Length(); MeshIndex++) { delete _Meshes[MeshIndex]; } _Meshes.FreeMemory(); } bool Pressed(SHORT Key) { return (Key == -32767 || Key == -32768); } D3D9Base::D3DXMATRIX Matrix4ToD3DXMATRIX(const Matrix4 &M) { D3D9Base::D3DXMATRIX Result; for(UINT i = 0; i < 4; i++) { for(UINT i2 = 0; i2 < 4; i2++) { Result(i, i2) = M[i][i2]; } } return Result; } void Overlay::RenderMeshes() { if(g_Globals.UsingOverlay && _Meshes.Length() > 0) { IDirect3DStateBlock9* pStateBlock = NULL; _Device->CreateStateBlock( D3D9Base::D3DSBT_ALL, &pStateBlock ); const UINT MaxTextureSlots = 8; for(UINT TextureIndex = 0; TextureIndex < MaxTextureSlots; TextureIndex++) { _Device->SetTexture(TextureIndex, NULL); } D3D9Base::D3DXMATRIXA16 NewTransformWorld, NewTransformView, NewTransformProjection; NewTransformWorld = Matrix4ToD3DXMATRIX(Matrix4::Identity()); NewTransformView = Matrix4ToD3DXMATRIX(Matrix4::Identity()); NewTransformProjection = Matrix4ToD3DXMATRIX(_MeshTransform); _Device->SetTransform(D3DTS_WORLD, &NewTransformWorld); _Device->SetTransform(D3D9Base::D3DTS_VIEW, &NewTransformView); _Device->SetTransform(D3D9Base::D3DTS_PROJECTION, &NewTransformProjection); _Device->SetRenderState(D3D9Base::D3DRS_ALPHABLENDENABLE, FALSE); //_Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_TRUE); _Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_FALSE); _Device->SetRenderState(D3D9Base::D3DRS_LIGHTING, FALSE); _Device->SetRenderState(D3D9Base::D3DRS_ZFUNC, D3D9Base::D3DCMP_ALWAYS); _Device->SetRenderState(D3D9Base::D3DRS_ALPHATESTENABLE, FALSE); _Device->SetRenderState(D3D9Base::D3DRS_CULLMODE, D3D9Base::D3DCULL_NONE); const DWORD D3DMeshFlags = D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1; _Device->SetFVF(D3DMeshFlags); _Device->SetVertexShader(NULL); _Device->SetPixelShader(NULL); for(UINT MeshIndex = 0; MeshIndex < _Meshes.Length(); MeshIndex++) { Mesh &CurMesh = *(_Meshes[MeshIndex]); _Device->DrawIndexedPrimitiveUP(D3D9Base::D3DPT_TRIANGLELIST, 0, CurMesh.VertexCount(), CurMesh.FaceCount(), CurMesh.Indices(), D3D9Base::D3DFMT_INDEX32, CurMesh.Vertices(), sizeof(MeshVertex)); } pStateBlock->Apply(); pStateBlock->Release(); } } void Overlay::RenderConsole() { const UINT ConsoleStartOffset = 3; const UINT ConsoleXSeparation = 210; const UINT ConsoleYSeparation = 13; if(Pressed(GetAsyncKeyState(KEY_F2))) { g_Globals.UsingNullPixelShader = !g_Globals.UsingNullPixelShader; } if(g_Globals.UsingOverlay) { if(Pressed(GetAsyncKeyState(KEY_DELETE))) { for(UINT PanelIndex = 0; PanelIndex < ConsolePanelCount; PanelIndex++) { ClearPanel(PanelIndex); } ClearMeshes(); } D3D9Base::LPDIRECT3DDEVICE9 Device = NULL; _Font->GetDevice(&Device); D3D9Base::LPDIRECT3DSURFACE9 BackBufferSurface = NULL; Device->GetBackBuffer(0, 0, D3D9Base::D3DBACKBUFFER_TYPE_MONO, &BackBufferSurface); D3DSURFACE_DESC BackBufferDesc; BackBufferSurface->GetDesc(&BackBufferDesc); D3DVIEWPORT9 Viewport; Viewport.X = 0; Viewport.Y = 0; Viewport.Width = BackBufferDesc.Width; Viewport.Height = BackBufferDesc.Height; Viewport.MinZ = 0.0f; Viewport.MaxZ = 1.0f; Device->SetViewport(&Viewport); BackBufferSurface->Release(); Device->Release(); _Sprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE ); for(UINT PanelIndex = 0; PanelIndex < ConsolePanelCount; PanelIndex++) { ConsolePanel &CurPanel = _Panels[PanelIndex]; UINT LineIndex = CurPanel.CurHeadPtr, YPos = ConsoleStartOffset; UINT XPos = ConsoleStartOffset + ConsoleXSeparation * PanelIndex; bool FlipLineOrder = false; if(PanelIndex == ConsolePanelCount - 1) { FlipLineOrder = true; //YPos = ConsoleStartOffset + ConsoleYSeparation * CurPanel.Lines.Length(); YPos = ConsoleStartOffset + ConsoleYSeparation; XPos = ConsoleStartOffset; } if(PanelIndex == ConsolePanelCount - 2) { XPos += 75; } bool Done = false; while(!Done) { // TODO: add sprite support UINT ModifiedLineIndex = LineIndex; if(FlipLineOrder) { //ModifiedLineIndex = CurPanel.Lines.Length() - 1 - LineIndex; } const ConsoleLine &CurLine = CurPanel.Lines[ModifiedLineIndex]; const String &CurText = CurLine.Text; if(CurText.Length() > 0) { RECT Rect; SetRect( &Rect, int(XPos), int(YPos), 0, 0 ); //RGBColor Color = RGBColor::Black; //_Font->DrawText(_Sprite, CurText.CString(), CurText.Length(), &Rect, DT_NOCLIP, D3D9Base::D3DXCOLOR(Color.r / 255.0f, Color.g / 255.0f, Color.b / 255.0f, 1.0f )); //Rect.left -= 1; //Rect.top -= 1; RGBColor Color = CurLine.Color; _Font->DrawText(_Sprite, CurText.CString(), CurText.Length(), &Rect, DT_NOCLIP, D3D9Base::D3DXCOLOR(Color.r / 255.0f, Color.g / 255.0f, Color.b / 255.0f, 1.0f )); } LineIndex = Math::Mod(LineIndex + 1, CurPanel.Lines.Length()); YPos += ConsoleYSeparation; if(LineIndex == Math::Mod(int(CurPanel.CurHeadPtr), CurPanel.Lines.Length())) { Done = true; } } } _Sprite->End(); } }