summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-28 08:02:46 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-04-08 20:43:23 +0200
commit14dc8218eeebd1583e6bd3c49013b3e501f47228 (patch)
tree387778ceddd2165ab033c742e5c0eff583a6327a
parentde442e7b15a52729ba37946e74f2799804a77dab (diff)
downloadmana-14dc8218eeebd1583e6bd3c49013b3e501f47228.tar.gz
mana-14dc8218eeebd1583e6bd3c49013b3e501f47228.tar.bz2
mana-14dc8218eeebd1583e6bd3c49013b3e501f47228.tar.xz
mana-14dc8218eeebd1583e6bd3c49013b3e501f47228.zip
Use ResourceRef<Image> in more places
Automatic reference counting of images is now used by Item, Icon, AnimatedSprite, ImageSprite, ParticleEmitter, Minimap, Desktop and Emote. Since ResourceManager::get automatically adds a reference, it needs to be explicitly subtracted when the resource is managed by ResourceRef. This is taken care of by the new ResourceManager::getImageRef. Also removed the apprently unused and duplicate "mDrawImage" from Item (which also didn't get decRef called on it). Fixes cleanup of emote ImageSet and ImageSprite instances, as well as particle images.
-rw-r--r--src/animatedsprite.cpp8
-rw-r--r--src/animatedsprite.h2
-rw-r--r--src/animationparticle.h2
-rw-r--r--src/gui/itempopup.cpp21
-rw-r--r--src/gui/minimap.cpp14
-rw-r--r--src/gui/minimap.h4
-rw-r--r--src/gui/widgets/desktop.cpp13
-rw-r--r--src/gui/widgets/desktop.h4
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp2
-rw-r--r--src/gui/widgets/icon.cpp7
-rw-r--r--src/gui/widgets/icon.h10
-rw-r--r--src/imagesprite.cpp9
-rw-r--r--src/imagesprite.h7
-rw-r--r--src/item.cpp26
-rw-r--r--src/item.h9
-rw-r--r--src/map.cpp5
-rw-r--r--src/particle.cpp8
-rw-r--r--src/particleemitter.cpp13
-rw-r--r--src/particleemitter.h5
-rw-r--r--src/resources/emotedb.cpp39
-rw-r--r--src/resources/emotedb.h7
-rw-r--r--src/resources/mapreader.cpp3
-rw-r--r--src/resources/resource.h23
-rw-r--r--src/resources/resourcemanager.cpp13
-rw-r--r--src/resources/resourcemanager.h9
25 files changed, 127 insertions, 136 deletions
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index 6a5800aa..7aa475d9 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -35,9 +35,6 @@ AnimatedSprite::AnimatedSprite(SpriteDef *sprite):
{
assert(mSprite);
- // Take possession of the sprite
- mSprite->incRef();
-
// Play the stand animation by default
play(SpriteAction::STAND);
}
@@ -53,10 +50,7 @@ AnimatedSprite *AnimatedSprite::load(const std::string &filename, int variant)
return as;
}
-AnimatedSprite::~AnimatedSprite()
-{
- mSprite->decRef();
-}
+AnimatedSprite::~AnimatedSprite() = default;
bool AnimatedSprite::reset()
{
diff --git a/src/animatedsprite.h b/src/animatedsprite.h
index 2c7d589f..05c73ddd 100644
--- a/src/animatedsprite.h
+++ b/src/animatedsprite.h
@@ -87,7 +87,7 @@ class AnimatedSprite final : public Sprite
int mFrameIndex = 0; /**< The index of the current frame. */
int mFrameTime = 0; /**< The time since start of frame. */
- SpriteDef *mSprite; /**< The sprite definition. */
+ ResourceRef<SpriteDef> mSprite; /**< The sprite definition. */
Action *mAction = nullptr; /**< The currently active action. */
Animation *mAnimation = nullptr; /**< The currently active animation. */
Frame *mFrame = nullptr; /**< The currently active frame. */
diff --git a/src/animationparticle.h b/src/animationparticle.h
index 230d4e7d..69b2dbbe 100644
--- a/src/animationparticle.h
+++ b/src/animationparticle.h
@@ -27,8 +27,6 @@
#include <libxml/tree.h>
-#include <memory>
-
class Map;
class AnimationParticle : public ImageParticle
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index f552a570..8208a5d8 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -102,7 +102,7 @@ ItemPopup::ItemPopup():
mItemWeight = new TextBox;
mItemWeight->setEditable(false);
- mIcon = new Icon(nullptr);
+ mIcon = new Icon;
add(mItemName);
add(mItemDesc);
@@ -113,15 +113,7 @@ ItemPopup::ItemPopup():
addMouseListener(this);
}
-ItemPopup::~ItemPopup()
-{
- if (mIcon)
- {
- Image *image = mIcon->getImage();
- if (image)
- image->decRef();
- }
-}
+ItemPopup::~ItemPopup() = default;
void ItemPopup::setEquipmentText(const std::string& text)
{
@@ -158,16 +150,11 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
int space = 0;
- Image *oldImage = mIcon->getImage();
- if (oldImage)
- oldImage->decRef();
-
if (showImage)
{
ResourceManager *resman = ResourceManager::getInstance();
- Image *image = resman->getImage(
- paths.getStringValue("itemIcons")
- + item.getDisplay().image);
+ auto image = resman->getImageRef(paths.getStringValue("itemIcons") +
+ item.getDisplay().image);
mIcon->setImage(image);
if (image)
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index 4a940254..cb38fba6 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -65,16 +65,12 @@ Minimap::Minimap():
Minimap::~Minimap()
{
config.setValue(getWindowName() + "Show", mShow);
-
- if (mMapImage)
- mMapImage->decRef();
}
void Minimap::setMap(Map *map)
{
// Set the title for the Minimap
std::string caption;
- std::string minimapName;
if (map)
caption = map->getName();
@@ -85,11 +81,7 @@ void Minimap::setMap(Map *map)
minimap->setCaption(caption);
// Adapt the image
- if (mMapImage)
- {
- mMapImage->decRef();
- mMapImage = nullptr;
- }
+ mMapImage = nullptr;
if (map)
{
@@ -98,13 +90,13 @@ void Minimap::setMap(Map *map)
"graphics/minimaps/" + map->getFilename() + ".png";
ResourceManager *resman = ResourceManager::getInstance();
- minimapName = map->getProperty("minimap");
+ std::string minimapName = map->getProperty("minimap");
if (minimapName.empty() && resman->exists(tempname))
minimapName = tempname;
if (!minimapName.empty())
- mMapImage = resman->getImage(minimapName);
+ mMapImage = resman->getImageRef(minimapName);
}
if (mMapImage)
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 6eb051ef..6e80a3c1 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -24,6 +24,8 @@
#include "gui/widgets/window.h"
+#include "resources/resource.h"
+
class Image;
class Map;
@@ -59,7 +61,7 @@ class Minimap : public Window
private:
Map *mMap = nullptr;
- Image *mMapImage = nullptr;
+ ResourceRef<Image> mMapImage;
float mWidthProportion = 0.5;
float mHeightProportion = 0.5;
static bool mShow;
diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp
index 474aadb0..ca86360e 100644
--- a/src/gui/widgets/desktop.cpp
+++ b/src/gui/widgets/desktop.cpp
@@ -52,11 +52,7 @@ Desktop::Desktop()
add(mVersionLabel, 25, 2);
}
-Desktop::~Desktop()
-{
- if (mWallpaper)
- mWallpaper->decRef();
-}
+Desktop::~Desktop() = default;
void Desktop::reloadWallpaper()
{
@@ -109,14 +105,11 @@ void Desktop::setBestFittingWallpaper()
return;
ResourceManager *resman = ResourceManager::getInstance();
- Image *wallpaper = resman->getImage(wallpaperName);
+ auto wallpaper = resman->getImageRef(wallpaperName);
if (wallpaper)
{
- if (mWallpaper)
- mWallpaper->decRef(Resource::DeleteImmediately);
-
- mWallpaper = wallpaper;
+ mWallpaper = std::move(wallpaper);
}
else
{
diff --git a/src/gui/widgets/desktop.h b/src/gui/widgets/desktop.h
index 97294423..5909ac72 100644
--- a/src/gui/widgets/desktop.h
+++ b/src/gui/widgets/desktop.h
@@ -26,6 +26,8 @@
#include "gui/widgets/container.h"
+#include "resources/resource.h"
+
#include <guichan/widgetlistener.hpp>
class Image;
@@ -61,7 +63,7 @@ class Desktop : public Container, gcn::WidgetListener
private:
void setBestFittingWallpaper();
- Image *mWallpaper = nullptr;
+ ResourceRef<Image> mWallpaper;
gcn::Label *mVersionLabel;
};
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
index 4df0c4b9..c72d166f 100644
--- a/src/gui/widgets/emoteshortcutcontainer.cpp
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -89,7 +89,7 @@ void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
if (mEmoteMoved != -1)
{
// Draw the emote image being dragged by the cursor.
- const ImageSprite *sprite = EmoteDB::get(mEmoteMoved).sprite;
+ const ImageSprite *sprite = EmoteDB::get(mEmoteMoved).sprite.get();
const int tPosX = mCursorPosX - (sprite->getWidth() / 2);
const int tPosY = mCursorPosY - (sprite->getHeight() / 2);
diff --git a/src/gui/widgets/icon.cpp b/src/gui/widgets/icon.cpp
index 5becadd1..67fd8384 100644
--- a/src/gui/widgets/icon.cpp
+++ b/src/gui/widgets/icon.cpp
@@ -27,14 +27,17 @@
#include "resources/resourcemanager.h"
Icon::Icon(const std::string &file)
- : Icon(ResourceManager::getInstance()->getImage(file))
-{}
+ : Icon(ResourceManager::getInstance()->getImageRef(file))
+{
+}
Icon::Icon(Image *image)
{
setImage(image);
}
+Icon::~Icon() = default;
+
void Icon::setImage(Image *image)
{
mImage = image;
diff --git a/src/gui/widgets/icon.h b/src/gui/widgets/icon.h
index 508d2095..3ebc2c16 100644
--- a/src/gui/widgets/icon.h
+++ b/src/gui/widgets/icon.h
@@ -22,6 +22,8 @@
#ifndef ICON_H
#define ICON_H
+#include "resources/resource.h"
+
#include <guichan/widget.hpp>
class Image;
@@ -39,12 +41,14 @@ class Icon : public gcn::Widget
*
* @param filename The file name of the image to display
*/
- Icon(const std::string &filename);
+ explicit Icon(const std::string &filename);
/**
* Constructor, uses an existing Image.
*/
- Icon(Image *image);
+ explicit Icon(Image *image = nullptr);
+
+ ~Icon() override;
/**
* Gets the current Image.
@@ -62,7 +66,7 @@ class Icon : public gcn::Widget
void draw(gcn::Graphics *g) override;
private:
- Image *mImage = nullptr;
+ ResourceRef<Image> mImage;
};
#endif // ICON_H
diff --git a/src/imagesprite.cpp b/src/imagesprite.cpp
index 74d9bc43..9ef27cd1 100644
--- a/src/imagesprite.cpp
+++ b/src/imagesprite.cpp
@@ -23,17 +23,12 @@
#include "graphics.h"
ImageSprite::ImageSprite(Image *image):
- mImage(image)
+ mImage(image)
{
mAlpha = mImage->getAlpha();
-
- mImage->incRef();
}
-ImageSprite::~ImageSprite()
-{
- mImage->decRef();
-}
+ImageSprite::~ImageSprite() = default;
bool ImageSprite::draw(Graphics *graphics, int posX, int posY) const
{
diff --git a/src/imagesprite.h b/src/imagesprite.h
index 5a04f9ed..4fc69927 100644
--- a/src/imagesprite.h
+++ b/src/imagesprite.h
@@ -60,8 +60,13 @@ public:
int getDuration() const override
{ return 0; }
+ // Hack to allow the ImageSprite to be used with SubImage instances, which
+ // are not reference counted.
+ void releaseImageRef()
+ { mImage.release(); }
+
private:
- Image *mImage;
+ ResourceRef<Image> mImage;
};
#endif // IMAGESPRITE_H
diff --git a/src/item.cpp b/src/item.cpp
index 30536df0..5ce1fea5 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -36,38 +36,24 @@ Item::Item(int id, int quantity, bool equipped):
setId(id);
}
-Item::~Item()
-{
- if (mImage)
- mImage->decRef();
-}
+Item::~Item() = default;
void Item::setId(int id)
{
mId = id;
// Load the associated image
- if (mImage)
- mImage->decRef();
-
- if (mDrawImage)
- mDrawImage->decRef();
-
ResourceManager *resman = ResourceManager::getInstance();
- SpriteDisplay display = getInfo().getDisplay();
- std::string imagePath = paths.getStringValue("itemIcons")
- + display.image;
- mImage = resman->getImage(imagePath);
- mDrawImage = resman->getImage(imagePath);
+ const SpriteDisplay &display = getInfo().getDisplay();
+ mImage = resman->getImage(paths.getStringValue("itemIcons") + display.image);
if (!mImage)
mImage = Theme::getImageFromTheme(paths.getValue("unknownItemFile",
"unknown-item.png"));
- if (!mDrawImage)
- mDrawImage = Theme::getImageFromTheme(
- paths.getValue("unknownItemFile",
- "unknown-item.png"));
+ // Remove the automatic reference added by the ResourceManager
+ if (mImage)
+ mImage->decRef();
}
void Item::doEvent(Event::Type eventName)
diff --git a/src/item.h b/src/item.h
index 2be75164..b5dd1fe2 100644
--- a/src/item.h
+++ b/src/item.h
@@ -25,6 +25,7 @@
#include "event.h"
#include "resources/itemdb.h"
+#include "resources/resource.h"
class Image;
@@ -56,11 +57,6 @@ class Item
Image *getImage() const { return mImage; }
/**
- * Returns the item image.
- */
- Image *getDrawImage() const { return mDrawImage; }
-
- /**
* Sets the number of items.
*/
void setQuantity(int quantity) { mQuantity = quantity; }
@@ -121,8 +117,7 @@ class Item
protected:
int mId; /**< Item type id. */
- Image *mImage = nullptr; /**< Item image. */
- Image *mDrawImage = nullptr; /**< Draw image. */
+ ResourceRef<Image> mImage; /**< Item image. */
int mQuantity; /**< Number of items. */
bool mEquipped; /**< Item is equipped. */
bool mInEquipment = false; /**< Item is in equipment */
diff --git a/src/map.cpp b/src/map.cpp
index 77f9feb8..e9d29b61 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -243,7 +243,7 @@ void Map::initializeAmbientLayers()
auto addAmbientLayer = [=](const std::string &name, std::vector<AmbientLayer> &list)
{
- if (Image *img = resman->getImage(getProperty(name + "image")))
+ if (auto img = resman->getImageRef(getProperty(name + "image")))
{
auto &ambientLayer = list.emplace_back(img);
ambientLayer.mParallax = getFloatProperty(name + "parallax");
@@ -251,9 +251,6 @@ void Map::initializeAmbientLayers()
ambientLayer.mSpeedY = getFloatProperty(name + "scrollY");
ambientLayer.mMask = getIntProperty(name + "mask", 1);
ambientLayer.mKeepRatio = getBoolProperty(name + "keepratio");
-
- // The AmbientLayer takes control over the image.
- img->decRef();
}
};
diff --git a/src/particle.cpp b/src/particle.cpp
index 953e4160..56998df4 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -19,17 +19,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "particle.h"
+
#include "animationparticle.h"
#include "configuration.h"
-#include "resources/dye.h"
#include "imageparticle.h"
#include "log.h"
#include "map.h"
-#include "particle.h"
#include "particleemitter.h"
#include "rotationalparticle.h"
#include "textparticle.h"
+#include "resources/dye.h"
+#include "resources/image.h"
#include "resources/resourcemanager.h"
#include "utils/dtor.h"
@@ -295,8 +297,8 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
std::string imageSrc = (const char*)node->xmlChildrenNode->content;
if (!imageSrc.empty() && !dyePalettes.empty())
Dye::instantiate(imageSrc, dyePalettes);
- Image *img= resman->getImage(imageSrc);
+ auto img = resman->getImageRef(imageSrc);
newParticle = new ImageParticle(mMap, img);
}
// Other
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index 196a43d2..edb892e1 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -41,9 +41,7 @@
ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target,
Map *map, int rotation,
- const std::string& dyePalettes):
- mOutputPauseLeft(0),
- mParticleImage(nullptr)
+ const std::string &dyePalettes)
{
mMap = map;
mParticleTarget = target;
@@ -104,7 +102,7 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target,
Dye::instantiate(image, dyePalettes);
ResourceManager *resman = ResourceManager::getInstance();
- mParticleImage = resman->getImage(image);
+ mParticleImage = resman->getImageRef(image);
}
}
else if (name == "horizontal-angle")
@@ -403,16 +401,11 @@ ParticleEmitter & ParticleEmitter::operator=(const ParticleEmitter &o)
mOutputPauseLeft = 0;
- if (mParticleImage) mParticleImage->incRef();
-
return *this;
}
-ParticleEmitter::~ParticleEmitter()
-{
- if (mParticleImage) mParticleImage->decRef();
-}
+ParticleEmitter::~ParticleEmitter() = default;
template <typename T> ParticleEmitterProp<T>
diff --git a/src/particleemitter.h b/src/particleemitter.h
index 5b139318..512272ff 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -25,6 +25,7 @@
#include "particleemitterprop.h"
#include "resources/animation.h"
+#include "resources/resource.h"
#include "utils/xml.h"
@@ -120,12 +121,12 @@ class ParticleEmitter
ParticleEmitterProp<int> mOutput; /**< Number of particles spawned per update */
ParticleEmitterProp<int> mOutputPause; /**< Pause in frames between two spawns */
- int mOutputPauseLeft;
+ int mOutputPauseLeft = 0;
/*
* Graphical representation of the particles
*/
- Image *mParticleImage; /**< Particle image, if used */
+ ResourceRef<Image> mParticleImage; /**< Particle image, if used */
Animation mParticleAnimation; /**< Filename of particle animation file */
Animation mParticleRotation; /**< Filename of particle rotation file */
ParticleEmitterProp<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
index e1dd8f4a..b0536a0e 100644
--- a/src/resources/emotedb.cpp
+++ b/src/resources/emotedb.cpp
@@ -44,8 +44,8 @@ void EmoteDB::init()
mUnknown.name = "unknown";
mUnknown.effectId = -1;
- mUnknown.sprite = new ImageSprite(
- ResourceManager::getInstance()->getImage("graphics/sprites/error.png"));
+ mUnknown.sprite = std::make_unique<ImageSprite>(
+ ResourceManager::getInstance()->getImageRef("graphics/sprites/error.png"));
}
void EmoteDB::readEmoteNode(xmlNodePtr node, const std::string &filename)
@@ -57,16 +57,16 @@ void EmoteDB::readEmoteNode(xmlNodePtr node, const std::string &filename)
return;
}
- Emote currentEmote;
+ Emote emote;
- currentEmote.id = id;
- currentEmote.name = XML::getProperty(node, "name", "unknown");
- currentEmote.effectId = XML::getProperty(node, "effectid", -1);
+ emote.id = id;
+ emote.name = XML::getProperty(node, "name", "unknown");
+ emote.effectId = XML::getProperty(node, "effectid", -1);
- if (currentEmote.effectId == -1)
+ if (emote.effectId == -1)
{
logger->log("Emote Database: Warning: Emote %s has no attached effect in %s!",
- currentEmote.name.c_str(), filename.c_str());
+ emote.name.c_str(), filename.c_str());
return;
}
@@ -77,25 +77,26 @@ void EmoteDB::readEmoteNode(xmlNodePtr node, const std::string &filename)
if (imageName.empty() || width <= 0 || height <= 0)
{
logger->log("Emote Database: Warning: Emote %s has bad imageset values in %s",
- currentEmote.name.c_str(), filename.c_str());
+ emote.name.c_str(), filename.c_str());
return;
}
- ImageSet *is = ResourceManager::getInstance()->getImageSet(imageName,
- width,
- height);
- if (!is || is->size() == 0)
+ emote.is = ResourceManager::getInstance()->getImageSet(imageName,
+ width,
+ height);
+ emote.is->decRef(); // clear automatic reference
+
+ if (!emote.is || emote.is->size() == 0)
{
logger->log("Emote Database: Error loading imageset for emote %s in %s",
- currentEmote.name.c_str(), filename.c_str());
- delete is;
+ emote.name.c_str(), filename.c_str());
return;
}
// For now we just use the first image in the animation
- currentEmote.sprite = new ImageSprite(is->get(0));
+ emote.sprite = std::make_unique<ImageSprite>(emote.is->get(0));
- mEmotes.push_back(std::move(currentEmote));
+ mEmotes.push_back(std::move(emote));
}
void EmoteDB::checkStatus()
@@ -105,7 +106,9 @@ void EmoteDB::checkStatus()
void EmoteDB::unload()
{
- // todo: don't we need to delete the sprites?
+ for (auto &emote : mEmotes)
+ emote.sprite->releaseImageRef();
+
mEmotes.clear();
mLoaded = false;
}
diff --git a/src/resources/emotedb.h b/src/resources/emotedb.h
index 1ed86a05..a6f93211 100644
--- a/src/resources/emotedb.h
+++ b/src/resources/emotedb.h
@@ -22,10 +22,14 @@
#ifndef EMOTE_DB_H
#define EMOTE_DB_H
+#include <memory>
#include <string>
+#include "resources/resource.h"
+
#include "utils/xml.h"
+class ImageSet;
class ImageSprite;
struct Emote
@@ -33,7 +37,8 @@ struct Emote
int id;
int effectId;
std::string name;
- ImageSprite *sprite;
+ ResourceRef<ImageSet> is;
+ std::unique_ptr<ImageSprite> sprite;
};
/**
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 2136ed58..b49195fc 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -529,13 +529,12 @@ static Tileset *readTileset(xmlNodePtr node, const std::string &path,
std::string sourceStr = resolveRelativePath(pathDir, source);
ResourceManager *resman = ResourceManager::getInstance();
- Image *tilebmp = resman->getImage(sourceStr);
+ auto tilebmp = resman->getImageRef(sourceStr);
if (tilebmp)
{
set = new Tileset(tilebmp, tw, th, firstGid, margin,
spacing);
- tilebmp->decRef();
}
else
{
diff --git a/src/resources/resource.h b/src/resources/resource.h
index 9fe00f3d..e1f37d73 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -120,6 +120,20 @@ public:
return *this;
}
+ // Move assignment operator
+ ResourceRef &operator=(ResourceRef &&other)
+ {
+ if (this != &other)
+ {
+ if (mResource)
+ mResource->decRef();
+
+ mResource = other.mResource;
+ other.mResource = nullptr;
+ }
+ return *this;
+ }
+
// Allow dereferencing
RESOURCE *operator->() const
{ return mResource; }
@@ -131,6 +145,15 @@ public:
operator RESOURCE *() const
{ return mResource; }
+ /**
+ * Releases the resource without decrementing the reference count!
+ *
+ * This is currently necessary to avoid calls to decRef on instances of
+ * SubImage, which are not reference counted resources.
+ */
+ void release()
+ { mResource = nullptr; }
+
private:
RESOURCE *mResource;
};
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index f43aea41..e6600236 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -310,6 +310,13 @@ Image *ResourceManager::getImage(const std::string &idPath)
}));
}
+ResourceRef<Image> ResourceManager::getImageRef(const std::string &idPath)
+{
+ ResourceRef<Image> img = getImage(idPath);
+ img->decRef(); // remove ref added by ResourceManager::get
+ return img;
+}
+
ImageSet *ResourceManager::getImageSet(const std::string &imagePath,
int w, int h)
{
@@ -317,13 +324,11 @@ ImageSet *ResourceManager::getImageSet(const std::string &imagePath,
ss << imagePath << "[" << w << "x" << h << "]";
return static_cast<ImageSet*>(get(ss.str(), [&] () -> Resource * {
- Image *img = getImage(imagePath);
+ auto img = getImageRef(imagePath);
if (!img)
return nullptr;
- auto *res = new ImageSet(img, w, h);
- img->decRef();
- return res;
+ return new ImageSet(img, w, h);
}));
}
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 6694321c..d1c32d8c 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -22,6 +22,8 @@
#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H
+#include "resources/resource.h"
+
#include <ctime>
#include <functional>
#include <map>
@@ -31,7 +33,6 @@
class Image;
class ImageSet;
class Music;
-class Resource;
class SoundEffect;
class SpriteDef;
@@ -144,6 +145,12 @@ class ResourceManager
/**
* Convenience wrapper around ResourceManager::get for loading
+ * images. Returns an automatically reference-counted resource.
+ */
+ ResourceRef<Image> getImageRef(const std::string &idPath);
+
+ /**
+ * Convenience wrapper around ResourceManager::get for loading
* songs.
*/
Music *getMusic(const std::string &idPath);