Game Development Community

Possible GuiObjectView Bug?

by Jason Guzzardo · in Torque 3D Professional · 07/20/2009 (10:38 am) · 7 replies

I tried to add a GuiObjectView to one of my GUIs and got the following error when I ran the GUI:

LightManager::registerGlobalLight - The light is already registered!

The following code, in GuiObjectView.cpp, seems to be where the issue is:
LightManager* lm = gClientSceneGraph->getLightManager();
   lm->setSpecialLight(LightManager::slSunLightType, mFakeSun);

I used the following horrible hack to make sure the light is only set once and everything seems to work just fine:
static int  once = 0;
if(once == 0)
{
   LightManager* lm = gClientSceneGraph->getLightManager();
   lm->setSpecialLight(LightManager::slSunLightType, mFakeSun);
   once++;
}

I was wondering if someone could explain what's going on here so I can come up with a better solution for this. Obviously I would not want to use the above hack in production code. I'm not exactly sure what's going on with this setSpecialLight method.

#1
07/20/2009 (3:49 pm)
I also found that the console method setSeq of GuiObjectView doesn't actually do anything. This console method simply calls object->setObjectAnimation(dAtoi(argv[2])); which sets mAnimationSeq equal to the animation index, however, mAnimationSeq doesn't actually appear to be used anywhere.

Is GuiObjectView still under development due to beta or are these real issues i'm finding?
#2
07/21/2009 (12:24 pm)
I can confirm: this is a new bug in Beta4, it wasn't in Beta3
#3
07/21/2009 (1:08 pm)
I've tried to fix this bug in this way:
Remove these 2 lines from the renderWorld function
LightManager* lm = gClientSceneGraph->getLightManager();
lm->setSpecialLight(LightManager::slSunLightType, mFakeSun);
And add these lines to the end of the onWake function,
LightManager* lm = gClientSceneGraph->getLightManager();
if (lm->getSpecialLight(LightManager::slSunLightType) != mFakeSun)
    lm->setSpecialLight(LightManager::slSunLightType, mFakeSun);

return(true);
}
It works, if you are not in mission, if you show the GuiObjectView while in a mission, all the objects are rendered black.
With Beta3 I haven't had these problems.
#4
07/21/2009 (1:17 pm)
Well, ok ... instead of moving those lines in the onWake function leave them in the renderWorld function and it works correctly. :)
#5
07/21/2009 (5:45 pm)
hey thanks davide...I'm actually using this before I enter a mission but it looks like it will work either way by implementing your fix in renderWorld.
#6
07/22/2009 (1:14 pm)
I got animation working in the GuiObjectView using setSeq. I'm not that familiar with T3D yet so if there is a better way to do this let me know. However, it's working good enouph for my needs right now.

code for console method setSeq:

void GuiObjectView::setObjectAnimation(S32 index)
{
   if ((0 > index) || (index > MAX_ANIMATIONS))
   {
      Con::warnf(avar("GuiObjectView: The index %d is outside the permissible range. Please specify an animation index in the range [0, %d]", index, MAX_ANIMATIONS));
      return;
   }
   
   if(!mModel)
   {
	  Con::warnf(avar("GuiObjectView: A valid model must be set using setModel() before choosing an animation sequence!"));
      return;
   }

   if(runThread != NULL)
   {
	   mModel->destroyThread(runThread);
	   runThread = NULL;
   }

   mAnimationSeq = index;
   
   runThread = mModel->addThread();
   mModel->setSequence(runThread, mAnimationSeq, 0);
}

Here is the code for renderWorld:

void GuiObjectView::renderWorld(const RectI &updateRect)
{
   if ((! mModel) && (! mMountedModel))
   {
      // nothing to render, punt
      return;
   }

   // Determine the camera position, and store off render state...
   MatrixF modelview;
   MatrixF mv;
   Point3F cp;

   modelview = GFX->getWorldMatrix();

   mv = modelview;
   mv.inverse();
   mv.getColumn(3, &cp);

   RenderPassManager *renderPass = gClientSceneGraph->getRenderPass();

   LightManager* lm = gClientSceneGraph->getLightManager();   
   if (lm->getSpecialLight(LightManager::slSunLightType) != mFakeSun)   
	    lm->setSpecialLight(LightManager::slSunLightType, mFakeSun);   
  
   GFX->setStateBlock(mDefaultGuiSB);

   MatrixF meshCamTrans(true);

   F32 left, right, top, bottom, nearPlane, farPlane;
   bool isOrtho;
   GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho);

   Frustum frust( false, left, right, top, bottom, nearPlane, farPlane, meshCamTrans );

   SceneState state(
      NULL,
      gClientSceneGraph,
      SPT_Diffuse,
      1,
      frust,
      GFX->getViewport(),
      meshCamTrans,
      false );

   // Set up our TS render state here.
   TSRenderState rdata;
   rdata.setCamTransform( meshCamTrans );
   rdata.setSceneState( &state );

   if (mModel)
   {
          if(runThread != NULL)
	  {
		S32 time = Platform::getVirtualMilliseconds();
		S32 dt = time - lastRenderTime;
		lastRenderTime = time;

		F32 fdt = dt;
		mModel->advanceTime( fdt/1000.f, runThread );
		mModel->animate();
	  }

      mModel->render( rdata );
   }

   if (mMountedModel)
   {
      // render a weapon
      MatrixF mat;
      getMountedObjTransform(&mat);

      GFX->pushWorldMatrix();
      GFX->multWorld( mat );
      
      mMountedModel->render( rdata );

      GFX->popWorldMatrix();
   }

   renderPass->renderPass(&state);
}

That's it! With this you should be able to call setSeq after setModel to set up an animation. I haven't tried this inside a mission yet but it works fine outside a mission. Again, if there is a better way to do this please let me know.
#7
10/05/2009 (9:52 pm)
thanks for this post Davide, totally hit this bug and here was the fix !