Game Development Community

dev|Pro Game Development Curriculum

Scrolling Bitmap Control

by Robert Brower · 04/14/2005 (2:55 pm) · 5 comments

Download Code File

1. Put guiScrollingBitmapCtrl.h and guiScrollingBitmapCtrl.cc in your engine/gui folder and add them to your project.

2. Put stars1.png in your starter.fps/client/ui folder.

3. Add the following text to the top of your mainMenuGui.gui file like this:

//--- OBJECT WRITE BEGIN ---
new GuiChunkedBitmapCtrl(MainMenuGui) {
profile = "GuiContentProfile";
horizSizing = "width";
vertSizing = "height";
position = "0 0";
extent = "640 480";
minExtent = "8 8";
visible = "1";
bitmap = "./background";
useVariable = "0";
tile = "0";
helpTag = "0";

// INSERT THIS TEXT HERE ->
new GuiScrollingBitmapCtrl() {
profile = "GuiDefaultProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "0 0";
extent = "1024 768";
minExtent = "1024 768";
visible = "1";
bitmap = "~/client/ui/stars1.png";
wrap = "1";
interval = "30";
xoffset = "1";
yoffset = "1";
};
// <- INSERT THIS TEXT HERE

***NOTES... Play with interval, xoffset, and yoffset to speed up or slow down the scrolling. Make sure you turn on wrap otherwise the image won't... wrap.

Good luck and enjoy,

Robert

#1
04/16/2005 (5:29 am)
Neat idea.

I have a slightly different use for it though. Smoothly scrolling end credits when the game is over. Get your art team to make a long and very pretty looking screen credit roll and just run it in a window when your game is over.

You could do it with text scrolling but this seems like a much nicer solution.

Thanks for the resource!
#2
08/07/2005 (12:08 pm)
There is a limit to the size of the image though... I got an error saying my image was longer than 2048 pixel high and it wasn't happy about it... Also wonder about the practicalities of using a really huge image for credits...

Cool control though, I've got 2 overlaid starfields at different speeds giving a nice parallax effect. :-) It's only until I can come up with a cooler front screen.. but the idea is nice.
#3
08/25/2005 (3:09 pm)
I wasn't able to get the stars to go in the opposite direction at first. I was able to by changing the GuiScrollingBitmapCtrl::onRender in the guiScrollingBitmapCtrl.cc file.

Change:

if (mCurrXOffset >= texture->bitmapWidth)
{
mCurrXOffset = 0;
}

if (mCurrYOffset >= texture->bitmapHeight)
{
mCurrYOffset = 0 ;
}


to

if (mCurrXOffset >= texture->bitmapWidth)
{
mCurrXOffset -= texture->bitmapWidth;
}

if (mCurrYOffset >= texture->bitmapHeight)
{
mCurrYOffset -= texture->bitmapHeight;
}

After you recompile you can adjust the xOffset and yOffset to be 1 less than the height and width of the image and then the stars will go in the opposite direction.
#4
12/29/2008 (6:29 am)
Hi Robert !!!

I have modified your code for my study on bitmapCtrl in Torque and I have added mouse control on the bitmap viewed.

Here the code H :
//-----------------------------------------------------------------------------
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUISCROLLINGBITMAPCTRL_H_
#define _GUISCROLLINGBITMAPCTRL_H_

#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
#ifndef _GTEXMANAGER_H_
#include "dgl/gTexManager.h"
#endif

/// Renders a bitmap and scroll inside it.
class GuiScrollingBitmapCtrl : public GuiControl
{
private:
   typedef GuiControl Parent;

protected:
   StringTableEntry mBitmapName;
   TextureHandle mTextureHandle;
   Point2I startPoint;
   bool mWrap;
   
   S32 mCurrXOffset;
   S32 mCurrYOffset;

   Point2I mMouseDownPosition;

   bool mLeftMouseDown;
   bool mRightMouseDown;

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

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

   void setBitmap(const char *name,bool resize = false);
   void setBitmap(const TextureHandle &handle,bool resize = false);
      
   void setMapPos(S32 x, S32 y);

   void onMouseDown(const GuiEvent &);
   void onMouseUp(const GuiEvent &event);
   void onMouseDragged(const GuiEvent &event);
   void onRightMouseDown(const GuiEvent &event);
   void onRightMouseUp(const GuiEvent & event);
   void onRightMouseDragged(const GuiEvent & event);
   void onMouseMove(const GuiEvent &event);
   bool onMouseWheelUp(const GuiEvent &event);
   bool onMouseWheelDown(const GuiEvent &event);

   S32 getWidth() const       { return(mTextureHandle.getWidth()); }
   S32 getHeight() const      { return(mTextureHandle.getHeight()); }

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

#endif

And cpp code :

//-------------------------------------------------------------------------------------------------------------------------------//
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-------------------------------------------------------------------------------------------------------------------------------//
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/dgl.h"

#include "gui/controls/guiScrollingBitmapCtrl.h"

IMPLEMENT_CONOBJECT(GuiScrollingBitmapCtrl);

GuiScrollingBitmapCtrl::GuiScrollingBitmapCtrl(void)
{
   mBitmapName = StringTable->insert("");
   startPoint.set(0, 0);
   mWrap = false;

   mCurrXOffset = 0;
   mCurrYOffset = 0;
}

void GuiScrollingBitmapCtrl::initPersistFields()
{
   Parent::initPersistFields();
   addGroup("Misc");		// MM: Added Group Header.
   
   addField("bitmap", TypeFilename, Offset(mBitmapName, GuiScrollingBitmapCtrl));
   addField("wrap",   TypeBool,     Offset(mWrap,       GuiScrollingBitmapCtrl));

   endGroup("Misc");		// MM: Added Group Footer.
}

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

ConsoleMethod( GuiScrollingBitmapCtrl, 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]);
}

