Client side TSStatic object
by Thomas \"Man of Ice\" Lund · 09/30/2004 (11:45 am) · 44 comments
Download Code File
What is this
With this code you can create 3d ingame objects that only exist in the scene of the client owning them. They do not exist on the server or other clients, and thus there is absolutely no overhead on the network when using these.
These objects are perfect for creating rich GUI's like waypoints, 3d reticles and other interfaces that you would otherwise have to do in 2d.
How to add
Simply unzip the files in the zip and dump into your game dir. Recompile. As simple as that
How to use
You can use this object from e.g. a GUI control. This example snippit below shows how to create the object on the client side. Remember to set a position.
There is no script interface. I'll leave that as an exercise to the reader ;-)
A special thanks to Ben for help on this resource.
What is this
With this code you can create 3d ingame objects that only exist in the scene of the client owning them. They do not exist on the server or other clients, and thus there is absolutely no overhead on the network when using these.
These objects are perfect for creating rich GUI's like waypoints, 3d reticles and other interfaces that you would otherwise have to do in 2d.
How to add
Simply unzip the files in the zip and dump into your game dir. Recompile. As simple as that
How to use
You can use this object from e.g. a GUI control. This example snippit below shows how to create the object on the client side. Remember to set a position.
ClientSideTSStatic* pWaypointMarker = new ClientSideTSStatic();
pWaypointMarker ->setField("shapeName", "game/data/shapes/waypoint.dts");
// Register the Object.
if (!pWaypointMarker ->registerObject())
{
Con::errorf("Could not create waypoint marker");
delete pWaypointMarker ;
}There is no script interface. I'll leave that as an exercise to the reader ;-)
A special thanks to Ben for help on this resource.
#3
-Barzahd
10/05/2004 (5:08 am)
Just as a general inquiry... How would one implement one of these so-called "rich GUIs"? For example, I would like to have the number of rounds and clips displayed in the weapon the player is currently using, sort of like Halo. Any ideas on how something like this could be done?-Barzahd
#4
I am not proficient in C++ so I had Robert Brower implement this resource and modify it to have an interface for scripted object placement. Here are the modifications Robert created for me:
Add this to the clientSideTSStatic.cc file:
Here is the call to use in Script:
Good luck and enjoy this addition to the resource. Thanks Robert for helping me out with this!
12/10/2004 (4:57 pm)
Thomas, Thanks for this resource! I needed this resource for client side only TSStatic objects. I did not use them as GUI, I actually used this resource to place Trees, etc in the world without any other client or the server knowing.I am not proficient in C++ so I had Robert Brower implement this resource and modify it to have an interface for scripted object placement. Here are the modifications Robert created for me:
Add this to the clientSideTSStatic.cc file:
// 12-08-2004 RFB -> console method to add shapes. can be called from client side script
ConsoleFunction( addClientSideTSStatic, S32, 5, 5, "(string shapeName, string position, string rotation, string scale)")
{
ClientSideTSStatic* pCSStatic = new ClientSideTSStatic();
pCSStatic->setField("shapeName", argv[1]);
pCSStatic->setField("position", argv[2]);
pCSStatic->setField("rotation", argv[3]);
pCSStatic->setField("scale", argv[4]);
// register the object
if (!pCSStatic->registerObject())
{
Con::errorf("Could not register a ClientSideTSStatic");
delete pCSStatic;
return false;
}
return true;
}
// <- 12-08-2004 RFBHere is the call to use in Script:
addClientSideTSStatic(%dtsincludingpath, %position, %rotation, %scale);
Good luck and enjoy this addition to the resource. Thanks Robert for helping me out with this!
#5
12/10/2004 (5:01 pm)
I hope she works! Good luck!
#6
12/11/2004 (1:11 am)
Verrrrryyyy cool :-)
#7
Thanks
02/05/2005 (10:28 pm)
I have added this resource and I can add TSStatic objects with a script command, but when I do the objects have no handle in the world editor. Could anyone give me an idea why that is?Thanks
#8
Also, the collisions of those realtime spawned clientside objects are not working properly.. Anyone knows how to fix this?
08/15/2005 (10:44 pm)
Thanks to everyone who posted on this topic so far! I played with the code Funkypeople posted and was able to make a a clientside object manager that can be accesed through the console. As Brandon noted, none of the client side objects are accesible from the world editor for reasons unknown to me. Also, the collisions of those realtime spawned clientside objects are not working properly.. Anyone knows how to fix this?
#9
03/12/2006 (10:03 pm)
I think I am right among those on the loyal wait for the response~
#10
Thats should also explain collisions and all the other things that "normally" work with regular objects. These things are calculated server side, and thats not happening with client side only objects.
So you can use these to offload work on the server, create 3d GUI elements and e.g.
They are _not_ regular objects
:-)
03/13/2006 (1:19 am)
The objects dont show up in the world editor, because they do not exist on the server side. There is no object id, replication to the clients etc.etc. - and thats what the editor manipulates.Thats should also explain collisions and all the other things that "normally" work with regular objects. These things are calculated server side, and thats not happening with client side only objects.
So you can use these to offload work on the server, create 3d GUI elements and e.g.
They are _not_ regular objects
:-)
#11
ClientSideTSStatic* pCSStatic = new ClientSideTSStatic();
04/13/2006 (5:32 am)
Anyone got this one to work under 1.4? My code seem to crash once it reaches ClientSideTSStatic* pCSStatic = new ClientSideTSStatic();
#12
function OnAdd
an example to create a shape in script
put it at the end of PlayGUI::OnWake (playgui.cs)
05/11/2006 (9:35 pm)
In order to work in 1.4 you should change following code:function OnAdd
bool ClientSideTSStatic::onAdd()
{
// Skip TSStatic onAdd
if(!SceneObject::onAdd())
return false;
if (!mShapeName || mShapeName[0] == '[[60c21f2b4c819]]')
{
Con::errorf("TSStatic::onAdd: no shape name!");
return false;
}
mShapeHash = _StringTable::hashString(mShapeName);
mShape = ResourceManager->load(mShapeName);
if (bool(mShape) == false)
{
Con::errorf("TSStatic::onAdd: unable to load shape: %s", mShapeName);
return false;
}
/* if(isClientObject() && !mShape->preloadMaterialList() && NetConnection::filesWereDownloaded())
return false; */
mObjBox = mShape->bounds;
resetWorldBox();
setRenderTransform(mObjToWorld);
mShapeInstance = new TSShapeInstance(mShape, true);
// Scan out the collision hulls...
//=== Tuan remove 12.5
/* U32 i;
for (i = 0; i < 8; i++)
{
char buff[128];
dSprintf(buff, sizeof(buff), "Collision-%d", i + 1);
mCollisionDetails[i] = mShape->findDetail(buff);
mLOSDetails[i] = mCollisionDetails[i];
}
// Compute the hull accelerators (actually, just force the shape to compute them)
for (i = 0; i < 8; i++)
{
if (mCollisionDetails[i] != -1) {
mShapeInstance->getShape()->getAccelerator(mCollisionDetails[i]);
}
}
//End remove
*/
//=== Tuan add 12.5
U32 i;
for (i = 0; i < mShape->details.size(); i++)
{
char* name = (char*)mShape->names[mShape->details[i].nameIndex];
if (dStrstr((const char*)dStrlwr(name), "collision-"))
{
mCollisionDetails.push_back(i);
// The way LOS works is that it will check to see if there is a LOS detail that matches
// the the collision detail + 1 + MaxCollisionShapes (this variable name should change in
// the future). If it can't find a matching LOS it will simply use the collision instead.
// We check for any "unmatched" LOS's further down
mLOSDetails.increment();
char buff[128];
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1);
U32 los = mShape->findDetail(buff);
if (los == -1)
mLOSDetails.last() = i;
else
mLOSDetails.last() = los;
}
}
// Snag any "unmatched" LOS details
for (i = 0; i < mShape->details.size(); i++)
{
char* name = (char*)mShape->names[mShape->details[i].nameIndex];
if (dStrstr((const char*)dStrlwr(name), "los-"))
{
// See if we already have this LOS
bool found = false;
for (U32 j = 0; j < mLOSDetails.size(); j++)
{
if (mLOSDetails[j] == i)
{
found = true;
break;
}
}
if (!found)
mLOSDetails.push_back(i);
}
}
// Compute the hull accelerators (actually, just force the shape to compute them)
for (i = 0; i < mCollisionDetails.size(); i++)
mShapeInstance->getShape()->getAccelerator(mCollisionDetails[i]);
//=== Tuan end add.
gClientContainer.addObject(this);
gClientSceneGraph->addObjectToScene(this);
return true;
}an example to create a shape in script
put it at the end of PlayGUI::OnWake (playgui.cs)
%pNPCMarker = new ClientSideTSStatic()
{
shapeName = "starter.fps/data/shapes/player/player.dts";
position = "195.826 117.462 223.813";
rotate = "0 0 -1 88.2355";
scale = "6.57362 7.48607 7.449463";
};
#13
Thanx
06/14/2006 (6:59 am)
Verry good resource!!! Thanx!!! One question, has someone modified this to use StaticShape instead of TSStatic, so we can for example change the skin of the object? Or is it not possible to use StaticShape?Thanx
#14
I found removeObjectFromScene,.. but how do i set that up for the script? I only need 1 thing per client.
07/30/2006 (11:39 am)
I have used the ConsoleFunction addClientSideTSStatic. It's great. How do i remove one again? Based on id or name or something. I'm having a click-to-walk game, and when you click it shows a little waypoint on the terrain... except i want it to dissappear again after he has reached that location or if he clicked again.I found removeObjectFromScene,.. but how do i set that up for the script? I only need 1 thing per client.
#15
StaticShape derives from ShapeBase, TSStatic is a totally different beast. This resource aint about advanced objects that collide, take damage, move.. etc. They are static client side objects. I dont know why people keep asking, it says all this in the description or the comments afterwards.
09/07/2006 (1:51 am)
Klass,StaticShape derives from ShapeBase, TSStatic is a totally different beast. This resource aint about advanced objects that collide, take damage, move.. etc. They are static client side objects. I dont know why people keep asking, it says all this in the description or the comments afterwards.
#16
I would like to use this as the start of my waypoint/Target directional arrow/pointer, and it seems to be the correct starting point.
How would I move/rotate this? Just add another ConsoleFunction? Then again comes the question of to what the Id or handle is. Any insight would be great...
02/06/2007 (4:21 am)
Okay.... Is it possible to move this? Because a static is not really moveable. I would like to use this as the start of my waypoint/Target directional arrow/pointer, and it seems to be the correct starting point.
How would I move/rotate this? Just add another ConsoleFunction? Then again comes the question of to what the Id or handle is. Any insight would be great...
#17
Movement can be dont using setTransform on the object inside the GUI code - on the same level as server side objects. But you will have to add console methods yourself and the needed interpolation code (if you want that).
I used this for a 3d target reticle that was moved to where the mouse pointed. It even pulsed with an animation.
What I would do in your case is to save a pointer to the object that you create in an array or hash array. Then generate id's yourself and use those as part of the console methods.
02/06/2007 (5:34 am)
Hi JamesMovement can be dont using setTransform on the object inside the GUI code - on the same level as server side objects. But you will have to add console methods yourself and the needed interpolation code (if you want that).
I used this for a 3d target reticle that was moved to where the mouse pointed. It even pulsed with an animation.
What I would do in your case is to save a pointer to the object that you create in an array or hash array. Then generate id's yourself and use those as part of the console methods.
#18
This seems harder than I was hoping for.
But I'll poke it, and see if it moves.
What have you done for waypoints in Air Ace?
02/06/2007 (5:59 am)
Wow... I have no idea how to do the Interpolation Code, was trying to avoid it... and hash arrays for the id's, I have no idea what that is or why I would use them, hehe. This seems harder than I was hoping for.
But I'll poke it, and see if it moves.
What have you done for waypoints in Air Ace?
#19
So there are ways to get around the math :-)
Else try to look in the item code - that has a simple rotation.
We dont have waypoints in Air Ace, as its a pure online deathmatch thing. So no need for it :-)
02/06/2007 (11:18 am)
You only need the interpolation if you want smooth movement/rotation between setting new values for the transformation. If you want to use absolute positions/rotations, then you dont need it. E.g. you can use a dts that has an animation in it instead.So there are ways to get around the math :-)
Else try to look in the item code - that has a simple rotation.
We dont have waypoints in Air Ace, as its a pure online deathmatch thing. So no need for it :-)
#20
I always thought it's to make sure the movement is smooth between updates from the server.
It's beside the point... But I was just wondering.
Thanx for the replies.
02/06/2007 (11:21 pm)
Would you need Interpolation when the object is only ever on the client? I always thought it's to make sure the movement is smooth between updates from the server.
It's beside the point... But I was just wondering.
Thanx for the replies.

Torque Owner Josh Moore