Updates to component classes -

Shift from ghosted components to entity-managed for networking
Initial implementation of Systems through the Mesh Component
This commit is contained in:
Areloch 2018-01-28 14:57:02 -06:00
parent ae5a43de70
commit 68efd8e22a
15 changed files with 706 additions and 312 deletions

View file

@ -72,7 +72,6 @@ IMPLEMENT_CALLBACK(AnimationComponent, onAnimationTrigger, void, (Component* obj
AnimationComponent::AnimationComponent() : Component()
{
mNetworked = true;
mNetFlags.set(Ghostable | ScopeAlways);
mFriendlyName = "Animation(Component)";
mComponentType = "Render";
@ -223,31 +222,19 @@ U32 AnimationComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stre
{
U32 retMask = Parent::packUpdate(con, mask, stream);
//early test if we lack an owner, ghost-wise
//no point in trying, just re-queue the mask and go
if (!mOwner || con->getGhostIndex(mOwner) == -1)
/*for (int i = 0; i < MaxScriptThreads; i++)
{
stream->writeFlag(false);
return retMask |= ThreadMask;
}
else
{
stream->writeFlag(true);
for (int i = 0; i < MaxScriptThreads; i++)
Thread& st = mAnimationThreads[i];
if (stream->writeFlag((st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i))))
{
Thread& st = mAnimationThreads[i];
if (stream->writeFlag( (st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i)) ) )
{
stream->writeInt(st.sequence,ThreadSequenceBits);
stream->writeInt(st.state,2);
stream->write(st.timescale);
stream->write(st.position);
stream->writeFlag(st.atEnd);
stream->writeFlag(st.transition);
}
stream->writeInt(st.sequence, ThreadSequenceBits);
stream->writeInt(st.state, 2);
stream->write(st.timescale);
stream->write(st.position);
stream->writeFlag(st.atEnd);
stream->writeFlag(st.transition);
}
}
}*/
return retMask;
}
@ -256,29 +243,26 @@ void AnimationComponent::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con, stream);
if (stream->readFlag())
/*for (S32 i = 0; i < MaxScriptThreads; i++)
{
for (S32 i = 0; i < MaxScriptThreads; i++)
if (stream->readFlag())
{
if (stream->readFlag())
{
Thread& st = mAnimationThreads[i];
U32 seq = stream->readInt(ThreadSequenceBits);
st.state = stream->readInt(2);
stream->read( &st.timescale );
stream->read( &st.position );
st.atEnd = stream->readFlag();
bool transition = stream->readFlag();
Thread& st = mAnimationThreads[i];
U32 seq = stream->readInt(ThreadSequenceBits);
st.state = stream->readInt(2);
stream->read( &st.timescale );
stream->read( &st.position );
st.atEnd = stream->readFlag();
bool transition = stream->readFlag();
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
setThreadSequence(i, seq, false, transition);
else
updateThread(st);
}
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
setThreadSequence(i, seq, false, transition);
else
updateThread(st);
}
}
}*/
}
void AnimationComponent::processTick()
{
Parent::processTick();
@ -327,9 +311,6 @@ const char *AnimationComponent::getThreadSequenceName(U32 slot)
bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool transition, F32 transTime)
{
if (!mOwnerShapeInstance)
return false;
Thread& st = mAnimationThreads[slot];
if (st.thread && st.sequence == seq && st.state == Thread::Play && !reset)
return true;
@ -340,7 +321,6 @@ bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool t
if (seq < MaxSequenceIndex)
{
setMaskBits(-1);
setMaskBits(ThreadMaskN << slot);
st.sequence = seq;
st.transition = transition;
@ -647,7 +627,7 @@ void AnimationComponent::advanceThreads(F32 dt)
st.atEnd = true;
updateThread(st);
if (!isGhost())
if (!isClientObject())
{
Con::executef(this, "onAnimationEnd", st.thread->getSequenceName());
}
@ -660,7 +640,7 @@ void AnimationComponent::advanceThreads(F32 dt)
mOwnerShapeInstance->advanceTime(dt, st.thread);
}
if (mOwnerShapeInstance && !isGhost())
if (mOwnerShapeInstance && !isClientObject())
{
for (U32 i = 1; i < 32; i++)
{
@ -672,8 +652,16 @@ void AnimationComponent::advanceThreads(F32 dt)
}
}
if (isGhost())
if (isClientObject())
{
mOwnerShapeInstance->animate();
/*mOwnerShapeInstance->animateGround();
MatrixF groundTransform = mOwnerShapeInstance->getGroundTransform();
if (groundTransform != MatrixF::Identity)
{
mOwner->setPosition(groundTransform.getPosition());
}*/
}
}
}
}

View file

