mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-02 20:10:32 +00:00
Merge branch 'GarageGames/master' into ueberengine-dev
Conflicts: Engine/source/windowManager/sdl/sdlWindowMgr.cpp Tools/CMake/torque3d.cmake 3.10 final update
This commit is contained in:
commit
aff033dd0d
1003 changed files with 53039 additions and 82707 deletions
|
|
@ -1043,9 +1043,9 @@ NavMesh *AIPlayer::findNavMesh() const
|
|||
}
|
||||
else
|
||||
{
|
||||
if(getNavSize() == Small && !m->mSmallCharacters ||
|
||||
getNavSize() == Regular && !m->mRegularCharacters ||
|
||||
getNavSize() == Large && !m->mLargeCharacters)
|
||||
if((getNavSize() == Small && !m->mSmallCharacters) ||
|
||||
(getNavSize() == Regular && !m->mRegularCharacters) ||
|
||||
(getNavSize() == Large && !m->mLargeCharacters))
|
||||
continue;
|
||||
}
|
||||
if(!mesh || m->getWorldBox().getVolume() < mesh->getWorldBox().getVolume())
|
||||
|
|
@ -1317,7 +1317,7 @@ bool AIPlayer::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabled)
|
|||
return hit;
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(NULL, false, false),
|
||||
DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(nullAsType<ShapeBase*>(), false, false),
|
||||
"@brief Check whether an object is in line of sight.\n"
|
||||
"@obj Object to check. (If blank, it will check the current target).\n"
|
||||
"@useMuzzle Use muzzle position. Otherwise use eye position. (defaults to false).\n"
|
||||
|
|
@ -1366,7 +1366,7 @@ bool AIPlayer::checkInFoV(GameBase* target, F32 camFov, bool _checkEnabled)
|
|||
return (dot > mCos(camFov));
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (NULL, 45.0f, false),
|
||||
DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (nullAsType<ShapeBase*>(), 45.0f, false),
|
||||
"@brief Check whether an object is within a specified veiw cone.\n"
|
||||
"@obj Object to check. (If blank, it will check the current target).\n"
|
||||
"@fov view angle in degrees.(Defaults to 45)\n"
|
||||
|
|
@ -1440,7 +1440,7 @@ F32 AIPlayer::getTargetDistance(GameBase* target, bool _checkEnabled)
|
|||
return (getPosition() - target->getPosition()).len();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, getTargetDistance, F32, (ShapeBase* obj, bool checkEnabled), (NULL, false),
|
||||
DefineEngineMethod(AIPlayer, getTargetDistance, F32, (ShapeBase* obj, bool checkEnabled), (nullAsType<ShapeBase*>(), false),
|
||||
"@brief The distance to a given object.\n"
|
||||
"@obj Object to check. (If blank, it will check the current target).\n"
|
||||
"@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n")
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ void Camera::processTick(const Move* move)
|
|||
// process input/determine rotation vector
|
||||
if(virtualMode != StationaryMode &&
|
||||
virtualMode != TrackObjectMode &&
|
||||
(!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
|
||||
(!mLocked || ((virtualMode != OrbitObjectMode) && (virtualMode != OrbitPointMode))))
|
||||
{
|
||||
if(!strafeMode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -632,9 +632,9 @@ DecalInstance* DecalManager::getClosestDecal( const Point3F &pos )
|
|||
}
|
||||
}
|
||||
|
||||
if ( !collectedInsts.empty() &&
|
||||
if ( (!collectedInsts.empty() &&
|
||||
collectedInsts[closestIndex] &&
|
||||
closestDistance < 1.0f ||
|
||||
closestDistance < 1.0f) ||
|
||||
worldInstSphere.isContained( pos ) )
|
||||
return collectedInsts[closestIndex];
|
||||
else
|
||||
|
|
|
|||
|
|
@ -64,16 +64,16 @@
|
|||
class fxFoliageItem
|
||||
{
|
||||
public:
|
||||
MatrixF Transform;
|
||||
F32 Width;
|
||||
F32 Height;
|
||||
Box3F FoliageBox;
|
||||
bool Flipped;
|
||||
MatrixF Transform;
|
||||
F32 Width;
|
||||
F32 Height;
|
||||
Box3F FoliageBox;
|
||||
bool Flipped;
|
||||
F32 SwayPhase;
|
||||
F32 SwayTimeRatio;
|
||||
F32 LightPhase;
|
||||
F32 LightPhase;
|
||||
F32 LightTimeRatio;
|
||||
U32 LastFrameSerialID;
|
||||
U32 LastFrameSerialID;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -104,9 +104,9 @@ public:
|
|||
Box3F QuadrantBox;
|
||||
fxFoliageQuadrantNode* QuadrantChildNode[4];
|
||||
Vector<fxFoliageItem*> RenderList;
|
||||
// Used in DrawIndexPrimitive call.
|
||||
U32 startIndex;
|
||||
U32 primitiveCount;
|
||||
// Used in DrawIndexPrimitive call.
|
||||
U32 startIndex;
|
||||
U32 primitiveCount;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ protected:
|
|||
|
||||
void CreateFoliage(void);
|
||||
void DestroyFoliage(void);
|
||||
void DestroyFoliageItems();
|
||||
void DestroyFoliageItems();
|
||||
|
||||
|
||||
void SyncFoliageReplicators(void);
|
||||
|
|
@ -172,11 +172,11 @@ protected:
|
|||
Vector<fxFoliageItem*> mReplicatedFoliage;
|
||||
fxFoliageRenderList mFrustumRenderSet;
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexFoliage> mVertexBuffer;
|
||||
GFXPrimitiveBufferHandle mPrimBuffer;
|
||||
GFXVertexBufferHandle<GFXVertexFoliage> mVertexBuffer;
|
||||
GFXPrimitiveBufferHandle mPrimBuffer;
|
||||
GFXShaderRef mShader;
|
||||
ShaderData* mShaderData;
|
||||
GBitmap* mAlphaLookup;
|
||||
GBitmap* mAlphaLookup;
|
||||
|
||||
MRandomLCG RandomGen;
|
||||
F32 mFadeInGradient;
|
||||
|
|
@ -193,8 +193,8 @@ protected:
|
|||
U32 mNextAllocatedNodeIdx; // Next Allocated Node Index.
|
||||
U32 mBillboardsAcquired; // Billboards Acquired.
|
||||
|
||||
// Used for alpha lookup in the pixel shader
|
||||
GFXTexHandle mAlphaTexture;
|
||||
// Used for alpha lookup in the pixel shader
|
||||
GFXTexHandle mAlphaTexture;
|
||||
|
||||
GFXStateBlockRef mPlacementSB;
|
||||
GFXStateBlockRef mRenderSB;
|
||||
|
|
@ -223,15 +223,15 @@ protected:
|
|||
|
||||
|
||||
bool mDirty;
|
||||
|
||||
|
||||
void SetupShader();
|
||||
void SetupBuffers();
|
||||
void SetupBuffers();
|
||||
void renderObject(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance*);
|
||||
void renderBuffers(SceneRenderState* state);
|
||||
void renderArc(const F32 fRadiusX, const F32 fRadiusY);
|
||||
void renderPlacementArea(const F32 ElapsedTime);
|
||||
void renderQuad(fxFoliageQuadrantNode* quadNode, const MatrixF& RenderTransform, const bool UseDebug);
|
||||
void computeAlphaTex();
|
||||
void renderBuffers(SceneRenderState* state);
|
||||
void renderArc(const F32 fRadiusX, const F32 fRadiusY);
|
||||
void renderPlacementArea(const F32 ElapsedTime);
|
||||
void renderQuad(fxFoliageQuadrantNode* quadNode, const MatrixF& RenderTransform, const bool UseDebug);
|
||||
void computeAlphaTex();
|
||||
public:
|
||||
fxFoliageReplicator();
|
||||
~fxFoliageReplicator();
|
||||
|
|
@ -325,7 +325,7 @@ public:
|
|||
mUseDebugInfo = false;
|
||||
mDebugBoxHeight = 1.0f;
|
||||
mSeed = 1376312589;
|
||||
mFoliageFile = StringTable->insert("");
|
||||
mFoliageFile = StringTable->EmptyString();
|
||||
mFoliageTexture = GFXTexHandle();
|
||||
mFoliageCount = 10;
|
||||
mFoliageRetries = 100;
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ public:
|
|||
{
|
||||
// Set Defaults.
|
||||
mSeed = 1376312589;
|
||||
mShapeFile = StringTable->insert("");
|
||||
mShapeFile = StringTable->EmptyString();
|
||||
mShapeCount = 10;
|
||||
mShapeRetries = 100;
|
||||
mInnerRadiusX = 0;
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ void LightningStrikeEvent::unpack(NetConnection* con, BitStream* stream)
|
|||
{
|
||||
if(!stream->readFlag())
|
||||
return;
|
||||
S32 mClientId = stream->readRangedU32(0, NetConnection::MaxGhostCount);
|
||||
mClientId = stream->readRangedU32(0, NetConnection::MaxGhostCount);
|
||||
mLightning = NULL;
|
||||
NetObject* pObject = con->resolveGhost(mClientId);
|
||||
if (pObject)
|
||||
|
|
@ -214,10 +214,10 @@ void LightningStrikeEvent::unpack(NetConnection* con, BitStream* stream)
|
|||
// target id
|
||||
S32 mTargetID = stream->readRangedU32(0, NetConnection::MaxGhostCount);
|
||||
|
||||
NetObject* pObject = con->resolveGhost(mTargetID);
|
||||
if( pObject != NULL )
|
||||
NetObject* tObject = con->resolveGhost(mTargetID);
|
||||
if(tObject != NULL )
|
||||
{
|
||||
mTarget = dynamic_cast<SceneObject*>(pObject);
|
||||
mTarget = dynamic_cast<SceneObject*>(tObject);
|
||||
}
|
||||
if( bool(mTarget) == false )
|
||||
{
|
||||
|
|
@ -243,6 +243,7 @@ LightningData::LightningData()
|
|||
dMemset( strikeTextureNames, 0, sizeof( strikeTextureNames ) );
|
||||
dMemset( strikeTextures, 0, sizeof( strikeTextures ) );
|
||||
dMemset( thunderSounds, 0, sizeof( thunderSounds ) );
|
||||
mNumStrikeTextures = 0;
|
||||
}
|
||||
|
||||
LightningData::~LightningData()
|
||||
|
|
@ -297,10 +298,14 @@ bool LightningData::preload(bool server, String &errorStr)
|
|||
if( !sfxResolve( &strikeSound, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
|
||||
mNumStrikeTextures = 0;
|
||||
for (U32 i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
if (strikeTextureNames[i][0])
|
||||
{
|
||||
strikeTextures[i] = GFXTexHandle(strikeTextureNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - strikeTextures[%d] (line %d)", __FUNCTION__, i, __LINE__));
|
||||
mNumStrikeTextures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +322,11 @@ void LightningData::packData(BitStream* stream)
|
|||
U32 i;
|
||||
for (i = 0; i < MaxThunders; i++)
|
||||
sfxWrite( stream, thunderSounds[ i ] );
|
||||
for (i = 0; i < MaxTextures; i++) {
|
||||
|
||||
stream->writeInt(mNumStrikeTextures, 4);
|
||||
|
||||
for (i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
stream->writeString(strikeTextureNames[i]);
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +340,11 @@ void LightningData::unpackData(BitStream* stream)
|
|||
U32 i;
|
||||
for (i = 0; i < MaxThunders; i++)
|
||||
sfxRead( stream, &thunderSounds[ i ] );
|
||||
for (i = 0; i < MaxTextures; i++) {
|
||||
|
||||
mNumStrikeTextures = stream->readInt(4);
|
||||
|
||||
for (i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
strikeTextureNames[i] = stream->readSTString();
|
||||
}
|
||||
|
||||
|
|
@ -368,16 +381,16 @@ Lightning::~Lightning()
|
|||
{
|
||||
while( mThunderListHead )
|
||||
{
|
||||
Thunder* next = mThunderListHead->next;
|
||||
Thunder* nextThunder = mThunderListHead->next;
|
||||
delete mThunderListHead;
|
||||
mThunderListHead = next;
|
||||
mThunderListHead = nextThunder;
|
||||
}
|
||||
|
||||
while( mStrikeListHead )
|
||||
{
|
||||
Strike* next = mStrikeListHead->next;
|
||||
Strike* nextStrike = mStrikeListHead->next;
|
||||
delete mStrikeListHead;
|
||||
mStrikeListHead = next;
|
||||
mStrikeListHead = nextStrike;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -478,11 +491,16 @@ void Lightning::renderObject(ObjectRenderInst *ri, SceneRenderState *state, Base
|
|||
desc.setBlend( true, GFXBlendSrcAlpha, GFXBlendOne);
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.zWriteEnable = false;
|
||||
desc.samplersDefined = true;
|
||||
desc.samplers[0].magFilter = GFXTextureFilterLinear;
|
||||
desc.samplers[0].minFilter = GFXTextureFilterLinear;
|
||||
desc.samplers[0].addressModeU = GFXAddressWrap;
|
||||
desc.samplers[0].addressModeV = GFXAddressWrap;
|
||||
desc.vertexColorEnable = true;
|
||||
|
||||
if (mDataBlock->mNumStrikeTextures != 0)
|
||||
{
|
||||
desc.samplersDefined = true;
|
||||
desc.samplers[0].magFilter = GFXTextureFilterLinear;
|
||||
desc.samplers[0].minFilter = GFXTextureFilterLinear;
|
||||
desc.samplers[0].addressModeU = GFXAddressWrap;
|
||||
desc.samplers[0].addressModeV = GFXAddressWrap;
|
||||
}
|
||||
|
||||
mLightningSB = GFX->createStateBlock(desc);
|
||||
|
||||
|
|
@ -494,9 +512,16 @@ void Lightning::renderObject(ObjectRenderInst *ri, SceneRenderState *state, Base
|
|||
Strike* walk = mStrikeListHead;
|
||||
while (walk != NULL)
|
||||
{
|
||||
GFX->setTexture(0, mDataBlock->strikeTextures[0]);
|
||||
if (mDataBlock->mNumStrikeTextures > 1)
|
||||
{
|
||||
GFX->setTexture(0, mDataBlock->strikeTextures[sgLightningRand.randI(0, mDataBlock->mNumStrikeTextures - 1)]);
|
||||
}
|
||||
else if (mDataBlock->mNumStrikeTextures > 0)
|
||||
{
|
||||
GFX->setTexture(0, mDataBlock->strikeTextures[0]);
|
||||
}
|
||||
|
||||
for( U32 i=0; i<3; i++ )
|
||||
for( U32 i=0; i<MAX_LIGHTNING; i++ )
|
||||
{
|
||||
if( walk->bolt[i].isFading )
|
||||
{
|
||||
|
|
@ -589,7 +614,7 @@ void Lightning::advanceTime(F32 dt)
|
|||
while (*pWalker != NULL) {
|
||||
Strike* pStrike = *pWalker;
|
||||
|
||||
for( U32 i=0; i<3; i++ )
|
||||
for( U32 i=0; i<MAX_LIGHTNING; i++ )
|
||||
{
|
||||
pStrike->bolt[i].update( dt );
|
||||
}
|
||||
|
|
@ -673,7 +698,7 @@ void Lightning::processEvent(LightningStrikeEvent* pEvent)
|
|||
pStrike->currentAge = 0.0f;
|
||||
pStrike->next = mStrikeListHead;
|
||||
|
||||
for( U32 i=0; i<3; i++ )
|
||||
for( U32 i=0; i<MAX_LIGHTNING; i++ )
|
||||
{
|
||||
F32 randStart = boltStartRadius;
|
||||
F32 height = mObjScale.z * 0.5f + getPosition().z;
|
||||
|
|
@ -709,6 +734,7 @@ void Lightning::warningFlashes()
|
|||
{
|
||||
AssertFatal(isServerObject(), "Error, client objects may not initiate lightning!");
|
||||
|
||||
Point3F strikePoint( gRandGen.randF( 0.0f, 1.0f ), gRandGen.randF( 0.0f, 1.0f ), 0.0f );
|
||||
|
||||
SimGroup* pClientGroup = Sim::getClientGroup();
|
||||
for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) {
|
||||
|
|
@ -717,6 +743,9 @@ void Lightning::warningFlashes()
|
|||
{
|
||||
LightningStrikeEvent* pEvent = new LightningStrikeEvent;
|
||||
pEvent->mLightning = this;
|
||||
|
||||
pEvent->mStart.x = strikePoint.x;
|
||||
pEvent->mStart.y = strikePoint.y;
|
||||
|
||||
nc->postNetEvent(pEvent);
|
||||
}
|
||||
|
|
@ -731,18 +760,19 @@ void Lightning::strikeRandomPoint()
|
|||
Point3F strikePoint( gRandGen.randF( 0.0f, 1.0f ), gRandGen.randF( 0.0f, 1.0f ), 0.0f );
|
||||
|
||||
// check if an object is within target range
|
||||
Point3F worldPosStrikePoint = strikePoint;
|
||||
|
||||
strikePoint *= mObjScale;
|
||||
strikePoint += getPosition();
|
||||
strikePoint += Point3F( -mObjScale.x * 0.5f, -mObjScale.y * 0.5f, 0.0f );
|
||||
worldPosStrikePoint *= mObjScale;
|
||||
worldPosStrikePoint += getPosition();
|
||||
worldPosStrikePoint += Point3F( -mObjScale.x * 0.5f, -mObjScale.y * 0.5f, 0.0f );
|
||||
|
||||
Box3F queryBox;
|
||||
F32 boxWidth = strikeRadius * 2.0f;
|
||||
|
||||
queryBox.minExtents.set( -boxWidth * 0.5f, -boxWidth * 0.5f, -mObjScale.z * 0.5f );
|
||||
queryBox.maxExtents.set( boxWidth * 0.5f, boxWidth * 0.5f, mObjScale.z * 0.5f );
|
||||
queryBox.minExtents += strikePoint;
|
||||
queryBox.maxExtents += strikePoint;
|
||||
queryBox.minExtents += worldPosStrikePoint;
|
||||
queryBox.maxExtents += worldPosStrikePoint;
|
||||
|
||||
SimpleQueryList sql;
|
||||
getContainer()->findObjects(queryBox, DAMAGEABLE_TYPEMASK,
|
||||
|
|
@ -837,13 +867,53 @@ void Lightning::strikeRandomPoint()
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void Lightning::strikeObject(ShapeBase*)
|
||||
void Lightning::strikeObject(ShapeBase* targetObj)
|
||||
{
|
||||
AssertFatal(isServerObject(), "Error, client objects may not initiate lightning!");
|
||||
|
||||
AssertFatal(false, "Lightning::strikeObject is not implemented.");
|
||||
}
|
||||
Point3F strikePoint = targetObj->getPosition();
|
||||
Point3F objectCenter;
|
||||
|
||||
Box3F wb = getWorldBox();
|
||||
if (!wb.isContained(strikePoint))
|
||||
return;
|
||||
|
||||
Point3F targetRel = strikePoint - getPosition();
|
||||
Point3F length(wb.len_x() / 2.0f, wb.len_y() / 2.0f, wb.len_z() / 2.0f);
|
||||
|
||||
Point3F strikePos = targetRel / length;
|
||||
|
||||
bool playerInWarmup = false;
|
||||
Player *playerObj = dynamic_cast< Player * >(targetObj);
|
||||
if (playerObj)
|
||||
{
|
||||
if (!playerObj->getControllingClient())
|
||||
{
|
||||
playerInWarmup = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!playerInWarmup)
|
||||
{
|
||||
applyDamage_callback(targetObj->getWorldSphere().center, VectorF(0.0, 0.0, 1.0), targetObj);
|
||||
}
|
||||
|
||||
SimGroup* pClientGroup = Sim::getClientGroup();
|
||||
for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) {
|
||||
NetConnection* nc = static_cast<NetConnection*>(*itr);
|
||||
if (nc != NULL)
|
||||
{
|
||||
LightningStrikeEvent* pEvent = new LightningStrikeEvent;
|
||||
pEvent->mLightning = this;
|
||||
|
||||
pEvent->mStart.x = strikePoint.x;
|
||||
pEvent->mStart.y = strikePoint.y;
|
||||
pEvent->mTarget = targetObj;
|
||||
|
||||
nc->postNetEvent(pEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
U32 Lightning::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||
|
|
@ -864,6 +934,7 @@ U32 Lightning::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
|||
stream->write(color.red);
|
||||
stream->write(color.green);
|
||||
stream->write(color.blue);
|
||||
stream->write(color.alpha);
|
||||
stream->write(fadeColor.red);
|
||||
stream->write(fadeColor.green);
|
||||
stream->write(fadeColor.blue);
|
||||
|
|
@ -895,6 +966,7 @@ void Lightning::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
stream->read(&color.red);
|
||||
stream->read(&color.green);
|
||||
stream->read(&color.blue);
|
||||
stream->read(&color.alpha);
|
||||
stream->read(&fadeColor.red);
|
||||
stream->read(&fadeColor.green);
|
||||
stream->read(&fadeColor.blue);
|
||||
|
|
@ -930,7 +1002,7 @@ DefineEngineMethod(Lightning, strikeRandomPoint, void, (),,
|
|||
object->strikeRandomPoint();
|
||||
}
|
||||
|
||||
DefineEngineMethod(Lightning, strikeObject, void, (ShapeBase* pSB),,
|
||||
DefineEngineMethod(Lightning, strikeObject, void, (ShapeBase* pSB), (nullAsType<ShapeBase*>()),
|
||||
"Creates a LightningStrikeEvent which strikes a specific object.\n"
|
||||
"@note This method is currently unimplemented.\n" )
|
||||
{
|
||||
|
|
@ -1154,7 +1226,7 @@ void LightningBolt::generateMinorNodes()
|
|||
//----------------------------------------------------------------------------
|
||||
// Recursive algo to create bolts that split off from main bolt
|
||||
//----------------------------------------------------------------------------
|
||||
void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPoint, U32 depth, F32 width )
|
||||
void LightningBolt::createSplit( const Point3F &startingPoint, const Point3F &endingPoint, U32 depth, F32 splitWidth )
|
||||
{
|
||||
if( depth == 0 )
|
||||
return;
|
||||
|
|
@ -1163,17 +1235,17 @@ void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPo
|
|||
if( chanceToEnd > 0.70f )
|
||||
return;
|
||||
|
||||
if( width < 0.75f )
|
||||
width = 0.75f;
|
||||
if(splitWidth < 0.75f )
|
||||
splitWidth = 0.75f;
|
||||
|
||||
VectorF diff = endPoint - startPoint;
|
||||
VectorF diff = endingPoint - startingPoint;
|
||||
F32 length = diff.len();
|
||||
diff.normalizeSafe();
|
||||
|
||||
LightningBolt newBolt;
|
||||
newBolt.startPoint = startPoint;
|
||||
newBolt.endPoint = endPoint;
|
||||
newBolt.width = width;
|
||||
newBolt.startPoint = startingPoint;
|
||||
newBolt.endPoint = endingPoint;
|
||||
newBolt.width = splitWidth;
|
||||
newBolt.numMajorNodes = 3;
|
||||
newBolt.maxMajorAngle = 30.0f;
|
||||
newBolt.numMinorNodes = 3;
|
||||
|
|
@ -1184,13 +1256,13 @@ void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPo
|
|||
splitList.pushBack( newBolt );
|
||||
|
||||
VectorF newDir1 = MathUtils::randomDir( diff, 10.0f, 45.0f );
|
||||
Point3F newEndPoint1 = endPoint + newDir1 * gRandGen.randF( 0.5f, 1.5f ) * length;
|
||||
Point3F newEndPoint1 = endingPoint + newDir1 * gRandGen.randF( 0.5f, 1.5f ) * length;
|
||||
|
||||
VectorF newDir2 = MathUtils::randomDir( diff, 10.0f, 45.0f );
|
||||
Point3F newEndPoint2 = endPoint + newDir2 * gRandGen.randF( 0.5f, 1.5f ) * length;
|
||||
Point3F newEndPoint2 = endingPoint + newDir2 * gRandGen.randF( 0.5f, 1.5f ) * length;
|
||||
|
||||
createSplit( endPoint, newEndPoint1, depth - 1, width * 0.30f );
|
||||
createSplit( endPoint, newEndPoint2, depth - 1, width * 0.30f );
|
||||
createSplit(endingPoint, newEndPoint1, depth - 1, splitWidth * 0.30f );
|
||||
createSplit(endingPoint, newEndPoint2, depth - 1, splitWidth * 0.30f );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class ShapeBase;
|
|||
class LightningStrikeEvent;
|
||||
class SFXTrack;
|
||||
|
||||
#define MAX_LIGHTNING 3
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
class LightningData : public GameBaseData
|
||||
|
|
@ -70,6 +71,7 @@ class LightningData : public GameBaseData
|
|||
|
||||
GFXTexHandle strikeTextures[MaxTextures];
|
||||
U32 numThunders;
|
||||
U32 mNumStrikeTextures;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
|
|
@ -227,7 +229,7 @@ class Lightning : public GameBase
|
|||
|
||||
void warningFlashes();
|
||||
void strikeRandomPoint();
|
||||
void strikeObject(ShapeBase*);
|
||||
void strikeObject(ShapeBase* targetObj);
|
||||
void processEvent(LightningStrikeEvent*);
|
||||
|
||||
DECLARE_CONOBJECT(Lightning);
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ void ParticleEmitterNode::setEmitterDataBlock(ParticleEmitterData* data)
|
|||
}
|
||||
|
||||
|
||||
DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (NULL),
|
||||
DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (nullAsType<ParticleEmitterData*>()),
|
||||
"Assigns the datablock for this emitter node.\n"
|
||||
"@param emitterDatablock ParticleEmitterData datablock to assign\n"
|
||||
"@tsexample\n"
|
||||
|
|
|
|||
|
|
@ -129,10 +129,10 @@ PrecipitationData::PrecipitationData()
|
|||
{
|
||||
soundProfile = NULL;
|
||||
|
||||
mDropName = StringTable->insert("");
|
||||
mDropShaderName = StringTable->insert("");
|
||||
mSplashName = StringTable->insert("");
|
||||
mSplashShaderName = StringTable->insert("");
|
||||
mDropName = StringTable->EmptyString();
|
||||
mDropShaderName = StringTable->EmptyString();
|
||||
mSplashName = StringTable->EmptyString();
|
||||
mSplashShaderName = StringTable->EmptyString();
|
||||
|
||||
mDropsPerSide = 4;
|
||||
mSplashesPerSide = 2;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ RibbonData::RibbonData()
|
|||
mUseFadeOut = false;
|
||||
mFadeAwayStep = 0.032f;
|
||||
segmentsPerUpdate = 1;
|
||||
mMatName = StringTable->insert("");
|
||||
mMatName = StringTable->EmptyString();
|
||||
mTileScale = 1.0f;
|
||||
mFixedTexcoords = false;
|
||||
mSegmentSkipAmount = 0;
|
||||
|
|
@ -318,7 +318,7 @@ void Ribbon::processTick(const Move* move)
|
|||
safeDeleteObject();
|
||||
return;
|
||||
//}
|
||||
//mSegmentPoints.pop_back();
|
||||
//mSegmentPoints.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -456,7 +456,7 @@ void Ribbon::setShaderParams() {
|
|||
F32 length = (F32)mDataBlock->mRibbonLength;
|
||||
Point3F radius(numSegments / length, numSegments, length);
|
||||
MaterialParameters* matParams = mRibbonMat->getMaterialParameters();
|
||||
matParams->setSafe( mRadiusSC, radius );
|
||||
matParams->setSafe( mRadiusSC, radius );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ ConsoleDocClass( RibbonNodeData,
|
|||
ConsoleDocClass( RibbonNode, ""
|
||||
);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RibbonNodeData
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -299,7 +298,7 @@ void RibbonNode::setRibbonDatablock(RibbonData* data)
|
|||
mRibbonDatablock = data;
|
||||
}
|
||||
|
||||
DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (0),
|
||||
DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (nullAsType<RibbonData*>()),
|
||||
"Assigns the datablock for this ribbon node.\n"
|
||||
"@param ribbonDatablock RibbonData datablock to assign\n"
|
||||
"@tsexample\n"
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ void LightFlareData::prepRender(SceneRenderState *state, LightFlareState *flareS
|
|||
// We can only skip rendering if the light is not
|
||||
// visible, and it has elapsed the fade out time.
|
||||
if (mIsZero(occlusionFade) ||
|
||||
!lightVisible && visDelta > FadeOutTime)
|
||||
(!lightVisible && visDelta > FadeOutTime))
|
||||
return;
|
||||
|
||||
const RectI &viewport = GFX->getViewport();
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ ConsoleDocClass( WayPoint,
|
|||
|
||||
WayPoint::WayPoint()
|
||||
{
|
||||
mName = StringTable->insert("");
|
||||
mName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
void WayPoint::setHidden(bool hidden)
|
||||
|
|
@ -256,7 +256,7 @@ void WayPoint::inspectPostApply()
|
|||
{
|
||||
Parent::inspectPostApply();
|
||||
if(!mName || !mName[0])
|
||||
mName = StringTable->insert("");
|
||||
mName = StringTable->EmptyString();
|
||||
setMaskBits(UpdateNameMask|UpdateTeamMask);
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ void WayPoint::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
|
||||
void WayPoint::initPersistFields()
|
||||
{
|
||||
addGroup("Misc");
|
||||
addGroup("Misc");
|
||||
addField("markerName", TypeCaseString, Offset(mName, WayPoint), "Unique name representing this waypoint");
|
||||
endGroup("Misc");
|
||||
Parent::initPersistFields();
|
||||
|
|
@ -363,7 +363,7 @@ bool SpawnSphere::onAdd()
|
|||
|
||||
if (!isGhost())
|
||||
{
|
||||
onAdd_callback( getId());
|
||||
onAdd_callback( getId());
|
||||
|
||||
if (mAutoSpawn)
|
||||
spawnObject();
|
||||
|
|
@ -527,7 +527,7 @@ ConsoleDocClass( CameraBookmark,
|
|||
|
||||
CameraBookmark::CameraBookmark()
|
||||
{
|
||||
mName = StringTable->insert("");
|
||||
mName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
bool CameraBookmark::onAdd()
|
||||
|
|
@ -571,7 +571,7 @@ void CameraBookmark::inspectPostApply()
|
|||
{
|
||||
Parent::inspectPostApply();
|
||||
if(!mName || !mName[0])
|
||||
mName = StringTable->insert("");
|
||||
mName = StringTable->EmptyString();
|
||||
setMaskBits(UpdateNameMask);
|
||||
|
||||
if( isMethod("onInspectPostApply") )
|
||||
|
|
@ -595,7 +595,7 @@ void CameraBookmark::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
|
||||
void CameraBookmark::initPersistFields()
|
||||
{
|
||||
//addGroup("Misc");
|
||||
//addGroup("Misc");
|
||||
//addField("name", TypeCaseString, Offset(mName, CameraBookmark));
|
||||
//endGroup("Misc");
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,4 @@
|
|||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
|
||||
#include <BulletMultiThreaded/PlatformDefinitions.h>
|
||||
#include <BulletMultiThreaded/SpuGatheringCollisionDispatcher.h>
|
||||
#include <BulletMultiThreaded/Win32ThreadSupport.h>
|
||||
#include <BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h>
|
||||
|
||||
|
||||
#endif // _BULLET_H_
|
||||
#endif // _BULLET_H_
|
||||
|
|
|
|||
|
|
@ -356,6 +356,35 @@ void BtBody::applyImpulse( const Point3F &origin, const Point3F &force )
|
|||
mActor->activate();
|
||||
}
|
||||
|
||||
void BtBody::applyTorque( const Point3F &torque )
|
||||
{
|
||||
AssertFatal(mActor, "BtBody::applyTorque - The actor is null!");
|
||||
AssertFatal(isDynamic(), "BtBody::applyTorque - This call is only for dynamics!");
|
||||
|
||||
mActor->applyTorque( btCast<btVector3>(torque) );
|
||||
|
||||
if (!mActor->isActive())
|
||||
mActor->activate();
|
||||
}
|
||||
|
||||
void BtBody::applyForce( const Point3F &force )
|
||||
{
|
||||
AssertFatal(mActor, "BtBody::applyForce - The actor is null!");
|
||||
AssertFatal(isDynamic(), "BtBody::applyForce - This call is only for dynamics!");
|
||||
|
||||
if (mCenterOfMass)
|
||||
{
|
||||
Point3F relForce(force);
|
||||
mCenterOfMass->mulV(relForce);
|
||||
mActor->applyCentralForce(btCast<btVector3>(relForce));
|
||||
}
|
||||
else
|
||||
mActor->applyCentralForce(btCast<btVector3>(force));
|
||||
|
||||
if (!mActor->isActive())
|
||||
mActor->activate();
|
||||
}
|
||||
|
||||
Box3F BtBody::getWorldBounds()
|
||||
{
|
||||
btVector3 min, max;
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ public:
|
|||
F32 staticFriction );
|
||||
virtual void applyCorrection( const MatrixF &xfm );
|
||||
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
|
||||
|
||||
virtual void applyTorque( const Point3F &torque );
|
||||
virtual void applyForce( const Point3F &force );
|
||||
virtual void findContact(SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects) const;
|
||||
virtual void moveKinematicTo(const MatrixF &xfm);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,42 @@
|
|||
#include "T3D/physics/bullet/bt.h"
|
||||
#include "T3D/physics/bullet/btCasts.h"
|
||||
|
||||
class btHeightfieldTerrainShapeCustom : public btHeightfieldTerrainShape
|
||||
{
|
||||
bool* mHoles;
|
||||
|
||||
public:
|
||||
btHeightfieldTerrainShapeCustom(const bool *holes,
|
||||
int heightStickWidth,
|
||||
int heightStickLength,
|
||||
const void* heightfieldData,
|
||||
btScalar heightScale,
|
||||
btScalar minHeight,
|
||||
btScalar maxHeight,
|
||||
int upAxis,
|
||||
PHY_ScalarType heightDataType,
|
||||
bool flipQuadEdges) : btHeightfieldTerrainShape(heightStickWidth,
|
||||
heightStickLength,
|
||||
heightfieldData,
|
||||
heightScale,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
upAxis,
|
||||
heightDataType,
|
||||
flipQuadEdges)
|
||||
{
|
||||
mHoles = new bool[heightStickWidth * heightStickLength];
|
||||
dMemcpy(mHoles, holes, heightStickWidth * heightStickLength * sizeof(bool));
|
||||
}
|
||||
|
||||
virtual ~btHeightfieldTerrainShapeCustom()
|
||||
{
|
||||
delete[] mHoles;
|
||||
}
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
|
||||
};
|
||||
|
||||
|
||||
BtCollision::BtCollision()
|
||||
: mCompound( NULL ),
|
||||
|
|
@ -170,13 +206,15 @@ bool BtCollision::addHeightfield( const U16 *heights,
|
|||
const F32 minHeight = 0;
|
||||
const F32 maxHeight = 65535 * heightScale;
|
||||
|
||||
btHeightfieldTerrainShape *shape = new btHeightfieldTerrainShape( blockSize, blockSize,
|
||||
(void*)heights,
|
||||
heightScale,
|
||||
minHeight, maxHeight,
|
||||
2, // Z up!
|
||||
PHY_SHORT,
|
||||
false );
|
||||
btHeightfieldTerrainShapeCustom* shape = new btHeightfieldTerrainShapeCustom(holes,
|
||||
blockSize, blockSize,
|
||||
reinterpret_cast<const void*>(heights),
|
||||
heightScale,
|
||||
0, 0xFFFF * heightScale,
|
||||
2, // Z up!
|
||||
PHY_SHORT,
|
||||
false);
|
||||
|
||||
shape->setMargin( 0.01f );
|
||||
shape->setLocalScaling( btVector3( metersPerSample, metersPerSample, 1.0f ) );
|
||||
shape->setUseDiamondSubdivision( true );
|
||||
|
|
@ -203,3 +241,116 @@ bool BtCollision::addHeightfield( const U16 *heights,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void btHeightfieldTerrainShapeCustom::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
|
||||
{
|
||||
// scale down the input aabb's so they are in local (non-scaled) coordinates
|
||||
btVector3 localAabbMin = aabbMin * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
|
||||
btVector3 localAabbMax = aabbMax * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
|
||||
|
||||
// account for local origin
|
||||
localAabbMin += m_localOrigin;
|
||||
localAabbMax += m_localOrigin;
|
||||
|
||||
//quantize the aabbMin and aabbMax, and adjust the start/end ranges
|
||||
int quantizedAabbMin[3];
|
||||
int quantizedAabbMax[3];
|
||||
quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
|
||||
quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
|
||||
|
||||
// expand the min/max quantized values
|
||||
// this is to catch the case where the input aabb falls between grid points!
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
quantizedAabbMin[i]--;
|
||||
quantizedAabbMax[i]++;
|
||||
}
|
||||
|
||||
int startX = 0;
|
||||
int endX = m_heightStickWidth - 1;
|
||||
int startJ = 0;
|
||||
int endJ = m_heightStickLength - 1;
|
||||
|
||||
switch (m_upAxis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (quantizedAabbMin[1] > startX)
|
||||
startX = quantizedAabbMin[1];
|
||||
if (quantizedAabbMax[1] < endX)
|
||||
endX = quantizedAabbMax[1];
|
||||
if (quantizedAabbMin[2] > startJ)
|
||||
startJ = quantizedAabbMin[2];
|
||||
if (quantizedAabbMax[2] < endJ)
|
||||
endJ = quantizedAabbMax[2];
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (quantizedAabbMin[0] > startX)
|
||||
startX = quantizedAabbMin[0];
|
||||
if (quantizedAabbMax[0] < endX)
|
||||
endX = quantizedAabbMax[0];
|
||||
if (quantizedAabbMin[2] > startJ)
|
||||
startJ = quantizedAabbMin[2];
|
||||
if (quantizedAabbMax[2] < endJ)
|
||||
endJ = quantizedAabbMax[2];
|
||||
break;
|
||||
};
|
||||
case 2:
|
||||
{
|
||||
if (quantizedAabbMin[0] > startX)
|
||||
startX = quantizedAabbMin[0];
|
||||
if (quantizedAabbMax[0] < endX)
|
||||
endX = quantizedAabbMax[0];
|
||||
if (quantizedAabbMin[1] > startJ)
|
||||
startJ = quantizedAabbMin[1];
|
||||
if (quantizedAabbMax[1] < endJ)
|
||||
endJ = quantizedAabbMax[1];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//need to get valid m_upAxis
|
||||
btAssert(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = startJ; j < endJ; j++)
|
||||
{
|
||||
for (int x = startX; x < endX; x++)
|
||||
{
|
||||
U32 index = (m_heightStickLength - (m_heightStickLength - x - 1)) + (j * m_heightStickWidth);
|
||||
|
||||
if (mHoles && mHoles[getMax((S32)index - 1, 0)])
|
||||
continue;
|
||||
|
||||
btVector3 vertices[3];
|
||||
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
|
||||
{
|
||||
//first triangle
|
||||
getVertex(x, j, vertices[0]);
|
||||
getVertex(x, j + 1, vertices[1]);
|
||||
getVertex(x + 1, j + 1, vertices[2]);
|
||||
callback->processTriangle(vertices, x, j);
|
||||
//second triangle
|
||||
// getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
|
||||
getVertex(x + 1, j + 1, vertices[1]);
|
||||
getVertex(x + 1, j, vertices[2]);
|
||||
callback->processTriangle(vertices, x, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
//first triangle
|
||||
getVertex(x, j, vertices[0]);
|
||||
getVertex(x, j + 1, vertices[1]);
|
||||
getVertex(x + 1, j, vertices[2]);
|
||||
callback->processTriangle(vertices, x, j);
|
||||
//second triangle
|
||||
getVertex(x + 1, j, vertices[0]);
|
||||
//getVertex(x,j+1,vertices[1]);
|
||||
getVertex(x + 1, j + 1, vertices[2]);
|
||||
callback->processTriangle(vertices, x, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -342,7 +342,7 @@ void BtPlayer::_stepForward( btVector3 *inOutCurrPos, const btVector3 &displacem
|
|||
start.setOrigin( *inOutCurrPos );
|
||||
end.setOrigin( *inOutCurrPos + disp );
|
||||
|
||||
BtPlayerSweepCallback callback( mGhostObject, disp.length2() > 0.0f ? disp.normalized() : disp );
|
||||
BtPlayerSweepCallback callback( mGhostObject, disp.length2() > SIMD_EPSILON ? disp.normalized() : disp );
|
||||
callback.m_collisionFilterGroup = mGhostObject->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = mGhostObject->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,11 +33,6 @@
|
|||
#include "console/consoleTypes.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "T3D/gameBase/gameProcess.h"
|
||||
#ifdef _WIN32
|
||||
#include "BulletMultiThreaded/Win32ThreadSupport.h"
|
||||
#elif defined (USE_PTHREADS)
|
||||
#include "BulletMultiThreaded/PosixThreadSupport.h"
|
||||
#endif
|
||||
|
||||
BtWorld::BtWorld() :
|
||||
mProcessList( NULL ),
|
||||
|
|
@ -46,8 +41,7 @@ BtWorld::BtWorld() :
|
|||
mTickCount( 0 ),
|
||||
mIsEnabled( false ),
|
||||
mEditorTimeScale( 1.0f ),
|
||||
mDynamicsWorld( NULL ),
|
||||
mThreadSupportCollision( NULL )
|
||||
mDynamicsWorld( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -59,33 +53,7 @@ bool BtWorld::initWorld( bool isServer, ProcessList *processList )
|
|||
{
|
||||
// Collision configuration contains default setup for memory, collision setup.
|
||||
mCollisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
|
||||
// TODO: There is something wrong with multithreading
|
||||
// and compound convex shapes... so disable it for now.
|
||||
static const U32 smMaxThreads = 1;
|
||||
|
||||
// Different initialization with threading enabled.
|
||||
if ( smMaxThreads > 1 )
|
||||
{
|
||||
|
||||
// TODO: ifdef assumes smMaxThread is always one at this point. MACOSX support to be decided
|
||||
#ifdef WIN32
|
||||
mThreadSupportCollision = new Win32ThreadSupport(
|
||||
Win32ThreadSupport::Win32ThreadConstructionInfo( isServer ? "bt_servercol" : "bt_clientcol",
|
||||
processCollisionTask,
|
||||
createCollisionLocalStoreMemory,
|
||||
smMaxThreads ) );
|
||||
|
||||
mDispatcher = new SpuGatheringCollisionDispatcher( mThreadSupportCollision,
|
||||
smMaxThreads,
|
||||
mCollisionConfiguration );
|
||||
#endif // WIN32
|
||||
}
|
||||
else
|
||||
{
|
||||
mThreadSupportCollision = NULL;
|
||||
mDispatcher = new btCollisionDispatcher( mCollisionConfiguration );
|
||||
}
|
||||
mDispatcher = new btCollisionDispatcher( mCollisionConfiguration );
|
||||
|
||||
btVector3 worldMin( -2000, -2000, -1000 );
|
||||
btVector3 worldMax( 2000, 2000, 1000 );
|
||||
|
|
@ -134,7 +102,6 @@ void BtWorld::_destroy()
|
|||
SAFE_DELETE( mSolver );
|
||||
SAFE_DELETE( mBroadphase );
|
||||
SAFE_DELETE( mDispatcher );
|
||||
SAFE_DELETE( mThreadSupportCollision );
|
||||
SAFE_DELETE( mCollisionConfiguration );
|
||||
}
|
||||
|
||||
|
|
@ -144,20 +111,20 @@ void BtWorld::tickPhysics( U32 elapsedMs )
|
|||
return;
|
||||
|
||||
// Did we forget to call getPhysicsResults somewhere?
|
||||
AssertFatal( !mIsSimulating, "PhysXWorld::tickPhysics() - Already simulating!" );
|
||||
AssertFatal( !mIsSimulating, "BtWorld::tickPhysics() - Already simulating!" );
|
||||
|
||||
// The elapsed time should be non-zero and
|
||||
// a multiple of TickMs!
|
||||
AssertFatal( elapsedMs != 0 &&
|
||||
( elapsedMs % TickMs ) == 0 , "PhysXWorld::tickPhysics() - Got bad elapsed time!" );
|
||||
( elapsedMs % TickMs ) == 0 , "BtWorld::tickPhysics() - Got bad elapsed time!" );
|
||||
|
||||
PROFILE_SCOPE(BtWorld_TickPhysics);
|
||||
|
||||
// Convert it to seconds.
|
||||
const F32 elapsedSec = (F32)elapsedMs * 0.001f;
|
||||
|
||||
// Simulate... it is recommended to always use Bullet's default fixed timestep/
|
||||
mDynamicsWorld->stepSimulation( elapsedSec * mEditorTimeScale );
|
||||
// Simulate
|
||||
mDynamicsWorld->stepSimulation( elapsedSec * mEditorTimeScale, smPhysicsMaxSubSteps, smPhysicsStepTime);
|
||||
|
||||
mIsSimulating = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#endif
|
||||
|
||||
class ProcessList;
|
||||
class btThreadSupportInterface;
|
||||
class PhysicsBody;
|
||||
|
||||
|
||||
|
|
@ -54,7 +53,6 @@ protected:
|
|||
btCollisionDispatcher *mDispatcher;
|
||||
btConstraintSolver *mSolver;
|
||||
btDefaultCollisionConfiguration *mCollisionConfiguration;
|
||||
btThreadSupportInterface *mThreadSupportCollision;
|
||||
|
||||
bool mErrorReport;
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ public:
|
|||
///
|
||||
virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;
|
||||
|
||||
///
|
||||
virtual void applyTorque( const Point3F &torque ) = 0;
|
||||
|
||||
///
|
||||
virtual void applyForce( const Point3F &force ) = 0;
|
||||
|
||||
|
||||
virtual void findContact(SceneObject **contactObject,
|
||||
VectorF *contactNormal,
|
||||
Vector<SceneObject*> *outOverlapObjects) const = 0;
|
||||
|
|
|
|||
|
|
@ -857,6 +857,18 @@ void PhysicsShape::applyImpulse( const Point3F &pos, const VectorF &vec )
|
|||
mPhysicsRep->applyImpulse( pos, vec );
|
||||
}
|
||||
|
||||
void PhysicsShape::applyTorque( const Point3F &torque )
|
||||
{
|
||||
if (mPhysicsRep && mPhysicsRep->isDynamic())
|
||||
mPhysicsRep->applyTorque( torque );
|
||||
}
|
||||
|
||||
void PhysicsShape::applyForce( const Point3F &force )
|
||||
{
|
||||
if (mPhysicsRep && mPhysicsRep->isDynamic())
|
||||
mPhysicsRep->applyForce( force );
|
||||
}
|
||||
|
||||
void PhysicsShape::applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude )
|
||||
{
|
||||
if ( !mPhysicsRep || !mPhysicsRep->isDynamic() )
|
||||
|
|
@ -1179,4 +1191,20 @@ DefineEngineMethod( PhysicsShape, restore, void, (),,
|
|||
"Has no effect if the shape is not destroyed.\n\n")
|
||||
{
|
||||
object->restore();
|
||||
}
|
||||
|
||||
DefineEngineMethod( PhysicsShape, applyTorque, void, (Point3F torque), ,
|
||||
"@brief Add a torque to a dynamic physics shape.\n\n"
|
||||
"@param torque to apply to the dynamic physics shape\n"
|
||||
"@note This value is ignored on physics shapes that are not dynamic. Wakes up the dynamic physics shape if it is sleeping.\n")
|
||||
{
|
||||
object->applyTorque( torque );
|
||||
}
|
||||
|
||||
DefineEngineMethod(PhysicsShape, applyForce, void, (Point3F force), ,
|
||||
"@brief Add a force to a dynamic physics shape.\n\n"
|
||||
"@param force to apply to the dynamic physics shape\n"
|
||||
"@note This value is ignored on physics shapes that are not dynamic. Wakes up the dynamic physics shape if it is sleeping.\n")
|
||||
{
|
||||
object->applyForce( force );
|
||||
}
|
||||
|
|
@ -246,6 +246,8 @@ public:
|
|||
Point3F getVelocity() const { return mState.linVelocity; }
|
||||
void applyImpulse( const Point3F &pos, const VectorF &vec );
|
||||
void applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude );
|
||||
void applyTorque( const Point3F &torque );
|
||||
void applyForce( const Point3F &force );
|
||||
void setScale(const VectorF & scale);
|
||||
|
||||
// GameBase
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physicsWorld.h"
|
||||
|
||||
//Physics timing
|
||||
F32 PhysicsWorld::smPhysicsStepTime = 1.0f / 60.f; //default 60fps
|
||||
U32 PhysicsWorld::smPhysicsMaxSubSteps = 4;
|
||||
|
||||
PhysicsWorld::PhysicsWorld()
|
||||
: mGravity( 0, 0, -20.0f ) // NOTE: This matches the gravity used for player objects.
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ public:
|
|||
virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All ) = 0;
|
||||
|
||||
virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) = 0;
|
||||
|
||||
/// Physics timing
|
||||
static F32 smPhysicsStepTime;
|
||||
static U32 smPhysicsMaxSubSteps;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// This PhysX implementation for Torque was originally based on
|
||||
// the "PhysX in TGEA" resource written by Shannon Scarvaci.
|
||||
//
|
||||
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=12711
|
||||
//
|
||||
|
||||
#ifndef _PHYSX_H_
|
||||
#define _PHYSX_H_
|
||||
|
||||
/*
|
||||
#ifndef _TORQUE_TYPES_H_
|
||||
# include "platform/types.h"
|
||||
#endif
|
||||
*/
|
||||
|
||||
#include "platform/tmm_off.h"
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#if defined(TORQUE_OS_MAC) && !defined(__APPLE__)
|
||||
#define __APPLE__
|
||||
#elif defined(TORQUE_OS_LINUX) && !defined(LINUX)
|
||||
#define LINUX
|
||||
#elif defined(TORQUE_OS_WIN) && !defined(WIN32)
|
||||
#define WIN32
|
||||
#endif
|
||||
|
||||
#ifndef NX_PHYSICS_NXPHYSICS
|
||||
#include <NxPhysics.h>
|
||||
#endif
|
||||
#ifndef NX_FOUNDATION_NXSTREAM
|
||||
#include <NxStream.h>
|
||||
#endif
|
||||
#ifndef NX_COOKING_H
|
||||
#include <NxCooking.h>
|
||||
#endif
|
||||
#ifndef NX_FOUNDATION_NXUSEROUTPUTSTREAM
|
||||
#include <NxUserOutputStream.h>
|
||||
#endif
|
||||
#ifndef NX_PHYSICS_NXBIG
|
||||
#include "NxExtended.h"
|
||||
#endif
|
||||
#include <NxUserAllocatorDefault.h>
|
||||
#include <CCTAllocator.h>
|
||||
#include <NxControllerManager.h>
|
||||
#include <CharacterControllerManager.h>
|
||||
#include <NxController.h>
|
||||
#include <NxCapsuleController.h>
|
||||
|
||||
/// The single global physx sdk object for this process.
|
||||
extern NxPhysicsSDK *gPhysicsSDK;
|
||||
|
||||
#include "platform/tmm_on.h"
|
||||
|
||||
#endif // _PHYSX_H_
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxBody.h"
|
||||
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
#include "T3D/physics/physX/pxCollision.h"
|
||||
|
||||
|
||||
PxBody::PxBody() :
|
||||
mActor( NULL ),
|
||||
mMaterial( NULL ),
|
||||
mWorld( NULL ),
|
||||
mBodyFlags( 0 ),
|
||||
mIsEnabled( true )
|
||||
{
|
||||
}
|
||||
|
||||
PxBody::~PxBody()
|
||||
{
|
||||
_releaseActor();
|
||||
}
|
||||
|
||||
void PxBody::_releaseActor()
|
||||
{
|
||||
if ( !mActor )
|
||||
return;
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
mActor->userData = NULL;
|
||||
|
||||
mWorld->releaseActor( *mActor );
|
||||
mActor = NULL;
|
||||
mBodyFlags = 0;
|
||||
|
||||
if ( mMaterial )
|
||||
{
|
||||
mWorld->releaseMaterial( *mMaterial );
|
||||
mMaterial = NULL;
|
||||
}
|
||||
|
||||
mColShape = NULL;
|
||||
}
|
||||
|
||||
bool PxBody::init( PhysicsCollision *shape,
|
||||
F32 mass,
|
||||
U32 bodyFlags,
|
||||
SceneObject *obj,
|
||||
PhysicsWorld *world )
|
||||
{
|
||||
AssertFatal( obj, "PxBody::init - Got a null scene object!" );
|
||||
AssertFatal( world, "PxBody::init - Got a null world!" );
|
||||
AssertFatal( dynamic_cast<PxWorld*>( world ), "PxBody::init - The world is the wrong type!" );
|
||||
AssertFatal( shape, "PxBody::init - Got a null collision shape!" );
|
||||
AssertFatal( dynamic_cast<PxCollision*>( shape ), "PxBody::init - The collision shape is the wrong type!" );
|
||||
AssertFatal( !((PxCollision*)shape)->getShapes().empty(), "PxBody::init - Got empty collision shape!" );
|
||||
|
||||
// Cleanup any previous actor.
|
||||
_releaseActor();
|
||||
|
||||
mWorld = (PxWorld*)world;
|
||||
mColShape = (PxCollision*)shape;
|
||||
mBodyFlags = bodyFlags;
|
||||
|
||||
NxActorDesc actorDesc;
|
||||
NxBodyDesc bodyDesc;
|
||||
|
||||
const bool isKinematic = mBodyFlags & BF_KINEMATIC;
|
||||
const bool isTrigger = mBodyFlags & BF_TRIGGER;
|
||||
const bool isDebris = mBodyFlags & BF_DEBRIS;
|
||||
|
||||
if ( isKinematic )
|
||||
{
|
||||
// Kinematics are dynamics... so they need
|
||||
// a body description.
|
||||
actorDesc.body = &bodyDesc;
|
||||
bodyDesc.mass = getMax( mass, 1.0f );
|
||||
bodyDesc.flags |= NX_BF_KINEMATIC;
|
||||
}
|
||||
else if ( mass > 0.0f )
|
||||
{
|
||||
// We have mass so its a dynamic.
|
||||
actorDesc.body = &bodyDesc;
|
||||
bodyDesc.mass = mass;
|
||||
}
|
||||
|
||||
if ( isTrigger )
|
||||
actorDesc.flags |= NX_AF_DISABLE_RESPONSE;
|
||||
|
||||
// Add all the shapes.
|
||||
const Vector<NxShapeDesc*> &shapes = mColShape->getShapes();
|
||||
for ( U32 i=0; i < shapes.size(); i++ )
|
||||
{
|
||||
NxShapeDesc *desc = shapes[i];
|
||||
|
||||
// If this hits then something is broken with
|
||||
// this descrption... check all the fields to be
|
||||
// sure their values are correctly filled out.
|
||||
AssertFatal( desc->isValid(), "PxBody::init - Got invalid shape description!" );
|
||||
|
||||
if ( isTrigger )
|
||||
desc->group = 31;
|
||||
|
||||
if ( isDebris )
|
||||
desc->group = 30;
|
||||
|
||||
actorDesc.shapes.push_back( desc );
|
||||
}
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
mActor = mWorld->getScene()->createActor( actorDesc );
|
||||
mIsEnabled = true;
|
||||
|
||||
if ( isDebris )
|
||||
mActor->setDominanceGroup( 31 );
|
||||
|
||||
mUserData.setObject( obj );
|
||||
mUserData.setBody( this );
|
||||
mActor->userData = &mUserData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxBody::setMaterial( F32 restitution,
|
||||
F32 friction,
|
||||
F32 staticFriction )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setMaterial - The actor is null!" );
|
||||
|
||||
// If the body is dynamic then wake it up as
|
||||
// it may need to change behavior.
|
||||
if ( isDynamic() )
|
||||
mActor->wakeUp();
|
||||
|
||||
NxMaterialDesc desc;
|
||||
desc.restitution = restitution;
|
||||
desc.dynamicFriction = friction;
|
||||
desc.staticFriction = staticFriction;
|
||||
|
||||
// If we have a material then just update it as the shapes
|
||||
// should already have them mapped.
|
||||
if ( mMaterial )
|
||||
{
|
||||
mMaterial->loadFromDesc( desc );
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got here then create a new material and
|
||||
// assign it to all our shapes.
|
||||
mMaterial = mWorld->createMaterial( desc );
|
||||
U32 matIndex = mMaterial->getMaterialIndex();
|
||||
U32 count = mActor->getNbShapes();
|
||||
NxShape*const* shapes = mActor->getShapes();
|
||||
for ( U32 i=0; i < count; i++ )
|
||||
shapes[i]->setMaterial( matIndex );
|
||||
}
|
||||
|
||||
void PxBody::setSleepThreshold( F32 linear, F32 angular )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setSleepThreshold - The actor is null!" );
|
||||
|
||||
mActor->setSleepLinearVelocity( linear );
|
||||
mActor->setSleepAngularVelocity( angular );
|
||||
}
|
||||
|
||||
void PxBody::setDamping( F32 linear, F32 angular )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setDamping - The actor is null!" );
|
||||
mActor->setLinearDamping( linear );
|
||||
mActor->setAngularDamping( angular );
|
||||
}
|
||||
|
||||
void PxBody::getState( PhysicsState *outState )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getState - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::getState - This call is only for dynamics!" );
|
||||
|
||||
// TODO: Fix this to do what we intended... to return
|
||||
// false so that the caller can early out of the state
|
||||
// hasn't changed since the last tick.
|
||||
|
||||
outState->position = pxCast<Point3F>( mActor->getGlobalPosition() );
|
||||
outState->orientation = pxCast<QuatF>( mActor->getGlobalOrientationQuat() );
|
||||
outState->linVelocity = pxCast<Point3F>( mActor->getLinearVelocity() );
|
||||
outState->angVelocity = pxCast<Point3F>( mActor->getAngularVelocity() );
|
||||
outState->sleeping = mActor->isSleeping();
|
||||
outState->momentum = pxCast<Point3F>( mActor->getLinearMomentum() );
|
||||
}
|
||||
|
||||
F32 PxBody::getMass() const
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
|
||||
return mActor->getMass();
|
||||
}
|
||||
|
||||
Point3F PxBody::getCMassPosition() const
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
|
||||
return pxCast<Point3F>( mActor->getCMassGlobalPosition() );
|
||||
}
|
||||
|
||||
void PxBody::setLinVelocity( const Point3F &vel )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setLinVelocity - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::setLinVelocity - This call is only for dynamics!" );
|
||||
|
||||
mActor->setLinearVelocity( pxCast<NxVec3>( vel ) );
|
||||
}
|
||||
|
||||
void PxBody::setAngVelocity( const Point3F &vel )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setAngVelocity - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::setAngVelocity - This call is only for dynamics!" );
|
||||
|
||||
mActor->setAngularVelocity( pxCast<NxVec3>( vel ) );
|
||||
}
|
||||
|
||||
Point3F PxBody::getLinVelocity() const
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getLinVelocity - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::getLinVelocity - This call is only for dynamics!" );
|
||||
|
||||
return pxCast<Point3F>( mActor->getLinearVelocity() );
|
||||
}
|
||||
|
||||
Point3F PxBody::getAngVelocity() const
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getAngVelocity - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::getAngVelocity - This call is only for dynamics!" );
|
||||
|
||||
return pxCast<Point3F>( mActor->getAngularVelocity() );
|
||||
}
|
||||
|
||||
void PxBody::setSleeping( bool sleeping )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setSleeping - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::setSleeping - This call is only for dynamics!" );
|
||||
|
||||
if ( sleeping )
|
||||
mActor->putToSleep();
|
||||
else
|
||||
mActor->wakeUp();
|
||||
}
|
||||
|
||||
bool PxBody::isDynamic() const
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" );
|
||||
return mActor->isDynamic() && ( mBodyFlags & BF_KINEMATIC ) == 0;
|
||||
}
|
||||
|
||||
PhysicsWorld* PxBody::getWorld()
|
||||
{
|
||||
return mWorld;
|
||||
}
|
||||
|
||||
PhysicsCollision* PxBody::getColShape()
|
||||
{
|
||||
return mColShape;
|
||||
}
|
||||
|
||||
MatrixF& PxBody::getTransform( MatrixF *outMatrix )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
|
||||
|
||||
mActor->getGlobalPose().getRowMajor44( *outMatrix );
|
||||
|
||||
return *outMatrix;
|
||||
}
|
||||
|
||||
Box3F PxBody::getWorldBounds()
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
|
||||
|
||||
NxBounds3 bounds;
|
||||
bounds.setEmpty();
|
||||
NxBounds3 shapeBounds;
|
||||
|
||||
NxShape *const* pShapeArray = mActor->getShapes();
|
||||
U32 shapeCount = mActor->getNbShapes();
|
||||
|
||||
for ( U32 i = 0; i < shapeCount; i++ )
|
||||
{
|
||||
// Get the shape's bounds.
|
||||
pShapeArray[i]->getWorldBounds( shapeBounds );
|
||||
|
||||
// Combine them into the total bounds.
|
||||
bounds.combine( shapeBounds );
|
||||
}
|
||||
|
||||
return pxCast<Box3F>( bounds );
|
||||
}
|
||||
|
||||
void PxBody::setSimulationEnabled( bool enabled )
|
||||
{
|
||||
if ( mIsEnabled == enabled )
|
||||
return;
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
if ( enabled )
|
||||
{
|
||||
mIsEnabled = true;
|
||||
mActor->clearActorFlag( NX_AF_DISABLE_RESPONSE );
|
||||
mActor->clearActorFlag( NX_AF_DISABLE_COLLISION );
|
||||
|
||||
// Don't clear the flag if its supposed to be kinematic.
|
||||
if ( !(mBodyFlags & BF_KINEMATIC) )
|
||||
mActor->clearBodyFlag( NX_BF_KINEMATIC );
|
||||
|
||||
if ( isDynamic() )
|
||||
mActor->wakeUp();
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsEnabled = false;
|
||||
mActor->raiseActorFlag( NX_AF_DISABLE_RESPONSE );
|
||||
mActor->raiseActorFlag( NX_AF_DISABLE_COLLISION );
|
||||
mActor->raiseBodyFlag( NX_BF_KINEMATIC );
|
||||
}
|
||||
|
||||
NxShape *const* shapes = mActor->getShapes();
|
||||
for ( S32 i = 0; i < mActor->getNbShapes(); i++ )
|
||||
shapes[i]->setFlag( NX_SF_DISABLE_RAYCASTING, !mIsEnabled );
|
||||
}
|
||||
|
||||
void PxBody::setTransform( const MatrixF &transform )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::setTransform - The actor is null!" );
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
NxMat34 xfm;
|
||||
xfm.setRowMajor44( transform );
|
||||
mActor->setGlobalPose( xfm );
|
||||
|
||||
// If its dynamic we have more to do.
|
||||
if ( mActor->isDynamic() && !mActor->readBodyFlag( NX_BF_KINEMATIC ) )
|
||||
{
|
||||
mActor->setLinearVelocity( NxVec3( 0, 0, 0 ) );
|
||||
mActor->setAngularVelocity( NxVec3( 0, 0, 0 ) );
|
||||
mActor->wakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
void PxBody::applyCorrection( const MatrixF &transform )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::applyCorrection - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "PxBody::applyCorrection - This call is only for dynamics!" );
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
NxMat34 xfm;
|
||||
xfm.setRowMajor44( transform );
|
||||
mActor->setGlobalPose( xfm );
|
||||
}
|
||||
|
||||
void PxBody::applyImpulse( const Point3F &origin, const Point3F &force )
|
||||
{
|
||||
AssertFatal( mActor, "PxBody::applyImpulse - The actor is null!" );
|
||||
|
||||
// This sucks, but it has to happen if we want
|
||||
// to avoid write lock errors from PhysX right now.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
if ( mIsEnabled && isDynamic() )
|
||||
mActor->addForceAtPos( pxCast<NxVec3>( force ),
|
||||
pxCast<NxVec3>( origin ),
|
||||
NX_IMPULSE );
|
||||
}
|
||||
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _T3D_PHYSICS_PXBODY_H_
|
||||
#define _T3D_PHYSICS_PXBODY_H_
|
||||
|
||||
#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
|
||||
#include "T3D/physics/physicsBody.h"
|
||||
#endif
|
||||
#ifndef _PHYSICS_PHYSICSUSERDATA_H_
|
||||
#include "T3D/physics/physicsUserData.h"
|
||||
#endif
|
||||
#ifndef _REFBASE_H_
|
||||
#include "core/util/refBase.h"
|
||||
#endif
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "math/mMatrix.h"
|
||||
#endif
|
||||
|
||||
class PxWorld;
|
||||
class NxActor;
|
||||
class PxCollision;
|
||||
class NxMaterial;
|
||||
|
||||
|
||||
class PxBody : public PhysicsBody
|
||||
{
|
||||
protected:
|
||||
|
||||
/// The physics world we are in.
|
||||
PxWorld *mWorld;
|
||||
|
||||
/// The physics actor.
|
||||
NxActor *mActor;
|
||||
|
||||
/// The unshared local material used on all the
|
||||
/// shapes on this actor.
|
||||
NxMaterial *mMaterial;
|
||||
|
||||
/// We hold the collision reference as it contains
|
||||
/// allocated objects that we own and must free.
|
||||
StrongRefPtr<PxCollision> mColShape;
|
||||
|
||||
///
|
||||
MatrixF mInternalTransform;
|
||||
|
||||
/// The body flags set at creation time.
|
||||
U32 mBodyFlags;
|
||||
|
||||
/// Is true if this body is enabled and active
|
||||
/// in the simulation of the scene.
|
||||
bool mIsEnabled;
|
||||
|
||||
///
|
||||
void _releaseActor();
|
||||
|
||||
public:
|
||||
|
||||
PxBody();
|
||||
virtual ~PxBody();
|
||||
|
||||
// PhysicsObject
|
||||
virtual PhysicsWorld* getWorld();
|
||||
virtual void setTransform( const MatrixF &xfm );
|
||||
virtual MatrixF& getTransform( MatrixF *outMatrix );
|
||||
virtual Box3F getWorldBounds();
|
||||
virtual void setSimulationEnabled( bool enabled );
|
||||
virtual bool isSimulationEnabled() { return mIsEnabled; }
|
||||
|
||||
// PhysicsBody
|
||||
virtual bool init( PhysicsCollision *shape,
|
||||
F32 mass,
|
||||
U32 bodyFlags,
|
||||
SceneObject *obj,
|
||||
PhysicsWorld *world );
|
||||
virtual bool isDynamic() const;
|
||||
virtual PhysicsCollision* getColShape();
|
||||
virtual void setSleepThreshold( F32 linear, F32 angular );
|
||||
virtual void setDamping( F32 linear, F32 angular );
|
||||
virtual void getState( PhysicsState *outState );
|
||||
virtual F32 getMass() const;
|
||||
virtual Point3F getCMassPosition() const;
|
||||
virtual void setLinVelocity( const Point3F &vel );
|
||||
virtual void setAngVelocity( const Point3F &vel );
|
||||
virtual Point3F getLinVelocity() const;
|
||||
virtual Point3F getAngVelocity() const;
|
||||
virtual void setSleeping( bool sleeping );
|
||||
virtual void setMaterial( F32 restitution,
|
||||
F32 friction,
|
||||
F32 staticFriction );
|
||||
virtual void applyCorrection( const MatrixF &xfm );
|
||||
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
|
||||
};
|
||||
|
||||
#endif // _T3D_PHYSICS_PXBODY_H_
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PHYSX_CASTS_H_
|
||||
#define _PHYSX_CASTS_H_
|
||||
|
||||
#ifndef _MPOINT3_H_
|
||||
#include "math/mPoint3.h"
|
||||
#endif
|
||||
#ifndef _MBOX_H_
|
||||
#include "math/mBox.h"
|
||||
#endif
|
||||
#ifndef _MQUAT_H_
|
||||
#include "math/mQuat.h"
|
||||
#endif
|
||||
|
||||
|
||||
template <class T, class F> inline T pxCast( const F &from );
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline Point3F pxCast( const NxVec3 &vec )
|
||||
{
|
||||
return Point3F( vec.x, vec.y, vec.z );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline NxVec3 pxCast( const Point3F &point )
|
||||
{
|
||||
return NxVec3( point.x, point.y, point.z );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline QuatF pxCast( const NxQuat &quat )
|
||||
{
|
||||
/// The Torque quat has the opposite winding order.
|
||||
return QuatF( -quat.x, -quat.y, -quat.z, quat.w );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline NxQuat pxCast( const QuatF &quat )
|
||||
{
|
||||
/// The Torque quat has the opposite winding order.
|
||||
NxQuat result;
|
||||
result.setWXYZ( quat.w, -quat.x, -quat.y, -quat.z );
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline NxBounds3 pxCast( const Box3F &box )
|
||||
{
|
||||
NxBounds3 bounds;
|
||||
bounds.set( box.minExtents.x,
|
||||
box.minExtents.y,
|
||||
box.minExtents.z,
|
||||
box.maxExtents.x,
|
||||
box.maxExtents.y,
|
||||
box.maxExtents.z );
|
||||
return bounds;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Box3F pxCast( const NxBounds3 &bounds )
|
||||
{
|
||||
return Box3F( bounds.min.x,
|
||||
bounds.min.y,
|
||||
bounds.min.z,
|
||||
bounds.max.x,
|
||||
bounds.max.y,
|
||||
bounds.max.z );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline NxVec3 pxCast( const NxExtendedVec3 &xvec )
|
||||
{
|
||||
return NxVec3( xvec.x, xvec.y, xvec.z );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline NxExtendedVec3 pxCast( const NxVec3 &vec )
|
||||
{
|
||||
return NxExtendedVec3( vec.x, vec.y, vec.z );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline NxExtendedVec3 pxCast( const Point3F &point )
|
||||
{
|
||||
return NxExtendedVec3( point.x, point.y, point.z );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Point3F pxCast( const NxExtendedVec3 &xvec )
|
||||
{
|
||||
return Point3F( xvec.x, xvec.y, xvec.z );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
template<>
|
||||
inline NxBox pxCast( const NxExtendedBounds3 &exBounds )
|
||||
{
|
||||
NxExtendedVec3 center;
|
||||
exBounds.getCenter( center );
|
||||
NxVec3 extents;
|
||||
exBounds.getExtents( extents );
|
||||
|
||||
NxBox box;
|
||||
box.center.set( center.x, center.y, center.z );
|
||||
box.extents = extents;
|
||||
box.rot.id();
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline NxExtendedBounds3 pxCast( const NxBox &box )
|
||||
{
|
||||
AssertFatal( false, "Casting a NxBox to NxExtendedBounds3 is impossible without losing rotation data!" );
|
||||
return NxExtendedBounds3();
|
||||
}
|
||||
|
||||
#endif // _PHYSX_CASTS_H_
|
||||
|
|
@ -1,923 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxCloth.h"
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "lighting/lightQuery.h"
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#include "T3D/physics/physx/pxWorld.h"
|
||||
#include "T3D/physics/physx/pxStream.h"
|
||||
#include "T3D/physics/physx/pxCasts.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "materials/baseMatInstance.h"
|
||||
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1( PxCloth );
|
||||
|
||||
ConsoleDocClass( PxCloth,
|
||||
|
||||
"@brief Rectangular patch of cloth simulated by PhysX.\n\n"
|
||||
|
||||
"PxCloth is affected by other objects in the simulation but does not itself "
|
||||
"affect others, it is essentially a visual effect. Eg, shooting at cloth will "
|
||||
"disturb it but will not explode the projectile.\n\n"
|
||||
|
||||
"Be careful with the cloth size and resolution because it can easily become "
|
||||
"performance intensive to simulate. A single piece of cloth that is very "
|
||||
"large or high resolution is also much more expensive than multiple pieces "
|
||||
"that add up to the same number of verts.\n\n"
|
||||
|
||||
"Note that most field docs have been copied from their PhysX counterpart.\n\n"
|
||||
|
||||
"@ingroup Physics"
|
||||
);
|
||||
|
||||
enum PxClothAttachment {};
|
||||
DefineBitfieldType( PxClothAttachment );
|
||||
|
||||
ImplementBitfieldType( PxClothAttachment,
|
||||
"Soon to be deprecated\n"
|
||||
"@internal" )
|
||||
{ 0, "Bottom Right" },
|
||||
{ 1, "Bottom Left" },
|
||||
{ 2, "Top Right" },
|
||||
{ 3, "Top Left" },
|
||||
{ 4, "Top Center" },
|
||||
{ 5, "Bottom Center" },
|
||||
{ 6, "Right Center" },
|
||||
{ 7, "Left Center" },
|
||||
{ 8, "Top Edge" },
|
||||
{ 9, "Bottom Edge" },
|
||||
{ 10, "Right Edge" },
|
||||
{ 11, "Left Edge" }
|
||||
EndImplementBitfieldType;
|
||||
|
||||
|
||||
PxCloth::PxCloth()
|
||||
: mWorld( NULL ),
|
||||
mScene( NULL ),
|
||||
mMatInst( NULL )
|
||||
{
|
||||
mVertexRenderBuffer = NULL;
|
||||
mIndexRenderBuffer = NULL;
|
||||
|
||||
mMaxVertices = 0;
|
||||
mMaxIndices = 0;
|
||||
|
||||
mClothMesh = NULL;
|
||||
mCloth = NULL;
|
||||
|
||||
mPatchVerts.set( 8, 8 );
|
||||
mPatchSize.set( 8.0f, 8.0f );
|
||||
|
||||
mNetFlags.set( Ghostable | ScopeAlways );
|
||||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
|
||||
mReceiveBuffers.setToDefault();
|
||||
|
||||
mBendingEnabled = false;
|
||||
mDampingEnabled = false;
|
||||
mTriangleCollisionEnabled = false;
|
||||
mSelfCollisionEnabled = false;
|
||||
|
||||
mDensity = 1.0f;
|
||||
mThickness = 0.1f;
|
||||
mFriction = 0.25f;
|
||||
mBendingStiffness = 0.5f;
|
||||
mDampingCoefficient = 0.25f;
|
||||
|
||||
mAttachmentMask = 0;
|
||||
}
|
||||
|
||||
PxCloth::~PxCloth()
|
||||
{
|
||||
}
|
||||
|
||||
bool PxCloth::onAdd()
|
||||
{
|
||||
if ( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
// Cloth is only created on the client.
|
||||
if ( isClientObject() )
|
||||
{
|
||||
mWorld = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( "client" ) );
|
||||
|
||||
if ( !mWorld || !mWorld->getScene() )
|
||||
{
|
||||
Con::errorf( "PxCloth::onAdd() - PhysXWorld not initialized... cloth disabled!" );
|
||||
return true;
|
||||
}
|
||||
|
||||
mScene = mWorld->getScene();
|
||||
|
||||
mResetXfm = getTransform();
|
||||
|
||||
_createClothPatch();
|
||||
|
||||
PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxCloth::onPhysicsReset, 1053.0f );
|
||||
}
|
||||
|
||||
// On the server we use the static update
|
||||
// to setup the bounds of the cloth.
|
||||
if ( isServerObject() )
|
||||
_updateStaticCloth();
|
||||
|
||||
addToScene();
|
||||
|
||||
// Also the server object never ticks.
|
||||
if ( isServerObject() )
|
||||
setProcessTick( false );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxCloth::onRemove()
|
||||
{
|
||||
SAFE_DELETE( mMatInst );
|
||||
|
||||
if ( isClientObject() )
|
||||
{
|
||||
_releaseCloth();
|
||||
_releaseMesh();
|
||||
|
||||
PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxCloth::onPhysicsReset );
|
||||
}
|
||||
|
||||
removeFromScene();
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void PxCloth::onPhysicsReset( PhysicsResetEvent reset )
|
||||
{
|
||||
// Store the reset transform for later use.
|
||||
if ( reset == PhysicsResetEvent_Store )
|
||||
mResetXfm = getTransform();
|
||||
|
||||
// Recreate the cloth at the last reset position.
|
||||
_recreateCloth( mResetXfm );
|
||||
}
|
||||
|
||||
void PxCloth::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField( "material", TypeMaterialName, Offset( mMaterialName, PxCloth ),
|
||||
"@brief Name of the material to render.\n\n" );
|
||||
|
||||
addField( "samples", TypePoint2I, Offset( mPatchVerts, PxCloth ),
|
||||
"@brief The number of cloth vertices in width and length.\n\n"
|
||||
"At least two verts should be defined.\n\n");
|
||||
|
||||
addField( "size", TypePoint2F, Offset( mPatchSize, PxCloth ),
|
||||
"@brief The width and height of the cloth.\n\n" );
|
||||
|
||||
addField( "bending", TypeBool, Offset( mBendingEnabled, PxCloth ),
|
||||
"@brief Enables or disables bending resistance.\n\n"
|
||||
"Set the bending resistance through PxCloth::bendingStiffness." );
|
||||
|
||||
addField( "damping", TypeBool, Offset( mDampingEnabled, PxCloth ),
|
||||
"@brief Enable/disable damping of internal velocities.\n\n" );
|
||||
|
||||
addField( "triangleCollision", TypeBool, Offset( mTriangleCollisionEnabled, PxCloth ),
|
||||
"@brief Not supported in current release (according to PhysX docs).\n\n"
|
||||
"Enables or disables collision detection of cloth triangles against the scene. "
|
||||
"If not set, only collisions of cloth particles are detected. If set, "
|
||||
"collisions of cloth triangles are detected as well." );
|
||||
|
||||
addField( "selfCollision", TypeBool, Offset( mSelfCollisionEnabled, PxCloth ),
|
||||
"@brief Enables or disables self-collision handling within a single piece of cloth.\n\n" );
|
||||
|
||||
addField( "density", TypeF32, Offset( mDensity, PxCloth ),
|
||||
"@brief Density of the cloth (Mass per Area).\n\n" );
|
||||
|
||||
addField( "thickness", TypeF32, Offset( mThickness, PxCloth ),
|
||||
"@brief Value representing how thick the cloth is.\n\n"
|
||||
"The thickness is usually a fraction of the overall extent of the cloth and "
|
||||
"should not be set to a value greater than that. A good value is the maximal "
|
||||
"distance between two adjacent cloth particles in their rest pose. Visual "
|
||||
"artifacts or collision problems may appear if the thickness is too small.\n\n" );
|
||||
|
||||
addField( "friction", TypeF32, Offset( mFriction, PxCloth ),
|
||||
"@brief Friction coefficient in the range 0 to 1.\n\n"
|
||||
"Defines the damping of the velocities of cloth particles that are in contact." );
|
||||
|
||||
addField( "bendingStiffness", TypeF32, Offset( mBendingStiffness, PxCloth ),
|
||||
"@brief Bending stiffness of the cloth in the range 0 to 1.\n\n" );
|
||||
|
||||
addField( "dampingCoefficient", TypeF32, Offset( mDampingCoefficient, PxCloth ),
|
||||
"@brief Spring damping of the cloth in the range 0 to 1.\n\n" );
|
||||
|
||||
addField( "attachments", TYPEID< PxClothAttachment >(), Offset( mAttachmentMask, PxCloth ),
|
||||
"@brief Optional way to specify cloth verts that will be attached to the world position "
|
||||
"it is created at.\n\n" );
|
||||
|
||||
// Cloth doesn't support scale.
|
||||
removeField( "scale" );
|
||||
}
|
||||
|
||||
void PxCloth::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
|
||||
// Must have at least 2 verts.
|
||||
mPatchVerts.x = getMax( 2, mPatchVerts.x );
|
||||
mPatchVerts.y = getMax( 2, mPatchVerts.y );
|
||||
if ( isServerObject() )
|
||||
_updateStaticCloth();
|
||||
|
||||
setMaskBits( TransformMask | MaterialMask | ClothMask );
|
||||
}
|
||||
|
||||
U32 PxCloth::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
|
||||
{
|
||||
U32 retMask = Parent::packUpdate( conn, mask, stream );
|
||||
|
||||
if ( stream->writeFlag( mask & TransformMask ) )
|
||||
mathWrite( *stream, getTransform() );
|
||||
|
||||
if ( stream->writeFlag( mask & MaterialMask ) )
|
||||
stream->write( mMaterialName );
|
||||
|
||||
if ( stream->writeFlag( mask & ClothMask ) )
|
||||
{
|
||||
mathWrite( *stream, mPatchVerts );
|
||||
mathWrite( *stream, mPatchSize );
|
||||
|
||||
stream->write( mAttachmentMask );
|
||||
|
||||
stream->writeFlag( mBendingEnabled );
|
||||
stream->writeFlag( mDampingEnabled );
|
||||
stream->writeFlag( mTriangleCollisionEnabled );
|
||||
stream->writeFlag( mSelfCollisionEnabled );
|
||||
stream->write( mThickness );
|
||||
stream->write( mFriction );
|
||||
stream->write( mBendingStiffness );
|
||||
stream->write( mDampingCoefficient );
|
||||
|
||||
stream->write( mDensity );
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void PxCloth::unpackUpdate( NetConnection *conn, BitStream *stream )
|
||||
{
|
||||
Parent::unpackUpdate( conn, stream );
|
||||
|
||||
// TransformMask
|
||||
if ( stream->readFlag() )
|
||||
{
|
||||
MatrixF mat;
|
||||
mathRead( *stream, &mat );
|
||||
setTransform( mat );
|
||||
}
|
||||
|
||||
// MaterialMask
|
||||
if ( stream->readFlag() )
|
||||
{
|
||||
stream->read( &mMaterialName );
|
||||
SAFE_DELETE( mMatInst );
|
||||
}
|
||||
|
||||
// ClothMask
|
||||
if ( stream->readFlag() )
|
||||
{
|
||||
Point2I patchVerts;
|
||||
Point2F patchSize;
|
||||
mathRead( *stream, &patchVerts );
|
||||
mathRead( *stream, &patchSize );
|
||||
|
||||
if ( patchVerts != mPatchVerts ||
|
||||
!patchSize.equal( mPatchSize ) )
|
||||
{
|
||||
mPatchVerts = patchVerts;
|
||||
mPatchSize = patchSize;
|
||||
_releaseMesh();
|
||||
}
|
||||
|
||||
U32 attachMask;
|
||||
stream->read( &attachMask );
|
||||
if ( attachMask != mAttachmentMask )
|
||||
{
|
||||
mAttachmentMask = attachMask;
|
||||
_releaseCloth();
|
||||
}
|
||||
|
||||
mBendingEnabled = stream->readFlag();
|
||||
mDampingEnabled = stream->readFlag();
|
||||
mTriangleCollisionEnabled = stream->readFlag();
|
||||
mSelfCollisionEnabled = stream->readFlag();
|
||||
stream->read( &mThickness );
|
||||
stream->read( &mFriction );
|
||||
stream->read( &mBendingStiffness );
|
||||
stream->read( &mDampingCoefficient );
|
||||
|
||||
F32 density;
|
||||
stream->read( &density );
|
||||
if ( density != mDensity )
|
||||
{
|
||||
mDensity = density;
|
||||
_releaseCloth();
|
||||
}
|
||||
|
||||
if ( isClientObject() &&
|
||||
isProperlyAdded() &&
|
||||
mWorld &&
|
||||
!mCloth )
|
||||
{
|
||||
_createClothPatch();
|
||||
}
|
||||
|
||||
_updateClothProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void PxCloth::_recreateCloth( const MatrixF &transform )
|
||||
{
|
||||
if ( !mWorld )
|
||||
return;
|
||||
|
||||
mWorld->getPhysicsResults();
|
||||
|
||||
Parent::setTransform( transform );
|
||||
|
||||
_createClothPatch();
|
||||
}
|
||||
|
||||
void PxCloth::setTransform( const MatrixF &mat )
|
||||
{
|
||||
Parent::setTransform( mat );
|
||||
setMaskBits( TransformMask );
|
||||
|
||||
// Only need to do this if we're on the server
|
||||
// or if we're not currently ticking physics.
|
||||
if ( !mWorld || !mWorld->isEnabled() )
|
||||
_updateStaticCloth();
|
||||
}
|
||||
|
||||
void PxCloth::setScale( const VectorF &scale )
|
||||
{
|
||||
// Cloth doesn't support scale as it has plenty
|
||||
// of complications... sharing meshes, thickness,
|
||||
// transform origin, etc.
|
||||
return;
|
||||
}
|
||||
|
||||
void PxCloth::prepRenderImage( SceneRenderState *state )
|
||||
{
|
||||
if ( mIsVBDirty )
|
||||
_updateVBIB();
|
||||
|
||||
// Recreate the material if we need to.
|
||||
if ( !mMatInst )
|
||||
_initMaterial();
|
||||
|
||||
// If we don't have a material instance after the override then
|
||||
// we can skip rendering all together.
|
||||
BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst );
|
||||
if ( !matInst )
|
||||
return;
|
||||
|
||||
MeshRenderInst *ri = state->getRenderPass()->allocInst<MeshRenderInst>();
|
||||
|
||||
// If we need lights then set them up.
|
||||
if ( matInst->isForwardLit() )
|
||||
{
|
||||
LightQuery query;
|
||||
query.init( getWorldSphere() );
|
||||
query.getLights( ri->lights, 8 );
|
||||
}
|
||||
|
||||
ri->projection = state->getRenderPass()->allocSharedXform(RenderPassManager::Projection);
|
||||
ri->objectToWorld = &MatrixF::Identity;
|
||||
|
||||
ri->worldToCamera = state->getRenderPass()->allocSharedXform(RenderPassManager::View);
|
||||
ri->type = RenderPassManager::RIT_Mesh;
|
||||
|
||||
ri->primBuff = &mPrimBuffer;
|
||||
ri->vertBuff = &mVB;
|
||||
|
||||
ri->matInst = matInst;
|
||||
ri->prim = state->getRenderPass()->allocPrim();
|
||||
ri->prim->type = GFXTriangleList;
|
||||
ri->prim->minIndex = 0;
|
||||
ri->prim->startIndex = 0;
|
||||
ri->prim->numPrimitives = mNumIndices / 3;
|
||||
|
||||
ri->prim->startVertex = 0;
|
||||
ri->prim->numVertices = mNumVertices;
|
||||
|
||||
ri->defaultKey = matInst->getStateHint();
|
||||
ri->defaultKey2 = (U32)ri->vertBuff;
|
||||
|
||||
state->getRenderPass()->addInst( ri );
|
||||
}
|
||||
|
||||
void PxCloth::_releaseMesh()
|
||||
{
|
||||
if ( !mClothMesh )
|
||||
return;
|
||||
|
||||
_releaseCloth();
|
||||
|
||||
mWorld->releaseClothMesh( *mClothMesh );
|
||||
mClothMesh = NULL;
|
||||
|
||||
delete [] mVertexRenderBuffer;
|
||||
mVertexRenderBuffer = NULL;
|
||||
delete [] mIndexRenderBuffer;
|
||||
mIndexRenderBuffer = NULL;
|
||||
}
|
||||
|
||||
void PxCloth::_releaseCloth()
|
||||
{
|
||||
if ( !mCloth )
|
||||
return;
|
||||
|
||||
mWorld->releaseCloth( *mCloth );
|
||||
mCloth = NULL;
|
||||
}
|
||||
|
||||
void PxCloth::_initClothMesh()
|
||||
{
|
||||
// Make sure we can change the world.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
_releaseMesh();
|
||||
|
||||
// Must have at least 2 verts.
|
||||
mPatchVerts.x = getMax( 2, mPatchVerts.x );
|
||||
mPatchVerts.y = getMax( 2, mPatchVerts.y );
|
||||
|
||||
// Generate a uniform cloth patch,
|
||||
// w and h are the width and height,
|
||||
// d is the distance between vertices.
|
||||
mNumVertices = mPatchVerts.x * mPatchVerts.y;
|
||||
mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2;
|
||||
|
||||
NxClothMeshDesc desc;
|
||||
desc.numVertices = mNumVertices;
|
||||
desc.numTriangles = mNumIndices;
|
||||
desc.pointStrideBytes = sizeof(NxVec3);
|
||||
desc.triangleStrideBytes = 3*sizeof(NxU32);
|
||||
desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices);
|
||||
desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3);
|
||||
desc.flags = 0;
|
||||
|
||||
U32 i,j;
|
||||
NxVec3 *p = (NxVec3*)desc.points;
|
||||
|
||||
F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 );
|
||||
F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 );
|
||||
|
||||
for (i = 0; i < mPatchVerts.y; i++)
|
||||
{
|
||||
for (j = 0; j < mPatchVerts.x; j++)
|
||||
{
|
||||
p->set( patchWidth * j, 0.0f, patchHeight * i );
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
NxU32 *id = (NxU32*)desc.triangles;
|
||||
|
||||
for (i = 0; i < mPatchVerts.y-1; i++)
|
||||
{
|
||||
for (j = 0; j < mPatchVerts.x-1; j++)
|
||||
{
|
||||
NxU32 i0 = i * mPatchVerts.x + j;
|
||||
NxU32 i1 = i0 + 1;
|
||||
NxU32 i2 = i0 + mPatchVerts.x;
|
||||
NxU32 i3 = i2 + 1;
|
||||
if ( (j+i) % 2 )
|
||||
{
|
||||
*id++ = i0;
|
||||
*id++ = i2;
|
||||
*id++ = i1;
|
||||
*id++ = i1;
|
||||
*id++ = i2;
|
||||
*id++ = i3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*id++ = i0;
|
||||
*id++ = i2;
|
||||
*id++ = i3;
|
||||
*id++ = i0;
|
||||
*id++ = i3;
|
||||
*id++ = i1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NxCookingInterface *cooker = PxWorld::getCooking();
|
||||
cooker->NxInitCooking();
|
||||
|
||||
// Ok... cook the mesh!
|
||||
NxCookingParams params;
|
||||
params.targetPlatform = PLATFORM_PC;
|
||||
params.skinWidth = 0.01f;
|
||||
params.hintCollisionSpeed = false;
|
||||
|
||||
cooker->NxSetCookingParams( params );
|
||||
|
||||
PxMemStream cooked;
|
||||
|
||||
if ( cooker->NxCookClothMesh( desc, cooked ) )
|
||||
{
|
||||
cooked.resetPosition();
|
||||
mClothMesh = gPhysicsSDK->createClothMesh( cooked );
|
||||
}
|
||||
|
||||
cooker->NxCloseCooking();
|
||||
|
||||
NxVec3 *ppoints = (NxVec3*)desc.points;
|
||||
NxU32 *triangs = (NxU32*)desc.triangles;
|
||||
|
||||
dFree( ppoints );
|
||||
dFree( triangs );
|
||||
|
||||
if ( mClothMesh )
|
||||
_initReceiveBuffers();
|
||||
}
|
||||
|
||||
void PxCloth::_initReceiveBuffers()
|
||||
{
|
||||
// here we setup the buffers through which the SDK returns the dynamic cloth data
|
||||
// we reserve more memory for vertices than the initial mesh takes
|
||||
// because tearing creates new vertices
|
||||
// the SDK only tears cloth as long as there is room in these buffers
|
||||
|
||||
mMaxVertices = 3 * mNumVertices;
|
||||
mMaxIndices = 3 * mNumIndices;
|
||||
|
||||
// Allocate Render Buffer for Vertices if it hasn't been done before
|
||||
mVertexRenderBuffer = new GFXVertexPNTT[mMaxVertices];
|
||||
mIndexRenderBuffer = new U16[mMaxIndices];
|
||||
|
||||
mReceiveBuffers.verticesPosBegin = &(mVertexRenderBuffer[0].point);
|
||||
mReceiveBuffers.verticesNormalBegin = &(mVertexRenderBuffer[0].normal);
|
||||
mReceiveBuffers.verticesPosByteStride = sizeof(GFXVertexPNTT);
|
||||
mReceiveBuffers.verticesNormalByteStride = sizeof(GFXVertexPNTT);
|
||||
mReceiveBuffers.maxVertices = mMaxVertices;
|
||||
mReceiveBuffers.numVerticesPtr = &mNumVertices;
|
||||
|
||||
// the number of triangles is constant, even if the cloth is torn
|
||||
mReceiveBuffers.indicesBegin = &mIndexRenderBuffer[0];
|
||||
mReceiveBuffers.indicesByteStride = sizeof(NxU16);
|
||||
mReceiveBuffers.maxIndices = mMaxIndices;
|
||||
mReceiveBuffers.numIndicesPtr = &mNumIndices;
|
||||
|
||||
// Set up texture coords.
|
||||
|
||||
F32 dx = 1.0f / (F32)(mPatchVerts.x-1);
|
||||
F32 dy = 1.0f / (F32)(mPatchVerts.y-1);
|
||||
|
||||
F32 *coord = (F32*)&mVertexRenderBuffer[0].texCoord;
|
||||
for ( U32 i = 0; i < mPatchVerts.y; i++)
|
||||
{
|
||||
for ( U32 j = 0; j < mPatchVerts.x; j++)
|
||||
{
|
||||
coord[0] = j*dx;
|
||||
coord[1] = i*-dy;
|
||||
coord += sizeof( GFXVertexPNTT ) / sizeof( F32 );
|
||||
}
|
||||
}
|
||||
|
||||
// the parent index information would be needed if we used textured cloth
|
||||
//mReceiveBuffers.parentIndicesBegin = (U32*)malloc(sizeof(U32)*mMaxVertices);
|
||||
//mReceiveBuffers.parentIndicesByteStride = sizeof(U32);
|
||||
//mReceiveBuffers.maxParentIndices = mMaxVertices;
|
||||
//mReceiveBuffers.numParentIndicesPtr = &mNumParentIndices;
|
||||
|
||||
mMeshDirtyFlags = 0;
|
||||
mReceiveBuffers.dirtyBufferFlagsPtr = &mMeshDirtyFlags;
|
||||
|
||||
// init the buffers in case we want to draw the mesh
|
||||
// before the SDK as filled in the correct values
|
||||
|
||||
mReceiveBuffers.flags |= NX_MDF_16_BIT_INDICES;
|
||||
}
|
||||
|
||||
bool PxCloth::_createClothPatch()
|
||||
{
|
||||
// Make sure we have a mesh.
|
||||
if ( !mClothMesh )
|
||||
{
|
||||
_initClothMesh();
|
||||
if ( !mClothMesh )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we can change the world.
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
_releaseCloth();
|
||||
|
||||
NxClothDesc desc;
|
||||
desc.globalPose.setRowMajor44( getTransform() );
|
||||
desc.thickness = mThickness;
|
||||
desc.density = mDensity;
|
||||
desc.bendingStiffness = mBendingStiffness;
|
||||
desc.dampingCoefficient = mDampingCoefficient;
|
||||
desc.friction = mFriction;
|
||||
|
||||
if ( mBendingEnabled )
|
||||
desc.flags |= NX_CLF_BENDING;
|
||||
if ( mDampingEnabled )
|
||||
desc.flags |= NX_CLF_DAMPING;
|
||||
if ( mTriangleCollisionEnabled )
|
||||
desc.flags |= NX_CLF_TRIANGLE_COLLISION;
|
||||
if ( mSelfCollisionEnabled )
|
||||
desc.flags |= NX_CLF_SELFCOLLISION;
|
||||
|
||||
desc.clothMesh = mClothMesh;
|
||||
desc.meshData = mReceiveBuffers;
|
||||
|
||||
if ( !desc.isValid() )
|
||||
return false;
|
||||
|
||||
mCloth = mScene->createCloth( desc );
|
||||
mIsVBDirty = true;
|
||||
|
||||
_updateStaticCloth();
|
||||
_setupAttachments();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxCloth::_updateClothProperties()
|
||||
{
|
||||
if ( !mCloth )
|
||||
return;
|
||||
|
||||
mCloth->setThickness( mThickness );
|
||||
mCloth->setBendingStiffness( mBendingStiffness );
|
||||
mCloth->setDampingCoefficient( mDampingCoefficient );
|
||||
mCloth->setFriction( mFriction );
|
||||
|
||||
NxU32 flags = NX_CLF_GRAVITY; // TODO: Expose this?
|
||||
if ( mBendingEnabled )
|
||||
flags |= NX_CLF_BENDING;
|
||||
if ( mDampingEnabled )
|
||||
flags |= NX_CLF_DAMPING;
|
||||
if ( mTriangleCollisionEnabled )
|
||||
flags |= NX_CLF_TRIANGLE_COLLISION;
|
||||
if ( mSelfCollisionEnabled )
|
||||
flags |= NX_CLF_SELFCOLLISION;
|
||||
mCloth->setFlags( flags );
|
||||
}
|
||||
|
||||
void PxCloth::_initMaterial()
|
||||
{
|
||||
SAFE_DELETE( mMatInst );
|
||||
|
||||
Material *material = NULL;
|
||||
if (mMaterialName.isNotEmpty() )
|
||||
Sim::findObject( mMaterialName, material );
|
||||
|
||||
if ( material )
|
||||
mMatInst = material->createMatInstance();
|
||||
else
|
||||
mMatInst = MATMGR->createMatInstance( "WarningMaterial" );
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode( GFXCullNone );
|
||||
mMatInst->addStateBlockDesc( desc );
|
||||
|
||||
mMatInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<GFXVertexPNTT>() );
|
||||
}
|
||||
|
||||
void PxCloth::_updateVBIB()
|
||||
{
|
||||
PROFILE_SCOPE( PxCloth_UpdateVBIB );
|
||||
|
||||
mIsVBDirty = false;
|
||||
|
||||
// Don't set the VB if the vertex count is the same!
|
||||
if ( mVB.isNull() || mVB->mNumVerts < mNumVertices )
|
||||
mVB.set( GFX, mNumVertices, GFXBufferTypeDynamic );
|
||||
|
||||
GFXVertexPNTT *vert = mVertexRenderBuffer;
|
||||
GFXVertexPNTT *secondVert = NULL;
|
||||
|
||||
for ( U32 i = 0; i < mNumVertices; i++ )
|
||||
{
|
||||
if ( i % (U32)mPatchSize.x == 0 && i != 0 )
|
||||
{
|
||||
secondVert = vert;
|
||||
secondVert--;
|
||||
vert->tangent = -(vert->point - secondVert->point);
|
||||
}
|
||||
else
|
||||
{
|
||||
secondVert = vert;
|
||||
secondVert++;
|
||||
vert->tangent = vert->point - secondVert->point;
|
||||
}
|
||||
|
||||
vert->tangent.normalize();
|
||||
vert++;
|
||||
}
|
||||
|
||||
GFXVertexPNTT *vpPtr = mVB.lock();
|
||||
dMemcpy( vpPtr, mVertexRenderBuffer, sizeof( GFXVertexPNTT ) * mNumVertices );
|
||||
mVB.unlock();
|
||||
|
||||
if ( mPrimBuffer.isNull() || mPrimBuffer->mIndexCount < mNumIndices )
|
||||
mPrimBuffer.set( GFX, mNumIndices, 0, GFXBufferTypeDynamic );
|
||||
|
||||
U16 *pbPtr;
|
||||
mPrimBuffer.lock( &pbPtr );
|
||||
dMemcpy( pbPtr, mIndexRenderBuffer, sizeof( U16 ) * mNumIndices );
|
||||
mPrimBuffer.unlock();
|
||||
}
|
||||
|
||||
void PxCloth::_updateStaticCloth()
|
||||
{
|
||||
// Setup the unsimulated world bounds.
|
||||
mObjBox.set( 0, mThickness * -0.5f, 0,
|
||||
mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
|
||||
resetWorldBox();
|
||||
|
||||
// If we don't have render buffers then we're done.
|
||||
if ( !mVertexRenderBuffer || !mIndexRenderBuffer )
|
||||
return;
|
||||
|
||||
// Make sure the VBs are updated.
|
||||
mIsVBDirty = true;
|
||||
|
||||
F32 patchWidth = mPatchSize.x / (F32)(mPatchVerts.x-1);
|
||||
F32 patchHeight = mPatchSize.y / (F32)(mPatchVerts.y-1);
|
||||
|
||||
Point3F normal( 0, 1, 0 );
|
||||
getTransform().mulV( normal );
|
||||
|
||||
GFXVertexPNTT *vert = mVertexRenderBuffer;
|
||||
|
||||
for (U32 y = 0; y < mPatchVerts.y; y++)
|
||||
{
|
||||
for (U32 x = 0; x < mPatchVerts.x; x++)
|
||||
{
|
||||
vert->point.set( patchWidth * x, 0.0f, patchHeight * y );
|
||||
getTransform().mulP( vert->point );
|
||||
vert->normal = normal;
|
||||
vert++;
|
||||
}
|
||||
}
|
||||
|
||||
U16 *index = mIndexRenderBuffer;
|
||||
mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 6;
|
||||
U16 yOffset = mPatchVerts.x;
|
||||
|
||||
for (U32 y = 0; y < mPatchVerts.y-1; y++)
|
||||
{
|
||||
for (U32 x = 0; x < mPatchVerts.x-1; x++)
|
||||
{
|
||||
U16 base = x + ( yOffset * y );
|
||||
|
||||
index[0] = base;
|
||||
index[1] = base + 1;
|
||||
index[2] = base + 1 + yOffset;
|
||||
|
||||
index[3] = base + 1 + yOffset;
|
||||
index[4] = base + yOffset;
|
||||
index[5] = base;
|
||||
|
||||
index += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxCloth::processTick( const Move *move )
|
||||
{
|
||||
// Make sure the cloth is created.
|
||||
if ( !mCloth )
|
||||
return;
|
||||
|
||||
// TODO: Remove this hack!
|
||||
const bool enableWind = Con::getBoolVariable( "$PxCloth::enableWind", false );
|
||||
|
||||
if ( enableWind )
|
||||
{
|
||||
NxVec3 windVec( 25.0f + NxMath::rand(-5.0f, 5.0f),
|
||||
NxMath::rand(-5.0f, 5.0f),
|
||||
NxMath::rand(-5.0f, 5.0f) );
|
||||
|
||||
mCloth->setWindAcceleration( windVec );
|
||||
|
||||
// Wake the cloth!
|
||||
mCloth->wakeUp();
|
||||
}
|
||||
else
|
||||
mCloth->setWindAcceleration( NxVec3( 0, 0, 0 ) );
|
||||
|
||||
// Update bounds.
|
||||
if ( mWorld->getEnabled() )
|
||||
{
|
||||
NxBounds3 box;
|
||||
mCloth->getWorldBounds( box );
|
||||
|
||||
Point3F min = pxCast<Point3F>( box.min );
|
||||
Point3F max = pxCast<Point3F>( box.max );
|
||||
|
||||
mWorldBox.set( min, max );
|
||||
mObjBox = mWorldBox;
|
||||
|
||||
getWorldTransform().mul( mObjBox );
|
||||
}
|
||||
else
|
||||
{
|
||||
mObjBox.set( 0, mThickness * -0.5f, 0,
|
||||
mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
|
||||
}
|
||||
|
||||
resetWorldBox();
|
||||
|
||||
// Update the VB on the next render.
|
||||
mIsVBDirty = true;
|
||||
}
|
||||
|
||||
void PxCloth::interpolateTick( F32 delta )
|
||||
{
|
||||
// Nothing to do for now!
|
||||
}
|
||||
|
||||
bool PxCloth::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PxCloth::_setupAttachments()
|
||||
{
|
||||
if ( !mCloth || !mWorld )
|
||||
return;
|
||||
|
||||
// Set up attachments
|
||||
// Bottom right = bit 0
|
||||
// Bottom left = bit 1
|
||||
// Top right = bit 2
|
||||
// Top left = bit 3
|
||||
|
||||
if ( mAttachmentMask & BIT( 0 ) )
|
||||
mCloth->attachVertexToGlobalPosition( 0, mCloth->getPosition( 0 ) );
|
||||
if ( mAttachmentMask & BIT( 1 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, mCloth->getPosition( mPatchVerts.x-1 ) );
|
||||
if ( mAttachmentMask & BIT( 2 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ) );
|
||||
if ( mAttachmentMask & BIT( 3 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ) );
|
||||
if ( mAttachmentMask & BIT( 4 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ) );
|
||||
if ( mAttachmentMask & BIT( 5 ) )
|
||||
mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), mCloth->getPosition( (mPatchVerts.x/2) ) );
|
||||
if ( mAttachmentMask & BIT( 6 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ) );
|
||||
if ( mAttachmentMask & BIT( 7 ) )
|
||||
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ) );
|
||||
|
||||
if ( mAttachmentMask & BIT( 8 ) )
|
||||
for ( U32 i = mPatchVerts.x * mPatchVerts.y - mPatchVerts.x; i < mPatchVerts.x * mPatchVerts.y; i++ )
|
||||
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
|
||||
|
||||
if ( mAttachmentMask & BIT( 9 ) )
|
||||
for ( U32 i = 0; i < mPatchVerts.x; i++ )
|
||||
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
|
||||
|
||||
if ( mAttachmentMask & BIT( 10 ) )
|
||||
for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
|
||||
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
|
||||
|
||||
if ( mAttachmentMask & BIT( 11 ) )
|
||||
for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
|
||||
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXCLOTH_H_
|
||||
#define _PXCLOTH_H_
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "T3D/gameBase/gameBase.h"
|
||||
#endif
|
||||
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||
#include "gfx/gfxPrimitiveBuffer.h"
|
||||
#endif
|
||||
#ifndef _GFXVERTEXBUFFER_H_
|
||||
#include "gfx/gfxVertexBuffer.h"
|
||||
#endif
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physx/px.h"
|
||||
#endif
|
||||
#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#endif
|
||||
|
||||
class Material;
|
||||
class BaseMatInstance;
|
||||
class PxWorld;
|
||||
class NxScene;
|
||||
class NxClothMesh;
|
||||
class NxCloth;
|
||||
|
||||
|
||||
class PxCloth : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
enum MaskBits
|
||||
{
|
||||
TransformMask = Parent::NextFreeMask << 0,
|
||||
ClothMask = Parent::NextFreeMask << 1,
|
||||
MaterialMask = Parent::NextFreeMask << 3,
|
||||
NextFreeMask = Parent::NextFreeMask << 4
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
PxCloth();
|
||||
virtual ~PxCloth();
|
||||
|
||||
DECLARE_CONOBJECT( PxCloth );
|
||||
|
||||
// SimObject
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
static void initPersistFields();
|
||||
virtual void inspectPostApply();
|
||||
void onPhysicsReset( PhysicsResetEvent reset );
|
||||
|
||||
// NetObject
|
||||
virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
|
||||
virtual void unpackUpdate( NetConnection *conn, BitStream *stream );
|
||||
|
||||
// SceneObject
|
||||
virtual void setTransform( const MatrixF &mat );
|
||||
virtual void setScale( const VectorF &scale );
|
||||
virtual void prepRenderImage( SceneRenderState *state );
|
||||
|
||||
// GameBase
|
||||
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
||||
virtual void processTick( const Move *move );
|
||||
virtual void interpolateTick( F32 delta );
|
||||
|
||||
protected:
|
||||
|
||||
PxWorld *mWorld;
|
||||
|
||||
NxScene *mScene;
|
||||
|
||||
/// Cooked cloth collision mesh.
|
||||
NxClothMesh *mClothMesh;
|
||||
|
||||
/// The cloth actor used
|
||||
NxCloth *mCloth;
|
||||
|
||||
NxMeshData mReceiveBuffers;
|
||||
|
||||
bool mBendingEnabled;
|
||||
bool mDampingEnabled;
|
||||
bool mTriangleCollisionEnabled;
|
||||
bool mSelfCollisionEnabled;
|
||||
|
||||
F32 mDensity;
|
||||
F32 mThickness;
|
||||
F32 mFriction;
|
||||
F32 mBendingStiffness;
|
||||
F32 mStretchingStiffness;
|
||||
F32 mDampingCoefficient;
|
||||
F32 mCollisionResponseCoefficient;
|
||||
F32 mAttachmentResponseCoefficient;
|
||||
|
||||
U32 mAttachmentMask;
|
||||
|
||||
static EnumTable mAttachmentFlagTable;
|
||||
|
||||
String mMaterialName;
|
||||
SimObjectPtr<Material> mMaterial;
|
||||
BaseMatInstance *mMatInst;
|
||||
|
||||
String lookupName;
|
||||
|
||||
/// The output verts from the PhysX simulation.
|
||||
GFXVertexPNTT *mVertexRenderBuffer;
|
||||
|
||||
/// The output indices from the PhysX simulation.
|
||||
U16 *mIndexRenderBuffer;
|
||||
|
||||
U32 mMaxVertices;
|
||||
U32 mMaxIndices;
|
||||
|
||||
/// The number of indices in the cloth which
|
||||
/// is updated by the PhysX simulation.
|
||||
U32 mNumIndices;
|
||||
|
||||
/// The number of verts in the cloth which
|
||||
/// is updated by the PhysX simulation.
|
||||
U32 mNumVertices;
|
||||
|
||||
U32 mMeshDirtyFlags;
|
||||
bool mIsVBDirty;
|
||||
|
||||
GFXPrimitiveBufferHandle mPrimBuffer;
|
||||
GFXVertexBufferHandle<GFXVertexPNTT> mVB;
|
||||
|
||||
Point2I mPatchVerts;
|
||||
Point2F mPatchSize;
|
||||
|
||||
MatrixF mResetXfm;
|
||||
|
||||
void _initMaterial();
|
||||
|
||||
void _releaseMesh();
|
||||
void _releaseCloth();
|
||||
|
||||
bool _createClothPatch();
|
||||
|
||||
void _recreateCloth( const MatrixF &transform );
|
||||
|
||||
void _updateClothProperties();
|
||||
|
||||
void _initClothMesh();
|
||||
void _initReceiveBuffers();
|
||||
void _setupAttachments();
|
||||
|
||||
void _updateStaticCloth();
|
||||
|
||||
void _updateVBIB();
|
||||
};
|
||||
|
||||
#endif // _PXCLOTH_H_
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxCollision.h"
|
||||
|
||||
#include "math/mPoint3.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
#include "T3D/physics/physX/pxStream.h"
|
||||
|
||||
|
||||
PxCollision::PxCollision()
|
||||
{
|
||||
}
|
||||
|
||||
PxCollision::~PxCollision()
|
||||
{
|
||||
// We may be deleteting SDK data... so make
|
||||
// sure we have the the scene write lock.
|
||||
PxWorld::releaseWriteLocks();
|
||||
|
||||
for ( U32 i=0; i < mColShapes.size(); i++ )
|
||||
{
|
||||
// Check for special types which need cleanup.
|
||||
NxShapeDesc *desc = mColShapes[i];
|
||||
|
||||
if ( desc->getType() == NX_SHAPE_CONVEX )
|
||||
gPhysicsSDK->releaseConvexMesh( *((NxConvexShapeDesc*)desc)->meshData );
|
||||
else if ( desc->getType() == NX_SHAPE_MESH )
|
||||
gPhysicsSDK->releaseTriangleMesh( *((NxTriangleMeshShapeDesc*)desc)->meshData );
|
||||
else if ( desc->getType() == NX_SHAPE_HEIGHTFIELD )
|
||||
gPhysicsSDK->releaseHeightField( *((NxHeightFieldShapeDesc*)desc)->heightField );
|
||||
|
||||
// Delete the descriptor.
|
||||
delete desc;
|
||||
}
|
||||
|
||||
mColShapes.clear();
|
||||
}
|
||||
|
||||
void PxCollision::addPlane( const PlaneF &plane )
|
||||
{
|
||||
NxBoxShapeDesc *desc = new NxBoxShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->dimensions.set( 10000.0f, 10000.0f, 100.0f );
|
||||
desc->localPose.t.z = -100.0f;
|
||||
|
||||
// TODO: Fix rotation to match plane normal!
|
||||
//boxDesc->localPose.M.setColumn( 0, NxVec3( plane.x, plane.y, plane.z ) );
|
||||
//boxDesc->localPose.M.setColumn( 1, NxVec3( plane.x, plane.y, plane.z ) );
|
||||
//boxDesc->localPose.M.setColumn( 2, NxVec3( plane.x, plane.y, plane.z ) );
|
||||
|
||||
mColShapes.push_back( desc );
|
||||
}
|
||||
|
||||
void PxCollision::addBox( const Point3F &halfWidth,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
NxBoxShapeDesc *desc = new NxBoxShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->dimensions.set( halfWidth.x, halfWidth.y, halfWidth.z );
|
||||
desc->localPose.setRowMajor44( localXfm );
|
||||
mColShapes.push_back( desc );
|
||||
}
|
||||
|
||||
void PxCollision::addSphere( F32 radius,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
NxSphereShapeDesc *desc = new NxSphereShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->radius = radius;
|
||||
desc->localPose.setRowMajor44( localXfm );
|
||||
mColShapes.push_back( desc );
|
||||
}
|
||||
|
||||
void PxCollision::addCapsule( F32 radius,
|
||||
F32 height,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
NxCapsuleShapeDesc *desc = new NxCapsuleShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->radius = radius;
|
||||
desc->height = height;
|
||||
desc->localPose.setRowMajor44( localXfm );
|
||||
mColShapes.push_back( desc );
|
||||
}
|
||||
|
||||
bool PxCollision::addConvex( const Point3F *points,
|
||||
U32 count,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
// Mesh cooking requires that both
|
||||
// scenes not be write locked!
|
||||
PxWorld::releaseWriteLocks();
|
||||
|
||||
NxCookingInterface *cooker = PxWorld::getCooking();
|
||||
cooker->NxInitCooking();
|
||||
|
||||
NxConvexMeshDesc meshDesc;
|
||||
meshDesc.numVertices = count;
|
||||
meshDesc.pointStrideBytes = sizeof(Point3F);
|
||||
meshDesc.points = points;
|
||||
meshDesc.flags = NX_CF_COMPUTE_CONVEX | NX_CF_INFLATE_CONVEX;
|
||||
|
||||
// Cook it!
|
||||
NxCookingParams params;
|
||||
#ifdef TORQUE_OS_XENON
|
||||
params.targetPlatform = PLATFORM_XENON;
|
||||
#else
|
||||
params.targetPlatform = PLATFORM_PC;
|
||||
#endif
|
||||
params.skinWidth = 0.01f;
|
||||
params.hintCollisionSpeed = true;
|
||||
cooker->NxSetCookingParams( params );
|
||||
|
||||
PxMemStream stream;
|
||||
bool cooked = cooker->NxCookConvexMesh( meshDesc, stream );
|
||||
cooker->NxCloseCooking();
|
||||
|
||||
if ( !cooked )
|
||||
return false;
|
||||
|
||||
stream.resetPosition();
|
||||
NxConvexMesh *meshData = gPhysicsSDK->createConvexMesh( stream );
|
||||
if ( !meshData )
|
||||
return false;
|
||||
|
||||
NxConvexShapeDesc *desc = new NxConvexShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->meshData = meshData;
|
||||
desc->localPose.setRowMajor44( localXfm );
|
||||
mColShapes.push_back( desc );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxCollision::addTriangleMesh( const Point3F *vert,
|
||||
U32 vertCount,
|
||||
const U32 *index,
|
||||
U32 triCount,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
// Mesh cooking requires that both
|
||||
// scenes not be write locked!
|
||||
PxWorld::releaseWriteLocks();
|
||||
|
||||
NxCookingInterface *cooker = PxWorld::getCooking();
|
||||
cooker->NxInitCooking();
|
||||
|
||||
NxTriangleMeshDesc meshDesc;
|
||||
meshDesc.numVertices = vertCount;
|
||||
meshDesc.numTriangles = triCount;
|
||||
meshDesc.pointStrideBytes = sizeof(Point3F);
|
||||
meshDesc.triangleStrideBytes = 3*sizeof(U32);
|
||||
meshDesc.points = vert;
|
||||
meshDesc.triangles = index;
|
||||
meshDesc.flags = NX_MF_FLIPNORMALS;
|
||||
|
||||
// Cook it!
|
||||
NxCookingParams params;
|
||||
#ifdef TORQUE_OS_XENON
|
||||
params.targetPlatform = PLATFORM_XENON;
|
||||
#else
|
||||
params.targetPlatform = PLATFORM_PC;
|
||||
#endif
|
||||
params.skinWidth = 0.01f;
|
||||
params.hintCollisionSpeed = true;
|
||||
cooker->NxSetCookingParams( params );
|
||||
|
||||
PxMemStream stream;
|
||||
bool cooked = cooker->NxCookTriangleMesh( meshDesc, stream );
|
||||
cooker->NxCloseCooking();
|
||||
if ( !cooked )
|
||||
return false;
|
||||
|
||||
stream.resetPosition();
|
||||
NxTriangleMesh *meshData = gPhysicsSDK->createTriangleMesh( stream );
|
||||
if ( !meshData )
|
||||
return false;
|
||||
|
||||
NxTriangleMeshShapeDesc *desc = new NxTriangleMeshShapeDesc;
|
||||
desc->skinWidth = 0.01f;
|
||||
desc->meshData = meshData;
|
||||
desc->localPose.setRowMajor44( localXfm );
|
||||
mColShapes.push_back( desc );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxCollision::addHeightfield( const U16 *heights,
|
||||
const bool *holes,
|
||||
U32 blockSize,
|
||||
F32 metersPerSample,
|
||||
const MatrixF &localXfm )
|
||||
{
|
||||
// Since we're creating SDK level data we
|
||||
// have to have access to all active worlds.
|
||||
PxWorld::releaseWriteLocks();
|
||||
|
||||
// Init the heightfield description.
|
||||
NxHeightFieldDesc heightFieldDesc;
|
||||
heightFieldDesc.nbColumns = blockSize;
|
||||
heightFieldDesc.nbRows = blockSize;
|
||||
heightFieldDesc.thickness = -10.0f;
|
||||
heightFieldDesc.convexEdgeThreshold = 0;
|
||||
|
||||
// Allocate the samples.
|
||||
heightFieldDesc.samples = new NxU32[ blockSize * blockSize ];
|
||||
heightFieldDesc.sampleStride = sizeof(NxU32);
|
||||
NxU8 *currentByte = (NxU8*)heightFieldDesc.samples;
|
||||
|
||||
for ( U32 row = 0; row < blockSize; row++ )
|
||||
{
|
||||
const U32 tess = ( row + 1 ) % 2;
|
||||
|
||||
for ( U32 column = 0; column < blockSize; column++ )
|
||||
{
|
||||
NxHeightFieldSample *currentSample = (NxHeightFieldSample*)currentByte;
|
||||
|
||||
U32 index = ( blockSize - row - 1 ) + ( column * blockSize );
|
||||
currentSample->height = heights[ index ];
|
||||
|
||||
if ( holes && holes[ getMax( (S32)index - 1, 0 ) ] ) // row index for holes adjusted so PhysX collision shape better matches rendered terrain
|
||||
{
|
||||
currentSample->materialIndex0 = 0;
|
||||
currentSample->materialIndex1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSample->materialIndex0 = 1; //materialIds[0];
|
||||
currentSample->materialIndex1 = 1; //materialIds[0];
|
||||
}
|
||||
|
||||
currentSample->tessFlag = ( column + tess ) % 2;
|
||||
|
||||
currentByte += heightFieldDesc.sampleStride;
|
||||
}
|
||||
}
|
||||
|
||||
// Build it.
|
||||
NxHeightFieldShapeDesc *desc = new NxHeightFieldShapeDesc;
|
||||
desc->heightField = gPhysicsSDK->createHeightField( heightFieldDesc );
|
||||
|
||||
// Destroy the temp sample array.
|
||||
delete [] heightFieldDesc.samples;
|
||||
|
||||
// TerrainBlock uses a 11.5 fixed point height format
|
||||
// giving it a maximum height range of 0 to 2048.
|
||||
desc->heightScale = 0.03125f;
|
||||
|
||||
desc->rowScale = metersPerSample;
|
||||
desc->columnScale = metersPerSample;
|
||||
desc->materialIndexHighBits = 0;
|
||||
desc->skinWidth = 0.01f;
|
||||
|
||||
// Use the local pose to align the heightfield
|
||||
// to what Torque will expect.
|
||||
NxMat33 rotX;
|
||||
rotX.rotX( Float_HalfPi );
|
||||
NxMat33 rotZ;
|
||||
rotZ.rotZ( Float_Pi );
|
||||
NxMat34 rot;
|
||||
rot.M.multiply( rotZ, rotX );
|
||||
rot.t.set( ( blockSize - 1 ) * metersPerSample, 0, 0 );
|
||||
desc->localPose = rot;
|
||||
|
||||
mColShapes.push_back( desc );
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _T3D_PHYSICS_PXCOLLISION_H_
|
||||
#define _T3D_PHYSICS_PXCOLLISION_H_
|
||||
|
||||
#ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_
|
||||
#include "T3D/physics/physicsCollision.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
|
||||
class NxShapeDesc;
|
||||
|
||||
|
||||
class PxCollision : public PhysicsCollision
|
||||
{
|
||||
protected:
|
||||
|
||||
/// The collision representation.
|
||||
Vector<NxShapeDesc*> mColShapes;
|
||||
|
||||
/// Helper for adding shapes.
|
||||
//void _addShape( btCollisionShape *shape, const MatrixF &localXfm );
|
||||
|
||||
public:
|
||||
|
||||
PxCollision();
|
||||
virtual ~PxCollision();
|
||||
|
||||
/// Return the PhysX shape descriptions.
|
||||
const Vector<NxShapeDesc*>& getShapes() const { return mColShapes; }
|
||||
|
||||
// PhysicsCollision
|
||||
virtual void addPlane( const PlaneF &plane );
|
||||
virtual void addBox( const Point3F &halfWidth,
|
||||
const MatrixF &localXfm );
|
||||
virtual void addSphere( F32 radius,
|
||||
const MatrixF &localXfm );
|
||||
virtual void addCapsule( F32 radius,
|
||||
F32 height,
|
||||
const MatrixF &localXfm );
|
||||
virtual bool addConvex( const Point3F *points,
|
||||
U32 count,
|
||||
const MatrixF &localXfm );
|
||||
virtual bool addTriangleMesh( const Point3F *vert,
|
||||
U32 vertCount,
|
||||
const U32 *index,
|
||||
U32 triCount,
|
||||
const MatrixF &localXfm );
|
||||
virtual bool addHeightfield( const U16 *heights,
|
||||
const bool *holes,
|
||||
U32 blockSize,
|
||||
F32 metersPerSample,
|
||||
const MatrixF &localXfm );
|
||||
};
|
||||
|
||||
#endif // _T3D_PHYSICS_PXCOLLISION_H_
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxContactReporter.h"
|
||||
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
#include "T3D/physics/physicsUserData.h"
|
||||
#include "T3D/physics/physX/pxMultiActor.h"
|
||||
#include "platform/profiler.h"
|
||||
|
||||
|
||||
PxContactReporter::PxContactReporter()
|
||||
{
|
||||
}
|
||||
|
||||
PxContactReporter::~PxContactReporter()
|
||||
{
|
||||
}
|
||||
|
||||
void PxContactReporter::onContactNotify( NxContactPair &pair, NxU32 events )
|
||||
{
|
||||
PROFILE_SCOPE( PxContactReporter_OnContactNotify );
|
||||
|
||||
// For now we only care about start touch events.
|
||||
if ( !( events & NX_NOTIFY_ON_START_TOUCH ) )
|
||||
return;
|
||||
|
||||
// Skip if either actor is deleted.
|
||||
if ( pair.isDeletedActor[0] || pair.isDeletedActor[1] )
|
||||
return;
|
||||
|
||||
NxActor *actor0 = pair.actors[0];
|
||||
NxActor *actor1 = pair.actors[1];
|
||||
|
||||
PhysicsUserData *userData0 = PhysicsUserData::cast( actor0->userData );
|
||||
PhysicsUserData *userData1 = PhysicsUserData::cast( actor1->userData );
|
||||
|
||||
// Early out if we don't have user data or signals to notify.
|
||||
if ( ( !userData0 || userData0->getContactSignal().isEmpty() ) &&
|
||||
( !userData1 || userData1->getContactSignal().isEmpty() ) )
|
||||
return;
|
||||
|
||||
// Get an average contact point.
|
||||
U32 points = 0;
|
||||
NxVec3 hitPoint( 0.0f );
|
||||
NxContactStreamIterator iter( pair.stream );
|
||||
while( iter.goNextPair() )
|
||||
{
|
||||
while( iter.goNextPatch() )
|
||||
{
|
||||
while( iter.goNextPoint() )
|
||||
{
|
||||
hitPoint += iter.getPoint();
|
||||
++points;
|
||||
}
|
||||
}
|
||||
}
|
||||
hitPoint /= (F32)points;
|
||||
|
||||
if ( userData0 )
|
||||
userData0->getContactSignal().trigger( userData0,
|
||||
userData1,
|
||||
pxCast<Point3F>( hitPoint ),
|
||||
pxCast<Point3F>( pair.sumNormalForce ) );
|
||||
|
||||
if ( userData1 )
|
||||
userData1->getContactSignal().trigger( userData1,
|
||||
userData0,
|
||||
pxCast<Point3F>( hitPoint ),
|
||||
pxCast<Point3F>( -pair.sumNormalForce ) );
|
||||
}
|
||||
|
||||
bool PxUserNotify::onJointBreak( NxReal breakingForce, NxJoint &brokenJoint )
|
||||
{
|
||||
PROFILE_SCOPE( PxUserNotify_OnJointBreak );
|
||||
|
||||
PxUserData *userData = PxUserData::getData( brokenJoint );
|
||||
|
||||
if ( userData )
|
||||
userData->getOnJointBreakSignal().trigger( breakingForce, brokenJoint );
|
||||
|
||||
// NOTE: Returning true here will tell the
|
||||
// PhysX SDK to delete the joint, which will
|
||||
// cause MANY problems if any of the user app's
|
||||
// objects still hold references to it.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXCONTACTREPORTER_H_
|
||||
#define _PXCONTACTREPORTER_H_
|
||||
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#endif
|
||||
|
||||
|
||||
class PxContactReporter : public NxUserContactReport
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual void onContactNotify( NxContactPair& pair, NxU32 events );
|
||||
|
||||
public:
|
||||
|
||||
PxContactReporter();
|
||||
virtual ~PxContactReporter();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PxUserNotify : public NxUserNotify
|
||||
{
|
||||
public:
|
||||
virtual bool onJointBreak( NxReal breakingForce, NxJoint &brokenJoint );
|
||||
virtual void onWake( NxActor **actors, NxU32 count ) {}
|
||||
virtual void onSleep ( NxActor **actors, NxU32 count ) {}
|
||||
};
|
||||
|
||||
|
||||
#endif // _PXCONTACTREPORTER_H_
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physx/pxFluid.h"
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#include "T3D/physics/physx/pxWorld.h"
|
||||
#include "T3D/physics/physx/pxCasts.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1( PxFluid );
|
||||
|
||||
ConsoleDocClass( PxFluid,
|
||||
"@brief Experimental and unfinished Torque wrapper class for NxFluid.\n\n"
|
||||
"@internal\n"
|
||||
);
|
||||
|
||||
PxFluid::PxFluid()
|
||||
: mWorld( NULL ),
|
||||
mScene( NULL ),
|
||||
mParticles( NULL ),
|
||||
mFluid( NULL ),
|
||||
mEmitter( NULL ),
|
||||
mParticleCount( 0 )
|
||||
{
|
||||
mNetFlags.set( Ghostable | ScopeAlways );
|
||||
mTypeMask |= StaticObjectType | StaticShapeObjectType;
|
||||
}
|
||||
|
||||
PxFluid::~PxFluid()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool PxFluid::onAdd()
|
||||
{
|
||||
if ( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
mWorld = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ) );
|
||||
|
||||
if ( !mWorld || !mWorld->getScene() )
|
||||
{
|
||||
Con::errorf( "PxMultiActor::onAdd() - PhysXWorld not initialized!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
mScene = mWorld->getScene();
|
||||
|
||||
if ( isClientObject() )
|
||||
_createFluid();
|
||||
|
||||
Point3F halfScale = Point3F::One * 0.5f;
|
||||
mObjBox.minExtents = -halfScale;
|
||||
mObjBox.maxExtents = halfScale;
|
||||
resetWorldBox();
|
||||
|
||||
addToScene();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxFluid::onRemove()
|
||||
{
|
||||
if ( isClientObject() )
|
||||
_destroyFluid();
|
||||
|
||||
removeFromScene();
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void PxFluid::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
void PxFluid::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
|
||||
setMaskBits( UpdateMask );
|
||||
}
|
||||
|
||||
U32 PxFluid::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
|
||||
{
|
||||
U32 retMask = Parent::packUpdate( conn, mask, stream );
|
||||
|
||||
if ( stream->writeFlag( mask & UpdateMask ) )
|
||||
{
|
||||
mathWrite( *stream, getTransform() );
|
||||
mathWrite( *stream, getScale() );
|
||||
|
||||
stream->write( mEmitter ? mEmitter->getRate() : 0 );
|
||||
}
|
||||
|
||||
stream->writeFlag( isProperlyAdded() && mask & ResetMask );
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void PxFluid::unpackUpdate( NetConnection *conn, BitStream *stream )
|
||||
{
|
||||
Parent::unpackUpdate( conn, stream );
|
||||
|
||||
// UpdateMask
|
||||
if ( stream->readFlag() )
|
||||
{
|
||||
MatrixF mat;
|
||||
mathRead( *stream, &mat );
|
||||
Point3F scale;
|
||||
mathRead( *stream, &scale );
|
||||
|
||||
setScale( scale );
|
||||
setTransform( mat );
|
||||
|
||||
F32 rate;
|
||||
stream->read( &rate );
|
||||
setRate( rate );
|
||||
}
|
||||
|
||||
// ResetMask
|
||||
if ( stream->readFlag() )
|
||||
resetParticles();
|
||||
}
|
||||
|
||||
void PxFluid::setTransform( const MatrixF &mat )
|
||||
{
|
||||
Parent::setTransform( mat );
|
||||
|
||||
if ( mEmitter )
|
||||
{
|
||||
NxMat34 nxMat;
|
||||
nxMat.setRowMajor44( mat );
|
||||
mEmitter->setGlobalPose( nxMat );
|
||||
}
|
||||
}
|
||||
|
||||
void PxFluid::setScale( const VectorF &scale )
|
||||
{
|
||||
Point3F lastScale = getScale();
|
||||
|
||||
Point3F halfScale = Point3F::One * 0.5f;
|
||||
mObjBox.minExtents = -halfScale;
|
||||
mObjBox.maxExtents = halfScale;
|
||||
resetWorldBox();
|
||||
|
||||
Parent::setScale( scale );
|
||||
|
||||
if ( lastScale != getScale() &&
|
||||
mEmitter )
|
||||
{
|
||||
_destroyFluid();
|
||||
_createFluid();
|
||||
}
|
||||
}
|
||||
|
||||
void PxFluid::prepRenderImage( SceneRenderState *state )
|
||||
{
|
||||
if ( !state->isDiffusePass() )
|
||||
return;
|
||||
|
||||
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
||||
ri->renderDelegate.bind( this, &PxFluid::renderObject );
|
||||
ri->type = RenderPassManager::RIT_Object;
|
||||
state->getRenderPass()->addInst( ri );
|
||||
}
|
||||
|
||||
void PxFluid::resetParticles()
|
||||
{
|
||||
if ( mEmitter )
|
||||
mEmitter->resetEmission( MAX_PARTICLES );
|
||||
setMaskBits( ResetMask );
|
||||
}
|
||||
|
||||
void PxFluid::setRate( F32 rate )
|
||||
{
|
||||
if ( mEmitter )
|
||||
mEmitter->setRate( rate );
|
||||
setMaskBits( UpdateMask );
|
||||
}
|
||||
|
||||
void PxFluid::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setBlend( true );
|
||||
desc.setZReadWrite( true, false );
|
||||
|
||||
for ( U32 i = 0; i < mParticleCount; i++ )
|
||||
{
|
||||
FluidParticle &particle = mParticles[i];
|
||||
Point3F pnt = pxCast<Point3F>( particle.position );
|
||||
|
||||
Box3F box( 0.2f );
|
||||
box.minExtents += pnt;
|
||||
box.maxExtents += pnt;
|
||||
|
||||
GFX->getDrawUtil()->drawCube( desc, box, ColorI::BLUE );
|
||||
}
|
||||
}
|
||||
|
||||
void PxFluid::_createFluid()
|
||||
{
|
||||
/*
|
||||
// Set structure to pass particles, and receive them after every simulation step
|
||||
NxParticleData particleData;
|
||||
particleData.numParticlesPtr = &mParticleCount;
|
||||
particleData.bufferPos = &mParticles[0].position.x;
|
||||
particleData.bufferPosByteStride = sizeof(FluidParticle);
|
||||
particleData.bufferVel = &mParticles[0].velocity.x;
|
||||
particleData.bufferVelByteStride = sizeof(FluidParticle);
|
||||
particleData.bufferLife = &mParticles[0].lifetime;
|
||||
particleData.bufferLifeByteStride = sizeof(FluidParticle);
|
||||
|
||||
// Create a fluid descriptor
|
||||
NxFluidDesc fluidDesc;
|
||||
fluidDesc.kernelRadiusMultiplier = 2.3f;
|
||||
fluidDesc.restParticlesPerMeter = 10.0f;
|
||||
fluidDesc.stiffness = 200.0f;
|
||||
fluidDesc.viscosity = 22.0f;
|
||||
fluidDesc.restDensity = 1000.0f;
|
||||
fluidDesc.damping = 0.0f;
|
||||
fluidDesc.simulationMethod = NX_F_SPH;
|
||||
fluidDesc.initialParticleData = particleData;
|
||||
fluidDesc.particlesWriteData = particleData;
|
||||
*/
|
||||
|
||||
NxFluidDesc fluidDesc;
|
||||
fluidDesc.setToDefault();
|
||||
fluidDesc.simulationMethod = NX_F_SPH;
|
||||
fluidDesc.maxParticles = MAX_PARTICLES;
|
||||
fluidDesc.restParticlesPerMeter = 50;
|
||||
fluidDesc.stiffness = 1;
|
||||
fluidDesc.viscosity = 6;
|
||||
fluidDesc.flags = NX_FF_VISUALIZATION|NX_FF_ENABLED;
|
||||
|
||||
mParticles = new FluidParticle[MAX_PARTICLES];
|
||||
dMemset( mParticles, 0, sizeof(FluidParticle) * MAX_PARTICLES );
|
||||
|
||||
NxParticleData &particleData = fluidDesc.particlesWriteData;
|
||||
|
||||
particleData.numParticlesPtr = &mParticleCount;
|
||||
particleData.bufferPos = &mParticles[0].position.x;
|
||||
particleData.bufferPosByteStride = sizeof(FluidParticle);
|
||||
particleData.bufferVel = &mParticles[0].velocity.x;
|
||||
particleData.bufferVelByteStride = sizeof(FluidParticle);
|
||||
particleData.bufferLife = &mParticles[0].lifetime;
|
||||
particleData.bufferLifeByteStride = sizeof(FluidParticle);
|
||||
|
||||
mFluid = mScene->createFluid( fluidDesc );
|
||||
|
||||
|
||||
//Create Emitter.
|
||||
NxFluidEmitterDesc emitterDesc;
|
||||
emitterDesc.setToDefault();
|
||||
emitterDesc.dimensionX = getScale().x;
|
||||
emitterDesc.dimensionY = getScale().y;
|
||||
emitterDesc.relPose.setColumnMajor44( getTransform() );
|
||||
emitterDesc.rate = 5.0f;
|
||||
emitterDesc.randomAngle = 0.1f;
|
||||
emitterDesc.fluidVelocityMagnitude = 6.5f;
|
||||
emitterDesc.maxParticles = 0;
|
||||
emitterDesc.particleLifetime = 4.0f;
|
||||
emitterDesc.type = NX_FE_CONSTANT_FLOW_RATE;
|
||||
emitterDesc.shape = NX_FE_ELLIPSE;
|
||||
mEmitter = mFluid->createEmitter(emitterDesc);
|
||||
}
|
||||
|
||||
void PxFluid::_destroyFluid()
|
||||
{
|
||||
delete[] mParticles;
|
||||
mScene->releaseFluid( *mFluid );
|
||||
mEmitter = NULL;
|
||||
}
|
||||
|
||||
ConsoleMethod( PxFluid, resetParticles, void, 2, 2, "" )
|
||||
{
|
||||
object->resetParticles();
|
||||
}
|
||||
|
||||
ConsoleMethod( PxFluid, setRate, void, 2, 2, "" )
|
||||
{
|
||||
object->setRate( dAtof(argv[2]) );
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXFLUID_H_
|
||||
#define _PXFLUID_H_
|
||||
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "scene/sceneObject.h"
|
||||
#endif
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physx/px.h"
|
||||
#endif
|
||||
|
||||
class BaseMatInstance;
|
||||
class PxWorld;
|
||||
class NxScene;
|
||||
|
||||
|
||||
class PxFluid : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
protected:
|
||||
|
||||
enum NetMasks
|
||||
{
|
||||
UpdateMask = Parent::NextFreeMask,
|
||||
ResetMask = Parent::NextFreeMask << 1,
|
||||
NextFreeMask = Parent::NextFreeMask << 2
|
||||
};
|
||||
|
||||
struct FluidParticle
|
||||
{
|
||||
NxVec3 position;
|
||||
NxVec3 velocity;
|
||||
NxReal density;
|
||||
NxReal lifetime;
|
||||
NxU32 id;
|
||||
NxVec3 collisionNormal;
|
||||
};
|
||||
|
||||
#define MAX_PARTICLES 100
|
||||
|
||||
public:
|
||||
|
||||
PxFluid();
|
||||
virtual ~PxFluid();
|
||||
|
||||
DECLARE_CONOBJECT( PxFluid );
|
||||
|
||||
// SimObject
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
static void initPersistFields();
|
||||
virtual void inspectPostApply();
|
||||
|
||||
// NetObject
|
||||
virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
|
||||
virtual void unpackUpdate( NetConnection *conn, BitStream *stream );
|
||||
|
||||
// SceneObject
|
||||
virtual void setTransform( const MatrixF &mat );
|
||||
virtual void setScale( const VectorF &scale );
|
||||
virtual void prepRenderImage( SceneRenderState *state );
|
||||
|
||||
void resetParticles();
|
||||
void setRate( F32 rate );
|
||||
|
||||
protected:
|
||||
|
||||
void renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
||||
|
||||
void _createFluid();
|
||||
void _destroyFluid();
|
||||
|
||||
protected:
|
||||
|
||||
PxWorld *mWorld;
|
||||
NxScene *mScene;
|
||||
|
||||
FluidParticle *mParticles;
|
||||
//NxParticleData *mParticleData;
|
||||
NxFluid *mFluid;
|
||||
U32 mParticleCount;
|
||||
NxFluidEmitter *mEmitter;
|
||||
};
|
||||
|
||||
#endif // _PXFLUID_H_
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/px.h"
|
||||
|
||||
#include "T3D/physics/physX/pxMaterial.h"
|
||||
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1( PxMaterial );
|
||||
|
||||
ConsoleDocClass( PxMaterial,
|
||||
|
||||
"@brief Defines a PhysX material assignable to a PxMaterial.\n\n"
|
||||
|
||||
"When two actors collide, the collision behavior that results depends on the material properties "
|
||||
"of the actors' surfaces. For example, the surface properties determine if the actors will or will "
|
||||
"not bounce, or if they will slide or stick. Currently, the only special feature supported by materials "
|
||||
"is anisotropic friction, but according to Nvidia, other effects such as moving surfaces and more types "
|
||||
"of friction are slotted for future release.\n\n"
|
||||
|
||||
"For more information, refer to Nvidia's PhysX docs.\n\n"
|
||||
|
||||
"@ingroup Physics"
|
||||
);
|
||||
|
||||
PxMaterial::PxMaterial()
|
||||
: mNxMat( NULL ),
|
||||
mNxMatId( -1 ),
|
||||
restitution( 0.0f ),
|
||||
staticFriction( 0.1f ),
|
||||
dynamicFriction( 0.95f ),
|
||||
mServer( false )
|
||||
{
|
||||
}
|
||||
|
||||
PxMaterial::~PxMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
void PxMaterial::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
}
|
||||
|
||||
void PxMaterial::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addGroup("PxMaterial");
|
||||
|
||||
addField( "restitution", TypeF32, Offset( restitution, PxMaterial ),
|
||||
"@brief Coeffecient of a bounce applied to the shape in response to a collision.\n\n"
|
||||
"A value of 0 makes the object bounce as little as possible, while higher values up to 1.0 result in more bounce.\n\n"
|
||||
"@note Values close to or above 1.0 may cause stability problems and/or increasing energy.");
|
||||
addField( "staticFriction", TypeF32, Offset( staticFriction, PxMaterial ),
|
||||
"@brief Coefficient of static %friction to be applied.\n\n"
|
||||
"Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
|
||||
"If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
|
||||
"A higher coefficient will require a larger force to start motion. "
|
||||
"@note This value should be larger than 0.\n\n");
|
||||
addField( "dynamicFriction", TypeF32, Offset( dynamicFriction, PxMaterial ),
|
||||
"@brief Coefficient of dynamic %friction to be applied.\n\n"
|
||||
"Dynamic %friction reduces the velocity of a moving object while it is in contact with a surface. "
|
||||
"A higher coefficient will result in a larger reduction in velocity. "
|
||||
"A shape's dynamicFriction should be equal to or larger than 0.\n\n");
|
||||
|
||||
endGroup("PxMaterial");
|
||||
}
|
||||
|
||||
void PxMaterial::onStaticModified( const char *slotName, const char *newValue )
|
||||
{
|
||||
if ( isProperlyAdded() && mNxMat != NULL )
|
||||
{
|
||||
mNxMat->setRestitution( restitution );
|
||||
mNxMat->setStaticFriction( staticFriction );
|
||||
mNxMat->setDynamicFriction( dynamicFriction );
|
||||
}
|
||||
}
|
||||
|
||||
bool PxMaterial::preload( bool server, String &errorBuffer )
|
||||
{
|
||||
mServer = server;
|
||||
|
||||
PxWorld *world = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( server ? "server" : "client" ) );
|
||||
|
||||
if ( !world )
|
||||
{
|
||||
// TODO: Error... in error buffer?
|
||||
return false;
|
||||
}
|
||||
|
||||
NxMaterialDesc material;
|
||||
material.restitution = restitution;
|
||||
material.staticFriction = staticFriction;
|
||||
material.dynamicFriction = dynamicFriction;
|
||||
|
||||
mNxMat = world->createMaterial( material );
|
||||
mNxMatId = mNxMat->getMaterialIndex();
|
||||
|
||||
if ( mNxMatId == -1 )
|
||||
{
|
||||
errorBuffer = "PxMaterial::preload() - unable to create material!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return Parent::preload( server, errorBuffer );
|
||||
}
|
||||
|
||||
void PxMaterial::packData( BitStream* stream )
|
||||
{
|
||||
Parent::packData( stream );
|
||||
|
||||
stream->write( restitution );
|
||||
stream->write( staticFriction );
|
||||
stream->write( dynamicFriction );
|
||||
}
|
||||
|
||||
void PxMaterial::unpackData( BitStream* stream )
|
||||
{
|
||||
Parent::unpackData( stream );
|
||||
|
||||
stream->read( &restitution );
|
||||
stream->read( &staticFriction );
|
||||
stream->read( &dynamicFriction );
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PHYSX_MATERIAL_H
|
||||
#define _PHYSX_MATERIAL_H
|
||||
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _DYNAMIC_CONSOLETYPES_H_
|
||||
#include "console/dynamicTypes.h"
|
||||
#endif
|
||||
|
||||
class NxMaterial;
|
||||
|
||||
class PxMaterial : public SimDataBlock
|
||||
{
|
||||
typedef SimDataBlock Parent;
|
||||
|
||||
protected:
|
||||
|
||||
F32 restitution;
|
||||
F32 staticFriction;
|
||||
F32 dynamicFriction;
|
||||
|
||||
NxMaterial *mNxMat;
|
||||
S32 mNxMatId;
|
||||
|
||||
bool mServer;
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT( PxMaterial );
|
||||
|
||||
PxMaterial();
|
||||
~PxMaterial();
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
virtual void onStaticModified( const char *slotName, const char *newValue );
|
||||
|
||||
bool preload( bool server, String &errorBuffer );
|
||||
virtual void packData( BitStream* stream );
|
||||
virtual void unpackData( BitStream* stream );
|
||||
|
||||
S32 getMaterialId() const { return mNxMatId; }
|
||||
|
||||
};
|
||||
|
||||
#endif // _PHYSX_MATERIAL_H
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,398 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXMULTIACTOR_H
|
||||
#define _PXMULTIACTOR_H
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "T3D/gameBase/gameBase.h"
|
||||
#endif
|
||||
#ifndef __RESOURCE_H__
|
||||
#include "core/resource.h"
|
||||
#endif
|
||||
#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#endif
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physx/px.h"
|
||||
#endif
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "core/strings/stringUnit.h"
|
||||
#endif
|
||||
#ifndef _PHYSICS_PHYSICSUSERDATA_H_
|
||||
#include "T3D/physics/physicsUserData.h"
|
||||
#endif
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
|
||||
|
||||
class TSShapeInstance;
|
||||
class BaseMatInstance;
|
||||
class PxMultiActor;
|
||||
class PxWorld;
|
||||
class PxMaterial;
|
||||
class NxScene;
|
||||
class NxActor;
|
||||
class NxShape;
|
||||
class NxCompartment;
|
||||
class NxJoint;
|
||||
class NxMat34;
|
||||
class NxVec3;
|
||||
class ParticleEmitterData;
|
||||
|
||||
|
||||
namespace NXU
|
||||
{
|
||||
class NxuPhysicsCollection;
|
||||
}
|
||||
|
||||
|
||||
class PxUserData : public PhysicsUserData
|
||||
{
|
||||
public:
|
||||
|
||||
/// The constructor.
|
||||
PxUserData()
|
||||
: PhysicsUserData(),
|
||||
mIsBroken( false ),
|
||||
mParticleEmitterData( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
static PxUserData* getData( const NxActor &actor )
|
||||
{
|
||||
PxUserData *result = (PxUserData*)actor.userData;
|
||||
|
||||
AssertFatal( !result || typeid( *result ) == typeid( PxUserData ),
|
||||
"PxUserData::getData - The pointer is the wrong type!" );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PxUserData* getData( const NxJoint &joint )
|
||||
{
|
||||
PxUserData *result = (PxUserData*)joint.userData;
|
||||
|
||||
AssertFatal( !result || typeid( *result ) == typeid( PxUserData ),
|
||||
"PxUserData::getData - The pointer is the wrong type!" );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef Signal<void(NxReal, NxJoint&)> JointBreakSignal;
|
||||
|
||||
JointBreakSignal& getOnJointBreakSignal() { return mOnJointBreakSignal; }
|
||||
|
||||
// Breakable stuff...
|
||||
Vector<NxActor*> mUnbrokenActors;
|
||||
Vector<NxActor*> mBrokenActors;
|
||||
Vector<NxMat34> mRelXfm;
|
||||
ParticleEmitterData *mParticleEmitterData;
|
||||
bool mIsBroken;
|
||||
JointBreakSignal mOnJointBreakSignal;
|
||||
};
|
||||
|
||||
|
||||
class ParticleEmitterData;
|
||||
|
||||
class PxMultiActorData : public GameBaseData
|
||||
{
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
|
||||
PxMultiActorData();
|
||||
virtual ~PxMultiActorData();
|
||||
|
||||
DECLARE_CONOBJECT(PxMultiActorData);
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
void packData(BitStream* stream);
|
||||
void unpackData(BitStream* stream);
|
||||
|
||||
bool preload( bool server, String &errorBuffer );
|
||||
//bool onAdd();
|
||||
|
||||
void allocPrimBuffer( S32 overrideSize = -1 );
|
||||
|
||||
bool _loadCollection( const UTF8 *path, bool isBinary );
|
||||
|
||||
void _onFileChanged( const Torque::Path &path );
|
||||
|
||||
void reload();
|
||||
|
||||
void dumpModel();
|
||||
|
||||
Signal<void(void)> mReloadSignal;
|
||||
|
||||
public:
|
||||
|
||||
// Rendering
|
||||
StringTableEntry shapeName;
|
||||
Resource<TSShape> shape;
|
||||
|
||||
PxMaterial *material;
|
||||
|
||||
/// Filename to load the physics actor from.
|
||||
StringTableEntry physXStream;
|
||||
|
||||
enum
|
||||
{
|
||||
NumMountPoints = 32,
|
||||
MaxCorrectionNodes = 2
|
||||
};
|
||||
|
||||
StringTableEntry correctionNodeNames[MaxCorrectionNodes];
|
||||
StringTableEntry mountNodeNames[NumMountPoints];
|
||||
S32 correctionNodes[MaxCorrectionNodes];
|
||||
S32 mountPointNode[NumMountPoints]; ///< Node index of mountPoint
|
||||
|
||||
/// If true no network corrections will
|
||||
/// be done during gameplay.
|
||||
bool noCorrection;
|
||||
|
||||
/// Physics collection that holds the actor
|
||||
/// and all associated shapes and data.
|
||||
NXU::NxuPhysicsCollection *collection;
|
||||
|
||||
bool createActors( NxScene *scene,
|
||||
NxCompartment *compartment,
|
||||
const NxMat34 *nxMat,
|
||||
const Point3F& scale,
|
||||
Vector<NxActor*> *outActors,
|
||||
Vector<NxShape*> *outShapes,
|
||||
Vector<NxJoint*> *outJoints,
|
||||
Vector<String> *outActorUserProperties,
|
||||
Vector<String> *outJointUserProperties );
|
||||
|
||||
/// Angular and Linear Drag (dampening) is scaled by this when in water.
|
||||
F32 waterDragScale;
|
||||
|
||||
/// The density of this object (for purposes of buoyancy calculation only).
|
||||
F32 buoyancyDensity;
|
||||
|
||||
F32 angularDrag;
|
||||
F32 linearDrag;
|
||||
|
||||
/// If this flag is set to true,
|
||||
/// the physics actors will only be
|
||||
/// created on the client, and the server
|
||||
/// object is only responsible for ghosting.
|
||||
/// Objects with this flag set will never stop
|
||||
/// the physics player from moving through them.
|
||||
bool clientOnly;
|
||||
|
||||
bool singlePlayerOnly;
|
||||
|
||||
/// When applyImpulse is passed a force of this magnitude or greater
|
||||
/// any actors hit by the force vector that have broken versions
|
||||
/// will become 'broken'.
|
||||
F32 breakForce;
|
||||
};
|
||||
|
||||
|
||||
class PxMultiActor : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
enum MaskBits
|
||||
{
|
||||
MoveMask = Parent::NextFreeMask << 0,
|
||||
WarpMask = Parent::NextFreeMask << 1,
|
||||
LightMask = Parent::NextFreeMask << 2,
|
||||
SleepMask = Parent::NextFreeMask << 3,
|
||||
ForceSleepMask = Parent::NextFreeMask << 4,
|
||||
ImpulseMask = Parent::NextFreeMask << 5,
|
||||
UpdateMask = Parent::NextFreeMask << 6,
|
||||
MountedMask = Parent::NextFreeMask << 7,
|
||||
NextFreeMask = Parent::NextFreeMask << 8
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
PxMultiActor();
|
||||
|
||||
DECLARE_CONOBJECT( PxMultiActor );
|
||||
static void initPersistFields();
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
void inspectPostApply();
|
||||
void onPhysicsReset( PhysicsResetEvent reset );
|
||||
void onStaticModified( const char *slotName, const char *newValue );
|
||||
void onDeleteNotify( SimObject *obj );
|
||||
|
||||
// NetObject
|
||||
U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
|
||||
void unpackUpdate( NetConnection *conn, BitStream *stream );
|
||||
|
||||
// SceneObject
|
||||
void prepRenderImage( SceneRenderState *state );
|
||||
void setScale( const VectorF &scale );
|
||||
void setTransform( const MatrixF &mat );
|
||||
virtual void mountObject( SceneObject *obj, U32 node );
|
||||
virtual void unmountObject( SceneObject *obj );
|
||||
virtual void getMountTransform( U32 mountPoint, MatrixF *mat );
|
||||
virtual void getRenderMountTransform( U32 index, MatrixF *mat );
|
||||
|
||||
// GameBase
|
||||
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
||||
virtual void processTick( const Move *move );
|
||||
virtual void interpolateTick( F32 delta );
|
||||
virtual void applyImpulse( const Point3F &pos, const VectorF &vec );
|
||||
virtual void applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude );
|
||||
|
||||
/// PxMultiActor
|
||||
/// @{
|
||||
|
||||
/// Set visibility of all broken/unbroken meshes to match this state.
|
||||
void setAllBroken( bool isBroken );
|
||||
|
||||
/// Sets up actors and meshes associated with the passed joint to reflect
|
||||
/// the desired state.
|
||||
void setBroken( const NxMat34 &parentPose,
|
||||
const NxVec3 &parentVel,
|
||||
PxUserData *userData,
|
||||
bool isBroken );
|
||||
|
||||
///
|
||||
void setMeshHidden( String namePrefix, bool hidden );
|
||||
|
||||
void setAllHidden( bool hide );
|
||||
|
||||
void listMeshes( const String &state ) const;
|
||||
|
||||
void _onJointBreak( NxReal breakForce, NxJoint &brokenJoint );
|
||||
|
||||
void _onContact( PhysicsUserData *us,
|
||||
PhysicsUserData *them,
|
||||
const Point3F &hitPoint,
|
||||
const Point3F &hitForce );
|
||||
|
||||
void applyWarp( const MatrixF& mat, bool interpRender, bool sweep );
|
||||
|
||||
void getDynamicXfms( PxMultiActor *srcObj, F32 dt );
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
|
||||
/// This creates the physics objects.
|
||||
bool _createActors( const MatrixF &xfm );
|
||||
|
||||
/// Creates a PxUserData for a joint and parses userProperties into it.
|
||||
PxUserData* _createJointUserData( NxJoint *joint, String &userProperties );
|
||||
|
||||
/// Creates a PxUserData and parses userProperties into it.
|
||||
PxUserData* _createActorUserData( NxActor *actor, String &userProperties );
|
||||
|
||||
/// Called to cleanup the physics objects.
|
||||
void _destroyActors();
|
||||
|
||||
NxActor* _findActor( const String &actorName ) const;
|
||||
|
||||
/// Get the corresponding meshName for a given actor.
|
||||
String _getMeshName( const NxActor *actor ) const;
|
||||
|
||||
///
|
||||
void _updateBounds();
|
||||
|
||||
void _updateContainerForces();
|
||||
|
||||
void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
||||
|
||||
void onFileNotify();
|
||||
|
||||
void _applyActorRadialForce( NxActor *inActor, const NxVec3 &origin, F32 radius, F32 magnitude );
|
||||
|
||||
void _updateDeltas( bool clearDelta );
|
||||
|
||||
bool _getNodeTransform( U32 nodeIdx, MatrixF *outXfm );
|
||||
|
||||
protected:
|
||||
|
||||
PxMultiActorData *mDataBlock;
|
||||
|
||||
PxWorld *mWorld;
|
||||
|
||||
Vector<NxActor*> mActors;
|
||||
Vector<NxActor*> mMappedActors;
|
||||
Vector<S32> mMappedToActorIndex;
|
||||
Vector<S32> mMappedActorDL;
|
||||
Vector<NxJoint*> mJoints;
|
||||
Vector<NxShape*> mShapes;
|
||||
|
||||
/// This is the root actor whose transform is the
|
||||
/// transform of this SceneObject.
|
||||
NxActor *mRootActor;
|
||||
|
||||
TSShapeInstance *mShapeInstance;
|
||||
Resource<TSShape> mDebrisShape;
|
||||
|
||||
struct Delta
|
||||
{
|
||||
Point3F pos;
|
||||
Point3F lastPos;
|
||||
QuatF rot;
|
||||
QuatF lastRot;
|
||||
};
|
||||
|
||||
Delta mDelta;
|
||||
|
||||
Vector<Delta> mActorDeltas;
|
||||
|
||||
/// The transform of this actor when it was first
|
||||
/// created. It is used to reset the physics state
|
||||
/// when the editor is enabled.
|
||||
MatrixF mResetXfm;
|
||||
|
||||
|
||||
/// The userdata object assigned to all actors
|
||||
/// and joints of this multi-actor.
|
||||
//PxUserData mUserData;
|
||||
|
||||
///
|
||||
//Vector<MatrixF> mRelXfms;
|
||||
|
||||
/// This is the scale the actors were built at and
|
||||
/// is used to decide if we need to recreate them.
|
||||
VectorF mActorScale;
|
||||
//F32 mBuildAngDrag;
|
||||
//F32 mBuildLinDrag;
|
||||
|
||||
VectorF mStartImpulse;
|
||||
|
||||
bool mDebugRender;
|
||||
|
||||
/// A helper set to true if is a client object and
|
||||
/// is a singlePlayerOnly object.
|
||||
bool mIsDummy;
|
||||
|
||||
/// Helper for
|
||||
bool mBroken;
|
||||
};
|
||||
|
||||
#endif // _PXMULTIACTOR_H
|
||||
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxPlayer.h"
|
||||
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
#include "collision/collision.h"
|
||||
//#include "gfx/gfxDrawUtil.h"
|
||||
//#include "sim/netConnection.h"
|
||||
|
||||
|
||||
PxPlayer::PxPlayer()
|
||||
: PhysicsPlayer(),
|
||||
mController( NULL ),
|
||||
mWorld( NULL ),
|
||||
mObject( NULL ),
|
||||
mSkinWidth( 0.1f ),
|
||||
mOriginOffset( 0.0f )
|
||||
{
|
||||
PHYSICSMGR->getPhysicsResetSignal().notify( this, &PxPlayer::_onPhysicsReset );
|
||||
}
|
||||
|
||||
PxPlayer::~PxPlayer()
|
||||
{
|
||||
_releaseController();
|
||||
PHYSICSMGR->getPhysicsResetSignal().remove( this, &PxPlayer::_onPhysicsReset );
|
||||
}
|
||||
|
||||
void PxPlayer::_releaseController()
|
||||
{
|
||||
if ( mController )
|
||||
{
|
||||
mController->getActor()->userData = NULL;
|
||||
mWorld->getStaticChangedSignal().remove( this, &PxPlayer::_onStaticChanged );
|
||||
mWorld->releaseController( *mController );
|
||||
mController = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void PxPlayer::init( const char *type,
|
||||
const Point3F &size,
|
||||
F32 runSurfaceCos,
|
||||
F32 stepHeight,
|
||||
SceneObject *obj,
|
||||
PhysicsWorld *world )
|
||||
{
|
||||
AssertFatal( obj, "PxPlayer::init - Got a null scene object!" );
|
||||
AssertFatal( world, "PxPlayer::init - Got a null world!" );
|
||||
AssertFatal( dynamic_cast<PxWorld*>( world ), "PxPlayer::init - The world is the wrong type!" );
|
||||
|
||||
// Cleanup any previous controller.
|
||||
_releaseController();
|
||||
|
||||
mObject = obj;
|
||||
mWorld = (PxWorld*)world;
|
||||
mOriginOffset = size.z * 0.5f;
|
||||
|
||||
//if ( dStricmp( type, "Capsule" ) == 0 )
|
||||
{
|
||||
NxCapsuleControllerDesc desc;
|
||||
desc.skinWidth = 0.05f; // Expose?
|
||||
desc.radius = getMax( size.x, size.y ) * 0.5f;
|
||||
desc.radius -= desc.skinWidth;
|
||||
desc.height = size.z - ( desc.radius * 2.0f );
|
||||
desc.height -= desc.skinWidth * 2.0f;
|
||||
|
||||
desc.climbingMode = CLIMB_CONSTRAINED;
|
||||
desc.position.set( 0, 0, 0 );
|
||||
desc.upDirection = NX_Z;
|
||||
desc.callback = this; // TODO: Fix this as well!
|
||||
desc.slopeLimit = runSurfaceCos;
|
||||
desc.stepOffset = stepHeight;
|
||||
mController = mWorld->createController( desc );
|
||||
}
|
||||
//else
|
||||
{
|
||||
//mColShape = new btBoxShape( btVector3( 0.5f, 0.5f, 1.0f ) );
|
||||
//mOriginOffset = 1.0f;
|
||||
}
|
||||
|
||||
mWorld->getStaticChangedSignal().notify( this, &PxPlayer::_onStaticChanged );
|
||||
|
||||
// Put the kinematic actor on group 29.
|
||||
NxActor *kineActor = mController->getActor();
|
||||
kineActor->setGroup( 29 );
|
||||
NxShape *const *shapes = kineActor->getShapes();
|
||||
for ( U32 i=0; i < kineActor->getNbShapes(); i++ )
|
||||
shapes[i]->setGroup( 29 );
|
||||
|
||||
mUserData.setObject( obj );
|
||||
kineActor->userData = &mUserData;
|
||||
}
|
||||
|
||||
void PxPlayer::_onStaticChanged()
|
||||
{
|
||||
mController->reportSceneChanged();
|
||||
}
|
||||
|
||||
void PxPlayer::_onPhysicsReset( PhysicsResetEvent reset )
|
||||
{
|
||||
// The PhysX controller will crash out if it doesn't clear its
|
||||
// list of static elements when they are deleted. By calling this
|
||||
// on physics events we clear the cache and we don't get crashes.
|
||||
//
|
||||
// This all depends on not doing moves and sweeps when the
|
||||
// simulation is paused... we need to stop operating.
|
||||
|
||||
if ( mController )
|
||||
mController->reportSceneChanged();
|
||||
}
|
||||
|
||||
Point3F PxPlayer::move( const VectorF &disp, CollisionList &outCol )
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::move - The controller is null!" );
|
||||
|
||||
// Return the last position if the simulation is stopped.
|
||||
//
|
||||
// See PxPlayer::_onPhysicsReset
|
||||
if ( !mWorld->isEnabled() )
|
||||
{
|
||||
Point3F newPos = pxCast<Point3F>( mController->getDebugPosition() );
|
||||
newPos.z -= mOriginOffset;
|
||||
//outCol->point = newPos;
|
||||
//outCol->normal.set( 0, 0, 1 );
|
||||
return newPos;
|
||||
}
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
mCollisionList = &outCol;
|
||||
|
||||
// PhysX 2.8.4 checks up an up displacement and if found will assume
|
||||
// the player is flying and remove the step offset. If we have a small
|
||||
// z displacement here, zero it out.
|
||||
NxVec3 dispNx( disp.x, disp.y, disp.z );
|
||||
if (mIsZero(disp.z))
|
||||
dispNx.z = 0.0f;
|
||||
|
||||
NxU32 activeGroups = 0xFFFFFFFF;
|
||||
activeGroups &= ~( 1<<31 ); // Skip activeGroup for triggers ( 31 )
|
||||
activeGroups &= ~( 1<<30 ); // Skip activeGroup for debris / non interactive dynamics ( 30 )
|
||||
|
||||
NxU32 collisionFlags = NXCC_COLLISION_SIDES | NXCC_COLLISION_DOWN | NXCC_COLLISION_UP;
|
||||
|
||||
mController->move( dispNx, activeGroups, 0.0001f, collisionFlags );
|
||||
|
||||
Point3F newPos = pxCast<Point3F>( mController->getDebugPosition() );
|
||||
newPos.z -= mOriginOffset;
|
||||
|
||||
mCollisionList = NULL;
|
||||
|
||||
return newPos;
|
||||
}
|
||||
|
||||
NxControllerAction PxPlayer::onShapeHit( const NxControllerShapeHit& hit )
|
||||
{
|
||||
if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions)
|
||||
return NX_ACTION_NONE;
|
||||
|
||||
NxActor *actor = &hit.shape->getActor();
|
||||
PhysicsUserData *userData = PhysicsUserData::cast( actor->userData );
|
||||
|
||||
if ( actor->readActorFlag( NX_AF_DISABLE_RESPONSE ) )
|
||||
return NX_ACTION_NONE;
|
||||
|
||||
// Fill out the Collision
|
||||
// structure for use later.
|
||||
Collision &col = mCollisionList->increment();
|
||||
dMemset( &col, 0, sizeof( col ) );
|
||||
|
||||
col.normal = pxCast<Point3F>( hit.worldNormal );
|
||||
col.point.set( hit.worldPos.x, hit.worldPos.y, hit.worldPos.z );
|
||||
col.distance = hit.length;
|
||||
if ( userData )
|
||||
col.object = userData->getObject();
|
||||
|
||||
// If the collision direction is sideways then modify the collision normal
|
||||
// to remove any z component. This takes care of any sideways collisions
|
||||
// with the round bottom of the capsule when it comes to the Player class
|
||||
// velocity calculations. We want all sideways collisions to be treated
|
||||
// as if they hit the side of a cylinder.
|
||||
if (mIsZero(hit.dir.z))
|
||||
{
|
||||
if (col.normal.z > 0.0f)
|
||||
{
|
||||
// This will only remove the z component of the collision normal
|
||||
// for the bottom of the character controller, which would hit during
|
||||
// a step. We'll leave the top hemisphere of the character's capsule
|
||||
// alone as bumping one's head is an entirely different story. This
|
||||
// helps with low doorways.
|
||||
col.normal.z = 0.0f;
|
||||
col.normal.normalizeSafe();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PhysX doesn't perform callbacks in its upwards collision check so if
|
||||
// this isn't a sideways collision then it must be a downwards one. In this
|
||||
// case we want to have the collision normal only point in the opposite direction.
|
||||
// i.e. up If we include the sideways part of the normal then the Player class
|
||||
// velocity calculations using this normal will affect the player's forwards
|
||||
// momentum. This is especially noticable on stairs as the rounded bottom of
|
||||
// the capsule slides up the corner of a stair.
|
||||
col.normal.set(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
if ( userData &&
|
||||
userData->mCanPush &&
|
||||
actor->isDynamic() &&
|
||||
!actor->readBodyFlag( NX_BF_KINEMATIC ) &&
|
||||
!mDummyMove )
|
||||
{
|
||||
NxActor *ctrlActor = mController->getActor();
|
||||
|
||||
// So the object is neither
|
||||
// a static or a kinematic,
|
||||
// meaning we need to figure out
|
||||
// if we have enough force to push it.
|
||||
|
||||
// Get the hit object's force
|
||||
// and scale it by the amount
|
||||
// that it's acceleration is going
|
||||
// against our acceleration.
|
||||
const Point3F &hitObjLinVel = pxCast<Point3F>( actor->getLinearVelocity() );
|
||||
|
||||
F32 hitObjMass = actor->getMass();
|
||||
|
||||
VectorF hitObjDeltaVel = hitObjLinVel * TickSec;
|
||||
VectorF hitObjAccel = hitObjDeltaVel / TickSec;
|
||||
|
||||
VectorF controllerLinVel = pxCast<Point3F>( controllerActor->getLinearVelocity() );
|
||||
VectorF controllerDeltaVel = controllerLinVel * TickSec;
|
||||
VectorF controllerAccel = controllerDeltaVel / TickSec;
|
||||
|
||||
Point3F hitObjForce = (hitObjMass * hitObjAccel);
|
||||
Point3F playerForce = (controllerActor->getMass() * controllerAccel);
|
||||
|
||||
VectorF normalizedObjVel( hitObjLinVel );
|
||||
normalizedObjVel.normalizeSafe();
|
||||
|
||||
VectorF normalizedPlayerVel( pxCast<Point3F>( controllerActor->getLinearVelocity() ) );
|
||||
normalizedPlayerVel.normalizeSafe();
|
||||
|
||||
F32 forceDot = mDot( normalizedObjVel, normalizedPlayerVel );
|
||||
|
||||
hitObjForce *= forceDot;
|
||||
|
||||
playerForce = playerForce - hitObjForce;
|
||||
|
||||
if ( playerForce.x > 0.0f || playerForce.y > 0.0f || playerForce.z > 0.0f )
|
||||
actor->addForceAtPos( NxVec3( playerForce.x, playerForce.y, playerForce.z ), actor->getCMassGlobalPosition() );
|
||||
|
||||
//Con::printf( "onShapeHit: %f %f %f", playerForce.x, playerForce.y, playerForce.z );
|
||||
}
|
||||
*/
|
||||
|
||||
return NX_ACTION_PUSH;
|
||||
}
|
||||
|
||||
NxControllerAction PxPlayer::onControllerHit( const NxControllersHit& hit )
|
||||
{
|
||||
if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions)
|
||||
return NX_ACTION_NONE;
|
||||
|
||||
NxActor *actor = hit.other->getActor();
|
||||
PhysicsUserData *userData = PhysicsUserData::cast( actor->userData );
|
||||
|
||||
if ( actor->readActorFlag( NX_AF_DISABLE_RESPONSE ) )
|
||||
return NX_ACTION_NONE;
|
||||
|
||||
// For controller-to-controller hit we don't have an actual hit point, so all
|
||||
// we can do is set the hit object.
|
||||
Collision &col = mCollisionList->increment();
|
||||
dMemset( &col, 0, sizeof( col ) );
|
||||
if ( userData )
|
||||
col.object = userData->getObject();
|
||||
|
||||
return NX_ACTION_NONE;
|
||||
}
|
||||
|
||||
void PxPlayer::findContact( SceneObject **contactObject,
|
||||
VectorF *contactNormal,
|
||||
Vector<SceneObject*> *outOverlapObjects ) const
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::findContact - The controller is null!" );
|
||||
|
||||
// See PxPlayer::_onPhysicsReset
|
||||
if ( !mWorld->isEnabled() )
|
||||
return;
|
||||
|
||||
// Calculate the sweep motion...
|
||||
F32 halfCapSize = mOriginOffset;
|
||||
F32 halfSmallCapSize = halfCapSize * 0.8f;
|
||||
F32 diff = halfCapSize - halfSmallCapSize;
|
||||
|
||||
const F32 mSkinWidth = 0.1f;
|
||||
|
||||
F32 offsetDist = diff + mSkinWidth + 0.01f;
|
||||
NxVec3 motion(0,0,-offsetDist);
|
||||
|
||||
/*
|
||||
// Construct the capsule...
|
||||
F32 radius = mCapsuleController->getRadius();
|
||||
F32 halfHeight = mCapsuleController->getHeight() * 0.5f;
|
||||
|
||||
NxCapsule capsule;
|
||||
capsule.p0 = capsule.p1 = pxCast<NxVec3>( mCapsuleController->getDebugPosition() );
|
||||
capsule.p0.z -= halfHeight;
|
||||
capsule.p1.z += halfHeight;
|
||||
capsule.radius = radius;
|
||||
*/
|
||||
|
||||
NxSweepQueryHit sweepHit;
|
||||
NxU32 hitCount = mController->getActor()->linearSweep( motion, NX_SF_STATICS | NX_SF_DYNAMICS, NULL, 1, &sweepHit, NULL );
|
||||
|
||||
if ( hitCount > 0 )
|
||||
{
|
||||
PhysicsUserData *data = PhysicsUserData::cast( sweepHit.hitShape->getActor().userData );
|
||||
if ( data )
|
||||
{
|
||||
*contactObject = data->getObject();
|
||||
*contactNormal = pxCast<Point3F>( sweepHit.normal );
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlapped objects ( triggers )
|
||||
|
||||
if ( !outOverlapObjects )
|
||||
return;
|
||||
|
||||
NxCapsuleShape *shape = reinterpret_cast<NxCapsuleShape*>( mController->getActor()->getShapes()[0] );
|
||||
NxCapsule worldCapsule;
|
||||
shape->getWorldCapsule( worldCapsule );
|
||||
|
||||
// Test only against activeGroup with triggers ( 31 ).
|
||||
NxU32 activeGroups = 1 << 31;
|
||||
|
||||
NxShape *shapes[10];
|
||||
|
||||
hitCount = mWorld->getScene()->overlapCapsuleShapes( worldCapsule, NX_ALL_SHAPES, 10, shapes, NULL, activeGroups );
|
||||
|
||||
for ( S32 i = 0; i < hitCount; i++ )
|
||||
{
|
||||
PhysicsUserData *data = PhysicsUserData::cast( shapes[i]->getActor().userData );
|
||||
if ( data )
|
||||
outOverlapObjects->push_back( data->getObject() );
|
||||
}
|
||||
}
|
||||
|
||||
void PxPlayer::enableCollision()
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::enableCollision - The controller is null!" );
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
mController->setCollision( true );
|
||||
}
|
||||
|
||||
void PxPlayer::disableCollision()
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::disableCollision - The controller is null!" );
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
mController->setCollision( false );
|
||||
}
|
||||
|
||||
PhysicsWorld* PxPlayer::getWorld()
|
||||
{
|
||||
return mWorld;
|
||||
}
|
||||
|
||||
void PxPlayer::setTransform( const MatrixF &transform )
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::setTransform - The controller is null!" );
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
|
||||
Point3F newPos = transform.getPosition();
|
||||
newPos.z += mOriginOffset;
|
||||
|
||||
const Point3F &curPos = pxCast<Point3F>(mController->getDebugPosition());
|
||||
|
||||
if ( !(newPos - curPos ).isZero() )
|
||||
mController->setPosition( pxCast<NxExtendedVec3>(newPos) );
|
||||
}
|
||||
|
||||
MatrixF& PxPlayer::getTransform( MatrixF *outMatrix )
|
||||
{
|
||||
AssertFatal( mController, "PxPlayer::getTransform - The controller is null!" );
|
||||
|
||||
Point3F newPos = pxCast<Point3F>( mController->getDebugPosition() );
|
||||
newPos.z -= mOriginOffset;
|
||||
outMatrix->setPosition( newPos );
|
||||
|
||||
return *outMatrix;
|
||||
}
|
||||
|
||||
void PxPlayer::setScale( const Point3F &scale )
|
||||
{
|
||||
}
|
||||
|
||||
Box3F PxPlayer::getWorldBounds()
|
||||
{
|
||||
Con::warnf( "PxPlayer::getWorldBounds - not implemented" );
|
||||
return Box3F::Invalid;
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXPLAYER_H
|
||||
#define _PXPLAYER_H
|
||||
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#endif
|
||||
#ifndef _T3D_PHYSICS_PHYSICSPLAYER_H_
|
||||
#include "T3D/physics/physicsPlayer.h"
|
||||
#endif
|
||||
#ifndef _T3D_PHYSICSCOMMON_H_
|
||||
#include "T3D/physics/physicsCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
class PxWorld;
|
||||
class NxController;
|
||||
|
||||
|
||||
class PxPlayer : public PhysicsPlayer, public NxUserControllerHitReport
|
||||
{
|
||||
protected:
|
||||
|
||||
NxController *mController;
|
||||
|
||||
F32 mSkinWidth;
|
||||
|
||||
PxWorld *mWorld;
|
||||
|
||||
SceneObject *mObject;
|
||||
|
||||
/// Used to get collision info out of the
|
||||
/// NxUserControllerHitReport callbacks.
|
||||
CollisionList *mCollisionList;
|
||||
|
||||
///
|
||||
F32 mOriginOffset;
|
||||
|
||||
///
|
||||
F32 mStepHeight;
|
||||
|
||||
///
|
||||
void _releaseController();
|
||||
|
||||
// NxUserControllerHitReport
|
||||
virtual NxControllerAction onShapeHit( const NxControllerShapeHit& hit );
|
||||
virtual NxControllerAction onControllerHit( const NxControllersHit& hit );
|
||||
|
||||
void _findContact( SceneObject **contactObject, VectorF *contactNormal ) const;
|
||||
|
||||
void _onPhysicsReset( PhysicsResetEvent reset );
|
||||
|
||||
void _onStaticChanged();
|
||||
|
||||
public:
|
||||
|
||||
PxPlayer();
|
||||
virtual ~PxPlayer();
|
||||
|
||||
// PhysicsObject
|
||||
virtual PhysicsWorld* getWorld();
|
||||
virtual void setTransform( const MatrixF &transform );
|
||||
virtual MatrixF& getTransform( MatrixF *outMatrix );
|
||||
virtual void setScale( const Point3F &scale );
|
||||
virtual Box3F getWorldBounds();
|
||||
virtual void setSimulationEnabled( bool enabled ) {}
|
||||
virtual bool isSimulationEnabled() { return true; }
|
||||
|
||||
// PhysicsPlayer
|
||||
virtual void init( const char *type,
|
||||
const Point3F &size,
|
||||
F32 runSurfaceCos,
|
||||
F32 stepHeight,
|
||||
SceneObject *obj,
|
||||
PhysicsWorld *world );
|
||||
virtual Point3F move( const VectorF &displacement, CollisionList &outCol );
|
||||
virtual void findContact( SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects ) const;
|
||||
virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const { return true; }
|
||||
virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {}
|
||||
virtual void enableCollision();
|
||||
virtual void disableCollision();
|
||||
};
|
||||
|
||||
|
||||
#endif // _PXPLAYER_H
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "T3D/physics/physX/pxPlugin.h"
|
||||
|
||||
#include "T3D/physics/physicsShape.h"
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
#include "T3D/physics/physX/pxBody.h"
|
||||
#include "T3D/physics/physX/pxPlayer.h"
|
||||
#include "T3D/physics/physX/pxCollision.h"
|
||||
#include "T3D/gameBase/gameProcess.h"
|
||||
#include "core/util/tNamedFactory.h"
|
||||
|
||||
|
||||
extern bool gPhysXLogWarnings;
|
||||
|
||||
AFTER_MODULE_INIT( Sim )
|
||||
{
|
||||
NamedFactory<PhysicsPlugin>::add( "PhysX", &PxPlugin::create );
|
||||
|
||||
#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
|
||||
NamedFactory<PhysicsPlugin>::add( "default", &PxPlugin::create );
|
||||
#endif
|
||||
|
||||
Con::addVariable( "$PhysXLogWarnings", TypeBool, &gPhysXLogWarnings,
|
||||
"@brief Output PhysX warnings to the console.\n\n"
|
||||
"@ingroup Physics\n");
|
||||
}
|
||||
|
||||
|
||||
PhysicsPlugin* PxPlugin::create()
|
||||
{
|
||||
// Only create the plugin if it hasn't been set up AND
|
||||
// the PhysX world is successfully initialized.
|
||||
bool success = PxWorld::restartSDK( false );
|
||||
if ( success )
|
||||
return new PxPlugin();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PxPlugin::PxPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
PxPlugin::~PxPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
void PxPlugin::destroyPlugin()
|
||||
{
|
||||
// Cleanup any worlds that are still kicking.
|
||||
Map<StringNoCase, PhysicsWorld*>::Iterator iter = mPhysicsWorldLookup.begin();
|
||||
for ( ; iter != mPhysicsWorldLookup.end(); iter++ )
|
||||
{
|
||||
iter->value->destroyWorld();
|
||||
delete iter->value;
|
||||
}
|
||||
mPhysicsWorldLookup.clear();
|
||||
|
||||
PxWorld::restartSDK( true );
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void PxPlugin::reset()
|
||||
{
|
||||
// First delete all the cleanup objects.
|
||||
if ( getPhysicsCleanup() )
|
||||
getPhysicsCleanup()->deleteAllObjects();
|
||||
|
||||
getPhysicsResetSignal().trigger( PhysicsResetEvent_Restore );
|
||||
|
||||
// Now let each world reset itself.
|
||||
Map<StringNoCase, PhysicsWorld*>::Iterator iter = mPhysicsWorldLookup.begin();
|
||||
for ( ; iter != mPhysicsWorldLookup.end(); iter++ )
|
||||
iter->value->reset();
|
||||
}
|
||||
|
||||
PhysicsCollision* PxPlugin::createCollision()
|
||||
{
|
||||
return new PxCollision();
|
||||
}
|
||||
|
||||
PhysicsBody* PxPlugin::createBody()
|
||||
{
|
||||
return new PxBody();
|
||||
}
|
||||
|
||||
PhysicsPlayer* PxPlugin::createPlayer()
|
||||
{
|
||||
return new PxPlayer();
|
||||
}
|
||||
|
||||
bool PxPlugin::isSimulationEnabled() const
|
||||
{
|
||||
bool ret = false;
|
||||
PxWorld *world = static_cast<PxWorld*>( getWorld( smClientWorldName ) );
|
||||
if ( world )
|
||||
{
|
||||
ret = world->getEnabled();
|
||||
return ret;
|
||||
}
|
||||
|
||||
world = static_cast<PxWorld*>( getWorld( smServerWorldName ) );
|
||||
if ( world )
|
||||
{
|
||||
ret = world->getEnabled();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PxPlugin::enableSimulation( const String &worldName, bool enable )
|
||||
{
|
||||
PxWorld *world = static_cast<PxWorld*>( getWorld( worldName ) );
|
||||
if ( world )
|
||||
world->setEnabled( enable );
|
||||
}
|
||||
|
||||
void PxPlugin::setTimeScale( const F32 timeScale )
|
||||
{
|
||||
// Grab both the client and
|
||||
// server worlds and set their time
|
||||
// scales to the passed value.
|
||||
PxWorld *world = static_cast<PxWorld*>( getWorld( smClientWorldName ) );
|
||||
if ( world )
|
||||
world->setEditorTimeScale( timeScale );
|
||||
|
||||
world = static_cast<PxWorld*>( getWorld( smServerWorldName ) );
|
||||
if ( world )
|
||||
world->setEditorTimeScale( timeScale );
|
||||
}
|
||||
|
||||
const F32 PxPlugin::getTimeScale() const
|
||||
{
|
||||
// Grab both the client and
|
||||
// server worlds and call
|
||||
// setEnabled( true ) on them.
|
||||
PxWorld *world = static_cast<PxWorld*>( getWorld( smClientWorldName ) );
|
||||
if ( !world )
|
||||
{
|
||||
world = static_cast<PxWorld*>( getWorld( smServerWorldName ) );
|
||||
if ( !world )
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return world->getEditorTimeScale();
|
||||
}
|
||||
|
||||
bool PxPlugin::createWorld( const String &worldName )
|
||||
{
|
||||
Map<StringNoCase, PhysicsWorld*>::Iterator iter = mPhysicsWorldLookup.find( worldName );
|
||||
PhysicsWorld *world = NULL;
|
||||
|
||||
iter != mPhysicsWorldLookup.end() ? world = (*iter).value : world = NULL;
|
||||
|
||||
if ( world )
|
||||
{
|
||||
Con::errorf( "PxPlugin::createWorld - %s world already exists!", worldName.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
world = new PxWorld();
|
||||
|
||||
if ( worldName.equal( smClientWorldName, String::NoCase ) )
|
||||
world->initWorld( false, ClientProcessList::get() );
|
||||
else
|
||||
world->initWorld( true, ServerProcessList::get() );
|
||||
|
||||
mPhysicsWorldLookup.insert( worldName, world );
|
||||
|
||||
return world != NULL;
|
||||
}
|
||||
|
||||
void PxPlugin::destroyWorld( const String &worldName )
|
||||
{
|
||||
Map<StringNoCase, PhysicsWorld*>::Iterator iter = mPhysicsWorldLookup.find( worldName );
|
||||
if ( iter == mPhysicsWorldLookup.end() )
|
||||
return;
|
||||
|
||||
PhysicsWorld *world = (*iter).value;
|
||||
world->destroyWorld();
|
||||
delete world;
|
||||
|
||||
mPhysicsWorldLookup.erase( iter );
|
||||
}
|
||||
|
||||
PhysicsWorld* PxPlugin::getWorld( const String &worldName ) const
|
||||
{
|
||||
if ( mPhysicsWorldLookup.isEmpty() )
|
||||
return NULL;
|
||||
|
||||
Map<StringNoCase, PhysicsWorld*>::ConstIterator iter = mPhysicsWorldLookup.find( worldName );
|
||||
|
||||
return iter != mPhysicsWorldLookup.end() ? (*iter).value : NULL;
|
||||
}
|
||||
|
||||
PhysicsWorld* PxPlugin::getWorld() const
|
||||
{
|
||||
if ( mPhysicsWorldLookup.size() == 0 )
|
||||
return NULL;
|
||||
|
||||
Map<StringNoCase, PhysicsWorld*>::ConstIterator iter = mPhysicsWorldLookup.begin();
|
||||
return iter->value;
|
||||
}
|
||||
|
||||
U32 PxPlugin::getWorldCount() const
|
||||
{
|
||||
return mPhysicsWorldLookup.size();
|
||||
}
|
||||
|
||||
void PxPlugin::_onDebugDrawEnabled( bool enabled )
|
||||
{
|
||||
if ( !enabled )
|
||||
gPhysicsSDK->setParameter( NX_VISUALIZATION_SCALE, 0.0f );
|
||||
}
|
||||
|
||||
ConsoleFunction( physXRemoteDebuggerConnect, bool, 1, 3, "" )
|
||||
{
|
||||
if ( !gPhysicsSDK )
|
||||
{
|
||||
Con::errorf( "PhysX SDK not initialized!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
NxRemoteDebugger *debugger = gPhysicsSDK->getFoundationSDK().getRemoteDebugger();
|
||||
|
||||
if ( debugger->isConnected() )
|
||||
{
|
||||
Con::errorf( "RemoteDebugger already connected... call disconnect first!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
const UTF8 *host = "localhost";
|
||||
U32 port = 5425;
|
||||
|
||||
if ( argc >= 2 )
|
||||
host = argv[1];
|
||||
if ( argc >= 3 )
|
||||
port = dAtoi( argv[2] );
|
||||
|
||||
// Before we connect we need to have write access
|
||||
// to both the client and server worlds.
|
||||
PxWorld::releaseWriteLocks();
|
||||
|
||||
// Connect!
|
||||
debugger->connect( host, port );
|
||||
if ( !debugger->isConnected() )
|
||||
{
|
||||
Con::errorf( "RemoteDebugger failed to connect!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
Con::printf( "RemoteDebugger connected to %s at port %u!", host, port );
|
||||
return true;
|
||||
}
|
||||
|
||||
ConsoleFunction( physXRemoteDebuggerDisconnect, void, 1, 1, "" )
|
||||
{
|
||||
if ( !gPhysicsSDK )
|
||||
{
|
||||
Con::errorf( "PhysX SDK not initialized!" );
|
||||
return;
|
||||
}
|
||||
|
||||
NxRemoteDebugger *debugger = gPhysicsSDK->getFoundationSDK().getRemoteDebugger();
|
||||
|
||||
if ( debugger->isConnected() )
|
||||
{
|
||||
debugger->flush();
|
||||
debugger->disconnect();
|
||||
Con::printf( "RemoteDebugger disconnected!" );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _T3D_PHYSICS_PXPLUGIN_H_
|
||||
#define _T3D_PHYSICS_PXPLUGIN_H_
|
||||
|
||||
#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
|
||||
#include "T3D/physics/physicsPlugin.h"
|
||||
#endif
|
||||
|
||||
|
||||
class PxPlugin : public PhysicsPlugin
|
||||
{
|
||||
public:
|
||||
|
||||
PxPlugin();
|
||||
~PxPlugin();
|
||||
|
||||
/// Create function for factory.
|
||||
static PhysicsPlugin* create();
|
||||
|
||||
// PhysicsPlugin
|
||||
virtual void destroyPlugin();
|
||||
virtual void reset();
|
||||
virtual PhysicsCollision* createCollision();
|
||||
virtual PhysicsBody* createBody();
|
||||
virtual PhysicsPlayer* createPlayer();
|
||||
virtual bool isSimulationEnabled() const;
|
||||
virtual void enableSimulation( const String &worldName, bool enable );
|
||||
virtual void setTimeScale( const F32 timeScale );
|
||||
virtual const F32 getTimeScale() const;
|
||||
virtual bool createWorld( const String &worldName );
|
||||
virtual void destroyWorld( const String &worldName );
|
||||
virtual PhysicsWorld* getWorld( const String &worldName ) const;
|
||||
virtual PhysicsWorld* getWorld() const;
|
||||
virtual U32 getWorldCount() const;
|
||||
virtual void _onDebugDrawEnabled( bool enabled );
|
||||
};
|
||||
|
||||
#endif // _T3D_PHYSICS_PXPLUGIN_H_
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxStream.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
|
||||
|
||||
PxMemStream::PxMemStream()
|
||||
: mMemStream( 1024 )
|
||||
{
|
||||
}
|
||||
|
||||
PxMemStream::~PxMemStream()
|
||||
{
|
||||
}
|
||||
|
||||
void PxMemStream::resetPosition()
|
||||
{
|
||||
mMemStream.setPosition( 0 );
|
||||
}
|
||||
|
||||
NxU8 PxMemStream::readByte() const
|
||||
{
|
||||
NxU8 out;
|
||||
mMemStream.read( &out );
|
||||
return out;
|
||||
}
|
||||
|
||||
NxU16 PxMemStream::readWord() const
|
||||
{
|
||||
NxU16 out;
|
||||
mMemStream.read( &out );
|
||||
return out;
|
||||
}
|
||||
|
||||
NxU32 PxMemStream::readDword() const
|
||||
{
|
||||
NxU32 out;
|
||||
mMemStream.read( &out );
|
||||
return out;
|
||||
}
|
||||
|
||||
float PxMemStream::readFloat() const
|
||||
{
|
||||
float out;
|
||||
mMemStream.read( &out );
|
||||
return out;
|
||||
}
|
||||
|
||||
double PxMemStream::readDouble() const
|
||||
{
|
||||
double out;
|
||||
mMemStream.read( &out );
|
||||
return out;
|
||||
}
|
||||
|
||||
void PxMemStream::readBuffer( void *buffer, NxU32 size ) const
|
||||
{
|
||||
mMemStream.read( size, buffer );
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeByte( NxU8 b )
|
||||
{
|
||||
mMemStream.write( b );
|
||||
return *this;
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeWord( NxU16 w )
|
||||
{
|
||||
mMemStream.write( w );
|
||||
return *this;
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeDword( NxU32 d )
|
||||
{
|
||||
mMemStream.write( d );
|
||||
return *this;
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeFloat( NxReal f )
|
||||
{
|
||||
mMemStream.write( f );
|
||||
return *this;
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeDouble( NxF64 f )
|
||||
{
|
||||
mMemStream.write( f );
|
||||
return *this;
|
||||
}
|
||||
|
||||
NxStream& PxMemStream::storeBuffer( const void *buffer, NxU32 size )
|
||||
{
|
||||
mMemStream.write( size, buffer );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool gPhysXLogWarnings = false;
|
||||
|
||||
PxConsoleStream::PxConsoleStream()
|
||||
{
|
||||
}
|
||||
|
||||
PxConsoleStream::~PxConsoleStream()
|
||||
{
|
||||
}
|
||||
|
||||
void PxConsoleStream::reportError( NxErrorCode code, const char *message, const char* file, int line )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG
|
||||
|
||||
// If we're in debug mode and the error code is serious then
|
||||
// pop up a message box to make sure we see it.
|
||||
if ( code < NXE_DB_INFO )
|
||||
{
|
||||
UTF8 info[1024];
|
||||
dSprintf( info, 1024, "File: %s\nLine: %d\n%s", file, line, message );
|
||||
Platform::AlertOK( "PhysX Error", info );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// In all other cases we just dump the message to the console.
|
||||
if ( code == NXE_DB_WARNING )
|
||||
{
|
||||
if ( gPhysXLogWarnings )
|
||||
Con::printf( "PhysX Warning:\n %s(%d) : %s\n", file, line, message );
|
||||
}
|
||||
else
|
||||
Con::printf( "PhysX Error:\n %s(%d) : %s\n", file, line, message );
|
||||
}
|
||||
|
||||
NxAssertResponse PxConsoleStream::reportAssertViolation (const char *message, const char *file,int line)
|
||||
{
|
||||
// Assert if we're in debug mode...
|
||||
bool triggerBreak = false;
|
||||
#ifdef TORQUE_DEBUG
|
||||
triggerBreak = PlatformAssert::processAssert( PlatformAssert::Fatal, file, line, message );
|
||||
#endif
|
||||
|
||||
// In all other cases we just dump the message to the console.
|
||||
Con::errorf( "PhysX Assert:\n %s(%d) : %s\n", file, line, message );
|
||||
|
||||
return triggerBreak ? NX_AR_BREAKPOINT : NX_AR_CONTINUE;
|
||||
}
|
||||
|
||||
void PxConsoleStream::print( const char *message )
|
||||
{
|
||||
Con::printf( "PhysX Says: %s\n", message );
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _T3D_PHYSICS_PXSTREAM_H_
|
||||
#define _T3D_PHYSICS_PXSTREAM_H_
|
||||
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#endif
|
||||
#ifndef _MEMSTREAM_H_
|
||||
#include "core/stream/memStream.h"
|
||||
#endif
|
||||
|
||||
|
||||
class PxMemStream : public NxStream
|
||||
{
|
||||
public:
|
||||
|
||||
PxMemStream();
|
||||
virtual ~PxMemStream();
|
||||
|
||||
void resetPosition();
|
||||
|
||||
// NxStream
|
||||
NxU8 readByte() const;
|
||||
NxU16 readWord() const;
|
||||
NxU32 readDword() const;
|
||||
float readFloat() const;
|
||||
double readDouble() const;
|
||||
void readBuffer( void *buffer, NxU32 size ) const;
|
||||
NxStream& storeByte( NxU8 b );
|
||||
NxStream& storeWord( NxU16 w );
|
||||
NxStream& storeDword( NxU32 d );
|
||||
NxStream& storeFloat( NxReal f );
|
||||
NxStream& storeDouble( NxF64 f );
|
||||
NxStream& storeBuffer( const void* buffer, NxU32 size );
|
||||
|
||||
protected:
|
||||
|
||||
mutable MemStream mMemStream;
|
||||
};
|
||||
|
||||
|
||||
class PxConsoleStream : public NxUserOutputStream
|
||||
{
|
||||
protected:
|
||||
|
||||
// NxUserOutputStream
|
||||
void reportError( NxErrorCode code, const char *message, const char* file, int line );
|
||||
NxAssertResponse reportAssertViolation( const char *message, const char *file, int line );
|
||||
void print( const char *message );
|
||||
|
||||
public:
|
||||
|
||||
PxConsoleStream();
|
||||
~PxConsoleStream();
|
||||
};
|
||||
|
||||
#endif // _T3D_PHYSICS_PXSTREAM_H_
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physx/pxUtils.h"
|
||||
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "math/mPoint3.h"
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
|
||||
namespace PxUtils {
|
||||
|
||||
void drawActor( NxActor *inActor )
|
||||
{
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
//drawer->setZRead( false );
|
||||
|
||||
// Determine alpha we render shapes with.
|
||||
const U8 enabledAlpha = 255;
|
||||
const U8 disabledAlpha = 100;
|
||||
U8 renderAlpha = inActor->readActorFlag( NX_AF_DISABLE_COLLISION ) ? disabledAlpha : enabledAlpha;
|
||||
|
||||
// Determine color we render actors and shapes with.
|
||||
ColorI actorColor( 0, 0, 255, 200 );
|
||||
ColorI shapeColor = ( inActor->isSleeping() ? ColorI( 0, 0, 255, renderAlpha ) : ColorI( 255, 0, 255, renderAlpha ) );
|
||||
|
||||
MatrixF actorMat(true);
|
||||
inActor->getGlobalPose().getRowMajor44( actorMat );
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setBlend( true );
|
||||
desc.setZReadWrite( true, false );
|
||||
desc.setCullMode( GFXCullNone );
|
||||
|
||||
// Draw an xfm gizmo for the actor's globalPose...
|
||||
//drawer->drawTransform( desc, actorMat, Point3F::One, actorColor );
|
||||
|
||||
// Loop through and render all the actor's shapes....
|
||||
|
||||
NxShape *const*pShapeArray = inActor->getShapes();
|
||||
U32 numShapes = inActor->getNbShapes();
|
||||
|
||||
for ( U32 i = 0; i < numShapes; i++ )
|
||||
{
|
||||
const NxShape *shape = pShapeArray[i];
|
||||
|
||||
Point3F shapePos = pxCast<Point3F>( shape->getGlobalPosition() );
|
||||
MatrixF shapeMat(true);
|
||||
shape->getGlobalPose().getRowMajor44(shapeMat);
|
||||
shapeMat.setPosition( Point3F::Zero );
|
||||
|
||||
switch ( shape->getType() )
|
||||
{
|
||||
case NX_SHAPE_SPHERE:
|
||||
{
|
||||
NxSphereShape *sphere = (NxSphereShape*)shape;
|
||||
drawer->drawSphere( desc, sphere->getRadius(), shapePos, shapeColor );
|
||||
|
||||
break;
|
||||
}
|
||||
case NX_SHAPE_BOX:
|
||||
{
|
||||
NxBoxShape *box = (NxBoxShape*)shape;
|
||||
Point3F size = pxCast<Point3F>( box->getDimensions() );
|
||||
drawer->drawCube( desc, size*2, shapePos, shapeColor, &shapeMat );
|
||||
break;
|
||||
}
|
||||
case NX_SHAPE_CAPSULE:
|
||||
{
|
||||
shapeMat.mul( MatrixF( EulerF( mDegToRad(90.0f), mDegToRad(90.0f), 0 ) ) );
|
||||
|
||||
NxCapsuleShape *capsule = (NxCapsuleShape*)shape;
|
||||
drawer->drawCapsule( desc, shapePos, capsule->getRadius(), capsule->getHeight(), shapeColor, &shapeMat );
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//drawer->clearZDefined();
|
||||
}
|
||||
|
||||
} // namespace PxUtils
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PXUTILS_H_
|
||||
#define _PXUTILS_H_
|
||||
|
||||
|
||||
class NxActor;
|
||||
|
||||
|
||||
namespace PxUtils {
|
||||
|
||||
/// Debug render an actor, loops through all shapes
|
||||
/// and translates primitive types into drawUtil calls.
|
||||
void drawActor( NxActor *inActor );
|
||||
|
||||
} // namespace PxUtils
|
||||
|
||||
#endif // _PXUTILS_H_
|
||||
|
|
@ -1,876 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/physics/physX/pxWorld.h"
|
||||
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#include "T3D/physics/physX/pxPlugin.h"
|
||||
#include "T3D/physics/physX/pxMaterial.h"
|
||||
#include "T3D/physics/physX/pxContactReporter.h"
|
||||
#include "T3D/physics/physX/pxStream.h"
|
||||
#include "T3D/physics/physX/pxCasts.h"
|
||||
#include "T3D/physics/physicsUserData.h"
|
||||
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "platform/profiler.h"
|
||||
#include "sim/netConnection.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "T3D/tsstatic.h"
|
||||
#include "T3D/gameBase/gameProcess.h"
|
||||
#include "gfx/sim/debugDraw.h"
|
||||
#include "gfx/primBuilder.h"
|
||||
|
||||
#include <NXU_helper.h>
|
||||
|
||||
|
||||
static const F32 PhysicsStepTime = (F32)TickMs / 1000.0f;
|
||||
static const U32 PhysicsMaxIterations = 8;
|
||||
static const F32 PhysicsMaxTimeStep = PhysicsStepTime / 2.0f;
|
||||
|
||||
NxPhysicsSDK *gPhysicsSDK = NULL;
|
||||
NxCookingInterface *PxWorld::smCooking = NULL;
|
||||
PxConsoleStream *PxWorld::smConsoleStream = NULL;
|
||||
|
||||
|
||||
PxWorld::PxWorld() :
|
||||
mScene( NULL ),
|
||||
mConactReporter( NULL ),
|
||||
mProcessList( NULL ),
|
||||
mIsSimulating( false ),
|
||||
mErrorReport( false ),
|
||||
mTickCount( 0 ),
|
||||
mIsEnabled( false ),
|
||||
mEditorTimeScale( 1.0f )
|
||||
{
|
||||
if ( !CCTAllocator::mAllocator )
|
||||
CCTAllocator::mAllocator = new NxUserAllocatorDefault();
|
||||
mControllerManager = new CharacterControllerManager( CCTAllocator::mAllocator );
|
||||
}
|
||||
|
||||
PxWorld::~PxWorld()
|
||||
{
|
||||
delete mControllerManager;
|
||||
}
|
||||
|
||||
NxCookingInterface* PxWorld::getCooking()
|
||||
{
|
||||
if ( !smCooking )
|
||||
smCooking = NxGetCookingLib( NX_PHYSICS_SDK_VERSION );
|
||||
|
||||
return smCooking;
|
||||
}
|
||||
|
||||
bool PxWorld::_init( bool isServer, ProcessList *processList )
|
||||
{
|
||||
if ( !gPhysicsSDK )
|
||||
{
|
||||
Con::errorf( "PhysXWorld::init - PhysXSDK not initialized!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the scene description.
|
||||
NxSceneDesc sceneDesc;
|
||||
sceneDesc.userData = this;
|
||||
|
||||
// Set up default gravity.
|
||||
sceneDesc.gravity.set( mGravity.x, mGravity.y, mGravity.z );
|
||||
|
||||
// The master scene is always on the CPU and is used
|
||||
// mostly for static shapes.
|
||||
sceneDesc.simType = NX_SIMULATION_SW; // [9/28/2009 Pat] Why is this software? Should be software server, hardware client?
|
||||
|
||||
// Threading... seems to improve performance.
|
||||
//
|
||||
// TODO: I was getting random crashes in debug when doing
|
||||
// edit and continue... lets see if i still get them with
|
||||
// the threading disabled.
|
||||
//
|
||||
sceneDesc.flags |= NX_SF_ENABLE_MULTITHREAD | NX_SF_DISABLE_SCENE_MUTEX;
|
||||
sceneDesc.threadMask = 0xfffffffe;
|
||||
sceneDesc.internalThreadCount = PHYSICSMGR->getThreadCount();
|
||||
|
||||
// Create the scene.
|
||||
mScene = gPhysicsSDK->createScene(sceneDesc);
|
||||
if ( !mScene )
|
||||
{
|
||||
Con::errorf( "PhysXWorld - %s world createScene returned a null scene!", isServer ? "Server" : "Client" );
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
// Make note of what we've created.
|
||||
String simType = sceneDesc.simType == NX_SIMULATION_SW ? "software" : "hardware";
|
||||
String clientOrServer = this == isServer ? "server" : "client";
|
||||
Con::printf( "PhysXWorld::init() - Created %s %s simulation!",
|
||||
clientOrServer.c_str(),
|
||||
simType.c_str() );
|
||||
*/
|
||||
|
||||
mScene->setTiming( PhysicsMaxTimeStep, PhysicsMaxIterations, NX_TIMESTEP_FIXED );
|
||||
|
||||
// TODO: Add dummy actor with scene name!
|
||||
|
||||
// Set the global contact reporter.
|
||||
|
||||
mConactReporter = new PxContactReporter();
|
||||
mScene->setUserContactReport( mConactReporter );
|
||||
|
||||
// Set the global PxUserNotify
|
||||
|
||||
mUserNotify = new PxUserNotify();
|
||||
mScene->setUserNotify( mUserNotify );
|
||||
|
||||
// Now create the dynamic rigid body compartment which
|
||||
// can reside on the hardware when hardware is present.
|
||||
/*
|
||||
NxCompartmentDesc compartmentDesc;
|
||||
compartmentDesc.type = NX_SCT_RIGIDBODY;
|
||||
compartmentDesc.deviceCode = NX_DC_PPU_AUTO_ASSIGN;
|
||||
mRigidCompartment = mScene->createCompartment( compartmentDesc );
|
||||
if ( !mRigidCompartment )
|
||||
{
|
||||
Con::errorf( "PhysXWorld - Creation of rigid body compartment failed!" );
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// Hook up the tick processing signals for advancing physics.
|
||||
//
|
||||
// First an overview of how physics and the game ticks
|
||||
// interact with each other.
|
||||
//
|
||||
// In Torque you normally tick the server and then the client
|
||||
// approximately every 32ms. So before the game tick we call
|
||||
// getPhysicsResults() to get the new physics state and call
|
||||
// tickPhysics() when the game tick is done to start processing
|
||||
// the next physics state. This means PhysX is happily doing
|
||||
// physics in a separate thread while we're doing rendering,
|
||||
// sound, input, networking, etc.
|
||||
//
|
||||
// Because your frame rate is rarely perfectly even you can
|
||||
// get cases where you may tick the server or the client
|
||||
// several times in a row. This happens most often in debug
|
||||
// mode, but can also happen in release.
|
||||
//
|
||||
// The simple implementation is to do a getPhysicsResults() and
|
||||
// tickPhysics() for each tick. But this very bad! It forces
|
||||
// immediate results from PhysX which blocks the primary thread
|
||||
// and further slows down processing. It leads to slower and
|
||||
// slower frame rates as the simulation is never able to catch
|
||||
// up to the current tick.
|
||||
//
|
||||
// The trick is processing physics once for backlogged ticks
|
||||
// with the total of the elapsed tick time. This is a huge
|
||||
// performance gain and keeps you from blocking on PhysX.
|
||||
//
|
||||
// This does have a side effect that when it occurs you'll get
|
||||
// ticks where the physics state hasn't advanced, but this beats
|
||||
// single digit frame rates.
|
||||
//
|
||||
AssertFatal( processList, "PxWorld::init() - We need a process list to create the world!" );
|
||||
mProcessList = processList;
|
||||
mProcessList->preTickSignal().notify( this, &PxWorld::getPhysicsResults );
|
||||
mProcessList->postTickSignal().notify( this, &PxWorld::tickPhysics, 1000.0f );
|
||||
|
||||
// Setup the default material.
|
||||
NxMaterial *dmat = mScene->getMaterialFromIndex( 0 );
|
||||
dmat->setRestitution( 0.2f );
|
||||
dmat->setStaticFriction( 0.6f );
|
||||
dmat->setDynamicFriction( 0.4f );
|
||||
|
||||
// Setup dominance groups.
|
||||
|
||||
// Group 31 is for debris and other objects which can be pushed but cannot push back.
|
||||
// Group 0 is for everything else.
|
||||
|
||||
NxConstraintDominance debrisDominance( 0.0f, 1.0f );
|
||||
mScene->setDominanceGroupPair( 0, 31, debrisDominance );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxWorld::_destroy()
|
||||
{
|
||||
// Make sure the simulation is stopped!
|
||||
getPhysicsResults();
|
||||
_releaseQueues();
|
||||
|
||||
#ifdef TORQUE_DEBUG
|
||||
|
||||
U32 actorCount = mScene->getNbActors();
|
||||
U32 jointCount = mScene->getNbJoints();
|
||||
|
||||
if ( actorCount != 0 || jointCount != 0 )
|
||||
{
|
||||
// Dump the names of any actors or joints that
|
||||
// were not released before the destruction of
|
||||
// this scene.
|
||||
|
||||
for ( U32 i=0; i < actorCount; i++ )
|
||||
{
|
||||
const NxActor *actor = mScene->getActors()[i];
|
||||
Con::errorf( "Orphan NxActor - '%s'!", actor->getName() );
|
||||
}
|
||||
|
||||
mScene->resetJointIterator();
|
||||
for ( ;; )
|
||||
{
|
||||
const NxJoint *joint = mScene->getNextJoint();
|
||||
if ( !joint )
|
||||
break;
|
||||
|
||||
Con::errorf( "Orphan NxJoint - '%s'!", joint->getName() );
|
||||
}
|
||||
|
||||
AssertFatal( false, "PhysXWorld::_destroy() - Some actors and/or joints were not released!" );
|
||||
}
|
||||
|
||||
#endif // TORQUE_DEBUG
|
||||
|
||||
//NxCloseCooking();
|
||||
|
||||
// Release the tick processing signals.
|
||||
if ( mProcessList )
|
||||
{
|
||||
mProcessList->preTickSignal().remove( this, &PxWorld::getPhysicsResults );
|
||||
mProcessList->postTickSignal().remove( this, &PxWorld::tickPhysics );
|
||||
mProcessList = NULL;
|
||||
}
|
||||
|
||||
// Destroy the scene.
|
||||
if ( mScene )
|
||||
{
|
||||
// Delete the contact reporter.
|
||||
mScene->setUserContactReport( NULL );
|
||||
SAFE_DELETE( mConactReporter );
|
||||
|
||||
// First shut down threads... this makes it
|
||||
// safe to release the scene.
|
||||
mScene->shutdownWorkerThreads();
|
||||
|
||||
// Release the scene.
|
||||
gPhysicsSDK->releaseScene( *mScene );
|
||||
mScene = NULL;
|
||||
}
|
||||
|
||||
// Try to restart the sdk if we can.
|
||||
//restartSDK();
|
||||
}
|
||||
|
||||
bool PxWorld::restartSDK( bool destroyOnly, PxWorld *clientWorld, PxWorld *serverWorld )
|
||||
{
|
||||
// If either the client or the server still exist
|
||||
// then we cannot reset the SDK.
|
||||
if ( clientWorld || serverWorld )
|
||||
return false;
|
||||
|
||||
// Destroy the existing SDK.
|
||||
if ( gPhysicsSDK )
|
||||
{
|
||||
NXU::releasePersistentMemory();
|
||||
gPhysicsSDK->release();
|
||||
gPhysicsSDK = NULL;
|
||||
smCooking = NULL;
|
||||
SAFE_DELETE( smConsoleStream );
|
||||
}
|
||||
|
||||
// If we're not supposed to restart... return.
|
||||
if ( destroyOnly )
|
||||
return true;
|
||||
|
||||
smConsoleStream = new PxConsoleStream();
|
||||
|
||||
NxPhysicsSDKDesc sdkDesc;
|
||||
sdkDesc.flags |= NX_SDKF_NO_HARDWARE; // [9/28/2009 Pat] Why is this disabled?
|
||||
|
||||
NxSDKCreateError error;
|
||||
gPhysicsSDK = NxCreatePhysicsSDK( NX_PHYSICS_SDK_VERSION,
|
||||
NULL,
|
||||
smConsoleStream,
|
||||
sdkDesc,
|
||||
&error );
|
||||
if ( !gPhysicsSDK )
|
||||
{
|
||||
Con::errorf( "PhysX failed to initialize! Error code: %d", error );
|
||||
Platform::messageBox( Con::getVariable( "$appName" ),
|
||||
avar("PhysX could not be started!\r\n"
|
||||
"Please be sure you have the latest version of PhysX installed.\r\n"
|
||||
"Error Code: %d", error),
|
||||
MBOk, MIStop );
|
||||
Platform::forceShutdown( -1 );
|
||||
|
||||
// We shouldn't get here, but this shuts up
|
||||
// source diagnostic tools.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the default skin width for all actors.
|
||||
gPhysicsSDK->setParameter( NX_SKIN_WIDTH, 0.01f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxWorld::tickPhysics( U32 elapsedMs )
|
||||
{
|
||||
if ( !mScene || !mIsEnabled )
|
||||
return;
|
||||
|
||||
// Did we forget to call getPhysicsResults somewhere?
|
||||
AssertFatal( !mIsSimulating, "PhysXWorld::tickPhysics() - Already simulating!" );
|
||||
|
||||
// The elapsed time should be non-zero and
|
||||
// a multiple of TickMs!
|
||||
AssertFatal( elapsedMs != 0 &&
|
||||
( elapsedMs % TickMs ) == 0 , "PhysXWorld::tickPhysics() - Got bad elapsed time!" );
|
||||
|
||||
PROFILE_SCOPE(PxWorld_TickPhysics);
|
||||
|
||||
// Convert it to seconds.
|
||||
const F32 elapsedSec = (F32)elapsedMs * 0.001f;
|
||||
|
||||
// For some reason this gets reset all the time
|
||||
// and it must be called before the simulate.
|
||||
mScene->setFilterOps( NX_FILTEROP_OR,
|
||||
NX_FILTEROP_OR,
|
||||
NX_FILTEROP_AND );
|
||||
mScene->setFilterBool( false );
|
||||
NxGroupsMask zeroMask;
|
||||
zeroMask.bits0=zeroMask.bits1=zeroMask.bits2=zeroMask.bits3=0;
|
||||
mScene->setFilterConstant0( zeroMask );
|
||||
mScene->setFilterConstant1( zeroMask );
|
||||
|
||||
mScene->simulate( elapsedSec * mEditorTimeScale );
|
||||
mScene->flushStream();
|
||||
mIsSimulating = true;
|
||||
|
||||
//Con::printf( "%s PhysXWorld::tickPhysics!", this == smClientWorld ? "Client" : "Server" );
|
||||
}
|
||||
|
||||
void PxWorld::releaseWriteLocks()
|
||||
{
|
||||
PxWorld *world = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( "server" ) );
|
||||
|
||||
if ( world )
|
||||
world->releaseWriteLock();
|
||||
|
||||
world = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( "client" ) );
|
||||
|
||||
if ( world )
|
||||
world->releaseWriteLock();
|
||||
}
|
||||
|
||||
void PxWorld::releaseWriteLock()
|
||||
{
|
||||
if ( !mScene || !mIsSimulating )
|
||||
return;
|
||||
|
||||
PROFILE_SCOPE(PxWorld_ReleaseWriteLock);
|
||||
|
||||
// We use checkResults here to release the write lock
|
||||
// but we do not change the simulation flag or increment
|
||||
// the tick count... we may have gotten results, but the
|
||||
// simulation hasn't really ticked!
|
||||
mScene->checkResults( NX_RIGID_BODY_FINISHED, true );
|
||||
AssertFatal( mScene->isWritable(), "PhysXWorld::releaseWriteLock() - We should have been writable now!" );
|
||||
}
|
||||
|
||||
void PxWorld::getPhysicsResults()
|
||||
{
|
||||
if ( !mScene || !mIsSimulating )
|
||||
return;
|
||||
|
||||
PROFILE_SCOPE(PxWorld_GetPhysicsResults);
|
||||
|
||||
// Get results from scene.
|
||||
mScene->fetchResults( NX_RIGID_BODY_FINISHED, true );
|
||||
mIsSimulating = false;
|
||||
mTickCount++;
|
||||
|
||||
// Release any joints/actors that were waiting
|
||||
// for the scene to become writable.
|
||||
_releaseQueues();
|
||||
|
||||
//Con::printf( "%s PhysXWorld::getPhysicsResults!", this == smClientWorld ? "Client" : "Server" );
|
||||
}
|
||||
|
||||
NxMaterial* PxWorld::createMaterial( NxMaterialDesc &material )
|
||||
{
|
||||
if ( !mScene )
|
||||
return NULL;
|
||||
|
||||
// We need the writelock to create a material!
|
||||
releaseWriteLock();
|
||||
|
||||
NxMaterial *mat = mScene->createMaterial( material );
|
||||
if ( !mat )
|
||||
return NULL;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
NxController* PxWorld::createController( NxControllerDesc &desc )
|
||||
{
|
||||
if ( !mScene )
|
||||
return NULL;
|
||||
|
||||
// We need the writelock!
|
||||
releaseWriteLock();
|
||||
|
||||
return mControllerManager->createController( mScene, desc );
|
||||
}
|
||||
|
||||
void PxWorld::releaseActor( NxActor &actor )
|
||||
{
|
||||
AssertFatal( &actor.getScene() == mScene, "PhysXWorld::releaseActor() - Bad scene!" );
|
||||
|
||||
// Clear the userdata.
|
||||
actor.userData = NULL;
|
||||
|
||||
// actors are one of the few objects that are stable removing this way in physx 2.8
|
||||
if (mScene->isWritable() )
|
||||
{
|
||||
mScene->releaseActor( actor );
|
||||
}
|
||||
else
|
||||
{
|
||||
mReleaseActorQueue.push_back( &actor );
|
||||
}
|
||||
}
|
||||
|
||||
void PxWorld::releaseMaterial( NxMaterial &mat )
|
||||
{
|
||||
AssertFatal( &mat.getScene() == mScene, "PhysXWorld::releaseMaterial() - Bad scene!" );
|
||||
|
||||
// If the scene is not simulating then we have the
|
||||
// write lock and can safely delete it now.
|
||||
if ( !mIsSimulating )
|
||||
mScene->releaseMaterial( mat );
|
||||
else
|
||||
mReleaseMaterialQueue.push_back( &mat );
|
||||
}
|
||||
|
||||
void PxWorld::releaseHeightField( NxHeightField &heightfield )
|
||||
{
|
||||
// Always delay releasing a heightfield, for whatever reason,
|
||||
// it causes lots of deadlock asserts if we do it here, even if
|
||||
// the scene "says" its writable.
|
||||
//
|
||||
// Actually this is probably because a heightfield is owned by the "sdk" and
|
||||
// not an individual scene so if either the client "or" server scene are
|
||||
// simulating it asserts, thats just my theory.
|
||||
|
||||
mReleaseHeightFieldQueue.push_back( &heightfield );
|
||||
}
|
||||
|
||||
void PxWorld::releaseJoint( NxJoint &joint )
|
||||
{
|
||||
AssertFatal( &joint.getScene() == mScene, "PhysXWorld::releaseJoint() - Bad scene!" );
|
||||
|
||||
AssertFatal( !mReleaseJointQueue.contains( &joint ),
|
||||
"PhysXWorld::releaseJoint() - Joint already exists in the release queue!" );
|
||||
|
||||
// Clear the userdata.
|
||||
joint.userData = NULL;
|
||||
|
||||
// If the scene is not simulating then we have the
|
||||
// write lock and can safely delete it now.
|
||||
if ( !mIsSimulating )
|
||||
mScene->releaseJoint( joint );
|
||||
else
|
||||
mReleaseJointQueue.push_back( &joint );
|
||||
}
|
||||
|
||||
void PxWorld::releaseCloth( NxCloth &cloth )
|
||||
{
|
||||
AssertFatal( &cloth.getScene() == mScene, "PhysXWorld::releaseCloth() - Bad scene!" );
|
||||
|
||||
// Clear the userdata.
|
||||
cloth.userData = NULL;
|
||||
|
||||
// If the scene is not simulating then we have the
|
||||
// write lock and can safely delete it now.
|
||||
if ( !mIsSimulating )
|
||||
mScene->releaseCloth( cloth );
|
||||
else
|
||||
mReleaseClothQueue.push_back( &cloth );
|
||||
}
|
||||
|
||||
void PxWorld::releaseFluid( NxFluid &fluid )
|
||||
{
|
||||
AssertFatal( &fluid.getScene() == mScene, "PhysXWorld::releaseFluid() - Bad scene!" );
|
||||
|
||||
// Clear the userdata.
|
||||
fluid.userData = NULL;
|
||||
|
||||
// If the scene is not simulating then we have the
|
||||
// write lock and can safely delete it now.
|
||||
if ( !mIsSimulating )
|
||||
mScene->releaseFluid( fluid );
|
||||
else
|
||||
mReleaseFluidQueue.push_back( &fluid );
|
||||
}
|
||||
|
||||
void PxWorld::releaseClothMesh( NxClothMesh &clothMesh )
|
||||
{
|
||||
// We need the writelock to release.
|
||||
releaseWriteLock();
|
||||
|
||||
gPhysicsSDK->releaseClothMesh( clothMesh );
|
||||
}
|
||||
|
||||
void PxWorld::releaseController( NxController &controller )
|
||||
{
|
||||
// TODO: This isn't safe to do with actors and
|
||||
// joints, so we probably need a queue like we
|
||||
// do for them.
|
||||
|
||||
// We need the writelock to release.
|
||||
releaseWriteLock();
|
||||
|
||||
mControllerManager->releaseController( controller );
|
||||
}
|
||||
|
||||
void PxWorld::_releaseQueues()
|
||||
{
|
||||
AssertFatal( mScene, "PhysXWorld::_releaseQueues() - The scene is null!" );
|
||||
|
||||
// We release joints still pending in the queue
|
||||
// first as they depend on the actors.
|
||||
for ( S32 i = 0; i < mReleaseJointQueue.size(); i++ )
|
||||
{
|
||||
NxJoint *currJoint = mReleaseJointQueue[i];
|
||||
mScene->releaseJoint( *currJoint );
|
||||
}
|
||||
|
||||
// All the joints should be released, clear the queue.
|
||||
mReleaseJointQueue.clear();
|
||||
|
||||
// Now release any actors still pending in the queue.
|
||||
bool staticChanged = false;
|
||||
for ( S32 i = 0; i < mReleaseActorQueue.size(); i++ )
|
||||
{
|
||||
NxActor *currActor = mReleaseActorQueue[i];
|
||||
staticChanged |= !currActor->isDynamic();
|
||||
mScene->releaseActor( *currActor );
|
||||
}
|
||||
|
||||
// All the actors should be released, clear the queue.
|
||||
mReleaseActorQueue.clear();
|
||||
|
||||
// Now release any materials still pending in the queue.
|
||||
for ( S32 i = 0; i < mReleaseMaterialQueue.size(); i++ )
|
||||
{
|
||||
NxMaterial *currMat = mReleaseMaterialQueue[i];
|
||||
mScene->releaseMaterial( *currMat );
|
||||
}
|
||||
|
||||
// All the materials should be released, clear the queue.
|
||||
mReleaseMaterialQueue.clear();
|
||||
|
||||
// Now release any cloth still pending in the queue.
|
||||
for ( S32 i = 0; i < mReleaseClothQueue.size(); i++ )
|
||||
{
|
||||
NxCloth *currCloth = mReleaseClothQueue[i];
|
||||
mScene->releaseCloth( *currCloth );
|
||||
}
|
||||
|
||||
// All the actors should be released, clear the queue.
|
||||
mReleaseClothQueue.clear();
|
||||
|
||||
// Release heightfields that don't still have references.
|
||||
for ( S32 i = 0; i < mReleaseHeightFieldQueue.size(); i++ )
|
||||
{
|
||||
NxHeightField *currHeightfield = mReleaseHeightFieldQueue[i];
|
||||
|
||||
if ( currHeightfield->getReferenceCount() == 0 )
|
||||
{
|
||||
gPhysicsSDK->releaseHeightField( *currHeightfield );
|
||||
mReleaseHeightFieldQueue.erase_fast( i );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear fluid queue
|
||||
for ( S32 i = 0; i < mReleaseFluidQueue.size(); i++ )
|
||||
{
|
||||
NxFluid *currFluid = mReleaseFluidQueue[i];
|
||||
mScene->releaseFluid( *currFluid );
|
||||
}
|
||||
mReleaseFluidQueue.clear();
|
||||
|
||||
if ( staticChanged )
|
||||
mStaticChangedSignal.trigger();
|
||||
}
|
||||
|
||||
void PxWorld::setEnabled( bool enabled )
|
||||
{
|
||||
mIsEnabled = enabled;
|
||||
|
||||
if ( !mIsEnabled )
|
||||
getPhysicsResults();
|
||||
}
|
||||
|
||||
bool PxWorld::initWorld( bool isServer, ProcessList *processList )
|
||||
{
|
||||
/* This stuff is handled outside.
|
||||
PxWorld* world = PxWorld::getWorld( isServer );
|
||||
if ( world )
|
||||
{
|
||||
Con::errorf( "PhysXWorld::initWorld - %s world already exists!", isServer ? "Server" : "Client" );
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
if ( !_init( isServer, processList ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PxWorld::destroyWorld()
|
||||
{
|
||||
//PxWorld* world = PxWorld::getWorld( serverWorld );
|
||||
/*
|
||||
if ( !world )
|
||||
{
|
||||
Con::errorf( "PhysXWorld::destroyWorld - %s world already destroyed!", serverWorld ? "Server" : "Client" );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
//world->_destroy();
|
||||
//delete world;
|
||||
|
||||
_destroy();
|
||||
}
|
||||
|
||||
bool PxWorld::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse )
|
||||
{
|
||||
NxRay worldRay;
|
||||
worldRay.orig = pxCast<NxVec3>( startPnt );
|
||||
worldRay.dir = pxCast<NxVec3>( endPnt - startPnt );
|
||||
NxF32 maxDist = worldRay.dir.magnitude();
|
||||
worldRay.dir.normalize();
|
||||
|
||||
U32 groups = 0xffffffff;
|
||||
groups &= ~( 1<<31 ); // No trigger shapes!
|
||||
|
||||
NxRaycastHit hitInfo;
|
||||
NxShape *hitShape = mScene->raycastClosestShape( worldRay, NX_ALL_SHAPES, hitInfo, groups, maxDist );
|
||||
|
||||
if ( !hitShape )
|
||||
return false;
|
||||
|
||||
//if ( hitShape->userData != NULL )
|
||||
// return false;
|
||||
|
||||
NxActor &actor = hitShape->getActor();
|
||||
PhysicsUserData *userData = PhysicsUserData::cast( actor.userData );
|
||||
|
||||
if ( ri )
|
||||
{
|
||||
ri->object = ( userData != NULL ) ? userData->getObject() : NULL;
|
||||
|
||||
// If we were passed a RayInfo, we can only return true signifying a collision
|
||||
// if we hit an object that actually has a torque object associated with it.
|
||||
//
|
||||
// In some ways this could be considered an error, either a physx object
|
||||
// has raycast-collision enabled that shouldn't or someone did not set
|
||||
// an object in this actor's userData.
|
||||
//
|
||||
if ( ri->object == NULL )
|
||||
return false;
|
||||
|
||||
ri->distance = hitInfo.distance;
|
||||
ri->normal = pxCast<Point3F>( hitInfo.worldNormal );
|
||||
ri->point = pxCast<Point3F>( hitInfo.worldImpact );
|
||||
ri->t = maxDist / hitInfo.distance;
|
||||
}
|
||||
|
||||
if ( impulse.isZero() ||
|
||||
!actor.isDynamic() ||
|
||||
actor.readBodyFlag( NX_BF_KINEMATIC ) )
|
||||
return true;
|
||||
|
||||
NxVec3 force = pxCast<NxVec3>( impulse );//worldRay.dir * forceAmt;
|
||||
actor.addForceAtPos( force, hitInfo.worldImpact, NX_IMPULSE );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PhysicsBody* PxWorld::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes )
|
||||
{
|
||||
NxRay worldRay;
|
||||
worldRay.orig = pxCast<NxVec3>( start );
|
||||
worldRay.dir = pxCast<NxVec3>( end - start );
|
||||
F32 maxDist = worldRay.dir.normalize();
|
||||
|
||||
U32 groups = 0xFFFFFFFF;
|
||||
if ( !( bodyTypes & BT_Player ) )
|
||||
groups &= ~( 1<<29 );
|
||||
|
||||
// TODO: For now always skip triggers and debris,
|
||||
// but we should consider how game specifc this API
|
||||
// should be in the future.
|
||||
groups &= ~( 1<<31 ); // triggers
|
||||
groups &= ~( 1<<30 ); // debris
|
||||
|
||||
U32 shapesType = 0;
|
||||
if ( bodyTypes & BT_Static )
|
||||
shapesType |= NX_STATIC_SHAPES;
|
||||
if ( bodyTypes & BT_Dynamic )
|
||||
shapesType |= NX_DYNAMIC_SHAPES;
|
||||
|
||||
NxRaycastHit hitInfo;
|
||||
NxShape *hitShape = mScene->raycastClosestShape( worldRay, (NxShapesType)shapesType, hitInfo, groups, maxDist );
|
||||
if ( !hitShape )
|
||||
return NULL;
|
||||
|
||||
NxActor &actor = hitShape->getActor();
|
||||
PhysicsUserData *userData = PhysicsUserData::cast( actor.userData );
|
||||
if ( !userData )
|
||||
return NULL;
|
||||
|
||||
return userData->getBody();
|
||||
}
|
||||
|
||||
void PxWorld::explosion( const Point3F &pos, F32 radius, F32 forceMagnitude )
|
||||
{
|
||||
// Find Actors at the position within the radius
|
||||
// and apply force to them.
|
||||
|
||||
NxVec3 nxPos = pxCast<NxVec3>( pos );
|
||||
NxShape **shapes = (NxShape**)NxAlloca(10*sizeof(NxShape*));
|
||||
NxSphere worldSphere( nxPos, radius );
|
||||
|
||||
NxU32 numHits = mScene->overlapSphereShapes( worldSphere, NX_ALL_SHAPES, 10, shapes, NULL );
|
||||
|
||||
for ( NxU32 i = 0; i < numHits; i++ )
|
||||
{
|
||||
NxActor &actor = shapes[i]->getActor();
|
||||
|
||||
bool dynamic = actor.isDynamic();
|
||||
|
||||
if ( !dynamic )
|
||||
continue;
|
||||
|
||||
bool kinematic = actor.readBodyFlag( NX_BF_KINEMATIC );
|
||||
|
||||
if ( kinematic )
|
||||
continue;
|
||||
|
||||
NxVec3 force = actor.getGlobalPosition() - nxPos;
|
||||
force.normalize();
|
||||
force *= forceMagnitude;
|
||||
|
||||
actor.addForceAtPos( force, nxPos, NX_IMPULSE, true );
|
||||
}
|
||||
}
|
||||
|
||||
static ColorI getDebugColor( NxU32 packed )
|
||||
{
|
||||
ColorI col;
|
||||
col.blue = (packed)&0xff;
|
||||
col.green = (packed>>8)&0xff;
|
||||
col.red = (packed>>16)&0xff;
|
||||
col.alpha = 255;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void PxWorld::onDebugDraw( const SceneRenderState *state )
|
||||
{
|
||||
if ( !mScene )
|
||||
return;
|
||||
|
||||
// We need the write lock to be able to request
|
||||
// the NxDebugRenderable object.
|
||||
releaseWriteLock();
|
||||
|
||||
// TODO: We need to expose the different types of visualization
|
||||
// options to script and add a GUI for toggling them!
|
||||
|
||||
gPhysicsSDK->setParameter( NX_VISUALIZATION_SCALE, 1.0f );
|
||||
//gPhysicsSDK->setParameter( NX_VISUALIZE_BODY_MASS_AXES, 0.0f );
|
||||
gPhysicsSDK->setParameter( NX_VISUALIZE_BODY_AXES, 1.0f );
|
||||
gPhysicsSDK->setParameter( NX_VISUALIZE_COLLISION_SHAPES, 1.0f );
|
||||
|
||||
const NxDebugRenderable *data = mScene->getDebugRenderable();
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// Render points
|
||||
{
|
||||
NxU32 numPoints = data->getNbPoints();
|
||||
const NxDebugPoint *points = data->getPoints();
|
||||
|
||||
PrimBuild::begin( GFXPointList, numPoints );
|
||||
|
||||
while ( numPoints-- )
|
||||
{
|
||||
PrimBuild::color( getDebugColor(points->color) );
|
||||
PrimBuild::vertex3fv( &points->p.x );
|
||||
points++;
|
||||
}
|
||||
|
||||
PrimBuild::end();
|
||||
}
|
||||
|
||||
// Render lines
|
||||
{
|
||||
NxU32 numLines = data->getNbLines();
|
||||
const NxDebugLine *lines = data->getLines();
|
||||
|
||||
PrimBuild::begin( GFXLineList, numLines * 2 );
|
||||
|
||||
while ( numLines-- )
|
||||
{
|
||||
PrimBuild::color( getDebugColor( lines->color ) );
|
||||
PrimBuild::vertex3fv( &lines->p0.x );
|
||||
PrimBuild::vertex3fv( &lines->p1.x );
|
||||
lines++;
|
||||
}
|
||||
|
||||
PrimBuild::end();
|
||||
}
|
||||
|
||||
// Render triangles
|
||||
{
|
||||
NxU32 numTris = data->getNbTriangles();
|
||||
const NxDebugTriangle *triangles = data->getTriangles();
|
||||
|
||||
PrimBuild::begin( GFXTriangleList, numTris * 3 );
|
||||
|
||||
while ( numTris-- )
|
||||
{
|
||||
PrimBuild::color( getDebugColor( triangles->color ) );
|
||||
PrimBuild::vertex3fv( &triangles->p0.x );
|
||||
PrimBuild::vertex3fv( &triangles->p1.x );
|
||||
PrimBuild::vertex3fv( &triangles->p2.x );
|
||||
triangles++;
|
||||
}
|
||||
|
||||
PrimBuild::end();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,193 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PHYSX_WORLD_H_
|
||||
#define _PHYSX_WORLD_H_
|
||||
|
||||
#ifndef _T3D_PHYSICS_PHYSICSWORLD_H_
|
||||
#include "T3D/physics/physicsWorld.h"
|
||||
#endif
|
||||
#ifndef _MMATH_H_
|
||||
#include "math/mMath.h"
|
||||
#endif
|
||||
#ifndef _PHYSX_H_
|
||||
#include "T3D/physics/physX/px.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
|
||||
class PxContactReporter;
|
||||
class PxUserNotify;
|
||||
class NxController;
|
||||
class NxControllerDesc;
|
||||
class ShapeBase;
|
||||
class TSStatic;
|
||||
class SceneObject;
|
||||
class ProcessList;
|
||||
class GameBase;
|
||||
class CharacterControllerManager;
|
||||
class PxConsoleStream;
|
||||
|
||||
|
||||
class PxWorld : public PhysicsWorld
|
||||
{
|
||||
protected:
|
||||
|
||||
F32 mEditorTimeScale;
|
||||
|
||||
Vector<NxCloth*> mReleaseClothQueue;
|
||||
Vector<NxJoint*> mReleaseJointQueue;
|
||||
Vector<NxActor*> mReleaseActorQueue;
|
||||
Vector<NxMaterial*> mReleaseMaterialQueue;
|
||||
Vector<NxHeightField*> mReleaseHeightFieldQueue;
|
||||
Vector<NxFluid*> mReleaseFluidQueue;
|
||||
//Vector<StrongRefPtr<PxCollision>> mReleaseColQueue;
|
||||
|
||||
Vector<NxActor*> mCatchupQueue;
|
||||
|
||||
PxContactReporter *mConactReporter;
|
||||
|
||||
PxUserNotify *mUserNotify;
|
||||
|
||||
NxScene *mScene;
|
||||
|
||||
CharacterControllerManager *mControllerManager;
|
||||
|
||||
bool mErrorReport;
|
||||
|
||||
bool mIsEnabled;
|
||||
|
||||
bool mIsSimulating;
|
||||
|
||||
U32 mTickCount;
|
||||
|
||||
ProcessList *mProcessList;
|
||||
|
||||
bool _init( bool isServer, ProcessList *processList );
|
||||
|
||||
void _destroy();
|
||||
|
||||
void _releaseQueues();
|
||||
|
||||
void _updateScheduledStatics();
|
||||
|
||||
/// The mesh cooking interface which is loaded on first use.
|
||||
/// @see getCooking
|
||||
static NxCookingInterface *smCooking;
|
||||
|
||||
/// The console stream for PhysX error reporting.
|
||||
static PxConsoleStream *smConsoleStream;
|
||||
|
||||
public:
|
||||
|
||||
// PhysicWorld
|
||||
virtual bool initWorld( bool isServer, ProcessList *processList );
|
||||
virtual void destroyWorld();
|
||||
virtual bool castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse );
|
||||
virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All );
|
||||
virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude );
|
||||
virtual void onDebugDraw( const SceneRenderState *state );
|
||||
virtual void reset() {}
|
||||
virtual bool isEnabled() const { return mIsEnabled; }
|
||||
|
||||
/// @name Static Methods
|
||||
/// @{
|
||||
|
||||
static bool restartSDK( bool destroyOnly = false, PxWorld *clientWorld = NULL, PxWorld *serverWorld = NULL );
|
||||
|
||||
static void releaseWriteLocks();
|
||||
|
||||
/// @}
|
||||
|
||||
PxWorld();
|
||||
virtual ~PxWorld();
|
||||
|
||||
public:
|
||||
|
||||
NxScene* getScene() { return mScene; }
|
||||
|
||||
/// Returns the cooking interface. Will only return NULL
|
||||
/// in the case of a missing or bad PhysX install.
|
||||
static NxCookingInterface* getCooking();
|
||||
|
||||
U32 getTick() { return mTickCount; }
|
||||
|
||||
void tickPhysics( U32 elapsedMs );
|
||||
|
||||
void getPhysicsResults();
|
||||
|
||||
//void enableCatchupMode( GameBase *obj );
|
||||
|
||||
bool isWritable() const { return !mIsSimulating; /* mScene->isWritable(); */ }
|
||||
|
||||
void releaseWriteLock();
|
||||
|
||||
void setEnabled( bool enabled );
|
||||
bool getEnabled() const { return mIsEnabled; }
|
||||
|
||||
NxMaterial* createMaterial( NxMaterialDesc &material );
|
||||
|
||||
///
|
||||
/// @see releaseController
|
||||
NxController* createController( NxControllerDesc &desc );
|
||||
|
||||
//U16 setMaterial(NxMaterialDesc &material, U16 id);
|
||||
|
||||
// NOTE: This is all a mess, but its a side effect of how
|
||||
// PhysX works. Many objects cannot be deleted without write
|
||||
// access to the scene. Worse some objects cannot be deleted
|
||||
// until their owner objects are deleted first.
|
||||
//
|
||||
// For these reasons we have these methods to register objects to be
|
||||
// released after the Scene has been ticked.
|
||||
//
|
||||
// Since there is no common base to PhysX objects we're stuck with
|
||||
// this list of release methods.
|
||||
//
|
||||
|
||||
void releaseActor( NxActor &actor );
|
||||
|
||||
void releaseMaterial( NxMaterial &mat );
|
||||
|
||||
void releaseJoint( NxJoint &joint );
|
||||
|
||||
void releaseCloth( NxCloth &cloth );
|
||||
|
||||
void releaseClothMesh( NxClothMesh &clothMesh );
|
||||
|
||||
void releaseController( NxController &controller );
|
||||
|
||||
void releaseHeightField( NxHeightField &heightfield );
|
||||
|
||||
void releaseFluid( NxFluid &fluid );
|
||||
|
||||
//void releaseCol( PxCollision *col );
|
||||
|
||||
/// Returns the contact reporter for this scene.
|
||||
PxContactReporter* getContactReporter() { return mConactReporter; }
|
||||
|
||||
void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; }
|
||||
const F32 getEditorTimeScale() const { return mEditorTimeScale; }
|
||||
};
|
||||
|
||||
#endif // _PHYSX_WORLD_H_
|
||||
|
|
@ -417,6 +417,26 @@ void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force )
|
|||
|
||||
}
|
||||
|
||||
void Px3Body::applyTorque( const Point3F &torque )
|
||||
{
|
||||
AssertFatal(mActor, "Px3Body::applyImpulse - The actor is null!");
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
|
||||
if (mIsEnabled && isDynamic())
|
||||
actor->addTorque( px3Cast<physx::PxVec3>(torque), physx::PxForceMode::eFORCE, true);
|
||||
}
|
||||
|
||||
void Px3Body::applyForce( const Point3F &force )
|
||||
{
|
||||
AssertFatal(mActor, "Px3Body::applyTorque - The actor is null!");
|
||||
|
||||
mWorld->releaseWriteLock();
|
||||
physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
|
||||
if (mIsEnabled && isDynamic())
|
||||
actor->addForce( px3Cast<physx::PxVec3>(force), physx::PxForceMode::eFORCE, true);
|
||||
}
|
||||
|
||||
void Px3Body::findContact(SceneObject **contactObject,
|
||||
VectorF *contactNormal,
|
||||
Vector<SceneObject*> *outOverlapObjects) const
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ public:
|
|||
F32 staticFriction );
|
||||
virtual void applyCorrection( const MatrixF &xfm );
|
||||
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
|
||||
|
||||
virtual void applyTorque( const Point3F &torque );
|
||||
virtual void applyForce( const Point3F &force );
|
||||
virtual void findContact(SceneObject **contactObject, VectorF *contactNormal,
|
||||
Vector<SceneObject*> *outOverlapObjects) const;
|
||||
virtual void moveKinematicTo(const MatrixF &xfm);
|
||||
|
|
|
|||
|
|
@ -50,9 +50,6 @@ physx::PxDefaultCpuDispatcher* Px3World::smCpuDispatcher=NULL;
|
|||
Px3ConsoleStream* Px3World::smErrorCallback = NULL;
|
||||
physx::PxVisualDebuggerConnection* Px3World::smPvdConnection=NULL;
|
||||
physx::PxDefaultAllocator Px3World::smMemoryAlloc;
|
||||
//Physics timing
|
||||
F32 Px3World::smPhysicsStepTime = 1.0f/(F32)TickMs;
|
||||
U32 Px3World::smPhysicsMaxIterations = 4;
|
||||
|
||||
Px3World::Px3World(): mScene( NULL ),
|
||||
mProcessList( NULL ),
|
||||
|
|
@ -63,7 +60,8 @@ Px3World::Px3World(): mScene( NULL ),
|
|||
mEditorTimeScale( 1.0f ),
|
||||
mAccumulator( 0 ),
|
||||
mControllerManager(NULL),
|
||||
mIsSceneLocked(false)
|
||||
mIsSceneLocked(false),
|
||||
mRenderBuffer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -76,12 +74,6 @@ physx::PxCooking *Px3World::getCooking()
|
|||
return smCooking;
|
||||
}
|
||||
|
||||
void Px3World::setTiming(F32 stepTime,U32 maxIterations)
|
||||
{
|
||||
smPhysicsStepTime = stepTime;
|
||||
smPhysicsMaxIterations = maxIterations;
|
||||
}
|
||||
|
||||
bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *serverWorld)
|
||||
{
|
||||
// If either the client or the server still exist
|
||||
|
|
@ -177,6 +169,8 @@ void Px3World::destroyWorld()
|
|||
{
|
||||
getPhysicsResults();
|
||||
|
||||
mRenderBuffer = NULL;
|
||||
|
||||
// Release the tick processing signals.
|
||||
if ( mProcessList )
|
||||
{
|
||||
|
|
@ -223,13 +217,14 @@ bool Px3World::initWorld( bool isServer, ProcessList *processList )
|
|||
sceneDesc.cpuDispatcher = smCpuDispatcher;
|
||||
Con::printf("PhysX3 using Cpu: %d workers", smCpuDispatcher->getWorkerCount());
|
||||
}
|
||||
|
||||
|
||||
sceneDesc.flags |= physx::PxSceneFlag::eENABLE_CCD;
|
||||
sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVETRANSFORMS;
|
||||
sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader;
|
||||
|
||||
mScene = gPhysics3SDK->createScene(sceneDesc);
|
||||
//cache renderbuffer for use with debug drawing
|
||||
mRenderBuffer = const_cast<physx::PxRenderBuffer*>(&mScene->getRenderBuffer());
|
||||
|
||||
physx::PxDominanceGroupPair debrisDominance( 0.0f, 1.0f );
|
||||
mScene->setDominanceGroupPair(0,31,debrisDominance);
|
||||
|
|
@ -246,20 +241,20 @@ bool Px3World::initWorld( bool isServer, ProcessList *processList )
|
|||
// Most of this borrowed from bullet physics library, see btDiscreteDynamicsWorld.cpp
|
||||
bool Px3World::_simulate(const F32 dt)
|
||||
{
|
||||
int numSimulationSubSteps = 0;
|
||||
S32 numSimulationSubSteps = 0;
|
||||
//fixed timestep with interpolation
|
||||
mAccumulator += dt;
|
||||
if (mAccumulator >= smPhysicsStepTime)
|
||||
{
|
||||
numSimulationSubSteps = int(mAccumulator / smPhysicsStepTime);
|
||||
numSimulationSubSteps = S32(mAccumulator / smPhysicsStepTime);
|
||||
mAccumulator -= numSimulationSubSteps * smPhysicsStepTime;
|
||||
}
|
||||
if (numSimulationSubSteps)
|
||||
{
|
||||
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
|
||||
int clampedSimulationSteps = (numSimulationSubSteps > smPhysicsMaxIterations)? smPhysicsMaxIterations : numSimulationSubSteps;
|
||||
S32 clampedSimulationSteps = (numSimulationSubSteps > smPhysicsMaxSubSteps)? smPhysicsMaxSubSteps : numSimulationSubSteps;
|
||||
|
||||
for (int i=0;i<clampedSimulationSteps;i++)
|
||||
for (S32 i=0;i<clampedSimulationSteps;i++)
|
||||
{
|
||||
mScene->fetchResults(true);
|
||||
mScene->simulate(smPhysicsStepTime);
|
||||
|
|
@ -548,22 +543,17 @@ static ColorI getDebugColor( physx::PxU32 packed )
|
|||
|
||||
void Px3World::onDebugDraw( const SceneRenderState *state )
|
||||
{
|
||||
if ( !mScene )
|
||||
if ( !mScene || !mRenderBuffer )
|
||||
return;
|
||||
|
||||
mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE,1.0f);
|
||||
mScene->setVisualizationParameter(physx::PxVisualizationParameter::eBODY_AXES,1.0f);
|
||||
mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES,1.0f);
|
||||
|
||||
const physx::PxRenderBuffer *renderBuffer = &mScene->getRenderBuffer();
|
||||
|
||||
if(!renderBuffer)
|
||||
return;
|
||||
|
||||
// Render points
|
||||
{
|
||||
physx::PxU32 numPoints = renderBuffer->getNbPoints();
|
||||
const physx::PxDebugPoint *points = renderBuffer->getPoints();
|
||||
physx::PxU32 numPoints = mRenderBuffer->getNbPoints();
|
||||
const physx::PxDebugPoint *points = mRenderBuffer->getPoints();
|
||||
|
||||
PrimBuild::begin( GFXPointList, numPoints );
|
||||
|
||||
|
|
@ -579,8 +569,8 @@ void Px3World::onDebugDraw( const SceneRenderState *state )
|
|||
|
||||
// Render lines
|
||||
{
|
||||
physx::PxU32 numLines = renderBuffer->getNbLines();
|
||||
const physx::PxDebugLine *lines = renderBuffer->getLines();
|
||||
physx::PxU32 numLines = mRenderBuffer->getNbLines();
|
||||
const physx::PxDebugLine *lines = mRenderBuffer->getLines();
|
||||
|
||||
PrimBuild::begin( GFXLineList, numLines * 2 );
|
||||
|
||||
|
|
@ -598,8 +588,8 @@ void Px3World::onDebugDraw( const SceneRenderState *state )
|
|||
|
||||
// Render triangles
|
||||
{
|
||||
physx::PxU32 numTris = renderBuffer->getNbTriangles();
|
||||
const physx::PxDebugTriangle *triangles = renderBuffer->getTriangles();
|
||||
physx::PxU32 numTris = mRenderBuffer->getNbTriangles();
|
||||
const physx::PxDebugTriangle *triangles = mRenderBuffer->getTriangles();
|
||||
|
||||
PrimBuild::begin( GFXTriangleList, numTris * 3 );
|
||||
|
||||
|
|
@ -618,8 +608,3 @@ void Px3World::onDebugDraw( const SceneRenderState *state )
|
|||
}
|
||||
|
||||
}
|
||||
//set simulation timing via script
|
||||
DefineEngineFunction( physx3SetSimulationTiming, void, ( F32 stepTime, U32 maxSteps ),, "Set simulation timing of the PhysX 3 plugin" )
|
||||
{
|
||||
Px3World::setTiming(stepTime,maxSteps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ protected:
|
|||
ProcessList *mProcessList;
|
||||
F32 mEditorTimeScale;
|
||||
bool mErrorReport;
|
||||
physx::PxRenderBuffer *mRenderBuffer;
|
||||
physx::PxControllerManager* mControllerManager;
|
||||
static Px3ConsoleStream *smErrorCallback;
|
||||
static physx::PxDefaultAllocator smMemoryAlloc;
|
||||
|
|
@ -69,8 +70,6 @@ protected:
|
|||
static physx::PxProfileZoneManager* smProfileZoneManager;
|
||||
static physx::PxDefaultCpuDispatcher* smCpuDispatcher;
|
||||
static physx::PxVisualDebuggerConnection* smPvdConnection;
|
||||
static F32 smPhysicsStepTime;
|
||||
static U32 smPhysicsMaxIterations;
|
||||
F32 mAccumulator;
|
||||
bool _simulate(const F32 dt);
|
||||
|
||||
|
|
@ -103,7 +102,6 @@ public:
|
|||
static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL );
|
||||
static void releaseWriteLocks();
|
||||
static physx::PxCooking *getCooking();
|
||||
static void setTiming(F32 stepTime,U32 maxIterations);
|
||||
static void lockScenes();
|
||||
static void unlockScenes();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -257,15 +257,15 @@ PlayerData::PlayerData()
|
|||
firstPersonShadows = false;
|
||||
|
||||
// Used for third person image rendering
|
||||
imageAnimPrefix = StringTable->insert("");
|
||||
imageAnimPrefix = StringTable->EmptyString();
|
||||
|
||||
allowImageStateAnimation = false;
|
||||
|
||||
// Used for first person image rendering
|
||||
imageAnimPrefixFP = StringTable->insert("");
|
||||
imageAnimPrefixFP = StringTable->EmptyString();
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
{
|
||||
shapeNameFP[i] = StringTable->insert("");
|
||||
shapeNameFP[i] = StringTable->EmptyString();
|
||||
mCRCFP[i] = 0;
|
||||
mValidShapeFP[i] = false;
|
||||
}
|
||||
|
|
@ -418,7 +418,7 @@ PlayerData::PlayerData()
|
|||
|
||||
jumpTowardsNormal = true;
|
||||
|
||||
physicsPlayerType = StringTable->insert("");
|
||||
physicsPlayerType = StringTable->EmptyString();
|
||||
|
||||
dMemset( actionList, 0, sizeof(actionList) );
|
||||
}
|
||||
|
|
@ -3930,9 +3930,9 @@ void Player::updateActionThread()
|
|||
if (mMountPending)
|
||||
mMountPending = (isMounted() ? 0 : (mMountPending - 1));
|
||||
|
||||
if (mActionAnimation.action == PlayerData::NullAnimation ||
|
||||
((!mActionAnimation.waitForEnd || mActionAnimation.atEnd)) &&
|
||||
!mActionAnimation.holdAtEnd && (mActionAnimation.delayTicks -= !mMountPending) <= 0)
|
||||
if ((mActionAnimation.action == PlayerData::NullAnimation) ||
|
||||
((!mActionAnimation.waitForEnd || mActionAnimation.atEnd) &&
|
||||
(!mActionAnimation.holdAtEnd && (mActionAnimation.delayTicks -= !mMountPending) <= 0)))
|
||||
{
|
||||
//The scripting language will get a call back when a script animation has finished...
|
||||
// example: When the chat menu animations are done playing...
|
||||
|
|
@ -6652,7 +6652,7 @@ DefineEngineMethod( Player, setActionThread, bool, ( const char* name, bool hold
|
|||
"@tsexample\n"
|
||||
"// Place the player in a sitting position after being mounted\n"
|
||||
"%player.setActionThread( \"sitting\", true, true );\n"
|
||||
"@endtsexample\n")
|
||||
"@endtsexample\n")
|
||||
{
|
||||
return object->setActionThread( name, hold, true, fsp);
|
||||
}
|
||||
|
|
@ -6700,11 +6700,11 @@ DefineEngineMethod( Player, clearControlObject, void, (),,
|
|||
"Returns control to the player. This internally calls "
|
||||
"Player::setControlObject(0).\n"
|
||||
"@tsexample\n"
|
||||
"%player.clearControlObject();\n"
|
||||
"%player.clearControlObject();\n"
|
||||
"echo(%player.getControlObject()); //<-- Returns 0, player assumes control\n"
|
||||
"%player.setControlObject(%vehicle);\n"
|
||||
"echo(%player.getControlObject()); //<-- Returns %vehicle, player controls the vehicle now.\n"
|
||||
"@endtsexample\n"
|
||||
"@endtsexample\n"
|
||||
"@note If the player does not have a control object, the player will receive all moves "
|
||||
"from its GameConnection. If you're looking to remove control from the player itself "
|
||||
"(i.e. stop sending moves to the player) use GameConnection::setControlObject() to transfer "
|
||||
|
|
@ -6762,63 +6762,63 @@ void Player::consoleInit()
|
|||
"@brief Determines if the player is rendered or not.\n\n"
|
||||
"Used on the client side to disable the rendering of all Player objects. This is "
|
||||
"mainly for the tools or debugging.\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::renderMyItems",TypeBool, &sRenderMyItems,
|
||||
"@brief Determines if mounted shapes are rendered or not.\n\n"
|
||||
"Used on the client side to disable the rendering of all Player mounted objects. This is "
|
||||
"mainly used for the tools or debugging.\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::renderCollision", TypeBool, &sRenderPlayerCollision,
|
||||
"@brief Determines if the player's collision mesh should be rendered.\n\n"
|
||||
"This is mainly used for the tools and debugging.\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
|
||||
Con::addVariable("$player::minWarpTicks",TypeF32,&sMinWarpTicks,
|
||||
"@brief Fraction of tick at which instant warp occures on the client.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::maxWarpTicks",TypeS32,&sMaxWarpTicks,
|
||||
"@brief When a warp needs to occur due to the client being too far off from the server, this is the "
|
||||
"maximum number of ticks we'll allow the client to warp to catch up.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::maxPredictionTicks",TypeS32,&sMaxPredictionTicks,
|
||||
"@brief Maximum number of ticks to predict on the client from the last known move obtained from the server.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
|
||||
Con::addVariable("$player::maxImpulseVelocity", TypeF32, &sMaxImpulseVelocity,
|
||||
"@brief The maximum velocity allowed due to a single impulse.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
|
||||
// Move triggers
|
||||
Con::addVariable("$player::jumpTrigger", TypeS32, &sJumpTrigger,
|
||||
"@brief The move trigger index used for player jumping.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::crouchTrigger", TypeS32, &sCrouchTrigger,
|
||||
"@brief The move trigger index used for player crouching.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::proneTrigger", TypeS32, &sProneTrigger,
|
||||
"@brief The move trigger index used for player prone pose.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::sprintTrigger", TypeS32, &sSprintTrigger,
|
||||
"@brief The move trigger index used for player sprinting.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::imageTrigger0", TypeS32, &sImageTrigger0,
|
||||
"@brief The move trigger index used to trigger mounted image 0.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::imageTrigger1", TypeS32, &sImageTrigger1,
|
||||
"@brief The move trigger index used to trigger mounted image 1 or alternate fire "
|
||||
"on mounted image 0.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::jumpJetTrigger", TypeS32, &sJumpJetTrigger,
|
||||
"@brief The move trigger index used for player jump jetting.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
Con::addVariable("$player::vehicleDismountTrigger", TypeS32, &sVehicleDismountTrigger,
|
||||
"@brief The move trigger index used to dismount player.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
|
||||
// ExtendedMove support
|
||||
Con::addVariable("$player::extendedMoveHeadPosRotIndex", TypeS32, &smExtendedMoveHeadPosRotIndex,
|
||||
"@brief The ExtendedMove position/rotation index used for head movements.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
"@ingroup GameObjects\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -152,13 +152,13 @@ ShapeBaseData::ShapeBaseData()
|
|||
shadowMaxVisibleDistance( 80.0f ),
|
||||
shadowProjectionDistance( 10.0f ),
|
||||
shadowSphereAdjust( 1.0f ),
|
||||
shapeName( StringTable->insert("") ),
|
||||
cloakTexName( StringTable->insert("") ),
|
||||
shapeName( StringTable->EmptyString() ),
|
||||
cloakTexName( StringTable->EmptyString() ),
|
||||
cubeDescId( 0 ),
|
||||
reflectorDesc( NULL ),
|
||||
debris( NULL ),
|
||||
debrisID( 0 ),
|
||||
debrisShapeName( StringTable->insert("") ),
|
||||
debrisShapeName( StringTable->EmptyString() ),
|
||||
explosion( NULL ),
|
||||
explosionID( 0 ),
|
||||
underwaterExplosion( NULL ),
|
||||
|
|
@ -447,12 +447,12 @@ bool ShapeBaseData::_setMass( void* object, const char* index, const char* data
|
|||
{
|
||||
ShapeBaseData* shape = reinterpret_cast< ShapeBaseData* >( object );
|
||||
|
||||
F32 mass = dAtof(data);
|
||||
F32 mass = dAtof(data);
|
||||
|
||||
if (mass <= 0)
|
||||
mass = 0.01f;
|
||||
if (mass <= 0)
|
||||
mass = 0.01f;
|
||||
|
||||
shape->mass = mass;
|
||||
shape->mass = mass;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -936,8 +936,8 @@ ShapeBase::ShapeBase()
|
|||
mScriptThread[i].thread = 0;
|
||||
mScriptThread[i].state = Thread::Stop;
|
||||
mScriptThread[i].atEnd = false;
|
||||
mScriptThread[i].timescale = 1.f;
|
||||
mScriptThread[i].position = -1.f;
|
||||
mScriptThread[i].timescale = 1.f;
|
||||
mScriptThread[i].position = -1.f;
|
||||
}
|
||||
|
||||
for (i = 0; i < MaxTriggerKeys; i++)
|
||||
|
|
@ -1043,7 +1043,7 @@ bool ShapeBase::onAdd()
|
|||
}
|
||||
|
||||
/*
|
||||
if(mDataBlock->cloakTexName != StringTable->insert(""))
|
||||
if(mDataBlock->cloakTexName != StringTable->EmptyString())
|
||||
mCloakTexture = TextureHandle(mDataBlock->cloakTexName, MeshTexture, false);
|
||||
*/
|
||||
// Accumulation and environment mapping
|
||||
|
|
@ -1513,8 +1513,8 @@ void ShapeBase::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery * query)
|
|||
eyeTransform.getColumn(1, &query->orientation);
|
||||
|
||||
// Get the visible distance.
|
||||
if (getSceneManager() != NULL)
|
||||
query->visibleDistance = getSceneManager()->getVisibleDistance();
|
||||
if (getSceneManager() != NULL)
|
||||
query->visibleDistance = getSceneManager()->getVisibleDistance();
|
||||
|
||||
Parent::onCameraScopeQuery( cr, query );
|
||||
}
|
||||
|
|
@ -2155,18 +2155,18 @@ void ShapeBase::updateAudioPos()
|
|||
|
||||
const char *ShapeBase::getThreadSequenceName( U32 slot )
|
||||
{
|
||||
Thread& st = mScriptThread[slot];
|
||||
if ( st.sequence == -1 )
|
||||
{
|
||||
// Invalid Animation.
|
||||
return "";
|
||||
}
|
||||
Thread& st = mScriptThread[slot];
|
||||
if ( st.sequence == -1 )
|
||||
{
|
||||
// Invalid Animation.
|
||||
return "";
|
||||
}
|
||||
|
||||
// Name Index
|
||||
const U32 nameIndex = getShape()->sequences[st.sequence].nameIndex;
|
||||
// Name Index
|
||||
const U32 nameIndex = getShape()->sequences[st.sequence].nameIndex;
|
||||
|
||||
// Return Name.
|
||||
return getShape()->getName( nameIndex );
|
||||
// Return Name.
|
||||
return getShape()->getName( nameIndex );
|
||||
}
|
||||
|
||||
bool ShapeBase::setThreadSequence(U32 slot, S32 seq, bool reset)
|
||||
|
|
@ -2201,39 +2201,39 @@ bool ShapeBase::setThreadSequence(U32 slot, S32 seq, bool reset)
|
|||
|
||||
void ShapeBase::updateThread(Thread& st)
|
||||
{
|
||||
switch (st.state)
|
||||
{
|
||||
case Thread::Stop:
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
} // Drop through to pause state
|
||||
switch (st.state)
|
||||
{
|
||||
case Thread::Stop:
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
} // Drop through to pause state
|
||||
|
||||
case Thread::Pause:
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 0.f );
|
||||
} break;
|
||||
case Thread::Pause:
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 0.f );
|
||||
} break;
|
||||
|
||||
case Thread::Play:
|
||||
{
|
||||
if (st.atEnd)
|
||||
{
|
||||
mShapeInstance->setTimeScale(st.thread,1);
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
mShapeInstance->setTimeScale(st.thread,0);
|
||||
case Thread::Play:
|
||||
{
|
||||
if (st.atEnd)
|
||||
{
|
||||
mShapeInstance->setTimeScale(st.thread,1);
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
mShapeInstance->setTimeScale(st.thread,0);
|
||||
st.state = Thread::Stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( st.position != -1.f )
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, st.position );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( st.position != -1.f )
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, st.position );
|
||||
}
|
||||
|
||||
mShapeInstance->setTimeScale(st.thread, st.timescale );
|
||||
}
|
||||
} break;
|
||||
mShapeInstance->setTimeScale(st.thread, st.timescale );
|
||||
}
|
||||
} break;
|
||||
|
||||
case Thread::Destroy:
|
||||
{
|
||||
|
|
@ -2245,7 +2245,7 @@ void ShapeBase::updateThread(Thread& st)
|
|||
st.thread = 0;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShapeBase::stopThread(U32 slot)
|
||||
|
|
@ -2298,50 +2298,50 @@ bool ShapeBase::playThread(U32 slot)
|
|||
|
||||
bool ShapeBase::setThreadPosition( U32 slot, F32 pos )
|
||||
{
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.position = pos;
|
||||
st.atEnd = false;
|
||||
updateThread(st);
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.position = pos;
|
||||
st.atEnd = false;
|
||||
updateThread(st);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeBase::setThreadDir(U32 slot,bool forward)
|
||||
{
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
if ( ( st.timescale >= 0.f ) != forward )
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.timescale *= -1.f ;
|
||||
st.atEnd = false;
|
||||
updateThread(st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
if ( ( st.timescale >= 0.f ) != forward )
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.timescale *= -1.f ;
|
||||
st.atEnd = false;
|
||||
updateThread(st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeBase::setThreadTimeScale( U32 slot, F32 timeScale )
|
||||
{
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
if (st.timescale != timeScale)
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.timescale = timeScale;
|
||||
updateThread(st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Thread& st = mScriptThread[slot];
|
||||
if (st.sequence != -1)
|
||||
{
|
||||
if (st.timescale != timeScale)
|
||||
{
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.timescale = timeScale;
|
||||
updateThread(st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShapeBase::advanceThreads(F32 dt)
|
||||
|
|
@ -2350,7 +2350,7 @@ void ShapeBase::advanceThreads(F32 dt)
|
|||
Thread& st = mScriptThread[i];
|
||||
if (st.thread) {
|
||||
if (!mShapeInstance->getShape()->sequences[st.sequence].isCyclic() && !st.atEnd &&
|
||||
( ( st.timescale > 0.f )? mShapeInstance->getPos(st.thread) >= 1.0:
|
||||
( ( st.timescale > 0.f )? mShapeInstance->getPos(st.thread) >= 1.0:
|
||||
mShapeInstance->getPos(st.thread) <= 0)) {
|
||||
st.atEnd = true;
|
||||
updateThread(st);
|
||||
|
|
@ -4434,7 +4434,7 @@ DefineEngineMethod( ShapeBase, isEnabled, bool, (),,
|
|||
|
||||
DefineEngineMethod(ShapeBase, blowUp, void, (),, "@brief Explodes an object into pieces.")
|
||||
{
|
||||
object->blowUp();
|
||||
object->blowUp();
|
||||
}
|
||||
|
||||
DefineEngineMethod( ShapeBase, applyDamage, void, ( F32 amount ),,
|
||||
|
|
@ -4738,22 +4738,22 @@ void ShapeBase::consoleInit()
|
|||
"@see ShapeBase::setDamageFlash()\n"
|
||||
"@see ShapeBase::getDamageFlash()\n"
|
||||
"@note Relies on the flash postFx.\n"
|
||||
"@ingroup gameObjects\n");
|
||||
"@ingroup gameObjects\n");
|
||||
Con::addVariable("SB::WODec", TypeF32, &sWhiteoutDec, "Speed to reduce the whiteout effect per tick.\n\n"
|
||||
"@see ShapeBase::setWhiteOut()\n"
|
||||
"@see ShapeBase::getWhiteOut"
|
||||
"@note Relies on the flash postFx.\n"
|
||||
"@ingroup gameObjects\n");
|
||||
"@ingroup gameObjects\n");
|
||||
Con::addVariable("SB::FullCorrectionDistance", TypeF32, &sFullCorrectionDistance,
|
||||
"@brief Distance at which a weapon's muzzle vector is fully corrected to match where the player is looking.\n\n"
|
||||
"When a weapon image has correctMuzzleVector set and the Player is in 1st person, the muzzle vector from the "
|
||||
"weapon is modified to match where the player is looking. Beyond the FullCorrectionDistance the muzzle vector "
|
||||
"is always corrected. Between FullCorrectionDistance and the player, the weapon's muzzle vector is adjusted so that "
|
||||
"the closer the aim point is to the player, the closer the muzzle vector is to the true (non-corrected) one.\n"
|
||||
"@ingroup gameObjects\n");
|
||||
"@ingroup gameObjects\n");
|
||||
Con::addVariable("SB::CloakSpeed", TypeF32, &sCloakSpeed,
|
||||
"@brief Time to cloak, in seconds.\n\n"
|
||||
"@ingroup gameObjects\n");
|
||||
"@ingroup gameObjects\n");
|
||||
}
|
||||
|
||||
void ShapeBase::_updateHiddenMeshes()
|
||||
|
|
@ -4874,17 +4874,17 @@ DefineEngineMethod( ShapeBase, getTargetName, const char*, ( S32 index ),,
|
|||
|
||||
"@see getTargetCount()\n")
|
||||
{
|
||||
ShapeBase *obj = dynamic_cast< ShapeBase* > ( object );
|
||||
if(obj)
|
||||
{
|
||||
// Try to use the client object (so we get the reskinned targets in the Material Editor)
|
||||
if ((ShapeBase*)obj->getClientObject())
|
||||
obj = (ShapeBase*)obj->getClientObject();
|
||||
ShapeBase *obj = dynamic_cast< ShapeBase* > ( object );
|
||||
if(obj)
|
||||
{
|
||||
// Try to use the client object (so we get the reskinned targets in the Material Editor)
|
||||
if ((ShapeBase*)obj->getClientObject())
|
||||
obj = (ShapeBase*)obj->getClientObject();
|
||||
|
||||
return obj->getShapeInstance()->getTargetName(index);
|
||||
}
|
||||
return obj->getShapeInstance()->getTargetName(index);
|
||||
}
|
||||
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
DefineEngineMethod( ShapeBase, getTargetCount, S32, (),,
|
||||
|
|
@ -4903,7 +4903,7 @@ DefineEngineMethod( ShapeBase, getTargetCount, S32, (),,
|
|||
|
||||
if (obj->getShapeInstance() != NULL)
|
||||
return obj->getShapeInstance()->getTargetCount();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -4980,11 +4980,11 @@ DefineEngineMethod( ShapeBase, getModelFile, const char *, (),,
|
|||
|
||||
"@return the shape filename\n\n" )
|
||||
{
|
||||
GameBaseData * datablock = object->getDataBlock();
|
||||
if( !datablock )
|
||||
return String::EmptyString;
|
||||
GameBaseData * datablock = object->getDataBlock();
|
||||
if( !datablock )
|
||||
return String::EmptyString;
|
||||
|
||||
const char *fieldName = StringTable->insert( String("shapeFile") );
|
||||
const char *fieldName = StringTable->insert( String("shapeFile") );
|
||||
return datablock->getDataField( fieldName, NULL );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
lightRadius = 10.f;
|
||||
lightBrightness = 1.0f;
|
||||
|
||||
shapeName = "";
|
||||
shapeName = "core/art/shapes/noshape.dts";
|
||||
shapeNameFP = "";
|
||||
imageAnimPrefix = "";
|
||||
imageAnimPrefixFP = "";
|
||||
|
|
@ -2638,7 +2638,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
F32 randomPos = Platform::getRandom();
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || i != imageShapeIndex && !image.doAnimateAllShapes)
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
||||
if (image.animThread[i] && image.state->sequence[i] != -1 && image.state->flashSequence[i]) {
|
||||
|
|
@ -2779,7 +2779,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
|
|||
updateAnimThread(imageSlot, imageShapeIndex, lastState);
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || i != imageShapeIndex && !image.doAnimateAllShapes)
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
||||
// Start spin thread
|
||||
|
|
@ -2834,7 +2834,7 @@ void ShapeBase::updateAnimThread(U32 imageSlot, S32 imageShapeIndex, ShapeBaseIm
|
|||
F32 randomPos = Platform::getRandom();
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || i != imageShapeIndex && !image.doAnimateAllShapes)
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
||||
if (image.animThread[i] && stateData.sequence[i] != -1)
|
||||
|
|
@ -3076,7 +3076,7 @@ TICKAGAIN:
|
|||
U32 imageShapeIndex = getImageShapeIndex(image);
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || i != imageShapeIndex && !image.doAnimateAllShapes)
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
||||
if (image.spinThread[i])
|
||||
|
|
@ -3131,7 +3131,7 @@ void ShapeBase::updateImageAnimation(U32 imageSlot, F32 dt)
|
|||
// Advance animation threads
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
|
||||
{
|
||||
if (!image.dataBlock->shapeIsValid[i] || i != imageShapeIndex && !image.doAnimateAllShapes)
|
||||
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
|
||||
continue;
|
||||
|
||||
if (image.ambientThread[i])
|
||||
|
|
|
|||
|
|
@ -251,14 +251,14 @@ void StaticShape::onUnmount(SceneObject*,S32)
|
|||
|
||||
U32 StaticShape::packUpdate(NetConnection *connection, U32 mask, BitStream *bstream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(connection, mask, bstream);
|
||||
if (bstream->writeFlag(mask & PositionMask | ExtendedInfoMask))
|
||||
U32 retMask = Parent::packUpdate(connection,mask,bstream);
|
||||
if (bstream->writeFlag(mask & (PositionMask | ExtendedInfoMask)))
|
||||
{
|
||||
|
||||
// Write the transform (do _not_ use writeAffineTransform. Since this is a static
|
||||
// object, the transform must be RIGHT THE *&)*$&^ ON or it will goof up the
|
||||
// synchronization between the client and the server.
|
||||
mathWrite(*bstream, mObjToWorld);
|
||||
mathWrite(*bstream,mObjToWorld);
|
||||
mathWrite(*bstream, mObjScale);
|
||||
}
|
||||
|
||||
|
|
@ -275,11 +275,11 @@ U32 StaticShape::packUpdate(NetConnection *connection, U32 mask, BitStream *bstr
|
|||
|
||||
void StaticShape::unpackUpdate(NetConnection *connection, BitStream *bstream)
|
||||
{
|
||||
Parent::unpackUpdate(connection, bstream);
|
||||
Parent::unpackUpdate(connection,bstream);
|
||||
if (bstream->readFlag())
|
||||
{
|
||||
MatrixF mat;
|
||||
mathRead(*bstream, &mat);
|
||||
mathRead(*bstream,&mat);
|
||||
Parent::setTransform(mat);
|
||||
Parent::setRenderTransform(mat);
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ void StaticShape::unpackUpdate(NetConnection *connection, BitStream *bstream)
|
|||
// This appears to be legacy T2 stuff
|
||||
// Marked internal, as this is flagged to be deleted
|
||||
// [8/1/2010 mperry]
|
||||
DefineConsoleMethod(StaticShape, setPoweredState, void, (bool isPowered), , "(bool isPowered)"
|
||||
DefineConsoleMethod( StaticShape, setPoweredState, void, (bool isPowered), , "(bool isPowered)"
|
||||
"@internal")
|
||||
{
|
||||
if(!object->isServerObject())
|
||||
|
|
@ -310,7 +310,7 @@ DefineConsoleMethod(StaticShape, setPoweredState, void, (bool isPowered), , "(bo
|
|||
object->setPowered(isPowered);
|
||||
}
|
||||
|
||||
DefineConsoleMethod(StaticShape, getPoweredState, bool, (), , "@internal")
|
||||
DefineConsoleMethod( StaticShape, getPoweredState, bool, (), , "@internal")
|
||||
{
|
||||
if(!object->isServerObject())
|
||||
return(false);
|
||||
|
|
|
|||
|
|
@ -1256,7 +1256,7 @@ DefineEngineMethod( TSStatic, getTargetCount, S32,(),,
|
|||
// This method is able to change materials per map to with others. The material that is being replaced is being mapped to
|
||||
// unmapped_mat as a part of this transition
|
||||
|
||||
DefineEngineMethod( TSStatic, changeMaterial, void, ( const char* mapTo, Material* oldMat, Material* newMat ),("",NULL,NULL),
|
||||
DefineEngineMethod( TSStatic, changeMaterial, void, ( const char* mapTo, Material* oldMat, Material* newMat ),("",nullAsType<Material*>(),nullAsType<Material*>()),
|
||||
"@brief Change one of the materials on the shape.\n\n"
|
||||
|
||||
"This method changes materials per mapTo with others. The material that "
|
||||
|
|
@ -1323,4 +1323,4 @@ DefineEngineMethod( TSStatic, getModelFile, const char *, (),,
|
|||
)
|
||||
{
|
||||
return object->getShapeFileName();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1163,7 +1163,7 @@ U32 AITurretShape::packUpdate(NetConnection *connection, U32 mask, BitStream *bs
|
|||
U32 retMask = Parent::packUpdate(connection,mask,bstream);
|
||||
|
||||
// Indicate that the transform has changed to update the scan box
|
||||
bstream->writeFlag(mask & PositionMask | ExtendedInfoMask);
|
||||
bstream->writeFlag(mask & (PositionMask | ExtendedInfoMask));
|
||||
|
||||
// Handle any state changes that need to be passed along
|
||||
if (bstream->writeFlag(mask & TurretStateMask))
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/controls/guiBitmapCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "T3D/vehicles/vehicle.h"
|
||||
#include "T3D/player.h"
|
||||
#include "gfx/primBuilder.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -147,42 +147,57 @@ void GuiSpeedometerHud::initPersistFields()
|
|||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
Gui onRender method.
|
||||
Renders a health bar with filled background and border.
|
||||
Renders an analog speedometer needle over a specified bitmap background.
|
||||
*/
|
||||
void GuiSpeedometerHud::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
// Must have a connection and player control object
|
||||
// Must have a connection
|
||||
GameConnection* conn = GameConnection::getConnectionToServer();
|
||||
if (!conn)
|
||||
return;
|
||||
Vehicle* control = dynamic_cast<Vehicle*>(conn->getControlObject());
|
||||
if (!control)
|
||||
return;
|
||||
|
||||
// Requires either a vehicle control object or a vehicle-mounted player
|
||||
Vehicle* vehicle = dynamic_cast<Vehicle*>(conn->getControlObject());
|
||||
if(!vehicle){
|
||||
Player * player = dynamic_cast<Player*>(conn->getControlObject());
|
||||
if(!player) return;
|
||||
if (!player->isMounted()) return;
|
||||
vehicle = dynamic_cast<Vehicle*>(player->getObjectMount());
|
||||
if(!vehicle) return;
|
||||
}
|
||||
|
||||
Parent::onRender(offset,updateRect);
|
||||
|
||||
// Use the vehicle's velocity as its speed...
|
||||
mSpeed = control->getVelocity().len();
|
||||
mSpeed = vehicle->getVelocity().len();
|
||||
if (mSpeed > mMaxSpeed)
|
||||
mSpeed = mMaxSpeed;
|
||||
|
||||
// Render the needle
|
||||
GFX->pushWorldMatrix();
|
||||
// Calculate center point if necessary and roll in offsets
|
||||
Point2F center = mCenter;
|
||||
if (mIsZero(center.x) && mIsZero(center.y))
|
||||
{
|
||||
center.x = getExtent().x / 2.0f;
|
||||
center.y = getExtent().y / 2.0f;
|
||||
}
|
||||
MatrixF newMat(1);
|
||||
F32 fillOffset = GFX->getFillConventionOffset(); // Find the fill offset
|
||||
Point2F viewCenter(offset.x + fillOffset + center.x, offset.y + fillOffset + center.y);
|
||||
|
||||
newMat.setPosition(Point3F(getLeft() + center.x, getTop() + center.y, 0.0f));
|
||||
|
||||
F32 rotation = mMinAngle + (mMaxAngle - mMinAngle) * (mSpeed / mMaxSpeed);
|
||||
AngAxisF newRot(Point3F(0.0f,0.0f,-1.0f), rotation);
|
||||
|
||||
newRot.setMatrix(&newMat);
|
||||
// Handle rotation calculations
|
||||
F32 rotation, spinAngle;
|
||||
rotation = mMinAngle + (mMaxAngle - mMinAngle) * (mSpeed / mMaxSpeed);
|
||||
spinAngle = mDegToRad(rotation);
|
||||
MatrixF rotMatrix(EulerF(0.0, 0.0, spinAngle));
|
||||
|
||||
// Set up the needle vertex list
|
||||
Point3F vertList[5];
|
||||
vertList[0].set(+mNeedleLength,-mNeedleWidth,0);
|
||||
vertList[1].set(+mNeedleLength,+mNeedleWidth,0);
|
||||
vertList[2].set(-mTailLength ,+mNeedleWidth,0);
|
||||
vertList[3].set(-mTailLength ,-mNeedleWidth,0);
|
||||
vertList[4].set(+mNeedleLength,-mNeedleWidth,0); //// Get back to the start!
|
||||
|
||||
// Create a GFXStateBlock description if one has not been set.
|
||||
if (mBlendSB.isNull())
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
|
|
@ -191,22 +206,15 @@ void GuiSpeedometerHud::onRender(Point2I offset, const RectI &updateRect)
|
|||
desc.samplers[0].textureColorOp = GFXTOPDisable;
|
||||
mBlendSB = GFX->createStateBlock(desc);
|
||||
}
|
||||
|
||||
GFX->setStateBlock(mBlendSB);
|
||||
|
||||
GFX->setTexture(0, NULL);
|
||||
|
||||
PrimBuild::begin(GFXLineStrip, 5);
|
||||
// Render the needle
|
||||
PrimBuild::color4f(mColor.red, mColor.green, mColor.blue, mColor.alpha);
|
||||
|
||||
PrimBuild::vertex2f(+mNeedleLength,-mNeedleWidth);
|
||||
PrimBuild::vertex2f(+mNeedleLength,+mNeedleWidth);
|
||||
PrimBuild::vertex2f(-mTailLength ,+mNeedleWidth);
|
||||
PrimBuild::vertex2f(-mTailLength ,-mNeedleWidth);
|
||||
|
||||
//// Get back to the start!
|
||||
PrimBuild::vertex2f(+mNeedleLength,-mNeedleWidth);
|
||||
|
||||
PrimBuild::begin(GFXLineStrip, 5);
|
||||
for(int k=0; k<5; k++){
|
||||
rotMatrix.mulP(vertList[k]);
|
||||
PrimBuild::vertex2f(vertList[k].x + viewCenter.x, vertList[k].y + viewCenter.y);
|
||||
}
|
||||
PrimBuild::end();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ DefineEngineFunction(addBadWord, bool, (const char* badWord),,
|
|||
return gBadWordFilter->addBadWord(badWord);
|
||||
}
|
||||
|
||||
DefineEngineFunction(filterString, const char *, (const char* baseString, const char* replacementChars), (NULL, NULL),
|
||||
DefineEngineFunction(filterString, const char *, (const char* baseString, const char* replacementChars), (nullAsType<const char*>(), nullAsType<const char*>()),
|
||||
"@brief Replaces the characters in a string with designated text\n\n"
|
||||
|
||||
"Uses the bad word filter to determine which characters within the string will be replaced.\n\n"
|
||||
|
|
|
|||
|
|
@ -774,9 +774,9 @@ YY_MALLOC_DECL
|
|||
|
||||
YY_DECL
|
||||
{
|
||||
register yy_state_type yy_current_state;
|
||||
register char *yy_cp, *yy_bp;
|
||||
register int yy_act;
|
||||
yy_state_type yy_current_state;
|
||||
char *yy_cp, *yy_bp;
|
||||
int yy_act;
|
||||
|
||||
#line 105 "CMDscan.l"
|
||||
|
||||
|
|
@ -823,7 +823,7 @@ YY_DECL
|
|||
yy_match:
|
||||
do
|
||||
{
|
||||
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
|
||||
YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
|
||||
if ( yy_accept[yy_current_state] )
|
||||
{
|
||||
yy_last_accepting_state = yy_current_state;
|
||||
|
|
@ -1048,7 +1048,7 @@ case 37:
|
|||
YY_RULE_SETUP
|
||||
#line 143 "CMDscan.l"
|
||||
{ /* this comment stops syntax highlighting from getting messed up when editing the lexer in TextPad */
|
||||
register int c = 0, l;
|
||||
int c = 0, l;
|
||||
for ( ; ; )
|
||||
{
|
||||
l = c;
|
||||
|
|
@ -1430,9 +1430,9 @@ case YY_STATE_EOF(INITIAL):
|
|||
|
||||
static int yy_get_next_buffer()
|
||||
{
|
||||
register char *dest = yy_current_buffer->yy_ch_buf;
|
||||
register char *source = yytext_ptr;
|
||||
register int number_to_move, i;
|
||||
char *dest = yy_current_buffer->yy_ch_buf;
|
||||
char *source = yytext_ptr;
|
||||
int number_to_move, i;
|
||||
int ret_val;
|
||||
|
||||
if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
|
||||
|
|
@ -1560,14 +1560,14 @@ static int yy_get_next_buffer()
|
|||
|
||||
static yy_state_type yy_get_previous_state()
|
||||
{
|
||||
register yy_state_type yy_current_state;
|
||||
register char *yy_cp;
|
||||
yy_state_type yy_current_state;
|
||||
char *yy_cp;
|
||||
|
||||
yy_current_state = yy_start;
|
||||
|
||||
for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
|
||||
{
|
||||
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
|
||||
YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
|
||||
if ( yy_accept[yy_current_state] )
|
||||
{
|
||||
yy_last_accepting_state = yy_current_state;
|
||||
|
|
@ -1599,10 +1599,10 @@ static yy_state_type yy_try_NUL_trans( yy_current_state )
|
|||
yy_state_type yy_current_state;
|
||||
#endif
|
||||
{
|
||||
register int yy_is_jam;
|
||||
register char *yy_cp = yy_c_buf_p;
|
||||
int yy_is_jam;
|
||||
char *yy_cp = yy_c_buf_p;
|
||||
|
||||
register YY_CHAR yy_c = 1;
|
||||
YY_CHAR yy_c = 1;
|
||||
if ( yy_accept[yy_current_state] )
|
||||
{
|
||||
yy_last_accepting_state = yy_current_state;
|
||||
|
|
@ -1623,14 +1623,14 @@ yy_state_type yy_current_state;
|
|||
|
||||
#ifndef YY_NO_UNPUT
|
||||
#ifdef YY_USE_PROTOS
|
||||
static void yyunput( int c, register char *yy_bp )
|
||||
static void yyunput( int c, char *yy_bp )
|
||||
#else
|
||||
static void yyunput( c, yy_bp )
|
||||
int c;
|
||||
register char *yy_bp;
|
||||
char *yy_bp;
|
||||
#endif
|
||||
{
|
||||
register char *yy_cp = yy_c_buf_p;
|
||||
char *yy_cp = yy_c_buf_p;
|
||||
|
||||
/* undo effects of setting up yytext */
|
||||
*yy_cp = yy_hold_char;
|
||||
|
|
@ -1638,10 +1638,10 @@ register char *yy_bp;
|
|||
if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
|
||||
{ /* need to shift things up to make room */
|
||||
/* +2 for EOB chars. */
|
||||
register int number_to_move = yy_n_chars + 2;
|
||||
register char *dest = &yy_current_buffer->yy_ch_buf[
|
||||
int number_to_move = yy_n_chars + 2;
|
||||
char *dest = &yy_current_buffer->yy_ch_buf[
|
||||
yy_current_buffer->yy_buf_size + 2];
|
||||
register char *source =
|
||||
char *source =
|
||||
&yy_current_buffer->yy_ch_buf[number_to_move];
|
||||
|
||||
while ( source > yy_current_buffer->yy_ch_buf )
|
||||
|
|
@ -2095,7 +2095,7 @@ yyconst char *s2;
|
|||
int n;
|
||||
#endif
|
||||
{
|
||||
register int i;
|
||||
int i;
|
||||
for ( i = 0; i < n; ++i )
|
||||
s1[i] = s2[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ HEXDIGIT [a-fA-F0-9]
|
|||
"SPC" { CMDlval.i = MakeToken< int >( ' ', lineIndex ); return '@'; }
|
||||
"@" { CMDlval.i = MakeToken< int >( 0, lineIndex ); return '@'; }
|
||||
"/*" { /* this comment stops syntax highlighting from getting messed up when editing the lexer in TextPad */
|
||||
register int c = 0, l;
|
||||
int c = 0, l;
|
||||
for ( ; ; )
|
||||
{
|
||||
l = c;
|
||||
|
|
|
|||
|
|
@ -49,40 +49,40 @@ ConsoleDocClass( SimXMLDocument,
|
|||
"// Thanks to Rex Hiebert for this example\n"
|
||||
"// Given the following XML\n"
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
|
||||
"<DataTables>\n"
|
||||
" <table tableName=\"2DShapes\">\n"
|
||||
" <rec id=\"1\">Triangle</rec>\n"
|
||||
" <rec id=\"2\">Square</rec>\n"
|
||||
" <rec id=\"3\">Circle</rec>\n"
|
||||
" </table>\n"
|
||||
" <table tableName=\"3DShapes\">\n"
|
||||
" <rec id=\"1\">Pyramid</rec>\n"
|
||||
" <rec id=\"2\">Cube</rec>\n"
|
||||
" <rec id=\"3\">Sphere</rec>\n"
|
||||
" </table>\n"
|
||||
"</DataTables>\n\n"
|
||||
"<DataTables>\n"
|
||||
" <table tableName=\"2DShapes\">\n"
|
||||
" <rec id=\"1\">Triangle</rec>\n"
|
||||
" <rec id=\"2\">Square</rec>\n"
|
||||
" <rec id=\"3\">Circle</rec>\n"
|
||||
" </table>\n"
|
||||
" <table tableName=\"3DShapes\">\n"
|
||||
" <rec id=\"1\">Pyramid</rec>\n"
|
||||
" <rec id=\"2\">Cube</rec>\n"
|
||||
" <rec id=\"3\">Sphere</rec>\n"
|
||||
" </table>\n"
|
||||
"</DataTables>\n\n"
|
||||
"// Using SimXMLDocument by itself\n"
|
||||
"function readXmlExample(%filename)\n"
|
||||
"{\n"
|
||||
" %xml = new SimXMLDocument() {};\n"
|
||||
" %xml.loadFile(%filename);\n\n"
|
||||
" %xml.pushChildElement(\"DataTables\");\n"
|
||||
" %xml.pushFirstChildElement(\"table\");\n"
|
||||
" while(true)\n"
|
||||
" {\n"
|
||||
" echo(\"TABLE:\" SPC %xml.attribute(\"tableName\"));\n"
|
||||
" %xml.pushFirstChildElement(\"rec\");\n"
|
||||
" while (true)\n"
|
||||
" {\n"
|
||||
" %id = %xml.attribute(\"id\");\n"
|
||||
" %desc = %xml.getData();\n"
|
||||
" echo(\" Shape\" SPC %id SPC %desc);\n"
|
||||
" if (!%xml.nextSiblingElement(\"rec\")) break;\n"
|
||||
" }\n"
|
||||
" %xml.popElement();\n"
|
||||
" if (!%xml.nextSiblingElement(\"table\")) break;\n"
|
||||
" }\n"
|
||||
"}\n\n"
|
||||
"{\n"
|
||||
" %xml = new SimXMLDocument() {};\n"
|
||||
" %xml.loadFile(%filename);\n\n"
|
||||
" %xml.pushChildElement(\"DataTables\");\n"
|
||||
" %xml.pushFirstChildElement(\"table\");\n"
|
||||
" while(true)\n"
|
||||
" {\n"
|
||||
" echo(\"TABLE:\" SPC %xml.attribute(\"tableName\"));\n"
|
||||
" %xml.pushFirstChildElement(\"rec\");\n"
|
||||
" while (true)\n"
|
||||
" {\n"
|
||||
" %id = %xml.attribute(\"id\");\n"
|
||||
" %desc = %xml.getData();\n"
|
||||
" echo(\" Shape\" SPC %id SPC %desc);\n"
|
||||
" if (!%xml.nextSiblingElement(\"rec\")) break;\n"
|
||||
" }\n"
|
||||
" %xml.popElement();\n"
|
||||
" if (!%xml.nextSiblingElement(\"table\")) break;\n"
|
||||
" }\n"
|
||||
"}\n\n"
|
||||
|
||||
"// Thanks to Scott Peal for this example\n"
|
||||
"// Using FileObject in conjunction with SimXMLDocument\n"
|
||||
|
|
@ -90,45 +90,45 @@ ConsoleDocClass( SimXMLDocument,
|
|||
"// <Models>\n"
|
||||
"// <Model category=\"\" name=\"\" path=\"\" />\n"
|
||||
"// </Models>\n"
|
||||
"function getModelsInCatagory()\n"
|
||||
"{\n"
|
||||
" %file = \"./Catalog.xml\";\n"
|
||||
" %fo = new FileObject();\n"
|
||||
" %text = \"\";\n\n"
|
||||
" if(%fo.openForRead(%file))\n"
|
||||
" {\n"
|
||||
" while(!%fo.isEOF())\n"
|
||||
" {\n"
|
||||
" %text = %text @ %fo.readLine();\n"
|
||||
" if (!%fo.isEOF()) %text = %text @ \"\\n\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" echo(\"Unable to locate the file: \" @ %file);\n"
|
||||
" }\n\n"
|
||||
" %fo.delete();\n\n"
|
||||
" %xml = new SimXMLDocument() {};\n"
|
||||
" %xml.parse(%text);\n"
|
||||
" // \"Get\" inside of the root element, \"Models\".\n"
|
||||
" %xml.pushChildElement(0);\n\n"
|
||||
" // \"Get\" into the first child element\n"
|
||||
" if (%xml.pushFirstChildElement(\"Model\"))\n"
|
||||
" {\n"
|
||||
" while (true)\n"
|
||||
" {\n"
|
||||
" // \n"
|
||||
" // Here, i read the element's attributes.\n"
|
||||
" // You might want to save these values in an array or call the %xml.getElementValue()\n"
|
||||
" // if you have a different XML structure.\n\n"
|
||||
" %catagory = %xml.attribute(\"catagory\");\n"
|
||||
" %name = %xml.attribute(\"name\");\n"
|
||||
" %path = %xml.attribute(\"path\");\n\n"
|
||||
" // now, read the next \"Model\"\n"
|
||||
" if (!%xml.nextSiblingElement(\"Model\")) break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"function getModelsInCatagory()\n"
|
||||
"{\n"
|
||||
" %file = \"./Catalog.xml\";\n"
|
||||
" %fo = new FileObject();\n"
|
||||
" %text = \"\";\n\n"
|
||||
" if(%fo.openForRead(%file))\n"
|
||||
" {\n"
|
||||
" while(!%fo.isEOF())\n"
|
||||
" {\n"
|
||||
" %text = %text @ %fo.readLine();\n"
|
||||
" if (!%fo.isEOF()) %text = %text @ \"\\n\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" echo(\"Unable to locate the file: \" @ %file);\n"
|
||||
" }\n\n"
|
||||
" %fo.delete();\n\n"
|
||||
" %xml = new SimXMLDocument() {};\n"
|
||||
" %xml.parse(%text);\n"
|
||||
" // \"Get\" inside of the root element, \"Models\".\n"
|
||||
" %xml.pushChildElement(0);\n\n"
|
||||
" // \"Get\" into the first child element\n"
|
||||
" if (%xml.pushFirstChildElement(\"Model\"))\n"
|
||||
" {\n"
|
||||
" while (true)\n"
|
||||
" {\n"
|
||||
" // \n"
|
||||
" // Here, i read the element's attributes.\n"
|
||||
" // You might want to save these values in an array or call the %xml.getElementValue()\n"
|
||||
" // if you have a different XML structure.\n\n"
|
||||
" %catagory = %xml.attribute(\"catagory\");\n"
|
||||
" %name = %xml.attribute(\"name\");\n"
|
||||
" %path = %xml.attribute(\"path\");\n\n"
|
||||
" // now, read the next \"Model\"\n"
|
||||
" if (!%xml.nextSiblingElement(\"Model\")) break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@note SimXMLDocument is a wrapper around TinyXml, a standard XML library. If you're familiar "
|
||||
|
|
@ -504,13 +504,13 @@ const char* SimXMLDocument::elementValue()
|
|||
{
|
||||
if(m_paNode.empty())
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
const S32 iLastElement = m_paNode.size() - 1;
|
||||
TiXmlElement* pNode = m_paNode[iLastElement];
|
||||
if(!pNode)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return pNode->Value();
|
||||
|
|
@ -545,18 +545,18 @@ const char* SimXMLDocument::attribute(const char* rAttribute)
|
|||
{
|
||||
if(m_paNode.empty())
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
const S32 iLastElement = m_paNode.size() - 1;
|
||||
TiXmlElement* pNode = m_paNode[iLastElement];
|
||||
if(!pNode)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
if(!pNode->Attribute(rAttribute))
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return pNode->Attribute(rAttribute);
|
||||
|
|
@ -629,20 +629,20 @@ const char* SimXMLDocument::firstAttribute()
|
|||
// Get the current element
|
||||
if(m_paNode.empty())
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
const S32 iLastElement = m_paNode.size() - 1;
|
||||
TiXmlElement* pNode = m_paNode[iLastElement];
|
||||
if(!pNode)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
// Gets its first attribute, if any
|
||||
m_CurrentAttribute = pNode->FirstAttribute();
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return m_CurrentAttribute->Name();
|
||||
|
|
@ -666,20 +666,20 @@ const char* SimXMLDocument::lastAttribute()
|
|||
// Get the current element
|
||||
if(m_paNode.empty())
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
const S32 iLastElement = m_paNode.size() - 1;
|
||||
TiXmlElement* pNode = m_paNode[iLastElement];
|
||||
if(!pNode)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
// Gets its last attribute, if any
|
||||
m_CurrentAttribute = pNode->LastAttribute();
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return m_CurrentAttribute->Name();
|
||||
|
|
@ -703,14 +703,14 @@ const char* SimXMLDocument::nextAttribute()
|
|||
{
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
// Gets its next attribute, if any
|
||||
m_CurrentAttribute = m_CurrentAttribute->Next();
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return m_CurrentAttribute->Name();
|
||||
|
|
@ -734,14 +734,14 @@ const char* SimXMLDocument::prevAttribute()
|
|||
{
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
// Gets its next attribute, if any
|
||||
m_CurrentAttribute = m_CurrentAttribute->Previous();
|
||||
if(!m_CurrentAttribute)
|
||||
{
|
||||
return StringTable->insert("");
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
return m_CurrentAttribute->Name();
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ ObjectDeclNode *ObjectDeclNode::alloc( S32 lineNumber, ExprNode *classNameExpr,
|
|||
if(parentObject)
|
||||
ret->parentObject = parentObject;
|
||||
else
|
||||
ret->parentObject = StringTable->insert("");
|
||||
ret->parentObject = StringTable->EmptyString();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1288,9 +1288,9 @@ __yy_memcpy (from, to, count)
|
|||
char *to;
|
||||
int count;
|
||||
{
|
||||
register char *f = from;
|
||||
register char *t = to;
|
||||
register int i = count;
|
||||
char *f = from;
|
||||
char *t = to;
|
||||
int i = count;
|
||||
|
||||
while (i-- > 0)
|
||||
*t++ = *f++;
|
||||
|
|
@ -1303,9 +1303,9 @@ __yy_memcpy (from, to, count)
|
|||
static void
|
||||
__yy_memcpy (char *from, char *to, int count)
|
||||
{
|
||||
register char *f = from;
|
||||
register char *t = to;
|
||||
register int i = count;
|
||||
char *f = from;
|
||||
char *t = to;
|
||||
int i = count;
|
||||
|
||||
while (i-- > 0)
|
||||
*t++ = *f++;
|
||||
|
|
@ -1333,10 +1333,10 @@ int
|
|||
yyparse(YYPARSE_PARAM)
|
||||
YYPARSE_PARAM_DECL
|
||||
{
|
||||
register int yystate;
|
||||
register int yyn;
|
||||
register short *yyssp;
|
||||
register YYSTYPE *yyvsp;
|
||||
int yystate;
|
||||
int yyn;
|
||||
short *yyssp;
|
||||
YYSTYPE *yyvsp;
|
||||
int yyerrstatus; /* number of tokens to shift before error messages enabled */
|
||||
int yychar1 = 0; /* lookahead token as an internal (translated) token number */
|
||||
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st)
|
|||
if(offset < globalSize)
|
||||
ste = StringTable->insert(globalStrings + offset);
|
||||
else
|
||||
ste = StringTable->insert("");
|
||||
ste = StringTable->EmptyString();
|
||||
U32 count;
|
||||
st.read(&count);
|
||||
while(count--)
|
||||
|
|
@ -455,8 +455,8 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st)
|
|||
|
||||
bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, const char *inScript, bool overrideNoDso)
|
||||
{
|
||||
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
|
||||
|
||||
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
|
||||
|
||||
// This will return true, but return value is ignored
|
||||
char *script;
|
||||
chompUTF8BOM( inScript, &script );
|
||||
|
|
@ -572,8 +572,8 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
|
|||
|
||||
ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
|
||||
{
|
||||
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
|
||||
|
||||
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
|
||||
|
||||
// Check for a UTF8 script file
|
||||
char *string;
|
||||
chompUTF8BOM( inString, &string );
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ struct ConsoleLogEntry
|
|||
Script,
|
||||
GUI,
|
||||
Network,
|
||||
GGConnect,
|
||||
NUM_TYPE
|
||||
GGConnect,
|
||||
NUM_TYPE
|
||||
} mType;
|
||||
|
||||
/// Indicates the actual log entry.
|
||||
|
|
@ -897,34 +897,28 @@ template<typename P1> struct _EngineConsoleExecCallbackHelper;
|
|||
|
||||
namespace Con
|
||||
{
|
||||
/// @name Console Execution - executef
|
||||
/// {
|
||||
///
|
||||
/// Implements a script function thunk which automatically converts parameters to relevant console types.
|
||||
/// Can be used as follows:
|
||||
/// - Con::executef("functionName", ...);
|
||||
/// - Con::executef(mySimObject, "functionName", ...);
|
||||
///
|
||||
/// NOTE: if you get a rather cryptic template error coming through here, most likely you are trying to
|
||||
/// convert a parameter which EngineMarshallType does not have a specialization for.
|
||||
/// Another problem can occur if you do not include "console/simBase.h" and "console/engineAPI.h"
|
||||
/// since _EngineConsoleExecCallbackHelper and SimConsoleThreadExecCallback are required.
|
||||
///
|
||||
/// @see _EngineConsoleExecCallbackHelper
|
||||
///
|
||||
template<typename A> ConsoleValueRef executef(A a) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(); }
|
||||
template<typename A, typename B> ConsoleValueRef executef(A a, B b) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b); }
|
||||
template<typename A, typename B, typename C> ConsoleValueRef executef(A a, B b, C c) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c); }
|
||||
template<typename A, typename B, typename C, typename D> ConsoleValueRef executef(A a, B b, C c, D d) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d); }
|
||||
template<typename A, typename B, typename C, typename D, typename E> ConsoleValueRef executef(A a, B b, C c, D d, E e) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j, k); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j, k, l); }
|
||||
/// }
|
||||
/// @name Console Execution - executef
|
||||
/// {
|
||||
///
|
||||
/// Implements a script function thunk which automatically converts parameters to relevant console types.
|
||||
/// Can be used as follows:
|
||||
/// - Con::executef("functionName", ...);
|
||||
/// - Con::executef(mySimObject, "functionName", ...);
|
||||
///
|
||||
/// NOTE: if you get a rather cryptic template error coming through here, most likely you are trying to
|
||||
/// convert a parameter which EngineMarshallType does not have a specialization for.
|
||||
/// Another problem can occur if you do not include "console/simBase.h" and "console/engineAPI.h"
|
||||
/// since _EngineConsoleExecCallbackHelper and SimConsoleThreadExecCallback are required.
|
||||
///
|
||||
/// @see _EngineConsoleExecCallbackHelper
|
||||
///
|
||||
template<typename R, typename ...ArgTs>
|
||||
ConsoleValueRef executef(R r, ArgTs ...argTs)
|
||||
{
|
||||
_EngineConsoleExecCallbackHelper<R> callback( r );
|
||||
return callback.template call<ConsoleValueRef>(argTs...);
|
||||
}
|
||||
/// }
|
||||
};
|
||||
|
||||
extern void expandEscape(char *dest, const char *src);
|
||||
|
|
@ -1149,19 +1143,19 @@ class ConsoleStackFrameSaver
|
|||
{
|
||||
public:
|
||||
|
||||
bool mSaved;
|
||||
bool mSaved;
|
||||
|
||||
ConsoleStackFrameSaver() : mSaved(false)
|
||||
{
|
||||
}
|
||||
ConsoleStackFrameSaver() : mSaved(false)
|
||||
{
|
||||
}
|
||||
|
||||
~ConsoleStackFrameSaver()
|
||||
{
|
||||
restore();
|
||||
}
|
||||
~ConsoleStackFrameSaver()
|
||||
{
|
||||
restore();
|
||||
}
|
||||
|
||||
void save();
|
||||
void restore();
|
||||
void save();
|
||||
void restore();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "console/engineStructs.h"
|
||||
#endif
|
||||
|
||||
template<typename T> inline const T nullAsType(){ return nullptr; }
|
||||
|
||||
/// @file
|
||||
/// Legacy TS-based console type definitions.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -23,6 +23,8 @@
|
|||
#ifndef _ENGINEFUNCTIONS_H_
|
||||
#define _ENGINEFUNCTIONS_H_
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#ifndef _ENGINEEXPORTS_H_
|
||||
#include "console/engineExports.h"
|
||||
#endif
|
||||
|
|
@ -87,693 +89,38 @@ struct EngineFunctionDefaultArguments
|
|||
// Structure encapsulating default arguments to an engine API function.
|
||||
template< typename T >
|
||||
struct _EngineFunctionDefaultArguments {};
|
||||
template<>
|
||||
struct _EngineFunctionDefaultArguments< void() > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
};
|
||||
template< typename A >
|
||||
struct _EngineFunctionDefaultArguments< void( A ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( A a )
|
||||
: a( a )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
};
|
||||
template< typename A, typename B >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( B b )
|
||||
: b( b )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( A a, B b )
|
||||
: a( a ),
|
||||
b( b )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
};
|
||||
template< typename A, typename B, typename C >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( C c )
|
||||
: c( c )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( B b, C c )
|
||||
: b( b ),
|
||||
c( c )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( D d )
|
||||
: d( d )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( C c, D d )
|
||||
: c( c ),
|
||||
d( d )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( E e )
|
||||
: e( e )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( D d, E e )
|
||||
: d( d ),
|
||||
e( e )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( F f )
|
||||
: f( f )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( E e, F f )
|
||||
: e( e ),
|
||||
f( f )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( G g )
|
||||
: g( g )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( F f, G g )
|
||||
: f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
typename EngineTypeTraits< H >::DefaultArgumentValueStoreType h;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( H h )
|
||||
: h( h )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( G g, H h )
|
||||
: g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( F f, G g, H h )
|
||||
: f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g, H h )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g, H h )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g, H h )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g, H h )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g, H h )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h )
|
||||
{ mNumDefaultArgs = 8; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
typename EngineTypeTraits< H >::DefaultArgumentValueStoreType h;
|
||||
typename EngineTypeTraits< I >::DefaultArgumentValueStoreType i;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( I i )
|
||||
: i( i )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( H h, I i )
|
||||
: h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( G g, H h, I i )
|
||||
: g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( F f, G g, H h, I i )
|
||||
: f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g, H h, I i )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g, H h, I i )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g, H h, I i )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g, H h, I i )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 8; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g, H h, I i )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i )
|
||||
{ mNumDefaultArgs = 9; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
typename EngineTypeTraits< H >::DefaultArgumentValueStoreType h;
|
||||
typename EngineTypeTraits< I >::DefaultArgumentValueStoreType i;
|
||||
typename EngineTypeTraits< J >::DefaultArgumentValueStoreType j;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( J j )
|
||||
: j( j )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( I i, J j )
|
||||
: i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( H h, I i, J j )
|
||||
: h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( G g, H h, I i, J j )
|
||||
: g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( F f, G g, H h, I i, J j )
|
||||
: f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g, H h, I i, J j )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g, H h, I i, J j )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g, H h, I i, J j )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 8; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g, H h, I i, J j )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 9; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j )
|
||||
{ mNumDefaultArgs = 10; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J, K ) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
typename EngineTypeTraits< H >::DefaultArgumentValueStoreType h;
|
||||
typename EngineTypeTraits< I >::DefaultArgumentValueStoreType i;
|
||||
typename EngineTypeTraits< J >::DefaultArgumentValueStoreType j;
|
||||
typename EngineTypeTraits< K >::DefaultArgumentValueStoreType k;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( K k )
|
||||
: k( k )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( J j, K k )
|
||||
: j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( I i, J j, K k )
|
||||
: i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( H h, I i, J j, K k )
|
||||
: h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( G g, H h, I i, J j, K k )
|
||||
: g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( F f, G g, H h, I i, J j, K k )
|
||||
: f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g, H h, I i, J j, K k )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g, H h, I i, J j, K k )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 8; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g, H h, I i, J j, K k )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 9; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g, H h, I i, J j, K k )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 10; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k )
|
||||
{ mNumDefaultArgs = 11; }
|
||||
};
|
||||
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
struct _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J, K, L ) > : public EngineFunctionDefaultArguments
|
||||
template<typename ...ArgTs>
|
||||
struct _EngineFunctionDefaultArguments< void(ArgTs...) > : public EngineFunctionDefaultArguments
|
||||
{
|
||||
typename EngineTypeTraits< A >::DefaultArgumentValueStoreType a;
|
||||
typename EngineTypeTraits< B >::DefaultArgumentValueStoreType b;
|
||||
typename EngineTypeTraits< C >::DefaultArgumentValueStoreType c;
|
||||
typename EngineTypeTraits< D >::DefaultArgumentValueStoreType d;
|
||||
typename EngineTypeTraits< E >::DefaultArgumentValueStoreType e;
|
||||
typename EngineTypeTraits< F >::DefaultArgumentValueStoreType f;
|
||||
typename EngineTypeTraits< G >::DefaultArgumentValueStoreType g;
|
||||
typename EngineTypeTraits< H >::DefaultArgumentValueStoreType h;
|
||||
typename EngineTypeTraits< I >::DefaultArgumentValueStoreType i;
|
||||
typename EngineTypeTraits< J >::DefaultArgumentValueStoreType j;
|
||||
typename EngineTypeTraits< K >::DefaultArgumentValueStoreType k;
|
||||
typename EngineTypeTraits< L >::DefaultArgumentValueStoreType l;
|
||||
|
||||
_EngineFunctionDefaultArguments()
|
||||
{ mNumDefaultArgs = 0; }
|
||||
_EngineFunctionDefaultArguments( L l )
|
||||
: l( l )
|
||||
{ mNumDefaultArgs = 1; }
|
||||
_EngineFunctionDefaultArguments( K k, L l )
|
||||
: k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 2; }
|
||||
_EngineFunctionDefaultArguments( J j, K k, L l )
|
||||
: j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 3; }
|
||||
_EngineFunctionDefaultArguments( I i, J j, K k, L l )
|
||||
: i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 4; }
|
||||
_EngineFunctionDefaultArguments( H h, I i, J j, K k, L l )
|
||||
: h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 5; }
|
||||
_EngineFunctionDefaultArguments( G g, H h, I i, J j, K k, L l )
|
||||
: g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 6; }
|
||||
_EngineFunctionDefaultArguments( F f, G g, H h, I i, J j, K k, L l )
|
||||
: f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 7; }
|
||||
_EngineFunctionDefaultArguments( E e, F f, G g, H h, I i, J j, K k, L l )
|
||||
: e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 8; }
|
||||
_EngineFunctionDefaultArguments( D d, E e, F f, G g, H h, I i, J j, K k, L l )
|
||||
: d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 9; }
|
||||
_EngineFunctionDefaultArguments( C c, D d, E e, F f, G g, H h, I i, J j, K k, L l )
|
||||
: c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 10; }
|
||||
_EngineFunctionDefaultArguments( B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l )
|
||||
: b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 11; }
|
||||
_EngineFunctionDefaultArguments( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l )
|
||||
: a( a ),
|
||||
b( b ),
|
||||
c( c ),
|
||||
d( d ),
|
||||
e( e ),
|
||||
f( f ),
|
||||
g( g ),
|
||||
h( h ),
|
||||
i( i ),
|
||||
j( j ),
|
||||
k( k ),
|
||||
l( l )
|
||||
{ mNumDefaultArgs = 12; }
|
||||
template<typename T> using DefVST = typename EngineTypeTraits<T>::DefaultArgumentValueStoreType;
|
||||
std::tuple<DefVST<ArgTs> ...> mArgs;
|
||||
private:
|
||||
using SelfType = _EngineFunctionDefaultArguments< void(ArgTs...) >;
|
||||
|
||||
template<size_t ...> struct Seq {};
|
||||
template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {};
|
||||
|
||||
template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; };
|
||||
|
||||
template<typename ...TailTs, size_t ...I>
|
||||
static void copyHelper(std::tuple<DefVST<ArgTs> ...> &args, std::tuple<DefVST<TailTs> ...> &defaultArgs, Seq<I...>) {
|
||||
std::tie(std::get<I + (sizeof...(ArgTs) - sizeof...(TailTs))>(args)...) = defaultArgs;
|
||||
}
|
||||
|
||||
template<typename ...TailTs> using MaybeSelfEnabled = typename std::enable_if<sizeof...(TailTs) <= sizeof...(ArgTs), decltype(mArgs)>::type;
|
||||
|
||||
template<typename ...TailTs> static MaybeSelfEnabled<TailTs...> tailInit(TailTs ...tail) {
|
||||
std::tuple<DefVST<ArgTs>...> argsT;
|
||||
std::tuple<DefVST<TailTs>...> tailT = std::make_tuple(tail...);
|
||||
SelfType::copyHelper<TailTs...>(argsT, tailT, typename Gens<sizeof...(TailTs)>::type());
|
||||
return argsT;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename ...TailTs> _EngineFunctionDefaultArguments(TailTs ...tail)
|
||||
: EngineFunctionDefaultArguments({sizeof...(TailTs)}), mArgs(SelfType::tailInit(tail...))
|
||||
{}
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ DECLARE_PRIMITIVE_R(S32);
|
|||
DECLARE_PRIMITIVE_R(U32);
|
||||
DECLARE_PRIMITIVE_R(F32);
|
||||
DECLARE_PRIMITIVE_R(F64);
|
||||
DECLARE_PRIMITIVE_R(U64);
|
||||
DECLARE_PRIMITIVE_R(S64);
|
||||
DECLARE_PRIMITIVE_R(void*);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -648,395 +648,33 @@ template< typename T > const EngineFunctionTypeInfo< T > _EngineFunctionTypeTrai
|
|||
// Function Argument Type Infos.
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template< typename R >
|
||||
struct _EngineArgumentTypeTable< R() > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 0;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
#ifdef TORQUE_COMPILER_GCC
|
||||
static const EngineTypeInfo* const ARGS[ 0 ];
|
||||
|
||||
#ifdef TORQUE_COMILER_GCC
|
||||
#define ARGS_SIZE_SAFE(wanted) (wanted)
|
||||
#else
|
||||
static const EngineTypeInfo* const ARGS[ 1 ];
|
||||
#define ARGS_SIZE_SAFE(wanted) (((wanted) < 1) ? 1 : (wanted))
|
||||
#endif
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R > const EngineTypeInfo* const _EngineArgumentTypeTable< R() >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
#ifdef TORQUE_COMPILER_GCC
|
||||
template< typename R > const EngineTypeInfo* const _EngineArgumentTypeTable< R() >::ARGS[ 0 ] = {};
|
||||
#else
|
||||
template< typename R > const EngineTypeInfo* const _EngineArgumentTypeTable< R() >::ARGS[ 1 ] = {};
|
||||
#endif
|
||||
template< typename R >
|
||||
struct _EngineArgumentTypeTable< R( ... ) > : public _EngineArgumentTypeTable< R() >
|
||||
template< typename R, typename ...ArgTs >
|
||||
struct _EngineArgumentTypeTable< R( ArgTs ... ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A >
|
||||
struct _EngineArgumentTypeTable< R( A ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 1;
|
||||
static const U32 NUM_ARGUMENTS = sizeof...(ArgTs);
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 1 ];
|
||||
static const EngineTypeInfo* const ARGS[ ARGS_SIZE_SAFE(sizeof...(ArgTs)) ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A ) >::ARGS[ 1 ] =
|
||||
template< typename R, typename ...ArgTs >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( ArgTs ... ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename ...ArgTs >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( ArgTs ... ) >::ARGS[ ARGS_SIZE_SAFE(sizeof...(ArgTs)) ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >()
|
||||
TYPE< typename EngineTypeTraits< ArgTs >::Type >() ...
|
||||
};
|
||||
template< typename R, typename A >
|
||||
struct _EngineArgumentTypeTable< R( A, ... ) > : public _EngineArgumentTypeTable< R( A ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B >
|
||||
struct _EngineArgumentTypeTable< R( A, B ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 2;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 2 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B ) >::ARGS[ 2 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B >
|
||||
struct _EngineArgumentTypeTable< R( A, B, ... ) > : public _EngineArgumentTypeTable< R( A, B ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 3;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 3 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C ) >::ARGS[ 3 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, ... ) > : public _EngineArgumentTypeTable< R( A, B, C ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 4;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 4 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D ) >::ARGS[ 4 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 5;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 5 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E ) >::ARGS[ 5 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 6;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 6 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F ) >::ARGS[ 6 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 7;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 7 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G ) >::ARGS[ 7 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 8;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 8 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H ) >::ARGS[ 8 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< H >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 9;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 9 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I ) >::ARGS[ 9 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< H >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< I >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 10;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 10 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J ) >::ARGS[ 10 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< H >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< I >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< J >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 11;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 11 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K ) >::ARGS[ 11 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< H >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< I >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< J >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< K >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
};
|
||||
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, L ) > : public EngineArgumentTypeTable
|
||||
{
|
||||
static const U32 NUM_ARGUMENTS = 12;
|
||||
static const bool VARIADIC = false;
|
||||
static const EngineTypeInfo* const RETURN;
|
||||
static const EngineTypeInfo* const ARGS[ 12 ];
|
||||
|
||||
_EngineArgumentTypeTable()
|
||||
: EngineArgumentTypeTable( TYPE< typename EngineTypeTraits< R >::Type >(), NUM_ARGUMENTS, ARGS ) {}
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, L ) >::RETURN = TYPE< typename EngineTypeTraits< R >::Type >();
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
const EngineTypeInfo* const _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, L ) >::ARGS[ 12 ] =
|
||||
{
|
||||
TYPE< typename EngineTypeTraits< A >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< B >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< C >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< D >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< E >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< F >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< G >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< H >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< I >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< J >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< K >::Type >(),
|
||||
TYPE< typename EngineTypeTraits< L >::Type >()
|
||||
};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
struct _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, L, ... ) > : public _EngineArgumentTypeTable< R( A, B, C, D, E, F, G, H, I, J, K, L ) >
|
||||
template< typename R, typename ... ArgTs >
|
||||
struct _EngineArgumentTypeTable< R( ArgTs ..., ... ) > : public _EngineArgumentTypeTable< R( ArgTs ... ) >
|
||||
{
|
||||
static const bool VARIADIC = true;
|
||||
_EngineArgumentTypeTable() {}
|
||||
|
|
|
|||
|
|
@ -284,58 +284,10 @@ template< typename T > const EngineTypeInfo* const _EngineFunctionTypeTraits< T
|
|||
// are not guaranteed to be any meaningful value or base types to the engine type system.
|
||||
#define T( x ) typename EngineTypeTraits< x >::ValueType
|
||||
|
||||
template< typename R >
|
||||
struct _EngineTypeTraits< R() > : public _EngineFunctionTypeTraits< T( R )() > {};
|
||||
template< typename R >
|
||||
struct _EngineTypeTraits< R( ... ) > : public _EngineFunctionTypeTraits< T( R )( ... ) > {};
|
||||
template< typename R, typename A >
|
||||
struct _EngineTypeTraits< R( A ) > : public _EngineFunctionTypeTraits< T( R )( T( A ) ) > {};
|
||||
template< typename R, typename A >
|
||||
struct _EngineTypeTraits< R( A, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), ... ) > {};
|
||||
template< typename R, typename A, typename B >
|
||||
struct _EngineTypeTraits< R( A, B ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ) ) > {};
|
||||
template< typename R, typename A, typename B >
|
||||
struct _EngineTypeTraits< R( A, B, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
struct _EngineTypeTraits< R( A, B, C ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C >
|
||||
struct _EngineTypeTraits< R( A, B, C, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
struct _EngineTypeTraits< R( A, B, C, D ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J, K ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ), T( K ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J, K, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ), T( K ), ... ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J, K, L ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ), T( K ), T( L ) ) > {};
|
||||
template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L >
|
||||
struct _EngineTypeTraits< R( A, B, C, D, E, F, G, H, I, J, K, L, ... ) > : public _EngineFunctionTypeTraits< T( R )( T( A ), T( B ), T( C ), T( D ), T( E ), T( F ), T( G ), T( H ), T( I ), T( J ), T( K ), T( L ), ... ) > {};
|
||||
template<typename R, typename ...ArgTs>
|
||||
struct _EngineTypeTraits< R(ArgTs ...) > : public _EngineFunctionTypeTraits<T(R)(T(ArgTs)...)> {};
|
||||
template<typename R, typename ...ArgTs>
|
||||
struct _EngineTypeTraits< R(ArgTs ..., ...) > : public _EngineFunctionTypeTraits<T(R)(T(ArgTs)..., ...)> {};
|
||||
|
||||
#undef T
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ ConsoleDocClass( FieldBrushObject,
|
|||
FieldBrushObject::FieldBrushObject()
|
||||
{
|
||||
// Reset Description.
|
||||
mDescription = StringTable->insert("");
|
||||
mSortName = StringTable->insert("");
|
||||
mDescription = StringTable->EmptyString();
|
||||
mSortName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -109,15 +109,15 @@ void FieldBrushObject::destroyFields()
|
|||
static char replacebuf[1024];
|
||||
static char* suppressSpaces(const char* in_pname)
|
||||
{
|
||||
U32 i = 0;
|
||||
char chr;
|
||||
do
|
||||
{
|
||||
chr = in_pname[i];
|
||||
replacebuf[i++] = (chr != 32) ? chr : '_';
|
||||
} while(chr);
|
||||
U32 i = 0;
|
||||
char chr;
|
||||
do
|
||||
{
|
||||
chr = in_pname[i];
|
||||
replacebuf[i++] = (chr != 32) ? chr : '_';
|
||||
} while(chr);
|
||||
|
||||
return replacebuf;
|
||||
return replacebuf;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -125,7 +125,7 @@ static char* suppressSpaces(const char* in_pname)
|
|||
//-----------------------------------------------------------------------------
|
||||
DefineConsoleMethod(FieldBrushObject, queryGroups, const char*, (const char* simObjName), , "(simObject) Query available static-field groups for selected object./\n"
|
||||
"@param simObject Object to query static-field groups on.\n"
|
||||
"@return Space-seperated static-field group list.")
|
||||
"@return Space-seperated static-field group list.")
|
||||
{
|
||||
// Fetch selected object.
|
||||
SimObject* pSimObject = dynamic_cast<SimObject*>( Sim::findObject( simObjName ) );
|
||||
|
|
@ -194,7 +194,7 @@ DefineConsoleMethod(FieldBrushObject, queryGroups, const char*, (const char* sim
|
|||
DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* simObjName, const char* groupList), (""), "(simObject, [groupList]) Query available static-fields for selected object./\n"
|
||||
"@param simObject Object to query static-fields on.\n"
|
||||
"@param groupList groups to filter static-fields against.\n"
|
||||
"@return Space-seperated static-field list.")
|
||||
"@return Space-seperated static-field list.")
|
||||
{
|
||||
// Fetch selected object.
|
||||
SimObject* pSimObject = dynamic_cast<SimObject*>( Sim::findObject( simObjName ) );
|
||||
|
|
@ -369,7 +369,7 @@ DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* sim
|
|||
DefineConsoleMethod(FieldBrushObject, copyFields, void, (const char* simObjName, const char* pFieldList), (""), "(simObject, [fieldList]) Copy selected static-fields for selected object./\n"
|
||||
"@param simObject Object to copy static-fields from.\n"
|
||||
"@param fieldList fields to filter static-fields against.\n"
|
||||
"@return No return value.")
|
||||
"@return No return value.")
|
||||
{
|
||||
// Fetch selected object.
|
||||
SimObject* pSimObject = dynamic_cast<SimObject*>( Sim::findObject( simObjName ) );
|
||||
|
|
@ -502,7 +502,7 @@ void FieldBrushObject::copyFields( SimObject* pSimObject, const char* fieldList
|
|||
//-----------------------------------------------------------------------------
|
||||
DefineConsoleMethod(FieldBrushObject, pasteFields, void, (const char* simObjName), , "(simObject) Paste copied static-fields to selected object./\n"
|
||||
"@param simObject Object to paste static-fields to.\n"
|
||||
"@return No return value.")
|
||||
"@return No return value.")
|
||||
{
|
||||
// Fetch selected object.
|
||||
SimObject* pSimObject = dynamic_cast<SimObject*>( Sim::findObject( simObjName ) );
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ DefineEngineFunction( findNextFile, String, ( const char* pattern ), ( "" ),
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction( getFileCount, S32, ( const char* pattern, bool recurse ), ( "", true ),
|
||||
"@brief Returns the number of files in the directory tree that match the given patterns\n\n"
|
||||
"@brief Returns the number of files in the directory tree that match the given patterns\n\n"
|
||||
|
||||
"This function differs from getFileCountMultiExpr() in that it supports a single search "
|
||||
"pattern being passed in.\n\n"
|
||||
|
|
@ -246,7 +246,7 @@ DefineEngineFunction( getFileCount, S32, ( const char* pattern, bool recurse ),
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction(findFirstFileMultiExpr, String, ( const char* pattern, bool recurse ), ( "", true),
|
||||
"@brief Returns the first file in the directory system matching the given patterns.\n\n"
|
||||
"@brief Returns the first file in the directory system matching the given patterns.\n\n"
|
||||
|
||||
"Use the corresponding findNextFileMultiExpr() to step through "
|
||||
"the results. If you're only interested in the number of files returned by the "
|
||||
|
|
@ -259,10 +259,10 @@ DefineEngineFunction(findFirstFileMultiExpr, String, ( const char* pattern, bool
|
|||
"call to findFirstFile() and findFirstFileMultiExpr() initiates a new search and renders "
|
||||
"a previous search invalid.\n\n"
|
||||
|
||||
"@param pattern The path and file name pattern to match against, such as *.cs. Separate "
|
||||
"@param pattern The path and file name pattern to match against, such as *.cs. Separate "
|
||||
"multiple patterns with TABs. For example: \"*.cs\" TAB \"*.dso\"\n"
|
||||
"@param recurse If true, the search will exhaustively recurse into subdirectories "
|
||||
"of the given path and match the given filename patterns.\n"
|
||||
"@param recurse If true, the search will exhaustively recurse into subdirectories "
|
||||
"of the given path and match the given filename patterns.\n"
|
||||
"@return String of the first matching file path, or an empty string if no matching "
|
||||
"files were found.\n\n"
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ DefineEngineFunction(findFirstFileMultiExpr, String, ( const char* pattern, bool
|
|||
"@see findNextFileMultiExpr()"
|
||||
"@see getFileCountMultiExpr()"
|
||||
"@see findFirstFile()"
|
||||
"@ingroup FileSearches")
|
||||
"@ingroup FileSearches")
|
||||
{
|
||||
S32 numResults = buildFileList(pattern, recurse, true);
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ DefineEngineFunction(findFirstFileMultiExpr, String, ( const char* pattern, bool
|
|||
DefineEngineFunction(findNextFileMultiExpr, String, ( const char* pattern ), (""),
|
||||
"@brief Returns the next file matching a search begun in findFirstFileMultiExpr().\n\n"
|
||||
|
||||
"@param pattern The path and file name pattern to match against. This is optional "
|
||||
"@param pattern The path and file name pattern to match against. This is optional "
|
||||
"and may be left out as it is not used by the code. It is here for legacy reasons.\n"
|
||||
"@return String of the next matching file path, or an empty string if no matching "
|
||||
"files were found.\n\n"
|
||||
|
|
@ -319,7 +319,7 @@ DefineEngineFunction(findNextFileMultiExpr, String, ( const char* pattern ), (""
|
|||
"@endtsexample\n\n"
|
||||
|
||||
"@see findFirstFileMultiExpr()"
|
||||
"@ingroup FileSearches")
|
||||
"@ingroup FileSearches")
|
||||
{
|
||||
if ( sgFindFilesPos + 1 > sgFindFilesResults.size() )
|
||||
return String();
|
||||
|
|
@ -328,16 +328,16 @@ DefineEngineFunction(findNextFileMultiExpr, String, ( const char* pattern ), (""
|
|||
}
|
||||
|
||||
DefineEngineFunction(getFileCountMultiExpr, S32, ( const char* pattern, bool recurse ), ( "", true),
|
||||
"@brief Returns the number of files in the directory tree that match the given patterns\n\n"
|
||||
"@brief Returns the number of files in the directory tree that match the given patterns\n\n"
|
||||
|
||||
"If you're interested in a list of files that match the given patterns and not just "
|
||||
"the number of files, use findFirstFileMultiExpr() and findNextFileMultiExpr().\n\n"
|
||||
|
||||
"@param pattern The path and file name pattern to match against, such as *.cs. Separate "
|
||||
"@param pattern The path and file name pattern to match against, such as *.cs. Separate "
|
||||
"multiple patterns with TABs. For example: \"*.cs\" TAB \"*.dso\"\n"
|
||||
"@param recurse If true, the search will exhaustively recurse into subdirectories "
|
||||
"of the given path and match the given filename pattern.\n"
|
||||
"@return Number of files located using the patterns\n\n"
|
||||
"@param recurse If true, the search will exhaustively recurse into subdirectories "
|
||||
"of the given path and match the given filename pattern.\n"
|
||||
"@return Number of files located using the patterns\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// Count all DTS or Collada models\n"
|
||||
|
|
@ -347,7 +347,7 @@ DefineEngineFunction(getFileCountMultiExpr, S32, ( const char* pattern, bool rec
|
|||
|
||||
"@see findFirstFileMultiExpr()"
|
||||
"@see findNextFileMultiExpr()"
|
||||
"@ingroup FileSearches")
|
||||
"@ingroup FileSearches")
|
||||
{
|
||||
S32 numResults = buildFileList(pattern, recurse, true);
|
||||
|
||||
|
|
@ -399,14 +399,14 @@ DefineEngineFunction(isFile, bool, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction( IsDirectory, bool, ( const char* directory ),,
|
||||
"@brief Determines if a specified directory exists or not\n\n"
|
||||
"@brief Determines if a specified directory exists or not\n\n"
|
||||
|
||||
"@param directory String containing path in the form of \"foo/bar\"\n"
|
||||
"@param directory String containing path in the form of \"foo/bar\"\n"
|
||||
"@return Returns true if the directory was found.\n"
|
||||
|
||||
"@note Do not include a trailing slash '/'.\n"
|
||||
"@note Do not include a trailing slash '/'.\n"
|
||||
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
String dir(Torque::Path::CleanSeparators(directory));
|
||||
Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), dir.c_str());
|
||||
|
|
@ -416,12 +416,12 @@ DefineEngineFunction( IsDirectory, bool, ( const char* directory ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(isWriteableFileName, bool, ( const char* fileName ),,
|
||||
"@brief Determines if a file name can be written to using File I/O\n\n"
|
||||
"@brief Determines if a file name can be written to using File I/O\n\n"
|
||||
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return Returns true if the file can be written to.\n"
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return Returns true if the file can be written to.\n"
|
||||
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
String filename(Torque::Path::CleanSeparators(fileName));
|
||||
Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), filename.c_str());
|
||||
|
|
@ -434,32 +434,32 @@ DefineEngineFunction(isWriteableFileName, bool, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(startFileChangeNotifications, void, (),,
|
||||
"@brief Start watching resources for file changes\n\n"
|
||||
"@brief Start watching resources for file changes\n\n"
|
||||
"Typically this is called during initializeCore().\n\n"
|
||||
"@see stopFileChangeNotifications()\n"
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
Torque::FS::StartFileChangeNotifications();
|
||||
}
|
||||
|
||||
DefineEngineFunction(stopFileChangeNotifications, void, (),,
|
||||
"@brief Stop watching resources for file changes\n\n"
|
||||
"@brief Stop watching resources for file changes\n\n"
|
||||
"Typically this is called during shutdownCore().\n\n"
|
||||
"@see startFileChangeNotifications()\n"
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
Torque::FS::StopFileChangeNotifications();
|
||||
}
|
||||
|
||||
|
||||
DefineEngineFunction(getDirectoryList, String, ( const char* path, S32 depth ), ( "", 0 ),
|
||||
"@brief Gathers a list of directories starting at the given path.\n\n"
|
||||
"@brief Gathers a list of directories starting at the given path.\n\n"
|
||||
|
||||
"@param path String containing the path of the directory\n"
|
||||
"@param depth Depth of search, as in how many subdirectories to parse through\n"
|
||||
"@return Tab delimited string containing list of directories found during search, \"\" if no files were found\n"
|
||||
"@param path String containing the path of the directory\n"
|
||||
"@param depth Depth of search, as in how many subdirectories to parse through\n"
|
||||
"@return Tab delimited string containing list of directories found during search, \"\" if no files were found\n"
|
||||
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
// Grab the full path.
|
||||
char fullpath[1024];
|
||||
|
|
@ -508,23 +508,23 @@ DefineEngineFunction(getDirectoryList, String, ( const char* path, S32 depth ),
|
|||
}
|
||||
|
||||
DefineEngineFunction(fileSize, S32, ( const char* fileName ),,
|
||||
"@brief Determines the size of a file on disk\n\n"
|
||||
"@brief Determines the size of a file on disk\n\n"
|
||||
|
||||
"@param fileName Name and path of the file to check\n"
|
||||
"@return Returns filesize in bytes, or -1 if no file\n"
|
||||
"@param fileName Name and path of the file to check\n"
|
||||
"@return Returns filesize in bytes, or -1 if no file\n"
|
||||
|
||||
"@ingroup FileSystem")
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), fileName);
|
||||
return Platform::getFileSize( sgScriptFilenameBuffer );
|
||||
}
|
||||
|
||||
DefineEngineFunction( fileModifiedTime, String, ( const char* fileName ),,
|
||||
"@brief Returns a platform specific formatted string with the last modified time for the file.\n\n"
|
||||
"@brief Returns a platform specific formatted string with the last modified time for the file.\n\n"
|
||||
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return Formatted string (OS specific) containing modified time, \"9/3/2010 12:33:47 PM\" for example\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return Formatted string (OS specific) containing modified time, \"9/3/2010 12:33:47 PM\" for example\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
Con::expandScriptFilename(sgScriptFilenameBuffer, sizeof(sgScriptFilenameBuffer), fileName);
|
||||
|
||||
|
|
@ -566,12 +566,12 @@ DefineEngineFunction( fileCreatedTime, String, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(fileDelete, bool, ( const char* path ),,
|
||||
"@brief Delete a file from the hard drive\n\n"
|
||||
"@brief Delete a file from the hard drive\n\n"
|
||||
|
||||
"@param path Name and path of the file to delete\n"
|
||||
"@note THERE IS NO RECOVERY FROM THIS. Deleted file is gone for good.\n"
|
||||
"@return True if file was successfully deleted\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param path Name and path of the file to delete\n"
|
||||
"@note THERE IS NO RECOVERY FROM THIS. Deleted file is gone for good.\n"
|
||||
"@return True if file was successfully deleted\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
static char fileName[1024];
|
||||
static char sandboxFileName[1024];
|
||||
|
|
@ -586,11 +586,11 @@ DefineEngineFunction(fileDelete, bool, ( const char* path ),,
|
|||
//----------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction(fileExt, String, ( const char* fileName ),,
|
||||
"@brief Get the extension of a file\n\n"
|
||||
"@brief Get the extension of a file\n\n"
|
||||
|
||||
"@param fileName Name and path of file\n"
|
||||
"@return String containing the extension, such as \".exe\" or \".cs\"\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param fileName Name and path of file\n"
|
||||
"@return String containing the extension, such as \".exe\" or \".cs\"\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
const char *ret = dStrrchr(fileName, '.');
|
||||
if(ret)
|
||||
|
|
@ -626,11 +626,11 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(fileName, String, ( const char* fileName ),,
|
||||
"@brief Get only the file name of a path and file name string (removes path)\n\n"
|
||||
"@brief Get only the file name of a path and file name string (removes path)\n\n"
|
||||
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return String containing the file name, minus the path\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return String containing the file name, minus the path\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
S32 pathLen = dStrlen( fileName );
|
||||
FrameTemp<char> szPathCopy( pathLen + 1);
|
||||
|
|
@ -649,11 +649,11 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(filePath, String, ( const char* fileName ),,
|
||||
"@brief Get the path of a file (removes name and extension)\n\n"
|
||||
"@brief Get the path of a file (removes name and extension)\n\n"
|
||||
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return String containing the path, minus name and extension\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param fileName Name and path of file to check\n"
|
||||
"@return String containing the path, minus name and extension\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
S32 pathLen = dStrlen( fileName );
|
||||
FrameTemp<char> szPathCopy( pathLen + 1);
|
||||
|
|
@ -672,10 +672,10 @@ DefineEngineFunction(filePath, String, ( const char* fileName ),,
|
|||
}
|
||||
|
||||
DefineEngineFunction(getWorkingDirectory, String, (),,
|
||||
"@brief Reports the current directory\n\n"
|
||||
"@brief Reports the current directory\n\n"
|
||||
|
||||
"@return String containing full file path of working directory\n"
|
||||
"@ingroup FileSystem")
|
||||
"@return String containing full file path of working directory\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
return Platform::getCurrentDirectory();
|
||||
}
|
||||
|
|
@ -687,13 +687,13 @@ DefineEngineFunction(getWorkingDirectory, String, (),,
|
|||
// are not currently built with TORQUE_TOOLS defined.
|
||||
|
||||
DefineEngineFunction(makeFullPath, String, ( const char* path, const char* cwd ), ( "", ""),
|
||||
"@brief Converts a relative file path to a full path\n\n"
|
||||
"@brief Converts a relative file path to a full path\n\n"
|
||||
|
||||
"For example, \"./console.log\" becomes \"C:/Torque/t3d/examples/FPS Example/game/console.log\"\n"
|
||||
"@param path Name of file or path to check\n"
|
||||
"For example, \"./console.log\" becomes \"C:/Torque/t3d/examples/FPS Example/game/console.log\"\n"
|
||||
"@param path Name of file or path to check\n"
|
||||
"@param cwd Optional current working directory from which to build the full path.\n"
|
||||
"@return String containing non-relative directory of path\n"
|
||||
"@ingroup FileSystem")
|
||||
"@return String containing non-relative directory of path\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
static const U32 bufSize = 512;
|
||||
char *buf = Con::getReturnBuffer(bufSize);
|
||||
|
|
@ -702,25 +702,25 @@ DefineEngineFunction(makeFullPath, String, ( const char* path, const char* cwd )
|
|||
}
|
||||
|
||||
DefineEngineFunction(makeRelativePath, String, ( const char* path, const char* to ), ( "", ""),
|
||||
"@brief Turns a full or local path to a relative one\n\n"
|
||||
"@brief Turns a full or local path to a relative one\n\n"
|
||||
|
||||
"For example, \"./game/art\" becomes \"game/art\"\n"
|
||||
"@param path Full path (may include a file) to convert\n"
|
||||
"@param to Optional base path used for the conversion. If not supplied the current "
|
||||
"working directory is used.\n"
|
||||
"@returns String containing relative path\n"
|
||||
"@ingroup FileSystem")
|
||||
"@returns String containing relative path\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
return Platform::makeRelativePathName( path, dStrlen(to) > 1 ? to : NULL );
|
||||
}
|
||||
|
||||
DefineEngineFunction(pathConcat, String, ( const char* path, const char* file), ( "", ""),
|
||||
"@brief Combines two separate strings containing a file path and file name together into a single string\n\n"
|
||||
"@brief Combines two separate strings containing a file path and file name together into a single string\n\n"
|
||||
|
||||
"@param path String containing file path\n"
|
||||
"@param file String containing file name\n"
|
||||
"@return String containing concatenated file name and path\n"
|
||||
"@ingroup FileSystem")
|
||||
"@param path String containing file path\n"
|
||||
"@param file String containing file name\n"
|
||||
"@return String containing concatenated file name and path\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
static const U32 bufSize = 1024;
|
||||
char *buf = Con::getReturnBuffer(bufSize);
|
||||
|
|
@ -731,10 +731,10 @@ DefineEngineFunction(pathConcat, String, ( const char* path, const char* file),
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction(getExecutableName, String, (),,
|
||||
"@brief Gets the name of the game's executable\n\n"
|
||||
"@brief Gets the name of the game's executable\n\n"
|
||||
|
||||
"@return String containing this game's executable name\n"
|
||||
"@ingroup FileSystem")
|
||||
"@return String containing this game's executable name\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
return Platform::getExecutableName();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,22 +34,22 @@
|
|||
IMPLEMENT_CONOBJECT(PersistenceManager);
|
||||
|
||||
ConsoleDocClass( PersistenceManager,
|
||||
"@brief this class manages updating SimObjects in the file they were "
|
||||
"created in non-destructively (mostly aimed at datablocks and materials).\n\n"
|
||||
"@brief this class manages updating SimObjects in the file they were "
|
||||
"created in non-destructively (mostly aimed at datablocks and materials).\n\n"
|
||||
|
||||
"Basic scripting interface:\n\n"
|
||||
" - Creation: new PersistenceManager(FooManager);\n"
|
||||
" - Flag objects as dirty: FooManager.setDirty(<object name or id>);\n"
|
||||
" - Remove objects from dirty list: FooManager.removeDirty(<object name or id>);\n"
|
||||
" - List all currently dirty objects: FooManager.listDirty();\n"
|
||||
" - Check to see if an object is dirty: FooManager.isDirty(<object name or id>);\n"
|
||||
" - Save dirty objects to their files: FooManager.saveDirty();\n\n"
|
||||
"@note Dirty objects don't update their files until saveDirty() is "
|
||||
"called so you can change their properties after you flag them as dirty\n\n"
|
||||
"@note Currently only used by editors, not intended for actual game development\n\n"
|
||||
"@ingroup Console\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal");
|
||||
"Basic scripting interface:\n\n"
|
||||
" - Creation: new PersistenceManager(FooManager);\n"
|
||||
" - Flag objects as dirty: FooManager.setDirty(<object name or id>);\n"
|
||||
" - Remove objects from dirty list: FooManager.removeDirty(<object name or id>);\n"
|
||||
" - List all currently dirty objects: FooManager.listDirty();\n"
|
||||
" - Check to see if an object is dirty: FooManager.isDirty(<object name or id>);\n"
|
||||
" - Save dirty objects to their files: FooManager.saveDirty();\n\n"
|
||||
"@note Dirty objects don't update their files until saveDirty() is "
|
||||
"called so you can change their properties after you flag them as dirty\n\n"
|
||||
"@note Currently only used by editors, not intended for actual game development\n\n"
|
||||
"@ingroup Console\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal");
|
||||
|
||||
PersistenceManager::PersistenceManager()
|
||||
{
|
||||
|
|
@ -328,7 +328,7 @@ void PersistenceManager::parseObject()
|
|||
|
||||
if (mParser.tokenICmp(")"))
|
||||
{
|
||||
mCurrentObject->name = StringTable->insert("");
|
||||
mCurrentObject->name = StringTable->EmptyString();
|
||||
|
||||
mCurrentObject->nameLine = mParser.getCurrentLine();
|
||||
mCurrentObject->namePosition = mParser.getTokenLineOffset();
|
||||
|
|
@ -890,7 +890,7 @@ PersistenceManager::ParsedObject* PersistenceManager::findParsedObject(SimObject
|
|||
{
|
||||
const ParsedProperty &prop = testObj->properties[j];
|
||||
|
||||
if ( dStrcmp( prop.name, "internalName" ) == 0 &&
|
||||
if ( dStrcmp( prop.name, "internalName" ) == 0 &&
|
||||
dStrcmp( prop.value, object->getInternalName() ) == 0 )
|
||||
return testObj;
|
||||
else if ( dStrcmp(prop.name, "internalName") == 0)
|
||||
|
|
@ -2037,24 +2037,24 @@ bool PersistenceManager::saveDirtyObject(SimObject* object)
|
|||
const char *name = object->getName();
|
||||
if (name)
|
||||
{
|
||||
Con::errorf("PersistenceManager::saveDirtyObject(): Unable to open %s to save %s %s (%d)",
|
||||
dirtyObject.fileName, object->getClassName(), name, object->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf("PersistenceManager::saveDirtyObject(): Unable to open %s to save %s (%d)",
|
||||
dirtyObject.fileName, object->getClassName(), object->getId());
|
||||
}
|
||||
Con::errorf("PersistenceManager::saveDirtyObject(): Unable to open %s to save %s %s (%d)",
|
||||
dirtyObject.fileName, object->getClassName(), name, object->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf("PersistenceManager::saveDirtyObject(): Unable to open %s to save %s (%d)",
|
||||
dirtyObject.fileName, object->getClassName(), object->getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the file exists then lets update and save
|
||||
if(mCurrentFile)
|
||||
{
|
||||
updateObject(object);
|
||||
if(mCurrentFile)
|
||||
{
|
||||
updateObject(object);
|
||||
saveDirtyFile();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -2230,7 +2230,7 @@ DefineConsoleMethod( PersistenceManager, removeDirty, void, ( const char * objNa
|
|||
"Remove a SimObject from the dirty list.")
|
||||
{
|
||||
SimObject *dirtyObject = NULL;
|
||||
if (dStrcmp( objName,"")!=0)
|
||||
if (dStrcmp( objName,"")!=0)
|
||||
{
|
||||
if (!Sim::findObject(objName, dirtyObject))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -343,10 +343,10 @@ bool collapseScriptFilename(char *filename, U32 size, const char *src)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleFunction(expandFilename, const char*, 2, 2, "(string filename)"
|
||||
"@brief Grabs the full path of a specified file\n\n"
|
||||
"@param filename Name of the local file to locate\n"
|
||||
"@return String containing the full filepath on disk\n"
|
||||
"@ingroup FileSystem")
|
||||
"@brief Grabs the full path of a specified file\n\n"
|
||||
"@param filename Name of the local file to locate\n"
|
||||
"@return String containing the full filepath on disk\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
TORQUE_UNUSED(argc);
|
||||
static const U32 bufSize = 1024;
|
||||
|
|
@ -356,9 +356,9 @@ ConsoleFunction(expandFilename, const char*, 2, 2, "(string filename)"
|
|||
}
|
||||
|
||||
ConsoleFunction(expandOldFilename, const char*, 2, 2, "(string filename)"
|
||||
"@brief Retrofits a filepath that uses old Torque style\n\n"
|
||||
"@return String containing filepath with new formatting\n"
|
||||
"@ingroup FileSystem")
|
||||
"@brief Retrofits a filepath that uses old Torque style\n\n"
|
||||
"@return String containing filepath with new formatting\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
TORQUE_UNUSED(argc);
|
||||
static const U32 bufSize = 1024;
|
||||
|
|
@ -372,7 +372,7 @@ ConsoleFunction(expandOldFilename, const char*, 2, 2, "(string filename)"
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleToolFunction(collapseFilename, const char*, 2, 2, "(string filename)"
|
||||
"@internal Editor use only")
|
||||
"@internal Editor use only")
|
||||
{
|
||||
TORQUE_UNUSED(argc);
|
||||
static const U32 bufSize = 1024;
|
||||
|
|
@ -382,7 +382,7 @@ ConsoleToolFunction(collapseFilename, const char*, 2, 2, "(string filename)"
|
|||
}
|
||||
|
||||
ConsoleToolFunction(setScriptPathExpando, void, 3, 4, "(string expando, string path[, bool toolsOnly])"
|
||||
"@internal Editor use only")
|
||||
"@internal Editor use only")
|
||||
{
|
||||
if(argc == 4)
|
||||
Con::setScriptPathExpando(argv[1], argv[2], dAtob(argv[3]));
|
||||
|
|
@ -391,13 +391,13 @@ ConsoleToolFunction(setScriptPathExpando, void, 3, 4, "(string expando, string p
|
|||
}
|
||||
|
||||
ConsoleToolFunction(removeScriptPathExpando, void, 2, 2, "(string expando)"
|
||||
"@internal Editor use only")
|
||||
"@internal Editor use only")
|
||||
{
|
||||
Con::removeScriptPathExpando(argv[1]);
|
||||
}
|
||||
|
||||
ConsoleToolFunction(isScriptPathExpando, bool, 2, 2, "(string expando)"
|
||||
"@internal Editor use only")
|
||||
"@internal Editor use only")
|
||||
{
|
||||
return Con::isScriptPathExpando(argv[1]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ ConsoleDocClass( ScriptObject,
|
|||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptObject, onAdd, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this ScriptObject is added to the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"Called when this ScriptObject is added to the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptObject, onRemove, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this ScriptObject is removed from the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"Called when this ScriptObject is removed from the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
|
||||
ScriptObject::ScriptObject()
|
||||
|
|
@ -105,18 +105,18 @@ ConsoleDocClass( ScriptTickObject,
|
|||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptTickObject, onInterpolateTick, void, ( F32 delta ), ( delta ),
|
||||
"This is called every frame, but only if the object is set to process ticks.\n"
|
||||
"@param delta The time delta for this frame.\n"
|
||||
"This is called every frame, but only if the object is set to process ticks.\n"
|
||||
"@param delta The time delta for this frame.\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptTickObject, onProcessTick, void, (), (),
|
||||
"Called once every 32ms if this object is set to process ticks.\n"
|
||||
"Called once every 32ms if this object is set to process ticks.\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptTickObject, onAdvanceTime, void, ( F32 timeDelta ), ( timeDelta ),
|
||||
"This is called every frame regardless if the object is set to process ticks, but only "
|
||||
"This is called every frame regardless if the object is set to process ticks, but only "
|
||||
"if the callOnAdvanceTime property is set to true.\n"
|
||||
"@param timeDelta The time delta for this frame.\n"
|
||||
"@param timeDelta The time delta for this frame.\n"
|
||||
"@see callOnAdvanceTime\n"
|
||||
);
|
||||
|
||||
|
|
@ -188,37 +188,37 @@ DefineEngineMethod( ScriptTickObject, isProcessingTicks, bool, ( ),,
|
|||
IMPLEMENT_CONOBJECT(ScriptGroup);
|
||||
|
||||
ConsoleDocClass( ScriptGroup,
|
||||
"@brief Essentially a SimGroup, but with onAdd and onRemove script callbacks.\n\n"
|
||||
"@brief Essentially a SimGroup, but with onAdd and onRemove script callbacks.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// First container, SimGroup containing a ScriptGroup\n"
|
||||
"new SimGroup(Scenes)\n"
|
||||
"{\n"
|
||||
" // Subcontainer, ScriptGroup containing variables\n"
|
||||
" // related to a cut scene and a starting WayPoint\n"
|
||||
" new ScriptGroup(WelcomeScene)\n"
|
||||
" {\n"
|
||||
" class = \"Scene\";\n"
|
||||
" pathName = \"Pathx\";\n"
|
||||
" description = \"A small orc village set in the Hardesty mountains. This town and its surroundings will be used to illustrate some the Torque Game Engine\'s features.\";\n"
|
||||
" pathTime = \"0\";\n"
|
||||
" title = \"Welcome to Orc Town\";\n\n"
|
||||
" new WayPoint(start)\n"
|
||||
" {\n"
|
||||
" position = \"163.873 -103.82 208.354\";\n"
|
||||
" rotation = \"0.136165 -0.0544916 0.989186 44.0527\";\n"
|
||||
" scale = \"1 1 1\";\n"
|
||||
" dataBlock = \"WayPointMarker\";\n"
|
||||
" team = \"0\";\n"
|
||||
" };\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
"@tsexample\n"
|
||||
"// First container, SimGroup containing a ScriptGroup\n"
|
||||
"new SimGroup(Scenes)\n"
|
||||
"{\n"
|
||||
" // Subcontainer, ScriptGroup containing variables\n"
|
||||
" // related to a cut scene and a starting WayPoint\n"
|
||||
" new ScriptGroup(WelcomeScene)\n"
|
||||
" {\n"
|
||||
" class = \"Scene\";\n"
|
||||
" pathName = \"Pathx\";\n"
|
||||
" description = \"A small orc village set in the Hardesty mountains. This town and its surroundings will be used to illustrate some the Torque Game Engine\'s features.\";\n"
|
||||
" pathTime = \"0\";\n"
|
||||
" title = \"Welcome to Orc Town\";\n\n"
|
||||
" new WayPoint(start)\n"
|
||||
" {\n"
|
||||
" position = \"163.873 -103.82 208.354\";\n"
|
||||
" rotation = \"0.136165 -0.0544916 0.989186 44.0527\";\n"
|
||||
" scale = \"1 1 1\";\n"
|
||||
" dataBlock = \"WayPointMarker\";\n"
|
||||
" team = \"0\";\n"
|
||||
" };\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see SimGroup\n"
|
||||
"@see SimGroup\n"
|
||||
|
||||
"@ingroup Console\n"
|
||||
"@ingroup Scripting"
|
||||
"@ingroup Console\n"
|
||||
"@ingroup Scripting"
|
||||
);
|
||||
|
||||
ScriptGroup::ScriptGroup()
|
||||
|
|
@ -226,13 +226,13 @@ ScriptGroup::ScriptGroup()
|
|||
}
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptGroup, onAdd, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this ScriptGroup is added to the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"Called when this ScriptGroup is added to the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( ScriptGroup, onRemove, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this ScriptObject is removed from the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"Called when this ScriptObject is removed from the system.\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
|
||||
bool ScriptGroup::onAdd()
|
||||
|
|
@ -248,7 +248,7 @@ bool ScriptGroup::onAdd()
|
|||
void ScriptGroup::onRemove()
|
||||
{
|
||||
// Call onRemove in script!
|
||||
onRemove_callback(getId());
|
||||
onRemove_callback(getId());
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ DefineConsoleFunction( spawnObject, S32, ( const char * spawnClass
|
|||
, const char * spawnProperties
|
||||
, const char * spawnScript
|
||||
),("","","","") ,"spawnObject(class [, dataBlock, name, properties, script])"
|
||||
"@hide")
|
||||
"@hide")
|
||||
{
|
||||
SimObject* spawnObject = Sim::spawnObject(spawnClass, spawnDataBlock, spawnName, spawnProperties, spawnScript);
|
||||
|
||||
|
|
@ -203,12 +203,12 @@ ConsoleFunction(schedule, S32, 4, 0, "schedule(time, refobject|0, command, <arg1
|
|||
}
|
||||
|
||||
DefineConsoleFunction( getUniqueName, const char*, (const char * baseName), ,
|
||||
"( String baseName )\n"
|
||||
"@brief Returns a unique unused SimObject name based on a given base name.\n\n"
|
||||
"@baseName Name to conver to a unique string if another instance exists\n"
|
||||
"@note Currently only used by editors\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal")
|
||||
"( String baseName )\n"
|
||||
"@brief Returns a unique unused SimObject name based on a given base name.\n\n"
|
||||
"@baseName Name to conver to a unique string if another instance exists\n"
|
||||
"@note Currently only used by editors\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal")
|
||||
{
|
||||
String outName = Sim::getUniqueName( baseName );
|
||||
|
||||
|
|
@ -247,10 +247,10 @@ DefineConsoleFunction( getUniqueInternalName, const char*, (const char * baseNam
|
|||
}
|
||||
|
||||
DefineConsoleFunction( isValidObjectName, bool, (const char * name), , "( string name )"
|
||||
"@brief Return true if the given name makes for a valid object name.\n\n"
|
||||
"@param name Name of object\n"
|
||||
"@return True if name is allowed, false if denied (usually because it starts with a number, _, or invalid character"
|
||||
"@ingroup Console")
|
||||
"@brief Return true if the given name makes for a valid object name.\n\n"
|
||||
"@param name Name of object\n"
|
||||
"@return True if name is allowed, false if denied (usually because it starts with a number, _, or invalid character"
|
||||
"@ingroup Console")
|
||||
{
|
||||
return Sim::isValidObjectName( name );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ void SimNameDictionary::remove(SimObject* obj)
|
|||
if(*walk == obj)
|
||||
{
|
||||
*walk = obj->nextNameObject;
|
||||
obj->nextNameObject = (SimObject*)-1;
|
||||
obj->nextNameObject = (SimObject*)-1;
|
||||
hashEntryCount--;
|
||||
|
||||
Mutex::unlockMutex(mutex);
|
||||
|
|
@ -164,7 +164,7 @@ void SimNameDictionary::remove(SimObject* obj)
|
|||
root.erase(name);
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -279,7 +279,7 @@ void SimManagerNameDictionary::remove(SimObject* obj)
|
|||
if(*walk == obj)
|
||||
{
|
||||
*walk = obj->nextManagerNameObject;
|
||||
obj->nextManagerNameObject = (SimObject*)-1;
|
||||
obj->nextManagerNameObject = (SimObject*)-1;
|
||||
hashEntryCount--;
|
||||
|
||||
Mutex::unlockMutex(mutex);
|
||||
|
|
@ -293,7 +293,7 @@ void SimManagerNameDictionary::remove(SimObject* obj)
|
|||
root.erase(name);
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ struct StringTableEntryEq
|
|||
}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<StringTableEntry, SimObject*, StringTableEntryHash, StringTableEntryEq> StringDictDef;
|
||||
typedef std::unordered_map<StringTableEntry, SimObject*, StringTableEntryHash, StringTableEntryEq> StringDictDef;
|
||||
typedef std::unordered_map<SimObjectId, SimObject*> SimObjectIdDictDef;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ SimConsoleEvent::SimConsoleEvent(S32 argc, ConsoleValueRef *argv, bool onObject)
|
|||
mArgv[i].value = new ConsoleValue();
|
||||
mArgv[i].value->type = ConsoleValue::TypeInternalString;
|
||||
mArgv[i].value->init();
|
||||
if (argv)
|
||||
{
|
||||
mArgv[i].value->setStringValue((const char*)argv[i]);
|
||||
}
|
||||
if (argv)
|
||||
{
|
||||
mArgv[i].value->setStringValue((const char*)argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static void shutdownEventQueue()
|
|||
|
||||
U32 postEvent(SimObject *destObject, SimEvent* event,U32 time)
|
||||
{
|
||||
AssertFatal(time == -1 || time >= getCurrentTime(),
|
||||
AssertFatal(time == -1 || time >= getCurrentTime(),
|
||||
"Sim::postEvent() - Event time must be greater than or equal to the current time." );
|
||||
AssertFatal(destObject, "Sim::postEvent() - Destination object for event doesn't exist.");
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ void advanceToTime(SimTime targetTime)
|
|||
event->process(obj);
|
||||
delete event;
|
||||
}
|
||||
gCurrentTime = targetTime;
|
||||
gCurrentTime = targetTime;
|
||||
|
||||
Mutex::unlockMutex(gEventQueueMutex);
|
||||
}
|
||||
|
|
@ -393,7 +393,7 @@ SimObject* findObject(const char* name)
|
|||
|
||||
SimObject* findObject(SimObjectId id)
|
||||
{
|
||||
return gIdDictionary->find(id);
|
||||
return gIdDictionary->find(id);
|
||||
}
|
||||
|
||||
SimObject *spawnObject(String spawnClass, String spawnDataBlock, String spawnName,
|
||||
|
|
@ -600,7 +600,7 @@ SimDataBlockGroup::SimDataBlockGroup()
|
|||
|
||||
S32 QSORT_CALLBACK SimDataBlockGroup::compareModifiedKey(const void* a,const void* b)
|
||||
{
|
||||
const SimDataBlock* dba = *((const SimDataBlock**)a);
|
||||
const SimDataBlock* dba = *((const SimDataBlock**)a);
|
||||
const SimDataBlock* dbb = *((const SimDataBlock**)b);
|
||||
|
||||
return dba->getModifiedKey() - dbb->getModifiedKey();
|
||||
|
|
@ -612,6 +612,6 @@ void SimDataBlockGroup::sort()
|
|||
if(mLastModifiedKey != SimDataBlock::getNextModifiedKey())
|
||||
{
|
||||
mLastModifiedKey = SimDataBlock::getNextModifiedKey();
|
||||
dQsort(objectList.address(),objectList.size(),sizeof(SimObject *),compareModifiedKey);
|
||||
dQsort(objectList.address(),objectList.size(),sizeof(SimObject *),compareModifiedKey);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ SimObject::SimObject()
|
|||
mFlags.set( ModStaticFields | ModDynamicFields );
|
||||
|
||||
mFieldDictionary = NULL;
|
||||
mCanSaveFieldDictionary = true;
|
||||
mCanSaveFieldDictionary = true;
|
||||
|
||||
mClassName = NULL;
|
||||
mSuperClassName = NULL;
|
||||
|
|
@ -592,7 +592,7 @@ void SimObject::setDeclarationLine(U32 lineNumber)
|
|||
bool SimObject::registerObject()
|
||||
{
|
||||
AssertFatal( !mFlags.test( Added ), "reigsterObject - Object already registered!");
|
||||
mFlags.clear(Deleted | Removed);
|
||||
mFlags.clear(Deleted | Removed);
|
||||
|
||||
if(smForceId)
|
||||
{
|
||||
|
|
@ -609,11 +609,11 @@ bool SimObject::registerObject()
|
|||
AssertFatal(Sim::gIdDictionary && Sim::gNameDictionary,
|
||||
"SimObject::registerObject - tried to register an object before Sim::init()!");
|
||||
|
||||
Sim::gIdDictionary->insert(this);
|
||||
Sim::gIdDictionary->insert(this);
|
||||
|
||||
Sim::gNameDictionary->insert(this);
|
||||
|
||||
// Notify object
|
||||
// Notify object
|
||||
bool ret = onAdd();
|
||||
|
||||
if(!ret)
|
||||
|
|
@ -661,10 +661,10 @@ void SimObject::deleteObject()
|
|||
|
||||
void SimObject::_destroySelf()
|
||||
{
|
||||
AssertFatal( !isDeleted(), "SimObject::destroySelf - Object has already been deleted" );
|
||||
AssertFatal( !isRemoved(), "SimObject::destroySelf - Object in the process of being removed" );
|
||||
AssertFatal( !isDeleted(), "SimObject::destroySelf - Object has already been deleted" );
|
||||
AssertFatal( !isRemoved(), "SimObject::destroySelf - Object in the process of being removed" );
|
||||
|
||||
mFlags.set( Deleted );
|
||||
mFlags.set( Deleted );
|
||||
|
||||
if( mFlags.test( Added ) )
|
||||
unregisterObject();
|
||||
|
|
@ -1308,7 +1308,7 @@ void SimObject::dumpClassHierarchy()
|
|||
while(pRep)
|
||||
{
|
||||
Con::warnf("%s ->", pRep->getClassName());
|
||||
pRep = pRep->getParentClass();
|
||||
pRep = pRep->getParentClass();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1376,7 +1376,7 @@ bool SimObject::isChildOfGroup(SimGroup* pGroup)
|
|||
if(pGroup == dynamic_cast<SimGroup*>(this))
|
||||
return true;
|
||||
|
||||
SimGroup* temp = mGroup;
|
||||
SimGroup* temp = mGroup;
|
||||
while(temp)
|
||||
{
|
||||
if(temp == pGroup)
|
||||
|
|
@ -2884,7 +2884,7 @@ DefineConsoleMethod( SimObject, isMemberOfClass, bool, ( const char* className )
|
|||
return true;
|
||||
}
|
||||
|
||||
pRep = pRep->getParentClass();
|
||||
pRep = pRep->getParentClass();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -826,7 +826,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
|
|||
virtual bool readObject(Stream *stream);
|
||||
|
||||
/// Set whether fields created at runtime should be saved. Default is true.
|
||||
void setCanSaveDynamicFields( bool bCanSave ) { mCanSaveFieldDictionary = bCanSave; }
|
||||
void setCanSaveDynamicFields( bool bCanSave ) { mCanSaveFieldDictionary = bCanSave; }
|
||||
|
||||
/// Get whether fields created at runtime should be saved. Default is true.
|
||||
bool getCanSaveDynamicFields( ) { return mCanSaveFieldDictionary;}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
SimObjectMemento::SimObjectMemento()
|
||||
: mState( NULL ),
|
||||
mIsDatablock( false )
|
||||
mIsDatablock( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -45,16 +45,16 @@ void SimObjectMemento::save( SimObject *object )
|
|||
dFree( mState );
|
||||
mObjectName = String::EmptyString;
|
||||
|
||||
// Use a stream to save the state.
|
||||
// Use a stream to save the state.
|
||||
MemStream stream( 256 );
|
||||
|
||||
U32 writeFlags = 0;
|
||||
SimDataBlock* db = dynamic_cast<SimDataBlock*>(object);
|
||||
if( !db )
|
||||
stream.write( sizeof( "return " ) - 1, "return " );
|
||||
else
|
||||
SimDataBlock* db = dynamic_cast<SimDataBlock*>(object);
|
||||
if( !db )
|
||||
stream.write( sizeof( "return " ) - 1, "return " );
|
||||
else
|
||||
{
|
||||
mIsDatablock = true;
|
||||
mIsDatablock = true;
|
||||
|
||||
// Cull the datablock name from the output so that
|
||||
// we can easily replace it in case the datablock's name
|
||||
|
|
@ -64,7 +64,7 @@ void SimObjectMemento::save( SimObject *object )
|
|||
|
||||
writeFlags |= SimObject::NoName;
|
||||
}
|
||||
|
||||
|
||||
object->write( stream, 0, writeFlags );
|
||||
stream.write( (UTF8)0 );
|
||||
|
||||
|
|
@ -82,9 +82,9 @@ SimObject *SimObjectMemento::restore() const
|
|||
// TODO: We could potentially make this faster by
|
||||
// caching the CodeBlock generated from the string
|
||||
|
||||
SimObject* object;
|
||||
if( !mIsDatablock )
|
||||
{
|
||||
SimObject* object;
|
||||
if( !mIsDatablock )
|
||||
{
|
||||
// Set the redefine behavior to automatically giving
|
||||
// the new objects unique names. This will restore the
|
||||
// old names if they are still available or give reasonable
|
||||
|
|
@ -95,22 +95,22 @@ SimObject *SimObjectMemento::restore() const
|
|||
|
||||
// Read the object.
|
||||
|
||||
const UTF8* result = Con::evaluate( mState );
|
||||
const UTF8* result = Con::evaluate( mState );
|
||||
|
||||
// Restore the redefine behavior.
|
||||
|
||||
Con::setVariable( "$Con::redefineBehavior", oldRedefineBehavior );
|
||||
|
||||
if ( !result || !result[ 0 ] )
|
||||
return NULL;
|
||||
if ( !result || !result[ 0 ] )
|
||||
return NULL;
|
||||
|
||||
// Look up the object.
|
||||
|
||||
U32 objectId = dAtoi( result );
|
||||
object = Sim::findObject( objectId );
|
||||
}
|
||||
else
|
||||
{
|
||||
U32 objectId = dAtoi( result );
|
||||
object = Sim::findObject( objectId );
|
||||
}
|
||||
else
|
||||
{
|
||||
String objectName = mObjectName;
|
||||
|
||||
// For datablocks, it's getting a little complicated. Datablock definitions cannot be used
|
||||
|
|
@ -140,16 +140,16 @@ SimObject *SimObjectMemento::restore() const
|
|||
dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] );
|
||||
}
|
||||
|
||||
Con::evaluate( tempBuffer );
|
||||
Con::evaluate( tempBuffer );
|
||||
|
||||
if( tempBuffer != mState )
|
||||
dFree( tempBuffer );
|
||||
|
||||
if( objectName == String::EmptyString )
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
object = Sim::findObject( objectName );
|
||||
}
|
||||
object = Sim::findObject( objectName );
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ protected:
|
|||
|
||||
/// The captured object's name.
|
||||
String mObjectName;
|
||||
bool mIsDatablock;
|
||||
bool mIsDatablock;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@
|
|||
IMPLEMENT_CONOBJECT( SimPersistSet );
|
||||
|
||||
ConsoleDocClass( SimPersistSet,
|
||||
"@brief A SimSet that can be safely persisted.\n\n"
|
||||
"Uses SimPersistIDs to reference objects in the set "
|
||||
"while persisted on disk. This allows the set to resolve "
|
||||
"its references no matter whether they are loaded before or "
|
||||
"after the set is created.\n\n"
|
||||
"Not intended for game development, for editors or internal use only.\n\n "
|
||||
"@internal");
|
||||
"@brief A SimSet that can be safely persisted.\n\n"
|
||||
"Uses SimPersistIDs to reference objects in the set "
|
||||
"while persisted on disk. This allows the set to resolve "
|
||||
"its references no matter whether they are loaded before or "
|
||||
"after the set is created.\n\n"
|
||||
"Not intended for game development, for editors or internal use only.\n\n "
|
||||
"@internal");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -213,18 +213,18 @@ SimObject *loadObjectStream(Stream *stream)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction(saveObject, bool, ( SimObject *object, const char *filename ),,
|
||||
"@brief Serialize the object to a file.\n\n"
|
||||
"@param object The object to serialize.\n"
|
||||
"@param filename The file name and path.\n"
|
||||
"@ingroup Console\n")
|
||||
"@brief Serialize the object to a file.\n\n"
|
||||
"@param object The object to serialize.\n"
|
||||
"@param filename The file name and path.\n"
|
||||
"@ingroup Console\n")
|
||||
{
|
||||
return object && Sim::saveObject(object, filename);
|
||||
}
|
||||
|
||||
DefineEngineFunction(loadObject, SimObject*, ( const char *filename ),,
|
||||
"@brief Loads a serialized object from a file.\n\n"
|
||||
"@param Name and path to text file containing the object\n"
|
||||
"@ingroup Console\n")
|
||||
"@brief Loads a serialized object from a file.\n\n"
|
||||
"@param Name and path to text file containing the object\n"
|
||||
"@ingroup Console\n")
|
||||
{
|
||||
return Sim::loadObjectStream(filename);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues)
|
|||
//Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
|
||||
for (U32 i=0; i<count; i++)
|
||||
{
|
||||
outValues[i].value = &mStack[mStackPos+i];
|
||||
outValues[i].value = &mStack[mStackPos+i];
|
||||
}
|
||||
mStackPos += count;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -67,17 +67,17 @@ DefineConsoleFunction( telnetSetParameters, void, ( int port, const char* consol
|
|||
"@param consolePass Password for read/write access to console.\n"
|
||||
"@param listenPass Password for read access to console.\n"
|
||||
"@param remoteEcho [optional] Enable echoing back to the client, off by default.\n\n"
|
||||
"@ingroup Debugging")
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
if (TelConsole)
|
||||
TelConsole->setTelnetParameters(port, consolePass, listenPass, remoteEcho);
|
||||
TelConsole->setTelnetParameters(port, consolePass, listenPass, remoteEcho);
|
||||
}
|
||||
|
||||
static void telnetCallback(U32 level, const char *consoleLine)
|
||||
{
|
||||
TORQUE_UNUSED(level);
|
||||
if (TelConsole)
|
||||
TelConsole->processConsoleLine(consoleLine);
|
||||
TelConsole->processConsoleLine(consoleLine);
|
||||
}
|
||||
|
||||
TelnetConsole::TelnetConsole()
|
||||
|
|
@ -121,9 +121,9 @@ void TelnetConsole::setTelnetParameters(S32 port, const char *telnetPassword, co
|
|||
mAcceptPort = port;
|
||||
if(mAcceptPort != -1 && mAcceptPort != 0)
|
||||
{
|
||||
NetAddress address;
|
||||
Net::getIdealListenAddress(&address);
|
||||
address.port = mAcceptPort;
|
||||
NetAddress address;
|
||||
Net::getIdealListenAddress(&address);
|
||||
address.port = mAcceptPort;
|
||||
|
||||
mAcceptSocket = Net::openSocket();
|
||||
Net::bindAddress(address, mAcceptSocket);
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ MODULE_END;
|
|||
|
||||
DefineConsoleFunction( dbgSetParameters, void, (S32 port, const char * password, bool waitForClient ), (false), "( int port, string password, bool waitForClient )"
|
||||
"Open a debug server port on the specified port, requiring the specified password, "
|
||||
"and optionally waiting for the debug client to connect.\n"
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
"and optionally waiting for the debug client to connect.\n"
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
{
|
||||
if (TelDebugger)
|
||||
{
|
||||
|
|
@ -126,17 +126,17 @@ DefineConsoleFunction( dbgSetParameters, void, (S32 port, const char * password,
|
|||
|
||||
DefineConsoleFunction( dbgIsConnected, bool, (), , "()"
|
||||
"Returns true if a script debugging client is connected else return false.\n"
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
{
|
||||
return TelDebugger && TelDebugger->isConnected();
|
||||
}
|
||||
|
||||
DefineConsoleFunction( dbgDisconnect, void, (), , "()"
|
||||
"Forcibly disconnects any attached script debugging client.\n"
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
"@internal Primarily used for Torsion and other debugging tools")
|
||||
{
|
||||
if (TelDebugger)
|
||||
TelDebugger->disconnect();
|
||||
TelDebugger->disconnect();
|
||||
}
|
||||
|
||||
static void debuggerConsumer(U32 level, const char *line)
|
||||
|
|
@ -244,9 +244,9 @@ void TelnetDebugger::setDebugParameters(S32 port, const char *password, bool wai
|
|||
mAcceptPort = port;
|
||||
if(mAcceptPort != -1 && mAcceptPort != 0)
|
||||
{
|
||||
NetAddress address;
|
||||
Net::getIdealListenAddress(&address);
|
||||
address.port = mAcceptPort;
|
||||
NetAddress address;
|
||||
Net::getIdealListenAddress(&address);
|
||||
address.port = mAcceptPort;
|
||||
|
||||
mAcceptSocket = Net::openSocket();
|
||||
Net::bindAddress(address, mAcceptSocket);
|
||||
|
|
@ -588,7 +588,7 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
|
|||
// TODO: This assumes that the OS file names are case
|
||||
// insensitive... Torque needs a dFilenameCmp() function.
|
||||
if( dStricmp( cur->fileName, code->name ) == 0 )
|
||||
{
|
||||
{
|
||||
cur->code = code;
|
||||
|
||||
// Find the fist breakline starting from and
|
||||
|
|
@ -741,7 +741,7 @@ void TelnetDebugger::removeBreakpoint(const char *fileName, S32 line)
|
|||
{
|
||||
Breakpoint *brk = *bp;
|
||||
*bp = brk->next;
|
||||
if ( brk->code )
|
||||
if ( brk->code )
|
||||
brk->code->clearBreakpoint(brk->lineNumber);
|
||||
dFree(brk->testExpression);
|
||||
delete brk;
|
||||
|
|
@ -754,7 +754,7 @@ void TelnetDebugger::removeAllBreakpoints()
|
|||
while(walk)
|
||||
{
|
||||
Breakpoint *temp = walk->next;
|
||||
if ( walk->code )
|
||||
if ( walk->code )
|
||||
walk->code->clearBreakpoint(walk->lineNumber);
|
||||
dFree(walk->testExpression);
|
||||
delete walk;
|
||||
|
|
@ -792,10 +792,10 @@ void TelnetDebugger::setBreakOnNextStatement( bool enabled )
|
|||
for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
|
||||
walk->clearAllBreaks();
|
||||
for(Breakpoint *w = mBreakpoints; w; w = w->next)
|
||||
{
|
||||
if ( w->code )
|
||||
{
|
||||
if ( w->code )
|
||||
w->code->setBreakpoint(w->lineNumber);
|
||||
}
|
||||
}
|
||||
mBreakOnNextStatement = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -848,7 +848,7 @@ void TelnetDebugger::debugStepOut()
|
|||
setBreakOnNextStatement( false );
|
||||
mStackPopBreakIndex = gEvalState.getStackDepth() - 1;
|
||||
if ( mStackPopBreakIndex == 0 )
|
||||
mStackPopBreakIndex = -1;
|
||||
mStackPopBreakIndex = -1;
|
||||
mProgramPaused = false;
|
||||
send("RUNNING\r\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,42 +49,42 @@ void TypeValidator::consoleError(SimObject *object, const char *format, ...)
|
|||
|
||||
void FRangeValidator::validateType(SimObject *object, void *typePtr)
|
||||
{
|
||||
F32 *v = (F32 *) typePtr;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Must be between %g and %g", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
F32 *v = (F32 *) typePtr;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Must be between %g and %g", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
}
|
||||
|
||||
void IRangeValidator::validateType(SimObject *object, void *typePtr)
|
||||
{
|
||||
S32 *v = (S32 *) typePtr;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Must be between %d and %d", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
S32 *v = (S32 *) typePtr;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Must be between %d and %d", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
}
|
||||
|
||||
void IRangeValidatorScaled::validateType(SimObject *object, void *typePtr)
|
||||
{
|
||||
S32 *v = (S32 *) typePtr;
|
||||
*v /= factor;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Scaled value must be between %d and %d", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
S32 *v = (S32 *) typePtr;
|
||||
*v /= factor;
|
||||
if(*v < minV || *v > maxV)
|
||||
{
|
||||
consoleError(object, "Scaled value must be between %d and %d", minV, maxV);
|
||||
if(*v < minV)
|
||||
*v = minV;
|
||||
else if(*v > maxV)
|
||||
*v = maxV;
|
||||
}
|
||||
}
|
||||
|
||||
void Point3NormalizeValidator::validateType(SimObject *object, void *typePtr)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
#include "console/engineAPI.h"
|
||||
#endif
|
||||
|
||||
const F32 gGamma = 2.2f;
|
||||
const F32 gOneOverGamma = 1.f / 2.2f;
|
||||
|
||||
class ColorI;
|
||||
|
||||
|
||||
|
|
@ -104,8 +107,10 @@ class ColorF
|
|||
(alpha >= 0.0f && alpha <= 1.0f); }
|
||||
void clamp();
|
||||
|
||||
ColorF toLinear() const;
|
||||
ColorF toGamma() const;
|
||||
ColorF toLinear();
|
||||
ColorF toGamma();
|
||||
//calculate luminance, make sure color is linear first
|
||||
F32 luminance();
|
||||
|
||||
static const ColorF ZERO;
|
||||
static const ColorF ONE;
|
||||
|
|
@ -209,6 +214,9 @@ class ColorI
|
|||
|
||||
operator const U8*() const { return &red; }
|
||||
|
||||
ColorI toLinear();
|
||||
ColorI toGamma();
|
||||
|
||||
static const ColorI ZERO;
|
||||
static const ColorI ONE;
|
||||
static const ColorI WHITE;
|
||||
|
|
@ -465,14 +473,32 @@ inline void ColorF::clamp()
|
|||
alpha = 0.0f;
|
||||
}
|
||||
|
||||
inline ColorF ColorF::toLinear() const
|
||||
inline ColorF ColorF::toGamma()
|
||||
{
|
||||
return ColorF(mPow(red, 2.2f), mPow(green, 2.2f), mPow(blue, 2.2f), alpha);
|
||||
ColorF color;
|
||||
color.red = mPow(red,gOneOverGamma);
|
||||
color.green = mPow(green, gOneOverGamma);
|
||||
color.blue = mPow(blue, gOneOverGamma);
|
||||
color.alpha = alpha;
|
||||
return color;
|
||||
}
|
||||
|
||||
inline ColorF ColorF::toGamma() const
|
||||
inline ColorF ColorF::toLinear()
|
||||
{
|
||||
return ColorF(mPow(red, 1.0f / 2.2f), mPow(green, 1.0f / 2.2f), mPow(blue, 1.0f / 2.2f), alpha);
|
||||
ColorF color;
|
||||
color.red = mPow(red,gGamma);
|
||||
color.green = mPow(green, gGamma);
|
||||
color.blue = mPow(blue, gGamma);
|
||||
color.alpha = alpha;
|
||||
return color;
|
||||
}
|
||||
|
||||
inline F32 ColorF::luminance()
|
||||
{
|
||||
// ITU BT.709
|
||||
//return red * 0.2126f + green * 0.7152f + blue * 0.0722f;
|
||||
// ITU BT.601
|
||||
return red * 0.3f + green * 0.59f + blue * 0.11f;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -945,6 +971,18 @@ inline String ColorI::getHex() const
|
|||
return result;
|
||||
}
|
||||
|
||||
inline ColorI ColorI::toGamma()
|
||||
{
|
||||
ColorF color = (ColorF)*this;
|
||||
return (ColorI)color.toGamma();
|
||||
}
|
||||
|
||||
inline ColorI ColorI::toLinear()
|
||||
{
|
||||
ColorF color = (ColorF)*this;
|
||||
return (ColorI)color.toLinear();
|
||||
}
|
||||
|
||||
//-------------------------------------- INLINE CONVERSION OPERATORS
|
||||
inline ColorF::operator ColorI() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ U32 oneUTF32toUTF8(const UTF32 codepoint, UTF8 *threeByteCodeunitBuf)
|
|||
// Process the 1st byte. filter based on the # of expected bytes.
|
||||
mask = sgByteMask8LUT[bytecount];
|
||||
marker = ( ~mask << 1 );
|
||||
threeByteCodeunitBuf[0] = marker | working & mask;
|
||||
threeByteCodeunitBuf[0] = marker | (working & mask);
|
||||
|
||||
PROFILE_END();
|
||||
return bytecount;
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ bool TagDictionary::match(const char* pattern, const char* str)
|
|||
return !*str;
|
||||
|
||||
case '*':
|
||||
return match(pattern+1, str) || *str && match(pattern, str+1);
|
||||
return match(pattern+1, str) || (*str && match(pattern, str+1));
|
||||
|
||||
case '?':
|
||||
return *str && match(pattern+1, str+1);
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ ConsoleDocClass( River,
|
|||
#define NODE_RADIUS 15.0f
|
||||
|
||||
static U32 gIdxArray[6][2][3] = {
|
||||
{ { 0, 4, 5 }, { 0, 5, 1 }, }, // Top Face
|
||||
{ { 2, 6, 4 }, { 2, 4, 0 }, }, // Left Face
|
||||
{ { 1, 5, 7 }, { 1, 7, 3 }, }, // Right Face
|
||||
{ { 2, 3, 7 }, { 2, 7, 6 }, }, // Bottom Face
|
||||
{ { 0, 1, 3 }, { 0, 3, 2 }, }, // Front Face
|
||||
{ { 4, 6, 7 }, { 4, 7, 5 }, }, // Back Face
|
||||
{ { 0, 4, 5 }, { 0, 5, 1 }, }, // Top Face
|
||||
{ { 2, 6, 4 }, { 2, 4, 0 }, }, // Left Face
|
||||
{ { 1, 5, 7 }, { 1, 7, 3 }, }, // Right Face
|
||||
{ { 2, 3, 7 }, { 2, 7, 6 }, }, // Bottom Face
|
||||
{ { 0, 1, 3 }, { 0, 3, 2 }, }, // Front Face
|
||||
{ { 4, 6, 7 }, { 4, 7, 5 }, }, // Back Face
|
||||
};
|
||||
|
||||
struct RiverHitSegment
|
||||
|
|
@ -93,10 +93,10 @@ struct RiverHitSegment
|
|||
|
||||
static S32 QSORT_CALLBACK compareHitSegments(const void* a,const void* b)
|
||||
{
|
||||
const RiverHitSegment *fa = (RiverHitSegment*)a;
|
||||
const RiverHitSegment *fb = (RiverHitSegment*)b;
|
||||
const RiverHitSegment *fa = (RiverHitSegment*)a;
|
||||
const RiverHitSegment *fb = (RiverHitSegment*)b;
|
||||
|
||||
return mSign(fb->t - fa->t);
|
||||
return mSign(fb->t - fa->t);
|
||||
}
|
||||
|
||||
static Point3F sSegmentPointComparePoints[4];
|
||||
|
|
@ -655,17 +655,17 @@ void River::consoleInit()
|
|||
Parent::consoleInit();
|
||||
|
||||
Con::addVariable( "$River::EditorOpen", TypeBool, &River::smEditorOpen, "For editor use.\n"
|
||||
"@ingroup Editors\n" );
|
||||
"@ingroup Editors\n" );
|
||||
Con::addVariable( "$River::showWalls", TypeBool, &River::smShowWalls, "For editor use.\n"
|
||||
"@ingroup Editors\n" );
|
||||
"@ingroup Editors\n" );
|
||||
Con::addVariable( "$River::showNodes", TypeBool, &River::smShowNodes, "For editor use.\n"
|
||||
"@ingroup Editors\n");
|
||||
"@ingroup Editors\n");
|
||||
Con::addVariable( "$River::showSpline", TypeBool, &River::smShowSpline, "For editor use.\n"
|
||||
"@ingroup Editors\n" );
|
||||
"@ingroup Editors\n" );
|
||||
Con::addVariable( "$River::showRiver", TypeBool, &River::smShowRiver, "For editor use.\n"
|
||||
"@ingroup Editors\n" );
|
||||
Con::addVariable( "$River::showWireframe", TypeBool, &River::smWireframe, "For editor use.\n"
|
||||
"@ingroup Editors\n");
|
||||
"@ingroup Editors\n" );
|
||||
Con::addVariable( "$River::showWireframe", TypeBool, &River::smWireframe, "For editor use.\n"
|
||||
"@ingroup Editors\n");
|
||||
}
|
||||
|
||||
bool River::addNodeFromField( void *object, const char *index, const char *data )
|
||||
|
|
@ -816,7 +816,7 @@ void River::innerRender( SceneRenderState *state )
|
|||
|
||||
_makeRenderBatches( camPosition );
|
||||
|
||||
if ( !River::smShowRiver )
|
||||
if ( !River::smShowRiver )
|
||||
return;
|
||||
|
||||
// If no material... we're done.
|
||||
|
|
@ -851,7 +851,7 @@ void River::innerRender( SceneRenderState *state )
|
|||
U32 vertCount = ( endVert - startVert ) + 1;
|
||||
U32 idxCount = ( endIdx - startIdx ) + 1;
|
||||
U32 triangleCount = idxCount / 3;
|
||||
|
||||
|
||||
AssertFatal( startVert < mLowVertCount, "River, bad draw call!" );
|
||||
AssertFatal( startVert + vertCount <= mLowVertCount, "River, bad draw call!" );
|
||||
AssertFatal( triangleCount <= mLowTriangleCount, "River, bad draw call!" );
|
||||
|
|
@ -962,7 +962,7 @@ U32 River::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
|
|||
stream->write( mSegmentsPerBatch );
|
||||
stream->write( mDepthScale );
|
||||
stream->write( mMaxDivisionSize );
|
||||
stream->write( mColumnCount );
|
||||
stream->write( mColumnCount );
|
||||
|
||||
stream->write( mFlowMagnitude );
|
||||
stream->write( mLodDistance );
|
||||
|
|
@ -1045,7 +1045,7 @@ void River::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
// RiverMask
|
||||
if(stream->readFlag())
|
||||
{
|
||||
MatrixF ObjectMatrix;
|
||||
MatrixF ObjectMatrix;
|
||||
stream->readAffineTransform(&ObjectMatrix);
|
||||
Parent::setTransform(ObjectMatrix);
|
||||
|
||||
|
|
@ -1053,7 +1053,7 @@ void River::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
stream->read( &mSegmentsPerBatch );
|
||||
stream->read( &mDepthScale );
|
||||
stream->read( &mMaxDivisionSize );
|
||||
stream->read( &mColumnCount );
|
||||
stream->read( &mColumnCount );
|
||||
|
||||
stream->read( &mFlowMagnitude );
|
||||
stream->read( &mLodDistance );
|
||||
|
|
@ -1198,56 +1198,56 @@ void River::setScale( const VectorF &scale )
|
|||
|
||||
bool River::castRay(const Point3F &s, const Point3F &e, RayInfo* info)
|
||||
{
|
||||
Point3F start = s;
|
||||
Point3F end = e;
|
||||
mObjToWorld.mulP(start);
|
||||
mObjToWorld.mulP(end);
|
||||
Point3F start = s;
|
||||
Point3F end = e;
|
||||
mObjToWorld.mulP(start);
|
||||
mObjToWorld.mulP(end);
|
||||
|
||||
F32 out = 1.0f; // The output fraction/percentage along the line defined by s and e
|
||||
VectorF norm(0.0f, 0.0f, 0.0f); // The normal of the face intersected
|
||||
F32 out = 1.0f; // The output fraction/percentage along the line defined by s and e
|
||||
VectorF norm(0.0f, 0.0f, 0.0f); // The normal of the face intersected
|
||||
|
||||
Vector<RiverHitSegment> hitSegments;
|
||||
Vector<RiverHitSegment> hitSegments;
|
||||
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
const RiverSegment &segment = mSegments[i];
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
const RiverSegment &segment = mSegments[i];
|
||||
|
||||
F32 t;
|
||||
VectorF n;
|
||||
F32 t;
|
||||
VectorF n;
|
||||
|
||||
if ( segment.worldbounds.collideLine( start, end, &t, &n ) )
|
||||
{
|
||||
hitSegments.increment();
|
||||
hitSegments.last().t = t;
|
||||
hitSegments.last().idx = i;
|
||||
}
|
||||
}
|
||||
if ( segment.worldbounds.collideLine( start, end, &t, &n ) )
|
||||
{
|
||||
hitSegments.increment();
|
||||
hitSegments.last().t = t;
|
||||
hitSegments.last().idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
dQsort( hitSegments.address(), hitSegments.size(), sizeof(RiverHitSegment), compareHitSegments );
|
||||
dQsort( hitSegments.address(), hitSegments.size(), sizeof(RiverHitSegment), compareHitSegments );
|
||||
|
||||
U32 idx0, idx1, idx2;
|
||||
F32 t;
|
||||
|
||||
for ( U32 i = 0; i < hitSegments.size(); i++ )
|
||||
{
|
||||
U32 segIdx = hitSegments[i].idx;
|
||||
const RiverSegment &segment = mSegments[segIdx];
|
||||
for ( U32 i = 0; i < hitSegments.size(); i++ )
|
||||
{
|
||||
U32 segIdx = hitSegments[i].idx;
|
||||
const RiverSegment &segment = mSegments[segIdx];
|
||||
|
||||
// Each segment has 6 faces
|
||||
for ( U32 j = 0; j < 6; j++ )
|
||||
{
|
||||
if ( j == 4 && segIdx != 0 )
|
||||
continue;
|
||||
// Each segment has 6 faces
|
||||
for ( U32 j = 0; j < 6; j++ )
|
||||
{
|
||||
if ( j == 4 && segIdx != 0 )
|
||||
continue;
|
||||
|
||||
if ( j == 5 && segIdx != mSegments.size() - 1 )
|
||||
continue;
|
||||
if ( j == 5 && segIdx != mSegments.size() - 1 )
|
||||
continue;
|
||||
|
||||
// Each face has 2 triangles
|
||||
for ( U32 k = 0; k < 2; k++ )
|
||||
{
|
||||
idx0 = gIdxArray[j][k][0];
|
||||
idx1 = gIdxArray[j][k][1];
|
||||
idx2 = gIdxArray[j][k][2];
|
||||
// Each face has 2 triangles
|
||||
for ( U32 k = 0; k < 2; k++ )
|
||||
{
|
||||
idx0 = gIdxArray[j][k][0];
|
||||
idx1 = gIdxArray[j][k][1];
|
||||
idx2 = gIdxArray[j][k][2];
|
||||
|
||||
const Point3F &v0 = segment[idx0];
|
||||
const Point3F &v1 = segment[idx1];
|
||||
|
|
@ -1257,40 +1257,40 @@ bool River::castRay(const Point3F &s, const Point3F &e, RayInfo* info)
|
|||
v2, v1, v0,
|
||||
NULL,
|
||||
&t ) )
|
||||
continue;
|
||||
continue;
|
||||
|
||||
if ( t >= 0.0f && t < 1.0f && t < out )
|
||||
{
|
||||
out = t;
|
||||
if ( t >= 0.0f && t < 1.0f && t < out )
|
||||
{
|
||||
out = t;
|
||||
|
||||
// optimize this, can be calculated easily within
|
||||
// the collision test
|
||||
norm = PlaneF( v0, v1, v2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out >= 0.0f && out < 1.0f)
|
||||
break;
|
||||
}
|
||||
if (out >= 0.0f && out < 1.0f)
|
||||
break;
|
||||
}
|
||||
|
||||
if (out >= 0.0f && out < 1.0f)
|
||||
{
|
||||
info->t = out;
|
||||
info->normal = norm;
|
||||
info->point.interpolate(start, end, out);
|
||||
info->face = -1;
|
||||
info->object = this;
|
||||
if (out >= 0.0f && out < 1.0f)
|
||||
{
|
||||
info->t = out;
|
||||
info->normal = norm;
|
||||
info->point.interpolate(start, end, out);
|
||||
info->face = -1;
|
||||
info->object = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool River::collideBox(const Point3F &start, const Point3F &end, RayInfo* info)
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool River::buildPolyList( PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& sphere )
|
||||
|
|
@ -1656,8 +1656,8 @@ void River::_generateVerts()
|
|||
// These will depend on the level of subdivision per segment
|
||||
// calculated below.
|
||||
mHighVertCount = 0;
|
||||
mHighTriangleCount = 0;
|
||||
|
||||
mHighTriangleCount = 0;
|
||||
|
||||
// Calculate the number of row/column subdivisions per each
|
||||
// RiverSegment.
|
||||
|
||||
|
|
@ -1671,18 +1671,18 @@ void River::_generateVerts()
|
|||
|
||||
mColumnCount = mCeil( greatestWidth / mMaxDivisionSize );
|
||||
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
RiverSegment &segment = mSegments[i];
|
||||
const RiverSlice *slice = segment.slice0;
|
||||
const RiverSlice *nextSlice = segment.slice1;
|
||||
const RiverSlice *nextSlice = segment.slice1;
|
||||
|
||||
// Calculate the size of divisions in the forward direction ( p00 -> p01 )
|
||||
F32 segLength = (nextSlice->p1 - slice->p1).len();
|
||||
// Calculate the size of divisions in the forward direction ( p00 -> p01 )
|
||||
F32 segLength = (nextSlice->p1 - slice->p1).len();
|
||||
|
||||
// A division count of one is actually NO subdivision,
|
||||
// the segment corners are the only verts in this segment.
|
||||
U32 numRows = 1;
|
||||
// A division count of one is actually NO subdivision,
|
||||
// the segment corners are the only verts in this segment.
|
||||
U32 numRows = 1;
|
||||
|
||||
if ( segLength > 0.0f )
|
||||
numRows = mCeil( segLength / mMaxDivisionSize );
|
||||
|
|
@ -1693,33 +1693,33 @@ void River::_generateVerts()
|
|||
// column data member we initialize all segments in the river to
|
||||
// the same (River::mColumnCount)
|
||||
|
||||
// Calculate the size of divisions in the right direction ( p00 -> p10 )
|
||||
// F32 segWidth = ( ( p11 - p01 ).len() + ( p10 - p00 ).len() ) * 0.5f;
|
||||
// Calculate the size of divisions in the right direction ( p00 -> p10 )
|
||||
// F32 segWidth = ( ( p11 - p01 ).len() + ( p10 - p00 ).len() ) * 0.5f;
|
||||
|
||||
// U32 numColumns = 5;
|
||||
//F32 columnSize = segWidth / numColumns;
|
||||
// U32 numColumns = 5;
|
||||
//F32 columnSize = segWidth / numColumns;
|
||||
|
||||
//while ( columnSize > mMaxDivisionSize )
|
||||
//{
|
||||
// numColumns++;
|
||||
// columnSize = segWidth / numColumns;
|
||||
//}
|
||||
|
||||
//while ( columnSize > mMaxDivisionSize )
|
||||
//{
|
||||
// numColumns++;
|
||||
// columnSize = segWidth / numColumns;
|
||||
//}
|
||||
|
||||
// Save the calculated numb of columns / rows for this segment.
|
||||
segment.columns = mColumnCount;
|
||||
segment.rows = numRows;
|
||||
|
||||
|
||||
// Save the corresponding number of verts/prims
|
||||
segment.numVerts = ( 1 + mColumnCount ) * ( 1 + numRows );
|
||||
segment.numTriangles = mColumnCount * numRows * 2;
|
||||
|
||||
mHighVertCount += segment.numVerts;
|
||||
mHighTriangleCount += segment.numTriangles;
|
||||
}
|
||||
mHighVertCount += segment.numVerts;
|
||||
mHighTriangleCount += segment.numTriangles;
|
||||
}
|
||||
|
||||
// Number of low detail verts/prims.
|
||||
mLowVertCount = mSlices.size() * 2;
|
||||
mLowTriangleCount = mSegments.size() * 2;
|
||||
mLowVertCount = mSlices.size() * 2;
|
||||
mLowTriangleCount = mSegments.size() * 2;
|
||||
|
||||
// Allocate the low detail VertexBuffer,
|
||||
// this will stay in memory and will never need to change.
|
||||
|
|
@ -1728,8 +1728,8 @@ void River::_generateVerts()
|
|||
GFXWaterVertex *lowVertPtr = mVB_low.lock();
|
||||
U32 vertCounter = 0;
|
||||
|
||||
// The texCoord.y value start/end for a segment
|
||||
// as we loop through them.
|
||||
// The texCoord.y value start/end for a segment
|
||||
// as we loop through them.
|
||||
F32 textCoordV = 0;
|
||||
|
||||
//
|
||||
|
|
@ -1760,7 +1760,7 @@ void River::_generateVerts()
|
|||
{
|
||||
// Increment the textCoordV for the next slice.
|
||||
F32 segLen = ( mSlices[i+1].p1 - slice.p1 ).len();
|
||||
textCoordV += segLen;
|
||||
textCoordV += segLen;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1771,8 +1771,8 @@ void River::_generateVerts()
|
|||
|
||||
//
|
||||
// Create the low-detail prim buffer(s)
|
||||
//
|
||||
mPB_low.set( GFX, mLowTriangleCount * 3, mLowTriangleCount, GFXBufferTypeStatic );
|
||||
//
|
||||
mPB_low.set( GFX, mLowTriangleCount * 3, mLowTriangleCount, GFXBufferTypeStatic );
|
||||
|
||||
U16 *lowIdxBuff;
|
||||
mPB_low.lock(&lowIdxBuff);
|
||||
|
|
@ -1784,13 +1784,13 @@ void River::_generateVerts()
|
|||
U32 offset = 0;
|
||||
|
||||
// Fill the low-detail PrimitiveBuffer
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
for ( U32 i = 0; i < mSegments.size(); i++ )
|
||||
{
|
||||
//const RiverSegment &segment = mSegments[i];
|
||||
|
||||
|
||||
// Two triangles formed by the corner points of this segment
|
||||
// into the the low detail primitive buffer.
|
||||
p00 = offset;
|
||||
p00 = offset;
|
||||
p01 = p00 + 2;
|
||||
p11 = p01 + 1;
|
||||
p10 = p00 + 1;
|
||||
|
|
@ -2158,8 +2158,8 @@ void River::_makeRenderBatches( const Point3F &cameraPos )
|
|||
|
||||
F32 dist = getMin( dist0, dist1 );
|
||||
highDetail = ( dist < lodDistSquared );
|
||||
if ( highDetail && lastDetail == 0 ||
|
||||
!highDetail && lastDetail == 1 )
|
||||
if ( (highDetail && lastDetail == 0) ||
|
||||
(!highDetail && lastDetail == 1) )
|
||||
{
|
||||
// We hit a segment with a different lod than the previous.
|
||||
// Save what we have so far...
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue