refactored to use templated predicates for RW callbacks

This commit is contained in:
Silent 2017-03-27 21:17:43 +02:00
parent d1db161070
commit a5c0dd54eb
13 changed files with 232 additions and 283 deletions

View file

@ -31,10 +31,8 @@ static void ResetEditableMaterials(std::pair<void*,int>* pData)
*static_cast<int*>(i->first) = i->second; *static_cast<int*>(i->first) = i->second;
} }
RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData) RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic)
{ {
UNREFERENCED_PARAMETER(pData);
if ( RpAtomicGetFlags(pAtomic) & rpATOMICRENDER ) if ( RpAtomicGetFlags(pAtomic) & rpATOMICRENDER )
{ {
RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic); RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic);
@ -106,7 +104,7 @@ RwCamera* CShadowCamera::Update(CEntity* pEntity)
if ( pEntity->nType == 3 ) if ( pEntity->nType == 3 )
static_cast<CPed*>(pEntity)->RenderForShadow(); static_cast<CPed*>(pEntity)->RenderForShadow();
else else
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(pEntity->m_pRwObject), ShadowCameraRenderCB, nullptr); RpClumpForAllAtomics(reinterpret_cast<RpClump*>(pEntity->m_pRwObject), ShadowCameraRenderCB);
} }
InvertRaster(); InvertRaster();

View file

@ -32,17 +32,17 @@ public:
friend constexpr CRGBA Blend(const CRGBA& From, const CRGBA& To, double BlendVal) friend constexpr CRGBA Blend(const CRGBA& From, const CRGBA& To, double BlendVal)
{ double InvBlendVal = 1.0 - BlendVal; { double InvBlendVal = 1.0 - BlendVal;
return CRGBA( To.r * BlendVal + From.r * InvBlendVal, return CRGBA( uint8_t(To.r * BlendVal + From.r * InvBlendVal),
To.g * BlendVal + From.g * InvBlendVal, uint8_t(To.g * BlendVal + From.g * InvBlendVal),
To.b * BlendVal + From.b * InvBlendVal, uint8_t(To.b * BlendVal + From.b * InvBlendVal),
To.a * BlendVal + From.a * InvBlendVal); } uint8_t(To.a * BlendVal + From.a * InvBlendVal)); }
friend constexpr CRGBA BlendSqr(const CRGBA& From, const CRGBA& To, double BlendVal) friend constexpr CRGBA BlendSqr(const CRGBA& From, const CRGBA& To, double BlendVal)
{ double InvBlendVal = 1.0 - BlendVal; { double InvBlendVal = 1.0 - BlendVal;
return CRGBA( sqrt((To.r * To.r) * BlendVal + (From.r * From.r) * InvBlendVal), return CRGBA( uint8_t(sqrt((To.r * To.r) * BlendVal + (From.r * From.r) * InvBlendVal)),
sqrt((To.g * To.g) * BlendVal + (From.g * From.g) * InvBlendVal), uint8_t(sqrt((To.g * To.g) * BlendVal + (From.g * From.g) * InvBlendVal)),
sqrt((To.b * To.b) * BlendVal + (From.b * From.b) * InvBlendVal), uint8_t(sqrt((To.b * To.b) * BlendVal + (From.b * From.b) * InvBlendVal)),
sqrt((To.a * To.a) * BlendVal + (From.a * From.a) * InvBlendVal)); } uint8_t(sqrt((To.a * To.a) * BlendVal + (From.a * From.a) * InvBlendVal))); }
// SilentPatch // SilentPatch
CRGBA* BlendGangColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a); CRGBA* BlendGangColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
@ -587,7 +587,7 @@ public:
}; };
RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData); RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic);
static_assert(sizeof(CEntity) == 0x38, "Wrong size: CEntity"); static_assert(sizeof(CEntity) == 0x38, "Wrong size: CEntity");
static_assert(sizeof(CPhysical) == 0x138, "Wrong size: CPhysical"); static_assert(sizeof(CPhysical) == 0x138, "Wrong size: CPhysical");

View file

