Advansed GUI on Irrlicht

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
FLUF
Posts: 14
Joined: Fri Jan 12, 2007 11:32 pm
Contact:

Advansed GUI on Irrlicht

Post by FLUF »

I need translate this gui http://flufx.narod.ru/archives/CruelTruck0.04alpha.rar (it's creat on guichan) on irrlicht.
But I find big problem.
I need overload Button class. I need add irrlicht button some new functions... How I can do it??
niko
Site Admin
Posts: 1759
Joined: Fri Aug 22, 2003 4:44 am
Location: Vienna, Austria
Contact:

Post by niko »

The simplest version: Take the source of the Irrlicht button (ICGUIButton.cpp) and derive your own class from it.
Another idea: you can also use external GUI frameworks with Irrlicht if you find the irrlicht GUI too limited. For example CEGUI.
FLUF
Posts: 14
Joined: Fri Jan 12, 2007 11:32 pm
Contact:

Post by FLUF »

Yes, I try use CEGUI, and what I undestend: CEGUI - sux!!! V_V'
No, it not difficult. I creat simple gui on CEGUI+irrlicht and add it on my game. But!!:
If use it's sux on irrlicht, then you have many problem:
1. alpha blending all cegui widgets is not work!
2. all pictures and even font are cutted on the top and left on two picseles!
3. CEGUI not so powerful as it seems! =)
4. I want use mingw32, and CEGUI don't support this compilator =\
5. CEGUI - sux! =)

