#include "common.h" #include "main.h" #include "PlayerSkin.h" #include "TxdStore.h" #include "rtbmp.h" #include "ClumpModelInfo.h" #include "VisibilityPlugins.h" #include "World.h" #include "PlayerInfo.h" #include "CdStream.h" #include "FileMgr.h" #include "Directory.h" #include "RwHelper.h" #include "Timer.h" #include "Lights.h" RpClump *gpPlayerClump; float gOldFov; int CPlayerSkin::m_txdSlot; void FindPlayerDff(uint32 &offset, uint32 &size) { int file; CDirectory::DirectoryInfo info; file = CFileMgr::OpenFile("models\\gta3.dir", "rb"); do { if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo))) return; } while (strcasecmp("player.dff", info.name) != 0); offset = info.offset; size = info.size; } void LoadPlayerDff(void) { RwStream *stream; RwMemory mem; uint32 offset, size; uint8 *buffer; bool streamWasAdded = false; if (CdStreamGetNumImages() == 0) { CdStreamAddImage("models\\gta3.img"); streamWasAdded = true; } FindPlayerDff(offset, size); buffer = (uint8*)RwMallocAlign(size << 11, 2048); CdStreamRead(0, buffer, offset, size); CdStreamSync(0); mem.start = buffer; mem.length = size << 11; stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem); if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) gpPlayerClump = RpClumpStreamRead(stream); RwStreamClose(stream, &mem); RwFreeAlign(buffer); if (streamWasAdded) CdStreamRemoveImages(); } void CPlayerSkin::Initialise(void) { m_txdSlot = CTxdStore::AddTxdSlot("skin"); CTxdStore::Create(m_txdSlot); CTxdStore::AddRef(m_txdSlot); } void CPlayerSkin::Shutdown(void) { CTxdStore::RemoveTxdSlot(m_txdSlot); } RwTexture * CPlayerSkin::GetSkinTexture(const char *texName) { RwTexture *tex; RwRaster *raster; int32 width, height, depth, format; CTxdStore::PushCurrentTxd(); CTxdStore::SetCurrentTxd(m_txdSlot); tex = RwTextureRead(texName, NULL); CTxdStore::PopCurrentTxd(); if (tex != nil) return tex; if (strcmp(DEFAULT_SKIN_NAME, texName) == 0) sprintf(gString, "models\\generic\\player.bmp"); else sprintf(gString, "skins\\%s.bmp", texName); if (RwImage *image = RtBMPImageRead(gString)) { RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format); raster = RwRasterCreate(width, height, depth, format); RwRasterSetFromImage(raster, image); tex = RwTextureCreate(raster); RwTextureSetName(tex, texName); #ifdef FIX_BUGS RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC #endif RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex); RwImageDestroy(image); } return tex; } void CPlayerSkin::BeginFrontendSkinEdit(void) { LoadPlayerDff(); RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); CWorld::Players[0].LoadPlayerSkin(); gOldFov = CDraw::GetFOV(); CDraw::SetFOV(30.0f); } void CPlayerSkin::EndFrontendSkinEdit(void) { RpClumpDestroy(gpPlayerClump); gpPlayerClump = NULL; CDraw::SetFOV(gOldFov); } void CPlayerSkin::RenderFrontendSkinEdit(void) { static float rotation = 0.0f; RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f }; const RwV3d pos = { 1.35f, 0.35f, 7.725f }; const RwV3d axis1 = { 1.0f, 0.0f, 0.0f }; const RwV3d axis2 = { 0.0f, 0.0f, 1.0f }; static uint32 LastFlash = 0; RwFrame *frame = RpClumpGetFrame(gpPlayerClump); if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) { rotation += 2.0f; if (rotation > 360.0f) rotation -= 360.0f; LastFlash = CTimer::GetTimeInMillisecondsPauseMode(); } RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE); RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT); RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT); RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT); RwFrameUpdateObjects(frame); SetAmbientColours(&AmbientColor); RpClumpRender(gpPlayerClump); }