Defer re-init'ing the shape when TSShapeConstructor is loading a shape

This commit is contained in:
James Urquhart 2016-09-03 10:41:25 +01:00
parent 0e717ea707
commit a46779fad6
5 changed files with 143 additions and 71 deletions

View file

@ -71,6 +71,7 @@ TSShape::TSShape()
mShapeDataSize = 0; mShapeDataSize = 0;
mUseDetailFromScreenError = false; mUseDetailFromScreenError = false;
mNeedReinit = false;
mDetailLevelLookup.setSize( 1 ); mDetailLevelLookup.setSize( 1 );
mDetailLevelLookup[0].set( -1, 0 ); mDetailLevelLookup[0].set( -1, 0 );
@ -412,9 +413,17 @@ void TSShape::getObjectDetails(S32 objIndex, Vector<S32>& objDetails)
} }
void TSShape::init() void TSShape::init()
{
initObjects();
initVertexFeatures();
initMaterialList();
mNeedReinit = false;
}
void TSShape::initObjects()
{ {
S32 numSubShapes = subShapeFirstNode.size(); S32 numSubShapes = subShapeFirstNode.size();
AssertFatal(numSubShapes==subShapeFirstObject.size(),"TSShape::init"); AssertFatal(numSubShapes == subShapeFirstObject.size(), "TSShape::initObjects");
S32 i, j; S32 i, j;
@ -592,9 +601,6 @@ void TSShape::init()
mesh->mVertexFormat = &mVertexFormat; mesh->mVertexFormat = &mVertexFormat;
} }
initVertexFeatures();
initMaterialList();
} }
void TSShape::initVertexBuffers() void TSShape::initVertexBuffers()

View file

@ -413,6 +413,7 @@ class TSShape
GFXPrimitiveBufferHandle mShapeVertexIndices; GFXPrimitiveBufferHandle mShapeVertexIndices;
bool mSequencesConstructed; bool mSequencesConstructed;
bool mNeedReinit;
// shape class has few methods -- // shape class has few methods --
@ -428,6 +429,9 @@ class TSShape
void setupBillboardDetails( const String &cachePath ); void setupBillboardDetails( const String &cachePath );
/// Inits object list (no geometry buffers)
void initObjects();
/// Initializes the main vertex buffer /// Initializes the main vertex buffer
void initVertexBuffers(); void initVertexBuffers();
@ -557,8 +561,6 @@ class TSShape
const GFXVertexFormat* getVertexFormat() const { return &mVertexFormat; } const GFXVertexFormat* getVertexFormat() const { return &mVertexFormat; }
bool needsBufferUpdate();
/// @} /// @}
/// @name Alpha Transitions /// @name Alpha Transitions
@ -685,6 +687,10 @@ class TSShape
bool setSequenceBlend(const String& seqName, bool blend, const String& blendRefSeqName, S32 blendRefFrame); bool setSequenceBlend(const String& seqName, bool blend, const String& blendRefSeqName, S32 blendRefFrame);
bool setSequenceGroundSpeed(const String& seqName, const Point3F& trans, const Point3F& rot); bool setSequenceGroundSpeed(const String& seqName, const Point3F& trans, const Point3F& rot);
void makeEditable();
bool needsReinit();
bool needsBufferUpdate();
/// @} /// @}
}; };

View file

@ -86,6 +86,11 @@ void TSShapeConstructor::_onTSShapeLoaded( Resource< TSShape >& resource )
TSShapeConstructor* ctor = findShapeConstructor( resource.getPath().getFullPath() ); TSShapeConstructor* ctor = findShapeConstructor( resource.getPath().getFullPath() );
if( ctor ) if( ctor )
ctor->_onLoad( resource ); ctor->_onLoad( resource );
if (ctor && ctor->mShape && ctor->mShape->needsReinit())
{
ctor->mShape->init();
}
} }
void TSShapeConstructor::_onTSShapeUnloaded( const Torque::Path& path, TSShape* shape ) void TSShapeConstructor::_onTSShapeUnloaded( const Torque::Path& path, TSShape* shape )
@ -128,7 +133,7 @@ static void SplitSequencePathAndName( String& srcPath, String& srcName )
IMPLEMENT_CONOBJECT(TSShapeConstructor); IMPLEMENT_CONOBJECT(TSShapeConstructor);
TSShapeConstructor::TSShapeConstructor() TSShapeConstructor::TSShapeConstructor()
: mShapePath("") : mShapePath(""), mLoadingShape(false)
{ {
mShape = NULL; mShape = NULL;
} }
@ -374,9 +379,15 @@ bool TSShapeConstructor::onAdd()
// If an instance of this shape has already been loaded, call onLoad now // If an instance of this shape has already been loaded, call onLoad now
Resource<TSShape> shape = ResourceManager::get().find( mShapePath ); Resource<TSShape> shape = ResourceManager::get().find( mShapePath );
if ( shape ) if ( shape )
_onLoad( shape ); _onLoad( shape );
if (mShape && mShape->needsReinit())
{
mShape->init();
}
return true; return true;
} }
@ -394,6 +405,7 @@ void TSShapeConstructor::_onLoad(TSShape* shape)
mShape = shape; mShape = shape;
mChangeSet.clear(); mChangeSet.clear();
mLoadingShape = true;
// Add sequences defined using field syntax // Add sequences defined using field syntax
for ( S32 i = 0; i < mSequences.size(); i++ ) for ( S32 i = 0; i < mSequences.size(); i++ )
@ -411,6 +423,7 @@ void TSShapeConstructor::_onLoad(TSShape* shape)
// Call script function // Call script function
onLoad_callback(); onLoad_callback();
mLoadingShape = false;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -3279,3 +3292,15 @@ bool TSShapeConstructor::ChangeSet::addCmd_removeImposter( const TSShapeConstruc
return true; return true;
} }
void TSShapeConstructor::onActionPerformed()
{
// Reinit shape if we modify stuff in the shape editor, otherwise delay
if (!mLoadingShape)
{
if (mShape && mShape->needsReinit())
{
mShape->init();
}
}
}

