Game Development Community

dev|Pro Game Development Curriculum

Updated GuiObjectView for TGEA 1.7.1 and 1.8.0

by Jaimi McEntire · 02/01/2009 (12:31 pm) · 26 comments

This is an updated GuiObjectView for TGEA versions 1.7.1 and 1.8.0. This includes new properties for lighting and interaction, and a bug fix.

Link: GuiObjectView Link

What's New:

Bug Fix: If the model is larger than 5 units, the Min and Max distance are automatically adjusted.

Bug Fix: SetSeq (SetObjectAnimation) was doing nothing. Thanks Mike!

New Properties:
Azimuth - The angle of the light around the Z axis (degrees)
Elevation - The Pitch of the light (degrees)
LightColor - The color of the light (ColorF)
Ambient - The ambient color (ColorF)


LockOrbit - Locks the orbit distance (bool)
OrbitDistance - The distance that the orbit distance is locked at (F32)

LockXRotation - Locks the rotation on the X axis (bool)
LockedXRotation - The value the X axis rotation is locked at (F32, Radians)

LockZRotation - Locks the rotation on the Z axis (bool)
LockedZRotation - The value that the Z Axis is locked at (F32, radians)

For example, If you only want the user to scroll around the object (instead of looking at the top and bottom):


MyObjectView.LockXRotation = true;
MyObjectView.LockedXRotation = 0;

Perhaps you want the lighting to be off center, to give a better shaded look:

MyObjectView.Azimuth = 190;
MyObjectView.Elevation = 45;
MyObjectView.Ambient = "0.3 0.3 0.3 1"; // Lower the ambient color

The zip file contains versions for both TGEA 1.7.1 and TGEA 1.8.0 in separate directories.

Still several things I plan to do:

1. Add support for multiple attachments (currently it's limited to 1)
2. Draw a shadow under the player to give a more 3D appearance

Update:

Added animation support thanks to Matt J. The zip file has been updated.
Page «Previous 1 2
#1
02/01/2009 (6:00 pm)
Excellent work on this and your other resources. thanks a bunch.
#2
02/01/2009 (11:23 pm)
Thank you Jaimi, this is saving me many hours! You should start calling your resources Jems. :)
#3
02/02/2009 (6:58 pm)
Thanks for the resource.

I went ahead and re-added animation support, as my game requires it (it looks like it was in there at one time though).

For anyone interested, make the following changes to add animation support:

In guiObjectView.h, change
class GuiObjectView : public GuiTSCtrl
to
class GuiObjectView : public GuiTSCtrl, public virtual ITickable
and add the following functions:
void setObjectAnimation(S32 index);
void setObjectAnimationByName(const char* name);
virtual void advanceTime( F32 timeDelta );

I also added an extra variable, 'thread':
TSThread *  runThread,*thread; //add the second var

Now, in GuiObjectView.cpp, replace
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;
   }

   mAnimationSeq = index;
}
with
void GuiObjectView::advanceTime( F32 timeDelta )
{
	if(mModel)
	mModel->advanceTime( timeDelta, thread );
}

void GuiObjectView::setObjectAnimationByName(const char* name)
{
   if(mModel)
   setObjectAnimation(mModel->getShape()->findSequence(name));
}
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)
   {
	   mAnimationSeq = index;
	   if(thread)
		   mModel->setSequence(thread,mAnimationSeq,0);
   }
}

Now, at the bottom of GuiObjectView::setObjectModel, add this:
thread = mModel->addThread();

Finally, find (in GuiObjectView::renderWorld)
if (mModel)
   {
      // animate and render in a run pose
      //F32 fdt = dt;
      // mModel->advanceTime( fdt/1000.f, runThread );
      // mModel->animate();
      mModel->render();
   }
and uncomment mModel->animate(), so it looks like this
if (mModel)
   {
      // animate and render in a run pose
      //F32 fdt = dt;
      // mModel->advanceTime( fdt/1000.f, runThread );
      mModel->animate();
      mModel->render();
   }

That's it for source changes.
Now, in your GUI script, in the OnWake function, add
view.setSequence("idle");
and of course replace view with whatever you named the objectview control, and idle with whatever animation you want.
#4
02/02/2009 (7:58 pm)
Thanks for the update, Matt. I went ahead and added the code to the download above - I'll update the resource to show the new functionality. I did make a couple of changes mostly to do with using runThread instead of creating a new thread.

Also, I needed to add

#include "core/itickable.h" to guiobjectview.h

and added these stubs so that guiObjectView was not abstract:

virtual void interpolateTick( F32 delta ) {};
virtual void processTick() {};



#5
02/08/2009 (4:03 am)
Uhm guys; I know the rule -never post when tired, but...

I have afully working and fresh compiled version of the thing you posted here and I've been trying to set an animation using modelview.setSequence("player_forwardw.dsq");

I get this feedback, and no animation playing...
scriptsAndAssets/client/scripts/createActorGui.cs (120): Unknown command setSequence.
Object modelView(4576) modelView -> GuiObjectView -> GuiTSCtrl -> GuiContainer -> GuiControl -> SimGroup -> SimSet -> SimObject

Is it just me or is anything broken ?
#6
02/08/2009 (8:05 am)
its setSeq:

ConsoleMethod(GuiObjectView, setSeq, void, 3, 3,
"(int index)\n"
"Sets the animation to play for the viewed object.\n\n"
"\\param index The index of the animation to play.")
#7
02/12/2009 (6:03 am)
Great work Jaimi
#8
03/19/2009 (1:18 pm)
Excellent resource ... unfortunately as usual it is me and the dreaded SetSequence.

I have tried setSeq(0); and setSeq("root"); and unfortunately the model displays correctly but the animation is never run. The animations are seperate DSQ files. Any suggesstions?

EDIT: Never mind ... it was a timing issue ... maybe I shouldn't work on my game when I haven't slept for like 2 days. :)
#9
03/24/2009 (1:17 am)
Where is the UnMount function?
Thanks!
#10
04/02/2009 (10:40 pm)
Sorry! I found something bugs when mount more than 2 times.
objview.setMount("DTSfile",0);
see the mount0

objview.setMount("DTSfile",0);
objview.setMount("DTSfile",1);
only see the mount1

Is ObjectView support that?
#11
04/10/2009 (1:51 am)
@ccljyc
actually ObjectView can mount an object only to mount0 node.
I've modified the code to handle more than one object, it's not difficult, just an extension to the actual code.
Don't know if I find the time today to post here my code, anyways I'll do it as soon as possible.
#12
04/14/2009 (5:06 am)
Ok, here's the code
First we need to store the objects models and their nodes so:
enum Nodes { MAX_NODES = 6};   //Add this line

   MouseState  mMouseState;

   TSShapeInstance*  mModel;
   TSShapeInstance*  mMountedModel[MAX_NODES];		//we need a vector 
   U32   mSkinTag;
   ...
   S32 mMountNode[MAX_NODES];           //

...
  void unMount(S32 mountPoint);        //the unmount function
  void getMountedObjTransform(MatrixF* mat, S32 mPoint);   //Changed this function to return the transform of the node mPoint
...

Now in the constructor, remove the
...
mMountModel(NULL),
...
mMountNode(NO_NODE),
...
and add in the constructor body this
for (int n=0; n<MAX_NODES; n++)
	{
		mMountedModel[n] = NULL;
		mMountNode[n] = NO_NODE;
	}

In the destructor replace the
SAFE_DELETE(mMountedModel);
with
for (int n=0; n<MAX_NODES; n++)			
	{
		SAFE_DELETE(mMountedModel[n]);
	}
Now in the setObjectModel function change the code to this one
...
   // the first time recording
   lastRenderTime = Platform::getVirtualMilliseconds();

   char * mountName = new char[16];
	for (int n=0; n<MAX_NODES; n++)		//Loop to find all the mount nodes
	{
		dStrncpy(mountName, avar("mount%d", n), 15);   //here we have n not 0
		mMountNode[n] = mModel->getShape()->findNode(mountName);
	}
   delete [] mountName;
...

