Game Development Community

GuiRadarCtrl TSE

by Chris Byars · in Torque Game Engine Advanced · 02/15/2006 (4:31 pm) · 25 replies

Would anyone care to port the old guiRadarCtrl to TSE? I've tried and tried and, you know me, I am clueless with C++. All that needs to be changed is those old DGL type things and the textureHandle stuff to match the new file structure and rendering code of TSE. Looks simple.. but I couldn't do it. :(

I beg, would someone please port this, please?

Thanks in advance.
Page «Previous 1 2
#1
02/16/2006 (1:57 am)
This is based on the resources by Thomas Larsen, Matt Webster and Thor Zollinger with some of my own stuff.

.cpp

#include "console/console.h"
#include "console/consoleTypes.h"
#include "game/game.h"
#include "gui/game/guibattlemap.h"
#include "game/missionArea.h"
#include "game/gameConnection.h"
#include "gfx/gfxDevice.h"


IMPLEMENT_CONOBJECT(GuiBattleMapCtrl);

GuiBattleMapCtrl::GuiBattleMapCtrl(void)
{

	mBounds.set(0, 0, 256, 256);

	mPlayersVisible = true;
	mVehiclesVisible = true;
	mMapSize = 1.5;  
	
	mMapAlpha = 1.0;
	mFriendlyDot = GFXTexHandle("jcsmith/client/ui/greenplayer.png", &GFXDefaultStaticDiffuseProfile);
	mEnemyDot = GFXTexHandle("jcsmith/client/ui/redplayer.png", &GFXDefaultStaticDiffuseProfile);

}

void GuiBattleMapCtrl::initPersistFields()
{
	Parent::initPersistFields();

	addField("PlayersVisible", TypeBool, Offset(mPlayersVisible, GuiBattleMapCtrl));
	addField("VehiclesVisible", TypeBool, Offset(mVehiclesVisible, GuiBattleMapCtrl));
	addField("MapAlpha", TypeF32, Offset(mMapAlpha, GuiBattleMapCtrl));
	addField("MapSize", TypeF32, Offset(mMapSize, GuiBattleMapCtrl));

}

// Conversion function, Degrees to vector (used after manipulating camera angle to represent angle of object on radar)

void DegreeToVector2d(float angle, Point2F &vector)
{
	angle = (angle / 180) * M_PI;
    vector.x = (1 * sin(angle) );
	vector.y = (-1 * cos(angle) );
}

float GuiBattleMapCtrl::Vector2dToDegree(Point3F vector)
{
    float angle;
    angle = mAtan((1.0F * vector.x),(1.0F * vector.y)) * (180.0F / M_PI);
	return angle;
}


void GuiBattleMapCtrl::onRender(Point2I offset, const RectI &updateRect) 
{ 	
    // Must have a connection
    GameConnection* conn = GameConnection::getServerConnection();
    if (!conn) return;
    
	// Must have controlled object
    ShapeBase* control = conn->getControlObject();
    if (!control) return;
	
   	//Find distance from top-left corner to center of map image 
	F32 HWidth = mBounds.extent.x/2.0;
	F32 HHeight = mBounds. extent.y / 2.0;
	Point2F center(HWidth,HHeight); 
	float mRadius = 50.0F;				//  Radar Range


	MatrixF cam;
 	Point3F cameraRot;
	Point2F pointA;
	Point2F pointB;

	//Make center the UI object's coordinate center 
	center.x += mBounds.point.x; 
	center.y += mBounds.point.y; 

	// Camera stuff

	conn->getControlCameraTransform(0,&cam); // store camera information
    cam.getColumn(3, &mMyCoords); // get camera position
 	cam.getRow(1,&cameraRot); // get camera rotation
	cameraRot.neg(); // bug forces us to need to invert camera rotation angle

	// Compass setup stuff
	cameraRot.z = 0; 
	float cameraAngle = Vector2dToDegree(cameraRot);

	DegreeToVector2d(cameraAngle+45.0F, pointA);
	DegreeToVector2d(cameraAngle-45.0F, pointB);

	//Sets vector length to fit to gui object's extent
	pointA.x = 0.390625 * 30 * pointA.x;
	pointA.y = 0.390625 * 30 * pointA.y;

	pointB.x = 0.390625 * 30 * pointB.x;
	pointB.y = 0.390625 * 30 * pointB.y;

	// End compass pre-stuff

	Point2I start((offset.x + HWidth)-4,(offset.y + HHeight)-4); 
	startPoint.set(-(HWidth) +(mMyCoords.x/mMapSize), -(HHeight)+(mMyCoords.y/mMapSize)); // This centers us properly in all resolutions


   GFX->pushWorldMatrix();   // glPushMatrix();;
 
//	Start Draw Map
   GFXTextureObject* texture = mTextureObject;

	RectI srcRegion;
	RectI dstRegion;

	float xdone = ((float)mBounds.extent.x/(float)texture->mBitmapSize.x)+1;
	float ydone = ((float)mBounds.extent.y/(float)texture->mBitmapSize.y)+1;

	int xshift = startPoint.x%texture->mBitmapSize.x;
	int yshift = startPoint.y%texture->mBitmapSize.y;

		for(int y = 0; y < ydone; ++y)
			for(int x = 0; x < xdone; ++x)
			{
		 		srcRegion.set(0,0,512, 512);
	
  				dstRegion.set( ((texture->mBitmapSize.x*x)+offset.x)-xshift,
							      ((texture->mBitmapSize.y*y)+offset.y)-yshift,
							      texture->mBitmapSize.x,
							      texture->mBitmapSize.y);
               GFX->drawBitmapStretchSR(texture,dstRegion, srcRegion, GFXBitmapFlip_Y);
			}
	// End Draw Map

	// Start Draw Field of View Indicator

	GFX->drawLine(Point2I(start.x+4, start.y+4), Point2I((start.x+4)+pointA.x, (start.y+4) + pointA.y), ColorI(0, 227, 0));
	GFX->drawLine(Point2I(start.x+4, start.y+4), Point2I((start.x+4)+pointB.x, (start.y+4) + pointB.y), ColorI(0, 227, 0));

	// End Draw Field of View Indicator

	// Draw Player in Center
	GFXTextureObject* friendlytexture = mFriendlyDot;
	GFXTextureObject* enemytexture = mEnemyDot;

	srcRegion.set (0,0,8,8);

	GFX->drawBitmapSR(friendlytexture,start, srcRegion);
	// End Draw Player in Center

	// Start Draw Radar Blips
	// Go through all ghosted objects on connection (client-side)
	for (SimSetIterator itr(conn); *itr; ++itr) {
      // Make sure that the object is a shapebase object
      if ((*itr)->getType() & ShapeBaseObjectType) {
         ShapeBase* shape = static_cast<ShapeBase*>(*itr);
		 // Make sure that the object isn't the client
         if (shape != control && shape->getShapeName()) {	// Don't draw ourself
 
			// Make sure the shapebase object is a player (or Vehicle)
 			if (shape->getType() & ( PlayerObjectType | VehicleObjectType) ) {
			    Point3F newCoord;
   			    // Get coords of player object
                newCoord = shape->getPosition();

				// Find distance from point A (player object) to point B (client's player)
				VectorF shapeDir = newCoord - mMyCoords;

				// Test to see if player object in range (deal with squared objects in cheap way to use non-negative value)
				F32 shapeDist = shapeDir.lenSquared();
				if (shapeDist == 0 || shapeDist > (mRadius * mRadius))
				   continue;

				newCoord.x -= mMyCoords.x;
				newCoord.y -= mMyCoords.y;
				newCoord.z = 0;
							
				start.x = offset.x + HWidth + newCoord.x -4;
				start.y = offset.y + HHeight + newCoord.y -4;

				if (control->getTeamId() == shape->getTeamId())
					GFX->drawBitmapSR(friendlytexture,start, srcRegion);
				else
					GFX->drawBitmapSR(enemytexture,start, srcRegion);
			
				}
			}
		}
    }
	// End Draw Radar Blips

	GFX->popWorldMatrix();

	renderChildControls(offset, updateRect); 
	
}

.h

#ifndef _GuiBattleMap_H_
#define _GuiBattleMap_H_

#ifndef _GUIBITMAPCTRL_H_
#include "gui/controls/guiBitmapCtrl.h"
#endif

#ifndef _SCENEOBJECT_H_
#include "sim/sceneObject.h"
#endif

#include "gfx/gfxDevice.h"

class GuiBattleMapCtrl : public GuiBitmapCtrl
{
private:
	typedef GuiBitmapCtrl Parent;
	
	Point3F mMyCoords;

	bool mPlayersVisible;
	bool mVehiclesVisible;	

	F32 mMapAlpha;

	F32 mMapSize; 

   
public:
	//creation methods
	DECLARE_CONOBJECT(GuiBattleMapCtrl);
	GuiBattleMapCtrl();
	static void initPersistFields();

	//Parental methods    
	void onRender(Point2I offset, const RectI &updateRect);		

protected:
	float Vector2dToDegree(Point3F vector);	
	GFXTexHandle mFriendlyDot;
	GFXTexHandle mEnemyDot;

};

#endif //_GuiBattleMap_H_

That should work. Though it has more than you need most likely. That is for an overhead map similar to those in Batlefield 2 that also features a radar. You can strip out the map code if you like.
#2
02/20/2006 (10:25 am)
Well it doesn't seem to be what I'm looking for. :/

I just need a direct port of the GuiRadarCtrl from Matt Webster to TSE. I've tried and tried and I can't seem to get it to compile. I have trouble figuring out what calls need to be changed, what things have changed in TSE's handling of "textureHandle"s and bitmaps and all that.

Please, anyone who can do it, I'm asking your aid.
#3
02/20/2006 (9:18 pm)
I'd help you out if I could there, but I just have no time for a while. Busiest time of the year for me at work. I run Ogaming's databases and basically we cover three MMOG games at the moment... 2 have expansions that ship today, and the third launches on Friday. Sorry I didn't check back in sooner. Swamped here.

You could probably look at the section between the start draw player comment and the end draw radar blips for an idea of how to use the texturehandles, though your going to need to put that between the push and popworld matrix calls.

When I originally wrote code I started by trying to port the radar code over. It's not going to port over directly, some of the gl calls just don't translate into GFX.
#4
02/28/2006 (8:40 pm)
// Start Draw Map
GFXTextureObject* texture = mTextureObject;
RectI srcRegion;
RectI dstRegion;

float xdone = ((float)mBounds.extent.x/(float)texture->mBitmapSize.x)+1;
float ydone = ((float)mBounds.extent.y/(float)texture->mBitmapSize.y)+1;


I'm having trouble with the above code.. texture is empty, because mTextureObject is empty.. did i do something wrong?
#5
03/02/2006 (9:53 am)
Solved! Fully functional, bug free. :) After many painstakingly mind-numbing efforts.