View file

@ -246,6 +246,7 @@ public:
TSShape* mShape; // Edited shape; NULL while not loaded; not a Resource<TSShape> as we don't want it to prevent from unloading. TSShape* mShape; // Edited shape; NULL while not loaded; not a Resource<TSShape> as we don't want it to prevent from unloading.
ColladaUtils::ImportOptions mOptions; ColladaUtils::ImportOptions mOptions;
bool mLoadingShape;
public: public:
@ -261,6 +262,7 @@ public:
bool onAdd(); bool onAdd();
void onScriptChanged(const Torque::Path& path); void onScriptChanged(const Torque::Path& path);
void onActionPerformed();
bool writeField(StringTableEntry fieldname, const char *value); bool writeField(StringTableEntry fieldname, const char *value);
void writeChangeSet(); void writeChangeSet();
@ -385,6 +387,14 @@ typedef ColladaUtils::ImportOptions::eLodType TSShapeConstructorLodType;
DefineEnumType( TSShapeConstructorUpAxis ); DefineEnumType( TSShapeConstructorUpAxis );
DefineEnumType(TSShapeConstructorLodType); DefineEnumType(TSShapeConstructorLodType);
class TSShapeConstructorMethodActionCallback
{
TSShapeConstructor* mObject;
public:
TSShapeConstructorMethodActionCallback(TSShapeConstructor *object) : mObject(object) { ; }
~TSShapeConstructorMethodActionCallback() { mObject->onActionPerformed(); }
};
/* This macro simplifies the definition of a TSShapeConstructor API method. It /* This macro simplifies the definition of a TSShapeConstructor API method. It
wraps the actual EngineMethod definition and automatically calls the real wraps the actual EngineMethod definition and automatically calls the real
@ -403,6 +413,7 @@ DefineEnumType( TSShapeConstructorLodType );
Con::errorf( "TSShapeConstructor::" #name " - shape not loaded" ); \ Con::errorf( "TSShapeConstructor::" #name " - shape not loaded" ); \
return defRet; \ return defRet; \
} \ } \
TSShapeConstructorMethodActionCallback actionCallback(object); \
return object->name rawArgs ; \ return object->name rawArgs ; \
} \ } \
/* Define the real TSShapeConstructor method */ \ /* Define the real TSShapeConstructor method */ \

View file