@ -17,18 +17,37 @@ void CVehicleModelInfo::Shutdown()
CBaseModelInfo::Shutdown(); CBaseModelInfo::Shutdown();
delete m_apPlateMaterials; delete m_apPlateMaterials;
m_apPlateMaterials = nullptr;
} }
void CVehicleModelInfo::FindEditableMaterialList() void CVehicleModelInfo::FindEditableMaterialList()
{ {
std::pair<CVehicleModelInfo*,int> MatsPair = std::make_pair(this, 0); int materialCount = 0;
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(pRwObject), GetEditableMaterialListCB, &MatsPair); auto GetEditableMaterialListCB = [&]( RpAtomic* atomic ) -> RpAtomic* {
RpGeometryForAllMaterials( RpAtomicGetGeometry(atomic), [&]( RpMaterial* material ) -> RpMaterial* {
if ( RwTexture* texture = RpMaterialGetTexture(material) )
{
if ( const char* texName = RwTextureGetName(texture) )
{
if ( _strnicmp(texName, "vehiclegrunge256", 16) == 0 )
{
if ( materialCount < _countof(m_apDirtMaterials) )
m_apDirtMaterials[materialCount++] = material;
}
}
}
return material;
} );
return atomic;
};
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(pRwObject), GetEditableMaterialListCB);
if ( m_pVehicleStruct->m_nNumExtras > 0 ) if ( m_pVehicleStruct->m_nNumExtras > 0 )
{ {
for ( int i = 0; i < m_pVehicleStruct->m_nNumExtras; i++ ) for ( int i = 0; i < m_pVehicleStruct->m_nNumExtras; i++ )
GetEditableMaterialListCB(m_pVehicleStruct->m_apExtras[i], &MatsPair); GetEditableMaterialListCB(m_pVehicleStruct->m_apExtras[i]);
} }
m_nPrimaryColor = -1; m_nPrimaryColor = -1;
@ -42,150 +61,61 @@ void CVehicleModelInfo::SetCarCustomPlate()
m_plateText[0] = '\0'; m_plateText[0] = '\0';
m_nPlateType = -1; m_nPlateType = -1;
m_apPlateMaterials = reinterpret_cast<RpMaterial**>(new DWORD_PTR[2*NUM_MAX_PLATES]); m_apPlateMaterials = new RpMaterial* [2*CCustomCarPlateMgr::NUM_MAX_PLATES];
for ( int i = 0; i < 2*NUM_MAX_PLATES; i++ ) for ( int i = 0; i < 2*CCustomCarPlateMgr::NUM_MAX_PLATES; i++ )
m_apPlateMaterials[i] = nullptr; m_apPlateMaterials[i] = nullptr;
CCustomCarPlateMgr::SetupClump(reinterpret_cast<RpClump*>(pRwObject), m_apPlateMaterials); CCustomCarPlateMgr::SetupClump(reinterpret_cast<RpClump*>(pRwObject), m_apPlateMaterials);
} }
RpAtomic* CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData) void CCustomCarPlateMgr::PollPlates( RpClump* clump, RpMaterial** materials )
{ {
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), GetEditableMaterialListCB, pData); RpMaterial** carplates = materials;
return pAtomic; RpMaterial** carpbacks = materials+NUM_MAX_PLATES;
}
RpMaterial* CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial* pMaterial, void* pData) int numCarplates = 0, numCarpbacks = 0;
{
if ( RpMaterialGetTexture(pMaterial) )
{
if ( !strncmp(RwTextureGetName(RpMaterialGetTexture(pMaterial)), "vehiclegrunge256", 16) )
{
std::pair<CVehicleModelInfo*,int>* pMats = static_cast<std::pair<CVehicleModelInfo*,int>*>(pData);
if ( pMats->second < 32 ) RpClumpForAllAtomics( clump, [carplates, carpbacks, &numCarplates, &numCarpbacks] ( RpAtomic* atomic ) -> RpAtomic* {
pMats->first->m_apDirtMaterials[pMats->second++] = pMaterial; RpGeometryForAllMaterials( RpAtomicGetGeometry(atomic), [&] ( RpMaterial* material ) -> RpMaterial* {
} if ( RwTexture* texture = RpMaterialGetTexture(material) )
}
return pMaterial;
}
// TODO: FIX IT
typedef std::tuple<RpMaterial**, RpMaterial**, int, int> PlateDataTuple;
static RpMaterial* PollPlateData(RpMaterial* pMaterial, void* pData)
{
if ( RwTexture* pTexture = RpMaterialGetTexture(pMaterial) )
{
const char* pTexName = RwTextureGetName(pTexture);
if ( pTexName )
{
if ( !_strnicmp(pTexName, "carplate", 8) )
{ {
auto& pCallbackData = *static_cast<PlateDataTuple*>(pData); if ( const char* texName = RwTextureGetName(texture) )
assert(std::get<2>(pCallbackData) < NUM_MAX_PLATES);
if ( std::get<2>(pCallbackData) < NUM_MAX_PLATES )
{ {
// Append data if ( _strnicmp( texName, "carplate", 8 ) == 0 )
for ( auto ptr = std::get<0>(pCallbackData); *ptr; ptr++ )
{ {
if ( *ptr == pMaterial ) assert(numCarplates < NUM_MAX_PLATES);
return pMaterial; if ( numCarplates < NUM_MAX_PLATES );
{
carplates[numCarplates++] = material;
}
}
else if ( _strnicmp( texName, "carpback", 8 ) == 0 )
{
assert(numCarpbacks < NUM_MAX_PLATES);
if ( numCarpbacks < NUM_MAX_PLATES );
{
carpbacks[numCarpbacks++] = material;
}
} }
while ( std::get<0>(pCallbackData)[std::get<2>(pCallbackData)] )
std::get<2>(pCallbackData)++;
std::get<0>(pCallbackData)[std::get<2>(pCallbackData)++] = pMaterial;
} }
} }
else if ( !_strnicmp(pTexName, "carpback", 8) )
{
auto& pCallbackData = *static_cast<PlateDataTuple*>(pData);
assert(std::get<3>(pCallbackData) < NUM_MAX_PLATES); return material;
if ( std::get<3>(pCallbackData) < NUM_MAX_PLATES ) } );
{ return atomic;
// Append data } );
for ( auto ptr = std::get<0>(pCallbackData); *ptr; ptr++ )
{
if ( *ptr == pMaterial )
return pMaterial;
}
while ( std::get<1>(pCallbackData)[std::get<3>(pCallbackData)] )
std::get<3>(pCallbackData)++;
std::get<1>(pCallbackData)[std::get<3>(pCallbackData)] = pMaterial;
}
}
}
}
return pMaterial;
}
static RpAtomic* PollPlateData(RpAtomic* pAtomic, void* pData)
{
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), PollPlateData, pData);
return pAtomic;
}
static RpMaterial* SetPlateData(RpMaterial* pMaterial, void* pData)
{
if ( RwTexture* pTexture = RpMaterialGetTexture(pMaterial) )
{
if ( RwTextureGetName(pTexture) )
{
if ( !_strnicmp(RwTextureGetName(pTexture), "carplate", 8) )
{
auto& pCallbackData = *static_cast<std::pair<RwTexture*,signed char>*>(pData);
RpMaterialSetTexture(pMaterial, pCallbackData.first);
}
else if ( !_strnicmp(RwTextureGetName(pTexture), "carpback", 8) )
{
auto& pCallbackData = *static_cast<std::pair<RwTexture*,signed char>*>(pData);
CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pMaterial, pCallbackData.second);
}
}
}
return pMaterial;
}
static RpAtomic* SetPlateData(RpAtomic* pAtomic, void* pData)
{
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), SetPlateData, pData);
return pAtomic;
} }
void CCustomCarPlateMgr::SetupClump(RpClump* pClump, RpMaterial** pMatsArray) void CCustomCarPlateMgr::SetupClump(RpClump* pClump, RpMaterial** pMatsArray)
{ {
// Split pMatsArray PollPlates( pClump, pMatsArray );
PlateDataTuple CallbackData = std::make_tuple(pMatsArray, pMatsArray+NUM_MAX_PLATES, 0, 0);
RpClumpForAllAtomics(pClump, PollPlateData, &CallbackData);
} }
void CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade(RpClump* pClump, RpMaterial** pMatsArray, signed char nDesign) void CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade(RpClump* pClump, RpMaterial** pMatsArray, signed char nDesign)
{ {
UNREFERENCED_PARAMETER(nDesign); UNREFERENCED_PARAMETER(nDesign);
if ( pMatsArray ) if ( pMatsArray != nullptr )
{ {
// Split pMatsArray PollPlates( pClump, pMatsArray );
PlateDataTuple CallbackData = std::make_tuple(pMatsArray, pMatsArray+NUM_MAX_PLATES, 0, 0);
RpClumpForAllAtomics(pClump, PollPlateData, &CallbackData);
} }
}
void CCustomCarPlateMgr::SetupPlates(RpClump* pClump, RwTexture* pTexture, signed char nDesign)
{
std::pair<RwTexture*,signed char> CallbackData = std::make_pair(pTexture, nDesign);
RpClumpForAllAtomics(pClump, SetPlateData, &CallbackData);
} }

