Code/Prism/PrismSubgraphFile.cs

Asset type class for Prism subgraph files (.prismfn). Defines hidden JSON-backed properties for document sections, normalizes the document on serialization, and provides an editor icon.

File Access
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace Sandbox.Prism;

/// <summary>
/// Registers the <c>.prismfn</c> extension with the asset system.
/// <para>
/// A subgraph — a reusable shader function authored as a graph and instanced inside other graphs.
/// Same rules as <see cref="PrismGraphFile"/>: no editable properties, no runtime load, and it must
/// live in the game assembly or every load and save fails silently.
/// </para>
/// <para>
/// This deliberately does not derive from <see cref="PrismGraphFile"/>. <c>AssetTypeAttribute</c> is
/// <c>IUninheritable</c>, and two independent types keep the two extensions independent in every
/// reflection sweep that walks the type library.
/// </para>
/// <para>
/// The section properties mirror <see cref="PrismGraphFile"/>'s and exist for the same reason: a
/// <c>GameResource</c> that serializes to less than it loaded overwrites the user's document when
/// anything outside Prism saves it. See <see cref="PrismGraphFile"/> for the full argument.
/// </para>
/// </summary>
[AssetType( Name = "Prism Subgraph", Extension = "prismfn", Category = "Shader",
	Flags = AssetTypeFlags.NoEmbedding, IconColor = "#4C8DFF" )]
public sealed class PrismSubgraphFile : GameResource
{
	/// <summary>Document schema version.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeySchema )]
	internal JsonNode SchemaSection { get; set; }

	/// <summary>Stable document id.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyId )]
	internal JsonNode IdSection { get; set; }

	/// <summary>Document kind — always <c>subgraph</c> here.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyKind )]
	internal JsonNode KindSection { get; set; }

	/// <summary>Authoring metadata.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyMeta )]
	internal JsonNode MetaSection { get; set; }

	/// <summary>Graph settings.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeySettings )]
	internal JsonNode SettingsSection { get; set; }

	/// <summary>Preview state.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyPreview )]
	internal JsonNode PreviewSection { get; set; }

	/// <summary>Blackboard parameters.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyParameters )]
	internal JsonNode ParametersSection { get; set; }

	/// <summary>Blackboard keywords.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyKeywords )]
	internal JsonNode KeywordsSection { get; set; }

	/// <summary>Every node in the subgraph.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyNodes )]
	internal JsonNode NodesSection { get; set; }

	/// <summary>Every connection.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyEdges )]
	internal JsonNode EdgesSection { get; set; }

	/// <summary>Node groups.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyGroups )]
	internal JsonNode GroupsSection { get; set; }

	/// <summary>Sticky notes.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyNotes )]
	internal JsonNode NotesSection { get; set; }

	/// <summary>Saved camera position and zoom.</summary>
	[Property, Hide, JsonPropertyName( PrismDocumentSkeleton.KeyView )]
	internal JsonNode ViewSection { get; set; }

	/// <summary>
	/// Give back exactly what was loaded, or an empty subgraph — one input node and one output node —
	/// when there was nothing to give back.
	/// </summary>
	protected override void OnJsonSerialize( JsonObject node )
	{
		PrismDocumentSkeleton.Normalize( node, true );
	}

	/// <summary>Asset-browser icon: Prism blue, distinct from a full graph at a glance.</summary>
	protected override Bitmap CreateAssetTypeIcon( int width, int height )
	{
		return CreateSimpleAssetTypeIcon( "functions", width, height, "#4C8DFF", "#EAF2FF" );
	}
}