summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/actorsprite.cpp8
-rw-r--r--src/actorsprite.h3
-rw-r--r--src/client.cpp2
-rw-r--r--src/flooritem.cpp7
-rw-r--r--src/gui/emotepopup.cpp5
-rw-r--r--src/gui/emotepopup.h3
-rw-r--r--src/gui/equipmentwindow.cpp5
-rw-r--r--src/gui/equipmentwindow.h4
-rw-r--r--src/gui/itempopup.cpp4
-rw-r--r--src/gui/minimap.cpp2
-rw-r--r--src/gui/skilldialog.cpp15
-rw-r--r--src/gui/widgets/avatarlistbox.cpp8
-rw-r--r--src/gui/widgets/avatarlistbox.h5
-rw-r--r--src/gui/widgets/button.cpp68
-rw-r--r--src/gui/widgets/button.h7
-rw-r--r--src/gui/widgets/checkbox.cpp3
-rw-r--r--src/gui/widgets/desktop.cpp2
-rw-r--r--src/gui/widgets/dropdown.cpp14
-rw-r--r--src/gui/widgets/dropdown.h3
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp20
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.h2
-rw-r--r--src/gui/widgets/icon.cpp2
-rw-r--r--src/gui/widgets/itemcontainer.cpp1
-rw-r--r--src/gui/widgets/itemcontainer.h4
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp16
-rw-r--r--src/gui/widgets/playerbox.cpp4
-rw-r--r--src/gui/widgets/progressbar.cpp4
-rw-r--r--src/gui/widgets/progressindicator.cpp9
-rw-r--r--src/gui/widgets/progressindicator.h3
-rw-r--r--src/gui/widgets/radiobutton.cpp24
-rw-r--r--src/gui/widgets/radiobutton.h14
-rw-r--r--src/gui/widgets/resizegrip.cpp4
-rw-r--r--src/gui/widgets/resizegrip.h5
-rw-r--r--src/gui/widgets/scrollarea.cpp29
-rw-r--r--src/gui/widgets/scrollarea.h6
-rw-r--r--src/gui/widgets/shortcutcontainer.cpp6
-rw-r--r--src/gui/widgets/shortcutcontainer.h11
-rw-r--r--src/gui/widgets/slider.cpp8
-rw-r--r--src/gui/widgets/tab.cpp7
-rw-r--r--src/gui/widgets/textfield.cpp4
-rw-r--r--src/imageparticle.cpp11
-rw-r--r--src/imageparticle.h3
-rw-r--r--src/item.cpp6
-rw-r--r--src/map.cpp2
-rw-r--r--src/particle.cpp2
-rw-r--r--src/particleemitter.cpp150
-rw-r--r--src/resources/animation.cpp92
-rw-r--r--src/resources/animation.h10
-rw-r--r--src/resources/emotedb.cpp3
-rw-r--r--src/resources/mapreader.cpp2
-rw-r--r--src/resources/music.cpp2
-rw-r--r--src/resources/music.h6
-rw-r--r--src/resources/resource.h8
-rw-r--r--src/resources/resourcemanager.cpp110
-rw-r--r--src/resources/resourcemanager.h75
-rw-r--r--src/resources/soundeffect.cpp13
-rw-r--r--src/resources/soundeffect.h12
-rw-r--r--src/resources/spritedef.cpp9
-rw-r--r--src/resources/spritedef.h4
-rw-r--r--src/resources/theme.cpp19
-rw-r--r--src/resources/theme.h13
-rw-r--r--src/rotationalparticle.cpp6
-rw-r--r--src/simpleanimation.cpp116
-rw-r--r--src/simpleanimation.h5
-rw-r--r--src/sound.cpp100
-rw-r--r--src/sound.h26
-rw-r--r--src/sprite.cpp8
-rw-r--r--src/text.cpp3
-rw-r--r--src/utils/filesystem.h9
69 files changed, 450 insertions, 726 deletions
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp
index f22fbd2d..28d5bed3 100644
--- a/src/actorsprite.cpp
+++ b/src/actorsprite.cpp
@@ -40,7 +40,7 @@
#define EFFECTS_FILE "effects.xml"
-ImageSet *ActorSprite::targetCursorImages[2][NUM_TC];
+ResourceRef<ImageSet> ActorSprite::targetCursorImages[2][NUM_TC];
SimpleAnimation *ActorSprite::targetCursor[2][NUM_TC];
bool ActorSprite::loaded = false;
@@ -212,8 +212,7 @@ void ActorSprite::cleanupTargetCursors()
for (int type = 0; type < NUM_TCT; type++)
{
delete targetCursor[type][size];
- if (targetCursorImages[type][size])
- targetCursorImages[type][size]->decRef();
+ targetCursorImages[type][size] = nullptr;
}
}
}
@@ -225,8 +224,7 @@ void ActorSprite::loadTargetCursor(const std::string &filename,
assert(size < 3);
ResourceManager *resman = ResourceManager::getInstance();
- ImageSet *currentImageSet = resman->getImageSet(filename, width, height);
-
+ auto currentImageSet = resman->getImageSet(filename, width, height);
if (!currentImageSet)
{
logger->log("Error loading target cursor: %s", filename.c_str());
diff --git a/src/actorsprite.h b/src/actorsprite.h
index 93a4551f..5993e4ea 100644
--- a/src/actorsprite.h
+++ b/src/actorsprite.h
@@ -26,7 +26,6 @@
#include "particle.h"
class SimpleAnimation;
-class StatusEffect;
class ActorSprite : public Actor
{
@@ -140,7 +139,7 @@ private:
int width, int height, int type, int size);
/** Images of the target cursor. */
- static ImageSet *targetCursorImages[NUM_TCT][NUM_TC];
+ static ResourceRef<ImageSet> targetCursorImages[NUM_TCT][NUM_TC];
/** Animated target cursors. */
static SimpleAnimation *targetCursor[NUM_TCT][NUM_TC];
diff --git a/src/client.cpp b/src/client.cpp
index 5c114911..e5178048 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -410,6 +410,8 @@ Client::~Client()
CharDB::unload();
delete itemDb;
+ ActorSprite::unload();
+
// Before config.write() since it writes the shortcuts to the config
delete itemShortcut;
delete emoteShortcut;
diff --git a/src/flooritem.cpp b/src/flooritem.cpp
index 330936ec..9c545560 100644
--- a/src/flooritem.cpp
+++ b/src/flooritem.cpp
@@ -54,12 +54,9 @@ FloorItem::FloorItem(int id,
ResourceManager *resman = ResourceManager::getInstance();
std::string imagePath = paths.getStringValue("itemIcons") + info.display.image;
- mImage = resman->getImageRef(imagePath);
+ mImage = resman->getImage(imagePath);
if (!mImage)
- {
- imagePath = Theme::resolveThemePath(paths.getStringValue("unknownItemFile"));
- mImage = resman->getImageRef(imagePath);
- }
+ mImage = Theme::getImageFromTheme(paths.getStringValue("unknownItemFile"));
}
}
diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp
index a906eb7e..e759ab25 100644
--- a/src/gui/emotepopup.cpp
+++ b/src/gui/emotepopup.cpp
@@ -52,10 +52,7 @@ EmotePopup::EmotePopup()
setVisible(true);
}
-EmotePopup::~EmotePopup()
-{
- mSelectionImage->decRef();
-}
+EmotePopup::~EmotePopup() = default;
void EmotePopup::draw(gcn::Graphics *graphics)
{
diff --git a/src/gui/emotepopup.h b/src/gui/emotepopup.h
index 19336426..c95c5723 100644
--- a/src/gui/emotepopup.h
+++ b/src/gui/emotepopup.h
@@ -23,6 +23,7 @@
#pragma once
#include "gui/widgets/popup.h"
+#include "resources/resource.h"
#include <guichan/mouselistener.hpp>
@@ -103,7 +104,7 @@ class EmotePopup : public Popup
*/
void distributeValueChangedEvent();
- Image *mSelectionImage;
+ ResourceRef<Image> mSelectionImage;
int mSelectedEmoteId = -1;
int mHoveredEmoteIndex = -1;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index e7eeb048..569bcf8b 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -96,10 +96,7 @@ void EquipmentWindow::loadEquipBoxes()
Net::getInventoryHandler()->getBoxBackground(i);
if (!backgroundFile.empty())
- {
- box.backgroundImage =
- Theme::instance()->getImageFromTheme(backgroundFile);
- }
+ box.backgroundImage = Theme::getImageFromTheme(backgroundFile);
}
}
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index a9635279..a5cda4e3 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -28,6 +28,8 @@
#include <guichan/actionlistener.hpp>
+#include <vector>
+
class Inventory;
class Item;
class ItemPopup;
@@ -72,7 +74,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener
{
int posX = 0;
int posY = 0;
- Image *backgroundImage = nullptr;
+ ResourceRef<Image> backgroundImage;
};
std::vector<EquipBox> mBoxes; /**< Equipment boxes. */
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 7f1dec3b..c21f4003 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -153,8 +153,8 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
if (showImage)
{
ResourceManager *resman = ResourceManager::getInstance();
- auto image = resman->getImageRef(paths.getStringValue("itemIcons") +
- item.display.image);
+ auto image = resman->getImage(paths.getStringValue("itemIcons") +
+ item.display.image);
mIcon->setImage(image);
if (image)
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index 41044431..14e2a257 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -91,7 +91,7 @@ void Minimap::setMap(Map *map)
minimapName = tempname;
if (!minimapName.empty())
- mMapImage = resman->getImageRef(minimapName);
+ mMapImage = resman->getImage(minimapName);
}
if (mMapImage)
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index 5b85252d..b830064a 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -61,7 +61,7 @@ struct SkillInfo
{
unsigned short id;
std::string name;
- Image *icon = nullptr;
+ ResourceRef<Image> icon;
bool modifiable;
bool visible;
SkillModel *model = nullptr;
@@ -73,25 +73,16 @@ struct SkillInfo
float progress;
gcn::Color color;
- ~SkillInfo()
- {
- if (icon)
- icon->decRef();
- }
+ ~SkillInfo() = default;
void setIcon(const std::string &iconPath)
{
ResourceManager *res = ResourceManager::getInstance();
if (!iconPath.empty())
- {
icon = res->getImage(iconPath);
- }
if (!icon)
- {
- icon = Theme::getImageFromTheme(
- paths.getStringValue("unknownItemFile"));
- }
+ icon = Theme::getImageFromTheme(paths.getStringValue("unknownItemFile"));
}
void update();
diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp
index ec3327b2..47e29ed0 100644
--- a/src/gui/widgets/avatarlistbox.cpp
+++ b/src/gui/widgets/avatarlistbox.cpp
@@ -33,8 +33,8 @@
#include <guichan/font.hpp>
int AvatarListBox::instances = 0;
-Image *AvatarListBox::onlineIcon = nullptr;
-Image *AvatarListBox::offlineIcon = nullptr;
+ResourceRef<Image> AvatarListBox::onlineIcon;
+ResourceRef<Image> AvatarListBox::offlineIcon;
AvatarListBox::AvatarListBox(AvatarListModel *model):
ListBox(model)
@@ -56,8 +56,8 @@ AvatarListBox::~AvatarListBox()
if (instances == 0)
{
- onlineIcon->decRef();
- offlineIcon->decRef();
+ onlineIcon = nullptr;
+ offlineIcon = nullptr;
}
}
diff --git a/src/gui/widgets/avatarlistbox.h b/src/gui/widgets/avatarlistbox.h
index 638e6223..9b0588ac 100644
--- a/src/gui/widgets/avatarlistbox.h
+++ b/src/gui/widgets/avatarlistbox.h
@@ -23,6 +23,7 @@
#include "avatar.h"
#include "gui/widgets/listbox.h"
+#include "resources/resource.h"
#include <string>
@@ -53,6 +54,6 @@ public:
private:
static int instances;
- static Image *onlineIcon;
- static Image *offlineIcon;
+ static ResourceRef<Image> onlineIcon;
+ static ResourceRef<Image> offlineIcon;
};
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 274f329b..ce7a856f 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -39,7 +39,7 @@ float Button::mAlpha = 1.0;
ImageRect *Button::mButton;
TextPopup *Button::mTextPopup = nullptr;
-enum{
+enum {
BUTTON_STANDARD, // 0
BUTTON_HIGHLIGHTED, // 1
BUTTON_PRESSED, // 2
@@ -80,18 +80,17 @@ Button::Button(const std::string &caption, const std::string &actionEventId,
adjustSize();
}
-bool Button::setButtonIcon(const std::string& iconFile)
+bool Button::setButtonIcon(const std::string &iconFile)
{
// We clean up possible older references.
- if (mButtonIcon)
- removeButtonIcon();
+ removeButtonIcon();
// If nothing relevant was set, we can quit now.
if (iconFile.empty())
return false;
// Load the icon frames.
- Image *btnIcons = Theme::getImageFromTheme(iconFile);
+ auto btnIcons = Theme::getImageFromTheme(iconFile);
if (!btnIcons)
return false;
@@ -101,36 +100,27 @@ bool Button::setButtonIcon(const std::string& iconFile)
if (frameWidth > 0 && frameHeight > 0)
{
- mButtonIcon = new Image*[BUTTON_COUNT];
+ mButtonIcon.resize(BUTTON_COUNT);
+
for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- mButtonIcon[mode] = btnIcons->getSubImage(mode * frameWidth, 0,
- frameWidth, frameHeight);
+ mButtonIcon[mode].reset(
+ btnIcons->getSubImage(mode * frameWidth, 0, frameWidth, frameHeight));
}
adjustSize();
}
- btnIcons->decRef();
- return (mButtonIcon);
+ return !mButtonIcon.empty();
}
-void Button::removeButtonIcon(bool adjustButtonSize)
+void Button::removeButtonIcon()
{
- if (!mButtonIcon)
+ if (mButtonIcon.empty())
return;
- // Delete potential button icons
- for (int mode = 0; mode < BUTTON_COUNT; ++mode)
- {
- delete mButtonIcon[mode];
- mButtonIcon[mode] = nullptr;
- }
- delete[] mButtonIcon;
- mButtonIcon = nullptr;
-
- if (adjustButtonSize)
- adjustSize();
+ mButtonIcon.clear();
+ adjustSize();
}
void Button::init()
@@ -144,7 +134,7 @@ void Button::init()
for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- Image *modeImage = Theme::getImageFromTheme(data[mode].file);
+ auto modeImage = Theme::getImageFromTheme(data[mode].file);
int a = 0;
for (int y = 0; y < 3; y++)
{
@@ -157,7 +147,6 @@ void Button::init()
a++;
}
}
- modeImage->decRef();
}
updateAlpha();
@@ -185,8 +174,6 @@ Button::~Button()
delete mTextPopup;
mTextPopup = nullptr;
}
- // Don' try to readjust the size when it's about to be deleted.
- removeButtonIcon(false);
}
void Button::updateAlpha()
@@ -227,15 +214,12 @@ void Button::draw(gcn::Graphics *graphics)
else
graphics->setColor(Theme::getThemeColor(Theme::BUTTON));
+ Image *icon = mButtonIcon.empty() ? nullptr : mButtonIcon[mode].get();
int textX = 0;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
int btnIconX = 0;
- int btnIconY = getHeight() / 2
- - ((mButtonIcon && mButtonIcon[mode]) ?
- mButtonIcon[mode]->getHeight() / 2 : 0);
-
- int btnIconWidth = (mButtonIcon && mButtonIcon[mode]) ?
- mButtonIcon[mode]->getWidth() : 0;
+ int btnIconY = getHeight() / 2 - (icon ? icon->getHeight() / 2 : 0);
+ int btnIconWidth = icon ? icon->getWidth() : 0;
switch (getAlignment())
{
@@ -243,7 +227,7 @@ void Button::draw(gcn::Graphics *graphics)
if (btnIconWidth)
{
btnIconX = 4;
- textX = btnIconX + mButtonIcon[mode]->getWidth() + 2;
+ textX = btnIconX + icon->getWidth() + 2;
}
else
{
@@ -254,8 +238,8 @@ void Button::draw(gcn::Graphics *graphics)
if (btnIconWidth)
{
btnIconX = getWidth() / 2 - (getFont()->getWidth(mCaption)
- + mButtonIcon[mode]->getWidth() + 2) / 2;
- textX = getWidth() / 2 + mButtonIcon[mode]->getWidth() / 2 + 2;
+ + icon->getWidth() + 2) / 2;
+ textX = getWidth() / 2 + icon->getWidth() / 2 + 2;
}
else
{
@@ -280,8 +264,7 @@ void Button::draw(gcn::Graphics *graphics)
}
if (btnIconWidth)
- static_cast<Graphics*>(graphics)->drawImage(mButtonIcon[mode],
- btnIconX, btnIconY);
+ static_cast<Graphics *>(graphics)->drawImage(icon, btnIconX, btnIconY);
graphics->drawText(getCaption(), textX, textY, getAlignment());
}
@@ -289,14 +272,13 @@ void Button::adjustSize()
{
// Size of the image button.
int iconWidth = 0, iconHeight = 0;
- if (mButtonIcon)
+ if (!mButtonIcon.empty())
{
for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- iconWidth = std::max(iconWidth, mButtonIcon[mode] ?
- mButtonIcon[mode]->getWidth() + 2 : 0);
- iconHeight = std::max(iconHeight, mButtonIcon[mode] ?
- mButtonIcon[mode]->getHeight() : 0);
+ const Image *icon = mButtonIcon[mode].get();
+ iconWidth = std::max(iconWidth, icon->getWidth() + 2);
+ iconHeight = std::max(iconHeight, icon->getHeight());
}
}
diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h
index 0f63c9f4..1502dc43 100644
--- a/src/gui/widgets/button.h
+++ b/src/gui/widgets/button.h
@@ -23,6 +23,9 @@
#include <guichan/widgets/button.hpp>
+#include <memory>
+#include <vector>
+
class ImageRect;
class Image;
class TextPopup;
@@ -88,13 +91,13 @@ class Button : public gcn::Button
private:
void init();
- void removeButtonIcon(bool adjustButtonSize = true);
+ void removeButtonIcon();
static ImageRect* mButton; /**< Button state graphics */
static int mInstances; /**< Number of button instances */
static float mAlpha;
- Image** mButtonIcon = nullptr; /**< Button Icons graphics */
+ std::vector<std::unique_ptr<Image>> mButtonIcon; /**< Button Icons graphics */
/**
* The buttons popup
diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp
index 274855fd..399ffeb4 100644
--- a/src/gui/widgets/checkbox.cpp
+++ b/src/gui/widgets/checkbox.cpp
@@ -41,7 +41,7 @@ CheckBox::CheckBox(const std::string &caption, bool selected):
{
if (instances == 0)
{
- Image *checkBox = Theme::getImageFromTheme("checkbox.png");
+ auto checkBox = Theme::getImageFromTheme("checkbox.png");
checkBoxNormal = checkBox->getSubImage(0, 0, 9, 10);
checkBoxChecked = checkBox->getSubImage(9, 0, 9, 10);
checkBoxDisabled = checkBox->getSubImage(18, 0, 9, 10);
@@ -54,7 +54,6 @@ CheckBox::CheckBox(const std::string &caption, bool selected):
checkBoxDisabledChecked->setAlpha(mAlpha);
checkBoxNormalHi->setAlpha(mAlpha);
checkBoxCheckedHi->setAlpha(mAlpha);
- checkBox->decRef();
}
instances++;
diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp
index c8ded9f5..e424beec 100644
--- a/src/gui/widgets/desktop.cpp
+++ b/src/gui/widgets/desktop.cpp
@@ -105,7 +105,7 @@ void Desktop::setBestFittingWallpaper()
return;
ResourceManager *resman = ResourceManager::getInstance();
- auto wallpaper = resman->getImageRef(wallpaperName);
+ auto wallpaper = resman->getImage(wallpaperName);
if (wallpaper)
{
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index 8811eb8d..2c78a3d7 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -37,7 +37,7 @@
#include <algorithm>
int DropDown::instances = 0;
-Image *DropDown::buttons[2][2];
+ResourceRef<Image> DropDown::buttons[2][2];
ImageRect DropDown::skin;
float DropDown::mAlpha = 1.0;
@@ -65,7 +65,7 @@ DropDown::DropDown(gcn::ListModel *listModel):
buttons[1][1]->setAlpha(mAlpha);
// get the border skin
- Image *boxBorder = Theme::getImageFromTheme("deepbox.png");
+ auto boxBorder = Theme::getImageFromTheme("deepbox.png");
int gridx[4] = {0, 3, 28, 31};
int gridy[4] = {0, 3, 28, 31};
int a = 0;
@@ -84,8 +84,6 @@ DropDown::DropDown(gcn::ListModel *listModel):
}
skin.setAlpha(mAlpha);
-
- boxBorder->decRef();
}
instances++;
@@ -97,10 +95,10 @@ DropDown::~DropDown()
// Free images memory
if (instances == 0)
{
- buttons[0][0]->decRef();
- buttons[0][1]->decRef();
- buttons[1][0]->decRef();
- buttons[1][1]->decRef();
+ buttons[0][0] = nullptr;
+ buttons[0][1] = nullptr;
+ buttons[1][0] = nullptr;
+ buttons[1][1] = nullptr;
std::for_each(skin.grid, skin.grid + 9, dtor<Image*>());
}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
index 9022e196..7c4e6d1d 100644
--- a/src/gui/widgets/dropdown.h
+++ b/src/gui/widgets/dropdown.h
@@ -21,6 +21,7 @@
#pragma once
+#include "resources/resource.h"
#include <guichan/widgets/dropdown.hpp>
class Image;
@@ -81,7 +82,7 @@ class DropDown : public gcn::DropDown
// Add own Images.
static int instances;
- static Image *buttons[2][2];
+ static ResourceRef<Image> buttons[2][2];
static ImageRect skin;
static float mAlpha;
};
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
index 812377e9..7f33538f 100644
--- a/src/gui/widgets/emoteshortcutcontainer.cpp
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -40,26 +40,18 @@ EmoteShortcutContainer::EmoteShortcutContainer()
mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
- mBackgroundImg->setAlpha(config.guiAlpha);
-
mMaxItems = std::min(EmoteDB::getEmoteCount(), MAX_ITEMS);
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
-}
-
-EmoteShortcutContainer::~EmoteShortcutContainer()
-{
- mBackgroundImg->decRef();
+ if (mBackgroundImg)
+ {
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
+ }
}
void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- mBackgroundImg->setAlpha(mAlpha);
- }
+ mBackgroundImg->setAlpha(config.guiAlpha);
auto *g = static_cast<Graphics*>(graphics);
diff --git a/src/gui/widgets/emoteshortcutcontainer.h b/src/gui/widgets/emoteshortcutcontainer.h
index 08133a50..57d5efd2 100644
--- a/src/gui/widgets/emoteshortcutcontainer.h
+++ b/src/gui/widgets/emoteshortcutcontainer.h
@@ -33,8 +33,6 @@ class EmoteShortcutContainer : public ShortcutContainer
public:
EmoteShortcutContainer();
- ~EmoteShortcutContainer() override;
-
/**
* Draws the items.
*/
diff --git a/src/gui/widgets/icon.cpp b/src/gui/widgets/icon.cpp
index 67fd8384..61506a6b 100644
--- a/src/gui/widgets/icon.cpp
+++ b/src/gui/widgets/icon.cpp
@@ -27,7 +27,7 @@
#include "resources/resourcemanager.h"
Icon::Icon(const std::string &file)
- : Icon(ResourceManager::getInstance()->getImageRef(file))
+ : Icon(ResourceManager::getInstance()->getImage(file))
{
}
diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp
index 940c69f4..d1d00677 100644
--- a/src/gui/widgets/itemcontainer.cpp
+++ b/src/gui/widgets/itemcontainer.cpp
@@ -64,7 +64,6 @@ ItemContainer::ItemContainer(Inventory *inventory):
ItemContainer::~ItemContainer()
{
- mSelImg->decRef();
delete mItemPopup;
}
diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h
index 2fb6bb9e..7c972347 100644
--- a/src/gui/widgets/itemcontainer.h
+++ b/src/gui/widgets/itemcontainer.h
@@ -21,6 +21,8 @@
#pragma once
+#include "resources/resource.h"
+
#include <guichan/keylistener.hpp>
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
@@ -177,7 +179,7 @@ class ItemContainer : public gcn::Widget,
Inventory *mInventory;
int mGridColumns = 1;
int mGridRows = 1;
- Image *mSelImg;
+ ResourceRef<Image> mSelImg;
int mSelectedIndex = -1;
int mHighlightedIndex = -1;
int mLastUsedSlot = -1;
diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
index 0b8f0c8c..594ad1ce 100644
--- a/src/gui/widgets/itemshortcutcontainer.cpp
+++ b/src/gui/widgets/itemshortcutcontainer.cpp
@@ -48,25 +48,21 @@ ItemShortcutContainer::ItemShortcutContainer()
mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
mMaxItems = itemShortcut->getItemCount();
- mBackgroundImg->setAlpha(config.guiAlpha);
-
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
+ if (mBackgroundImg)
+ {
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
+ }
}
ItemShortcutContainer::~ItemShortcutContainer()
{
- mBackgroundImg->decRef();
delete mItemPopup;
}
void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- mBackgroundImg->setAlpha(mAlpha);
- }
+ mBackgroundImg->setAlpha(config.guiAlpha);
auto *g = static_cast<Graphics*>(graphics);
diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp
index 3bdd6bd1..9858727d 100644
--- a/src/gui/widgets/playerbox.cpp
+++ b/src/gui/widgets/playerbox.cpp
@@ -42,7 +42,7 @@ PlayerBox::PlayerBox(const Being *being):
if (instances == 0)
{
// Load the background skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
+ auto textbox = Theme::getImageFromTheme("deepbox.png");
int bggridx[4] = {0, 3, 28, 31};
int bggridy[4] = {0, 3, 28, 31};
int a = 0;
@@ -60,8 +60,6 @@ PlayerBox::PlayerBox(const Being *being):
}
background.setAlpha(config.guiAlpha);
-
- textbox->decRef();
}
instances++;
diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp
index 9d41d1af..ec9690ab 100644
--- a/src/gui/widgets/progressbar.cpp
+++ b/src/gui/widgets/progressbar.cpp
@@ -56,7 +56,7 @@ ProgressBar::ProgressBar(float progress,
if (mInstances == 0)
{
- Image *dBorders = Theme::getImageFromTheme("vscroll_grey.png");
+ auto dBorders = Theme::getImageFromTheme("vscroll_grey.png");
mBorder.grid[0] = dBorders->getSubImage(0, 0, 4, 4);
mBorder.grid[1] = dBorders->getSubImage(4, 0, 3, 4);
mBorder.grid[2] = dBorders->getSubImage(7, 0, 4, 4);
@@ -68,8 +68,6 @@ ProgressBar::ProgressBar(float progress,
mBorder.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
mBorder.setAlpha(mAlpha);
-
- dBorders->decRef();
}
mInstances++;
diff --git a/src/gui/widgets/progressindicator.cpp b/src/gui/widgets/progressindicator.cpp
index 496bd8a1..a103c8b4 100644
--- a/src/gui/widgets/progressindicator.cpp
+++ b/src/gui/widgets/progressindicator.cpp
@@ -24,7 +24,6 @@
#include "simpleanimation.h"
#include "resources/animation.h"
-#include "resources/imageset.h"
#include "resources/resourcemanager.h"
#include "resources/theme.h"
@@ -32,12 +31,12 @@
ProgressIndicator::ProgressIndicator()
{
- ImageSet *images = Theme::getImageSetFromTheme("progress-indicator.png",
- 32, 32);
+ const std::string path = Theme::resolveThemePath("progress-indicator.png");
+ mImageSet = ResourceManager::getInstance()->getImageSet(path, 32, 32);
Animation anim;
- for (size_t i = 0; i < images->size(); ++i)
- anim.addFrame(images->get(i), 100, 0, 0);
+ for (size_t i = 0; i < mImageSet->size(); ++i)
+ anim.addFrame(mImageSet->get(i), 100, 0, 0);
mIndicator = std::make_unique<SimpleAnimation>(std::move(anim));
diff --git a/src/gui/widgets/progressindicator.h b/src/gui/widgets/progressindicator.h
index cb66a887..4a6ea339 100644
--- a/src/gui/widgets/progressindicator.h
+++ b/src/gui/widgets/progressindicator.h
@@ -20,6 +20,8 @@
#pragma once
+#include "resources/imageset.h"
+
#include <guichan/widget.hpp>
#include <memory>
@@ -41,4 +43,5 @@ public:
private:
std::unique_ptr<SimpleAnimation> mIndicator;
+ ResourceRef<ImageSet> mImageSet;
};
diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp
index 92cdacd1..9fcc34fa 100644
--- a/src/gui/widgets/radiobutton.cpp
+++ b/src/gui/widgets/radiobutton.cpp
@@ -29,12 +29,12 @@
int RadioButton::instances = 0;
float RadioButton::mAlpha = 1.0;
-Image *RadioButton::radioNormal;
-Image *RadioButton::radioChecked;
-Image *RadioButton::radioDisabled;
-Image *RadioButton::radioDisabledChecked;
-Image *RadioButton::radioNormalHi;
-Image *RadioButton::radioCheckedHi;
+ResourceRef<Image> RadioButton::radioNormal;
+ResourceRef<Image> RadioButton::radioChecked;
+ResourceRef<Image> RadioButton::radioDisabled;
+ResourceRef<Image> RadioButton::radioDisabledChecked;
+ResourceRef<Image> RadioButton::radioNormalHi;
+ResourceRef<Image> RadioButton::radioCheckedHi;
RadioButton::RadioButton(const std::string &caption, const std::string &group,
bool marked):
@@ -65,12 +65,12 @@ RadioButton::~RadioButton()
if (instances == 0)
{
- radioNormal->decRef();
- radioChecked->decRef();
- radioDisabled->decRef();
- radioDisabledChecked->decRef();
- radioNormalHi->decRef();
- radioCheckedHi->decRef();
+ radioNormal = nullptr;
+ radioChecked = nullptr;
+ radioDisabled = nullptr;
+ radioDisabledChecked = nullptr;
+ radioNormalHi = nullptr;
+ radioCheckedHi = nullptr;
}
}
diff --git a/src/gui/widgets/radiobutton.h b/src/gui/widgets/radiobutton.h
index b8026e56..4f6b5a49 100644
--- a/src/gui/widgets/radiobutton.h
+++ b/src/gui/widgets/radiobutton.h
@@ -21,6 +21,8 @@
#pragma once
+#include "resources/resource.h"
+
#include <guichan/widgets/radiobutton.hpp>
class Image;
@@ -61,10 +63,10 @@ class RadioButton : public gcn::RadioButton
static int instances;
static float mAlpha;
bool mHasMouse = false;
- static Image *radioNormal;
- static Image *radioChecked;
- static Image *radioDisabled;
- static Image *radioDisabledChecked;
- static Image *radioNormalHi;
- static Image *radioCheckedHi;
+ static ResourceRef<Image> radioNormal;
+ static ResourceRef<Image> radioChecked;
+ static ResourceRef<Image> radioDisabled;
+ static ResourceRef<Image> radioDisabledChecked;
+ static ResourceRef<Image> radioNormalHi;
+ static ResourceRef<Image> radioCheckedHi;
};
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index dd29a977..b7d2ec16 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -29,7 +29,7 @@
#include <guichan/graphics.hpp>
-Image *ResizeGrip::gripImage = nullptr;
+ResourceRef<Image> ResizeGrip::gripImage;
int ResizeGrip::mInstances = 0;
float ResizeGrip::mAlpha = 1.0;
@@ -53,7 +53,7 @@ ResizeGrip::~ResizeGrip()
mInstances--;
if (mInstances == 0)
- gripImage->decRef();
+ gripImage = nullptr;
}
void ResizeGrip::draw(gcn::Graphics *graphics)
diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h
index 7d496950..5638eff4 100644
--- a/src/gui/widgets/resizegrip.h
+++ b/src/gui/widgets/resizegrip.h
@@ -21,6 +21,8 @@
#pragma once
+#include "resources/resource.h"
+
#include <guichan/widget.hpp>
class Image;
@@ -36,7 +38,6 @@ class ResizeGrip : public gcn::Widget
{
public:
ResizeGrip(const std::string &image = "resize.png");
-
~ResizeGrip() override;
/**
@@ -45,7 +46,7 @@ class ResizeGrip : public gcn::Widget
void draw(gcn::Graphics *graphics) override;
private:
- static Image *gripImage; /**< Resize grip image */
+ static ResourceRef<Image> gripImage; /**< Resize grip image */
static int mInstances; /**< Number of resize grip instances */
static float mAlpha;
};
diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp
index 225a231d..44065580 100644
--- a/src/gui/widgets/scrollarea.cpp
+++ b/src/gui/widgets/scrollarea.cpp
@@ -34,7 +34,7 @@ float ScrollArea::mAlpha = 1.0;
ImageRect ScrollArea::background;
ImageRect ScrollArea::vMarker;
ImageRect ScrollArea::vMarkerHi;
-Image *ScrollArea::buttons[4][2];
+ResourceRef<Image> ScrollArea::buttons[4][2];
ScrollArea::ScrollArea()
{
@@ -60,14 +60,14 @@ ScrollArea::~ScrollArea()
std::for_each(vMarker.grid, vMarker.grid + 9, dtor<Image*>());
std::for_each(vMarkerHi.grid, vMarkerHi.grid + 9, dtor<Image*>());
- buttons[UP][0]->decRef();
- buttons[UP][1]->decRef();
- buttons[DOWN][0]->decRef();
- buttons[DOWN][1]->decRef();
- buttons[LEFT][0]->decRef();
- buttons[LEFT][1]->decRef();
- buttons[RIGHT][0]->decRef();
- buttons[RIGHT][1]->decRef();
+ buttons[UP][0] = nullptr;
+ buttons[UP][1] = nullptr;
+ buttons[DOWN][0] = nullptr;
+ buttons[DOWN][1] = nullptr;
+ buttons[LEFT][0] = nullptr;
+ buttons[LEFT][1] = nullptr;
+ buttons[RIGHT][0] = nullptr;
+ buttons[RIGHT][1] = nullptr;
}
}
@@ -84,7 +84,7 @@ void ScrollArea::init()
if (instances == 0)
{
// Load the background skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
+ auto textbox = Theme::getImageFromTheme("deepbox.png");
const int bggridx[4] = {0, 3, 28, 31};
const int bggridy[4] = {0, 3, 28, 31};
int a = 0;
@@ -102,11 +102,9 @@ void ScrollArea::init()
}
background.setAlpha(config.guiAlpha);
- textbox->decRef();
-
// Load vertical scrollbar skin
- Image *vscroll = Theme::getImageFromTheme("vscroll_grey.png");
- Image *vscrollHi = Theme::getImageFromTheme("vscroll_highlight.png");
+ auto vscroll = Theme::getImageFromTheme("vscroll_grey.png");
+ auto vscrollHi = Theme::getImageFromTheme("vscroll_highlight.png");
int vsgridx[4] = {0, 4, 7, 11};
int vsgridy[4] = {0, 4, 15, 19};
@@ -131,9 +129,6 @@ void ScrollArea::init()
vMarker.setAlpha(config.guiAlpha);
vMarkerHi.setAlpha(config.guiAlpha);
- vscroll->decRef();
- vscrollHi->decRef();
-
buttons[UP][0] =
Theme::getImageFromTheme("vscroll_up_default.png");
buttons[DOWN][0] =
diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h
index ef20610b..faec0e8f 100644
--- a/src/gui/widgets/scrollarea.h
+++ b/src/gui/widgets/scrollarea.h
@@ -21,8 +21,10 @@
#pragma once
-#include <guichan/widgets/scrollarea.hpp>
+#include "resources/resource.h"
+
#include <guichan/widgetlistener.hpp>
+#include <guichan/widgets/scrollarea.hpp>
class Image;
class ImageRect;
@@ -133,7 +135,7 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
static ImageRect background;
static ImageRect vMarker;
static ImageRect vMarkerHi;
- static Image *buttons[4][2];
+ static ResourceRef<Image> buttons[4][2];
int mX = 0;
int mY = 0;
diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp
index 5925752e..4bcf3860 100644
--- a/src/gui/widgets/shortcutcontainer.cpp
+++ b/src/gui/widgets/shortcutcontainer.cpp
@@ -21,11 +21,7 @@
#include "gui/widgets/shortcutcontainer.h"
-float ShortcutContainer::mAlpha = 1.0;
-
-ShortcutContainer::ShortcutContainer()
-{
-}
+ShortcutContainer::~ShortcutContainer() = default;
void ShortcutContainer::widgetResized(const gcn::Event &event)
{
diff --git a/src/gui/widgets/shortcutcontainer.h b/src/gui/widgets/shortcutcontainer.h
index dd88bded..9998e188 100644
--- a/src/gui/widgets/shortcutcontainer.h
+++ b/src/gui/widgets/shortcutcontainer.h
@@ -21,12 +21,12 @@
#pragma once
+#include "resources/image.h"
+
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
-class Image;
-
/**
* A generic shortcut container.
*
@@ -37,7 +37,8 @@ class ShortcutContainer : public gcn::Widget,
public gcn::MouseListener
{
public:
- ShortcutContainer();
+ ShortcutContainer() = default;
+ ~ShortcutContainer();
/**
* Draws the shortcuts
@@ -69,9 +70,7 @@ class ShortcutContainer : public gcn::Widget,
*/
int getIndexFromGrid(int pointX, int pointY) const;
- Image *mBackgroundImg;
-
- static float mAlpha;
+ ResourceRef<Image> mBackgroundImg;
int mMaxItems = 0;
int mBoxWidth = 0;
diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp
index a7ba37e8..f0b61667 100644
--- a/src/gui/widgets/slider.cpp
+++ b/src/gui/widgets/slider.cpp
@@ -79,8 +79,8 @@ void Slider::init()
// Load resources
if (mInstances == 0)
{
- Image *slider = Theme::getImageFromTheme("slider.png");
- Image *sliderHi = Theme::getImageFromTheme("slider_hilight.png");
+ auto slider = Theme::getImageFromTheme("slider.png");
+ auto sliderHi = Theme::getImageFromTheme("slider_hilight.png");
x = 0; y = 0;
w = 15; h = 6;
@@ -111,9 +111,6 @@ void Slider::init()
w = 9; h = 10;
vGrip = slider->getSubImage(x, y, w, h);
vGripHi = sliderHi->getSubImage(x, y, w, h);
-
- slider->decRef();
- sliderHi->decRef();
}
mInstances++;
@@ -205,4 +202,3 @@ void Slider::mouseExited(gcn::MouseEvent& event)
{
mHasMouse = false;
}
-
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index 64f49eac..d20e7993 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -88,17 +88,15 @@ void Tab::init()
if (mInstances == 0)
{
// Load the skin
- Image *tab[TAB_COUNT];
-
for (int mode = 0; mode < TAB_COUNT; mode++)
{
- tab[mode] = Theme::getImageFromTheme(data[mode].file);
+ auto tabImage = Theme::getImageFromTheme(data[mode].file);
int a = 0;
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 3; x++)
{
- tabImg[mode].grid[a] = tab[mode]->getSubImage(
+ tabImg[mode].grid[a] = tabImage->getSubImage(
data[mode].gridX[x], data[mode].gridY[y],
data[mode].gridX[x + 1] - data[mode].gridX[x] + 1,
data[mode].gridY[y + 1] - data[mode].gridY[y] + 1);
@@ -106,7 +104,6 @@ void Tab::init()
}
}
tabImg[mode].setAlpha(mAlpha);
- tab[mode]->decRef();
}
}
mInstances++;
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index dd0adecd..be75a96f 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -53,7 +53,7 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab):
if (instances == 0)
{
// Load the skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
+ auto textbox = Theme::getImageFromTheme("deepbox.png");
int gridx[4] = {0, 3, 28, 31};
int gridy[4] = {0, 3, 28, 31};
int a = 0;
@@ -70,8 +70,6 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab):
}
}
skin.setAlpha(config.guiAlpha);
-
- textbox->decRef();
}
instances++;
diff --git a/src/imageparticle.cpp b/src/imageparticle.cpp
index 9cde91d0..86f955c0 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -27,17 +27,12 @@
ImageParticle::ImageParticle(Map *map, Image *image):
Particle(map),
- mImage(image)
+ mImageRef(image)
{
- if (mImage)
- mImage->incRef();
+ mImage = mImageRef;
}
-ImageParticle::~ImageParticle()
-{
- if (mImage)
- mImage->decRef();
-}
+ImageParticle::~ImageParticle() = default;
bool ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
diff --git a/src/imageparticle.h b/src/imageparticle.h
index 5e968a38..0f135c33 100644
--- a/src/imageparticle.h
+++ b/src/imageparticle.h
@@ -23,6 +23,8 @@
#include "particle.h"
+#include "resources/resource.h"
+
class Image;
class Map;
@@ -49,4 +51,5 @@ class ImageParticle : public Particle
protected:
Image *mImage; /**< The image used for this particle. */
+ ResourceRef<Image> mImageRef;
};
diff --git a/src/item.cpp b/src/item.cpp
index cae545b1..120c55a7 100644
--- a/src/item.cpp
+++ b/src/item.cpp
@@ -48,12 +48,10 @@ void Item::setId(int id)
mImage = resman->getImage(paths.getStringValue("itemIcons") + display.image);
if (!mImage)
+ {
mImage = 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/map.cpp b/src/map.cpp
index 929d66f8..835d400d 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -245,7 +245,7 @@ void Map::initializeAmbientLayers()
auto addAmbientLayer = [=](const std::string &name, std::vector<AmbientLayer> &list)
{
- if (auto img = resman->getImageRef(getProperty(name + "image")))
+ if (auto img = resman->getImage(getProperty(name + "image")))
{
auto &ambientLayer = list.emplace_back(img);
ambientLayer.mParallax = getFloatProperty(name + "parallax");
diff --git a/src/particle.cpp b/src/particle.cpp
index 6717653f..cb79c86f 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -294,7 +294,7 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
if (!imageSrc.empty() && !dyePalettes.empty())
Dye::instantiate(imageSrc, dyePalettes);
- auto img = resman->getImageRef(imageSrc);
+ auto img = resman->getImage(imageSrc);
newParticle = new ImageParticle(mMap, img);
}
// Other
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index a436d913..4954d317 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -29,11 +29,8 @@
#include "resources/dye.h"
#include "resources/image.h"
-#include "resources/imageset.h"
#include "resources/resourcemanager.h"
-#include "utils/stringutils.h"
-
#include <cmath>
#define SIN45 0.707106781f
@@ -102,7 +99,7 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
Dye::instantiate(image, dyePalettes);
ResourceManager *resman = ResourceManager::getInstance();
- mParticleImage = resman->getImageRef(image);
+ mParticleImage = resman->getImage(image);
}
}
else if (name == "horizontal-angle")
@@ -195,150 +192,13 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
}
else if (propertyNode.name() == "rotation")
{
- ImageSet *imageset = ResourceManager::getInstance()->getImageSet(
- propertyNode.getProperty("imageset", ""),
- propertyNode.getProperty("width", 0),
- propertyNode.getProperty("height", 0)
- );
-
- // Get animation frames
- for (auto frameNode : propertyNode.children())
- {
- int delay = frameNode.getProperty("delay", 0);
- int offsetX = frameNode.getProperty("offsetX", 0);
- int offsetY = frameNode.getProperty("offsetY", 0);
- if (mMap)
- {
- offsetX -= imageset->getWidth() / 2
- - mMap->getTileWidth() / 2;
- offsetY -= imageset->getHeight() - mMap->getTileHeight();
- }
-
- if (frameNode.name() == "frame")
- {
- int index = frameNode.getProperty("index", -1);
-
- if (index < 0)
- {
- logger->log("No valid value for 'index'");
- continue;
- }
-
- Image *img = imageset->get(index);
-
- if (!img)
- {
- logger->log("No image at index %d", index);
- continue;
- }
-
- mParticleRotation.addFrame(img, delay, offsetX, offsetY);
- }
- else if (frameNode.name() == "sequence")
- {
- int start = frameNode.getProperty("start", -1);
- int end = frameNode.getProperty("end", -1);
-
- if (start < 0 || end < 0)
- {
- logger->log("No valid value for 'start' or 'end'");
- continue;
- }
-
- while (end >= start)
- {
- Image *img = imageset->get(start);
-
- if (!img)
- {
- logger->log("No image at index %d", start);
- continue;
- }
-
- mParticleRotation.addFrame(img, delay, offsetX, offsetY);
- start++;
- }
- }
- else if (frameNode.name() == "end")
- {
- mParticleRotation.addTerminator();
- }
- } // for frameNode
+ mParticleRotation = Animation::fromXML(propertyNode);
}
else if (propertyNode.name() == "animation")
{
- std::string imagesetPath =
- propertyNode.getProperty("imageset", "");
- ImageSet *imageset = ResourceManager::getInstance()->getImageSet(
- imagesetPath,
- propertyNode.getProperty("width", 0),
- propertyNode.getProperty("height", 0)
- );
-
- if (!imageset)
- logger->error(strprintf("Failed to load \"%s\"",
- imagesetPath.c_str()));
-
- // Get animation frames
- for (auto frameNode : propertyNode.children())
- {
- int delay = frameNode.getProperty("delay", 0);
- int offsetX = frameNode.getProperty("offsetX", 0);
- int offsetY = frameNode.getProperty("offsetY", 0);
- offsetY -= imageset->getHeight() - 32;
- offsetX -= imageset->getWidth() / 2 - 16;
-
- if (frameNode.name() == "frame")
- {
- int index = frameNode.getProperty("index", -1);
-
- if (index < 0)
- {
- logger->log("No valid value for 'index'");
- continue;
- }
-
- Image *img = imageset->get(index);
-
- if (!img)
- {
- logger->log("No image at index %d", index);
- continue;
- }
-
- mParticleAnimation.addFrame(img, delay, offsetX, offsetY);
- }
- else if (frameNode.name() == "sequence")
- {
- int start = frameNode.getProperty("start", -1);
- int end = frameNode.getProperty("end", -1);
-
- if (start < 0 || end < 0)
- {
- logger->log("No valid value for 'start' or 'end'");
- continue;
- }
-
- while (end >= start)
- {
- Image *img = imageset->get(start);
-
- if (!img)
- {
- logger->log("No image at index %d", start);
- continue;
- }
-
- mParticleAnimation.addFrame(img, delay, offsetX, offsetY);
- start++;
- }
- }
- else if (frameNode.name() == "end")
- {
- mParticleAnimation.addTerminator();
- }
- } // for frameNode
- } else if (propertyNode.name() == "deatheffect")
+ mParticleAnimation = Animation::fromXML(propertyNode);
+ }
+ else if (propertyNode.name() == "deatheffect")
{
mDeathEffect = propertyNode.textContent();
mDeathEffectConditions = 0x00;
diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp
index b48e8cff..91c22236 100644
--- a/src/resources/animation.cpp
+++ b/src/resources/animation.cpp
@@ -21,6 +21,11 @@
#include "resources/animation.h"
+#include "dye.h"
+#include "game.h"
+#include "log.h"
+#include "resourcemanager.h"
+
void Animation::addFrame(Image *image, int delay, int offsetX, int offsetY)
{
auto &frame = mFrames.emplace_back();
@@ -41,3 +46,90 @@ bool Animation::isTerminator(const Frame &candidate)
{
return candidate.image == nullptr;
}
+
+Animation Animation::fromXML(XML::Node node, const std::string &dyePalettes)
+{
+ Animation animation;
+
+ std::string imagePath = node.getProperty("imageset", std::string());
+
+ // Instanciate the dye coloration.
+ Dye::instantiate(imagePath, dyePalettes);
+
+ auto imageSet = ResourceManager::getInstance()->getImageSet(
+ imagePath,
+ node.getProperty("width", 0),
+ node.getProperty("height", 0)
+ );
+
+ if (!imageSet)
+ return animation;
+
+ // Get animation frames
+ for (auto frameNode : node.children())
+ {
+ int delay = frameNode.getProperty("delay", 0);
+ int offsetX = frameNode.getProperty("offsetX", 0);
+ int offsetY = frameNode.getProperty("offsetY", 0);
+ Game *game = Game::instance();
+ if (game)
+ {
+ offsetX -= imageSet->getWidth() / 2 - game->getCurrentTileWidth() / 2;
+ offsetY -= imageSet->getHeight() - game->getCurrentTileHeight();
+ }
+
+ if (frameNode.name() == "frame")
+ {
+ int index = frameNode.getProperty("index", -1);
+
+ if (index < 0)
+ {
+ logger->log("No valid value for 'index'");
+ continue;
+ }
+
+ Image *img = imageSet->get(index);
+
+ if (!img)
+ {
+ logger->log("No image at index %d", index);
+ continue;
+ }
+
+ animation.addFrame(img, delay, offsetX, offsetY);
+ }
+ else if (frameNode.name() == "sequence")
+ {
+ int start = frameNode.getProperty("start", -1);
+ int end = frameNode.getProperty("end", -1);
+
+ if (start < 0 || end < 0)
+ {
+ logger->log("No valid value for 'start' or 'end'");
+ continue;
+ }
+
+ while (end >= start)
+ {
+ Image *img = imageSet->get(start);
+
+ if (!img)
+ {
+ logger->log("No image at index %d", start);
+ continue;
+ }
+
+ animation.addFrame(img, delay, offsetX, offsetY);
+ start++;
+ }
+ }
+ else if (frameNode.name() == "end")
+ {
+ animation.addTerminator();
+ }
+ }
+
+ animation.mImageSet = imageSet;
+
+ return animation;
+}
diff --git a/src/resources/animation.h b/src/resources/animation.h
index 01b8b388..cc3abd58 100644
--- a/src/resources/animation.h
+++ b/src/resources/animation.h
@@ -21,6 +21,9 @@
#pragma once
+#include "resources/imageset.h"
+#include "utils/xml.h"
+
#include <vector>
class Image;
@@ -76,7 +79,14 @@ class Animation final
*/
static bool isTerminator(const Frame &phase);
+ /**
+ * Loads an animation from XML.
+ */
+ static Animation fromXML(XML::Node node,
+ const std::string &dyePalettes = {});
+
protected:
+ ResourceRef<ImageSet> mImageSet;
std::vector<Frame> mFrames;
int mDuration = 0;
};
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
index 53038e12..d29483d1 100644
--- a/src/resources/emotedb.cpp
+++ b/src/resources/emotedb.cpp
@@ -43,7 +43,7 @@ void EmoteDB::init()
mUnknown.name = "unknown";
mUnknown.effectId = -1;
- mUnknown.image = ResourceManager::getInstance()->getImageRef("graphics/sprites/error.png");
+ mUnknown.image = ResourceManager::getInstance()->getImage("graphics/sprites/error.png");
}
void EmoteDB::readEmoteNode(XML::Node node, const std::string &filename)
@@ -82,7 +82,6 @@ void EmoteDB::readEmoteNode(XML::Node node, const std::string &filename)
emote.is = ResourceManager::getInstance()->getImageSet(imageName,
width,
height);
- emote.is->decRef(); // clear automatic reference
if (!emote.is || emote.is->size() == 0)
{
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index b5a5e258..b952cdcc 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -527,7 +527,7 @@ static Tileset *readTileset(XML::Node node, const std::string &path,
std::string sourceStr = resolveRelativePath(pathDir, source);
ResourceManager *resman = ResourceManager::getInstance();
- auto tilebmp = resman->getImageRef(sourceStr);
+ auto tilebmp = resman->getImage(sourceStr);
if (tilebmp)
{
diff --git a/src/resources/music.cpp b/src/resources/music.cpp
index 12c723bd..069af588 100644
--- a/src/resources/music.cpp
+++ b/src/resources/music.cpp
@@ -33,7 +33,7 @@ Music::~Music()
Mix_FreeMusic(mMusic);
}
-Resource *Music::load(SDL_RWops *rw)
+Music *Music::load(SDL_RWops *rw)
{
if (Mix_Music *music = Mix_LoadMUS_RW(rw, 1))
{
diff --git a/src/resources/music.h b/src/resources/music.h
index 81dc0d19..d22257da 100644
--- a/src/resources/music.h
+++ b/src/resources/music.h
@@ -38,10 +38,10 @@ class Music : public Resource
*
* @param rw The SDL_RWops to load the music data from.
*
- * @return <code>NULL</code> if the an error occurred, a valid pointer
- * otherwise.
+ * @return <code>nullptr</code> if the an error occurred, a valid
+ * pointer otherwise.
*/
- static Resource *load(SDL_RWops *rw);
+ static Music *load(SDL_RWops *rw);
/**
* Plays the music.
diff --git a/src/resources/resource.h b/src/resources/resource.h
index c6b41295..ba8d17cc 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -150,8 +150,12 @@ public:
* This is currently necessary to avoid calls to decRef on instances of
* SubImage, which are not reference counted resources.
*/
- void release()
- { mResource = nullptr; }
+ RESOURCE *release()
+ {
+ RESOURCE *resource = mResource;
+ mResource = nullptr;
+ return resource;
+ }
private:
RESOURCE *mResource;
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index c64786ab..5045d21b 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -44,56 +44,40 @@
ResourceManager *ResourceManager::instance = nullptr;
ResourceManager::ResourceManager()
- : mOldestOrphan(0)
{
logger->log("Initializing resource manager...");
}
ResourceManager::~ResourceManager()
{
+ // Put the orphaned resources into the main list for cleanup
mResources.insert(mOrphanedResources.begin(), mOrphanedResources.end());
- // Release any remaining spritedefs first because they depend on image sets
- auto iter = mResources.begin();
- while (iter != mResources.end())
+ auto cleanupResources = [&](auto match)
{
- if (dynamic_cast<SpriteDef*>(iter->second) != nullptr)
+ for (auto iter = mResources.begin(); iter != mResources.end(); )
{
- cleanUp(iter->second);
- auto toErase = iter;
- ++iter;
- mResources.erase(toErase);
- }
- else
- {
- ++iter;
+ if (match(iter->second))
+ {
+ cleanUp(iter->second);
+ iter = mResources.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
}
- }
+ };
- // Release any remaining image sets first because they depend on images
- iter = mResources.begin();
- while (iter != mResources.end())
- {
- if (dynamic_cast<ImageSet*>(iter->second) != nullptr)
- {
- cleanUp(iter->second);
- auto toErase = iter;
- ++iter;
- mResources.erase(toErase);
- }
- else
- {
- ++iter;
- }
- }
+ // SpriteDef references ImageSet
+ cleanupResources([](Resource *res) { return dynamic_cast<SpriteDef *>(res); });
- // Release remaining resources, logging the number of dangling references.
- iter = mResources.begin();
- while (iter != mResources.end())
- {
- cleanUp(iter->second);
- ++iter;
- }
+ // ImageSet references Image
+ cleanupResources([](Resource *res) { return dynamic_cast<ImageSet *>(res); });
+
+ // Release remaining resources
+ for (const auto &resource : mResources)
+ cleanUp(resource.second);
}
void ResourceManager::cleanUp(Resource *res)
@@ -162,7 +146,7 @@ void ResourceManager::searchAndAddArchives(const std::string &path,
{
const size_t len = strlen(fileName);
- if (len > ext.length() && !ext.compare(fileName + (len - ext.length())))
+ if (len > ext.length() && ext != (fileName + (len - ext.length())))
{
std::string file = path + fileName;
if (auto realDir = FS::getRealDir(file))
@@ -200,7 +184,6 @@ Resource *ResourceManager::get(const std::string &idPath,
auto resIter = mResources.find(idPath);
if (resIter != mResources.end())
{
- resIter->second->incRef();
return resIter->second;
}
@@ -210,53 +193,41 @@ Resource *ResourceManager::get(const std::string &idPath,
Resource *res = resIter->second;
mResources.insert(*resIter);
mOrphanedResources.erase(resIter);
- res->incRef();
return res;
}
Resource *resource = generator();
-
if (resource)
{
- resource->incRef();
resource->mIdPath = idPath;
mResources[idPath] = resource;
cleanOrphans();
}
- // Returns NULL if the object could not be created.
return resource;
}
-Resource *ResourceManager::get(const std::string &path, loader fun)
+ResourceRef<Music> ResourceManager::getMusic(const std::string &path)
{
- return get(path, [&] () -> Resource * {
- //
- // We use a buffered SDL_RWops to workaround a performance issue when
- // SDL_mixer is using stb_vorbis. The overhead of calling
- // PHYSFS_readBytes each time is too high because stb_vorbis requests
- // the file one byte at a time.
- //
- // See https://github.com/libsdl-org/SDL_mixer/issues/670
- //
+ return static_cast<Music*>(get(path, [&] () -> Resource * {
if (SDL_RWops *rw = FS::openBufferedRWops(path))
- return fun(rw);
+ return Music::load(rw);
return nullptr;
- });
+ }));
}
-Music *ResourceManager::getMusic(const std::string &idPath)
+ResourceRef<SoundEffect> ResourceManager::getSoundEffect(const std::string &path)
{
- return static_cast<Music*>(get(idPath, Music::load));
-}
+ return static_cast<SoundEffect*>(get(path, [&] () -> Resource * {
+ if (SDL_RWops *rw = FS::openBufferedRWops(path))
+ return SoundEffect::load(rw);
-SoundEffect *ResourceManager::getSoundEffect(const std::string &idPath)
-{
- return static_cast<SoundEffect*>(get(idPath, SoundEffect::load));
+ return nullptr;
+ }));
}
-Image *ResourceManager::getImage(const std::string &idPath)
+ResourceRef<Image> ResourceManager::getImage(const std::string &idPath)
{
return static_cast<Image*>(get(idPath, [&] () -> Resource * {
std::string path = idPath;
@@ -277,21 +248,14 @@ 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)
+ResourceRef<ImageSet> ResourceManager::getImageSet(const std::string &imagePath,
+ int w, int h)
{
std::stringstream ss;
ss << imagePath << "[" << w << "x" << h << "]";
return static_cast<ImageSet*>(get(ss.str(), [&] () -> Resource * {
- auto img = getImageRef(imagePath);
+ auto img = getImage(imagePath);
if (!img)
return nullptr;
@@ -299,7 +263,7 @@ ImageSet *ResourceManager::getImageSet(const std::string &imagePath,
}));
}
-SpriteDef *ResourceManager::getSprite(const std::string &path, int variant)
+ResourceRef<SpriteDef> ResourceManager::getSprite(const std::string &path, int variant)
{
std::stringstream ss;
ss << path << "[" << variant << "]";
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 5464ff3d..728a9b74 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -34,8 +34,6 @@ class Music;
class SoundEffect;
class SpriteDef;
-struct SDL_RWops;
-
/**
* A class for loading and managing resources.
*/
@@ -44,9 +42,6 @@ class ResourceManager
friend class Resource;
public:
-
- using loader = Resource *(*)(SDL_RWops *);
-
ResourceManager();
/**
@@ -81,62 +76,31 @@ class ResourceManager
static std::string getPath(const std::string &file);
/**
- * Creates a resource and adds it to the resource map.
- *
- * @param idPath The resource identifier path.
- * @param fun A function for generating the resource.
- * @param data Extra parameters for the generator.
- * @return A valid resource or <code>NULL</code> if the resource could
- * not be generated.
- */
- Resource *get(const std::string &idPath,
- const std::function<Resource *()> &generator);
-
- /**
- * Loads a resource from a file and adds it to the resource map.
- *
- * @param path The file name.
- * @param fun A function for parsing the file.
- * @return A valid resource or <code>NULL</code> if the resource could
- * not be loaded.
- */
- Resource *get(const std::string &path, loader fun);
-
- /**
- * Convenience wrapper around ResourceManager::get for loading
- * images.
- */
- Image *getImage(const std::string &idPath);
-
- /**
- * Convenience wrapper around ResourceManager::get for loading
- * images. Returns an automatically reference-counted resource.
+ * Loads the Image resource found at the given identifier path. The
+ * path can include a dye specification after a '|' character.
*/
- ResourceRef<Image> getImageRef(const std::string &idPath);
+ ResourceRef<Image> getImage(const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::get for loading
- * songs.
+ * Loads the Music resource found at the given path.
*/
- Music *getMusic(const std::string &idPath);
+ ResourceRef<Music> getMusic(const std::string &path);
/**
- * Convenience wrapper around ResourceManager::get for loading
- * samples.
+ * Loads the SoundEffect resource found at the given path.
*/
- SoundEffect *getSoundEffect(const std::string &idPath);
+ ResourceRef<SoundEffect> getSoundEffect(const std::string &path);
/**
- * Creates a image set based on the image referenced by the given
- * path and the supplied sprite sizes
+ * Loads a image set based on the image referenced by the given path
+ * and the supplied sprite sizes.
*/
- ImageSet *getImageSet(const std::string &imagePath, int w, int h);
+ ResourceRef<ImageSet> getImageSet(const std::string &imagePath, int w, int h);
/**
- * Creates a sprite definition based on a given path and the supplied
- * variant.
+ * Loads a SpriteDef based on a given path and the supplied variant.
*/
- SpriteDef *getSprite(const std::string &path, int variant = 0);
+ ResourceRef<SpriteDef> getSprite(const std::string &path, int variant = 0);
/**
* Returns an instance of the class, creating one if it does not
@@ -151,6 +115,19 @@ class ResourceManager
private:
/**
+ * Looks up a resource, creating it with the generator function if it
+ * does not exist. Does not increment the reference count of the
+ * resource.
+ *
+ * @param idPath The resource identifier path.
+ * @param generator A function for generating the resource.
+ * @return A valid resource or <code>nullptr</code> if the resource could
+ * not be generated.
+ */
+ Resource *get(const std::string &idPath,
+ const std::function<Resource *()> &generator);
+
+ /**
* Releases a resource, placing it in the set of orphaned resources.
* Only called from Resource::decRef,
*/
@@ -172,5 +149,5 @@ class ResourceManager
static ResourceManager *instance;
std::map<std::string, Resource *> mResources;
std::map<std::string, Resource *> mOrphanedResources;
- time_t mOldestOrphan;
+ time_t mOldestOrphan = 0;
};
diff --git a/src/resources/soundeffect.cpp b/src/resources/soundeffect.cpp
index 8f8cdfc5..19d7a820 100644
--- a/src/resources/soundeffect.cpp
+++ b/src/resources/soundeffect.cpp
@@ -28,23 +28,20 @@ SoundEffect::~SoundEffect()
Mix_FreeChunk(mChunk);
}
-Resource *SoundEffect::load(SDL_RWops *rw)
+SoundEffect *SoundEffect::load(SDL_RWops *rw)
{
// Load the music data and free the RWops structure
- Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 1);
-
- if (tmpSoundEffect)
+ if (Mix_Chunk *soundEffect = Mix_LoadWAV_RW(rw, 1))
{
- return new SoundEffect(tmpSoundEffect);
+ return new SoundEffect(soundEffect);
}
logger->log("Error, failed to load sound effect: %s", Mix_GetError());
return nullptr;
}
-bool SoundEffect::play(int loops, int volume, int channel)
+int SoundEffect::play(int loops, int volume, int channel)
{
Mix_VolumeChunk(mChunk, volume);
-
- return Mix_PlayChannel(channel, mChunk, loops) != -1;
+ return Mix_PlayChannel(channel, mChunk, loops);
}
diff --git a/src/resources/soundeffect.h b/src/resources/soundeffect.h
index 127b1ce6..9ca8490d 100644
--- a/src/resources/soundeffect.h
+++ b/src/resources/soundeffect.h
@@ -36,12 +36,12 @@ class SoundEffect : public Resource
/**
* Loads a sample from a buffer in memory.
*
- * @param rw The SDL_RWops to load the sample data from.
+ * @param rw The SDL_RWops to load the sample data from.
*
- * @return <code>NULL</code> if the an error occurred, a valid pointer
+ * @return <code>nullptr</code> if the an error occurred, a valid pointer
* otherwise.
*/
- static Resource *load(SDL_RWops *rw);
+ static SoundEffect *load(SDL_RWops *rw);
/**
* Plays the sample.
@@ -50,10 +50,10 @@ class SoundEffect : public Resource
* @param volume Sample playback volume.
* @param channel Sample playback channel.
*
- * @return <code>true</code> if the playback started properly
- * <code>false</code> otherwise.
+ * @return which channel was used to play the sound, or -1 if sound could not
+ * be played.
*/
- bool play(int loops, int volume, int channel = -1);
+ int play(int loops, int volume, int channel = -1);
protected:
SoundEffect(Mix_Chunk *soundEffect): mChunk(soundEffect) {}
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index f42e623e..85e5e566 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -28,7 +28,6 @@
#include "resources/animation.h"
#include "resources/dye.h"
#include "resources/image.h"
-#include "resources/imageset.h"
#include "resources/resourcemanager.h"
#include "configuration.h"
@@ -155,8 +154,7 @@ void SpriteDef::loadImageSet(XML::Node node, const std::string &palettes)
Dye::instantiate(imageSrc, palettes);
ResourceManager *resman = ResourceManager::getInstance();
- ImageSet *imageSet = resman->getImageSet(imageSrc, width, height);
-
+ auto imageSet = resman->getImageSet(imageSrc, width, height);
if (!imageSet)
{
logger->error(strprintf("Couldn't load imageset (%s)!",
@@ -328,11 +326,6 @@ SpriteDef::~SpriteDef()
{
delete action;
}
-
- for (auto &imageSet : mImageSets)
- {
- imageSet.second->decRef();
- }
}
SpriteDirection SpriteDef::makeSpriteDirection(const std::string &direction)
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 0f6e9966..83bd9598 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -21,7 +21,7 @@
#pragma once
-#include "resources/resource.h"
+#include "resources/imageset.h"
#include "utils/xml.h"
@@ -146,6 +146,6 @@ class SpriteDef : public Resource
*/
void substituteAction(std::string complete, std::string with);
- std::map<std::string, ImageSet *> mImageSets;
+ std::map<std::string, ResourceRef<ImageSet>> mImageSets;
std::map<std::string, Action *> mActions;
};
diff --git a/src/resources/theme.cpp b/src/resources/theme.cpp
index 26ab3aed..fe25a31b 100644
--- a/src/resources/theme.cpp
+++ b/src/resources/theme.cpp
@@ -64,7 +64,6 @@ Skin::~Skin()
for (auto img : mBorder.grid)
delete img;
- mCloseImage->decRef();
delete mStickyImageUp;
delete mStickyImageDown;
}
@@ -233,7 +232,7 @@ Skin *Theme::readSkin(const std::string &filename)
logger->log("Theme::load(): <skinset> defines '%s' as a skin image.",
skinSetImage.c_str());
- Image *dBorders = Theme::getImageFromTheme(skinSetImage);
+ auto dBorders = Theme::getImageFromTheme(skinSetImage);
ImageRect border;
memset(&border, 0, sizeof(ImageRect));
@@ -299,16 +298,13 @@ Skin *Theme::readSkin(const std::string &filename)
}
}
- dBorders->decRef();
-
logger->log("Finished loading skin.");
// Hard-coded for now until we update the above code to look for window buttons
- Image *closeImage = Theme::getImageFromTheme("close_button.png");
- Image *sticky = Theme::getImageFromTheme("sticky_button.png");
+ auto closeImage = Theme::getImageFromTheme("close_button.png");
+ auto sticky = Theme::getImageFromTheme("sticky_button.png");
Image *stickyImageUp = sticky->getSubImage(0, 0, 15, 15);
Image *stickyImageDown = sticky->getSubImage(15, 0, 15, 15);
- sticky->decRef();
Skin *skin = new Skin(border, closeImage, stickyImageUp, stickyImageDown);
skin->updateAlpha(mMinimumOpacity);
@@ -369,19 +365,12 @@ std::string Theme::resolveThemePath(const std::string &path)
return std::string(defaultThemePath) + "/" + path;
}
-Image *Theme::getImageFromTheme(const std::string &path)
+ResourceRef<Image> Theme::getImageFromTheme(const std::string &path)
{
ResourceManager *resman = ResourceManager::getInstance();
return resman->getImage(resolveThemePath(path));
}
-ImageSet *Theme::getImageSetFromTheme(const std::string &path,
- int w, int h)
-{
- ResourceManager *resman = ResourceManager::getInstance();
- return resman->getImageSet(resolveThemePath(path), w, h);
-}
-
static int readColorType(const std::string &type)
{
static std::string colors[] = {
diff --git a/src/resources/theme.h b/src/resources/theme.h
index 13491e26..d914fb7f 100644
--- a/src/resources/theme.h
+++ b/src/resources/theme.h
@@ -27,6 +27,7 @@
#include "eventlistener.h"
#include "gui/palette.h"
+#include "resources/resource.h"
#include <map>
#include <string>
@@ -77,10 +78,10 @@ class Skin
int instances = 0;
private:
- ImageRect mBorder; /**< The window border and background */
- Image *mCloseImage; /**< Close Button Image */
- Image *mStickyImageUp; /**< Sticky Button Image */
- Image *mStickyImageDown; /**< Sticky Button Image */
+ ImageRect mBorder; /**< The window border and background */
+ ResourceRef<Image> mCloseImage; /**< Close Button Image */
+ Image *mStickyImageUp; /**< Sticky Button Image */
+ Image *mStickyImageDown; /**< Sticky Button Image */
};
class Theme : public Palette, public EventListener
@@ -98,9 +99,7 @@ class Theme : public Palette, public EventListener
*/
static std::string resolveThemePath(const std::string &path);
- static Image *getImageFromTheme(const std::string &path);
- static ImageSet *getImageSetFromTheme(const std::string &path,
- int w, int h);
+ static ResourceRef<Image> getImageFromTheme(const std::string &path);
enum ThemePalette {
TEXT,
diff --git a/src/rotationalparticle.cpp b/src/rotationalparticle.cpp
index bcdb9bad..cdd7de61 100644
--- a/src/rotationalparticle.cpp
+++ b/src/rotationalparticle.cpp
@@ -35,11 +35,7 @@ RotationalParticle::RotationalParticle(Map *map, XML::Node animationNode,
mAnimation(animationNode, dyePalettes)
{}
-RotationalParticle::~RotationalParticle()
-{
- // Prevent ImageParticle from decreasing the reference count of the image
- mImage = nullptr;
-}
+RotationalParticle::~RotationalParticle() = default;
bool RotationalParticle::update()
{
diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp
index 506714d2..1ef22d84 100644
--- a/src/simpleanimation.cpp
+++ b/src/simpleanimation.cpp
@@ -21,28 +21,32 @@
#include "simpleanimation.h"
-#include "game.h"
#include "graphics.h"
-#include "log.h"
#include "resources/animation.h"
-#include "resources/dye.h"
#include "resources/image.h"
#include "resources/imageset.h"
#include "resources/resourcemanager.h"
-SimpleAnimation::SimpleAnimation(Animation animation):
- mAnimation(std::move(animation)),
- mCurrentFrame(mAnimation.getFrame(0)),
- mInitialized(true)
+SimpleAnimation::SimpleAnimation(Animation animation)
+ : mAnimation(std::move(animation))
+ , mInitialized(true)
{
+ if (mAnimation.getLength() > 0)
+ mCurrentFrame = mAnimation.getFrame(0);
}
SimpleAnimation::SimpleAnimation(XML::Node animationNode,
const std::string &dyePalettes)
{
- initializeAnimation(animationNode, dyePalettes);
- mCurrentFrame = mAnimation.getFrame(0);
+ if (animationNode)
+ {
+ mAnimation = Animation::fromXML(animationNode, dyePalettes);
+ mInitialized = true;
+ }
+
+ if (mAnimation.getLength() > 0)
+ mCurrentFrame = mAnimation.getFrame(0);
}
bool SimpleAnimation::draw(Graphics *graphics, int posX, int posY) const
@@ -90,103 +94,9 @@ void SimpleAnimation::update(int dt)
}
}
-int SimpleAnimation::getLength() const
-{
- return mAnimation.getLength();
-}
-
Image *SimpleAnimation::getCurrentImage() const
{
if (mCurrentFrame)
return mCurrentFrame->image;
return nullptr;
}
-
-void SimpleAnimation::initializeAnimation(XML::Node animationNode,
- const std::string& dyePalettes)
-{
- if (!animationNode)
- return;
-
- std::string imagePath = animationNode.getProperty( "imageset", "");
-
- // Instanciate the dye coloration.
- if (!imagePath.empty() && !dyePalettes.empty())
- Dye::instantiate(imagePath, dyePalettes);
-
- ImageSet *imageset = ResourceManager::getInstance()->getImageSet(
- animationNode.getProperty("imageset", ""),
- animationNode.getProperty("width", 0),
- animationNode.getProperty("height", 0)
- );
-
- if (!imageset)
- return;
-
- // Get animation frames
- for (auto frameNode : animationNode.children())
- {
- int delay = frameNode.getProperty("delay", 0);
- int offsetX = frameNode.getProperty("offsetX", 0);
- int offsetY = frameNode.getProperty("offsetY", 0);
- Game *game = Game::instance();
- if (game)
- {
- offsetX -= imageset->getWidth() / 2
- - game->getCurrentTileWidth() / 2;
- offsetY -= imageset->getHeight() - game->getCurrentTileHeight();
- }
-
- if (frameNode.name() == "frame")
- {
- int index = frameNode.getProperty("index", -1);
-
- if (index < 0)
- {
- logger->log("No valid value for 'index'");
- continue;
- }
-
- Image *img = imageset->get(index);
-
- if (!img)
- {
- logger->log("No image at index %d", index);
- continue;
- }
-
- mAnimation.addFrame(img, delay, offsetX, offsetY);
- }
- else if (frameNode.name() == "sequence")
- {
- int start = frameNode.getProperty("start", -1);
- int end = frameNode.getProperty("end", -1);
-
- if (start < 0 || end < 0)
- {
- logger->log("No valid value for 'start' or 'end'");
- continue;
- }
-
- while (end >= start)
- {
- Image *img = imageset->get(start);
-
- if (!img)
- {
- logger->log("No image at index %d", start);
- continue;
- }
-
- mAnimation.addFrame(img, delay, offsetX, offsetY);
- start++;
- }
- }
- else if (frameNode.name() == "end")
- {
- mAnimation.addTerminator();
- }
- }
-
- mInitialized = true;
-}
diff --git a/src/simpleanimation.h b/src/simpleanimation.h
index 94cc3a34..299b243f 100644
--- a/src/simpleanimation.h
+++ b/src/simpleanimation.h
@@ -48,7 +48,7 @@ class SimpleAnimation final
void setFrame(int frame);
- int getLength() const;
+ int getLength() const { return mAnimation.getLength(); }
void update(int dt);
@@ -62,9 +62,6 @@ class SimpleAnimation final
Image *getCurrentImage() const;
private:
- void initializeAnimation(XML::Node animationNode,
- const std::string& dyePalettes = std::string());
-
/** The hosted animation. */
Animation mAnimation;
diff --git a/src/sound.cpp b/src/sound.cpp
index 60cc2c10..c97951a3 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -30,42 +30,32 @@
#include "resources/resourcemanager.h"
#include "resources/soundeffect.h"
-enum {
- CHANNEL_NOTIFICATIONS = 0
-};
-
/**
- * This will be set to true, when a music can be freed after a fade out
- * Currently used by fadeOutCallBack()
+ * This will be set to true when the music that was playing can be freed.
*/
-static bool sFadingOutEnded = false;
+static bool sMusicFinished;
+static bool sChannelFinished[Sound::CHANNEL_COUNT];
-/**
- * Callback used at end of fadeout.
- * It is called by Mix_MusicFadeFinished().
- */
-static void fadeOutCallBack()
+static void musicFinishedCallBack()
{
- sFadingOutEnded = true;
+ sMusicFinished = true;
}
-Sound::Sound():
- mInstalled(false),
- mSfxVolume(100),
- mNotificationsVolume(100),
- mMusicVolume(60),
- mMusic(nullptr)
+static void channelFinishedCallBack(int channel)
{
- // This set up our callback function used to
- // handle fade outs endings.
- sFadingOutEnded = false;
- Mix_HookMusicFinished(fadeOutCallBack);
+ sChannelFinished[channel] = true;
+}
+
+Sound::Sound()
+{
+ Mix_HookMusicFinished(musicFinishedCallBack);
+ Mix_ChannelFinished(channelFinishedCallBack);
}
Sound::~Sound()
{
- // Unlink the callback function.
Mix_HookMusicFinished(nullptr);
+ Mix_ChannelFinished(nullptr);
}
void Sound::init()
@@ -93,8 +83,8 @@ void Sound::init()
return;
}
- Mix_AllocateChannels(16);
- Mix_ReserveChannels(1); // reserve one channel for notification sounds
+ Mix_AllocateChannels(CHANNEL_COUNT);
+ Mix_ReserveChannels(CHANNEL_RESERVED_COUNT);
Mix_VolumeMusic(mMusicVolume);
Mix_Volume(-1, mSfxVolume);
Mix_Volume(CHANNEL_NOTIFICATIONS, mNotificationsVolume);
@@ -173,25 +163,9 @@ void Sound::setNotificationsVolume(int volume)
Mix_Volume(CHANNEL_NOTIFICATIONS, mNotificationsVolume);
}
-static Music *loadMusic(const std::string &fileName)
-{
- ResourceManager *resman = ResourceManager::getInstance();
- return resman->getMusic(paths.getStringValue("music") + fileName);
-}
-
-
void Sound::playMusic(const std::string &fileName)
{
- mCurrentMusicFile = fileName;
-
- if (!mInstalled)
- return;
-
- haltMusic();
-
- mMusic = loadMusic(fileName);
- if (mMusic)
- mMusic->play();
+ fadeInMusic(fileName, 0);
}
void Sound::stopMusic()
@@ -213,7 +187,9 @@ void Sound::fadeInMusic(const std::string &fileName, int ms)
haltMusic();
- mMusic = loadMusic(fileName);
+ ResourceManager *resman = ResourceManager::getInstance();
+ mMusic = resman->getMusic(paths.getStringValue("music") + fileName);
+
if (mMusic)
mMusic->play(-1, ms);
}
@@ -230,12 +206,12 @@ void Sound::fadeOutMusic(int ms)
if (mMusic)
{
Mix_FadeOutMusic(ms);
- // Note: The fadeOutCallBack handler will take care about freeing
+ // Note: The musicFinishedCallBack will take care about freeing
// the music file at fade out ending.
}
else
{
- sFadingOutEnded = true;
+ sMusicFinished = true;
}
}
@@ -247,14 +223,10 @@ void Sound::fadeOutAndPlayMusic(const std::string &fileName, int ms)
void Sound::logic()
{
- if (sFadingOutEnded)
+ if (sMusicFinished)
{
- if (mMusic)
- {
- mMusic->decRef();
- mMusic = nullptr;
- }
- sFadingOutEnded = false;
+ sMusicFinished = false;
+ mMusic = nullptr;
if (!mNextMusicFile.empty())
{
@@ -262,6 +234,15 @@ void Sound::logic()
mNextMusicFile.clear();
}
}
+
+ for (int i = 0; i < CHANNEL_COUNT; i++)
+ {
+ if (sChannelFinished[i])
+ {
+ sChannelFinished[i] = false;
+ mSounds[i] = nullptr;
+ }
+ }
}
void Sound::playSfx(const std::string &path, int x, int y)
@@ -277,7 +258,7 @@ void Sound::playSfx(const std::string &path, int x, int y)
ResourceManager *resman = ResourceManager::getInstance();
- if (SoundEffect *sample = resman->getSoundEffect(tmpPath))
+ if (ResourceRef<SoundEffect> sound = resman->getSoundEffect(tmpPath))
{
logger->log("Sound::playSfx() Playing: %s", path.c_str());
int vol = 120;
@@ -293,7 +274,9 @@ void Sound::playSfx(const std::string &path, int x, int y)
vol -= std::min(120, dist / 4);
}
- sample->play(0, vol);
+ int channel = sound->play(0, vol);
+ if (channel != -1)
+ mSounds[channel] = sound;
}
}
@@ -302,9 +285,11 @@ void Sound::playNotification(const std::string &path)
const std::string fullPath = paths.getValue("sfx", "sfx/") + path;
ResourceManager *resman = ResourceManager::getInstance();
- if (SoundEffect *sample = resman->getSoundEffect(fullPath))
+ if (ResourceRef<SoundEffect> sound = resman->getSoundEffect(fullPath))
{
- sample->play(0, 128, CHANNEL_NOTIFICATIONS);
+ int channel = sound->play(0, MIX_MAX_VOLUME, CHANNEL_NOTIFICATIONS);
+ if (channel != -1)
+ mSounds[channel] = sound;
}
}
@@ -326,6 +311,5 @@ void Sound::haltMusic()
return;
Mix_HaltMusic();
- mMusic->decRef();
mMusic = nullptr;
}
diff --git a/src/sound.h b/src/sound.h
index 9d3aa28e..98286d76 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -21,11 +21,14 @@
#pragma once
+#include "resources/resource.h"
+
#include <SDL_mixer.h>
#include <string>
class Music;
+class SoundEffect;
/** Sound engine
*
@@ -107,11 +110,19 @@ class Sound
/**
* The sound logic.
- * Currently used to check whether the music file can be freed after
- * a fade out, and whether new music has to be played.
+ *
+ * Checks whether the music and sound effects can be freed after they
+ * finished playing, and whether new music has to be played.
*/
void logic();
+ enum Channel {
+ CHANNEL_NOTIFICATIONS = 0,
+ CHANNEL_RESERVED_COUNT,
+
+ CHANNEL_COUNT = 16,
+ };
+
private:
/** Logs various info about sound device. */
void info();
@@ -125,14 +136,15 @@ class Sound
*/
std::string mNextMusicFile;
- bool mInstalled;
+ bool mInstalled = false;
- int mSfxVolume;
- int mNotificationsVolume;
- int mMusicVolume;
+ int mSfxVolume = 100;
+ int mNotificationsVolume = 100;
+ int mMusicVolume = 60;
std::string mCurrentMusicFile;
- Music *mMusic;
+ ResourceRef<Music> mMusic;
+ ResourceRef<SoundEffect> mSounds[CHANNEL_COUNT];
};
extern Sound sound;
diff --git a/src/sprite.cpp b/src/sprite.cpp
index 3d9608f3..c2e434e7 100644
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -42,12 +42,10 @@ Sprite::Sprite(SpriteDef *sprite):
Sprite *Sprite::load(const std::string &filename, int variant)
{
ResourceManager *resman = ResourceManager::getInstance();
- SpriteDef *s = resman->getSprite(filename, variant);
- if (!s)
+ auto spriteDef = resman->getSprite(filename, variant);
+ if (!spriteDef)
return nullptr;
- auto *as = new Sprite(s);
- s->decRef();
- return as;
+ return new Sprite(spriteDef);
}
Sprite::~Sprite() = default;
diff --git a/src/text.cpp b/src/text.cpp
index e3776410..7f305401 100644
--- a/src/text.cpp
+++ b/src/text.cpp
@@ -53,7 +53,7 @@ Text::Text(const std::string &text, int x, int y,
if (textManager == nullptr)
{
textManager = new TextManager;
- Image *sbImage = Theme::getImageFromTheme("bubble.png|W:#"
+ auto sbImage = Theme::getImageFromTheme("bubble.png|W:#"
+ config.speechBubblecolor);
mBubble.grid[0] = sbImage->getSubImage(0, 0, 5, 5);
mBubble.grid[1] = sbImage->getSubImage(5, 0, 5, 5);
@@ -67,7 +67,6 @@ Text::Text(const std::string &text, int x, int y,
mBubbleArrow = sbImage->getSubImage(0, 15, 15, 10);
mBubble.setAlpha(config.speechBubbleAlpha);
mBubbleArrow->setAlpha(config.speechBubbleAlpha);
- sbImage->decRef();
}
++mInstances;
mHeight = mFont->getHeight();
diff --git a/src/utils/filesystem.h b/src/utils/filesystem.h
index 10c67202..0363cd22 100644
--- a/src/utils/filesystem.h
+++ b/src/utils/filesystem.h
@@ -264,6 +264,15 @@ inline SDL_RWops *openRWops(const std::string &path)
return PHYSFSRWOPS_openRead(path.c_str());
}
+/**
+ * Creates a buffered SDL_RWops.
+ *
+ * Used to workaround a performance issue when SDL_mixer is using stb_vorbis.
+ * The overhead of calling PHYSFS_readBytes each time is too high because
+ * stb_vorbis requests the file one byte at a time.
+ *
+ * See https://github.com/libsdl-org/SDL_mixer/issues/670
+ */
inline SDL_RWops *openBufferedRWops(const std::string &path)
{
auto rw = PHYSFSRWOPS_openRead(path.c_str());