@ -79,6 +79,7 @@ CameraComponent::CameraComponent() : Component()
mTargetNode = "";
mUseParentTransform = true;
mNetworked = true;
mFriendlyName = "Camera(Component)";
}
@ -202,7 +203,7 @@ void CameraComponent::setCameraFov(F32 fov)
void CameraComponent::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery * query)
{
// update the camera query
query->camera = this;
query->camera = mOwner;//this;
if(GameConnection * con = dynamic_cast<GameConnection*>(cr))
{
@ -357,7 +358,8 @@ U32 CameraComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
mTargetNodeIdx = nodeIndex;
}
stream->writeInt(mTargetNodeIdx, 32);
if(stream->writeFlag(mTargetNodeIdx > -1))
stream->writeInt(mTargetNodeIdx, 32);
//send offsets here
stream->writeCompressedPoint(mPosOffset);
@ -382,7 +384,10 @@ void CameraComponent::unpackUpdate(NetConnection *con, BitStream *stream)
if(stream->readFlag())
{
mTargetNodeIdx = stream->readInt(32);
if (stream->readFlag())
mTargetNodeIdx = stream->readInt(32);
else
mTargetNodeIdx = -1;
stream->readCompressedPoint(&mPosOffset);

View file

@ -125,8 +125,6 @@ EndImplementEnumType;
//
CollisionComponent::CollisionComponent() : Component()
{
mNetFlags.set(Ghostable | ScopeAlways);
mFriendlyName = "Collision(Component)";
mOwnerRenderInterface = NULL;

View file

@ -31,6 +31,7 @@
#include "console/engineAPI.h"
#include "sim/netConnection.h"
#include "console/consoleInternal.h"
#include "T3D/assets/MaterialAsset.h"
#define DECLARE_NATIVE_COMPONENT( ComponentType ) \
Component* staticComponentTemplate = new ComponentType; \
@ -52,7 +53,6 @@ Component::Component()
mNetworked = false;
// [tom, 1/12/2007] We manage the memory for the description since it
// could be loaded from a file and thus massive. This is accomplished with
// protected fields, but since they still call Con::getData() the field
@ -66,7 +66,7 @@ Component::Component()
mOriginatingAssetId = StringTable->EmptyString();
mNetFlags.set(Ghostable);
mIsServerObject = true;
}
Component::~Component()
@ -198,7 +198,6 @@ void Component::onComponentRemove()
{
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
}
mOwner = NULL;
@ -212,7 +211,6 @@ void Component::setOwner(Entity* owner)
{
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
mOwner->removeComponent(this, false);
}
@ -223,11 +221,18 @@ void Component::setOwner(Entity* owner)
{
mOwner->onComponentAdded.notify(this, &Component::componentAddedToOwner);
mOwner->onComponentRemoved.notify(this, &Component::componentRemovedFromOwner);
mOwner->onTransformSet.notify(this, &Component::ownerTransformSet);
}
if (isServerObject())
{
setMaskBits(OwnerMask);
//if we have any outstanding maskbits, push them along to have the network update happen on the entity
if (mDirtyMaskBits != 0 && mOwner)
{
mOwner->setMaskBits(Entity::ComponentsUpdateMask);
}
}
}
void Component::componentAddedToOwner(Component *comp)
@ -240,16 +245,19 @@ void Component::componentRemovedFromOwner(Component *comp)
return;
}
void Component::ownerTransformSet(MatrixF *mat)
void Component::setMaskBits(U32 orMask)
{
return;
AssertFatal(orMask != 0, "Invalid net mask bits set.");
if (mOwner)
mOwner->setComponentNetMask(this, orMask);
}
U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
U32 retMask = 0;
if (mask & OwnerMask)
/*if (mask & OwnerMask)
{
if (mOwner != NULL)
{
@ -274,7 +282,7 @@ U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
}
}
else
stream->writeFlag(false);
stream->writeFlag(false);*/
if (stream->writeFlag(mask & EnableMask))
{
@ -299,9 +307,7 @@ U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
void Component::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con, stream);
if (stream->readFlag())
/*if (stream->readFlag())
{
if (stream->readFlag())
{
@ -317,7 +323,7 @@ void Component::unpackUpdate(NetConnection *con, BitStream *stream)
//it's being nulled out
setOwner(NULL);
}
}
}*/
if (stream->readFlag())
{
@ -467,7 +473,7 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
else if (fieldType == StringTable->insert("vector"))
fieldTypeMask = TypePoint3F;
else if (fieldType == StringTable->insert("material"))
fieldTypeMask = TypeMaterialName;
fieldTypeMask = TypeMaterialAssetPtr;
else if (fieldType == StringTable->insert("image"))
fieldTypeMask = TypeImageFilename;
else if (fieldType == StringTable->insert("shape"))
@ -488,6 +494,7 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
fieldTypeMask = TypeGameObjectAssetPtr;
else
fieldTypeMask = TypeString;
field.mFieldTypeName = fieldType;
field.mFieldType = fieldTypeMask;

View file

@ -64,9 +64,9 @@ struct ComponentField
///
///
//////////////////////////////////////////////////////////////////////////
class Component : public NetObject, public UpdateInterface
class Component : public SimObject, public UpdateInterface
{
typedef NetObject Parent;
typedef SimObject Parent;
protected:
StringTableEntry mFriendlyName;
@ -92,6 +92,10 @@ protected:
StringTableEntry mOriginatingAssetId;
AssetPtr<ComponentAsset> mOriginatingAsset;
U32 mDirtyMaskBits;
bool mIsServerObject;
public:
Component();
virtual ~Component();
@ -113,7 +117,8 @@ public:
//This is called when a different component is removed from our owner entity
virtual void componentRemovedFromOwner(Component *comp);
virtual void ownerTransformSet(MatrixF *mat);
//Overridden by components that actually care
virtual void ownerTransformSet(MatrixF *mat) {}
void setOwner(Entity* pOwner);
inline Entity *getOwner() { return mOwner ? mOwner : NULL; }
@ -190,6 +195,16 @@ public:
NextFreeMask = BIT(5)
};
virtual void setMaskBits(U32 orMask);
virtual void clearMaskBits() {
mDirtyMaskBits = 0;
}
bool isServerObject() { return mIsServerObject; }
bool isClientObject() { return !mIsServerObject; }
void setIsServerObject(bool isServerObj) { mIsServerObject = isServerObj; }
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
/// @}

View file

@ -57,7 +57,6 @@ StateMachineComponent::StateMachineComponent() : Component()
//doesn't need to be networked
mNetworked = false;
mNetFlags.clear();
}
StateMachineComponent::~StateMachineComponent()

View file

@ -288,7 +288,7 @@ void RigidBodyComponent::processTick()
return;
// SINGLE PLAYER HACK!!!!
if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
/*if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
{
RigidBodyComponent *servObj = (RigidBodyComponent*)getServerObject();
mOwner->setTransform(servObj->mState.getTransform());
@ -296,7 +296,7 @@ void RigidBodyComponent::processTick()
mRenderState[1] = servObj->mRenderState[1];
return;
}
}*/
// Store the last render state.
mRenderState[0] = mRenderState[1];

View file