ConsoleMethod( GuiScrollingBitmapCtrl, setMapPos, void, 4, 4, "(int X, int Y)"
              "Set offset of the bitmap viewed.")
{
   object->setMapPos(dAtoi(argv[2]), dAtoi(argv[3]));
}

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

   mCurrXOffset = 0;
   mCurrYOffset = 0;

   return true;
}

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

void GuiScrollingBitmapCtrl::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 && (mBounds.extent.x == 0) && (mBounds.extent.y == 0) && mTextureHandle)
   {
      TextureObject *texture = (TextureObject *) mTextureHandle;
      mBounds.extent.x = texture->bitmapWidth;
      mBounds.extent.y = texture->bitmapHeight;
   }
}

void GuiScrollingBitmapCtrl::setBitmap(const char *name, bool resize)
{
   mBitmapName = StringTable->insert(name);
   if (*mBitmapName) {
      mTextureHandle = TextureHandle(mBitmapName, BitmapTexture, true);

      // Resize the control to fit the bitmap
      if (resize) {
         TextureObject* texture = (TextureObject *) mTextureHandle;
         mBounds.extent.x = texture->bitmapWidth;
         mBounds.extent.y = texture->bitmapHeight;
         Point2I extent = getParent()->getExtent();
         parentResized(extent,extent);
      }
   }
   else
      mTextureHandle = NULL;
   setUpdate();
}   

void GuiScrollingBitmapCtrl::setBitmap(const TextureHandle &handle, bool resize)
{
   mTextureHandle = handle;   

   // Resize the control to fit the bitmap
   if (resize) {
      TextureObject* texture = (TextureObject *) mTextureHandle;
      mBounds.extent.x = texture->bitmapWidth;
      mBounds.extent.y = texture->bitmapHeight;
      Point2I extent = getParent()->getExtent();
      parentResized(extent,extent);
   }
}   

void GuiScrollingBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
{
   TextureObject* texture = (TextureObject *) mTextureHandle;

   if (mTextureHandle)
   {
       dglClearBitmapModulation();

       if(mWrap)
	   {
 	     RectI srcRegion;
		 RectI dstRegion;
		 
		 float xdone = ((float)mBounds.extent.x/(float)texture->bitmapWidth)+1;
		 float ydone = ((float)mBounds.extent.y/(float)texture->bitmapHeight)+1;

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

         xshift += mCurrXOffset;
	     yshift += mCurrYOffset;

		 for(int y = 0; y < ydone; ++y)
		    for(int x = 0; x < xdone; ++x)
			{
		 	   srcRegion.set(0,0,texture->bitmapWidth,texture->bitmapHeight);
  			   dstRegion.set(((texture->bitmapWidth*x)+offset.x)-xshift,
			                 ((texture->bitmapHeight*y)+offset.y)-yshift,
					       texture->bitmapWidth,
					       texture->bitmapHeight);
   			   dglDrawBitmapStretchSR(texture,dstRegion, srcRegion, false);
		    }
       }
	   else
       {

	     Point2I mTempOffset(0, 0);
         mTempOffset.x += mCurrXOffset;
	     mTempOffset.y += mCurrYOffset;
         RectI rect(mTempOffset, mBounds.extent);
	     dglDrawBitmapStretch(mTextureHandle, rect);
       }
   }

   if (mProfile->mBorder || !mTextureHandle)
   {
      RectI rect(offset.x, offset.y, mBounds.extent.x, mBounds.extent.y);
      dglDrawRect(rect, mProfile->mBorderColor);
   }

   renderChildControls(offset, updateRect);
}

