New GUI element: CGUIAnimatedImage

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
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

New GUI element: CGUIAnimatedImage

Post by 3DModelerMan »

I just started programming an animated GUI element and decided to let other people use it too. I've still got some more features to add though.
TODO:
Time based animation (need to figure out how to get the frame time from in the GUI element),
and maybe better looping features (Ping-pong animation mode etc.).
CGUIAnimatedImage.h

Code: Select all

#ifndef ANIMATEDGUIELEMENT_H_INCLUDED
#define ANIMATEDGUIELEMENT_H_INCLUDED
#include <Irrlicht.h>
using namespace irr;

class CGUIAnimatedImage : gui::IGUIElement
{
 public:
 //Constructor/destructor.
 CGUIAnimatedImage(gui::IGUIEnvironment* environment, gui::IGUIElement* parent, s32 id, core::rect<s32> rectangle, core::array<video::ITexture*>& textures);
 //Set frame loop.
 void setFrameLoop(irr::u32 begin, irr::u32 end);
 void setLoopMode(bool loopMode = true)
 {
  m_ShouldLoop = loopMode;
 }
 //Draw function.
 virtual void draw();

 private:
 core::rect<s32> m_Rect;
 core::array<video::ITexture*> m_TextureArray;
 irr::u32 m_StartFrame;
 irr::u32 m_EndFrame;
 irr::u32 m_CurrentFrame;
 bool m_ShouldLoop;
};

#endif // ANIMATEDGUIELEMENT_H_INCLUDED

CGUIAnimatedImage.cpp

Code: Select all

#include "CGUIAnimatedImage.h"

//Constructor/destructor.
CGUIAnimatedImage::CGUIAnimatedImage(gui::IGUIEnvironment* environment, gui::IGUIElement* parent, s32 id, core::rect<s32> rectangle, core::array<video::ITexture*>& textures)
: IGUIElement(gui::EGUIET_ELEMENT , environment, parent, id, rectangle)
{
 //Store pointers to textures...
 m_TextureArray = textures;

 //Set default frame loop.
 m_StartFrame = 0;
 m_EndFrame = m_TextureArray.size();
 m_ShouldLoop = true;
 m_CurrentFrame = m_StartFrame;
 //Set rectangle.
 m_Rect = rectangle;
}
//Animation control functions.
void CGUIAnimatedImage::setFrameLoop(irr::u32 begin, irr::u32 end)
{
 m_StartFrame = begin;
 m_EndFrame = end;
}
//Draw.
void CGUIAnimatedImage::draw()
{
 //don't draw if not visible or no images.
 if ( !IsVisible )
 return;
 if ( m_TextureArray.empty() )
 return;

 //Store video driver.
 video::IVideoDriver* driver = Environment->getVideoDriver();
 //Draw the images.
 core::rect<s32> pos = AbsoluteRect;
 if (m_CurrentFrame == m_TextureArray.size() )
 m_CurrentFrame = m_StartFrame;

 driver->draw2DImage(m_TextureArray[m_CurrentFrame], pos, m_Rect, 0, 0, true);

 if ( m_ShouldLoop )
 m_CurrentFrame++;
 else
 m_CurrentFrame = m_EndFrame;
}

Use like this.

Code: Select all

irr::core::array<irr::video::ITexture*> textures;

 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal1.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal2.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal3.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal4.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal5.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal6.bmp") );
 textures.push_back( m_Guienv->getVideoDriver()->getTexture("../irrlicht-1.6/media/portal7.bmp") );

 CGUIAnimatedImage* image = new CGUIAnimatedImage(m_Guienv, m_Guienv->getRootGUIElement(), -1, core::rect<s32>(0,0,100,100), textures);
 image->setLoopMode(true);
 image->setFrameLoop(0,800);
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

Hm cool... maybe you can merge this with my GUI Animator.
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

Post by 3DModelerMan »

I will if the devs add those animators to the SDK. Can you update it for Irr 1.6 and see if they'll put it in?
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
CuteAlien
Admin
Posts: 9926
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Dev already noticed gui animator and likes it, just finds no time adding it so far ;-)
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
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

Post by 3DModelerMan »

Oh okay. I'll make an animator for this too then.
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

3DModelerMan, you have these variables

Code: Select all

private:
 core::rect<s32> m_Rect;
 core::array<video::ITexture*> m_TextureArray; 
Are you supposed to use the CGuiSpriteBank?
Besides that, shouldn't you have a separate rect for each texture?

