Game Development Community

Alpha 1.4]Adding sceneobject to SimSet stops rendering

by Jared Coliadis · in Torque Game Builder · 02/01/2006 (8:44 am) · 13 replies

I have a "transition" object that is added to a scene based off of TileScript callbacks. The function called to create a transition object puts it on the scene and adds the object to a SimSet so it can be deleted later:
function createTransition(%xy, %dest, %newpos)
{
	echo("Creating transition At" SPC %xy);
	%trans = new t2dStaticSprite(){scenegraph = t2dSceneGraph;};
	%trans.setSize("5 3.75");
	%trans.class = "transition";
	%trans.setPosition(%xy);
	%trans.setLayer(6);
	%trans.setCollisionActive(true, true);
	%trans.setCollisionPhysics(false, false);
	%trans.setCollisionCallback(true);
	%trans.setUseMouseEvents(true);
	%trans.dest = %dest;
	%trans.newpos = %newpos;
	transitions.add(%trans); //transitions is a SimSet declared previously in another file.
	return %trans;
}
In Alpha 1.3b, this worked fine. However, now when the object is added to the SimSet, it is not rendered to the scenegraph. According to the debug screen's object count and some echoing, the objects are being created.

I can work around it by adding a ScriptObject with a member referencing the object itself, but that adds some unneeded objects and complexity. Even though the workaround works, and I'm most likely going to handle this object creation in a completely different manner pretty soon, this does seem to be a bug.

#1
02/01/2006 (1:57 pm)
For kicks, can you add the following lines after setUseMouseEvents(true):

%trans.setVisible(true);
%trans.setEnabled(true);
#2
02/01/2006 (2:30 pm)
Yeah, I've tried that too. I've set an ImageMap as well and still nothing. Once I remove the add to the SimSet they load right up, but unfortunately I have no control over them since they aren't part of the set.
#3
02/01/2006 (3:19 pm)
The issue shows up in the tilemap editor too...can't select any brushes since it adds them to a SimGroup.
Changing imageTileGroup to a SimSet resolves the issue.
#4
02/01/2006 (3:42 pm)
The change to the tilemap editor doesn't work exactly. Selecting multiple brushes doesn't clear out the old brush, so you get each object stacking on top of the one previous to it.
#5
02/01/2006 (3:49 pm)
This sounds like a side effect of a recent change we made. t2dSceneGraphs are now inheriting from SimGroup instead of SimObject. Therefore, if you try to add objects to a SimGroup, they will be removed from the scenegraph.

This is bad.

Until I get time to make the scenegraph SimGroup relationship more robust, you can either:

Use SimSets to store your objects.
Add your SimGroup to the scenegraph, add your objects to the SimGroup, then add your objects to the scene - in that order.
Or, change the inheritance of t2dSceneGraph from SimGroup to SimSet <-This is probably what I will be doing as a quick fix until I can spend some more time on this.

The eventual goal is to have scene graphs be able to contain simgroups and/or simsets, with all of the contained objects a part of the scene. This will give a nice structure for the level builder tree view, and just generally makes level handling easier.
#6
02/01/2006 (7:17 pm)
Ok, so I didn't just change it to a SimSet. In Tools\tileEditor\scripts\imageSelection.cs I changed the function selectImageTileSet starting around line 168.

// Delete Image-Group if it exists.
if ( isObject(imageTileGroup) )
{
for (%i = imageTileGroup.getCount()-1; %i >= 0; %i--)
{
%obj = imageTileGroup.getObject(%i);
imageTileGroup.remove(%obj);
%obj.safeDelete();
}
imageTileGroup.delete();
}



// Create new Image-Group.
new SimSet(imageTileGroup);
#7
02/01/2006 (11:33 pm)
Thanks for the heads up Jared, this is a bummer of a bug, but there's good news.

It is indeed fixed, and so, in an effort to ease any undue pain caused by my oversight, here are the changes you need to fix it.

In t2dSceneGraph.h on line 122 change
///-----------------------------------------------------------------------------
/// SceneGraph Object.
///-----------------------------------------------------------------------------
class t2dSceneGraph : public [b]SimGroup[/b]
{
private:
    typedef [b]SimGroup[/b] Parent;

to

///-----------------------------------------------------------------------------
/// SceneGraph Object.
///-----------------------------------------------------------------------------
class t2dSceneGraph : public [b]SimSet[/b]
{
private:
    typedef [b]SimSet[/b] Parent;

Then inside of t2dSceneGraph.cc at line 617 change
// Fetch Object's Group.
    SimGroup* pCurrGroup = dynamic_cast<SimGroup*>( pSceneObject2D->getGroup() );

