Large diffs are not rendered by default.

@@ -27,11 +27,40 @@
#include "T3D/player.h"
#endif

// start ds
#ifndef _NODEINTERPOLATOR_H_
#include "T3D/nodeInterpolator.h"
#endif
// end jc

// start jc
/*
class AIPlayerData : public PlayerData {
typedef PlayerData Parent;
public:
AIPlayerData(); // CTor
// maximum yaw rate
//F32 maxTurnRate;
// standard datablock stuff
DECLARE_CONOBJECT(AIPlayerData);
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
};
*/
// end jc

class AIPlayer : public Player {

typedef Player Parent;

// start jc
// AIPlayerData *mDataBlock; // our new datablock type
// end jc

public:
enum MoveState {
ModeStop, // AI has stopped moving.
@@ -42,7 +71,9 @@ class AIPlayer : public Player {

private:
MoveState mMoveState;
F32 mMoveSpeed;
// start jc - moved to player for variable motion.
// F32 mMoveSpeed;
// end jc
F32 mMoveTolerance; // Distance from destination before we stop
Point3F mMoveDestination; // Destination for movement
Point3F mLastLocation; // For stuck check
@@ -56,6 +87,24 @@ class AIPlayer : public Player {
Point3F mAimLocation; // Point to look at
bool mTargetInLOS; // Is target object visible?

// start ds
// Added by Brendan Ledwich 2005-11-9
// NodeInterpolator *mInterpolator;
Point3F mAvoidPoint;
F32 mWidth;
F32 mTurnDirection;
F32 mTurnRateMod;
// F32 mMaxTurnAngle;

ShapeBase * mFollowObject;
S32 mFollowNodeIndex;
//S32 mFollowSlotIndex;
//Point3F mCollisionPoint;
//Point3F mMoveDestination; // Destination for movement
// end ds



Point3F mAimOffset;

// Utility Methods
@@ -67,6 +116,10 @@ class AIPlayer : public Player {
AIPlayer();
~AIPlayer();

// start jc
bool onNewDataBlock(GameBaseData* dptr, bool reload); // new datablock assigned
// end jc

static void initPersistFields();

bool onAdd();
@@ -82,13 +135,61 @@ class AIPlayer : public Player {
void clearAim();

// Movement sets/gets
void setMoveSpeed( const F32 speed );
F32 getMoveSpeed() const { return mMoveSpeed; }
// start jc - moved to player for variable motion.
// void setMoveSpeed( const F32 speed );
// F32 getMoveSpeed() const { return mMoveSpeed; }
// end jc
void setMoveTolerance( const F32 tolerance );
F32 getMoveTolerance() const { return mMoveTolerance; }
void setMoveDestination( const Point3F &location, bool slowdown );
Point3F getMoveDestination() const { return mMoveDestination; }
void stopMove();

// start jc
// Point3F getMoveDestination() const { return mMoveDestination; }

Point3F getMoveDestination() const
{
if (mFollowObject)
if(mFollowNodeIndex != -1)
{
MatrixF mat;
mFollowObject->getNodeWorldTransform(mFollowNodeIndex, &mat);
return mat.getPosition();
}
else
return mFollowObject->getPosition();
else
return mMoveDestination;
// return (mInterpolator->getNumPoints())?*(mInterpolator->getPoint(mInterpolator->getNumPoints()-1)):Point3F(0,0,0);
}
void changePose(S32 poseNumber);

F32 getVectorAngle(const Point3F &v1, const Point3F &v2, U32 discardDimension);
Point3F rotateVec(const Point3F &v,F32 angle, U32 axis);
bool findClosestObjectInFront(F32 range, Collision *closest, U32 mask = 0);

void setMoveDestination( const Point3F &location, const Point3F &approachVector, bool slowdown = false );
void setFollowObject( ShapeBase *targetObject, bool slowdown );
void setFollowObjectNode( ShapeBase *targetObject, S32 nodeIndex = -1, bool slowdown = false );
void clearFollowObject();

virtual void updateMoveDestination(const Point3F &location, const Point3F &forwardVector, const bool is3D);

F32 getTurnRateMod() { return mTurnRateMod; }
void setTurnRateMod(F32 mod) { mTurnRateMod = mod; }

void updateMove(const Move* move)
{
// todo: see if this works
if (!getControllingClient() && isGhost())
return;

if(mFlying)
updateMoveFlight(move);
else updateMoveOriginal(move);
}
// end jc

void stopMove();
};

#endif
@@ -289,6 +289,10 @@ Camera::Camera()
mCurrentEditOrbitDist = 2.0;

mLocked = false;

// start jc
mEarOffset.identity();
// end jc
}

//----------------------------------------------------------------------------
@@ -352,6 +356,23 @@ void Camera::getCameraTransform(F32* pos, MatrixF* mat)
mat->mul( gCamFXMgr.getTrans() );
}

// start jc
void Camera::getCameraEarTransform(F32* pos, MatrixF* mat)
{
// The camera doesn't support a third person mode,
// so we want to override the default ShapeBase behavior.
ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
obj->getCameraEarTransform(pos, mat);
else
getRenderEyeTransform(mat);

// Apply Camera FX.
mat->mul( mEarOffset );
mat->mul( gCamFXMgr.getTrans() );
}
// end jc

//----------------------------------------------------------------------------

F32 Camera::getCameraFov()
@@ -1000,6 +1021,9 @@ U32 Camera::packUpdate(NetConnection *con, U32 mask, BitStream *bstream)
{
bstream->writeFlag(mLocked);
mathWrite(*bstream, mOffset);
// start jc
mathWrite(*bstream, mEarOffset);
// end jc
}

if(bstream->writeFlag(mask & NewtonCameraMask))
@@ -1076,6 +1100,9 @@ void Camera::unpackUpdate(NetConnection *con, BitStream *bstream)
{
mLocked = bstream->readFlag();
mathRead(*bstream, &mOffset);
// start jc
mathRead(*bstream, &mEarOffset);
// end jc
}

// NewtonCameraMask
@@ -1170,6 +1197,12 @@ void Camera::initPersistFields()
"Speed multiplier when triggering the brake (Newton mode only). Default value is 2." );
endGroup( "Camera: Newton Mode" );

// start jc
addGroup( "Audio" );
addField( "earOffset", TypeMatrixPosition, Offset( mEarOffset, Camera ), "@brief " );
endGroup( "Audio" );
// end jc

Parent::initPersistFields();
}

@@ -1691,6 +1724,21 @@ DefineEngineMethod( Camera, setOffset, void, (Point3F offset), ,

//-----------------------------------------------------------------------------



// start jc
DefineEngineMethod( Camera, setEarOffset, void, (Point3F offset), ,
"Set the camera's ear offset.\n\n"
".\n"
"@param .")
{
object->setEarOffset(offset);
}
// end jc


//-----------------------------------------------------------------------------

DefineEngineMethod( Camera, setOrbitMode, void, (GameBase* orbitObject, TransformF orbitPoint, F32 minDistance, F32 maxDistance,
F32 initDistance, bool ownClientObj, Point3F offset, bool locked), (false, Point3F(0.0f, 0.0f, 0.0f), false),
"Set the camera to orbit around the given object, or if none is given, around the given point.\n\n"
@@ -133,6 +133,9 @@ class Camera: public ShapeBase
/// @}

bool mLocked;
// start jc
MatrixF mEarOffset;
// end jc

CameraMotionMode mMode;

@@ -170,6 +173,10 @@ class Camera: public ShapeBase
Point3F getOffset() { return mOffset; };
void lookAt( const Point3F& pos);
void setOffset( const Point3F& offset) { if( mOffset != offset ) mOffset = offset; setMaskBits( UpdateMask ); }
// start jc
void setEarOffset( const Point3F& offset) { if( mEarOffset.getPosition() != offset ) mEarOffset.setPosition(offset); setMaskBits( UpdateMask ); }

// end jc
void setFlyMode();
void setOrbitMode( GameBase *obj, const Point3F& pos, const Point3F& rot, const Point3F& offset,
F32 minDist, F32 maxDist, F32 curDist, bool ownClientObject, bool locked = false );
@@ -213,6 +220,13 @@ class Camera: public ShapeBase
void autoFitRadius( F32 radius );

/// @}
// start jc
/// Returns the transform which can be used to convert object space
/// to world space
void getCameraEarTransform(F32* pos, MatrixF* mat);
// virtual MatrixF getEarTransform() { return mEarOffset.isIdentity() ? getTransform() : MatrixF().mul(mObjToWorld,mEarOffset); }
// end jc


// ShapeBase.
static void initPersistFields();
@@ -55,9 +55,16 @@ class GuiShapeNameHud : public GuiControl {
F32 mDistanceFade;
bool mShowFrame;
bool mShowFill;
// start pg
bool mMultiLine;
bool mHideFurtherBack;
// end pg

protected:
void drawName( Point2I offset, const char *buf, F32 opacity);
// start pg
void drawNameMultiLine( Point2I offset, const char *buf, F32 opacity);
// end pg

public:
GuiShapeNameHud();
@@ -111,6 +118,10 @@ GuiShapeNameHud::GuiShapeNameHud()
mShowFrame = mShowFill = true;
mVerticalOffset = 0.5f;
mDistanceFade = 0.1f;
// start pg
mMultiLine = false;
mHideFurtherBack = true;
// end pg
}

void GuiShapeNameHud::initPersistFields()
@@ -126,6 +137,12 @@ void GuiShapeNameHud::initPersistFields()
addField( "showFrame", TypeBool, Offset( mShowFrame, GuiShapeNameHud ), "If true, we draw the frame of the control." );
addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, GuiShapeNameHud ), "Amount to vertically offset the control in relation to the ShapeBase object in focus." );
addField( "distanceFade", TypeF32, Offset( mDistanceFade, GuiShapeNameHud ), "Visibility distance (how far the player must be from the ShapeBase object in focus) for this control to render." );

// start pg
addField( "multiLine", TypeBool, Offset( mMultiLine, GuiShapeNameHud ), "If true, draw info over multiple lines." );
addField( "hideFurtherBack", TypeBool, Offset( mHideFurtherBack, GuiShapeNameHud ), "If true, dont hide text if parent object hidden" );
// end pg

endGroup("Misc");
Parent::initPersistFields();
}
@@ -223,19 +240,25 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
if (dot < camFov)
continue;

// Test to see if it's behind something, and we want to
// ignore anything it's mounted on when we run the LOS.
RayInfo info;
shape->disableCollision();
SceneObject *mount = shape->getObjectMount();
if (mount)
mount->disableCollision();
bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info);
shape->enableCollision();
if (mount)
mount->enableCollision();
if (!los)
continue;
// start pg
if(mHideFurtherBack){
// end pg
// Test to see if it's behind something, and we want to
// ignore anything it's mounted on when we run the LOS.
RayInfo info;
shape->disableCollision();
SceneObject *mount = shape->getObjectMount();
if (mount)
mount->disableCollision();
bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info);
shape->enableCollision();
if (mount)
mount->enableCollision();
if (!los)
continue;
// start pg
}
// end pg

// Project the shape pos into screen space and calculate
// the distance opacity used to fade the labels into the
@@ -248,10 +271,18 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance);

// Render the shape's name
// start pg
if(mMultiLine){
drawNameMultiLine(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
}else{
// end pg
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
}
}
}
// start pg
}
// end pg

// Restore control object collision
control->enableCollision();
@@ -282,6 +313,64 @@ void GuiShapeNameHud::drawName(Point2I offset, const char *name, F32 opacity)
mTextColor.alpha = opacity;
GFX->getDrawUtil()->setBitmapModulation(mTextColor);
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, name);


