truly a community project, this has been kicking around since 2003 in various forms. adds a path following shape that can be ridden.

This commit is contained in:
AzaezelX 2020-01-11 23:58:30 -06:00
parent f007700646
commit f7f8faf47e
14 changed files with 1399 additions and 8 deletions

View file

@ -404,6 +404,12 @@ void GameBase::processTick(const Move * move)
#endif
}
void GameBase::interpolateTick(F32 dt)
{
// PATHSHAPE
updateRenderChangesByParent();
// PATHSHAPE END
}
//----------------------------------------------------------------------------
F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 updateSkips)
@ -471,14 +477,15 @@ F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 u
// Weight by updateSkips
F32 wSkips = updateSkips * 0.5;
// Calculate final priority, should total to about 1.0f
// Calculate final priority, should total to about 1.0f (plus children)
//
return
wFov * sUpFov +
wDistance * sUpDistance +
wVelocity * sUpVelocity +
wSkips * sUpSkips +
wInterest * sUpInterest;
wInterest * sUpInterest +
getNumChildren();
}
//----------------------------------------------------------------------------
@ -757,3 +764,44 @@ DefineEngineMethod( GameBase, applyRadialImpulse, void, ( Point3F origin, F32 ra
{
object->applyRadialImpulse( origin, radius, magnitude );
}
// PATHSHAPE
// Console Methods for attach children. can't put them in sceneobject because //
// we want the processafter functions////////////////////////////////////////////
DefineEngineMethod(GameBase, attachChild, bool, (GameBase* _subObject), (nullAsType<GameBase*>()), "(SceneObject subObject)"
"attach an object to this one, preserving its present transform.")
{
if (_subObject != nullptr)
{
if (_subObject->getParent() != object){
Con::errorf("Object is (%d)", _subObject->getId());
_subObject->clearProcessAfter();
_subObject->processAfter(object);
return object->attachChild(_subObject);
}
else
return false;
}
else
{
Con::errorf("Couldn't addObject()!");
return false;
}
}
DefineEngineMethod(GameBase, detachChild, bool, (GameBase* _subObject), (nullAsType<GameBase*>()), "(SceneObject subObject)"
"attach an object to this one, preserving its present transform.")
{
if (_subObject != nullptr)
{
_subObject->clearProcessAfter();
return _subObject->attachToParent(NULL);
}
else
{
return false;
}
}//end
// PATHSHAPE END

View file

@ -665,6 +665,9 @@ static void RegisterGameFunctions()
Con::setIntVariable("$TypeMasks::DebrisObjectType", DebrisObjectType);
Con::setIntVariable("$TypeMasks::PhysicalZoneObjectType", PhysicalZoneObjectType);
Con::setIntVariable("$TypeMasks::LightObjectType", LightObjectType);
// PATHSHAPE
Con::setIntVariable("$TypeMasks::PathShapeObjectType", PathShapeObjectType);
// PATHSHAPE END
Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
"InOut ease for curve movement.\n"

View file

@ -618,6 +618,9 @@ void Item::interpolateTick(F32 dt)
mat.setColumn(3,pos);
setRenderTransform(mat);
mDelta.dt = dt;
// PATHSHAPE
updateRenderChangesByParent();
// PATHSHAPE END
}

View file

@ -162,6 +162,12 @@ enum SceneObjectTypes
#if defined(AFX_CAP_AFXMODEL_TYPE)
afxModelObjectType = BIT(26)
#endif
// PATHSHAPE
PathShapeObjectType = BIT( 28 ),
// PATHSHAPE END
/// @}
};
enum SceneObjectTypeMasks : U32

View file

