Using IGUISpriteBank

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Using IGUISpriteBank

Post by bitplane »

okay first I apologise for the monstrosity that is IGUISpriteBank. Currently there's no way to load and save them, so they need to be created manually. I will make it more user friendly in future, but a lot of people were asking about this so for the moment here's a snippet that demonstrates how to redefine a gui icon manually.

First, due to a bug I missed, non-looping sprite animations currently crash in 1.4. So if you're using 1.4 and not latest SVN you'll need to edit CGUISpriteBank.cpp and change line 106 to-

Code: Select all

frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
Now we need a texture, so I made this: (notice it is a power of 2 in both dimensions)
Image

Finally, open the user interface example and paste the following code somewhere after "IGUIEnvironment* env = "

Code: Select all

	IGUISpriteBank* sprites = env->getSkin()->getSpriteBank();

	// load and add the texture to the bank
	driver->makeColorKeyTexture(driver->getTexture("../../sprite.png"), position2di(0,0));
	sprites->addTexture(driver->getTexture("../../sprite.png"));
	u32 textureIndex = sprites->getTextureCount() - 1;

	// now lets get the sprite bank's rectangles and add some for our animation
	core::array<core::rect<s32> >& rectangles = sprites->getPositions();
	u32 firstRect = rectangles.size();
	// remember that rectangles are not in pixels, they enclose pixels!
	// to draw a rectangle around the pixel at 0,0, it would rect<s32>(0,0, 1,1)
	rectangles.push_back(rect<s32>(0,1, 8,8));
	rectangles.push_back(rect<s32>(9,1, 16,8));
	rectangles.push_back(rect<s32>(0,9, 5,16));
	rectangles.push_back(rect<s32>(6,9, 10,16));
	rectangles.push_back(rect<s32>(11,9, 14,16));

	// now we make a sprite..
	SGUISprite sprite;
	sprite.frameTime = 30;
	// add some frames of animation.
	s32 n;
	for (n=0; n < 5; ++n)
	{
		// animate forward
		SGUISpriteFrame frame;
		frame.rectNumber = firstRect + n;
		frame.textureNumber = textureIndex;

		// add this frame
		sprite.Frames.push_back(frame);
	}
	for (n=4; n > -1; --n)
	{
		// and now in reverse
		SGUISpriteFrame frame;
		frame.rectNumber = firstRect + n;
		frame.textureNumber = textureIndex;

		// add this frame
		sprite.Frames.push_back(frame);
	}
	
	
	// add the sprite
	u32 spriteIndex = sprites->getSprites().size();
	sprites->getSprites().push_back(sprite);

	// now let's use this as the X window button 
	env->getSkin()->setIcon(EGDI_WINDOW_CLOSE, spriteIndex);
Run the example, click the close button on the window and see what happens :)
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Hi Bitplane.

I need to simply create icons in a new sprite bank and use them in a listbox before some names.

Like that. :idea: Name1
Every time I try to apply the icon I defined in the spritebank to the listbox, it crash. Would I need also to define the rectangle of the sprite?
It's not an animated icon, just a "status" icon.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Yes you still need at least one frame and a rectangle or it won't know where to get the sprite region from the texture
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Ok. Thank Bitplane.

I've done something that work to create non-animated customs icons in Listbox

Here is the code:

Code: Select all

void addIcon(IGUISpriteBank* sb, c8* fn, int sizex, int sizey)
{
    // load and add the texture to the bank 
   Device->getVideoDriver()->makeColorKeyTexture(Device->getVideoDriver()->getTexture(fn), position2di(0,0)); 
    
   sb->addTexture(Device->getVideoDriver()->getTexture(fn)); 
   u32 textureIndex = sb->getTextureCount() - 1; 
  
   // now lets get the sprite bank's rectangles and add some for our animation 
   core::array<core::rect<s32> >& rectangles = sb->getPositions(); 
   u32 firstRect = rectangles.size(); 
   // remember that rectangles are not in pixels, they enclose pixels! 
   // to draw a rectangle around the pixel at 0,0, it would rect<s32>(0,0, 1,1) 
   rectangles.push_back(rect<s32>(0,0, sizex+1,sizey+1)); 
   

   // now we make a sprite.. 
   SGUISprite sprite; 
   sprite.frameTime = 30; 
   // add some frames of animation. 
   SGUISpriteFrame frame; 
   frame.rectNumber = firstRect; 
   frame.textureNumber = textureIndex; 

   // add this frame 
   sprite.Frames.push_back(frame); 
   // add the sprite 
   u32 spriteIndex = sb->getSprites().size(); 
   sb->getSprites().push_back(sprite);  
}

