Support reading/displaying custom border sizes

This commit is contained in:
GriffinR 2020-03-13 02:23:47 -04:00
parent a5c47b6333
commit 629abd3c06
9 changed files with 95 additions and 19 deletions

View file

@ -109,6 +109,8 @@ public:
void setUsePoryScript(bool usePoryScript); void setUsePoryScript(bool usePoryScript);
bool getUsePoryScript(); bool getUsePoryScript();
void setProjectDir(QString projectDir); void setProjectDir(QString projectDir);
void setUseCustomBorderSize(bool enable);
bool getUseCustomBorderSize();
protected: protected:
QString getConfigFilepath(); QString getConfigFilepath();
void parseConfigKeyValue(QString key, QString value); void parseConfigKeyValue(QString key, QString value);
@ -119,6 +121,7 @@ private:
QString projectDir; QString projectDir;
bool useEncounterJson; bool useEncounterJson;
bool usePoryScript; bool usePoryScript;
bool useCustomBorderSize;
}; };
extern ProjectConfig projectConfig; extern ProjectConfig projectConfig;

View file

@ -14,6 +14,9 @@
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <math.h> #include <math.h>
#define DEFAULT_BORDER_WIDTH 2
#define DEFAULT_BORDER_HEIGHT 2
class Map : public QObject class Map : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -58,6 +61,8 @@ public:
static QString bgEventsLabelFromName(QString mapName); static QString bgEventsLabelFromName(QString mapName);
int getWidth(); int getWidth();
int getHeight(); int getHeight();
int getBorderWidth();
int getBorderHeight();
QPixmap render(bool ignoreCache, MapLayout * fromLayout = nullptr); QPixmap render(bool ignoreCache, MapLayout * fromLayout = nullptr);
QPixmap renderCollision(qreal opacity, bool ignoreCache); QPixmap renderCollision(qreal opacity, bool ignoreCache);
bool blockChanged(int, Blockdata*); bool blockChanged(int, Blockdata*);

View file

@ -15,6 +15,8 @@ public:
QString name; QString name;
QString width; QString width;
QString height; QString height;
QString border_width;
QString border_height;
QString border_path; QString border_path;
QString blockdata_path; QString blockdata_path;
QString tileset_primary_label; QString tileset_primary_label;

View file

