Game Development Community

dev|Pro Game Development Curriculum

Fuel, Speed or Manual Bitmap Meter TGEA

by Jorge Luis Gandulfo · 05/27/2008 (9:45 am) · 5 comments

Download Code File

This is a port from this resouce.

What it does?
Instead of drawing the needle as box this resource paints a texture.
It will allow to be used Manually or binded to vehicle Speed or Energy.

How to add it?
Simply copy guiMeterCtrl.cc and guiMeterCtrl.h to the engine\source\gui\controls directory.
Then add this files to your project.

Then in gfxDrawUtil.h add the following arround line 67:
void drawBitmapRotated( GFXTextureObject*texture, const RectI &dstRect, const RectI &srcRect, const U32 in_flip ,F32 spinAngle = 0, const Point2F spinOffset = Point2F(0,0) );
this will be near the line
void drawBitmap( GFXTextureObject*texture, const Point2I &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None );

Also in gfxDrawUtil.ccp add the following function:

void GFXDrawUtil::drawBitmapRotated(GFXTextureObject *texture,const RectI& dstRect,const RectI& srcRect,const U32 in_flip,F32 spinAngle, const Point2F spinOffset)
{
	if(!texture)
      return;

   mDevice->setBaseRenderState();

   GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile );
   verts.lock();

   F32 texLeft   = F32(srcRect.point.x)                    / F32(texture->mTextureSize.x);
   F32 texRight  = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->mTextureSize.x);
   F32 texTop    = F32(srcRect.point.y)                    / F32(texture->mTextureSize.y);
   F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->mTextureSize.y);

   F32 screenLeft   = dstRect.point.x;
   F32 screenRight  = dstRect.point.x + dstRect.extent.x;
   F32 screenTop    = dstRect.point.y;
   F32 screenBottom = dstRect.point.y + dstRect.extent.y;

	if(in_flip & GFXBitmapFlip_X)
   {
      F32 temp = texLeft;
      texLeft = texRight;
      texRight = temp;
   }
   if(in_flip & GFXBitmapFlip_Y)
   {
      F32 temp = texTop;
      texTop = texBottom;
      texBottom = temp;
   }

	F32 X = 0;

   // calculate the centroid of the rectangle (to use as rotation pivot)
   if (screenLeft < screenRight)
   {
        X = screenLeft + ((screenRight - screenLeft)*0.5f);
   }
   else
   {
        X = screenRight + ((screenLeft - screenRight)*0.5f);
   };

   F32 Y = 0;

   if (screenTop < screenBottom)
   {
        Y = screenTop + ((screenBottom - screenTop)*0.5f);
   }
   else
   {
        Y = screenBottom + ((screenTop - screenBottom)*0.5f);
   };
   
   // spin angle is in degree's so convert to radians..radians = degrees * pi /180
   spinAngle = spinAngle * 3.14 / 180.0f;

   Point2F screenPoint(X,Y); 

   F32 width = dstRect.extent.x;
   width *= 0.5;

   MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );

   Point3F offset( screenPoint.x, screenPoint.y, 0.0 );

	//const F32 fillConv = mDevice->getFillConventionOffset();
   verts[0].point.set( -width + spinOffset.x, -width + spinOffset.y, 0.0 );
   verts[1].point.set( -width + spinOffset.x,  width + spinOffset.y, 0.0 );
   verts[2].point.set( width + spinOffset.x,  width + spinOffset.y, 0.0 );
   verts[3].point.set( width + spinOffset.x, -width + spinOffset.y, 0.0 );

   verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation;

   verts[0].texCoord.set( texLeft,  texTop );
   verts[1].texCoord.set( texLeft, texBottom );
   verts[2].texCoord.set( texRight,  texBottom );
   verts[3].texCoord.set( texRight, texTop );

	for( int i=0; i<4; i++ )
   {
      rotMatrix.mulP( verts[i].point );
      verts[i].point += offset;
   }

   verts.unlock();
  
   mDevice->setVertexBuffer( verts );

   mDevice->setCullMode( GFXCullNone );
   mDevice->setLightingEnable( false );
   mDevice->setAlphaBlendEnable( true );
   mDevice->setSrcBlend( GFXBlendSrcAlpha );
   mDevice->setDestBlend( GFXBlendInvSrcAlpha );
   mDevice->setTextureStageColorOp( 0, GFXTOPModulate );
   mDevice->setTextureStageColorOp( 1, GFXTOPDisable );
   mDevice->setTexture( 0, texture );
   mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );

   mDevice->drawPrimitive(GFXTriangleFan, 0, 2 );

   mDevice->setAlphaBlendEnable( false );
}

