2025-09-07 12:36:35 +02:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2025-10-21 10:05:49 +02:00
|
|
|
|
using AppleHills.Editor.Utilities;
|
2025-09-07 12:36:35 +02:00
|
|
|
|
using Bootstrap;
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEditor.AddressableAssets.Settings;
|
|
|
|
|
|
using UnityEditorInternal;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.AddressableAssets;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Editor.Bootstrap
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Helper methods for CustomBoot configuration
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class CustomBootSettingsUtil
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Path to the ProjectSettings file
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private const string PROJECT_SETTINGS_PATH = "ProjectSettings/CustomBoot.asset";
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Path to the runtime custom boot settings file
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private const string RUNTIME_CUSTOM_BOOT_SETTINGS_PATH =
|
|
|
|
|
|
"Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset";
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Path to the editor custom boot settings file
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private const string EDITOR_CUSTOM_BOOT_SETTINGS_PATH =
|
|
|
|
|
|
"Assets/Data/Bootstrap/Editor/CustomBootSettings_Editor.asset";
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Determine whether the settings asset file is available
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
internal static bool IsSettingsAvailable()
|
|
|
|
|
|
{
|
|
|
|
|
|
return File.Exists(PROJECT_SETTINGS_PATH);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Retrieve the settings object if it exists, otherwise create and return it.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
internal static CustomBootProjectSettings GetOrCreateSettings()
|
|
|
|
|
|
{
|
|
|
|
|
|
CustomBootProjectSettings projectSettings;
|
|
|
|
|
|
|
|
|
|
|
|
//Check whether the settings file already exists
|
|
|
|
|
|
if (IsSettingsAvailable())
|
|
|
|
|
|
{
|
|
|
|
|
|
//If it exists, load it
|
|
|
|
|
|
projectSettings = InternalEditorUtility.LoadSerializedFileAndForget(PROJECT_SETTINGS_PATH).First() as
|
|
|
|
|
|
CustomBootProjectSettings;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//If it doesn't exist, create a new ScriptableObject
|
|
|
|
|
|
projectSettings = ScriptableObject.CreateInstance<CustomBootProjectSettings>();
|
|
|
|
|
|
|
|
|
|
|
|
//Configure the settings file
|
|
|
|
|
|
CreateBootSettingsAssets(out var runtimeEntry, out var editorEntry);
|
|
|
|
|
|
projectSettings.RuntimeSettings = new AssetReference(runtimeEntry.guid);
|
|
|
|
|
|
projectSettings.EditorSettings = new AssetReference(editorEntry.guid);
|
|
|
|
|
|
|
|
|
|
|
|
//And save it!
|
|
|
|
|
|
InternalEditorUtility.SaveToSerializedFileAndForget(new Object[] { projectSettings },
|
|
|
|
|
|
PROJECT_SETTINGS_PATH, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Finally, return our settings object
|
|
|
|
|
|
return projectSettings;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create the Runtime and Editor CustomBootSettings assets.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="runtimeEntry"></param>
|
|
|
|
|
|
/// <param name="editorEntry"></param>
|
|
|
|
|
|
private static void CreateBootSettingsAssets(out AddressableAssetEntry runtimeEntry,
|
|
|
|
|
|
out AddressableAssetEntry editorEntry)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Create two assets representing our boot configurations
|
|
|
|
|
|
var runtimeSettings =
|
|
|
|
|
|
GetOrCreateBootSettingsAsset(RUNTIME_CUSTOM_BOOT_SETTINGS_PATH, out var runtimeCreated);
|
|
|
|
|
|
var editorSettings = GetOrCreateBootSettingsAsset(EDITOR_CUSTOM_BOOT_SETTINGS_PATH, out var editorCreated);
|
|
|
|
|
|
|
|
|
|
|
|
//Save the AssetDatabase state if either asset is new
|
|
|
|
|
|
if (runtimeCreated || editorCreated)
|
|
|
|
|
|
{
|
|
|
|
|
|
AssetDatabase.SaveAssets();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Configure the Addressables system with the new assets.
|
|
|
|
|
|
AddSettingsToAddressables(runtimeSettings, editorSettings, out runtimeEntry, out editorEntry);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Load, or create, a CustomBootSettings asset at the given path
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="path"></param>
|
|
|
|
|
|
/// <param name="wasCreated"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static CustomBootSettings GetOrCreateBootSettingsAsset(string path, out bool wasCreated)
|
|
|
|
|
|
{
|
|
|
|
|
|
var settings = AssetDatabase.LoadAssetAtPath<CustomBootSettings>(path);
|
|
|
|
|
|
if (!settings)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Make sure full path is created
|
|
|
|
|
|
var dirPath = Path.GetDirectoryName(path);
|
|
|
|
|
|
if (!Directory.Exists(dirPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(dirPath);
|
|
|
|
|
|
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
settings = ScriptableObject.CreateInstance<CustomBootSettings>();
|
|
|
|
|
|
AssetDatabase.CreateAsset(settings, path);
|
|
|
|
|
|
wasCreated = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
wasCreated = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return settings;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add the CustomBootSettings asset to the relevant Addressables groups.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="runtimeSettings"></param>
|
|
|
|
|
|
/// <param name="editorSettings"></param>
|
|
|
|
|
|
/// <param name="runtimeEntry"></param>
|
|
|
|
|
|
/// <param name="editorEntry"></param>
|
|
|
|
|
|
private static void AddSettingsToAddressables(CustomBootSettings runtimeSettings,
|
|
|
|
|
|
CustomBootSettings editorSettings, out AddressableAssetEntry runtimeEntry,
|
|
|
|
|
|
out AddressableAssetEntry editorEntry)
|
|
|
|
|
|
{
|
|
|
|
|
|
InitialiseAddressableGroups(out var runtimeGroup, out var editorGroup);
|
|
|
|
|
|
runtimeEntry =
|
|
|
|
|
|
CreateCustomBootSettingsEntry(runtimeSettings, runtimeGroup, $"{nameof(CustomBootSettings)}_Runtime");
|
|
|
|
|
|
editorEntry =
|
|
|
|
|
|
CreateCustomBootSettingsEntry(editorSettings, editorGroup, $"{nameof(CustomBootSettings)}_Editor");
|
|
|
|
|
|
AssetDatabase.SaveAssets();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create an Addressables entry for the given CustomBootSettings object, and add it to the given group.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="bootSettings"></param>
|
|
|
|
|
|
/// <param name="group"></param>
|
|
|
|
|
|
/// <param name="key"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static AddressableAssetEntry CreateCustomBootSettingsEntry(CustomBootSettings bootSettings,
|
|
|
|
|
|
AddressableAssetGroup group, string key)
|
|
|
|
|
|
{
|
2025-10-21 10:05:49 +02:00
|
|
|
|
string assetPath = AssetDatabase.GetAssetPath(bootSettings);
|
|
|
|
|
|
var settings = AddressablesUtility.GetAddressableSettings(false);
|
|
|
|
|
|
if (settings == null || string.IsNullOrEmpty(assetPath) || group == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var guid = AssetDatabase.AssetPathToGUID(assetPath);
|
|
|
|
|
|
var entry = settings.CreateOrMoveEntry(guid, group);
|
2025-09-07 12:36:35 +02:00
|
|
|
|
entry.address = key;
|
|
|
|
|
|
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entry, true);
|
|
|
|
|
|
return entry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Ensure the Runtime and Editor Addressables groups exist
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="runtimeGroup"></param>
|
|
|
|
|
|
/// <param name="editorGroup"></param>
|
|
|
|
|
|
private static void InitialiseAddressableGroups(out AddressableAssetGroup runtimeGroup,
|
|
|
|
|
|
out AddressableAssetGroup editorGroup)
|
|
|
|
|
|
{
|
|
|
|
|
|
runtimeGroup = GetOrCreateGroup($"{nameof(CustomBoot)}_Runtime", true);
|
|
|
|
|
|
editorGroup = GetOrCreateGroup($"{nameof(CustomBoot)}_Editor", false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Retrieve or create an Addressables group.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="name"></param>
|
|
|
|
|
|
/// <param name="includeInBuild"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static AddressableAssetGroup GetOrCreateGroup(string name, bool includeInBuild)
|
|
|
|
|
|
{
|
2025-10-21 10:05:49 +02:00
|
|
|
|
return AddressablesUtility.GetOrCreateGroup(name, includeInBuild);
|
2025-09-07 12:36:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Retrieve the serialised representation of the settings object
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
internal static SerializedObject GetSerializedSettings()
|
|
|
|
|
|
{
|
|
|
|
|
|
return new SerializedObject(GetOrCreateSettings());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|