@ -45,52 +45,49 @@
#include "core/strings/findMatch.h"
#include "T3D/components/render/meshComponent_ScriptBinding.h"
ImplementEnumType(BatchingMode,
"Type of mesh data available in a shape.\n"
"@ingroup gameObjects")
{
MeshComponent::Individual, "Individual", "This mesh is rendered indivudally, wthout batching or instancing."
},
{ MeshComponent::StaticBatch, "Static Batching", "Statically batches this mesh together with others to reduce drawcalls." },
//{ MeshComponent::DynamicBatch, "Dynamic Batching", "Dynamical batches this mesh together with others to reduce drawcalls each frame." },
// { MeshComponent::Instanced, "Instanced", "This mesh is rendered as an instance, reducing draw overhead with others that share the same mesh and material." },
EndImplementEnumType;
//////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
//////////////////////////////////////////////////////////////////////////
MeshComponent::MeshComponent() : Component()
{
mShapeName = StringTable->insert("");
mShapeAsset = StringTable->insert("");
mShapeInstance = NULL;
mChangingMaterials.clear();
mMaterials.clear();
mFriendlyName = "Mesh Component";
mComponentType = "Render";
mDescription = getDescriptionText("Causes the object to render a non-animating 3d shape using the file provided.");
mNetworked = true;
mNetFlags.set(Ghostable | ScopeAlways);
mShapeName = StringTable->EmptyString();
mShapeAsset = StringTable->EmptyString();
mMeshAsset = StringTable->EmptyString();
mMeshAssetId = StringTable->EmptyString();
mInterfaceData = new MeshRenderSystemInterface();
mRenderMode = Individual;
}
MeshComponent::~MeshComponent(){}
MeshComponent::~MeshComponent()
{
if (mInterfaceData)
SAFE_DELETE(mInterfaceData);
}
IMPLEMENT_CO_NETOBJECT_V1(MeshComponent);
//==========================================================================================
void MeshComponent::boneObject::addObject(SimObject* object)
{
SceneObject* sc = dynamic_cast<SceneObject*>(object);
if(sc && mOwner)
{
if(TSShape* shape = mOwner->getShape())
{
S32 nodeID = shape->findNode(mBoneName);
//we may have a offset on the shape's center
//so make sure we accomodate for that when setting up the mount offsets
MatrixF mat = mOwner->getNodeTransform(nodeID);
mOwner->getOwner()->mountObject(sc, nodeID, mat);
}
}
}
bool MeshComponent::onAdd()
{
if(! Parent::onAdd())
@ -106,6 +103,12 @@ void MeshComponent::onComponentAdd()
{
Parent::onComponentAdd();
if (isClientObject())
mInterfaceData->mIsClient = true;
// if (mInterfaceData != nullptr)
// mInterfaceData->mIsClient = isClientObject();
//get the default shape, if any
updateShape();
}
@ -113,10 +116,6 @@ void MeshComponent::onComponentAdd()
void MeshComponent::onRemove()
{
Parent::onRemove();
mMeshAsset.clear();
SAFE_DELETE(mShapeInstance);
}
void MeshComponent::onComponentRemove()
@ -135,9 +134,14 @@ void MeshComponent::initPersistFields()
{
Parent::initPersistFields();
addGroup("Rendering");
addField("BatchingMode", TypeBatchingMode, Offset(mRenderMode, MeshComponent),
"The mode of batching this shape should be rendered with.");
endGroup("Rendering");
//create a hook to our internal variables
addGroup("Model");
addProtectedField("MeshAsset", TypeAssetId, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
addProtectedField("MeshAsset", TypeShapeAssetPtr, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
"The asset Id used for the mesh.", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
endGroup("Model");
}
@ -165,6 +169,9 @@ bool MeshComponent::_setShape( void *object, const char *index, const char *data
bool MeshComponent::setMeshAsset(const char* assetName)
{
// Fetch the asset Id.
if (mInterfaceData == nullptr)
return false;
mMeshAssetId = StringTable->insert(assetName);
mMeshAsset = mMeshAssetId;
@ -183,9 +190,129 @@ bool MeshComponent::setMeshAsset(const char* assetName)
return true;
}
void MeshComponent::updateShape()
{
if (mInterfaceData == nullptr)
return;
//if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
if ((mShapeName && mShapeName[0] != '\0') || (mMeshAssetId && mMeshAssetId[0] != '\0'))
{
if (mMeshAsset == NULL)
return;
mShape = mMeshAsset->getShape();
if (!mMeshAsset->getShape())
return;
setupShape();
//Do this on both the server and client
S32 materialCount = mMeshAsset->getShape()->materialList->getMaterialNameList().size();
if (isServerObject())
{
//we need to update the editor
for (U32 i = 0; i < mFields.size(); i++)
{
//find any with the materialslot title and clear them out
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
{
setDataField(mFields[i].mFieldName, NULL, "");
mFields.erase(i);
continue;
}
}
//next, get a listing of our materials in the shape, and build our field list for them
char matFieldName[128];
if (materialCount > 0)
mComponentGroup = StringTable->insert("Materials");
for (U32 i = 0; i < materialCount; i++)
{
String materialname = mMeshAsset->getShape()->materialList->getMaterialName(i);
if (materialname == String("ShapeBounds"))
continue;
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
addComponentField(matFieldName, "A material used in the shape file", "Material", materialname, "");
}
if (materialCount > 0)
mComponentGroup = "";
}
if (mOwner != NULL)
{
Point3F min, max, pos;
pos = mOwner->getPosition();
mOwner->getWorldToObj().mulP(pos);
min = mMeshAsset->getShape()->bounds.minExtents;
max = mMeshAsset->getShape()->bounds.maxExtents;
if (mInterfaceData)
{
mInterfaceData->mBounds.set(min, max);
mInterfaceData->mScale = mOwner->getScale();
mInterfaceData->mTransform = mOwner->getRenderTransform();
}
mOwner->setObjectBox(Box3F(min, max));
mOwner->resetWorldBox();
if (mOwner->getSceneManager() != NULL)
mOwner->getSceneManager()->notifyObjectDirty(mOwner);
}
if (isClientObject() && mInterfaceData)
{
if (mRenderMode == StaticBatch)
{
mInterfaceData->mStatic = true;
OptimizedPolyList geom;
MatrixF transform = mInterfaceData->mTransform;
mInterfaceData->mGeometry.setTransform(&transform, mInterfaceData->mScale);
mInterfaceData->mGeometry.setObject(mOwner);
mInterfaceData->mShapeInstance->buildPolyList(&mInterfaceData->mGeometry, 0);
}
else
{
mInterfaceData->mStatic = false;
}
MeshRenderSystem::rebuildBuffers();
}
//finally, notify that our shape was changed
onShapeInstanceChanged.trigger(this);
}
}
void MeshComponent::setupShape()
{
mInterfaceData->mShapeInstance = new TSShapeInstance(mMeshAsset->getShape(), true);
}
void MeshComponent::_onResourceChanged( const Torque::Path &path )
{
if ( path != Torque::Path( mShapeName ) )
if (mInterfaceData == nullptr)
return;
String filePath;
if (mMeshAsset)
filePath = Torque::Path(mMeshAsset->getShapeFilename());
if (!mMeshAsset || path != Torque::Path(mMeshAsset->getShapeFilename()) )
return;
updateShape();
@ -216,6 +343,8 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
if (stream->writeFlag(mask & ShapeMask))
{
stream->writeString(mShapeName);
stream->writeInt(mRenderMode, 8);
}
if (stream->writeFlag( mask & MaterialMask ))
@ -226,7 +355,7 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
stream->writeInt(mChangingMaterials[i].slot, 16);
NetStringHandle matNameStr = mChangingMaterials[i].matName.c_str();
NetStringHandle matNameStr = mChangingMaterials[i].assetId.c_str();
con->packNetStringHandleU(stream, matNameStr);
}
@ -243,6 +372,8 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
if(stream->readFlag())
{
mShapeName = stream->readSTString();
mRenderMode = (RenderMode)stream->readInt(8);
setMeshAsset(mShapeName);
updateShape();
}
@ -256,7 +387,10 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
{
matMap newMatMap;
newMatMap.slot = stream->readInt(16);
newMatMap.matName = String(con->unpackNetStringHandleU(stream).getString());
newMatMap.assetId = String(con->unpackNetStringHandleU(stream).getString());
//do the lookup, now
newMatMap.matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newMatMap.assetId);
mChangingMaterials.push_back(newMatMap);
}
@ -267,7 +401,7 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
void MeshComponent::prepRenderImage( SceneRenderState *state )
{
if (!mEnabled || !mOwner || !mShapeInstance)
/*if (!mEnabled || !mOwner || !mShapeInstance)
return;
Point3F cameraOffset;
@ -300,114 +434,41 @@ void MeshComponent::prepRenderImage( SceneRenderState *state )
rdata.setLightQuery(&query);
MatrixF mat = mOwner->getRenderTransform();
Point3F renderPos = mat.getPosition();
EulerF renderRot = mat.toEuler();
if (mOwner->isMounted())
{
MatrixF wrldPos = mOwner->getWorldTransform();
Point3F wrldPosPos = wrldPos.getPosition();
Point3F mntPs = mat.getPosition();
EulerF mntRt = RotationF(mat).asEulerF();
bool tr = true;
}
mat.scale(objScale);
GFX->setWorldMatrix(mat);
mShapeInstance->render(rdata);
}
void MeshComponent::updateShape()
{
bool isServer = isServerObject();
if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
{
if (mMeshAsset == NULL)
return;
mShape = mMeshAsset->getShape();
if (!mShape)
return;
setupShape();
//Do this on both the server and client
S32 materialCount = mShape->materialList->getMaterialNameList().size();
if(isServerObject())
{
//we need to update the editor
for (U32 i = 0; i < mFields.size(); i++)
{
//find any with the materialslot title and clear them out
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
{
setDataField(mFields[i].mFieldName, NULL, "");
mFields.erase(i);
continue;
}
}
//next, get a listing of our materials in the shape, and build our field list for them
char matFieldName[128];
if(materialCount > 0)
mComponentGroup = StringTable->insert("Materials");
for(U32 i=0; i < materialCount; i++)
{
String materialname = mShape->materialList->getMaterialName(i);
if(materialname == String("ShapeBounds"))
continue;
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
addComponentField(matFieldName, "A material used in the shape file", "TypeAssetId", materialname, "");
}
if(materialCount > 0)
mComponentGroup = "";
}
if(mOwner != NULL)
{
Point3F min, max, pos;
pos = mOwner->getPosition();
mOwner->getWorldToObj().mulP(pos);
min = mShape->bounds.minExtents;
max = mShape->bounds.maxExtents;
mShapeBounds.set(min, max);
mOwner->setObjectBox(Box3F(min, max));
if( mOwner->getSceneManager() != NULL )
mOwner->getSceneManager()->notifyObjectDirty( mOwner );
}
//finally, notify that our shape was changed
onShapeInstanceChanged.trigger(this);
}
}
void MeshComponent::setupShape()
{
mShapeInstance = new TSShapeInstance(mShape, true);
mShapeInstance->render(rdata);*/
}
void MeshComponent::updateMaterials()
{
if (mChangingMaterials.empty() || !mShape)
if (mChangingMaterials.empty() || !mMeshAsset->getShape())
return;
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
const Vector<String> &materialNames = pMatList->getMaterialNameList();
for ( S32 i = 0; i < materialNames.size(); i++ )
{
const String &pName = materialNames[i];
for(U32 m=0; m < mChangingMaterials.size(); m++)
{
if(mChangingMaterials[m].slot == i)
{
pMatList->renameMaterial( i, mChangingMaterials[m].matName );
//Fetch the actual material asset
pMatList->renameMaterial( i, mChangingMaterials[m].matAsset->getMaterialDefinitionName());
}
}
@ -415,22 +476,31 @@ void MeshComponent::updateMaterials()
}
// Initialize the material instances
mShapeInstance->initMaterialList();
mInterfaceData->mShapeInstance->initMaterialList();
}
MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
{
if (mShape)
if (mInterfaceData != nullptr && mMeshAsset->getShape())
{
S32 nodeCount = getShape()->nodes.size();
if(nodeIdx >= 0 && nodeIdx < nodeCount)
{
//animate();
MatrixF mountTransform = mShapeInstance->mNodeTransforms[nodeIdx];
mountTransform.mul(mOwner->getRenderTransform());
MatrixF nodeTransform = mInterfaceData->mShapeInstance->mNodeTransforms[nodeIdx];
const Point3F& scale = mOwner->getScale();
return mountTransform;
// The position of the node needs to be scaled.
Point3F position = nodeTransform.getPosition();
position.convolve(scale);
nodeTransform.setPosition(position);
MatrixF finalTransform = MatrixF::Identity;
finalTransform.mul(mOwner->getRenderTransform(), nodeTransform);
return finalTransform;
}
}
@ -439,7 +509,7 @@ MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
S32 MeshComponent::getNodeByName(String nodeName)
{
if (mShape)
if (mMeshAsset->getShape())
{
S32 nodeIdx = getShape()->findNode(nodeName);
@ -485,12 +555,18 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
if(slot == -1)
return;
//Safe to assume the inbound value for the material will be a MaterialAsset, so lets do a lookup on the name
MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newValue);
if (!matAsset)
return;
bool found = false;
for(U32 i=0; i < mChangingMaterials.size(); i++)
{
if(mChangingMaterials[i].slot == slot)
{
mChangingMaterials[i].matName = String(newValue);
mChangingMaterials[i].matAsset = matAsset;
mChangingMaterials[i].assetId = newValue;
found = true;
}
}
@ -499,7 +575,8 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
{
matMap newMatMap;
newMatMap.slot = slot;
newMatMap.matName = String(newValue);
newMatMap.matAsset = matAsset;
newMatMap.assetId = newValue;
mChangingMaterials.push_back(newMatMap);
}
@ -510,14 +587,31 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
Parent::onDynamicModified(slotName, newValue);
}
void MeshComponent::changeMaterial(U32 slot, const char* newMat)
void MeshComponent::changeMaterial(U32 slot, MaterialAsset* newMat)
{
char fieldName[512];
//update our respective field
dSprintf(fieldName, 512, "materialSlot%d", slot);
setDataField(fieldName, NULL, newMat);
setDataField(fieldName, NULL, newMat->getAssetId());
}
bool MeshComponent::setMatInstField(U32 slot, const char* field, const char* value)
{
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
MaterialParameters* params = pMatList->getMaterialInst(slot)->getMaterialParameters();
if (pMatList->getMaterialInst(slot)->getFeatures().hasFeature(MFT_DiffuseColor))
{
MaterialParameterHandle* handle = pMatList->getMaterialInst(slot)->getMaterialParameterHandle("DiffuseColor");
params->set(handle, LinearColorF(0, 0, 0));
}
return true;
}
void MeshComponent::onInspect()
@ -526,4 +620,13 @@ void MeshComponent::onInspect()
void MeshComponent::onEndInspect()
{
}
void MeshComponent::ownerTransformSet(MatrixF *mat)
{
if (mInterfaceData != nullptr)
{
MatrixF newTransform = *mat;
mInterfaceData->mTransform = newTransform;
}
}

View file

@ -60,6 +60,8 @@
#include "gfx/gfxVertexFormat.h"
#endif
#include "T3D/systems/render/meshRenderSystem.h"
class TSShapeInstance;
class SceneRenderState;
//////////////////////////////////////////////////////////////////////////
@ -84,37 +86,38 @@ protected:
StringTableEntry mShapeName;
StringTableEntry mShapeAsset;
TSShape* mShape;
Box3F mShapeBounds;
//Box3F mShapeBounds;
Point3F mCenterOffset;
MeshRenderSystemInterface* mInterfaceData;
struct matMap
{
String matName;
MaterialAsset* matAsset;
String assetId;
U32 slot;
};
Vector<matMap> mChangingMaterials;
Vector<matMap> mMaterials;
class boneObject : public SimGroup
public:
enum RenderMode
{
MeshComponent *mOwner;
public:
boneObject(MeshComponent *owner){ mOwner = owner; }
StringTableEntry mBoneName;
S32 mItemID;
virtual void addObject(SimObject *obj);
Individual = 0,
DynamicBatch,
StaticBatch,
Instanced
};
Vector<boneObject*> mNodesList;
protected:
RenderMode mRenderMode;
public:
StringTableEntry mMeshAssetId;
AssetPtr<ShapeAsset> mMeshAsset;
TSShapeInstance* mShapeInstance;
//TSShapeInstance* mShapeInstance;
public:
MeshComponent();
@ -132,7 +135,7 @@ public:
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
Box3F getShapeBounds() { return mShapeBounds; }
Box3F getShapeBounds() { return mInterfaceData->mBounds; }
virtual MatrixF getNodeTransform(S32 nodeIdx);
S32 getNodeByName(String nodeName);
@ -144,6 +147,8 @@ public:
virtual void onComponentRemove();
virtual void onComponentAdd();
virtual void ownerTransformSet(MatrixF *mat);
static bool _setMesh(void *object, const char *index, const char *data);
static bool _setShape(void *object, const char *index, const char *data);
const char* _getShape(void *object, const char *data);
@ -151,7 +156,7 @@ public:
bool setMeshAsset(const char* assetName);
virtual TSShape* getShape() { if (mMeshAsset) return mMeshAsset->getShape(); else return NULL; }
virtual TSShapeInstance* getShapeInstance() { return mShapeInstance; }
virtual TSShapeInstance* getShapeInstance() { return mInterfaceData->mShapeInstance; }
Resource<TSShape> getShapeResource() { return mMeshAsset->getShapeResource(); }
@ -163,7 +168,8 @@ public:
virtual void onDynamicModified(const char* slotName, const char* newValue);
void changeMaterial(U32 slot, const char* newMat);
void changeMaterial(U32 slot, MaterialAsset* newMat);
bool setMatInstField(U32 slot, const char* field, const char* value);
virtual void onInspect();
virtual void onEndInspect();
@ -180,4 +186,7 @@ public:
}
};
typedef MeshComponent::RenderMode BatchingMode;
DefineEnumType(BatchingMode);
#endif

View file

@ -126,6 +126,28 @@ DefineEngineMethod(MeshComponent, getNodePosition, Point3F,
return Point3F(0, 0, 0);
}
DefineEngineMethod(MeshComponent, getNodeRotation, EulerF,
(S32 node), (-1),
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
"@param objB Object to mount onto us\n"
"@param slot Mount slot ID\n"
"@param txfm (optional) mount offset transform\n"
"@return true if successful, false if failed (objB is not valid)")
{
if (node != -1)
{
//BUG: Unsure how it broke, but atm the default transform passed in here is rotated 180 degrees. This doesn't happen
//for the SceneObject mountobject method. Hackish, but for now, just default to a clean MatrixF::Identity
//object->mountObjectToNode( objB, node, /*MatrixF::Identity*/txfm.getMatrix() );
RotationF mat = object->getNodeTransform(node);
return mat.asEulerF(RotationF::Degrees);
}
return EulerF(0, 0, 0);
}
DefineEngineMethod(MeshComponent, getNodeByName, S32,
(String nodeName), ,
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
@ -148,8 +170,14 @@ DefineEngineMethod(MeshComponent, getNodeByName, S32,
return -1;
}
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, const char* newMat), (0, ""),
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, MaterialAsset* newMat), (0, nullAsType<MaterialAsset*>()),
"@brief Change one of the materials on the shape.\n\n")
{
object->changeMaterial(slot, newMat);
}
DefineEngineMethod(MeshComponent, setMatInstField, bool, (U32 slot, const char* field, const char* value), (0, "", ""),
"@brief Change one of the materials on the shape.\n\n")
{
return object->setMatInstField(slot, field, value);
}