Posting a resource.
#6
03/02/2006 (11:02 am)
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9946

I don't recall clicking a category (TSE), so hopefully it will be posted to the right place when it's approved.
#7
03/02/2006 (12:50 pm)
:( it crashes for me when i try to add it to my gui, tells me "graphics exceed world matrix size"
the code by J.C. Smith also crashes for me, however that is because mtexture object is null..

any ideas?
#8
03/02/2006 (12:54 pm)
Oops, ok i lied, it doesn't crash, i just forgot to change teh path to the image files.
#9
03/05/2006 (1:00 am)
Yeah the code I posted above doesn't rotate at all. It's a straight Battlfield 2 clone. It displays the map in the background, uses images for the players or vehicles and draws a \/ indicator to display your field of fov.
#10
03/05/2006 (9:02 pm)
Oh, jc i can't get yours to work, every time i try to create an instance of it, it crashes because:
GFXTextureObject* texture = mTextureObject;
is all empty
#11
03/12/2006 (8:45 pm)
Where is the 'getTeamId' method? I've looked through both the TGE and TSE source and can't find a method by that name. Is it something that got pulled out at some point?
#12
03/14/2006 (8:03 am)
You have to add it yourself, its fairly simple:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=5592
(although in that case you call it FactionId not teamId )

i think there is an identical resource out there that just uses the word team instead of faction
#13
06/13/2006 (11:10 am)
Sorry hadn't checked back in here. You need to add this block to your playgui:

new GuiBattleMapCtrl(BattleMap) {
      profile = "GuiDefaultProfile";
      horizSizing = "relative";
      vertSizing = "relative";
      position = "557 32";
      extent = "64 64";
      minExtent = "8 2";
      visible = "1";
      bitmap = "~/data/missions/yourmaphere";
      wrap = "0";
      MyControlVisible = "1";
      PlayersVisible = "1";
      VehiclesVisible = "1";
      MapAlpha = "1";
      PointSize = "10";
      MapSize = 2;
      MapOffset = 0;
   };

What we did in our client was to add the mapbitmap name in the missioninfo and have it set it when it loads the map client side. You'd also have to edit the friendly and enemy images since they are hardcoded in the source.
#14
07/18/2006 (1:10 am)
Any news on this?
#15
07/26/2006 (4:36 pm)
Here's some kind-of-working map code (from Ben's TGE commanderhud & Shannon Scarvaci's TSE port of it)

This stuff is really funky, but if anyone can fix it up...be my guest

There's a lot of 'force-discarding tile' errors on the console.

Nevertheless, here it is....


Part 1: (8192 char limit)

//-----------------------------------------------------------------------------
// Commander Map HUD
//
// Portions Copyright (c) GarageGames.Com
// Copyright (c) Ben Garney
// Convert into TSE by Shannon Scarvaci
//-----------------------------------------------------------------------------

#include "atlas/atlasInstance.h"
#include "atlas/atlasInstanceEntry.h"
#include "platform/platform.h"
#include "platform/platformVideo.h"
#include "platform/platformAudio.h"
#include "platform/platformInput.h"
#include "core/findMatch.h"

#include "game/game.h"
#include "math/mMath.h"
#include "console/simBase.h"
#include "console/console.h"
#include "game/collisionTest.h"
#include "game/showTSShape.h"
#include "sceneGraph/sceneGraph.h"
#include "gui/core/guiTSControl.h"
#include "game/moveManager.h"
#include "console/consoleTypes.h"
#include "game/shapeBase.h"
#include "core/dnet.h"
#include "game/gameConnection.h"
#include "core/fileStream.h"
#include "gui/core/guiCanvas.h"
#include "sceneGraph/sceneLighting.h"
#include "terrain/sky.h"
#include "game/ambientAudioManager.h"
#include "core/frameAllocator.h"
#include "sceneGraph/detailManager.h"
#include "gui/controls/guiMLTextCtrl.h"
#include "platform/profiler.h"
#include "game/fx/underLava.h"

//-----------------------------------------------------------------------------

class GuiCommanderHud : public GuiTSCtrl
{
private:
   typedef GuiTSCtrl Parent;


   Point2F mPanSpeed;
   F32     mZoomSpeed;
   S32     mLastRenderTime;

public:
   Point2F mPanGoal, mCurPan;
   F32     mZoomGoal, mCurZoom;

   GuiCommanderHud();

   bool processCameraQuery(CameraQuery *query);
   void renderWorld(const RectI &updateRect);

   void onRender( Point2I, const RectI &);
   static void initPersistFields();

   DECLARE_CONOBJECT( GuiCommanderHud );
};


//-----------------------------------------------------------------------------

IMPLEMENT_CONOBJECT( GuiCommanderHud );

GuiCommanderHud::GuiCommanderHud()
:   mPanSpeed(10, 10), mZoomSpeed(1), mCurPan(0,0), mCurZoom(M_PI_F/2),
    mPanGoal(0,0), mZoomGoal(M_PI_F/2), mLastRenderTime(0)
{
}

void GuiCommanderHud::initPersistFields()
{
   Parent::initPersistFields();

   addField("panSpeed",  TypePoint2F, Offset(mPanSpeed,  GuiCommanderHud), "Set the speed (x/y) we pan to our goal.");
   addField("zoomSpeed", TypeF32,     Offset(mZoomSpeed, GuiCommanderHud), "Set the speed we zoom with to our goal.");
}

static void findObjectsCallback(SceneObject* obj, void * val)
{
   Vector<SceneObject*> * list = (Vector<SceneObject*>*)val;
   list->push_back(obj);
}

bool GuiCommanderHud::processCameraQuery(CameraQuery *q)
{
   // draw all the objects
   Vector<SceneObject*> objects;
   U32 mask = AtlasObjectType;
   gClientContainer.findObjects(mask, findObjectsCallback, &objects);
	 Box3F box;
	 Point3F pt;
   for(U32 i = 0; i < objects.size(); i++)
   {
      // get the color
		 if(objects[i]->getTypeMask() & AtlasObjectType) {
			 pt = objects[i]->getBoxCenter();
			 box = objects[i]->getWorldBox();
			 break;
		 }
	 }
   
   // Scale ranges based on the highest/lowest point in the terrain
   F32 maxHi = box.max.z; //gClientSceneGraph->getCurrentTerrain()->findSquare(8, 0,0)->maxHeight / 10;
   F32 minHi = box.min.z;//gClientSceneGraph->getCurrentTerrain()->findSquare(8, 0,0)->minHeight / 10;

   q->object = NULL;
//	 q->nearPlane = 0.1 * (maxHi - minHi);
//	 q->farPlane = box.len_z() + q->nearPlane + 1000;
   q->nearPlane = 1;
   q->farPlane  = q->nearPlane + mFabs(maxHi) + mFabs(minHi) + 100;
   q->fov       = mCurZoom;


   // Make us high up, facing straight down.
   q->cameraMatrix = MatrixF(EulerF(M_PI/2, 0, 0)); // rotate us to look straight down
   q->cameraMatrix.setPosition(Point3F(mCurPan.x + pt.x,mCurPan.y + pt.y, maxHi + 100)); // and high enough we won't clip

   return true;
}

void GuiCommanderHud::renderWorld(const RectI &updateRect)
{
   // Set up state
   // draw all the objects
   Vector<SceneObject*> objects;
   U32 mask = AtlasObjectType;
   gClientContainer.findObjects(mask, findObjectsCallback, &objects);
	 Box3F box;
	 Point3F pt;
   for(U32 i = 0; i < objects.size(); i++)
   {
      // get the color
		 if(objects[i]->getTypeMask() & AtlasObjectType) {
			 pt = objects[i]->getBoxCenter();
			 box = objects[i]->getWorldBox();
			 break;
		 }
   }
   
   //TerrainRender::mRenderingCommander = true;
   F32 oldVisDist = gClientSceneGraph->getVisibleDistance();
   gClientSceneGraph->setVisibleDistance(box.len_z());
   F32 oldFogDist = gClientSceneGraph->getFogDistance();
   gClientSceneGraph->setFogDistance(box.len_z());

   // set up the camera and viewport stuff:

   // Render (stolen from GameRenderWorld)
   PROFILE_START(GameRenderCommanderWorld);
   FrameAllocator::setWaterMark(0);

#if defined(GATHER_METRICS) && GATHER_METRICS > 1
   TextureManager::smTextureCacheMisses = 0;
#endif

   /*glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   glClear(GL_DEPTH_BUFFER_BIT);
   glDisable(GL_CULL_FACE);
   glMatrixMode(GL_MODELVIEW);*/
	 GFX->setZEnable(true);
	 GFX->setZFunc(GFXCmpLessEqual);
   GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI(0,0,0), 1.0f, 0 );
	 GFX->setCullMode(GFXCullNone);
   //dglSetCanonicalState();
   // If you want to render other things, change this mask.
   gClientSceneGraph->renderScene(  EnvironmentObjectType |  AtlasObjectType | InteriorObjectType | WaterObjectType | SimChild2ObjectType );
	 GFX->setZEnable(false);
   //glDisable(GL_DEPTH_TEST);

#if defined(GATHER_METRICS) && GATHER_METRICS > 1
   Con::setFloatVariable("Video::texResidentPercentage",
                         TextureManager::getResidentFraction());
   Con::setIntVariable("Video::textureCacheMisses",
                       TextureManager::smTextureCacheMisses);
#endif

   AssertFatal(FrameAllocator::getWaterMark() == 0, "Error, someone didn't reset the water mark on the frame allocator!");
   FrameAllocator::setWaterMark(0);
   PROFILE_END();


   // Restore state
   gClientSceneGraph->setVisibleDistance(oldVisDist);
   gClientSceneGraph->setFogDistance    (oldFogDist);
   //TerrainRender::mRenderingCommander = false;

   GFX->setClipRect( updateRect);//dglSetClipRect(updateRect);
}