void GuiScrollingBitmapCtrl::setValue(S32 x, S32 y)
{
   if (mTextureHandle)
   {
	TextureObject* texture = (TextureObject *) mTextureHandle;
	x+=texture->bitmapWidth/2;
	y+=texture->bitmapHeight/2;
   }

   while (x < 0)
  	x += 256;
  	startPoint.x = x % 256;
   while (y < 0)
  	y += 256;
  	startPoint.y = y % 256;
}

void GuiScrollingBitmapCtrl::setMapPos(S32 x, S32 y)
{
	mCurrXOffset = x;
	mCurrYOffset = y;
}

void GuiScrollingBitmapCtrl::onMouseDown(const GuiEvent &event)
{
   if (!mActive)
      return;
   
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);
  
   Con::executef(this, 3, "onMouseDown",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));

   mLeftMouseDown = true;
}

void GuiScrollingBitmapCtrl::onMouseUp(const GuiEvent &event)
{
   mLeftMouseDown = false;
   Parent::onMouseUp(event);
}

void GuiScrollingBitmapCtrl::onMouseDragged(const GuiEvent &event)
{
	if (!mActive)
      return;

	if (!mLeftMouseDown)
      return;
  
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   Con::executef(this, 3, "onMouseDragged",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));
}

void GuiScrollingBitmapCtrl::onRightMouseDown(const GuiEvent & event)
{
   if (!mActive)
      return;
   
   mMouseDownPosition = event.mousePoint;

   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   Con::executef(this, 3, "onRightMouseDown",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));

   mRightMouseDown = true;
}

void GuiScrollingBitmapCtrl::onRightMouseUp(const GuiEvent & event)
{
   Con::executef(this, 1, "onRightMouseUp");
   mRightMouseDown = false;
   Parent::onRightMouseUp(event);
}

void GuiScrollingBitmapCtrl::onRightMouseDragged(const GuiEvent & event)
{
	if (!mActive)
      return;

	if (!mRightMouseDown)
      return;
  
   Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   if (deltaMousePosition.x<0) mCurrXOffset = mCurrXOffset + 1;
   if (deltaMousePosition.x>0) mCurrXOffset = mCurrXOffset - 1;

   if (mCurrXOffset<0) mCurrXOffset = 0;
   if (mCurrXOffset>1048) mCurrXOffset=1048; 

   if (deltaMousePosition.y<0) mCurrYOffset = mCurrYOffset + 1;
   if (deltaMousePosition.y>0) mCurrYOffset = mCurrYOffset - 1;

   if (mCurrYOffset<0) mCurrYOffset = 0;
   if (mCurrYOffset>1048) mCurrYOffset=1048;

   Con::executef(this, 3, "onRightMouseDragged",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));
}

void GuiScrollingBitmapCtrl::onMouseMove(const GuiEvent &event)
{
}

bool GuiScrollingBitmapCtrl::onMouseWheelUp(const GuiEvent &event)
{
   mCurrYOffset -= 10;
   if (mCurrYOffset<0) mCurrYOffset = 0;

   return( true );
}

bool GuiScrollingBitmapCtrl::onMouseWheelDown(const GuiEvent &event)
{
   mCurrYOffset += 10;
   if (mCurrYOffset>1048) mCurrYOffset=1048;

   return( true );
}

The script code is :