View file

@ -47,7 +47,9 @@
#include "T3D/gameBase/std/stdMoveList.h"
#include "T3D/prefab.h"
#include "T3D/gameBase/gameConnection.h"
#include <thread>
//
#include "gfx/sim/debugDraw.h"
//
@ -118,6 +120,8 @@ Entity::Entity()
mInitialized = false;
mLifetimeMS = 0;
mGameObjectAssetId = StringTable->insert("");
}
@ -147,6 +151,10 @@ void Entity::initPersistFields()
endGroup("Transform");
addGroup("Misc");
addField("LifetimeMS", TypeS32, Offset(mLifetimeMS, Entity), "Object world orientation.");
endGroup("Misc");
addGroup("GameObject");
addProtectedField("gameObjectName", TypeGameObjectAssetPtr, Offset(mGameObjectAsset, Entity), &_setGameObject, &defaultProtectedGetFn,
"The asset Id used for the game object this entity is based on.");
@ -231,8 +239,19 @@ bool Entity::onAdd()
addToScene();
//Make sure we get positioned
setMaskBits(TransformMask);
setMaskBits(NamespaceMask);
if (isServerObject())
{
setMaskBits(TransformMask);
setMaskBits(NamespaceMask);
}
else
{
//We can shortcut the initialization here because stuff generally ghosts down in order, and onPostAdd isn't called on ghosts.
onPostAdd();
}
if (mLifetimeMS != 0)
mStartTimeMS = Platform::getRealMilliseconds();
return true;
}
@ -245,6 +264,8 @@ void Entity::onRemove()
onDataSet.removeAll();
mGameObjectAsset.clear();
Parent::onRemove();
}
@ -258,6 +279,27 @@ void Entity::onPostAdd()
mComponents[i]->onComponentAdd();
}
//Set up the networked components
mNetworkedComponents.clear();
for (U32 i = 0; i < mComponents.size(); i++)
{
if (mComponents[i]->isNetworked())
{
NetworkedComponent netComp;
netComp.componentIndex = i;
netComp.updateState = NetworkedComponent::Adding;
netComp.updateMaskBits = -1;
mNetworkedComponents.push_back(netComp);
}
}
if (!mNetworkedComponents.empty())
{
setMaskBits(AddComponentsMask);
setMaskBits(ComponentsUpdateMask);
}
if (isMethod("onAdd"))
Con::executef(this, "onAdd");
}
@ -396,6 +438,14 @@ void Entity::processTick(const Move* move)
mDelta.rot[1] = mRot.asQuatF();
setTransform(getPosition(), mRot);
//Lifetime test
if (mLifetimeMS != 0)
{
S32 currentTime = Platform::getRealMilliseconds();
if (currentTime - mStartTimeMS >= mLifetimeMS)
deleteObject();
}
}
}
@ -446,62 +496,107 @@ U32 Entity::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
mathWrite(*stream, mObjBox);
}
//pass our behaviors around
if (mask & ComponentsMask || mask & InitialUpdateMask)
if (stream->writeFlag(mask & AddComponentsMask))
{
stream->writeFlag(true);
//now, we run through a list of our to-be-sent behaviors and begin sending them
//if any fail, we keep our list and re-queue the mask
S32 componentCount = mToLoadComponents.size();
U32 toAddComponentCount = 0;
//build our 'ready' list
//This requires both the instance and the instances' template to be prepped(if the template hasn't been ghosted,
//then we know we shouldn't be passing the instance's ghosts around yet)
U32 ghostedCompCnt = 0;
for (U32 i = 0; i < componentCount; i++)
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (con->getGhostIndex(mToLoadComponents[i]) != -1)
ghostedCompCnt++;
}
if (ghostedCompCnt != 0)
{
stream->writeFlag(true);
stream->writeFlag(mStartComponentUpdate);
//if not all the behaviors have been ghosted, we'll need another pass
if (ghostedCompCnt != componentCount)
retMask |= ComponentsMask;
//write the currently ghosted behavior count
stream->writeInt(ghostedCompCnt, 16);
for (U32 i = 0; i < mToLoadComponents.size(); i++)
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
//now fetch them and pass the ghost
S32 ghostIndex = con->getGhostIndex(mToLoadComponents[i]);
if (ghostIndex != -1)
{
stream->writeInt(ghostIndex, NetConnection::GhostIdBitSize);
mToLoadComponents.erase(i);
i--;
mStartComponentUpdate = false;
}
toAddComponentCount++;
}
}
else if (componentCount)
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toAddComponentCount, 8);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
//on the odd chance we have behaviors to ghost, but NONE of them have been yet, just set the flag now
stream->writeFlag(false);
retMask |= ComponentsMask;
NetworkedComponent::UpdateState state = mNetworkedComponents[i].updateState;
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
const char* className = mComponents[mNetworkedComponents[i].componentIndex]->getClassName();
stream->writeString(className, strlen(className));
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
}
}
else
stream->writeFlag(false);
}
else
stream->writeFlag(false);
if (stream->writeFlag(mask & RemoveComponentsMask))
{
/*U32 toRemoveComponentCount = 0;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
{
toRemoveComponentCount++;
}
}
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toRemoveComponentCount, 8);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Removing)
{
stream->writeInt(i, 16);
}
}*/
/*for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::UpdateState::Removing)
{
removeComponent(mComponents[mNetworkedComponents[i].componentIndex], true);
mNetworkedComponents.erase(i);
i--;
}
}*/
}
//Update our components
if (stream->writeFlag(mask & ComponentsUpdateMask))
{
U32 toUpdateComponentCount = 0;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
{
toUpdateComponentCount++;
}
}
//you reaaaaally shouldn't have >255 networked components on a single entity
stream->writeInt(toUpdateComponentCount, 8);
bool forceUpdate = false;
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
{
stream->writeInt(i, 8);
mNetworkedComponents[i].updateMaskBits = mComponents[mNetworkedComponents[i].componentIndex]->packUpdate(con, mNetworkedComponents[i].updateMaskBits, stream);
if (mNetworkedComponents[i].updateMaskBits != 0)
forceUpdate = true;
else
mNetworkedComponents[i].updateState = NetworkedComponent::None;
}
}
//If we have leftover, we need to re-iterate our packing
if (forceUpdate)
setMaskBits(ComponentsUpdateMask);
}
/*if (stream->writeFlag(mask & NamespaceMask))
{
@ -594,25 +689,52 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
resetWorldBox();
}
//AddComponentMask
if (stream->readFlag())
{
//are we passing any behaviors currently?
if (stream->readFlag())
U32 addedComponentCount = stream->readInt(8);
for (U32 i = 0; i < addedComponentCount; i++)
{
//if we've just started the update, clear our behaviors
if (stream->readFlag())
clearComponents(false);
char className[256] = "";
stream->readString(className);
S32 componentCount = stream->readInt(16);
//Change to components, so iterate our list and create any new components
// Well, looks like we have to create a new object.
const char* componentType = className;
for (U32 i = 0; i < componentCount; i++)
ConsoleObject *object = ConsoleObject::create(componentType);
// Finally, set currentNewObject to point to the new one.
Component* newComponent = dynamic_cast<Component *>(object);
if (newComponent)
{
S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
addComponent(dynamic_cast<Component*>(con->resolveGhost(gIndex)));
addComponent(newComponent);
}
}
}
//RemoveComponentMask
if (stream->readFlag())
{
}
//ComponentUpdateMask
if (stream->readFlag())
{
U32 updatingComponents = stream->readInt(8);
for (U32 i = 0; i < updatingComponents; i++)
{
U32 updateComponentIndex = stream->readInt(8);
Component* comp = mComponents[updateComponentIndex];
comp->unpackUpdate(con, stream);
}
}
/*if (stream->readFlag())
{
if (stream->readFlag())
@ -640,6 +762,26 @@ void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
}*/
}
void Entity::setComponentNetMask(Component* comp, U32 mask)
{
setMaskBits(Entity::ComponentsUpdateMask);
for (U32 i = 0; i < mNetworkedComponents.size(); i++)
{
U32 netCompId = mComponents[mNetworkedComponents[i].componentIndex]->getId();
U32 compId = comp->getId();
if (netCompId == compId &&
(mNetworkedComponents[i].updateState == NetworkedComponent::None || mNetworkedComponents[i].updateState == NetworkedComponent::Updating))
{
mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
mNetworkedComponents[i].updateMaskBits |= mask;
break;
}
}
}
//Manipulation
void Entity::setTransform(const MatrixF &mat)
{
@ -758,7 +900,11 @@ void Entity::setTransform(Point3F position, RotationF rotation)
// Update the transforms.
Parent::setTransform(newMat);
onTransformSet.trigger(&newMat);
U32 compCount = mComponents.size();
for (U32 i = 0; i < compCount; ++i)
{
mComponents[i]->ownerTransformSet(&newMat);
}
Point3F newPos = newMat.getPosition();
RotationF newRot = newMat;
@ -800,7 +946,11 @@ void Entity::setRenderTransform(Point3F position, RotationF rotation)
Parent::setRenderTransform(newMat);
onTransformSet.trigger(&newMat);
U32 compCount = mComponents.size();
for (U32 i = 0; i < compCount; ++i)
{
mComponents[i]->ownerTransformSet(&newMat);
}
}
}
@ -1155,11 +1305,28 @@ bool Entity::addComponent(Component *comp)
// Register the component with this owner.
comp->setOwner(this);
comp->setIsServerObject(isServerObject());
//if we've already been added and this is being added after the fact(at runtime),
//then just go ahead and call it's onComponentAdd so it can get to work
if (mInitialized)
//if (mInitialized)
{
comp->onComponentAdd();
if (comp->isNetworked())
{
NetworkedComponent netComp;
netComp.componentIndex = mComponents.size() - 1;
netComp.updateState = NetworkedComponent::Adding;
netComp.updateMaskBits = -1;
mNetworkedComponents.push_back(netComp);
setMaskBits(AddComponentsMask);
setMaskBits(ComponentsUpdateMask);
}
}
onComponentAdded.trigger(comp);
return true;
@ -1269,7 +1436,7 @@ Component *Entity::getComponent(String componentType)
Namespace *NS = comp->getNamespace();
//we shouldn't ever go past Component into net object, as we're no longer dealing with component classes
while (dStrcmp(NS->getName(), "NetObject"))
while (dStrcmp(NS->getName(), "SimObject"))
{
String namespaceName = NS->getName();
@ -1497,7 +1664,8 @@ void Entity::notifyComponents(String signalFunction, String argA, String argB, S
void Entity::setComponentsDirty()
{
if (mToLoadComponents.empty())
bool tmp = true;
/*if (mToLoadComponents.empty())
mStartComponentUpdate = true;
//we need to build a list of behaviors that need to be pushed across the network
@ -1522,7 +1690,7 @@ void Entity::setComponentsDirty()
}
}
setMaskBits(ComponentsMask);
setMaskBits(ComponentsMask);*/
}
void Entity::setComponentDirty(Component *comp, bool forceUpdate)
@ -1654,7 +1822,7 @@ ConsoleMethod(Entity, addComponents, void, 2, 2, "() - Add all fielded behaviors
object->addComponents();
}*/
ConsoleMethod(Entity, addComponent, bool, 3, 3, "(Component* bi) - Add a behavior to the object\n"
ConsoleMethod(Entity, addComponent, bool, 3, 3, "(ComponentInstance bi) - Add a behavior to the object\n"
"@param bi The behavior instance to add"
"@return (bool success) Whether or not the behavior was successfully added")
{
@ -1679,7 +1847,7 @@ ConsoleMethod(Entity, addComponent, bool, 3, 3, "(Component* bi) - Add a behavio
return false;
}
ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(Component* bi, [bool deleteBehavior = true])\n"
ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(ComponentInstance bi, [bool deleteBehavior = true])\n"
"@param bi The behavior instance to remove\n"
"@param deleteBehavior Whether or not to delete the behavior\n"
"@return (bool success) Whether the behavior was successfully removed")
@ -1834,4 +2002,43 @@ DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, S
return;
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);
}
DefineConsoleFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType<SimGroup*>(), ""),
"Finds all entities that have the provided tags.\n"
"@param searchingGroup The SimGroup to search inside. If null, we'll search the entire dictionary(this can be slow!).\n"
"@param tags Word delimited list of tags to search for. If multiple tags are included, the list is eclusively parsed, requiring all tags provided to be found on an entity for a match.\n"
"@return A word list of IDs of entities that match the tag search terms.")
{
//if (tags.isEmpty())
return "";
/*if (searchingGroup == nullptr)
{
searchingGroup = Sim::getRootGroup();
}
StringTableEntry entityStr = StringTable->insert("Entity");
std::thread threadBob;
std::thread::id a = threadBob.get_id();
std::thread::id b = std::this_thread::get_id().;
if (a == b)
{
//do
}
for (SimGroup::iterator itr = searchingGroup->begin(); itr != searchingGroup->end(); itr++)
{
Entity* ent = dynamic_cast<Entity*>((*itr));
if (ent != nullptr)
{
ent->mTags.
}
}
object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);*/
}

