Simplify metatile attribute layouts

This commit is contained in:
GriffinR 2022-10-26 04:13:53 -04:00
parent 9cd8777246
commit 577dc2fce2
5 changed files with 145 additions and 134 deletions

View file

@ -30,6 +30,29 @@ enum {
NUM_METATILE_TERRAIN_TYPES NUM_METATILE_TERRAIN_TYPES
}; };
class MetatileAttr
{
public:
MetatileAttr();
MetatileAttr(uint32_t mask, int shift);
public:
uint32_t mask;
int shift;
// Given the raw value for all attributes of a metatile
// Returns the extracted value for this attribute
uint32_t fromRaw(uint32_t raw) const { return (raw & this->mask) >> this->shift; }
// Given a value for this attribute
// Returns the raw value to OR together with the other attributes
uint32_t toRaw(uint32_t value) const { return (value << this->shift) & this->mask; }
// Given an arbitrary value to set for an attribute
// Returns a bounded value for that attribute
uint32_t getClamped(int value) const { return static_cast<uint32_t>(value) & (this->mask >> this->shift); }
};
class Metatile class Metatile
{ {
public: public:
@ -47,30 +70,23 @@ public:
uint32_t unusedAttributes; uint32_t unusedAttributes;
QString label; QString label;
enum Attr {
Behavior,
TerrainType,
EncounterType,
LayerType,
};
struct AttrLayout {
uint32_t mask;
int shift;
};
static const QHash<Metatile::Attr, Metatile::AttrLayout> defaultLayoutFRLG;
static const QHash<Metatile::Attr, Metatile::AttrLayout> defaultLayoutRSE;
static QHash<Metatile::Attr, Metatile::AttrLayout> customLayout;
uint32_t getAttributes(); uint32_t getAttributes();
void setAttributes(uint32_t data); void setAttributes(uint32_t data);
void convertAttributes(uint32_t data, BaseGameVersion version); void setAttributes(uint32_t data, BaseGameVersion version);
void setBehavior(uint32_t); void setBehavior(int value) { this->behavior = behaviorAttr.getClamped(value); }
void setTerrainType(uint32_t); void setTerrainType(int value) { this->terrainType = terrainTypeAttr.getClamped(value); }
void setEncounterType(uint32_t); void setEncounterType(int value) { this->encounterType = encounterTypeAttr.getClamped(value); }
void setLayerType(uint32_t); void setLayerType(int value) { this->layerType = layerTypeAttr.getClamped(value); }
static uint32_t getBehaviorMask() { return behaviorAttr.mask; }
static uint32_t getTerrainTypeMask() { return terrainTypeAttr.mask; }
static uint32_t getEncounterTypeMask() { return encounterTypeAttr.mask; }
static uint32_t getLayerTypeMask() { return layerTypeAttr.mask; }
static uint32_t getBehaviorMask(BaseGameVersion version);
static uint32_t getTerrainTypeMask(BaseGameVersion version);
static uint32_t getEncounterTypeMask(BaseGameVersion version);
static uint32_t getLayerTypeMask(BaseGameVersion version);
static int getIndexInTileset(int); static int getIndexInTileset(int);
static QPoint coordFromPixmapCoord(const QPointF &pixelCoord); static QPoint coordFromPixmapCoord(const QPointF &pixelCoord);
@ -78,11 +94,22 @@ public:
static void setCustomLayout(); static void setCustomLayout();
private: private:
// Stores how each attribute should be laid out for all metatiles, according to the user's config
static MetatileAttr behaviorAttr;
static MetatileAttr terrainTypeAttr;
static MetatileAttr encounterTypeAttr;
static MetatileAttr layerTypeAttr;
static uint32_t unusedAttrMask; static uint32_t unusedAttrMask;
void setAttributes(uint32_t, const QHash<Metatile::Attr, Metatile::AttrLayout>*); // Stores how each attribute should be laid out for all metatiles, according to the vanilla games
static void setCustomAttributeLayout(Metatile::AttrLayout *, uint32_t, uint32_t); // Used to set default config values and import maps with AdvanceMap
static bool isMaskTooSmall(Metatile::AttrLayout * layout, int n); static const QHash<QString, MetatileAttr> defaultLayoutFRLG;
static const QHash<QString, MetatileAttr> defaultLayoutRSE;
static const QHash<BaseGameVersion, const QHash<QString, MetatileAttr>*> defaultLayouts;
static void setCustomAttributeLayout(MetatileAttr *, uint32_t, uint32_t);
static bool isMaskTooSmall(MetatileAttr *, int);
static bool doMasksOverlap(QList<uint32_t>); static bool doMasksOverlap(QList<uint32_t>);
}; };

