mirror of
https://github.com/huderlem/porymap.git
synced 2026-09-27 10:26:33 -05:00
Merge branch 'master' into label-copy
This commit is contained in:
@@ -522,11 +522,11 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for enable_heal_location_respawn_data: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if (key == "enable_object_event_in_connection") {
|
||||
} else if (key == "enable_event_clone_object") {
|
||||
bool ok;
|
||||
this->enableObjectEventInConnection = value.toInt(&ok);
|
||||
this->enableEventCloneObject = value.toInt(&ok);
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for enable_object_event_in_connection: '%1'. Must be 0 or 1.").arg(value));
|
||||
logWarn(QString("Invalid config value for enable_event_clone_object: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if (key == "enable_floor_number") {
|
||||
bool ok;
|
||||
@@ -570,7 +570,7 @@ void ProjectConfig::setUnreadKeys() {
|
||||
if (!readKeys.contains("enable_hidden_item_quantity")) this->enableHiddenItemQuantity = isPokefirered;
|
||||
if (!readKeys.contains("enable_hidden_item_requires_itemfinder")) this->enableHiddenItemRequiresItemfinder = isPokefirered;
|
||||
if (!readKeys.contains("enable_heal_location_respawn_data")) this->enableHealLocationRespawnData = isPokefirered;
|
||||
if (!readKeys.contains("enable_object_event_in_connection")) this->enableObjectEventInConnection = isPokefirered;
|
||||
if (!readKeys.contains("enable_event_clone_object")) this->enableEventCloneObject = isPokefirered;
|
||||
if (!readKeys.contains("enable_floor_number")) this->enableFloorNumber = isPokefirered;
|
||||
if (!readKeys.contains("create_map_text_file")) this->createMapTextFile = (this->baseGameVersion != BaseGameVersion::pokeemerald);
|
||||
}
|
||||
@@ -587,7 +587,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
||||
map.insert("enable_hidden_item_quantity", QString::number(this->enableHiddenItemQuantity));
|
||||
map.insert("enable_hidden_item_requires_itemfinder", QString::number(this->enableHiddenItemRequiresItemfinder));
|
||||
map.insert("enable_heal_location_respawn_data", QString::number(this->enableHealLocationRespawnData));
|
||||
map.insert("enable_object_event_in_connection", QString::number(this->enableObjectEventInConnection));
|
||||
map.insert("enable_event_clone_object", QString::number(this->enableEventCloneObject));
|
||||
map.insert("enable_floor_number", QString::number(this->enableFloorNumber));
|
||||
map.insert("create_map_text_file", QString::number(this->createMapTextFile));
|
||||
map.insert("enable_triple_layer_metatiles", QString::number(this->enableTripleLayerMetatiles));
|
||||
@@ -628,7 +628,7 @@ void ProjectConfig::onNewConfigFileCreated() {
|
||||
this->enableHiddenItemQuantity = isPokefirered;
|
||||
this->enableHiddenItemRequiresItemfinder = isPokefirered;
|
||||
this->enableHealLocationRespawnData = isPokefirered;
|
||||
this->enableObjectEventInConnection = isPokefirered;
|
||||
this->enableEventCloneObject = isPokefirered;
|
||||
this->enableFloorNumber = isPokefirered;
|
||||
this->createMapTextFile = (this->baseGameVersion != BaseGameVersion::pokeemerald);
|
||||
this->useEncounterJson = true;
|
||||
@@ -739,13 +739,13 @@ bool ProjectConfig::getHealLocationRespawnDataEnabled() {
|
||||
return this->enableHealLocationRespawnData;
|
||||
}
|
||||
|
||||
void ProjectConfig::setObjectEventInConnectionEnabled(bool enable) {
|
||||
this->enableObjectEventInConnection = enable;
|
||||
void ProjectConfig::setEventCloneObjectEnabled(bool enable) {
|
||||
this->enableEventCloneObject = enable;
|
||||
this->save();
|
||||
}
|
||||
|
||||
bool ProjectConfig::getObjectEventInConnectionEnabled() {
|
||||
return this->enableObjectEventInConnection;
|
||||
bool ProjectConfig::getEventCloneObjectEnabled() {
|
||||
return this->enableEventCloneObject;
|
||||
}
|
||||
|
||||
void ProjectConfig::setFloorNumberEnabled(bool enable) {
|
||||
|
||||
@@ -9,18 +9,16 @@
|
||||
int getEventTypeMask(QList<Event *> events) {
|
||||
int eventTypeMask = 0;
|
||||
for (auto event : events) {
|
||||
if (event->get("event_type") == EventType::Object) {
|
||||
QString groupType = event->get("event_group_type");
|
||||
if (groupType == EventGroup::Object) {
|
||||
eventTypeMask |= IDMask_EventType_Object;
|
||||
} else if (event->get("event_type") == EventType::Warp) {
|
||||
} else if (groupType == EventGroup::Warp) {
|
||||
eventTypeMask |= IDMask_EventType_Warp;
|
||||
} else if (event->get("event_type") == EventType::Trigger ||
|
||||
event->get("event_type") == EventType::WeatherTrigger) {
|
||||
} else if (groupType == EventGroup::Coord) {
|
||||
eventTypeMask |= IDMask_EventType_Trigger;
|
||||
} else if (event->get("event_type") == EventType::Sign ||
|
||||
event->get("event_type") == EventType::HiddenItem ||
|
||||
event->get("event_type") == EventType::SecretBase) {
|
||||
} else if (groupType == EventGroup::Bg) {
|
||||
eventTypeMask |= IDMask_EventType_BG;
|
||||
} else if (event->get("event_type") == EventType::HealLocation) {
|
||||
} else if (groupType == EventGroup::Heal) {
|
||||
eventTypeMask |= IDMask_EventType_Heal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,33 @@
|
||||
#include "project.h"
|
||||
#include "config.h"
|
||||
|
||||
QString EventGroup::Object = "object_event_group";
|
||||
QString EventGroup::Warp = "warp_event_group";
|
||||
QString EventGroup::Heal = "heal_event_group";
|
||||
QString EventGroup::Coord = "coord_event_group";
|
||||
QString EventGroup::Bg = "bg_event_group";
|
||||
|
||||
QString EventType::Object = "event_object";
|
||||
QString EventType::CloneObject = "event_clone_object";
|
||||
QString EventType::Warp = "event_warp";
|
||||
QString EventType::Trigger = "event_trigger";
|
||||
QString EventType::WeatherTrigger = "event_weather_trigger";
|
||||
QString EventType::Sign = "event_sign";
|
||||
QString EventType::HiddenItem = "event_hidden_item";
|
||||
QString EventType::SecretBase = "event_secret_base";
|
||||
QString EventType::HealLocation = "event_heal_location";
|
||||
QString EventType::HealLocation = "event_healspot";
|
||||
|
||||
const QMap<QString, QString> EventTypeTable = {
|
||||
{EventType::Object, EventGroup::Object},
|
||||
{EventType::CloneObject, EventGroup::Object},
|
||||
{EventType::Warp, EventGroup::Warp},
|
||||
{EventType::Trigger, EventGroup::Coord},
|
||||
{EventType::WeatherTrigger, EventGroup::Coord},
|
||||
{EventType::Sign, EventGroup::Bg},
|
||||
{EventType::HiddenItem, EventGroup::Bg},
|
||||
{EventType::SecretBase, EventGroup::Bg},
|
||||
{EventType::HealLocation, EventGroup::Heal},
|
||||
};
|
||||
|
||||
Event::Event() :
|
||||
spriteWidth(16),
|
||||
@@ -41,6 +60,8 @@ Event* Event::createNewEvent(QString event_type, QString map_name, Project *proj
|
||||
if (event_type == EventType::Object) {
|
||||
event = createNewObjectEvent(project);
|
||||
event->setFrameFromMovement(event->get("movement_type"));
|
||||
} else if (event_type == EventType::CloneObject) {
|
||||
event = createNewCloneObjectEvent(project, map_name);
|
||||
} else if (event_type == EventType::Warp) {
|
||||
event = createNewWarpEvent(map_name);
|
||||
} else if (event_type == EventType::HealLocation) {
|
||||
@@ -60,6 +81,8 @@ Event* Event::createNewEvent(QString event_type, QString map_name, Project *proj
|
||||
event = new Event;
|
||||
}
|
||||
|
||||
event->put("event_type", event_type);
|
||||
event->put("event_group_type", typeToGroup(event_type));
|
||||
event->setX(0);
|
||||
event->setY(0);
|
||||
return event;
|
||||
@@ -68,13 +91,8 @@ Event* Event::createNewEvent(QString event_type, QString map_name, Project *proj
|
||||
Event* Event::createNewObjectEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "object_event_group");
|
||||
event->put("event_type", EventType::Object);
|
||||
event->put("sprite", project->gfxNames.first());
|
||||
event->put("sprite", project->gfxDefines.keys().first());
|
||||
event->put("movement_type", project->movementTypes.first());
|
||||
if (projectConfig.getObjectEventInConnectionEnabled()) {
|
||||
event->put("in_connection", false);
|
||||
}
|
||||
event->put("radius_x", 0);
|
||||
event->put("radius_y", 0);
|
||||
event->put("script_label", "NULL");
|
||||
@@ -86,11 +104,18 @@ Event* Event::createNewObjectEvent(Project *project)
|
||||
return event;
|
||||
}
|
||||
|
||||
Event* Event::createNewCloneObjectEvent(Project *project, QString map_name)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("sprite", project->gfxDefines.keys().first());
|
||||
event->put("target_local_id", 1);
|
||||
event->put("target_map", map_name);
|
||||
return event;
|
||||
}
|
||||
|
||||
Event* Event::createNewWarpEvent(QString map_name)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "warp_event_group");
|
||||
event->put("event_type", EventType::Warp);
|
||||
event->put("destination_warp", 0);
|
||||
event->put("destination_map_name", map_name);
|
||||
event->put("elevation", 0);
|
||||
@@ -100,8 +125,6 @@ Event* Event::createNewWarpEvent(QString map_name)
|
||||
Event* Event::createNewHealLocationEvent(QString map_name)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "heal_event_group");
|
||||
event->put("event_type", EventType::HealLocation);
|
||||
event->put("loc_name", QString(Map::mapConstantFromName(map_name)).remove(0,4));
|
||||
event->put("id_name", map_name.replace(QRegularExpression("([a-z])([A-Z])"), "\\1_\\2").toUpper());
|
||||
event->put("elevation", 3);
|
||||
@@ -115,8 +138,6 @@ Event* Event::createNewHealLocationEvent(QString map_name)
|
||||
Event* Event::createNewTriggerEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "coord_event_group");
|
||||
event->put("event_type", EventType::Trigger);
|
||||
event->put("script_label", "NULL");
|
||||
event->put("script_var", project->varNames.first());
|
||||
event->put("script_var_value", "0");
|
||||
@@ -127,8 +148,6 @@ Event* Event::createNewTriggerEvent(Project *project)
|
||||
Event* Event::createNewWeatherTriggerEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "coord_event_group");
|
||||
event->put("event_type", EventType::WeatherTrigger);
|
||||
event->put("weather", project->coordEventWeatherNames.first());
|
||||
event->put("elevation", 0);
|
||||
return event;
|
||||
@@ -137,8 +156,6 @@ Event* Event::createNewWeatherTriggerEvent(Project *project)
|
||||
Event* Event::createNewSignEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "bg_event_group");
|
||||
event->put("event_type", EventType::Sign);
|
||||
event->put("player_facing_direction", project->bgEventFacingDirections.first());
|
||||
event->put("script_label", "NULL");
|
||||
event->put("elevation", 0);
|
||||
@@ -148,8 +165,6 @@ Event* Event::createNewSignEvent(Project *project)
|
||||
Event* Event::createNewHiddenItemEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "bg_event_group");
|
||||
event->put("event_type", EventType::HiddenItem);
|
||||
event->put("item", project->itemNames.first());
|
||||
event->put("flag", project->flagNames.first());
|
||||
event->put("elevation", 3);
|
||||
@@ -165,8 +180,6 @@ Event* Event::createNewHiddenItemEvent(Project *project)
|
||||
Event* Event::createNewSecretBaseEvent(Project *project)
|
||||
{
|
||||
Event *event = new Event;
|
||||
event->put("event_group_type", "bg_event_group");
|
||||
event->put("event_type", EventType::SecretBase);
|
||||
event->put("secret_base_id", project->secretBaseIds.first());
|
||||
event->put("elevation", 0);
|
||||
return event;
|
||||
@@ -182,81 +195,76 @@ int Event::getPixelY()
|
||||
return (this->y() * 16) - qMax(0, this->spriteHeight - 16);
|
||||
}
|
||||
|
||||
static QMap<QString, bool> expectedObjectFields {
|
||||
{"graphics_id", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"movement_type", true},
|
||||
{"movement_range_x", true},
|
||||
{"movement_range_y", true},
|
||||
{"trainer_type", true},
|
||||
{"trainer_sight_or_berry_tree_id", true},
|
||||
{"script", true},
|
||||
{"flag", true},
|
||||
const QSet<QString> expectedObjectFields = {
|
||||
"graphics_id",
|
||||
"elevation",
|
||||
"movement_type",
|
||||
"movement_range_x",
|
||||
"movement_range_y",
|
||||
"trainer_type",
|
||||
"trainer_sight_or_berry_tree_id",
|
||||
"script",
|
||||
"flag",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedWarpFields {
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"dest_map", true},
|
||||
{"dest_warp_id", true},
|
||||
const QSet<QString> expectedCloneObjectFields = {
|
||||
"type",
|
||||
"graphics_id",
|
||||
"target_local_id",
|
||||
"target_map",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedTriggerFields {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"var", true},
|
||||
{"var_value", true},
|
||||
{"script", true},
|
||||
const QSet<QString> expectedWarpFields = {
|
||||
"elevation",
|
||||
"dest_map",
|
||||
"dest_warp_id",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedWeatherTriggerFields {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"weather", true},
|
||||
const QSet<QString> expectedTriggerFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"var",
|
||||
"var_value",
|
||||
"script",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedSignFields {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"player_facing_dir", true},
|
||||
{"script", true},
|
||||
const QSet<QString> expectedWeatherTriggerFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"weather",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedHiddenItemFields {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"item", true},
|
||||
{"flag", true},
|
||||
const QSet<QString> expectedSignFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"player_facing_dir",
|
||||
"script",
|
||||
};
|
||||
|
||||
static QMap<QString, bool> expectedSecretBaseFields {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"secret_base_id", true},
|
||||
const QSet<QString> expectedHiddenItemFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"item",
|
||||
"flag",
|
||||
};
|
||||
|
||||
QMap<QString, bool> Event::getExpectedFields()
|
||||
const QSet<QString> expectedSecretBaseFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"secret_base_id",
|
||||
};
|
||||
|
||||
QSet<QString> Event::getExpectedFields()
|
||||
{
|
||||
QString type = this->get("event_type");
|
||||
QMap<QString, bool> expectedFields = QMap<QString, bool>();
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
if (type == EventType::Object) {
|
||||
expectedFields = expectedObjectFields;
|
||||
if (projectConfig.getObjectEventInConnectionEnabled()) {
|
||||
expectedFields.insert("in_connection", true);
|
||||
if (projectConfig.getEventCloneObjectEnabled()) {
|
||||
expectedFields.insert("type");
|
||||
}
|
||||
} else if (type == EventType::CloneObject) {
|
||||
expectedFields = expectedCloneObjectFields;
|
||||
} else if (type == EventType::Warp) {
|
||||
expectedFields = expectedWarpFields;
|
||||
} else if (type == EventType::Trigger) {
|
||||
@@ -268,23 +276,24 @@ QMap<QString, bool> Event::getExpectedFields()
|
||||
} else if (type == EventType::HiddenItem) {
|
||||
expectedFields = expectedHiddenItemFields;
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
expectedFields.insert("quantity", true);
|
||||
expectedFields.insert("quantity");
|
||||
}
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
expectedFields.insert("underfoot", true);
|
||||
expectedFields.insert("underfoot");
|
||||
}
|
||||
} else if (type == EventType::SecretBase) {
|
||||
expectedFields = expectedSecretBaseFields;
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
return expectedFields;
|
||||
};
|
||||
|
||||
void Event::readCustomValues(QJsonObject values)
|
||||
{
|
||||
this->customValues.clear();
|
||||
QMap<QString, bool> expectedValues = this->getExpectedFields();
|
||||
QSet<QString> expectedFields = this->getExpectedFields();
|
||||
for (QString key : values.keys()) {
|
||||
if (!expectedValues.contains(key)) {
|
||||
if (!expectedFields.contains(key)) {
|
||||
this->customValues[key] = values[key].toString();
|
||||
}
|
||||
}
|
||||
@@ -301,24 +310,38 @@ void Event::addCustomValuesTo(OrderedJson::object *obj)
|
||||
|
||||
OrderedJson::object Event::buildObjectEventJSON()
|
||||
{
|
||||
OrderedJson::object eventObj;
|
||||
eventObj["graphics_id"] = this->get("sprite");
|
||||
if (projectConfig.getObjectEventInConnectionEnabled()) {
|
||||
eventObj["in_connection"] = this->getInt("in_connection") > 0 || this->get("in_connection") == "TRUE";
|
||||
OrderedJson::object objectObj;
|
||||
if (projectConfig.getEventCloneObjectEnabled()) {
|
||||
objectObj["type"] = "object";
|
||||
}
|
||||
eventObj["x"] = this->getS16("x");
|
||||
eventObj["y"] = this->getS16("y");
|
||||
eventObj["elevation"] = this->getInt("elevation");
|
||||
eventObj["movement_type"] = this->get("movement_type");
|
||||
eventObj["movement_range_x"] = this->getInt("radius_x");
|
||||
eventObj["movement_range_y"] = this->getInt("radius_y");
|
||||
eventObj["trainer_type"] = this->get("trainer_type");
|
||||
eventObj["trainer_sight_or_berry_tree_id"] = this->get("sight_radius_tree_id");
|
||||
eventObj["script"] = this->get("script_label");
|
||||
eventObj["flag"] = this->get("event_flag");
|
||||
this->addCustomValuesTo(&eventObj);
|
||||
objectObj["graphics_id"] = this->get("sprite");
|
||||
objectObj["x"] = this->getS16("x");
|
||||
objectObj["y"] = this->getS16("y");
|
||||
objectObj["elevation"] = this->getInt("elevation");
|
||||
objectObj["movement_type"] = this->get("movement_type");
|
||||
objectObj["movement_range_x"] = this->getInt("radius_x");
|
||||
objectObj["movement_range_y"] = this->getInt("radius_y");
|
||||
objectObj["trainer_type"] = this->get("trainer_type");
|
||||
objectObj["trainer_sight_or_berry_tree_id"] = this->get("sight_radius_tree_id");
|
||||
objectObj["script"] = this->get("script_label");
|
||||
objectObj["flag"] = this->get("event_flag");
|
||||
this->addCustomValuesTo(&objectObj);
|
||||
|
||||
return eventObj;
|
||||
return objectObj;
|
||||
}
|
||||
|
||||
OrderedJson::object Event::buildCloneObjectEventJSON(const QMap<QString, QString> &mapNamesToMapConstants)
|
||||
{
|
||||
OrderedJson::object cloneObj;
|
||||
cloneObj["type"] = "clone";
|
||||
cloneObj["graphics_id"] = this->get("sprite");
|
||||
cloneObj["x"] = this->getS16("x");
|
||||
cloneObj["y"] = this->getS16("y");
|
||||
cloneObj["target_local_id"] = this->getInt("target_local_id");
|
||||
cloneObj["target_map"] = mapNamesToMapConstants.value(this->get("target_map"));
|
||||
this->addCustomValuesTo(&cloneObj);
|
||||
|
||||
return cloneObj;
|
||||
}
|
||||
|
||||
OrderedJson::object Event::buildWarpEventJSON(const QMap<QString, QString> &mapNamesToMapConstants)
|
||||
@@ -442,3 +465,16 @@ void Event::setFrameFromMovement(QString facingDir) {
|
||||
this->hFlip = true;
|
||||
}
|
||||
}
|
||||
|
||||
// All event groups excepts warps have IDs that start at 1
|
||||
int Event::getIndexOffset(QString group_type) {
|
||||
return (group_type == EventGroup::Warp) ? 0 : 1;
|
||||
}
|
||||
|
||||
bool Event::isValidType(QString event_type) {
|
||||
return EventTypeTable.contains(event_type);
|
||||
}
|
||||
|
||||
QString Event::typeToGroup(QString event_type) {
|
||||
return EventTypeTable.value(event_type, QString());
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ QString ParseUtil::readTextFile(const QString &path) {
|
||||
return QString();
|
||||
}
|
||||
QTextStream in(&file);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
in.setCodec("UTF-8");
|
||||
#endif // Qt6 defaults to UTF-8, but setCodec is renamed to setEncoding
|
||||
QString text = "";
|
||||
while (!in.atEnd()) {
|
||||
text += in.readLine() + '\n';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
286
src/core/regionmapeditcommands.cpp
Normal file
286
src/core/regionmapeditcommands.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "regionmapeditcommands.h"
|
||||
|
||||
|
||||
|
||||
EditTilemap::EditTilemap(RegionMap *map, QByteArray oldTilemap, QByteArray newTilemap, unsigned actionId, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Edit Tilemap");
|
||||
|
||||
this->map = map;
|
||||
this->oldTilemap = oldTilemap;
|
||||
this->newTilemap = newTilemap;
|
||||
this->actionId = actionId;
|
||||
}
|
||||
|
||||
void EditTilemap::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->setTilemap(this->newTilemap);
|
||||
}
|
||||
|
||||
void EditTilemap::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setTilemap(this->oldTilemap);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
bool EditTilemap::mergeWith(const QUndoCommand *command) {
|
||||
const EditTilemap *other = static_cast<const EditTilemap *>(command);
|
||||
|
||||
if (this->map != other->map)
|
||||
return false;
|
||||
|
||||
if (this->actionId != other->actionId)
|
||||
return false;
|
||||
|
||||
newTilemap = other->newTilemap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
EditLayout::EditLayout(RegionMap *map, QString layer, int index, QList<LayoutSquare> oldLayout, QList<LayoutSquare> newLayout, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Edit Layout");
|
||||
|
||||
this->map = map;
|
||||
this->layer = layer;
|
||||
this->index = index;
|
||||
this->oldLayout = oldLayout;
|
||||
this->newLayout = newLayout;
|
||||
}
|
||||
|
||||
void EditLayout::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->setLayout(this->layer, this->newLayout);
|
||||
}
|
||||
|
||||
void EditLayout::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setLayout(this->layer, this->oldLayout);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
bool EditLayout::mergeWith(const QUndoCommand *command) {
|
||||
const EditLayout *other = static_cast<const EditLayout *>(command);
|
||||
|
||||
if (this->map != other->map)
|
||||
return false;
|
||||
|
||||
if (this->text() != other->text())
|
||||
return false;
|
||||
|
||||
if (this->index != other->index)
|
||||
return false;
|
||||
|
||||
this->newLayout = other->newLayout;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
ResizeLayout::ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight,
|
||||
QMap<QString, QList<LayoutSquare>> oldLayouts, QMap<QString, QList<LayoutSquare>> newLayouts, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Change Layout Dimensions");
|
||||
|
||||
this->map = map;
|
||||
this->oldWidth = oldWidth;
|
||||
this->oldHeight = oldHeight;
|
||||
this->newWidth = newWidth;
|
||||
this->newHeight = newHeight;
|
||||
this->oldLayouts = oldLayouts;
|
||||
this->newLayouts = newLayouts;
|
||||
}
|
||||
|
||||
void ResizeLayout::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->setLayoutDimensions(newWidth, newHeight, false);
|
||||
map->setAllLayouts(this->newLayouts);
|
||||
}
|
||||
|
||||
void ResizeLayout::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setLayoutDimensions(oldWidth, oldHeight, false);
|
||||
map->setAllLayouts(this->oldLayouts);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
bool ResizeLayout::mergeWith(const QUndoCommand *command) {
|
||||
const ResizeLayout *other = static_cast<const ResizeLayout *>(command);
|
||||
|
||||
if (this->map != other->map)
|
||||
return false;
|
||||
|
||||
// always allow consecutive dimension changes to merge
|
||||
|
||||
this->newWidth = other->newWidth;
|
||||
this->newHeight = other->newHeight;
|
||||
this->newLayouts = other->newLayouts;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
EditEntry::EditEntry(RegionMap *map, QString section, MapSectionEntry oldEntry, MapSectionEntry newEntry, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Change Entry for " + section);
|
||||
|
||||
this->map = map;
|
||||
this->section = section;
|
||||
this->oldEntry = oldEntry;
|
||||
this->newEntry = newEntry;
|
||||
}
|
||||
|
||||
void EditEntry::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->setEntry(section, newEntry);
|
||||
}
|
||||
|
||||
void EditEntry::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setEntry(section, oldEntry);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
bool EditEntry::mergeWith(const QUndoCommand *command) {
|
||||
const EditEntry *other = static_cast<const EditEntry *>(command);
|
||||
|
||||
if (this->map != other->map)
|
||||
return false;
|
||||
|
||||
if (this->section != other->section)
|
||||
return false;
|
||||
|
||||
this->newEntry = other->newEntry;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
AddEntry::AddEntry(RegionMap *map, QString section, MapSectionEntry oldEntry, MapSectionEntry newEntry, QUndoCommand *parent)
|
||||
: EditEntry(map, section, oldEntry, newEntry, parent) {
|
||||
setText("Add Entry for " + section);
|
||||
}
|
||||
|
||||
void AddEntry::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->setEntry(section, newEntry);
|
||||
}
|
||||
|
||||
void AddEntry::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->removeEntry(section);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
RemoveEntry::RemoveEntry(RegionMap *map, QString section, MapSectionEntry oldEntry, MapSectionEntry newEntry, QUndoCommand *parent)
|
||||
: EditEntry(map, section, oldEntry, newEntry, parent) {
|
||||
setText("Remove Entry for " + section);
|
||||
}
|
||||
|
||||
void RemoveEntry::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->removeEntry(section);
|
||||
}
|
||||
|
||||
void RemoveEntry::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setEntry(section, oldEntry);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
ResizeTilemap::ResizeTilemap(RegionMap *map, QByteArray oldTilemap, QByteArray newTilemap,
|
||||
int oldWidth, int oldHeight, int newWidth, int newHeight, QUndoCommand *parent)
|
||||
: EditTilemap(map, oldTilemap, newTilemap, -1, parent) {
|
||||
setText("Resize Tilemap");
|
||||
|
||||
this->oldWidth = oldWidth;
|
||||
this->oldHeight = oldHeight;
|
||||
this->newWidth = newWidth;
|
||||
this->newHeight = newHeight;
|
||||
}
|
||||
|
||||
void ResizeTilemap::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->resizeTilemap(this->newWidth, this->newHeight, false);
|
||||
map->setTilemap(this->newTilemap);
|
||||
map->emitDisplay();
|
||||
}
|
||||
|
||||
void ResizeTilemap::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->resizeTilemap(this->oldWidth, this->oldHeight, false);
|
||||
map->setTilemap(this->oldTilemap);
|
||||
map->emitDisplay();
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
ClearEntries::ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry> entries, QUndoCommand *parent) {
|
||||
setText("Clear Entries");
|
||||
|
||||
this->map = map;
|
||||
this->entries = entries;
|
||||
}
|
||||
|
||||
void ClearEntries::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
if (!map) return;
|
||||
|
||||
map->clearEntries();
|
||||
}
|
||||
|
||||
void ClearEntries::undo() {
|
||||
if (!map) return;
|
||||
|
||||
map->setEntries(entries);
|
||||
|
||||
QUndoCommand::undo();
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ bool Tileset::appendToMetatiles(QString metatileFile, QString friendlyName, bool
|
||||
dataString.append(QString("\t.incbin \"data/tilesets/%1/%2/metatiles.bin\"\n").arg(primaryString, friendlyName.toLower()));
|
||||
dataString.append(QString("\n\t.align 1\n"));
|
||||
dataString.append(QString("gMetatileAttributes_%1::\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.incbin \"data/tilesets/%1/%2/metatile_attributes.bin\"").arg(primaryString, friendlyName.toLower()));
|
||||
dataString.append(QString("\t.incbin \"data/tilesets/%1/%2/metatile_attributes.bin\"\n").arg(primaryString, friendlyName.toLower()));
|
||||
file.write(dataString.toUtf8());
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
@@ -2064,8 +2064,8 @@ DraggablePixmapItem* Editor::addNewEvent(QString event_type) {
|
||||
bool Editor::eventLimitReached(Map *map, QString event_type)
|
||||
{
|
||||
if (project && map && !event_type.isEmpty()) {
|
||||
if (event_type == EventType::Object)
|
||||
return map->events.value("object_event_group").length() >= project->getMaxObjectEvents();
|
||||
if (Event::typeToGroup(event_type) == EventGroup::Object)
|
||||
return map->events.value(EventGroup::Object).length() >= project->getMaxObjectEvents();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -349,12 +349,15 @@ void MainWindow::markMapEdited() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setWildEncountersUIEnabled(bool enabled) {
|
||||
ui->actionUse_Encounter_Json->setChecked(enabled);
|
||||
ui->mainTabBar->setTabEnabled(4, enabled);
|
||||
}
|
||||
|
||||
void MainWindow::setProjectSpecificUIVisibility()
|
||||
{
|
||||
ui->actionUse_Encounter_Json->setChecked(projectConfig.getEncounterJsonActive());
|
||||
ui->actionUse_Poryscript->setChecked(projectConfig.getUsePoryScript());
|
||||
|
||||
ui->mainTabBar->setTabEnabled(4, projectConfig.getEncounterJsonActive());
|
||||
this->setWildEncountersUIEnabled(projectConfig.getEncounterJsonActive());
|
||||
|
||||
switch (projectConfig.getBaseGameVersion())
|
||||
{
|
||||
@@ -385,27 +388,17 @@ void MainWindow::setProjectSpecificUIVisibility()
|
||||
ui->label_AllowEscapeRope->setVisible(true);
|
||||
// TODO: pokefirered is not set up for the Region Map Editor and vice versa.
|
||||
// porymap will crash on attempt. Remove below once resolved
|
||||
ui->actionRegion_Map_Editor->setVisible(false);
|
||||
ui->actionRegion_Map_Editor->setVisible(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (projectConfig.getEventWeatherTriggerEnabled()) {
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(true);
|
||||
} else {
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(false);
|
||||
}
|
||||
if (projectConfig.getEventSecretBaseEnabled()) {
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(true);
|
||||
} else {
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(false);
|
||||
}
|
||||
if (projectConfig.getFloorNumberEnabled()) {
|
||||
ui->spinBox_FloorNumber->setVisible(true);
|
||||
ui->label_FloorNumber->setVisible(true);
|
||||
} else {
|
||||
ui->spinBox_FloorNumber->setVisible(false);
|
||||
ui->label_FloorNumber->setVisible(false);
|
||||
}
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(projectConfig.getEventWeatherTriggerEnabled());
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(projectConfig.getEventSecretBaseEnabled());
|
||||
ui->newEventToolButton->newCloneObjectAction->setVisible(projectConfig.getEventCloneObjectEnabled());
|
||||
|
||||
bool floorNumEnabled = projectConfig.getFloorNumberEnabled();
|
||||
ui->spinBox_FloorNumber->setVisible(floorNumEnabled);
|
||||
ui->label_FloorNumber->setVisible(floorNumEnabled);
|
||||
}
|
||||
|
||||
void MainWindow::mapSortOrder_changed(QAction *action)
|
||||
@@ -525,6 +518,7 @@ bool MainWindow::openProject(QString dir) {
|
||||
editor->project = new Project(this);
|
||||
QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
|
||||
QObject::connect(editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
|
||||
QObject::connect(editor->project, &Project::disableWildEncountersUI, [this]() { this->setWildEncountersUIEnabled(false); });
|
||||
QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() { ui->actionMonitor_Project_Files->setChecked(false); });
|
||||
on_actionMonitor_Project_Files_triggered(porymapConfig.getMonitorFiles());
|
||||
editor->project->set_root(dir);
|
||||
@@ -702,22 +696,22 @@ void MainWindow::refreshMapScene()
|
||||
on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value());
|
||||
}
|
||||
|
||||
void MainWindow::openWarpMap(QString map_name, QString warp_num) {
|
||||
void MainWindow::openWarpMap(QString map_name, QString event_id, QString event_group) {
|
||||
// Ensure valid destination map name.
|
||||
if (!editor->project->mapNames.contains(map_name)) {
|
||||
logError(QString("Invalid warp destination map name '%1'").arg(map_name));
|
||||
logError(QString("Invalid map name '%1'").arg(map_name));
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure valid destination warp number.
|
||||
// Ensure valid event number.
|
||||
bool ok;
|
||||
int warpNum = warp_num.toInt(&ok, 0);
|
||||
int event_index = event_id.toInt(&ok, 0);
|
||||
if (!ok) {
|
||||
logError(QString("Invalid warp number '%1' for destination map '%2'").arg(warp_num).arg(map_name));
|
||||
logError(QString("Invalid event number '%1' for map '%2'").arg(event_id).arg(map_name));
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the destination map, and select the target warp event.
|
||||
// Open the destination map.
|
||||
if (!setMap(map_name, true)) {
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3")
|
||||
@@ -728,11 +722,13 @@ void MainWindow::openWarpMap(QString map_name, QString warp_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<Event*> warp_events = editor->map->events["warp_event_group"];
|
||||
if (warp_events.length() > warpNum) {
|
||||
Event *warp_event = warp_events.at(warpNum);
|
||||
// Select the target event.
|
||||
event_index -= Event::getIndexOffset(event_group);
|
||||
QList<Event*> events = editor->map->events[event_group];
|
||||
if (event_index < events.length() && event_index >= 0) {
|
||||
Event *event = events.at(event_index);
|
||||
for (DraggablePixmapItem *item : editor->getObjects()) {
|
||||
if (item->event == warp_event) {
|
||||
if (item->event == event) {
|
||||
editor->selected_events->clear();
|
||||
editor->selected_events->append(item);
|
||||
editor->updateSelectedEvents();
|
||||
@@ -1170,11 +1166,11 @@ void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction)
|
||||
}
|
||||
|
||||
void MainWindow::onNewMapCreated() {
|
||||
QString newMapName = this->newmapprompt->map->name;
|
||||
int newMapGroup = this->newmapprompt->group;
|
||||
Map *newMap = this->newmapprompt->map;
|
||||
bool existingLayout = this->newmapprompt->existingLayout;
|
||||
bool importedMap = this->newmapprompt->importedMap;
|
||||
QString newMapName = this->newMapPrompt->map->name;
|
||||
int newMapGroup = this->newMapPrompt->group;
|
||||
Map *newMap = this->newMapPrompt->map;
|
||||
bool existingLayout = this->newMapPrompt->existingLayout;
|
||||
bool importedMap = this->newMapPrompt->importedMap;
|
||||
|
||||
newMap = editor->project->addNewMapToGroup(newMapName, newMapGroup, newMap, existingLayout, importedMap);
|
||||
|
||||
@@ -1199,52 +1195,52 @@ void MainWindow::onNewMapCreated() {
|
||||
editor->save();// required
|
||||
}
|
||||
|
||||
disconnect(this->newmapprompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
disconnect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
delete newMap;
|
||||
}
|
||||
|
||||
void MainWindow::openNewMapPopupWindow(int type, QVariant data) {
|
||||
if (!this->newmapprompt) {
|
||||
this->newmapprompt = new NewMapPopup(this, this->editor->project);
|
||||
if (!this->newMapPrompt) {
|
||||
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
|
||||
}
|
||||
if (!this->newmapprompt->isVisible()) {
|
||||
this->newmapprompt->show();
|
||||
if (!this->newMapPrompt->isVisible()) {
|
||||
this->newMapPrompt->show();
|
||||
} else {
|
||||
this->newmapprompt->raise();
|
||||
this->newmapprompt->activateWindow();
|
||||
this->newMapPrompt->raise();
|
||||
this->newMapPrompt->activateWindow();
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case MapSortOrder::Group:
|
||||
this->newmapprompt->init(type, data.toInt(), QString(), QString());
|
||||
this->newMapPrompt->init(type, data.toInt(), QString(), QString());
|
||||
break;
|
||||
case MapSortOrder::Area:
|
||||
this->newmapprompt->init(type, 0, data.toString(), QString());
|
||||
this->newMapPrompt->init(type, 0, data.toString(), QString());
|
||||
break;
|
||||
case MapSortOrder::Layout:
|
||||
this->newmapprompt->init(type, 0, QString(), data.toString());
|
||||
this->newMapPrompt->init(type, 0, QString(), data.toString());
|
||||
break;
|
||||
}
|
||||
connect(this->newmapprompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
this->newmapprompt->setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
void MainWindow::openNewMapPopupWindowImportMap(MapLayout *mapLayout) {
|
||||
if (!this->newmapprompt) {
|
||||
this->newmapprompt = new NewMapPopup(this, this->editor->project);
|
||||
if (!this->newMapPrompt) {
|
||||
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
|
||||
}
|
||||
if (!this->newmapprompt->isVisible()) {
|
||||
this->newmapprompt->show();
|
||||
if (!this->newMapPrompt->isVisible()) {
|
||||
this->newMapPrompt->show();
|
||||
} else {
|
||||
this->newmapprompt->raise();
|
||||
this->newmapprompt->activateWindow();
|
||||
this->newMapPrompt->raise();
|
||||
this->newMapPrompt->activateWindow();
|
||||
}
|
||||
|
||||
this->newmapprompt->initImportMap(mapLayout);
|
||||
this->newMapPrompt->initImportMap(mapLayout);
|
||||
|
||||
connect(this->newmapprompt, SIGNAL(applied()), this, SLOT(onNewMapCreated()));
|
||||
connect(this->newmapprompt, &QObject::destroyed, [=](QObject *) { this->newmapprompt = nullptr; });
|
||||
this->newmapprompt->setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(this->newMapPrompt, SIGNAL(applied()), this, SLOT(onNewMapCreated()));
|
||||
connect(this->newMapPrompt, &QObject::destroyed, [=](QObject *) { this->newMapPrompt = nullptr; });
|
||||
this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_NewMap_triggered() {
|
||||
@@ -1802,14 +1798,11 @@ void MainWindow::connectSubEditorsToShortcutsEditor() {
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
tilesetEditor, &TilesetEditor::applyUserShortcuts);
|
||||
|
||||
// TODO: Remove this check when the region map editor supports pokefirered.
|
||||
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokefirered) {
|
||||
if (!regionMapEditor)
|
||||
initRegionMapEditor();
|
||||
if (regionMapEditor)
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
regionMapEditor, &RegionMapEditor::applyUserShortcuts);
|
||||
}
|
||||
if (!regionMapEditor)
|
||||
initRegionMapEditor();
|
||||
if (regionMapEditor)
|
||||
connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved,
|
||||
regionMapEditor, &RegionMapEditor::applyUserShortcuts);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPencil_triggered()
|
||||
@@ -1859,7 +1852,7 @@ void MainWindow::addNewEvent(QString event_type)
|
||||
} else {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to add new event");
|
||||
if (event_type == EventType::Object) {
|
||||
if (Event::typeToGroup(event_type) == EventGroup::Object) {
|
||||
msgBox.setInformativeText(QString("The limit for object events (%1) has been reached.\n\n"
|
||||
"This limit can be adjusted with OBJECT_EVENT_TEMPLATES_COUNT in 'include/constants/global.h'.")
|
||||
.arg(editor->project->getMaxObjectEvents()));
|
||||
@@ -1879,57 +1872,20 @@ void MainWindow::updateObjects() {
|
||||
selectedHealspot = nullptr;
|
||||
ui->tabWidget_EventType->clear();
|
||||
|
||||
bool hasObjects = false;
|
||||
bool hasWarps = false;
|
||||
bool hasTriggers = false;
|
||||
bool hasBGs = false;
|
||||
bool hasHealspots = false;
|
||||
|
||||
for (DraggablePixmapItem *item : editor->getObjects())
|
||||
{
|
||||
QString event_type = item->event->get("event_type");
|
||||
|
||||
if (event_type == EventType::Object) {
|
||||
hasObjects = true;
|
||||
}
|
||||
else if (event_type == EventType::Warp) {
|
||||
hasWarps = true;
|
||||
}
|
||||
else if (event_type == EventType::Trigger || event_type == EventType::WeatherTrigger) {
|
||||
hasTriggers = true;
|
||||
}
|
||||
else if (event_type == EventType::Sign || event_type == EventType::HiddenItem || event_type == EventType::SecretBase) {
|
||||
hasBGs = true;
|
||||
}
|
||||
else if (event_type == EventType::HealLocation) {
|
||||
hasHealspots = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasObjects)
|
||||
{
|
||||
if (editor->map->events.value(EventGroup::Object).length())
|
||||
ui->tabWidget_EventType->addTab(eventTabObjectWidget, "Objects");
|
||||
}
|
||||
|
||||
if (hasWarps)
|
||||
{
|
||||
if (editor->map->events.value(EventGroup::Warp).length())
|
||||
ui->tabWidget_EventType->addTab(eventTabWarpWidget, "Warps");
|
||||
}
|
||||
|
||||
if (hasTriggers)
|
||||
{
|
||||
if (editor->map->events.value(EventGroup::Coord).length())
|
||||
ui->tabWidget_EventType->addTab(eventTabTriggerWidget, "Triggers");
|
||||
}
|
||||
|
||||
if (hasBGs)
|
||||
{
|
||||
if (editor->map->events.value(EventGroup::Bg).length())
|
||||
ui->tabWidget_EventType->addTab(eventTabBGWidget, "BGs");
|
||||
}
|
||||
|
||||
if (hasHealspots)
|
||||
{
|
||||
if (editor->map->events.value(EventGroup::Heal).length())
|
||||
ui->tabWidget_EventType->addTab(eventTabHealspotWidget, "Healspots");
|
||||
}
|
||||
|
||||
updateSelectedObjects();
|
||||
}
|
||||
@@ -1956,7 +1912,6 @@ void MainWindow::updateSelectedObjects() {
|
||||
|
||||
QList<EventPropertiesFrame *> frames;
|
||||
|
||||
bool inConnectionEnabled = projectConfig.getObjectEventInConnectionEnabled();
|
||||
bool quantityEnabled = projectConfig.getHiddenItemQuantityEnabled();
|
||||
bool underfootEnabled = projectConfig.getHiddenItemRequiresItemfinderEnabled();
|
||||
bool respawnDataEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
@@ -1991,9 +1946,7 @@ void MainWindow::updateSelectedObjects() {
|
||||
QString event_type = item->event->get("event_type");
|
||||
QString event_group_type = item->event->get("event_group_type");
|
||||
QString map_name = item->event->get("map_name");
|
||||
int event_offs;
|
||||
if (event_type == EventType::Warp) { event_offs = 0; }
|
||||
else { event_offs = 1; }
|
||||
int event_offs = Event::getIndexOffset(event_group_type);
|
||||
frame->ui->label_name->setText(QString("%1 Id").arg(event_type));
|
||||
|
||||
if (events.count() == 1)
|
||||
@@ -2021,7 +1974,6 @@ void MainWindow::updateSelectedObjects() {
|
||||
field_labels["radius_y"] = "Movement Radius Y";
|
||||
field_labels["trainer_type"] = "Trainer Type";
|
||||
field_labels["sight_radius_tree_id"] = "Sight Radius / Berry Tree ID";
|
||||
field_labels["in_connection"] = "In Connection";
|
||||
field_labels["destination_warp"] = "Destination Warp";
|
||||
field_labels["destination_map_name"] = "Destination Map";
|
||||
field_labels["script_var"] = "Var";
|
||||
@@ -2035,13 +1987,15 @@ void MainWindow::updateSelectedObjects() {
|
||||
field_labels["secret_base_id"] = "Secret Base Id";
|
||||
field_labels["respawn_map"] = "Respawn Map";
|
||||
field_labels["respawn_npc"] = "Respawn NPC";
|
||||
field_labels["target_local_id"] = "Target Local Id";
|
||||
field_labels["target_map"] = "Target Map";
|
||||
|
||||
QStringList fields;
|
||||
|
||||
if (event_type == EventType::Object) {
|
||||
|
||||
frame->ui->sprite->setVisible(true);
|
||||
frame->ui->comboBox_sprite->addItems(editor->project->gfxNames);
|
||||
frame->ui->comboBox_sprite->addItems(editor->project->gfxDefines.keys());
|
||||
frame->ui->comboBox_sprite->setCurrentIndex(frame->ui->comboBox_sprite->findText(item->event->get("sprite")));
|
||||
connect(frame->ui->comboBox_sprite, &QComboBox::currentTextChanged, item, &DraggablePixmapItem::set_sprite);
|
||||
connect(frame->ui->comboBox_sprite, &QComboBox::currentTextChanged, this, &MainWindow::markMapEdited);
|
||||
@@ -2063,7 +2017,17 @@ void MainWindow::updateSelectedObjects() {
|
||||
fields << "event_flag";
|
||||
fields << "trainer_type";
|
||||
fields << "sight_radius_tree_id";
|
||||
if (inConnectionEnabled) fields << "in_connection";
|
||||
}
|
||||
else if (event_type == EventType::CloneObject) {
|
||||
frame->ui->sprite->setVisible(true);
|
||||
frame->ui->comboBox_sprite->setEnabled(false);
|
||||
frame->ui->comboBox_sprite->addItem(item->event->get("sprite"));
|
||||
|
||||
frame->ui->spinBox_z->setVisible(false);
|
||||
frame->ui->label_z->setVisible(false);
|
||||
|
||||
fields << "target_local_id";
|
||||
fields << "target_map";
|
||||
}
|
||||
else if (event_type == EventType::Warp) {
|
||||
fields << "destination_map_name";
|
||||
@@ -2101,8 +2065,8 @@ void MainWindow::updateSelectedObjects() {
|
||||
}
|
||||
|
||||
// Some keys shouldn't use a combobox
|
||||
QStringList spinKeys = {"quantity", "respawn_npc"};
|
||||
QStringList checkKeys = {"underfoot", "in_connection"};
|
||||
QStringList spinKeys = {"quantity", "respawn_npc", "target_local_id"};
|
||||
QStringList checkKeys = {"underfoot"};
|
||||
for (QString key : fields) {
|
||||
QString value = item->event->get(key);
|
||||
QWidget *widget = new QWidget(frame);
|
||||
@@ -2226,8 +2190,6 @@ void MainWindow::updateSelectedObjects() {
|
||||
combo->setToolTip("The maximum sight range of a trainer,\n"
|
||||
"OR the unique id of the berry tree.");
|
||||
combo->setMinimumContentsLength(4);
|
||||
} else if (key == "in_connection") {
|
||||
check->setToolTip("Check if object is positioned in the connection to another map.");
|
||||
} else if (key == "respawn_map") {
|
||||
if (!editor->project->mapNames.contains(value)) {
|
||||
combo->addItem(value);
|
||||
@@ -2239,6 +2201,27 @@ void MainWindow::updateSelectedObjects() {
|
||||
"upon respawning after whiteout.");
|
||||
spin->setMinimum(1);
|
||||
spin->setMaximum(126);
|
||||
} else if (key == "target_local_id") {
|
||||
spin->setToolTip("event_object ID of the object being cloned.");
|
||||
spin->setMinimum(1);
|
||||
spin->setMaximum(126);
|
||||
connect(spin, QOverload<int>::of(&NoScrollSpinBox::valueChanged), [item, frame](int value) {
|
||||
item->event->put("target_local_id", value);
|
||||
item->updatePixmap();
|
||||
frame->ui->comboBox_sprite->setItemText(0, item->event->get("sprite"));
|
||||
});
|
||||
} else if (key == "target_map") {
|
||||
if (!editor->project->mapNames.contains(value)) {
|
||||
combo->addItem(value);
|
||||
}
|
||||
combo->addItems(editor->project->mapNames);
|
||||
combo->setCurrentIndex(combo->findText(value));
|
||||
combo->setToolTip("The name of the map that the object being cloned is on.");
|
||||
connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), this, [item, frame](QString value){
|
||||
item->event->put("target_map", value);
|
||||
item->updatePixmap();
|
||||
frame->ui->comboBox_sprite->setItemText(0, item->event->get("sprite"));
|
||||
});
|
||||
} else {
|
||||
combo->addItem(value);
|
||||
}
|
||||
@@ -2323,27 +2306,27 @@ void MainWindow::updateSelectedObjects() {
|
||||
{
|
||||
QString event_group_type = events[0]->event->get("event_group_type");
|
||||
|
||||
if (event_group_type == "object_event_group") {
|
||||
if (event_group_type == EventGroup::Object) {
|
||||
scrollTarget = ui->scrollArea_Objects;
|
||||
target = ui->scrollAreaWidgetContents_Objects;
|
||||
ui->tabWidget_EventType->setCurrentWidget(ui->tab_Objects);
|
||||
}
|
||||
else if (event_group_type == "warp_event_group") {
|
||||
else if (event_group_type == EventGroup::Warp) {
|
||||
scrollTarget = ui->scrollArea_Warps;
|
||||
target = ui->scrollAreaWidgetContents_Warps;
|
||||
ui->tabWidget_EventType->setCurrentWidget(ui->tab_Warps);
|
||||
}
|
||||
else if (event_group_type == "coord_event_group") {
|
||||
else if (event_group_type == EventGroup::Coord) {
|
||||
scrollTarget = ui->scrollArea_Triggers;
|
||||
target = ui->scrollAreaWidgetContents_Triggers;
|
||||
ui->tabWidget_EventType->setCurrentWidget(ui->tab_Triggers);
|
||||
}
|
||||
else if (event_group_type == "bg_event_group") {
|
||||
else if (event_group_type == EventGroup::Bg) {
|
||||
scrollTarget = ui->scrollArea_BGs;
|
||||
target = ui->scrollAreaWidgetContents_BGs;
|
||||
ui->tabWidget_EventType->setCurrentWidget(ui->tab_BGs);
|
||||
}
|
||||
else if (event_group_type == "heal_event_group") {
|
||||
else if (event_group_type == EventGroup::Heal) {
|
||||
scrollTarget = ui->scrollArea_Healspots;
|
||||
target = ui->scrollAreaWidgetContents_Healspots;
|
||||
ui->tabWidget_EventType->setCurrentWidget(ui->tab_Healspots);
|
||||
@@ -2400,23 +2383,23 @@ QString MainWindow::getEventGroupFromTabWidget(QWidget *tab)
|
||||
QString ret = "";
|
||||
if (tab == eventTabObjectWidget)
|
||||
{
|
||||
ret = "object_event_group";
|
||||
ret = EventGroup::Object;
|
||||
}
|
||||
else if (tab == eventTabWarpWidget)
|
||||
{
|
||||
ret = "warp_event_group";
|
||||
ret = EventGroup::Warp;
|
||||
}
|
||||
else if (tab == eventTabTriggerWidget)
|
||||
{
|
||||
ret = "coord_event_group";
|
||||
ret = EventGroup::Coord;
|
||||
}
|
||||
else if (tab == eventTabBGWidget)
|
||||
{
|
||||
ret = "bg_event_group";
|
||||
ret = EventGroup::Bg;
|
||||
}
|
||||
else if (tab == eventTabHealspotWidget)
|
||||
{
|
||||
ret = "heal_event_group";
|
||||
ret = EventGroup::Heal;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2426,23 +2409,23 @@ void MainWindow::eventTabChanged(int index) {
|
||||
QString group = getEventGroupFromTabWidget(ui->tabWidget_EventType->widget(index));
|
||||
DraggablePixmapItem *selectedEvent = nullptr;
|
||||
|
||||
if (group == "object_event_group") {
|
||||
if (group == EventGroup::Object) {
|
||||
selectedEvent = selectedObject;
|
||||
ui->newEventToolButton->setDefaultAction(ui->newEventToolButton->newObjectAction);
|
||||
}
|
||||
else if (group == "warp_event_group") {
|
||||
else if (group == EventGroup::Warp) {
|
||||
selectedEvent = selectedWarp;
|
||||
ui->newEventToolButton->setDefaultAction(ui->newEventToolButton->newWarpAction);
|
||||
}
|
||||
else if (group == "coord_event_group") {
|
||||
else if (group == EventGroup::Coord) {
|
||||
selectedEvent = selectedTrigger;
|
||||
ui->newEventToolButton->setDefaultAction(ui->newEventToolButton->newTriggerAction);
|
||||
}
|
||||
else if (group == "bg_event_group") {
|
||||
else if (group == EventGroup::Bg) {
|
||||
selectedEvent = selectedBG;
|
||||
ui->newEventToolButton->setDefaultAction(ui->newEventToolButton->newSignAction);
|
||||
}
|
||||
else if (group == "heal_event_group") {
|
||||
else if (group == EventGroup::Heal) {
|
||||
selectedEvent = selectedHealspot;
|
||||
}
|
||||
|
||||
@@ -2468,7 +2451,7 @@ void MainWindow::eventTabChanged(int index) {
|
||||
void MainWindow::selectedEventIndexChanged(int index)
|
||||
{
|
||||
QString group = getEventGroupFromTabWidget(ui->tabWidget_EventType->currentWidget());
|
||||
int event_offs = group == "warp_event_group" ? 0 : 1;
|
||||
int event_offs = Event::getIndexOffset(group);
|
||||
Event *event = editor->map->events.value(group).at(index - event_offs);
|
||||
DraggablePixmapItem *selectedEvent = nullptr;
|
||||
for (QGraphicsItem *child : editor->events_group->childItems()) {
|
||||
@@ -2502,7 +2485,7 @@ void MainWindow::on_toolButton_deleteObject_clicked() {
|
||||
int numDeleted = 0;
|
||||
for (DraggablePixmapItem *item : *editor->selected_events) {
|
||||
QString event_group = item->event->get("event_group_type");
|
||||
if (event_group != "heal_event_group") {
|
||||
if (event_group != EventGroup::Heal) {
|
||||
// Get the index for the event that should be selected after this event has been deleted.
|
||||
// If it's at the end of the list, select the previous event, otherwise select the next one.
|
||||
// Don't bother getting the event to select if there are still more events to delete
|
||||
@@ -3164,8 +3147,12 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
|
||||
|
||||
bool MainWindow::initRegionMapEditor() {
|
||||
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
|
||||
bool success = this->regionMapEditor->loadRegionMapData()
|
||||
&& this->regionMapEditor->loadCityMaps();
|
||||
this->regionMapEditor->setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(this->regionMapEditor, &QObject::destroyed, [this](){
|
||||
this->regionMapEditor = nullptr;
|
||||
});
|
||||
|
||||
bool success = this->regionMapEditor->load();
|
||||
if (!success) {
|
||||
delete this->regionMapEditor;
|
||||
this->regionMapEditor = nullptr;
|
||||
@@ -3182,16 +3169,26 @@ bool MainWindow::initRegionMapEditor() {
|
||||
}
|
||||
|
||||
void MainWindow::closeSupplementaryWindows() {
|
||||
if (this->tilesetEditor)
|
||||
if (this->tilesetEditor) {
|
||||
delete this->tilesetEditor;
|
||||
if (this->regionMapEditor)
|
||||
this->tilesetEditor = nullptr;
|
||||
}
|
||||
if (this->regionMapEditor) {
|
||||
delete this->regionMapEditor;
|
||||
if (this->mapImageExporter)
|
||||
this->regionMapEditor = nullptr;
|
||||
}
|
||||
if (this->mapImageExporter) {
|
||||
delete this->mapImageExporter;
|
||||
if (this->newmapprompt)
|
||||
delete this->newmapprompt;
|
||||
if (this->shortcutsEditor)
|
||||
this->mapImageExporter = nullptr;
|
||||
}
|
||||
if (this->newMapPrompt) {
|
||||
delete this->newMapPrompt;
|
||||
this->newMapPrompt = nullptr;
|
||||
}
|
||||
if (this->shortcutsEditor) {
|
||||
delete this->shortcutsEditor;
|
||||
this->shortcutsEditor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
|
||||
@@ -833,7 +833,7 @@ void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) {
|
||||
this->editor->project->saveTilesetMetatileAttributes(tileset);
|
||||
|
||||
// If the Tileset Editor is currently displaying the updated metatile, refresh it
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatile() == metatileId)
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatileId() == metatileId)
|
||||
this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label);
|
||||
}
|
||||
|
||||
@@ -863,7 +863,7 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatile() == metatileId) {
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatileId() == metatileId) {
|
||||
this->tilesetEditor->setMetatileLabel(label);
|
||||
} else if (metatile->label != label) {
|
||||
metatile->label = label;
|
||||
|
||||
200
src/project.cpp
200
src/project.cpp
@@ -211,31 +211,56 @@ bool Project::loadMapData(Map* map) {
|
||||
map->sharedScriptsMap = mapObj["shared_scripts_map"].toString();
|
||||
|
||||
// Events
|
||||
map->events["object_event_group"].clear();
|
||||
map->events[EventGroup::Object].clear();
|
||||
QJsonArray objectEventsArr = mapObj["object_events"].toArray();
|
||||
bool hasCloneObjects = projectConfig.getEventCloneObjectEnabled();
|
||||
for (int i = 0; i < objectEventsArr.size(); i++) {
|
||||
QJsonObject event = objectEventsArr[i].toObject();
|
||||
Event *object = new Event(event, EventType::Object);
|
||||
object->put("map_name", map->name);
|
||||
object->put("sprite", event["graphics_id"].toString());
|
||||
if (projectConfig.getObjectEventInConnectionEnabled()) {
|
||||
object->put("in_connection", event["in_connection"].toBool());
|
||||
// If clone objects are not enabled then no type field is present
|
||||
QString type = hasCloneObjects ? event["type"].toString() : "object";
|
||||
if (type.isEmpty() || type == "object") {
|
||||
Event *object = new Event(event, EventType::Object);
|
||||
object->put("map_name", map->name);
|
||||
object->put("sprite", event["graphics_id"].toString());
|
||||
object->put("x", QString::number(event["x"].toInt()));
|
||||
object->put("y", QString::number(event["y"].toInt()));
|
||||
object->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
object->put("movement_type", event["movement_type"].toString());
|
||||
object->put("radius_x", QString::number(event["movement_range_x"].toInt()));
|
||||
object->put("radius_y", QString::number(event["movement_range_y"].toInt()));
|
||||
object->put("trainer_type", event["trainer_type"].toString());
|
||||
object->put("sight_radius_tree_id", event["trainer_sight_or_berry_tree_id"].toString());
|
||||
object->put("script_label", event["script"].toString());
|
||||
object->put("event_flag", event["flag"].toString());
|
||||
object->put("event_group_type", EventGroup::Object);
|
||||
map->events[EventGroup::Object].append(object);
|
||||
} else if (type == "clone") {
|
||||
Event *object = new Event(event, EventType::CloneObject);
|
||||
object->put("map_name", map->name);
|
||||
object->put("sprite", event["graphics_id"].toString());
|
||||
object->put("x", QString::number(event["x"].toInt()));
|
||||
object->put("y", QString::number(event["y"].toInt()));
|
||||
object->put("target_local_id", QString::number(event["target_local_id"].toInt()));
|
||||
|
||||
// Ensure the target map constant is valid before adding it to the events.
|
||||
QString mapConstant = event["target_map"].toString();
|
||||
if (mapConstantsToMapNames.contains(mapConstant)) {
|
||||
object->put("target_map", mapConstantsToMapNames.value(mapConstant));
|
||||
object->put("event_group_type", EventGroup::Object);
|
||||
map->events[EventGroup::Object].append(object);
|
||||
} else if (mapConstant == NONE_MAP_CONSTANT) {
|
||||
object->put("target_map", NONE_MAP_NAME);
|
||||
object->put("event_group_type", EventGroup::Object);
|
||||
map->events[EventGroup::Object].append(object);
|
||||
} else {
|
||||
logError(QString("Destination map constant '%1' is invalid").arg(mapConstant));
|
||||
}
|
||||
} else {
|
||||
logError(QString("Map %1 object_event %2 has invalid type '%3'. Must be 'object' or 'clone'.").arg(map->name).arg(i).arg(type));
|
||||
}
|
||||
object->put("x", QString::number(event["x"].toInt()));
|
||||
object->put("y", QString::number(event["y"].toInt()));
|
||||
object->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
object->put("movement_type", event["movement_type"].toString());
|
||||
object->put("radius_x", QString::number(event["movement_range_x"].toInt()));
|
||||
object->put("radius_y", QString::number(event["movement_range_y"].toInt()));
|
||||
object->put("trainer_type", event["trainer_type"].toString());
|
||||
object->put("sight_radius_tree_id", event["trainer_sight_or_berry_tree_id"].toString());
|
||||
object->put("script_label", event["script"].toString());
|
||||
object->put("event_flag", event["flag"].toString());
|
||||
object->put("event_group_type", "object_event_group");
|
||||
map->events["object_event_group"].append(object);
|
||||
}
|
||||
|
||||
map->events["warp_event_group"].clear();
|
||||
map->events[EventGroup::Warp].clear();
|
||||
QJsonArray warpEventsArr = mapObj["warp_events"].toArray();
|
||||
for (int i = 0; i < warpEventsArr.size(); i++) {
|
||||
QJsonObject event = warpEventsArr[i].toObject();
|
||||
@@ -250,18 +275,18 @@ bool Project::loadMapData(Map* map) {
|
||||
QString mapConstant = event["dest_map"].toString();
|
||||
if (mapConstantsToMapNames.contains(mapConstant)) {
|
||||
warp->put("destination_map_name", mapConstantsToMapNames.value(mapConstant));
|
||||
warp->put("event_group_type", "warp_event_group");
|
||||
map->events["warp_event_group"].append(warp);
|
||||
warp->put("event_group_type", EventGroup::Warp);
|
||||
map->events[EventGroup::Warp].append(warp);
|
||||
} else if (mapConstant == NONE_MAP_CONSTANT) {
|
||||
warp->put("destination_map_name", NONE_MAP_NAME);
|
||||
warp->put("event_group_type", "warp_event_group");
|
||||
map->events["warp_event_group"].append(warp);
|
||||
warp->put("event_group_type", EventGroup::Warp);
|
||||
map->events[EventGroup::Warp].append(warp);
|
||||
} else {
|
||||
logError(QString("Destination map constant '%1' is invalid for warp").arg(mapConstant));
|
||||
}
|
||||
}
|
||||
|
||||
map->events["heal_event_group"].clear();
|
||||
map->events[EventGroup::Heal].clear();
|
||||
for (auto it = healLocations.begin(); it != healLocations.end(); it++) {
|
||||
|
||||
HealLocation loc = *it;
|
||||
@@ -277,18 +302,18 @@ bool Project::loadMapData(Map* map) {
|
||||
heal->put("index", loc.index);
|
||||
heal->put("elevation", 3); // TODO: change this?
|
||||
heal->put("destination_map_name", mapConstantsToMapNames.value(map->name));
|
||||
heal->put("event_group_type", "heal_event_group");
|
||||
heal->put("event_group_type", EventGroup::Heal);
|
||||
heal->put("event_type", EventType::HealLocation);
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
heal->put("respawn_map", mapConstantsToMapNames.value(QString("MAP_" + loc.respawnMap)));
|
||||
heal->put("respawn_npc", loc.respawnNPC);
|
||||
}
|
||||
map->events["heal_event_group"].append(heal);
|
||||
map->events[EventGroup::Heal].append(heal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
map->events["coord_event_group"].clear();
|
||||
map->events[EventGroup::Coord].clear();
|
||||
QJsonArray coordEventsArr = mapObj["coord_events"].toArray();
|
||||
for (int i = 0; i < coordEventsArr.size(); i++) {
|
||||
QJsonObject event = coordEventsArr[i].toObject();
|
||||
@@ -302,8 +327,8 @@ bool Project::loadMapData(Map* map) {
|
||||
coord->put("script_var", event["var"].toString());
|
||||
coord->put("script_var_value", event["var_value"].toString());
|
||||
coord->put("script_label", event["script"].toString());
|
||||
coord->put("event_group_type", "coord_event_group");
|
||||
map->events["coord_event_group"].append(coord);
|
||||
coord->put("event_group_type", EventGroup::Coord);
|
||||
map->events[EventGroup::Coord].append(coord);
|
||||
} else if (type == "weather") {
|
||||
Event *coord = new Event(event, EventType::WeatherTrigger);
|
||||
coord->put("map_name", map->name);
|
||||
@@ -311,15 +336,15 @@ bool Project::loadMapData(Map* map) {
|
||||
coord->put("y", QString::number(event["y"].toInt()));
|
||||
coord->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
coord->put("weather", event["weather"].toString());
|
||||
coord->put("event_group_type", "coord_event_group");
|
||||
coord->put("event_group_type", EventGroup::Coord);
|
||||
coord->put("event_type", EventType::WeatherTrigger);
|
||||
map->events["coord_event_group"].append(coord);
|
||||
map->events[EventGroup::Coord].append(coord);
|
||||
} else {
|
||||
logError(QString("Map %1 coord_event %2 has invalid type '%3'. Must be 'trigger' or 'weather'.").arg(map->name).arg(i).arg(type));
|
||||
}
|
||||
}
|
||||
|
||||
map->events["bg_event_group"].clear();
|
||||
map->events[EventGroup::Bg].clear();
|
||||
QJsonArray bgEventsArr = mapObj["bg_events"].toArray();
|
||||
for (int i = 0; i < bgEventsArr.size(); i++) {
|
||||
QJsonObject event = bgEventsArr[i].toObject();
|
||||
@@ -332,8 +357,8 @@ bool Project::loadMapData(Map* map) {
|
||||
bg->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
bg->put("player_facing_direction", event["player_facing_dir"].toString());
|
||||
bg->put("script_label", event["script"].toString());
|
||||
bg->put("event_group_type", "bg_event_group");
|
||||
map->events["bg_event_group"].append(bg);
|
||||
bg->put("event_group_type", EventGroup::Bg);
|
||||
map->events[EventGroup::Bg].append(bg);
|
||||
} else if (type == "hidden_item") {
|
||||
Event *bg = new Event(event, EventType::HiddenItem);
|
||||
bg->put("map_name", map->name);
|
||||
@@ -348,8 +373,8 @@ bool Project::loadMapData(Map* map) {
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
bg->put("underfoot", event["underfoot"].toBool());
|
||||
}
|
||||
bg->put("event_group_type", "bg_event_group");
|
||||
map->events["bg_event_group"].append(bg);
|
||||
bg->put("event_group_type", EventGroup::Bg);
|
||||
map->events[EventGroup::Bg].append(bg);
|
||||
} else if (type == "secret_base") {
|
||||
Event *bg = new Event(event, EventType::SecretBase);
|
||||
bg->put("map_name", map->name);
|
||||
@@ -357,8 +382,8 @@ bool Project::loadMapData(Map* map) {
|
||||
bg->put("y", QString::number(event["y"].toInt()));
|
||||
bg->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
bg->put("secret_base_id", event["secret_base_id"].toString());
|
||||
bg->put("event_group_type", "bg_event_group");
|
||||
map->events["bg_event_group"].append(bg);
|
||||
bg->put("event_group_type", EventGroup::Bg);
|
||||
map->events[EventGroup::Bg].append(bg);
|
||||
} else {
|
||||
logError(QString("Map %1 bg_event %2 has invalid type '%3'. Must be 'sign', 'hidden_item', or 'secret_base'.").arg(map->name).arg(i).arg(type));
|
||||
}
|
||||
@@ -861,8 +886,8 @@ void Project::saveHealLocationStruct(Map *map) {
|
||||
}
|
||||
|
||||
// set new location in healLocations list
|
||||
if (map->events["heal_event_group"].length() > 0) {
|
||||
for (Event *healEvent : map->events["heal_event_group"]) {
|
||||
if (map->events[EventGroup::Heal].length() > 0) {
|
||||
for (Event *healEvent : map->events[EventGroup::Heal]) {
|
||||
HealLocation hl = HealLocation::fromEvent(healEvent);
|
||||
healLocations[hl.index - 1] = hl;
|
||||
}
|
||||
@@ -1333,17 +1358,23 @@ void Project::saveMap(Map *map) {
|
||||
if (map->sharedEventsMap.isEmpty()) {
|
||||
// Object events
|
||||
OrderedJson::array objectEventsArr;
|
||||
for (int i = 0; i < map->events["object_event_group"].length(); i++) {
|
||||
Event *object_event = map->events["object_event_group"].value(i);
|
||||
OrderedJson::object eventObj = object_event->buildObjectEventJSON();
|
||||
objectEventsArr.push_back(eventObj);
|
||||
for (int i = 0; i < map->events[EventGroup::Object].length(); i++) {
|
||||
Event *event = map->events[EventGroup::Object].value(i);
|
||||
QString event_type = event->get("event_type");
|
||||
OrderedJson::object jsonObj;
|
||||
if (event_type == EventType::Object) {
|
||||
jsonObj = event->buildObjectEventJSON();
|
||||
} else if (event_type == EventType::CloneObject) {
|
||||
jsonObj = event->buildCloneObjectEventJSON(mapNamesToMapConstants);
|
||||
}
|
||||
objectEventsArr.push_back(jsonObj);
|
||||
}
|
||||
mapObj["object_events"] = objectEventsArr;
|
||||
|
||||
// Warp events
|
||||
OrderedJson::array warpEventsArr;
|
||||
for (int i = 0; i < map->events["warp_event_group"].length(); i++) {
|
||||
Event *warp_event = map->events["warp_event_group"].value(i);
|
||||
for (int i = 0; i < map->events[EventGroup::Warp].length(); i++) {
|
||||
Event *warp_event = map->events[EventGroup::Warp].value(i);
|
||||
OrderedJson::object warpObj = warp_event->buildWarpEventJSON(mapNamesToMapConstants);
|
||||
warpEventsArr.append(warpObj);
|
||||
}
|
||||
@@ -1351,8 +1382,8 @@ void Project::saveMap(Map *map) {
|
||||
|
||||
// Coord events
|
||||
OrderedJson::array coordEventsArr;
|
||||
for (int i = 0; i < map->events["coord_event_group"].length(); i++) {
|
||||
Event *event = map->events["coord_event_group"].value(i);
|
||||
for (int i = 0; i < map->events[EventGroup::Coord].length(); i++) {
|
||||
Event *event = map->events[EventGroup::Coord].value(i);
|
||||
QString event_type = event->get("event_type");
|
||||
if (event_type == EventType::Trigger) {
|
||||
OrderedJson::object triggerObj = event->buildTriggerEventJSON();
|
||||
@@ -1366,8 +1397,8 @@ void Project::saveMap(Map *map) {
|
||||
|
||||
// Bg Events
|
||||
OrderedJson::array bgEventsArr;
|
||||
for (int i = 0; i < map->events["bg_event_group"].length(); i++) {
|
||||
Event *event = map->events["bg_event_group"].value(i);
|
||||
for (int i = 0; i < map->events[EventGroup::Bg].length(); i++) {
|
||||
Event *event = map->events[EventGroup::Bg].value(i);
|
||||
QString event_type = event->get("event_type");
|
||||
if (event_type == EventType::Sign) {
|
||||
OrderedJson::object signObj = event->buildSignEventJSON();
|
||||
@@ -1692,8 +1723,12 @@ bool Project::readWildMonData() {
|
||||
|
||||
OrderedJson::object wildMonObj;
|
||||
if (!parser.tryParseOrderedJsonFile(&wildMonObj, wildMonJsonFilepath)) {
|
||||
logError(QString("Failed to read wild encounters from %1").arg(wildMonJsonFilepath));
|
||||
return false;
|
||||
// Failing to read wild encounters data is not a critical error, just disable the
|
||||
// encounter editor and log a warning in case the user intended to have this data.
|
||||
projectConfig.setEncounterJsonActive(false);
|
||||
emit disableWildEncountersUI();
|
||||
logWarn(QString("Failed to read wild encounters from %1").arg(wildMonJsonFilepath));
|
||||
return true;
|
||||
}
|
||||
|
||||
for (OrderedJson subObjectRef : wildMonObj["wild_encounter_groups"].array_items()) {
|
||||
@@ -2248,9 +2283,8 @@ bool Project::readObjEventGfxConstants() {
|
||||
QStringList objEventGfxPrefixes("\\bOBJ_EVENT_GFX_");
|
||||
QString filename = "include/constants/event_objects.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> gfxDefines = parser.readCDefines(filename, objEventGfxPrefixes);
|
||||
this->gfxNames = gfxDefines.keys();
|
||||
if (this->gfxNames.isEmpty()) {
|
||||
this->gfxDefines = parser.readCDefines(filename, objEventGfxPrefixes);
|
||||
if (this->gfxDefines.isEmpty()) {
|
||||
logError(QString("Failed to read object event graphics constants from %1.").arg(filename));
|
||||
return false;
|
||||
}
|
||||
@@ -2380,25 +2414,48 @@ void Project::setEventPixmap(Event * event, bool forceLoad) {
|
||||
event->spriteHeight = 16;
|
||||
event->usingSprite = false;
|
||||
|
||||
QString event_type = event->get("event_type");
|
||||
if (event_type == EventType::Object) {
|
||||
QString gfxName = event->get("sprite");
|
||||
QString group_type = event->get("event_group_type");
|
||||
if (group_type == EventGroup::Object) {
|
||||
QString gfxName;
|
||||
QString movement;
|
||||
QString event_type = event->get("event_type");
|
||||
if (event_type == EventType::CloneObject) {
|
||||
// Try to get the targeted object to clone
|
||||
int eventIndex = event->getInt("target_local_id") - 1;
|
||||
Map * clonedMap = getMap(event->get("target_map"));
|
||||
Event * clonedEvent = clonedMap ? clonedMap->events[EventGroup::Object].value(eventIndex, nullptr) : nullptr;
|
||||
if (clonedEvent && clonedEvent->get("event_type") == EventType::Object) {
|
||||
// Get graphics data from cloned object
|
||||
gfxName = clonedEvent->get("sprite");
|
||||
movement = clonedEvent->get("movement_type");
|
||||
} else {
|
||||
// Invalid object specified, use default graphics data (as would be shown in-game)
|
||||
gfxName = gfxDefines.key(0);
|
||||
movement = movementTypes.first();
|
||||
}
|
||||
// Update clone object's sprite text to match target object
|
||||
event->put("sprite", gfxName);
|
||||
} else {
|
||||
// Get graphics data of regular object
|
||||
gfxName = event->get("sprite");
|
||||
movement = event->get("movement_type");
|
||||
}
|
||||
EventGraphics * eventGfx = eventGraphicsMap.value(gfxName, nullptr);
|
||||
if (!eventGfx || eventGfx->spritesheet.isNull()) {
|
||||
// No sprite associated with this gfx constant.
|
||||
// Use default sprite instead.
|
||||
event->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16);
|
||||
} else {
|
||||
event->setFrameFromMovement(facingDirections.value(event->get("movement_type")));
|
||||
event->setFrameFromMovement(facingDirections.value(movement));
|
||||
event->setPixmapFromSpritesheet(eventGfx->spritesheet, eventGfx->spriteWidth, eventGfx->spriteHeight, eventGfx->inanimate);
|
||||
}
|
||||
} else if (event_type == EventType::Warp) {
|
||||
} else if (group_type == EventGroup::Warp) {
|
||||
event->pixmap = QPixmap(":/images/Entities_16x16.png").copy(16, 0, 16, 16);
|
||||
} else if (event_type == EventType::Trigger || event_type == EventType::WeatherTrigger) {
|
||||
} else if (group_type == EventGroup::Coord) {
|
||||
event->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16);
|
||||
} else if (event_type == EventType::Sign || event_type == EventType::HiddenItem || event_type == EventType::SecretBase) {
|
||||
} else if (group_type == EventGroup::Bg) {
|
||||
event->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16);
|
||||
} else if (event_type == EventType::HealLocation) {
|
||||
} else if (group_type == EventGroup::Heal) {
|
||||
event->pixmap = QPixmap(":/images/Entities_16x16.png").copy(64, 0, 16, 16);
|
||||
}
|
||||
}
|
||||
@@ -2413,7 +2470,8 @@ bool Project::readEventGraphics() {
|
||||
|
||||
qDeleteAll(eventGraphicsMap);
|
||||
eventGraphicsMap.clear();
|
||||
for (QString gfxName : this->gfxNames) {
|
||||
QStringList gfxNames = gfxDefines.keys();
|
||||
for (QString gfxName : gfxNames) {
|
||||
EventGraphics * eventGraphics = new EventGraphics;
|
||||
|
||||
QString info_label = pointerHash[gfxName].replace("&", "");
|
||||
@@ -2473,8 +2531,8 @@ bool Project::readSpeciesIconPaths() {
|
||||
|
||||
void Project::saveMapHealEvents(Map *map) {
|
||||
// save heal event changes
|
||||
if (map->events["heal_event_group"].length() > 0) {
|
||||
for (Event *healEvent : map->events["heal_event_group"]) {
|
||||
if (map->events[EventGroup::Heal].length() > 0) {
|
||||
for (Event *healEvent : map->events[EventGroup::Heal]) {
|
||||
HealLocation hl = HealLocation::fromEvent(healEvent);
|
||||
healLocations[hl.index - 1] = hl;
|
||||
}
|
||||
@@ -2483,11 +2541,11 @@ void Project::saveMapHealEvents(Map *map) {
|
||||
}
|
||||
|
||||
void Project::setNewMapEvents(Map *map) {
|
||||
map->events["object_event_group"].clear();
|
||||
map->events["warp_event_group"].clear();
|
||||
map->events["heal_event_group"].clear();
|
||||
map->events["coord_event_group"].clear();
|
||||
map->events["bg_event_group"].clear();
|
||||
map->events[EventGroup::Object].clear();
|
||||
map->events[EventGroup::Warp].clear();
|
||||
map->events[EventGroup::Heal].clear();
|
||||
map->events[EventGroup::Coord].clear();
|
||||
map->events[EventGroup::Bg].clear();
|
||||
}
|
||||
|
||||
int Project::getNumTilesPrimary()
|
||||
|
||||
@@ -26,15 +26,16 @@ void CityMapPixmapItem::init() {
|
||||
void CityMapPixmapItem::draw() {
|
||||
QImage image(width_ * 8, height_ * 8, QImage::Format_RGBA8888);
|
||||
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < data.size() / 2; i++) {
|
||||
QImage img = this->tile_selector->tileImg(data[i * 2]);// need to skip every other tile
|
||||
int x = i % width_;
|
||||
int y = i / width_;
|
||||
QPoint pos = QPoint(x * 8, y * 8);
|
||||
painter.drawImage(pos, img);
|
||||
}
|
||||
painter.end();
|
||||
// TODO: construct temporary tile from this based on the id?
|
||||
// QPainter painter(&image);
|
||||
// for (int i = 0; i < data.size() / 2; i++) {
|
||||
// QImage img = this->tile_selector->tileImg(data[i * 2]);// need to skip every other tile
|
||||
// int x = i % width_;
|
||||
// int y = i / width_;
|
||||
// QPoint pos = QPoint(x * 8, y * 8);
|
||||
// painter.drawImage(pos, img);
|
||||
// }
|
||||
// painter.end();
|
||||
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
}
|
||||
|
||||
@@ -102,17 +102,24 @@ void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *) {
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
||||
if (this->event->get("event_type") == EventType::Warp) {
|
||||
QString eventType = this->event->get("event_type");
|
||||
if (eventType == EventType::Warp) {
|
||||
QString destMap = this->event->get("destination_map_name");
|
||||
if (destMap != NONE_MAP_NAME) {
|
||||
emit editor->warpEventDoubleClicked(this->event->get("destination_map_name"), this->event->get("destination_warp"));
|
||||
emit editor->warpEventDoubleClicked(destMap, this->event->get("destination_warp"), EventGroup::Warp);
|
||||
}
|
||||
}
|
||||
else if (this->event->get("event_type") == EventType::SecretBase) {
|
||||
else if (eventType == EventType::CloneObject) {
|
||||
QString destMap = this->event->get("target_map");
|
||||
if (destMap != NONE_MAP_NAME) {
|
||||
emit editor->warpEventDoubleClicked(destMap, this->event->get("target_local_id"), EventGroup::Object);
|
||||
}
|
||||
}
|
||||
else if (eventType == EventType::SecretBase) {
|
||||
QString baseId = this->event->get("secret_base_id");
|
||||
QString destMap = editor->project->mapConstantsToMapNames.value("MAP_" + baseId.left(baseId.lastIndexOf("_")));
|
||||
if (destMap != NONE_MAP_NAME) {
|
||||
emit editor->warpEventDoubleClicked(destMap, "0");
|
||||
emit editor->warpEventDoubleClicked(destMap, "0", EventGroup::Warp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,11 +371,11 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
||||
for (Event *event : events) {
|
||||
editor->project->setEventPixmap(event);
|
||||
QString group = event->get("event_group_type");
|
||||
if ((showObjects && group == "object_event_group")
|
||||
|| (showWarps && group == "warp_event_group")
|
||||
|| (showBGs && group == "bg_event_group")
|
||||
|| (showTriggers && group == "coord_event_group")
|
||||
|| (showHealSpots && group == "heal_event_group"))
|
||||
if ((showObjects && group == EventGroup::Object)
|
||||
|| (showWarps && group == EventGroup::Warp)
|
||||
|| (showBGs && group == EventGroup::Bg)
|
||||
|| (showTriggers && group == EventGroup::Coord)
|
||||
|| (showHealSpots && group == EventGroup::Heal))
|
||||
eventPainter.drawImage(QPoint(event->getPixelX(), event->getPixelY()), event->pixmap.toImage());
|
||||
}
|
||||
eventPainter.end();
|
||||
|
||||
@@ -18,6 +18,10 @@ void NewEventToolButton::init()
|
||||
this->newObjectAction->setIcon(QIcon(":/icons/add.ico"));
|
||||
connect(this->newObjectAction, &QAction::triggered, this, &NewEventToolButton::newObject);
|
||||
|
||||
this->newCloneObjectAction = new QAction("New Clone Object", this);
|
||||
this->newCloneObjectAction->setIcon(QIcon(":/icons/add.ico"));
|
||||
connect(this->newCloneObjectAction, &QAction::triggered, this, &NewEventToolButton::newCloneObject);
|
||||
|
||||
this->newWarpAction = new QAction("New Warp", this);
|
||||
this->newWarpAction->setIcon(QIcon(":/icons/add.ico"));
|
||||
connect(this->newWarpAction, &QAction::triggered, this, &NewEventToolButton::newWarp);
|
||||
@@ -50,6 +54,7 @@ void NewEventToolButton::init()
|
||||
|
||||
QMenu *alignMenu = new QMenu();
|
||||
alignMenu->addAction(this->newObjectAction);
|
||||
alignMenu->addAction(this->newCloneObjectAction);
|
||||
alignMenu->addAction(this->newWarpAction);
|
||||
//alignMenu->addAction(this->newHealLocationAction);
|
||||
alignMenu->addAction(this->newTriggerAction);
|
||||
@@ -72,6 +77,12 @@ void NewEventToolButton::newObject()
|
||||
emit newEventAdded(this->selectedEventType);
|
||||
}
|
||||
|
||||
void NewEventToolButton::newCloneObject()
|
||||
{
|
||||
this->selectedEventType = EventType::CloneObject;
|
||||
emit newEventAdded(this->selectedEventType);
|
||||
}
|
||||
|
||||
void NewEventToolButton::newWarp()
|
||||
{
|
||||
this->selectedEventType = EventType::Warp;
|
||||
|
||||
@@ -156,6 +156,8 @@ void NewMapPopup::setDefaultValuesImportMap(MapLayout *mapLayout) {
|
||||
ui->comboBox_NewMap_Group->addItems(project->groupNames);
|
||||
ui->comboBox_NewMap_Group->setCurrentText(project->groupNames.at(0));
|
||||
|
||||
ui->comboBox_Song->addItems(project->songNames);
|
||||
|
||||
ui->spinBox_NewMap_Width->setValue(mapLayout->width.toInt(nullptr, 0));
|
||||
ui->spinBox_NewMap_Height->setValue(mapLayout->height.toInt(nullptr, 0));
|
||||
ui->comboBox_NewMap_Primary_Tileset->setCurrentText(mapLayout->tileset_primary_label);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,12 @@
|
||||
void RegionMapEntriesPixmapItem::draw() {
|
||||
if (!region_map) return;
|
||||
|
||||
RegionMapEntry entry = region_map->mapSecToMapEntry.value(currentSection);
|
||||
MapSectionEntry entry = this->region_map->getEntry(currentSection);
|
||||
bool selectingEntry = false;
|
||||
|
||||
int entry_x, entry_y, entry_w, entry_h;
|
||||
|
||||
if (entry.name.isEmpty() || entry.name == "MAPSEC_NONE") {
|
||||
if (!entry.valid || entry.name == "MAPSEC_NONE") {
|
||||
entry_x = entry_y = 0;
|
||||
entry_w = entry_h = 1;
|
||||
} else {
|
||||
@@ -17,25 +17,25 @@ void RegionMapEntriesPixmapItem::draw() {
|
||||
entry_w = entry.width, entry_h = entry.height;
|
||||
}
|
||||
|
||||
QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
|
||||
QImage image(region_map->tilemapWidth() * 8, region_map->tilemapHeight() * 8, QImage::Format_RGBA8888);
|
||||
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < region_map->map_squares.size(); i++) {
|
||||
QImage bottom_img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
|
||||
for (int i = 0; i < region_map->tilemapSize(); i++) {
|
||||
QImage bottom_img = this->tile_selector->tileImg(region_map->getTile(i));
|
||||
QImage top_img(8, 8, QImage::Format_RGBA8888);
|
||||
int x = i % region_map->width();
|
||||
int y = i / region_map->width();
|
||||
int x = i % region_map->tilemapWidth();
|
||||
int y = i / region_map->tilemapWidth();
|
||||
bool insideEntry = false;
|
||||
if (selectingEntry) {
|
||||
if (x == entry_x + this->region_map->padLeft && y == entry_y + this->region_map->padTop)
|
||||
if (x == entry_x + this->region_map->padLeft() && y == entry_y + this->region_map->padTop())
|
||||
insideEntry = true;
|
||||
else if (x - this->region_map->padLeft - entry_x < entry_w && x >= entry_x + this->region_map->padLeft
|
||||
&& y - this->region_map->padTop - entry_y < entry_h && y >= entry_y + this->region_map->padTop)
|
||||
else if (x - this->region_map->padLeft() - entry_x < entry_w && x >= entry_x + this->region_map->padLeft()
|
||||
&& y - this->region_map->padTop() - entry_y < entry_h && y >= entry_y + this->region_map->padTop())
|
||||
insideEntry = true;
|
||||
}
|
||||
if (insideEntry) {
|
||||
top_img.fill(QColor(255, 68, 68));
|
||||
} else if (region_map->map_squares[i].has_map) {
|
||||
} else if (region_map->squareHasMap(i)) {
|
||||
top_img.fill(Qt::gray);
|
||||
} else {
|
||||
top_img.fill(Qt::black);
|
||||
@@ -44,7 +44,7 @@ void RegionMapEntriesPixmapItem::draw() {
|
||||
painter.setOpacity(1);
|
||||
painter.drawImage(pos, bottom_img);
|
||||
painter.save();
|
||||
painter.setOpacity(0.55);
|
||||
painter.setOpacity(0.65);
|
||||
painter.drawImage(pos, top_img);
|
||||
painter.restore();
|
||||
}
|
||||
@@ -54,7 +54,8 @@ void RegionMapEntriesPixmapItem::draw() {
|
||||
this->selectionOffsetY = entry_h - 1;
|
||||
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
this->drawSelection();
|
||||
|
||||
if (selectingEntry) this->drawSelection();
|
||||
}
|
||||
|
||||
void RegionMapEntriesPixmapItem::select(int x, int y) {
|
||||
@@ -63,25 +64,25 @@ void RegionMapEntriesPixmapItem::select(int x, int y) {
|
||||
this->selectedTile = index;
|
||||
this->updateSelectedTile();
|
||||
|
||||
emit selectedTileChanged(this->region_map->map_squares[index].mapsec);
|
||||
emit selectedTileChanged(this->region_map->squareMapSection(index));
|
||||
}
|
||||
|
||||
void RegionMapEntriesPixmapItem::select(int index) {
|
||||
int x = index % this->region_map->width();
|
||||
int y = index / this->region_map->width();
|
||||
int x = index % this->region_map->tilemapWidth();
|
||||
int y = index / this->region_map->tilemapWidth();
|
||||
SelectablePixmapItem::select(x, y, 0, 0);
|
||||
this->selectedTile = index;
|
||||
this->updateSelectedTile();
|
||||
|
||||
emit selectedTileChanged(this->region_map->map_squares[index].mapsec);
|
||||
emit selectedTileChanged(this->region_map->squareMapSection(index));
|
||||
}
|
||||
|
||||
void RegionMapEntriesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
int x = pos.x() - this->region_map->padLeft;
|
||||
int y = pos.y() - this->region_map->padTop;
|
||||
int x = pos.x() - this->region_map->padLeft();
|
||||
int y = pos.y() - this->region_map->padTop();
|
||||
|
||||
RegionMapEntry entry = this->region_map->mapSecToMapEntry.value(currentSection);
|
||||
MapSectionEntry entry = this->region_map->getEntry(currentSection);
|
||||
pressedX = x - entry.x;
|
||||
pressedY = y - entry.y;
|
||||
if (entry.x == x && entry.y == y) {
|
||||
@@ -92,6 +93,7 @@ void RegionMapEntriesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: update this function, especially bounds check
|
||||
void RegionMapEntriesPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
if (!draggingEntry) {
|
||||
event->ignore();
|
||||
@@ -99,14 +101,14 @@ void RegionMapEntriesPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
int new_x = pos.x() - this->region_map->padLeft - pressedX;
|
||||
int new_y = pos.y() - this->region_map->padTop - pressedY;
|
||||
int new_x = pos.x() - this->region_map->padLeft() - pressedX;
|
||||
int new_y = pos.y() - this->region_map->padTop() - pressedY;
|
||||
|
||||
RegionMapEntry entry = this->region_map->mapSecToMapEntry.value(currentSection);
|
||||
MapSectionEntry entry = this->region_map->getEntry(currentSection);
|
||||
|
||||
// check to make sure not moving out of bounds
|
||||
if (new_x + entry.width > this->region_map->width() - this->region_map->padLeft - this->region_map->padRight
|
||||
|| new_y + entry.height > this->region_map->height() - this->region_map->padTop - this->region_map->padBottom
|
||||
if (new_x + entry.width > this->region_map->tilemapWidth() - this->region_map->padLeft() //- this->region_map->padRight
|
||||
|| new_y + entry.height > this->region_map->tilemapHeight() - this->region_map->padTop() //- this->region_map->padBottom
|
||||
|| new_x < 0 || new_y < 0)
|
||||
return;
|
||||
|
||||
|
||||
@@ -3,24 +3,29 @@
|
||||
void RegionMapLayoutPixmapItem::draw() {
|
||||
if (!region_map) return;
|
||||
|
||||
QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
|
||||
QImage image(region_map->pixelWidth(), region_map->pixelHeight(), QImage::Format_RGBA8888);
|
||||
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < region_map->map_squares.size(); i++) {
|
||||
QImage bottom_img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
|
||||
for (int i = 0; i < region_map->tilemapSize(); i++) {
|
||||
QImage bottom_img = this->tile_selector->tileImg(region_map->getTile(i));
|
||||
QImage top_img(8, 8, QImage::Format_RGBA8888);
|
||||
if (region_map->map_squares[i].has_map) {
|
||||
if (region_map->squareHasMap(i)) {
|
||||
top_img.fill(Qt::gray);
|
||||
} else {
|
||||
top_img.fill(Qt::black);
|
||||
}
|
||||
int x = i % region_map->width();
|
||||
int y = i / region_map->width();
|
||||
int x = i % region_map->tilemapWidth();
|
||||
int y = i / region_map->tilemapWidth();
|
||||
QPoint pos = QPoint(x * 8, y * 8);
|
||||
painter.setOpacity(1);
|
||||
painter.drawImage(pos, bottom_img);
|
||||
painter.save();
|
||||
painter.setOpacity(0.55);
|
||||
if (region_map->squareInLayout(x, y)) {
|
||||
painter.setOpacity(0.55);
|
||||
} else {
|
||||
painter.setOpacity(0.8);
|
||||
}
|
||||
|
||||
painter.drawImage(pos, top_img);
|
||||
painter.restore();
|
||||
}
|
||||
@@ -40,8 +45,8 @@ void RegionMapLayoutPixmapItem::select(int x, int y) {
|
||||
}
|
||||
|
||||
void RegionMapLayoutPixmapItem::select(int index) {
|
||||
int x = index % this->region_map->width();
|
||||
int y = index / this->region_map->width();
|
||||
int x = index % this->region_map->tilemapWidth();
|
||||
int y = index / this->region_map->tilemapWidth();
|
||||
SelectablePixmapItem::select(x, y, 0, 0);
|
||||
this->selectedTile = index;
|
||||
this->updateSelectedTile();
|
||||
@@ -51,15 +56,13 @@ void RegionMapLayoutPixmapItem::select(int index) {
|
||||
|
||||
void RegionMapLayoutPixmapItem::highlight(int x, int y, int red) {
|
||||
this->highlightedTile = red;
|
||||
SelectablePixmapItem::select(x + this->region_map->padLeft, y + this->region_map->padTop, 0, 0);
|
||||
SelectablePixmapItem::select(x + this->region_map->padLeft(), y + this->region_map->padTop(), 0, 0);
|
||||
draw();
|
||||
}
|
||||
|
||||
void RegionMapLayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
int index = this->region_map->getMapSquareIndex(pos.x(), pos.y());
|
||||
if (this->region_map->map_squares[index].x >= 0
|
||||
&& this->region_map->map_squares[index].y >= 0) {
|
||||
if (this->region_map->squareInLayout(pos.x(), pos.y())) {
|
||||
SelectablePixmapItem::mousePressEvent(event);
|
||||
this->updateSelectedTile();
|
||||
emit selectedTileChanged(this->selectedTile);
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#include "regionmappixmapitem.h"
|
||||
#include "regionmapeditcommands.h"
|
||||
|
||||
void RegionMapPixmapItem::draw() {
|
||||
if (!region_map) return;
|
||||
|
||||
QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
|
||||
QImage image(region_map->pixelWidth(), region_map->pixelHeight(), QImage::Format_RGBA8888);
|
||||
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < region_map->map_squares.size(); i++) {
|
||||
QImage img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
|
||||
int x = i % region_map->width();
|
||||
int y = i / region_map->width();
|
||||
for (int i = 0; i < region_map->tilemapSize(); i++) {
|
||||
QImage img = this->tile_selector->tileImg(region_map->getTile(i));
|
||||
int x = i % region_map->tilemapWidth();
|
||||
int y = i / region_map->tilemapWidth();
|
||||
QPoint pos = QPoint(x * 8, y * 8);
|
||||
painter.drawImage(pos, img);
|
||||
}
|
||||
@@ -23,8 +24,77 @@ void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 8;
|
||||
int y = static_cast<int>(pos.y()) / 8;
|
||||
int index = x + y * region_map->width();
|
||||
this->region_map->map_squares[index].tile_img_id = this->tile_selector->selectedTile;
|
||||
int index = x + y * region_map->tilemapWidth();
|
||||
this->region_map->setTileData(index,
|
||||
this->tile_selector->selectedTile,
|
||||
this->tile_selector->tile_hFlip,
|
||||
this->tile_selector->tile_vFlip,
|
||||
this->tile_selector->tile_palette
|
||||
);
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPixmapItem::floodFill(int x, int y, std::shared_ptr<TilemapTile> oldTile, std::shared_ptr<TilemapTile> newTile) {
|
||||
// out of bounds
|
||||
if (x < 0
|
||||
|| y < 0
|
||||
|| x >= this->region_map->tilemapWidth()
|
||||
|| y >= this->region_map->tilemapHeight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tile = this->region_map->getTile(x, y);
|
||||
if (!tile->operator==(*oldTile) || tile->operator==(*newTile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = x + y * this->region_map->tilemapWidth();
|
||||
this->region_map->setTileData(index,
|
||||
newTile->id(),
|
||||
newTile->hFlip(),
|
||||
newTile->vFlip(),
|
||||
newTile->palette()
|
||||
);
|
||||
|
||||
floodFill(x + 1, y, oldTile, newTile);
|
||||
floodFill(x - 1, y, oldTile, newTile);
|
||||
floodFill(x, y + 1, oldTile, newTile);
|
||||
floodFill(x, y - 1, oldTile, newTile);
|
||||
}
|
||||
|
||||
void RegionMapPixmapItem::fill(QGraphicsSceneMouseEvent *event) {
|
||||
if (region_map) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 8;
|
||||
int y = static_cast<int>(pos.y()) / 8;
|
||||
int index = x + y * this->region_map->tilemapWidth();
|
||||
std::shared_ptr<TilemapTile> currentTile, newTile, oldTile;
|
||||
currentTile = this->region_map->getTile(index);
|
||||
switch(this->tile_selector->format) {
|
||||
case TilemapFormat::Plain:
|
||||
oldTile = std::make_shared<PlainTile>(currentTile->raw());
|
||||
newTile = std::make_shared<PlainTile>(currentTile->raw());
|
||||
newTile->setId(this->tile_selector->selectedTile);
|
||||
break;
|
||||
case TilemapFormat::BPP_4:
|
||||
oldTile = std::make_shared<BPP4Tile>(currentTile->raw());
|
||||
newTile = std::make_shared<BPP4Tile>(currentTile->raw());
|
||||
newTile->setId(this->tile_selector->selectedTile);
|
||||
newTile->setHFlip(this->tile_selector->tile_hFlip);
|
||||
newTile->setVFlip(this->tile_selector->tile_vFlip);
|
||||
newTile->setPalette(this->tile_selector->tile_palette);
|
||||
break;
|
||||
case TilemapFormat::BPP_8:
|
||||
oldTile = std::make_shared<BPP8Tile>(currentTile->raw());
|
||||
newTile = std::make_shared<BPP8Tile>(currentTile->raw());
|
||||
newTile->setId(this->tile_selector->selectedTile);
|
||||
newTile->setId(this->tile_selector->selectedTile);
|
||||
newTile->setHFlip(this->tile_selector->tile_hFlip);
|
||||
newTile->setVFlip(this->tile_selector->tile_vFlip);
|
||||
break;
|
||||
}
|
||||
floodFill(x, y, oldTile, newTile);
|
||||
draw();
|
||||
}
|
||||
}
|
||||
@@ -54,8 +124,8 @@ void RegionMapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 8;
|
||||
int y = static_cast<int>(pos.y()) / 8;
|
||||
if (x < this->region_map->width() && x >= 0
|
||||
&& y < this->region_map->height() && y >= 0) {
|
||||
if (x < this->region_map->tilemapWidth() && x >= 0
|
||||
&& y < this->region_map->tilemapHeight() && y >= 0) {
|
||||
emit this->hoveredRegionMapTileChanged(x, y);
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
|
||||
257
src/ui/regionmappropertiesdialog.cpp
Normal file
257
src/ui/regionmappropertiesdialog.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
#include "project.h"
|
||||
#include "regionmappropertiesdialog.h"
|
||||
#include "ui_regionmappropertiesdialog.h"
|
||||
|
||||
RegionMapPropertiesDialog::RegionMapPropertiesDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::RegionMapPropertiesDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->hideMessages();
|
||||
}
|
||||
|
||||
RegionMapPropertiesDialog::~RegionMapPropertiesDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::hideMessages() {
|
||||
ui->message_alias->setVisible(false);
|
||||
ui->message_tilemapFormat->setVisible(false);
|
||||
ui->message_tilemapWidth->setVisible(false);
|
||||
ui->message_tilemapHeight->setVisible(false);
|
||||
ui->message_tilemapImagePath->setVisible(false);
|
||||
ui->message_tilemapBinPath->setVisible(false);
|
||||
ui->message_layoutFormat->setVisible(false);
|
||||
ui->message_layoutPath->setVisible(false);
|
||||
ui->message_layoutWidth->setVisible(false);
|
||||
ui->message_layoutHeight->setVisible(false);
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
QString RegionMapPropertiesDialog::browse(QString filter, QFileDialog::FileMode mode) {
|
||||
if (!this->project) return QString();
|
||||
QFileDialog browser;
|
||||
browser.setFileMode(mode);
|
||||
QString filepath = browser.getOpenFileName(this, "Select a File", this->project->root, filter);
|
||||
|
||||
// remove the project root from the filepath
|
||||
return filepath.replace(this->project->root + "/", "");
|
||||
}
|
||||
|
||||
// TODO: test for missing fields/invalid cases
|
||||
void RegionMapPropertiesDialog::setProperties(poryjson::Json json) {
|
||||
poryjson::Json::object object = json.object_items();
|
||||
|
||||
// Region Map Properties
|
||||
ui->config_alias->setText(object["alias"].string_value());
|
||||
|
||||
// Tilemap properties
|
||||
poryjson::Json::object tilemap = object["tilemap"].object_items();
|
||||
ui->config_tilemapFormat->setCurrentText(tilemap["format"].string_value());
|
||||
ui->config_tilemapWidth->setValue(tilemap["width"].int_value());
|
||||
ui->config_tilemapHeight->setValue(tilemap["height"].int_value());
|
||||
|
||||
ui->config_tilemapImagePath->setText(tilemap["tileset_path"].string_value());
|
||||
ui->config_tilemapBinPath->setText(tilemap["tilemap_path"].string_value());
|
||||
if (tilemap.contains("palette"))
|
||||
ui->config_tilemapPalettePath->setText(tilemap["palette"].string_value());
|
||||
|
||||
// Layout props
|
||||
if (object["layout"].is_null()) {
|
||||
ui->group_layout->setChecked(false);
|
||||
} else {
|
||||
poryjson::Json::object layout = object["layout"].object_items();
|
||||
ui->config_layoutFormat->setCurrentText(layout["format"].string_value());
|
||||
ui->config_layoutPath->setText(layout["path"].string_value());
|
||||
ui->config_layoutWidth->setValue(layout["width"].int_value());
|
||||
ui->config_layoutHeight->setValue(layout["height"].int_value());
|
||||
ui->config_leftOffs->setValue(layout["offset_left"].int_value());
|
||||
ui->config_topOffs->setValue(layout["offset_top"].int_value());
|
||||
}
|
||||
}
|
||||
|
||||
poryjson::Json RegionMapPropertiesDialog::saveToJson() {
|
||||
poryjson::Json::object config;
|
||||
|
||||
// TODO: make sure next comment is not a lie
|
||||
// data should already be verified and valid at this point
|
||||
config["alias"] = ui->config_alias->text();
|
||||
|
||||
poryjson::Json::object tilemapObject;
|
||||
tilemapObject["width"] = ui->config_tilemapWidth->value();
|
||||
tilemapObject["height"] = ui->config_tilemapHeight->value();
|
||||
tilemapObject["format"] = ui->config_tilemapFormat->currentText();
|
||||
tilemapObject["tileset_path"] = ui->config_tilemapImagePath->text();
|
||||
tilemapObject["tilemap_path"] = ui->config_tilemapBinPath->text();
|
||||
tilemapObject["palette"] = ui->config_tilemapPalettePath->text();
|
||||
config["tilemap"] = tilemapObject;
|
||||
|
||||
if (ui->group_layout->isChecked()) {
|
||||
poryjson::Json::object layoutObject;
|
||||
layoutObject["format"] = ui->config_layoutFormat->currentText();
|
||||
layoutObject["path"] = ui->config_layoutPath->text();
|
||||
layoutObject["width"] = ui->config_layoutWidth->value();
|
||||
layoutObject["height"] = ui->config_layoutHeight->value();
|
||||
layoutObject["offset_left"] = ui->config_leftOffs->value();
|
||||
layoutObject["offset_top"] = ui->config_topOffs->value();
|
||||
config["layout"] = layoutObject;
|
||||
} else {
|
||||
config["layout"] = nullptr;
|
||||
}
|
||||
|
||||
return poryjson::Json(config);
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilesetImagePath_clicked() {
|
||||
QString path = browse("Images (*.png *.bmp)", QFileDialog::ExistingFile);
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapImagePath->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilemapBinPath_clicked() {
|
||||
QString path = browse("Binary (*.bin *.tilemap *.4bpp *.8bpp)", QFileDialog::AnyFile);
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapBinPath->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilemapPalettePath_clicked() {
|
||||
QString path = browse("Text (*.pal)", QFileDialog::AnyFile);
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapPalettePath->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_layoutPath_clicked() {
|
||||
if (ui->config_layoutFormat->currentIndex() == 0) {
|
||||
QString path = browse("Text File (*.h *.c *.inc *.txt)", QFileDialog::AnyFile);
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_layoutPath->setText(path);
|
||||
}
|
||||
} else {
|
||||
QString path = browse("Binary (*.bin)", QFileDialog::AnyFile);
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_layoutPath->setText(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::accept() {
|
||||
bool valid = true;
|
||||
|
||||
// verify alias is okay
|
||||
QString alias = ui->config_alias->text();
|
||||
if (alias.isEmpty()) {
|
||||
valid = false;
|
||||
ui->message_alias->setText("alias cannot be empty");
|
||||
ui->message_alias->setVisible(true);
|
||||
} else {
|
||||
QRegularExpression re("[A-Za-z0-9_\\- ]+");
|
||||
int temp = 0;
|
||||
QRegularExpressionValidator v(re, 0);
|
||||
|
||||
if (v.validate(alias, temp) != QValidator::Acceptable) {
|
||||
ui->message_alias->setText("this alias is not an acceptable string");
|
||||
ui->message_alias->setVisible(true);
|
||||
valid = false;
|
||||
}
|
||||
else { // no issues detected
|
||||
ui->message_alias->setText("");
|
||||
ui->message_alias->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
// tilemap properties
|
||||
// tilemap dimensions are specific: 64x32, 32x64, 16x16, 32x32, 64x64, 128x128
|
||||
// TODO: why is 30x20 allowed in firered?
|
||||
int tilemapWidth = ui->config_tilemapWidth->value();
|
||||
int tilemapHeight = ui->config_tilemapHeight->value();
|
||||
QMap<int, QList<int>> acceptableDimensions = { {16, {16}}, {30, {20}}, {32, {32, 64}}, {64, {32, 64}}, {128, {128}} };
|
||||
if (!acceptableDimensions.contains(tilemapWidth)) {
|
||||
// width not valid
|
||||
valid = false;
|
||||
ui->message_tilemapWidth->setText("tilemap width not valid, must be one of [16, 32, 64, 128]");
|
||||
ui->message_tilemapWidth->setVisible(true);
|
||||
} else {
|
||||
ui->message_tilemapWidth->setText("");
|
||||
ui->message_tilemapWidth->setVisible(false);
|
||||
// check width, height combo
|
||||
if (!acceptableDimensions.value(tilemapWidth).contains(tilemapHeight)) {
|
||||
valid = false;
|
||||
QString options = "";
|
||||
for (int i : acceptableDimensions.value(tilemapWidth))
|
||||
options += QString::number(i) + ", ";
|
||||
options.chop(2);
|
||||
ui->message_tilemapHeight->setText("tilemap height not valid, must be one of [" + options + "]");
|
||||
ui->message_tilemapHeight->setVisible(true);
|
||||
}
|
||||
else { // no issues detected
|
||||
ui->message_tilemapHeight->setText("");
|
||||
ui->message_tilemapHeight->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
// layout dimensions
|
||||
// need to verify <= tilemap dimensions, only req here
|
||||
int width = ui->config_layoutWidth->value() + ui->config_leftOffs->value();
|
||||
int height = ui->config_layoutHeight->value() + ui->config_topOffs->value();
|
||||
if (width > tilemapWidth) {
|
||||
valid = false;
|
||||
ui->message_layoutWidth->setText("layout map width + left offset cannot be larger than tilemap width");
|
||||
ui->message_layoutWidth->setVisible(true);
|
||||
} else {
|
||||
ui->message_layoutWidth->setText("");
|
||||
ui->message_layoutWidth->setVisible(false);
|
||||
}
|
||||
if (height > tilemapHeight) {
|
||||
valid = false;
|
||||
ui->message_layoutHeight->setText("layout map height + top offset cannot be larger than tilemap height");
|
||||
ui->message_layoutHeight->setVisible(true);
|
||||
} else {
|
||||
ui->message_layoutHeight->setText("");
|
||||
ui->message_layoutHeight->setVisible(false);
|
||||
}
|
||||
|
||||
// make sure paths arent empty
|
||||
if (ui->config_tilemapImagePath->text().isEmpty()) {
|
||||
valid = false;
|
||||
ui->message_tilemapImagePath->setText("this path cannot be empty");
|
||||
ui->message_tilemapImagePath->setVisible(true);
|
||||
} else {
|
||||
ui->message_tilemapImagePath->setText("");
|
||||
ui->message_tilemapImagePath->setVisible(false);
|
||||
}
|
||||
|
||||
if (ui->config_tilemapBinPath->text().isEmpty()) {
|
||||
valid = false;
|
||||
ui->message_tilemapBinPath->setText("this path cannot be empty");
|
||||
ui->message_tilemapBinPath->setVisible(true);
|
||||
} else {
|
||||
ui->message_tilemapBinPath->setText("");
|
||||
ui->message_tilemapBinPath->setVisible(false);
|
||||
}
|
||||
|
||||
// layout path only needs to exist if layout is enabled (obviously)
|
||||
if (ui->group_layout->isChecked()) {
|
||||
if (ui->config_layoutPath->text().isEmpty()) {
|
||||
valid = false;
|
||||
ui->message_layoutPath->setText("this path cannot be empty");
|
||||
ui->message_layoutPath->setVisible(true);
|
||||
} else {
|
||||
ui->message_layoutPath->setText("");
|
||||
ui->message_layoutPath->setVisible(false);
|
||||
}
|
||||
} else {
|
||||
ui->message_layoutPath->setText("");
|
||||
ui->message_layoutPath->setVisible(false);
|
||||
}
|
||||
|
||||
// TODO: limitations for map width/height if implementing
|
||||
|
||||
if (valid) {
|
||||
QDialog::accept();
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,16 @@
|
||||
#include <QDebug>
|
||||
|
||||
void TilemapTileSelector::draw() {
|
||||
size_t width_ = this->tilemap.width();
|
||||
size_t width_ = this->tileset.width();
|
||||
this->pixelWidth = width_;
|
||||
size_t height_ = this->tilemap.height();
|
||||
size_t height_ = this->tileset.height();
|
||||
this->pixelHeight = height_;
|
||||
size_t ntiles_ = (width_/8) * (height_/8);
|
||||
|
||||
this->numTilesWide = width_ / 8;
|
||||
this->numTiles = ntiles_;
|
||||
|
||||
this->setPixmap(tilemap);
|
||||
this->setPixmap(QPixmap::fromImage(this->setPalette(this->tile_palette)));
|
||||
this->drawSelection();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ void TilemapTileSelector::select(unsigned tileId) {
|
||||
QPoint coords = this->getTileIdCoords(tileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
this->selectedTile = tileId;
|
||||
this->drawSelection();
|
||||
emit selectedTileChanged(tileId);
|
||||
}
|
||||
|
||||
@@ -28,10 +29,6 @@ void TilemapTileSelector::updateSelectedTile() {
|
||||
this->selectedTile = this->getTileId(origin.x(), origin.y());
|
||||
}
|
||||
|
||||
unsigned TilemapTileSelector::getSelectedTile() {
|
||||
return this->selectedTile;
|
||||
}
|
||||
|
||||
unsigned TilemapTileSelector::getTileId(int x, int y) {
|
||||
unsigned index = y * this->numTilesWide + x;
|
||||
return index < this->numTiles ? index : this->numTiles % index;
|
||||
@@ -42,9 +39,63 @@ QPoint TilemapTileSelector::getTileIdCoords(unsigned tileId) {
|
||||
return QPoint(index % this->numTilesWide, index / this->numTilesWide);
|
||||
}
|
||||
|
||||
QImage TilemapTileSelector::tileImg(unsigned tileId) {
|
||||
QImage TilemapTileSelector::setPalette(int paletteIndex) {
|
||||
QImage tilesetImage = this->tileset;
|
||||
tilesetImage.convertTo(QImage::Format::Format_Indexed8);
|
||||
|
||||
// TODO: bounds check on the palette copying
|
||||
switch(this->format) {
|
||||
case TilemapFormat::Plain:
|
||||
break;
|
||||
case TilemapFormat::BPP_4:
|
||||
{
|
||||
QVector<QRgb> newColorTable;
|
||||
int palMinLength = paletteIndex * 16 + 16;
|
||||
if ((this->palette.count() < palMinLength) || (tilesetImage.colorTable().count() != 16)) {
|
||||
// either a) the palette has less than 256 colors, or b) the image is improperly indexed
|
||||
for (QRgb color : tilesetImage.colorTable()) {
|
||||
int gray = qGray(color);
|
||||
newColorTable.append(qRgb(gray, gray, gray));
|
||||
}
|
||||
} else {
|
||||
// use actual pal
|
||||
// before Qt 6, the color table is a QVector which is deprecated now, and this method does not exits
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
newColorTable = this->palette.toVector().mid(paletteIndex * 16, 16);
|
||||
#else
|
||||
newColorTable = this->palette.mid(paletteIndex * 16, 16);
|
||||
#endif
|
||||
}
|
||||
tilesetImage.setColorTable(newColorTable);
|
||||
break;
|
||||
}
|
||||
case TilemapFormat::BPP_8:
|
||||
{
|
||||
if (tilesetImage.colorTable().count() == this->palette.count()) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
tilesetImage.setColorTable(this->palette.toVector());
|
||||
#else
|
||||
tilesetImage.setColorTable(this->palette);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return tilesetImage;
|
||||
}
|
||||
|
||||
QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
|
||||
unsigned tileId = tile->id();
|
||||
QPoint pos = getTileIdCoords(tileId);
|
||||
return this->tilemap.copy(pos.x() * 8, pos.y() * 8, 8, 8).toImage();
|
||||
|
||||
QImage tilesetImage = setPalette(tile->palette());
|
||||
|
||||
// take a tile from the tileset
|
||||
QImage img = tilesetImage.copy(pos.x() * 8, pos.y() * 8, 8, 8);
|
||||
img = img.mirrored(tile->hFlip(), tile->vFlip());
|
||||
return img;
|
||||
}
|
||||
|
||||
void TilemapTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
|
||||
@@ -40,6 +40,7 @@ TilesetEditor::~TilesetEditor()
|
||||
delete selectedTilePixmapItem;
|
||||
delete selectedTileScene;
|
||||
delete metatileLayersScene;
|
||||
delete copiedMetatile;
|
||||
}
|
||||
|
||||
void TilesetEditor::update(Map *map, QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
@@ -76,8 +77,8 @@ bool TilesetEditor::selectMetatile(uint16_t metatileId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t TilesetEditor::getSelectedMetatile() {
|
||||
return this->metatileSelector->getSelectedMetatile();
|
||||
uint16_t TilesetEditor::getSelectedMetatileId() {
|
||||
return this->metatileSelector->getSelectedMetatileId();
|
||||
}
|
||||
|
||||
void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
@@ -177,7 +178,7 @@ void TilesetEditor::initMetatileSelector()
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileLayersItem() {
|
||||
Metatile *metatile = Tileset::getMetatile(this->getSelectedMetatile(), this->primaryTileset, this->secondaryTileset);
|
||||
Metatile *metatile = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::tileChanged,
|
||||
this, &TilesetEditor::onMetatileLayerTileChanged);
|
||||
@@ -282,7 +283,7 @@ void TilesetEditor::refresh() {
|
||||
this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileSelector->select(this->getSelectedMetatile());
|
||||
this->metatileSelector->select(this->getSelectedMetatileId());
|
||||
this->drawSelectedTiles();
|
||||
|
||||
if (metatileSelector) {
|
||||
@@ -419,7 +420,7 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) {
|
||||
this->metatileLayersItem->draw();
|
||||
this->hasUnsavedChanges = true;
|
||||
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
}
|
||||
@@ -486,7 +487,7 @@ void TilesetEditor::on_comboBox_metatileBehaviors_textActivated(const QString &m
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->behavior = static_cast<uint16_t>(project->metatileBehaviorMap[metatileBehavior]);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
this->hasUnsavedChanges = true;
|
||||
@@ -510,7 +511,7 @@ void TilesetEditor::saveMetatileLabel()
|
||||
if (this->metatile && this->metatile->label != this->ui->lineEdit_metatileLabel->text()) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->label = this->ui->lineEdit_metatileLabel->text();
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
this->hasUnsavedChanges = true;
|
||||
@@ -522,7 +523,7 @@ void TilesetEditor::on_comboBox_layerType_activated(int layerType)
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->layerType = static_cast<uint8_t>(layerType);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
this->hasUnsavedChanges = true;
|
||||
@@ -534,7 +535,7 @@ void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->encounterType = static_cast<uint8_t>(encounterType);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
this->hasUnsavedChanges = true;
|
||||
@@ -546,7 +547,7 @@ void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->terrainType = static_cast<uint8_t>(terrainType);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
this->hasUnsavedChanges = true;
|
||||
@@ -811,6 +812,21 @@ void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) {
|
||||
this->on_spinBox_paletteSelector_valueChanged(paletteId);
|
||||
}
|
||||
|
||||
bool TilesetEditor::replaceMetatile(uint16_t metatileId, Metatile * src)
|
||||
{
|
||||
Metatile * dest = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
|
||||
if (!dest || !src || *dest == *src)
|
||||
return false;
|
||||
|
||||
this->metatile = dest;
|
||||
*this->metatile = *src;
|
||||
this->metatileSelector->select(metatileId);
|
||||
this->metatileSelector->draw();
|
||||
this->metatileLayersItem->draw();
|
||||
this->metatileLayersItem->clearLastModifiedCoords();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionUndo_triggered()
|
||||
{
|
||||
MetatileHistoryItem *commit = this->metatileHistory.current();
|
||||
@@ -818,34 +834,39 @@ void TilesetEditor::on_actionUndo_triggered()
|
||||
Metatile *prev = commit->prevMetatile;
|
||||
if (!prev) return;
|
||||
this->metatileHistory.back();
|
||||
|
||||
Metatile *temp = Tileset::getMetatile(commit->metatileId, this->primaryTileset, this->secondaryTileset);
|
||||
if (temp) {
|
||||
this->metatile = temp;
|
||||
*this->metatile = *prev;
|
||||
this->metatileSelector->select(commit->metatileId);
|
||||
this->metatileSelector->draw();
|
||||
this->metatileLayersItem->draw();
|
||||
this->metatileLayersItem->clearLastModifiedCoords();
|
||||
}
|
||||
this->replaceMetatile(commit->metatileId, prev);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionRedo_triggered()
|
||||
{
|
||||
MetatileHistoryItem *commit = this->metatileHistory.next();
|
||||
if (!commit) return;
|
||||
Metatile *next = commit->newMetatile;
|
||||
if (!next) return;
|
||||
this->replaceMetatile(commit->metatileId, commit->newMetatile);
|
||||
}
|
||||
|
||||
Metatile *temp = Tileset::getMetatile(commit->metatileId, this->primaryTileset, this->secondaryTileset);
|
||||
if (temp) {
|
||||
this->metatile = temp;
|
||||
*this->metatile = *next;
|
||||
this->metatileSelector->select(commit->metatileId);
|
||||
this->metatileSelector->draw();
|
||||
this->metatileLayersItem->draw();
|
||||
this->metatileLayersItem->clearLastModifiedCoords();
|
||||
void TilesetEditor::on_actionCopy_triggered()
|
||||
{
|
||||
Metatile * toCopy = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset);
|
||||
if (!toCopy) return;
|
||||
|
||||
if (!this->copiedMetatile)
|
||||
this->copiedMetatile = new Metatile(*toCopy);
|
||||
else
|
||||
*this->copiedMetatile = *toCopy;
|
||||
this->copiedMetatile->label = ""; // Don't copy the label, these should be unique to each metatile
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionPaste_triggered()
|
||||
{
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
uint16_t metatileId = this->getSelectedMetatileId();
|
||||
if (!this->replaceMetatile(metatileId, this->copiedMetatile)) {
|
||||
delete prevMetatile;
|
||||
return;
|
||||
}
|
||||
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId, prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered()
|
||||
|
||||
@@ -78,7 +78,7 @@ void TilesetEditorMetatileSelector::updateSelectedMetatile() {
|
||||
emit selectedMetatileChanged(this->selectedMetatile);
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getSelectedMetatile() {
|
||||
uint16_t TilesetEditorMetatileSelector::getSelectedMetatileId() {
|
||||
return this->selectedMetatile;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user