mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-27 19:16:31 -05:00
Read MAP_OFFSET_W, MAP_OFFSET_H from project
This commit is contained in:
@@ -214,6 +214,8 @@ enum ProjectIdentifier {
|
||||
define_pals_total,
|
||||
define_tiles_per_metatile,
|
||||
define_map_size,
|
||||
define_map_offset_width,
|
||||
define_map_offset_height,
|
||||
define_mask_metatile,
|
||||
define_mask_collision,
|
||||
define_mask_elevation,
|
||||
|
||||
@@ -240,24 +240,27 @@ public:
|
||||
static QString getExistingFilepath(QString filepath);
|
||||
void applyParsedLimits();
|
||||
|
||||
int getMapDataSize(int width, int height) const;
|
||||
int getMaxMapDataSize() const { return this->maxMapDataSize; }
|
||||
int getMaxMapWidth() const;
|
||||
int getMaxMapHeight() const;
|
||||
bool mapDimensionsValid(int width, int height) const;
|
||||
bool calculateDefaultMapSize();
|
||||
int getDefaultMapDimension() const { return this->defaultMapDimension; }
|
||||
QSize getMapSizeAddition() const { return this->mapSizeAddition; }
|
||||
|
||||
int getMaxEvents(Event::Group group) const;
|
||||
|
||||
static QString getEmptyMapDefineName();
|
||||
static QString getDynamicMapDefineName();
|
||||
static QString getDynamicMapName();
|
||||
static QString getEmptySpeciesName();
|
||||
static int getNumTilesPrimary();
|
||||
static int getNumTilesTotal();
|
||||
static int getNumMetatilesPrimary();
|
||||
static int getNumMetatilesTotal();
|
||||
static int getNumPalettesPrimary();
|
||||
static int getNumPalettesTotal();
|
||||
static int getMaxMapDataSize();
|
||||
static int getDefaultMapDimension();
|
||||
static int getMaxMapWidth();
|
||||
static int getMaxMapHeight();
|
||||
static int getMapDataSize(int width, int height);
|
||||
static bool mapDimensionsValid(int width, int height);
|
||||
bool calculateDefaultMapSize();
|
||||
int getMaxEvents(Event::Group group);
|
||||
static int getNumTilesPrimary() { return num_tiles_primary; }
|
||||
static int getNumTilesTotal() { return num_tiles_total; }
|
||||
static int getNumMetatilesPrimary() { return num_metatiles_primary; }
|
||||
static int getNumMetatilesTotal() { return Block::getMaxMetatileId() + 1; }
|
||||
static int getNumPalettesPrimary(){ return num_pals_primary; }
|
||||
static int getNumPalettesTotal() { return num_pals_total; }
|
||||
static QString getEmptyMapsecName();
|
||||
static QString getMapGroupPrefix();
|
||||
|
||||
@@ -302,15 +305,19 @@ private:
|
||||
|
||||
QString findSpeciesIconPath(const QStringList &names) const;
|
||||
|
||||
int maxEventsPerGroup;
|
||||
int maxObjectEvents;
|
||||
QSize mapSizeAddition;
|
||||
int maxMapDataSize;
|
||||
int defaultMapDimension;
|
||||
|
||||
// TODO: These really shouldn't be static, they're specific to a single project.
|
||||
// We're making an assumption here that we only have one project open at a single time
|
||||
// (which is true, but then if that's the case we should have some global Project instance instead)
|
||||
static int num_tiles_primary;
|
||||
static int num_tiles_total;
|
||||
static int num_metatiles_primary;
|
||||
static int num_pals_primary;
|
||||
static int num_pals_total;
|
||||
static int max_map_data_size;
|
||||
static int default_map_dimension;
|
||||
|
||||
signals:
|
||||
void fileChanged(const QString &filepath);
|
||||
|
||||
@@ -89,6 +89,8 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
||||
{ProjectIdentifier::define_pals_total, {"define_pals_total", "NUM_PALS_TOTAL"}},
|
||||
{ProjectIdentifier::define_tiles_per_metatile, {"define_tiles_per_metatile", "NUM_TILES_PER_METATILE"}},
|
||||
{ProjectIdentifier::define_map_size, {"define_map_size", "MAX_MAP_DATA_SIZE"}},
|
||||
{ProjectIdentifier::define_map_offset_width, {"define_map_offset_width", "MAP_OFFSET_W"}},
|
||||
{ProjectIdentifier::define_map_offset_height, {"define_map_offset_height", "MAP_OFFSET_H"}},
|
||||
{ProjectIdentifier::define_mask_metatile, {"define_mask_metatile", "MAPGRID_METATILE_ID_MASK"}},
|
||||
{ProjectIdentifier::define_mask_collision, {"define_mask_collision", "MAPGRID_COLLISION_MASK"}},
|
||||
{ProjectIdentifier::define_mask_elevation, {"define_mask_elevation", "MAPGRID_ELEVATION_MASK"}},
|
||||
|
||||
119
src/project.cpp
119
src/project.cpp
@@ -29,8 +29,6 @@ int Project::num_tiles_total = 1024;
|
||||
int Project::num_metatiles_primary = 512;
|
||||
int Project::num_pals_primary = 6;
|
||||
int Project::num_pals_total = 13;
|
||||
int Project::max_map_data_size = 10240; // 0x2800
|
||||
int Project::default_map_dimension = 20;
|
||||
|
||||
Project::Project(QObject *parent) :
|
||||
QObject(parent),
|
||||
@@ -2109,7 +2107,12 @@ bool Project::readFieldmapProperties() {
|
||||
const QString numPalsTotalName = projectConfig.getIdentifier(ProjectIdentifier::define_pals_total);
|
||||
const QString maxMapSizeName = projectConfig.getIdentifier(ProjectIdentifier::define_map_size);
|
||||
const QString numTilesPerMetatileName = projectConfig.getIdentifier(ProjectIdentifier::define_tiles_per_metatile);
|
||||
const QSet<QString> names = {
|
||||
const QString mapOffsetWidthName = projectConfig.getIdentifier(ProjectIdentifier::define_map_offset_width);
|
||||
const QString mapOffsetHeightName = projectConfig.getIdentifier(ProjectIdentifier::define_map_offset_height);
|
||||
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
const QMap<QString, int> defines = parser.readCDefinesByName(filename, {
|
||||
numTilesPrimaryName,
|
||||
numTilesTotalName,
|
||||
numMetatilesPrimaryName,
|
||||
@@ -2117,10 +2120,9 @@ bool Project::readFieldmapProperties() {
|
||||
numPalsTotalName,
|
||||
maxMapSizeName,
|
||||
numTilesPerMetatileName,
|
||||
};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
const QMap<QString, int> defines = parser.readCDefinesByName(filename, names);
|
||||
mapOffsetWidthName,
|
||||
mapOffsetHeightName,
|
||||
});
|
||||
|
||||
auto loadDefine = [defines](const QString name, int * dest, int min, int max) {
|
||||
auto it = defines.find(name);
|
||||
@@ -2146,25 +2148,35 @@ bool Project::readFieldmapProperties() {
|
||||
// we don't actually know what the maximum number of metatiles is.
|
||||
loadDefine(numMetatilesPrimaryName, &Project::num_metatiles_primary, 1, 0xFFFF - 1);
|
||||
|
||||
int w = 15, h = 14; // Default values of MAP_OFFSET_W, MAP_OFFSET_H
|
||||
loadDefine(mapOffsetWidthName, &w, 0, INT_MAX);
|
||||
loadDefine(mapOffsetHeightName, &h, 0, INT_MAX);
|
||||
this->mapSizeAddition = QSize(w, h);
|
||||
|
||||
this->maxMapDataSize = 10240; // Default value of MAX_MAP_DATA_SIZE
|
||||
this->defaultMapDimension = 20; // Arbitrary default of 20x20.
|
||||
auto it = defines.find(maxMapSizeName);
|
||||
if (it != defines.end()) {
|
||||
int min = getMapDataSize(1, 1);
|
||||
if (it.value() >= min) {
|
||||
Project::max_map_data_size = it.value();
|
||||
calculateDefaultMapSize();
|
||||
this->maxMapDataSize = it.value();
|
||||
if (getMapDataSize(this->defaultMapDimension, this->defaultMapDimension) > this->maxMapDataSize) {
|
||||
// The specified map size is too small to use the default map dimensions.
|
||||
// Calculate the largest square map size that we can use instead.
|
||||
this->defaultMapDimension = qFloor((qSqrt(4 * this->maxMapDataSize + 1) - (w + h)) / 2);
|
||||
}
|
||||
} else {
|
||||
// must be large enough to support a 1x1 map
|
||||
logWarn(QString("Value for map property '%1' is %2, must be at least %3. Using default (%4) instead.")
|
||||
logWarn(QString("Value for map property '%1' of %2 is too small to support a 1x1 map. Must be at least %3. Using default (%4) instead.")
|
||||
.arg(maxMapSizeName)
|
||||
.arg(it.value())
|
||||
.arg(min)
|
||||
.arg(Project::max_map_data_size));
|
||||
.arg(this->maxMapDataSize));
|
||||
}
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for map property '%1' not found. Using default (%2) instead.")
|
||||
.arg(maxMapSizeName)
|
||||
.arg(Project::max_map_data_size));
|
||||
.arg(this->maxMapDataSize));
|
||||
}
|
||||
|
||||
it = defines.find(numTilesPerMetatileName);
|
||||
@@ -3112,91 +3124,28 @@ QPixmap Project::getSpeciesIcon(const QString &species) {
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
int Project::getNumTilesPrimary()
|
||||
{
|
||||
return Project::num_tiles_primary;
|
||||
int Project::getMapDataSize(int width, int height) const {
|
||||
return (width + this->mapSizeAddition.width())
|
||||
* (height + this->mapSizeAddition.height());
|
||||
}
|
||||
|
||||
int Project::getNumTilesTotal()
|
||||
{
|
||||
return Project::num_tiles_total;
|
||||
int Project::getMaxMapWidth() const {
|
||||
return (getMaxMapDataSize() / (1 + this->mapSizeAddition.height())) - this->mapSizeAddition.width();
|
||||
}
|
||||
|
||||
int Project::getNumMetatilesPrimary()
|
||||
{
|
||||
return Project::num_metatiles_primary;
|
||||
int Project::getMaxMapHeight() const {
|
||||
return (getMaxMapDataSize() / (1 + this->mapSizeAddition.width())) - this->mapSizeAddition.height();
|
||||
}
|
||||
|
||||
int Project::getNumMetatilesTotal()
|
||||
{
|
||||
return Block::getMaxMetatileId() + 1;
|
||||
}
|
||||
|
||||
int Project::getNumPalettesPrimary()
|
||||
{
|
||||
return Project::num_pals_primary;
|
||||
}
|
||||
|
||||
int Project::getNumPalettesTotal()
|
||||
{
|
||||
return Project::num_pals_total;
|
||||
}
|
||||
|
||||
int Project::getMaxMapDataSize()
|
||||
{
|
||||
return Project::max_map_data_size;
|
||||
}
|
||||
|
||||
int Project::getMapDataSize(int width, int height)
|
||||
{
|
||||
// + 15 and + 14 come from fieldmap.c in pokeruby/pokeemerald/pokefirered.
|
||||
return (width + 15) * (height + 14);
|
||||
}
|
||||
|
||||
int Project::getDefaultMapDimension()
|
||||
{
|
||||
return Project::default_map_dimension;
|
||||
}
|
||||
|
||||
int Project::getMaxMapWidth()
|
||||
{
|
||||
return (getMaxMapDataSize() / (1 + 14)) - 15;
|
||||
}
|
||||
|
||||
int Project::getMaxMapHeight()
|
||||
{
|
||||
return (getMaxMapDataSize() / (1 + 15)) - 14;
|
||||
}
|
||||
|
||||
bool Project::mapDimensionsValid(int width, int height) {
|
||||
bool Project::mapDimensionsValid(int width, int height) const {
|
||||
return getMapDataSize(width, height) <= getMaxMapDataSize();
|
||||
}
|
||||
|
||||
// Get largest possible square dimensions for a map up to maximum of 20x20 (arbitrary)
|
||||
bool Project::calculateDefaultMapSize(){
|
||||
int max = getMaxMapDataSize();
|
||||
|
||||
if (max >= getMapDataSize(20, 20)) {
|
||||
default_map_dimension = 20;
|
||||
} else if (max >= getMapDataSize(1, 1)) {
|
||||
// Below equation derived from max >= (x + 15) * (x + 14)
|
||||
// x^2 + 29x + (210 - max), then complete the square and simplify
|
||||
default_map_dimension = qFloor((qSqrt(4 * getMaxMapDataSize() + 1) - 29) / 2);
|
||||
} else {
|
||||
logError(QString("'%1' of %2 is too small to support a 1x1 map. Must be at least %3.")
|
||||
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_size))
|
||||
.arg(max)
|
||||
.arg(getMapDataSize(1, 1)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object events have their own limit specified by ProjectIdentifier::define_obj_event_count.
|
||||
// The default value for this is 64. All events (object events included) are also limited by
|
||||
// the data types of the event counters in the project. This would normally be u8, so the limit is 255.
|
||||
// We let the users tell us this limit in case they change these data types.
|
||||
int Project::getMaxEvents(Event::Group group) {
|
||||
int Project::getMaxEvents(Event::Group group) const {
|
||||
if (group == Event::Group::Object)
|
||||
return qMin(this->maxObjectEvents, projectConfig.maxEventsPerGroup);
|
||||
return projectConfig.maxEventsPerGroup;
|
||||
|
||||
@@ -227,7 +227,7 @@ int MainWindow::getHeight() {
|
||||
void MainWindow::setDimensions(int width, int height) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(width, height))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(width, height))
|
||||
return;
|
||||
this->editor->layout->setDimensions(width, height);
|
||||
this->tryCommitMapChanges(true);
|
||||
@@ -237,7 +237,7 @@ void MainWindow::setDimensions(int width, int height) {
|
||||
void MainWindow::setWidth(int width) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(width, this->editor->layout->getHeight()))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(width, this->editor->layout->getHeight()))
|
||||
return;
|
||||
this->editor->layout->setDimensions(width, this->editor->layout->getHeight());
|
||||
this->tryCommitMapChanges(true);
|
||||
@@ -247,7 +247,7 @@ void MainWindow::setWidth(int width) {
|
||||
void MainWindow::setHeight(int height) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(this->editor->layout->getWidth(), height))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(this->editor->layout->getWidth(), height))
|
||||
return;
|
||||
this->editor->layout->setDimensions(this->editor->layout->getWidth(), height);
|
||||
this->tryCommitMapChanges(true);
|
||||
|
||||
@@ -86,17 +86,14 @@ bool NewLayoutForm::validateMapDimensions() {
|
||||
int size = m_project->getMapDataSize(ui->spinBox_MapWidth->value(), ui->spinBox_MapHeight->value());
|
||||
int maxSize = m_project->getMaxMapDataSize();
|
||||
|
||||
// TODO: Get from project
|
||||
const int additionalWidth = 15;
|
||||
const int additionalHeight = 14;
|
||||
|
||||
QString errorText;
|
||||
if (size > maxSize) {
|
||||
QSize addition = m_project->getMapSizeAddition();
|
||||
errorText = QString("The specified width and height are too large.\n"
|
||||
"The maximum map width and height is the following: (width + %1) * (height + %2) <= %3\n"
|
||||
"The specified map width and height was: (%4 + %1) * (%5 + %2) = %6")
|
||||
.arg(additionalWidth)
|
||||
.arg(additionalHeight)
|
||||
.arg(addition.width())
|
||||
.arg(addition.height())
|
||||
.arg(maxSize)
|
||||
.arg(ui->spinBox_MapWidth->value())
|
||||
.arg(ui->spinBox_MapHeight->value())
|
||||
|
||||
@@ -145,15 +145,18 @@ void ResizeLayoutPopup::setupLayoutView() {
|
||||
// Upper limits: maximum metatiles in a map formula:
|
||||
// max = (width + 15) * (height + 14)
|
||||
// This limit can be found in fieldmap.c in pokeruby/pokeemerald/pokefirered.
|
||||
int numMetatiles = editor->project->getMapDataSize(rect.width() / 16, rect.height() / 16);
|
||||
int maxMetatiles = editor->project->getMaxMapDataSize();
|
||||
if (numMetatiles > maxMetatiles) {
|
||||
QString errorText = QString("The maximum layout width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
||||
"The specified layout width and height was: (%2 + 15) * (%3 + 14) = %4")
|
||||
.arg(maxMetatiles)
|
||||
int size = editor->project->getMapDataSize(rect.width() / 16, rect.height() / 16);
|
||||
int maxSize = editor->project->getMaxMapDataSize();
|
||||
if (size > maxSize) {
|
||||
QSize addition = editor->project->getMapSizeAddition();
|
||||
QString errorText = QString("The maximum layout width and height is the following: (width + %1) * (height + %2) <= %3\n"
|
||||
"The specified layout width and height was: (%4 + %1) * (%5 + %2) = %6")
|
||||
.arg(addition.width())
|
||||
.arg(addition.height())
|
||||
.arg(maxSize)
|
||||
.arg(rect.width() / 16)
|
||||
.arg(rect.height() / 16)
|
||||
.arg(numMetatiles);
|
||||
.arg(size);
|
||||
QMessageBox warning;
|
||||
warning.setIcon(QMessageBox::Warning);
|
||||
warning.setText("The specified width and height are too large.");
|
||||
|
||||
Reference in New Issue
Block a user