using System.IO;
using System.Linq;
using AppleHills.Editor.Utilities;
using Bootstrap;
using UnityEditor;
using UnityEditor.AddressableAssets.Settings;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace Editor.Bootstrap
{
///
/// Helper methods for CustomBoot configuration
///
public class CustomBootSettingsUtil
{
///
/// Path to the ProjectSettings file
///
private const string PROJECT_SETTINGS_PATH = "ProjectSettings/CustomBoot.asset";
///
/// Path to the runtime custom boot settings file
///
private const string RUNTIME_CUSTOM_BOOT_SETTINGS_PATH =
"Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset";
///
/// Path to the editor custom boot settings file
///
private const string EDITOR_CUSTOM_BOOT_SETTINGS_PATH =
"Assets/Data/Bootstrap/Editor/CustomBootSettings_Editor.asset";
///
/// Determine whether the settings asset file is available
///
///
internal static bool IsSettingsAvailable()
{
return File.Exists(PROJECT_SETTINGS_PATH);
}
///
/// Retrieve the settings object if it exists, otherwise create and return it.
///
///
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();
//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;
}
///
/// Create the Runtime and Editor CustomBootSettings assets.
///
///
///
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);
}
///
/// Load, or create, a CustomBootSettings asset at the given path
///
///
///
///
private static CustomBootSettings GetOrCreateBootSettingsAsset(string path, out bool wasCreated)
{
var settings = AssetDatabase.LoadAssetAtPath(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();
AssetDatabase.CreateAsset(settings, path);
wasCreated = true;
}
else
{
wasCreated = false;
}
return settings;
}
///
/// Add the CustomBootSettings asset to the relevant Addressables groups.
///
///
///
///
///
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();
}
///
/// Create an Addressables entry for the given CustomBootSettings object, and add it to the given group.
///
///
///
///
///
private static AddressableAssetEntry CreateCustomBootSettingsEntry(CustomBootSettings bootSettings,
AddressableAssetGroup group, string key)
{
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);
entry.address = key;
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entry, true);
return entry;
}
///
/// Ensure the Runtime and Editor Addressables groups exist
///
///
///
private static void InitialiseAddressableGroups(out AddressableAssetGroup runtimeGroup,
out AddressableAssetGroup editorGroup)
{
runtimeGroup = GetOrCreateGroup($"{nameof(CustomBoot)}_Runtime", true);
editorGroup = GetOrCreateGroup($"{nameof(CustomBoot)}_Editor", false);
}
///
/// Retrieve or create an Addressables group.
///
///
///
///
private static AddressableAssetGroup GetOrCreateGroup(string name, bool includeInBuild)
{
return AddressablesUtility.GetOrCreateGroup(name, includeInBuild);
}
///
/// Retrieve the serialised representation of the settings object
///
///
internal static SerializedObject GetSerializedSettings()
{
return new SerializedObject(GetOrCreateSettings());
}
}
}