I don't understand the CGuiSpriteBank.
How do you set these variables (below) in CGuiSpriteBank?

Code: Select all

core::array<SGUISprite> Sprites;
core::array< core::rect<s32> > Rectangles;
Or how do you use them?
Do they hold the texture and source rect for each texture?

Can CGuiSpriteBank be used by 3DModelerMan to implement his animation? I haven't really got time to look into it alone, but I'm interested.
3DModelerMan wrote:Time based animation (need to figure out how to get the frame time from in the GUI element)
SGUISprite has frame time variable.
Or are you talking about getting real time changes?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

Post by 3DModelerMan »

I don't know how to use the sprite bank. But I'll look into it because of the frame time variable. I don't have a seperate rect for each texture yet because I didn't need it at the time I made this and didn't think I ever would. But I guess I should so that I can have different sized animation frames. The only thing I see a problem with there, is that you can't stretch the size of the animation as easily. Which version of Irrlicht are the GUI animators going in?
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

But I guess I should so that I can have different sized animation frames.
Also, so you can have multiple frames on one texture. You don't necessarily need a different texture for each frame. They might all fit on one texture.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

Post by 3DModelerMan »

Good point. I'll implement that as soon as I get a chance. Right now I can't do anything until I've tested this implementation for bugs. I'm working on other parts of my game right now. I'll try to get around to this soon though.
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
swesoulc
Posts: 17
Joined: Tue Apr 03, 2007 10:05 am

old work of mine

Post by swesoulc »

I got something that is exactly like what you are working on, with a handler... it's a modified version of a animator that was posted here, years ago, you can take a look at it, see if it helps.
I made the handler (sprite enviroment ) myself, though that you can make sprites ( 2d animated pictures for gui ) that either loops, plays and disapears automaticley, or as a button. and the images needed are all stored in one file ( original code used separete file for each frame )
this works in irrlicht 1.4 atleast
... and sorry for all the crappy code, havn't looked at this for the last year and a half... more. might needs some optimization


4 files
Anim_Sprite.h
Anim_Sprite.cpp
SpriteEnviroment.h
SpriteEnviroment.cpp
#include <irrlicht.h>
#ifndef __Anim_Sprite_H__
#define __Anim_Sprite_H__

using namespace irr;

//#pragma once;
//!
/*API
//Texture
video::ITexture* image = driver->getTexture("data/anims/newgame/testoptions.jpg");
//Draw area within texture storage
irr::core::array<core::rect<s32>> RectArray ;
//Set up draw areas
RectArray.push_back(core::rect<s32>(0,0, 255,63));
//Create Sprite
Anim_Sprite* Sprite;
Sprite = new Anim_Sprite(device);
Sprite->init();
// if the sprite should be looping - non responsive to input
Sprite->setPlaying(true);
// update after guienv->drawall()
Sprite->update( device->getCursorControl()->getPosition(), device->getTimer()->getTime() );
*/
class Anim_Sprite
{
public:
//! Creator
//! IrrlichtDevice* device : pointer to irr-dev
//! core::position2di position : Sets Default position
//! core::array<core::rect<s32>> RectArray : List of rects
//! video::ITexture* in_image : pointer to file / texture to be used by the animation
//! int in_speed : Sets default speed of animation, higher # = slower
//! bool in_loop : Sets if to be looping animation by default
//! bool in_visible : Sets if to be visible by default
//! bool isAMouseOver : Sets if sprtie is to react to mouseover
Anim_Sprite( IrrlichtDevice* device, core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* in_image ,int in_speed, bool in_loop, bool in_visible, bool isAMouseOver);
~Anim_Sprite() {}

void setFrame(s32 toFrame);
void setSpeed(u32 newSpeed);
void setPlaying(bool truefalse);
void setVisible(bool truefalse);
void setDirection(bool forward);
void setPosition(core::position2di newPos);
void setDeleteDelay(u32 inDeleteDelay){
DeleteDelay = inDeleteDelay;
}
void setID(int in_id){
ID = in_id;
}
void setAnimation(s32 StartFrame,s32 EndFrame);
void toggleDirection();
void togglePlaying();
void toggleVisible();


bool update(core::position2d<s32> MousePos, u32 time);
bool drop();

int getFrame();
int getFrameCount();
bool getDeleteWhenPlayed(){
if( DeleteDelay != 0 )
return true;
else
return false;
}
int getSpeed();
core::position2di getPosition();
bool getDirection();
core::dimension2d<s32> getSize();

bool isFinished(){
return finished;
}
bool isMouseInside(core::position2di mousepos);
bool isPlaying();
bool isVisible();


private:

IrrlichtDevice* dev;
irr::core::array< core::rect<s32> > RectArray_part_to_draw;
video::ITexture* image;
//irr::gui::IGUISpriteBank* tex;

int curFrame;
//! The total amount of frames in RectArray_part_to_draw
int Nr_of_Frames;
//! The Last frame to be played in the Animation
//! Can not be higher then Anim_Sprite->Nr_of_Frames
//! or lower then 0
int Anim_End_Frame;
//! The first frame of the animation to be played
//! Can not be higher then Anim_Sprite->Nr_of_Frames
//! or lower then 0
int Anim_Start_Frame;
int speed;

//! Id to the Sprite
//! Not related to the id of irrlicht objects
int ID;

bool direction;
bool finished;

int DeleteDelay;
bool loop;
bool playing;
bool visible;
bool mouseover;
core::dimension2d<s32> size;
int oldtime;
// core::rect<s32> rect;
core::position2d<s32> pos;

};