View file

@ -292,25 +292,17 @@ public:
void FindEditableMaterialList(); void FindEditableMaterialList();
void SetCarCustomPlate(); void SetCarCustomPlate();
static RpAtomic* GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData);
static RpMaterial* GetEditableMaterialListCB(RpMaterial* pMaterial, void* pData);
}; };
extern CBaseModelInfo** const ms_modelInfoPtrs; extern CBaseModelInfo** const ms_modelInfoPtrs;
extern const uint32_t m_numModelInfoPtrs; extern const uint32_t m_numModelInfoPtrs;
#define NUM_MAX_PLATES 12
class CCustomCarPlateMgr class CCustomCarPlateMgr
{ {
// Pretty much rewritten for SilentPatch // Pretty much rewritten for SilentPatch
private:
//static RpMaterial** m_pMaterialsWeWorkingWith;
//static unsigned char m_nCurPlateMaterial, m_nCurPlateBackMaterial;
//static signed char m_nCurPlateDesign;
public: public:
static const size_t NUM_MAX_PLATES = 12;
static RwTexture* (*CreatePlateTexture)(const char* pText, signed char nDesign); static RwTexture* (*CreatePlateTexture)(const char* pText, signed char nDesign);
static bool (*GeneratePlateText)(char* pBuf, int nLen); static bool (*GeneratePlateText)(char* pBuf, int nLen);
static signed char (*GetMapRegionPlateDesign)(); static signed char (*GetMapRegionPlateDesign)();
@ -319,7 +311,8 @@ public:
static void SetupClump(RpClump* pClump, RpMaterial** pMatsArray); static void SetupClump(RpClump* pClump, RpMaterial** pMatsArray);
static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, RpMaterial** pMatsArray, signed char nDesign); static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, RpMaterial** pMatsArray, signed char nDesign);
static void SetupPlates(RpClump* pClump, RwTexture* pTexture, signed char nDesign); private:
static void PollPlates( RpClump* clump, RpMaterial** materials );
}; };
static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo"); static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo");

