Support setting custom attributes as defaults
This commit is contained in:
parent
eb6a56bd60
commit
e421a84542
12 changed files with 300 additions and 76 deletions
|
@ -29,6 +29,7 @@ public:
|
||||||
void save();
|
void save();
|
||||||
void load();
|
void load();
|
||||||
void setSaveDisabled(bool disabled);
|
void setSaveDisabled(bool disabled);
|
||||||
|
void logInvalidKey(const QString &key);
|
||||||
virtual ~KeyValueConfigBase();
|
virtual ~KeyValueConfigBase();
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
protected:
|
protected:
|
||||||
|
@ -319,6 +320,8 @@ public:
|
||||||
this->blockCollisionMask = 0x0C00;
|
this->blockCollisionMask = 0x0C00;
|
||||||
this->blockElevationMask = 0xF000;
|
this->blockElevationMask = 0xF000;
|
||||||
this->identifiers.clear();
|
this->identifiers.clear();
|
||||||
|
this->defaultEventCustomAttributes.clear();
|
||||||
|
this->defaultMapCustomAttributes.clear();
|
||||||
this->readKeys.clear();
|
this->readKeys.clear();
|
||||||
}
|
}
|
||||||
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
|
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
|
||||||
|
@ -417,6 +420,12 @@ public:
|
||||||
int getCollisionSheetHeight();
|
int getCollisionSheetHeight();
|
||||||
void setWarpBehaviors(const QSet<uint32_t> &behaviors);
|
void setWarpBehaviors(const QSet<uint32_t> &behaviors);
|
||||||
QSet<uint32_t> getWarpBehaviors();
|
QSet<uint32_t> getWarpBehaviors();
|
||||||
|
void insertDefaultEventCustomAttribute(Event::Type eventType, const QString &key, QJsonValue value);
|
||||||
|
void insertDefaultMapCustomAttribute(const QString &key, QJsonValue value);
|
||||||
|
void removeDefaultEventCustomAttribute(Event::Type eventType, const QString &key);
|
||||||
|
void removeDefaultMapCustomAttribute(const QString &key);
|
||||||
|
QMap<QString, QJsonValue> getDefaultEventCustomAttributes(Event::Type eventType);
|
||||||
|
QMap<QString, QJsonValue> getDefaultMapCustomAttributes();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString getConfigFilepath() override;
|
virtual QString getConfigFilepath() override;
|
||||||
|
@ -425,6 +434,9 @@ protected:
|
||||||
virtual void onNewConfigFileCreated() override;
|
virtual void onNewConfigFileCreated() override;
|
||||||
virtual void setUnreadKeys() override;
|
virtual void setUnreadKeys() override;
|
||||||
private:
|
private:
|
||||||
|
void parseCustomAttributes(const QString &key, const QString &value);
|
||||||
|
QString customAttributesToString(const QMap<QString, QJsonValue> attributes);
|
||||||
|
|
||||||
BaseGameVersion baseGameVersion;
|
BaseGameVersion baseGameVersion;
|
||||||
QString projectDir;
|
QString projectDir;
|
||||||
QMap<ProjectIdentifier, QString> identifiers;
|
QMap<ProjectIdentifier, QString> identifiers;
|
||||||
|
@ -466,6 +478,8 @@ private:
|
||||||
int collisionSheetWidth;
|
int collisionSheetWidth;
|
||||||
int collisionSheetHeight;
|
int collisionSheetHeight;
|
||||||
QSet<uint32_t> warpBehaviors;
|
QSet<uint32_t> warpBehaviors;
|
||||||
|
QMap<Event::Type, QMap<QString, QJsonValue>> defaultEventCustomAttributes;
|
||||||
|
QMap<QString, QJsonValue> defaultMapCustomAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ProjectConfig projectConfig;
|
extern ProjectConfig projectConfig;
|
||||||
|
|
|
@ -158,10 +158,11 @@ public:
|
||||||
virtual void setDefaultValues(Project *project);
|
virtual void setDefaultValues(Project *project);
|
||||||
|
|
||||||
virtual QSet<QString> getExpectedFields() = 0;
|
virtual QSet<QString> getExpectedFields() = 0;
|
||||||
void readCustomValues(QJsonObject values);
|
void readCustomAttributes(QJsonObject values);
|
||||||
void addCustomValuesTo(OrderedJson::object *obj);
|
void addCustomAttributesTo(OrderedJson::object *obj);
|
||||||
const QMap<QString, QJsonValue> getCustomValues() { return this->customValues; }
|
const QMap<QString, QJsonValue> getCustomAttributes() { return this->customAttributes; }
|
||||||
void setCustomValues(const QMap<QString, QJsonValue> newCustomValues) { this->customValues = newCustomValues; }
|
void setCustomAttributes(const QMap<QString, QJsonValue> newCustomAttributes) { this->customAttributes = newCustomAttributes; }
|
||||||
|
void setDefaultCustomAttributes();
|
||||||
|
|
||||||
virtual void loadPixmap(Project *project);
|
virtual void loadPixmap(Project *project);
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@ protected:
|
||||||
int spriteHeight = 16;
|
int spriteHeight = 16;
|
||||||
bool usingSprite = false;
|
bool usingSprite = false;
|
||||||
|
|
||||||
QMap<QString, QJsonValue> customValues;
|
QMap<QString, QJsonValue> customAttributes;
|
||||||
|
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
DraggablePixmapItem *pixmapItem = nullptr;
|
DraggablePixmapItem *pixmapItem = nullptr;
|
||||||
|
|
|
@ -379,7 +379,7 @@ private:
|
||||||
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
||||||
void closeSupplementaryWindows();
|
void closeSupplementaryWindows();
|
||||||
void setWindowDisabled(bool);
|
void setWindowDisabled(bool);
|
||||||
|
void resetMapCustomAttributesTable();
|
||||||
void initTilesetEditor();
|
void initTilesetEditor();
|
||||||
bool initRegionMapEditor(bool silent = false);
|
bool initRegionMapEditor(bool silent = false);
|
||||||
void initShortcutsEditor();
|
void initShortcutsEditor();
|
||||||
|
|
|
@ -23,7 +23,8 @@ private:
|
||||||
CustomAttributesTable *const table;
|
CustomAttributesTable *const table;
|
||||||
|
|
||||||
void addNewAttribute();
|
void addNewAttribute();
|
||||||
bool verifyName();
|
bool verifyInput();
|
||||||
|
QVariant getValue() const;
|
||||||
void setNameEditHighlight(bool highlight);
|
void setNameEditHighlight(bool highlight);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,27 +16,31 @@ public:
|
||||||
|
|
||||||
QMap<QString, QJsonValue> getAttributes() const;
|
QMap<QString, QJsonValue> getAttributes() const;
|
||||||
void setAttributes(const QMap<QString, QJsonValue> attributes);
|
void setAttributes(const QMap<QString, QJsonValue> attributes);
|
||||||
void addNewAttribute(const QString &key, QJsonValue value);
|
void addNewAttribute(const QString &key, QJsonValue value, bool setAsDefault);
|
||||||
|
|
||||||
void setDefaultAttribute(const QString &key, QJsonValue value);
|
|
||||||
void unsetDefaultAttribute(const QString &key);
|
|
||||||
|
|
||||||
QSet<QString> keys() const;
|
QSet<QString> keys() const;
|
||||||
|
QSet<QString> defaultKeys() const;
|
||||||
QSet<QString> restrictedKeys() const;
|
QSet<QString> restrictedKeys() const;
|
||||||
|
void setDefaultKeys(const QSet<QString> keys);
|
||||||
void setRestrictedKeys(const QSet<QString> keys);
|
void setRestrictedKeys(const QSet<QString> keys);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void edited();
|
void edited();
|
||||||
|
void defaultSet(QString key, QJsonValue value);
|
||||||
|
void defaultRemoved(QString key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTableWidget *table;
|
QTableWidget *table;
|
||||||
|
|
||||||
QSet<QString> m_keys;
|
QSet<QString> m_keys; // All keys currently in the table
|
||||||
QSet<QString> m_restrictedKeys;
|
QSet<QString> m_defaultKeys; // All keys that are in this table by default (whether or not they're present)
|
||||||
|
QSet<QString> m_restrictedKeys; // All keys not allowed in the table
|
||||||
|
|
||||||
int addAttribute(const QString &key, QJsonValue value);
|
int addAttribute(const QString &key, QJsonValue value);
|
||||||
void removeAttribute(const QString &key);
|
void removeAttribute(const QString &key);
|
||||||
bool deleteSelectedAttributes();
|
bool deleteSelectedAttributes();
|
||||||
|
void setDefaultAttribute(const QString &key, QJsonValue value);
|
||||||
|
void unsetDefaultAttribute(const QString &key);
|
||||||
void resizeVertically();
|
void resizeVertically();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
139
src/config.cpp
139
src/config.cpp
|
@ -292,6 +292,10 @@ void KeyValueConfigBase::setSaveDisabled(bool disabled) {
|
||||||
this->saveDisabled = disabled;
|
this->saveDisabled = disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyValueConfigBase::logInvalidKey(const QString &key) {
|
||||||
|
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||||
|
}
|
||||||
|
|
||||||
const QMap<MapSortOrder, QString> mapSortOrderMap = {
|
const QMap<MapSortOrder, QString> mapSortOrderMap = {
|
||||||
{MapSortOrder::Group, "group"},
|
{MapSortOrder::Group, "group"},
|
||||||
{MapSortOrder::Layout, "layout"},
|
{MapSortOrder::Layout, "layout"},
|
||||||
|
@ -400,7 +404,7 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
||||||
} else if (key == "warp_behavior_warning_disabled") {
|
} else if (key == "warp_behavior_warning_disabled") {
|
||||||
this->warpBehaviorWarningDisabled = getConfigBool(key, value);
|
this->warpBehaviorWarningDisabled = getConfigBool(key, value);
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logInvalidKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,14 +876,14 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||||
if (k != static_cast<ProjectFilePath>(-1)) {
|
if (k != static_cast<ProjectFilePath>(-1)) {
|
||||||
this->setFilePath(k, value);
|
this->setFilePath(k, value);
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logInvalidKey(key);
|
||||||
}
|
}
|
||||||
} else if (key.startsWith("ident/")) {
|
} else if (key.startsWith("ident/")) {
|
||||||
auto identifierId = reverseDefaultIdentifier(key.mid(6));
|
auto identifierId = reverseDefaultIdentifier(key.mid(6));
|
||||||
if (identifierId != static_cast<ProjectIdentifier>(-1)) {
|
if (identifierId != static_cast<ProjectIdentifier>(-1)) {
|
||||||
this->setIdentifier(identifierId, value);
|
this->setIdentifier(identifierId, value);
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logInvalidKey(key);
|
||||||
}
|
}
|
||||||
} else if (key == "prefabs_filepath") {
|
} else if (key == "prefabs_filepath") {
|
||||||
this->prefabFilepath = value;
|
this->prefabFilepath = value;
|
||||||
|
@ -913,8 +917,10 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||||
QStringList behaviorList = value.split(",", Qt::SkipEmptyParts);
|
QStringList behaviorList = value.split(",", Qt::SkipEmptyParts);
|
||||||
for (auto s : behaviorList)
|
for (auto s : behaviorList)
|
||||||
this->warpBehaviors.insert(getConfigUint32(key, s));
|
this->warpBehaviors.insert(getConfigUint32(key, s));
|
||||||
|
} else if (key.startsWith("custom_attributes/")) {
|
||||||
|
this->parseCustomAttributes(key, value);
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logInvalidKey(key);
|
||||||
}
|
}
|
||||||
readKeys.append(key);
|
readKeys.append(key);
|
||||||
}
|
}
|
||||||
|
@ -1004,6 +1010,12 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
||||||
for (auto value : this->warpBehaviors)
|
for (auto value : this->warpBehaviors)
|
||||||
warpBehaviorStrs.append("0x" + QString("%1").arg(value, 2, 16, QChar('0')).toUpper());
|
warpBehaviorStrs.append("0x" + QString("%1").arg(value, 2, 16, QChar('0')).toUpper());
|
||||||
map.insert("warp_behaviors", warpBehaviorStrs.join(","));
|
map.insert("warp_behaviors", warpBehaviorStrs.join(","));
|
||||||
|
if (!this->defaultMapCustomAttributes.isEmpty())
|
||||||
|
map.insert("custom_attributes/header", this->customAttributesToString(this->defaultMapCustomAttributes));
|
||||||
|
for (auto i = this->defaultEventCustomAttributes.cbegin(), end = this->defaultEventCustomAttributes.cend(); i != end; i++) {
|
||||||
|
if (!i.value().isEmpty())
|
||||||
|
map.insert("custom_attributes/" + Event::eventTypeToString(i.key()), this->customAttributesToString(i.value()));
|
||||||
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@ -1466,6 +1478,123 @@ QSet<uint32_t> ProjectConfig::getWarpBehaviors() {
|
||||||
return this->warpBehaviors;
|
return this->warpBehaviors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProjectConfig::insertDefaultEventCustomAttribute(Event::Type eventType, const QString &key, QJsonValue value) {
|
||||||
|
this->defaultEventCustomAttributes[eventType].insert(key, value);
|
||||||
|
this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectConfig::insertDefaultMapCustomAttribute(const QString &key, QJsonValue value) {
|
||||||
|
this->defaultMapCustomAttributes.insert(key, value);
|
||||||
|
this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectConfig::removeDefaultEventCustomAttribute(Event::Type eventType, const QString &key) {
|
||||||
|
this->defaultEventCustomAttributes[eventType].remove(key);
|
||||||
|
this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectConfig::removeDefaultMapCustomAttribute(const QString &key) {
|
||||||
|
this->defaultMapCustomAttributes.remove(key);
|
||||||
|
this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QJsonValue> ProjectConfig::getDefaultEventCustomAttributes(Event::Type eventType) {
|
||||||
|
return this->defaultEventCustomAttributes.value(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QJsonValue> ProjectConfig::getDefaultMapCustomAttributes() {
|
||||||
|
return this->defaultMapCustomAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectConfig::parseCustomAttributes(const QString &key, const QString &value) {
|
||||||
|
static const QRegularExpression regex("custom_attributes/(?<identifier>\\w+)");
|
||||||
|
auto match = regex.match(key);
|
||||||
|
if (!match.hasMatch()){
|
||||||
|
logInvalidKey(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value should be a comma-separated list of sequences of the form 'key:type:value'.
|
||||||
|
// Some day if this config file is formatted as JSON data we wouldn't need to store 'type' (among other simplifications).
|
||||||
|
QMap<QString, QJsonValue> map;
|
||||||
|
const QStringList attributeSequences = value.split(",", Qt::SkipEmptyParts);
|
||||||
|
if (attributeSequences.isEmpty())
|
||||||
|
return;
|
||||||
|
for (auto sequence : attributeSequences) {
|
||||||
|
// Parse each 'type:key:value' sequence
|
||||||
|
const QStringList attributeData = sequence.split(":");
|
||||||
|
if (attributeData.length() != 3) {
|
||||||
|
logWarn(QString("Invalid value '%1' for custom attribute in '%2'").arg(sequence).arg(key));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const QString attrKey = attributeData.at(0);
|
||||||
|
const QString attrType = attributeData.at(1);
|
||||||
|
const QString attrValue = attributeData.at(2);
|
||||||
|
|
||||||
|
QJsonValue value;
|
||||||
|
if (attrType == "string") {
|
||||||
|
value = QJsonValue(attrValue);
|
||||||
|
} else if (attrType == "number") {
|
||||||
|
bool ok;
|
||||||
|
int num = attrValue.toInt(&ok, 0);
|
||||||
|
if (!ok)
|
||||||
|
logWarn(QString("Invalid value '%1' for custom attribute '%2' in '%3'").arg(attrValue).arg(attrKey).arg(key));
|
||||||
|
value = QJsonValue(num);
|
||||||
|
} else if (attrType == "bool") {
|
||||||
|
bool ok;
|
||||||
|
int num = attrValue.toInt(&ok, 0);
|
||||||
|
if (!ok || (num != 0 && num != 1))
|
||||||
|
logWarn(QString("Invalid value '%1' for custom attribute '%2' in '%3'").arg(attrValue).arg(attrKey).arg(key));
|
||||||
|
value = QJsonValue(num == 1);
|
||||||
|
} else {
|
||||||
|
logWarn(QString("Invalid value type '%1' for custom attribute '%2' in '%3'").arg(attrType).arg(attrKey).arg(key));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Successfully parsed a 'type:key:value' sequence
|
||||||
|
map.insert(attrKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine who the custom attribute map belongs to (either the map header or some Event type)
|
||||||
|
const QString identifier = match.captured("identifier");
|
||||||
|
|
||||||
|
if (identifier == "header") {
|
||||||
|
this->defaultMapCustomAttributes = map;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Type eventType = Event::eventTypeFromString(identifier);
|
||||||
|
if (eventType != Event::Type::None) {
|
||||||
|
this->defaultEventCustomAttributes[eventType] = map;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logWarn(QString("Invalid custom attributes identifier '%1' in '%2'").arg(identifier).arg(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble comma-separated list of sequences of the form 'key:type:value'.
|
||||||
|
QString ProjectConfig::customAttributesToString(const QMap<QString, QJsonValue> attributes) {
|
||||||
|
QStringList output;
|
||||||
|
for (auto i = attributes.cbegin(), end = attributes.cend(); i != end; i++) {
|
||||||
|
QString value;
|
||||||
|
QString typeStr;
|
||||||
|
QJsonValue::Type type = i.value().type();
|
||||||
|
if (type == QJsonValue::Type::String) {
|
||||||
|
typeStr = "string";
|
||||||
|
value = i.value().toString();
|
||||||
|
} else if (type == QJsonValue::Type::Double) {
|
||||||
|
typeStr = "number";
|
||||||
|
value = QString::number(i.value().toInt());
|
||||||
|
} else if (type == QJsonValue::Type::Bool) {
|
||||||
|
typeStr = "bool";
|
||||||
|
value = QString::number(i.value().toBool());
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
output.append(QString("%1:%2:%3").arg(i.key()).arg(typeStr).arg(value));
|
||||||
|
}
|
||||||
|
return output.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UserConfig userConfig;
|
UserConfig userConfig;
|
||||||
|
|
||||||
|
@ -1482,7 +1611,7 @@ void UserConfig::parseConfigKeyValue(QString key, QString value) {
|
||||||
} else if (key == "custom_scripts") {
|
} else if (key == "custom_scripts") {
|
||||||
this->parseCustomScripts(value);
|
this->parseCustomScripts(value);
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logInvalidKey(key);
|
||||||
}
|
}
|
||||||
readKeys.append(key);
|
readKeys.append(key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,22 +36,27 @@ void Event::setDefaultValues(Project *) {
|
||||||
this->setX(0);
|
this->setX(0);
|
||||||
this->setY(0);
|
this->setY(0);
|
||||||
this->setElevation(projectConfig.getDefaultElevation());
|
this->setElevation(projectConfig.getDefaultElevation());
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::readCustomValues(QJsonObject values) {
|
void Event::setDefaultCustomAttributes() {
|
||||||
this->customValues.clear();
|
this->setCustomAttributes(projectConfig.getDefaultEventCustomAttributes(this->getEventType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::readCustomAttributes(QJsonObject values) {
|
||||||
|
this->customAttributes.clear();
|
||||||
QSet<QString> expectedFields = this->getExpectedFields();
|
QSet<QString> expectedFields = this->getExpectedFields();
|
||||||
for (QString key : values.keys()) {
|
for (QString key : values.keys()) {
|
||||||
if (!expectedFields.contains(key)) {
|
if (!expectedFields.contains(key)) {
|
||||||
this->customValues[key] = values[key];
|
this->customAttributes[key] = values[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::addCustomValuesTo(OrderedJson::object *obj) {
|
void Event::addCustomAttributesTo(OrderedJson::object *obj) {
|
||||||
for (QString key : this->customValues.keys()) {
|
for (QString key : this->customAttributes.keys()) {
|
||||||
if (!obj->contains(key)) {
|
if (!obj->contains(key)) {
|
||||||
(*obj)[key] = OrderedJson::fromQJsonValue(this->customValues[key]);
|
(*obj)[key] = OrderedJson::fromQJsonValue(this->customAttributes[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +184,7 @@ Event *ObjectEvent::duplicate() {
|
||||||
copy->setSightRadiusBerryTreeID(this->getSightRadiusBerryTreeID());
|
copy->setSightRadiusBerryTreeID(this->getSightRadiusBerryTreeID());
|
||||||
copy->setScript(this->getScript());
|
copy->setScript(this->getScript());
|
||||||
copy->setFlag(this->getFlag());
|
copy->setFlag(this->getFlag());
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +214,7 @@ OrderedJson::object ObjectEvent::buildEventJson(Project *) {
|
||||||
objectJson["trainer_sight_or_berry_tree_id"] = this->getSightRadiusBerryTreeID();
|
objectJson["trainer_sight_or_berry_tree_id"] = this->getSightRadiusBerryTreeID();
|
||||||
objectJson["script"] = this->getScript();
|
objectJson["script"] = this->getScript();
|
||||||
objectJson["flag"] = this->getFlag();
|
objectJson["flag"] = this->getFlag();
|
||||||
this->addCustomValuesTo(&objectJson);
|
this->addCustomAttributesTo(&objectJson);
|
||||||
|
|
||||||
return objectJson;
|
return objectJson;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +232,7 @@ bool ObjectEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setScript(ParseUtil::jsonToQString(json["script"]));
|
this->setScript(ParseUtil::jsonToQString(json["script"]));
|
||||||
this->setFlag(ParseUtil::jsonToQString(json["flag"]));
|
this->setFlag(ParseUtil::jsonToQString(json["flag"]));
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -242,6 +247,7 @@ void ObjectEvent::setDefaultValues(Project *project) {
|
||||||
this->setRadiusY(0);
|
this->setRadiusY(0);
|
||||||
this->setSightRadiusBerryTreeID("0");
|
this->setSightRadiusBerryTreeID("0");
|
||||||
this->setFrameFromMovement(project->facingDirections.value(this->getMovement()));
|
this->setFrameFromMovement(project->facingDirections.value(this->getMovement()));
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedObjectFields = {
|
const QSet<QString> expectedObjectFields = {
|
||||||
|
@ -353,7 +359,7 @@ Event *CloneObjectEvent::duplicate() {
|
||||||
copy->setGfx(this->getGfx());
|
copy->setGfx(this->getGfx());
|
||||||
copy->setTargetID(this->getTargetID());
|
copy->setTargetID(this->getTargetID());
|
||||||
copy->setTargetMap(this->getTargetMap());
|
copy->setTargetMap(this->getTargetMap());
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +381,7 @@ OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) {
|
||||||
cloneJson["y"] = this->getY();
|
cloneJson["y"] = this->getY();
|
||||||
cloneJson["target_local_id"] = this->getTargetID();
|
cloneJson["target_local_id"] = this->getTargetID();
|
||||||
cloneJson["target_map"] = project->mapNamesToMapConstants.value(this->getTargetMap());
|
cloneJson["target_map"] = project->mapNamesToMapConstants.value(this->getTargetMap());
|
||||||
this->addCustomValuesTo(&cloneJson);
|
this->addCustomAttributesTo(&cloneJson);
|
||||||
|
|
||||||
return cloneJson;
|
return cloneJson;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +404,7 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
||||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +413,7 @@ void CloneObjectEvent::setDefaultValues(Project *project) {
|
||||||
this->setGfx(project->gfxDefines.keys().first());
|
this->setGfx(project->gfxDefines.keys().first());
|
||||||
this->setTargetID(1);
|
this->setTargetID(1);
|
||||||
if (this->getMap()) this->setTargetMap(this->getMap()->name);
|
if (this->getMap()) this->setTargetMap(this->getMap()->name);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedCloneObjectFields = {
|
const QSet<QString> expectedCloneObjectFields = {
|
||||||
|
@ -465,7 +472,7 @@ Event *WarpEvent::duplicate() {
|
||||||
copy->setDestinationMap(this->getDestinationMap());
|
copy->setDestinationMap(this->getDestinationMap());
|
||||||
copy->setDestinationWarpID(this->getDestinationWarpID());
|
copy->setDestinationWarpID(this->getDestinationWarpID());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -487,7 +494,7 @@ OrderedJson::object WarpEvent::buildEventJson(Project *project) {
|
||||||
warpJson["dest_map"] = project->mapNamesToMapConstants.value(this->getDestinationMap());
|
warpJson["dest_map"] = project->mapNamesToMapConstants.value(this->getDestinationMap());
|
||||||
warpJson["dest_warp_id"] = this->getDestinationWarpID();
|
warpJson["dest_warp_id"] = this->getDestinationWarpID();
|
||||||
|
|
||||||
this->addCustomValuesTo(&warpJson);
|
this->addCustomAttributesTo(&warpJson);
|
||||||
|
|
||||||
return warpJson;
|
return warpJson;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +517,7 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
||||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -519,6 +526,7 @@ void WarpEvent::setDefaultValues(Project *) {
|
||||||
if (this->getMap()) this->setDestinationMap(this->getMap()->name);
|
if (this->getMap()) this->setDestinationMap(this->getMap()->name);
|
||||||
this->setDestinationWarpID("0");
|
this->setDestinationWarpID("0");
|
||||||
this->setElevation(0);
|
this->setElevation(0);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedWarpFields = {
|
const QSet<QString> expectedWarpFields = {
|
||||||
|
@ -552,7 +560,7 @@ Event *TriggerEvent::duplicate() {
|
||||||
copy->setScriptVarValue(this->getScriptVarValue());
|
copy->setScriptVarValue(this->getScriptVarValue());
|
||||||
copy->setScriptLabel(this->getScriptLabel());
|
copy->setScriptLabel(this->getScriptLabel());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -576,7 +584,7 @@ OrderedJson::object TriggerEvent::buildEventJson(Project *) {
|
||||||
triggerJson["var_value"] = this->getScriptVarValue();
|
triggerJson["var_value"] = this->getScriptVarValue();
|
||||||
triggerJson["script"] = this->getScriptLabel();
|
triggerJson["script"] = this->getScriptLabel();
|
||||||
|
|
||||||
this->addCustomValuesTo(&triggerJson);
|
this->addCustomAttributesTo(&triggerJson);
|
||||||
|
|
||||||
return triggerJson;
|
return triggerJson;
|
||||||
}
|
}
|
||||||
|
@ -589,7 +597,7 @@ bool TriggerEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setScriptVarValue(ParseUtil::jsonToQString(json["var_value"]));
|
this->setScriptVarValue(ParseUtil::jsonToQString(json["var_value"]));
|
||||||
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -599,6 +607,7 @@ void TriggerEvent::setDefaultValues(Project *project) {
|
||||||
this->setScriptVar(project->varNames.first());
|
this->setScriptVar(project->varNames.first());
|
||||||
this->setScriptVarValue("0");
|
this->setScriptVarValue("0");
|
||||||
this->setElevation(0);
|
this->setElevation(0);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedTriggerFields = {
|
const QSet<QString> expectedTriggerFields = {
|
||||||
|
@ -626,7 +635,7 @@ Event *WeatherTriggerEvent::duplicate() {
|
||||||
copy->setElevation(this->getElevation());
|
copy->setElevation(this->getElevation());
|
||||||
copy->setWeather(this->getWeather());
|
copy->setWeather(this->getWeather());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +657,7 @@ OrderedJson::object WeatherTriggerEvent::buildEventJson(Project *) {
|
||||||
weatherJson["elevation"] = this->getElevation();
|
weatherJson["elevation"] = this->getElevation();
|
||||||
weatherJson["weather"] = this->getWeather();
|
weatherJson["weather"] = this->getWeather();
|
||||||
|
|
||||||
this->addCustomValuesTo(&weatherJson);
|
this->addCustomAttributesTo(&weatherJson);
|
||||||
|
|
||||||
return weatherJson;
|
return weatherJson;
|
||||||
}
|
}
|
||||||
|
@ -659,7 +668,7 @@ bool WeatherTriggerEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||||
this->setWeather(ParseUtil::jsonToQString(json["weather"]));
|
this->setWeather(ParseUtil::jsonToQString(json["weather"]));
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -667,6 +676,7 @@ bool WeatherTriggerEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
void WeatherTriggerEvent::setDefaultValues(Project *project) {
|
void WeatherTriggerEvent::setDefaultValues(Project *project) {
|
||||||
this->setWeather(project->coordEventWeatherNames.first());
|
this->setWeather(project->coordEventWeatherNames.first());
|
||||||
this->setElevation(0);
|
this->setElevation(0);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedWeatherTriggerFields = {
|
const QSet<QString> expectedWeatherTriggerFields = {
|
||||||
|
@ -693,7 +703,7 @@ Event *SignEvent::duplicate() {
|
||||||
copy->setFacingDirection(this->getFacingDirection());
|
copy->setFacingDirection(this->getFacingDirection());
|
||||||
copy->setScriptLabel(this->getScriptLabel());
|
copy->setScriptLabel(this->getScriptLabel());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -716,7 +726,7 @@ OrderedJson::object SignEvent::buildEventJson(Project *) {
|
||||||
signJson["player_facing_dir"] = this->getFacingDirection();
|
signJson["player_facing_dir"] = this->getFacingDirection();
|
||||||
signJson["script"] = this->getScriptLabel();
|
signJson["script"] = this->getScriptLabel();
|
||||||
|
|
||||||
this->addCustomValuesTo(&signJson);
|
this->addCustomAttributesTo(&signJson);
|
||||||
|
|
||||||
return signJson;
|
return signJson;
|
||||||
}
|
}
|
||||||
|
@ -728,7 +738,7 @@ bool SignEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setFacingDirection(ParseUtil::jsonToQString(json["player_facing_dir"]));
|
this->setFacingDirection(ParseUtil::jsonToQString(json["player_facing_dir"]));
|
||||||
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -737,6 +747,7 @@ void SignEvent::setDefaultValues(Project *project) {
|
||||||
this->setFacingDirection(project->bgEventFacingDirections.first());
|
this->setFacingDirection(project->bgEventFacingDirections.first());
|
||||||
this->setScriptLabel("NULL");
|
this->setScriptLabel("NULL");
|
||||||
this->setElevation(0);
|
this->setElevation(0);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedSignFields = {
|
const QSet<QString> expectedSignFields = {
|
||||||
|
@ -766,7 +777,7 @@ Event *HiddenItemEvent::duplicate() {
|
||||||
copy->setQuantity(this->getQuantity());
|
copy->setQuantity(this->getQuantity());
|
||||||
copy->setQuantity(this->getQuantity());
|
copy->setQuantity(this->getQuantity());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -795,7 +806,7 @@ OrderedJson::object HiddenItemEvent::buildEventJson(Project *) {
|
||||||
hiddenItemJson["underfoot"] = this->getUnderfoot();
|
hiddenItemJson["underfoot"] = this->getUnderfoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->addCustomValuesTo(&hiddenItemJson);
|
this->addCustomAttributesTo(&hiddenItemJson);
|
||||||
|
|
||||||
return hiddenItemJson;
|
return hiddenItemJson;
|
||||||
}
|
}
|
||||||
|
@ -813,7 +824,7 @@ bool HiddenItemEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setUnderfoot(ParseUtil::jsonToBool(json["underfoot"]));
|
this->setUnderfoot(ParseUtil::jsonToBool(json["underfoot"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -827,6 +838,7 @@ void HiddenItemEvent::setDefaultValues(Project *project) {
|
||||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||||
this->setUnderfoot(false);
|
this->setUnderfoot(false);
|
||||||
}
|
}
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedHiddenItemFields = {
|
const QSet<QString> expectedHiddenItemFields = {
|
||||||
|
@ -859,7 +871,7 @@ Event *SecretBaseEvent::duplicate() {
|
||||||
copy->setElevation(this->getElevation());
|
copy->setElevation(this->getElevation());
|
||||||
copy->setBaseID(this->getBaseID());
|
copy->setBaseID(this->getBaseID());
|
||||||
|
|
||||||
copy->setCustomValues(this->getCustomValues());
|
copy->setCustomAttributes(this->getCustomAttributes());
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -881,7 +893,7 @@ OrderedJson::object SecretBaseEvent::buildEventJson(Project *) {
|
||||||
secretBaseJson["elevation"] = this->getElevation();
|
secretBaseJson["elevation"] = this->getElevation();
|
||||||
secretBaseJson["secret_base_id"] = this->getBaseID();
|
secretBaseJson["secret_base_id"] = this->getBaseID();
|
||||||
|
|
||||||
this->addCustomValuesTo(&secretBaseJson);
|
this->addCustomAttributesTo(&secretBaseJson);
|
||||||
|
|
||||||
return secretBaseJson;
|
return secretBaseJson;
|
||||||
}
|
}
|
||||||
|
@ -892,7 +904,7 @@ bool SecretBaseEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||||
this->setBaseID(ParseUtil::jsonToQString(json["secret_base_id"]));
|
this->setBaseID(ParseUtil::jsonToQString(json["secret_base_id"]));
|
||||||
|
|
||||||
this->readCustomValues(json);
|
this->readCustomAttributes(json);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -900,6 +912,7 @@ bool SecretBaseEvent::loadFromJson(QJsonObject json, Project *) {
|
||||||
void SecretBaseEvent::setDefaultValues(Project *project) {
|
void SecretBaseEvent::setDefaultValues(Project *project) {
|
||||||
this->setBaseID(project->secretBaseIds.first());
|
this->setBaseID(project->secretBaseIds.first());
|
||||||
this->setElevation(0);
|
this->setElevation(0);
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString> expectedSecretBaseFields = {
|
const QSet<QString> expectedSecretBaseFields = {
|
||||||
|
@ -931,6 +944,7 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *) {
|
||||||
|
|
||||||
void HealLocationEvent::setDefaultValues(Project *) {
|
void HealLocationEvent::setDefaultValues(Project *) {
|
||||||
this->setElevation(projectConfig.getDefaultElevation());
|
this->setElevation(projectConfig.getDefaultElevation());
|
||||||
|
this->setDefaultCustomAttributes();
|
||||||
if (!this->getMap())
|
if (!this->getMap())
|
||||||
return;
|
return;
|
||||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||||
|
|
|
@ -302,10 +302,23 @@ void MainWindow::initEditor() {
|
||||||
this->editor->selectedEventIndexChanged(value, Event::Group::Heal);
|
this->editor->selectedEventIndexChanged(value, Event::Group::Heal);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Connect the Custom Attributes table on the Header tab
|
||||||
connect(ui->mapCustomAttributesTable, &CustomAttributesTable::edited, [this]() {
|
connect(ui->mapCustomAttributesTable, &CustomAttributesTable::edited, [this]() {
|
||||||
this->markMapEdited();
|
this->markMapEdited();
|
||||||
this->editor->updateCustomMapHeaderValues();
|
this->editor->updateCustomMapHeaderValues();
|
||||||
});
|
});
|
||||||
|
connect(ui->mapCustomAttributesTable, &CustomAttributesTable::defaultSet, [](QString key, QJsonValue value) {
|
||||||
|
projectConfig.insertDefaultMapCustomAttribute(key, value);
|
||||||
|
});
|
||||||
|
connect(ui->mapCustomAttributesTable, &CustomAttributesTable::defaultRemoved, [](QString key) {
|
||||||
|
projectConfig.removeDefaultMapCustomAttribute(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetMapCustomAttributesTable() {
|
||||||
|
QStringList keys = projectConfig.getDefaultMapCustomAttributes().keys();
|
||||||
|
ui->mapCustomAttributesTable->setDefaultKeys(QSet<QString>(keys.begin(), keys.end()));
|
||||||
|
ui->mapCustomAttributesTable->setRestrictedKeys(Project::getTopLevelMapFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::initMiscHeapObjects() {
|
void MainWindow::initMiscHeapObjects() {
|
||||||
|
@ -512,8 +525,8 @@ bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||||
projectConfig.load();
|
projectConfig.load();
|
||||||
|
|
||||||
this->closeSupplementaryWindows();
|
this->closeSupplementaryWindows();
|
||||||
|
this->resetMapCustomAttributesTable();
|
||||||
this->newMapDefaultsSet = false;
|
this->newMapDefaultsSet = false;
|
||||||
ui->mapCustomAttributesTable->setRestrictedKeys(Project::getTopLevelMapFields());
|
|
||||||
|
|
||||||
if (isProjectOpen())
|
if (isProjectOpen())
|
||||||
Scripting::cb_ProjectClosed(editor->project->root);
|
Scripting::cb_ProjectClosed(editor->project->root);
|
||||||
|
|
|
@ -31,16 +31,23 @@ CustomAttributesDialog::CustomAttributesDialog(CustomAttributesTable *parent) :
|
||||||
this->setNameEditHighlight(false);
|
this->setNameEditHighlight(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Exclude delimiters used in the config
|
||||||
|
static const QRegularExpression expression("[^:,=/]*");
|
||||||
|
ui->lineEdit_Name->setValidator(new QRegularExpressionValidator(expression));
|
||||||
|
|
||||||
// Button box
|
// Button box
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton *button) {
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton *button) {
|
||||||
auto buttonRole = ui->buttonBox->buttonRole(button);
|
auto buttonRole = ui->buttonBox->buttonRole(button);
|
||||||
if (buttonRole == QDialogButtonBox::AcceptRole && this->verifyName()) {
|
if (buttonRole == QDialogButtonBox::AcceptRole && this->verifyInput()) {
|
||||||
this->addNewAttribute();
|
this->addNewAttribute();
|
||||||
this->done(QDialog::Accepted);
|
this->done(QDialog::Accepted);
|
||||||
} else if (buttonRole == QDialogButtonBox::RejectRole) {
|
} else if (buttonRole == QDialogButtonBox::RejectRole) {
|
||||||
this->done(QDialog::Rejected);
|
this->done(QDialog::Rejected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui->spinBox_Value->setMinimum(INT_MIN);
|
||||||
|
ui->spinBox_Value->setMaximum(INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttributesDialog::~CustomAttributesDialog() {
|
CustomAttributesDialog::~CustomAttributesDialog() {
|
||||||
|
@ -51,7 +58,7 @@ void CustomAttributesDialog::setNameEditHighlight(bool highlight) {
|
||||||
ui->lineEdit_Name->setStyleSheet(highlight ? "QLineEdit { background-color: rgba(255, 0, 0, 25%) }" : "");
|
ui->lineEdit_Name->setStyleSheet(highlight ? "QLineEdit { background-color: rgba(255, 0, 0, 25%) }" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomAttributesDialog::verifyName() {
|
bool CustomAttributesDialog::verifyInput() {
|
||||||
const QString name = ui->lineEdit_Name->text();
|
const QString name = ui->lineEdit_Name->text();
|
||||||
|
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
|
@ -67,8 +74,16 @@ bool CustomAttributesDialog::verifyName() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warn user if changing the default value of a "Default" custom attribute
|
||||||
|
if (this->table->defaultKeys().contains(name) && ui->checkBox_Default->isChecked()) {
|
||||||
|
const QString msg = QString("'%1' is already a default attribute. Replace its default value with '%2'?")
|
||||||
|
.arg(name)
|
||||||
|
.arg(this->getValue().toString());
|
||||||
|
if (QMessageBox::warning(this, "Warning", msg, QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Warn user if key name would overwrite an existing custom attribute
|
// Warn user if key name would overwrite an existing custom attribute
|
||||||
if (this->table->keys().contains(name)) {
|
else if (this->table->keys().contains(name)) {
|
||||||
const QString msg = QString("Overwrite value for existing attribute '%1'?").arg(name);
|
const QString msg = QString("Overwrite value for existing attribute '%1'?").arg(name);
|
||||||
if (QMessageBox::warning(this, "Warning", msg, QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel)
|
if (QMessageBox::warning(this, "Warning", msg, QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel)
|
||||||
return false;
|
return false;
|
||||||
|
@ -77,20 +92,19 @@ bool CustomAttributesDialog::verifyName() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomAttributesDialog::addNewAttribute() {
|
QVariant CustomAttributesDialog::getValue() const {
|
||||||
QJsonValue value;
|
QVariant value;
|
||||||
const QString type = ui->comboBox_Type->currentText();
|
const QString type = ui->comboBox_Type->currentText();
|
||||||
if (type == "String") {
|
if (type == "String") {
|
||||||
value = QJsonValue(ui->lineEdit_Value->text());
|
value = QVariant(ui->lineEdit_Value->text());
|
||||||
} else if (type == "Number") {
|
} else if (type == "Number") {
|
||||||
value = QJsonValue(ui->spinBox_Value->value());
|
value = QVariant(ui->spinBox_Value->value());
|
||||||
} else if (type == "Boolean") {
|
} else if (type == "Boolean") {
|
||||||
value = QJsonValue(ui->checkBox_Value->isChecked());
|
value = QVariant(ui->checkBox_Value->isChecked());
|
||||||
}
|
}
|
||||||
|
return value;
|
||||||
const QString key = ui->lineEdit_Name->text();
|
}
|
||||||
this->table->addNewAttribute(key, value);
|
|
||||||
|
void CustomAttributesDialog::addNewAttribute() {
|
||||||
if (ui->checkBox_Default->isChecked())
|
this->table->addNewAttribute(ui->lineEdit_Name->text(), QJsonValue::fromVariant(this->getValue()), ui->checkBox_Default->isChecked());
|
||||||
this->table->setDefaultAttribute(key, value);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,11 @@ enum Column {
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Tooltip-- "Custom fields will be added to the map.json file for the current map."?
|
|
||||||
// TODO: Fix squishing when first element is added
|
|
||||||
// TODO: Fix Header table size on first open
|
|
||||||
// TODO: Take control of Delete key?
|
|
||||||
// TODO: Edit history?
|
|
||||||
CustomAttributesTable::CustomAttributesTable(QWidget *parent) :
|
CustomAttributesTable::CustomAttributesTable(QWidget *parent) :
|
||||||
QFrame(parent)
|
QFrame(parent)
|
||||||
{
|
{
|
||||||
|
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
QLabel *label = new QLabel("Custom Attributes");
|
QLabel *label = new QLabel("Custom Attributes");
|
||||||
layout->addWidget(label);
|
layout->addWidget(label);
|
||||||
|
@ -72,9 +69,19 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) :
|
||||||
// Adding the "Selectable" flag to the Key cell changes its appearance to match the Value cell, which
|
// Adding the "Selectable" flag to the Key cell changes its appearance to match the Value cell, which
|
||||||
// makes it confusing that you can't edit the Key cell. To keep the uneditable appearance and allow
|
// makes it confusing that you can't edit the Key cell. To keep the uneditable appearance and allow
|
||||||
// deleting rows by selecting Key cells, we select the full row when a Key cell is selected.
|
// deleting rows by selecting Key cells, we select the full row when a Key cell is selected.
|
||||||
|
// Double clicking the Key cell will begin editing the value cell, as it would for double-clicking the value cell.
|
||||||
connect(this->table, &QTableWidget::cellClicked, [this](int row, int column) {
|
connect(this->table, &QTableWidget::cellClicked, [this](int row, int column) {
|
||||||
if (column == Column::Key) this->table->selectRow(row);
|
if (column == Column::Key) {
|
||||||
|
this->table->selectRow(row);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
connect(this->table, &QTableWidget::cellDoubleClicked, [this](int row, int column) {
|
||||||
|
if (column == Column::Key) {
|
||||||
|
auto index = this->table->model()->index(row, Column::Value);
|
||||||
|
this->table->edit(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// TODO: Right-click for context menu to set a default?
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttributesTable::~CustomAttributesTable()
|
CustomAttributesTable::~CustomAttributesTable()
|
||||||
|
@ -142,7 +149,7 @@ int CustomAttributesTable::addAttribute(const QString &key, QJsonValue value) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Overwrite existing key (if present)
|
// Overwrite existing key (if present)
|
||||||
if (this->m_keys.remove(key))
|
if (this->m_keys.contains(key))
|
||||||
this->removeAttribute(key);
|
this->removeAttribute(key);
|
||||||
|
|
||||||
// Add new row
|
// Add new row
|
||||||
|
@ -170,6 +177,7 @@ int CustomAttributesTable::addAttribute(const QString &key, QJsonValue value) {
|
||||||
spinBox->setMinimum(INT_MIN);
|
spinBox->setMinimum(INT_MIN);
|
||||||
spinBox->setMaximum(INT_MAX);
|
spinBox->setMaximum(INT_MAX);
|
||||||
spinBox->setValue(ParseUtil::jsonToInt(value));
|
spinBox->setValue(ParseUtil::jsonToInt(value));
|
||||||
|
// This connection will be handled by QTableWidget::cellChanged for other cell types
|
||||||
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), [this]() { emit this->edited(); });
|
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), [this]() { emit this->edited(); });
|
||||||
this->table->setCellWidget(rowIndex, Column::Value, spinBox);
|
this->table->setCellWidget(rowIndex, Column::Value, spinBox);
|
||||||
break;
|
break;
|
||||||
|
@ -194,9 +202,10 @@ int CustomAttributesTable::addAttribute(const QString &key, QJsonValue value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the user adding an attribute by interacting with the table
|
// For the user adding an attribute by interacting with the table
|
||||||
void CustomAttributesTable::addNewAttribute(const QString &key, QJsonValue value) {
|
void CustomAttributesTable::addNewAttribute(const QString &key, QJsonValue value, bool setAsDefault) {
|
||||||
int row = this->addAttribute(key, value);
|
int row = this->addAttribute(key, value);
|
||||||
if (row < 0) return;
|
if (row < 0) return;
|
||||||
|
if (setAsDefault) this->setDefaultAttribute(key, value);
|
||||||
this->table->selectRow(row);
|
this->table->selectRow(row);
|
||||||
this->resizeVertically();
|
this->resizeVertically();
|
||||||
}
|
}
|
||||||
|
@ -210,21 +219,25 @@ void CustomAttributesTable::setAttributes(const QMap<QString, QJsonValue> attrib
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomAttributesTable::setDefaultAttribute(const QString &key, QJsonValue value) {
|
void CustomAttributesTable::setDefaultAttribute(const QString &key, QJsonValue value) {
|
||||||
// TODO
|
m_defaultKeys.insert(key);
|
||||||
|
emit this->defaultSet(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomAttributesTable::unsetDefaultAttribute(const QString &key) {
|
void CustomAttributesTable::unsetDefaultAttribute(const QString &key) {
|
||||||
// TODO
|
if (m_defaultKeys.remove(key))
|
||||||
|
emit this->defaultRemoved(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomAttributesTable::removeAttribute(const QString &key) {
|
void CustomAttributesTable::removeAttribute(const QString &key) {
|
||||||
for (int row = 0; row < this->table->rowCount(); row++) {
|
for (int row = 0; row < this->table->rowCount(); row++) {
|
||||||
auto keyItem = this->table->item(row, Column::Key);
|
auto keyItem = this->table->item(row, Column::Key);
|
||||||
if (keyItem && keyItem->text() == key) {
|
if (keyItem && keyItem->text() == key) {
|
||||||
|
this->m_keys.remove(key);
|
||||||
this->table->removeRow(row);
|
this->table->removeRow(row);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No need to adjust size because this is (at the moment) only used for replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomAttributesTable::deleteSelectedAttributes() {
|
bool CustomAttributesTable::deleteSelectedAttributes() {
|
||||||
|
@ -243,7 +256,10 @@ bool CustomAttributesTable::deleteSelectedAttributes() {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (QPersistentModelIndex index : persistentIndexes) {
|
for (QPersistentModelIndex index : persistentIndexes) {
|
||||||
this->table->removeRow(index.row());
|
auto row = index.row();
|
||||||
|
auto item = this->table->item(row, Column::Key);
|
||||||
|
if (item) this->m_keys.remove(item->text());
|
||||||
|
this->table->removeRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->table->rowCount() > 0) {
|
if (this->table->rowCount() > 0) {
|
||||||
|
@ -257,10 +273,18 @@ QSet<QString> CustomAttributesTable::keys() const {
|
||||||
return this->m_keys;
|
return this->m_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSet<QString> CustomAttributesTable::defaultKeys() const {
|
||||||
|
return this->m_defaultKeys;
|
||||||
|
}
|
||||||
|
|
||||||
QSet<QString> CustomAttributesTable::restrictedKeys() const {
|
QSet<QString> CustomAttributesTable::restrictedKeys() const {
|
||||||
return this->m_restrictedKeys;
|
return this->m_restrictedKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CustomAttributesTable::setDefaultKeys(const QSet<QString> keys) {
|
||||||
|
this->m_defaultKeys = keys;
|
||||||
|
}
|
||||||
|
|
||||||
void CustomAttributesTable::setRestrictedKeys(const QSet<QString> keys) {
|
void CustomAttributesTable::setRestrictedKeys(const QSet<QString> keys) {
|
||||||
this->m_restrictedKeys = keys;
|
this->m_restrictedKeys = keys;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,9 @@ void EventFrame::setup() {
|
||||||
|
|
||||||
void EventFrame::initCustomAttributesTable() {
|
void EventFrame::initCustomAttributesTable() {
|
||||||
this->custom_attributes = new CustomAttributesTable(this);
|
this->custom_attributes = new CustomAttributesTable(this);
|
||||||
|
QStringList keys = projectConfig.getDefaultEventCustomAttributes(this->event->getEventType()).keys();
|
||||||
|
this->custom_attributes->setDefaultKeys(QSet<QString>(keys.begin(), keys.end()));
|
||||||
this->custom_attributes->setRestrictedKeys(this->event->getExpectedFields());
|
this->custom_attributes->setRestrictedKeys(this->event->getExpectedFields());
|
||||||
this->custom_attributes->setAttributes(this->event->getCustomValues());
|
|
||||||
this->layout_contents->addWidget(this->custom_attributes);
|
this->layout_contents->addWidget(this->custom_attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +139,15 @@ void EventFrame::connectSignals(MainWindow *) {
|
||||||
|
|
||||||
this->custom_attributes->disconnect();
|
this->custom_attributes->disconnect();
|
||||||
connect(this->custom_attributes, &CustomAttributesTable::edited, [this]() {
|
connect(this->custom_attributes, &CustomAttributesTable::edited, [this]() {
|
||||||
this->event->setCustomValues(this->custom_attributes->getAttributes());
|
this->event->setCustomAttributes(this->custom_attributes->getAttributes());
|
||||||
this->event->modify();
|
this->event->modify();
|
||||||
});
|
});
|
||||||
|
connect(this->custom_attributes, &CustomAttributesTable::defaultSet, [this](QString key, QJsonValue value) {
|
||||||
|
projectConfig.insertDefaultEventCustomAttribute(this->event->getEventType(), key, value);
|
||||||
|
});
|
||||||
|
connect(this->custom_attributes, &CustomAttributesTable::defaultRemoved, [this](QString key) {
|
||||||
|
projectConfig.removeDefaultEventCustomAttribute(this->event->getEventType(), key);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventFrame::initialize() {
|
void EventFrame::initialize() {
|
||||||
|
@ -152,6 +159,8 @@ void EventFrame::initialize() {
|
||||||
this->spinner_y->setValue(this->event->getY());
|
this->spinner_y->setValue(this->event->getY());
|
||||||
this->spinner_z->setValue(this->event->getZ());
|
this->spinner_z->setValue(this->event->getZ());
|
||||||
|
|
||||||
|
this->custom_attributes->setAttributes(this->event->getCustomAttributes());
|
||||||
|
|
||||||
this->label_icon->setPixmap(this->event->getPixmap());
|
this->label_icon->setPixmap(this->event->getPixmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,7 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
||||||
if (projectConfig.getFloorNumberEnabled()) {
|
if (projectConfig.getFloorNumberEnabled()) {
|
||||||
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
|
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
|
||||||
}
|
}
|
||||||
|
newMap->customHeaders = projectConfig.getDefaultMapCustomAttributes();
|
||||||
|
|
||||||
newMap->layout = layout;
|
newMap->layout = layout;
|
||||||
newMap->layoutId = layout->id;
|
newMap->layoutId = layout->id;
|
||||||
|
|
Loading…
Reference in a new issue