christianclavet wrote:What I would like to do, is to do a similar thing that we have with Adobe Flash buttons. To change the picture when then mouse "get in" the button and set it back to it's last "button state" when the mouse pointer "get out" of the zone. I don't think it would be hard to do if I do my own button class, but was wondering if someone was able to do this externally (using the Irrlicht button, and doing this from outside the Irrlicht class)
Yes, I believe the sprite bank will do that.
You can set the button sprites one of two ways: 1) in your constructor or 2) make editing their sprite bank accessible after creation.
For example:
First, make a sprite bank:
Code: Select all
/* We use a function that could be a member function of a class which is called during or after initialization of the GUI element whose buttons use this sprite bank. We use the same sprite bank in this example so that all of the buttons receive the same hover effect. */
IGUISpriteBank* getMenuSpriteBank() /* or myClass::getMenuSpriteBank() . You may be able to make this class const - I haven't checked */
{
/* If this is the member function of a class, we can conveniently pre-save a sprite bank so we don't have to create it each time. Or, while I haven't checked, I believe you can get a named sprite bank from the GUI environment, and that way you don't have to save a pointer to it and this function does not have to be a member function of some class. */
if ( spriteBank ) { return spriteBank; }
/* Otherwise, we initialize it */
IGUISpriteBank* spriteBank;
/* Now we get a new sprite bank from the GUI environment.
For in classes, this is convenient. We call getEnvironment() . Otherwise, we would have to pass in the environment as a parameter. */
spriteBank = getEnvironment()->addEmptySpriteBank( "mybank" ); /* This is an io::path, so it should be unique. I believe you can use this name to find the bank again if it has already been made. */
/* In order to prevent our sprite bank from drawing anything when the button is not being hovered over, we add a blank frame. */
SGUISpriteFrame noHoverFrame;
noHoverFrame.rectNumber = 0;
noHoverFrame.textureNumber = 0;
/* Repeat the following for the number of frames you want */
SGUISpriteFrame hoverFrame0;
hoverFrame.rectNumber = 0;
hoverFrame.textureNumber = 1;
/* Notably, the rectNumber is the same for all frames. This is because our button doesn't change size, so why should the image rectangle? */
SGUISprite hoverSprite;
hoverSprite.frameTime = 100; /* A good time length for about 5 frames or so */
hoverSprite.Frames.push_back( noHoverFrame );
hoverSprite.Frames.push_back( hoverFrame0 );
// ... etc.
/* For smooth transitions, I also add a hover-off sprite, which is made the same way as the hover-on sprite but with the frames added in the reverse order. */
// Add the sprites to the bank
spriteBank->getSprites().push_back( hoverSprite );
// ... etc
// button area rectangle
spriteBank->getPositions().push_back( recti( position2di(), myDimension ) );
// add textures
/* Notice the first one is blank. This is the texture when the button is not being hovered over, so we just want a blank texture of the same type as the other textures. */
spriteBank->addTexture( getEnvironment()->getVideoDriver()->getTexture( "" ) );
spriteBank->addTexture( getEnvironment()->getVideoDriver()->getTexture( hoverTexturePath ) );
return spriteBank;
}
Next, we use the sprite bank in the class, either in the constructor,
Code: Select all
// Sample GUI class
class myElem :: public IGUIElement
{
protected:
IGUIButton* button;
public:
myElem( IGUIEnvironment* environment, /* Optionally: */ mySpriteBank // ... etc. )
{
button = environment->addButton( button_rectangle, this );
button->setSubElement( true );
/* At this point, you can add your images to your buttons. I discovered that setting useAlphaChannel does nothing to the sprite's alpha channel settings (thankfully). */
// Here, you can add the sprite bank, if you want
button->setSpriteBank( mySpriteBank );
// Now set the hover sprite
button->setSprite( EGBS_BUTTON_MOUSE_OVER, 0 /* hover sprite index */, SColor() /* specific hover color */, false /* don't loop frames */ );
// Now set the hover-off sprite - same as above but with the sprite index set to 1
}
/* Or, you can set it externally.
I have not tested this, but given how sprites work, I can't imagine why it wouldn't work. */
void setButtonSpriteBank( IGUISpriteBank* mySpriteBank )
{
button->setSpriteBank( mySpriteBank );
// Now set the hover sprite
button->setSprite( EGBS_BUTTON_MOUSE_OVER, 0 /* hover sprite index */, SColor() /* specific hover color */, false /* don't loop frames */ );
// Now set the hover-off sprite - same as above but with the sprite index set to 1
}
};
In my example, there is only one button, though you can obviously do this for every button, even simplifying your code by passing your buttons to a single function like so:
Code: Select all
void setButtonSpriteBank( IGUIButton* button, IGUISpriteBank* bank )
{
// ... same code as setButtonSpriteBank() given above
}
You don't ever have to grab or drop the sprite bank. The GUI environment and the GUI buttons will do all of that (see docs for addEmptySpriteBank() ).
I think this should get you what you want. Of course, you'll have to make the hover button textures yourself.