Editor/EmededResourceEditorWidget.cs
using System;
using System.Linq;
using System.Reflection;
using Editor;
using Editor.Experimental;
using Editor.Inspectors;
using Sandbox;
using Sandbox.UI;
using Button = Editor.Button;

namespace ResourceEmbed.Editor;

[CustomEditor(typeof(GameResource), WithAllAttributes = new[] { typeof(EmbedAttribute) })]
public class EmbeddedResourceEditorWidget : ControlWidget
{
	public override bool SupportsMultiEdit => false;

	private Widget resourceProperty;
	private IconButton dropDownButton;
	private TrimmedAssetInspector inspector;
	private Guid GameObjectId;
	
	string ExpandedCookieString => $"embed_expand.{GameObjectId}.{SerializedProperty.Name}";

	/// <summary>
	/// The user's local preference to having this component expanded or not.
	/// </summary>
	bool ExpandedCookie
	{
		get => ProjectCookie.Get( ExpandedCookieString, true );
		set
		{
			// Don't bother storing the cookie if it's an expanded component
			if ( value )
			{
				ProjectCookie.Remove( ExpandedCookieString );
			}
			else
			{
				ProjectCookie.Set( ExpandedCookieString, value );
			}
		}
	}

	/// <summary>
	/// Is this component currently expanded?
	/// </summary>
	internal bool Expanded { get; set; } = true;

	/// <summary>
	/// Expands/shrinks the component in the component list.
	/// </summary>
	/// <param name="expanded"></param>
	internal void SetExpanded( bool expanded )
	{
		if (expanded)
			Layout.Margin = new Margin(0, 0, 0, 5);
		else
			Layout.Margin = new Margin(0, 0, 0, 0);
		
		Expanded = expanded;
		RebuildContent();
		ExpandedCookie = expanded; 
		dropDownButton.Icon = expanded ? "arrow_drop_down" : "arrow_left";
	}

	public EmbeddedResourceEditorWidget(SerializedProperty property) : base(property)
	{
		GameObjectId = property.Parent.Targets.OfType<Component>().Select( x => x.Id ).Single();
		
		Expanded = ExpandedCookie;
		
		Layout = Layout.Column();
		Layout.Spacing = 2;
		
		resourceProperty = CanEditAttribute.CreateEditorFor(property.PropertyType);
		resourceProperty.Layout = Layout.Row();
		resourceProperty.Layout.Alignment = TextFlag.Right;
		Layout.Add( resourceProperty );
		
		resourceProperty.Bind("Value").From(() =>
			{
				return SerializedProperty.GetValue<Resource>();
			},
			x =>
			{
				var oldValue = SerializedProperty.GetValue<Resource>();
				SerializedProperty.SetValue(x);

				if (x is null || oldValue is null)
				{
					RebuildContent();
					return;
				}

				if (inspector is not null)
				{
					inspector.Asset = AssetSystem.FindByPath( x.ResourcePath );
					inspector.RebuildUI();
				}
			});

		RebuildContent();
	}
	
	private void RebuildContent()
	{
		dropDownButton?.Destroy();
		inspector?.Destroy();
		
		var resource = SerializedProperty.GetValue<Resource>();
		
		if (resource is null)
			return;
		
		dropDownButton = new IconButton("expand_more", () => SetExpanded(!Expanded), resourceProperty);
		dropDownButton.FixedSize = resourceProperty.MinimumHeight;
		dropDownButton.IconSize = resourceProperty.MinimumHeight;
		resourceProperty.Layout.Add(dropDownButton); 
		
		var asset = AssetSystem.FindByPath(resource.ResourcePath);
		
		inspector = new TrimmedAssetInspector( asset.GetSerialized() );
		
		if (!Expanded)
			return;
		
		Layout.Add( inspector );
	}
}