Firstborn/Library/PackageCache/com.unity.addressables@1.19.19/Editor/GUI/AssetInspectorGUI.cs

330 lines
15 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
namespace UnityEditor.AddressableAssets.GUI
{
using Object = UnityEngine.Object;
[InitializeOnLoad]
internal static class AddressableAssetInspectorGUI
{
static GUIStyle s_ToggleMixed;
static GUIContent s_AddressableAssetToggleText;
static AddressableAssetInspectorGUI()
{
s_ToggleMixed = null;
s_AddressableAssetToggleText = new GUIContent("Addressable", "Check this to mark this asset as an Addressable Asset, which includes it in the bundled data and makes it loadable via script by its address.");
Editor.finishedDefaultHeaderGUI += OnPostHeaderGUI;
}
static void SetAaEntry(AddressableAssetSettings aaSettings, List<TargetInfo> targetInfos, bool create)
{
if (create && aaSettings.DefaultGroup.ReadOnly)
{
Debug.LogError("Current default group is ReadOnly. Cannot add addressable assets to it");
return;
}
Undo.RecordObject(aaSettings, "AddressableAssetSettings");
if (!create)
{
List<AddressableAssetEntry> removedEntries = new List<AddressableAssetEntry>(targetInfos.Count);
for (int i = 0; i < targetInfos.Count; ++i)
{
AddressableAssetEntry e = aaSettings.FindAssetEntry(targetInfos[i].Guid);
AddressableAssetUtility.OpenAssetIfUsingVCIntegration(e.parentGroup);
removedEntries.Add(e);
aaSettings.RemoveAssetEntry(removedEntries[i], false);
}
if (removedEntries.Count > 0)
aaSettings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryRemoved, removedEntries, true, false);
}
else
{
AddressableAssetGroup parentGroup = aaSettings.DefaultGroup;
var resourceTargets = targetInfos.Where(ti => AddressableAssetUtility.IsInResources(ti.Path));
if (resourceTargets.Any())
{
var resourcePaths = resourceTargets.Select(t => t.Path).ToList();
var resourceGuids = resourceTargets.Select(t => t.Guid).ToList();
AddressableAssetUtility.SafeMoveResourcesToGroup(aaSettings, parentGroup, resourcePaths, resourceGuids);
}
var otherTargetInfos = targetInfos.Except(resourceTargets);
List<string> otherTargetGuids = new List<string>(targetInfos.Count);
foreach (var info in otherTargetInfos)
otherTargetGuids.Add(info.Guid);
var entriesCreated = new List<AddressableAssetEntry>();
var entriesMoved = new List<AddressableAssetEntry>();
aaSettings.CreateOrMoveEntries(otherTargetGuids, parentGroup, entriesCreated, entriesMoved, false, false);
bool openedInVC = false;
if (entriesMoved.Count > 0)
{
AddressableAssetUtility.OpenAssetIfUsingVCIntegration(parentGroup);
openedInVC = true;
aaSettings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entriesMoved, true, false);
}
if (entriesCreated.Count > 0)
{
if (!openedInVC)
AddressableAssetUtility.OpenAssetIfUsingVCIntegration(parentGroup);
aaSettings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryAdded, entriesCreated, true, false);
}
}
}
static void OnPostHeaderGUI(Editor editor)
{
var aaSettings = AddressableAssetSettingsDefaultObject.Settings;
if (editor.targets.Length > 0)
{
foreach (var t in editor.targets)
{
if (t is AddressableAssetGroup || t is AddressableAssetGroupSchema)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Profile: " + AddressableAssetSettingsDefaultObject.GetSettings(true).profileSettings.
GetProfileName(AddressableAssetSettingsDefaultObject.GetSettings(true).activeProfileId));
GUILayout.FlexibleSpace();
if (GUILayout.Button("System Settings", "MiniButton"))
{
EditorGUIUtility.PingObject(AddressableAssetSettingsDefaultObject.Settings);
Selection.activeObject = AddressableAssetSettingsDefaultObject.Settings;
}
GUILayout.EndHorizontal();
return;
}
}
List<TargetInfo> targetInfos = GatherTargetInfos(editor.targets, aaSettings);
if (targetInfos.Count == 0)
return;
bool targetHasAddressableSubObject = false;
int mainAssetsAddressable = 0;
int subAssetsAddressable = 0;
foreach (TargetInfo info in targetInfos)
{
if (info.MainAssetEntry == null)
continue;
if (info.MainAssetEntry.IsSubAsset)
subAssetsAddressable++;
else
mainAssetsAddressable++;
if (!info.IsMainAsset)
targetHasAddressableSubObject = true;
}
// Overrides a DisabledScope in the EditorElement.cs that disables GUI drawn in the header when the asset cannot be edited.
bool prevEnabledState = UnityEngine.GUI.enabled;
if (targetHasAddressableSubObject)
UnityEngine.GUI.enabled = false;
else
{
UnityEngine.GUI.enabled = true;
foreach (var info in targetInfos)
{
if (!info.IsMainAsset)
{
UnityEngine.GUI.enabled = false;
break;
}
}
}
int totalAddressableCount = mainAssetsAddressable + subAssetsAddressable;
if (totalAddressableCount == 0) // nothing is addressable
{
if (GUILayout.Toggle(false, s_AddressableAssetToggleText, GUILayout.ExpandWidth(false)))
SetAaEntry(AddressableAssetSettingsDefaultObject.GetSettings(true), targetInfos, true);
}
else if (totalAddressableCount == editor.targets.Length) // everything is addressable
{
var entryInfo = targetInfos[targetInfos.Count - 1];
if (entryInfo == null || entryInfo.MainAssetEntry == null)
throw new NullReferenceException("EntryInfo incorrect for Addressables content.");
GUILayout.BeginHorizontal();
if (mainAssetsAddressable > 0 && subAssetsAddressable > 0)
{
if (s_ToggleMixed == null)
s_ToggleMixed = new GUIStyle("ToggleMixed");
if (GUILayout.Toggle(false, s_AddressableAssetToggleText, s_ToggleMixed, GUILayout.ExpandWidth(false)))
SetAaEntry(aaSettings, targetInfos, true);
}
else if (mainAssetsAddressable > 0)
{
if (!GUILayout.Toggle(true, s_AddressableAssetToggleText, GUILayout.ExpandWidth(false)))
{
SetAaEntry(aaSettings, targetInfos, false);
UnityEngine.GUI.enabled = prevEnabledState;
GUIUtility.ExitGUI();
}
}
else if (GUILayout.Toggle(false, s_AddressableAssetToggleText, GUILayout.ExpandWidth(false)))
SetAaEntry(aaSettings, targetInfos, true);
if (editor.targets.Length == 1)
{
if (!entryInfo.IsMainAsset || entryInfo.MainAssetEntry.IsSubAsset)
{
bool preAddressPrevEnabledState = UnityEngine.GUI.enabled;
UnityEngine.GUI.enabled = false;
string address = entryInfo.Address + (entryInfo.IsMainAsset ? "" : $"[{entryInfo.TargetObject.name}]");
EditorGUILayout.DelayedTextField(address, GUILayout.ExpandWidth(true));
UnityEngine.GUI.enabled = preAddressPrevEnabledState;
}
else
{
string newAddress = EditorGUILayout.DelayedTextField(entryInfo.Address, GUILayout.ExpandWidth(true));
if (newAddress != entryInfo.Address)
{
if (newAddress.Contains("[") && newAddress.Contains("]"))
Debug.LogErrorFormat("Rename of address '{0}' cannot contain '[ ]'.", entryInfo.Address);
else
{
entryInfo.MainAssetEntry.address = newAddress;
AddressableAssetUtility.OpenAssetIfUsingVCIntegration(entryInfo.MainAssetEntry.parentGroup, true);
}
}
}
}
else
{
FindUniqueAssetGuids(targetInfos, out var uniqueAssetGuids, out var uniqueAddressableAssetGuids);
EditorGUILayout.LabelField(uniqueAddressableAssetGuids.Count + " out of " + uniqueAssetGuids.Count + " assets are addressable.");
}
DrawSelectEntriesButton(targetInfos);
GUILayout.EndHorizontal();
}
else // mixed addressable selected
{
GUILayout.BeginHorizontal();
if (s_ToggleMixed == null)
s_ToggleMixed = new GUIStyle("ToggleMixed");
if (GUILayout.Toggle(false, s_AddressableAssetToggleText, s_ToggleMixed, GUILayout.ExpandWidth(false)))
SetAaEntry(AddressableAssetSettingsDefaultObject.GetSettings(true), targetInfos, true);
FindUniqueAssetGuids(targetInfos, out var uniqueAssetGuids, out var uniqueAddressableAssetGuids);
EditorGUILayout.LabelField(uniqueAddressableAssetGuids.Count + " out of " + uniqueAssetGuids.Count + " assets are addressable.");
DrawSelectEntriesButton(targetInfos);
GUILayout.EndHorizontal();
}
UnityEngine.GUI.enabled = prevEnabledState;
}
}
internal static List<TargetInfo> GatherTargetInfos(Object[] targets, AddressableAssetSettings aaSettings)
{
var targetInfos = new List<TargetInfo>();
AddressableAssetEntry entry;
foreach (var t in targets)
{
if (AddressableAssetUtility.TryGetPathAndGUIDFromTarget(t, out var path, out var guid))
{
var mainAssetType = AssetDatabase.GetMainAssetTypeAtPath(path);
// Is asset
if (mainAssetType != null && !BuildUtility.IsEditorAssembly(mainAssetType.Assembly))
{
bool isMainAsset = t is AssetImporter || AssetDatabase.IsMainAsset(t);
var info = new TargetInfo() {TargetObject = t, Guid = guid, Path = path, IsMainAsset = isMainAsset};
if (aaSettings != null)
{
entry = aaSettings.FindAssetEntry(guid, true);
if (entry != null)
info.MainAssetEntry = entry;
}
targetInfos.Add(info);
}
}
}
return targetInfos;
}
internal static void FindUniqueAssetGuids(List<TargetInfo> targetInfos, out HashSet<string> uniqueAssetGuids, out HashSet<string> uniqueAddressableAssetGuids)
{
uniqueAssetGuids = new HashSet<string>();
uniqueAddressableAssetGuids = new HashSet<string>();
foreach (TargetInfo info in targetInfos)
{
uniqueAssetGuids.Add(info.Guid);
if (info.MainAssetEntry != null)
uniqueAddressableAssetGuids.Add(info.Guid);
}
}
static void DrawSelectEntriesButton(List<TargetInfo> targets)
{
var prevGuiEnabled = UnityEngine.GUI.enabled;
UnityEngine.GUI.enabled = true;
if (GUILayout.Button("Select"))
{
AddressableAssetsWindow.Init();
var window = EditorWindow.GetWindow<AddressableAssetsWindow>();
List<AddressableAssetEntry> entries = new List<AddressableAssetEntry>(targets.Count);
foreach (TargetInfo info in targets)
{
if (info.MainAssetEntry != null)
{
if (info.IsMainAsset == false && ProjectConfigData.ShowSubObjectsInGroupView)
{
List<AddressableAssetEntry> subs = new List<AddressableAssetEntry>();
info.MainAssetEntry.GatherAllAssets(subs, false, true, true);
foreach (AddressableAssetEntry sub in subs)
{
if (sub.TargetAsset == info.TargetObject)
{
entries.Add(sub);
break;
}
}
}
else
entries.Add(info.MainAssetEntry);
}
}
if (entries.Count > 0)
window.SelectAssetsInGroupEditor(entries);
}
UnityEngine.GUI.enabled = prevGuiEnabled;
}
internal class TargetInfo
{
public UnityEngine.Object TargetObject;
public string Guid;
public string Path;
public bool IsMainAsset;
public AddressableAssetEntry MainAssetEntry;
public string Address
{
get
{
if (MainAssetEntry == null)
throw new NullReferenceException("No Entry set for Target info with AssetPath " + Path);
return MainAssetEntry.address;
}
}
}
}
}