    if( pCurrGroup )
    {
        // Check Group Requirements.
        // The Object Must - Be in the Base Group -OR- Be in a child group of the base group.
        if( pCurrGroup->getId() != this->getId() && !pCurrGroup->isChildOfGroup( this ) )  
           Parent::addObject(pSceneObject2D);
    }
    else
    {
       // No Group Found, Add To Base.
       Parent::addObject(pSceneObject2D);
    }

to

// Add the object to our set if it's not already there
    SimSet::iterator pObjectLookup = find( begin(), end(), pSceneObject2D );
    if( pObjectLookup == end() )
       Parent::addObject(pSceneObject2D);

then finally around right below that replace the function
// These just need to be redirected to the scene object management versions of the function.
void t2dSceneGraph::addObject( SimObject* object )
{
   t2dSceneObject* obj = dynamic_cast<t2dSceneObject*>(object);
   // addToScene will perform the parent calling - but it does so in such a way that trying to
   // move an object from a child group of the scenegraph to the scenegraph won't happen.
   if (obj)
      addToScene(obj);
}

with

// These just need to be redirected to the scene object management versions of the function.
void t2dSceneGraph::addObject( SimObject* object )
{
   t2dSceneObject* obj = dynamic_cast<t2dSceneObject*>(object);
   // addToScene will perform the parent calling - but it does so in such a way that trying to
   // move an object from a child group of the scenegraph to the scenegraph won't happen.
   if (obj)
      addToScene(obj);
[b]   else
      Parent::addObject( object );[/b]
}

I've tested this with your code before hand and it did indeed break it, and then after these changes all is well and the scene saves out properly!

Best Regards,
-Justin
#8
02/02/2006 (6:47 am)
I think you'll also need to modify, in "t2dSceneGraph.cc" (t2dSceneGraph::removeFromScene) this...
// Remove from Group, When Appropriate.
    if( pSceneObject2D->isChildOfGroup( this ) )
    {
        SimGroup* pGroup = pSceneObject2D->getGroup();
        if( pGroup )
        {
           Parent::removeObject(pSceneObject2D);
        }
    }
... with this ...
// Remove from Set, When Appropriate.
    SimSet::iterator pObjectLookup = find( begin(), end(), pSceneObject2D );
    if( pObjectLookup != end() )
       Parent::removeObject(pSceneObject2D);

I believe that Justins fix above also solves the issue of the tile-map editor not showing the image-maps in the image-library window.

- Melv.
#9
02/02/2006 (7:38 am)
SimSet::iterator pObjectLookup = find( begin(), end(), pSceneObject2D ); [b]// <-- Why this line? ... [/b]
    if( pObjectLookup != end() )
       Parent::removeObject(pSceneObject2D);

... because SimSet::removeObject has to do this anyway.
#10
02/02/2006 (8:29 am)
I have no idea, I just posted this from the changes made in the repository, I didn't make 'em. ;)

To clarify, I've not had chance to go through this code, I've been working on other stuff.

- Melv.
#11
02/02/2006 (11:50 am)
Michael,
You are correct in that SimSet::removeObject does eventually end up at SimObjectList::remove which does indeed do the same check. The reason I added that line to removeFromScene is that, well it's removeFromScene, not removeObject.

If you follow the code through, calling Parent::removeObject with an object that isn't in the set will more than likely not doing anything bad, but I don't like to take chances with stuff like that.

Also, since I'm calling a method that is *not* the method that our code is supposed to be flowing through, I like to make sure there's reason to be going down that rabbit hole before I jump in.

So in short, does it *need* to be there, no; do I feel better about it being there, yep :)

Melv,
Thanks for catching that, I thought I had it all, but apparently not :)

-J
#12
02/02/2006 (12:25 pm)
Well since I am still using visual basic 6, I dont have any way to add these changes to the engine.
So hopefully in the beta these iussues will work themselves out, and I will look at other compilers I guess since I am slowly being left behind.. :)
#13
02/02/2006 (1:06 pm)
@Justin
Yeah, I just wondered if there was any deeper meaning to that check that I didn't not see.
And you are totally right, I wouldn't make any sense to optimize rarely called functions like this for speed more than safety. :)