mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 11:28:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
186 lines
5.3 KiB
C#
186 lines
5.3 KiB
C#
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// An object (or data) that can be accessed as an object
|
|
/// </summary>
|
|
public class MultiSerializedObject : SerializedObject
|
|
{
|
|
List<SerializedObject> children = new List<SerializedObject>();
|
|
|
|
private static TResult SelectDistincSingleOrFallback<TSource, TResult>( IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult fallback )
|
|
{
|
|
// Last 2 elements is all we need to check if there is more than 2 we want to return fallback
|
|
var distinct = source.Select( selector ).Distinct().Take( 2 );
|
|
var isSingle = distinct.Count() == 1;
|
|
return isSingle ? distinct.FirstOrDefault() : fallback;
|
|
}
|
|
|
|
public override string TypeIcon => SelectDistincSingleOrFallback( children, x => x.TypeIcon, "multiple-icon" );
|
|
public override string TypeName => SelectDistincSingleOrFallback( children, x => x.TypeName, "MultipleTypes" );
|
|
public override string TypeTitle => SelectDistincSingleOrFallback( children, x => x.TypeTitle, "Multiple Objects" );
|
|
|
|
public override bool IsValid => children.Where( x => x.IsValid() ).Any();
|
|
|
|
public MultiSerializedObject()
|
|
{
|
|
PropertyList = new List<SerializedProperty>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add an object. Don't forget to rebuild after editing!
|
|
/// </summary>
|
|
public void Add( SerializedObject obj )
|
|
{
|
|
obj.OnPropertyChanged += p => OnPropertyChanged?.Invoke( p );
|
|
obj.OnPropertyPreChange += p => OnPropertyPreChange?.Invoke( p );
|
|
obj.OnPropertyStartEdit += p => OnPropertyStartEdit?.Invoke( p );
|
|
obj.OnPropertyFinishEdit += p => OnPropertyFinishEdit?.Invoke( p );
|
|
children.Add( obj );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rebuild the object after modifying. This updates PropertyList.
|
|
/// </summary>
|
|
public void Rebuild()
|
|
{
|
|
PropertyList.Clear();
|
|
|
|
SerializedProperty[] childProperties = children.SelectMany( x => x ).ToArray();
|
|
var groupedProperties = childProperties.GroupBy( x => x.Name ).ToArray();
|
|
|
|
foreach ( var group in groupedProperties )
|
|
{
|
|
if ( group.Count() == 1 )
|
|
{
|
|
PropertyList.Add( group.First() );
|
|
continue;
|
|
}
|
|
|
|
var msp = new MultiSerializedProperty( this, group.Select( x => x ) );
|
|
PropertyList.Add( msp );
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if the target is multiple objects
|
|
/// </summary>
|
|
public override bool IsMultipleTargets => children.Count > 1;
|
|
|
|
/// <summary>
|
|
/// A list of actual target objects - if applicable
|
|
/// </summary>
|
|
public override IEnumerable<object> Targets => children.Where( x => x.IsValid() ).SelectMany( x => x.Targets );
|
|
}
|
|
|
|
|
|
class MultiSerializedProperty : SerializedProperty
|
|
{
|
|
readonly List<SerializedProperty> properties;
|
|
readonly MultiSerializedObject parent;
|
|
|
|
public override SerializedObject Parent => parent;
|
|
|
|
public override string Name => properties.First().Name;
|
|
public override string DisplayName => properties.First().DisplayName;
|
|
public override string Description => properties.First().Description;
|
|
public override string GroupName => properties.First().GroupName;
|
|
public override int Order => properties.First().Order;
|
|
public override bool IsEditable => properties.First().IsEditable;
|
|
public override bool IsPublic => properties.First().IsPublic;
|
|
public override Type PropertyType => properties.First().PropertyType;
|
|
public override string SourceFile => properties.First().SourceFile;
|
|
public override int SourceLine => properties.First().SourceLine;
|
|
public override bool HasChanges => properties.First().HasChanges;
|
|
public override bool IsProperty => properties.First().IsProperty;
|
|
public override bool IsField => properties.First().IsField;
|
|
public override bool IsMethod => properties.First().IsMethod;
|
|
|
|
public override IEnumerable<Attribute> GetAttributes()
|
|
{
|
|
// TODO: maybe this should be attributes that all targets share?
|
|
return properties?.FirstOrDefault()?.GetAttributes() ?? base.GetAttributes();
|
|
}
|
|
|
|
public override bool TryGetAsObject( out SerializedObject obj )
|
|
{
|
|
var mso = new MultiSerializedObject();
|
|
int count = 0;
|
|
|
|
foreach ( var e in properties )
|
|
{
|
|
if ( e.TryGetAsObject( out var o ) )
|
|
{
|
|
mso.Add( o );
|
|
count++;
|
|
}
|
|
}
|
|
|
|
mso.Rebuild();
|
|
obj = mso;
|
|
|
|
return count > 0;
|
|
}
|
|
|
|
public MultiSerializedProperty( MultiSerializedObject parent, IEnumerable<SerializedProperty> enumerable )
|
|
{
|
|
this.parent = parent;
|
|
properties = enumerable.ToList();
|
|
}
|
|
|
|
public override T GetValue<T>( T defaultValue = default )
|
|
{
|
|
return properties.First().GetValue<T>( defaultValue );
|
|
}
|
|
|
|
public override void SetValue<T>( T value )
|
|
{
|
|
NotePreChange();
|
|
|
|
foreach ( var prop in properties )
|
|
{
|
|
prop.SetValue( value );
|
|
}
|
|
|
|
NoteChanged();
|
|
}
|
|
|
|
protected override void NoteStartEdit()
|
|
{
|
|
foreach ( var prop in properties )
|
|
{
|
|
prop.NoteStartEdit( prop );
|
|
}
|
|
}
|
|
|
|
internal override void NoteStartEdit( SerializedProperty childProperty )
|
|
{
|
|
foreach ( var prop in properties )
|
|
{
|
|
prop.NoteStartEdit( prop );
|
|
}
|
|
}
|
|
|
|
protected override void NoteFinishEdit()
|
|
{
|
|
foreach ( var prop in properties )
|
|
{
|
|
prop.NoteFinishEdit( prop );
|
|
}
|
|
}
|
|
|
|
internal override void NoteFinishEdit( SerializedProperty childProperty )
|
|
{
|
|
foreach ( var prop in properties )
|
|
{
|
|
prop.NoteFinishEdit( prop );
|
|
}
|
|
}
|
|
|
|
public override bool IsMultipleValues => properties.Count > 1;
|
|
|
|
public override bool IsMultipleDifferentValues => properties.Select( x => x.GetValue<object>() ).Distinct().Count() > 1;
|
|
|
|
public override IEnumerable<SerializedProperty> MultipleProperties => properties;
|
|
}
|