GuiSingleBitmapButtonCtrl
by Orion Elenzil · 06/22/2009 (7:17 pm) · 7 comments
this resource implements a new GuiControl, GuiSingleBitmapButtonCtrl.
this is very similar to a GuiBitmapButtonCtrl, but only takes a single bitmap instead of four.
the four states of the button (normal, highlighted, depressed, inactive) are visually indicated by four different bitmap modulation colors, and / or by four different background fill colors.
motivation:
it's a pain to make four bitmaps for a single button, especially when prototyping,
and often a simple change in color is sufficient to indicate the button's four states.
example 1, source bitmap:

resulting four states:

code:
example 2, source bitmap (the "G" is cut-out):

resulting states ("inactive" state not shown)

code:
This is based on a TGE 1.3.4 codebase,
but should be relevant to any torque engine using the same GuiControl system and OpenGL.
Some familiarity w/ C++ & Torque is assumed.
I have to admit i just wrote this in the last hour or so, and it's only been minimally tested.
Also note that the "lazyLoad" stuff is optional, if you don't feel like including it.
see this resource for more discussion.
create new file GuiSingleBitmapCtrl.h
create new file GuiSingleBitmapCtrl.cc
be sure to add them to your project file!
GuiCanvas.cc add a #include:
and add an IMPLEMENT_CONOBJECT: (anyone know why these are all in Canvas.cc instead of in their respective GuiControlFoo.cc files?)
and shazam!
this is very similar to a GuiBitmapButtonCtrl, but only takes a single bitmap instead of four.
the four states of the button (normal, highlighted, depressed, inactive) are visually indicated by four different bitmap modulation colors, and / or by four different background fill colors.
motivation:
it's a pain to make four bitmaps for a single button, especially when prototyping,
and often a simple change in color is sufficient to indicate the button's four states.
example 1, source bitmap:

resulting four states:

code:
canvas.getContent().add(new GuiSingleBitmapCtrl() {
extent = "180 120";
bitmap = "dev/gg1";
});example 2, source bitmap (the "G" is cut-out):

resulting states ("inactive" state not shown)

