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.
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" );
}
}