GFX->getDrawUtil()->clearBitmapModulation();
}

// start pg

void GuiShapeNameHud::drawNameMultiLine(Point2I offset, const char *name, F32 opacity)
{
int nLine = 0;
const char *startLine = name;
int nChar = 0;
int width=0;
while(true){
char c = startLine[nChar];
if(c=='\n' || c==0 ){
int w = mProfile->mFont->getStrNWidth( (const UTF8 *)startLine, nChar );
width = getMax(w,width);
nLine++;
if(c==0){
break;
}else{
startLine = &startLine[nChar+1];
nChar=0;
}
}else{
nChar++;
}
}
int height = nLine*mProfile->mFont->getHeight();


offset.x -= (width/2);
// offset.y -= height;

// Deal with opacity and draw.
mTextColor.alpha = opacity;
GFX->getDrawUtil()->setBitmapModulation(mTextColor);
startLine = name;
nChar = 0;
while(true){
char c = startLine[nChar];
if(c=='\n' || c==0 ){
int w = mProfile->mFont->getStrNWidth( (const UTF8 *)startLine, nChar );
Point2I plot;
plot.x = offset.x + (width-w)/2;
plot.y = offset.y;
GFX->getDrawUtil()->drawTextN(mProfile->mFont, plot, startLine,nChar);
offset.y += mProfile->mFont->getHeight();
if(c==0){
break;
}else{
startLine = &startLine[nChar+1];
nChar=0;
}
}else{
nChar++;
}
}
GFX->getDrawUtil()->clearBitmapModulation();
}
@@ -36,6 +36,12 @@
#include "T3D/gameBase/gameProcess.h"
#include "lighting/lightInfo.h"
#include "console/engineAPI.h"
// start jc
#include "math/mathIO.h"
#include "materials/materialManager.h"
#include "materials/matInstance.h"
#include "materials/sceneData.h"
// end jc

#if defined(TORQUE_OS_XENON)
# include "gfx/D3D9/360/gfx360MemVertexBuffer.h"
@@ -150,6 +156,10 @@ ParticleEmitterData::ParticleEmitterData()

alignParticles = false;
alignDirection = Point3F(0.0f, 1.0f, 0.0f);

// start jc
overrideBounds = Box3F(0,0,0,0,0,0);
// end jc
}


@@ -277,6 +287,11 @@ void ParticleEmitterData::initPersistFields()
addField( "renderReflection", TYPEID< bool >(), Offset(renderReflection, ParticleEmitterData),
"Controls whether particles are rendered onto reflective surfaces like water." );

// start jc
addField( "overrideBounds", TypeBox3F, Offset(overrideBounds, ParticleEmitterData),
"overrideBounds flag; when false the shape will not be reflected." );
// end jc

//@}

endGroup( "ParticleEmitterData" );
@@ -302,7 +317,10 @@ void ParticleEmitterData::packData(BitStream* stream)
{
Parent::packData(stream);

stream->writeInt(ejectionPeriodMS, 10);
// start jc
// stream->writeInt(ejectionPeriodMS, 10);
stream->writeInt(ejectionPeriodMS, 16);
// end jc
stream->writeInt(periodVarianceMS, 10);
stream->writeInt((S32)(ejectionVelocity * 100), 16);
stream->writeInt((S32)(velocityVariance * 100), 14);
@@ -343,6 +361,10 @@ void ParticleEmitterData::packData(BitStream* stream)
stream->writeFlag(highResOnly);
stream->writeFlag(renderReflection);
stream->writeInt( blendStyle, 4 );

// start jc
mathWrite(*stream, overrideBounds );
// end jc
}

//-----------------------------------------------------------------------------
@@ -352,7 +374,10 @@ void ParticleEmitterData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);

ejectionPeriodMS = stream->readInt(10);
// start jc
// ejectionPeriodMS = stream->readInt(10);
ejectionPeriodMS = stream->readInt(16);
// end jc
periodVarianceMS = stream->readInt(10);
ejectionVelocity = stream->readInt(16) / 100.0f;
velocityVariance = stream->readInt(14) / 100.0f;
@@ -402,6 +427,10 @@ void ParticleEmitterData::unpackData(BitStream* stream)
highResOnly = stream->readFlag();
renderReflection = stream->readFlag();
blendStyle = stream->readInt( 4 );

// start jc
mathRead(*stream, &overrideBounds);
// end jc
}

//-----------------------------------------------------------------------------
@@ -815,6 +844,10 @@ bool ParticleEmitter::onNewDataBlock( GameBaseData *dptr, bool reload )
part_list_head.next = NULL;
n_parts = 0;
}
// start jc
if(!mDataBlock->overrideBounds.isEmpty())
mObjBox = mDataBlock->overrideBounds;
// end jc

scriptOnNewDataBlock();
return true;
@@ -878,7 +911,12 @@ void ParticleEmitter::prepRenderImage(SceneRenderState* state)
ri->primBuff = &getDataBlock()->primBuff;
ri->translucentSort = true;
ri->type = RenderPassManager::RIT_Particle;
ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint( camPos );
// start jc
// ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint( camPos );

// todo: find out why 2 works? I through this in as a guess but now I have to move on.
ri->sortDistSq = ((getRenderWorldBox().getCenter() - camPos )/2).lenSquared();
// end jc

// Draw the system offscreen unless the highResOnly flag is set on the datablock
ri->systemState = ( getDataBlock()->highResOnly ? PSS_AwaitingHighResDraw : PSS_AwaitingOffscreenDraw );
@@ -1207,6 +1245,15 @@ void ParticleEmitter::emitParticles(const Point3F& rCenter,
//-----------------------------------------------------------------------------
void ParticleEmitter::updateBBox()
{
// start jc
if(!mDataBlock->overrideBounds.isEmpty())
{
mObjBox = mDataBlock->overrideBounds;
}
else
{
// end jc

Point3F minPt(1e10, 1e10, 1e10);
Point3F maxPt(-1e10, -1e10, -1e10);

@@ -1218,6 +1265,9 @@ void ParticleEmitter::updateBBox()
}

mObjBox = Box3F(minPt, maxPt);
// start jc
}
// end jc
MatrixF temp = getTransform();
setTransform(temp);

@@ -2004,3 +2054,34 @@ DefineEngineMethod(ParticleEmitterData, reload, void,(),,
{
object->reload();
}

// start jc
DefineEngineMethod(ParticleEmitterData, onAdd, bool,(),,
"")
{
return object->onAdd();
}

DefineEngineMethod(ParticleEmitter, emitParticles, void,(Point3F point, bool useLastPoint,
Point3F emitAxis, Point3F emitVelocity, U32 dt),,
"")
{
object->emitParticles(point, useLastPoint,
emitAxis, emitVelocity, (U32)(dt * 1000.0f));
}
DefineEngineMethod(ParticleEmitter, deleteWhenEmpty, void,(),,
"")
{
object->deleteWhenEmpty();
}
DefineEngineMethod(ParticleEmitter, onNewDataBlock, void,(GameBaseData *dptr, bool reload),,
"")
{
object->onNewDataBlock( dptr, reload );
}
DefineEngineMethod(ParticleEmitter, onAdd, bool,(),,
"")
{
return object->onAddClient();
}
// end jc
@@ -82,6 +82,9 @@ class ParticleEmitterData : public GameBaseData

F32 softnessDistance; ///< For soft particles, the distance (in meters) where particles will be faded
///< based on the difference in depth between the particle and the scene geometry.
// start jc
Box3F overrideBounds;
// end jc

/// A scalar value used to influence the effect
/// of the ambient color on the particle.
@@ -157,6 +160,9 @@ class ParticleEmitter : public GameBase
/// By default, a particle renderer will wait for it's owner to delete it. When this
/// is turned on, it will delete itself as soon as it's particle count drops to zero.
void deleteWhenEmpty();
// start jc
bool onAddClient() { return this->onAdd(); }
// end jc

/// @name Particle Emission
/// Main interface for creating particles. The emitter does _not_ track changes
@@ -215,8 +215,21 @@ bool ParticleEmitterNode::onAdd()
setMaskBits( StateMask | EmitterDBMask );
}

// start jc
// mObjBox.minExtents.set(-0.5, -0.5, -0.5);
// mObjBox.maxExtents.set( 0.5, 0.5, 0.5);

if(mEmitterDatablock && !mEmitterDatablock->overrideBounds.isEmpty())
{
mObjBox = mEmitterDatablock->overrideBounds;
}
else
{
mObjBox.minExtents.set(-0.5, -0.5, -0.5);
mObjBox.maxExtents.set( 0.5, 0.5, 0.5);
}
// end jc

resetWorldBox();
addToScene();

@@ -393,6 +406,13 @@ void ParticleEmitterNode::setEmitterDataBlock(ParticleEmitterData* data)

mEmitterDatablock = data;
}
// start jc
void ParticleEmitterNode::setObjectBox(Box3F objBox)
{
mObjBox = objBox;
resetWorldBox();
}
// end jc

DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (0),
"Assigns the datablock for this emitter node.\n"
@@ -417,3 +437,33 @@ DefineEngineMethod(ParticleEmitterNode, setActive, void, (bool active),,
{
object->setActive( active );
}
// start jc
DefineEngineMethod(ParticleEmitterNode, onAdd, bool,(),,
"")
{
return object->onAdd();
}
DefineEngineMethod( ParticleEmitterNode, setObjectBox, void, (Box3F objBox),,
"Get the model filename used by this shape.\n"
"@return the shape filename\n\n" )
{
object->setObjectBox(objBox);
}
// end jc
// start jc
IMPLEMENT_CO_NETOBJECT_V1(ParticleEmitterNodeClient);
ParticleEmitterNodeClient::ParticleEmitterNodeClient()
{
mNetFlags.clear(Ghostable | ScopeAlways);
mNetFlags.set(IsGhost);
}
ParticleEmitterNodeClient::~ParticleEmitterNodeClient()
{
}
// end jc
@@ -77,8 +77,13 @@ class ParticleEmitterNode : public GameBase
private:
ParticleEmitterNodeData* mDataBlock;

protected:
// start jc
// protected:
// bool onAdd();
public:
bool onAdd();
protected:
// end jc
void onRemove();
bool onNewDataBlock( GameBaseData *dptr, bool reload );
void inspectPostApply();
@@ -112,7 +117,27 @@ class ParticleEmitterNode : public GameBase
inline void setActive( bool active ) { mActive = active; setMaskBits( StateMask ); };

void setEmitterDataBlock(ParticleEmitterData* data);
// start jc
void setObjectBox(Box3F objBox);
// end jc
};

// start jc
class ParticleEmitterNodeClient : public ParticleEmitterNode
{
typedef ParticleEmitterNode Parent;

protected:


public:
ParticleEmitterNodeClient();
~ParticleEmitterNodeClient();

DECLARE_CONOBJECT(ParticleEmitterNodeClient);

};
// end jc

#endif // _H_PARTICLEEMISSIONDUMMY

