Game Development Community

GuiBitmapSelCtrl

by JohnT · 07/03/2006 (11:18 am) · 5 comments

Download Code File

This is a relatively simple modification to the guiBitmaopCtrl that I made for my game and thought others might have some use for it so I thought I'd go ahead and submit it as a resource. I have been on the receiving end for the past year on the GG forums (thanks everyone) and felt it was time I start giving something back.

This resource adds a new type of bitmap control that can be used in your GUI's without any changes to the existing code. The new control is essentially a BitmapCtrl with mouse events added and a crosshair for selecting a position within the image.

This resource has been tested on TGE 1.4 and TLK 1.4 on the PC and Mac successfully and is pretty much a drop in and compile resource, no heavy coding required!

Installing the Control:
1. Download the associated source code files with this resource.
2. Extract the files guiBitmapSelCtrl.cc and guiBitmapSelCtrl.h from the zip file and move them into the engine/gui/controls directory.
3. Make sure to include the files in Visual Studio, XCode, or whatever your using to compile with.
4. Build TGE.

Using the Control:
1. Inside of your GUI, just select the guiBitmapSelCtrl from the Controls selection list.
2. Position the control and size as needed.
3. In the attributes pane in the lower right side of the GUI editor, give the control a name (my example below uses "WorldMap")
4. Scroll down to the bottom of the pane and set your bitmap name.
5. Below the bitmap are the following parameters that can be set as needed:
a. cursorColor - changes the default red cursor to whatever color you want. Also Alpha channel is supported for transparency.
b. cursorWidth - sets the line widths (number is in pixels wide)
c. boxSizeWidth - If set to zero, no center box will be displayed otherwise setting a number will make a targeting box with the width entered.
d. boxSizeHeight - Same as above except for vertical measurement.
6. Save your gui and now its time to add the mouse click event to your script.

Shown below is an example of the code that I've used in my game to determine the Longitude/ Latitude on the map that the player has selected. Although I'm using this for a simulation, this could just as easily be used to select a location in the game world where a player is to be dropped.

Please note that the size of your bitmap on the screen is passed down to the script event along with the mouse click position so that you can determine the exact position that was selected without needing to hardcode bitmap sizes in your script.

Enter the following function into your associated *.cs file for the GUI or else add it directly inside. Remember that you must have named the control before this will work!

function WorldMap::onMouseDown(%this, %MouseX, %MouseY, %width, %height)
{
   if((%width > 0) && (%height>0)) //Make sure we don't divide by zero
   {
      %longitude = 180-(%MouseX/%width)*360;
      %latitude =  90 - (%MouseY/%height)*180;
 
      if(%longitude >0)
         %strLongitude = mFloor(%longitude*100)/100 SPC "W"; //Need to get 2 decimal places
      else
         %strLongitude = mFloor(-%longitude*100)/100 SPC "E";

      if(%latitude >0)
         %strLatitude = mFloor(%latitude*100)/100 SPC "N";
      else
         %strLatitude = mFloor(-%latitude*100)/100 SPC "S";
      
      //Write out result to Text Edit Controls for viewing results
      Longitude.setValue(%strLongitude);
      Latitude.setValue(%strLatitude);
   }
}

About the author

Recent Blogs


#1
03/21/2007 (7:34 pm)
@JTripodo;

Thank you. You helped me alot.
#2
11/03/2007 (4:06 am)
very cool,

is it possible to add this to the commandermap resource?


Thanks Rik.
#3
12/14/2008 (8:56 am)
Hi ! I have converted your code for TGEA :

GuiBitmapSelCtrl.h

#ifndef _GUIBITMAPCTRL_H_
#define _GUIBITMAPCTRL_H_

#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
#ifndef _GUIMOUSEEVENTCTRL_H_
#include "gui/utility/guiMouseEventCtrl.h"
#endif

/// Renders a bitmap.
class GuiBitmapSelCtrl : public GuiControl
{
private:
   typedef GuiControl Parent;

protected:
   StringTableEntry mBitmapName;
   GFXTexHandle mTextureHandle;
   Point2I startPoint;
   bool mWrap;
   Point2I mousePos;
   bool mShowCursor;
   ColorI mCursorColor;
   F32 mCursorWidth;
   F32 mBoxSizeWidth;
   F32 mBoxSizeHeight;

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

   //Parental methods
   bool onWake();
   void onSleep();
   void inspectPostApply();

