mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 08:04:40 +00:00
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:
parent
f007700646
commit
f7f8faf47e
14 changed files with 1399 additions and 8 deletions
|
|
@ -404,6 +404,12 @@ void GameBase::processTick(const Move * move)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameBase::interpolateTick(F32 dt)
|
||||||
|
{
|
||||||
|
// PATHSHAPE
|
||||||
|
updateRenderChangesByParent();
|
||||||
|
// PATHSHAPE END
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 updateSkips)
|
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
|
// Weight by updateSkips
|
||||||
F32 wSkips = updateSkips * 0.5;
|
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
|
return
|
||||||
wFov * sUpFov +
|
wFov * sUpFov +
|
||||||
wDistance * sUpDistance +
|
wDistance * sUpDistance +
|
||||||
wVelocity * sUpVelocity +
|
wVelocity * sUpVelocity +
|
||||||
wSkips * sUpSkips +
|
wSkips * sUpSkips +
|
||||||
wInterest * sUpInterest;
|
wInterest * sUpInterest +
|
||||||
|
getNumChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
@ -757,3 +764,44 @@ DefineEngineMethod( GameBase, applyRadialImpulse, void, ( Point3F origin, F32 ra
|
||||||
{
|
{
|
||||||
object->applyRadialImpulse( origin, radius, magnitude );
|
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
|
||||||
|
|
|
||||||
|
|
@ -665,6 +665,9 @@ static void RegisterGameFunctions()
|
||||||
Con::setIntVariable("$TypeMasks::DebrisObjectType", DebrisObjectType);
|
Con::setIntVariable("$TypeMasks::DebrisObjectType", DebrisObjectType);
|
||||||
Con::setIntVariable("$TypeMasks::PhysicalZoneObjectType", PhysicalZoneObjectType);
|
Con::setIntVariable("$TypeMasks::PhysicalZoneObjectType", PhysicalZoneObjectType);
|
||||||
Con::setIntVariable("$TypeMasks::LightObjectType", LightObjectType);
|
Con::setIntVariable("$TypeMasks::LightObjectType", LightObjectType);
|
||||||
|
// PATHSHAPE
|
||||||
|
Con::setIntVariable("$TypeMasks::PathShapeObjectType", PathShapeObjectType);
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
|
Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
|
||||||
"InOut ease for curve movement.\n"
|
"InOut ease for curve movement.\n"
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,9 @@ void Item::interpolateTick(F32 dt)
|
||||||
mat.setColumn(3,pos);
|
mat.setColumn(3,pos);
|
||||||
setRenderTransform(mat);
|
setRenderTransform(mat);
|
||||||
mDelta.dt = dt;
|
mDelta.dt = dt;
|
||||||
|
// PATHSHAPE
|
||||||
|
updateRenderChangesByParent();
|
||||||
|
// PATHSHAPE END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,12 @@ enum SceneObjectTypes
|
||||||
#if defined(AFX_CAP_AFXMODEL_TYPE)
|
#if defined(AFX_CAP_AFXMODEL_TYPE)
|
||||||
afxModelObjectType = BIT(26)
|
afxModelObjectType = BIT(26)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
PathShapeObjectType = BIT( 28 ),
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SceneObjectTypeMasks : U32
|
enum SceneObjectTypeMasks : U32
|
||||||
|
|
|
||||||
588
Engine/source/T3D/pathShape.cpp
Normal file
588
Engine/source/T3D/pathShape.cpp
Normal 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();
|
||||||
|
}
|
||||||
114
Engine/source/T3D/pathShape.h
Normal file
114
Engine/source/T3D/pathShape.h
Normal 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
|
||||||
|
|
@ -120,7 +120,10 @@ static U32 sCollisionMoveMask = TerrainObjectType |
|
||||||
PlayerObjectType |
|
PlayerObjectType |
|
||||||
StaticShapeObjectType |
|
StaticShapeObjectType |
|
||||||
VehicleObjectType |
|
VehicleObjectType |
|
||||||
PhysicalZoneObjectType;
|
PhysicalZoneObjectType |
|
||||||
|
// PATHSHAPE
|
||||||
|
PathShapeObjectType;
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
static U32 sServerCollisionContactMask = sCollisionMoveMask |
|
static U32 sServerCollisionContactMask = sCollisionMoveMask |
|
||||||
ItemObjectType |
|
ItemObjectType |
|
||||||
|
|
@ -2206,6 +2209,9 @@ void Player::processTick(const Move* move)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// PATHSHAPE
|
||||||
|
if (!isGhost()) updateAttachment();
|
||||||
|
// PATHSHAPE END
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::interpolateTick(F32 dt)
|
void Player::interpolateTick(F32 dt)
|
||||||
|
|
@ -2239,6 +2245,9 @@ void Player::interpolateTick(F32 dt)
|
||||||
|
|
||||||
updateLookAnimation(dt);
|
updateLookAnimation(dt);
|
||||||
mDelta.dt = dt;
|
mDelta.dt = dt;
|
||||||
|
// PATHSHAPE
|
||||||
|
updateRenderChangesByParent();
|
||||||
|
// PATHSHAPE END
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::advanceTime(F32 dt)
|
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)
|
static void accel(F32& from, F32 to, F32 rate)
|
||||||
{
|
{
|
||||||
|
|
@ -4780,6 +4792,45 @@ bool Player::step(Point3F *pos,F32 *maxStep,F32 time)
|
||||||
return false;
|
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)
|
inline Point3F createInterpPos(const Point3F& s, const Point3F& e, const F32 t, const F32 d)
|
||||||
|
|
|
||||||
|
|
@ -614,6 +614,9 @@ protected:
|
||||||
void _handleCollision( const Collision &collision );
|
void _handleCollision( const Collision &collision );
|
||||||
virtual bool updatePos(const F32 travelTime = TickSec);
|
virtual bool updatePos(const F32 travelTime = TickSec);
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
void updateAttachment();
|
||||||
|
// PATHSHAPE END
|
||||||
///Update head animation
|
///Update head animation
|
||||||
void updateLookAnimation(F32 dT = 0.f);
|
void updateLookAnimation(F32 dT = 0.f);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
void StaticShape::setTransform(const MatrixF& mat)
|
||||||
{
|
{
|
||||||
Parent::setTransform(mat);
|
Parent::setTransform(mat);
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ public:
|
||||||
bool onNewDataBlock(GameBaseData *dptr, bool reload);
|
bool onNewDataBlock(GameBaseData *dptr, bool reload);
|
||||||
|
|
||||||
void processTick(const Move *move);
|
void processTick(const Move *move);
|
||||||
|
void interpolateTick(F32 delta);
|
||||||
void setTransform(const MatrixF &mat);
|
void setTransform(const MatrixF &mat);
|
||||||
|
|
||||||
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
|
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,13 @@ SceneObject::SceneObject()
|
||||||
mSceneObjectLinks = NULL;
|
mSceneObjectLinks = NULL;
|
||||||
|
|
||||||
mObjectFlags.set( RenderEnabledFlag | SelectionEnabledFlag );
|
mObjectFlags.set( RenderEnabledFlag | SelectionEnabledFlag );
|
||||||
|
// PATHSHAPE
|
||||||
|
// init the scenegraph relationships to indicate no parent, no children, and no siblings
|
||||||
|
mGraph.parent = NULL;
|
||||||
|
mGraph.nextSibling = NULL;
|
||||||
|
mGraph.firstChild = NULL;
|
||||||
|
mGraph.objToParent.identity();
|
||||||
|
// PATHSHAPE END
|
||||||
mIsScopeAlways = false;
|
mIsScopeAlways = false;
|
||||||
|
|
||||||
mAccuTex = NULL;
|
mAccuTex = NULL;
|
||||||
|
|
@ -330,6 +337,9 @@ void SceneObject::onRemove()
|
||||||
plUnlink();
|
plUnlink();
|
||||||
|
|
||||||
Parent::onRemove();
|
Parent::onRemove();
|
||||||
|
// PATHSHAPE
|
||||||
|
if ( getParent() != NULL) attachToParent( NULL);
|
||||||
|
// PATHSHAPE END
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -402,6 +412,9 @@ void SceneObject::setTransform( const MatrixF& mat )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PROFILE_SCOPE( SceneObject_setTransform );
|
PROFILE_SCOPE( SceneObject_setTransform );
|
||||||
|
// PATHSHAPE
|
||||||
|
PerformUpdatesForChildren(mat);
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
// Update the transforms.
|
// Update the transforms.
|
||||||
|
|
||||||
|
|
@ -876,6 +889,36 @@ U32 SceneObject::packUpdate( NetConnection* conn, U32 mask, BitStream* stream )
|
||||||
if ( stream->writeFlag( mask & FlagMask ) )
|
if ( stream->writeFlag( mask & FlagMask ) )
|
||||||
stream->writeRangedU32( (U32)mObjectFlags, 0, getObjectFlagMax() );
|
stream->writeRangedU32( (U32)mObjectFlags, 0, getObjectFlagMax() );
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
//Begin attachment
|
||||||
|
retMask = 0; //retry mask
|
||||||
|
|
||||||
|
if (stream->writeFlag(getParent() != NULL)) {
|
||||||
|
stream->writeAffineTransform(mGraph.objToParent);
|
||||||
|
}
|
||||||
|
if (stream->writeFlag(mask & MountedMask))
|
||||||
|
{
|
||||||
|
// Check to see if we need to write an object ID
|
||||||
|
if (stream->writeFlag(mGraph.parent)) {
|
||||||
|
S32 t = conn->getGhostIndex(mGraph.parent);
|
||||||
|
// Check to see if we can actually ghost this...
|
||||||
|
if (t == -1) {
|
||||||
|
// Cant, try again later
|
||||||
|
retMask |= MountedMask;
|
||||||
|
stream->writeFlag(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Can, write it.
|
||||||
|
stream->writeFlag(true);
|
||||||
|
stream->writeRangedU32(U32(t), 0, NetConnection::MaxGhostCount);
|
||||||
|
stream->writeAffineTransform(mGraph.objToParent);
|
||||||
|
//Con::errorf("%d: sent mounted on %d", getId(), mGraph.parent->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End of Attachment
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
if ( mask & MountedMask )
|
if ( mask & MountedMask )
|
||||||
{
|
{
|
||||||
if ( mMount.object )
|
if ( mMount.object )
|
||||||
|
|
@ -915,6 +958,44 @@ void SceneObject::unpackUpdate( NetConnection* conn, BitStream* stream )
|
||||||
if ( stream->readFlag() )
|
if ( stream->readFlag() )
|
||||||
mObjectFlags = stream->readRangedU32( 0, getObjectFlagMax() );
|
mObjectFlags = stream->readRangedU32( 0, getObjectFlagMax() );
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
// begin of attachment
|
||||||
|
if (stream->readFlag())
|
||||||
|
{
|
||||||
|
MatrixF m;
|
||||||
|
stream->readAffineTransform(&m);
|
||||||
|
mGraph.objToParent = m;
|
||||||
|
}
|
||||||
|
if (stream->readFlag())
|
||||||
|
{
|
||||||
|
// Check to see if we need to read an object ID
|
||||||
|
if (stream->readFlag())
|
||||||
|
{
|
||||||
|
// Check to see if we can actually ghost this...
|
||||||
|
if (stream->readFlag())
|
||||||
|
{
|
||||||
|
GameBase *newParent = static_cast<GameBase*>(conn->resolveGhost(stream->readRangedU32(0, NetConnection::MaxGhostCount)));
|
||||||
|
MatrixF m;
|
||||||
|
stream->readAffineTransform(&m);
|
||||||
|
|
||||||
|
if (getParent() != newParent)
|
||||||
|
{
|
||||||
|
clearProcessAfter();
|
||||||
|
processAfter(newParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
attachToParent(newParent, &m);
|
||||||
|
//Con::errorf("%d: got mounted on %d", getId(), mParentObject->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attachToParent(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End of attachment
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
// MountedMask
|
// MountedMask
|
||||||
if ( stream->readFlag() )
|
if ( stream->readFlag() )
|
||||||
{
|
{
|
||||||
|
|
@ -1479,6 +1560,9 @@ DefineEngineMethod( SceneObject, setTransform, void, ( TransformF txfm ),,
|
||||||
"Set the object's transform (orientation and position)."
|
"Set the object's transform (orientation and position)."
|
||||||
"@param txfm object transform to set" )
|
"@param txfm object transform to set" )
|
||||||
{
|
{
|
||||||
|
// PATHSHAPE
|
||||||
|
object->PerformUpdatesForChildren(txfm.getMatrix());
|
||||||
|
// PATHSHAPE END
|
||||||
if ( !txfm.hasRotation() )
|
if ( !txfm.hasRotation() )
|
||||||
object->setPosition( txfm.getPosition() );
|
object->setPosition( txfm.getPosition() );
|
||||||
else
|
else
|
||||||
|
|
@ -1552,3 +1636,356 @@ DefineEngineMethod(SceneObject, setForwardVector, void, (VectorF newForward, Vec
|
||||||
{
|
{
|
||||||
object->setForwardVector(newForward, upVector);
|
object->setForwardVector(newForward, upVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
// Move RenderTransform by set amount
|
||||||
|
// no longer used
|
||||||
|
|
||||||
|
void SceneObject::moveRender(const Point3F &delta)
|
||||||
|
{
|
||||||
|
Point3F pos;
|
||||||
|
|
||||||
|
const MatrixF& tmat = getRenderTransform();
|
||||||
|
tmat.getColumn(3,&pos);
|
||||||
|
AngAxisF aa(tmat);
|
||||||
|
pos += delta;
|
||||||
|
|
||||||
|
MatrixF mat;
|
||||||
|
aa.setMatrix(&mat);
|
||||||
|
mat.setColumn(3,pos);
|
||||||
|
setRenderTransform(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneObject::PerformUpdatesForChildren(MatrixF mat){
|
||||||
|
UpdateXformChange(mat);
|
||||||
|
for (U32 i=0; i < getNumChildren(); i++) {
|
||||||
|
SceneObject *o = getChild(i);
|
||||||
|
o->updateChildTransform(); //update the position of the child object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This function will move the players based on how much it's
|
||||||
|
// parent have moved
|
||||||
|
void SceneObject::updateChildTransform(){
|
||||||
|
if (getParent() != NULL){
|
||||||
|
MatrixF one;
|
||||||
|
MatrixF two;
|
||||||
|
MatrixF three;
|
||||||
|
MatrixF four;
|
||||||
|
MatrixF mat;
|
||||||
|
one= getTransform();
|
||||||
|
two = getParent()->getTransform();
|
||||||
|
one.affineInverse();
|
||||||
|
four.mul(two,one);
|
||||||
|
mat.mul(getParent()->mLastXform,getTransform());
|
||||||
|
setTransform(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will move the rendered image based on how much it's
|
||||||
|
// parent have moved since the processtick.
|
||||||
|
// For some reason the player object must be updated via it's GetRenderTransform seen below,
|
||||||
|
// Other objects seem to require getTransform() only
|
||||||
|
void SceneObject::updateRenderChangesByParent(){
|
||||||
|
if (getParent() != NULL){
|
||||||
|
MatrixF renderXform = getParent()->getRenderTransform();
|
||||||
|
MatrixF xform = getParent()->getTransform();
|
||||||
|
xform.affineInverse();
|
||||||
|
|
||||||
|
MatrixF offset;
|
||||||
|
offset.mul(renderXform, xform);
|
||||||
|
|
||||||
|
MatrixF mat;
|
||||||
|
|
||||||
|
//add the "offset" caused by the parents change, and add it to it's own
|
||||||
|
// This is needed by objects that update their own render transform thru interpolate tick
|
||||||
|
// Mostly for stationary objects.
|
||||||
|
|
||||||
|
if (getClassName() == "Player")
|
||||||
|
mat.mul(offset,getRenderTransform());
|
||||||
|
else
|
||||||
|
mat.mul(offset,getTransform());
|
||||||
|
setRenderTransform(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Ramen - Move Transform by set amount
|
||||||
|
//written by Anthony Lovell
|
||||||
|
void SceneObject::move(F32 x, F32 y, F32 z)
|
||||||
|
{
|
||||||
|
Point3F delta;
|
||||||
|
delta.x = x;
|
||||||
|
delta.y = y;
|
||||||
|
delta.z = z;
|
||||||
|
move(delta);
|
||||||
|
}
|
||||||
|
// move by a specified delta in root coordinate space
|
||||||
|
void SceneObject::move(const Point3F &delta)
|
||||||
|
{
|
||||||
|
Point3F pos;
|
||||||
|
|
||||||
|
const MatrixF& tmat = getTransform();
|
||||||
|
tmat.getColumn(3,&pos);
|
||||||
|
AngAxisF aa(tmat);
|
||||||
|
|
||||||
|
pos += delta;
|
||||||
|
|
||||||
|
MatrixF mat;
|
||||||
|
aa.setMatrix(&mat);
|
||||||
|
mat.setColumn(3,pos);
|
||||||
|
setTransform(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//written by Anthony Lovell ----------------------------------------------------------
|
||||||
|
U32
|
||||||
|
SceneObject::getNumChildren() const
|
||||||
|
{
|
||||||
|
U32 num = 0;
|
||||||
|
for (SceneObject *cur = mGraph.firstChild; cur; cur = cur->mGraph.nextSibling)
|
||||||
|
num++;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
//written by Anthony Lovell ----------------------------------------------------------
|
||||||
|
SceneObject *
|
||||||
|
SceneObject::getChild(U32 index) const
|
||||||
|
{
|
||||||
|
SceneObject *cur = mGraph.firstChild;
|
||||||
|
for (U32 i = 0;
|
||||||
|
cur && i < index;
|
||||||
|
i++)
|
||||||
|
cur = cur->mGraph.nextSibling;
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SceneObject::UpdateXformChange(const MatrixF &mat){
|
||||||
|
// This function gets the difference between the Transform and current Render transform
|
||||||
|
// Used for Interpolation matching with the child objects who rely on this data.
|
||||||
|
|
||||||
|
MatrixF oldxform = getTransform();
|
||||||
|
|
||||||
|
oldxform.affineInverse();
|
||||||
|
mLastXform.mul(mat,oldxform);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
bool
|
||||||
|
SceneObject::attachChildAt(SceneObject *subObject, MatrixF atThisOffset, S32 node)
|
||||||
|
{
|
||||||
|
AssertFatal(subObject, "attaching a null subObject");
|
||||||
|
AssertFatal(!isChildOf(subObject), "cyclic attachChild()");
|
||||||
|
bool b = subObject->attachToParent(this, &atThisOffset, node);
|
||||||
|
if (!b)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
bool
|
||||||
|
SceneObject::attachChildAt(SceneObject *subObject, Point3F atThisPosition)
|
||||||
|
{
|
||||||
|
AssertFatal(subObject, "attaching a null subObject");
|
||||||
|
AssertFatal(!isChildOf(subObject), "cyclic attachChild()");
|
||||||
|
bool b = subObject->attachToParent(this);
|
||||||
|
if (!b)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
subObject->mGraph.objToParent.setColumn(3, atThisPosition);
|
||||||
|
// calcTransformFromLocalTransform();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
bool
|
||||||
|
SceneObject::attachChild(SceneObject *child)
|
||||||
|
{
|
||||||
|
AssertFatal(child, "attaching a null subObject");
|
||||||
|
AssertFatal(!isChildOf(child), "cyclic attachChild()");
|
||||||
|
|
||||||
|
return child->attachToParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
/// returns a count of children plus their children, recursively
|
||||||
|
U32
|
||||||
|
SceneObject::getNumProgeny() const
|
||||||
|
{
|
||||||
|
U32 num = 0;
|
||||||
|
for (SceneObject *cur = mGraph.firstChild; cur; cur = cur->mGraph.nextSibling) {
|
||||||
|
num += 1 + cur->getNumProgeny();
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, getNumChildren, S32, (),, "returns number of direct child objects")
|
||||||
|
{
|
||||||
|
return object->getNumChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, getNumProgeny, S32, (),, "returns number of recursively-nested child objects")
|
||||||
|
{
|
||||||
|
return object->getNumProgeny();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, getChild, S32, (S32 _index), (0), "getChild(S32 index) -- returns child SceneObject at given index")
|
||||||
|
{
|
||||||
|
SceneObject *s = object->getChild(_index);
|
||||||
|
return s ? s->getId() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, attachChildAt, bool, (SceneObject* _subObject, MatrixF _offset, S32 _node), (nullAsType<SceneObject*>(), MatrixF::Identity, 0), "(SceneObject subObject, MatrixF offset, S32 offset)"
|
||||||
|
"Mount object to this one with the specified offset expressed in our coordinate space.")
|
||||||
|
{
|
||||||
|
if (_subObject != nullptr)
|
||||||
|
{
|
||||||
|
return object->attachChildAt(_subObject, _offset, _node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con::errorf("Couldn't addObject()!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, attachToParent, bool, (const char*_sceneObject), ,"attachToParent(SceneObject)"
|
||||||
|
"specify a null or non-null parent")
|
||||||
|
{
|
||||||
|
SceneObject * t;
|
||||||
|
|
||||||
|
if(Sim::findObject(_sceneObject, t))
|
||||||
|
{
|
||||||
|
return object->attachToParent(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((!dStrcmp("0", _sceneObject))|| (!dStrcmp("", _sceneObject)))
|
||||||
|
return object->attachToParent(NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con::errorf("Couldn't setParent()!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, getParent, S32, (),, "returns ID of parent SceneObject")
|
||||||
|
{
|
||||||
|
SceneObject *p = object->getParent();
|
||||||
|
return p ? p->getId() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, attachChild, bool, (const char*_subObject),, "(SceneObject subObject)"
|
||||||
|
"attach an object to this one, preserving its present transform.")
|
||||||
|
{
|
||||||
|
SceneObject * t;
|
||||||
|
MatrixF m;
|
||||||
|
if(Sim::findObject(_subObject, t))
|
||||||
|
return object->attachChild(t);
|
||||||
|
|
||||||
|
Con::errorf("Couldn't addObject()!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneObject::isChildOf(SceneObject *so)
|
||||||
|
{
|
||||||
|
SceneObject *p = mGraph.parent;
|
||||||
|
if (p) {
|
||||||
|
if (p == so)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return p->isChildOf(so);
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool SceneObject::attachToParent(SceneObject *newParent, MatrixF *atThisOffset/* = NULL */, S32 node )
|
||||||
|
{
|
||||||
|
SceneObject *oldParent = mGraph.parent;
|
||||||
|
|
||||||
|
if (oldParent == newParent)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// cycles in the scene hierarchy are forbidden!
|
||||||
|
// that is: a SceneObject cannot be a child of its progeny
|
||||||
|
if (newParent && newParent->isChildOf(this))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mGraph.parent = newParent;
|
||||||
|
|
||||||
|
if (oldParent) {
|
||||||
|
|
||||||
|
clearNotify(oldParent);
|
||||||
|
|
||||||
|
// remove this SceneObject from the list of children of oldParent
|
||||||
|
SceneObject *cur = oldParent->mGraph.firstChild;
|
||||||
|
if (cur == this) { // if we are the first child, this is easy
|
||||||
|
oldParent->mGraph.firstChild = mGraph.nextSibling;
|
||||||
|
} else {
|
||||||
|
while (cur->mGraph.nextSibling != this) {
|
||||||
|
cur = cur->mGraph.nextSibling;
|
||||||
|
// ASSERT cur != NULL;
|
||||||
|
}
|
||||||
|
cur->mGraph.nextSibling = mGraph.nextSibling;
|
||||||
|
}
|
||||||
|
oldParent->onLostChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newParent) {
|
||||||
|
|
||||||
|
deleteNotify(newParent); // if we are deleted, inform our parent
|
||||||
|
|
||||||
|
// add this SceneObject to the list of children of oldParent
|
||||||
|
mGraph.nextSibling = newParent->mGraph.firstChild;
|
||||||
|
newParent->mGraph.firstChild = this;
|
||||||
|
mGraph.parent = newParent;
|
||||||
|
|
||||||
|
newParent->onNewChild(this);
|
||||||
|
|
||||||
|
if (atThisOffset)
|
||||||
|
mGraph.objToParent = *atThisOffset;
|
||||||
|
} else {
|
||||||
|
mGraph.parent = NULL;
|
||||||
|
mGraph.nextSibling = NULL;
|
||||||
|
mGraph.objToParent = mObjToWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
onLostParent(oldParent);
|
||||||
|
onNewParent(newParent);
|
||||||
|
|
||||||
|
setMaskBits(MountedMask);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(SceneObject, detachChild, bool, (const char*_subObject),, "SceneObject subObject")
|
||||||
|
{
|
||||||
|
SceneObject * t;
|
||||||
|
if(Sim::findObject(_subObject, t)) {
|
||||||
|
return t->attachToParent(NULL);
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// subclasses can do something with these if they care to
|
||||||
|
void SceneObject::onNewParent(SceneObject *newParent) {}
|
||||||
|
void SceneObject::onLostParent(SceneObject *oldParent){}
|
||||||
|
void SceneObject::onNewChild(SceneObject *newKid){}
|
||||||
|
void SceneObject::onLostChild(SceneObject *lostKid){}
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,10 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
||||||
/// @name Transform and Collision Members
|
/// @name Transform and Collision Members
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
// PATHSHAPE
|
||||||
|
MatrixF mLastXform;
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
/// Transform from object space to world space.
|
/// Transform from object space to world space.
|
||||||
MatrixF mObjToWorld;
|
MatrixF mObjToWorld;
|
||||||
|
|
||||||
|
|
@ -819,6 +823,27 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
||||||
static bool _setAccuEnabled( void *object, const char *index, const char *data );
|
static bool _setAccuEnabled( void *object, const char *index, const char *data );
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
// PATHSHAPE
|
||||||
|
/// @}
|
||||||
|
//Anthony's Original Code, still used so i keep it here
|
||||||
|
/// TGE uses the term "mount" in a quirky, staticky way relating to its limited use to have
|
||||||
|
/// riders and guns mounted on a vehicle (and similar)
|
||||||
|
/// I did not alter that code at all (yet) and did not want to keep its terminology for other reasons
|
||||||
|
/// I decided to support a hierarchy of scene objects and dubbed the operations
|
||||||
|
/// attaching and removing child SceneObjects
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// this member struct tracks the relationship to parent and children
|
||||||
|
// sceneObjects in a hierarchical scene graph whose root is the entire Scene
|
||||||
|
struct AttachInfo {
|
||||||
|
SceneObject* firstChild; ///< Objects mounted on this object
|
||||||
|
SimObjectPtr<SceneObject> parent; ///< Object this object is mounted on.
|
||||||
|
SceneObject* nextSibling; ///< Link to next child object of this object's parent
|
||||||
|
MatrixF objToParent; ///< this obects transformation in the parent object's space
|
||||||
|
MatrixF RenderobjToParent; ///< this obects Render Offset transformation to the parent object
|
||||||
|
} mGraph;
|
||||||
|
// PATHSHAPE END
|
||||||
|
|
||||||
|
|
||||||
// Accumulation Texture
|
// Accumulation Texture
|
||||||
// Note: This was placed in SceneObject to both ShapeBase and TSStatic could support it.
|
// Note: This was placed in SceneObject to both ShapeBase and TSStatic could support it.
|
||||||
|
|
@ -841,6 +866,83 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
||||||
// as opposed to something like a Player that has a built-in camera that requires
|
// as opposed to something like a Player that has a built-in camera that requires
|
||||||
// special calculations to determine the view transform.
|
// special calculations to determine the view transform.
|
||||||
virtual bool isCamera() const { return false; }
|
virtual bool isCamera() const { return false; }
|
||||||
|
// AFX CODE BLOCK (is-camera) >>
|
||||||
|
// PATHSHAPE
|
||||||
|
// Added for dynamic attaching
|
||||||
|
void UpdateXformChange(const MatrixF &mat);
|
||||||
|
/// this is useful for setting NULL parent (making SceneObject a root object)
|
||||||
|
virtual bool attachToParent(SceneObject *parent, MatrixF *atThisOffset = NULL, S32 node=0);
|
||||||
|
SceneObject *getParent() { return mGraph.parent; };
|
||||||
|
|
||||||
|
|
||||||
|
/// attach a subobject, but do not alter the subObject's present absolute position or orientation
|
||||||
|
bool attachChild(SceneObject* subObject);
|
||||||
|
/// attach a subobject, at the specified offset expressed in our local coordinate space
|
||||||
|
bool attachChildAt(SceneObject* subObject, MatrixF atThisTransform, S32 node);
|
||||||
|
|
||||||
|
/// attach a subobject, at the specified position expressed in our local coordinate space
|
||||||
|
bool attachChildAt(SceneObject* subObject, Point3F atThisPosition);
|
||||||
|
|
||||||
|
/// how many child SceneObjects are (directly) attached to this one?
|
||||||
|
U32 getNumChildren() const;
|
||||||
|
|
||||||
|
/// how many child objects does this SceneObject have when we count them recursively?
|
||||||
|
U32 getNumProgeny() const;
|
||||||
|
|
||||||
|
/// returns the (direct) child SceneObject at the given index (0 <= index <= getNumChildren() - 1)
|
||||||
|
SceneObject *getChild(U32 index) const;
|
||||||
|
|
||||||
|
/// is this SceneObject a child (directly or indirectly) of the given object?
|
||||||
|
bool isChildOf(SceneObject *);
|
||||||
|
|
||||||
|
/// set position in parent SceneObject's coordinate space (or in world space if no parent)
|
||||||
|
//void setLocalPosition(const Point3F &pos);
|
||||||
|
|
||||||
|
/// move the object in parent SceneObject's coordinate space (or in world space if no parent)
|
||||||
|
//void localMove(const Point3F &delta);
|
||||||
|
/// as localMove(const Point3F &delta), with different signature
|
||||||
|
//void localMove(F32 x, F32 y, F32 z);
|
||||||
|
|
||||||
|
/// move the object in world space, without altering place in scene hierarchy
|
||||||
|
void move(const Point3F &delta);
|
||||||
|
|
||||||
|
// Does checks for children objects and updates their positions
|
||||||
|
void PerformUpdatesForChildren(MatrixF mat);
|
||||||
|
|
||||||
|
// Move the RenderTransform
|
||||||
|
void moveRender(const Point3F &delta);
|
||||||
|
//Calculate how much to adjust the render transform - Called by the child objects
|
||||||
|
void updateRenderChangesByParent();
|
||||||
|
//Calculate how much to adjust the transform - Called by the parent object
|
||||||
|
void updateChildTransform();
|
||||||
|
/// as move(const Point3F &delta), with different signature
|
||||||
|
void move(F32 x, F32 y, F32 z);
|
||||||
|
|
||||||
|
/// returns the transform relative to parent SceneObject transform (or world transform if no parent)
|
||||||
|
//const MatrixF& getLocalTransform() const;
|
||||||
|
/// returns the position within parent SceneObject space (or world space if no parent)
|
||||||
|
//Point3F getLocalPosition() const;
|
||||||
|
|
||||||
|
|
||||||
|
// virtual void onParentScaleChanged();
|
||||||
|
// virtual void onParentTransformChanged();
|
||||||
|
|
||||||
|
/// Sets the Object -> Parent transform. If no parent SceneObject, this is equivalent to
|
||||||
|
/// setTransform()
|
||||||
|
///
|
||||||
|
/// @param mat New transform matrix
|
||||||
|
//virtual void setLocalTransform(const MatrixF & mat);
|
||||||
|
|
||||||
|
|
||||||
|
/// Called to let instance specific code happen
|
||||||
|
virtual void onLostParent(SceneObject *oldParent);
|
||||||
|
/// Called to let instance specific code happen
|
||||||
|
virtual void onNewParent(SceneObject *newParent);
|
||||||
|
/// notification that a direct child object has been attached
|
||||||
|
virtual void onNewChild(SceneObject *subObject);
|
||||||
|
/// notification that a direct child object has been detached
|
||||||
|
virtual void onLostChild(SceneObject *subObject);
|
||||||
|
// PATHSHAPE END
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _SCENEOBJECT_H_
|
#endif // _SCENEOBJECT_H_
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include "core/stream/bitStream.h"
|
#include "core/stream/bitStream.h"
|
||||||
#include "renderInstance/renderPassManager.h"
|
#include "renderInstance/renderPassManager.h"
|
||||||
#include "console/engineAPI.h"
|
#include "console/engineAPI.h"
|
||||||
|
#include "T3D/pathShape.h"
|
||||||
|
|
||||||
#include "T3D/Scene.h"
|
#include "T3D/Scene.h"
|
||||||
|
|
||||||
|
|
@ -155,6 +156,11 @@ Path::Path()
|
||||||
{
|
{
|
||||||
mPathIndex = NoPathIndex;
|
mPathIndex = NoPathIndex;
|
||||||
mIsLooping = true;
|
mIsLooping = true;
|
||||||
|
mPathSpeed = 1.0f;
|
||||||
|
mDataBlock = NULL;
|
||||||
|
mSpawnCount = 1;
|
||||||
|
mMinDelay = 0;
|
||||||
|
mMaxDelay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path::~Path()
|
Path::~Path()
|
||||||
|
|
@ -166,6 +172,13 @@ Path::~Path()
|
||||||
void Path::initPersistFields()
|
void Path::initPersistFields()
|
||||||
{
|
{
|
||||||
addField("isLooping", TypeBool, Offset(mIsLooping, Path), "If this is true, the loop is closed, otherwise it is open.\n");
|
addField("isLooping", TypeBool, Offset(mIsLooping, Path), "If this is true, the loop is closed, otherwise it is open.\n");
|
||||||
|
addField("Speed", TypeF32, Offset(mPathSpeed, Path), "Speed.\n");
|
||||||
|
addProtectedField("mPathShape", TYPEID< PathShapeData >(), Offset(mDataBlock, Path),
|
||||||
|
&setDataBlockProperty, &defaultProtectedGetFn,
|
||||||
|
"@brief Spawned PathShape.\n\n");
|
||||||
|
addField("spawnCount", TypeS32, Offset(mSpawnCount, Path), "Spawn Count.\n");
|
||||||
|
addField("minDelay", TypeS32, Offset(mMinDelay, Path), "Spawn Delay (min).\n");
|
||||||
|
addField("maxDelay", TypeS32, Offset(mMaxDelay, Path), "Spawn Delay (max).\n");
|
||||||
|
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
//
|
//
|
||||||
|
|
@ -179,9 +192,14 @@ bool Path::onAdd()
|
||||||
if(!Parent::onAdd())
|
if(!Parent::onAdd())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
onAdd_callback(getId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK(Path, onAdd, void, (SimObjectId ID), (ID),
|
||||||
|
"Called when this ScriptGroup is added to the system.\n"
|
||||||
|
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||||
|
);
|
||||||
|
|
||||||
void Path::onRemove()
|
void Path::onRemove()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,17 +36,21 @@
|
||||||
#include "gfx/gfxPrimitiveBuffer.h"
|
#include "gfx/gfxPrimitiveBuffer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class BaseMatInstance;
|
#ifndef _STATICSHAPE_H_
|
||||||
|
#include "T3D/staticShape.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class BaseMatInstance;
|
||||||
|
struct PathShapeData;
|
||||||
|
|
||||||
namespace SimPath
|
namespace SimPath
|
||||||
{
|
{
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
/// A path!
|
/// A path!
|
||||||
class Path : public SimGroup
|
class Path : public GameBase
|
||||||
{
|
{
|
||||||
typedef SimGroup Parent;
|
typedef GameBase Parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum : U32
|
enum : U32
|
||||||
|
|
@ -57,8 +61,12 @@ class Path : public SimGroup
|
||||||
|
|
||||||
private:
|
private:
|
||||||
U32 mPathIndex;
|
U32 mPathIndex;
|
||||||
|
F32 mPathSpeed;
|
||||||
bool mIsLooping;
|
bool mIsLooping;
|
||||||
|
PathShapeData* mDataBlock;
|
||||||
|
S32 mSpawnCount;
|
||||||
|
S32 mMinDelay;
|
||||||
|
S32 mMaxDelay;
|
||||||
protected:
|
protected:
|
||||||
bool onAdd();
|
bool onAdd();
|
||||||
void onRemove();
|
void onRemove();
|
||||||
|
|
@ -77,6 +85,7 @@ class Path : public SimGroup
|
||||||
|
|
||||||
DECLARE_CONOBJECT(Path);
|
DECLARE_CONOBJECT(Path);
|
||||||
static void initPersistFields();
|
static void initPersistFields();
|
||||||
|
DECLARE_CALLBACK(void, onAdd, (SimObjectId ID));
|
||||||
};
|
};
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue