Add config settings for rendering transparency
This commit is contained in:
parent
d768075a26
commit
486d1b7335
10 changed files with 201 additions and 47 deletions
|
@ -369,7 +369,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>548</height>
|
||||
<height>560</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
|
@ -602,7 +602,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_MetatileIdMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_MetatileIdMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write metatile IDs in map data.</string>
|
||||
</property>
|
||||
|
@ -616,7 +616,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_CollisionMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_CollisionMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write collision values in map data.</string>
|
||||
</property>
|
||||
|
@ -630,7 +630,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_ElevationMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_ElevationMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write elevation values in map data.</string>
|
||||
</property>
|
||||
|
@ -742,7 +742,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>568</height>
|
||||
<height>798</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
|
@ -775,6 +775,86 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_TransparentPixelRendering">
|
||||
<property name="title">
|
||||
<string>Transparent Pixel Rendering</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_RenderBlack">
|
||||
<property name="toolTip">
|
||||
<string>Fully transparent pixels will be rendered as black pixels (the Pokémon games do this by default)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as black</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_RenderFirstPalColor">
|
||||
<property name="toolTip">
|
||||
<string>Fully transparent pixels will be rendered using the first palette color (this the default behavior for the GBA)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render using first palette color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_UnusedLayerRendering">
|
||||
<property name="title">
|
||||
<string>Unused Layer Rendering</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_UnusedTileNorma">
|
||||
<property name="text">
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileNormal">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused bottom layer of Normal metatiles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_UnusedTileCovered">
|
||||
<property name="text">
|
||||
<string>Covered</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileCovered">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused top layer of Covered metatiles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_UnusedTileSplit">
|
||||
<property name="text">
|
||||
<string>Split</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileSplit">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused middle layer of Split metatiles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_WarningTilesetsTab">
|
||||
<property name="styleSheet">
|
||||
|
@ -810,14 +890,14 @@
|
|||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="4" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_LayerTypeMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_LayerTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BehaviorMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BehaviorMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
</property>
|
||||
|
@ -864,7 +944,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_TerrainTypeMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_TerrainTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
</property>
|
||||
|
@ -891,7 +971,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_EncounterTypeMask" native="true">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_EncounterTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
</property>
|
||||
|
@ -1549,10 +1629,15 @@
|
|||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIntHexSpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<class>UIntSpinBox</class>
|
||||
<extends>QAbstractSpinBox</extends>
|
||||
<header>uintspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIntHexSpinBox</class>
|
||||
<extends>UIntSpinBox</extends>
|
||||
<header location="global">uintspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/images.qrc"/>
|
||||
|
|
|
@ -301,6 +301,7 @@ public:
|
|||
this->prefabImportPrompted = false;
|
||||
this->tilesetsHaveCallback = true;
|
||||
this->tilesetsHaveIsCompressed = true;
|
||||
this->setTransparentPixelsBlack = true;
|
||||
this->filePaths.clear();
|
||||
this->eventIconPaths.clear();
|
||||
this->pokemonIconPaths.clear();
|
||||
|
@ -310,6 +311,9 @@ public:
|
|||
this->blockMetatileIdMask = 0x03FF;
|
||||
this->blockCollisionMask = 0x0C00;
|
||||
this->blockElevationMask = 0xF000;
|
||||
this->unusedTileNormal = 0x3014;
|
||||
this->unusedTileCovered = 0x0000;
|
||||
this->unusedTileSplit = 0x0000;
|
||||
this->identifiers.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
|
@ -362,6 +366,7 @@ public:
|
|||
bool prefabImportPrompted;
|
||||
bool tilesetsHaveCallback;
|
||||
bool tilesetsHaveIsCompressed;
|
||||
bool setTransparentPixelsBlack;
|
||||
int metatileAttributesSize;
|
||||
uint32_t metatileBehaviorMask;
|
||||
uint32_t metatileTerrainTypeMask;
|
||||
|
@ -370,6 +375,9 @@ public:
|
|||
uint16_t blockMetatileIdMask;
|
||||
uint16_t blockCollisionMask;
|
||||
uint16_t blockElevationMask;
|
||||
uint16_t unusedTileNormal;
|
||||
uint16_t unusedTileCovered;
|
||||
uint16_t unusedTileSplit;
|
||||
bool mapAllowFlagsEnabled;
|
||||
QString collisionSheetPath;
|
||||
int collisionSheetWidth;
|
||||
|
|
|
@ -19,6 +19,8 @@ public:
|
|||
uint16_t rawValue() const;
|
||||
|
||||
static int getIndexInTileset(int);
|
||||
|
||||
static const uint16_t maxValue;
|
||||
};
|
||||
|
||||
inline bool operator==(const Tile &a, const Tile &b) {
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
QImage getCollisionMetatileImage(Block);
|
||||
QImage getCollisionMetatileImage(int, int);
|
||||
QImage getMetatileImage(uint16_t, Tileset*, Tileset*, QList<int>, QList<float>, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(Metatile*, Tileset*, Tileset*, QList<int>, QList<float>, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(uint16_t, Tileset*, Tileset*, const QList<int>&, const QList<float>&, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(Metatile*, Tileset*, Tileset*, const QList<int>&, const QList<float>&, bool useTruePalettes = false);
|
||||
QImage getTileImage(uint16_t, Tileset*, Tileset*);
|
||||
QImage getPalettedTileImage(uint16_t, Tileset*, Tileset*, int, bool useTruePalettes = false);
|
||||
QImage getGreyscaleTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset);
|
||||
|
|
|
@ -720,6 +720,12 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->blockCollisionMask = getConfigUint32(key, value, 0, Block::maxValue);
|
||||
} else if (key == "block_elevation_mask") {
|
||||
this->blockElevationMask = getConfigUint32(key, value, 0, Block::maxValue);
|
||||
} else if (key == "unused_tile_normal") {
|
||||
this->unusedTileNormal = getConfigUint32(key, value, 0, Tile::maxValue);
|
||||
} else if (key == "unused_tile_covered") {
|
||||
this->unusedTileCovered = getConfigUint32(key, value, 0, Tile::maxValue);
|
||||
} else if (key == "unused_tile_split") {
|
||||
this->unusedTileSplit = getConfigUint32(key, value, 0, Tile::maxValue);
|
||||
} else if (key == "enable_map_allow_flags") {
|
||||
this->mapAllowFlagsEnabled = getConfigBool(key, value);
|
||||
#ifdef CONFIG_BACKWARDS_COMPATABILITY
|
||||
|
@ -752,6 +758,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->tilesetsHaveCallback = getConfigBool(key, value);
|
||||
} else if (key == "tilesets_have_is_compressed") {
|
||||
this->tilesetsHaveIsCompressed = getConfigBool(key, value);
|
||||
} else if (key == "set_transparent_pixels_black") {
|
||||
this->setTransparentPixelsBlack = getConfigBool(key, value);
|
||||
} else if (key == "event_icon_path_object") {
|
||||
this->eventIconPaths[Event::Group::Object] = value;
|
||||
} else if (key == "event_icon_path_warp") {
|
||||
|
@ -839,6 +847,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
}
|
||||
map.insert("tilesets_have_callback", QString::number(this->tilesetsHaveCallback));
|
||||
map.insert("tilesets_have_is_compressed", QString::number(this->tilesetsHaveIsCompressed));
|
||||
map.insert("set_transparent_pixels_black", QString::number(this->setTransparentPixelsBlack));
|
||||
map.insert("metatile_attributes_size", QString::number(this->metatileAttributesSize));
|
||||
map.insert("metatile_behavior_mask", "0x" + QString::number(this->metatileBehaviorMask, 16).toUpper());
|
||||
map.insert("metatile_terrain_type_mask", "0x" + QString::number(this->metatileTerrainTypeMask, 16).toUpper());
|
||||
|
@ -847,6 +856,9 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
map.insert("block_metatile_id_mask", "0x" + QString::number(this->blockMetatileIdMask, 16).toUpper());
|
||||
map.insert("block_collision_mask", "0x" + QString::number(this->blockCollisionMask, 16).toUpper());
|
||||
map.insert("block_elevation_mask", "0x" + QString::number(this->blockElevationMask, 16).toUpper());
|
||||
map.insert("unused_tile_normal", "0x" + QString::number(this->unusedTileNormal, 16).toUpper());
|
||||
map.insert("unused_tile_covered", "0x" + QString::number(this->unusedTileCovered, 16).toUpper());
|
||||
map.insert("unused_tile_split", "0x" + QString::number(this->unusedTileSplit, 16).toUpper());
|
||||
map.insert("enable_map_allow_flags", QString::number(this->mapAllowFlagsEnabled));
|
||||
map.insert("event_icon_path_object", this->eventIconPaths[Event::Group::Object]);
|
||||
map.insert("event_icon_path_warp", this->eventIconPaths[Event::Group::Warp]);
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
#include "tile.h"
|
||||
#include "project.h"
|
||||
#include "bitpacker.h"
|
||||
|
||||
// Upper limit for raw value (i.e., uint16_t max).
|
||||
const uint16_t Tile::maxValue = 0xFFFF;
|
||||
|
||||
// At the moment these are fixed, and not exposed to the user.
|
||||
// We're only using them for convenience when converting between raw values.
|
||||
// The actual job of clamping Tile's members to correct values is handled by the widths in the bit field.
|
||||
const BitPacker bitsTileId = BitPacker(0x03FF);
|
||||
const BitPacker bitsXFlip = BitPacker(0x0400);
|
||||
const BitPacker bitsYFlip = BitPacker(0x0800);
|
||||
const BitPacker bitsPalette = BitPacker(0xF000);
|
||||
|
||||
Tile::Tile() :
|
||||
tileId(0),
|
||||
|
@ -16,18 +28,17 @@
|
|||
{ }
|
||||
|
||||
Tile::Tile(uint16_t raw) :
|
||||
tileId(raw & 0x3FF),
|
||||
xflip((raw >> 10) & 1),
|
||||
yflip((raw >> 11) & 1),
|
||||
palette((raw >> 12) & 0xF)
|
||||
tileId(bitsTileId.unpack(raw)),
|
||||
xflip(bitsXFlip.unpack(raw)),
|
||||
yflip(bitsYFlip.unpack(raw)),
|
||||
palette(bitsPalette.unpack(raw))
|
||||
{ }
|
||||
|
||||
uint16_t Tile::rawValue() const {
|
||||
return static_cast<uint16_t>(
|
||||
(this->tileId & 0x3FF)
|
||||
| ((this->xflip & 1) << 10)
|
||||
| ((this->yflip & 1) << 11)
|
||||
| ((this->palette & 0xF) << 12));
|
||||
return bitsTileId.pack(this->tileId)
|
||||
| bitsXFlip.pack(this->xflip)
|
||||
| bitsYFlip.pack(this->yflip)
|
||||
| bitsPalette.pack(this->palette);
|
||||
}
|
||||
|
||||
int Tile::getIndexInTileset(int tileId) {
|
||||
|
|
|
@ -2096,19 +2096,29 @@ bool Project::readFieldmapProperties() {
|
|||
fileWatcher.addPath(root + "/" + filename);
|
||||
const QMap<QString, int> defines = parser.readCDefinesByName(filename, names);
|
||||
|
||||
auto loadDefine = [defines](const QString name, int * dest) {
|
||||
auto loadDefine = [defines](const QString name, int * dest, int min, int max) {
|
||||
auto it = defines.find(name);
|
||||
if (it != defines.end()) {
|
||||
*dest = it.value();
|
||||
if (*dest < min) {
|
||||
logWarn(QString("Value for tileset property '%1' (%2) is below the minimum (%3). Defaulting to minimum.").arg(name).arg(*dest).arg(min));
|
||||
*dest = min;
|
||||
} else if (*dest > max) {
|
||||
logWarn(QString("Value for tileset property '%1' (%2) is above the maximum (%3). Defaulting to maximum.").arg(name).arg(*dest).arg(max));
|
||||
*dest = max;
|
||||
}
|
||||
} else {
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.").arg(name).arg(*dest));
|
||||
}
|
||||
};
|
||||
loadDefine(numTilesPrimaryName, &Project::num_tiles_primary);
|
||||
loadDefine(numTilesTotalName, &Project::num_tiles_total);
|
||||
loadDefine(numMetatilesPrimaryName, &Project::num_metatiles_primary);
|
||||
loadDefine(numPalsPrimaryName, &Project::num_pals_primary);
|
||||
loadDefine(numPalsTotalName, &Project::num_pals_total);
|
||||
loadDefine(numPalsTotalName, &Project::num_pals_total, 2, INT_MAX); // In reality the max would be 16, but as far as Porymap is concerned it doesn't matter.
|
||||
loadDefine(numTilesTotalName, &Project::num_tiles_total, 2, 1024); // 1024 is fixed because we store tile IDs in a 10-bit field.
|
||||
loadDefine(numPalsPrimaryName, &Project::num_pals_primary, 1, Project::num_pals_total - 1);
|
||||
loadDefine(numTilesPrimaryName, &Project::num_tiles_primary, 1, Project::num_tiles_total - 1);
|
||||
|
||||
// This maximum is overly generous, because until we parse the appropriate masks from the project
|
||||
// we don't actually know what the maximum number of metatiles is.
|
||||
loadDefine(numMetatilesPrimaryName, &Project::num_metatiles_primary, 1, 0xFFFF - 1);
|
||||
|
||||
auto it = defines.find(maxMapSizeName);
|
||||
if (it != defines.end()) {
|
||||
|
@ -3020,12 +3030,12 @@ void Project::applyParsedLimits() {
|
|||
Block::setLayout();
|
||||
Metatile::setLayout(this);
|
||||
|
||||
Project::num_metatiles_primary = qMin(Project::num_metatiles_primary, Block::getMaxMetatileId() + 1);
|
||||
Project::num_metatiles_primary = qMin(qMax(Project::num_metatiles_primary, 1), Block::getMaxMetatileId() + 1);
|
||||
projectConfig.defaultMetatileId = qMin(projectConfig.defaultMetatileId, Block::getMaxMetatileId());
|
||||
projectConfig.defaultElevation = qMin(projectConfig.defaultElevation, Block::getMaxElevation());
|
||||
projectConfig.defaultCollision = qMin(projectConfig.defaultCollision, Block::getMaxCollision());
|
||||
projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1);
|
||||
projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1);
|
||||
projectConfig.collisionSheetHeight = qMin(qMax(projectConfig.collisionSheetHeight, 1), Block::getMaxElevation() + 1);
|
||||
projectConfig.collisionSheetWidth = qMin(qMax(projectConfig.collisionSheetWidth, 1), Block::getMaxCollision() + 1);
|
||||
}
|
||||
|
||||
bool Project::hasUnsavedChanges() {
|
||||
|
|
|
@ -17,8 +17,8 @@ QImage getMetatileImage(
|
|||
uint16_t metatileId,
|
||||
Tileset *primaryTileset,
|
||||
Tileset *secondaryTileset,
|
||||
QList<int> layerOrder,
|
||||
QList<float> layerOpacity,
|
||||
const QList<int> &layerOrder,
|
||||
const QList<float> &layerOpacity,
|
||||
bool useTruePalettes)
|
||||
{
|
||||
Metatile* metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset);
|
||||
|
@ -34,8 +34,8 @@ QImage getMetatileImage(
|
|||
Metatile *metatile,
|
||||
Tileset *primaryTileset,
|
||||
Tileset *secondaryTileset,
|
||||
QList<int> layerOrder,
|
||||
QList<float> layerOpacity,
|
||||
const QList<int> &layerOrder,
|
||||
const QList<float> &layerOpacity,
|
||||
bool useTruePalettes)
|
||||
{
|
||||
QImage metatile_image(16, 16, QImage::Format_RGBA8888);
|
||||
|
@ -44,13 +44,15 @@ QImage getMetatileImage(
|
|||
return metatile_image;
|
||||
}
|
||||
|
||||
// The GBA renders transparent pixels using palette 0 color 0. We have access to that color (palettes.value(0).value(0))
|
||||
// but all 3 games actually overwrite this color with black when loading the tileset palettes, so we fill the metatile
|
||||
// image with black so that any pixels we don't render will reveal the correct color.
|
||||
metatile_image.fill(Qt::black);
|
||||
|
||||
QList<QList<QRgb>> palettes = Tileset::getBlockPalettes(primaryTileset, secondaryTileset, useTruePalettes);
|
||||
|
||||
// We need to fill the metatile image with something so that if any transparent
|
||||
// tile pixels line up across layers we will still have something to render.
|
||||
// The GBA renders transparent pixels using palette 0 color 0. We have this color,
|
||||
// but all 3 games actually overwrite it with black when loading the tileset palettes,
|
||||
// so we have a setting to choose between these two behaviors.
|
||||
metatile_image.fill(projectConfig.setTransparentPixelsBlack ? QColor("black") : QColor(palettes.value(0).value(0)));
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
const int numLayers = 3; // When rendering, metatiles always have 3 layers
|
||||
uint32_t layerType = metatile->layerType();
|
||||
|
@ -66,25 +68,25 @@ QImage getMetatileImage(
|
|||
tile = metatile->tiles.value(tileOffset + (l * 4));
|
||||
} else {
|
||||
// "Vanilla" metatiles only have 8 tiles, but render 12.
|
||||
// The remaining 4 tiles are rendered either as tile 0 or 0x3014 (tile 20, palette 3) depending on layer type.
|
||||
// The remaining 4 tiles are rendered using user-specified tiles depending on layer type.
|
||||
switch (layerType)
|
||||
{
|
||||
default:
|
||||
case METATILE_LAYER_MIDDLE_TOP:
|
||||
if (l == 0)
|
||||
tile = Tile(0x3014);
|
||||
tile = Tile(projectConfig.unusedTileNormal);
|
||||
else // Tiles are on layers 1 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((l - 1) * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_MIDDLE:
|
||||
if (l == 2)
|
||||
tile = Tile();
|
||||
tile = Tile(projectConfig.unusedTileCovered);
|
||||
else // Tiles are on layers 0 and 1
|
||||
tile = metatile->tiles.value(tileOffset + (l * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_TOP:
|
||||
if (l == 1)
|
||||
tile = Tile();
|
||||
tile = Tile(projectConfig.unusedTileSplit);
|
||||
else // Tiles are on layers 0 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((l == 0 ? 0 : 1) * 4));
|
||||
break;
|
||||
|
@ -101,7 +103,7 @@ QImage getMetatileImage(
|
|||
|
||||
// Colorize the metatile tiles with its palette.
|
||||
if (tile.palette < palettes.length()) {
|
||||
QList<QRgb> palette = palettes.value(tile.palette);
|
||||
const QList<QRgb> palette = palettes.value(tile.palette);
|
||||
for (int j = 0; j < palette.length(); j++) {
|
||||
tile_image.setColor(j, palette.value(j));
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ QImage getTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondary
|
|||
return tileset->tiles.value(index, QImage());
|
||||
}
|
||||
|
||||
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, QList<QRgb> palette) {
|
||||
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList<QRgb> &palette) {
|
||||
QImage tileImage = getTileImage(tileId, primaryTileset, secondaryTileset);
|
||||
if (tileImage.isNull()) {
|
||||
tileImage = QImage(8, 8, QImage::Format_RGBA8888);
|
||||
|
|
|
@ -82,6 +82,8 @@ void ProjectSettingsEditor::connectSignals() {
|
|||
}
|
||||
for (auto checkBox : ui->centralwidget->findChildren<QCheckBox *>())
|
||||
connect(checkBox, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited);
|
||||
for (auto radioButton : ui->centralwidget->findChildren<QRadioButton *>())
|
||||
connect(radioButton, &QRadioButton::toggled, this, &ProjectSettingsEditor::markEdited);
|
||||
for (auto lineEdit : ui->centralwidget->findChildren<QLineEdit *>())
|
||||
connect(lineEdit, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited);
|
||||
for (auto spinBox : ui->centralwidget->findChildren<NoScrollSpinBox *>())
|
||||
|
@ -135,6 +137,9 @@ void ProjectSettingsEditor::initUi() {
|
|||
ui->spinBox_MetatileIdMask->setMaximum(Block::maxValue);
|
||||
ui->spinBox_CollisionMask->setMaximum(Block::maxValue);
|
||||
ui->spinBox_ElevationMask->setMaximum(Block::maxValue);
|
||||
ui->spinBox_UnusedTileNormal->setMaximum(Tile::maxValue);
|
||||
ui->spinBox_UnusedTileCovered->setMaximum(Tile::maxValue);
|
||||
ui->spinBox_UnusedTileSplit->setMaximum(Tile::maxValue);
|
||||
|
||||
// The values for some of the settings we provide in this window can be determined using constants in the user's projects.
|
||||
// If the user has these constants we disable these settings in the UI -- they can modify them using their constants.
|
||||
|
@ -442,6 +447,12 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->checkBox_OutputIsCompressed->setChecked(projectConfig.tilesetsHaveIsCompressed);
|
||||
ui->checkBox_DisableWarning->setChecked(porymapConfig.warpBehaviorWarningDisabled);
|
||||
|
||||
// Radio buttons
|
||||
if (projectConfig.setTransparentPixelsBlack)
|
||||
ui->radioButton_RenderBlack->setChecked(true);
|
||||
else
|
||||
ui->radioButton_RenderFirstPalColor->setChecked(true);
|
||||
|
||||
// Set spin box values
|
||||
ui->spinBox_Elevation->setValue(projectConfig.defaultElevation);
|
||||
ui->spinBox_Collision->setValue(projectConfig.defaultCollision);
|
||||
|
@ -455,6 +466,9 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->spinBox_MetatileIdMask->setValue(projectConfig.blockMetatileIdMask & ui->spinBox_MetatileIdMask->maximum());
|
||||
ui->spinBox_CollisionMask->setValue(projectConfig.blockCollisionMask & ui->spinBox_CollisionMask->maximum());
|
||||
ui->spinBox_ElevationMask->setValue(projectConfig.blockElevationMask & ui->spinBox_ElevationMask->maximum());
|
||||
ui->spinBox_UnusedTileNormal->setValue(projectConfig.unusedTileNormal);
|
||||
ui->spinBox_UnusedTileCovered->setValue(projectConfig.unusedTileCovered);
|
||||
ui->spinBox_UnusedTileSplit->setValue(projectConfig.unusedTileSplit);
|
||||
|
||||
// Set (and sync) border metatile IDs
|
||||
this->setBorderMetatileIds(false, projectConfig.newMapBorderMetatileIds);
|
||||
|
@ -511,6 +525,7 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.tilesetsHaveCallback = ui->checkBox_OutputCallback->isChecked();
|
||||
projectConfig.tilesetsHaveIsCompressed = ui->checkBox_OutputIsCompressed->isChecked();
|
||||
porymapConfig.warpBehaviorWarningDisabled = ui->checkBox_DisableWarning->isChecked();
|
||||
projectConfig.setTransparentPixelsBlack = ui->radioButton_RenderBlack->isChecked();
|
||||
|
||||
// Save spin box settings
|
||||
projectConfig.defaultElevation = ui->spinBox_Elevation->value();
|
||||
|
@ -525,6 +540,9 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.blockMetatileIdMask = ui->spinBox_MetatileIdMask->value();
|
||||
projectConfig.blockCollisionMask = ui->spinBox_CollisionMask->value();
|
||||
projectConfig.blockElevationMask = ui->spinBox_ElevationMask->value();
|
||||
projectConfig.unusedTileNormal = ui->spinBox_UnusedTileNormal->value();
|
||||
projectConfig.unusedTileCovered = ui->spinBox_UnusedTileCovered->value();
|
||||
projectConfig.unusedTileSplit = ui->spinBox_UnusedTileSplit->value();
|
||||
|
||||
// Save line edit settings
|
||||
projectConfig.prefabFilepath = ui->lineEdit_PrefabsPath->text();
|
||||
|
|
|
@ -99,7 +99,13 @@ void TilesetEditor::initUi() {
|
|||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
this->ui->spinBox_paletteSelector->setMinimum(0);
|
||||
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
this->ui->actionShow_Tileset_Divider->setChecked(porymapConfig.showTilesetEditorDivider);
|
||||
|
||||
// TODO: The dividing line at the moment is only accurate if the number of primary metatiles is divisible by 8.
|
||||
// If it's not, the secondary metatiles will wrap above the line. This has other problems (like skewing
|
||||
// metatile groups the user may have designed) so this should be fixed by filling the primary metatiles
|
||||
// image with invalid magenta metatiles until it's divisible by 8. Then the line can be re-enabled as-is.
|
||||
this->ui->actionShow_Tileset_Divider->setChecked(/*porymapConfig.showTilesetEditorDivider*/false);
|
||||
this->ui->actionShow_Tileset_Divider->setVisible(false);
|
||||
|
||||
this->setAttributesUi();
|
||||
this->setMetatileLabelValidator();
|
||||
|
|
Loading…
Reference in a new issue