View file

@ -627,11 +627,10 @@ void ProjectConfig::setUnreadKeys() {
if (!readKeys.contains("new_map_border_metatiles")) this->newMapBorderMetatileIds = isPokefirered ? DEFAULT_BORDER_FRLG : DEFAULT_BORDER_RSE; if (!readKeys.contains("new_map_border_metatiles")) this->newMapBorderMetatileIds = isPokefirered ? DEFAULT_BORDER_FRLG : DEFAULT_BORDER_RSE;
if (!readKeys.contains("default_secondary_tileset")) this->defaultSecondaryTileset = isPokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg"; if (!readKeys.contains("default_secondary_tileset")) this->defaultSecondaryTileset = isPokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg";
if (!readKeys.contains("metatile_attributes_size")) this->metatileAttributesSize = Metatile::getDefaultAttributesSize(this->baseGameVersion); if (!readKeys.contains("metatile_attributes_size")) this->metatileAttributesSize = Metatile::getDefaultAttributesSize(this->baseGameVersion);
const QHash<Metatile::Attr, Metatile::AttrLayout> layout = isPokefirered ? Metatile::defaultLayoutFRLG : Metatile::defaultLayoutRSE; if (!readKeys.contains("metatile_behavior_mask")) this->metatileBehaviorMask = Metatile::getBehaviorMask(this->baseGameVersion);
if (!readKeys.contains("metatile_behavior_mask")) this->metatileBehaviorMask = layout[Metatile::Attr::Behavior].mask; if (!readKeys.contains("metatile_terrain_type_mask")) this->metatileTerrainTypeMask = Metatile::getTerrainTypeMask(this->baseGameVersion);
if (!readKeys.contains("metatile_terrain_type_mask")) this->metatileTerrainTypeMask = layout[Metatile::Attr::TerrainType].mask; if (!readKeys.contains("metatile_encounter_type_mask")) this->metatileEncounterTypeMask = Metatile::getEncounterTypeMask(this->baseGameVersion);
if (!readKeys.contains("metatile_encounter_type_mask")) this->metatileEncounterTypeMask = layout[Metatile::Attr::EncounterType].mask; if (!readKeys.contains("metatile_layer_type_mask")) this-> metatileLayerTypeMask = Metatile::getLayerTypeMask(this->baseGameVersion);
if (!readKeys.contains("metatile_layer_type_mask")) this-> metatileLayerTypeMask = layout[Metatile::Attr::LayerType].mask;
if (!readKeys.contains("enable_map_allow_flags")) this->enableMapAllowFlags = (this->baseGameVersion != BaseGameVersion::pokeruby); if (!readKeys.contains("enable_map_allow_flags")) this->enableMapAllowFlags = (this->baseGameVersion != BaseGameVersion::pokeruby);
} }

View file