View file

@ -14,16 +14,13 @@ WRAPPER CTaskSimpleJetPack* CPedIntelligence::GetTaskJetPack() const { VARJMP(va
static void* varRenderJetPack = AddressByVersion<void*>(0x67F6A0, 0x67FEC0, 0x6AB110); static void* varRenderJetPack = AddressByVersion<void*>(0x67F6A0, 0x67FEC0, 0x6AB110);
WRAPPER void CTaskSimpleJetPack::RenderJetPack(CPed* pPed) { WRAPARG(pPed); VARJMP(varRenderJetPack); } WRAPPER void CTaskSimpleJetPack::RenderJetPack(CPed* pPed) { WRAPARG(pPed); VARJMP(varRenderJetPack); }
static RwObject* GetFirstObjectCallback(RwObject* pObject, void* pData)
{
*static_cast<RwObject**>(pData) = pObject;
return nullptr;
}
RwObject* GetFirstObject(RwFrame* pFrame) RwObject* GetFirstObject(RwFrame* pFrame)
{ {
RwObject* pObject = nullptr; RwObject* pObject = nullptr;
RwFrameForAllObjects(pFrame, GetFirstObjectCallback, &pObject); RwFrameForAllObjects( pFrame, [&pObject]( RwObject* object ) -> RwObject* {
pObject = object;
return nullptr;
} );
return pObject; return pObject;
} }
@ -47,13 +44,14 @@ void CPed::RenderWeapon(bool bMuzzleFlash, bool bForShadow)
RwFrameUpdateObjects(pFrame); RwFrameUpdateObjects(pFrame);
if ( bForShadow ) if ( bForShadow )
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pWeaponObject), ShadowCameraRenderCB, nullptr); RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pWeaponObject), ShadowCameraRenderCB);
else if ( !bMuzzleFlash ) else if ( !bMuzzleFlash )
RpClumpRender(reinterpret_cast<RpClump*>(m_pWeaponObject)); RpClumpRender(reinterpret_cast<RpClump*>(m_pWeaponObject));
else if ( m_pMuzzleFlashFrame ) else if ( m_pMuzzleFlashFrame )
{ {
SetGunFlashAlpha(false); SetGunFlashAlpha(false);
RpAtomicRender(reinterpret_cast<RpAtomic*>(GetFirstObject(m_pMuzzleFlashFrame))); RpAtomic* atomic = reinterpret_cast<RpAtomic*>(GetFirstObject(m_pMuzzleFlashFrame));
RpAtomicRender( atomic );
} }
// Dual weapons // Dual weapons
@ -68,13 +66,14 @@ void CPed::RenderWeapon(bool bMuzzleFlash, bool bForShadow)
RwFrameUpdateObjects(pFrame); RwFrameUpdateObjects(pFrame);
if ( bForShadow ) if ( bForShadow )
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pWeaponObject), ShadowCameraRenderCB, nullptr); RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pWeaponObject), ShadowCameraRenderCB);
else if ( !bMuzzleFlash ) else if ( !bMuzzleFlash )
RpClumpRender(reinterpret_cast<RpClump*>(m_pWeaponObject)); RpClumpRender(reinterpret_cast<RpClump*>(m_pWeaponObject));
else if ( m_pMuzzleFlashFrame ) else if ( m_pMuzzleFlashFrame )
{ {
SetGunFlashAlpha(true); SetGunFlashAlpha(true);
RpAtomicRender(reinterpret_cast<RpAtomic*>(GetFirstObject(m_pMuzzleFlashFrame))); RpAtomic* atomic = reinterpret_cast<RpAtomic*>(GetFirstObject(m_pMuzzleFlashFrame));
RpAtomicRender( atomic );
} }
} }
if ( bMuzzleFlash ) if ( bMuzzleFlash )
@ -84,7 +83,7 @@ void CPed::RenderWeapon(bool bMuzzleFlash, bool bForShadow)
void CPed::RenderForShadow() void CPed::RenderForShadow()
{ {
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pRwObject), ShadowCameraRenderCB, nullptr); RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pRwObject), ShadowCameraRenderCB);
RenderWeapon(false, true); RenderWeapon(false, true);
// Render jetpack // Render jetpack