void createIconBank()
{
   IGUISpriteBank* sprites = Device->getGUIEnvironment()->addEmptySpriteBank("icons"); 
   //IGUISpriteBank* sprites = Device->getGUIEnvironment()->getSkin()->getSpriteBank(); 
   addIcon(sprites, "media/ui/am_solid.png",35,19);
   addIcon(sprites, "media/ui/am_hide.png",35,19);
   addIcon(sprites, "media/ui/am_wire.png",35,19);
   addIcon(sprites, "media/ui/ot_solid.png",35,19);
   addIcon(sprites, "media/ui/am_hide.png",35,19);
   addIcon(sprites, "media/ui/am_wire.png",35,19);
   addIcon(sprites, "media/ui/ms_solid.png",35,19);
   addIcon(sprites, "media/ui/ms_hide.png",35,19);
   addIcon(sprites, "media/ui/ms_wire.png",35,19);
   // My icons size are 34x18 pixels
   // Each textures are 64x64 pixels
   if (sprites) selList->setSpriteBank(sprites);
   // selList is my LISTBOX
   
   
   // now let's use this as the X window button 
   //Device->getGUIEnvironment()->getSkin()->setIcon(EGDI_WINDOW_CLOSE, spriteIndex); 

     
}

Once this is done you initialise it like that:

Code: Select all

createIconBank();
Then on when you add your item:

Code: Select all

selList->addItem("Item 1",0); //-> will use the first icon from the bank
You also need to define something global (easier, and can be worked out without being global is you use parameters). Put this at the beginning of your code.

Code: Select all

IGUISpriteBank* sprites;
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

christianclavet wrote:

Code: Select all

   sb->addTexture(Device->getVideoDriver()->getTexture(fn));
Very strange, but in my code it crashed until i set after same as above string next(adapted to your snippet):

Code: Select all

sb->setTexture(sb->getTextureCount()-1,Device->getVideoDriver()->getTexture(fn));
Without this ny code asserted with irrarray assert something like that index of the drawing (it asserts on gui drawAll() method) sprite texture is greate than a count of the sprite's textures:( i used latest SVN version.
CuteAlien
Admin
Posts: 9716
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

I've also used the spritebank by now and once I learned how it works I actually like it :-)

Still I also needed it mostly as icons, so I've done something similar to christianclavet's code. But I've added it to my engine version here and it's working a little different, so maybe someone is interested:

(edit: Those functions are now (in 1.7) in Irrlicht)

Code: Select all

//! clear everything 
void CGUISpriteBank::clear()
{
	// drop textures
	for (u32 i=0; i<Textures.size(); ++i)
		if (Textures[i])
			Textures[i]->drop();
	Textures.clear();
	Sprites.clear();
	Rectangles.clear();
}

//! Use the whole texture as one non-animated sprite
//! The texture and the corresponding rectangle and sprite will all be added to the end of each array.
//! returns the index of the sprite or -1 on failure
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)
{
	if ( !texture )
		return -1;

	addTexture(texture);
	u32 textureIndex = getTextureCount() - 1;

	u32 rectangleIndex = Rectangles.size();
	Rectangles.push_back( core::rect<s32>(0,0, texture->getSize().Width, texture->getSize().Height) ); 

	SGUISprite sprite;
	sprite.frameTime = 0;

	SGUISpriteFrame frame;
	frame.textureNumber = textureIndex;
	frame.rectNumber = rectangleIndex;
	sprite.Frames.push_back( frame );

	Sprites.push_back( sprite );

	return Sprites.size() - 1;
}
CGUISpriteBank.h and IGUISpriteBank.h certainly got the corresponding function declarations added.

Also I hope my bugreport for the spritebanks at http://irrlicht.sourceforge.net/phpBB2/ ... highlight= doesn't get lost. (Edit: It got fixed by now)
Last edited by CuteAlien on Tue Dec 08, 2009 12:15 am, edited 1 time in total.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Antaka
Posts: 7
Joined: Tue Jul 28, 2009 4:37 pm

Post by Antaka »

sorry to bring back such an old topic, but I'm really stuck with the spritebank and the guiskin.
I'm trying to use diferent icons for the scrollbars, I've tried everything told here, everything that came to my mind, but it's still not working.
Did anyone used CuteAlien's functions succesfully? I've added the code to my engine, loaded the sprite, but I dont see it in the game...

here's my code

Code: Select all

	IGUISkin *guiSkin = l_irr_manager->getGUIEnv()->getSkin();
	gui::CGUISpriteBank * spriteBank = (gui::CGUISpriteBank *)guiSkin->getSpriteBank();
	s32 spriteIndex = spriteBank->addTextureAsSprite(l_irr_manager->getVideo()->getTexture("textures/sprite.png"));
	
	guiSkin->setSpriteBank((gui::CGUISpriteBank*)spriteBank);
	
	guiSkin->setColor(gui::EGUI_DEFAULT_COLOR::EGDC_SCROLLBAR, video::SColor(0,1,1,1));
	guiSkin->setIcon(gui::EGDI_CURSOR_LEFT,spriteIndex);
	printf("%d\n",spriteIndex);
	l_irr_manager->getGUIEnv()->setSkin(guiSkin);
I'm sure I'm missing some stupid thing hehe

Thanks :)


EDIT: I was making the settings to the skin after loading the scrollbars, that's why i couldnt see anyting, I've now change that, but all I get are balck squares in the scrollbar buttons instead of the image I'm loading...


EDIT II: Ok... I loaded a png with most of it in transparent, and it loaded well.
Post Reply