player and ground cover

This commit is contained in:
marauder2k7 2025-06-19 14:10:00 +01:00
parent c6ec2fd6a1
commit 5d641929cf
5 changed files with 95 additions and 39 deletions

View file

@ -678,6 +678,64 @@ public:
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
StringTableEntry get##name##File(const U32& idx) { return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->getShapePath() : ""; }
#define DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(className, name, max, mask) \
private: \
AssetPtr<ShapeAsset> m##name##Asset[max]; \
StringTableEntry m##name##File[max] = {StringTable->EmptyString() }; \
public: \
void _set##name(StringTableEntry _in, const U32& index){ \
if (m##name##Asset[index].getAssetId() == _in) \
return; \
if(get##name##File(index) == _in) \
return; \
if (_in == NULL || _in == StringTable->EmptyString()) \
{ \
m##name##Asset[index] = NULL; \
m##name##File[index] = ""; \
setMaskBits(mask); \
return; \
} \
if (!AssetDatabase.isDeclaredAsset(_in)) \
{ \
StringTableEntry shapeAssetId = StringTable->EmptyString(); \
AssetQuery query; \
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); \
if (foundAssetcount != 0) \
{ \
shapeAssetId = query.mAssetList[0]; \
} \
else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) \
{ \
shapeAssetId = ShapeAsset::getAssetIdByFilename(_in); \
if (shapeAssetId == ShapeAsset::smNoShapeAssetFallback) \
{ \
ShapeAsset* privateShape = new ShapeAsset(); \
privateShape->setShapeFile(_in); \
shapeAssetId = AssetDatabase.addPrivateAsset(privateShape); \
} \
} \
else \
{ \
Con::warnf("%s::%s: Could not find asset for: %s using fallback", #className, #name, _in); \
shapeAssetId = ShapeAsset::smNoShapeAssetFallback; \
} \
m##name##Asset[index] = shapeAssetId; \
m##name##File[index] = _in; \
} \
else \
{ \
m##name##Asset[index] = _in; \
m##name##File[index] = get##name##File(index); \
} \
setMaskBits(mask); \
}; \
\
inline StringTableEntry _get##name##AssetId(const U32& index) const { return m##name##Asset[index].getAssetId(); } \
Resource<TSShape> get##name(const U32& index) { if (m##name##Asset[index].notNull()) return m##name##Asset[index]->getShapeResource(); else return NULL; } \
AssetPtr<ShapeAsset> get##name##Asset(const U32& index) { return m##name##Asset[index]; } \
static bool _set##name##Data(void* obj, const char* index, const char* data) { static_cast<className*>(obj)->_set##name(_getStringTable()->insert(data), dAtoi(index)); return false;}\
StringTableEntry get##name##File(const U32& idx) { return m##name##Asset[idx].notNull() ? m##name##Asset[idx]->getShapePath() : ""; }
#define INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(name, arraySize, consoleClass, docs) \
addProtectedField(assetText(name, Asset), TypeShapeAssetPtrRefactor, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));\
addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, arraySize, assetDoc(name, asset docs.));

View file

