mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 19:38:24 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
211 lines
5.9 KiB
C#
211 lines
5.9 KiB
C#
using System.Collections.ObjectModel;
|
|
using System.Text.Json.Nodes;
|
|
|
|
namespace Sandbox;
|
|
|
|
public partial class GameObject
|
|
{
|
|
/// <summary>
|
|
/// We are cloned from a prefab. Stop that.
|
|
/// </summary>
|
|
public void BreakFromPrefab()
|
|
{
|
|
if ( !IsOutermostPrefabInstanceRoot )
|
|
return;
|
|
|
|
PrefabInstanceData.ConvertTopLevelNestedToFullPrefabInstances( this );
|
|
|
|
ClearPrefabInstance();
|
|
}
|
|
|
|
public void UpdateFromPrefab()
|
|
{
|
|
if ( !IsPrefabInstance )
|
|
return;
|
|
|
|
if ( !IsPrefabInstanceRoot )
|
|
{
|
|
Clear();
|
|
return;
|
|
}
|
|
|
|
PrefabInstance.UpdateGameObjectFromPrefab( this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the GameObject of a prefab from file path
|
|
/// </summary>
|
|
public static GameObject GetPrefab( string prefabFilePath )
|
|
{
|
|
var prefabFile = ResourceLibrary.Get<PrefabFile>( prefabFilePath );
|
|
if ( prefabFile is null ) return default;
|
|
|
|
return SceneUtility.GetPrefabScene( prefabFile );
|
|
}
|
|
|
|
public string PrefabInstanceSource
|
|
{
|
|
get
|
|
{
|
|
return PrefabInstance?.PrefabSource;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This GameObject is part of a prefab instance.
|
|
/// </summary>
|
|
public bool IsPrefabInstance
|
|
{
|
|
get
|
|
{
|
|
if ( IsPrefabInstanceRoot ) return true;
|
|
if ( Parent is null ) return false;
|
|
|
|
return Parent.IsPrefabInstance;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This GameObject is the root of a prefab instance.
|
|
/// Returns true for regular instance roots and nested prefab instance roots.
|
|
/// </summary>
|
|
public bool IsPrefabInstanceRoot => _prefabInstanceData is not null && !IsPrefabCacheSceneRoot;
|
|
|
|
/// <summary>
|
|
/// Get the root of the prefab instance this GameObject is part of.
|
|
/// </summary>
|
|
internal GameObject PrefabInstanceRoot
|
|
{
|
|
get
|
|
{
|
|
return IsPrefabInstanceRoot ? this : Parent?.PrefabInstanceRoot;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the outermost prefab instance root of this GameObject.
|
|
/// This is the root of the prefab instance this GameObject is part of, or the root of the prefab instance this GameObject is nested in.
|
|
/// </summary>
|
|
internal GameObject OutermostPrefabInstanceRoot
|
|
{
|
|
get
|
|
{
|
|
Assert.True( IsPrefabInstance );
|
|
|
|
if ( Parent == null ) return this;
|
|
|
|
// Case 1: GameObject is inside a prefab but isn't the root
|
|
if ( IsPrefabInstance && !IsPrefabInstanceRoot ) return Parent.OutermostPrefabInstanceRoot;
|
|
|
|
// Case 2: GameObject is a prefab root but is nested inside another prefab
|
|
if ( IsPrefabInstanceRoot && Parent.IsPrefabInstance && IsNestedPrefabInstanceRoot ) return Parent.OutermostPrefabInstanceRoot;
|
|
|
|
// Otherwise, we've found the outermost prefab instance root
|
|
return this;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This GameObject is the root of a prefab instance and is not nested inside another prefab instance.
|
|
/// </summary>
|
|
internal bool IsOutermostPrefabInstanceRoot => IsPrefabInstanceRoot && OutermostPrefabInstanceRoot == this;
|
|
|
|
/// <summary>
|
|
/// This GameObject is the root of a nested prefab instance.
|
|
/// </summary>
|
|
internal bool IsNestedPrefabInstanceRoot => IsPrefabInstanceRoot && PrefabInstance.IsNested;
|
|
|
|
/// <summary>
|
|
/// Is this PrefabRoot the root of a prefab cache scene?
|
|
/// </summary>
|
|
internal bool IsPrefabCacheSceneRoot => this is PrefabCacheScene;
|
|
|
|
/// <summary>
|
|
/// The filename of the map this object is defined in.
|
|
/// </summary>
|
|
private string MapSource { get; set; }
|
|
|
|
// This should never have been public (maybe we did it for easy access from the editor?),
|
|
// It is super easy to mess stuff up when using this incorrectly, even worse now with the new prefab system.
|
|
[Obsolete( "Stop using this, you will most likely mess something up." )]
|
|
public void SetPrefabSource( string prefabSource )
|
|
{
|
|
InitPrefabInstance( prefabSource, false );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes the instance data.
|
|
/// </summary>
|
|
internal void InitPrefabInstance( string prefabSource, bool isNested )
|
|
{
|
|
if ( string.IsNullOrEmpty( prefabSource ) )
|
|
{
|
|
_prefabInstanceData = null;
|
|
return;
|
|
}
|
|
|
|
// Added 12th Dec 2023
|
|
prefabSource = prefabSource.Replace( ".object", ".prefab", StringComparison.OrdinalIgnoreCase );
|
|
|
|
_prefabInstanceData = new PrefabInstanceData( prefabSource, this, isNested );
|
|
}
|
|
|
|
internal void ClearPrefabInstance()
|
|
{
|
|
_prefabInstanceData = null;
|
|
}
|
|
|
|
internal void SetMapSource( string mapSource )
|
|
{
|
|
MapSource = mapSource;
|
|
}
|
|
|
|
internal bool IsMapInstanceRoot => MapSource is not null;
|
|
|
|
/// <summary>
|
|
/// Access point for all prefab instance related data.
|
|
/// Can be accessed on both instance root and children contained within the instance.
|
|
/// For outermost prefab instances this will contain a patch and guid mappings.
|
|
/// For nested prefab instances this will just contain the prefab source.
|
|
/// </summary>
|
|
internal PrefabInstanceData PrefabInstance
|
|
{
|
|
get
|
|
{
|
|
return IsPrefabInstanceRoot ? _prefabInstanceData : Parent?.PrefabInstance;
|
|
}
|
|
}
|
|
PrefabInstanceData _prefabInstanceData = null;
|
|
|
|
/// <summary>
|
|
/// Defines objects within a scene hierarchy we want to track for prefab diffing and patching.
|
|
/// </summary>
|
|
internal static HashSet<Json.TrackedObjectDefinition> DiffObjectDefinitions =
|
|
[
|
|
Json.TrackedObjectDefinition.CreatePresenceBasedDefinition(
|
|
type: "GameObject",
|
|
requiredFields: [JsonKeys.Id, JsonKeys.Children, JsonKeys.Components, JsonKeys.Flags],
|
|
idProperty: JsonKeys.Id,
|
|
parentType: "GameObject",
|
|
allowedAsRoot: true,
|
|
ignoredProperties: [ JsonKeys.EditorPrefabInstanceNestedSource, JsonKeys.EditorSkipPrefabBreakOnRefresh ]
|
|
),
|
|
// Prefab Instances are GameObjects as well but have a different structure (children and components array can be omitted)
|
|
Json.TrackedObjectDefinition.CreatePresenceBasedDefinition(
|
|
type: "GameObject",
|
|
requiredFields: [JsonKeys.Id, JsonKeys.PrefabInstanceSource],
|
|
idProperty: JsonKeys.Id,
|
|
parentType: "GameObject",
|
|
allowedAsRoot: false,
|
|
atomic: true
|
|
),
|
|
Json.TrackedObjectDefinition.CreatePresenceBasedDefinition(
|
|
type: "Component",
|
|
requiredFields: [Component.JsonKeys.Id, Component.JsonKeys.Type, Component.JsonKeys.Enabled],
|
|
idProperty: Component.JsonKeys.Id,
|
|
parentType: "GameObject",
|
|
allowedAsRoot: true
|
|
),
|
|
];
|
|
}
|