|
|
|
|
@@ -8,7 +8,9 @@
|
|
|
|
|
#include <QSet>
|
|
|
|
|
#include <QStringList>
|
|
|
|
|
|
|
|
|
|
// TODO: Convert to modal dialog (among other things, this means we wouldn't need to worry about changes to the map list while this is open)
|
|
|
|
|
// TODO: Make ui->groupBox_HeaderData collapsible
|
|
|
|
|
|
|
|
|
|
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
|
|
|
|
|
|
|
|
|
struct NewMapDialog::Settings NewMapDialog::settings = {};
|
|
|
|
|
|
|
|
|
|
@@ -21,6 +23,16 @@ NewMapDialog::NewMapDialog(QWidget *parent, Project *project) :
|
|
|
|
|
this->project = project;
|
|
|
|
|
this->existingLayout = false;
|
|
|
|
|
this->importedMap = false;
|
|
|
|
|
|
|
|
|
|
// Map names and IDs can only contain word characters, and cannot start with a digit.
|
|
|
|
|
// TODO: Also validate this when we read ProjectIdentifier::define_map_prefix from the config
|
|
|
|
|
static const QRegularExpression re("[A-Za-z_]+[\\w]*");
|
|
|
|
|
auto validator = new QRegularExpressionValidator(re, this);
|
|
|
|
|
ui->lineEdit_Name->setValidator(validator);
|
|
|
|
|
ui->lineEdit_ID->setValidator(validator);
|
|
|
|
|
|
|
|
|
|
connect(ui->spinBox_MapWidth, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){validateMapDimensions();});
|
|
|
|
|
connect(ui->spinBox_MapHeight, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){validateMapDimensions();});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NewMapDialog::~NewMapDialog()
|
|
|
|
|
@@ -29,93 +41,77 @@ NewMapDialog::~NewMapDialog()
|
|
|
|
|
delete ui;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::initUi() {
|
|
|
|
|
void NewMapDialog::init() {
|
|
|
|
|
// Populate combo boxes
|
|
|
|
|
ui->comboBox_NewMap_Primary_Tileset->addItems(project->primaryTilesetLabels);
|
|
|
|
|
ui->comboBox_NewMap_Secondary_Tileset->addItems(project->secondaryTilesetLabels);
|
|
|
|
|
ui->comboBox_NewMap_Group->addItems(project->groupNames);
|
|
|
|
|
ui->comboBox_NewMap_Song->addItems(project->songNames);
|
|
|
|
|
ui->comboBox_NewMap_Type->addItems(project->mapTypes);
|
|
|
|
|
ui->comboBox_NewMap_Location->addItems(project->mapSectionIdNames);
|
|
|
|
|
|
|
|
|
|
const QSignalBlocker b(ui->comboBox_Layout);
|
|
|
|
|
ui->comboBox_Layout->addItems(project->mapLayoutsTable);
|
|
|
|
|
this->layoutId = project->mapLayoutsTable.first();
|
|
|
|
|
ui->comboBox_PrimaryTileset->addItems(project->primaryTilesetLabels);
|
|
|
|
|
ui->comboBox_SecondaryTileset->addItems(project->secondaryTilesetLabels);
|
|
|
|
|
ui->comboBox_Group->addItems(project->groupNames);
|
|
|
|
|
ui->comboBox_Song->addItems(project->songNames);
|
|
|
|
|
ui->comboBox_Location->addItems(project->mapSectionIdNames);
|
|
|
|
|
ui->comboBox_Weather->addItems(project->weatherNames);
|
|
|
|
|
ui->comboBox_Type->addItems(project->mapTypes);
|
|
|
|
|
ui->comboBox_BattleScene->addItems(project->mapBattleScenes);
|
|
|
|
|
|
|
|
|
|
// Set spin box limits
|
|
|
|
|
ui->spinBox_NewMap_Width->setMinimum(1);
|
|
|
|
|
ui->spinBox_NewMap_Height->setMinimum(1);
|
|
|
|
|
ui->spinBox_NewMap_Width->setMaximum(project->getMaxMapWidth());
|
|
|
|
|
ui->spinBox_NewMap_Height->setMaximum(project->getMaxMapHeight());
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setMinimum(1);
|
|
|
|
|
ui->spinBox_NewMap_BorderHeight->setMinimum(1);
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setMaximum(MAX_BORDER_WIDTH);
|
|
|
|
|
ui->spinBox_NewMap_BorderHeight->setMaximum(MAX_BORDER_HEIGHT);
|
|
|
|
|
ui->spinBox_NewMap_Floor_Number->setMinimum(-128);
|
|
|
|
|
ui->spinBox_NewMap_Floor_Number->setMaximum(127);
|
|
|
|
|
ui->spinBox_MapWidth->setMaximum(project->getMaxMapWidth());
|
|
|
|
|
ui->spinBox_MapHeight->setMaximum(project->getMaxMapHeight());
|
|
|
|
|
ui->spinBox_BorderWidth->setMaximum(MAX_BORDER_WIDTH);
|
|
|
|
|
ui->spinBox_BorderHeight->setMaximum(MAX_BORDER_HEIGHT);
|
|
|
|
|
|
|
|
|
|
// Hide config specific ui elements
|
|
|
|
|
bool hasFlags = projectConfig.mapAllowFlagsEnabled;
|
|
|
|
|
ui->checkBox_NewMap_Allow_Running->setVisible(hasFlags);
|
|
|
|
|
ui->checkBox_NewMap_Allow_Biking->setVisible(hasFlags);
|
|
|
|
|
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
|
|
|
|
ui->label_NewMap_Allow_Running->setVisible(hasFlags);
|
|
|
|
|
ui->label_NewMap_Allow_Biking->setVisible(hasFlags);
|
|
|
|
|
ui->label_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
|
|
|
|
ui->checkBox_AllowRunning->setVisible(hasFlags);
|
|
|
|
|
ui->checkBox_AllowBiking->setVisible(hasFlags);
|
|
|
|
|
ui->checkBox_AllowEscaping->setVisible(hasFlags);
|
|
|
|
|
ui->label_AllowRunning->setVisible(hasFlags);
|
|
|
|
|
ui->label_AllowBiking->setVisible(hasFlags);
|
|
|
|
|
ui->label_AllowEscaping->setVisible(hasFlags);
|
|
|
|
|
|
|
|
|
|
bool hasCustomBorders = projectConfig.useCustomBorderSize;
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
|
|
|
|
ui->spinBox_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
|
|
|
|
ui->label_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
|
|
|
|
ui->label_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
|
|
|
|
ui->groupBox_BorderDimensions->setVisible(projectConfig.useCustomBorderSize);
|
|
|
|
|
|
|
|
|
|
bool hasFloorNumber = projectConfig.floorNumberEnabled;
|
|
|
|
|
ui->spinBox_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
|
|
|
|
ui->label_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
|
|
|
|
ui->spinBox_FloorNumber->setVisible(hasFloorNumber);
|
|
|
|
|
ui->label_FloorNumber->setVisible(hasFloorNumber);
|
|
|
|
|
|
|
|
|
|
this->updateGeometry();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::init() {
|
|
|
|
|
// Restore previous settings
|
|
|
|
|
ui->lineEdit_NewMap_Name->setText(project->getNewMapName());
|
|
|
|
|
ui->comboBox_NewMap_Group->setTextItem(settings.group);
|
|
|
|
|
ui->spinBox_NewMap_Width->setValue(settings.width);
|
|
|
|
|
ui->spinBox_NewMap_Height->setValue(settings.height);
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setValue(settings.borderWidth);
|
|
|
|
|
ui->spinBox_NewMap_BorderHeight->setValue(settings.borderHeight);
|
|
|
|
|
ui->comboBox_NewMap_Primary_Tileset->setTextItem(settings.primaryTilesetLabel);
|
|
|
|
|
ui->comboBox_NewMap_Secondary_Tileset->setTextItem(settings.secondaryTilesetLabel);
|
|
|
|
|
ui->comboBox_NewMap_Type->setTextItem(settings.type);
|
|
|
|
|
ui->comboBox_NewMap_Location->setTextItem(settings.location);
|
|
|
|
|
ui->comboBox_NewMap_Song->setTextItem(settings.song);
|
|
|
|
|
ui->checkBox_NewMap_Flyable->setChecked(settings.canFlyTo);
|
|
|
|
|
ui->checkBox_NewMap_Show_Location->setChecked(settings.showLocationName);
|
|
|
|
|
ui->checkBox_NewMap_Allow_Running->setChecked(settings.allowRunning);
|
|
|
|
|
ui->checkBox_NewMap_Allow_Biking->setChecked(settings.allowBiking);
|
|
|
|
|
ui->checkBox_NewMap_Allow_Escape_Rope->setChecked(settings.allowEscaping);
|
|
|
|
|
ui->spinBox_NewMap_Floor_Number->setValue(settings.floorNumber);
|
|
|
|
|
|
|
|
|
|
// Connect signals
|
|
|
|
|
connect(ui->spinBox_NewMap_Width, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();});
|
|
|
|
|
connect(ui->spinBox_NewMap_Height, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();});
|
|
|
|
|
|
|
|
|
|
ui->frame_NewMap_Options->setEnabled(true);
|
|
|
|
|
ui->lineEdit_Name->setText(project->getNewMapName());
|
|
|
|
|
ui->comboBox_Group->setTextItem(settings.group);
|
|
|
|
|
ui->spinBox_MapWidth->setValue(settings.width);
|
|
|
|
|
ui->spinBox_MapHeight->setValue(settings.height);
|
|
|
|
|
ui->spinBox_BorderWidth->setValue(settings.borderWidth);
|
|
|
|
|
ui->spinBox_BorderHeight->setValue(settings.borderHeight);
|
|
|
|
|
ui->comboBox_PrimaryTileset->setTextItem(settings.primaryTilesetLabel);
|
|
|
|
|
ui->comboBox_SecondaryTileset->setTextItem(settings.secondaryTilesetLabel);
|
|
|
|
|
ui->comboBox_Song->setTextItem(settings.song);
|
|
|
|
|
ui->comboBox_Location->setTextItem(settings.location);
|
|
|
|
|
ui->checkBox_RequiresFlash->setChecked(settings.requiresFlash);
|
|
|
|
|
ui->comboBox_Weather->setTextItem(settings.weather);
|
|
|
|
|
ui->comboBox_Type->setTextItem(settings.type);
|
|
|
|
|
ui->comboBox_BattleScene->setTextItem(settings.battleScene);
|
|
|
|
|
ui->checkBox_ShowLocation->setChecked(settings.showLocationName);
|
|
|
|
|
ui->checkBox_AllowRunning->setChecked(settings.allowRunning);
|
|
|
|
|
ui->checkBox_AllowBiking->setChecked(settings.allowBiking);
|
|
|
|
|
ui->checkBox_AllowEscaping->setChecked(settings.allowEscaping);
|
|
|
|
|
ui->spinBox_FloorNumber->setValue(settings.floorNumber);
|
|
|
|
|
ui->checkBox_CanFlyTo->setChecked(settings.canFlyTo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Creating new map by right-clicking in the map list
|
|
|
|
|
void NewMapDialog::init(int tabIndex, QString fieldName) {
|
|
|
|
|
initUi();
|
|
|
|
|
//initUi();
|
|
|
|
|
switch (tabIndex)
|
|
|
|
|
{
|
|
|
|
|
case MapListTab::Groups:
|
|
|
|
|
settings.group = fieldName;
|
|
|
|
|
//ui->label_Group->setDisabled(true);
|
|
|
|
|
//ui->comboBox_Group->setDisabled(true);
|
|
|
|
|
break;
|
|
|
|
|
case MapListTab::Areas:
|
|
|
|
|
settings.location = fieldName;
|
|
|
|
|
//ui->label_Location->setDisabled(true);
|
|
|
|
|
//ui->comboBox_Location->setDisabled(true);
|
|
|
|
|
break;
|
|
|
|
|
case MapListTab::Layouts:
|
|
|
|
|
this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked);
|
|
|
|
|
useLayout(fieldName);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -123,234 +119,268 @@ void NewMapDialog::init(int tabIndex, QString fieldName) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Creating new map from AdvanceMap import
|
|
|
|
|
void NewMapDialog::init(Layout *mapLayout) {
|
|
|
|
|
initUi();
|
|
|
|
|
void NewMapDialog::init(Layout *layout) {
|
|
|
|
|
this->importedMap = true;
|
|
|
|
|
useLayoutSettings(mapLayout);
|
|
|
|
|
useLayoutSettings(layout);
|
|
|
|
|
|
|
|
|
|
// TODO: These are probably leaking
|
|
|
|
|
this->map = new Map();
|
|
|
|
|
this->map->setLayout(new Layout());
|
|
|
|
|
this->map->layout()->blockdata = mapLayout->blockdata;
|
|
|
|
|
this->map->layout()->blockdata = layout->blockdata;
|
|
|
|
|
|
|
|
|
|
if (!mapLayout->border.isEmpty()) {
|
|
|
|
|
this->map->layout()->border = mapLayout->border;
|
|
|
|
|
if (!layout->border.isEmpty()) {
|
|
|
|
|
this->map->layout()->border = layout->border;
|
|
|
|
|
}
|
|
|
|
|
init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NewMapDialog::checkNewMapDimensions() {
|
|
|
|
|
int numMetatiles = project->getMapDataSize(ui->spinBox_NewMap_Width->value(), ui->spinBox_NewMap_Height->value());
|
|
|
|
|
int maxMetatiles = project->getMaxMapDataSize();
|
|
|
|
|
|
|
|
|
|
if (numMetatiles > maxMetatiles) {
|
|
|
|
|
ui->frame_NewMap_Warning->setVisible(true);
|
|
|
|
|
QString errorText = QString("Error: The specified width and height are too large.\n"
|
|
|
|
|
"The maximum map width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
|
|
|
|
"The specified map width and height was: (%2 + 15) * (%3 + 14) = %4")
|
|
|
|
|
.arg(maxMetatiles)
|
|
|
|
|
.arg(ui->spinBox_NewMap_Width->value())
|
|
|
|
|
.arg(ui->spinBox_NewMap_Height->value())
|
|
|
|
|
.arg(numMetatiles);
|
|
|
|
|
ui->label_NewMap_WarningMessage->setText(errorText);
|
|
|
|
|
ui->label_NewMap_WarningMessage->setWordWrap(true);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ui->frame_NewMap_Warning->setVisible(false);
|
|
|
|
|
ui->label_NewMap_WarningMessage->clear();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NewMapDialog::checkNewMapGroup() {
|
|
|
|
|
group = project->groupNames.indexOf(this->ui->comboBox_NewMap_Group->currentText());
|
|
|
|
|
|
|
|
|
|
if (group < 0) {
|
|
|
|
|
ui->frame_NewMap_Warning->setVisible(true);
|
|
|
|
|
QString errorText = QString("Error: The specified map group '%1' does not exist.")
|
|
|
|
|
.arg(ui->comboBox_NewMap_Group->currentText());
|
|
|
|
|
ui->label_NewMap_WarningMessage->setText(errorText);
|
|
|
|
|
ui->label_NewMap_WarningMessage->setWordWrap(true);
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
ui->frame_NewMap_Warning->setVisible(false);
|
|
|
|
|
ui->label_NewMap_WarningMessage->clear();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::setDefaultSettings(Project *project) {
|
|
|
|
|
settings.group = project->groupNames.at(0);
|
|
|
|
|
settings.width = project->getDefaultMapSize();
|
|
|
|
|
settings.height = project->getDefaultMapSize();
|
|
|
|
|
settings.width = project->getDefaultMapDimension();
|
|
|
|
|
settings.height = project->getDefaultMapDimension();
|
|
|
|
|
settings.borderWidth = DEFAULT_BORDER_WIDTH;
|
|
|
|
|
settings.borderHeight = DEFAULT_BORDER_HEIGHT;
|
|
|
|
|
settings.primaryTilesetLabel = project->getDefaultPrimaryTilesetLabel();
|
|
|
|
|
settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel();
|
|
|
|
|
settings.type = project->mapTypes.value(0, "0");
|
|
|
|
|
settings.location = project->mapSectionIdNames.value(0, "0");
|
|
|
|
|
settings.song = project->defaultSong;
|
|
|
|
|
settings.canFlyTo = false;
|
|
|
|
|
settings.location = project->mapSectionIdNames.value(0, "0");
|
|
|
|
|
settings.requiresFlash = false;
|
|
|
|
|
settings.weather = project->weatherNames.value(0, "0");
|
|
|
|
|
settings.type = project->mapTypes.value(0, "0");
|
|
|
|
|
settings.battleScene = project->mapBattleScenes.value(0, "0");
|
|
|
|
|
settings.showLocationName = true;
|
|
|
|
|
settings.allowRunning = false;
|
|
|
|
|
settings.allowBiking = false;
|
|
|
|
|
settings.allowEscaping = false;
|
|
|
|
|
settings.floorNumber = 0;
|
|
|
|
|
settings.canFlyTo = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::saveSettings() {
|
|
|
|
|
settings.group = ui->comboBox_NewMap_Group->currentText();
|
|
|
|
|
settings.width = ui->spinBox_NewMap_Width->value();
|
|
|
|
|
settings.height = ui->spinBox_NewMap_Height->value();
|
|
|
|
|
settings.borderWidth = ui->spinBox_NewMap_BorderWidth->value();
|
|
|
|
|
settings.borderHeight = ui->spinBox_NewMap_BorderHeight->value();
|
|
|
|
|
settings.primaryTilesetLabel = ui->comboBox_NewMap_Primary_Tileset->currentText();
|
|
|
|
|
settings.secondaryTilesetLabel = ui->comboBox_NewMap_Secondary_Tileset->currentText();
|
|
|
|
|
settings.type = ui->comboBox_NewMap_Type->currentText();
|
|
|
|
|
settings.location = ui->comboBox_NewMap_Location->currentText();
|
|
|
|
|
settings.song = ui->comboBox_NewMap_Song->currentText();
|
|
|
|
|
settings.canFlyTo = ui->checkBox_NewMap_Flyable->isChecked();
|
|
|
|
|
settings.showLocationName = ui->checkBox_NewMap_Show_Location->isChecked();
|
|
|
|
|
settings.allowRunning = ui->checkBox_NewMap_Allow_Running->isChecked();
|
|
|
|
|
settings.allowBiking = ui->checkBox_NewMap_Allow_Biking->isChecked();
|
|
|
|
|
settings.allowEscaping = ui->checkBox_NewMap_Allow_Escape_Rope->isChecked();
|
|
|
|
|
settings.floorNumber = ui->spinBox_NewMap_Floor_Number->value();
|
|
|
|
|
settings.group = ui->comboBox_Group->currentText();
|
|
|
|
|
settings.width = ui->spinBox_MapWidth->value();
|
|
|
|
|
settings.height = ui->spinBox_MapHeight->value();
|
|
|
|
|
settings.borderWidth = ui->spinBox_BorderWidth->value();
|
|
|
|
|
settings.borderHeight = ui->spinBox_BorderHeight->value();
|
|
|
|
|
settings.primaryTilesetLabel = ui->comboBox_PrimaryTileset->currentText();
|
|
|
|
|
settings.secondaryTilesetLabel = ui->comboBox_SecondaryTileset->currentText();
|
|
|
|
|
settings.song = ui->comboBox_Song->currentText();
|
|
|
|
|
settings.location = ui->comboBox_Location->currentText();
|
|
|
|
|
settings.requiresFlash = ui->checkBox_RequiresFlash->isChecked();
|
|
|
|
|
settings.weather = ui->comboBox_Weather->currentText();
|
|
|
|
|
settings.type = ui->comboBox_Type->currentText();
|
|
|
|
|
settings.battleScene = ui->comboBox_BattleScene->currentText();
|
|
|
|
|
settings.showLocationName = ui->checkBox_ShowLocation->isChecked();
|
|
|
|
|
settings.allowRunning = ui->checkBox_AllowRunning->isChecked();
|
|
|
|
|
settings.allowBiking = ui->checkBox_AllowBiking->isChecked();
|
|
|
|
|
settings.allowEscaping = ui->checkBox_AllowEscaping->isChecked();
|
|
|
|
|
settings.floorNumber = ui->spinBox_FloorNumber->value();
|
|
|
|
|
settings.canFlyTo = ui->checkBox_CanFlyTo->isChecked();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::useLayoutSettings(Layout *layout) {
|
|
|
|
|
if (!layout) return;
|
|
|
|
|
|
|
|
|
|
settings.width = layout->width;
|
|
|
|
|
ui->spinBox_NewMap_Width->setValue(layout->width);
|
|
|
|
|
|
|
|
|
|
settings.height = layout->height;
|
|
|
|
|
ui->spinBox_NewMap_Height->setValue(layout->height);
|
|
|
|
|
|
|
|
|
|
settings.borderWidth = layout->border_width;
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setValue(layout->border_width);
|
|
|
|
|
|
|
|
|
|
settings.borderHeight = layout->border_height;
|
|
|
|
|
ui->spinBox_NewMap_BorderWidth->setValue(layout->border_height);
|
|
|
|
|
|
|
|
|
|
settings.primaryTilesetLabel = layout->tileset_primary_label;
|
|
|
|
|
ui->comboBox_NewMap_Primary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Primary_Tileset->findText(layout->tileset_primary_label));
|
|
|
|
|
|
|
|
|
|
settings.secondaryTilesetLabel = layout->tileset_secondary_label;
|
|
|
|
|
ui->comboBox_NewMap_Secondary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Secondary_Tileset->findText(layout->tileset_secondary_label));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::useLayout(QString layoutId) {
|
|
|
|
|
this->existingLayout = true;
|
|
|
|
|
this->layoutId = layoutId;
|
|
|
|
|
|
|
|
|
|
this->ui->comboBox_Layout->setCurrentIndex(this->ui->comboBox_Layout->findText(layoutId));
|
|
|
|
|
|
|
|
|
|
useLayoutSettings(project->mapLayouts.value(this->layoutId));
|
|
|
|
|
|
|
|
|
|
// Dimensions and tilesets can't be changed for new maps using an existing layout
|
|
|
|
|
ui->groupBox_MapDimensions->setDisabled(true);
|
|
|
|
|
ui->groupBox_BorderDimensions->setDisabled(true);
|
|
|
|
|
ui->groupBox_Tilesets->setDisabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::on_checkBox_UseExistingLayout_stateChanged(int state) {
|
|
|
|
|
bool layoutEditsEnabled = (state == Qt::Unchecked);
|
|
|
|
|
|
|
|
|
|
this->ui->comboBox_Layout->setEnabled(!layoutEditsEnabled);
|
|
|
|
|
bool NewMapDialog::validateMapDimensions() {
|
|
|
|
|
int size = project->getMapDataSize(ui->spinBox_MapWidth->value(), ui->spinBox_MapHeight->value());
|
|
|
|
|
int maxSize = project->getMaxMapDataSize();
|
|
|
|
|
|
|
|
|
|
this->ui->spinBox_NewMap_Width->setEnabled(layoutEditsEnabled);
|
|
|
|
|
this->ui->spinBox_NewMap_Height->setEnabled(layoutEditsEnabled);
|
|
|
|
|
this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled);
|
|
|
|
|
this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled);
|
|
|
|
|
this->ui->comboBox_NewMap_Primary_Tileset->setEnabled(layoutEditsEnabled);
|
|
|
|
|
this->ui->comboBox_NewMap_Secondary_Tileset->setEnabled(layoutEditsEnabled);
|
|
|
|
|
QString errorText;
|
|
|
|
|
if (size > maxSize) {
|
|
|
|
|
errorText = QString("The specified width and height are too large.\n"
|
|
|
|
|
"The maximum map width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
|
|
|
|
"The specified map width and height was: (%2 + 15) * (%3 + 14) = %4")
|
|
|
|
|
.arg(maxSize)
|
|
|
|
|
.arg(ui->spinBox_MapWidth->value())
|
|
|
|
|
.arg(ui->spinBox_MapHeight->value())
|
|
|
|
|
.arg(size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!layoutEditsEnabled) {
|
|
|
|
|
useLayout(this->layoutId);//this->ui->comboBox_Layout->currentText());
|
|
|
|
|
bool isValid = errorText.isEmpty();
|
|
|
|
|
ui->label_MapDimensionsError->setText(errorText);
|
|
|
|
|
ui->label_MapDimensionsError->setVisible(!isValid);
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NewMapDialog::validateMapGroup() {
|
|
|
|
|
this->group = project->groupNames.indexOf(ui->comboBox_Group->currentText());
|
|
|
|
|
|
|
|
|
|
QString errorText;
|
|
|
|
|
if (this->group < 0) {
|
|
|
|
|
errorText = QString("The specified map group '%1' does not exist.")
|
|
|
|
|
.arg(ui->comboBox_Group->currentText());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isValid = errorText.isEmpty();
|
|
|
|
|
ui->label_GroupError->setText(errorText);
|
|
|
|
|
ui->label_GroupError->setVisible(!isValid);
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NewMapDialog::validateTilesets() {
|
|
|
|
|
QString primaryTileset = ui->comboBox_PrimaryTileset->currentText();
|
|
|
|
|
QString secondaryTileset = ui->comboBox_SecondaryTileset->currentText();
|
|
|
|
|
|
|
|
|
|
QString primaryErrorText;
|
|
|
|
|
if (primaryTileset.isEmpty()) {
|
|
|
|
|
primaryErrorText = QString("The primary tileset cannot be empty.");
|
|
|
|
|
} else if (ui->comboBox_PrimaryTileset->findText(primaryTileset) < 0) {
|
|
|
|
|
primaryErrorText = QString("The specified primary tileset '%1' does not exist.").arg(primaryTileset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString secondaryErrorText;
|
|
|
|
|
if (secondaryTileset.isEmpty()) {
|
|
|
|
|
secondaryErrorText = QString("The secondary tileset cannot be empty.");
|
|
|
|
|
} else if (ui->comboBox_SecondaryTileset->findText(secondaryTileset) < 0) {
|
|
|
|
|
secondaryErrorText = QString("The specified secondary tileset '%2' does not exist.").arg(secondaryTileset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString errorText = QString("%1%2%3")
|
|
|
|
|
.arg(primaryErrorText)
|
|
|
|
|
.arg(!primaryErrorText.isEmpty() ? "\n" : "")
|
|
|
|
|
.arg(secondaryErrorText);
|
|
|
|
|
|
|
|
|
|
bool isValid = errorText.isEmpty();
|
|
|
|
|
ui->label_TilesetsError->setText(errorText);
|
|
|
|
|
ui->label_TilesetsError->setVisible(!isValid);
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NewMapDialog::validateID() {
|
|
|
|
|
QString id = ui->lineEdit_ID->text();
|
|
|
|
|
|
|
|
|
|
QString errorText;
|
|
|
|
|
QString expectedPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
|
|
|
|
if (!id.startsWith(expectedPrefix)) {
|
|
|
|
|
errorText = QString("The specified ID name '%1' must start with '%2'.").arg(id).arg(expectedPrefix);
|
|
|
|
|
} else {
|
|
|
|
|
this->existingLayout = false;
|
|
|
|
|
for (auto i = project->mapNamesToMapConstants.constBegin(), end = project->mapNamesToMapConstants.constEnd(); i != end; i++) {
|
|
|
|
|
if (id == i.value()) {
|
|
|
|
|
errorText = QString("The specified ID name '%1' is already in use.").arg(id);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isValid = errorText.isEmpty();
|
|
|
|
|
ui->label_IDError->setText(errorText);
|
|
|
|
|
ui->label_IDError->setVisible(!isValid);
|
|
|
|
|
ui->lineEdit_ID->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::on_comboBox_Layout_currentTextChanged(const QString &text) {
|
|
|
|
|
if (this->project->mapLayoutsTable.contains(text)) {
|
|
|
|
|
useLayout(text);
|
|
|
|
|
}
|
|
|
|
|
void NewMapDialog::on_lineEdit_ID_textChanged(const QString &) {
|
|
|
|
|
validateID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::on_lineEdit_NewMap_Name_textChanged(const QString &text) {
|
|
|
|
|
if (project->mapNames.contains(text)) {
|
|
|
|
|
this->ui->lineEdit_NewMap_Name->setStyleSheet("QLineEdit { background-color: rgba(255, 0, 0, 25%) }");
|
|
|
|
|
} else {
|
|
|
|
|
this->ui->lineEdit_NewMap_Name->setStyleSheet("");
|
|
|
|
|
bool NewMapDialog::validateName() {
|
|
|
|
|
QString name = ui->lineEdit_Name->text();
|
|
|
|
|
|
|
|
|
|
QString errorText;
|
|
|
|
|
if (project->mapNames.contains(name)) {
|
|
|
|
|
errorText = QString("The specified map name '%1' is already in use.").arg(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isValid = errorText.isEmpty();
|
|
|
|
|
ui->label_NameError->setText(errorText);
|
|
|
|
|
ui->label_NameError->setVisible(!isValid);
|
|
|
|
|
ui->lineEdit_Name->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::on_pushButton_NewMap_Accept_clicked() {
|
|
|
|
|
if (!checkNewMapDimensions() || !checkNewMapGroup()) {
|
|
|
|
|
// ignore when map dimensions or map group are invalid
|
|
|
|
|
void NewMapDialog::on_lineEdit_Name_textChanged(const QString &text) {
|
|
|
|
|
validateName();
|
|
|
|
|
ui->lineEdit_ID->setText(Map::mapConstantFromName(text));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NewMapDialog::on_pushButton_Accept_clicked() {
|
|
|
|
|
// Make sure to call each validation function so that all errors are shown at once.
|
|
|
|
|
bool success = true;
|
|
|
|
|
if (!validateMapDimensions()) success = false;
|
|
|
|
|
if (!validateMapGroup()) success = false;
|
|
|
|
|
if (!validateTilesets()) success = false;
|
|
|
|
|
if (!validateID()) success = false;
|
|
|
|
|
if (!validateName()) success = false;
|
|
|
|
|
if (!success)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// We check if the map name is empty separately from the validation above because it's likely
|
|
|
|
|
// that users will clear the name text box while editing, and we don't want to flash errors at them for this.
|
|
|
|
|
if (ui->lineEdit_Name->text().isEmpty()) {
|
|
|
|
|
ui->label_NameError->setText("The specified map name cannot be empty.");
|
|
|
|
|
ui->label_NameError->setVisible(true);
|
|
|
|
|
ui->lineEdit_Name->setStyleSheet(lineEdit_ErrorStylesheet);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map *newMap = new Map;
|
|
|
|
|
Layout *layout;
|
|
|
|
|
|
|
|
|
|
// If map name is not unique, use default value. Also use only valid characters.
|
|
|
|
|
// After stripping invalid characters, strip any leading digits.
|
|
|
|
|
static const QRegularExpression re_invalidChars("[^a-zA-Z0-9_]+");
|
|
|
|
|
QString newMapName = this->ui->lineEdit_NewMap_Name->text().remove(re_invalidChars);
|
|
|
|
|
static const QRegularExpression re_NaN("^[0-9]*");
|
|
|
|
|
newMapName.remove(re_NaN);
|
|
|
|
|
if (project->mapNames.contains(newMapName) || newMapName.isEmpty()) {
|
|
|
|
|
newMapName = project->getNewMapName();
|
|
|
|
|
newMap->setName(ui->lineEdit_Name->text());
|
|
|
|
|
newMap->setConstantName(ui->lineEdit_ID->text());
|
|
|
|
|
newMap->setSong(ui->comboBox_Song->currentText());
|
|
|
|
|
newMap->setLocation(ui->comboBox_Location->currentText());
|
|
|
|
|
newMap->setRequiresFlash(ui->checkBox_RequiresFlash->isChecked());
|
|
|
|
|
newMap->setWeather(ui->comboBox_Weather->currentText());
|
|
|
|
|
newMap->setType(ui->comboBox_Type->currentText());
|
|
|
|
|
newMap->setBattleScene(ui->comboBox_BattleScene->currentText());
|
|
|
|
|
newMap->setShowsLocation(ui->checkBox_ShowLocation->isChecked());
|
|
|
|
|
if (projectConfig.mapAllowFlagsEnabled) {
|
|
|
|
|
newMap->setAllowsRunning(ui->checkBox_AllowRunning->isChecked());
|
|
|
|
|
newMap->setAllowsBiking(ui->checkBox_AllowBiking->isChecked());
|
|
|
|
|
newMap->setAllowsEscaping(ui->checkBox_AllowEscaping->isChecked());
|
|
|
|
|
}
|
|
|
|
|
if (projectConfig.floorNumberEnabled) {
|
|
|
|
|
newMap->setFloorNumber(ui->spinBox_FloorNumber->value());
|
|
|
|
|
}
|
|
|
|
|
newMap->setNeedsHealLocation(ui->checkBox_CanFlyTo->isChecked());
|
|
|
|
|
|
|
|
|
|
newMap->setName(newMapName);
|
|
|
|
|
newMap->setType(this->ui->comboBox_NewMap_Type->currentText());
|
|
|
|
|
newMap->setLocation(this->ui->comboBox_NewMap_Location->currentText());
|
|
|
|
|
newMap->setSong(this->ui->comboBox_NewMap_Song->currentText());
|
|
|
|
|
newMap->setRequiresFlash(false);
|
|
|
|
|
newMap->setWeather(this->project->weatherNames.value(0, "0"));
|
|
|
|
|
newMap->setShowsLocation(this->ui->checkBox_NewMap_Show_Location->isChecked());
|
|
|
|
|
newMap->setBattleScene(this->project->mapBattleScenes.value(0, "0"));
|
|
|
|
|
|
|
|
|
|
Layout *layout;
|
|
|
|
|
if (this->existingLayout) {
|
|
|
|
|
layout = this->project->mapLayouts.value(this->layoutId);
|
|
|
|
|
newMap->setNeedsLayoutDir(false);
|
|
|
|
|
} else {
|
|
|
|
|
layout = new Layout;
|
|
|
|
|
layout->id = Layout::layoutConstantFromName(newMapName);
|
|
|
|
|
layout->id = Layout::layoutConstantFromName(newMap->name());
|
|
|
|
|
layout->name = QString("%1_Layout").arg(newMap->name());
|
|
|
|
|
layout->width = this->ui->spinBox_NewMap_Width->value();
|
|
|
|
|
layout->height = this->ui->spinBox_NewMap_Height->value();
|
|
|
|
|
layout->width = ui->spinBox_MapWidth->value();
|
|
|
|
|
layout->height = ui->spinBox_MapHeight->value();
|
|
|
|
|
if (projectConfig.useCustomBorderSize) {
|
|
|
|
|
layout->border_width = this->ui->spinBox_NewMap_BorderWidth->value();
|
|
|
|
|
layout->border_height = this->ui->spinBox_NewMap_BorderHeight->value();
|
|
|
|
|
layout->border_width = ui->spinBox_BorderWidth->value();
|
|
|
|
|
layout->border_height = ui->spinBox_BorderHeight->value();
|
|
|
|
|
} else {
|
|
|
|
|
layout->border_width = DEFAULT_BORDER_WIDTH;
|
|
|
|
|
layout->border_height = DEFAULT_BORDER_HEIGHT;
|
|
|
|
|
}
|
|
|
|
|
layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText();
|
|
|
|
|
layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText();
|
|
|
|
|
layout->tileset_primary_label = ui->comboBox_PrimaryTileset->currentText();
|
|
|
|
|
layout->tileset_secondary_label = ui->comboBox_SecondaryTileset->currentText();
|
|
|
|
|
QString basePath = projectConfig.getFilePath(ProjectFilePath::data_layouts_folders);
|
|
|
|
|
layout->border_path = QString("%1%2/border.bin").arg(basePath, newMapName);
|
|
|
|
|
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, newMapName);
|
|
|
|
|
layout->border_path = QString("%1%2/border.bin").arg(basePath, newMap->name());
|
|
|
|
|
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, newMap->name());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->importedMap) {
|
|
|
|
|
layout->blockdata = map->layout()->blockdata;
|
|
|
|
|
if (!map->layout()->border.isEmpty())
|
|
|
|
|
layout->border = map->layout()->border;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->ui->checkBox_NewMap_Flyable->isChecked()) {
|
|
|
|
|
newMap->setNeedsHealLocation(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (projectConfig.mapAllowFlagsEnabled) {
|
|
|
|
|
newMap->setAllowsRunning(this->ui->checkBox_NewMap_Allow_Running->isChecked());
|
|
|
|
|
newMap->setAllowsBiking(this->ui->checkBox_NewMap_Allow_Biking->isChecked());
|
|
|
|
|
newMap->setAllowsEscaping(this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked());
|
|
|
|
|
}
|
|
|
|
|
if (projectConfig.floorNumberEnabled) {
|
|
|
|
|
newMap->setFloorNumber(this->ui->spinBox_NewMap_Floor_Number->value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newMap->setLayout(layout);
|
|
|
|
|
|
|
|
|
|
if (this->existingLayout) {
|
|
|
|
|
project->loadMapLayout(newMap);
|
|
|
|
|
}
|
|
|
|
|
|