Editor/ActionBasedSerializedProperty.cs
using Facepunch.ActionGraphs;
using Sandbox;
using Sandbox.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace ExtendedBox;
public sealed class ActionBasedSerializedProperty : SerializedProperty
{
public Func<SerializedProperty, SerializedObject>? PropertyToObject;
private readonly string _name;
private readonly string _title;
private readonly string _description;
private readonly string _groupName;
private readonly string _sourceFile;
private readonly int _sourceLine;
private readonly Func<object> _get;
private readonly Action<object> _set;
private readonly List<Attribute> _attributes;
private readonly SerializedObject _parent;
public override SerializedObject Parent => _parent;
public override bool IsMethod => false;
public override string Name => _name;
public override string DisplayName => _title;
public override string Description => _description;
public override string GroupName => _groupName;
public override bool IsEditable => true;
public override int Order => 0;
public override Type PropertyType { get; }
public override string SourceFile => _sourceFile;
public override int SourceLine => _sourceLine;
public override bool HasChanges => false;
public override ref AsAccessor As => ref base.As;
public ActionBasedSerializedProperty(Type type, string name, string title, string description, Func<object> get, Action<object> set, IEnumerable<Attribute> attributes, SerializedObject parent)
{
PropertyType = type;
_name = name;
_title = title;
_description = description;
_get = get;
_set = set;
_attributes = new List<Attribute>(attributes ?? []);
_parent = parent;
_groupName = _attributes.OfType<IGroupAttribute>().FirstOrDefault()?.Value ?? _groupName!;
_groupName = _attributes.OfType<ICategoryProvider>().FirstOrDefault()?.Value ?? _groupName;
_description = _attributes.OfType<IDescriptionAttribute>().FirstOrDefault()?.Value ?? _description;
_title = _attributes.OfType<ITitleProvider>().FirstOrDefault()?.Value ?? _title;
_sourceFile = _attributes.OfType<ISourcePathProvider>().FirstOrDefault()?.Path ?? _sourceFile!;
_sourceLine = _attributes.OfType<ISourceLineProvider>().FirstOrDefault()?.Line ?? _sourceLine;
}
public override U GetValue<U>(U defaultValue = default!)
{
return ValueToType<U>(_get());
}
public override void SetValue<U>(U value)
{
_set(ValueToType(PropertyType, value)!);
}
public override IEnumerable<Attribute> GetAttributes()
{
return _attributes;
}
public override bool TryGetAsObject(out SerializedObject obj)
{
obj = PropertyToObject?.Invoke(this) ?? null!;
return obj != null;
}
private object? ValueToType(Type targetType, object value, object? defaultValue = null)
{
try
{
if(value == null)
{
return GetDefaultValue();
}
if(value.GetType().IsAssignableTo(targetType))
return value;
if(targetType == typeof(string))
return Convert.ChangeType($"{value}", targetType);
if(value is string str)
return JsonSerializer.Deserialize(str, targetType);
if(targetType.IsEnum && value is IConvertible)
{
try
{
return Enum.ToObject(targetType, Convert.ToInt64(value));
}
catch
{
return GetDefaultValue();
}
}
object obj2 = Convert.ChangeType(value, targetType);
if(obj2 != null)
return obj2;
return JsonSerializer.SerializeToElement(value).Deserialize(targetType);
}
catch(Exception)
{
return GetDefaultValue();
}
object? GetDefaultValue()
{
if(defaultValue is null || !defaultValue.GetType().IsAssignableTo(targetType))
{
if(targetType.IsValueType)
return Activator.CreateInstance(targetType)!;
return null;
}
return defaultValue;
}
}
}