Editor/ShaderGraphPlus/ShaderGraphPlus.V12Upgrade.cs

An editor-side JSON upgrader for ShaderGraphPlus that migrates saved shader graph data to version 12. It converts parameter group references from GUIDs to group names, places ungrouped parameters into a "General" group, and rebuilds group data entries.

File Access
using System.Text.Json.Nodes;

namespace ShaderGraphPlus;

public partial class ShaderGraphPlus
{
	/// <summary>
	/// Changes : <br/>
	/// - Reference Groups by name on parameters instead of guid's.<br/>
	/// - Ungrouped parameters go into the "General" group.<br/>
	/// </summary>
	[SGPJsonUpgrader( typeof( ShaderGraphPlus ), 12 )]
	internal static void Upgrader_v12( JsonObject obj )
	{
		if ( obj[JsonKeys.ParameterArray] is not JsonArray oldParameterArray )
			throw new Exception( $"Cannot find jsonArray \"{JsonKeys.ParameterArray}\"" );

		if ( obj[JsonKeys.NodeArray] is not JsonArray oldNodeArray )
			throw new Exception( $"Cannot find jsonArray \"{JsonKeys.NodeArray}\"" );

		if ( obj[JsonKeys.OldGroupDataArray] is not JsonArray oldCategoryDataArray )
			throw new Exception( $"Cannot find jsonArray \"{JsonKeys.OldGroupDataArray}\"" );

		var isSubgraph = CheckIfSubgraph( obj );

		var gatheredCategories = new Dictionary<Guid, string>();

		foreach ( var jsonNode in oldCategoryDataArray )
		{
			if ( jsonNode[JsonKeys.Identifier] is not JsonValue identifierValue )
				continue;

			if ( jsonNode["Name"] is not JsonValue nameValue )
				continue;

			if ( !gatheredCategories.ContainsKey( identifierValue.GetValue<Guid>() ) )
			{
				gatheredCategories.Add( identifierValue.GetValue<Guid>(), nameValue.GetValue<string>() );
			}
		}

		//
		// Upgrade Parameters
		//

		var newParameterArray = new JsonArray();
		var groupsToAdd = new Dictionary<string, List<Guid>>();

		foreach ( var jsonNode in oldParameterArray )
		{
			if ( jsonNode[JsonKeys.Class] is not JsonValue classValue )
				continue;

			var typeName = classValue.GetValue<string>();
			var typeDesc = EditorTypeLibrary.GetType<BlackboardParameter>( typeName );
			var type = new ClassBlackboardParameterType( typeDesc );

			var newParameterObj = jsonNode.DeepClone().AsObject();

			if ( typeDesc != null )
			{
				if ( JsonUtils.GetPropertyValue( newParameterObj, "GroupReference", SerializerOptions(), Guid.Empty, out var groupReference ) && groupReference != Guid.Empty )
				{
					if ( gatheredCategories.TryGetValue( groupReference, out var groupName ) )
					{
						newParameterObj.Remove( "GroupReference" );
						newParameterObj.Remove( "Group" );
						newParameterObj.Add( "Group", groupName );
					}

					newParameterArray.Add( newParameterObj );
				}
				else
				{
					newParameterObj.Remove( "GroupReference" );
					newParameterObj.Remove( "Group" );
					newParameterObj.Add( "Group", "" );

					JsonUtils.GetPropertyValue( newParameterObj, JsonKeys.Identifier, SerializerOptions(), Guid.Empty, out var parameterReference );

					if ( !groupsToAdd.ContainsKey( "General" ) )
					{
						groupsToAdd.TryAdd( "General", [parameterReference] );
					}
					else
					{
						groupsToAdd["General"].Add( parameterReference );
					}


					newParameterArray.Add( newParameterObj );
				}
			}
		}

		//
		// Upgrade Groups
		//

		var newGroupDataArray = new JsonArray();

		foreach ( var group in groupsToAdd )
		{
			var groupDataJsonObj = new JsonObject
			{
				{ JsonKeys.Class, "GroupData" },
				{ "Identifier", Guid.NewGuid() },
				{ "Name", group.Key },
				{ "ParameterReferences", JsonSerializer.SerializeToNode( group.Value, SerializerOptions() ) }
			};

			newGroupDataArray.Add( groupDataJsonObj );
		}

		foreach ( var jsonNode in oldCategoryDataArray )
		{
			var groupDataJsonObj = jsonNode.DeepClone().AsObject();

			JsonUtils.UpdatePropertyValue( groupDataJsonObj, JsonKeys.Class, "GroupData", SerializerOptions() );
			groupDataJsonObj.Remove( "Priority" );

			newGroupDataArray.Add( groupDataJsonObj );
		}

		obj.Remove( JsonKeys.ParameterArray );
		obj.Add( JsonKeys.ParameterArray, newParameterArray );

		obj.Remove( JsonKeys.OldGroupDataArray );
		obj.Add( JsonKeys.GroupDataArray, newGroupDataArray );
	}
}