//--- OBJECT WRITE BEGIN ---
new GuiControl(ScrollBitmapGui) {
   canSaveDynamicFields = "0";
   Profile = "GuiDefaultProfile";
   HorizSizing = "center";
   VertSizing = "center";
   Position = "0 0";
   Extent = "1024 768";
   MinExtent = "8 2";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";

   new GuiBitmapCtrl(BACKGROUND) {
      canSaveDynamicFields = "0";
      Profile = "GuiDefaultProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      Position = "0 0";
      Extent = "1024 768";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      bitmap = "./background.jpg";
      wrap = "0";

      new GuiScrollingBitmapCtrl(Map) {
         canSaveDynamicFields = "0";
         Profile = "GuiDefaultProfile";
         HorizSizing = "center";
         VertSizing = "center";
         Position = "12 16";
         Extent = "1000 600";
         MinExtent = "1000 600";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         bitmap = "./themap.jpg";    // MAX DIM. => 2048 x 2048
         wrap = "1";
      };
      new GuiButtonCtrl(BACKMENU) {
         canSaveDynamicFields = "0";
         Profile = "GuiButtonProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         Position = "17 716";
         Extent = "140 30";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "Canvas.popDialog(ScrollBitmapGui);";
         hovertime = "1000";
         text = "BACK";
         groupNum = "-1";
         buttonType = "PushButton";
      };
   };
};
//--- OBJECT WRITE END ---

function ScrollBitmapGui::onWake()
{
 Map.setMapPos(524,524); // Set Initial Position of the map !!!
 moveMap.pop();
}

function ScrollBitmapGui::onSleep(%this)
{
 moveMap.push();
}

function Map::onMouseDown(%this, %MouseX, %MouseY, %width, %height)
{
  echo("mouse X = " @ %MouseX);
  echo("mouse Y = " @ %MouseY);
}

function Map::onMouseDragged(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
}

function Map::onLeftMouseUp(%this)
{
}

function Map::onRightMouseDown(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
  Canvas.setCursor(MoveCursor);
}

function Map::onRightMouseDragged(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
}

function Map::onRightMouseUp(%this)
{ 
 Canvas.setCursor(DefaultCursor);
}


My target is realize a new MapHud for strategic game.

Bye !!

^_^
#5
12/29/2008 (6:37 am)
Remember the limit of the bitmap on TGE is 2048X2048

Indeed for TGEA is 1024x1024 I have converted the code for TGEA 1.7.0 :

the .H code :

//-----------------------------------------------------------------------------
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUISCROLLINGBITMAPCTRL_H_
#define _GUISCROLLINGBITMAPCTRL_H_

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

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

protected:
   StringTableEntry mBitmapName;
   GFXTexHandle mTextureHandle;
   Point2I startPoint;
   bool mWrap;
   
   S32 mCurrXOffset;
   S32 mCurrYOffset;

   Point2I mMouseDownPosition;

   bool mLeftMouseDown;
   bool mRightMouseDown;

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

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

   void setBitmap(const char *name,bool resize = false);
   void setBitmap(GFXTexHandle &handle,bool resize = false);
      
   void setMapPos(S32 x, S32 y);

   void onMouseDown(const GuiEvent &);
   void onMouseUp(const GuiEvent &event);
   void onMouseDragged(const GuiEvent &event);
   void onRightMouseDown(const GuiEvent &event);
   void onRightMouseUp(const GuiEvent & event);
   void onRightMouseDragged(const GuiEvent & event);
   void onMouseMove(const GuiEvent &event);
   bool onMouseWheelUp(const GuiEvent &event);
   bool onMouseWheelDown(const GuiEvent &event);

   void updateSizing();

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

#endif


The .CPP code :

//-------------------------------------------------------------------------------------------------------------------------------//
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-------------------------------------------------------------------------------------------------------------------------------//
#include "console/console.h"
#include "console/consoleTypes.h"
#include "gfx/gfxDevice.h"

#include "gui/controls/guiScrollingBitmapCtrl.h"

IMPLEMENT_CONOBJECT(GuiScrollingBitmapCtrl);

GuiScrollingBitmapCtrl::GuiScrollingBitmapCtrl(void)
{
   mBitmapName = StringTable->insert("");
   startPoint.set(0, 0);
   mWrap = false;

   mCurrXOffset = 0;
   mCurrYOffset = 0;

}

void GuiScrollingBitmapCtrl::initPersistFields()
{
   Parent::initPersistFields();
   addGroup("Misc");		// MM: Added Group Header.
   
   addField("bitmap", TypeFilename, Offset(mBitmapName, GuiScrollingBitmapCtrl));
   addField("wrap",   TypeBool,     Offset(mWrap,       GuiScrollingBitmapCtrl));

   endGroup("Misc");		// MM: Added Group Footer.
}

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

