Asset type for Prism subgraph files (.prismfn). It declares hidden JSON sections that mirror the prism document structure, ensures serialization normalization, and provides an icon for the asset browser.
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" );
}
}