Modified GuiShapeNameHUD
by Dreamer · 02/23/2006 (10:50 am) · 11 comments
On a lark I decided for fun I would see if I could get the GuiShapeNameHud to display damage values as well as names...
Well I took the relevant bits from GuiCrossHairHud and merged them in.
It works!
*update*
Added the ability to turn the damage view on and off, I also added the ability to change how far away you can see the players name and damage.
Just replace your current GuiShapeNameHud.cc file with this one and recomplie...
Enjoy!
Well I took the relevant bits from GuiCrossHairHud and merged them in.
It works!
*update*
Added the ability to turn the damage view on and off, I also added the ability to change how far away you can see the players name and damage.
Just replace your current GuiShapeNameHud.cc file with this one and recomplie...
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/dgl.h"
#include "dgl/gNewFont.h"
#include "gui/core/guiControl.h"
#include "gui/core/guiTSControl.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "game/shapeBase.h"
#include "game/gameConnection.h"
//----------------------------------------------------------------------------
/// Displays name & damage above shape objects.
///
/// This control displays the name and damage value of all named
/// ShapeBase objects on the client. The name and damage of objects
/// within the control's display area are overlayed above the object.
///
/// This GUI control must be a child of a TSControl, and a server connection
/// and control object must be present.
///
/// This is a stand-alone control and relies only on the standard base GuiControl.
class GuiShapeNameHud : public GuiControl
{
typedef GuiControl Parent;
// field data
ColorF mFillColor;
ColorF mFrameColor;
ColorF mTextColor;
F32 mVerticalOffset;
F32 mDistanceFade;
// Visible distance info & name fading
F32 mVisDistance;
bool mShowFrame;
bool mShowFill;
bool mShowDamage;
ColorF mDamageFillColor;
ColorF mDamageFrameColor;
Point2I mDamageRectSize;
Point2I mDamageOffset;
protected:
void drawName( Point2I offset, const char *buf, F32 opacity);
void drawDamage(Point2I offset, F32 damage, F32 opacity);
public:
GuiShapeNameHud();
// GuiControl
virtual void onRender(Point2I offset, const RectI &updateRect);
// object selection additions
virtual void onMouseDown(const GuiEvent &evt);
static void initPersistFields();
DECLARE_CONOBJECT( GuiShapeNameHud );
};
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiShapeNameHud);
/// Default distance for object's information to be displayed.
static const F32 cDefaultVisibleDistance = 500.0f;
GuiShapeNameHud::GuiShapeNameHud()
{
mFillColor.set( 0.25, 0.25, 0.25, 0.25 );
mFrameColor.set( 0, 1, 0, 1 );
mTextColor.set( 0, 1, 0, 1 );
mShowFrame = mShowFill = true;
mShowDamage = true;
mVerticalOffset = 0.5;
mDistanceFade = 0.1;
mVisDistance = gClientSceneGraph->getVisibleDistance();
mDamageFillColor.set( 0, 1, 0, 1 );
mDamageFrameColor.set( 1, 0.6, 0, 1 );
mDamageRectSize.set(50, 4);
mDamageOffset.set(0,32);
}
void GuiShapeNameHud::initPersistFields()
{
Parent::initPersistFields();
addGroup("Colors");
addField( "fillColor", TypeColorF, Offset( mFillColor, GuiShapeNameHud ) );
addField( "frameColor", TypeColorF, Offset( mFrameColor, GuiShapeNameHud ) );
addField( "textColor", TypeColorF, Offset( mTextColor, GuiShapeNameHud ) );
endGroup("Colors");
addGroup("Misc");
addField( "showFill", TypeBool, Offset( mShowFill, GuiShapeNameHud ) );
addField( "showFrame", TypeBool, Offset( mShowFrame, GuiShapeNameHud ) );
addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, GuiShapeNameHud ) );
addField( "distanceFade", TypeF32, Offset( mDistanceFade, GuiShapeNameHud ) );
addField( "visibleDistance", TypeF32, Offset( mVisDistance, GuiShapeNameHud ) );
endGroup("Misc");
addGroup("Damage");
addField( "showDamage", TypeBool, Offset( mShowDamage, GuiShapeNameHud ) );
addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiShapeNameHud) );
addField( "damageFrameColor", TypeColorF, Offset( mDamageFrameColor, GuiShapeNameHud) );
addField( "damageRect", TypePoint2I, Offset( mDamageRectSize, GuiShapeNameHud) );
addField( "damageOffset", TypePoint2I, Offset( mDamageOffset, GuiShapeNameHud) );
endGroup("Damage");
}
//--------------------------------------------------------------------------
// object selection additions
//--------------------------------------------------------------------------
void GuiShapeNameHud::onMouseDown(const GuiEvent &evt)
{
// Let's let the parent execute its event handling (if any)
GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
if (parent)
parent->onMouseDown(evt);
}
//----------------------------------------------------------------------------
/// Core rendering method for this control.
///
/// This method scans through all the current client ShapeBase objects.
/// If one is named, it displays the name and damage information for it.
///
/// Information is offset from the center of the object's bounding box,
/// unless the object is a PlayerObjectType, in which case the eye point
/// is used.
///
/// @param updateRect Extents of control.
void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
{
// Background fill first
if (mShowFill)
dglDrawRectFill(updateRect, mFillColor);
// Must be in a TS Control
GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
if (!parent) return;
// Must have a connection and control object
GameConnection* conn = GameConnection::getConnectionToServer();
if (!conn)
return;
ShapeBase* control = conn->getControlObject();
if (!control)
return;
// Get control camera info
MatrixF cam;
Point3F camPos;
VectorF camDir;
conn->getControlCameraTransform(0,&cam);
cam.getColumn(3, &camPos);
cam.getColumn(1, &camDir);
F32 camFov;
conn->getControlCameraFov(&camFov);
camFov = mDegToRad(camFov) / 2;
// Visible distance info & name fading
//F32 visDistance = gClientSceneGraph->getVisibleDistance();
//F32 visDistanceSqr = visDistance / 2;
F32 fadeDistance = mVisDistance * mDistanceFade;
// Collision info. We're going to be running LOS tests and we
// don't want to collide with the control object.
static U32 losMask = TerrainObjectType | InteriorObjectType | ShapeBaseObjectType;
control->disableCollision();
// All ghosted objects are added to the server connection group,
// so we can find all the shape base objects by iterating through
// our current connection.
for (SimSetIterator itr(conn); *itr; ++itr)
{
if ((*itr)->getType() & ShapeBaseObjectType)
{
ShapeBase* shape = static_cast<ShapeBase*>(*itr);
if (shape != control && shape->getShapeName())
{
// Target pos to test, if it's a player run the LOS to his eye
// point, otherwise we'll grab the generic box center.
Point3F shapePos;
if (shape->getType() & PlayerObjectType)
{
MatrixF eye;
// Use the render eye transform, otherwise we'll see jittering
shape->getRenderEyeTransform(&eye);
eye.getColumn(3, &shapePos);
}
else
{
// Use the render transform instead of the box center
// otherwise it'll jitter.
MatrixF srtMat = shape->getRenderTransform();
srtMat.getColumn(3, &shapePos);
}
VectorF shapeDir = shapePos - camPos;
// Test to see if it's in range
F32 shapeDist = shapeDir.lenSquared();
if (shapeDist == 0 || shapeDist > mVisDistance)
continue;
shapeDist = mSqrt(shapeDist);
// Test to see if it's within our viewcone, this test doesn't
// actually match the viewport very well, should consider
// projection and box test.
shapeDir.normalize();
F32 dot = mDot(shapeDir, camDir);
if (dot < camFov)
continue;
// Test to see if it's behind something, and we want to
// ignore anything it's mounted on when we run the LOS.
RayInfo info;
shape->disableCollision();
ShapeBase *mount = shape->getObjectMount();
if (mount)
mount->disableCollision();
bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info);
shape->enableCollision();
if (mount)
mount->enableCollision();
if (!los)
continue;
// Project the shape pos into screen space and calculate
// the distance opacity used to fade the labels into the
// distance.
Point3F projPnt;
shapePos.z += mVerticalOffset;
if (!parent->project(shapePos, &projPnt))
continue;
F32 opacity = (shapeDist < fadeDistance)? 1.0:
1.0 - (shapeDist - fadeDistance) / (mVisDistance - fadeDistance);
// Render the shape's name
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
if(mShowDamage)
drawDamage(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getDamageValue(), opacity);
}
}
}
// Restore control object collision
control->enableCollision();
// Border last
if (mShowFrame)
dglDrawRect(updateRect, mFrameColor);
}
//----------------------------------------------------------------------------
/// Render object names.
///
/// Helper function for GuiShapeNameHud::onRender
///
/// @param offset Screen coordinates to render name label. (Text is centered
/// horizontally about this location, with bottom of text at
/// specified y position.)
/// @param name String name to display.
/// @param opacity Opacity of name (a fraction).
void GuiShapeNameHud::drawName(Point2I offset, const char *name, F32 opacity)
{
// Center the name
offset.x -= mProfile->mFont->getStrWidth((const UTF8 *)name) / 2;
offset.y -= mProfile->mFont->getHeight();
// Deal with opacity and draw.
mTextColor.alpha = opacity;
dglSetBitmapModulation(mTextColor);
dglDrawText(mProfile->mFont, offset, name);
dglClearBitmapModulation();
}
void GuiShapeNameHud::drawDamage(Point2I offset, F32 damage, F32 opacity)
{
mDamageFillColor.alpha = mDamageFrameColor.alpha = opacity;
// Damage should be 0->1 (0 being no damage,or healthy), but
// we'll just make sure here as we flip it.
damage = mClampF(1 - damage, 0, 1);
// Center the bar
RectI rect(offset, mDamageRectSize);
rect.point.x -= mDamageRectSize.x / 2;
// Draw the border
dglDrawRect(rect, mDamageFrameColor);
// Draw the damage % fill
rect.point += Point2I(1, 1);
rect.extent -= Point2I(1, 1);
rect.extent.x = (S32)(rect.extent.x * damage);
if (rect.extent.x == 1)
rect.extent.x = 2;
if (rect.extent.x > 0)
dglDrawRectFill(rect, mDamageFillColor);
}Enjoy!
#2
02/28/2006 (7:53 pm)
Ok I added those features and a couple more, now rate this a 5 please ;)
#3
07/14/2006 (9:19 pm)
rated as requested -:)
#4
07/16/2006 (4:17 pm)
Very useful 5*
#5
08/02/2006 (3:10 pm)
Dreamer I am running into a snag here. Say I want different color names based on what type of player/AI/team/whatever. How would you go about say, having a blue name for players and a red name for AI units?
#6
In the MMOKit we have modified it for instance to show the level difference between you and what your looking at.
Red for > 10 level Yellow for >5 white for equal etc.
It's not hard to do, and I may update this in the near future to show how it's done.
Regards,
Dreamer
08/02/2006 (4:15 pm)
Propegate the value, and change the color based on either the value or some mathematical representation of the value.In the MMOKit we have modified it for instance to show the level difference between you and what your looking at.
Red for > 10 level Yellow for >5 white for equal etc.
It's not hard to do, and I may update this in the near future to show how it's done.
Regards,
Dreamer
#7
09/24/2006 (1:18 am)
Great resource!
#8
I'm a hair away from cracking the code for guiShapeNameHud to allow for custom colors for in-game shapes, but I'm missing something small I believe. Perhaps you could check what I am doing:
In shapebase.h (in the public area of ShapeBase)
In shapeBase.cc
Also in shapeBase.cc, in the function ShapeBase::ShapeBase()
Finally in guiShapeNameHud.cc:
in class GuiShapeNamedHUD : public GuiControl change
protected:
void drawName( Point2I offset, const char *buf, F32 opacity)
to
protected:
void drawName( Point2I offset, const char *buf, F32 opacity, const char *cColor);
in guiShapeNamedHud::onRender change:
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
to
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity, shape->getTextColor());
and then:
Now interestingly enough, everything works EXCEPT for the console method setNameColor. The names are rendered in RED regardless of what the guishapenamehud control's color is set to, which is excellent because that's the default.
If I get an object's ID in the game then type in the console "echo(%obj.getnamecolor());", it returns the correct value of "1 0 0 1".
However, if I try to set the color using the console method %obj.setnamecolor("0 1 1 0"), not only does it NOT change the color, but when I try to type "echo(%obj.getnamecolor());" in the console it will return as blank or will actually return the literal words "%obj.getnamecolor()".
I am obviously doing something wrong that is very simple but I need another set of eyes to take a look at my code. It's proving to be a stubborn box to unlock.
Thanks!
12/03/2006 (9:43 am)
@Dreamer and anyone else who may be able to help:I'm a hair away from cracking the code for guiShapeNameHud to allow for custom colors for in-game shapes, but I'm missing something small I believe. Perhaps you could check what I am doing:
In shapebase.h (in the public area of ShapeBase)
//ADDED FOR CUSTOMIZING THE COLOR OF THE NAME char* mTextColor; /// The default color of the object's name void setTextColor(const char*); // <== added to set name color const char* getTextColor(); // <== added to return name color void setShapeName(const char*); const char* getShapeName(); void setSkinName(const char*); const char* getSkinName();
In shapeBase.cc
// ADDED TO SUPPORT CUSTOM SHAPENAME COLORS
void ShapeBase::setTextColor(const char* cColor)
{
mTextColor = (char *)cColor;
}
const char* ShapeBase::getTextColor()
{
return mTextColor;
}
ConsoleMethod( ShapeBase, getNameColor, const char*, 2, 2, "")
{
return object->mTextColor;
}
ConsoleMethod( ShapeBase, setNameColor, void, 3, 3, "Color(R G B A)")
{
object->setTextColor(argv[2]);
}
//Also in shapeBase.cc, in the function ShapeBase::ShapeBase()
mTextColor = "1 0 0 1"; // initializes the color to red
Finally in guiShapeNameHud.cc:
in class GuiShapeNamedHUD : public GuiControl change
protected:
void drawName( Point2I offset, const char *buf, F32 opacity)
to
protected:
void drawName( Point2I offset, const char *buf, F32 opacity, const char *cColor);
in guiShapeNamedHud::onRender change:
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity);
to
drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity, shape->getTextColor());
and then:
void GuiShapeNameHud::drawName(Point2I offset, const char *name, F32 opacity, const char *cColor)
{
// Center the name
offset.x -= mProfile->mFont->getStrWidth((const UTF8 *)name) / 2;
offset.y -= mProfile->mFont->getHeight();
//
// CUSTOM COLOR - Added from here
int i_red, i_green, i_blue, i_alpha;
dSscanf(cColor, "%d %d %d %d", &i_red, &i_green, &i_blue, &i_alpha );
mTextColor.set((const F32)i_red, (const F32)i_green, (const F32)i_blue, (const F32)i_alpha);
// CUSTOM COLOR - to here
//
// Deal with opacity and draw.
mTextColor.alpha = opacity;
dglSetBitmapModulation(mTextColor);
dglDrawText(mProfile->mFont, offset, name);
dglClearBitmapModulation();
}Now interestingly enough, everything works EXCEPT for the console method setNameColor. The names are rendered in RED regardless of what the guishapenamehud control's color is set to, which is excellent because that's the default.
If I get an object's ID in the game then type in the console "echo(%obj.getnamecolor());", it returns the correct value of "1 0 0 1".
However, if I try to set the color using the console method %obj.setnamecolor("0 1 1 0"), not only does it NOT change the color, but when I try to type "echo(%obj.getnamecolor());" in the console it will return as blank or will actually return the literal words "%obj.getnamecolor()".
I am obviously doing something wrong that is very simple but I need another set of eyes to take a look at my code. It's proving to be a stubborn box to unlock.
Thanks!
#9
01/31/2007 (7:21 pm)
#10
09/09/2007 (4:55 am)
I used the faction resource and instead of modifying guiCrosshairHud.cc, I modified guiShapeNameHud.cc.
#11
01/08/2008 (5:37 pm)
@Robert Seeman: did you ever figure out your problem with this? I'm getting the same thing with your nice code.. :-) 
Torque 3D Owner Kevin Rogers