ConsoleMethod( GuiScrollingBitmapCtrl, 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]);
}

ConsoleMethod( GuiScrollingBitmapCtrl, setMapPos, void, 4, 4, "(int X, int Y)"
              "Set offset of the bitmap viewed.")
{
   object->setMapPos(dAtoi(argv[2]), dAtoi(argv[3]));
}

bool GuiScrollingBitmapCtrl::onWake()
{
   if (! Parent::onWake())
      return false;

   setActive(true);
   setBitmap(mBitmapName);

   mCurrXOffset = 0;
   mCurrYOffset = 0;
 
   return true;
}

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

void GuiScrollingBitmapCtrl::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 GuiScrollingBitmapCtrl::updateSizing()
{
   if(!getParent())
      return;
   // updates our bounds according to our horizSizing and verSizing rules
   RectI fakeBounds( getPosition(), getParent()->getExtent());
   parentResized( fakeBounds, fakeBounds);
}

void GuiScrollingBitmapCtrl::setBitmap(const char *name, bool resize)
{
   mBitmapName = StringTable->insert(name);
   if (*mBitmapName)
   {
      //mTextureHandle = TextureHandle(mBitmapName, BitmapTexture, true);
      mTextureHandle.set(mBitmapName, &GFXDefaultGUIProfile);

      // Resize the control to fit the bitmap
      if( mTextureHandle && resize )
      {
         setExtent(mTextureHandle->getWidth(), mTextureHandle->getHeight());
         updateSizing();
      }
   }
   else
      mTextureHandle = NULL;

   setUpdate();
}   

void GuiScrollingBitmapCtrl::setBitmap(GFXTexHandle &handle, bool resize)
{
   mTextureHandle = handle;   

   // Resize the control to fit the bitmap
   if (resize)
   {
      setExtent(mTextureHandle->getWidth(), mTextureHandle->getHeight());
      updateSizing();
   }

}   

void GuiScrollingBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
{
   GFXTextureObject* texture = mTextureHandle;

   if (mTextureHandle)
   {
       GFX->getDrawUtil()->clearBitmapModulation();
       
       if(mWrap)
	   {
 	     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;

         xshift += mCurrXOffset;
         yshift += mCurrYOffset;

	 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
       {

         Point2I mTempOffset(0, 0);
         mTempOffset.x += mCurrXOffset;
         mTempOffset.y += mCurrYOffset;
         RectI rect(mTempOffset, getExtent());
         GFX->getDrawUtil()->drawBitmapStretch(mTextureHandle, rect);
       }
   }

   if (mProfile->mBorder || !mTextureHandle)
   {
      RectI rect(offset.x, offset.y, getExtent().x, getExtent().y);
      GFX->getDrawUtil()->drawRect(rect, mProfile->mBorderColor);
   }

   renderChildControls(offset, updateRect);
}

void GuiScrollingBitmapCtrl::setValue(S32 x, S32 y)
{
   if (mTextureHandle)
   {
	x += mTextureHandle->getWidth() / 2;
	y += mTextureHandle->getHeight() / 2;
   }

   while (x < 0)
  	x += 256;
  	startPoint.x = x % 256;
   while (y < 0)
  	y += 256;
  	startPoint.y = y % 256;
}

void GuiScrollingBitmapCtrl::setMapPos(S32 x, S32 y)
{
	mCurrXOffset = x;
	mCurrYOffset = y;
}

void GuiScrollingBitmapCtrl::onMouseDown(const GuiEvent &event)
{
   if (!mActive)
      return;
   
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);
  
   Con::executef(this, "onMouseDown",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));

   mLeftMouseDown = true;
}

void GuiScrollingBitmapCtrl::onMouseUp(const GuiEvent &event)
{
   mLeftMouseDown = false;
   Parent::onMouseUp(event);
}

void GuiScrollingBitmapCtrl::onMouseDragged(const GuiEvent &event)
{
	if (!mActive)
      return;

	if (!mLeftMouseDown)
      return;
  
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   Con::executef(this, "onMouseDragged",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));
}

void GuiScrollingBitmapCtrl::onRightMouseDown(const GuiEvent & event)
{
   if (!mActive)
      return;
   
   mMouseDownPosition = event.mousePoint;

   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   Con::executef(this, "onRightMouseDown",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));

   mRightMouseDown = true;
}

