mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
145 lines
4.3 KiB
C#
145 lines
4.3 KiB
C#
using AssetRipper.Assets;
|
|
using AssetRipper.Assets.Collections;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_1;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_1001;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_114;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_141;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_2;
|
|
using AssetRipper.SourceGenerated.Classes.ClassID_3;
|
|
using AssetRipper.SourceGenerated.Extensions;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace AssetRipper.Processing.Scenes
|
|
{
|
|
public static class SceneHelpers
|
|
{
|
|
private const string AssetsName = "Assets/";
|
|
private const string LevelName = "level";
|
|
private const string MainSceneName = "maindata";
|
|
|
|
private static readonly Regex s_sceneNameFormat = new Regex($"^{LevelName}(0|[1-9][0-9]*)$");
|
|
|
|
public static int FileNameToSceneIndex(string name, UnityVersion version)
|
|
{
|
|
if (HasMainData(version))
|
|
{
|
|
if (name == MainSceneName)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return int.Parse(name.AsSpan(LevelName.Length)) + 1;
|
|
}
|
|
else
|
|
{
|
|
return int.Parse(name.AsSpan(LevelName.Length));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Less than 5.3.0
|
|
/// </summary>
|
|
public static bool HasMainData(UnityVersion version) => version.LessThan(5, 3);
|
|
|
|
/// <summary>
|
|
/// GameObjects, Classes inheriting from LevelGameManager, MonoBehaviours with GameObjects, Components, and PrefabInstances
|
|
/// </summary>
|
|
public static bool IsSceneCompatible(IUnityObjectBase asset)
|
|
{
|
|
return asset switch
|
|
{
|
|
IGameObject => true,
|
|
ILevelGameManager => true,
|
|
IMonoBehaviour monoBeh => monoBeh.IsComponentOnGameObject(),
|
|
IComponent => true,
|
|
IPrefabInstance => true,
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
public static string SceneIndexToFileName(int index, UnityVersion version)
|
|
{
|
|
if (HasMainData(version))
|
|
{
|
|
if (index == 0)
|
|
{
|
|
return MainSceneName;
|
|
}
|
|
return $"{LevelName}{index - 1}";
|
|
}
|
|
return $"{LevelName}{index}";
|
|
}
|
|
|
|
public static bool TryGetScenePath(AssetCollection collection, [NotNullWhen(true)] IBuildSettings? buildSettings, [NotNullWhen(true)] out string? result)
|
|
{
|
|
if (buildSettings is not null && IsSceneName(collection.Name))
|
|
{
|
|
int index = FileNameToSceneIndex(collection.Name, collection.Version);
|
|
if (index >= buildSettings.Scenes.Count)
|
|
{
|
|
//This can happen in the following situation:
|
|
//1. A game is built with N scenes and published to a distribution platform.
|
|
//2. One of the scenes is removed from the project, for whatever reason.
|
|
//3. The game is built again, with the new scene list.
|
|
//4. When updating the game, the developer forgets to delete the Nth scene file.
|
|
//5. Now, there are N-1 scenes in the BuildSettings, but N scene files for AssetRipper to find.
|
|
result = null;
|
|
return false;
|
|
}
|
|
string scenePath = buildSettings.Scenes[index].String;
|
|
if (scenePath.StartsWith(AssetsName, StringComparison.Ordinal))
|
|
{
|
|
string extension = Path.GetExtension(scenePath);
|
|
result = scenePath[..^extension.Length];
|
|
return true;
|
|
}
|
|
else if (Path.IsPathRooted(scenePath))
|
|
{
|
|
// pull/uTiny 617
|
|
// NOTE: absolute project path may contain Assets/ in its name so in this case we get incorrect scene path, but there is no way to bypass this issue
|
|
int assetIndex = scenePath.IndexOf(AssetsName);
|
|
string extension = Path.GetExtension(scenePath);
|
|
result = scenePath.Substring(assetIndex, scenePath.Length - assetIndex - extension.Length);
|
|
return true;
|
|
}
|
|
else if (scenePath.Length == 0)
|
|
{
|
|
// If a game is built without included scenes, Unity creates one with empty name.
|
|
result = null;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
result = Path.Join("Assets", "Scenes", scenePath);
|
|
return true;
|
|
}
|
|
}
|
|
result = null;
|
|
return false;
|
|
}
|
|
|
|
public static bool IsSceneDuplicate(int sceneIndex, IBuildSettings? buildSettings)
|
|
{
|
|
if (buildSettings == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string sceneName = buildSettings.Scenes[sceneIndex].String;
|
|
for (int i = 0; i < buildSettings.Scenes.Count; i++)
|
|
{
|
|
if (buildSettings.Scenes[i] == sceneName)
|
|
{
|
|
if (i != sceneIndex)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsSceneName(string name) => name == MainSceneName || s_sceneNameFormat.IsMatch(name);
|
|
}
|
|
}
|