@ -0,0 +1,588 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
// @author Stefan "Beffy" Moises
// this is a modified version of PathCamera that allows to move shapes along paths
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "math/mMath.h"
#include "math/mathIO.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "core/dnet.h"
#include "scene/pathManager.h"
#include "T3D/gameFunctions.h"
#include "T3D/gameBase/gameConnection.h"
#include "gui/worldEditor/editor.h"
#include "console/engineAPI.h"
#include "math/mTransform.h"
#include "T3D/pathShape.h"
//----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(PathShapeData);
void PathShapeData::consoleInit()
{
}
bool PathShapeData::preload(bool server, String &errorStr)
{
if(!Parent::preload(server, errorStr))
return false;
return true;
}
void PathShapeData::initPersistFields()
{
Parent::initPersistFields();
}
void PathShapeData::packData(BitStream* stream)
{
Parent::packData(stream);
}
void PathShapeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
}
//----------------------------------------------------------------------------
IMPLEMENT_CO_NETOBJECT_V1(PathShape);
PathShape::PathShape()
{
mNetFlags.set(Ghostable|ScopeAlways);
mTypeMask |= PathShapeObjectType | StaticShapeObjectType;
delta.time = 0;
delta.timeVec = 0;
mDataBlock = NULL;
mState = Forward;
mNodeBase = 0;
mNodeCount = 0;
mPosition = 0;
mTarget = 0;
mTargetSet = false;
MatrixF mat(1);
mat.setPosition(Point3F(0,0,700));
Parent::setTransform(mat);
mLastXform = mat;
for (U32 i = 0; i < 4; i++)
{
mControl[i] = StringTable->insert("");
}
}
PathShape::~PathShape()
{
}
//----------------------------------------------------------------------------
bool PathShape::onAdd()
{
if(!Parent::onAdd() && !mDataBlock)
return false;
mTypeMask |= PathShapeObjectType | StaticShapeObjectType;
// Initialize from the current transform.
if (!mNodeCount) {
QuatF rot(getTransform());
Point3F pos = getPosition();
mSpline.removeAll();
mSpline.push_back(new CameraSpline::Knot(pos,rot,1,
CameraSpline::Knot::NORMAL, CameraSpline::Knot::SPLINE));
mNodeCount = 1;
}
if (isServerObject()) scriptOnAdd();
return true;
}
void PathShape::onRemove()
{
scriptOnRemove();
removeFromScene();
unmount();
Parent::onRemove();
if (isGhost())
for (S32 i = 0; i < MaxSoundThreads; i++)
stopAudio(i);
}
bool PathShape::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<PathShapeData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
scriptOnNewDataBlock();
return true;
}
PathShapeData::PathShapeData()
{
}
//----------------------------------------------------------------------------
void PathShape::initPersistFields()
{
addField( "Path", TYPEID< SimObjectRef<SimPath::Path> >(), Offset( mSimPath, PathShape ),
"@brief Name of a Path to follow." );
addField("Controler", TypeString, Offset(mControl, PathShape), 4, "controlers");
Parent::initPersistFields();
}
void PathShape::consoleInit()
{
}
//----------------------------------------------------------------------------
void PathShape::processTick(const Move* move)
{
// client and server
Parent::processTick(move);
// Move to new time
advancePosition(TickMs);
MatrixF mat;
interpolateMat(mPosition,&mat);
Parent::setTransform(mat);
updateContainer();
}
void PathShape::interpolateTick(F32 dt)
{
Parent::interpolateTick(dt);
MatrixF mat;
interpolateMat(delta.time + (delta.timeVec * dt),&mat);
Parent::setRenderTransform(mat);
}
void PathShape::interpolateMat(F32 pos,MatrixF* mat)
{
CameraSpline::Knot knot;
mSpline.value(pos - mNodeBase,&knot);
knot.mRotation.setMatrix(mat);
mat->setPosition(knot.mPosition);
}
void PathShape::advancePosition(S32 ms)
{
delta.timeVec = mPosition;
// Advance according to current speed
if (mState == Forward) {
mPosition = mSpline.advanceTime(mPosition - mNodeBase,ms);
if (mPosition > F32(mNodeCount - 1))
mPosition = F32(mNodeCount - 1);
mPosition += (F32)mNodeBase;
if (mTargetSet && mPosition >= mTarget) {
mTargetSet = false;
mPosition = mTarget;
mState = Stop;
}
}
else
if (mState == Backward) {
mPosition = mSpline.advanceTime(mPosition - mNodeBase,-ms);
if (mPosition < 0)
mPosition = 0;
mPosition += mNodeBase;
if (mTargetSet && mPosition <= mTarget) {
mTargetSet = false;
mPosition = mTarget;
mState = Stop;
}
}
// Script callbacks
if (int(mPosition) != int(delta.timeVec))
onNode(int(mPosition));
// Set frame interpolation
delta.time = mPosition;
delta.timeVec -= mPosition;
}
//----------------------------------------------------------------------------
void PathShape::setPosition(F32 pos)
{
mPosition = mClampF(pos,mNodeBase,mNodeBase + mNodeCount - 1);
MatrixF mat;
interpolateMat(mPosition,&mat);
Parent::setTransform(mat);
setMaskBits(PositionMask);
}
void PathShape::setTarget(F32 pos)
{
mTarget = pos;
mTargetSet = true;
if (mTarget > mPosition)
mState = Forward;
else
if (mTarget < mPosition)
mState = Backward;
else {
mTargetSet = false;
mState = Stop;
}
setMaskBits(TargetMask | StateMask);
}
void PathShape::setState(State s)
{
mState = s;
setMaskBits(StateMask);
}
S32 PathShape::getState()
{
return mState;
}
//-----------------------------------------------------------------------------
void PathShape::reset(F32 speed)
{
CameraSpline::Knot *knot = new CameraSpline::Knot;
mSpline.value(mPosition - mNodeBase,knot);
if (speed)
knot->mSpeed = speed;
mSpline.removeAll();
mSpline.push_back(knot);
mNodeBase = 0;
mNodeCount = 1;
mPosition = 0;
mTargetSet = false;
mState = Forward;
setMaskBits(StateMask | PositionMask | WindowMask | TargetMask);
}
void PathShape::pushBack(CameraSpline::Knot *knot)
{
// Make room at the end
if (mNodeCount == NodeWindow) {
delete mSpline.remove(mSpline.getKnot(0));
mNodeBase++;
}
else
mNodeCount++;
// Fill in the new node
mSpline.push_back(knot);
setMaskBits(WindowMask);
// Make sure the position doesn't fall off
if (mPosition < mNodeBase) {
mPosition = mNodeBase;
setMaskBits(PositionMask);
}
}
void PathShape::pushFront(CameraSpline::Knot *knot)
{
// Make room at the front
if (mNodeCount == NodeWindow)
delete mSpline.remove(mSpline.getKnot(mNodeCount));
else
mNodeCount++;
mNodeBase--;
// Fill in the new node
mSpline.push_front(knot);
setMaskBits(WindowMask);
// Make sure the position doesn't fall off
if (mPosition > mNodeBase + (NodeWindow - 1)) {
mPosition = mNodeBase + (NodeWindow - 1);
setMaskBits(PositionMask);
}
}
void PathShape::popFront()
{
if (mNodeCount < 2)
return;
// Remove the first node. Node base and position are unaffected.
mNodeCount--;
delete mSpline.remove(mSpline.getKnot(0));
}
//----------------------------------------------------------------------------
void PathShape::onNode(S32 node)
{
if (!isGhost())
Con::executef(mDataBlock,"onNode",getIdString(), Con::getIntArg(node));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
U32 PathShape::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
Parent::packUpdate(con,mask,stream);
if (stream->writeFlag(mask & StateMask))
stream->writeInt(mState,StateBits);
if (stream->writeFlag(mask & PositionMask))
stream->write(mPosition);
if (stream->writeFlag(mask & TargetMask))
if (stream->writeFlag(mTargetSet))
stream->write(mTarget);
if (stream->writeFlag(mask & WindowMask)) {
stream->write(mNodeBase);
stream->write(mNodeCount);
for (S32 i = 0; i < mNodeCount; i++) {
CameraSpline::Knot *knot = mSpline.getKnot(i);
mathWrite(*stream, knot->mPosition);
mathWrite(*stream, knot->mRotation);
stream->write(knot->mSpeed);
stream->writeInt(knot->mType, CameraSpline::Knot::NUM_TYPE_BITS);
stream->writeInt(knot->mPath, CameraSpline::Knot::NUM_PATH_BITS);
}
}
// The rest of the data is part of the control object packet update.
// If we're controlled by this client, we don't need to send it.
if(stream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
return 0;
return 0;
}
void PathShape::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con,stream);
// StateMask
if (stream->readFlag())
mState = stream->readInt(StateBits);
// PositionMask
if (stream->readFlag()) {
stream->read(&mPosition);
delta.time = mPosition;
delta.timeVec = 0;
}
// TargetMask
if (stream->readFlag()) {
mTargetSet = stream->readFlag();
if (mTargetSet) {
stream->read(&mTarget);
}
}
// WindowMask
if (stream->readFlag()) {
mSpline.removeAll();
stream->read(&mNodeBase);
stream->read(&mNodeCount);
for (S32 i = 0; i < mNodeCount; i++) {
CameraSpline::Knot *knot = new CameraSpline::Knot();
mathRead(*stream, &knot->mPosition);
mathRead(*stream, &knot->mRotation);
stream->read(&knot->mSpeed);
knot->mType = (CameraSpline::Knot::Type)stream->readInt(CameraSpline::Knot::NUM_TYPE_BITS);
knot->mPath = (CameraSpline::Knot::Path)stream->readInt(CameraSpline::Knot::NUM_PATH_BITS);
mSpline.push_back(knot);
}
}
// Controlled by the client?
if (stream->readFlag()) return;
}
//-----------------------------------------------------------------------------
// Console access methods
//-----------------------------------------------------------------------------
DefineEngineMethod(PathShape, setPosition, void, (F32 position), (0.0f), "Set the current position of the camera along the path.\n"
"@param position Position along the path, from 0.0 (path start) - 1.0 (path end), to place the camera.\n"
"@tsexample\n"
"// Set the camera on a position along its path from 0.0 - 1.0.\n"
"%position = \"0.35\";\n\n"
"// Force the pathCamera to its new position along the path.\n"
"%pathCamera.setPosition(%position);\n"
"@endtsexample\n")
{
object->setPosition(position);
}
DefineEngineMethod(PathShape, setTarget, void, (F32 position), (1.0f), "@brief Set the movement target for this camera along its path.\n\n"
"The camera will attempt to move along the path to the given target in the direction provided "
"by setState() (the default is forwards). Once the camera moves past this target it will come "
"to a stop, and the target state will be cleared.\n"
"@param position Target position, between 0.0 (path start) and 1.0 (path end), for the camera to move to along its path.\n"
"@tsexample\n"
"// Set the position target, between 0.0 (path start) and 1.0 (path end), for this camera to move to.\n"
"%position = \"0.50\";\n\n"
"// Inform the pathCamera of the new target position it will move to.\n"
"%pathCamera.setTarget(%position);\n"
"@endtsexample\n")
{
object->setTarget(position);
}
DefineEngineMethod(PathShape, setState, void, (const char* newState), ("forward"), "Set the movement state for this path camera.\n"
"@param newState New movement state type for this camera. Forward, Backward or Stop.\n"
"@tsexample\n"
"// Set the state type (forward, backward, stop).\n"
"// In this example, the camera will travel from the first node\n"
"// to the last node (or target if given with setTarget())\n"
"%state = \"forward\";\n\n"
"// Inform the pathCamera to change its movement state to the defined value.\n"
"%pathCamera.setState(%state);\n"
"@endtsexample\n")
{
if (!dStricmp(newState, "forward"))
object->setState(PathShape::Forward);
else
if (!dStricmp(newState, "backward"))
object->setState(PathShape::Backward);
else
object->setState(PathShape::Stop);
}
DefineEngineMethod(PathShape, reset, void, (F32 speed), (1.0f), "@brief Clear the camera's path and set the camera's current transform as the start of the new path.\n\n"
"What specifically occurs is a new knot is created from the camera's current transform. Then the current path "
"is cleared and the new knot is pushed onto the path. Any previous target is cleared and the camera's movement "
"state is set to Forward. The camera is now ready for a new path to be defined.\n"
"@param speed Speed for the camera to move along its path after being reset.\n"
"@tsexample\n"
"//Determine the new movement speed of this camera. If not set, the speed will default to 1.0.\n"
"%speed = \"0.50\";\n\n"
"// Inform the path camera to start a new path at"
"// the camera's current position, and set the new "
"// path's speed value.\n"
"%pathCamera.reset(%speed);\n"
"@endtsexample\n")
{
object->reset(speed);
}
static CameraSpline::Knot::Type resolveKnotType(const char *arg)
{
if (dStricmp(arg, "Position Only") == 0)
return CameraSpline::Knot::POSITION_ONLY;
if (dStricmp(arg, "Kink") == 0)
return CameraSpline::Knot::KINK;
return CameraSpline::Knot::NORMAL;
}
static CameraSpline::Knot::Path resolveKnotPath(const char *arg)
{
if (!dStricmp(arg, "Linear"))
return CameraSpline::Knot::LINEAR;
return CameraSpline::Knot::SPLINE;
}
DefineEngineMethod(PathShape, pushBack, void, (TransformF transform, F32 speed, const char* type, const char* path),
(TransformF::Identity, 1.0f, "Normal", "Linear"),
"@brief Adds a new knot to the back of a path camera's path.\n"
"@param transform Transform for the new knot. In the form of \"x y z ax ay az aa\" such as returned by SceneObject::getTransform()\n"
"@param speed Speed setting for this knot.\n"
"@param type Knot type (Normal, Position Only, Kink).\n"
"@param path %Path type (Linear, Spline).\n"
"@tsexample\n"
"// Transform vector for new knot. (Pos_X Pos_Y Pos_Z Rot_X Rot_Y Rot_Z Angle)\n"
"%transform = \"15.0 5.0 5.0 1.4 1.0 0.2 1.0\"\n\n"
"// Speed setting for knot.\n"
"%speed = \"1.0\"\n\n"
"// Knot type. (Normal, Position Only, Kink)\n"
"%type = \"Normal\";\n\n"
"// Path Type. (Linear, Spline)\n"
"%path = \"Linear\";\n\n"
"// Inform the path camera to add a new knot to the back of its path\n"
"%pathCamera.pushBack(%transform,%speed,%type,%path);\n"
"@endtsexample\n")
{
QuatF rot(transform.getOrientation());
object->pushBack(new CameraSpline::Knot(transform.getPosition(), rot, speed, resolveKnotType(type), resolveKnotPath(path)));
}
DefineEngineMethod(PathShape, pushFront, void, (TransformF transform, F32 speed, const char* type, const char* path),
(1.0f, "Normal", "Linear"),
"@brief Adds a new knot to the front of a path camera's path.\n"
"@param transform Transform for the new knot. In the form of \"x y z ax ay az aa\" such as returned by SceneObject::getTransform()\n"
"@param speed Speed setting for this knot.\n"
"@param type Knot type (Normal, Position Only, Kink).\n"
"@param path %Path type (Linear, Spline).\n"
"@tsexample\n"
"// Transform vector for new knot. (Pos_X,Pos_Y,Pos_Z,Rot_X,Rot_Y,Rot_Z,Angle)\n"
"%transform = \"15.0 5.0 5.0 1.4 1.0 0.2 1.0\"\n\n"
"// Speed setting for knot.\n"
"%speed = \"1.0\";\n\n"
"// Knot type. (Normal, Position Only, Kink)\n"
"%type = \"Normal\";\n\n"
"// Path Type. (Linear, Spline)\n"
"%path = \"Linear\";\n\n"
"// Inform the path camera to add a new knot to the front of its path\n"
"%pathCamera.pushFront(%transform, %speed, %type, %path);\n"
"@endtsexample\n")
{
QuatF rot(transform.getOrientation());
object->pushFront(new CameraSpline::Knot(transform.getPosition(), rot, speed, resolveKnotType(type), resolveKnotPath(path)));
}
DefineEngineMethod(PathShape, popFront, void, (), , "Removes the knot at the front of the camera's path.\n"
"@tsexample\n"
"// Remove the first knot in the camera's path.\n"
"%pathCamera.popFront();\n"
"@endtsexample\n")
{
object->popFront();
}
DefineEngineMethod(PathShape, getState, S32, (), , "PathShape.getState()")
{
return object->getState();
}