void GuiCommanderHud::onRender(Point2I offset, const RectI &updateRect)
{
   // Update pan/zoom

   S32 time = Platform::getVirtualMilliseconds();
   S32 dt = time - mLastRenderTime;

   mLastRenderTime = time;

   mCurPan  += (mPanGoal  - mCurPan)  * (F32)dt/1000.f;
   mCurZoom += (mZoomGoal - mCurZoom) * (F32)dt/1000.f;

   // Render the world...
   Parent::onRender(offset, updateRect);

   // If you wanted to render custom GUI elements, like a sensor map, icons for
   // players/vehicles/objectives, you would do it here by calling project()
   // for all their positions and drawing bitmaps at the appropriate locations.
}

ConsoleMethod(GuiCommanderHud, pan, void, 4, 4, "(x, y) Cut to a location.")
{
   object->mPanGoal.set(dAtof(argv[2]), dAtof(argv[3]));
   object->mCurPan.set (dAtof(argv[2]), dAtof(argv[3]));
}

ConsoleMethod(GuiCommanderHud, panTo, void, 4, 4, "(x, y) Smoothly pan to a location.")
{
   object->mPanGoal.set(dAtof(argv[2]), dAtof(argv[3]));
}

ConsoleMethod(GuiCommanderHud, zoom, void, 3, 3, "(val) Zoom to a specified level.")
{
   object->mZoomGoal = dAtof(argv[2]);
   object->mCurZoom  = dAtof(argv[2]);
}