View file

@ -58,7 +58,27 @@ private:
Vector<Component*> mComponents;
Vector<Component*> mToLoadComponents;
//Bit of helper data to let us track and manage the adding, removal and updating of networked components
struct NetworkedComponent
{
U32 componentIndex;
enum UpdateState
{
None,
Adding,
Removing,
Updating
};
UpdateState updateState;
U32 updateMaskBits;
};
Vector<NetworkedComponent> mNetworkedComponents;
U32 mComponentNetMask;
bool mStartComponentUpdate;
@ -69,10 +89,12 @@ private:
bool mInitialized;
String mTags;
Signal< void(Component*) > onComponentAdded;
Signal< void(Component*) > onComponentRemoved;
Signal< void(MatrixF*) > onTransformSet;
S32 mLifetimeMS;
protected:
@ -105,10 +127,12 @@ public:
{
TransformMask = Parent::NextFreeMask << 0,
BoundsMask = Parent::NextFreeMask << 1,
ComponentsMask = Parent::NextFreeMask << 2,
NoWarpMask = Parent::NextFreeMask << 3,
NamespaceMask = Parent::NextFreeMask << 4,
NextFreeMask = Parent::NextFreeMask << 5
ComponentsUpdateMask = Parent::NextFreeMask << 2,
AddComponentsMask = Parent::NextFreeMask << 3,
RemoveComponentsMask = Parent::NextFreeMask << 4,
NoWarpMask = Parent::NextFreeMask << 5,
NamespaceMask = Parent::NextFreeMask << 6,
NextFreeMask = Parent::NextFreeMask << 7
};
StateDelta mDelta;
@ -116,6 +140,8 @@ public:
Move lastMove;
S32 mStartTimeMS;
//
Entity();
~Entity();
@ -163,6 +189,9 @@ public:
/// @param client Client that is now controlling this object
virtual void setControllingClient(GameConnection *client);
//
//Networking
//
// NetObject
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
@ -170,6 +199,8 @@ public:
void setComponentsDirty();
void setComponentDirty(Component *comp, bool forceUpdate = false);
void setComponentNetMask(Component* comp, U32 mask);
//Components
virtual bool deferAddingComponents() const { return true; }

