Editor/PrefabUtility.cs
using Sandbox.Diagnostics;
using System.Text.Json.Nodes;
namespace Editor;
public static class PrefabUtility
{
public static GameObject CreateGameObject( PrefabFile prefabFile, GameObject parent = null )
{
Assert.NotNull( Game.ActiveScene, "No Active Scene" );
JsonObject json = prefabFile.RootObject;
//if ( template is PrefabScene prefabScene && prefabScene.Source is PrefabFile prefabFile )
//{
// json = prefabFile.RootObject;
//}
//else
//{
// json = template.Serialize();
//}
MakeGameObjectsUnique( json );
var go = new GameObject();
go.Deserialize( json );
go.SetPrefabSource( prefabFile.ResourcePath );
if ( parent != null )
{
go.Parent = parent;
}
return go;
}
/// <summary>
/// Find all "Id" guids, and replace them with new Guids.
/// This is used to make GameObject serializations unique, so when
/// you duplicate stuff, it copies over uniquely and keeps associations.
/// </summary>
public static void MakeGameObjectsUnique( JsonObject json )
{
Dictionary<Guid, Guid> translate = new();
//
// Find all guids with "Id" as their name. Add them to translate
// with a new target value.
//
Sandbox.Json.WalkJsonTree( json, ( k, v ) =>
{
if ( k != "Id" ) return v;
if ( v.TryGetValue<Guid>( out var guid ) )
{
translate[guid] = Guid.NewGuid();
}
return v;
} );
//
// Find every guid and translate them, but only if they're in our
// guid dictionary.
//
Sandbox.Json.WalkJsonTree( json, ( k, v ) =>
{
if ( !v.TryGetValue<Guid>( out var guid ) ) return v;
if ( !translate.TryGetValue( guid, out var updatedGuid ) ) return v;
return updatedGuid;
} );
}
}