#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; 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");
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);
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_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;
XPos = ConsoleStartOffset;
}
if(PanelIndex == ConsolePanelCount - 2)
{
XPos += 75;
}
bool Done = false;
while(!Done)
{
UINT ModifiedLineIndex = LineIndex;
if(FlipLineOrder)
{
}
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 = 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();
}
}