@@ -370,6 +370,9 @@ F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 u
{
TORQUE_UNUSED(updateMask);

// start jc
/*
// Calculate a priority used to decide if this object
// will be updated on the client. All the weights
// are calculated 0 -> 1 Then weighted together at the
@@ -437,6 +440,83 @@ F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 u
wVelocity * sUpVelocity +
wSkips * sUpSkips +
wInterest * sUpInterest;
*/

// Calculate a priority used to decide if this object
// will be updated on the client. All the weights
// are calculated 0 -> 1 Then weighted together at the
// end to produce a priority.
Point3F pos;
getWorldBox().getCenter(&pos);
pos -= camInfo->pos;
F32 dist = pos.len();
if (dist == 0.0f) dist = 0.001f;
pos *= 1.0f / dist;

// Weight based on linear distance, the basic stuff.
F32 wDistance = (dist < camInfo->visibleDistance)?
1.0f - (dist / camInfo->visibleDistance): 0.0f;

// Weight by field of view, objects directly in front
// will be weighted 1, objects behind will be 0
F32 dot = mDot(pos,camInfo->orientation);
// start jc - objects near the edge of screen need more priority to stay smooth
// bool inFov = dot > camInfo->cosFov;
bool inFov = dot > camInfo->cosFov*1.5f;

F32 wFov = inFov? 1.0f: 0;

// Weight by linear velocity parallel to the viewing plane
// (if it's the field of view, 0 if it's not).
F32 wVelocity = 0.0f;
if (inFov)
{
Point3F vec;
mCross(camInfo->orientation,getVelocity(),&vec);
wVelocity = (vec.len() * camInfo->fov) /
(camInfo->fov * camInfo->visibleDistance);
if (wVelocity > 1.0f)
wVelocity = 1.0f;
}

// Weight by interest.
F32 wInterest;

// if (getTypeMask() & PlayerObjectType)
if (getTypeMask() & (PlayerObjectType || VehicleObjectType || InputEventObjectType))

wInterest = 0.75f;
else if (getTypeMask() & ProjectileObjectType)
{
// Projectiles are more interesting if they
// are heading for us.
wInterest = 0.30f;
F32 dot = -mDot(pos,getVelocity());
if (dot > 0.0f)
wInterest += 0.20 * dot;
}
else
{
if (getTypeMask() & ItemObjectType)
wInterest = 0.25f;
else
// Everything else is less interesting.
wInterest = 0.0f;
}

// Weight by updateSkips
F32 wSkips = updateSkips * 0.5;

// Calculate final priority, should total to about 1.0f
//
return
wFov * sUpFov +
wDistance * sUpDistance +
wVelocity * sUpVelocity +
wSkips * sUpSkips +
wInterest * sUpInterest;
// end jc

}

//----------------------------------------------------------------------------
@@ -570,8 +650,26 @@ void GameBase::unpackUpdate(NetConnection *con, BitStream *stream)
if ( stream->readFlag() )
mOrderGUID = stream->readInt( 16 );

// start jc
//*******************************************
bool good = true;
if ( !Sim::findObject( id, dptr ) ){
good = false;
Con::printf("Failed to find object %d",id);
}
if ( !setDataBlock( dptr ) ){
good = false;
Con::printf("Failed to set data block");
}
if(!good){
con->setLastError( "Invalid packet GameBase::unpackUpdate()" );
}

/*
if ( !Sim::findObject( id, dptr ) || !setDataBlock( dptr ) )
con->setLastError( "Invalid packet GameBase::unpackUpdate()" );
*/
// end jc
}

#ifdef TORQUE_DEBUG_NET_MOVES
@@ -217,7 +217,14 @@ class GameBase : public SceneObject
public:

GameBase();
~GameBase();
// start jc
// ~GameBase();
// The code is incorrect and leads to memory leak. At the moment of deleting the object only
// the destructor in the 'GameBase' class is called. To call the 'Son' class' destructor you
// should make the destructor virtual.
virtual ~GameBase();
// end jc


enum GameBaseMasks {
DataBlockMask = Parent::NextFreeMask << 0,
@@ -414,6 +421,9 @@ class GameBase : public SceneObject

// Not implemented here, but should return the Camera to world transformation matrix
virtual void getCameraTransform (F32 *pos, MatrixF *mat ) { *mat = MatrixF::Identity; }
// start jc
virtual void getCameraEarTransform (F32 *pos, MatrixF *mat ) { *mat = MatrixF::Identity; }
// end jc

/// Returns the water object we are colliding with, it is up to derived
/// classes to actually set this object.
@@ -202,6 +202,10 @@ GameConnection::GameConnection()
mCameraFov = 90.f;
mUpdateCameraFov = false;

// start jc
mCameraFrustumOffset = Point4F::Zero;
// end jc

mAIControlled = false;

mDisconnectReason[0] = 0;
@@ -636,6 +640,57 @@ bool GameConnection::getControlCameraTransform(F32 dt, MatrixF* mat)
return true;
}

// start jc
bool GameConnection::getControlCameraEarTransform(F32 dt, MatrixF* mat)
{
GameBase* obj = getCameraObject();
if(!obj)
return false;

GameBase* cObj = obj;
while((cObj = cObj->getControlObject()) != 0)
{
if(cObj->useObjsEyePoint())
obj = cObj;
}

if (dt)
{
if (mFirstPerson || obj->onlyFirstPerson())
{
if (mCameraPos > 0)
if ((mCameraPos -= mCameraSpeed * dt) <= 0)
mCameraPos = 0;
}
else
{
if (mCameraPos < 1)
if ((mCameraPos += mCameraSpeed * dt) > 1)
mCameraPos = 1;
}
}

if (!sChaseQueueSize || mFirstPerson || obj->onlyFirstPerson())
obj->getCameraEarTransform(&mCameraPos,mat);
else
{
MatrixF& hm = sChaseQueue[sChaseQueueHead];
MatrixF& tm = sChaseQueue[sChaseQueueTail];
obj->getCameraEarTransform(&mCameraPos,&hm);
*mat = tm;
if (dt)
{
if ((sChaseQueueHead += 1) >= sChaseQueueSize)
sChaseQueueHead = 0;
if (sChaseQueueHead == sChaseQueueTail)
if ((sChaseQueueTail += 1) >= sChaseQueueSize)
sChaseQueueTail = 0;
}
}
return true;
}
// end jc

bool GameConnection::getControlCameraDefaultFov(F32 * fov)
{
//find the last control object in the chain (client->player->turret->whatever...)
@@ -673,6 +728,13 @@ bool GameConnection::getControlCameraFov(F32 * fov)

return(false);
}
// start jc
bool GameConnection::getControlCameraFrustumOffset(Point4F *offset)
{
*offset = mCameraFrustumOffset;
return true;
}
// end jc

bool GameConnection::isValidControlCameraFov(F32 fov)
{
@@ -722,6 +784,25 @@ bool GameConnection::getControlCameraVelocity(Point3F *vel)
}
return false;
}
// start jc
bool GameConnection::setControlCameraFrustumOffset(Point4F offset)
{
//find the last control object in the chain (client->player->turret->whatever...)
GameBase *obj = getCameraObject();
GameBase *cObj = NULL;
while (obj)
{
cObj = obj;
obj = obj->getControlObject();
}
if (cObj)
{
mCameraFrustumOffset = offset;
return(true);
}
return(false);
}
// end jc

bool GameConnection::isControlObjectRotDampedCamera()
{
@@ -1351,7 +1432,19 @@ void GameConnection::play3D(SFXProfile* profile, const MatrixF *transform)
// of the control object.
Point3F ear,pos;
transform->getColumn(3,&pos);
mControlObject->getTransform().getColumn(3,&ear);
// start jc
// mControlObject->getTransform().getColumn(3,&ear);
// mControlObject->getEarTransform().getColumn(3,&ear);

static MatrixF mat;
static F32 state = 0;
if (!this->isFirstPerson())
state = 1.0f;

mControlObject->getCameraEarTransform(&state, &mat);
mat.getColumn(3,&ear);
// end jc

if ((ear - pos).len() < profile->getDescription()->mMaxDistance)
postNetEvent(new Sim3DAudioEvent(profile,transform));
}
@@ -86,6 +86,9 @@ class GameConnection : public NetConnection
F32 mCameraFov; ///< Current camera fov (in degrees).
F32 mCameraPos; ///< Current camera pos (0-1).
F32 mCameraSpeed; ///< Camera in/out speed.
// start jc
Point4F mCameraFrustumOffset;
// end jc
/// @}

public:
@@ -258,6 +261,14 @@ class GameConnection : public NetConnection
bool setControlCameraFov(F32 fov);
bool isValidControlCameraFov(F32 fov);

// start jc
bool setControlCameraFrustumOffset(Point4F offset);
bool getControlCameraFrustumOffset(Point4F *offset);

bool getControlCameraEarTransform(F32 dt, MatrixF* mat);

// end jc

// Used by editor
bool isControlObjectRotDampedCamera();

@@ -28,7 +28,10 @@
#endif

enum MoveConstants {
MaxTriggerKeys = 6,
// start jc
// MaxTriggerKeys = 6,
MaxTriggerKeys = 100,
// end jc
MaxMoveQueueSize = 45,
};

@@ -36,6 +36,9 @@
#include "T3D/gameBase/gameConnection.h"
#include "T3D/gameBase/std/stdMoveList.h"
#include "T3D/fx/cameraFXMgr.h"
// start jc
#include "T3D/aiClient.h"
// end jc

MODULE_BEGIN( ProcessList )

@@ -331,6 +334,11 @@ void StdServerProcessList::onTickObject( ProcessObject *pobj )
// For debugging it can be useful to know when this happens.
//if ( numMoves > 1 )
// Con::printf( "numMoves: %i", numMoves );
// start jc
//Midhir was here.
if (con->isAIControlled())
dynamic_cast<AIConnection*>(con)->getMoveList(&movePtr, &numMoves);
// end jc

// Do we really need to test the control object each iteration? Does it change?
for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, movePtr++ )
@@ -366,8 +374,11 @@ void StdServerProcessList::onTickObject( ProcessObject *pobj )
}
}
}

con->mMoveList->clearMoves( m );
// start jc
//Midhir was here.
if (!con->isAIControlled()) con->mMoveList->clearMoves(m);
//con->mMoveList->clearMoves( m );
// end jc
}
else if ( pobj->isTicking() )
pobj->processTick( 0 );
@@ -96,6 +96,9 @@ namespace {
static F32 sTargetFov = 90.f; ///< the desired FOV
static F32 sLastCameraUpdateTime = 0; ///< last time camera was updated
static S32 sZoomSpeed = 500; ///< ms per 90deg fov change
// start jc
static Point4F sFrustumOffset = Point4F::Zero;
// end jc

/// A scale to apply to the normal visible distance
/// typically used for tuning performance.
@@ -180,6 +183,61 @@ bool GameGetCameraTransform(MatrixF *mat, Point3F *velocity)
return connection && connection->getControlCameraTransform(0, mat) &&
connection->getControlCameraVelocity(velocity);
}
//start pg
//------------------------------------------------------------------------------
DefineEngineFunction( getCameraMatrix, MatrixF, ( ),,
"get camera matrix")
{
Point3F velocity;
MatrixF matrix;
GameGetCameraTransform(&matrix, &velocity);
return matrix;
}
//------------------------------------------------------------------------------
DefineEngineFunction( getCameraX, Point3F, ( ),,
"get camera X axis (camera side vector)")
{
Point3F velocity;
MatrixF matrix;
GameGetCameraTransform(&matrix, &velocity);
Point3F p;
matrix.getColumn(0,&p);
return p;
}
//------------------------------------------------------------------------------
DefineEngineFunction( getCameraY, Point3F, ( ),,
"get camera Y axis (vector into view)")
{
Point3F velocity;
MatrixF matrix;
GameGetCameraTransform(&matrix, &velocity);
Point3F p;
matrix.getColumn(1,&p);
return p;
}
//------------------------------------------------------------------------------
DefineEngineFunction( getCameraZ, Point3F, ( ),,
"get camera Z axis which is cameras up")
{
Point3F velocity;
MatrixF matrix;
GameGetCameraTransform(&matrix, &velocity);
Point3F p;
matrix.getColumn(2,&p);
return p;
}
//------------------------------------------------------------------------------
DefineEngineFunction( getCameraP, Point3F, ( ),,
"get camera position")
{
Point3F velocity;
MatrixF matrix;
GameGetCameraTransform(&matrix, &velocity);
Point3F p;
matrix.getColumn(3,&p);
return p;
}
//end pg

