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:
Duion 2017-03-23 20:36:21 +01:00
commit aff033dd0d
1003 changed files with 53039 additions and 82707 deletions

View file

@ -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")

View file

@ -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)
{

View file

@ -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

View file

@ -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;

View file

@ -153,7 +153,7 @@ public:
{
// Set Defaults.
mSeed = 1376312589;
mShapeFile = StringTable->insert("");
mShapeFile = StringTable->EmptyString();
mShapeCount = 10;
mShapeRetries = 100;
mInnerRadiusX = 0;

View file

@ -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 );
}

View file

@ -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);

View file

@ -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"

View file

@ -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;

View file

@ -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 );
}
//--------------------------------------------------------------------------

View file

@ -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"

View file

@ -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();

View file

@ -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");

View file

@ -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_

View file

@ -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;

View file

@ -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);

View file

@ -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);
}
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 );
}

View file

@ -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

View file

@ -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.

View file

@ -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;
};

View file

@ -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_

View file

@ -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 );
}

View file

@ -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_

View file

@ -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_

View file

@ -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 ) );
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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_

View file

@ -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]) );
}

View file

@ -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_

View file

@ -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 );
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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!" );
}
}

View file

@ -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_

View file

@ -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 );
}

View file

@ -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_

View file

@ -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

View file

@ -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_

View file

@ -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();
}
}

View file

@ -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_

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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();
};

View file

@ -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");
}
//--------------------------------------------------------------------------

View file

@ -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 );
}

View file

@ -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])

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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))

View file

@ -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();
}

View file

@ -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"

View file

@ -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];
}

View file

@ -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;

View file

@ -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();

View file

@ -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;
}

View file

@ -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 */

View file

@ -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 );

View file

@ -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();
};

View file

@ -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

View file

@ -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 )

View file

@ -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*);

View file

@ -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() {}

View file

@ -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

View file

@ -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 ) );

View file

@ -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();
}

View file

@ -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))
{

View file

@ -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]);
}

View file

@ -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();
}

View file

@ -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 );
}

View file

@ -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);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

View file

@ -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

View file

@ -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]);
}
}
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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;}

View file

@ -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;
}

View file

@ -42,7 +42,7 @@ protected:
/// The captured object's name.
String mObjectName;
bool mIsDatablock;
bool mIsDatablock;
public:

View file

@ -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");
//-----------------------------------------------------------------------------

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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");
}

View file

@ -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)

View file

@ -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
{

View file

@ -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;

View file

@ -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);

View file

@ -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