#endif
#include <irrlicht.h>
#include "Anim_Sprite.h"

using namespace irr;
Anim_Sprite::Anim_Sprite( IrrlichtDevice* device, core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* in_image ,int in_speed, bool in_loop, bool in_visible, bool isAMouseOver)
{
dev = device;
RectArray_part_to_draw = RectArray;

image = in_image;
image->grab();
Nr_of_Frames = RectArray.size();
Anim_End_Frame = Nr_of_Frames-1;
Anim_Start_Frame = 0;

pos = position;
speed = in_speed;
loop = in_loop;
visible = in_visible;
mouseover = isAMouseOver;

oldtime = 0;
playing = false;
direction = true;
curFrame = 0;
finished = false;
DeleteDelay = 0;

size.Width = ( RectArray[0].UpperLeftCorner.X + RectArray[0].LowerRightCorner.X ) - RectArray[0].UpperLeftCorner.X ;
size.Height = ( RectArray[0].UpperLeftCorner.Y + RectArray[0].LowerRightCorner.Y ) - RectArray[0].UpperLeftCorner.Y ;

}

bool Anim_Sprite::drop()
{
visible = false;
RectArray_part_to_draw.clear();
image->drop();
delete this;
return false;
}

int Anim_Sprite::getFrame()
{
return curFrame;
}

int Anim_Sprite::getSpeed()
{
return speed;
}

bool Anim_Sprite::getDirection()
{
return direction;
}

void Anim_Sprite::setDirection(bool forward)
{
direction = forward;
}

void Anim_Sprite::setSpeed(u32 newSpeed)
{
speed = newSpeed;
}

void Anim_Sprite::setPosition(core::position2di newPos)
{
pos = newPos;
}


void Anim_Sprite::togglePlaying()
{
playing = !playing;
}

void Anim_Sprite::toggleDirection()
{
direction = !direction;
}

core::position2di Anim_Sprite::getPosition()
{
return pos;
}

core::dimension2d<s32> Anim_Sprite::getSize()
{
return size;
}

void Anim_Sprite::toggleVisible()
{
visible = !visible;
}


void Anim_Sprite::setPlaying(bool truefalse)
{
playing = truefalse;
}

void Anim_Sprite::setVisible(bool truefalse)
{
visible = truefalse;
}

s32 Anim_Sprite::getFrameCount()
{
return Nr_of_Frames;
}

bool Anim_Sprite::isPlaying()
{
return playing;
}

void Anim_Sprite::setFrame(irr::s32 toFrame)
{
if(toFrame <= Nr_of_Frames)
{
curFrame = toFrame;
}
}

bool Anim_Sprite::isMouseInside(core::position2di mousepos)
{
bool answer = false;

core::rect<s32> spriteRect;
spriteRect.UpperLeftCorner.X = pos.X;
spriteRect.UpperLeftCorner.Y = pos.Y;
spriteRect.LowerRightCorner.X = pos.X + size.Width;
spriteRect.LowerRightCorner.Y = pos.Y + size.Height;

answer = spriteRect.isPointInside(mousepos);

return answer;
}


void Anim_Sprite::setAnimation(int StartFrame,int EndFrame)
{
Anim_End_Frame = EndFrame;

Anim_Start_Frame = StartFrame;
}