   void onMouseDown(const GuiEvent &);
   void onMouseEnter(const GuiEvent & event);
   void onMouseLeave(const GuiEvent & event);
   void onMouseMove(const GuiEvent & event);
   void setBitmap(const char *name,bool resize = false);
   void setBitmap(const GFXTexHandle handle, bool resize = false);

   void updateSizing();

   void onRender(Point2I offset, const RectI &updateRect);
   void setValue(S32 x, S32 y);
};

#endif

GuiBitmapSelCtrl.cpp

#include "console/console.h"
#include "console/consoleTypes.h"
#include "gfx/gfxDevice.h"
#include "gui/core/guiCanvas.h"

#include "gui/controls/GuiBitmapSelCtrl.h"

IMPLEMENT_CONOBJECT(GuiBitmapSelCtrl);

GuiBitmapSelCtrl::GuiBitmapSelCtrl(void)
{
   mBitmapName = StringTable->insert("");
	startPoint.set(0, 0);
	mWrap = false;
	mCursorWidth = 1.0f;
	mCursorColor = ColorI(255,0,0,255);
    mBoxSizeWidth = 0;
    mBoxSizeHeight = 0;
}

void GuiBitmapSelCtrl::onMouseEnter(const GuiEvent & event)
{
	GuiCanvas* Canvas = getRoot();
	mShowCursor = false;
	Canvas->showCursor(false);
}

void GuiBitmapSelCtrl::onMouseLeave(const GuiEvent & event)
{
	GuiCanvas* Canvas = getRoot();
	mShowCursor = true;
    Canvas->showCursor(true);
}

void GuiBitmapSelCtrl::onMouseMove(const GuiEvent & event)
{
	mousePos.x = event.mousePoint.x;
	mousePos.y = event.mousePoint.y;
}

void GuiBitmapSelCtrl::onMouseDown(const GuiEvent &event)
{
   if (!mActive)
      return;
   
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   Con::executef(this, "onMouseDown", Con::getIntArg(curMousePos.x), Con::getIntArg(curMousePos.y),
                 Con::getIntArg(getBounds().extent.x), Con::getIntArg(getBounds().extent.y));                               
}

void GuiBitmapSelCtrl::initPersistFields()
{
   Parent::initPersistFields();
   addGroup("Misc");		
   addField("bitmap", TypeFilename, Offset(mBitmapName, GuiBitmapSelCtrl));
   addField("wrap",   TypeBool,     Offset(mWrap,       GuiBitmapSelCtrl));
   addField("cursorColor",    TypeColorI,    Offset(mCursorColor, GuiBitmapSelCtrl));
   addField("cursorWidth",    TypeF32,    Offset(mCursorWidth, GuiBitmapSelCtrl));
   addField("boxSizeWidth",    TypeF32,    Offset(mBoxSizeWidth, GuiBitmapSelCtrl));
   addField("boxSizeHeight",    TypeF32,    Offset(mBoxSizeHeight, GuiBitmapSelCtrl));
   endGroup("Misc");		
}

ConsoleMethod( GuiBitmapSelCtrl, setValue, void, 4, 4, "(int xAxis, int yAxis)"
              "Set the offset of the bitmap.")
{
   object->setValue(dAtoi(argv[2]), dAtoi(argv[3]));
}

ConsoleMethod( GuiBitmapSelCtrl, setBitmap, void, 3, 3, "(string filename)"
              "Set the bitmap displayed in the control. Note that it is limited in size, to 256x256.")
{
   object->setBitmap(argv[2]);
}

bool GuiBitmapSelCtrl::onWake()
{
   if (! Parent::onWake())
      return false;
   setActive(true);
   setBitmap(mBitmapName);

   return true;
}

void GuiBitmapSelCtrl::onSleep()
{
   mTextureHandle = NULL;
   Parent::onSleep();
}

//-------------------------------------
void GuiBitmapSelCtrl::inspectPostApply()
{
   // if the extent is set to (0,0) in the gui editor and appy hit, this control will
   // set it's extent to be exactly the size of the bitmap (if present)
   Parent::inspectPostApply();

   if (!mWrap && (getExtent().x == 0) && (getExtent().y == 0) && mTextureHandle)
   {
      setExtent( mTextureHandle->getWidth(), mTextureHandle->getHeight());
   }
}