//------------------------------------------------------------------------------
DefineEngineFunction( setDefaultFov, void, ( F32 defaultFOV ),,
@@ -209,6 +267,26 @@ DefineEngineFunction( setFov, void, ( F32 FOV ),,
{
sTargetFov = mClampF(FOV, MinCameraFov, MaxCameraFov);
}
// start jc
DefineEngineFunction( setFrustumOffset, void, ( Point4F offset ),,
"@brief .\n")
{
sFrustumOffset = offset;
}
DefineEngineFunction( getFrustumOffset, Point4F, (),,
"@brief .\n")
{
return sFrustumOffset;
}
void GameSetCameraFov(Point4F offset)
{
sFrustumOffset = offset;
}
Point4F GameGetFrustumOffset()
{
return sFrustumOffset;
}
// end jc

F32 GameGetCameraFov()
{
@@ -353,6 +431,9 @@ bool GameProcessCameraQuery(CameraQuery *query)
// tuning scale which we never let over 1.
sVisDistanceScale = mClampF( sVisDistanceScale, 0.01f, 1.0f );
query->farPlane = gClientSceneGraph->getVisibleDistance() * sVisDistanceScale;
// start jc
query->frustumOffset = gClientSceneGraph->getFrustumOffset();
// end jc

F32 cameraFov;
if(!connection->getControlCameraFov(&cameraFov))

Large diffs are not rendered by default.

@@ -36,6 +36,12 @@
#endif
#endif

// start jc
#ifndef _SIMTUIO_H_
#include "console/simTUIO.h"
#endif
// end jc

class ProjectileData;
class GameBase;

@@ -75,4 +81,133 @@ class GameTSCtrl : public GuiTSCtrl
virtual bool onAdd();
};

// start jc

//----------------------------------------------------------------------------
//struct Gui3DMouseEvent;
//struct Gui3DTouchEvent;
//struct ShapeInputEvent;
//struct ShapeTouchEvent;
//struct GuiTouchEvent;

class TouchTSCtrl : public GameTSCtrl
{
private:
typedef GameTSCtrl Parent;

SimObjectPtr<SceneObject> mMouseCapturedControl; ///< All mouse events will go to this ctrl only
SimObjectPtr<SceneObject> mMouseControl; ///< the control the mouse was last seen in unless some other one captured it
HashTable<U32, SceneObject*> mTouchCapturedControl;

bool _findInputEventObject(const Gui3DMouseEvent &event, ShapeInputEvent &ri);
bool _findTouchEventObject(const Gui3DTouchEvent &event, ShapeTouchEvent &ri);
// start jc
bool _findInputEventObjectHitPoint(SceneObject *obj, const Gui3DMouseEvent &event, ShapeInputEvent &objEvent);
bool _findTouchEventObjectHitPoint(SceneObject *obj, const Gui3DTouchEvent &event, ShapeTouchEvent &objEvent);
// end jc
// start pg
void removeDeadObjects();
// end pg

public:
TouchTSCtrl();

DECLARE_CONOBJECT(TouchTSCtrl);
DECLARE_DESCRIPTION( "A control that renders a 3D view from the current control object." );

Gui3DMouseEvent mLastEvent;
Gui3DTouchEvent mLastTouchEvent;
bool mLeftMouseDown;
bool mRightMouseDown;
bool mMiddleMouseDown;
bool mMouseLeft;

bool mEnable3DInputEvents;
F32 m3DInputEventRange;

Point2I mLastMousePos;
bool mLastMouseClamping;

void make3DMouseEvent(Gui3DMouseEvent & gui3Devent, const GuiEvent &event);
void make3DTouchEvent(Gui3DTouchEvent & gui3Devent, const GuiTouchEvent &event);
bool getCameraTransform(MatrixF* cameraMatrix);

DECLARE_CALLBACK( void, onMouseDown, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onMouseUp, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onMouseMove, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onMouseDragged, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onMouseEnter, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onMouseLeave, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onRightMouseDown, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onRightMouseUp, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onRightMouseDragged, ( U8 modifier, Point2I mousePoint,U8 mouseClickCount ));
DECLARE_CALLBACK( void, onTouchDown, ( S32 id, Point2I touchPoint ));
DECLARE_CALLBACK( void, onTouchMove, ( S32 id, Point2I touchPoint ));
DECLARE_CALLBACK( void, onTouchUp, ( S32 id, Point2I touchPoint ));


virtual void onMouseUp(const GuiEvent & event);
virtual void onMouseDown(const GuiEvent & event);
virtual void onMouseMove(const GuiEvent & event);
virtual void onMouseDragged(const GuiEvent & event);
virtual void onMouseEnter(const GuiEvent & event);
virtual void onMouseLeave(const GuiEvent & event);
virtual void onRightMouseDown(const GuiEvent & event);
virtual void onRightMouseUp(const GuiEvent & event);
virtual void onRightMouseDragged(const GuiEvent & event);
virtual bool onMouseWheelUp(const GuiEvent & event);
virtual bool onMouseWheelDown(const GuiEvent & event);

virtual bool onTouchUp(const GuiTouchEvent & event);
virtual bool onTouchDown(const GuiTouchEvent & event);
virtual bool onTouchMove(const GuiTouchEvent & event);

virtual void on3DMouseUp(const Gui3DMouseEvent &);
virtual void on3DMouseDown(const Gui3DMouseEvent &);
virtual void on3DMouseMove(const Gui3DMouseEvent &);
virtual void on3DMouseDragged(const Gui3DMouseEvent &);
virtual void on3DMouseEnter(const Gui3DMouseEvent &);
virtual void on3DMouseLeave(const Gui3DMouseEvent &);
virtual void on3DRightMouseDown(const Gui3DMouseEvent &);
virtual void on3DRightMouseUp(const Gui3DMouseEvent &);
virtual void on3DRightMouseDragged(const Gui3DMouseEvent &);
virtual void on3DMouseWheelUp(const Gui3DMouseEvent &);
virtual void on3DMouseWheelDown(const Gui3DMouseEvent &);

virtual bool on3DTouchUp(const Gui3DTouchEvent &);
virtual bool on3DTouchDown(const Gui3DTouchEvent &);
virtual bool on3DTouchMove(const Gui3DTouchEvent &);
// virtual void get3DCursor(GuiCursor *&cursor, bool &visible, const Gui3DMouseEvent &);
// void lockMouse(SceneObject* object);
// void lockTouchID(U32 touchID, SceneObject* object);
// void unlockMouse(SceneObject* object);
// void unlockTouchID(U32 touchID);

virtual void mouseLock(SceneObject *lockingControl);
virtual void mouseUnlock(SceneObject *lockingControl);
virtual SceneObject* getMouseControl() { return mMouseControl; }
virtual SceneObject* getMouseLockedControl() { return mMouseCapturedControl; }
virtual void touchIDLock(U32 touchID, SceneObject *lockingControl);
virtual void touchIDUnlock(U32 touchID, SceneObject *lockingControl);
virtual void TouchTSCtrl::touchIDUnlockAll(SceneObject *lockingControl);

virtual SceneObject* getTouchIDLockedControl(U32 touchID)
{
SceneObject* obj;
if(mTouchCapturedControl.find(touchID, obj))
return obj;
return NULL;
}

bool processCameraQuery(CameraQuery * query);

static Point3F smCamPos;
static MatrixF smCamMatrix;
static bool smCamOrtho;
static F32 smCamNearPlane;
static F32 smVisibleDistanceScale;

};
// end jc

#endif
@@ -76,6 +76,7 @@ static SFXAmbience sDefaultAmbience;

LevelInfo::LevelInfo()
: mNearClip( 0.1f ),
mFrustumOffset( Point4F::Zero ), // start jc
mVisibleDistance( 1000.0f ),
mDecalBias( 0.0015f ),
mCanvasClearColor( 255, 0, 255, 255 ),
@@ -117,6 +118,11 @@ void LevelInfo::initPersistFields()
addField( "decalBias", TypeF32, Offset( mDecalBias, LevelInfo ),
"NearPlane bias used when rendering Decal and DecalRoad. This should be tuned to the visibleDistance in your level." );

// start jc
addField( "frustumOffset", TypePoint4F, Offset( mFrustumOffset, LevelInfo ),
"Point4F(left, right, top, bottom) - Offset to allow non axis aligned frustum. For full frustum use (0,1,0,1)" );
// end jc

endGroup( "Visibility" );

addGroup( "Fog" );
@@ -300,6 +306,9 @@ void LevelInfo::_updateSceneGraph()

scene->setNearClip( mNearClip );
scene->setVisibleDistance( mVisibleDistance );
// start jc
scene->setFrustumOffset(mFrustumOffset);
// end jc

gDecalBias = mDecalBias;

@@ -336,4 +345,31 @@ void LevelInfo::_onLMActivate(const char *lm, bool enable)
lightMgr->getLightBinManager()->MRTLightmapsDuringPrePass(mAdvancedLightmapSupport);
}
#endif
}
}

// start jc
// MACSK >>
void LevelInfo::setNearClip( F32 nearClip )
{
// We must update both scene graphs.
SceneManager *sm;
if ( isClientObject() )
sm = gClientSceneGraph;
else
sm = gServerSceneGraph;


// Clamp above zero before setting on the sceneGraph.
// If we don't we get serious crashes.
if ( nearClip <= 0.0f )
nearClip = 0.001f;
mNearClip = nearClip;
sm->setNearClip( mNearClip );
}

ConsoleMethod( LevelInfo, setNearClip, void, 3, 3, "( F32 nearClip )")
{
object->setNearClip( dAtof( argv[2] ));
}
// MACSK <<
// end jc
@@ -58,6 +58,9 @@ class LevelInfo : public NetObject
F32 mDecalBias;

ColorI mCanvasClearColor;
// start jc
Point4F mFrustumOffset;
// end jc

/// @name Lighting Properties
/// @{
@@ -97,7 +100,9 @@ class LevelInfo : public NetObject
void _onLMActivate(const char *lm, bool enable);

public:

// start jc
void setNearClip( F32 nearClip ); // MACSK ++
// end jc
LevelInfo();
virtual ~LevelInfo();

@@ -151,7 +151,18 @@ enum SceneObjectTypes
/// @see PhysicalZone
PhysicalZoneObjectType = BIT( 23 ),

// start jc
TurretObjectType = BIT( 24 ), // MACSK ++

AircraftObjectType = BIT ( 25 ), // MACSK ++

InputEventObjectType = BIT(26),
// end jc
// start pg
TrafficControllerObjectType = BIT(27)
// end pg
/// @}

};

enum SceneObjectTypeMasks
@@ -172,6 +172,9 @@ void BtBody::setMaterial( F32 restitution,
// like that.

mActor->setFriction( friction );
// start jc
mActor->setHitFraction( staticFriction );
// end jc

// Wake it up... it may need to move.
mActor->activate();
@@ -36,7 +36,10 @@ AFTER_MODULE_INIT( Sim )
{
NamedFactory<PhysicsPlugin>::add( "Bullet", &BtPlugin::create );

#if defined(TORQUE_OS_MAC)
// start jc
// #if defined(TORQUE_OS_MAC)
#if defined(TORQUE_OS_MAC) || defined(TORQUE_PHYSICS_BULLET)
// end jc
NamedFactory<PhysicsPlugin>::add( "default", &BtPlugin::create );
#endif
}
@@ -113,6 +113,10 @@ class PhysicsBody : public PhysicsObject

///
virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;

// start jc
virtual void moveGlobalPosition(const Point3F& vec) = 0;
// end jc
};