bool Anim_Sprite::isVisible()
{
return visible;
}

bool Anim_Sprite::update(core::position2d<s32> MousePos, u32 time)
{
bool Animation_Ended = false;

if( finished ){
oldtime + DeleteDelay <= time;
Animation_Ended = true;
}

if(oldtime + speed <= time )
{
// Failsafe
if( Anim_End_Frame > Nr_of_Frames )
Anim_End_Frame = Nr_of_Frames-1;

if( Anim_Start_Frame < 0)
Anim_Start_Frame = 0;

if( Anim_Start_Frame > Nr_of_Frames )
Anim_Start_Frame = Nr_of_Frames-1;

if( Anim_End_Frame < 0)
Anim_End_Frame = 0;
//*********************
//*********************

if(mouseover)
{
if(isMouseInside( MousePos ))
{
if(!isPlaying()) { setDirection(true); setPlaying(true); } //if its playing leave it else play it
}
else
{
setDirection(false); setPlaying(true); //if its playing reverse the direction stop it else leave it
}
}
//**********************
//**********************
switch(direction)
{
case true:
{
if(playing) {
curFrame++;
}

if(curFrame >= Anim_End_Frame)
{
if(loop) {
curFrame = Anim_Start_Frame;
}
else {
curFrame = Anim_End_Frame;
playing = false;
finished = true;
}
}
break;
}

case false:
{
if(playing) {
curFrame--;
}
if(curFrame <= 1)
{
if(loop) {
curFrame = Anim_End_Frame;
}
else {
curFrame = Anim_Start_Frame;
playing = false;
}
}
break;
}

}//switch
//**********************
oldtime = time;
//**********************
}
//**********************
if(visible )
{

dev->getVideoDriver()->draw2DImage(
image,
pos,
RectArray_part_to_draw[curFrame],
0,
video::SColor(255,255,255,255),
true);

}
//*********************
return Animation_Ended;
}
#include <irrlicht.h>
#include "Anim_Sprite.h"

#ifndef __SpriteEnviroment_h__
#define __SpriteEnviroment_h__

using namespace irr;
/* video::ITexture* image = driver->getTexture("data/anims/newgame/testoptions.jpg");
//driver->makeColorKeyTexture(image, core::position2d<s32>(0,0));
irr::core::array<core::rect<s32>> RectArray ;
RectArray.push_back(core::rect<s32>(0,0, 255,63));
RectArray.push_back(core::rect<s32>(256,0, 512,63));
RectArray.push_back(core::rect<s32>(0,64, 255,127));
RectArray.push_back(core::rect<s32>(256,64, 512,127));
//************************************

SpriteEnviroment * SpriteEnv = new SpriteEnviroment(device);

SpriteEnv->addSprite(core::position2di(384,100), RectArray,image,33,true,true,true);
SpriteEnv->addSpriteButton(core::position2di(384,164), RectArray,image,33,true);
SpriteEnv->addTMPSprite(core::position2di(384,250), RectArray,image,2000,true,5000);
*/
class SpriteEnviroment
{
public:
SpriteEnviroment(IrrlichtDevice* device){
dev = device;
};
~SpriteEnviroment(){}
//! Anim_Sprite* addSprite
//! Returns pointer to created sprite
Anim_Sprite* addSprite( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool loop, bool visible, bool Playing);
//! Anim_Sprite* addTMPSprite
//! Returns pointer to created sprite
//! Sprite is set to Playing = true by default
//! Returned pointer can be ignored -
//! SpriteEnviroment handles destruction
Anim_Sprite* addTMPSprite( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool visible, u32 DeleteDelay);
//! Anim_Sprite* addSpriteButton
//! Returns pointer to created sprite
//! pointer need to be handled / catched
Anim_Sprite* addSpriteButton( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool visible );

void draw();
void drop(){
// Make sure all Sprites are dropped
if(ButtonArray.size() > 0)
for (int object = 0; object < ButtonArray.size(); object++)
ButtonArray[object]->drop();
if(SpriteArray.size() > 0 )
for (int object = 0; object < SpriteArray.size(); object++)
SpriteArray[object]->drop();
// Clear any leftovers
SpriteArray.clear();
ButtonArray.clear();
}

private:
IrrlichtDevice* dev;
irr::core::array< Anim_Sprite* > ButtonArray;
irr::core::array< Anim_Sprite* > SpriteArray;
};
#endif
#include "SpriteEnviroment.h"
#include <irrlicht.h>