@ -521,7 +521,7 @@ GroundCover::GroundCover()
mBillboardRects[i].point.set( 0.0f, 0.0f );
mBillboardRects[i].extent.set( 1.0f, 1.0f );
INIT_ASSET_ARRAY(Shape, i);
mShapeAsset[i].registerRefreshNotify(this);
mShapeInstances[i] = NULL;
@ -563,8 +563,7 @@ void GroundCover::initPersistFields()
addField( "billboardUVs", TypeRectUV, Offset( mBillboardRects, GroundCover ), MAX_COVERTYPES, "Subset material UV coordinates for this cover billboard." );
addField("shapeFilename", TypeFilename, Offset(mShapeName, GroundCover), MAX_COVERTYPES, "The cover shape filename. [Optional]", AbstractClassRep::FIELD_HideInInspectors);
INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]");
INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]");
addField( "layer", TypeTerrainMaterialAssetId, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material assetId to limit coverage to, or blank to not limit." );
@ -767,10 +766,10 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str
stream->write( mBillboardRects[i].point.y );
stream->write( mBillboardRects[i].extent.x );
stream->write( mBillboardRects[i].extent.y );
PACK_ASSET_ARRAY(connection, Shape, i);
}
PACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
stream->writeFlag( mDebugRenderCells );
stream->writeFlag( mDebugNoBillboards );
stream->writeFlag( mDebugNoShapes );
@ -838,10 +837,10 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream )
stream->read( &mBillboardRects[i].point.y );
stream->read( &mBillboardRects[i].extent.x );
stream->read( &mBillboardRects[i].extent.y );
UNPACK_ASSET_ARRAY(connection, Shape, i);
}
UNPACK_ASSET_ARRAY_REFACTOR(connection, Shape, MAX_COVERTYPES)
mDebugRenderCells = stream->readFlag();
mDebugNoBillboards = stream->readFlag();
mDebugNoShapes = stream->readFlag();
@ -887,17 +886,17 @@ void GroundCover::_initShapes()
for ( S32 i=0; i < MAX_COVERTYPES; i++ )
{
if ( mShapeAsset[i].isNull() || mShape[i] == nullptr)
if ( mShapeAsset[i].isNull() || getShape(i) == nullptr)
continue;
if ( isClientObject() && !mShape[i]->preloadMaterialList(mShape[i].getPath()) && NetConnection::filesWereDownloaded() )
if ( isClientObject() && !getShape(i)->preloadMaterialList(getShape(i).getPath()) && NetConnection::filesWereDownloaded() )
{
Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", mShapeAssetId[i] );
Con::warnf( "GroundCover::_initShapes() material preload failed for shape: %s", _getShapeAssetId(i));
continue;
}
// Create the shape instance.
mShapeInstances[i] = new TSShapeInstance(mShape[i], isClientObject() );
mShapeInstances[i] = new TSShapeInstance(getShape(i), isClientObject() );
}
}

View file