Compile and you are set!


How to make it work?
Simply add a guiMeterCtrl to your PlayGui.gui, and set the variables according to your needs.

maxangle and minangle: to adjust your spin movement angle (this helps since each kind of meter start at a different angle, and they also end in a different angle).

spinBitmapOffset: the offset that the center of the spin have inside its bitmap image, this will affect from where the spin rotates.

SpinOffset: moves the center of the spin to the desirex (x,y).

Special thanks to:
Frank Bignone, for making the original resource back in TGE (2002).
Eric Armstrong, without him this resource wouldn't be ported to TGEA today.

#1
05/27/2008 (12:59 pm)
Thanks I had already muddled my way through this, but I think I like your method better.
#2
06/26/2008 (12:09 am)
Sorry, Noobie question here...applied code as you directed, but seem to have a problem with adding a guiMeterCtrl to PlayGui.gui

Copied code from Frank Bignone's tutorial at

http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2676

and put the code below into my playGui.gui using Franks values.

new guiMeterCtrl(fuelguage) {
profile = "GuiDefaultProfile";
horizSizing = "relative";
vertSizing = "relative";
position = "349 120";
extent = "83 81";
minExtent = "8 8";
visible = "1";
helpTag = "0";
lockMouse = "0";
bitmap = "~/fuel/panel.png";
wrap = "0";
spinBitmap = "~/fuel/spin.png";
color = "1.000000 1.000000 1.000000 1.000000";
angle = "50";
spinAngle = "0.000000 180.000000";
spinOffset = "2.000000 3.000000";
};


But am getting an 'Unable to instantiate non-conobject class guiMeterCtrl' error. As I don't know what this error refers to I don't really know where I can start troubleshooting.

Any help would be much appreciated.

Thankyou
#3
06/26/2008 (6:34 pm)
Im gonna asnwer with some newbie answers :)

Did you added guiMeterCtrl.cc and guiMeterCtrl.h to your project files before compiling?

Why i ask thisn becouse in guiMeterCtrl.cc you have this line IMPLEMENT_CONOBJECT(GuiMeterCtrl), which basically implements the Con Object, the error you are describing looks like you don't have the GuiMeterCtrl implemented..

Did the exe compiled?

Are you running the exe that compiled from the same directory?, maybe you forgot to copy, this happend to me a lot..

Hope any of this can be of help.
#4
06/26/2008 (8:05 pm)
Thanks for the fast response!

What I have done:

1. Unzipped meter.zip

2. Added the two folders 'speed' and 'fuel' to game/scriptsAndAssets/data/shapes folder

2. Added guiMeter.cc and guiMeterCtrl.h to engine/source/gui/controls folder

3. Added the one line of code to gfxDrawUtil.h somewhere near line 67

4. Added the section of code to the end of gfxDrawUtil.cpp

5. Compiled ('built') the 'solution' in MS VC++ Express

6. Added the following guiMeterCtrl code to playGui.gui in game/scriptsAndAssets/client/ui

new GuiMeterCtrl(fuelguage) {
Profile = "GuiDefaultProfile";
HorizSizing = "center";
VertSizing = "relative";
position = "280 1";
Extent = "80 80";
MinExtent = "80 80";
Visible = "1";
bitmap = "~/data/shapes/fuel/panel.png";
wrap = "0";
spinBitmap = "~/data/shapes/fuel/spin.png";
color = "1 1 1 1";
value = "0";
maxvalue = "180";
maxangle = "180";
minangle = "0";
spinAngle = "0 100";
spinBitmapOffset = "2 1";
spinOffset = "0 0";
valuetype = "CheckPointArrow";
invert = "0";
angle = "0";
};

Based on code from another forum entry. The original guiMeterCtrl (see my entry above) gave a few errors.

Voila! I now have a fuel guage in the top middle of my screen.

Thankyou very much Jorge, Eric & Frank for providing this great resource!
#5
03/20/2009 (11:04 pm)
Has anyone gotten the drawBitmapRotated function converted to TGEA 1.8.1 yet?