View file

@ -38,6 +38,9 @@
#include "T3D/gameBase/gameConnection.h"
#include "math/mathUtils.h"
#include "T3D/components/render/renderComponentInterface.h"
#include "T3D/systems/render/meshRenderSystem.h"
// For player object bounds workaround.
#include "T3D/player.h"
@ -358,6 +361,8 @@ void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZ
if( gEditingMission && state->isDiffusePass() )
objectMask = EDITOR_RENDER_TYPEMASK;
MeshRenderSystem::render(this, state);
// Update the zoning state and traverse zones.
if( getZoneManager() )

View file

@ -106,17 +106,6 @@ void SceneRenderState::renderObjects( SceneObject** objects, U32 numObjects )
object->prepRenderImage( this );
}
U32 interfaceCount = RenderComponentInterface::all.size();
for (U32 i = 0; i < RenderComponentInterface::all.size(); i++)
{
Component* comp = dynamic_cast<Component*>(RenderComponentInterface::all[i]);
if (comp->isClientObject() && comp->isActive())
{
RenderComponentInterface::all[i]->prepRenderImage(this);
}
}
PROFILE_END();
// Render what the objects have batched.

View file

@ -0,0 +1,10 @@
function CoreComponentsModule::onCreate(%this)
{
%classList = enumerateConsoleClasses( "Component" );
foreach$( %componentClass in %classList )
{
echo("Native Component of type: " @ %componentClass);
}
}