View file

@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _PATHSHAPE_H_
#define _PATHSHAPE_H_
#ifndef _STATICSHAPE_H_
#include "T3D/staticShape.h"
#endif
#ifndef _CAMERASPLINE_H_
#include "T3D/cameraSpline.h"
#endif
#ifndef _SIMPATH_H_
#include "scene/simPath.h"
#endif
//----------------------------------------------------------------------------
struct PathShapeData: public StaticShapeData {
typedef StaticShapeData Parent;
PathShapeData();
static void consoleInit();
DECLARE_CONOBJECT(PathShapeData);
bool preload(bool server, String &errorStr);
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
};
//----------------------------------------------------------------------------
class PathShape: public StaticShape
{
public:
enum State {
Forward,
Backward,
Stop,
StateBits = 3
};
private:
typedef StaticShape Parent;
enum MaskBits {
WindowMask = Parent::NextFreeMask,
PositionMask = WindowMask << 1,
TargetMask = PositionMask << 1,
StateMask = TargetMask << 1,
NextFreeMask = StateMask << 1
};
struct StateDelta {
F32 time;
F32 timeVec;
};
StateDelta delta;
enum Constants {
NodeWindow = 20 // Maximum number of active nodes
};
PathShapeData* mDataBlock;
CameraSpline mSpline;
S32 mNodeBase;
S32 mNodeCount;
F32 mPosition;
S32 mState;
F32 mTarget;
bool mTargetSet;
void interpolateMat(F32 pos,MatrixF* mat);
void advancePosition(S32 ms);
public:
DECLARE_CONOBJECT(PathShape);
PathShape();
~PathShape();
StringTableEntry mControl[4];
static void initPersistFields();
static void consoleInit();
bool onAdd();
void onRemove();
bool onNewDataBlock(GameBaseData* dptr, bool reload);
void onNode(S32 node);
void processTick(const Move*);
void interpolateTick(F32 dt);
U32 packUpdate(NetConnection *, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *, BitStream *stream);
void reset(F32 speed = 1);
void pushFront(CameraSpline::Knot *knot);
void pushBack(CameraSpline::Knot *knot);
void popFront();
void setPosition(F32 pos);
void setTarget(F32 pos);
void setState(State s);
S32 getState();
SimObjectRef< SimPath::Path > mSimPath;
};
#endif

