Editor/TypeSelectorAttribute.cs
using System;
using System.Collections.Generic;
using Editor;
using Sandbox;
using Sandbox.Diagnostics;

namespace TheDimin
{
	namespace Internal
	{
		sealed class ResourceTypeControlWidget : DropdownControlWidget<object>
		{
			private Type _BaseType;

			public ResourceTypeControlWidget( SerializedProperty property, Type baseType ) : base( property )
			{
				_BaseType = baseType;
			}


			protected override IEnumerable<object> GetDropdownValues()
			{
				List<object> list = new();

				foreach ( var type in TypeLibrary.GetTypes( _BaseType ) )
				{
					if ( !type.IsAbstract )
					{
						list.Add( new Entry() { Value = type.Create<object>(), Label = type.Name } );
					}
				}

				return list;
			}
		}
	}

	[CustomEditor( typeof(object), WithAllAttributes = new[] { typeof(TypeSelectorAttribute) } )]
	public class TypeSelectCW : ControlWidget
	{
		// Whether or not this control supports multi-editing (if you have multiple GameObjects selected)
		public override bool SupportsMultiEdit => true;

		private ControlSheet _controlSheet = null;

		public TypeSelectCW( SerializedProperty property ) : base( property )
		{
			Layout = Layout.Column();
			Layout.Spacing = 2;
			_controlSheet = new ControlSheet();

			SerializedProperty.TryGetAttribute<TypeSelectorAttribute>( out var b );


			var rtcw = new TheDimin.Internal.
				ResourceTypeControlWidget( SerializedProperty, SerializedProperty.PropertyType );

			var t = Layout.Add( rtcw );

			Layout.AddLayout( _controlSheet );

			ReDraw();
		}

		protected override void OnValueChanged()
		{
			base.OnValueChanged();
			ReDraw();
		}

		private void ReDraw()
		{
			var task = SerializedProperty.GetValue<object>();

			if ( task != null )
			{
				var serializedTask = task.GetSerialized();

				_controlSheet?.Clear( true );
				_controlSheet?.AddObject( serializedTask );
				serializedTask.OnPropertyChanged += property =>
				{
					SerializedProperty.SetValue( SerializedProperty.GetValue<object>() );
				};
			}
		}

		/// <inheritdoc />
		protected override void OnPaint()
		{
			//base.OnPaint();
		}
	}
}