ConsoleMethod(GuiCommanderHud, zoomTo, void, 3, 3, "(val) Smoothly zoom to a specified level.")
{
   object->mZoomGoal = dAtof(argv[2]);
}
#16
07/26/2006 (4:36 pm)
Part 2:
ConsoleMethod(GuiCommanderHud, zoomToArea, void, 6, 7, "(top, left, right, bottom, bool cut) Smoothly zoom to view the specified area. If cut is set, we jump there.")
{
   // Parse arguments
   F32 top, left, right, bottom;

   top    = dAtof(argv[2]);
   left   = dAtof(argv[3]);
   right  = dAtof(argv[4]);
   bottom = dAtof(argv[5]);

   // Figure out the center of the area
   Point2F center;

   center.x = (left + right) * 0.5f;
   center.y = (top + bottom) * 0.5f;

   object->mZoomGoal = mFabs(left - right) / 200; // Cheesy scaling fakery.

   // And set our motion
   object->mPanGoal = center;

   // Cut if requested
   if(argc > 6)
      if(dAtob(argv[6]))
      {
         object->mCurPan  = object->mPanGoal;
         object->mCurZoom = object->mZoomGoal;
      }
}

Throw these concatenated into a .cpp file
#17
07/27/2006 (2:28 pm)
Trying out the GuiCommanderHud and I get an 'Error, no plane possible!" fatal assert when I try to add one to the GUI via the GUI editor. Any pointers to how to fix this?
#18
07/28/2006 (9:19 am)
I've never encountered that error, but can you try this stuff out? Mine looks like this right now (still a work-in-progress)