@@ -97,6 +97,19 @@ void PhysicsForce::attach( const Point3F &start, const Point3F &direction, F32 m
mBody = body;
}

// start jc
void PhysicsForce::attach( PhysicsBody* body )
{
detach();

// If there is no physics world then we cannot apply any forces.
if ( !mWorld && body )
return;

mBody = body;
}
// end jc

void PhysicsForce::detach( const Point3F &force )
{
if ( mBody && !force.isZero() )
@@ -63,6 +63,9 @@ class PhysicsForce : public SceneObject

///
void attach( const Point3F &start, const Point3F &direction, F32 maxDist );
// start jc
void attach( PhysicsBody* body );
// end jc

///
void detach( const Point3F &force = Point3F::Zero );
@@ -33,6 +33,9 @@
#include "T3D/physics/physicsObject.h"
#include "T3D/physics/physicsWorld.h"
#include "core/util/tNamedFactory.h"
// start jc
#include "console/engineAPI.h"
// end jc


PhysicsPlugin* PhysicsPlugin::smSingleton = NULL;
@@ -213,4 +216,12 @@ ConsoleFunction( physicsDebugDraw, void, 2, 2, "physicsDebugDraw( bool enable )"
{
if ( PHYSICSMGR )
PHYSICSMGR->enableDebugDraw( dAtoi( argv[1] ) );
}
}

// start jc
DefineEngineFunction( physicsSetGravity, void, (String worldName, Point3F gravity),,"physicsSetGravity( Point3F gravity )" )
{
if ( PHYSICSMGR )
PHYSICSMGR->getWorld(worldName)->setGravity(gravity);
}
// end jc

Large diffs are not rendered by default.

@@ -41,12 +41,24 @@
#ifndef _SIMOBJECTREF_H_
#include "console/simObjectRef.h"
#endif
// start jc
#ifndef _NETSTRINGTABLE_H_
#include "sim/netStringTable.h"
#endif
#ifndef _SIMTUIO_H_
#include "console/simTUIO.h"
#endif
class PhysicsShape;
// end jc

class TSShapeInstance;
class PhysicsBody;
class PhysicsWorld;
class PhysicsDebrisData;
class ExplosionData;
// start jc
class WebViewData;
// end jc


class PhysicsShapeData : public GameBaseData
@@ -135,6 +147,27 @@ class PhysicsShapeData : public GameBaseData
SimObjectRef< PhysicsDebrisData > debris;
SimObjectRef< ExplosionData > explosion;
SimObjectRef< PhysicsShapeData > destroyedShape;

// start jc
// DECLARE_CALLBACK( void, onCollision, ( PhysicsShape* obj, SceneObject* collObj, VectorF vec, F32 len ) );
DECLARE_CALLBACK( void, onAddClient, ( PhysicsShape* obj ) );
DECLARE_CALLBACK( void, onMouseDown, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseUp, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseMove, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseDragged, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseEnter, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseLeave, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseDown, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseUp, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseDragged, ( PhysicsShape* obj, U8 modifier, Point2I mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));

DECLARE_CALLBACK( bool, onTouchDown, ( PhysicsShape* obj, S32 id, Point2I touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));
DECLARE_CALLBACK( bool, onTouchMove, ( PhysicsShape* obj, S32 id, Point2I touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));
DECLARE_CALLBACK( bool, onTouchUp, ( PhysicsShape* obj, S32 id, Point2I touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));

DECLARE_CALLBACK(void, onMaterialsLoaded, (PhysicsShape* obj) );

// end jc
};

typedef PhysicsShapeData::SimType PhysicsSimType;
@@ -176,6 +209,17 @@ class PhysicsShape : public GameBase
/// True if the PhysicsShape has been destroyed ( gameplay ).
bool mDestroyed;

// start jc
U32 mSkinHash;
NetStringHandle mSkinNameHandle;
String mAppliedSkinName;
WebViewData* mWebViewData;
SimObjectId mWebViewID;

bool mEnableInputEvents;
// F32 mGravityMod;
// end jc

/// Enables automatic playing of the animation named "ambient" (if it exists)
/// when the PhysicsShape is loaded.
bool mPlayAmbient;
@@ -264,6 +308,65 @@ class PhysicsShape : public GameBase
/// event occurs. This is automatically set in onAdd but some manipulators
/// such as Prefab need to make use of this.
void storeRestorePos();

// start jc
void setEnableInputEvents( bool enable );
virtual void onMouseDown(const ShapeInputEvent & event);
virtual void onMouseUp(const ShapeInputEvent & event);
virtual void onMouseMove(const ShapeInputEvent & event);
virtual void onMouseDragged(const ShapeInputEvent & event);
virtual void onMouseEnter(const ShapeInputEvent & event);
virtual void onMouseLeave(const ShapeInputEvent & event);
virtual void onRightMouseDown(const ShapeInputEvent & event);
virtual void onRightMouseUp(const ShapeInputEvent & event);
virtual void onRightMouseDragged(const ShapeInputEvent & event);

virtual bool onTouchDown(const ShapeTouchEvent & event);
virtual bool onTouchMove(const ShapeTouchEvent & event);
virtual bool onTouchUp(const ShapeTouchEvent & event);

bool castRay(const Point3F &start, const Point3F &end, RayInfo* info);
bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo* info);

Point3F getCMassPosition(void);
void setLinVelocity(const Point3F velocity);
Point3F getLinVelocity() const;
void moveGlobalPosition(const Point3F& vec);

void setSkinName(const char*);
const char* getSkinName();

void reSkin();
void reSkinNewPath();
void reSkin(const char* oldSkin);
void webSkin();
Point2I getTextureResolution(U32 index);
bool rayCrossesTransparency(RayInfo* ri);

void setWebViewData(WebViewData* webview)
{
mWebViewData = webview;
setMaskBits(SkinMask);
}
WebViewData* getWebViewData()
{
return mWebViewData;
}
bool hasWebViewData()
{
return bool(mWebViewData);
}

// end jc

};

// start jc
inline const char* PhysicsShape::getSkinName()
{
return mSkinNameHandle.getString();
}
// end jc


#endif // _PHYSICSSHAPE_H_
@@ -37,7 +37,11 @@ class SceneRenderState;
class PhysicsBody;



struct SweepResult{
Point3F point;
Point3F normal;
F32 pathFraction;
};
class PhysicsWorld
{
protected:
@@ -81,6 +85,11 @@ class PhysicsWorld
/// Returns the active gravity force.
const Point3F& getGravity() const { return mGravity; }

// start jc
/// Returns the active gravity force.
virtual void setGravity(const Point3F& gravity) = 0;
// end jc

/// An abstract way to raycast into any type of PhysicsWorld, in a way
/// that mirrors a Torque-style raycast.
//
@@ -105,6 +114,9 @@ class PhysicsWorld
///
virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All ) = 0;

//pghack
virtual bool sweepSphere(SweepResult &sweepResult, const Point3F &start, const Point3F &end, const F32 &radius ){return false;}

virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) = 0;
};

@@ -402,3 +402,10 @@ void PxBody::applyImpulse( const Point3F &origin, const Point3F &force )
NX_IMPULSE );
}

// start jc
void PxBody::moveGlobalPosition(const Point3F& vec)
{
mActor->moveGlobalPosition(pxCast<NxVec3>(vec));
}

// end jc
@@ -109,6 +109,10 @@ class PxBody : public PhysicsBody
F32 staticFriction );
virtual void applyCorrection( const MatrixF &xfm );
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
// start jc
virtual void moveGlobalPosition(const Point3F& vec);

// end jc
};

#endif // _T3D_PHYSICS_PXBODY_H_
@@ -37,7 +37,9 @@
#include "core/stream/bitStream.h"
#include "materials/materialManager.h"
#include "materials/baseMatInstance.h"

// start jc
#include "console/engineAPI.h"
// end jc

IMPLEMENT_CO_NETOBJECT_V1( PxCloth );

@@ -114,6 +116,10 @@ PxCloth::PxCloth()
mDampingCoefficient = 0.25f;

mAttachmentMask = 0;

// start jc
mAttachmentPointScale = Point3F::One;
// end jc
}

PxCloth::~PxCloth()
@@ -240,6 +246,13 @@ void PxCloth::initPersistFields()
"@brief Optional way to specify cloth verts that will be attached to the world position "
"it is created at.\n\n" );

// start jc

addField( "attachmentPointScale", TypePoint3F, Offset( mAttachmentPointScale, PxCloth ),
"@brief .\n\n" );

// end jc

// Cloth doesn't support scale.
removeField( "scale" );
}
@@ -264,6 +277,11 @@ U32 PxCloth::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
if ( stream->writeFlag( mask & TransformMask ) )
mathWrite( *stream, getTransform() );

// start jc
if ( stream->writeFlag( mask & ScaleAttachmentPointsMask ) )
mathWrite( *stream, mAttachmentPointScale);
// end jc

if ( stream->writeFlag( mask & MaterialMask ) )
stream->write( mMaterialName );

@@ -298,9 +316,109 @@ void PxCloth::unpackUpdate( NetConnection *conn, BitStream *stream )
{
MatrixF mat;
mathRead( *stream, &mat );
// start jc
if(mCloth)
{
NxVec3 delta(mat.getPosition() - getTransform().getPosition());

if(mCloth->isSleeping())
mCloth->wakeUp();

if ( mAttachmentMask & BIT( 0 ) )
mCloth->attachVertexToGlobalPosition( 0, mCloth->getPosition( 0 ) + delta );
if ( mAttachmentMask & BIT( 1 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, mCloth->getPosition( mPatchVerts.x-1 ) + delta );
if ( mAttachmentMask & BIT( 2 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ) + delta );
if ( mAttachmentMask & BIT( 3 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ) + delta );
if ( mAttachmentMask & BIT( 4 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ) + delta );
if ( mAttachmentMask & BIT( 5 ) )
mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), mCloth->getPosition( (mPatchVerts.x/2) ) + delta );
if ( mAttachmentMask & BIT( 6 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ) + delta );
if ( mAttachmentMask & BIT( 7 ) )
mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ) + delta );

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 ) + delta );

if ( mAttachmentMask & BIT( 9 ) )
for ( U32 i = 0; i < mPatchVerts.x; i++ )
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) + delta );

if ( mAttachmentMask & BIT( 10 ) )
for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) + delta );

if ( mAttachmentMask & BIT( 11 ) )
for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) + delta );
}
// end jc


setTransform( mat );
}

// start jc
// ScaleAttachmentPointsMask
if ( stream->readFlag() )
{
Point3F attachmentPointScale;
mathRead( *stream, &attachmentPointScale );

if(mCloth)
{
Point3F scale(Point3F::One);
scale.convolveInverse(mAttachmentPointScale);
scale.convolve(attachmentPointScale);
NxVec3 delta(scale);

if(mCloth->isSleeping())
mCloth->wakeUp();

static NxVec3 delta2;
if ( mAttachmentMask & BIT( 0 ) )
{ delta2.arrayMultiply(mCloth->getPosition( 0 ),delta); mCloth->attachVertexToGlobalPosition( 0, delta2); }
if ( mAttachmentMask & BIT( 1 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x-1 ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, delta2); }
if ( mAttachmentMask & BIT( 2 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, delta2); }
if ( mAttachmentMask & BIT( 3 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, delta2); }
if ( mAttachmentMask & BIT( 4 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), delta2); }
if ( mAttachmentMask & BIT( 5 ) )
{ delta2.arrayMultiply(mCloth->getPosition( (mPatchVerts.x/2) ), delta); mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), delta2); }
if ( mAttachmentMask & BIT( 6 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), delta2); }
if ( mAttachmentMask & BIT( 7 ) )
{ delta2.arrayMultiply(mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ), delta); mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), delta2); }

