#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 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"); }