img225.imageshack.us/img225/9420/m1og4.jpg
//-----------------------------------------------------------------------------
// Commander Map HUD
//
// Portions Copyright (c) GarageGames.Com
// Copyright (c) Ben Garney
// Convert into TSE by Shannon Scarvaci
//-----------------------------------------------------------------------------

//this control renders an overhead view
//of the environment with X,Y position equal to that of the control object (player or camera)
//you can change the renderScene() call to render other things like players & such, or you can
//use the project(Point3F 3d_world_position, Point3F* 2d_projection_destination_address) call
//to transform them into 2d & draw a bitmap according to the new 2d point.


//max z on terrain + MAP_HEIGHT_DISPLACEMENT = z location the camera will be looking down from
#define MAP_HEIGHT_DISPLACEMENT		100
//note: having too high a MAP_HEIGHT_DISPLACEMENT causes the actual terrain in the world to act funny, so be aware 
//of that. 

#include "core/frameAllocator.h"
#include "game/game.h"
#include "game/gameConnection.h"
#include "game/shapebase.h"
#include "gfx/gfxDevice.h"
#include "gui/core/guiTSControl.h"
#include "sceneGraph/sceneGraph.h"


//-----------------------------------------------------------------------------

class GuiCommanderHud : public GuiTSCtrl
{
private:
   typedef GuiTSCtrl Parent;