if ( mAttachmentMask & BIT( 8 ) )
for ( U32 i = mPatchVerts.x * mPatchVerts.y - mPatchVerts.x; i < mPatchVerts.x * mPatchVerts.y; i++ )
{ delta2.arrayMultiply(mCloth->getPosition( i ), delta); mCloth->attachVertexToGlobalPosition( i, delta2); }

if ( mAttachmentMask & BIT( 9 ) )
for ( U32 i = 0; i < mPatchVerts.x; i++ )
{ delta2.arrayMultiply(mCloth->getPosition( i ), delta); mCloth->attachVertexToGlobalPosition( i, delta2); }

if ( mAttachmentMask & BIT( 10 ) )
for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
{ delta2.arrayMultiply(mCloth->getPosition( i ), delta); mCloth->attachVertexToGlobalPosition( i, delta2); }

if ( mAttachmentMask & BIT( 11 ) )
for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
{ delta2.arrayMultiply(mCloth->getPosition( i ), delta); mCloth->attachVertexToGlobalPosition( i, delta2); }
}

mAttachmentPointScale = attachmentPointScale;
}
// end jc

// MaterialMask
if ( stream->readFlag() )
{
@@ -392,6 +510,14 @@ void PxCloth::setScale( const VectorF &scale )
return;
}

// start jc
void PxCloth::setAttachmentPointScale( const Point3F &scale )
{
mAttachmentPointScale = scale;
setMaskBits( ScaleAttachmentPointsMask );
}
// end jc

void PxCloth::prepRenderImage( SceneRenderState *state )
{
if ( mIsVBDirty )
@@ -650,6 +776,10 @@ bool PxCloth::_createClothPatch()
desc.bendingStiffness = mBendingStiffness;
desc.dampingCoefficient = mDampingCoefficient;
desc.friction = mFriction;
// start jc
// todo: expose this
desc.sleepLinearVelocity = 0.0000001f;
// end jc

if ( mBendingEnabled )
desc.flags |= NX_CLF_BENDING;
@@ -920,4 +1050,15 @@ void PxCloth::_setupAttachments()
if ( mAttachmentMask & BIT( 11 ) )
for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
}
}

//-----------------------------------------------------------------------------

DefineEngineMethod( PxCloth, setAttachmentPointScale, void, ( Point3F scale ),,
"Set the scale of attachment points.\n"
"@param scale object scale to set\n" )
{
object->setAttachmentPointScale( scale );
}

//-----------------------------------------------------------------------------
@@ -56,7 +56,11 @@ class PxCloth : public GameBase
TransformMask = Parent::NextFreeMask << 0,
ClothMask = Parent::NextFreeMask << 1,
MaterialMask = Parent::NextFreeMask << 3,
NextFreeMask = Parent::NextFreeMask << 4
// start jc
// NextFreeMask = Parent::NextFreeMask << 4
ScaleAttachmentPointsMask = Parent::NextFreeMask << 4,
NextFreeMask = Parent::NextFreeMask << 5
// end jc
};

public:
@@ -81,7 +85,9 @@ class PxCloth : public GameBase
virtual void setTransform( const MatrixF &mat );
virtual void setScale( const VectorF &scale );
virtual void prepRenderImage( SceneRenderState *state );

// start jc
virtual void setAttachmentPointScale( const Point3F &scale );
// end jc
// GameBase
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
virtual void processTick( const Move *move );
@@ -116,6 +122,9 @@ class PxCloth : public GameBase
F32 mAttachmentResponseCoefficient;

U32 mAttachmentMask;
// start jc
Point3F mAttachmentPointScale;
// end jc

static EnumTable mAttachmentFlagTable;

@@ -30,6 +30,15 @@
//#include "gfx/gfxDrawUtil.h"
//#include "sim/netConnection.h"

// start pg
#include "platform\platform.h"
#include "platform\profiler.h"

static const
F32 MIN_CAPSULE_HEIGHT = 0.0005f,
MIN_CAPSULE_RADIUS = 0.05f,
SKIN_WIDTH = 0.05f;
// end pg

PxPlayer::PxPlayer()
: PhysicsPlayer(),
@@ -75,7 +84,8 @@ void PxPlayer::init( const char *type,
mObject = obj;
mWorld = (PxWorld*)world;
mOriginOffset = size.z * 0.5f;

// start pg
/*
//if ( dStricmp( type, "Capsule" ) == 0 )
{
NxCapsuleControllerDesc desc;
@@ -85,6 +95,7 @@ void PxPlayer::init( const char *type,
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;
@@ -98,6 +109,56 @@ void PxPlayer::init( const char *type,
//mColShape = new btBoxShape( btVector3( 0.5f, 0.5f, 1.0f ) );
//mOriginOffset = 1.0f;
}
*/

if ( dStricmp( type, "FishController" ) == 0 ){

//capsule with radius and height comiong from x & y component of size
F32 _radius = size.x;
F32 _height = size.y;
//mOriginOffset = (_height + 2.0f*_radius)*0.5f; //capsules base on point

NxCapsuleControllerDesc desc;

desc.interactionFlag = NXIF_INTERACTION_EXCLUDE;

desc.skinWidth = SKIN_WIDTH;
desc.radius = _radius;
desc.height = _height;

desc.climbingMode = CLIMB_EASY;
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 if ( dStricmp( type, "Capsule" ) == 0 ){
}else{
NxCapsuleControllerDesc desc;
desc.skinWidth = SKIN_WIDTH; // Expose?

//shrink box to allow for skin
Point3F newSize;
newSize.x = size.x - 2.0f*SKIN_WIDTH;
newSize.y = size.y - 2.0f*SKIN_WIDTH;
newSize.z = size.z - 2.0f*SKIN_WIDTH;
//make biggest capsule that will fit in box vertically
desc.radius = getMax( newSize.x, newSize.y ) * 0.5f;
desc.height = newSize.z - ( desc.radius * 2.0f );

if(desc.height<MIN_CAPSULE_HEIGHT)desc.height =MIN_CAPSULE_HEIGHT;
if(desc.radius<MIN_CAPSULE_RADIUS)desc.radius = MIN_CAPSULE_RADIUS;

desc.climbingMode = CLIMB_EASY; //pghack
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 );
}
// end pg

// Put the kinematic actor on group 29.
NxActor *kineActor = mController->getActor();
@@ -147,8 +208,10 @@ Point3F PxPlayer::move( const VectorF &disp, CollisionList &outCol )
// 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;
// start jc
// if (mIsZero(disp.z))
// dispNx.z = 0.0f;
// end jc

NxU32 activeGroups = 0xFFFFFFFF;
activeGroups &= ~( 1<<31 ); // Skip activeGroup for triggers ( 31 )
@@ -411,7 +474,26 @@ MatrixF& PxPlayer::getTransform( MatrixF *outMatrix )

void PxPlayer::setScale( const Point3F &scale )
{
// start jc
AssertFatal( mController, "PxPlayer::setTransform - The controller is null!" );

NxCapsuleController *capsule = static_cast<NxCapsuleController*>(mController);
if(capsule)
{
mWorld->releaseWriteLock();
capsule->setRadius(scale.x);
capsule->setHeight(scale.y);
}
// end jc
}
// start jc
// virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {}
void PxPlayer::setSpacials( const Point3F &nPos, const Point3F &nSize )
{
setScale(nSize);
}
// end jc


Box3F PxPlayer::getWorldBounds()
{
@@ -95,7 +95,10 @@ class PxPlayer : public PhysicsPlayer, public NxUserControllerHitReport
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 ) {}
// start jc
// virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {}
virtual void setSpacials( const Point3F &nPos, const Point3F &nSize );
// end jc
virtual void enableCollision();
virtual void disableCollision();
};
@@ -39,7 +39,10 @@ AFTER_MODULE_INIT( Sim )
{
NamedFactory<PhysicsPlugin>::add( "PhysX", &PxPlugin::create );

#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
// start jc
// #if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
#if (defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)) && !defined(TORQUE_PHYSICS_BULLET)
// end jc
NamedFactory<PhysicsPlugin>::add( "default", &PxPlugin::create );
#endif

@@ -714,6 +714,65 @@ bool PxWorld::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *

return true;
}
// start pg
class UserEntityReport : public NxUserEntityReport<NxSweepQueryHit>
{
public:
NxSweepQueryHit bestHit;
void reset()
{
bestHit.t = 1;
}
virtual bool onEvent(NxU32 nbEntities, NxSweepQueryHit* entities)
{
for(int j=0; j<nbEntities; j++){
NxSweepQueryHit &e = entities[j];
if(e.t<bestHit.t){
bestHit = e;
}
}
return true;
}
};

UserEntityReport myReport;


bool PxWorld::sweepSphere( SweepResult &res, const Point3F &start, const Point3F &end, const F32 &radius)
{
// asdasd
NxCapsule capsule;
capsule.p0.x = start.x;
capsule.p0.y = start.y;
capsule.p0.z = start.z;
capsule.p1.x = start.x;
capsule.p1.y = start.y;
capsule.p1.z = start.z;
capsule.radius = 1.0f;

NxU32 flags = NX_STATIC_SHAPES;
NxVec3 range;
range.x = end.x - start.x;
range.y = end.y - start.y;
range.z = end.z - start.z;

myReport.reset();
mScene->linearCapsuleSweep(capsule, range, flags, 0, 0, 0, &myReport);
if(myReport.bestHit.t<1.0f){
res.normal.x = myReport.bestHit.normal.x;
res.normal.y = myReport.bestHit.normal.y;
res.normal.z = myReport.bestHit.normal.z;

res.point.x = myReport.bestHit.point.x;
res.point.y = myReport.bestHit.point.y;
res.point.z = myReport.bestHit.point.z;
res.pathFraction = myReport.bestHit.t;
return true;
}else{
return false;
}
}
// end pg

PhysicsBody* PxWorld::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes )
{
@@ -870,3 +929,11 @@ void PxWorld::onDebugDraw( const SceneRenderState *state )
PrimBuild::end();
}
}

// start jc
/// Returns the active gravity force.
void PxWorld::setGravity(const Point3F& gravity)
{
mScene->setGravity(pxCast<NxVec3>(gravity));
}
// end jc
@@ -109,6 +109,9 @@ class PxWorld : public PhysicsWorld
virtual void onDebugDraw( const SceneRenderState *state );
virtual void reset() {}
virtual bool isEnabled() const { return mIsEnabled; }
// start pg
virtual bool sweepSphere(SweepResult &res, const Point3F &start, const Point3F &end, const F32 &radius );
// end pg

/// @name Static Methods
/// @{
@@ -188,6 +191,12 @@ class PxWorld : public PhysicsWorld

void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; }
const F32 getEditorTimeScale() const { return mEditorTimeScale; }

// start jc
/// Returns the active gravity force.
void setGravity(const Point3F& gravity);
// end jc

};

#endif // _PHYSX_WORLD_H_

Large diffs are not rendered by default.

