// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #ifndef PX_META_DATA_PROPERTY_VISITOR_H #define PX_META_DATA_PROPERTY_VISITOR_H #include #include "PvdMetaDataExtensions.h" namespace physx { namespace Vd { //PVD only deals with read-only properties, indexed, and properties like this by in large. //so we have a filter that expands properties to a level where we can get to them and expands them into //named functions that make more sense and are easier to read than operator() template struct PvdPropertyFilter { private: PvdPropertyFilter& operator=(const PvdPropertyFilter&); public: TOperatorType mOperator; PxU32* mKeyOverride; PxU32* mOffsetOverride; PvdPropertyFilter( TOperatorType& inOperator ) : mOperator( inOperator ) , mKeyOverride( 0 ) , mOffsetOverride( 0 ) {} PvdPropertyFilter( TOperatorType& inOperator, PxU32* inKeyOverride, PxU32* inOffsetOverride ) : mOperator( inOperator ) , mKeyOverride( inKeyOverride ) , mOffsetOverride( inOffsetOverride ) {} PvdPropertyFilter( const PvdPropertyFilter& inOther ) : mOperator( inOther.mOperator ), mKeyOverride( inOther.mKeyOverride ), mOffsetOverride( inOther.mOffsetOverride ) {} template void dispatchAccessor( PxU32 inKey, const TAccessorType& inAccessor, bool, bool, bool) { mOperator.simpleProperty(inKey, inAccessor ); } template void dispatchAccessor( PxU32 inKey, const TAccessorType& inAccessor, bool, bool, const PxU32ToName* inConversions ) { mOperator.flagsProperty(inKey, inAccessor, inConversions ); } template void dispatchAccessor( PxU32 inKey, const TAccessorType& inAccessor, const PxU32ToName* inConversions, bool, bool ) { mOperator.enumProperty( inKey, inAccessor, inConversions ); } template void dispatchAccessor(PxU32, const TAccessorType& inAccessor, bool, const TInfoType* inInfo, bool ) { PxU32 rangeStart = TKey; PxU32& propIdx = mKeyOverride == NULL ? rangeStart : *mKeyOverride; mOperator.complexProperty( &propIdx, inAccessor, *inInfo ); } PxU32 getKeyValue( PxU32 inPropertyKey ) { PxU32 retval = inPropertyKey; if ( mKeyOverride ) { retval = *mKeyOverride; (*mKeyOverride)++; } return retval; } void setupValueStructOffset( const ValueStructOffsetRecord&, bool, PxU32* ) {} void setupValueStructOffset( const ValueStructOffsetRecord& inAccessor, PxU32 inOffset, PxU32* inAdditionalOffset ) { //This allows us to nest properties correctly. if ( inAdditionalOffset ) inOffset += *inAdditionalOffset; inAccessor.setupValueStructOffset( inOffset ); } template void handleAccessor( PxU32 inKey, const TAccessorType& inAccessor ) { typedef typename TAccessorType::prop_type TPropertyType; dispatchAccessor( inKey , inAccessor , PxEnumTraits().NameConversion , PxClassInfoTraits().getInfo() , IsFlagsType().FlagData ); } template void handleAccessor( const TAccessorType& inAccessor ) { setupValueStructOffset( inAccessor, PxPropertyToValueStructMemberMap().Offset, mOffsetOverride ); handleAccessor( getKeyValue( TKey ), inAccessor ); } template void operator()( const PxReadOnlyPropertyInfo& inProperty, PxU32 ) { PxPvdReadOnlyPropertyAccessor< TKey, TObjType, TPropertyType > theAccessor( inProperty ); mOperator.pushName( inProperty.mName ); handleAccessor( theAccessor ); mOperator.popName(); } //We don't handle unbounded indexed properties template void indexedProperty( PxU32, const PxIndexedPropertyInfo&, bool, TValueConversionType, const TInfoType& ) {} template void indexedProperty( PxU32, const PxIndexedPropertyInfo& inProp, const PxU32ToName* theConversions, const PxUnknownClassInfo& ) { mOperator.pushName( inProp.mName ); PxU32 rangeStart = TKey; PxU32& propIdx = mKeyOverride == NULL ? rangeStart : *mKeyOverride; PxU32 theOffset = 0; if ( mOffsetOverride ) theOffset = *mOffsetOverride; while( theConversions->mName != NULL ) { mOperator.pushBracketedName( theConversions->mName ); PxPvdIndexedPropertyAccessor theAccessor( inProp, theConversions->mValue ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); handleAccessor( propIdx, theAccessor ); mOperator.popName(); ++propIdx; ++theConversions; theOffset += sizeof( TPropertyType ); } mOperator.popName(); } template void indexedProperty( PxU32, const PxIndexedPropertyInfo& inProp, const PxU32ToName* theConversions, const TInfoType& inInfo ) { //ouch, not nice. Indexed complex property. mOperator.pushName( inProp.mName ); PxU32 propIdx = TKey; PxU32 theOffset = 0; if ( mOffsetOverride ) theOffset = *mOffsetOverride; while( theConversions->mName != NULL ) { mOperator.pushBracketedName( theConversions->mName ); PxPvdIndexedPropertyAccessor theAccessor( inProp, theConversions->mValue ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); PX_ASSERT( theAccessor.mHasValidOffset ); mOperator.complexProperty( &propIdx, theAccessor, inInfo ); mOperator.popName(); ++theConversions; theOffset += sizeof( TPropertyType ); } mOperator.popName(); } static char* myStrcat(const char* a,const char * b) { size_t len = strlen(a)+strlen(b); char* result = new char[len+1]; strcpy(result,a); strcat(result,b); result[len] = 0; return result; } template void handleBufferCollectionProperty(PxU32 , const PxBufferCollectionPropertyInfo& inProp, const TInfoType& inInfo) { //append 'Collection' to buffer properties char* name = myStrcat(inProp.mName, "Collection"); mOperator.pushName(name); PxU32 propIdx = TKey; PxU32 theOffset = 0; PxBufferCollectionPropertyAccessor theAccessor( inProp, inProp.mName ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); mOperator.bufferCollectionProperty( &propIdx, theAccessor, inInfo ); mOperator.popName(); delete []name; } template void operator()( const PxIndexedPropertyInfo& inProp, PxU32 inIndex ) { indexedProperty( inIndex, inProp, IndexerToNameMap().Converter.NameConversion , PxClassInfoTraits().Info ); } template void handleExtendedIndexProperty(PxU32 inIndex, const PxExtendedIndexedPropertyInfo& inProp, const TInfoType& inInfo) { mOperator.pushName(inProp.mName); PxU32 propIdx = TKey; PxU32 theOffset = 0; PxPvdExtendedIndexedPropertyAccessor theAccessor( inProp, inIndex ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); mOperator.extendedIndexedProperty( &propIdx, theAccessor, inInfo ); mOperator.popName(); } template void handlePxFixedSizeLookupTableProperty( const PxU32 inIndex, const PxFixedSizeLookupTablePropertyInfo& inProp, const TInfoType& inInfo) { mOperator.pushName(inProp.mName); PxU32 propIdx = TKey; PxU32 theOffset = 0; PxPvdFixedSizeLookupTablePropertyAccessor theAccessor( inProp, inIndex ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); mOperator.PxFixedSizeLookupTableProperty( &propIdx, theAccessor, inInfo ); mOperator.popName(); } template void operator()( const PxExtendedIndexedPropertyInfo& inProp, PxU32 inIndex ) { handleExtendedIndexProperty( inIndex, inProp, PxClassInfoTraits().Info ); } template void operator()( const PxFixedSizeLookupTablePropertyInfo& inProp, PxU32 inIndex) { handlePxFixedSizeLookupTableProperty(inIndex, inProp, PxClassInfoTraits().Info); } //We don't handle unbounded indexed properties template void dualIndexedProperty( PxU32 idx, const PxDualIndexedPropertyInfo&, TNameConv, TNameConv2 ) { PX_UNUSED(idx); } template void dualIndexedProperty( PxU32 /*idx*/, const PxDualIndexedPropertyInfo& inProp, const PxU32ToName* c1, const PxU32ToName* c2 ) { mOperator.pushName( inProp.mName ); PxU32 rangeStart = TKey; PxU32& propIdx = mKeyOverride == NULL ? rangeStart : *mKeyOverride; PxU32 theOffset = 0; if ( mOffsetOverride ) theOffset = *mOffsetOverride; while( c1->mName != NULL ) { mOperator.pushBracketedName( c1->mName ); const PxU32ToName* c2Idx = c2; while( c2Idx->mName != NULL ) { mOperator.pushBracketedName( c2Idx->mName ); PxPvdDualIndexedPropertyAccessor theAccessor( inProp, c1->mValue, c2Idx->mValue ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); handleAccessor( propIdx, theAccessor ); mOperator.popName(); ++propIdx; ++c2Idx; theOffset += sizeof( TPropertyType ); } mOperator.popName(); ++c1; } mOperator.popName(); } template void extendedDualIndexedProperty( PxU32 /*idx*/, const PxExtendedDualIndexedPropertyInfo& inProp, PxU32 id0Count, PxU32 id1Count ) { mOperator.pushName( inProp.mName ); PxU32 rangeStart = TKey; PxU32& propIdx = mKeyOverride == NULL ? rangeStart : *mKeyOverride; PxU32 theOffset = 0; if ( mOffsetOverride ) theOffset = *mOffsetOverride; for(PxU32 i = 0; i < id0Count; ++i) { char buffer1[32] = { 0 }; sprintf( buffer1, "eId1_%u", i ); mOperator.pushBracketedName( buffer1 ); for(PxU32 j = 0; j < id1Count; ++j) { char buffer2[32] = { 0 }; sprintf( buffer2, "eId2_%u", j ); mOperator.pushBracketedName( buffer2 ); PxPvdExtendedDualIndexedPropertyAccessor theAccessor( inProp, i, j ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); handleAccessor( propIdx, theAccessor ); mOperator.popName(); ++propIdx; theOffset += sizeof( TPropertyType ); } mOperator.popName(); } mOperator.popName(); } template void operator()( const PxDualIndexedPropertyInfo& inProp, PxU32 idx ) { dualIndexedProperty( idx, inProp , IndexerToNameMap().Converter.NameConversion , IndexerToNameMap().Converter.NameConversion ); } template void operator()( const PxExtendedDualIndexedPropertyInfo& inProp, PxU32 idx ) { extendedDualIndexedProperty( idx, inProp, inProp.mId0Count, inProp.mId1Count ); } template void operator()( const PxRangePropertyInfo& inProperty, PxU32 /*idx*/) { PxU32 rangeStart = TKey; PxU32& propIdx = mKeyOverride == NULL ? rangeStart : *mKeyOverride; PxU32 theOffset = 0; if ( mOffsetOverride ) theOffset = *mOffsetOverride; mOperator.pushName( inProperty.mName ); mOperator.pushName( inProperty.mArg0Name ); PxPvdRangePropertyAccessor theAccessor( inProperty, true ); setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); handleAccessor( propIdx, theAccessor ); ++propIdx; theOffset += sizeof( TPropertyType ); mOperator.popName(); mOperator.pushName( inProperty.mArg1Name ); theAccessor.mFirstValue = false; setupValueStructOffset( theAccessor, PxPropertyToValueStructMemberMap().Offset, &theOffset ); handleAccessor( propIdx, theAccessor ); mOperator.popName(); mOperator.popName(); } template void operator()( const PxBufferCollectionPropertyInfo& inProp, PxU32 count ) { handleBufferCollectionProperty( count, inProp, PxClassInfoTraits().Info ); } template void handleBuffer( const PxBufferPropertyInfo& inProp ) { mOperator.handleBuffer( inProp ); } template void operator()( const PxBufferPropertyInfo& inProp, PxU32 ) { handleBuffer( inProp ); } template void operator()( const PxReadOnlyCollectionPropertyInfo& prop, PxU32 ) { mOperator.handleCollection( prop ); } template void operator()( const PxReadOnlyCollectionPropertyInfo& prop, PxU32 ) { mOperator.handleCollection( prop ); } template void operator()( const PxWriteOnlyPropertyInfo&, PxU32 ) {} template void operator()( const PxReadOnlyCollectionPropertyInfo&, PxU32 ) {} template void operator()( const PxReadOnlyFilteredCollectionPropertyInfo&, PxU32 ) {} //We don't deal with these property datatypes. #define DEFINE_PVD_PROPERTY_NOP(datatype) \ template \ void operator()( const PxReadOnlyPropertyInfo& inProperty, PxU32 ){PX_UNUSED(inProperty); } DEFINE_PVD_PROPERTY_NOP( const void* ) DEFINE_PVD_PROPERTY_NOP( void* ) DEFINE_PVD_PROPERTY_NOP( PxSimulationFilterCallback * ) DEFINE_PVD_PROPERTY_NOP( physx::PxTaskManager * ) DEFINE_PVD_PROPERTY_NOP( PxSimulationFilterShader * ) DEFINE_PVD_PROPERTY_NOP( PxSimulationFilterShader) DEFINE_PVD_PROPERTY_NOP( PxContactModifyCallback * ) DEFINE_PVD_PROPERTY_NOP( PxCCDContactModifyCallback * ) DEFINE_PVD_PROPERTY_NOP( PxSimulationEventCallback * ) DEFINE_PVD_PROPERTY_NOP( physx::PxCudaContextManager* ) DEFINE_PVD_PROPERTY_NOP( physx::PxCpuDispatcher * ) DEFINE_PVD_PROPERTY_NOP( PxRigidActor ) DEFINE_PVD_PROPERTY_NOP( const PxRigidActor ) DEFINE_PVD_PROPERTY_NOP( PxRigidActor& ) DEFINE_PVD_PROPERTY_NOP( const PxRigidActor& ) DEFINE_PVD_PROPERTY_NOP( PxScene* ) DEFINE_PVD_PROPERTY_NOP( PxConstraint ) DEFINE_PVD_PROPERTY_NOP( PxConstraint* ) DEFINE_PVD_PROPERTY_NOP( PxConstraint& ) DEFINE_PVD_PROPERTY_NOP( const PxConstraint& ) DEFINE_PVD_PROPERTY_NOP( PxAggregate * ) DEFINE_PVD_PROPERTY_NOP( PxArticulationBase& ) DEFINE_PVD_PROPERTY_NOP( PxArticulation& ) DEFINE_PVD_PROPERTY_NOP( PxArticulationReducedCoordinate&) DEFINE_PVD_PROPERTY_NOP( const PxArticulationLink * ) DEFINE_PVD_PROPERTY_NOP( const PxRigidDynamic * ) DEFINE_PVD_PROPERTY_NOP( const PxRigidStatic * ) DEFINE_PVD_PROPERTY_NOP( PxArticulationJointBase * ) DEFINE_PVD_PROPERTY_NOP( PxArticulationJointReducedCoordinate * ) DEFINE_PVD_PROPERTY_NOP( PxArticulationJoint * ) DEFINE_PVD_PROPERTY_NOP( PxBroadPhaseCallback * ) DEFINE_PVD_PROPERTY_NOP( const PxBroadPhaseRegion * ) DEFINE_PVD_PROPERTY_NOP( PxU32 * ) }; template inline PvdPropertyFilter makePvdPropertyFilter( TOperator inOperator ) { return PvdPropertyFilter( inOperator ); } template inline PvdPropertyFilter makePvdPropertyFilter( TOperator inOperator, PxU32* inKey, PxU32* inOffset ) { return PvdPropertyFilter( inOperator, inKey, inOffset ); } template inline void visitWithPvdFilter( TOperator inOperator, TFuncType inFuncType ) { PX_UNUSED(inFuncType); TFuncType( makePvdPropertyFilter( inOperator ) ); } template inline void visitInstancePvdProperties( TOperator inOperator ) { visitInstanceProperties( makePvdPropertyFilter( inOperator ) ); } template struct PvdAllPropertyVisitor { TOperator mOperator; PvdAllPropertyVisitor( TOperator op ) : mOperator( op ) {} template bool operator()( const TObjectType* ) { visitInstancePvdProperties( mOperator ); return false; } }; template struct PvdAllInfoVisitor { TOperator mOperator; PvdAllInfoVisitor( TOperator op ) : mOperator( op ) {} template void operator()( TInfoType inInfo ) { inInfo.template visitType( PvdAllPropertyVisitor( mOperator ) ); inInfo.visitBases( *this ); } }; template inline void visitAllPvdProperties( TOperator inOperator ) { visitAllProperties( makePvdPropertyFilter( inOperator ) ); } template inline void visitRigidDynamicPerFrameProperties( TOperator inOperator ) { PvdPropertyFilter theFilter( inOperator ); PxRigidDynamicGeneratedInfo theInfo; theFilter( theInfo.GlobalPose, 0 ); theFilter( theInfo.LinearVelocity, 1 ); theFilter( theInfo.AngularVelocity, 2 ); theFilter( theInfo.IsSleeping, 3 ); } template inline void visitArticulationLinkPerFrameProperties( TOperator inOperator ) { PvdPropertyFilter theFilter( inOperator ); PxArticulationLinkGeneratedInfo theInfo; theFilter( theInfo.GlobalPose, 0 ); theFilter( theInfo.LinearVelocity, 1 ); theFilter( theInfo.AngularVelocity, 2 ); } } } #endif