2023-06-24 14:27:50 +02:00
using System.Collections.Generic ;
2023-06-24 16:43:10 +02:00
using System.IO ;
2023-06-26 01:03:14 +02:00
using System.Text.RegularExpressions ;
2023-06-24 14:27:50 +02:00
using UnityEditor ;
2023-06-24 16:43:10 +02:00
using UnityEditor.SceneManagement ;
2023-06-24 14:27:50 +02:00
using UnityEngine ;
2023-06-24 16:43:10 +02:00
using UnityEngine.SceneManagement ;
2023-06-24 14:27:50 +02:00
2023-06-24 16:43:10 +02:00
namespace VertexColor.ScenePartition.Editor
2023-06-24 14:27:50 +02:00
{
[CreateAssetMenu(fileName = "Scene", menuName = "Max/ScenePartitionSO")]
public class ScenePartitionSO : ScriptableObject
{
[field: SerializeField]
2023-06-26 01:03:14 +02:00
public SceneAsset SceneAsset { get ; private set ; } = null ;
public string SceneName = > SceneAsset = = null ? name : SceneAsset . name ;
2023-07-03 23:35:29 +02:00
public List < ulong > alwaysLoadIds = new List < ulong > { 0 , 1 , 2 , 3 , 4 } ;
2023-06-24 16:43:10 +02:00
2023-06-27 01:09:28 +02:00
public ScenePartitionData Data
2023-06-27 00:24:46 +02:00
{
get
{
2023-06-27 01:09:28 +02:00
// Load data from the ScriptableSingleton.
data ? ? = ScenePartitionSS . instance . GetScenePartitionData ( this ) ;
return data ;
2023-06-27 00:24:46 +02:00
}
}
2023-06-27 01:09:28 +02:00
private ScenePartitionData data = null ;
2023-06-27 00:24:46 +02:00
2023-06-24 16:43:10 +02:00
public void CreateScene ( )
{
2023-06-26 01:03:14 +02:00
if ( SceneAsset ! = null ) return ;
2023-06-24 16:43:10 +02:00
string scenePath = Path . Combine ( AssetDatabase . GetAssetPath ( this ) , $"../{this.name}.unity" ) ;
Scene scene = EditorSceneManager . NewScene ( NewSceneSetup . EmptyScene , NewSceneMode . Single ) ;
EditorSceneManager . SaveScene ( scene , scenePath ) ;
2023-06-27 00:24:46 +02:00
Save ( ) ;
2023-06-24 16:43:10 +02:00
2023-06-27 00:24:46 +02:00
AssetDatabase . SaveAssets ( ) ;
2023-06-24 16:43:10 +02:00
AssetDatabase . Refresh ( ) ;
2023-06-25 04:39:12 +02:00
2023-06-26 01:03:14 +02:00
SceneAsset = AssetDatabase . LoadAssetAtPath < SceneAsset > ( scenePath ) ;
2023-06-25 04:39:12 +02:00
AssetDatabase . SaveAssets ( ) ;
AssetDatabase . Refresh ( ) ;
2023-06-24 16:43:10 +02:00
}
2023-06-25 04:39:12 +02:00
/// <summary>
/// Load partitions from disk and construct the scene file.
/// </summary>
2023-06-24 16:43:10 +02:00
public void LoadAll ( )
2023-06-25 04:39:12 +02:00
{
CreateScenePartitions ( ) ;
2023-07-03 23:35:29 +02:00
SortedSet < ulong > ids = new SortedSet < ulong > ( Data . ScenePartitions . Keys ) ;
2023-06-25 04:39:12 +02:00
LoadScenePartitions ( ids ) ;
}
2023-06-27 01:09:28 +02:00
/// <summary>
2023-06-28 01:07:27 +02:00
/// Discard changes and reload loaded partitions.
2023-06-27 01:09:28 +02:00
/// </summary>
public void Reload ( )
{
if ( ! Data . HasLoadedPartitions ) return ;
2023-07-03 23:35:29 +02:00
LoadScenePartitions ( new SortedSet < ulong > ( Data . LoadedScenePartitions . Keys ) ) ;
2023-06-27 01:09:28 +02:00
}
2023-06-25 04:39:12 +02:00
private void CreateScenePartitions ( )
2023-06-24 16:43:10 +02:00
{
string dataPath = ScenePartitionUtils . GetDataPath ( this ) ;
2023-06-25 04:39:12 +02:00
string [ ] files = Directory . GetFiles ( dataPath ) ;
2023-06-27 01:09:28 +02:00
Data . ScenePartitions = new ScenePartitionSortedList ( ) ;
2023-06-25 04:39:12 +02:00
for ( int i = 0 ; i < files . Length ; i + + )
{
ScenePartition scenePartition = new ScenePartition ( files [ i ] ) ;
2023-06-27 01:09:28 +02:00
Data . ScenePartitions . Add ( scenePartition . id , scenePartition ) ;
2023-06-25 04:39:12 +02:00
}
}
2023-07-03 23:35:29 +02:00
private void LoadScenePartitions ( SortedSet < ulong > partitionIds )
2023-06-25 04:39:12 +02:00
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(LoadScenePartitions)}" ) )
{
if ( ! Data . HasCreatedPartitions ) return ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
string scenePath = ScenePartitionUtils . GetScenePath ( this ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
Data . LoadedScenePartitions . Clear ( ) ;
2023-06-25 04:39:12 +02:00
2023-07-16 19:58:37 +02:00
// Add always load ids.
SortedSet < ulong > baseIds = GetAlwaysLoadIds ( ) ;
foreach ( var id in baseIds )
{
partitionIds . Add ( id ) ;
}
2023-06-25 04:39:12 +02:00
2023-07-16 19:58:37 +02:00
// Clear file.
File . WriteAllText ( scenePath , string . Empty ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
// Create scene data.
try
{
using ( FileStream outputStream = new FileStream ( scenePath , FileMode . Append , FileAccess . Write ) )
{
foreach ( ulong id in partitionIds )
{
ScenePartition p = Data . ScenePartitions [ id ] ;
using ( FileStream inputStream = new FileStream ( p . filePath , FileMode . Open , FileAccess . Read ) )
{
byte [ ] buffer = new byte [ 4096 ] ;
int bytesRead ;
while ( ( bytesRead = inputStream . Read ( buffer , 0 , buffer . Length ) ) > 0 )
{
outputStream . Write ( buffer , 0 , bytesRead ) ;
}
}
Data . LoadedScenePartitions . Add ( p . id , p ) ;
}
}
}
catch ( System . Exception ex )
{
Debug . LogException ( ex ) ;
}
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
AssetDatabase . Refresh ( ) ;
}
2023-06-24 16:43:10 +02:00
}
2023-06-25 04:39:12 +02:00
/// <summary>
/// Convert scene to partitions and save them to disk.
/// </summary>
2023-06-25 15:51:54 +02:00
public void Save ( )
2023-06-24 16:43:10 +02:00
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(Save)}" ) )
{
DeleteLoadedPartitions ( ) ; // Delete the loaded partitions from disk so we can write the new ones.
2023-06-24 16:43:10 +02:00
2023-07-30 01:36:26 +02:00
const string objectIdPattern = @"&(\d+)" ;
2023-07-16 19:58:37 +02:00
string dataPath = ScenePartitionUtils . GetDataPath ( this ) ;
string scenePath = ScenePartitionUtils . GetScenePath ( this ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
// Read the data from the scene file.
string [ ] sceneData = File . ReadAllLines ( scenePath ) ;
2023-06-24 16:43:10 +02:00
2023-07-30 01:36:26 +02:00
Dictionary < ulong , string > sceneObjectNameById = GetSceneObjectNames ( in sceneData ) ;
2023-07-16 19:58:37 +02:00
// Split it into blocks.
int lastIndex = sceneData . Length ;
for ( int i = sceneData . Length - 1 ; i > = 0 ; i - - )
2023-06-24 16:43:10 +02:00
{
2023-07-16 19:58:37 +02:00
if ( sceneData [ i ] . StartsWith ( "---" ) ) // --- is the start of a new yaml document.
2023-06-26 01:03:14 +02:00
{
2023-07-30 01:36:26 +02:00
Match match = Regex . Match ( sceneData [ i ] , objectIdPattern ) ;
2023-06-26 01:03:14 +02:00
2023-07-16 19:58:37 +02:00
if ( match . Success )
{
// Extract the file number
string id = match . Groups [ 1 ] . Value ;
2023-07-30 01:36:26 +02:00
ulong objectId = ulong . Parse ( id ) ;
string extraInfo = "" ;
if ( TryGetObjectInfo ( in sceneData , in sceneObjectNameById , i , lastIndex , objectId , out string objectInfo ) )
{
extraInfo = $"-{objectInfo}" ;
}
2023-07-16 19:58:37 +02:00
// Write data to disk.
2023-07-30 01:36:26 +02:00
File . WriteAllLines ( $"{dataPath}/{SceneName}-{id}{extraInfo}.yaml" , sceneData [ i . . lastIndex ] ) ;
2023-07-16 19:58:37 +02:00
}
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
lastIndex = i ;
}
2023-06-24 16:43:10 +02:00
}
2023-07-16 19:58:37 +02:00
// Write header to disk.
File . WriteAllLines ( $"{dataPath}/{SceneName}.yaml" , sceneData [ 0. . lastIndex ] ) ;
}
2023-06-24 16:43:10 +02:00
}
2023-06-25 04:39:12 +02:00
/// <summary>
/// Empty the scene and save it (so it has no changes in source control).
/// </summary>
2023-06-24 16:43:10 +02:00
public void Unload ( )
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(Unload)}" ) )
{
string dataPath = ScenePartitionUtils . GetDataPath ( this ) ;
string scenePath = ScenePartitionUtils . GetScenePath ( this ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
Scene scene = EditorSceneManager . OpenScene ( scenePath , OpenSceneMode . Single ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
GameObject [ ] gameObjects = scene . GetRootGameObjects ( ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
for ( int i = gameObjects . Length - 1 ; i > = 0 ; i - - )
{
DestroyImmediate ( gameObjects [ i ] ) ;
}
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
EditorSceneManager . SaveScene ( scene ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
Data . LoadedScenePartitions . Clear ( ) ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
AssetDatabase . Refresh ( ) ;
}
2023-06-24 16:43:10 +02:00
}
private void DeleteLoadedPartitions ( )
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(DeleteLoadedPartitions)}" ) )
2023-06-24 16:43:10 +02:00
{
2023-07-16 19:58:37 +02:00
if ( ! Data . HasLoadedPartitions ) return ;
foreach ( KeyValuePair < ulong , ScenePartition > scenePartition in Data . LoadedScenePartitions )
{
if ( ! File . Exists ( scenePartition . Value . filePath ) ) continue ;
2023-06-24 16:43:10 +02:00
2023-07-16 19:58:37 +02:00
File . Delete ( scenePartition . Value . filePath ) ;
}
2023-06-24 16:43:10 +02:00
}
}
2023-06-24 14:27:50 +02:00
2023-07-03 23:35:29 +02:00
public void LoadPartitions ( ulong [ ] ids )
2023-06-24 14:27:50 +02:00
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(LoadPartitions)}" ) )
2023-06-24 14:27:50 +02:00
{
2023-07-16 19:58:37 +02:00
SortedSet < ulong > partitionIds = new SortedSet < ulong > ( ) ;
for ( int i = 0 ; i < ids . Length ; i + + )
2023-06-25 04:39:12 +02:00
{
2023-07-16 19:58:37 +02:00
SortedSet < ulong > connections = ScenePartitionUtils . FindDeeplyLinkedObjects ( Data . ScenePartitions , ids [ i ] ) ;
foreach ( ulong c in connections )
{
partitionIds . Add ( c ) ;
}
2023-06-25 04:39:12 +02:00
}
2023-07-16 19:58:37 +02:00
LoadScenePartitions ( partitionIds ) ;
}
2023-06-24 14:27:50 +02:00
}
2023-06-28 01:07:27 +02:00
2023-07-29 16:06:03 +02:00
public void LoadPartitionsAdditive ( ulong [ ] ids )
{
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(LoadPartitions)}" ) )
{
SortedSet < ulong > partitionIds = new SortedSet < ulong > ( ) ;
// Additive partitions to load.
for ( int i = 0 ; i < ids . Length ; i + + )
{
SortedSet < ulong > connections = ScenePartitionUtils . FindDeeplyLinkedObjects ( Data . ScenePartitions , ids [ i ] ) ;
foreach ( ulong c in connections )
{
partitionIds . Add ( c ) ;
}
}
// Partitions already loaded.
if ( Data . HasLoadedPartitions )
{
foreach ( KeyValuePair < ulong , ScenePartition > item in Data . LoadedScenePartitions )
{
partitionIds . Add ( item . Key ) ;
}
}
LoadScenePartitions ( partitionIds ) ;
}
}
2023-07-03 23:35:29 +02:00
private SortedSet < ulong > GetAlwaysLoadIds ( )
2023-06-28 01:07:27 +02:00
{
2023-07-03 23:35:29 +02:00
SortedSet < ulong > partitionIds = new SortedSet < ulong > ( ) ;
2023-06-30 03:28:44 +02:00
2023-07-03 23:35:29 +02:00
foreach ( ulong id in alwaysLoadIds )
2023-06-30 03:28:44 +02:00
{
2023-07-03 23:35:29 +02:00
SortedSet < ulong > connections = ScenePartitionUtils . FindDeeplyLinkedObjects ( Data . ScenePartitions , id ) ;
foreach ( ulong c in connections )
2023-06-30 03:28:44 +02:00
{
partitionIds . Add ( c ) ;
}
}
2023-06-28 01:07:27 +02:00
2023-06-30 03:28:44 +02:00
return partitionIds ;
}
public void GenerateSceneGridData ( )
{
2023-07-16 19:58:37 +02:00
using ( new ProfilerUtility . ProfilerScope ( $"{nameof(GenerateSceneGridData)}" ) )
2023-06-30 03:28:44 +02:00
{
2023-07-16 19:58:37 +02:00
LoadAll ( ) ;
if ( ! Data . HasCreatedPartitions ) return ;
Scene scene = EditorSceneManager . OpenScene ( ScenePartitionUtils . GetScenePath ( this ) , OpenSceneMode . Single ) ;
GameObject [ ] rootGameObjects = scene . GetRootGameObjects ( ) ;
Data . SceneGrid . Grid . Clear ( ) ;
//// Maybe later switch to getting the data from disk instead of loading the scene and then unloading it again.
//foreach (GameObject gameObject in rootGameObjects)
//{
// // https://forum.unity.com/threads/how-to-get-the-local-identifier-in-file-for-scene-objects.265686/
// PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
// SerializedObject serializedObject = new SerializedObject(gameObject.transform);
// inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
// SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile");
// long localId = localIdProp.longValue;
// if (localId == 0)
// {
// if (PrefabUtility.IsPartOfPrefabInstance(gameObject))
// {
// GlobalObjectId id = GlobalObjectId.GetGlobalObjectIdSlow(gameObject); // We could use this funtion for all objects. Might be a bit slower but is also simple.
// localId = long.Parse(id.targetPrefabId.ToString());
// Debug.Log($"{id.assetGUID} | {id.identifierType} | {id.targetObjectId} | {id.targetPrefabId}");
// if (id.targetObjectId == 0 && id.targetPrefabId == 0)
// {
// Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}");
// continue;
// }
// }
// else
// {
// Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}");
// continue;
// }
// }
// if (!Data.ScenePartitions.ContainsKey(localId))
// {
// Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}");
// continue;
// }
// Data.SceneGrid.Insert(localId, gameObject.transform.position);
//}
GlobalObjectId [ ] ids = new GlobalObjectId [ rootGameObjects . Length ] ;
GlobalObjectId . GetGlobalObjectIdsSlow ( rootGameObjects , ids ) ;
for ( int i = 0 ; i < ids . Length ; i + + )
2023-06-28 01:07:27 +02:00
{
2023-07-16 19:58:37 +02:00
//Debug.Log($"{ids[i].assetGUID} | {ids[i].identifierType} | {ids[i].targetObjectId} | {ids[i].targetPrefabId}");
if ( ids [ i ] . targetPrefabId = = 0 ) // 0 = no prefab.
{
Data . SceneGrid . Insert ( ids [ i ] . targetObjectId , rootGameObjects [ i ] . transform . position , ScenePartitionSceneViewEditor . cellSize ) ;
}
else
{
Data . SceneGrid . Insert ( ids [ i ] . targetPrefabId , rootGameObjects [ i ] . transform . position , ScenePartitionSceneViewEditor . cellSize ) ;
}
2023-06-28 01:07:27 +02:00
}
2023-07-16 19:58:37 +02:00
Unload ( ) ;
}
2023-06-28 01:07:27 +02:00
}
public void LoadCell ( int gridId )
{
2023-07-03 23:35:29 +02:00
if ( Data . SceneGrid . Grid . TryGetValue ( gridId , out GridList ids ) )
2023-06-28 01:07:27 +02:00
{
2023-07-03 23:35:29 +02:00
LoadPartitions ( ids . list . ToArray ( ) ) ;
2023-06-28 01:07:27 +02:00
}
}
2023-06-30 03:28:44 +02:00
2023-07-29 16:06:03 +02:00
public void LoadCellAdditive ( int gridId )
{
if ( Data . SceneGrid . Grid . TryGetValue ( gridId , out GridList ids ) )
{
LoadPartitionsAdditive ( ids . list . ToArray ( ) ) ;
}
}
2023-06-30 03:28:44 +02:00
public void ClearCache ( )
{
data = null ;
}
2023-07-30 01:36:26 +02:00
private Dictionary < ulong , string > GetSceneObjectNames ( in string [ ] sceneData )
{
using ProfilerUtility.ProfilerScope profilerScope = new ( nameof ( GetSceneObjectNames ) ) ;
Dictionary < ulong , string > sceneObjectNameById = new Dictionary < ulong , string > ( ) ;
const string objectIdPattern = @"&(\d+)" ;
int lastIndex = sceneData . Length ;
for ( int i = sceneData . Length - 1 ; i > = 0 ; i - - )
{
bool foundName = false ;
{ // GameObjects.
const string gameObjectHeaderPattern = "--- !u!1 &" ;
if ( ! foundName & & sceneData [ i ] . StartsWith ( gameObjectHeaderPattern ) )
{
Match match = Regex . Match ( sceneData [ i ] , objectIdPattern ) ;
if ( ! match . Success ) continue ;
if ( ! ulong . TryParse ( match . Groups [ 1 ] . Value , out ulong id ) ) continue ;
for ( int j = i ; j < lastIndex ; j + + )
{
const string namePattern = "m_Name: " ;
int nameStartIndex = sceneData [ j ] . LastIndexOf ( namePattern ) ;
if ( nameStartIndex < 0 ) continue ;
nameStartIndex + = namePattern . Length ;
string name = sceneData [ j ] [ nameStartIndex . . ] ;
sceneObjectNameById . Add ( id , name ) ;
foundName = true ;
break ;
}
}
}
{ // Prefabs.
const string prefabHeaderPattern = "--- !u!1001 &" ;
if ( ! foundName & & sceneData [ i ] . StartsWith ( prefabHeaderPattern ) )
{
Match match = Regex . Match ( sceneData [ i ] , objectIdPattern ) ;
if ( ! match . Success ) continue ;
if ( ! ulong . TryParse ( match . Groups [ 1 ] . Value , out ulong id ) ) continue ;
// Get name form property override in Scene.
for ( int j = i ; j < lastIndex ; j + + )
{
const string propertyPattern = "propertyPath: m_Name" ;
int propertyStartIndex = sceneData [ j ] . LastIndexOf ( propertyPattern ) ;
if ( propertyStartIndex < 0 ) continue ;
const string valuePattern = "value: " ;
int valueStartIndex = sceneData [ j + 1 ] . LastIndexOf ( valuePattern ) ;
if ( valueStartIndex < 0 ) continue ;
valueStartIndex + = valuePattern . Length ;
string name = sceneData [ j + 1 ] [ valueStartIndex . . ] ;
sceneObjectNameById . Add ( id , name ) ;
foundName = true ;
break ;
}
// Get name from prefab in AssetDatabase.
if ( ! foundName )
{
// Find the match using regex
const string guidPattern = @"guid:\s(\w+)" ;
Match guidMatch = Regex . Match ( sceneData [ lastIndex - 1 ] , guidPattern ) ;
if ( guidMatch . Success )
{
// Extract the GUID
string guid = guidMatch . Groups [ 1 ] . Value ;
string path = AssetDatabase . GUIDToAssetPath ( guid ) ;
string name = Path . GetFileNameWithoutExtension ( path ) ;
sceneObjectNameById . Add ( id , name ) ;
foundName = true ;
}
}
}
}
if ( sceneData [ i ] . StartsWith ( "---" ) )
{
lastIndex = i ;
continue ;
}
}
return sceneObjectNameById ;
}
private bool TryGetObjectTypeName ( string data , out string objectTypeName )
{
objectTypeName = data . Remove ( data . Length - 1 ) ;
return true ;
}
private bool TryGetObjectInfo ( in string [ ] sceneData , in Dictionary < ulong , string > sceneObjectNameById , int index , int lastIndex , ulong objectId , out string objectInfo )
{
using ProfilerUtility.ProfilerScope profilerScope = new ( nameof ( TryGetObjectInfo ) ) ;
objectInfo = "" ;
// Try get scene object name.
bool foundSceneObjectName = false ;
// If it is a gameObject or prefab try to get the name directly.
const string gameObjectHeaderPattern = "--- !u!1 &" ;
const string prefabHeaderPattern = "--- !u!1001 &" ;
if ( ! foundSceneObjectName & & sceneData [ index ] . StartsWith ( gameObjectHeaderPattern ) | | sceneData [ index ] . StartsWith ( prefabHeaderPattern ) )
{
if ( sceneObjectNameById . TryGetValue ( objectId , out string sceneObjectName ) )
{
objectInfo + = $"-{sceneObjectName}" ;
foundSceneObjectName = true ;
}
}
if ( ! foundSceneObjectName )
{
// Most components have a property that links to the GameObject.
for ( int j = index ; j < lastIndex ; j + + )
{
const string gameObjectPattern = @"m_GameObject:\s{fileID:\s(\d+)}" ;
// Find the match using regex
Match gameObjectMatch = Regex . Match ( sceneData [ j ] , gameObjectPattern ) ;
if ( ! gameObjectMatch . Success ) continue ;
if ( ulong . TryParse ( gameObjectMatch . Groups [ 1 ] . Value , out ulong fileNumber ) )
{
if ( fileNumber = = 0 ) break ; // 0 == nothing.
if ( ! sceneObjectNameById . TryGetValue ( fileNumber , out string sceneObjectName ) ) break ;
objectInfo + = $"-{sceneObjectName}" ;
foundSceneObjectName = true ;
}
break ;
}
}
if ( ! foundSceneObjectName )
{
// Some have a property that links to the PrefabInstance.
for ( int j = index ; j < lastIndex ; j + + )
{
const string prefabInstancePattern = @"m_PrefabInstance:\s{fileID:\s(\d+)}" ;
// Find the match using regex
Match prefabInstanceMatch = Regex . Match ( sceneData [ j ] , prefabInstancePattern ) ;
if ( ! prefabInstanceMatch . Success ) continue ;
if ( ulong . TryParse ( prefabInstanceMatch . Groups [ 1 ] . Value , out ulong fileNumber ) )
{
if ( fileNumber = = 0 ) break ; // 0 == nothing.
if ( ! sceneObjectNameById . TryGetValue ( fileNumber , out string sceneObjectName ) ) break ;
objectInfo + = $"-{sceneObjectName}" ;
foundSceneObjectName = true ;
}
break ;
}
}
bool foundObjectTypeName = false ;
// Try get object type name.
if ( TryGetObjectTypeName ( sceneData [ index + 1 ] , out string objectTypeName ) )
{
objectInfo + = $"-{objectTypeName}" ;
foundObjectTypeName = true ;
}
return foundSceneObjectName | | foundObjectTypeName ;
}
2023-06-24 14:27:50 +02:00
}
}