SceneObjectNames & ObjectInfo

- Try to get the scene object names
- Try to get the object type
- Try to get create object info
This commit is contained in:
max 2023-07-30 01:36:26 +02:00
parent 40c49b076e
commit 83776072c9

View File

@ -141,28 +141,37 @@ public void Save()
{ {
DeleteLoadedPartitions(); // Delete the loaded partitions from disk so we can write the new ones. DeleteLoadedPartitions(); // Delete the loaded partitions from disk so we can write the new ones.
string pattern = @"&(\d+)"; const string objectIdPattern = @"&(\d+)";
string dataPath = ScenePartitionUtils.GetDataPath(this); string dataPath = ScenePartitionUtils.GetDataPath(this);
string scenePath = ScenePartitionUtils.GetScenePath(this); string scenePath = ScenePartitionUtils.GetScenePath(this);
// Read the data from the scene file. // Read the data from the scene file.
string[] sceneData = File.ReadAllLines(scenePath); string[] sceneData = File.ReadAllLines(scenePath);
Dictionary<ulong, string> sceneObjectNameById = GetSceneObjectNames(in sceneData);
// Split it into blocks. // Split it into blocks.
int lastIndex = sceneData.Length; int lastIndex = sceneData.Length;
for (int i = sceneData.Length - 1; i >= 0; i--) for (int i = sceneData.Length - 1; i >= 0; i--)
{ {
if (sceneData[i].StartsWith("---")) // --- is the start of a new yaml document. if (sceneData[i].StartsWith("---")) // --- is the start of a new yaml document.
{ {
Match match = Regex.Match(sceneData[i], pattern); Match match = Regex.Match(sceneData[i], objectIdPattern);
if (match.Success) if (match.Success)
{ {
// Extract the file number // Extract the file number
string id = match.Groups[1].Value; string id = match.Groups[1].Value;
ulong objectId = ulong.Parse(id);
string extraInfo = "";
if (TryGetObjectInfo(in sceneData, in sceneObjectNameById, i, lastIndex, objectId, out string objectInfo))
{
extraInfo = $"-{objectInfo}";
}
// Write data to disk. // Write data to disk.
File.WriteAllLines($"{dataPath}/{SceneName}-{id}.yaml", sceneData[i..lastIndex]); File.WriteAllLines($"{dataPath}/{SceneName}-{id}{extraInfo}.yaml", sceneData[i..lastIndex]);
} }
lastIndex = i; lastIndex = i;
@ -377,5 +386,190 @@ public void ClearCache()
{ {
data = null; data = null;
} }
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;
}
} }
} }