void SpriteEnviroment::draw(){

core::position2d<s32> MousePos =dev->getCursorControl()->getPosition();
u32 time = dev->getTimer()->getTime();

if( SpriteArray.size() != 0 )
{
for( int SpriteToDraw = 0; SpriteToDraw < SpriteArray.size(); SpriteToDraw++)
{
if(SpriteArray[SpriteToDraw]->update(MousePos, time)){
// Sprite has finished
// see if it is to be deleted
if( SpriteArray[SpriteToDraw]->getDeleteWhenPlayed()){
SpriteArray[SpriteToDraw]->drop();
SpriteArray.erase(SpriteToDraw);
SpriteToDraw -= 1;
}
}
}
}

if( ButtonArray.size() != 0 )
{
for( int SpriteToDraw = 0; SpriteToDraw < ButtonArray.size()-1 ; SpriteToDraw++)
{
if(ButtonArray[SpriteToDraw]->update(MousePos, time)){
// Sprite has finished
// see if it is to be deleted
if( ButtonArray[SpriteToDraw]->getDeleteWhenPlayed()){
ButtonArray[SpriteToDraw]->drop();
ButtonArray.erase(SpriteToDraw);
}
}
}
}

}

Anim_Sprite* SpriteEnviroment::addSprite( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool loop, bool visible, bool Playing){

Anim_Sprite* tmp = new Anim_Sprite(dev, position, RectArray, image, speed, loop, visible, false);
tmp->setPlaying(Playing);

SpriteArray.push_back(tmp);

return SpriteArray[ SpriteArray.size() - 1 ];

}

Anim_Sprite* SpriteEnviroment::addTMPSprite( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool visible, u32 DeleteDelay){

Anim_Sprite* tmp = new Anim_Sprite(dev, position, RectArray, image, speed, false, visible, false);
tmp->setPlaying(true);
tmp->setDeleteDelay(DeleteDelay);

SpriteArray.push_back(tmp);

return SpriteArray[ SpriteArray.size() - 1 ];

}

Anim_Sprite* SpriteEnviroment::addSpriteButton( core::position2di position, core::array<core::rect<s32>> RectArray, video::ITexture* image ,int speed, bool visible ){

Anim_Sprite* tmp = new Anim_Sprite(dev, position, RectArray, image, speed, false, true, true);

SpriteArray.push_back(tmp);

return SpriteArray[ SpriteArray.size() - 1 ];
}
swesoulc
Posts: 17
Joined: Tue Apr 03, 2007 10:05 am

Post by swesoulc »

working usage example

//initialise them with the options jpg file :)
//************************************
//************************************
video::ITexture* image = driver->getTexture("data/anims/newgame/testoptions.jpg");
//driver->makeColorKeyTexture(image, core::position2d<s32>(0,0));
irr::core::array<core::rect<s32>> RectArray ;
RectArray.push_back(core::rect<s32>(0,0, 255,63));
RectArray.push_back(core::rect<s32>(256,0, 512,63));
RectArray.push_back(core::rect<s32>(0,64, 255,127));
RectArray.push_back(core::rect<s32>(256,64, 512,127));
//************************************

SpriteEnviroment * SpriteEnv = new SpriteEnviroment(device);

SpriteEnv->addSprite(core::position2di(384,100), RectArray,image,33,true,true,true);
SpriteEnv->addSpriteButton(core::position2di(384,164), RectArray,image,33,true);
SpriteEnv->addTMPSprite(core::position2di(384,250), RectArray,image,2000,true,5000);

Anim_Sprite* cursor = SpriteEnv->addSprite(core::position2di(384,100), RectArray,image,100,true,true,true);


device->getCursorControl()->setVisible(false);


while(device->run())
{
if (device->isWindowActive())
{

driver->beginScene(true, true, video::SColor(255,0,0,0));

smgr->drawAll();
guienv->drawAll();
cursor->setPosition(device->getCursorControl()->getPosition());
SpriteEnv->draw();

driver->endScene();
}
}
3DModelerMan
Posts: 1691
Joined: Sun May 18, 2008 9:42 pm

Post by 3DModelerMan »

Thanks. That's interesting. I'll get back to this once I finish the special purpose terrain node I'm working on for my game.
That would be illogical captain...

My first full game:
http://www.kongregate.com/games/3DModel ... tor#tipjar
Post Reply