Provide our own version of irrlicht's IGUISpriteBank, since theirs is too limited for our needs

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5346 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2010-05-02 18:08:14 +00:00
parent 0c90c98215
commit c731ae5fc4
5 changed files with 397 additions and 4 deletions

View File

@@ -77,6 +77,8 @@ supertuxkart_SOURCES = \
graphics/water_splash.cpp \
guiengine/CGUIFont.cpp \
guiengine/CGUIFont.h \
guiengine/CGUISpriteBank.cpp \
guiengine/CGUISpriteBank.h \
guiengine/abstract_state_manager.cpp \
guiengine/abstract_state_manager.hpp \
guiengine/engine.cpp \

View File

@@ -0,0 +1,284 @@
// Copyright (C) 2002-2009 Nikolaus Gebhardt, modified by Marianne Gagnon
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "guiengine/CGUISpriteBank.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "ITexture.h"
#include <cassert>
namespace irr
{
namespace gui
{
STKModifiedSpriteBank::STKModifiedSpriteBank(IGUIEnvironment* env) :
Environment(env), Driver(0)
{
m_magic_number = 0xCAFEC001;
#ifdef _DEBUG
setDebugName("STKModifiedSpriteBank");
#endif
m_scale = 1.0f;
if (Environment)
{
Driver = Environment->getVideoDriver();
if (Driver)
Driver->grab();
}
}
STKModifiedSpriteBank::~STKModifiedSpriteBank()
{
// drop textures
for (u32 i=0; i<Textures.size(); ++i)
if (Textures[i])
Textures[i]->drop();
// drop video driver
if (Driver)
Driver->drop();
m_magic_number = 0xDEADBEEF;
}
core::array< core::rect<s32> >& STKModifiedSpriteBank::getPositions()
{
assert( m_magic_number == 0xCAFEC001 );
copy.clear();
//FIXME: terribly unefficient, CGUIListBox will call this once for every item xD
// but I have no choice, short of re-implementing IGUIListBox too
for (int n=0; n<(int)Rectangles.size(); n++)
{
copy.push_back(
core::rect<s32>(Rectangles[n].UpperLeftCorner,
core::dimension2d<s32>(Rectangles[n].getWidth()*m_scale,
Rectangles[n].getHeight()*m_scale) )
);
}
return copy;
}
core::array< SGUISprite >& STKModifiedSpriteBank::getSprites()
{
assert( m_magic_number == 0xCAFEC001 );
return Sprites;
}
u32 STKModifiedSpriteBank::getTextureCount() const
{
assert( m_magic_number == 0xCAFEC001 );
return Textures.size();
}
video::ITexture* STKModifiedSpriteBank::getTexture(u32 index) const
{
assert( m_magic_number == 0xCAFEC001 );
if (index < Textures.size())
return Textures[index];
else
return 0;
}
void STKModifiedSpriteBank::addTexture(video::ITexture* texture)
{
assert( m_magic_number == 0xCAFEC001 );
if (texture)
texture->grab();
Textures.push_back(texture);
}
void STKModifiedSpriteBank::setTexture(u32 index, video::ITexture* texture)
{
assert( m_magic_number == 0xCAFEC001 );
while (index >= Textures.size())
Textures.push_back(0);
if (texture)
texture->grab();
if (Textures[index])
Textures[index]->drop();
Textures[index] = texture;
}
//! clear everything
void STKModifiedSpriteBank::clear()
{
assert( m_magic_number == 0xCAFEC001 );
// drop textures
for (u32 i=0; i<Textures.size(); ++i)
if (Textures[i])
Textures[i]->drop();
Textures.clear();
Sprites.clear();
Rectangles.clear();
}
//! Add the texture and use it for a single non-animated sprite.
s32 STKModifiedSpriteBank::addTextureAsSprite(video::ITexture* texture)
{
assert( m_magic_number == 0xCAFEC001 );
if ( !texture )
return -1;
addTexture(texture);
u32 textureIndex = getTextureCount() - 1;
u32 rectangleIndex = Rectangles.size();
Rectangles.push_back( core::rect<s32>(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().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;
}
//! draws a sprite in 2d with scale and color
void STKModifiedSpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
const core::rect<s32>* clip, const video::SColor& color,
u32 starttime, u32 currenttime, bool loop, bool center)
{
assert( m_magic_number == 0xCAFEC001 );
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
return;
// work out frame number
u32 frame = 0;
if (Sprites[index].frameTime)
{
u32 f = ((currenttime - starttime) / Sprites[index].frameTime);
if (loop)
frame = f % Sprites[index].Frames.size();
else
frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
}
const video::ITexture* tex = Textures[Sprites[index].Frames[frame].textureNumber];
if (!tex)
return;
const u32 rn = Sprites[index].Frames[frame].rectNumber;
if (rn >= Rectangles.size())
return;
const core::rect<s32>& r = Rectangles[rn];
const core::dimension2d<s32>& dim = r.getSize();
core::rect<s32> dest( pos, core::dimension2d<s32>(dim.Width*m_scale, dim.Height*m_scale) );
if (center)
{
dest -= dest.getSize() / 2;
}
/*
draw2DImage (const video::ITexture *texture, const core::rect< s32 > &destRect,
const core::rect< s32 > &sourceRect, const core::rect< s32 > *clipRect=0,
const video::SColor *const colors=0, bool useAlphaChannelOfTexture=false)=0
*/
Driver->draw2DImage(tex, dest, r /* source rect */, clip, NULL /* colors */, true);
}
void STKModifiedSpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
const core::array<core::position2di>& pos,
const core::rect<s32>* clip,
const video::SColor& color,
u32 starttime, u32 currenttime,
bool loop, bool center)
{
assert( m_magic_number == 0xCAFEC001 );
const irr::u32 drawCount = core::min_<u32>(indices.size(), pos.size());
core::array<SDrawBatch> drawBatches(Textures.size());
for(u32 i = 0;i < Textures.size();i++)
{
drawBatches.push_back(SDrawBatch());
drawBatches[i].positions.reallocate(drawCount);
drawBatches[i].sourceRects.reallocate(drawCount);
}
for(u32 i = 0;i < drawCount;i++)
{
const u32 index = indices[i];
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
continue;
// work out frame number
u32 frame = 0;
if (Sprites[index].frameTime)
{
u32 f = ((currenttime - starttime) / Sprites[index].frameTime);
if (loop)
frame = f % Sprites[index].Frames.size();
else
frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
}
const u32 texNum = Sprites[index].Frames[frame].textureNumber;
SDrawBatch& currentBatch = drawBatches[texNum];
const u32 rn = Sprites[index].Frames[frame].rectNumber;
if (rn >= Rectangles.size())
return;
const core::rect<s32>& r = Rectangles[rn];
if (center)
{
core::position2di p = pos[i];
p -= r.getSize() / 2;
currentBatch.positions.push_back(p);
currentBatch.sourceRects.push_back(r);
}
else
{
currentBatch.positions.push_back(pos[i]);
currentBatch.sourceRects.push_back(r);
}
}
for(u32 i = 0;i < drawBatches.size();i++)
{
if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())
Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions,
drawBatches[i].sourceRects, clip, color, true);
}
}
} // namespace gui
} // namespace irr
#endif // _IRR_COMPILE_WITH_GUI_

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2002-2009 Nikolaus Gebhardt, modified by Marianne Gagnon
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_GUI_MODIFIED_SPRITE_BANK_H_INCLUDED__
#define __C_GUI_MODIFIED_SPRITE_BANK_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include <cassert>
#include "IGUISpriteBank.h"
namespace irr
{
namespace video
{
class IVideoDriver;
class ITexture;
}
namespace gui
{
class IGUIEnvironment;
//! Sprite bank interface.
class STKModifiedSpriteBank : public IGUISpriteBank
{
public:
STKModifiedSpriteBank(IGUIEnvironment* env);
virtual ~STKModifiedSpriteBank();
virtual core::array< core::rect<s32> >& getPositions();
virtual core::array< SGUISprite >& getSprites();
virtual u32 getTextureCount() const;
virtual video::ITexture* getTexture(u32 index) const;
virtual void addTexture(video::ITexture* texture);
virtual void setTexture(u32 index, video::ITexture* texture);
//! Add the texture and use it for a single non-animated sprite.
virtual s32 addTextureAsSprite(video::ITexture* texture);
//! clears sprites, rectangles and textures
virtual void clear();
//! Draws a sprite in 2d with position and color
virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false);
//! Draws a sprite batch in 2d using an array of positions and a color
virtual void draw2DSpriteBatch(const core::array<u32>& indices, const core::array<core::position2di>& pos,
const core::rect<s32>* clip=0,
const video::SColor& color= video::SColor(255,255,255,255),
u32 starttime=0, u32 currenttime=0,
bool loop=true, bool center=false);
void setScale(float scale)
{
assert( m_magic_number == 0xCAFEC001 );
m_scale = scale;
}
protected:
// this object was getting access after being freed, I wanna see when/why
unsigned int m_magic_number;
float m_scale;
struct SDrawBatch
{
core::array<core::position2di> positions;
core::array<core::recti> sourceRects;
u32 textureNumber;
};
//FIXME: ugly hack to work around irrLicht limitations, see STKModifiedSpriteBank::getPositions()
// for all the gory details.
core::array< core::rect<s32> > copy;
core::array<SGUISprite> Sprites;
core::array< core::rect<s32> > Rectangles;
core::array<video::ITexture*> Textures;
IGUIEnvironment* Environment;
video::IVideoDriver* Driver;
};
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
#endif // __C_GUI_SPRITE_BANK_H_INCLUDED__

View File

@@ -21,6 +21,8 @@
#include "io/file_manager.hpp"
#include "guiengine/CGUISpriteBank.h"
using namespace GUIEngine;
using namespace irr::core;
using namespace irr::gui;
@@ -46,12 +48,12 @@ void ListWidget::add()
//TODO: allow choosing which icons to use
video::ITexture* icon = irr_driver->getTexture( file_manager->getGUIDir() + "/difficulty_medium.png" );
//FIXME: I have no clue what the parameter to 'addEmptySpriteBank' is for
//FIXME: remember the created bank for future 'add's, since a bank must be created once only
IGUISpriteBank* bank = GUIEngine::getGUIEnv()->addEmptySpriteBank( file_manager->getGUIDir().c_str() );
// TODO: delete the bank when done using, it currently leaks
STKModifiedSpriteBank* bank = new STKModifiedSpriteBank( GUIEngine::getGUIEnv() );
bank->setScale(0.5f);
bank->addTextureAsSprite(icon);
list->setSpriteBank(bank);
list->setItemHeight( icon->getSize().Height );
list->setItemHeight( icon->getSize().Height*0.5f );
}
m_element = list;