code:
canvas.getContent().add(new GuiSingleBitmapCtrl() {
extent = "180 120";
bitmap = "dev/gg2";
modulationcolor_n = "255 255 255 255";
modulationcolor_h = "255 255 255 255";
modulationcolor_d = "255 255 255 255";
backgroundcolor_n = "169 164 169 255";
backgroundcolor_h = "170 170 170 255";
backgroundcolor_d = "250 220 80 255";
});This is based on a TGE 1.3.4 codebase,
but should be relevant to any torque engine using the same GuiControl system and OpenGL.
Some familiarity w/ C++ & Torque is assumed.
I have to admit i just wrote this in the last hour or so, and it's only been minimally tested.
Also note that the "lazyLoad" stuff is optional, if you don't feel like including it.
see this resource for more discussion.
create new file GuiSingleBitmapCtrl.h
//-----------------------------------------------------------------------------
// orion elenzil
// doppelganger
// 20090622
//-----------------------------------------------------------------------------
#ifndef _GUI_SINGLE_BITMAP_BUTTON_CTRL_H_
#define _GUI_SINGLE_BITMAP_BUTTON_CTRL_H_
#include "gui/guiButtonCtrl.h"
#include "dgl/gTexManager.h"
class GuiSingleBitmapButtonCtrl : public GuiButtonCtrl
{
private:
typedef GuiButtonCtrl Parent;
protected:
StringTableEntry mBitmapName;
TextureHandle mTexture;
bool mLazyLoad;
bool mNeedLazyLoad;
void renderButton(TextureHandle &texture, Point2I &offset, const RectI& updateRect);
public:
ColorI mModulationColor_Master; // master modulation
ColorI mModulationColor_N; // modulation in the neutral state
ColorI mModulationColor_D; // modulation while the button is down (poor button)
ColorI mModulationColor_H; // modulation while the button is hovered-over
ColorI mModulationColor_I; // modulation while the button is inactive
ColorI mBackgroundColor_N; // Background in the neutral state
ColorI mBackgroundColor_D; // Background while the button is down (poor button)
ColorI mBackgroundColor_H; // Background while the button is hovered-over
ColorI mBackgroundColor_I; // Background while the button is inactive
public:
DECLARE_CONOBJECT(GuiSingleBitmapButtonCtrl);
GuiSingleBitmapButtonCtrl();
static void initPersistFields();
//Parent methods
bool onWake ();
void onSleep ();
void inspectPostApply();
StringTableEntry getBitmap();
void setBitmap(const char *name);
void onRender (Point2I offset, const RectI &updateRect);
void lazyLoad ();
};
#endif //_GUI_SINGLE_BITMAP_BUTTON_CTRL_H_create new file GuiSingleBitmapCtrl.cc
//-----------------------------------------------------------------------------
// orion elenzil
// doppelganger
// 20090622
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/platformAudio.h"
#include "gui/guiCanvas.h"
#include "gui/guiSingleBitmapButtonCtrl.h"
#include "gui/guiDefaultControlRender.h"
//-------------------------------------
GuiSingleBitmapButtonCtrl::GuiSingleBitmapButtonCtrl()
{
mBitmapName = StringTable->insert("");
mBounds.extent = Point2I(140, 30);
mModulationColor_Master = ColorI(255, 255, 255, 255);
mModulationColor_N = ColorI(200, 200, 200, 255);
mModulationColor_D = ColorI(180, 180, 180, 255);
mModulationColor_H = ColorI(255, 225, 255, 255);
mModulationColor_I = ColorI(200, 200, 200, 170);
mBackgroundColor_N = ColorI(200, 200, 200, 0);
mBackgroundColor_D = ColorI(180, 180, 180, 0);
mBackgroundColor_H = ColorI(255, 225, 255, 0);
mBackgroundColor_I = ColorI(200, 200, 200, 0);
mLazyLoad = true ;
mNeedLazyLoad = false;
}
//-------------------------------------
void GuiSingleBitmapButtonCtrl::initPersistFields()
{
Parent::initPersistFields();
addField("bitmap" , TypeFilename, Offset(mBitmapName , GuiSingleBitmapButtonCtrl));
addField("modulationColor_Master", TypeColorI , Offset(mModulationColor_Master, GuiSingleBitmapButtonCtrl));
addField("modulationColor_N" , TypeColorI , Offset(mModulationColor_N , GuiSingleBitmapButtonCtrl));
addField("modulationColor_D" , TypeColorI , Offset(mModulationColor_D , GuiSingleBitmapButtonCtrl));
addField("modulationColor_H" , TypeColorI , Offset(mModulationColor_H , GuiSingleBitmapButtonCtrl));
addField("modulationColor_I" , TypeColorI , Offset(mModulationColor_I , GuiSingleBitmapButtonCtrl));
addField("backgroundColor_N" , TypeColorI , Offset(mBackgroundColor_N , GuiSingleBitmapButtonCtrl));
addField("backgroundColor_D" , TypeColorI , Offset(mBackgroundColor_D , GuiSingleBitmapButtonCtrl));
addField("backgroundColor_H" , TypeColorI , Offset(mBackgroundColor_H , GuiSingleBitmapButtonCtrl));
addField("backgroundColor_I" , TypeColorI , Offset(mBackgroundColor_I , GuiSingleBitmapButtonCtrl));
addField("lazyLoad" , TypeBool , Offset(mLazyLoad , GuiSingleBitmapButtonCtrl));
}
//-------------------------------------
bool GuiSingleBitmapButtonCtrl::onWake()
{
if (! Parent::onWake())
return false;
setActive(mActive);
setBitmap(mBitmapName);
return true;
}
//-------------------------------------
void GuiSingleBitmapButtonCtrl::onSleep()
{
mTexture = NULL;
Parent::onSleep();
}
//-------------------------------------
ConsoleMethod( GuiSingleBitmapButtonCtrl, setBitmap, void, 3, 3, "(filepath name)")
{
object->setBitmap(argv[2]);
}
//-------------------------------------
void GuiSingleBitmapButtonCtrl::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 normal bitmap (if present)
Parent::inspectPostApply();
if ((mBounds.extent.x == 0) && (mBounds.extent.y == 0) && mTexture)
{
TextureObject *texture = (TextureObject *) mTexture;
mBounds.extent.x = texture->bitmapWidth;
mBounds.extent.y = texture->bitmapHeight;
}
}
//-------------------------------------
StringTableEntry GuiSingleBitmapButtonCtrl::getBitmap()
{
return mBitmapName;
}
void GuiSingleBitmapButtonCtrl::setBitmap(const char *name)
{
mBitmapName = StringTable->insert(name);
mNeedLazyLoad = true;
if (!mLazyLoad)
{
lazyLoad();
}
}
void GuiSingleBitmapButtonCtrl::lazyLoad()
{
if (!mNeedLazyLoad)
{
return;
}
mNeedLazyLoad = false;
if(!isAwake())
return;
// Con::errorf("%s() - loading %s", __FUNCTION__, mBitmapName ? mBitmapName : "(null)");
if (*mBitmapName)
{
mTexture = TextureHandle(mBitmapName, BitmapTexture, true);
}
else
{
mBitmapName = NULL;
}
setUpdate();
}
//-------------------------------------
void GuiSingleBitmapButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
{
lazyLoad();
enum
{
NORMAL,
HILIGHT,
DEPRESSED,
INACTIVE
} state = NORMAL;
if (mActive)
{
if(mDepressed)
{
state = DEPRESSED;
}
else if (mMouseOver)
{
state = HILIGHT;
}
else if (mStateOn)
{
state = DEPRESSED;
}
}
else
{
state = INACTIVE;
}
ColorI modulationColor;
ColorI backgroundColor;
switch (state)
{
case NORMAL:
modulationColor = mModulationColor_N;
backgroundColor = mBackgroundColor_N;
break;
case HILIGHT:
modulationColor = mModulationColor_H;
backgroundColor = mBackgroundColor_H;
break;
case DEPRESSED:
modulationColor = mModulationColor_D;
backgroundColor = mBackgroundColor_D;
break;
case INACTIVE:
modulationColor = mModulationColor_I;
backgroundColor = mBackgroundColor_I;
break;
}
modulationColor *= mModulationColor_Master; // see ColorI convolution resource - http://www.garagegames.com/community/resources/view/17177
backgroundColor *= mModulationColor_Master; // see ColorI convolution resource - http://www.garagegames.com/community/resources/view/17177
RectI rect(offset, mBounds.extent);
if (backgroundColor.alpha > 0)
{
dglDrawRectFill(rect, backgroundColor);
}
if (mTexture && modulationColor.alpha > 0)
{
dglSetBitmapModulation(modulationColor);
dglDrawBitmapStretch (mTexture, rect);
}
renderChildControls( offset, updateRect);
}be sure to add them to your project file!
GuiCanvas.cc add a #include:
#include "gui/guiSingleBitmapButtonCtrl.h"
and add an IMPLEMENT_CONOBJECT: (anyone know why these are all in Canvas.cc instead of in their respective GuiControlFoo.cc files?)
IMPLEMENT_CONOBJECT(GuiSingleBitmapButtonCtrl);
and shazam!
About the author
#2
06/22/2009 (8:41 pm)
Thanks Orion!
#3
I wrote this resource some time ago explaining a little how TGE uses the color modulation. It uses default TGE functions.
http://www.garagegames.com/community/resources/view/11774
Maybe it help somebody to make an improved control.
Luck!
06/23/2009 (1:12 am)
Nice resource.I wrote this resource some time ago explaining a little how TGE uses the color modulation. It uses default TGE functions.
http://www.garagegames.com/community/resources/view/11774
Maybe it help somebody to make an improved control.
Luck!
#4
06/23/2009 (3:37 am)
very coool, thanks a lot, ill try it!.
#5
06/23/2009 (8:26 am)
Cool! This will be handy for sure. Thanks !
#6
07/08/2009 (4:49 pm)
Sadly, I can't get this to work in TGEA 1.8.1. :(
#7
07/08/2009 (10:01 pm)
XD - hmm, bummer. i'm unfamiliar w/ TGEA. for the most part this resource is a subset of GuiBitmapButtonCtrl, so i would suggest looking at GuiBitmapButtonCtrl in TGEA and seeing how the textures are handled.
Associate Matt Motsinger