mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-12 20:05:55 -05:00
Only load event sprites when requested
This commit is contained in:
@@ -41,14 +41,6 @@ public:
|
||||
virtual void visitSign(SignEvent *) = 0;
|
||||
};
|
||||
|
||||
struct EventGraphics
|
||||
{
|
||||
QImage spritesheet;
|
||||
int spriteWidth;
|
||||
int spriteHeight;
|
||||
bool inanimate;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// Event base class -- purely virtual
|
||||
@@ -64,11 +56,7 @@ public:
|
||||
Event& operator=(const Event &other) = delete;
|
||||
|
||||
protected:
|
||||
Event() {
|
||||
this->spriteWidth = 16;
|
||||
this->spriteHeight = 16;
|
||||
this->usingSprite = false;
|
||||
}
|
||||
Event() {}
|
||||
|
||||
// public enums & static methods
|
||||
public:
|
||||
@@ -143,8 +131,8 @@ public:
|
||||
int getZ() const { return this->elevation; }
|
||||
int getElevation() const { return this->elevation; }
|
||||
|
||||
int getPixelX() const { return (this->x * 16) - qMax(0, (this->spriteWidth - 16) / 2); }
|
||||
int getPixelY() const { return (this->y * 16) - qMax(0, this->spriteHeight - 16); }
|
||||
int getPixelX() const { return (this->x * 16) - qMax(0, (pixmap.width() - 16) / 2); }
|
||||
int getPixelY() const { return (this->y * 16) - qMax(0, pixmap.height() - 16); }
|
||||
|
||||
virtual EventFrame *getEventFrame();
|
||||
virtual EventFrame *createEventFrame() = 0;
|
||||
@@ -172,14 +160,8 @@ public:
|
||||
void setPixmapItem(DraggablePixmapItem *item);
|
||||
DraggablePixmapItem *getPixmapItem() const { return this->pixmapItem; }
|
||||
|
||||
void setUsingSprite(bool newUsingSprite) { this->usingSprite = newUsingSprite; }
|
||||
bool getUsingSprite() const { return this->usingSprite; }
|
||||
|
||||
void setSpriteWidth(int newSpriteWidth) { this->spriteWidth = newSpriteWidth; }
|
||||
int getspriteWidth() const { return this->spriteWidth; }
|
||||
|
||||
void setSpriteHeight(int newSpriteHeight) { this->spriteHeight = newSpriteHeight; }
|
||||
int getspriteHeight() const { return this->spriteHeight; }
|
||||
void setUsesDefaultPixmap(bool newUsesDefaultPixmap) { this->usesDefaultPixmap = newUsesDefaultPixmap; }
|
||||
bool getUsesDefaultPixmap() const { return this->usesDefaultPixmap; }
|
||||
|
||||
int getEventIndex();
|
||||
|
||||
@@ -204,9 +186,7 @@ protected:
|
||||
int y = 0;
|
||||
int elevation = 0;
|
||||
|
||||
int spriteWidth = 16;
|
||||
int spriteHeight = 16;
|
||||
bool usingSprite = false;
|
||||
bool usesDefaultPixmap = true;
|
||||
|
||||
// Some events can have an associated #define name that should be unique to this event.
|
||||
// e.g. object events can have a 'LOCALID', or Heal Locations have a 'HEAL_LOCATION' id.
|
||||
@@ -273,10 +253,6 @@ public:
|
||||
void setFlag(QString newFlag) { this->flag = newFlag; }
|
||||
QString getFlag() const { return this->flag; }
|
||||
|
||||
public:
|
||||
void setFrameFromMovement(QString movement);
|
||||
void setPixmapFromSpritesheet(EventGraphics * gfx);
|
||||
|
||||
|
||||
protected:
|
||||
QString gfx;
|
||||
|
||||
@@ -45,7 +45,6 @@ public:
|
||||
QStringList layoutIdsMaster;
|
||||
QMap<QString, Layout*> mapLayouts;
|
||||
QMap<QString, Layout*> mapLayoutsMaster;
|
||||
QMap<QString, EventGraphics*> eventGraphicsMap;
|
||||
QMap<QString, int> gfxDefines;
|
||||
QString defaultSong;
|
||||
QStringList songNames;
|
||||
@@ -68,7 +67,6 @@ public:
|
||||
QMap<QString, uint16_t> unusedMetatileLabels;
|
||||
QMap<QString, uint32_t> metatileBehaviorMap;
|
||||
QMap<uint32_t, QString> metatileBehaviorMapInverse;
|
||||
QMap<QString, QString> facingDirections;
|
||||
ParseUtil parser;
|
||||
QFileSystemWatcher fileWatcher;
|
||||
QSet<QString> modifiedFiles;
|
||||
@@ -210,7 +208,10 @@ public:
|
||||
bool readFieldmapMasks();
|
||||
QMap<QString, QMap<QString, QString>> readObjEventGfxInfo();
|
||||
|
||||
void setEventPixmap(Event *event, bool forceLoad = false);
|
||||
QPixmap getEventPixmap(const QString &gfxName, const QString &movementName);
|
||||
QPixmap getEventPixmap(const QString &gfxName, int frame, bool hFlip);
|
||||
QPixmap getEventPixmap(Event::Group group);
|
||||
void loadEventPixmap(Event *event, bool forceLoad = false);
|
||||
|
||||
QString fixPalettePath(QString path);
|
||||
QString fixGraphicPath(QString path);
|
||||
@@ -254,6 +255,18 @@ public:
|
||||
private:
|
||||
QMap<QString, QString> mapSectionDisplayNames;
|
||||
QMap<QString, qint64> modifiedFileTimestamps;
|
||||
QMap<QString, QString> facingDirections;
|
||||
|
||||
struct EventGraphics
|
||||
{
|
||||
QString filepath;
|
||||
bool loaded = false;
|
||||
QImage spritesheet;
|
||||
int spriteWidth = -1;
|
||||
int spriteHeight = -1;
|
||||
bool inanimate = false;
|
||||
};
|
||||
QMap<QString, EventGraphics*> eventGraphicsMap;
|
||||
|
||||
void updateLayout(Layout *);
|
||||
|
||||
|
||||
@@ -107,9 +107,10 @@ Event::Type Event::typeFromString(QString type) {
|
||||
return typeToStringMap.key(type, Event::Type::None);
|
||||
}
|
||||
|
||||
void Event::loadPixmap(Project *) {
|
||||
void Event::loadPixmap(Project *project) {
|
||||
const QPixmap * pixmap = Event::icons.value(this->getEventGroup());
|
||||
this->pixmap = pixmap ? *pixmap : QPixmap();
|
||||
this->usesDefaultPixmap = true;
|
||||
}
|
||||
|
||||
void Event::clearIcons() {
|
||||
@@ -230,7 +231,6 @@ void ObjectEvent::setDefaultValues(Project *project) {
|
||||
this->setRadiusX(0);
|
||||
this->setRadiusY(0);
|
||||
this->setSightRadiusBerryTreeID("0");
|
||||
this->setFrameFromMovement(project->facingDirections.value(this->getMovement()));
|
||||
}
|
||||
|
||||
const QSet<QString> expectedObjectFields = {
|
||||
@@ -257,78 +257,11 @@ QSet<QString> ObjectEvent::getExpectedFields() {
|
||||
}
|
||||
|
||||
void ObjectEvent::loadPixmap(Project *project) {
|
||||
EventGraphics *eventGfx = project->eventGraphicsMap.value(this->gfx, nullptr);
|
||||
if (!eventGfx) {
|
||||
// Invalid gfx constant.
|
||||
// If this is a number, try to use that instead.
|
||||
bool ok;
|
||||
int altGfx = ParseUtil::gameStringToInt(this->gfx, &ok);
|
||||
if (ok && (altGfx < project->gfxDefines.count())) {
|
||||
eventGfx = project->eventGraphicsMap.value(project->gfxDefines.key(altGfx, "NULL"), nullptr);
|
||||
}
|
||||
}
|
||||
if (!eventGfx || eventGfx->spritesheet.isNull()) {
|
||||
// No sprite associated with this gfx constant.
|
||||
// Use default sprite instead.
|
||||
this->pixmap = project->getEventPixmap(this->gfx, this->movement);
|
||||
if (!this->pixmap.isNull()) {
|
||||
this->usesDefaultPixmap = false;
|
||||
} else {
|
||||
Event::loadPixmap(project);
|
||||
this->spriteWidth = 16;
|
||||
this->spriteHeight = 16;
|
||||
this->usingSprite = false;
|
||||
} else {
|
||||
this->setFrameFromMovement(project->facingDirections.value(this->movement));
|
||||
this->setPixmapFromSpritesheet(eventGfx);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectEvent::setPixmapFromSpritesheet(EventGraphics * gfx)
|
||||
{
|
||||
QImage img;
|
||||
if (gfx->inanimate) {
|
||||
img = gfx->spritesheet.copy(0, 0, gfx->spriteWidth, gfx->spriteHeight);
|
||||
} else {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
// Get frame's position in spritesheet.
|
||||
// Assume horizontal layout. If position would exceed sheet width, try vertical layout.
|
||||
if ((this->frame + 1) * gfx->spriteWidth <= gfx->spritesheet.width()) {
|
||||
x = this->frame * gfx->spriteWidth;
|
||||
} else if ((this->frame + 1) * gfx->spriteHeight <= gfx->spritesheet.height()) {
|
||||
y = this->frame * gfx->spriteHeight;
|
||||
}
|
||||
|
||||
img = gfx->spritesheet.copy(x, y, gfx->spriteWidth, gfx->spriteHeight);
|
||||
|
||||
// Right-facing sprite is just the left-facing sprite mirrored
|
||||
if (this->hFlip) {
|
||||
img = img.transformed(QTransform().scale(-1, 1));
|
||||
}
|
||||
}
|
||||
// Set first palette color fully transparent.
|
||||
img.setColor(0, qRgba(0, 0, 0, 0));
|
||||
pixmap = QPixmap::fromImage(img);
|
||||
this->spriteWidth = gfx->spriteWidth;
|
||||
this->spriteHeight = gfx->spriteHeight;
|
||||
this->usingSprite = true;
|
||||
}
|
||||
|
||||
void ObjectEvent::setFrameFromMovement(QString facingDir) {
|
||||
// defaults
|
||||
// TODO: read this from a file somewhere?
|
||||
this->frame = 0;
|
||||
this->hFlip = false;
|
||||
if (facingDir == "DIR_NORTH") {
|
||||
this->frame = 1;
|
||||
this->hFlip = false;
|
||||
} else if (facingDir == "DIR_SOUTH") {
|
||||
this->frame = 0;
|
||||
this->hFlip = false;
|
||||
} else if (facingDir == "DIR_WEST") {
|
||||
this->frame = 2;
|
||||
this->hFlip = false;
|
||||
} else if (facingDir == "DIR_EAST") {
|
||||
this->frame = 2;
|
||||
this->hFlip = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,19 +363,7 @@ void CloneObjectEvent::loadPixmap(Project *project) {
|
||||
this->gfx = project->gfxDefines.key(0, "0");
|
||||
this->movement = project->movementTypes.value(0, "0");
|
||||
}
|
||||
|
||||
EventGraphics *eventGfx = project->eventGraphicsMap.value(gfx, nullptr);
|
||||
if (!eventGfx || eventGfx->spritesheet.isNull()) {
|
||||
// No sprite associated with this gfx constant.
|
||||
// Use default sprite instead.
|
||||
Event::loadPixmap(project);
|
||||
this->spriteWidth = 16;
|
||||
this->spriteHeight = 16;
|
||||
this->usingSprite = false;
|
||||
} else {
|
||||
this->setFrameFromMovement(project->facingDirections.value(this->movement));
|
||||
this->setPixmapFromSpritesheet(eventGfx);
|
||||
}
|
||||
ObjectEvent::loadPixmap(project);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1670,7 +1670,7 @@ void Editor::displayMapEvents() {
|
||||
}
|
||||
|
||||
DraggablePixmapItem *Editor::addEventPixmapItem(Event *event) {
|
||||
this->project->setEventPixmap(event);
|
||||
this->project->loadEventPixmap(event);
|
||||
auto item = new DraggablePixmapItem(event, this);
|
||||
redrawEventPixmapItem(item);
|
||||
this->events_group->addToGroup(item);
|
||||
@@ -1955,13 +1955,13 @@ qreal Editor::getEventOpacity(const Event *event) const {
|
||||
// - On the Events tab, and the event has a custom sprite (1.0)
|
||||
if (this->editMode != EditMode::Events)
|
||||
return porymapConfig.eventOverlayEnabled ? 0.5 : 0.0;
|
||||
return event->getUsingSprite() ? 1.0 : 0.7;
|
||||
return event->getUsesDefaultPixmap() ? 0.7 : 1.0;
|
||||
}
|
||||
|
||||
void Editor::redrawEventPixmapItem(DraggablePixmapItem *item) {
|
||||
if (item && item->event && !item->event->getPixmap().isNull()) {
|
||||
item->setOpacity(getEventOpacity(item->event));
|
||||
project->setEventPixmap(item->event, true);
|
||||
project->loadEventPixmap(item->event, true);
|
||||
item->setPixmap(item->event->getPixmap());
|
||||
item->setShapeMode(porymapConfig.eventSelectionShapeMode);
|
||||
|
||||
|
||||
186
src/project.cpp
186
src/project.cpp
@@ -2664,92 +2664,176 @@ QStringList Project::getEventScriptsFilePaths() const {
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
void Project::setEventPixmap(Event *event, bool forceLoad) {
|
||||
void Project::loadEventPixmap(Event *event, bool forceLoad) {
|
||||
if (event && (event->getPixmap().isNull() || forceLoad))
|
||||
event->loadPixmap(this);
|
||||
}
|
||||
|
||||
void Project::clearEventGraphics() {
|
||||
qDeleteAll(eventGraphicsMap);
|
||||
eventGraphicsMap.clear();
|
||||
qDeleteAll(this->eventGraphicsMap);
|
||||
this->eventGraphicsMap.clear();
|
||||
}
|
||||
|
||||
bool Project::readEventGraphics() {
|
||||
clearEventGraphics();
|
||||
|
||||
fileWatcher.addPaths(QStringList() << root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers)
|
||||
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info)
|
||||
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables)
|
||||
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx));
|
||||
|
||||
const QString pointersFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers);
|
||||
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
|
||||
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(pointersFilepath, pointersName);
|
||||
const QString gfxInfoFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
|
||||
const QString picTablesFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables);
|
||||
const QString gfxFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx);
|
||||
fileWatcher.addPaths({pointersFilepath, gfxInfoFilepath, picTablesFilepath, gfxFilepath});
|
||||
|
||||
QStringList gfxNames = gfxDefines.keys();
|
||||
// Read the table mapping OBJ_EVENT_GFX constants to the names of pointers to data about their graphics.
|
||||
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
|
||||
const QMap<QString, QString> pointerMap = parser.readNamedIndexCArray(pointersFilepath, pointersName);
|
||||
|
||||
// The positions of each of the required members for the gfx info struct.
|
||||
// For backwards compatibility if the struct doesn't use initializers.
|
||||
static const auto gfxInfoMemberMap = QHash<int, QString>{
|
||||
static const QHash<int, QString> gfxInfoMemberMap = {
|
||||
{8, "inanimate"},
|
||||
{11, "oam"},
|
||||
{12, "subspriteTables"},
|
||||
{14, "images"},
|
||||
};
|
||||
// Read the structs containing data about each of the event sprites.
|
||||
auto gfxInfos = parser.readCStructs(gfxInfoFilepath, "", gfxInfoMemberMap);
|
||||
|
||||
QString filepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
|
||||
auto gfxInfos = parser.readCStructs(filepath, "", gfxInfoMemberMap);
|
||||
// We need data in both of these files to translate data from the structs above into the path for a .png file.
|
||||
const QMap<QString, QStringList> picTables = parser.readCArrayMulti(picTablesFilepath);
|
||||
const QMap<QString, QString> graphicIncbins = parser.readCIncbinMulti(gfxFilepath);
|
||||
|
||||
QMap<QString, QStringList> picTables = parser.readCArrayMulti(projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables));
|
||||
QMap<QString, QString> graphicIncbins = parser.readCIncbinMulti(projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx));
|
||||
for (auto i = this->gfxDefines.constBegin(); i != this->gfxDefines.constEnd(); i++) {
|
||||
const QString gfxName = i.key();
|
||||
|
||||
for (QString gfxName : gfxNames) {
|
||||
QString info_label = pointerHash[gfxName].replace("&", "");
|
||||
// Strip the address-of operator to get the pointer's name. We'll use this name to get data about the event's sprite.
|
||||
// If we don't recognize the name, ignore it. The event will use a default sprite.
|
||||
QString info_label = pointerMap[gfxName].replace("&", "");
|
||||
if (!gfxInfos.contains(info_label))
|
||||
continue;
|
||||
const QHash<QString, QString> gfxInfoAttributes = gfxInfos[info_label];
|
||||
|
||||
auto gfxInfoAttributes = gfxInfos[info_label];
|
||||
auto gfx = new EventGraphics;
|
||||
|
||||
auto eventGraphics = new EventGraphics;
|
||||
eventGraphics->inanimate = ParseUtil::gameStringToBool(gfxInfoAttributes.value("inanimate"));
|
||||
QString pic_label = gfxInfoAttributes.value("images");
|
||||
QString dimensions_label = gfxInfoAttributes.value("oam");
|
||||
QString subsprites_label = gfxInfoAttributes.value("subspriteTables");
|
||||
|
||||
QString gfx_label = picTables[pic_label].value(0);
|
||||
// We need the .png filepath for the event's sprite. This is buried behind a few levels of indirection.
|
||||
// The 'images' field gives us the name of the table containing the sprite's image data.
|
||||
// The entries in this table are expected to be in the format (PngSymbolName, ...).
|
||||
// We extract the symbol name of the .png's INCBIN'd data by looking at the first entry in this table.
|
||||
// Once we have the .png's symbol name we can get the actual filepath from its INCBIN.
|
||||
QString gfx_label = picTables[gfxInfoAttributes.value("images")].value(0);
|
||||
static const QRegularExpression re_parens("[\\(\\)]");
|
||||
gfx_label = gfx_label.section(re_parens, 1, 1);
|
||||
QString path = graphicIncbins[gfx_label];
|
||||
gfx->filepath = fixGraphicPath(graphicIncbins[gfx_label]);
|
||||
|
||||
if (!path.isNull()) {
|
||||
path = fixGraphicPath(path);
|
||||
eventGraphics->spritesheet = QImage(root + "/" + path);
|
||||
if (!eventGraphics->spritesheet.isNull()) {
|
||||
// Infer the sprite dimensions from the OAM labels.
|
||||
static const QRegularExpression re("\\S+_(\\d+)x(\\d+)");
|
||||
QRegularExpressionMatch dimensionMatch = re.match(dimensions_label);
|
||||
QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label);
|
||||
if (oamTablesMatch.hasMatch()) {
|
||||
eventGraphics->spriteWidth = oamTablesMatch.captured(1).toInt(nullptr, 0);
|
||||
eventGraphics->spriteHeight = oamTablesMatch.captured(2).toInt(nullptr, 0);
|
||||
} else if (dimensionMatch.hasMatch()) {
|
||||
eventGraphics->spriteWidth = dimensionMatch.captured(1).toInt(nullptr, 0);
|
||||
eventGraphics->spriteHeight = dimensionMatch.captured(2).toInt(nullptr, 0);
|
||||
} else {
|
||||
eventGraphics->spriteWidth = eventGraphics->spritesheet.width();
|
||||
eventGraphics->spriteHeight = eventGraphics->spritesheet.height();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eventGraphics->spritesheet = QImage();
|
||||
eventGraphics->spriteWidth = 16;
|
||||
eventGraphics->spriteHeight = 16;
|
||||
// Note: gfx has a 'spritesheet' field that will contain a QImage for the event's sprite.
|
||||
// We don't create this QImage yet. Reading the image now is unnecessary overhead for startup.
|
||||
// We'll read the image file when the event's sprite is first requested to be drawn.
|
||||
|
||||
// The .png file is expected to be a spritesheet that can have multiple frames.
|
||||
// We only want to show one frame at a time, so we need to know the dimensions of each frame.
|
||||
// TODO: Describe different ways we read these. Use width/height?
|
||||
static const QRegularExpression re("\\S+_(\\d+)x(\\d+)");
|
||||
QRegularExpressionMatch dimensionMatch = re.match(gfxInfoAttributes.value("oam"));
|
||||
QRegularExpressionMatch oamTablesMatch = re.match(gfxInfoAttributes.value("subspriteTables"));
|
||||
if (oamTablesMatch.hasMatch()) {
|
||||
gfx->spriteWidth = oamTablesMatch.captured(1).toInt(nullptr, 0);
|
||||
gfx->spriteHeight = oamTablesMatch.captured(2).toInt(nullptr, 0);
|
||||
} else if (dimensionMatch.hasMatch()) {
|
||||
gfx->spriteWidth = dimensionMatch.captured(1).toInt(nullptr, 0);
|
||||
gfx->spriteHeight = dimensionMatch.captured(2).toInt(nullptr, 0);
|
||||
}
|
||||
eventGraphicsMap.insert(gfxName, eventGraphics);
|
||||
|
||||
// Inanimate events will only ever use the first frame of their spritesheet.
|
||||
gfx->inanimate = ParseUtil::gameStringToBool(gfxInfoAttributes.value("inanimate"));
|
||||
|
||||
this->eventGraphicsMap.insert(gfxName, gfx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QPixmap Project::getEventPixmap(const QString &gfxName, const QString &movementName) {
|
||||
struct FrameData {
|
||||
int index = 0;
|
||||
bool hFlip = false;
|
||||
};
|
||||
// TODO: Expose as a setting to users
|
||||
static const QMap<QString, FrameData> directionToFrameData = {
|
||||
{"DIR_SOUTH", { .index = 0, .hFlip = false }},
|
||||
{"DIR_NORTH", { .index = 1, .hFlip = false }},
|
||||
{"DIR_WEST", { .index = 2, .hFlip = false }},
|
||||
{"DIR_EAST", { .index = 2, .hFlip = true }}, // East-facing sprite is just the West-facing sprite mirrored
|
||||
};
|
||||
const QString direction = this->facingDirections.value(movementName, "DIR_SOUTH");
|
||||
auto frameData = directionToFrameData.value(direction);
|
||||
return getEventPixmap(gfxName, frameData.index, frameData.hFlip);
|
||||
}
|
||||
|
||||
QPixmap Project::getEventPixmap(const QString &gfxName, int frame, bool hFlip) {
|
||||
EventGraphics* gfx = this->eventGraphicsMap.value(gfxName, nullptr);
|
||||
if (!gfx) {
|
||||
// Invalid gfx constant. If this is a number, try to use that instead.
|
||||
bool ok;
|
||||
int gfxNum = ParseUtil::gameStringToInt(gfxName, &ok);
|
||||
if (ok && gfxNum < this->gfxDefines.count()) {
|
||||
gfx = this->eventGraphicsMap.value(this->gfxDefines.key(gfxNum, "NULL"), nullptr);
|
||||
}
|
||||
}
|
||||
if (gfx && !gfx->loaded) {
|
||||
// This is the first request for this event's sprite. We'll attempt to load it now.
|
||||
if (!gfx->filepath.isEmpty()) {
|
||||
gfx->spritesheet = QImage(QString("%1/%2").arg(this->root).arg(gfx->filepath));
|
||||
if (gfx->spritesheet.isNull()) {
|
||||
logWarn(QString("Failed to open '%1' for event's sprite. Event will use a default sprite instead.").arg(gfx->filepath));
|
||||
} else {
|
||||
// If we were unable to find the dimensions of a frame within the spritesheet we'll use the full image dimensions.
|
||||
if (gfx->spriteWidth <= 0) {
|
||||
gfx->spriteWidth = gfx->spritesheet.width();
|
||||
}
|
||||
if (gfx->spriteHeight <= 0) {
|
||||
gfx->spriteHeight = gfx->spritesheet.height();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set this whether we were successful or not, we only need to try to load it once.
|
||||
gfx->loaded = true;
|
||||
}
|
||||
if (!gfx || gfx->spritesheet.isNull()) {
|
||||
// Either we didn't recognize the gfxName, or we were unable to load the sprite's image.
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
QImage img;
|
||||
if (gfx->inanimate) {
|
||||
img = gfx->spritesheet.copy(0, 0, gfx->spriteWidth, gfx->spriteHeight);
|
||||
} else {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
// Get frame's position in spritesheet.
|
||||
// Assume horizontal layout. If position would exceed sheet width, try vertical layout.
|
||||
if ((frame + 1) * gfx->spriteWidth <= gfx->spritesheet.width()) {
|
||||
x = frame * gfx->spriteWidth;
|
||||
} else if ((frame + 1) * gfx->spriteHeight <= gfx->spritesheet.height()) {
|
||||
y = frame * gfx->spriteHeight;
|
||||
}
|
||||
|
||||
img = gfx->spritesheet.copy(x, y, gfx->spriteWidth, gfx->spriteHeight);
|
||||
if (hFlip) {
|
||||
img = img.transformed(QTransform().scale(-1, 1));
|
||||
}
|
||||
}
|
||||
// Set first palette color fully transparent.
|
||||
img.setColor(0, qRgba(0, 0, 0, 0));
|
||||
QPixmap pixmap = QPixmap::fromImage(img);
|
||||
|
||||
// TODO: Cache?
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QPixmap Project::getEventPixmap(Event::Group) {
|
||||
// TODO
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
bool Project::readSpeciesIconPaths() {
|
||||
this->speciesToIconPath.clear();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void DraggablePixmapItem::emitPositionChanged() {
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::updatePixmap() {
|
||||
editor->project->setEventPixmap(event, true);
|
||||
editor->project->loadEventPixmap(event, true);
|
||||
this->updatePosition();
|
||||
editor->redrawEventPixmapItem(this);
|
||||
emit spriteChanged(event->getPixmap());
|
||||
|
||||
@@ -517,7 +517,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
||||
|| (m_settings.showBGs && group == Event::Group::Bg)
|
||||
|| (m_settings.showTriggers && group == Event::Group::Coord)
|
||||
|| (m_settings.showHealLocations && group == Event::Group::Heal)) {
|
||||
m_editor->project->setEventPixmap(event);
|
||||
m_editor->project->loadEventPixmap(event);
|
||||
eventPainter.drawImage(QPoint(event->getPixelX() + pixelOffset, event->getPixelY() + pixelOffset), event->getPixmap().toImage());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user