Merge branch 'master' into new-map-config

This commit is contained in:
Marcus Huderle 2022-09-24 15:40:08 -05:00
commit 07f1dd7a62
10 changed files with 43003 additions and 19 deletions

View file

@ -162,6 +162,7 @@ public:
this->newMapElevation = 3;
this->newMapBorderMetatileIds = DEFAULT_BORDER_RSE;
this->prefabFilepath = QString();
this->prefabImportPrompted = false;
this->customScripts.clear();
this->readKeys.clear();
}
@ -205,7 +206,9 @@ public:
void setCustomScripts(QList<QString> scripts);
QList<QString> getCustomScripts();
void setPrefabFilepath(QString filepath);
QString getPrefabFilepath();
QString getPrefabFilepath(bool setIfEmpty);
void setPrefabImportPrompted(bool prompted);
bool getPrefabImportPrompted();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@ -234,6 +237,7 @@ private:
QList<QString> customScripts;
QStringList readKeys;
QString prefabFilepath;
bool prefabImportPrompted;
};
extern ProjectConfig projectConfig;

View file

@ -33,6 +33,7 @@ class MetatileSelector: public SelectablePixmapItem {
public:
MetatileSelector(int numMetatilesWide, Map *map): SelectablePixmapItem(16, 16) {
this->externalSelection = false;
this->prefabSelection = false;
this->numMetatilesWide = numMetatilesWide;
this->map = map;
this->primaryTileset = map->layout->tileset_primary;
@ -46,7 +47,7 @@ public:
bool selectFromMap(uint16_t metatileId, uint16_t collision, uint16_t elevation);
void setTilesets(Tileset*, Tileset*);
MetatileSelection getMetatileSelection();
void setDirectSelection(MetatileSelection selection);
void setPrefabSelection(MetatileSelection selection);
void setExternalSelection(int, int, QList<uint16_t>, QList<QPair<uint16_t, uint16_t>>);
QPoint getMetatileIdCoordsOnWidget(uint16_t);
void setMap(Map*);
@ -60,6 +61,7 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
private:
bool externalSelection;
bool prefabSelection;
int numMetatilesWide;
Map *map;
int externalSelectionWidth;

View file

@ -23,6 +23,7 @@ public:
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
void addPrefab(MetatileSelection selection, Map *map, QString name);
void updatePrefabUi(Map *map);
void handlePrefabImport();
private:
MetatileSelector *selector;

View file

@ -3,5 +3,8 @@
<file>text/region_map_default_emerald.json</file>
<file>text/region_map_default_firered.json</file>
<file>text/region_map_default_ruby.json</file>
<file>text/prefabs_default_emerald.json</file>
<file>text/prefabs_default_firered.json</file>
<file>text/prefabs_default_ruby.json</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -504,6 +504,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
}
} else if (key == "prefabs_filepath") {
this->prefabFilepath = value;
} else if (key == "prefabs_import_prompted") {
setConfigBool(key, &this->prefabImportPrompted, value);
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
}
@ -549,6 +551,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
map.insert("new_map_border_metatiles", metatiles.join(","));
map.insert("custom_scripts", this->customScripts.join(","));
map.insert("prefabs_filepath", this->prefabFilepath);
map.insert("prefabs_import_prompted", QString::number(this->prefabImportPrompted));
return map;
}
@ -776,14 +779,22 @@ void ProjectConfig::setPrefabFilepath(QString filepath) {
this->save();
}
QString ProjectConfig::getPrefabFilepath() {
if (this->prefabFilepath.isEmpty()) {
// Default to the <projectroot>/prefabs.json, if no path exists.
this->setPrefabFilepath(QDir(this->projectDir).filePath("prefabs.json"));
QString ProjectConfig::getPrefabFilepath(bool setIfEmpty) {
if (setIfEmpty && this->prefabFilepath.isEmpty()) {
this->setPrefabFilepath("prefabs.json");
}
return this->prefabFilepath;
}
void ProjectConfig::setPrefabImportPrompted(bool prompted) {
this->prefabImportPrompted = prompted;
this->save();
}
bool ProjectConfig::getPrefabImportPrompted() {
return this->prefabImportPrompted;
}
ShortcutsConfig shortcutsConfig;
QString ShortcutsConfig::getConfigFilepath() {

View file

@ -36,7 +36,7 @@ void MetatileSelector::draw() {
painter.end();
this->setPixmap(QPixmap::fromImage(image));
if (!this->externalSelection || (this->externalSelectionWidth == 1 && this->externalSelectionHeight == 1)) {
if (!this->prefabSelection && (!this->externalSelection || (this->externalSelectionWidth == 1 && this->externalSelectionHeight == 1))) {
this->drawSelection();
}
}
@ -44,6 +44,13 @@ void MetatileSelector::draw() {
bool MetatileSelector::select(uint16_t metatileId) {
if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false;
this->externalSelection = false;
this->prefabSelection = false;
this->selection = MetatileSelection{
QPoint(1, 1),
false,
QList<MetatileSelectionItem>({MetatileSelectionItem{true, metatileId}}),
QList<CollisionSelectionItem>(),
};
QPoint coords = this->getMetatileIdCoords(metatileId);
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
this->updateSelectedMetatiles();
@ -73,6 +80,7 @@ MetatileSelection MetatileSelector::getMetatileSelection() {
}
void MetatileSelector::setExternalSelection(int width, int height, QList<uint16_t> metatiles, QList<QPair<uint16_t, uint16_t>> collisions) {
this->prefabSelection = false;
this->externalSelection = true;
this->externalSelectionWidth = width;
this->externalSelectionHeight = height;
@ -95,8 +103,9 @@ void MetatileSelector::setExternalSelection(int width, int height, QList<uint16_
emit selectedMetatilesChanged();
}
void MetatileSelector::setDirectSelection(MetatileSelection selection) {
void MetatileSelector::setPrefabSelection(MetatileSelection selection) {
this->externalSelection = false;
this->prefabSelection = true;
this->externalSelectedMetatiles.clear();
this->selection = selection;
this->draw();
@ -142,6 +151,7 @@ void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
void MetatileSelector::updateSelectedMetatiles() {
this->externalSelection = false;
this->prefabSelection = false;
this->selection.metatileItems.clear();
this->selection.collisionItems.clear();
this->selection.hasCollision = false;

View file

@ -21,17 +21,18 @@ using OrderedJsonDoc = poryjson::JsonDoc;
void Prefab::loadPrefabs() {
this->items.clear();
QString filepath = projectConfig.getPrefabFilepath();
QString filepath = projectConfig.getPrefabFilepath(false);
if (filepath.isEmpty()) return;
ParseUtil parser;
QJsonDocument prefabDoc;
QFileInfo info(filepath);
if (info.isRelative()) {
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
}
if (!QFile::exists(filepath) || !parser.tryParseJsonFile(&prefabDoc, filepath)) {
QString relativePath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
if (!parser.tryParseJsonFile(&prefabDoc, relativePath)) {
logError(QString("Failed to prefab data from %1").arg(filepath));
return;
}
logError(QString("Failed to read prefab data from %1").arg(filepath));
return;
}
QJsonArray prefabs = prefabDoc.array();
@ -84,11 +85,22 @@ void Prefab::loadPrefabs() {
}
void Prefab::savePrefabs() {
QString filepath = projectConfig.getPrefabFilepath();
QString filepath = projectConfig.getPrefabFilepath(true);
if (filepath.isEmpty()) return;
QFileInfo info(filepath);
if (info.isRelative()) {
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
}
QFile prefabsFile(filepath);
if (!prefabsFile.open(QIODevice::WriteOnly)) {
logError(QString("Error: Could not open %1 for writing").arg(filepath));
QMessageBox messageBox;
messageBox.setText("Failed to save prefabs file!");
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath));
messageBox.setDetailedText("Any created prefabs will not be available next time Porymap is opened. Please fix your prefabs_filepath in the Porymap project config file.");
messageBox.setIcon(QMessageBox::Warning);
messageBox.exec();
return;
}
@ -106,13 +118,15 @@ void Prefab::savePrefabs() {
int index = y * item.selection.dimensions.x() + x;
auto metatileItem = item.selection.metatileItems.at(index);
if (metatileItem.enabled) {
auto collisionItem = item.selection.collisionItems.at(index);
OrderedJson::object metatileObj;
metatileObj["x"] = x;
metatileObj["y"] = y;
metatileObj["metatile_id"] = metatileItem.metatileId;
metatileObj["collision"] = collisionItem.collision;
metatileObj["elevation"] = collisionItem.elevation;
if (item.selection.hasCollision && index < item.selection.collisionItems.size()) {
auto collisionItem = item.selection.collisionItems.at(index);
metatileObj["collision"] = collisionItem.collision;
metatileObj["elevation"] = collisionItem.elevation;
}
metatiles.push_back(metatileObj);
}
}
@ -145,6 +159,7 @@ void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLa
this->selector = selector;
this->prefabWidget = prefabWidget;
this->emptyPrefabLabel = emptyPrefabLabel;
this->handlePrefabImport();
this->loadPrefabs();
this->updatePrefabUi(map);
}
@ -194,7 +209,7 @@ void Prefab::updatePrefabUi(Map *map) {
// Clicking on the prefab graphics item selects it for painting.
QObject::connect(frame->ui->graphicsView_Prefab, &ClickableGraphicsView::clicked, [this, item](){
selector->setDirectSelection(item.selection);
selector->setPrefabSelection(item.selection);
});
// Clicking the delete button removes it from the list of known prefabs and updates the UI.
@ -254,4 +269,69 @@ void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) {
this->updatePrefabUi(map);
}
void Prefab::handlePrefabImport() {
BaseGameVersion version = projectConfig.getBaseGameVersion();
// Ensure we have default prefabs for the project's game version.
if (version != BaseGameVersion::pokeruby && version != BaseGameVersion::pokeemerald && version != BaseGameVersion::pokefirered)
return;
// Exit early if the user has already setup prefabs.
if (!projectConfig.getPrefabFilepath(false).isEmpty())
return;
// Exit early if the user has already gone through this import prompt before.
if (projectConfig.getPrefabImportPrompted())
return;
// Display a dialog box to the user, asking if the default prefabs should be imported
// into their project.
QMessageBox::StandardButton prompt =
QMessageBox::question(nullptr,
"Import Default Prefabs",
QString("Would you like to import the default prefabs for %1? This will create a file called 'prefabs.json' in your project directory.")
.arg(projectConfig.getBaseGameVersionString()),
QMessageBox::Yes | QMessageBox::No);
if (prompt == QMessageBox::Yes) {
// Sets up the default prefabs.json filepath.
QString filepath = projectConfig.getPrefabFilepath(true);
QFileInfo info(filepath);
if (info.isRelative()) {
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
}
QFile prefabsFile(filepath);
if (!prefabsFile.open(QIODevice::WriteOnly)) {
projectConfig.setPrefabFilepath(QString());
logError(QString("Error: Could not open %1 for writing").arg(filepath));
QMessageBox messageBox;
messageBox.setText("Failed to import default prefabs file!");
messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath));
messageBox.setIcon(QMessageBox::Warning);
messageBox.exec();
return;
}
ParseUtil parser;
QString content;
switch (version) {
case BaseGameVersion::pokeruby:
content = parser.readTextFile(":/text/prefabs_default_ruby.json");
break;
case BaseGameVersion::pokefirered:
content = parser.readTextFile(":/text/prefabs_default_firered.json");
break;
case BaseGameVersion::pokeemerald:
content = parser.readTextFile(":/text/prefabs_default_emerald.json");
break;
}
prefabsFile.write(content.toUtf8());
prefabsFile.close();
}
projectConfig.setPrefabImportPrompted(true);
}
Prefab prefab;