@@ -80,6 +80,15 @@ struct PlayerData: public ShapeBaseData {
/// @name Physics constants
/// @{


// start ds
F32 walkForce; ///< Force used to accelerate player
F32 walkEnergyDrain; ///< Energy drain/tick
F32 maxWalkForwardSpeed; ///< Maximum forward speed when running
F32 maxWalkBackwardSpeed; ///< Maximum backward speed when running
F32 maxWalkSideSpeed; ///< Maximum side speed when running
// end ds

F32 maxStepHeight; ///< Maximum height the player can step up
F32 runSurfaceAngle; ///< Maximum angle from vertical in degrees the player can run up

@@ -135,7 +144,9 @@ struct PlayerData: public ShapeBaseData {
F32 maxUnderwaterForwardSpeed; ///< Maximum underwater forward speed when running
F32 maxUnderwaterBackwardSpeed; ///< Maximum underwater backward speed when running
F32 maxUnderwaterSideSpeed; ///< Maximum underwater side speed when running

// start ds
F32 swimDepth;
// end ds
// Crouching
F32 crouchForce; ///< Force used to accelerate player while crouching
F32 maxCrouchForwardSpeed; ///< Maximum forward speed when crouching
@@ -155,6 +166,12 @@ struct PlayerData: public ShapeBaseData {
F32 jetMinJumpSpeed;
F32 jetMaxJumpSpeed;
F32 jetJumpSurfaceAngle; ///< Angle vertical degrees

// strat jc
// Flying
bool canFly;
// end jc

/// @}

/// @name Hitboxes
@@ -179,6 +196,15 @@ struct PlayerData: public ShapeBaseData {
VectorF groundImpactShakeAmp; ///< How much to shake
F32 groundImpactShakeDuration; ///< How long to shake
F32 groundImpactShakeFalloff; ///< How fast the shake disapates
// start jc - Dan&rsquo;s mods (turning intertia) ->
F32 horizTurnSpeedInertia; ///< Amount of z-axis rotation to carry over from last tick
F32 vertTurnSpeedInertia; ///< Amount of x-axis rotation to carry over from last tick
// F32 AITurnSpeed; ///< Fraction of actual distance for AIPlayers to turn

F32 maxTurnRate;
bool conformToGround;
F32 smoothCamera;
// end jc - <- Dan&rsquo;s mods (turning inertia)

/// Zounds!
enum Sounds {
@@ -208,6 +234,9 @@ struct PlayerData: public ShapeBaseData {
Point3F crouchBoxSize;
Point3F proneBoxSize;
Point3F swimBoxSize;
// start ds - offset collision box and zrotation
Point3F renderOffset;
// end ds

/// Animation and other data initialized in onAdd
struct ActionAnimationDef {
@@ -378,7 +407,7 @@ class Player: public ShapeBase
CrouchPose,
PronePose,
SwimPose,
NumPoseBits = 3
NumPoseBits = 4
};

protected:
@@ -443,6 +472,21 @@ class Player: public ShapeBase
S32 mMountPending; ///< mMountPending suppresses tickDelay countdown so players will sit until
///< their mount, or another animation, comes through (or 13 seconds elapses).

// start ds
// Variable Movement! -- Zshazz
/*
F32 mRunForceMod; // Modifies the runForce
F32 mMaxForwardSpeedMod;
F32 mMaxBackwardSpeedMod;
F32 mMaxWalkForwardSpeedMod;
F32 mMaxWalkBackwardSpeedMod;
F32 mMaxSideSpeedMod;
*/
// end ds
// start jc - moved to player for variable motion.
F32 mMoveSpeed;
// end jc

/// Main player state
enum ActionState {
NullState,
@@ -512,6 +556,9 @@ class Player: public ShapeBase

bool mInWater; ///< Is true if WaterCoverage is greater than zero
bool mSwimming; ///< Is true if WaterCoverage is above the swimming threshold
// start jc
bool mFlying; ///< Is true if WaterCoverage is above the swimming threshold
// end jc
//
PlayerData* mDataBlock; ///< MMmmmmm...datablock...

@@ -588,6 +635,10 @@ class Player: public ShapeBase

///Update the movement
virtual void updateMove(const Move *move);
// start jc
void updateMoveFlight(const Move *move);
void updateMoveOriginal(const Move *move);
// end jc

///Interpolate movement
Point3F _move( const F32 travelTime, Collision *outCol );
@@ -620,6 +671,9 @@ class Player: public ShapeBase
/// @}

void setPosition(const Point3F& pos,const Point3F& viewRot);
// start ds - conform to ground
void setRenderTransform(const MatrixF &);
// end ds
void setRenderPosition(const Point3F& pos,const Point3F& viewRot,F32 dt=-1);
void _findContact( SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects );
void findContact( bool *run, bool *jump, VectorF *contactNormal );
@@ -748,6 +802,10 @@ class Player: public ShapeBase
void setControlObject(ShapeBase *obj);
ShapeBase* getControlObject();

// start ds
// Variable Movement -- Zshazz
// static void initPersistFields(); // Has to be declared so that the engine knows to use my persist fields
// end ds
//
void updateWorkingCollisionSet();
virtual void processTick(const Move *move);
@@ -767,6 +825,14 @@ class Player: public ShapeBase
virtual void prepRenderImage( SceneRenderState* state );
virtual void renderConvex( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
virtual void renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRenderState *state );
// start ds
bool mFrozen;
void setFrozen(bool frozen) {if (frozen != mFrozen && isServerObject()) {setMaskBits(MoveMask);} mFrozen = frozen;}
// end ds
// start jc - moved to player for variable motion.
void setMoveSpeed( const F32 speed );
F32 getMoveSpeed() const { return mMoveSpeed; }
// end jc
};

typedef Player::Pose PlayerPose;
@@ -196,7 +196,10 @@ namespace {

// Physics and collision constants
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
static int sRestCount = 10; // Consecutive ticks before comming to rest
// start jc
// static int sRestCount = 10; // Consecutive ticks before comming to rest
static int sRestCount = 1000; // Consecutive ticks before comming to rest
// end jc

const U32 sCollisionMoveMask = (TerrainObjectType | InteriorObjectType |
PlayerObjectType | StaticShapeObjectType | VehicleObjectType |
@@ -794,6 +797,16 @@ void RigidShape::interpolateTick(F32 dt)
{
Parent::interpolateTick(dt);

// start jc
if ( isMounted() )
{
MatrixF mat;
setTransform(mat);
}
else
{
// end jc

if(dt == 0.0f)
setRenderPosition(mDelta.pos, mDelta.rot[1]);
else
@@ -804,6 +817,9 @@ void RigidShape::interpolateTick(F32 dt)
setRenderPosition(pos,rot);
}
mDelta.dt = dt;
// start jc
}
// end jc
}

void RigidShape::advanceTime(F32 dt)
@@ -997,8 +1013,24 @@ void RigidShape::setRenderPosition(const Point3F& pos, const QuatF& rot)

void RigidShape::setTransform(const MatrixF& newMat)
{
mRigid.setTransform(newMat);
Parent::setTransform(newMat);
// start jc
// mRigid.setTransform(newMat);
// Parent::setTransform(newMat);
if ( isMounted() )
{
MatrixF mat;
mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );

mRigid.setTransform(mat);
Parent::setTransform(mat);
}
else
{
mRigid.setTransform(newMat);
Parent::setTransform(newMat);
}
// end jc

mRigid.atRest = false;
mContacts.clear();
}
@@ -1040,6 +1072,8 @@ void RigidShape::updatePos(F32 dt)
// the shape is less than some percentage of the energy added
// by gravity for a short period, we're considered at rest.
// This should really be part of the rigid class...
// start jc
/*
if (mCollisionList.getCount())
{
F32 k = mRigid.getKineticEnergy();
@@ -1050,6 +1084,8 @@ void RigidShape::updatePos(F32 dt)
}
else
restCount = 0;
*/
// end jc
}

// Integrate forward
@@ -1686,6 +1722,13 @@ void RigidShape::freezeSim(bool frozen)
setMaskBits(FreezeMask);
}

// start jc
bool RigidShape::isFrozen(void)
{
return mDisableMove;
}
// end jc

DefineEngineMethod( RigidShape, reset, void, (),,
"@brief Clears physic forces from the shape and sets it at rest.\n\n"
"@tsexample\n"
@@ -1710,3 +1753,19 @@ DefineEngineMethod( RigidShape, freezeSim, void, (bool isFrozen),,
{
object->freezeSim(isFrozen);
}

// start jc
DefineEngineMethod( RigidShape, isFrozen, bool, (),,
"@brief Enables or disables the physics simulation on the RigidShape object.\n\n"
"@param isFrozen Boolean frozen state to set the object.\n"
"@tsexample\n"
"// Define the frozen state.\n"
"%isFrozen = \"true\";\n\n"
"// Inform the object of the defined frozen state\n"
"%thisRigidShape.freezeSim(%isFrozen);\n"
"@endtsexample\n\n"
"@see ShapeBaseData")
{
return object->isFrozen();
}
// end jc
@@ -268,6 +268,9 @@ class RigidShape: public ShapeBase
// xgalaxy cool hacks
void reset();
void freezeSim(bool frozen);
// start jc
bool isFrozen(void);
// end jc

///@name Rigid body methods
///@{
@@ -91,7 +91,15 @@ void SFX3DObject::getEarTransform( MatrixF& transform ) const
if ( !shapeInstance )
{
// Just in case.
transform = mObject->getTransform();
// start jc
// transform = mObject->getTransform();
F32 pos = 0;
GameConnection * gc = shape->getControllingClient();
if (gc && !gc->isFirstPerson())
pos = 1.0f;

shape->getCameraEarTransform(&pos, &transform);
// end jc
return;
}

@@ -110,7 +118,10 @@ void SFX3DObject::getEarTransform( MatrixF& transform ) const
else
{
GameConnection* connection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer());
if ( !connection || !connection->getControlCameraTransform( 0.0f, &transform ) )
// start jc
// if ( !connection || !connection->getControlCameraTransform( 0.0f, &transform ) )
if ( !connection || !connection->getControlCameraEarTransform( 0.0f, &transform ) )
// end jc
transform = mObject->getTransform();
}
}
@@ -654,6 +654,10 @@ bool SFXEmitter::onAdd()
if( mPlayOnAdd && mSource )
mSource->play();
}
// start jc
if(!mPlayOnAdd)
stop();
// end jc

// Setup the bounds.

@@ -63,12 +63,19 @@ class SFXEmitter : public SceneObject
/// Network update masks.
enum UpdateMasks
{
// start jc
// InitialUpdateMask = BIT(0),
// TransformUpdateMask = BIT(1),
// DirtyUpdateMask = BIT(2),
// SourcePlayMask = BIT(3),
// SourceStopMask = BIT(4),
InitialUpdateMask = BIT(0),
TransformUpdateMask = BIT(1),
DirtyUpdateMask = BIT(2),

SourcePlayMask = BIT(3),
SourceStopMask = BIT(4),
TransformUpdateMask = Parent::NextFreeMask << 0,
DirtyUpdateMask = Parent::NextFreeMask << 1,
SourcePlayMask = Parent::NextFreeMask << 2,
SourceStopMask = Parent::NextFreeMask << 3,
NextFreeMask = Parent::NextFreeMask << 4,
// end jc

AllSourceMasks = SourcePlayMask | SourceStopMask,
};

Large diffs are not rendered by default.

@@ -62,6 +62,15 @@
#ifndef _DYNAMIC_CONSOLETYPES_H_
#include "console/dynamicTypes.h"
#endif
// start jc
#ifndef _SIMTUIO_H_
#include "console/simTUIO.h"
#endif

#define TORQUE_RESYNC_ANIM
//#define TORQUE_RESYNC_ANIM_TIME 1000.0f * 60.0f * 5.0f
#define TORQUE_RESYNC_ANIM_TIME 1000.0f * 60.0f
// end jc


class GFXCubemap;
@@ -79,6 +88,9 @@ class ShapeBase;
class SFXSource;
class SFXTrack;
class SFXProfile;
// start jc
class WebViewData;
// end jc

typedef void* Light;

@@ -88,6 +100,21 @@ typedef void* Light;
extern void collisionFilter(SceneObject* object,S32 key);
extern void defaultFilter(SceneObject* object,S32 key);

// start jc
//--------------------------------------------------------------------------

class ShapeBaseWebViewEvent : public SimEvent
{
typedef SimEvent Parent;
// NetConnection *mCon;
public:

ShapeBaseWebViewEvent() {}
//virtual void process( SimObject *object );
virtual void process( SimObject *object );
};
// end jc


//--------------------------------------------------------------------------
class ShapeBaseConvex : public Convex
@@ -613,6 +640,13 @@ struct ShapeBaseData : public GameBaseData {
bool useEyePoint; ///< Do we use this object's eye point to view from?
bool isInvincible; ///< If set, object cannot take damage (won't show up with damage bar either)
bool renderWhenDestroyed; ///< If set, will not render this object when destroyed.
// start jc
bool renderInReflections;
Box3F overrideBounds;
// end jc
// start jc
bool mAlwaysUnderwater;
// end jc

bool inheritEnergyFromMount;

@@ -644,6 +678,31 @@ struct ShapeBaseData : public GameBaseData {
DECLARE_CALLBACK( void, onTrigger, ( ShapeBase* obj, S32 index, bool state ) );
DECLARE_CALLBACK( void, onEndSequence, ( ShapeBase* obj, S32 slot ) );
DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) );

// start jc
DECLARE_CALLBACK( void, onAddClient, ( ShapeBase* obj ) );
DECLARE_CALLBACK( void, onRemoveClient, ( ShapeBase* obj ) );
DECLARE_CALLBACK( void, onMouseDown, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseUp, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseMove, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseDragged, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseEnter, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onMouseLeave, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseDown, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseUp, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));
DECLARE_CALLBACK( void, onRightMouseDragged, ( ShapeBase* obj, U8 modifier, Point3F mousePoint,U8 mouseClickCount, Point3F pos, Point3F vec, Point2F mouseUVCoord ));

DECLARE_CALLBACK( bool, onTouchDown, ( ShapeBase* obj, S32 id, Point3F touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));
DECLARE_CALLBACK( bool, onTouchMove, ( ShapeBase* obj, S32 id, Point3F touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));
DECLARE_CALLBACK( bool, onTouchUp, ( ShapeBase* obj, S32 id, Point3F touchPoint, Point3F pos, Point3F vec, Point2F touchUVCoord ));

DECLARE_CALLBACK(void, onMaterialsLoaded, (ShapeBase* obj) );

// DECLARE_CALLBACK(void, onAdd, (ShapeBase* obj, SimObjectId ID) );
// DECLARE_CALLBACK(void, onRemove, (ShapeBase* obj, SimObjectId ID));


// end jc
/// @}
};

@@ -665,6 +724,9 @@ class ShapeBase : public GameBase, public ISceneLight
friend struct ShapeBaseImageData;
friend void waterFind(SceneObject*, void*);
friend void physicalZoneFind(SceneObject*, void*);
// start jc
friend class ShapeBaseWebViewEvent;
// end jc

public:
typedef GameBase Parent;
@@ -684,7 +746,11 @@ class ShapeBase : public GameBase, public ISceneLight
MaxImageEmitters = 3,
NumImageBits = 3,
ShieldNormalBits = 8,
CollisionTimeoutValue = 250 ///< Timeout in ms.
//start pg
// CollisionTimeoutValue = 250 ///< Timeout in ms.
CollisionTimeoutValue = 64 ///< Timeout in ms.
// CollisionTimeoutValue = 25000 ///< Timeout in ms.
//end pg
};

