Game Development Community

Bug/Addition: t2dPath does not properly deference its attachees

by Fenrir Wolf · in Torque Game Builder · 06/29/2006 (2:16 pm) · 1 replies

This one was a bit of a bear and I am not happy with my solution here, but I am tossing it out anyway so perhaps smarter minds can make something of it.

Basically, I wanted to add a callback to t2dPath so that my objects could act intelligently when they reach the end of the path. I don't plan on using t2dPaths as repeating tracks -- They will act as a single path that is used once by the object, and then the object's behavior changes. (Perhaps switching to another path, or deleting itself entirely.)

Okay, adding an event was easy, and there's my code to do it:

t2dPath.cc, t2dPath::preIntegrate (line ~759)

else
	  {
			object.mObject->setLinearVelocity(t2dVector(0, 0));
			// DAVIDG
			// We need a callback!  So do it
			Con::executef (object.mObject, 1, "onPathEnd") ;
	  }
   }

Unfortunately, this introduced a rather nasty crash when using t2dPaths. After extensive debugging I traced it down to the fact that simobjects that remove themselves are leaving dead SimObjectPtrs inside the PathedObject vector pool. So it was necessary to prevent the in situ trimming of the pool as so:

t2dPath.cc, t2dPath::preIntegrate (line ~671)

for (i = mObjects.begin(); i != mObjects.end(); i++)
   {		
      if (i->mObject.isNull())
      {
         //mObjects.erase(i);  // Leave erasing until postIntegrate method  DAVIDG
         continue;

My solution is ugly. I've added a postIntegrate method that simply exists to tidy up the pathedObject pool when all simobject references are aged out. This means the PathedObjects are kept around longer than they should be, but the SimObjectPtrs inside the PathedObjects are kept consistant.

void t2dPath::postIntegrate (const F32 sceneTime, const F32 elapsedTime, CDebugStats *pDebugStats) // DAVIDG
{
	// DAVIDG
	// Find all dead paths and remove from list
	U32 count = 0;

	for ( U32 requestIndex = 0; requestIndex < mObjects.size(); requestIndex++ )
	{
		PathedObject& PathObject = mObjects[requestIndex];
      // Remove the pathed object if its referenced t2dsceneobject is gone
      if ( PathObject.mObject.isNull() )
      {
				// Quickly remove delete-request.
				//mObjects.erase( requestIndex );
				// Why can't we erase from the list without bunging up the SimObjectPtrs?
				// Possible: Registrations via SimObjectPtr are unaware of the list reordering/deletion, and therefore
				// do not update the SimObjectPtr appropriately.
				// Fix: ?
				count++ ;

        // Repeat this item.
        continue ;
      }

      // Skip to next PathedObject index.
      //++requestIndex;
	}
	// Ugh.  Kludge.  Clear the list if all references are gone, as the above code does NOT work.
	if (mObjects.size() > 0 && count == mObjects.size())
		mObjects.clear() ;
}

It works but it's ugly IMHO.

Maybe someone can shed some light on why the SimObjectPtrs are being corrupted?