View file

@ -261,23 +261,28 @@ static struct
// Regular functions // Regular functions
static RpMaterial* AlphaTest(RpMaterial* pMaterial, void* pData) static bool AtomicAlphaTest( RpAtomic* atomic )
{ {
if ( RpMaterialGetTexture(pMaterial) ) bool hasAlpha = false;
{ RpGeometryForAllMaterials( RpAtomicGetGeometry(atomic), [&hasAlpha]( RpMaterial* material ) -> RpMaterial* {
if ( __rwD3D9TextureHasAlpha(RpMaterialGetTexture(pMaterial)) ) if ( RpMaterialGetTexture(material) != nullptr )
{ {
*static_cast<BOOL*>(pData) = TRUE; if ( __rwD3D9TextureHasAlpha(RpMaterialGetTexture(material)) )
{
hasAlpha = true;
return nullptr;
}
}
else if ( RpMaterialGetColor(material)->alpha < 255 )
{
hasAlpha = true;
return nullptr; return nullptr;
} }
}
else if ( RpMaterialGetColor(pMaterial)->alpha < 255 )
{
*static_cast<BOOL*>(pData) = TRUE;
return nullptr;
}
return pMaterial; return material;
} );
return hasAlpha;
} }
static RpAtomic* RenderAtomic(RpAtomic* pAtomic, float fComp) static RpAtomic* RenderAtomic(RpAtomic* pAtomic, float fComp)
@ -422,10 +427,7 @@ void RenderVehicleHiDetailAlphaCB_HunterDoor(RpAtomic* pAtomic)
template <RpAtomic* renderer(RpAtomic*)> template <RpAtomic* renderer(RpAtomic*)>
void SetRendererForAtomic(RpAtomic* pAtomic) void SetRendererForAtomic(RpAtomic* pAtomic)
{ {
BOOL bHasAlpha = FALSE; if ( AtomicAlphaTest( pAtomic ) )
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), AlphaTest, &bHasAlpha);
if ( bHasAlpha )
RpAtomicSetRenderCallBack(pAtomic, renderer); RpAtomicSetRenderCallBack(pAtomic, renderer);
} }
@ -487,10 +489,7 @@ void RenderWeaponPedsForPC()
template <RpAtomic* renderer(RpAtomic*)> template <RpAtomic* renderer(RpAtomic*)>
RpAtomic* RenderPedCB(RpAtomic* pAtomic) RpAtomic* RenderPedCB(RpAtomic* pAtomic)
{ {
BOOL bHasAlpha = FALSE; if ( AtomicAlphaTest( pAtomic ) )
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), AlphaTest, &bHasAlpha);
if ( bHasAlpha )
return renderer(pAtomic); return renderer(pAtomic);
return AtomicDefaultRenderCallBack(pAtomic); return AtomicDefaultRenderCallBack(pAtomic);

View file

@ -174,6 +174,7 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio
<ClInclude Include="PedSA.h" /> <ClInclude Include="PedSA.h" />
<ClInclude Include="PNGFile.h" /> <ClInclude Include="PNGFile.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="rwpred.hpp" />
<ClInclude Include="ScriptSA.h" /> <ClInclude Include="ScriptSA.h" />
<ClInclude Include="StdAfxSA.h" /> <ClInclude Include="StdAfxSA.h" />
<ClInclude Include="TimerSA.h" /> <ClInclude Include="TimerSA.h" />

View file

@ -140,6 +140,9 @@
<ClInclude Include="..\SilentPatch\DelimStringReader.h"> <ClInclude Include="..\SilentPatch\DelimStringReader.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="rwpred.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="Shaders.rc"> <ResourceCompile Include="Shaders.rc">

View file

@ -25,6 +25,7 @@
#include "MemoryMgr.h" #include "MemoryMgr.h"
#include "Maths.h" #include "Maths.h"
#include "rwpred.hpp"
// SA operator delete // SA operator delete
extern void (*GTAdelete)(void* data); extern void (*GTAdelete)(void* data);

View file

