fix preset system

This commit is contained in:
XtraCube committed 2025-05-02 14:54:42 -04:00
1 parent a96ffc42f2
commit 68f40a96b7
5 files changed
+234 -171

No files matched your search

+12
View File
@@ -90,4 +90,16 @@ public interface IModdedOption
/// <param name="presetConfig">The ConfigFile representing the preset configuration.</param>
/// <param name="saveDefault">Indicates whether to save the default value instead of the current value.</param>
void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false);
/// <summary>
/// Binds the option to a configuration file.
/// </summary>
/// <param name="config">The ConfigFile to bind the option to.</param>
void Bind(ConfigFile config);
/// <summary>
/// Loads the option from a preset configuration file, applying the values to the option's configuration.
/// </summary>
/// <param name="presetConfig">The ConfigFile representing the preset configuration.</param>
void LoadFromPreset(ConfigFile presetConfig);
}
@@ -136,6 +136,25 @@ public abstract class ModdedOption<T> : IModdedOption
presetConfig[ConfigDefinition].BoxedValue = value;
}
/// <inheritdoc />
public void Bind(ConfigFile config)
{
config.Bind(ConfigDefinition, DefaultValue);
}
/// <inheritdoc />
public void LoadFromPreset(ConfigFile presetConfig)
{
if (presetConfig.TryGetEntry(ConfigDefinition, out ConfigEntry<T> entry))
{
SetValue(entry.Value);
}
else
{
Logger<MiraApiPlugin>.Error($"Attempted to load {Title} from preset, but ConfigDefinition is not found in preset.");
}
}
/// <inheritdoc />
public abstract float GetFloatData();
+189 -163
View File
@@ -3,7 +3,6 @@ using System.IO;
using System.Linq;
using BepInEx.Configuration;
using HarmonyLib;
using MiraAPI.Hud;
using MiraAPI.PluginLoading;
using MiraAPI.Presets;
using MiraAPI.Utilities.Assets;
@@ -26,164 +25,10 @@ internal static class GamePresetsTabPatches
private static GameObject _presetHolder = null!;
private static GridArrange _arrange = null!;
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.Start))]
public static class GamePresetsTabStartPatch
{
// ReSharper disable once InconsistentNaming
public static void Postfix(GamePresetsTab __instance)
{
Logger<MiraApiPlugin>.Error("GamePresetsTab Start called");
var prefab = GameSettingMenu.Instance.GameSettingsButton;
if (prefab == null)
{
Logger<MiraApiPlugin>.Error("GameSettingsButton prefab is null");
return;
}
private static FileSystemWatcher? _watcher;
__instance.PresetDescriptionText.gameObject.GetComponent<TextTranslatorTMP>().Destroy();
private static readonly object Lock = new();
var oldDiv = __instance.transform.FindChild("DividerImage");
_newDivider = Object.Instantiate(oldDiv.gameObject, oldDiv.transform.parent);
_newDivider.transform.localPosition = new Vector3(1.85f, 0.13f, 0f);
_newDivider.transform.localScale = new Vector3(1.13f, 1, 1);
_newDivider.transform.localRotation = Quaternion.Euler(new Vector3(0, 0, 90));
// create the save button
var saveButton = Object.Instantiate(prefab, __instance.transform);
_saveButton = saveButton.gameObject;
_saveButton.gameObject.name = "SaveButton";
_saveButton.transform.localPosition = new Vector3(3.2f, 1.7f, -2);
// set the button text and alignment
var saveText = saveButton.buttonText;
saveText.text = "Save";
saveText.GetComponent<TextTranslatorTMP>().Destroy();
saveText.alignment = TextAlignmentOptions.Center;
saveText.transform.parent.localPosition = new Vector3(
-.525f,
saveText.transform.parent.localPosition.y,
saveText.transform.parent.localPosition.z);
DivideSize(saveButton.gameObject, 2f);
// Create refresh button
var refreshButton = Object.Instantiate(saveButton, __instance.transform);
_refreshButton = refreshButton.gameObject;
_refreshButton.name = "RefreshButton";
_refreshButton.transform.localPosition = new Vector3(2.85f, 1.1f, -2);
var icon = new GameObject("Sprite");
icon.transform.SetParent(refreshButton.transform);
icon.transform.localPosition = new Vector3(-0.47f, -0.08f, -5f);
icon.transform.localScale = new Vector3(0.5f, 0.5f, 1);
icon.layer = refreshButton.gameObject.layer;
var iconSpriteRend = icon.AddComponent<SpriteRenderer>();
iconSpriteRend.sprite = MiraAssets.RefreshIcon.LoadAsset();
DivideSize(refreshButton.gameObject, 2f);
refreshButton.buttonText.gameObject.Destroy();
var openFolderButton = Object.Instantiate(refreshButton, __instance.transform);
_folderButton = openFolderButton.gameObject;
_folderButton.name = "OpenFolderButton";
_folderButton.transform.localPosition = new Vector3(3.55f, 1.1f, -2);
var folderRend = openFolderButton.transform.FindChild("Sprite").gameObject.GetComponent<SpriteRenderer>();
folderRend.sprite = MiraAssets.FolderIcon.LoadAsset();
folderRend.transform.localScale = new Vector3(0.4f, 0.4f, 1);
openFolderButton.OnClick = new Button.ButtonClickedEvent();
openFolderButton.OnClick.AddListener(
(UnityAction)(() =>
{
var directory = Path.Join(PresetManager.PresetDirectory, GameSettingMenuPatches.SelectedMod?.PluginId ?? string.Empty);
Directory.CreateDirectory(directory);
Process.Start(
new ProcessStartInfo
{
FileName = directory,
UseShellExecute = true,
Verb = "open",
});
}));
// add the click event to save the preset
saveButton.OnClick = new Button.ButtonClickedEvent();
saveButton.OnClick.AddListener(
(UnityAction)(() =>
{
if (GameSettingMenuPatches.SelectedModIdx == 0)
{
return;
}
SavePresetPopup.CreatePopup(name =>
{
if (GameSettingMenuPatches.SelectedMod == null)
{
return;
}
if (name == string.Empty)
{
return;
}
var presetFile = new ConfigFile(
Path.Join(PresetManager.PresetDirectory, GameSettingMenuPatches.SelectedMod.PluginId, $"{name}.cfg"),
false);
foreach (var option in GameSettingMenuPatches.SelectedMod.InternalOptions.Where(x => x.IncludeInPreset))
{
option.SaveToPreset(presetFile);
}
presetFile.Save();
Refresh();
});
}));
// add the click event to refresh the presets
refreshButton.OnClick = new Button.ButtonClickedEvent();
refreshButton.OnClick.AddListener((UnityAction)Refresh);
_saveButton.SetActive(false);
_refreshButton.SetActive(false);
_folderButton.SetActive(false);
_newDivider.SetActive(false);
_presetHolder = new GameObject("PresetHolder");
_presetHolder.transform.SetParent(__instance.transform, false);
_presetHolder.transform.localScale = new Vector3(0.9f, 0.9f, 1);
_presetHolder.transform.localPosition = new Vector3(-1.9f, 1.7f, 0);
_arrange = _presetHolder.AddComponent<GridArrange>();
_arrange.Alignment = GridArrange.StartAlign.Right;
_arrange.CellSize = new Vector2(2.15f, -.55f);
_arrange.MaxColumns = 2;
var watcher = new FileSystemWatcher
{
Path = PresetManager.PresetDirectory,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
Filter = "*.cfg",
IncludeSubdirectories = true,
EnableRaisingEvents = true,
};
watcher.Changed += (_, _) => { Refresh(); };
}
private static void Refresh()
{
Logger<MiraApiPlugin>.Error("Refreshing presets");
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
PresetManager.LoadPresets(mod);
}
GameSettingMenu.Instance.ChangeTab(0, false); // refresh the tab
}
}
public static void DivideSize(GameObject obj, float amount)
{
foreach (var collider in obj.GetComponentsInChildren<Collider2D>(true))
@@ -206,7 +51,13 @@ internal static class GamePresetsTabPatches
// ReSharper disable once InconsistentNaming
public static void Postfix(GamePresetsTab __instance)
{
Logger<MiraApiPlugin>.Error("OnEnable called");
if (!GameSettingMenu.Instance)
{
return;
}
CreatePresetMenu(__instance);
__instance.StandardPresetButton.gameObject.SetActive(GameSettingMenuPatches.SelectedModIdx == 0);
__instance.SecondPresetButton.gameObject.SetActive(GameSettingMenuPatches.SelectedModIdx == 0);
@@ -232,7 +83,6 @@ internal static class GamePresetsTabPatches
{
_folderButton.SetActive(GameSettingMenuPatches.SelectedModIdx != 0);
}
if (_newDivider)
{
_newDivider.SetActive(GameSettingMenuPatches.SelectedModIdx != 0);
@@ -255,7 +105,6 @@ internal static class GamePresetsTabPatches
button.OnClick.AddListener(
(UnityAction)(() =>
{
Logger<MiraApiPlugin>.Error($"Loading preset {preset.Name}");
preset.LoadPreset();
}));
button.gameObject.SetActive(false);
@@ -264,7 +113,7 @@ internal static class GamePresetsTabPatches
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
foreach (var button in mod.Presets.Select(x=>x.PresetButton))
foreach (var button in mod.Presets.Select(x => x.PresetButton))
{
if (button != null)
{
@@ -272,6 +121,7 @@ internal static class GamePresetsTabPatches
}
}
}
_arrange.Start();
_arrange.ArrangeChilds();
}
@@ -285,7 +135,6 @@ internal static class GamePresetsTabPatches
{
Logger<MiraApiPlugin>.Error("OnDisable called");
// Hide the save and refresh buttons
if (_saveButton)
{
_saveButton.SetActive(false);
@@ -299,9 +148,14 @@ internal static class GamePresetsTabPatches
_folderButton.SetActive(false);
}
if (_newDivider)
{
_newDivider.SetActive(false);
}
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
foreach (var button in mod.Presets.Select(x=>x.PresetButton))
foreach (var button in mod.Presets.Select(x => x.PresetButton))
{
if (button != null)
{
@@ -311,4 +165,176 @@ internal static class GamePresetsTabPatches
}
}
}
public static void CreatePresetMenu(GamePresetsTab presetTab)
{
var prefab = GameSettingMenu.Instance.GameSettingsButton;
if (prefab == null)
{
Logger<MiraApiPlugin>.Error("GameSettingsButton prefab is null");
return;
}
var tmpTranslator = presetTab.PresetDescriptionText.gameObject.GetComponent<TextTranslatorTMP>();
if (tmpTranslator)
{
tmpTranslator.Destroy();
}
if (!_newDivider)
{
var oldDiv = presetTab.transform.FindChild("DividerImage");
_newDivider = Object.Instantiate(oldDiv.gameObject, oldDiv.transform.parent);
_newDivider.transform.localPosition = new Vector3(1.85f, 0.13f, 0f);
_newDivider.transform.localScale = new Vector3(1.13f, 1, 1);
_newDivider.transform.localRotation = Quaternion.Euler(new Vector3(0, 0, 90));
}
PassiveButton saveButton;
if (!_saveButton)
{
saveButton = Object.Instantiate(prefab, presetTab.transform);
_saveButton = saveButton.gameObject;
_saveButton.gameObject.name = "SaveButton";
_saveButton.transform.localPosition = new Vector3(3.2f, 1.7f, -2);
// set the button text and alignment
var saveText = saveButton.buttonText;
saveText.text = "Save";
saveText.GetComponent<TextTranslatorTMP>().Destroy();
saveText.alignment = TextAlignmentOptions.Center;
saveText.transform.parent.localPosition = new Vector3(
-.525f,
saveText.transform.parent.localPosition.y,
saveText.transform.parent.localPosition.z);
DivideSize(saveButton.gameObject, 2f);
saveButton.OnClick = new Button.ButtonClickedEvent();
saveButton.OnClick.AddListener(
(UnityAction)(() =>
{
if (GameSettingMenuPatches.SelectedModIdx == 0)
{
return;
}
SavePresetPopup.CreatePopup(
name =>
{
if (GameSettingMenuPatches.SelectedMod == null)
{
return;
}
if (name == string.Empty)
{
return;
}
var presetFile = new ConfigFile(
Path.Combine(
PresetManager.PresetDirectory,
GameSettingMenuPatches.SelectedMod.PluginId,
$"{name}.cfg"),
false);
foreach (var option in GameSettingMenuPatches.SelectedMod.InternalOptions.Where(
x => x.IncludeInPreset))
{
option.SaveToPreset(presetFile);
}
presetFile.Save();
Refresh();
});
}));
}
saveButton = _saveButton.GetComponent<PassiveButton>();
PassiveButton refreshButton;
if (!_refreshButton)
{
refreshButton = Object.Instantiate(saveButton, presetTab.transform);
_refreshButton = refreshButton.gameObject;
_refreshButton.name = "RefreshButton";
_refreshButton.transform.localPosition = new Vector3(2.85f, 1.1f, -2);
var icon = new GameObject("Sprite");
icon.transform.SetParent(refreshButton.transform);
icon.transform.localPosition = new Vector3(-0.47f, -0.08f, -5f);
icon.transform.localScale = new Vector3(0.5f, 0.5f, 1);
icon.layer = refreshButton.gameObject.layer;
var iconSpriteRend = icon.AddComponent<SpriteRenderer>();
iconSpriteRend.sprite = MiraAssets.RefreshIcon.LoadAsset();
DivideSize(refreshButton.gameObject, 2f);
refreshButton.buttonText.gameObject.Destroy();
refreshButton.OnClick = new Button.ButtonClickedEvent();
refreshButton.OnClick.AddListener((UnityAction)Refresh);
}
refreshButton = _refreshButton.GetComponent<PassiveButton>();
if (!_folderButton)
{
var openFolderButton = Object.Instantiate(refreshButton, presetTab.transform);
_folderButton = openFolderButton.gameObject;
_folderButton.name = "OpenFolderButton";
_folderButton.transform.localPosition = new Vector3(3.55f, 1.1f, -2);
var folderRend = openFolderButton.transform.FindChild("Sprite").gameObject.GetComponent<SpriteRenderer>();
folderRend.sprite = MiraAssets.FolderIcon.LoadAsset();
folderRend.transform.localScale = new Vector3(0.4f, 0.4f, 1);
openFolderButton.OnClick = new Button.ButtonClickedEvent();
openFolderButton.OnClick.AddListener(
(UnityAction)(() =>
{
var directory = Path.Combine(
PresetManager.PresetDirectory,
GameSettingMenuPatches.SelectedMod?.PluginId ?? string.Empty);
Directory.CreateDirectory(directory);
Process.Start(
new ProcessStartInfo
{
FileName = directory,
UseShellExecute = true,
Verb = "open",
});
}));
}
_saveButton.SetActive(false);
_refreshButton.SetActive(false);
_folderButton.SetActive(false);
_newDivider.SetActive(false);
if (!_presetHolder)
{
_presetHolder = new GameObject("PresetHolder");
_presetHolder.transform.SetParent(presetTab.transform, false);
_presetHolder.transform.localScale = new Vector3(0.9f, 0.9f, 1);
_presetHolder.transform.localPosition = new Vector3(-1.9f, 1.7f, 0);
_arrange = _presetHolder.AddComponent<GridArrange>();
_arrange.Alignment = GridArrange.StartAlign.Right;
_arrange.CellSize = new Vector2(2.15f, -.55f);
_arrange.MaxColumns = 2;
}
}
private static void Refresh()
{
lock (Lock)
{
Logger<MiraApiPlugin>.Error("Refreshing presets");
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
PresetManager.LoadPresets(mod);
}
GameSettingMenu.Instance.ChangeTab(0, false); // refresh the tab
}
}
}
+4 -4
View File
@@ -1,5 +1,4 @@
using System.Linq;
using BepInEx.Configuration;
using BepInEx.Configuration;
using MiraAPI.PluginLoading;
using UnityEngine;
@@ -54,9 +53,10 @@ public class OptionPreset
/// </summary>
public void LoadPreset()
{
foreach (var option in PresetConfig.Where(x=>PluginConfig.ContainsKey(x.Key)))
PresetConfig.Reload();
foreach (var option in Plugin.InternalOptions)
{
PluginConfig[option.Key].BoxedValue = option.Value.BoxedValue;
option.LoadFromPreset(PresetConfig);
}
}
}
+10 -4
View File
@@ -2,6 +2,7 @@
using System.Linq;
using BepInEx.Configuration;
using MiraAPI.PluginLoading;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.Presets;
@@ -14,17 +15,17 @@ public static class PresetManager
/// <summary>
/// Gets the directory where the presets are stored.
/// </summary>
public static string PresetDirectory { get; } = Path.Join(Application.persistentDataPath, "mira_presets");
public static string PresetDirectory { get; } = Path.GetFullPath("mira_presets", Application.persistentDataPath);
internal static void CreateDefaultPreset(MiraPluginInfo plugin)
{
var presetPath = Path.Join(PresetManager.PresetDirectory, plugin.PluginId);
var presetPath = Path.Combine(PresetDirectory, plugin.PluginId);
if (!Directory.Exists(presetPath))
{
Directory.CreateDirectory(presetPath);
}
var presetConfig = new ConfigFile(Path.Join(presetPath, "Default.cfg"), true);
var presetConfig = new ConfigFile(Path.Combine(presetPath, "Default.cfg"), false);
foreach (var option in plugin.InternalOptions.Where(x => x.IncludeInPreset))
{
@@ -54,7 +55,7 @@ public static class PresetManager
Directory.CreateDirectory(PresetDirectory);
}
var pluginPresetPath = Path.Join(PresetDirectory, plugin.PluginId);
var pluginPresetPath = Path.Combine(PresetDirectory, plugin.PluginId);
if (!Directory.Exists(pluginPresetPath))
{
Directory.CreateDirectory(pluginPresetPath);
@@ -62,8 +63,13 @@ public static class PresetManager
foreach (var file in Directory.GetFiles(pluginPresetPath, "*.cfg"))
{
Logger<MiraApiPlugin>.Info($"Loading preset file {file}");
var presetName = Path.GetFileNameWithoutExtension(file);
var presetConfig = new ConfigFile(file, true);
foreach (var option in plugin.InternalOptions.Where(x=>x.IncludeInPreset))
{
option.Bind(presetConfig);
}
plugin.InternalPresets.Add(new OptionPreset(presetName, plugin, presetConfig));
}
plugin.Presets = [.. plugin.InternalPresets];