View File

@@ -11,6 +11,7 @@
9507E9D10FC1CDCE00BD2B92 /* Ogg.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 9551C7F90FC1B63C00DB481B /* Ogg.framework */; };
9507E9D20FC1CDCE00BD2B92 /* OpenAL.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 9551C7FA0FC1B63C00DB481B /* OpenAL.framework */; };
9507E9DB0FC1CDD500BD2B92 /* Vorbis.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 9551C7FB0FC1B63C00DB481B /* Vorbis.framework */; };
950D448C118DEE3C006CFC41 /* CGUISpriteBank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 950D448A118DEE3C006CFC41 /* CGUISpriteBank.cpp */; };
951B7D19108E52C900BC03AE /* challenges.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 951B7D18108E52C900BC03AE /* challenges.cpp */; };
951BC65E0FFAF290006B5FF1 /* ipo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 951BC65C0FFAF290006B5FF1 /* ipo.cpp */; };
9522F125107948AD0067ECF5 /* main_menu_screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9522F124107948AD0067ECF5 /* main_menu_screen.cpp */; };
@@ -306,6 +307,8 @@
9505575F0F6968A50056E88C /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = "<absolute>"; };
950557640F6968BE0056E88C /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
9507E9B60FC1CCE900BD2B92 /* stk.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = stk.icns; sourceTree = SOURCE_ROOT; };
950D448A118DEE3C006CFC41 /* CGUISpriteBank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGUISpriteBank.cpp; path = ../../guiengine/CGUISpriteBank.cpp; sourceTree = SOURCE_ROOT; };
950D448B118DEE3C006CFC41 /* CGUISpriteBank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGUISpriteBank.h; path = ../../guiengine/CGUISpriteBank.h; sourceTree = SOURCE_ROOT; };
951B7D17108E52C900BC03AE /* challenges.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = challenges.hpp; path = ../../states_screens/challenges.hpp; sourceTree = SOURCE_ROOT; };
951B7D18108E52C900BC03AE /* challenges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = challenges.cpp; path = ../../states_screens/challenges.cpp; sourceTree = SOURCE_ROOT; };
951BC65C0FFAF290006B5FF1 /* ipo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ipo.cpp; path = ../../animations/ipo.cpp; sourceTree = SOURCE_ROOT; };
@@ -1220,6 +1223,8 @@
children = (
953C3CC910CAF3EE0025F78A /* CGUIFont.cpp */,
953C3CCD10CAF4150025F78A /* CGUIFont.h */,
950D448A118DEE3C006CFC41 /* CGUISpriteBank.cpp */,
950D448B118DEE3C006CFC41 /* CGUISpriteBank.h */,
9583319810123B0200C5137E /* abstract_state_manager.cpp */,
9583319710123B0200C5137E /* abstract_state_manager.hpp */,
958330B210122B4A00C5137E /* engine.cpp */,
@@ -2531,6 +2536,7 @@
957ED4801163FF18002AB42C /* ai_base_controller.cpp in Sources */,
958BD770117F6AE90095B483 /* music_manager.cpp in Sources */,
95453ACA11808B8700A155B9 /* emergency_animation.cpp in Sources */,
950D448C118DEE3C006CFC41 /* CGUISpriteBank.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};