   F32     mZoomSpeed;
   S32     mLastRenderTime;

public:
   Point2F mCurPan;
   F32     mZoomGoal, mCurZoom;

   GuiCommanderHud();

   bool processCameraQuery(CameraQuery *query);
   void renderWorld(const RectI &updateRect);

   void onRender( Point2I, const RectI &);

   DECLARE_CONOBJECT( GuiCommanderHud );
};


//-----------------------------------------------------------------------------

IMPLEMENT_CONOBJECT( GuiCommanderHud );

GuiCommanderHud::GuiCommanderHud()
:   mZoomSpeed(1), mCurPan(0,0), mCurZoom(M_PI_F/2),
    mZoomGoal(M_PI_F/2), mLastRenderTime(0)
{
}


static void findObjectsCallback(SceneObject* obj, void * val)
{
   Vector<SceneObject*> * list = (Vector<SceneObject*>*)val;
   list->push_back(obj);
}

bool GuiCommanderHud::processCameraQuery(CameraQuery *q)
{
   // draw all the objects
   Vector<SceneObject*> objects;
   gClientContainer.findObjects(AtlasObjectType, findObjectsCallback, &objects);
   Box3F atlasWorldBox;
   Point3F atlasCenterPoint;
   for(U32 i = 0; i < objects.size(); i++) {
       if(objects[i]->getTypeMask() & AtlasObjectType) {
           atlasCenterPoint = objects[i]->getBoxCenter();
           atlasWorldBox = objects[i]->getWorldBox();
           break;
	   }
   }
   
   // Scale ranges based on the highest/lowest point in the terrain
   F32 maxHi = atlasWorldBox.max.z; //gClientSceneGraph->getCurrentTerrain()->findSquare(8, 0,0)->maxHeight / 10;
   F32 minHi = atlasWorldBox.min.z;//gClientSceneGraph->getCurrentTerrain()->findSquare(8, 0,0)->minHeight / 10;

   q->object = NULL;
   q->nearPlane = 1;
   q->farPlane  = q->nearPlane + mFabs(maxHi) + mFabs(minHi) + MAP_HEIGHT_DISPLACEMENT;
   q->fov       = mCurZoom;

   //if we have a control object, pan to its poisition
   GameConnection* conn = GameConnection::getConnectionToServer();
   if (conn) {
       MatrixF cam;
       Point3F cameraRot;
       Point3F camCoords;

       conn->getControlCameraTransform(0,&cam); // store camera information
       cam.getRow(1,&cameraRot); // get camera rotation
       
	   cameraRot.neg(); // bug forces us to need to invert camera rotation angle

       float cameraAngleInDegrees = Vector3dToDegree(cameraRot);

       //get camera rotation about Z into a matrix
       MatrixF rotTransMat(1), tempMat(1);
       AngAxisF axisRot(Point3F(0.0f,0.0f,1.0f), cameraAngleInDegrees * (M_PI_F/180));
       axisRot.setMatrix(&rotTransMat);

       //make a matrix to rotate about X axis to look straight down
       axisRot.axis.set(1.0F, 0.0F, 0.0F);
       axisRot.angle = M_PI_F/2;
       axisRot.setMatrix(&tempMat);

       //combine camera rotation with look-straight-down matrix
       rotTransMat.mul(tempMat);
       
	   if (ShapeBase* cntrlObj = conn->getControlObject()) {
           Point3F cntrlPos = cntrlObj->getPosition();
           //set the pan location to the position of control object (player or camera)
		   mCurPan.set(cntrlPos.x, cntrlPos.y);
		} else {	//just use camera stuff?
			mCurPan.set(camCoords.x, camCoords.y);
		}

		rotTransMat.setPosition(Point3F(mCurPan.x,mCurPan.y, maxHi + MAP_HEIGHT_DISPLACEMENT));
		q->cameraMatrix = rotTransMat;
		return true;
   } else {
	   return false;
   }
}

