From f40b3d162da708e77bea2836701b867060ce9f6d Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 27 Jul 2022 22:43:50 +0300 Subject: [PATCH] Code to support effects ini version 2 (#813) * Code to support effects ini version 2 * Update theme commit * Get it to actually work properly * Rework effect loading code * Added auto-migration to new format * Reorganised code for improved readability and clarity * Add functional checks for operation to not run into missing file issues * Minor logic fix * Add debug message * Trim any empty items from the list * Add mandatory culling * See https://discord.com/channels/278529040497770496/323377366997008394/998661402669617233 * Reworked implementation * Resolve warning of temporary container allocation * Unbreak what I broke last commit * Also make it a QStringLiteral to cheat clazy. * Set default layer * Ignore that for realization, that one covers the screen. * Document migration regex * This should clarify the ambiguity of its functionality and reason why it exists. Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com> Co-authored-by: TrickyLeifa --- base/themes | 2 +- include/aoutils.h | 15 +++++++ src/aoutils.cpp | 87 +++++++++++++++++++++++++++++++++++++ src/courtroom.cpp | 9 +--- src/text_file_functions.cpp | 75 ++++++++++++++++++++++++-------- 5 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 include/aoutils.h create mode 100644 src/aoutils.cpp diff --git a/base/themes b/base/themes index 413411a..859f59b 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit 413411ae0f421066bb9c605d6757fa2cf588d7d7 +Subproject commit 859f59b5d441fbf6c4d992a1af3ece35f1b0e946 diff --git a/include/aoutils.h b/include/aoutils.h new file mode 100644 index 0000000..a4fd7bb --- /dev/null +++ b/include/aoutils.h @@ -0,0 +1,15 @@ +#ifndef AOUTILS_H +#define AOUTILS_H + +#include + +namespace AOUtils +{ +/** + * @brief Migrates the effects from the old format to version 2. + * @param QSettings object reference of the old effects.ini + */ +void migrateEffects(QSettings &p_fileName); +}; + +#endif // AOUTILS_H diff --git a/src/aoutils.cpp b/src/aoutils.cpp new file mode 100644 index 0000000..ee2e90b --- /dev/null +++ b/src/aoutils.cpp @@ -0,0 +1,87 @@ +#include "aoutils.h" + +#include +#include +#include +#include +#include +#include + +void AOUtils::migrateEffects(QSettings &p_effects_ini) +{ + qDebug() << "Migrating effects from file:" << p_effects_ini.fileName(); + + QMap l_effect_map; + { + const QStringList l_key_list = p_effects_ini.childKeys(); + for (const QString &i_key : l_key_list) + { + l_effect_map.insert(i_key, p_effects_ini.value(i_key).toString()); + } + + p_effects_ini.clear(); + p_effects_ini.sync(); + } + // update revision + p_effects_ini.beginGroup("version"); + p_effects_ini.setValue("major", "2"); + p_effects_ini.endGroup(); + + const QStringList l_property_list{ + "sound", + "scaling", + "stretch", + "ignore_offset", + "under_chatbox", + }; + + const QMap> l_property_replacement_list{ + {"under_chatbox", {"layer", "character"}}, + }; + + QStringList l_key_list; + // Matches old effects.ini childKeys that are not the effect name, but a property that applies to an effect. + // This is due to the name also being used as a key to apply the sfx property. + // Example : + // realization_scaling - This would not be appended to the key_list as it matches scaling property. + // realization_alt - This would be appened as it contains an underscore, but not a property. + // hearts - This would be appended as it does not contain a property + const QRegularExpression l_regex(QStringLiteral("(\\w+)_(%1)$").arg(l_property_list.join("|"))); + for (auto i = l_effect_map.begin(); i != l_effect_map.end(); i++) + { + if (l_regex.match(i.key()).hasMatch()) + { + continue; + } + l_key_list.append(i.key()); + } + + int i = 0; + for (const QString &i_effect_key : qAsConst(l_key_list)) + { + p_effects_ini.beginGroup(QString::number(i++)); + p_effects_ini.setValue("name", i_effect_key); + p_effects_ini.setValue("sound", l_effect_map.value(i_effect_key)); + p_effects_ini.setValue("cull", true); + p_effects_ini.setValue("layer", "character"); + + if (i_effect_key == "realization") { + p_effects_ini.setValue("stretch", true); + p_effects_ini.setValue("layer", "chat"); + } + + for (const QString &i_property : l_property_list) + { + const QString l_property_key = QString("%1_%2").arg(i_effect_key, i_property); + if (l_effect_map.contains(l_property_key)) + { + const QString l_property_value = l_effect_map.value(l_property_key); + const auto [l_converted_key, l_converted_value] = l_property_replacement_list.value(i_property, {i_property, l_property_value}); + p_effects_ini.setValue(l_converted_key, l_converted_value); + } + } + + p_effects_ini.endGroup(); + } + p_effects_ini.sync(); +} diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fdb1613..f39ec82 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -4676,14 +4676,7 @@ void Courtroom::set_effects_dropdown() return; } QStringList effectslist; - QStringList char_effects = ao_app->get_effects(current_char); - for (int i = 0; i < char_effects.size(); ++i) { - QString effect = char_effects[i]; - if (effect.contains(":")) { - effect = effect.section(':', 1); - } - effectslist.append(effect); - } + effectslist.append(ao_app->get_effects(current_char)); if (effectslist.empty()) { ui_effects_dropdown->hide(); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index ee6db6b..f1e1fbb 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -1,4 +1,5 @@ #include "text_file_functions.h" +#include "aoutils.h" QString AOApplication::read_theme() { @@ -900,22 +901,61 @@ int AOApplication::get_text_delay(QString p_char, QString p_emote) QStringList AOApplication::get_effects(QString p_char) { - QString p_misc = read_char_ini(p_char, "effects", "Options"); - QString p_path = get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, ""); - QString p_misc_path = get_asset("effects.ini", current_theme, get_subtheme(), default_theme, p_misc); - QSettings effects_config(p_path, QSettings::IniFormat); - effects_config.setIniCodec("UTF-8"); - QStringList effects = effects_config.childGroups(); - std::sort(effects.begin(), effects.end(), [] (const QString &a, const QString &b) {return a.split(":")[0].toInt() < b.split(":")[0].toInt();}); - if (p_path != p_misc_path) { - // If misc path is different from default path, stack the new miscs on top of the defaults - QSettings effects_config_misc(p_misc_path, QSettings::IniFormat); - effects_config_misc.setIniCodec("UTF-8"); - QStringList misc_effects = effects_config_misc.childGroups(); - std::sort(misc_effects.begin(), misc_effects.end(), [] (const QString &a, const QString &b) {return a.split(":")[0].toInt() < b.split(":")[0].toInt();}); - effects += misc_effects; + const QStringList l_filepath_list{ + get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, ""), + get_asset("effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options")), + }; + + QStringList l_effect_name_list; + for (const QString &i_filepath : l_filepath_list) + { + if (!QFile::exists(i_filepath)) + { + continue; + } + + QSettings l_effects_ini(i_filepath, QSettings::IniFormat); + l_effects_ini.setIniCodec("UTF-8"); + + // port legacy effects + if (!l_effects_ini.contains("version/major") || l_effects_ini.value("version/major").toInt() < 2) + { + AOUtils::migrateEffects(l_effects_ini); + } + + QStringList l_group_list; + for (const QString &i_group : l_effects_ini.childGroups()) + { + bool l_result; + i_group.toInt(&l_result); + if (l_result) + { + l_group_list.append(i_group); + } + } + + std::sort(l_group_list.begin(), l_group_list.end(), [](const QString &lhs, const QString &rhs) { + return lhs.toInt() < rhs.toInt(); + }); + + for (const QString &i_group : qAsConst(l_group_list)) + { + const QString l_key = i_group + "/name"; + if (!l_effects_ini.contains(l_key)) + { + continue; + } + + const QString l_effect_name = l_effects_ini.value(l_key).toString(); + if (l_effect_name.isEmpty()) + { + continue; + } + + l_effect_name_list.append(l_effect_name); + } } - return effects; + return l_effect_name_list; } QString AOApplication::get_effect(QString effect, QString p_char, @@ -949,10 +989,7 @@ QString AOApplication::get_effect_property(QString fx_name, QString p_char, settings.setIniCodec("UTF-8"); QStringList char_effects = settings.childGroups(); for (int i = 0; i < char_effects.size(); ++i) { - QString effect = char_effects[i]; - if (effect.contains(":")) { - effect = effect.section(':', 1); - } + QString effect = settings.value(char_effects[i] + "/name").toString(); if (effect.toLower() == fx_name.toLower()) { f_result = settings.value(char_effects[i] + "/" + p_property).toString(); if (!f_result.isEmpty()) {