summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2006-07-24 00:13:24 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2006-07-24 00:13:24 +0000
commit4789ebb11407eb9402c385f3cc6fa242d91214c2 (patch)
tree6bf5bed52073ae19ef4b5b08e7fe92af603f04d8 /src
parent1b7ff9ad4160fd0ff79d2da658eca8d8c8abf815 (diff)
downloadmana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.gz
mana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.bz2
mana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.xz
mana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.zip
Implemented caching of spritesets, including a lot of cleanups to the new
animation system. Action now refers to the Spriteset directly and AnimatedSprite refers to the current Action directly instead of using the std::map with a std::string constantly. Some methods and parameters are marked as const. The READ_PROP macro was replaced by static methods. Warnings are logged when unnamed actions are defined or when actions refer to undefined imagesets. Code is more tolerant towards missing actions.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/animation.cpp320
-rw-r--r--src/animation.h100
-rw-r--r--src/being.cpp10
-rw-r--r--src/being.h2
-rw-r--r--src/engine.cpp25
-rw-r--r--src/floor_item.cpp3
-rw-r--r--src/gui/equipmentwindow.cpp7
-rw-r--r--src/gui/itemcontainer.cpp7
-rw-r--r--src/gui/playerbox.cpp2
-rw-r--r--src/log.cpp3
-rw-r--r--src/main.cpp21
-rw-r--r--src/resources/mapreader.cpp3
-rw-r--r--src/resources/resourcemanager.cpp74
-rw-r--r--src/resources/resourcemanager.h8
-rw-r--r--src/resources/spriteset.cpp (renamed from src/graphic/spriteset.cpp)9
-rw-r--r--src/resources/spriteset.h (renamed from src/graphic/spriteset.h)11
-rw-r--r--src/tileset.h4
18 files changed, 376 insertions, 239 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c6db2ec6..1bb1d538 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,5 @@
bin_PROGRAMS = tmw
-tmw_SOURCES = graphic/spriteset.cpp \
- graphic/imagerect.h \
- graphic/spriteset.h \
+tmw_SOURCES = graphic/imagerect.h \
gui/browserbox.cpp \
gui/browserbox.h \
gui/buddywindow.cpp \
@@ -177,6 +175,8 @@ tmw_SOURCES = graphic/spriteset.cpp \
resources/sdlimageloader.cpp \
resources/soundeffect.h \
resources/soundeffect.cpp \
+ resources/spriteset.h \
+ resources/spriteset.cpp \
resources/buddylist.h \
resources/buddylist.cpp \
utils/dtor.h \
diff --git a/src/animation.cpp b/src/animation.cpp
index 4dae04c4..313fd25c 100644
--- a/src/animation.cpp
+++ b/src/animation.cpp
@@ -23,21 +23,13 @@
#include "animation.h"
-#include <libxml/tree.h>
+#include <cassert>
#include "log.h"
-#include "graphic/spriteset.h"
-
#include "resources/image.h"
#include "resources/resourcemanager.h"
-
-#define READ_PROP(node, prop, name, target, cast) \
- prop = xmlGetProp(node, BAD_CAST name); \
- if (prop) { \
- target = cast((const char*)prop); \
- xmlFree(prop); \
- }
+#include "resources/spriteset.h"
Animation::Animation():
mTime(0)
@@ -65,7 +57,7 @@ Animation::update(unsigned int time)
}
int
-Animation::getCurrentPhase()
+Animation::getCurrentPhase() const
{
if (mAnimationPhases.empty())
{
@@ -78,7 +70,7 @@ Animation::getCurrentPhase()
}
void
-Animation::addPhase (int image, unsigned int delay, int offsetX, int offsetY)
+Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY)
{
//add new phase to animation list
AnimationPhase newPhase;
@@ -106,10 +98,9 @@ Animation::getLength()
return length;
}
-Action::Action()
- :mImageset("")
+Action::Action():
+ mSpriteset(NULL)
{
- //NOOP
}
Action::~Action()
@@ -121,28 +112,30 @@ Action::~Action()
mAnimations.clear();
}
-Animation *
-Action::getAnimation(std::string direction)
+Animation*
+Action::getAnimation(const std::string& direction) const
{
Animation *animation = NULL;
- AnimationIterator i = mAnimations.find(direction);
+ Animations::const_iterator i = mAnimations.find(direction);
+
+ // When the direction isn't defined, try the default
if (i == mAnimations.end())
{
- //when the direction isn't defined just use another one
- animation = mAnimations["default"];
+ i = mAnimations.find("default");
}
- else
+
+ if (i != mAnimations.end())
{
- animation = mAnimations[direction];
+ animation = i->second;
}
return animation;
}
void
-Action::setAnimation(std::string direction, Animation *animation)
+Action::setAnimation(const std::string& direction, Animation *animation)
{
- //set first direction as default direction
+ // Set first direction as default direction
if (mAnimations.empty())
{
mAnimations["default"] = animation;
@@ -152,18 +145,18 @@ Action::setAnimation(std::string direction, Animation *animation)
}
-AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
- mAction("stand"), mDirection("down"), mLastTime(0), mSpeed(1.0f)
+AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant):
+ mAction(NULL),
+ mDirection("down"),
+ mLastTime(0),
+ mSpeed(1.0f)
{
- int variant_num = 0;
- int variant_offset = 0;
int size;
ResourceManager *resman = ResourceManager::getInstance();
- char *data = (char*)resman->loadFile(
- animationFile.c_str(), size);
+ char *data = (char*)resman->loadFile(animationFile.c_str(), size);
if (!data) {
- logger->error("Animation: Could not find " + animationFile + " !");
+ logger->error("Animation: Could not find " + animationFile + "!");
}
xmlDocPtr doc = xmlParseMemory(data, size);
@@ -182,10 +175,9 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
return;
}
- //get the variant
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "variants", variant_num, atoi);
- READ_PROP(node, prop, "variant_offset", variant_offset, atoi);
+ // Get the variant
+ int variant_num = getProperty(node, "variants", 0);
+ int variant_offset = getProperty(node, "variant_offset", 0);
if (variant_num > 0 && variant < variant_num )
{
@@ -200,16 +192,14 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
{
if (xmlStrEqual(node->name, BAD_CAST "imageset"))
{
- int width = 0, height = 0;
- std::string name = "", imageSrc = "";
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "name", name, );
- READ_PROP(node, prop, "src", imageSrc, );
- READ_PROP(node, prop, "width", width, atoi);
- READ_PROP(node, prop, "height", height, atoi);
-
- Spriteset *spriteset = resman->createSpriteset(
- imageSrc, width, height);
+ int width = getProperty(node, "width", 0);
+ int height = getProperty(node, "height", 0);
+ std::string name = getProperty(node, "name", "");
+ std::string imageSrc = getProperty(node, "src", "");
+
+ Spriteset *spriteset =
+ resman->getSpriteset(imageSrc, width, height);
+
if (!spriteset)
{
logger->error("Couldn't load spriteset!");
@@ -222,59 +212,73 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
// get action
else if (xmlStrEqual(node->name, BAD_CAST "action"))
{
- std::string name = "", imageset = "";
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "name", name, );
- READ_PROP(node, prop, "imageset", imageset, );
+ std::string name = getProperty(node, "name", "");
+ std::string imageset = getProperty(node, "imageset", "");
+
+ if (name.length() == 0)
+ {
+ logger->log("Warning: unnamed action in %s",
+ animationFile.c_str());
+ }
Action *action = new Action();
- mActions[name] = action;
- action->setImageset(imageset);
- //get animations
- for ( xmlNodePtr animationNode = node->xmlChildrenNode;
- animationNode != NULL;
- animationNode = animationNode->next)
+ if (mSpritesets.find(imageset) != mSpritesets.end())
+ {
+ action->setSpriteset(mSpritesets[imageset]);
+ mActions[name] = action;
+ }
+ else
+ {
+ logger->log("Warning: imageset \"%s\" not defined in %s",
+ imageset.c_str(),
+ animationFile.c_str());
+
+ // Discard action and skip loading animations
+ delete action;
+ continue;
+ }
+
+ // get animations
+ for (xmlNodePtr animationNode = node->xmlChildrenNode;
+ animationNode != NULL;
+ animationNode = animationNode->next)
{
if (xmlStrEqual(animationNode->name, BAD_CAST "animation"))
{
- std::string direction = "";
-
+ std::string direction =
+ getProperty(animationNode, "direction", "");
Animation *animation = new Animation();
- READ_PROP(animationNode, prop, "direction", direction, );
- //get animation phases
- for ( xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
- phaseNode != NULL;
- phaseNode = phaseNode->next)
+ // Get animation phases
+ for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
+ phaseNode != NULL;
+ phaseNode = phaseNode->next)
{
- int index = -1;
- int start = 0;
- int end = 0;
- int delay = 0;
- int offsetX = 0;
- int offsetY = 0;
+ int delay = getProperty(phaseNode, "delay", 0);
+
if (xmlStrEqual(phaseNode->name, BAD_CAST "frame"))
{
- READ_PROP(phaseNode, prop, "index", index, atoi);
- READ_PROP(phaseNode, prop, "delay", delay, atoi);
- READ_PROP(phaseNode, prop, "offsetX", offsetX, atoi);
- READ_PROP(phaseNode, prop, "offsetY", offsetY, atoi);
+ int index = getProperty(phaseNode, "index", -1);
+ int offsetX = getProperty(phaseNode, "offsetX", 0);
+ int offsetY = getProperty(phaseNode, "offsetY", 0);
+
offsetY = offsetY - mSpritesets[imageset]->getHeight() + 32;
offsetX = offsetX - mSpritesets[imageset]->getWidth() / 2 + 16;
- animation->addPhase(index + variant_offset, delay, offsetX, offsetY);
+ animation->addPhase(index + variant_offset, delay,
+ offsetX, offsetY);
}
- if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
{
- READ_PROP(phaseNode, prop, "start", start, atoi);
- READ_PROP(phaseNode, prop, "end", end, atoi);
- READ_PROP(phaseNode, prop, "delay", delay, atoi);
- offsetY = 0 - mSpritesets[imageset]->getHeight() + 32;
- offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16;
+ int start = getProperty(phaseNode, "start", 0);
+ int end = getProperty(phaseNode, "end", 0);
+ int offsetY = 0 - mSpritesets[imageset]->getHeight() + 32;
+ int offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16;
while (end >= start)
{
- animation->addPhase(start + variant_offset, delay, offsetX, offsetY);
+ animation->addPhase(start + variant_offset,
+ delay, offsetX, offsetY);
start++;
}
}
@@ -285,8 +289,7 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
} // if "<imageset>" else if "<action>"
} // for node
- //complete missing actions
- substituteAction("stand", "");
+ // Complete missing actions
substituteAction("walk", "stand");
substituteAction("walk", "run");
substituteAction("attack", "stand");
@@ -301,11 +304,44 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
substituteAction("hurt", "stand");
substituteAction("dead", "hurt");
+ // Play the stand animation by default
+ play("stand");
+
xmlFreeDoc(doc);
}
+int
+AnimatedSprite::getProperty(xmlNodePtr node, const char* name, int def)
+{
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop) {
+ int val = atoi((char*)prop);
+ xmlFree(prop);
+ return val;
+ }
+ else {
+ return def;
+ }
+}
+
+std::string
+AnimatedSprite::getProperty(xmlNodePtr node, const char* name,
+ const std::string& def)
+{
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop) {
+ std::string val = (char*)prop;
+ xmlFree(prop);
+ return val;
+ }
+ else {
+ return def;
+ }
+}
+
void
-AnimatedSprite::substituteAction(std::string complete, std::string with)
+AnimatedSprite::substituteAction(const std::string& complete,
+ const std::string& with)
{
if (mActions.find(complete) == mActions.end())
{
@@ -315,104 +351,106 @@ AnimatedSprite::substituteAction(std::string complete, std::string with)
AnimatedSprite::~AnimatedSprite()
{
- for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); i++)
+ for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i)
{
- delete i->second;
+ i->second->decRef();
}
mSpritesets.clear();
}
void
-AnimatedSprite::play(std::string action)
+AnimatedSprite::play(const std::string& action)
{
- if (mAction != action)
+ Actions::iterator iAction;
+ iAction = mActions.find(action);
+
+ if (iAction == mActions.end())
+ {
+ logger->log("Warning: no action \"%s\" defined!", action.c_str());
+ mAction = NULL;
+ return;
+ }
+
+ if (mAction != iAction->second)
{
- mAction = action;
+ mAction = iAction->second;
+ mLastTime = 0;
}
- mLastTime = 0;
+
mSpeed = 1.0f;
}
void
-AnimatedSprite::play(std::string action, int time)
+AnimatedSprite::play(const std::string& action, int time)
{
- if (mAction != action)
+ play(action);
+
+ if (mAction != NULL)
{
- mAction = action;
+ Animation *animation = mAction->getAnimation(mDirection);
+ int animationLength = animation->getLength();
+ mSpeed = (float) animationLength / time;
}
- mLastTime = 0;
- int animationLength = 0;
- Action *nextAction = mActions[mAction];
- Animation *animation = nextAction->getAnimation(mDirection);
- animationLength = animation->getLength();
- mSpeed = (float)animationLength / time;
}
void
AnimatedSprite::update(int time)
{
- // avoid freaking out at first frame or when tick_time overflows
+ // Avoid freaking out at first frame or when tick_time overflows
if (time < mLastTime || mLastTime == 0) mLastTime = time;
- // if not enough time have passed yet, do nothing
+ // If not enough time have passed yet, do nothing
if (time > mLastTime)
{
- Action *action = mActions[mAction];
- Animation *animation = action->getAnimation(mDirection);
- animation->update((unsigned int)((time - mLastTime) * mSpeed));
- mLastTime = time;
+ if (mAction != NULL)
+ {
+ Animation *animation = mAction->getAnimation(mDirection);
+ animation->update((unsigned int)((time - mLastTime) * mSpeed));
+ mLastTime = time;
+ }
}
}
bool
-AnimatedSprite::draw(Graphics * graphics, Sint32 posX, Sint32 posY)
+AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const
{
- Sint32 offsetX, offsetY;
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- Animation *animation = action->getAnimation(mDirection);
-
- if (animation->getCurrentPhase() >= 0)
- {
- Image *image = spriteset->get(animation->getCurrentPhase());
- offsetX = animation->getOffsetX();
- offsetY = animation->getOffsetY();
- return graphics->drawImage(image, posX + offsetX, posY + offsetY);
- }
- else
+ if (mAction != NULL)
{
- return false;
+ Animation *animation = mAction->getAnimation(mDirection);
+
+ if (animation->getCurrentPhase() >= 0)
+ {
+ Spriteset *spriteset = mAction->getSpriteset();
+ Image *image = spriteset->get(animation->getCurrentPhase());
+ Sint32 offsetX = animation->getOffsetX();
+ Sint32 offsetY = animation->getOffsetY();
+ return graphics->drawImage(image, posX + offsetX, posY + offsetY);
+ }
}
+
+ return false;
}
-Image *
-AnimatedSprite::getCurrentFrame()
+int
+AnimatedSprite::getWidth() const
{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- Animation *animation = action->getAnimation(mDirection);
- if (animation->getCurrentPhase() >= 0)
+ if (mAction != NULL)
{
- return spriteset->get(animation->getCurrentPhase());
+ Spriteset *spriteset = mAction->getSpriteset();
+ return spriteset->getWidth();
}
- else
- {
- return NULL;
- }
-}
-int
-AnimatedSprite::getWidth()
-{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- return spriteset->getWidth();
+ return 0;
}
int
-AnimatedSprite::getHeight()
+AnimatedSprite::getHeight() const
{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- return spriteset->getHeight();
+ if (mAction != NULL)
+ {
+ Spriteset *spriteset = mAction->getSpriteset();
+ return spriteset->getHeight();
+ }
+
+ return 0;
}
diff --git a/src/animation.h b/src/animation.h
index 4f7d57a9..c5adb873 100644
--- a/src/animation.h
+++ b/src/animation.h
@@ -28,11 +28,16 @@
#include <map>
#include <string>
+#include <libxml/tree.h>
+
#include "graphics.h"
class Image;
class Spriteset;
+/**
+ * A single frame in an animation, with a delay and an offset.
+ */
struct AnimationPhase
{
int image;
@@ -41,19 +46,26 @@ struct AnimationPhase
int offsetY;
};
+/**
+ * An animation consists of several frames, each with their own delay and
+ * offset.
+ */
class Animation
{
public:
+ /**
+ * Constructor.
+ */
Animation();
void addPhase(int image, unsigned int delay, int offsetX, int offsetY);
void update(unsigned int time);
- int getCurrentPhase();
+ int getCurrentPhase() const;
- int getOffsetX() { return (*iCurrentPhase).offsetX; };
- int getOffsetY() { return (*iCurrentPhase).offsetY; };
+ int getOffsetX() const { return (*iCurrentPhase).offsetX; };
+ int getOffsetY() const { return (*iCurrentPhase).offsetY; };
int getLength();
@@ -63,23 +75,42 @@ class Animation
unsigned int mTime;
};
+/**
+ * An action consists of several animations, one for each direction.
+ */
class Action
{
public:
+ /**
+ * Constructor.
+ */
Action();
+ /**
+ * Destructor.
+ */
~Action();
- void setImageset(std::string imageset) { mImageset = imageset; }
+ /**
+ * Sets the spriteset used by this action.
+ */
+ void
+ setSpriteset(Spriteset *spriteset) { mSpriteset = spriteset; }
- std::string getImageset() { return mImageset; }
+ /**
+ * Returns the spriteset used by this action.
+ */
+ Spriteset*
+ getSpriteset() const { return mSpriteset; }
- void setAnimation(std::string direction, Animation *animation);
+ void
+ setAnimation(const std::string& direction, Animation *animation);
- Animation *getAnimation(std::string direction); // { return mAnimations[direction]; }
+ Animation*
+ getAnimation(const std::string& direction) const;
protected:
- std::string mImageset;
+ Spriteset *mSpriteset;
typedef std::map<std::string, Animation*> Animations;
typedef Animations::iterator AnimationIterator;
Animations mAnimations;
@@ -94,7 +125,7 @@ class AnimatedSprite
/**
* Constructor.
*/
- AnimatedSprite(std::string animationFile, int variant);
+ AnimatedSprite(const std::string& animationFile, int variant);
/**
* Destructor.
@@ -104,12 +135,14 @@ class AnimatedSprite
/**
* Sets a new action using the current direction.
*/
- void play(std::string action);
+ void
+ play(const std::string& action);
/**
* Plays an action in a specified time.
*/
- void play(std::string action, int time);
+ void
+ play(const std::string& action, int time);
/**
* Inform the animation of the passed time so that it can output the
@@ -119,45 +152,66 @@ class AnimatedSprite
/**
* Draw the current animation phase at the coordinates given in screen
- * pixels
- */
- bool draw(Graphics * graphics, Sint32 posX, Sint32 posY);
-
- /**
- * Draw the current animation phase.
+ * pixels.
*/
- Image *getCurrentFrame();
+ bool
+ draw(Graphics* graphics, Sint32 posX, Sint32 posY) const;
/**
* gets the width in pixels of the current animation phase.
*/
- int getWidth();
+ int
+ getWidth() const;
/**
* gets the height in pixels of the current animation phase.
*/
- int getHeight();
+ int
+ getHeight() const;
/**
* Sets the direction.
*/
- void setDirection(std::string direction) { mDirection = direction; }
+ void
+ setDirection(const std::string& direction)
+ {
+ mDirection = direction;
+ }
protected:
/**
* When there are no animations defined for the action "complete", its
* animations become a copy of those of the action "with".
*/
- void substituteAction(std::string complete, std::string with);
+ void
+ substituteAction(const std::string& complete,
+ const std::string& with);
typedef std::map<std::string, Spriteset*> Spritesets;
typedef Spritesets::iterator SpritesetIterator;
Spritesets mSpritesets;
typedef std::map<std::string, Action*> Actions;
Actions mActions;
- std::string mAction, mDirection;
+ Action *mAction;
+ std::string mDirection;
int mLastTime;
float mSpeed;
+
+ private:
+ /**
+ * Gets an integer property from an xmlNodePtr.
+ *
+ * TODO: Same function is present in MapReader. Should probably be
+ * TODO: shared in a static utility class.
+ */
+ static int
+ getProperty(xmlNodePtr node, const char* name, int def);
+
+ /**
+ * Gets a string property from an xmlNodePtr.
+ */
+ static std::string
+ getProperty(xmlNodePtr node, const char* name, const std::string& def);
};
#endif
diff --git a/src/being.cpp b/src/being.cpp
index d34ea43e..437023d4 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -28,7 +28,7 @@
#include "log.h"
#include "map.h"
-#include "graphic/spriteset.h"
+#include "resources/spriteset.h"
#include "gui/gui.h"
@@ -65,9 +65,12 @@ Being::Being(Uint32 id, Uint16 job, Map *map):
Being::~Being()
{
- for (int i =0; i < VECTOREND_SPRITE; i++)
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- delete mSprites[i];
+ if (mSprites[i] != NULL)
+ {
+ delete mSprites[i];
+ }
}
clearPath();
@@ -266,7 +269,6 @@ Being::setDirection(Uint8 direction)
{
if (mSprites[i] != NULL) mSprites[i]->setDirection(dir);
}
-
}
void
diff --git a/src/being.h b/src/being.h
index 6fac98b7..6d2bada6 100644
--- a/src/being.h
+++ b/src/being.h
@@ -371,7 +371,7 @@ class Being : public Sprite
bool mShowSpeech, mShowDamage;
Sint32 mPx, mPy; /**< Pixel coordinates */
- std::vector<AnimatedSprite *>mSprites;
+ std::vector<AnimatedSprite*> mSprites;
};
#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index c5cf5c1a..b1fb9b4b 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -38,8 +38,6 @@
#include "map.h"
#include "sound.h"
-#include "graphic/spriteset.h"
-
#include "gui/gui.h"
#include "gui/minimap.h"
@@ -49,6 +47,7 @@
#include "resources/itemmanager.h"
#include "resources/mapreader.h"
#include "resources/resourcemanager.h"
+#include "resources/spriteset.h"
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -75,12 +74,12 @@ Engine::Engine(Network *network):
// Load the sprite sets
ResourceManager *resman = ResourceManager::getInstance();
- npcset = resman->createSpriteset("graphics/sprites/npcs.png", 50, 80);
- emotionset = resman->createSpriteset("graphics/sprites/emotions.png",
+ npcset = resman->getSpriteset("graphics/sprites/npcs.png", 50, 80);
+ emotionset = resman->getSpriteset("graphics/sprites/emotions.png",
30, 32);
for (int i = 0; i < 2; i++)
{
- Spriteset *tmp = ResourceManager::getInstance()->createSpriteset(
+ Spriteset *tmp = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/weapon" + toString(i) + ".png", 64, 64);
if (!tmp) {
logger->error("Unable to load weaponset");
@@ -88,11 +87,10 @@ Engine::Engine(Network *network):
weaponset.push_back(tmp);
}
}
- itemset = resman->createSpriteset("graphics/sprites/items.png", 32, 32);
+ itemset = resman->getSpriteset("graphics/sprites/items.png", 32, 32);
if (!npcset) logger->error("Unable to load NPC spriteset!");
if (!emotionset) logger->error("Unable to load emotions spriteset!");
- //if (!weaponset) logger->error("Unable to load weapon spriteset!");
if (!itemset) logger->error("Unable to load item spriteset!");
// Initialize item manager
@@ -102,11 +100,16 @@ Engine::Engine(Network *network):
Engine::~Engine()
{
// Delete sprite sets
- delete npcset;
- delete emotionset;
- for_each(weaponset.begin(), weaponset.end(), make_dtor(weaponset));
+ npcset->decRef();
+ emotionset->decRef();
+ itemset->decRef();
+
+ std::vector<Spriteset *>::iterator iter;
+ for (iter = weaponset.begin(); iter != weaponset.end(); ++iter)
+ {
+ (*iter)->decRef();
+ }
weaponset.clear();
- delete itemset;
delete itemDb;
diff --git a/src/floor_item.cpp b/src/floor_item.cpp
index 4573d646..1581b201 100644
--- a/src/floor_item.cpp
+++ b/src/floor_item.cpp
@@ -25,10 +25,9 @@
#include "map.h"
-#include "graphic/spriteset.h"
-
#include "resources/itemmanager.h"
#include "resources/iteminfo.h"
+#include "resources/spriteset.h"
extern Spriteset *itemset;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index fd979beb..bef39dff 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -28,10 +28,9 @@
#include "../item.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/tostring.h"
@@ -42,14 +41,14 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
setDefaultSize(5, 230, 200, 120);
loadWindowState();
- mItemset = ResourceManager::getInstance()->createSpriteset(
+ mItemset = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/items.png", 32, 32);
if (!mItemset) logger->error("Unable to load items.png");
}
EquipmentWindow::~EquipmentWindow()
{
- delete mItemset;
+ mItemset->decRef();
}
void EquipmentWindow::draw(gcn::Graphics *graphics)
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index 9b8dc09b..edcf9764 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -30,11 +30,10 @@
#include "../item.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
#include "../resources/image.h"
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/tostring.h"
@@ -42,7 +41,7 @@ ItemContainer::ItemContainer(Inventory *inventory):
mInventory(inventory)
{
ResourceManager *resman = ResourceManager::getInstance();
- mItemset = resman->createSpriteset("graphics/sprites/items.png", 32, 32);
+ mItemset = resman->getSpriteset("graphics/sprites/items.png", 32, 32);
if (!mItemset) logger->error("Unable to load items.png");
mSelImg = resman->getImage("graphics/gui/selection.png");
@@ -56,7 +55,7 @@ ItemContainer::ItemContainer(Inventory *inventory):
ItemContainer::~ItemContainer()
{
- delete mItemset;
+ mItemset->decRef();
mSelImg->decRef();
}
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index d5c70ffe..f0ed9b71 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -27,10 +27,10 @@
#include "../graphics.h"
#include "../graphic/imagerect.h"
-#include "../graphic/spriteset.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/dtor.h"
diff --git a/src/log.cpp b/src/log.cpp
index d40927c5..3d101d29 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -53,7 +53,8 @@ void Logger::setLogFile(const std::string &logFilename)
void Logger::log(const char *log_text, ...)
{
- if (!mLogFile.is_open()) {
+ if (!mLogFile.is_open())
+ {
return;
}
diff --git a/src/main.cpp b/src/main.cpp
index 5ecb4f35..28debf47 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -56,8 +56,6 @@
#endif
#include "sound.h"
-#include "graphic/spriteset.h"
-
#include "gui/char_server.h"
#include "gui/char_select.h"
#include "gui/connection.h"
@@ -76,6 +74,7 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/spriteset.h"
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -244,17 +243,17 @@ void init_engine()
// Initialize for drawing
graphics->_beginDraw();
- playerset[0] = resman->createSpriteset(
+ playerset[0] = resman->getSpriteset(
"graphics/sprites/player_male_base.png", 64, 64);
if (!playerset[0]) logger->error("Couldn't load male player spriteset!");
- playerset[1] = resman->createSpriteset(
+ playerset[1] = resman->getSpriteset(
"graphics/sprites/player_female_base.png", 64, 64);
if (!playerset[1]) logger->error("Couldn't load female player spriteset!");
for (int i=0; i < NR_HAIR_STYLES; i++)
{
- Spriteset *tmp = ResourceManager::getInstance()->createSpriteset(
+ Spriteset *tmp = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/hairstyle" + toString(i + 1) + ".png",
40, 40);
if (!tmp) {
@@ -288,10 +287,16 @@ void exit_engine()
config.write();
delete gui;
delete graphics;
- for_each(hairset.begin(), hairset.end(), make_dtor(hairset));
+
+ std::vector<Spriteset *>::iterator iter;
+ for (iter = hairset.begin(); iter != hairset.end(); ++iter)
+ {
+ (*iter)->decRef();
+ }
hairset.clear();
- delete playerset[0];
- delete playerset[1];
+
+ playerset[0]->decRef();
+ playerset[1]->decRef();
// Shutdown libxml
xmlCleanupParser();
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 48f23aea..af79480a 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -28,14 +28,13 @@
#include "resourcemanager.h"
#include "image.h"
+#include "spriteset.h"
#include "../base64.h"
#include "../log.h"
#include "../map.h"
#include "../tileset.h"
-#include "../graphic/spriteset.h"
-
const unsigned int DEFAULT_TILE_WIDTH = 32;
const unsigned int DEFAULT_TILE_HEIGHT = 32;
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index a6dc692b..26899d77 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -30,11 +30,10 @@
#include "image.h"
#include "music.h"
#include "soundeffect.h"
+#include "spriteset.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
ResourceManager *ResourceManager::instance = NULL;
@@ -44,25 +43,39 @@ ResourceManager::ResourceManager()
ResourceManager::~ResourceManager()
{
- // Create our resource iterator.
+ // Release any remaining spritesets first because they depend on images
ResourceIterator iter = mResources.begin();
+ while (iter != mResources.end())
+ {
+ if (dynamic_cast<Spriteset*>(iter->second) != NULL)
+ {
+ cleanUp(iter->second);
+ ResourceIterator toErase = iter;
+ ++iter;
+ mResources.erase(toErase);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
- // Iterate through and release references until objects are deleted.
+ // Release remaining resources, logging the number of dangling references.
while (!mResources.empty())
{
- Resource *res = mResources.begin()->second;
- std::string id = res->getIdPath();
- int references = 0;
-
- references += res->mRefCount;
- release(res->mIdPath);
- delete res;
-
- logger->log("ResourceManager::~ResourceManager() cleaned up %d "
- "references to %s", references, id.c_str());
+ cleanUp(mResources.begin()->second);
+ mResources.erase(mResources.begin());
}
}
+void
+ResourceManager::cleanUp(Resource *res)
+{
+ logger->log("ResourceManager::~ResourceManager() cleaning up %d "
+ "references to %s", res->mRefCount, res->mIdPath.c_str());
+ delete res;
+}
+
bool
ResourceManager::setWriteDir(const std::string &path)
{
@@ -151,42 +164,55 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath)
mResources[idPath] = resource;
}
- // Return NULL if the object could not be created.
+ // Returns NULL if the object could not be created.
return resource;
}
Image*
ResourceManager::getImage(const std::string &idPath)
{
- return (Image*)get(IMAGE, idPath);
+ return dynamic_cast<Image*>(get(IMAGE, idPath));
}
Music*
ResourceManager::getMusic(const std::string &idPath)
{
- return (Music*)get(MUSIC, idPath);
+ return dynamic_cast<Music*>(get(MUSIC, idPath));
}
SoundEffect*
ResourceManager::getSoundEffect(const std::string &idPath)
{
- return (SoundEffect*)get(SOUND_EFFECT, idPath);
+ return dynamic_cast<SoundEffect*>(get(SOUND_EFFECT, idPath));
}
-Spriteset* ResourceManager::createSpriteset(const std::string &imagePath,
- int w, int h)
+Spriteset*
+ResourceManager::getSpriteset(const std::string &imagePath, int w, int h)
{
- Image *img;
+ std::stringstream ss;
+ ss << imagePath << "[" << w << "x" << h << "]";
+ const std::string idPath = ss.str();
+
+ ResourceIterator resIter = mResources.find(idPath);
+
+ if (resIter != mResources.end()) {
+ resIter->second->incRef();
+ return dynamic_cast<Spriteset*>(resIter->second);
+ }
+
+ Image *img = getImage(imagePath);
- if (!(img = getImage(imagePath))) {
+ if (!img) {
return NULL;
}
- Spriteset *result = new Spriteset(img, w, h);
+ Spriteset *spriteset = new Spriteset(idPath, img, w, h);
+ spriteset->incRef();
+ mResources[idPath] = spriteset;
img->decRef();
- return result;
+ return spriteset;
}
void
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 8d60ae8c..f254a8b4 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -136,7 +136,7 @@ class ResourceManager
* Creates a spriteset based on the image referenced by the given
* path and the supplied sprite sizes
*/
- Spriteset* createSpriteset(const std::string &imagePath, int w, int h);
+ Spriteset* getSpriteset(const std::string &imagePath, int w, int h);
/**
* Releases a resource, removing it from the set of loaded resources.
@@ -177,6 +177,12 @@ class ResourceManager
deleteInstance();
private:
+ /**
+ * Deletes the resource after logging a cleanup message.
+ */
+ static void
+ cleanUp(Resource *resource);
+
static ResourceManager *instance;
typedef std::map<std::string, Resource*> Resources;
typedef Resources::iterator ResourceIterator;
diff --git a/src/graphic/spriteset.cpp b/src/resources/spriteset.cpp
index 3b190f31..9b09f1e5 100644
--- a/src/graphic/spriteset.cpp
+++ b/src/resources/spriteset.cpp
@@ -25,11 +25,14 @@
#include "../log.h"
-#include "../resources/image.h"
+#include "image.h"
#include "../utils/dtor.h"
-Spriteset::Spriteset(Image *img, int width, int height)
+Spriteset::Spriteset(const std::string& idPath,
+ Image *img,
+ int width, int height):
+ Resource(idPath)
{
for (int y = 0; y + height <= img->getHeight(); y += height)
{
@@ -47,7 +50,7 @@ Spriteset::~Spriteset()
for_each(mSpriteset.begin(), mSpriteset.end(), make_dtor(mSpriteset));
}
-Image *
+Image*
Spriteset::get(size_type i)
{
if (i > mSpriteset.size())
diff --git a/src/graphic/spriteset.h b/src/resources/spriteset.h
index 94ccb742..c51e6a75 100644
--- a/src/graphic/spriteset.h
+++ b/src/resources/spriteset.h
@@ -26,18 +26,21 @@
#include <vector>
+#include "resource.h"
+
class Image;
/**
* Stores a complete set of sprites.
*/
-class Spriteset {
+class Spriteset : public Resource
+{
public:
/*
* Cuts the passed image in a grid of sub images.
*/
- Spriteset(Image *img, int w, int h);
+ Spriteset(const std::string& idPath, Image *img, int w, int h);
/**
* Destructor.
@@ -49,14 +52,14 @@ class Spriteset {
int getHeight() { return mHeight; };
typedef std::vector<Image*>::size_type size_type;
- Image * get(size_type i);
+ Image* get(size_type i);
size_type size() { return mSpriteset.size(); }
private:
// Vector storing the whole spriteset.
std::vector<Image*> mSpriteset;
- //height and width of the images in the spriteset
+ // Height and width of the images in the spriteset
int mHeight;
int mWidth;
};
diff --git a/src/tileset.h b/src/tileset.h
index 5fa4ade1..27bc28c3 100644
--- a/src/tileset.h
+++ b/src/tileset.h
@@ -24,7 +24,7 @@
#ifndef _TMW_TILESET_H_
#define _TMW_TILESET_H_
-#include "graphic/spriteset.h"
+#include "resources/spriteset.h"
/**
* A tileset, which is basically just a spriteset but it stores a firstgid.
@@ -36,7 +36,7 @@ class Tileset : public Spriteset
* Constructor.
*/
Tileset(Image *img, int w, int h, int firstGid):
- Spriteset(img, w, h),
+ Spriteset("", img, w, h),
mFirstGid(firstGid)
{
}