@ -111,7 +111,7 @@ public:
};
class GroundCover : public SceneObject
class GroundCover : public SceneObject, protected AssetPtrCallback
{
friend class GroundCoverShaderConstHandles;
friend class GroundCoverCell;
@ -341,8 +341,7 @@ protected:
RectF mBillboardRects[MAX_COVERTYPES];
/// The cover shape filenames.
DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES, onShapeChanged);
DECLARE_ASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1);
DECLARE_SHAPEASSET_ARRAY_NET_REFACTOR(GroundCover, Shape, MAX_COVERTYPES, -1)
/// The cover shape instances.
TSShapeInstance* mShapeInstances[MAX_COVERTYPES];
@ -410,7 +409,8 @@ protected:
void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
void onShapeChanged()
protected:
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
{
_initShapes();
setMaskBits(U32(-1));

View file

@ -297,7 +297,7 @@ PlayerData::PlayerData()
imageAnimPrefixFP = StringTable->EmptyString();
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
{
INIT_ASSET_ARRAY(ShapeFP, i);
mShapeFPAsset[i].registerRefreshNotify(this);
mCRCFP[i] = 0;
mValidShapeFP[i] = false;
}
@ -607,26 +607,26 @@ bool PlayerData::preload(bool server, String &errorStr)
{
bool shapeError = false;
if (mShapeFPAssetId[i] != StringTable->EmptyString())
if (mShapeFPAsset[i].notNull())
{
if (!mShapeFP[i])
if (!getShapeFP(i))
{
errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, mShapeFPAssetId[i]);
errorStr = String::ToString("PlayerData: Couldn't load mounted image %d shape \"%s\"", i, _getShapeFPAssetId(i));
return false;
}
if (!server && !mShapeFP[i]->preloadMaterialList(mShapeFP[i].getPath()) && NetConnection::filesWereDownloaded())
if (!server && !getShapeFP(i)->preloadMaterialList(getShapeFP(i).getPath()) && NetConnection::filesWereDownloaded())
shapeError = true;
if (computeCRC)
{
Con::printf("Validation required for mounted image %d shape: %s", i, mShapeFPAssetId[i]);
Con::printf("Validation required for mounted image %d shape: %s", i, _getShapeFPAssetId(i));
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeFP[i].getPath());
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(getShapeFP(i).getPath());
if (!fileRef)
{
errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, mShapeFP[i].getPath().getFullPath().c_str());
errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.", i, getShapeFP(i).getPath().getFullPath().c_str());
return false;
}
@ -634,7 +634,7 @@ bool PlayerData::preload(bool server, String &errorStr)
mCRCFP[i] = fileRef->getChecksum();
else if (mCRCFP[i] != fileRef->getChecksum())
{
errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, mShapeFPAssetId[i]);
errorStr = String::ToString("PlayerData: Mounted image %d shape \"%s\" does not match version on server.", i, _getShapeFPAssetId(i));
return false;
}
}
@ -1134,13 +1134,8 @@ void PlayerData::initPersistFields()
// Mounted images arrays
addArray( "Mounted Images", ShapeBase::MaxMountedImages );
addProtectedField("shapeNameFP", TypeShapeFilename, Offset(mShapeFPName, PlayerData), &_setShapeFPData, &defaultProtectedGetFn, ShapeBase::MaxMountedImages,
"@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n"
"These optional parameters correspond to each mounted image slot to indicate a shape that is rendered "
"in addition to the mounted image shape. Typically these are a player's arms (or arm) that is "
"animated along with the mounted image's state animation sequences.\n", AbstractClassRep::FIELD_HideInInspectors);
INITPERSISTFIELD_SHAPEASSET_ARRAY(ShapeFP, ShapeBase::MaxMountedImages, PlayerData, "@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n"
INITPERSISTFIELD_SHAPEASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages, PlayerData, "@brief File name of this player's shape that will be used in conjunction with the corresponding mounted image.\n\n"
"These optional parameters correspond to each mounted image slot to indicate a shape that is rendered "
"in addition to the mounted image shape. Typically these are a player's arms (or arm) that is "
"animated along with the mounted image's state animation sequences.\n");
@ -1340,14 +1335,14 @@ void PlayerData::packData(BitStream* stream)
stream->writeString(imageAnimPrefixFP);
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
{
PACKDATA_ASSET_ARRAY(ShapeFP, i);
// computeCRC is handled in ShapeBaseData
if (computeCRC)
{
stream->write(mCRCFP[i]);
}
}
PACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages)
}
void PlayerData::unpackData(BitStream* stream)
@ -1520,14 +1515,14 @@ void PlayerData::unpackData(BitStream* stream)
imageAnimPrefixFP = stream->readSTString();
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
{
UNPACKDATA_ASSET_ARRAY(ShapeFP, i);
// computeCRC is handled in ShapeBaseData
if (computeCRC)
{
stream->read(&(mCRCFP[i]));
}
}
UNPACKDATA_ASSET_ARRAY_REFACTOR(ShapeFP, ShapeBase::MaxMountedImages)
}
@ -1863,9 +1858,9 @@ bool Player::onNewDataBlock( GameBaseData *dptr, bool reload )
{
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
{
if (bool(mDataBlock->mShapeFP[i]))
if (bool(mDataBlock->getShapeFP(i)))
{
mShapeFPInstance[i] = new TSShapeInstance(mDataBlock->mShapeFP[i], isClientObject());
mShapeFPInstance[i] = new TSShapeInstance(mDataBlock->getShapeFP(i), isClientObject());
mShapeFPInstance[i]->cloneMaterialList();

View file

@ -58,7 +58,7 @@ class OpenVRTrackedObject;
//----------------------------------------------------------------------------
struct PlayerData: public ShapeBaseData {
struct PlayerData: public ShapeBaseData /*protected AssetPtrCallback < already in shapebasedata. */ {
typedef ShapeBaseData Parent;
enum Constants {
RecoverDelayBits = 7,
@ -82,8 +82,7 @@ struct PlayerData: public ShapeBaseData {
/// that we don't create a TSThread on the player if we don't
/// need to.
DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages, onShapeChanged); ///< Used to render with mounted images in first person [optional]
DECLARE_ASSET_ARRAY_SETGET(PlayerData, ShapeFP);
DECLARE_SHAPEASSET_ARRAY_REFACTOR(PlayerData, ShapeFP, ShapeBase::MaxMountedImages)
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
/// animation sequences played in first person. [optional]
@ -391,6 +390,11 @@ struct PlayerData: public ShapeBaseData {
DECLARE_CALLBACK( void, onEnterMissionArea, ( Player* obj ) );
DECLARE_CALLBACK( void, onLeaveMissionArea, ( Player* obj ) );
/// @}
protected:
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
{
reloadOnLocalClient();
}
};