SHA256
Add Preset System
This commit is contained in:
7 files changed
+931
-151
No files matched your search
+203
-10
@@ -2,24 +2,118 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ADOFAIRenderer.Core.Data;
|
||||
using ADOFAIRenderer.Data;
|
||||
using MelonLoader;
|
||||
using MelonLoader.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ADOFAIRenderer.Data;
|
||||
namespace ADOFAIRenderer.Core;
|
||||
|
||||
internal class RenderPreset
|
||||
public class RenderPreset
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public RenderConfig Config { get; set; } = null!;
|
||||
|
||||
public RenderPreset Clone()
|
||||
{
|
||||
return new RenderPreset
|
||||
{
|
||||
Name = Name,
|
||||
Config = Config.Clone()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PresetManager
|
||||
public static class PresetManager
|
||||
{
|
||||
private static readonly List<RenderPreset> DefaultPresets = new()
|
||||
{
|
||||
new RenderPreset
|
||||
{
|
||||
Name = "FHD 60fps (1x)",
|
||||
Config = new RenderConfig
|
||||
{
|
||||
RenderWidth = 1920,
|
||||
RenderHeight = 1080,
|
||||
RenderFPS = 60,
|
||||
VideoFPS = 60,
|
||||
DelayAfterEnd = 15,
|
||||
ShowJudgementText = false,
|
||||
VideoConfig = new VideoEncodingConfig { Codec = Codec.H264, RateControlMode = RateControlMode.CBR, Bitrate = 20000, MaxBitrate = 35000, QP = 18, KeyframeInterval = 2.0 },
|
||||
AudioConfig = new AudioEncodingConfig { RenderAudio = true, AudioSampleRate = 48000, AudioChannels = 2, AudioBitrate = 256000 },
|
||||
AdvancedConfig = new AdvancedConfig { ProcessAudio = true, NonTile = false, FileExtension = "mkv" }
|
||||
}
|
||||
},
|
||||
new RenderPreset
|
||||
{
|
||||
Name = "FHD 60fps (4x)",
|
||||
Config = new RenderConfig
|
||||
{
|
||||
RenderWidth = 1920,
|
||||
RenderHeight = 1080,
|
||||
RenderFPS = 240,
|
||||
VideoFPS = 60,
|
||||
DelayAfterEnd = 15,
|
||||
ShowJudgementText = false,
|
||||
VideoConfig = new VideoEncodingConfig { Codec = Codec.H264, RateControlMode = RateControlMode.CBR, Bitrate = 30000, MaxBitrate = 50000, QP = 18, KeyframeInterval = 2.0 },
|
||||
AudioConfig = new AudioEncodingConfig { RenderAudio = true, AudioSampleRate = 48000, AudioChannels = 2, AudioBitrate = 256000 },
|
||||
AdvancedConfig = new AdvancedConfig { ProcessAudio = true, NonTile = false, FileExtension = "mkv" }
|
||||
}
|
||||
},
|
||||
new RenderPreset
|
||||
{
|
||||
Name = "QHD 60fps (4x)",
|
||||
Config = new RenderConfig
|
||||
{
|
||||
RenderWidth = 2560,
|
||||
RenderHeight = 1440,
|
||||
RenderFPS = 240,
|
||||
VideoFPS = 60,
|
||||
DelayAfterEnd = 15,
|
||||
ShowJudgementText = false,
|
||||
VideoConfig = new VideoEncodingConfig { Codec = Codec.H264, RateControlMode = RateControlMode.CBR, Bitrate = 35000, MaxBitrate = 60000, QP = 18, KeyframeInterval = 2.0 },
|
||||
AudioConfig = new AudioEncodingConfig { RenderAudio = true, AudioSampleRate = 48000, AudioChannels = 2, AudioBitrate = 256000 },
|
||||
AdvancedConfig = new AdvancedConfig { ProcessAudio = true, NonTile = false, FileExtension = "mkv" }
|
||||
}
|
||||
},
|
||||
new RenderPreset
|
||||
{
|
||||
Name = "4K 60fps (4x)",
|
||||
Config = new RenderConfig
|
||||
{
|
||||
RenderWidth = 3840,
|
||||
RenderHeight = 2160,
|
||||
RenderFPS = 240,
|
||||
VideoFPS = 60,
|
||||
DelayAfterEnd = 15,
|
||||
ShowJudgementText = false,
|
||||
VideoConfig = new VideoEncodingConfig { Codec = Codec.H264, RateControlMode = RateControlMode.CBR, Bitrate = 60000, MaxBitrate = 100000, QP = 18, KeyframeInterval = 2.0 },
|
||||
AudioConfig = new AudioEncodingConfig { RenderAudio = true, AudioSampleRate = 48000, AudioChannels = 2, AudioBitrate = 256000 },
|
||||
AdvancedConfig = new AdvancedConfig { ProcessAudio = true, NonTile = false, FileExtension = "mkv" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static string GetPresetsDirectory()
|
||||
{
|
||||
return Path.Combine(MelonEnvironment.GameRootDirectory, "UserData", "ADOFAIRenderer", "Presets");
|
||||
string? root = null;
|
||||
try
|
||||
{
|
||||
root = MelonEnvironment.GameRootDirectory;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Outside MelonLoader host environment (e.g. tests)
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(root))
|
||||
{
|
||||
root = AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
|
||||
return Path.Combine(root, "UserData", "ADOFAIRenderer", "Presets");
|
||||
}
|
||||
|
||||
private static string GetSafeFileName(string name)
|
||||
@@ -27,6 +121,45 @@ internal static class PresetManager
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
|
||||
public static void EnsureDefaultPresetsCreated()
|
||||
{
|
||||
try
|
||||
{
|
||||
var dir = GetPresetsDirectory();
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
if (!GlobalSettings.Current.DefaultPresetsInitialized)
|
||||
{
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
settings.Converters.Add(new ColorJsonConverter());
|
||||
|
||||
foreach (var def in DefaultPresets)
|
||||
{
|
||||
var safeName = GetSafeFileName(def.Name);
|
||||
var filePath = Path.Combine(dir, safeName + ".json");
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(def, settings);
|
||||
File.WriteAllText(filePath, json);
|
||||
}
|
||||
}
|
||||
|
||||
GlobalSettings.Current.DefaultPresetsInitialized = true;
|
||||
GlobalSettings.Save();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MelonLogger.Warning($"Error initializing default presets: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void SavePreset(string name, RenderConfig config)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
@@ -43,10 +176,16 @@ internal static class PresetManager
|
||||
var preset = new RenderPreset
|
||||
{
|
||||
Name = name,
|
||||
Config = config
|
||||
Config = config.Clone()
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(preset, Formatting.Indented);
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
settings.Converters.Add(new ColorJsonConverter());
|
||||
|
||||
string json = JsonConvert.SerializeObject(preset, settings);
|
||||
string safeName = GetSafeFileName(name);
|
||||
string filePath = Path.Combine(dir, safeName + ".json");
|
||||
File.WriteAllText(filePath, json);
|
||||
@@ -54,14 +193,26 @@ internal static class PresetManager
|
||||
|
||||
public static List<RenderPreset> GetPresets()
|
||||
{
|
||||
EnsureDefaultPresetsCreated();
|
||||
|
||||
var presets = new List<RenderPreset>();
|
||||
var dir = GetPresetsDirectory();
|
||||
|
||||
if (!Directory.Exists(dir)) return presets;
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
foreach (var b in DefaultPresets)
|
||||
{
|
||||
presets.Add(b.Clone());
|
||||
}
|
||||
return presets;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var files = Directory.GetFiles(dir, "*.json");
|
||||
var serializerSettings = new JsonSerializerSettings();
|
||||
serializerSettings.Converters.Add(new ColorJsonConverter());
|
||||
var serializer = JsonSerializer.Create(serializerSettings);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
try
|
||||
@@ -146,9 +297,20 @@ internal static class PresetManager
|
||||
}
|
||||
}
|
||||
|
||||
var preset = jObject.ToObject<RenderPreset>();
|
||||
if (preset != null && !string.IsNullOrEmpty(preset.Name))
|
||||
var preset = jObject.ToObject<RenderPreset>(serializer);
|
||||
if (preset != null)
|
||||
{
|
||||
var fileBaseName = Path.GetFileNameWithoutExtension(file);
|
||||
if (string.IsNullOrWhiteSpace(preset.Name))
|
||||
{
|
||||
preset.Name = fileBaseName;
|
||||
}
|
||||
|
||||
if (presets.Any(p => string.Equals(p.Name, preset.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
presets.Add(preset);
|
||||
}
|
||||
}
|
||||
@@ -177,13 +339,44 @@ internal static class PresetManager
|
||||
|
||||
public static void DeletePreset(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) return;
|
||||
|
||||
var dir = GetPresetsDirectory();
|
||||
if (!Directory.Exists(dir)) return;
|
||||
|
||||
var safeName = GetSafeFileName(name);
|
||||
var filePath = Path.Combine(dir, safeName + ".json");
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(dir, "*.json"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileBaseName = Path.GetFileNameWithoutExtension(file);
|
||||
if (string.Equals(fileBaseName, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
File.Delete(file);
|
||||
return;
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(file);
|
||||
var jObject = JsonConvert.DeserializeObject<JObject>(json);
|
||||
var pName = (string?)jObject?["Name"];
|
||||
if (string.Equals(pName, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
File.Delete(file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore read errors during cleanup search
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user