client/EterPythonLib/PythonGraphic.cpp

625 lines
16 KiB
C++

#include "StdAfx.h"
#include "../eterLib/StateManager.h"
#include "../eterLib/JpegFile.h"
#include "PythonGraphic.h"
bool g_isScreenShotKey = false;
void CPythonGraphic::Destroy()
{
}
LPDIRECT3D8 CPythonGraphic::GetD3D()
{
return ms_lpd3d;
}
float CPythonGraphic::GetOrthoDepth()
{
return m_fOrthoDepth;
}
void CPythonGraphic::SetInterfaceRenderState()
{
STATEMANAGER.SetTransform(D3DTS_PROJECTION, &ms_matIdentity);
STATEMANAGER.SetTransform(D3DTS_VIEW, &ms_matIdentity);
STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_NONE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
CPythonGraphic::Instance().SetBlendOperation();
CPythonGraphic::Instance().SetOrtho2D(ms_iWidth, ms_iHeight, GetOrthoDepth());
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
}
void CPythonGraphic::SetGameRenderState()
{
STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE);
}
void CPythonGraphic::SetCursorPosition(int x, int y)
{
CScreen::SetCursorPosition(x, y, ms_iWidth, ms_iHeight);
}
void CPythonGraphic::SetOmniLight()
{
// Set up a material
D3DMATERIAL8 Material;
Material.Ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
Material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
Material.Emissive = D3DXCOLOR(0.1f, 0.1f, 0.1f, 1.0f);
STATEMANAGER.SetMaterial(&Material);
D3DLIGHT8 Light;
Light.Type = D3DLIGHT_SPOT;
Light.Position = D3DXVECTOR3(50.0f, 150.0f, 350.0f);
Light.Direction = D3DXVECTOR3(-0.15f, -0.3f, -0.9f);
Light.Theta = D3DXToRadian(30.0f);
Light.Phi = D3DXToRadian(45.0f);
Light.Falloff = 1.0f;
Light.Attenuation0 = 0.0f;
Light.Attenuation1 = 0.005f;
Light.Attenuation2 = 0.0f;
Light.Diffuse.r = 1.0f;
Light.Diffuse.g = 1.0f;
Light.Diffuse.b = 1.0f;
Light.Diffuse.a = 1.0f;
Light.Ambient.r = 1.0f;
Light.Ambient.g = 1.0f;
Light.Ambient.b = 1.0f;
Light.Ambient.a = 1.0f;
Light.Range = 500.0f;
ms_lpd3dDevice->SetLight(0, &Light);
ms_lpd3dDevice->LightEnable(0, TRUE);
Light.Type = D3DLIGHT_POINT;
Light.Position = D3DXVECTOR3(0.0f, 200.0f, 200.0f);
Light.Attenuation0 = 0.1f;
Light.Attenuation1 = 0.01f;
Light.Attenuation2 = 0.0f;
ms_lpd3dDevice->SetLight(1, &Light);
ms_lpd3dDevice->LightEnable(1, TRUE);
}
void CPythonGraphic::SetViewport(float fx, float fy, float fWidth, float fHeight)
{
ms_lpd3dDevice->GetViewport(&m_backupViewport);
D3DVIEWPORT8 ViewPort;
ViewPort.X = fx;
ViewPort.Y = fy;
ViewPort.Width = fWidth;
ViewPort.Height = fHeight;
ViewPort.MinZ = 0.0f;
ViewPort.MaxZ = 1.0f;
if (FAILED(
ms_lpd3dDevice->SetViewport(&ViewPort)
))
{
Tracef("CPythonGraphic::SetViewport(%d, %d, %d, %d) - Error",
ViewPort.X, ViewPort.Y,
ViewPort.Width, ViewPort.Height
);
}
}
void CPythonGraphic::RestoreViewport()
{
ms_lpd3dDevice->SetViewport(&m_backupViewport);
}
void CPythonGraphic::SetGamma(float fGammaFactor)
{
D3DCAPS8 d3dCaps;
D3DGAMMARAMP NewRamp;
int ui, val;
ms_lpd3dDevice->GetDeviceCaps(&d3dCaps);
if (D3DCAPS2_FULLSCREENGAMMA != (d3dCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA))
return;
for (int i = 0; i < 256; ++i)
{
val = (int) (i * fGammaFactor * 255.0f);
ui = 0;
if (val > 32767)
{
val = val - 32767;
ui = 1;
}
if (val > 32767)
val = 32767;
NewRamp.red[i] = (WORD) (val | (32768 * ui));
NewRamp.green[i] = (WORD) (val | (32768 * ui));
NewRamp.blue[i] = (WORD) (val | (32768 * ui));
}
ms_lpd3dDevice->SetGammaRamp(D3DSGR_NO_CALIBRATION, &NewRamp);
}
void GenScreenShotTag(const char* src, DWORD crc32, char* leaf, size_t leafLen)
{
const char* p = src;
const char* n = p;
while (n = strchr(p, '\\'))
p = n + 1;
_snprintf(leaf, leafLen, "YMIR_METIN2:%s:0x%.8x", p, crc32);
}
bool CPythonGraphic::SaveJPEG(const char * pszFileName, LPBYTE pbyBuffer, UINT uWidth, UINT uHeight)
{
return jpeg_save(pbyBuffer, uWidth, uHeight, 85, pszFileName) != 0;
}
bool CPythonGraphic::SaveScreenShot(const char * c_pszFileName)
{
HRESULT hr;
LPDIRECT3DSURFACE8 lpSurface;
D3DSURFACE_DESC stSurfaceDesc;
if (FAILED(hr = ms_lpd3dDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &lpSurface)))
{
TraceError("Failed to get back buffer (0x%08x)", hr);
return false;
}
if (FAILED(hr = lpSurface->GetDesc(&stSurfaceDesc)))
{
TraceError("Failed to get surface desc (0x%08x)", hr);
SAFE_RELEASE(lpSurface);
return false;
}
UINT uWidth = stSurfaceDesc.Width;
UINT uHeight = stSurfaceDesc.Height;
switch( stSurfaceDesc.Format ) {
case D3DFMT_R8G8B8 :
case D3DFMT_A8R8G8B8 :
case D3DFMT_X8R8G8B8 :
case D3DFMT_R5G6B5 :
case D3DFMT_X1R5G5B5 :
case D3DFMT_A1R5G5B5 :
break;
case D3DFMT_A4R4G4B4 :
case D3DFMT_R3G3B2 :
case D3DFMT_A8R3G3B2 :
case D3DFMT_X4R4G4B4 :
case D3DFMT_A2B10G10R10 :
TraceError("Unsupported BackBuffer Format(%d). Please contact Metin 2 Administrator.", stSurfaceDesc.Format);
SAFE_RELEASE(lpSurface);
return false;
}
D3DLOCKED_RECT lockRect;
if (FAILED(hr = lpSurface->LockRect(&lockRect, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
{
TraceError("Failed to lock the surface (0x%08x)", hr);
SAFE_RELEASE(lpSurface);
return false;
}
BYTE* pbyBuffer = new BYTE[uWidth * uHeight * 3];
if (pbyBuffer == NULL) {
lpSurface->UnlockRect();
lpSurface->Release();
lpSurface = NULL;
TraceError("Failed to allocate screenshot buffer");
return false;
}
BYTE* pbySource = (BYTE*) lockRect.pBits;
BYTE* pbyDestination = (BYTE*) pbyBuffer;
for(UINT y = 0; y < uHeight; ++y) {
BYTE *pRow = pbySource;
switch( stSurfaceDesc.Format ) {
case D3DFMT_R8G8B8 :
for(UINT x = 0; x < uWidth; ++x) {
*pbyDestination++ = pRow[2]; // Blue
*pbyDestination++ = pRow[1]; // Green
*pbyDestination++ = pRow[0]; // Red
pRow += 3;
}
break;
case D3DFMT_A8R8G8B8 :
case D3DFMT_X8R8G8B8 :
for(UINT x = 0; x < uWidth; ++x) {
*pbyDestination++ = pRow[2]; // Blue
*pbyDestination++ = pRow[1]; // Green
*pbyDestination++ = pRow[0]; // Red
pRow += 4;
}
break;
case D3DFMT_R5G6B5 :
{
for(UINT x = 0; x < uWidth; ++x) {
UINT uColor = *((UINT *) pRow);
BYTE byBlue = (uColor >> 11) & 0x1F;
BYTE byGreen = (uColor >> 5) & 0x3F;
BYTE byRed = uColor & 0x1F;
*pbyDestination++ = (byBlue << 3) | (byBlue >> 2); // Blue
*pbyDestination++ = (byGreen << 2) | (byGreen >> 2); // Green
*pbyDestination++ = (byRed << 3) | (byRed >> 2); // Red
pRow += 2;
}
}
break;
case D3DFMT_X1R5G5B5 :
case D3DFMT_A1R5G5B5 :
{
for(UINT x = 0; x < uWidth; ++x) {
UINT uColor = *((UINT *) pRow);
BYTE byBlue = (uColor >> 10) & 0x1F;
BYTE byGreen = (uColor >> 5) & 0x1F;
BYTE byRed = uColor & 0x1F;
*pbyDestination++ = (byBlue << 3) | (byBlue >> 2); // Blue
*pbyDestination++ = (byGreen << 3) | (byGreen >> 2); // Green
*pbyDestination++ = (byRed << 3) | (byRed >> 2); // Red
pRow += 2;
}
}
break;
}
// increase by one line
pbySource += lockRect.Pitch;
}
if(lpSurface) {
lpSurface->UnlockRect();
lpSurface->Release();
lpSurface = NULL;
}
bool bSaved = SaveJPEG(c_pszFileName, pbyBuffer, uWidth, uHeight);
if(pbyBuffer) {
delete [] pbyBuffer;
pbyBuffer = NULL;
}
if(bSaved == false) {
TraceError("Failed to save JPEG file. (%s, %d, %d)", c_pszFileName, uWidth, uHeight);
return false;
}
if (g_isScreenShotKey)
{
FILE* srcFilePtr = fopen(c_pszFileName, "rb");
if (srcFilePtr)
{
fseek(srcFilePtr, 0, SEEK_END);
size_t fileSize = ftell(srcFilePtr);
fseek(srcFilePtr, 0, SEEK_SET);
char head[21];
size_t tailSize = fileSize - sizeof(head);
char* tail = (char*)malloc(tailSize);
fread(head, sizeof(head), 1, srcFilePtr);
fread(tail, tailSize, 1, srcFilePtr);
fclose(srcFilePtr);
char imgDesc[64];
GenScreenShotTag(c_pszFileName, GetCRC32(tail, tailSize), imgDesc, sizeof(imgDesc));
int imgDescLen = strlen(imgDesc) + 1;
unsigned char exifHeader[] = {
0xe1,
0, // blockLen[1],
0, // blockLen[0],
0x45,
0x78,
0x69,
0x66,
0x0,
0x0,
0x49,
0x49,
0x2a,
0x0,
0x8,
0x0,
0x0,
0x0,
0x1,
0x0,
0xe,
0x1,
0x2,
0x0,
imgDescLen, // textLen[0],
0, // textLen[1],
0, // textLen[2],
0, // textLen[3],
0x1a,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
};
exifHeader[2] = sizeof(exifHeader) + imgDescLen;
FILE* dstFilePtr = fopen(c_pszFileName, "wb");
//FILE* dstFilePtr = fopen("temp.jpg", "wb");
if (dstFilePtr)
{
fwrite(head, sizeof(head), 1, dstFilePtr);
fwrite(exifHeader, sizeof(exifHeader), 1, dstFilePtr);
fwrite(imgDesc, imgDescLen, 1, dstFilePtr);
fputc(0x00, dstFilePtr);
fputc(0xff, dstFilePtr);
fwrite(tail, tailSize, 1, dstFilePtr);
fclose(dstFilePtr);
}
free(tail);
}
}
return true;
}
void CPythonGraphic::PushState()
{
TState curState;
curState.matProj = ms_matProj;
curState.matView = ms_matView;
//STATEMANAGER.SaveTransform(D3DTS_WORLD, &m_SaveWorldMatrix);
m_stateStack.push(curState);
//CCamera::Instance().PushParams();
}
void CPythonGraphic::PopState()
{
if (m_stateStack.empty())
{
assert(!"PythonGraphic::PopState StateStack is EMPTY");
return;
}
TState & rState = m_stateStack.top();
//STATEMANAGER.RestoreTransform(D3DTS_WORLD);
ms_matProj = rState.matProj;
ms_matView = rState.matView;
UpdatePipeLineMatrix();
m_stateStack.pop();
//CCamera::Instance().PopParams();
}
void CPythonGraphic::RenderImage(CGraphicImageInstance* pImageInstance, float x, float y)
{
assert(pImageInstance != NULL);
//SetColorRenderState();
const CGraphicTexture * c_pTexture = pImageInstance->GetTexturePointer();
float width = (float) pImageInstance->GetWidth();
float height = (float) pImageInstance->GetHeight();
c_pTexture->SetTextureStage(0);
RenderTextureBox(x,
y,
x + width,
y + height,
0.0f,
0.5f / width,
0.5f / height,
(width + 0.5f) / width,
(height + 0.5f) / height);
}
void CPythonGraphic::RenderAlphaImage(CGraphicImageInstance* pImageInstance, float x, float y, float aLeft, float aRight)
{
assert(pImageInstance != NULL);
D3DXCOLOR DiffuseColor1 = D3DXCOLOR(1.0f, 1.0f, 1.0f, aLeft);
D3DXCOLOR DiffuseColor2 = D3DXCOLOR(1.0f, 1.0f, 1.0f, aRight);
const CGraphicTexture * c_pTexture = pImageInstance->GetTexturePointer();
float width = (float) pImageInstance->GetWidth();
float height = (float) pImageInstance->GetHeight();
c_pTexture->SetTextureStage(0);
float sx = x;
float sy = y;
float ex = x + width;
float ey = y + height;
float z = 0.0f;
float su = 0.0f;
float sv = 0.0f;
float eu = 1.0f;
float ev = 1.0f;
TPDTVertex vertices[4];
vertices[0].position = TPosition(sx, sy, z);
vertices[0].diffuse = DiffuseColor1;
vertices[0].texCoord = TTextureCoordinate(su, sv);
vertices[1].position = TPosition(ex, sy, z);
vertices[1].diffuse = DiffuseColor2;
vertices[1].texCoord = TTextureCoordinate(eu, sv);
vertices[2].position = TPosition(sx, ey, z);
vertices[2].diffuse = DiffuseColor1;
vertices[2].texCoord = TTextureCoordinate(su, ev);
vertices[3].position = TPosition(ex, ey, z);
vertices[3].diffuse = DiffuseColor2;
vertices[3].texCoord = TTextureCoordinate(eu, ev);
STATEMANAGER.SetVertexShader(ms_pntVS);
// 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer
CGraphicBase::SetDefaultIndexBuffer(DEFAULT_IB_FILL_RECT);
if (CGraphicBase::SetPDTStream(vertices, 4))
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2);
}
void CPythonGraphic::RenderCoolTimeBox(float fxCenter, float fyCenter, float fRadius, float fTime)
{
if (fTime >= 1.0f)
return;
fTime = max(0.0f, fTime);
static D3DXCOLOR color = D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.5f);
static WORD s_wBoxIndicies[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
static D3DXVECTOR2 s_v2BoxPos[8] =
{
D3DXVECTOR2( -1.0f, -1.0f ),
D3DXVECTOR2( -1.0f, 0.0f ),
D3DXVECTOR2( -1.0f, +1.0f ),
D3DXVECTOR2( 0.0f, +1.0f ),
D3DXVECTOR2( +1.0f, +1.0f ),
D3DXVECTOR2( +1.0f, 0.0f ),
D3DXVECTOR2( +1.0f, -1.0f ),
D3DXVECTOR2( 0.0f, -1.0f ),
};
int iTriCount = int(8 - 8.0f * fTime);
float fLastPercentage = (8 - 8.0f * fTime) - iTriCount;
std::vector<TPDTVertex> vertices;
TPDTVertex vertex;
vertex.position.x = fxCenter;
vertex.position.y = fyCenter;
vertex.position.z = 0.0f;
vertex.diffuse = color;
vertex.texCoord.x = 0.0f;
vertex.texCoord.x = 0.0f;
vertices.push_back(vertex);
vertex.position.x = fxCenter;
vertex.position.y = fyCenter - fRadius;
vertex.position.z = 0.0f;
vertex.diffuse = color;
vertex.texCoord.x = 0.0f;
vertex.texCoord.x = 0.0f;
vertices.push_back(vertex);
for (int j = 0; j < iTriCount; ++j)
{
vertex.position.x = fxCenter + s_v2BoxPos[j].x * fRadius;
vertex.position.y = fyCenter + s_v2BoxPos[j].y * fRadius;
vertices.push_back(vertex);
}
if (fLastPercentage > 0.0f)
{
D3DXVECTOR2 * pv2Pos;
D3DXVECTOR2 * pv2LastPos;
assert((iTriCount-1+8)%8 >= 0 && (iTriCount-1+8)%8 < 8);
assert((iTriCount+8)%8 >= 0 && (iTriCount+8)%8 < 8);
pv2LastPos = &s_v2BoxPos[(iTriCount-1+8)%8];
pv2Pos = &s_v2BoxPos[(iTriCount+8)%8];
vertex.position.x = fxCenter + ((pv2Pos->x-pv2LastPos->x) * fLastPercentage + pv2LastPos->x) * fRadius;
vertex.position.y = fyCenter + ((pv2Pos->y-pv2LastPos->y) * fLastPercentage + pv2LastPos->y) * fRadius;
vertices.push_back(vertex);
++iTriCount;
}
if (vertices.empty())
return;
if (SetPDTStream(&vertices[0], vertices.size()))
{
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLEFAN, 0, iTriCount);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP);
}
}
long CPythonGraphic::GenerateColor(float r, float g, float b, float a)
{
return GetColor(r, g, b, a);
}
void CPythonGraphic::RenderDownButton(float sx, float sy, float ex, float ey)
{
RenderBox2d(sx, sy, ex, ey);
SetDiffuseColor(m_darkColor);
RenderLine2d(sx, sy, ex, sy);
RenderLine2d(sx, sy, sx, ey);
SetDiffuseColor(m_lightColor);
RenderLine2d(sx, ey, ex, ey);
RenderLine2d(ex, sy, ex, ey);
}
void CPythonGraphic::RenderUpButton(float sx, float sy, float ex, float ey)
{
RenderBox2d(sx, sy, ex, ey);
SetDiffuseColor(m_lightColor);
RenderLine2d(sx, sy, ex, sy);
RenderLine2d(sx, sy, sx, ey);
SetDiffuseColor(m_darkColor);
RenderLine2d(sx, ey, ex, ey);
RenderLine2d(ex, sy, ex, ey);
}
DWORD CPythonGraphic::GetAvailableMemory()
{
return ms_lpd3dDevice->GetAvailableTextureMem();
}
CPythonGraphic::CPythonGraphic()
{
m_lightColor = GetColor(1.0f, 1.0f, 1.0f);
m_darkColor = GetColor(0.0f, 0.0f, 0.0f);
memset(&m_backupViewport, 0, sizeof(D3DVIEWPORT8));
m_fOrthoDepth = 1000.0f;
}
CPythonGraphic::~CPythonGraphic()
{
Tracef("Python Graphic Clear\n");
}