void GuiScrollingBitmapCtrl::onRightMouseUp(const GuiEvent & event)
{
   Con::executef(this, "onRightMouseUp");
   mRightMouseDown = false;
   Parent::onRightMouseUp(event);
}

void GuiScrollingBitmapCtrl::onRightMouseDragged(const GuiEvent & event)
{
	if (!mActive)
      return;

	if (!mRightMouseDown)
      return;
  
   Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
   Point2I curMousePos = globalToLocalCoord(event.mousePoint);

   if (deltaMousePosition.x<0) mCurrXOffset = mCurrXOffset + 1;
   if (deltaMousePosition.x>0) mCurrXOffset = mCurrXOffset - 1;

   if (mCurrXOffset<0) mCurrXOffset = 0;
   if (mCurrXOffset>224) mCurrXOffset=224;

   if (deltaMousePosition.y<0) mCurrYOffset = mCurrYOffset + 1;
   if (deltaMousePosition.y>0) mCurrYOffset = mCurrYOffset - 1;

   if (mCurrYOffset<0) mCurrYOffset = 0;
   if (mCurrYOffset>224) mCurrYOffset=224;

   Con::executef(this, "onRightMouseDragged",
                 Con::getIntArg(curMousePos.x),
                 Con::getIntArg(curMousePos.y));
}

void GuiScrollingBitmapCtrl::onMouseMove(const GuiEvent &event)
{
}

bool GuiScrollingBitmapCtrl::onMouseWheelUp(const GuiEvent &event)
{
   mCurrYOffset -= 10;
   if (mCurrYOffset<0) mCurrYOffset = 0;

   return( true );
}

bool GuiScrollingBitmapCtrl::onMouseWheelDown(const GuiEvent &event)
{
   mCurrYOffset += 10;
   if (mCurrYOffset>224) mCurrYOffset=224;

   return( true );
}

And scripting :

//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(ScrollBitmapGui) {
   canSaveDynamicFields = "0";
   Enabled = "1";
   isContainer = "1";
   Profile = "GuiDefaultProfile";
   HorizSizing = "center";
   VertSizing = "center";
   position = "0 0";
   Extent = "1024 768";
   MinExtent = "8 2";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";

   new GuiBitmapCtrl(BACKGROUND) {
      canSaveDynamicFields = "0";
      Enabled = "1";
      isContainer = "0";
      Profile = "GuiDefaultProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      position = "0 0";
      Extent = "1024 768";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      bitmap = "scriptsAndAssets/client/ui/GarageGames.jpg";
      wrap = "0";

      new GuiScrollingBitmapCtrl(Map) {
         canSaveDynamicFields = "0";
         Enabled = "1";
         isContainer = "0";
         Profile = "GuiDefaultProfile";
         HorizSizing = "center";
         VertSizing = "center";
         position = "12 16";
         Extent = "800 600";
         MinExtent = "800 600";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         bitmap = "scriptsAndAssets/client/ui/themap.jpg";
         wrap = "1";
      };
      new GuiButtonCtrl(BACKMENU) {
         canSaveDynamicFields = "0";
         Enabled = "1";
         isContainer = "0";
         Profile = "GuiButtonProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "17 716";
         Extent = "140 30";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "Canvas.popDialog(ScrollBitmapGui);";
         hovertime = "1000";
         text = "BACK";
         groupNum = "-1";
         buttonType = "PushButton";
         useMouseEvents = "0";
      };
   };
};
//--- OBJECT WRITE END ---
function ScrollBitmapGui::onWake()
{
 Map.setMapPos(124,124); // Set Initial Position of the map !!!
 moveMap.pop();
}

function ScrollBitmapGui::onSleep(%this)
{
 moveMap.push();
}

function Map::onMouseDown(%this, %MouseX, %MouseY, %width, %height)
{
  echo("mouse X = " @ %MouseX);
  echo("mouse Y = " @ %MouseY);
}

function Map::onMouseDragged(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
}

function Map::onLeftMouseUp(%this)
{
}

function Map::onRightMouseDown(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
  Canvas.setCursor(MoveCursor);
}

function Map::onRightMouseDragged(%this, %MouseX, %MouseY)
{
  echo("mouse X" @ %MouseX);
  echo("mouse Y" @ %MouseY);
}

function Map::onRightMouseUp(%this)
{ 
 Canvas.setCursor(DefaultCursor);
}


That's all !!!

If anyone have ideas about eventual development write here ;-)

Bye