@ -2,22 +2,42 @@
#include "tileset.h" #include "tileset.h"
#include "project.h" #include "project.h"
QHash<Metatile::Attr, Metatile::AttrLayout> Metatile::customLayout = {}; const QHash<QString, MetatileAttr> Metatile::defaultLayoutFRLG = {
{"behavior", MetatileAttr(0x000001FF, 0) },
{"terrainType", MetatileAttr(0x00003E00, 9) },
{"encounterType", MetatileAttr(0x07000000, 24) },
{"layerType", MetatileAttr(0x60000000, 29) },
};
const QHash<QString, MetatileAttr> Metatile::defaultLayoutRSE = {
{"behavior", MetatileAttr(0x00FF, 0) },
{"terrainType", MetatileAttr() },
{"encounterType", MetatileAttr() },
{"layerType", MetatileAttr(0xF000, 12) },
};
const QHash<BaseGameVersion, const QHash<QString, MetatileAttr>*> Metatile::defaultLayouts = {
{ BaseGameVersion::pokeruby, &defaultLayoutRSE },
{ BaseGameVersion::pokefirered, &defaultLayoutFRLG },
{ BaseGameVersion::pokeemerald, &defaultLayoutRSE },
};
MetatileAttr Metatile::behaviorAttr;
MetatileAttr Metatile::terrainTypeAttr;
MetatileAttr Metatile::encounterTypeAttr;
MetatileAttr Metatile::layerTypeAttr;
uint32_t Metatile::unusedAttrMask = 0; uint32_t Metatile::unusedAttrMask = 0;
const QHash<Metatile::Attr, Metatile::AttrLayout> Metatile::defaultLayoutFRLG = { MetatileAttr::MetatileAttr() :
{Metatile::Attr::Behavior, { .mask = 0x000001FF, .shift = 0} }, mask(0),
{Metatile::Attr::TerrainType, { .mask = 0x00003E00, .shift = 9} }, shift(0)
{Metatile::Attr::EncounterType, { .mask = 0x07000000, .shift = 24} }, { }
{Metatile::Attr::LayerType, { .mask = 0x60000000, .shift = 29} },
};
const QHash<Metatile::Attr, Metatile::AttrLayout> Metatile::defaultLayoutRSE = { MetatileAttr::MetatileAttr(uint32_t mask, int shift) :
{Metatile::Attr::Behavior, { .mask = 0x000000FF, .shift = 0} }, mask(mask),
{Metatile::Attr::TerrainType, { .mask = 0x00000000, .shift = 0} }, shift(shift)
{Metatile::Attr::EncounterType, { .mask = 0x00000000, .shift = 0} }, { }
{Metatile::Attr::LayerType, { .mask = 0x0000F000, .shift = 12} },
};
Metatile::Metatile() : Metatile::Metatile() :
behavior(0), behavior(0),
@ -48,19 +68,14 @@ int Metatile::getIndexInTileset(int metatileId) {
} }
} }
// Get the vanilla attribute sizes based on version.
// Used as a default in the config and for AdvanceMap import.
int Metatile::getDefaultAttributesSize(BaseGameVersion version) {
return (version == BaseGameVersion::pokefirered) ? 4 : 2;
}
QPoint Metatile::coordFromPixmapCoord(const QPointF &pixelCoord) { QPoint Metatile::coordFromPixmapCoord(const QPointF &pixelCoord) {
int x = static_cast<int>(pixelCoord.x()) / 16; int x = static_cast<int>(pixelCoord.x()) / 16;
int y = static_cast<int>(pixelCoord.y()) / 16; int y = static_cast<int>(pixelCoord.y()) / 16;
return QPoint(x, y); return QPoint(x, y);
} }
void Metatile::setCustomAttributeLayout(Metatile::AttrLayout * layout, uint32_t mask, uint32_t max) { // Set the layout of a metatile attribute using the mask read from the config file
void Metatile::setCustomAttributeLayout(MetatileAttr * attr, uint32_t mask, uint32_t max) {
if (mask > max) { if (mask > max) {
uint32_t oldMask = mask; uint32_t oldMask = mask;
mask &= max; mask &= max;
@ -68,15 +83,22 @@ void Metatile::setCustomAttributeLayout(Metatile::AttrLayout * layout, uint32_t
.arg(QString::number(oldMask, 16).toUpper()) .arg(QString::number(oldMask, 16).toUpper())
.arg(QString::number(mask, 16).toUpper())); .arg(QString::number(mask, 16).toUpper()));
} }
layout->mask = mask; attr->mask = mask;
layout->shift = log2(mask & ~(mask - 1)); // Get the position of the rightmost set bit attr->shift = mask ? log2(mask & ~(mask - 1)) : 0; // Get position of the least significant set bit
} }
// For checking whether a metatile attribute mask can contain all the hard-coded values // For checking whether a metatile attribute mask can contain all the available hard-coded options
bool Metatile::isMaskTooSmall(Metatile::AttrLayout * layout, int n) { bool Metatile::isMaskTooSmall(MetatileAttr * attr, int max) {
if (!layout->mask) return false; if (attr->mask == 0 || max <= 0) return false;
uint32_t maxValue = n - 1;
return (maxValue & (layout->mask >> layout->shift)) != maxValue; // Get position of the most significant set bit
uint32_t n = log2(max);
// Get a mask for all values 0 to max.
// This may fail for n=31, but that's not a concern here.
uint32_t rangeMask = (1 << (n + 1)) - 1;
return attr->getClamped(rangeMask) != rangeMask;
} }
bool Metatile::doMasksOverlap(QList<uint32_t> masks) { bool Metatile::doMasksOverlap(QList<uint32_t> masks) {
@ -98,107 +120,70 @@ void Metatile::setCustomLayout() {
const uint32_t maxMask = maxMasks.value(projectConfig.getMetatileAttributesSize(), 0); const uint32_t maxMask = maxMasks.value(projectConfig.getMetatileAttributesSize(), 0);
// Set custom attribute masks from the config file // Set custom attribute masks from the config file
setCustomAttributeLayout(&customLayout[Attr::Behavior], projectConfig.getMetatileBehaviorMask(), maxMask); setCustomAttributeLayout(&Metatile::behaviorAttr, projectConfig.getMetatileBehaviorMask(), maxMask);
setCustomAttributeLayout(&customLayout[Attr::TerrainType], projectConfig.getMetatileTerrainTypeMask(), maxMask); setCustomAttributeLayout(&Metatile::terrainTypeAttr, projectConfig.getMetatileTerrainTypeMask(), maxMask);
setCustomAttributeLayout(&customLayout[Attr::EncounterType], projectConfig.getMetatileEncounterTypeMask(), maxMask); setCustomAttributeLayout(&Metatile::encounterTypeAttr, projectConfig.getMetatileEncounterTypeMask(), maxMask);
setCustomAttributeLayout(&customLayout[Attr::LayerType], projectConfig.getMetatileLayerTypeMask(), maxMask); setCustomAttributeLayout(&Metatile::layerTypeAttr, projectConfig.getMetatileLayerTypeMask(), maxMask);
// Set mask for preserving any attribute bits not used by Porymap // Set mask for preserving any attribute bits not used by Porymap
Metatile::unusedAttrMask = ~(customLayout[Attr::Behavior].mask Metatile::unusedAttrMask = ~(getBehaviorMask() | getTerrainTypeMask() | getEncounterTypeMask() | getLayerTypeMask());
| customLayout[Attr::TerrainType].mask
| customLayout[Attr::EncounterType].mask
| customLayout[Attr::LayerType].mask);
Metatile::unusedAttrMask &= maxMask; Metatile::unusedAttrMask &= maxMask;
// Overlapping masks are technically ok, but probably not intended. // Overlapping masks are technically ok, but probably not intended.
// Additionally, Porymap will not properly reflect that the values are linked. // Additionally, Porymap will not properly reflect that the values are linked.
if (doMasksOverlap({customLayout[Attr::Behavior].mask, if (doMasksOverlap({getBehaviorMask(), getTerrainTypeMask(), getEncounterTypeMask(), getLayerTypeMask()})) {
customLayout[Attr::TerrainType].mask, logWarn("Metatile attribute masks are overlapping. This may result in unexpected attribute values.");
customLayout[Attr::EncounterType].mask,
customLayout[Attr::LayerType].mask})) {
logWarn("Metatile attribute masks are overlapping.");
} }
// The available options in the Tileset Editor for Terrain Type, Encounter Type, and Layer Type are hard-coded. // The available options in the Tileset Editor for Terrain Type, Encounter Type, and Layer Type are hard-coded.
// Warn the user if they have set a nonzero mask that is too small to contain these options. // Warn the user if they have set a nonzero mask that is too small to contain these options.
// They'll be allowed to select them, but they'll be truncated to a different value when revisited. // They'll be allowed to select them, but they'll be truncated to a different value when revisited.
if (isMaskTooSmall(&customLayout[Attr::TerrainType], NUM_METATILE_TERRAIN_TYPES)) if (isMaskTooSmall(&Metatile::terrainTypeAttr, NUM_METATILE_TERRAIN_TYPES - 1))
logWarn(QString("Metatile Terrain Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_TERRAIN_TYPES)); logWarn(QString("Metatile Terrain Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_TERRAIN_TYPES));
if (isMaskTooSmall(&customLayout[Attr::EncounterType], NUM_METATILE_ENCOUNTER_TYPES)) if (isMaskTooSmall(&Metatile::encounterTypeAttr, NUM_METATILE_ENCOUNTER_TYPES - 1))
logWarn(QString("Metatile Encounter Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_ENCOUNTER_TYPES)); logWarn(QString("Metatile Encounter Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_ENCOUNTER_TYPES));
if (isMaskTooSmall(&customLayout[Attr::LayerType], NUM_METATILE_LAYER_TYPES)) if (isMaskTooSmall(&Metatile::layerTypeAttr, NUM_METATILE_LAYER_TYPES - 1))
logWarn(QString("Metatile Layer Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_LAYER_TYPES)); logWarn(QString("Metatile Layer Type mask is too small to contain all %1 available options.").arg(NUM_METATILE_LAYER_TYPES));
} }
uint32_t Metatile::getAttributes() { uint32_t Metatile::getAttributes() {
uint32_t attributes = this->unusedAttributes & Metatile::unusedAttrMask; uint32_t attributes = this->unusedAttributes & Metatile::unusedAttrMask;
attributes |= Metatile::behaviorAttr.toRaw(this->behavior);
// Behavior attributes |= Metatile::terrainTypeAttr.toRaw(this->terrainType);
Metatile::AttrLayout attr = Metatile::customLayout[Attr::Behavior]; attributes |= Metatile::encounterTypeAttr.toRaw(this->encounterType);
attributes |= (this->behavior << attr.shift) & attr.mask; attributes |= Metatile::layerTypeAttr.toRaw(this->layerType);
// Terrain Type
attr = Metatile::customLayout[Attr::TerrainType];
attributes |= (this->terrainType << attr.shift) & attr.mask;
// Encounter Type
attr = Metatile::customLayout[Attr::EncounterType];
attributes |= (this->encounterType << attr.shift) & attr.mask;
// Layer Type
attr = Metatile::customLayout[Attr::LayerType];
attributes |= (this->layerType << attr.shift) & attr.mask;
return attributes; return attributes;
} }
void Metatile::setAttributes(uint32_t data, const QHash<Metatile::Attr, Metatile::AttrLayout> * layout) { void Metatile::setAttributes(uint32_t data) {
// Behavior this->behavior = Metatile::behaviorAttr.fromRaw(data);
Metatile::AttrLayout attr = layout->value(Attr::Behavior); this->terrainType = Metatile::terrainTypeAttr.fromRaw(data);
this->behavior = (data & attr.mask) >> attr.shift; this->encounterType = Metatile::encounterTypeAttr.fromRaw(data);
this->layerType = Metatile::layerTypeAttr.fromRaw(data);
// Terrain Type
attr = layout->value(Attr::TerrainType);
this->terrainType = (data & attr.mask) >> attr.shift;
// Encounter Type
attr = layout->value(Attr::EncounterType);
this->encounterType = (data & attr.mask) >> attr.shift;
// Layer Type
attr = layout->value(Attr::LayerType);
this->layerType = (data & attr.mask) >> attr.shift;
this->unusedAttributes = data & Metatile::unusedAttrMask; this->unusedAttributes = data & Metatile::unusedAttrMask;
} }
void Metatile::setAttributes(uint32_t data) {
this->setAttributes(data, &Metatile::customLayout);
}
// Read attributes using a vanilla layout, then set them using the user's layout. For AdvanceMap import // Read attributes using a vanilla layout, then set them using the user's layout. For AdvanceMap import
void Metatile::convertAttributes(uint32_t data, BaseGameVersion version) { void Metatile::setAttributes(uint32_t data, BaseGameVersion version) {
if (version == BaseGameVersion::pokefirered) { const auto defaultLayout = Metatile::defaultLayouts.value(version);
this->setAttributes(data, &Metatile::defaultLayoutFRLG); this->setBehavior(defaultLayout->value("behavior").fromRaw(data));
} else { this->setTerrainType(defaultLayout->value("terrainType").fromRaw(data));
this->setAttributes(data, &Metatile::defaultLayoutRSE); this->setEncounterType(defaultLayout->value("encounterType").fromRaw(data));
} this->setLayerType(defaultLayout->value("layerType").fromRaw(data));
// Clean data to fit the user's custom masks
this->setAttributes(this->getAttributes());
} }
void Metatile::setBehavior(uint32_t value) { int Metatile::getDefaultAttributesSize(BaseGameVersion version) {
this->behavior = value & Metatile::customLayout[Attr::Behavior].mask; return (version == BaseGameVersion::pokefirered) ? 4 : 2;
} }
uint32_t Metatile::getBehaviorMask(BaseGameVersion version) {
void Metatile::setTerrainType(uint32_t value) { return Metatile::defaultLayouts.value(version)->value("behavior").mask;
this->terrainType = value & Metatile::customLayout[Attr::TerrainType].mask;
} }
uint32_t Metatile::getTerrainTypeMask(BaseGameVersion version) {
void Metatile::setEncounterType(uint32_t value) { return Metatile::defaultLayouts.value(version)->value("terrainType").mask;
this->encounterType = value & Metatile::customLayout[Attr::EncounterType].mask;
} }
uint32_t Metatile::getEncounterTypeMask(BaseGameVersion version) {
void Metatile::setLayerType(uint32_t value) { return Metatile::defaultLayouts.value(version)->value("encounterType").mask;
this->layerType = value & Metatile::customLayout[Attr::LayerType].mask; }
uint32_t Metatile::getLayerTypeMask(BaseGameVersion version) {
return Metatile::defaultLayouts.value(version)->value("layerType").mask;
} }

View file

@ -82,7 +82,7 @@ QList<Metatile*> MetatileParser::parse(QString filepath, bool *error, bool prima
uint32_t attributes = 0; uint32_t attributes = 0;
for (int j = 0; j < attrSize; j++) for (int j = 0; j < attrSize; j++)
attributes |= static_cast<unsigned char>(in.at(attrOffset + j)) << (8 * j); attributes |= static_cast<unsigned char>(in.at(attrOffset + j)) << (8 * j);
metatile->convertAttributes(attributes, version); metatile->setAttributes(attributes, version);
metatile->tiles = tiles; metatile->tiles = tiles;
metatiles.append(metatile); metatiles.append(metatile);
} }

View file

@ -113,7 +113,7 @@ void TilesetEditor::initUi() {
void TilesetEditor::setAttributesUi() { void TilesetEditor::setAttributesUi() {
// Behavior // Behavior
if (Metatile::customLayout[Metatile::Attr::Behavior].mask) { if (Metatile::getBehaviorMask()) {
for (int num : project->metatileBehaviorMapInverse.keys()) { for (int num : project->metatileBehaviorMapInverse.keys()) {
this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num); this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num);
} }
@ -123,7 +123,7 @@ void TilesetEditor::setAttributesUi() {
} }
// Terrain Type // Terrain Type
if (Metatile::customLayout[Metatile::Attr::TerrainType].mask) { if (Metatile::getTerrainTypeMask()) {
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE); this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS); this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER); this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
@ -134,7 +134,7 @@ void TilesetEditor::setAttributesUi() {
} }
// Encounter Type // Encounter Type
if (Metatile::customLayout[Metatile::Attr::EncounterType].mask) { if (Metatile::getEncounterTypeMask()) {
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE); this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND); this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER); this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
@ -148,7 +148,7 @@ void TilesetEditor::setAttributesUi() {
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP); this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE); this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP); this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
if (!Metatile::customLayout[Metatile::Attr::LayerType].mask) { if (!Metatile::getLayerTypeMask()) {
// User doesn't have triple layer metatiles, but has no layer type attribute. // User doesn't have triple layer metatiles, but has no layer type attribute.
// Porymap is still using the layer type value to render metatiles, and with // Porymap is still using the layer type value to render metatiles, and with
// no mask set every metatile will be "Middle/Top", so just display the combo // no mask set every metatile will be "Middle/Top", so just display the combo