@ -356,12 +356,18 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
if (!ok) { if (!ok) {
logWarn(QString("Invalid config value for use_encounter_json: '%1'. Must be 0 or 1.").arg(value)); logWarn(QString("Invalid config value for use_encounter_json: '%1'. Must be 0 or 1.").arg(value));
} }
} else if(key == "use_poryscript") { } else if (key == "use_poryscript") {
bool ok; bool ok;
this->usePoryScript = value.toInt(&ok); this->usePoryScript = value.toInt(&ok);
if(!ok) { if (!ok) {
logWarn(QString("Invalid config value for use_poryscript: '%1'. Must be 0 or 1.").arg(value)); logWarn(QString("Invalid config value for use_poryscript: '%1'. Must be 0 or 1.").arg(value));
} }
} else if (key == "use_custom_border_size") {
bool ok;
this->useCustomBorderSize = value.toInt(&ok);
if (!ok) {
logWarn(QString("Invalid config value for use_custom_border_size: '%1'. Must be 0 or 1.").arg(value));
}
} else { } else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
} }
@ -372,6 +378,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
map.insert("base_game_version", baseGameVersionMap.value(this->baseGameVersion)); map.insert("base_game_version", baseGameVersionMap.value(this->baseGameVersion));
map.insert("use_encounter_json", QString::number(this->useEncounterJson)); map.insert("use_encounter_json", QString::number(this->useEncounterJson));
map.insert("use_poryscript", QString::number(this->usePoryScript)); map.insert("use_poryscript", QString::number(this->usePoryScript));
map.insert("use_custom_border_size", QString::number(this->useCustomBorderSize));
return map; return map;
} }
@ -401,6 +408,7 @@ void ProjectConfig::onNewConfigFileCreated() {
this->baseGameVersion = static_cast<BaseGameVersion>(baseGameVersionComboBox->currentData().toInt()); this->baseGameVersion = static_cast<BaseGameVersion>(baseGameVersionComboBox->currentData().toInt());
} }
} }
this->useCustomBorderSize = this->baseGameVersion == BaseGameVersion::pokefirered;
this->useEncounterJson = true; this->useEncounterJson = true;
this->usePoryScript = false; this->usePoryScript = false;
} }
@ -435,3 +443,12 @@ void ProjectConfig::setUsePoryScript(bool usePoryScript) {
bool ProjectConfig::getUsePoryScript() { bool ProjectConfig::getUsePoryScript() {
return this->usePoryScript; return this->usePoryScript;
} }
void ProjectConfig::setUseCustomBorderSize(bool enable) {
this->useCustomBorderSize = enable;
this->save();
}
bool ProjectConfig::getUseCustomBorderSize() {
return this->useCustomBorderSize;
}

View file

@ -59,6 +59,14 @@ int Map::getHeight() {
return layout->height.toInt(nullptr, 0); return layout->height.toInt(nullptr, 0);
} }
int Map::getBorderWidth() {
return layout->border_width.toInt(nullptr, 0);
}
int Map::getBorderHeight() {
return layout->border_height.toInt(nullptr, 0);
}
bool Map::blockChanged(int i, Blockdata *cache) { bool Map::blockChanged(int i, Blockdata *cache) {
if (!cache) if (!cache)
return true; return true;
@ -197,8 +205,8 @@ QPixmap Map::render(bool ignoreCache = false, MapLayout * fromLayout) {
QPixmap Map::renderBorder() { QPixmap Map::renderBorder() {
bool changed_any = false; bool changed_any = false;
int width_ = 2; int width_ = getBorderWidth();
int height_ = 2; int height_ = getBorderHeight();
if (layout->border_image.isNull()) { if (layout->border_image.isNull()) {
layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true; changed_any = true;

View file

@ -1335,8 +1335,8 @@ void Editor::displayMapBorder() {
borderItems.clear(); borderItems.clear();
QPixmap pixmap = map->renderBorder(); QPixmap pixmap = map->renderBorder();
for (int y = -6; y < map->getHeight() + 6; y += 2) for (int y = -6; y < map->getHeight() + 6; y += map->getBorderHeight())
for (int x = -6; x < map->getWidth() + 6; x += 2) { for (int x = -6; x < map->getWidth() + 6; x += map->getBorderWidth()) {
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
item->setX(x * 16); item->setX(x * 16);
item->setY(y * 16); item->setY(y * 16);

View file

@ -8,6 +8,7 @@
#include "tile.h" #include "tile.h"
#include "tileset.h" #include "tileset.h"
#include "imageexport.h" #include "imageexport.h"
#include "map.h"
#include <QDir> #include <QDir>
#include <QJsonArray> #include <QJsonArray>
@ -489,6 +490,11 @@ bool Project::readMapLayouts() {
"border_filepath", "border_filepath",
"blockdata_filepath", "blockdata_filepath",
}; };
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
if (useCustomBorderSize) {
requiredFields.append("border_width");
requiredFields.append("border_height");
}
for (int i = 0; i < layouts.size(); i++) { for (int i = 0; i < layouts.size(); i++) {
QJsonObject layoutObj = layouts[i].toObject(); QJsonObject layoutObj = layouts[i].toObject();
if (layoutObj.isEmpty()) if (layoutObj.isEmpty())
@ -520,6 +526,23 @@ bool Project::readMapLayouts() {
return false; return false;
} }
layout->height = QString::number(lheight); layout->height = QString::number(lheight);
if (useCustomBorderSize) {
int bwidth = layoutObj["border_width"].toInt();
if (bwidth <= 0) { // 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
logWarn(QString("Invalid layout 'border_width' value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bwidth).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_WIDTH));
bwidth = DEFAULT_BORDER_WIDTH;
}
layout->border_width = QString::number(bwidth);
int bheight = layoutObj["border_height"].toInt();
if (bheight <= 0) {
logWarn(QString("Invalid layout 'border_height value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bheight).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_HEIGHT));
bheight = DEFAULT_BORDER_HEIGHT;
}
layout->border_height = QString::number(bheight);
} else {
layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
}
layout->tileset_primary_label = layoutObj["primary_tileset"].toString(); layout->tileset_primary_label = layoutObj["primary_tileset"].toString();
if (layout->tileset_primary_label.isEmpty()) { if (layout->tileset_primary_label.isEmpty()) {
logError(QString("Missing 'primary_tileset' value on layout %1 in %2").arg(i).arg(layoutsFilepath)); logError(QString("Missing 'primary_tileset' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
@ -536,7 +559,7 @@ bool Project::readMapLayouts() {
return false; return false;
} }
layout->blockdata_path = layoutObj["blockdata_filepath"].toString(); layout->blockdata_path = layoutObj["blockdata_filepath"].toString();
if (layout->border_path.isEmpty()) { if (layout->blockdata_path.isEmpty()) {
logError(QString("Missing 'blockdata_filepath' value on layout %1 in %2").arg(i).arg(layoutsFilepath)); logError(QString("Missing 'blockdata_filepath' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false; return false;
} }
@ -563,6 +586,7 @@ void Project::saveMapLayouts() {
QJsonObject layoutsObj; QJsonObject layoutsObj;
layoutsObj["layouts_table_label"] = layoutsLabel; layoutsObj["layouts_table_label"] = layoutsLabel;
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
QJsonArray layoutsArr; QJsonArray layoutsArr;
for (QString layoutId : mapLayoutsTableMaster) { for (QString layoutId : mapLayoutsTableMaster) {
MapLayout *layout = mapLayouts.value(layoutId); MapLayout *layout = mapLayouts.value(layoutId);
@ -571,6 +595,10 @@ void Project::saveMapLayouts() {
layoutObj["name"] = layout->name; layoutObj["name"] = layout->name;
layoutObj["width"] = layout->width.toInt(nullptr, 0); layoutObj["width"] = layout->width.toInt(nullptr, 0);
layoutObj["height"] = layout->height.toInt(nullptr, 0); layoutObj["height"] = layout->height.toInt(nullptr, 0);
if (useCustomBorderSize) {
layoutObj["border_width"] = layout->border_width.toInt(nullptr, 0);
layoutObj["border_height"] = layout->border_height.toInt(nullptr, 0);
}
layoutObj["primary_tileset"] = layout->tileset_primary_label; layoutObj["primary_tileset"] = layout->tileset_primary_label;
layoutObj["secondary_tileset"] = layout->tileset_secondary_label; layoutObj["secondary_tileset"] = layout->tileset_secondary_label;
layoutObj["border_filepath"] = layout->border_path; layoutObj["border_filepath"] = layout->border_path;
@ -1034,7 +1062,7 @@ bool Project::loadMapBorder(Map *map) {
QString path = QString("%1/%2").arg(root).arg(map->layout->border_path); QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
map->layout->border = readBlockdata(path); map->layout->border = readBlockdata(path);
int borderLength = 4; int borderLength = map->getBorderWidth() * map->getBorderHeight();
if (map->layout->border->blocks->count() != borderLength) { if (map->layout->border->blocks->count() != borderLength) {
logWarn(QString("Layout border blockdata length %1 must be %2. Resizing border blockdata.") logWarn(QString("Layout border blockdata length %1 must be %2. Resizing border blockdata.")
.arg(map->layout->border->blocks->count()) .arg(map->layout->border->blocks->count())
@ -1046,10 +1074,17 @@ bool Project::loadMapBorder(Map *map) {
void Project::setNewMapBorder(Map *map) { void Project::setNewMapBorder(Map *map) {
Blockdata *blockdata = new Blockdata; Blockdata *blockdata = new Blockdata;
blockdata->addBlock(qint16(0x01D4)); if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
blockdata->addBlock(qint16(0x01D5)); blockdata->addBlock(qint16(0x0014));
blockdata->addBlock(qint16(0x01DC)); blockdata->addBlock(qint16(0x0015));
blockdata->addBlock(qint16(0x01DD)); blockdata->addBlock(qint16(0x001C));
blockdata->addBlock(qint16(0x001D));
} else {
blockdata->addBlock(qint16(0x01D4));
blockdata->addBlock(qint16(0x01D5));
blockdata->addBlock(qint16(0x01DC));
blockdata->addBlock(qint16(0x01DD));
}
map->layout->border = blockdata; map->layout->border = blockdata;
} }
@ -1136,6 +1171,10 @@ void Project::saveMap(Map *map) {
newLayoutObj["name"] = map->layout->name; newLayoutObj["name"] = map->layout->name;
newLayoutObj["width"] = map->layout->width.toInt(); newLayoutObj["width"] = map->layout->width.toInt();
newLayoutObj["height"] = map->layout->height.toInt(); newLayoutObj["height"] = map->layout->height.toInt();
if (projectConfig.getUseCustomBorderSize()) {
newLayoutObj["border_width"] = map->layout->border_width.toInt();
newLayoutObj["border_height"] = map->layout->border_height.toInt();
}
newLayoutObj["primary_tileset"] = map->layout->tileset_primary_label; newLayoutObj["primary_tileset"] = map->layout->tileset_primary_label;
newLayoutObj["secondary_tileset"] = map->layout->tileset_secondary_label; newLayoutObj["secondary_tileset"] = map->layout->tileset_secondary_label;
newLayoutObj["border_filepath"] = map->layout->border_path; newLayoutObj["border_filepath"] = map->layout->border_path;

View file

@ -9,9 +9,9 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
int x = static_cast<int>(pos.x()) / 16; int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16; int y = static_cast<int>(pos.y()) / 16;
for (int i = 0; i < selectionDimensions.x() && (i + x) < 2; i++) { for (int i = 0; i < selectionDimensions.x() && (i + x) < map->getBorderWidth(); i++) {
for (int j = 0; j < selectionDimensions.y() && (j + y) < 2; j++) { for (int j = 0; j < selectionDimensions.y() && (j + y) < map->getBorderHeight(); j++) {
int blockIndex = (j + y) * 2 + (i + x); int blockIndex = (j + y) * map->getBorderWidth() + (i + x);
uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i); uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
(*map->layout->border->blocks)[blockIndex].tile = tile; (*map->layout->border->blocks)[blockIndex].tile = tile;
} }
@ -22,15 +22,15 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
} }
void BorderMetatilesPixmapItem::draw() { void BorderMetatilesPixmapItem::draw() {
QImage image(32, 32, QImage::Format_RGBA8888); QImage image(16 * map->getBorderWidth(), 16 * map->getBorderHeight(), QImage::Format_RGBA8888);
QPainter painter(&image); QPainter painter(&image);
QVector<Block> *blocks = map->layout->border->blocks; QVector<Block> *blocks = map->layout->border->blocks;
for (int i = 0; i < 2; i++) { for (int i = 0; i < map->getBorderWidth(); i++) {
for (int j = 0; j < 2; j++) { for (int j = 0; j < map->getBorderHeight(); j++) {
int x = i * 16; int x = i * 16;
int y = j * 16; int y = j * 16;
int index = j * 2 + i; int index = j * map->getBorderWidth() + i;
QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary); QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary);
QPoint metatile_origin = QPoint(x, y); QPoint metatile_origin = QPoint(x, y);
painter.drawImage(metatile_origin, metatile_image); painter.drawImage(metatile_origin, metatile_image);

View file

@ -154,6 +154,8 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
layout->name = QString("%1_Layout").arg(newMap->name); layout->name = QString("%1_Layout").arg(newMap->name);
layout->width = QString::number(this->ui->spinBox_NewMap_Width->value()); layout->width = QString::number(this->ui->spinBox_NewMap_Width->value());
layout->height = QString::number(this->ui->spinBox_NewMap_Height->value()); layout->height = QString::number(this->ui->spinBox_NewMap_Height->value());
layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText(); layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText();
layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText(); layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText();
layout->border_path = QString("data/layouts/%1/border.bin").arg(newMapName); layout->border_path = QString("data/layouts/%1/border.bin").arg(newMapName);