@ -435,6 +435,9 @@ bool TSShape::addNode(const String& name, const String& parentName, const Point3
} }
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Insert node at the end of the subshape // Insert node at the end of the subshape
S32 subShapeIndex = (parentIndex >= 0) ? getSubShapeForNode(parentIndex) : 0; S32 subShapeIndex = (parentIndex >= 0) ? getSubShapeForNode(parentIndex) : 0;
S32 nodeIndex = subShapeNumNodes[subShapeIndex]; S32 nodeIndex = subShapeNumNodes[subShapeIndex];
@ -493,8 +496,7 @@ bool TSShape::addNode(const String& name, const String& parentName, const Point3
} }
} }
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -548,6 +550,9 @@ bool TSShape::removeNode(const String& name)
((nodeParentIndex >= 0) ? getName(nodes[nodeParentIndex].nameIndex).c_str() : "null")); ((nodeParentIndex >= 0) ? getName(nodes[nodeParentIndex].nameIndex).c_str() : "null"));
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Update animation sequences // Update animation sequences
for (S32 iSeq = 0; iSeq < sequences.size(); iSeq++) for (S32 iSeq = 0; iSeq < sequences.size(); iSeq++)
{ {
@ -626,8 +631,7 @@ bool TSShape::removeNode(const String& name)
// Remove the sequence name if it is no longer in use // Remove the sequence name if it is no longer in use
removeName(name); removeName(name);
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -855,6 +859,9 @@ bool TSShape::removeObject(const String& name)
return false; return false;
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Destroy all meshes in the object // Destroy all meshes in the object
TSShape::Object& obj = objects[objIndex]; TSShape::Object& obj = objects[objIndex];
while ( obj.numMeshes ) while ( obj.numMeshes )
@ -893,14 +900,7 @@ bool TSShape::removeObject(const String& name)
// Update smallest visible detail // Update smallest visible detail
updateSmallestVisibleDL(); updateSmallestVisibleDL();
// Ensure shape is dirty initObjects();
if (meshes[0])
{
meshes[0]->makeEditable();
}
// Re-initialise the shape
init();
return true; return true;
} }
@ -961,6 +961,9 @@ bool TSShape::addMesh(TSMesh* mesh, const String& meshName)
// Ensure mesh is in editable state // Ensure mesh is in editable state
mesh->makeEditable(); mesh->makeEditable();
// Need to make everything editable since node indexes etc will change
makeEditable();
// Determine the object name and detail size from the mesh name // Determine the object name and detail size from the mesh name
S32 detailSize = 999; S32 detailSize = 999;
String objName(String::GetTrailingNumber(meshName, detailSize)); String objName(String::GetTrailingNumber(meshName, detailSize));
@ -1049,8 +1052,7 @@ bool TSShape::addMesh(TSMesh* mesh, const String& meshName)
} }
} }
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -1140,6 +1142,9 @@ bool TSShape::setMeshSize(const String& meshName, S32 size)
return false; return false;
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Remove the mesh from the object, but don't destroy it // Remove the mesh from the object, but don't destroy it
TSShape::Object& obj = objects[objIndex]; TSShape::Object& obj = objects[objIndex];
TSMesh* mesh = meshes[obj.startMeshIndex + meshIndex]; TSMesh* mesh = meshes[obj.startMeshIndex + meshIndex];
@ -1151,8 +1156,7 @@ bool TSShape::setMeshSize(const String& meshName, S32 size)
// Update smallest visible detail // Update smallest visible detail
updateSmallestVisibleDL(); updateSmallestVisibleDL();
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -1167,6 +1171,9 @@ bool TSShape::removeMesh(const String& meshName)
return false; return false;
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Destroy and remove the mesh // Destroy and remove the mesh
TSShape::Object& obj = objects[objIndex]; TSShape::Object& obj = objects[objIndex];
destructInPlace(meshes[obj.startMeshIndex + meshIndex]); destructInPlace(meshes[obj.startMeshIndex + meshIndex]);
@ -1179,8 +1186,7 @@ bool TSShape::removeMesh(const String& meshName)
// Update smallest visible detail // Update smallest visible detail
updateSmallestVisibleDL(); updateSmallestVisibleDL();
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -1294,8 +1300,8 @@ S32 TSShape::setDetailSize(S32 oldSize, S32 newSize)
// Update smallest visible detail // Update smallest visible detail
updateSmallestVisibleDL(); updateSmallestVisibleDL();
// Re-initialise the shape // Nothing major, just reint object lists
init(); initObjects();
return newIndex; return newIndex;
} }
@ -1310,6 +1316,9 @@ bool TSShape::removeDetail( S32 size )
return false; return false;
} }
// Need to make everything editable since node indexes etc will change
makeEditable();
// Destroy and remove each mesh in the detail level // Destroy and remove each mesh in the detail level
for ( S32 objIndex = objects.size()-1; objIndex >= 0; objIndex-- ) for ( S32 objIndex = objects.size()-1; objIndex >= 0; objIndex-- )
{ {
@ -1339,17 +1348,10 @@ bool TSShape::removeDetail( S32 size )
billboardDetails.erase( dl ); billboardDetails.erase( dl );
} }
// Ensure shape is dirty
if (meshes[0])
{
meshes[0]->makeEditable();
}
// Update smallest visible detail // Update smallest visible detail
updateSmallestVisibleDL(); updateSmallestVisibleDL();
// Re-initialise the shape initObjects();
init();
return true; return true;
} }
@ -2140,3 +2142,25 @@ bool TSShape::setSequenceGroundSpeed(const String& seqName, const Point3F& trans
return true; return true;
} }
void TSShape::makeEditable()
{
mNeedReinit = true;
if (mShapeVertexData.base == NULL)
return;
for (U32 i = 0; i < meshes.size(); i++)
{
if (meshes[i])
{
meshes[i]->makeEditable();
}
}
mShapeVertexData.set(NULL, 0);
}
bool TSShape::needsReinit()
{
return mVertexSize == 0 || mShapeVertexData.base == NULL || mNeedReinit;
}