Hm, ok, I use first metod, what you say. But new I try undestend, what is
void grab() { ++ReferenceCounter; }
=)
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Well, I had a look at the "CruelTruck" demo...
Such a GUI is not really hard to create with Irrlicht (I don't say it's not much work, just it's not really complicated) !!!

You simply set the gui invisible (full transparent) and add bitmaps to each button...
For the animations you'll have to code an bitmap animation player for it...
To change the bitmaps while the mouse moves over the button, you'll have to check if the mouse is over the button inside the event receiver...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

There's actually a bug in CGUIButton.cpp that doesn't properly draw images for buttons. In the draw function in CGUIButton change the function to look like this -

Code: Select all

void CGUIButton::draw()
{
	if (!IsVisible)
		return;

	IGUISkin* skin = Environment->getSkin();
	irr::video::IVideoDriver* driver = Environment->getVideoDriver();

	IGUIFont* font = OverrideFont;
	if (!OverrideFont)
		font = skin->getFont();

	core::rect<s32> rect = AbsoluteRect;
	core::rect<s32> *clip = &AbsoluteClippingRect;
	if (NoClip)
		clip = 0;

	if (!Pressed)
	{
		if (Image)
		{
			core::position2d<s32> pos = AbsoluteRect.getCenter();
			pos.X -= ImageRect.getWidth() / 2;
			pos.Y -= ImageRect.getHeight() / 2;

			driver->draw2DImage(Image, pos, ImageRect, clip, 
				video::SColor(255,255,255,255), UseAlphaChannel);
		}
		else
		{
			skin->draw3DButtonPaneStandard(this, rect, clip);
		}
	}
	else
	{
		if (PressedImage)
		{
			core::position2d<s32> pos = AbsoluteRect.getCenter();
			pos.X -= PressedImageRect.getWidth() / 2;
			pos.Y -= PressedImageRect.getHeight() / 2;
			// patch by Alan Tyndall/Jonas Petersen
			if (Image == PressedImage)
			{
				pos.X += 1;
				pos.Y += 1;
			}
			driver->draw2DImage(PressedImage, pos, PressedImageRect, clip,
				video::SColor(255,255,255,255), UseAlphaChannel);
		}
		else
		{
			skin->draw3DButtonPanePressed(this, rect, clip);
		}
	}

	if (Text.size())
	{
		rect = AbsoluteRect;
        if (Pressed && !PressedImage)
			rect.UpperLeftCorner.Y += 2;

		if (font)
			font->draw(Text.c_str(), rect, skin->getColor(IsEnabled ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), true, true, clip);
	}

	IGUIElement::draw();
}
Oh, and if you want to do animated images in the GUI here's a class for doing do -

CGUIAnimatedImage.h -

Code: Select all

// Copyright (C) 2002-2007 Thomas Ince( Spintz )
// This file is part of the "IrrSpintz Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#ifndef __C_GUI_ANIMATED_IMAGE_H_INCLUDED__
#define __C_GUI_ANIMATED_IMAGE_H_INCLUDED__

#include "IGUIAnimatedImage.h"
#include "vector2d.h"

namespace irr
{
namespace gui
{

	class CGUIAnimatedImage : public IGUIAnimatedImage
	{
	public:

		//! constructor
		CGUIAnimatedImage(core::array<video::STextureAnimation>& textureAnimations, s32 timePerFrame, const video::E_TEXTURE_ANIMATION_MODE& animationMode, f32 rotationPerSecond,
			IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);

		//! destructor
		~CGUIAnimatedImage();

		//! sets all images
		virtual void setImages(core::array<video::STextureAnimation>& textureAnimations);

		//! draws the element and its children
		virtual void draw();

		//! sets if the image should use its alpha channel to draw itself
		virtual void setUseAlphaChannel(bool use);

		//! sets the destination rect for drawing this image
		virtual void setDestinationRect( const core::rect<s32>& r );

	private:

		core::array<video::STextureAnimation> TextureAnimations;
		video::ITexture* CurrentTexture;
		u32 TimePerFrame;
		u32 StartTime;
		u32 EndTime;
		video::E_TEXTURE_ANIMATION_MODE AnimationMode;
		bool UseAlphaChannel;
		f32	RotationPerSecond;
	};


} // end namespace gui
} // end namespace irr

#endif
and CGUIAnimatedImage.cpp -

Code: Select all

// Copyright (C) 2002-2007 Thomas Ince( Spintz )
// This file is part of the "IrrSpintz Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#include "CGUIAnimatedImage.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "os.h"

namespace irr
{
namespace gui
{
	//! constructor
	CGUIAnimatedImage::CGUIAnimatedImage(core::array<video::STextureAnimation>& textureAnimations, s32 timePerFrame, const video::E_TEXTURE_ANIMATION_MODE& animationMode, f32 rotationPerSecond,
		IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
	: IGUIAnimatedImage(environment, parent, id, rectangle)
	, CurrentTexture( NULL )
	, TimePerFrame( timePerFrame )
	, StartTime( 0 )
	, EndTime( 0 )
	, AnimationMode( animationMode )
	, UseAlphaChannel( false )
	, RotationPerSecond( rotationPerSecond )
	{
#ifdef _DEBUG
		setDebugName("CGUIImage");
#endif

		// Grab new textures
		for( u32 i=0; i<textureAnimations.size(); i++ )
		{
			if( textureAnimations[i].Texture )
				textureAnimations[i].Texture->grab();

			TextureAnimations.push_back( textureAnimations[i] );
		}

		CurrentTexture = TextureAnimations[0].Texture;
		StartTime = os::Timer::getTime();
		EndTime = StartTime + TimePerFrame * TextureAnimations.size();
	}

	//! destructor
	CGUIAnimatedImage::~CGUIAnimatedImage()
	{
		// Drop current textures
		for( u32 i=0; i<TextureAnimations.size(); i++ )
			TextureAnimations[i].Texture->drop();
		TextureAnimations.clear();
	}

	//! sets an image
	void CGUIAnimatedImage::setImages(core::array<video::STextureAnimation>& textureAnimations)
	{
		u32 i = 0;

		// Drop current textures
		for( i=0; i<TextureAnimations.size(); i++ )
			TextureAnimations[i].Texture->drop();
		TextureAnimations.clear();

		// Grab new textures
		for( i=0; i<textureAnimations.size(); i++ )
		{
			if( textureAnimations[i].Texture )
				textureAnimations[i].Texture->grab();

			TextureAnimations.push_back( textureAnimations[i] );
		}

		CurrentTexture = TextureAnimations[0].Texture;
		StartTime = os::Timer::getTime();
		EndTime = StartTime + TimePerFrame * TextureAnimations.size();
	}

	//! draws the element and its children
	void CGUIAnimatedImage::draw()
	{
		if( !IsVisible )
			return;

		irr::video::IVideoDriver* driver = Environment->getVideoDriver();

		u32 t = os::Timer::getTime() - StartTime;
		u32 index = 0;
		if( AnimationMode == video::ETAM_PLAY_ONCE )
		{
			if( t >= EndTime )
				index = TextureAnimations.size() - 1;
			else
				index = ( t / TimePerFrame ) % TextureAnimations.size();
		}
		else if( AnimationMode == video::ETAM_REPEAT )
		{
			index = ( t / TimePerFrame ) % TextureAnimations.size();
		}
		else if( AnimationMode == video::ETAM_BACK_AND_FORTH_ONCE )
		{
			if( t >= EndTime * 2 )
			{
				index = 0;
			}
			else
			{
				index = ( t / TimePerFrame ) % ( TextureAnimations.size() * 2 );
				if( index > TextureAnimations.size() - 1 )
					index = ( ( TextureAnimations.size() * 2 ) - 1 ) - index;
			}
		}
		else // AnimationMode == video::ETAM_BACK_AND_FORTH_REPEAT
		{
			index = ( t / TimePerFrame ) % ( TextureAnimations.size() * 2 );
			if( index > TextureAnimations.size() - 1 )
				index = ( ( TextureAnimations.size() * 2 ) - 1 ) - index;
		}

		if( index < TextureAnimations.size() )
		{
			CurrentTexture = TextureAnimations[index].Texture;
		}

		if( CurrentTexture )
		{
			if( RotationPerSecond != 0.0f )
			{
				f32 rotation = ( t * 0.001f ) * RotationPerSecond;
				driver->draw2DImage( CurrentTexture, rotation, AbsoluteRect.UpperLeftCorner, TextureAnimations[index].SourceRect,
					&AbsoluteClippingRect, video::SColor( 255,255,255,255 ), UseAlphaChannel );
			}
			else
			{
				driver->draw2DImage( CurrentTexture, AbsoluteRect.UpperLeftCorner, TextureAnimations[index].SourceRect,
					&AbsoluteClippingRect, video::SColor( 255,255,255,255 ), UseAlphaChannel );
			}
		}
		else
		{
			IGUISkin* skin = Environment->getSkin();
			driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), AbsoluteRect, &AbsoluteClippingRect);
		}

		IGUIElement::draw();
	}

	//! sets if the image should use its alpha channel to draw itself
	void CGUIAnimatedImage::setUseAlphaChannel( bool use )
	{
		UseAlphaChannel = use;
	}

	//! sets the destination rect for drawing this image
	void CGUIAnimatedImage::setDestinationRect( const core::rect<s32>& r )
	{
	}

} // end namespace gui
} // end namespace irr
The classes will need some adaptation, since they are from IrrSpintz, you'll need this enumeration -