@ -1,5 +1,6 @@
#include "StdAfxSA.h" #include "StdAfxSA.h"
#include <functional>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include "VehicleSA.h" #include "VehicleSA.h"
@ -23,35 +24,50 @@ static int32_t random(int32_t from, int32_t to)
return from + ( Int32Rand() % (to-from) ); return from + ( Int32Rand() % (to-from) );
} }
static RwObject* GetCurrentAtomicObjectCB(RwObject* pObject, void* data) static RwObject* GetCurrentAtomicObject( RwFrame* frame )
{ {
if ( RpAtomicGetFlags(pObject) & rpATOMICRENDER ) RwObject* obj = nullptr;
{ RwFrameForAllObjects( frame, [&obj]( RwObject* object ) -> RwObject* {
*static_cast<RwObject**>(data) = pObject; if ( RpAtomicGetFlags(object) & rpATOMICRENDER )
return nullptr; {
} obj = object;
return pObject; return nullptr;
}
return object;
} );
return obj;
} }
static RwFrame* GetFrameFromNameCB(RwFrame* pFrame, void* pData) static RwFrame* GetFrameFromName( RwFrame* topFrame, const char* name )
{ {
// Is this a frame we want? class GetFramePredicate
std::pair<const char*,RwFrame*>* pFindData = static_cast<std::pair<const char*,RwFrame*>*>(pData);
if ( !strcmp(pFindData->first, GetFrameNodeName(pFrame)) )
{ {
pFindData->second = pFrame; public:
return nullptr; RwFrame* foundFrame = nullptr;
}
// Try children GetFramePredicate( const char* name )
RwFrameForAllChildren(pFrame, GetFrameFromNameCB, pData); : m_name( name )
return !pFindData->second ? pFrame : nullptr; {
} }
static RpMaterial* SetCompAlphaCB(RpMaterial* pMaterial, void* data) RwFrame* operator() ( RwFrame* frame )
{ {
pMaterial->color.alpha = reinterpret_cast<RwUInt8>(data); if ( strcmp( m_name, GetFrameNodeName(frame) ) == 0 )
return pMaterial; {
foundFrame = frame;
return nullptr;
}
RwFrameForAllChildren( frame, std::ref(*this) );
return foundFrame != nullptr ? nullptr : frame;
}
private:
const char* const m_name;
};
GetFramePredicate p( name );
RwFrameForAllChildren( topFrame, std::ref(p) );
return p.foundFrame;
} }
void ReadRotorFixExceptions(const wchar_t* pPath) void ReadRotorFixExceptions(const wchar_t* pPath)
@ -73,7 +89,10 @@ void CVehicle::SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha)
RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic); RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic);
pGeometry->flags |= rpGEOMETRYMODULATEMATERIALCOLOR; pGeometry->flags |= rpGEOMETRYMODULATEMATERIALCOLOR;
RpGeometryForAllMaterials(pGeometry, SetCompAlphaCB, reinterpret_cast<void*>(nAlpha)); RpGeometryForAllMaterials( pGeometry, [nAlpha] (RpMaterial* material) {
material->color.alpha = RwUInt8(nAlpha);
return material;
} );
} }
bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo) bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
@ -93,7 +112,7 @@ bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
else if ( IsLawEnforcementVehicle() ) else if ( IsLawEnforcementVehicle() )
PlateDesign = CCustomCarPlateMgr::GetMapRegionPlateDesign(); PlateDesign = CCustomCarPlateMgr::GetMapRegionPlateDesign();
else else
PlateDesign = random(0, 20) == 0 ? random(0, 3) : CCustomCarPlateMgr::GetMapRegionPlateDesign(); PlateDesign = random(0, 20) == 0 ? int8_t(random(0, 3)) : CCustomCarPlateMgr::GetMapRegionPlateDesign();
assert(PlateDesign >= 0 && PlateDesign < 3); assert(PlateDesign >= 0 && PlateDesign < 3);
@ -103,53 +122,21 @@ bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
return true; return true;
} }
//static RwTexture* pPushedTextures[NUM_MAX_PLATES];
void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo) void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo)
{ {
//CCustomCarPlateMgr::SetupPlates(reinterpret_cast<RpClump*>(pModelInfo->pRwObject), PlateTexture, PlateDesign); for ( ptrdiff_t i = 0; i < CCustomCarPlateMgr::NUM_MAX_PLATES; i++ )
for ( ptrdiff_t i = 0; i < NUM_MAX_PLATES; i++ )
{ {
if ( pModelInfo->m_apPlateMaterials[i] ) if ( pModelInfo->m_apPlateMaterials[i] != nullptr )
{ {
//RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]);
//RwTextureAddRef(pPlateTex);
//pPushedTextures[i] = pPlateTex;
RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture); RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture);
} }
if ( pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i] ) if ( pModelInfo->m_apPlateMaterials[CCustomCarPlateMgr::NUM_MAX_PLATES+i] != nullptr )
CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i], PlateDesign);
//RwTexture* pPlatebackTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[4+i]);
//RwTextureAddRef(pPlatebackTex);
//pPushedTextures[4+i] = pPlateTex;
//RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture);
}
}
// This is not needed
/*void CVehicle::CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo)
{
for ( int i = 0; i < NUM_MAX_PLATES; i++ )
{
if ( pModelInfo->m_apPlateMaterials[i] )
{ {
//RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]); CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials[CCustomCarPlateMgr::NUM_MAX_PLATES+i], PlateDesign);
//RwTextureAddRef(pPlateTex);
//pPushedTextures[i] = pPlateTex;
//RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], pPushedTextures[i]);
//RwTextureDestroy(pPushedTextures[i]);
//pPushedTextures[i] = nullptr;
} }
} }
}
}*/
void CHeli::Render() void CHeli::Render()
{ {
@ -172,35 +159,31 @@ void CHeli::Render()
int nStaticRotorAlpha = static_cast<int>(std::min((1.5-dRotorsSpeed) * 255.0, 255.0)); int nStaticRotorAlpha = static_cast<int>(std::min((1.5-dRotorsSpeed) * 255.0, 255.0));
int nMovingRotorAlpha = static_cast<int>(std::min(dMovingRotorSpeed * 175.0, 175.0)); int nMovingRotorAlpha = static_cast<int>(std::min(dMovingRotorSpeed * 175.0, 175.0));
if ( m_pCarNode[12] ) if ( m_pCarNode[12] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[12] );
RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor ? nStaticRotorAlpha : 255); SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor ? nStaticRotorAlpha : 255);
} }
if ( m_pCarNode[14] ) if ( m_pCarNode[14] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[14] );
RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor2 ? nStaticRotorAlpha : 255); SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor2 ? nStaticRotorAlpha : 255);
} }
if ( m_pCarNode[13] ) if ( m_pCarNode[13] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[13] );
RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor ? nMovingRotorAlpha : 0); SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor ? nMovingRotorAlpha : 0);
} }
if ( m_pCarNode[15] ) if ( m_pCarNode[15] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[15] );
RwFrameForAllObjects(m_pCarNode[15], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor2 ? nMovingRotorAlpha : 0); SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor2 ? nMovingRotorAlpha : 0);
} }
@ -228,35 +211,31 @@ void CPlane::Render()
int nStaticRotorAlpha = static_cast<int>(std::min((1.5-dRotorsSpeed) * 255.0, 255.0)); int nStaticRotorAlpha = static_cast<int>(std::min((1.5-dRotorsSpeed) * 255.0, 255.0));
int nMovingRotorAlpha = static_cast<int>(std::min(dMovingRotorSpeed * 175.0, 175.0)); int nMovingRotorAlpha = static_cast<int>(std::min(dMovingRotorSpeed * 175.0, 175.0));
if ( m_pCarNode[12] ) if ( m_pCarNode[12] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[12] );
RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp ? nStaticRotorAlpha : 255); SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp ? nStaticRotorAlpha : 255);
} }
if ( m_pCarNode[14] ) if ( m_pCarNode[14] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[14] );
RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp2 ? nStaticRotorAlpha : 255); SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp2 ? nStaticRotorAlpha : 255);
} }
if ( m_pCarNode[13] ) if ( m_pCarNode[13] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[13] );
RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp ? nMovingRotorAlpha : 0); SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp ? nMovingRotorAlpha : 0);
} }
if ( m_pCarNode[15] ) if ( m_pCarNode[15] != nullptr )
{ {
RpAtomic* pOutAtomic = nullptr; RpAtomic* pOutAtomic = (RpAtomic*)GetCurrentAtomicObject( m_pCarNode[15] );
RwFrameForAllObjects(m_pCarNode[15], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic != nullptr )
if ( pOutAtomic )
SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp2 ? nMovingRotorAlpha : 0); SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp2 ? nMovingRotorAlpha : 0);
} }
@ -288,22 +267,19 @@ void CAutomobile::Fix_SilentPatch()
void CAutomobile::ResetFrames() void CAutomobile::ResetFrames()
{ {
RpClump* pOrigClump = reinterpret_cast<RpClump*>(ms_modelInfoPtrs[m_nModelIndex]->pRwObject); RpClump* pOrigClump = reinterpret_cast<RpClump*>(ms_modelInfoPtrs[m_nModelIndex]->pRwObject);
if ( pOrigClump ) if ( pOrigClump != nullptr )
{ {
// Instead of setting frame rotation to (0,0,0) like R* did, obtain the original frame matrix from CBaseNodelInfo clump // Instead of setting frame rotation to (0,0,0) like R* did, obtain the original frame matrix from CBaseNodelInfo clump
for ( ptrdiff_t i = 8; i < 25; i++ ) for ( ptrdiff_t i = 8; i < 25; i++ )
{ {
if ( m_pCarNode[i] ) if ( m_pCarNode[i] != nullptr )
{ {
// Find a frame in CBaseModelInfo object // Find a frame in CBaseModelInfo object
std::pair<const char*,RwFrame*> FindData = std::make_pair(GetFrameNodeName(m_pCarNode[i]), nullptr); RwFrame* origFrame = GetFrameFromName( RpClumpGetFrame(pOrigClump), GetFrameNodeName(m_pCarNode[i]) );
if ( origFrame != nullptr )
RwFrameForAllChildren(RpClumpGetFrame(pOrigClump), GetFrameFromNameCB, &FindData);
if ( FindData.second )
{ {
// Found a frame, reset it // Found a frame, reset it
*RwFrameGetMatrix(m_pCarNode[i]) = *RwFrameGetMatrix(FindData.second); *RwFrameGetMatrix(m_pCarNode[i]) = *RwFrameGetMatrix(origFrame);
RwMatrixUpdate(RwFrameGetMatrix(m_pCarNode[i])); RwMatrixUpdate(RwFrameGetMatrix(m_pCarNode[i]));
} }
} }

View file

@ -123,7 +123,7 @@ protected:
CEntity* pDamagingEntity; CEntity* pDamagingEntity;
BYTE __pad3[116]; BYTE __pad3[116];
char padpad, padpad2, padpad3; char padpad, padpad2, padpad3;
signed char PlateDesign; int8_t PlateDesign;
RwTexture* PlateTexture; RwTexture* PlateTexture;
BYTE __pad5[20]; BYTE __pad5[20];

49
SilentPatchSA/rwpred.hpp Normal file
View file

@ -0,0 +1,49 @@
#pragma once
#include <rwcore.h>
#include <rpworld.h>
template <typename Pred>
RwFrame* RwFrameForAllChildren(RwFrame* frame, Pred callback)
{
for ( RwFrame* curFrame = frame->child; curFrame != nullptr; curFrame = curFrame->next )
{
if ( callback(curFrame) == nullptr )
break;
}
return frame;
}
template <typename Pred>
RwFrame* RwFrameForAllObjects(RwFrame* frame, Pred callback)
{
for ( RwLLLink* link = rwLinkListGetFirstLLLink(&frame->objectList); link != rwLinkListGetTerminator(&frame->objectList); link = rwLLLinkGetNext(link) )
{
if ( callback(&rwLLLinkGetData(link, RwObjectHasFrame, lFrame)->object) == nullptr )
break;
}
return frame;
}
template <typename Pred>
RpClump* RpClumpForAllAtomics(RpClump* clump, Pred callback)
{
for ( RwLLLink* link = rwLinkListGetFirstLLLink(&clump->atomicList); link != rwLinkListGetTerminator(&clump->atomicList); link = rwLLLinkGetNext(link) )
{
if ( callback(rwLLLinkGetData(link, RpAtomic, inClumpLink)) == nullptr )
break;
}
return clump;
}
template <typename Pred>
RpGeometry* RpGeometryForAllMaterials(RpGeometry* geometry, Pred callback)
{
for ( RwInt32 i = 0, j = geometry->matList.numMaterials; i < j; i++ )
{
if ( callback(geometry->matList.materials[i]) == nullptr )
break;
}
return geometry;
}

View file

@ -5,8 +5,8 @@
<SILENTPATCH_NAME>SilentPatchSA</SILENTPATCH_NAME> <SILENTPATCH_NAME>SilentPatchSA</SILENTPATCH_NAME>
<SILENTPATCH_EXT>.asi</SILENTPATCH_EXT> <SILENTPATCH_EXT>.asi</SILENTPATCH_EXT>
<SILENTPATCH_FULL_NAME>SilentPatch for San Andreas</SILENTPATCH_FULL_NAME> <SILENTPATCH_FULL_NAME>SilentPatch for San Andreas</SILENTPATCH_FULL_NAME>
<SILENTPATCH_REVISION_ID>28</SILENTPATCH_REVISION_ID> <SILENTPATCH_REVISION_ID>29</SILENTPATCH_REVISION_ID>
<SILENTPATCH_BUILD_ID>5</SILENTPATCH_BUILD_ID> <SILENTPATCH_BUILD_ID>0</SILENTPATCH_BUILD_ID>
<SILENTPATCH_COPYRIGHT>2014-2017</SILENTPATCH_COPYRIGHT> <SILENTPATCH_COPYRIGHT>2014-2017</SILENTPATCH_COPYRIGHT>
</PropertyGroup> </PropertyGroup>
<PropertyGroup /> <PropertyGroup />