void GuiBitmapSelCtrl::setBitmap(const char *name, bool resize)
{
   mBitmapName = StringTable->insert(name);
   if (*mBitmapName) 
   {
      mTextureHandle.set( mBitmapName, &GFXDefaultGUIProfile );
      // Resize the control to fit the bitmap
      //if( mTextureHandle && resize )
      if( resize )
      {
         setExtent(mTextureHandle->getWidth(), mTextureHandle->getHeight());
         updateSizing();
      }
   
   }
   else
      mTextureHandle = NULL;
   setUpdate();
}
 
void GuiBitmapSelCtrl::setBitmap(GFXTexHandle handle, bool resize)
{
   mTextureHandle = handle;
   // Resize the control to fit the bitmap
   if (resize) 
   {
      setExtent(mTextureHandle->getWidth(), mTextureHandle->getHeight());
      updateSizing();
   }
}

void GuiBitmapSelCtrl::onRender(Point2I offset, const RectI &updateRect)
{
   if (mTextureHandle)
   {
	   GFX->getDrawUtil()->clearBitmapModulation();
		if(mWrap)
		{
 			GFXTextureObject* texture = mTextureHandle;
			RectI srcRegion;
			RectI dstRegion;
			float xdone = ((float)getExtent().x/(float)texture->mBitmapSize.x)+1;
			float ydone = ((float)getExtent().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,texture->mBitmapSize.x,texture->mBitmapSize.y);
  					dstRegion.set( ((texture->mBitmapSize.x*x)+offset.x)-xshift,
								      ((texture->mBitmapSize.y*y)+offset.y)-yshift,
								      texture->mBitmapSize.x,	
								      texture->mBitmapSize.y);
   				GFX->getDrawUtil()->drawBitmapStretchSR(texture,dstRegion, srcRegion);
				}
		}
		else
      {
        RectI rect(offset, getExtent());
        GFX->getDrawUtil()->drawBitmapStretch(mTextureHandle, rect);
      }
	  if(!mShowCursor)
	  {
       	  GFX->getDrawUtil()->drawLine(mousePos.x, offset.y, mousePos.x, mousePos.y-mBoxSizeHeight, mCursorColor);
              GFX->getDrawUtil()->drawLine(mousePos.x, mousePos.y+mBoxSizeHeight+mCursorWidth, mousePos.x, offset.y + getBounds().extent.y, mCursorColor); 
		  GFX->getDrawUtil()->drawLine(offset.x, mousePos.y, mousePos.x-mBoxSizeWidth, mousePos.y, mCursorColor);
		  GFX->getDrawUtil()->drawLine(mousePos.x+mBoxSizeWidth+mCursorWidth, mousePos.y, offset.x+getBounds().extent.x, mousePos.y, mCursorColor);
              Point2I minPoint = Point2I(mousePos.x-mBoxSizeWidth, mousePos.y-mBoxSizeHeight);
		  Point2I maxPoint = Point2I(mousePos.x+mBoxSizeWidth, mousePos.y+mBoxSizeHeight);
		  GFX->getDrawUtil()->drawRect(minPoint, maxPoint, mCursorColor);
	  }
   }
   if (mProfile->mBorder || !mTextureHandle)
   {
      RectI rect(offset.x, offset.y, getBounds().extent.x, getBounds().extent.y);
      GFX->getDrawUtil()->drawRect(rect, mProfile->mBorderColor);
   }
   renderChildControls(offset, updateRect);
}

void GuiBitmapSelCtrl::updateSizing()
{
   if(!getParent())
      return;
   // updates our bounds according to our horizSizing and verSizing rules
   RectI fakeBounds( getPosition(), getParent()->getExtent());
   parentResized( fakeBounds, fakeBounds);
}

void GuiBitmapSelCtrl::setValue(S32 x, S32 y)
{
   if (mTextureHandle)
   {
		GFXTextureObject* texture = mTextureHandle;
            x+=texture->getWidth()/2;
		y+=texture->getHeight()/2;
  	}
  	while (x < 0)
  		x += 256;
  	startPoint.x = x % 256;
  				
  	while (y < 0)
  		y += 256;
  	startPoint.y = y % 256;
}

Bye !!!

^_^
#4
12/15/2008 (8:42 am)
Grande Andrea! ;-)
#5
03/08/2009 (7:56 am)
Screenies? Sounds like a great resource, though.