View file

@ -120,7 +120,10 @@ static U32 sCollisionMoveMask = TerrainObjectType |
PlayerObjectType |
StaticShapeObjectType |
VehicleObjectType |
PhysicalZoneObjectType;
PhysicalZoneObjectType |
// PATHSHAPE
PathShapeObjectType;
// PATHSHAPE END
static U32 sServerCollisionContactMask = sCollisionMoveMask |
ItemObjectType |
@ -2206,6 +2209,9 @@ void Player::processTick(const Move* move)
}
}
}
// PATHSHAPE
if (!isGhost()) updateAttachment();
// PATHSHAPE END
}
void Player::interpolateTick(F32 dt)
@ -2239,6 +2245,9 @@ void Player::interpolateTick(F32 dt)
updateLookAnimation(dt);
mDelta.dt = dt;
// PATHSHAPE
updateRenderChangesByParent();
// PATHSHAPE END
}
void Player::advanceTime(F32 dt)
@ -3658,7 +3667,10 @@ void Player::updateDeathOffsets()
//----------------------------------------------------------------------------
static const U32 sPlayerConformMask = StaticShapeObjectType | StaticObjectType | TerrainObjectType;
// PATHSHAPE
static const U32 sPlayerConformMask = StaticShapeObjectType | StaticObjectType |
TerrainObjectType | PathShapeObjectType;
// PATHSHAPE END
static void accel(F32& from, F32 to, F32 rate)
{
@ -4780,6 +4792,45 @@ bool Player::step(Point3F *pos,F32 *maxStep,F32 time)
return false;
}
// PATHSHAPE
// This Function does a ray cast down to see if a pathshape object is below
// If so, it will attempt to attach to it.
void Player::updateAttachment(){
Point3F rot, pos;
RayInfo rInfo;
MatrixF mat = getTransform();
mat.getColumn(3, &pos);
if (gServerContainer.castRay(Point3F(pos.x, pos.y, pos.z + 0.1f),
Point3F(pos.x, pos.y, pos.z - 1.0f ),
PathShapeObjectType, &rInfo))
{
if( rInfo.object->getTypeMask() & PathShapeObjectType) //Ramen
{
if (getParent() == NULL)
{ // ONLY do this if we are not parented
//Con::printf("I'm on a pathshape object. Going to attempt attachment.");
ShapeBase* col = static_cast<ShapeBase*>(rInfo.object);
if (!isGhost())
{
this->attachToParent(col);
}
}
}
else
{
//Con::printf("object %i",rInfo.object->getId());
}
}
else
{
if (getParent() !=NULL)
{
clearProcessAfter();
attachToParent(NULL);
}
}
}
// PATHSHAPE END
//----------------------------------------------------------------------------
inline Point3F createInterpPos(const Point3F& s, const Point3F& e, const F32 t, const F32 d)

View file

@ -614,6 +614,9 @@ protected:
void _handleCollision( const Collision &collision );
virtual bool updatePos(const F32 travelTime = TickSec);
// PATHSHAPE
void updateAttachment();
// PATHSHAPE END
///Update head animation
void updateLookAnimation(F32 dT = 0.f);

View file

@ -246,6 +246,14 @@ void StaticShape::processTick(const Move* move)
}
}
void StaticShape::interpolateTick(F32 delta)
{
Parent::interpolateTick(delta);
// PATHSHAPE
updateRenderChangesByParent();
// PATHSHAPE END
}
void StaticShape::setTransform(const MatrixF& mat)
{
Parent::setTransform(mat);

View file

@ -84,6 +84,7 @@ public:
bool onNewDataBlock(GameBaseData *dptr, bool reload);
void processTick(const Move *move);
void interpolateTick(F32 delta);
void setTransform(const MatrixF &mat);
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);