void GuiCommanderHud::renderWorld(const RectI &updateRect)
{
   // Set up state
   // draw all the objects
   Vector<SceneObject*> objects;
   Box3F atlasWorldBox;
   Point3F atlasCenterPoint;

   gClientContainer.findObjects(AtlasObjectType, findObjectsCallback, &objects);
   for(U32 i = 0; i < objects.size(); i++) {
       if(objects[i]->getTypeMask() & AtlasObjectType) {
           atlasCenterPoint = objects[i]->getBoxCenter();
           atlasWorldBox = objects[i]->getWorldBox();
           break;
	   }
   }
   
   F32 oldVisDist = gClientSceneGraph->getVisibleDistance();
   gClientSceneGraph->setVisibleDistance(atlasWorldBox.len_z());

   F32 oldFogDist = gClientSceneGraph->getFogDistance();
   gClientSceneGraph->setFogDistance(atlasWorldBox.len_z());

   // Render (stolen from GameRenderWorld)
   PROFILE_START(GameRenderCommanderWorld);
   FrameAllocator::setWaterMark(0);

#if defined(GATHER_METRICS) && GATHER_METRICS > 1
   TextureManager::smTextureCacheMisses = 0;
#endif

   GFX->setZEnable(true);
   GFX->setZFunc(GFXCmpLessEqual);
   GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI(0,0,0), 1.0f, 0 );
   GFX->setCullMode(GFXCullNone);

   // If you want to render other things, change this mask.
   gClientSceneGraph->renderScene(  EnvironmentObjectType |  AtlasObjectType | InteriorObjectType | WaterObjectType);
   GFX->setZEnable(false);