Now the setMountedObject function
void GuiObjectView::setMountedObject(const char * modelName, S32 mountPoint)
{
   SAFE_DELETE(mMountedModel[mountPoint]);		//***** 

   // create a weapon for this dude
   Resource<TSShape> model = ResourceManager::get().load(modelName);

   if (! bool(model))
   {
      Con::warnf(avar("GuiObjectView: Failed to load mounted object model %s. Please check your model name and load a valid model.", modelName));
      return;
   }

	/*
   char * mountName = new char[16];
   dStrncpy(mountName, avar("mount%d", 0), 15);
   mMountNode = mModel->getShape()->findNode(mountName);
   delete [] mountName;
	*/ // code commented out because the mMountNode has been already initialized in the SetObjectModel function, if we haven't a model we shouldn't mount an object to it!

   mMountedModel[mountPoint] = new TSShapeInstance(model, true);
   AssertFatal(mMountedModel[mountPoint], avar("GuiObjectView: Failed to load mounted object model %s. Please check your model name and load a valid model.", modelName));
}
The new unMount function
void GuiObjectView::unMount(S32 mountPoint)
{
	SAFE_DELETE(mMountedModel[mountPoint]);
}
and now the modified getMountedObjTransform
void GuiObjectView::getMountedObjTransform(MatrixF * mat, S32 mPoint)
{
   if ((! mMountedModel[mPoint]) || (mMountNode[mPoint] == NO_NODE))
   {
      // there is no mounted model or node to mount to
      return;
   }

   MatrixF mountedTrans;
   mountedTrans.identity();

   S32 mountPoint = mMountedModel[mPoint]->getShape()->findNode("mountPoint");
   if (mountPoint != -1)
      mountedTrans = mMountedModel[mPoint]->mNodeTransforms[mountPoint];
    
   Point3F mountedOffset = -mountedTrans.getPosition();
   MatrixF modelTrans = mModel->mNodeTransforms[mMountNode[mPoint]];
   modelTrans.mulP(mountedOffset);
   modelTrans.setPosition(mountedOffset);
   *mat = modelTrans;
}

The renderWorld function
void GuiObjectView::renderWorld(const RectI &updateRect)
{
   if ((! mModel) )//&& (! mMountedModel))    //remove the mMountedModel check
   {
      // nothing to render, punt
      return;
   }
...
   if (mModel)
   {
      // MIKE J.
      mModel->animate(); 
      // MIKE J.
      mModel->render();
   }

	for (int n=0; n<MAX_NODES; n++)			//loop for each mounted object
	{
		if (mMountedModel[n])
		{
			// render a weapon
			MatrixF mat;
			getMountedObjTransform(&mat,n);

			GFX->pushWorldMatrix();
			GFX->multWorld( mat );
      
			mMountedModel[n]->render();

			GFX->popWorldMatrix();
		}
	}

   F32 left, right, top, bottom, nearPlane, farPlane;
   bool isOrtho;

...

now we need only the script for the unMount function
ConsoleMethod(GuiObjectView, unMount, void, 3, 3, "(mountpoint)")
{
	argc;
	object->unMount(dAtoi(argv[2]));
}

Ok, that's all.


#13
04/14/2009 (8:58 pm)
Thank You!
I can support mount objects ("mount0"~"mount31") now!
My changes are...
1.
enum Nodes { MAX_MOUNT_NODE = 32}; //MAX_NODES

2.void GuiObjectView::getMountedObjTransformByIndex(MatrixF * mat, S32 index) //new getMountedObjTransform
S32 mountPoint = mMountedModel->getShape()->findNode("mountPoint");
To
S32 mountPoint = mMountedModel[index]->getShape()->findNode( avar("mount%d",index) );	//CCL add
3.void GuiObjectView::renderWorld(const RectI &updateRect)
for(int i=0;i<MAX_MOUNT_NODE;i++)	
{
 if (mMountedModel[i])   
 {...}
}
To
for(int i=0;i<MAX_MOUNT_NODE;i++)	
{
 if (mMountedModel[i] && (mMountNode[i]!=NO_NODE)) //CCL add  
 {...}
It's working for me in TGEA 1.7.1
#14
05/26/2009 (9:51 pm)
Good!! Thanks Jaimi :D
#15
06/06/2009 (6:22 pm)
I added the code posted above from Davide Archetti, got a successful rebuild but I have a question about how to work it. I can still only get one object to mount at a time. Also the unmount function isn't being recognized, is the problem probably with my rebuild then?
#16
06/06/2009 (11:09 pm)
@Jeff
perhaps you should post the script you use, and check if there are some console errors.

#17
06/07/2009 (2:23 pm)
I hit 'rebuild solution' instead of 'rebuild "projectName"'. The unMount works just fine now, so I'm assuming so will mounting multiple objects.
#18
06/10/2009 (11:01 pm)
I tried changing the maxOrbitDist to 10 since my models are quite a bit larger then the player models. I get a successful rebuild, but the max is still 5, should I be changing something somewhere besides these values?

GuiObjectView::GuiObjectView()
:  mMaxOrbitDist(10.0f),
   mMinOrbitDist(0.0f),
   mOrbitDist(10.0f),
#19
06/11/2009 (2:56 pm)
Broken link for file download (expired domain)?
#20
06/11/2009 (7:22 pm)
ObjectView.setSeq(1);

-> TSThread::setSequence: invalid shape handle, sequence number, or position.

setSeq not working. bug?
Page «Previous 1 2