/// This enum indexes into the sDamageStateName array
@@ -695,6 +761,14 @@ class ShapeBase : public GameBase, public ISceneLight
NumDamageStates,
NumDamageStateBits = 2, ///< Should be log2 of the number of states.
};
// start jc
enum InputEventsMethod {
MeshHit,
ConvexHit,
HybridHit,
BoxHit
};
// end jc

protected:
ShapeBaseData* mDataBlock; ///< Datablock
@@ -731,6 +805,12 @@ class ShapeBase : public GameBase, public ISceneLight
F32 timescale; ///< Timescale
U32 sound; ///< Handle to sound.
bool atEnd; ///< Are we at the end of this thread?
// start jc
#ifdef TORQUE_RESYNC_ANIM
F32 reSyncFactor; ///< Are we at the end of this thread?
F32 reSync; ///< Are we at the end of this thread?
#endif
// end jc
F32 position;
};
Thread mScriptThread[MaxScriptThreads];
@@ -873,6 +953,20 @@ class ShapeBase : public GameBase, public ISceneLight
Convex * mConvexList;
NetStringHandle mSkinNameHandle;
String mAppliedSkinName;
// start jc
WebViewData* mWebViewData;
SimObjectId mWebViewID;
bool mHasWebSkin;

bool mEnableInputEvents;
InputEventsMethod mInputEventsMethod;
U32 mTriggerStates;

/// If true each submesh within the TSShape is culled
/// against the object space frustum.
bool mMeshCulling;

// end jc

NetStringHandle mShapeNameHandle; ///< Name sent to client
/// @}
@@ -1002,6 +1096,16 @@ class ShapeBase : public GameBase, public ISceneLight
/// Do a reskin if necessary.
virtual void reSkin();

// start jc
void reSkinNewPath();
void reSkin(const char* oldSkin);
void webSkin();

// void onScaleChanged();

void setEnableInputEvents( bool enable );
// end jc

/// This recalculates the total mass of the object, and all mounted objects
void updateMass();

@@ -1155,7 +1259,9 @@ class ShapeBase : public GameBase, public ISceneLight
InvincibleMask = Parent::NextFreeMask << 5,
SkinMask = Parent::NextFreeMask << 6,
MeshHiddenMask = Parent::NextFreeMask << 7,
SoundMaskN = Parent::NextFreeMask << 8, ///< Extends + MaxSoundThreads bits
GravityMask = Parent::NextFreeMask << 8, // start jc
UVAnimMask = Parent::NextFreeMask << 9, // start pg
SoundMaskN = Parent::NextFreeMask << 10, ///< Extends + MaxSoundThreads bits
ThreadMaskN = SoundMaskN << MaxSoundThreads, ///< Extends + MaxScriptThreads bits
ImageMaskN = ThreadMaskN << MaxScriptThreads, ///< Extends + MaxMountedImage bits
NextFreeMask = ImageMaskN << MaxMountedImages
@@ -1175,6 +1281,9 @@ class ShapeBase : public GameBase, public ISceneLight
static F32 sCloakSpeed; // Time to cloak, in seconds

CubeReflector mCubeReflector;
// start jc
PlaneReflector mPlaneReflector;
// end jc

/// @name Initialization
/// @{
@@ -1184,6 +1293,16 @@ class ShapeBase : public GameBase, public ISceneLight
void onSceneRemove();
static void consoleInit();
bool onNewDataBlock( GameBaseData *dptr, bool reload );
// start jc
// static void initPersistFields();
void updateCollisionBox();
void setObjectBox(Box3F objBox);
Point2I getTextureResolution(U32 index);

bool rayCrossesTransparency(RayInfo* ri);
InputEventsMethod getInputEventsMethod() { return mInputEventsMethod; }

// end jc

/// @}

@@ -1195,6 +1314,40 @@ class ShapeBase : public GameBase, public ISceneLight
const char* getSkinName();
/// @}

//start pg
void cloneMaterial(String name);

void materialAnimStart(const char *baseMaterialName, const char *animMaterialPrefix,int frameCount, F32 animTime);
void materialAnimSetTime(F32 _time);
void materialAnimReset();
void materialAnimTick();

struct MaterialAnim{
NetStringHandle animName;
NetStringHandle animPrefix;
String oldSkinName;
F32 totalTime;
F32 time;
U32 frame;
U32 frameCount;
bool enabled;
};
MaterialAnim mMaterialAnim;


//end pg

// start jc
/// @name Node utility functions
/// @{
S32 findNode(const String &nodeName);
MatrixF getNodeTransform(S32 nodeIndex);
#ifdef TORQUE_CUBE_NODESCALES
Point3F getNodeScale(S32 nodeIndex);
#endif

/// @}
// end jc
/// @name Mesh Visibility
/// @{

@@ -1350,6 +1503,10 @@ class ShapeBase : public GameBase, public ISceneLight
/// @param pos Position
bool setThreadPosition( U32 slot, F32 pos );

// start jc
F32 getThreadPosition( U32 slot );
// end jc

/// Toggle the thread as reversed or normal (For example, sidestep-right reversed is sidestep-left)
/// @param slot Mount slot ID
/// @param forward True if the animation is to be played normally
@@ -1399,6 +1556,42 @@ class ShapeBase : public GameBase, public ISceneLight
virtual void getRenderMountTransform( F32 delta, S32 index, const MatrixF &xfm, MatrixF *outMat );
/// @}

// start jc

void setUrl(const char *url);
void setWebViewData(WebViewData* webview)
{
mWebViewData = webview;
setMaskBits(SkinMask);
}
WebViewData* getWebViewData()
{
return mWebViewData;
}
bool hasWebViewData()
{
return bool(mWebViewData);
}

S32 findNode(const String &name) const;
void getNodeWorldTransform(S32 nodeIndex, MatrixF* mat) const;

virtual void onMouseDown(const ShapeInputEvent & event);
virtual void onMouseUp(const ShapeInputEvent & event);
virtual void onMouseMove(const ShapeInputEvent & event);
virtual void onMouseDragged(const ShapeInputEvent & event);
virtual void onMouseEnter(const ShapeInputEvent & event);
virtual void onMouseLeave(const ShapeInputEvent & event);
virtual void onRightMouseDown(const ShapeInputEvent & event);
virtual void onRightMouseUp(const ShapeInputEvent & event);
virtual void onRightMouseDragged(const ShapeInputEvent & event);

virtual bool onTouchDown(const ShapeTouchEvent & event);
virtual bool onTouchMove(const ShapeTouchEvent & event);
virtual bool onTouchUp(const ShapeTouchEvent & event);

// end jc

/// Returns where the AI should be to repair this object
///
/// @note Legacy code from Tribes 2, but still works
@@ -1780,6 +1973,10 @@ class ShapeBase : public GameBase, public ISceneLight


void processTick(const Move *move);
// start jc
void interpolateTick(F32 delta);
// end jc

void advanceTime(F32 dt);

/// @name Rendering
@@ -1880,6 +2077,12 @@ class ShapeBase : public GameBase, public ISceneLight
};


// start jc
typedef ShapeBase::InputEventsMethod ShapeBaseInputEventsMethod;
DefineEnumType( ShapeBaseInputEventsMethod );
// end jc


//------------------------------------------------------------------------------
// inlines
//------------------------------------------------------------------------------
@@ -1825,6 +1825,11 @@ void ShapeBase::scriptCallback(U32 imageSlot,const char* function)

void ShapeBase::getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat )
{
// start jc
if(isServerObject())
mShapeInstance->animate(0);
// end jc

// Returns mount point to world space transform
if ( index >= 0 && index < SceneObject::NumMountPoints) {
S32 ni = mDataBlock->mountPointNode[index];
@@ -242,6 +242,10 @@ void StaticShape::processTick(const Move* move)

void StaticShape::interpolateTick(F32 delta)
{
// start jc
Parent::interpolateTick(delta);
// end jc

if (isMounted()) {
MatrixF mat;
mMount.object->getRenderMountTransform( delta, mMount.node, mMount.xfm, &mat );