#if defined(GATHER_METRICS) && GATHER_METRICS > 1
   Con::setFloatVariable("Video::texResidentPercentage",
                         TextureManager::getResidentFraction());
   Con::setIntVariable("Video::textureCacheMisses",
                       TextureManager::smTextureCacheMisses);
#endif

   AssertFatal(FrameAllocator::getWaterMark() == 0, "Error, someone didn't reset the water mark on the frame allocator!");
   FrameAllocator::setWaterMark(0);
   PROFILE_END();

   // Restore state
   gClientSceneGraph->setVisibleDistance(oldVisDist);
   gClientSceneGraph->setFogDistance    (oldFogDist);

   GFX->setClipRect( updateRect);
}


void GuiCommanderHud::onRender(Point2I offset, const RectI &updateRect)
{
   // Update pan/zoom
   S32 time = Platform::getVirtualMilliseconds();
   S32 dt = time - mLastRenderTime;

   mLastRenderTime = time;

   mCurZoom += (mZoomGoal - mCurZoom) * (F32)dt/1000.f;

   // Render the world...
   Parent::onRender(offset, updateRect);

   // If you wanted to render custom GUI elements, like a sensor map, icons for
   // players/vehicles/objectives, you would do it here by calling project()
   // for all their positions and drawing bitmaps at the appropriate locations.
}

ConsoleMethod(GuiCommanderHud, zoom, void, 3, 3, "(val) Zoom to a specified level.")
{
   object->mZoomGoal = dAtof(argv[2]);
   object->mCurZoom  = dAtof(argv[2]);
}

ConsoleMethod(GuiCommanderHud, zoomTo, void, 3, 3, "(val) Smoothly zoom to a specified level.")
{
   object->mZoomGoal = dAtof(argv[2]);
}
#19
07/28/2006 (9:21 am)
And if you don't have it already:

float Vector3dToDegree(Point3F vector)
{
    float angle;
	if (vector.x == 0.0F)
    {
        if (vector.y > 0.0F)
            return 0.0F;
        else if (vector.y == 0.0F)
            return -1.0F;
        else
            return 180.0F;
    }
    if (vector.y == 0.0F)
    {
        if (vector.x < 0.0F)
            return 270.0F;
        else
            return 90.0F;
    }
    angle = atanf((vector.x) / (-vector.y)) * (180.0F / M_PI);
    if ((-vector.y) < 0.0F)
        return angle + 180.0F;
    else
    {
        if (vector.x > 0.0F)
            return angle;
        else
            return angle + 360.0F;
    }
}
#20
08/01/2006 (11:06 am)
OK I hate to be a total n00b, but how do you actually add this into a game? I don't mean in the code - i've added and compiled it fine. But how do you actually make it show up in game?

I tried adding it by...

1) Starting up my FPS port to TSE (3.5)
2) Opening up the GUI editor (F10)
3) Selecting the "PlayGui"
4) Choosing "GuiCommanderHud" from the "NewControl" dropdown
5) Saving the PlayGui script
6) Starting up a mission

But then the game bombs with an "Error, no plane possible!" message

If I try to actually start up a mission first, then directly edit or add the GuiCommanderHud I also get the same error.

So am I doing this right? Obviously not I guess :^) What's the basic process for actually adding this HUD element to a game?
Page «Previous 1 2