Fix some issues rendering animated terrains in dialogs, and avoid a crash if a graphics sheet cannot be found

This commit is contained in:
2023-01-30 00:07:25 -05:00
parent f2b438d5c5
commit 8a2cfbae7e
5 changed files with 41 additions and 2 deletions

View File

@@ -18,6 +18,7 @@
#include "gfx/tiling.hpp"
#include "location.hpp"
#include "dialogxml/dialogs/dialog.hpp"
#include "dialogxml/dialogs/strdlog.hpp"
#include "fileio/resmgr/res_image.hpp"
extern sf::Texture bg_gworld;
@@ -96,6 +97,8 @@ bool cPict::manageFormat(eFormat prop, bool set, boost::any* val) {
}
void cPict::setPict(pic_num_t num, ePicType type){
sheetCached.reset();
sheetCachedType = NUM_SHEET_TYPES;
picNum = num;
picType = type;
if(picType == PIC_MONST && picNum < 1000) {
@@ -108,6 +111,8 @@ void cPict::setPict(pic_num_t num, ePicType type){
picType += PIC_PARTY;
} else {
picType += PIC_CUSTOM;
if(picNum >= 2000 && picType == PIC_CUSTOM_TER)
picType = PIC_CUSTOM_TER_ANIM;
if(picType != PIC_CUSTOM_TER_MAP)
picNum %= 1000;
}
@@ -586,6 +591,16 @@ void cPict::recalcRect() {
}
std::shared_ptr<const sf::Texture> cPict::getSheet(eSheetType type, size_t n) {
if(type == sheetCachedType && n == sheetCachedNum) {
return sheetCached;
}
sheetCachedType = type;
sheetCachedNum = n;
sheetCached = getSheetInternal(type, n);
return sheetCached;
}
std::shared_ptr<const sf::Texture> cPict::getSheetInternal(eSheetType type, size_t n) {
std::ostringstream sout;
bool purgeable = false;
switch(type) {
@@ -672,7 +687,13 @@ std::shared_ptr<const sf::Texture> cPict::getSheet(eSheetType type, size_t n) {
sout << "sheet" << n;
}
}
return &ResMgr::graphics.get(sout.str(), purgeable);
auto name = sout.str();
try {
return &ResMgr::graphics.get(name, purgeable);
} catch(ResMgr::xError& e) {
showError(e.what());
return nullptr;
}
}
void cPict::draw(){
@@ -690,6 +711,10 @@ void cPict::draw(){
}
void cPict::drawPresetTer(short num, rectangle to_rect){
if(num >= 960) {
drawPresetTerAnim(num - 960, to_rect);
return;
}
auto from_gw = getSheet(SHEET_TER, num / 50);
if(!from_gw) return;
num = num % 50;
@@ -702,6 +727,7 @@ void cPict::drawPresetTer(short num, rectangle to_rect){
void cPict::drawPresetTerAnim(short num, rectangle to_rect){
rectangle from_rect = calc_rect(4 * (num / 5) + animFrame % 4, num % 5);
auto from_gw = getSheet(SHEET_TER_ANIM);
if(!from_gw) return;
if(to_rect.right - to_rect.left > 28) {
to_rect.inset(4,0);
to_rect.right = to_rect.left + 28;

View File

@@ -88,7 +88,11 @@ public:
cPict& operator=(cPict& other) = delete;
cPict(cPict& other) = delete;
private:
static std::shared_ptr<const sf::Texture> getSheet(eSheetType type, size_t n = 0);
static std::shared_ptr<const sf::Texture> getSheetInternal(eSheetType type, size_t n);
std::shared_ptr<const sf::Texture> getSheet(eSheetType type, size_t n = 0);
std::shared_ptr<const sf::Texture> sheetCached;
eSheetType sheetCachedType;
size_t sheetCachedNum;
static short animFrame;
pic_num_t picNum;
ePicType picType;

View File

@@ -78,6 +78,10 @@ void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::Re
}
void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,sf::RenderStates mode) {
rectangle src_gworld_rect(src_gworld), targ_gworld_rect(targ_gworld);
src_rect &= src_gworld_rect;
targ_rect &= targ_gworld_rect;
if(src_rect.empty() || targ_rect.empty()) return;
setActiveRenderTarget(targ_gworld);
sf::Sprite tile(src_gworld, src_rect);
tile.setPosition(targ_rect.left, targ_rect.top);

View File

@@ -98,6 +98,10 @@ bool rectangle::contains(int x, int y) const {
return contains(location(x,y));
}
bool rectangle::empty() const {
return height() == 0 && width() == 0;
}
rectangle_size_delegate::rectangle_size_delegate(rectangle& rect, int rectangle::* first, int rectangle::* last) :
forRect(rect), b1(first), b2(last) {}

View File

@@ -88,6 +88,7 @@ struct rectangle {
location bottomRight() const;
bool contains(location p) const;
bool contains(int x, int y) const;
bool empty() const;
void offset(int h, int v);
void offset(location diff);
void move_to(int x, int y);