Code: Select all

	//! Enumeration for how to play the animation of textures
	enum E_TEXTURE_ANIMATION_MODE
	{
		//! Play the animation one time, first to last
		ETAM_PLAY_ONCE,

		//! Repeat the animation, playing it from frist to last, after last, skip back to first
		ETAM_REPEAT,

		//! Play the animation once, from first to last, and then from last to first
		ETAM_BACK_AND_FORTH_ONCE,

		//! Repeat the animation, from first to last, then last to first
		ETAM_BACK_AND_FORTH_REPEAT
	};
and also this structure definition ( which I defined in IVideoDriver.h )

Code: Select all

	//! Structure defining an entry into the list of texture animations
	//! Maintains a Texture and a rect
	struct STextureAnimation
	{
		STextureAnimation() : Texture( 0 ), SourceRect( 0,0,0,0 ) {}
		STextureAnimation( video::ITexture* texture, const core::rect<s32>& sourceRect )
			: Texture( texture ), SourceRect( sourceRect ) {}
		STextureAnimation( const STextureAnimation& another )
			: Texture( another.Texture ), SourceRect( another.SourceRect ) {}

		video::ITexture*	Texture;
		core::rect<s32>		SourceRect;
	};
I didn't look at the GUI you're trying to make, but based on what Acki said, this should be all you need. If you need anything more, let me know, I've got a TON of other GUI changes in IrrSpintz.
Image
Post Reply