Editor/Util/CustomSerializedProperty.cs
using Sandbox.Diagnostics;
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Panelize;
internal class CustomSerializedProperty : SerializedProperty
{
protected Type _type;
private readonly PropertyInfo _prop;
private readonly object _target;
private readonly DisplayInfo _info;
public CustomSerializedProperty( PropertyInfo prop, object target )
{
Assert.NotNull( target );
Assert.True( prop.CanRead );
_type = prop.PropertyType;
_prop = prop;
_target = target;
_info = DisplayInfo.ForMember( _prop );
InitProperties();
}
public CustomSerializedProperty( MemberExpression expression, object target )
{
Assert.NotNull( expression );
if ( expression.Member is not PropertyInfo prop )
throw new ArgumentException( "Member must be a property!" );
_type = expression.Type;
_prop = prop;
_target = target;
_info = DisplayInfo.ForMember( prop );
InitProperties();
}
protected void InitProperties()
{
CustomName = _prop.Name;
CustomTitle = string.IsNullOrEmpty(_info.Name) ? _prop.Name.ToTitleCase() : _info.Name;
CustomDescription = _info.Description;
CustomGroup = _info.Group;
CustomOrder = _info.Order;
EditableOverride = _info.Browsable && _prop.CanWrite;
}
public override SerializedObject Parent
{
get
{
if(EditorTypeLibrary.TryGetType(_target.GetType(), out var desc))
{
return EditorTypeLibrary.GetSerializedObject( _target );
}
return null;
}
}
public override bool IsProperty => true;
public override string Name => CustomName;
public override string DisplayName => CustomTitle;
public override string Description => CustomDescription;
public override string GroupName => CustomGroup;
public override int Order => CustomOrder;
public override bool IsEditable => EditableOverride;
public override Type PropertyType => _prop.PropertyType;
public override string SourceFile => default;
public override int SourceLine => default;
public override bool HasChanges => false;
public string CustomName;
public string CustomTitle;
public string CustomDescription;
public string CustomGroup;
public int CustomOrder;
public bool EditableOverride;
public Action<object> OnSetValue;
public override T GetValue<T>( T defaultValue = default )
{
try
{
return (T)ValueToType( typeof(T), _prop.GetValue( _target ), defaultValue );
}
catch
{
return defaultValue;
}
}
public override void SetValue<T>( T value )
{
try
{
_prop.SetValue( _target, ValueToType( _type, value ) );
OnSetValue?.Invoke( value );
}
catch
{
}
}
public override IEnumerable<Attribute> GetAttributes()
{
return _prop?.GetCustomAttributes() ?? base.GetAttributes();
}
public override bool TryGetAsObject( out SerializedObject obj )
{
if(EditorTypeLibrary.TryGetType(_target.GetType(), out var _))
{
obj = EditorTypeLibrary.GetSerializedObject( _target );
return true;
}
return base.TryGetAsObject( out obj );
}
protected object ValueToType( Type type, object value, object defaultValue = default )
{
try
{
if ( value == null )
{
return defaultValue;
}
if ( value.GetType().IsAssignableTo( type ) )
{
return value;
}
if ( type == typeof( string ) )
{
return $"{value}";
}
if ( value.GetType() == typeof( string ) )
{
return JsonSerializer.Deserialize( (string)value, type );
}
if ( type.IsEnum && value is IConvertible )
{
try
{
return Enum.ToObject( type, Convert.ToInt64( value ) );
}
catch
{
return defaultValue;
}
}
object converted = Convert.ChangeType( value, type );
if ( converted != null )
{
return converted;
}
return JsonSerializer.SerializeToElement( value ).Deserialize( type );
}
catch ( Exception )
{
return defaultValue;
}
}
}