Files
sbox-public/game/editor/MovieMaker/Code/Extensions/FromThemeAttribute.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

122 lines
2.5 KiB
C#

using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace Editor.MovieMaker;
#nullable enable
public sealed class FromThemeAttribute : Attribute
{
public string? Key { get; init; }
private const string ThemePath = "/editor/moviemaker/assets/styles/theme.json";
private static IEnumerable<(PropertyInfo Property, string Key)> FindProperties()
{
foreach ( var type in typeof( MovieEditor ).Assembly.GetTypes() )
{
var staticProperties = type.GetProperties(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly );
foreach ( var property in staticProperties )
{
if ( property.GetCustomAttribute<FromThemeAttribute>() is not { } attrib )
{
continue;
}
var key = attrib.Key ?? GetDefaultKey( property );
yield return (property, key);
}
}
}
[ConCmd( "moviemaker_save_theme" )]
public static void Save()
{
var json = new JsonObject();
foreach ( var (property, key) in FindProperties().OrderBy( x => x.Key ) )
{
try
{
var value = property.GetValue( null );
if ( value is Color color )
{
json.TryAdd( key, color.Hex );
}
else
{
var valueString = JsonSerializer.Serialize( value, property.PropertyType, EditorJsonOptions );
json.TryAdd( key, valueString );
}
}
catch
{
//
}
}
FileSystem.Root.WriteAllText( ThemePath,
json.ToJsonString( new JsonSerializerOptions { WriteIndented = true } ) );
}
[ConCmd( "moviemaker_load_theme" )]
public static void Apply()
{
var themeJson = FileSystem.Root.ReadAllText( ThemePath );
if ( themeJson is null )
{
return;
}
var theme = Json.Deserialize<Dictionary<string, string>>( themeJson );
var hasMissingKeys = false;
foreach ( var (property, key) in FindProperties() )
{
if ( !theme.TryGetValue( key, out var valueString ) )
{
hasMissingKeys = true;
continue;
}
try
{
var value = property.PropertyType == typeof(Color)
? Color.Parse( valueString )!.Value
: Json.Deserialize( valueString, property.PropertyType );
property.SetValue( null, value );
}
catch ( Exception ex )
{
Log.Warning( ex, $"Couldn't set property \"{property}\" from theme." );
}
}
if ( hasMissingKeys )
{
Save();
}
}
private static string GetDefaultKey( PropertyInfo property )
{
var key = $"{property.DeclaringType?.Name}{property.Name}";
if ( key.EndsWith( "Color" ) )
{
key = key[..^"Color".Length];
}
return key;
}
}