WuhuIslandTesting/Library/PackageCache/com.unity.addressables@1.21.12/Editor/GUI/ContentUpdatePreviewWindow.cs
2025-01-07 02:06:59 +01:00

342 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Serialization;
namespace UnityEditor.AddressableAssets.GUI
{
class ContentUpdatePreviewWindow : EditorWindow
{
private GUIContent m_ApplyChangesGUIContent = new GUIContent("Apply Changes", "Move assets to a new remote group in preparation for the content update build");
internal static bool PrepareForContentUpdate(AddressableAssetSettings settings, string buildPath, Action applyChangesCallback = null)
{
var modifiedEntries = ContentUpdateScript.GatherModifiedEntriesWithDependencies(settings, buildPath);
var previewWindow = GetWindow<ContentUpdatePreviewWindow>();
previewWindow.Show(settings, modifiedEntries, applyChangesCallback);
return true;
}
internal static void ShowUpdatePreviewWindow(AddressableAssetSettings settings, Dictionary<AddressableAssetEntry, List<AddressableAssetEntry>> modifiedEntries,
Action applyChangesCallback = null)
{
var previewWindow = GetWindow<ContentUpdatePreviewWindow>();
previewWindow.Show(settings, modifiedEntries, applyChangesCallback, true);
}
void OnEnable()
{
titleContent = new GUIContent("Assets with update issues");
}
class ContentUpdateTreeView : TreeView
{
class Item : TreeViewItem
{
internal AddressableAssetEntry entry;
internal bool enabled;
public Item(AddressableAssetEntry entry, int itemDepth = 1) : base(entry.guid.GetHashCode(), itemDepth)
{
this.entry = entry;
enabled = true;
}
}
ContentUpdatePreviewWindow m_Preview;
public ContentUpdateTreeView(ContentUpdatePreviewWindow preview, TreeViewState state, MultiColumnHeaderState mchs) : base(state, new MultiColumnHeader(mchs))
{
m_Preview = preview;
}
internal List<AddressableAssetEntry> GetEnabledEntries()
{
var result = new HashSet<AddressableAssetEntry>();
foreach (var i in GetRows())
{
var item = i as Item;
if (item != null && item.enabled)
{
result.Add(item.entry);
if (item.hasChildren)
{
foreach (var child in i.children)
{
var childItem = child as Item;
if (childItem != null && !result.Contains(childItem.entry))
result.Add(childItem.entry);
}
}
}
}
return result.ToList();
}
protected override TreeViewItem BuildRoot()
{
columnIndexForTreeFoldouts = 1;
var root = new TreeViewItem(-1, -1);
root.children = new List<TreeViewItem>();
foreach (var k in m_Preview.m_DepEntriesMap.Keys)
{
var mainItem = new Item(k, 0);
root.AddChild(mainItem);
foreach (var dep in m_Preview.m_DepEntriesMap[k])
mainItem.AddChild(new Item(dep, mainItem.depth + 1));
}
return root;
}
protected override void RowGUI(RowGUIArgs args)
{
var item = args.item as Item;
if (item == null)
{
base.RowGUI(args);
return;
}
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
{
CellGUI(args.GetCellRect(i), item, args.GetColumn(i));
}
}
private const int kToggleOffset = 5;
private const int kMainAssetXOffset = 20;
private const int kDependencyAssetXOffset = 40;
void CellGUI(Rect cellRect, Item item, int column)
{
if (column == 0)
cellRect.xMin = (cellRect.xMax / 2) - kToggleOffset;
else //Only want this indent on every column that isn't 0
{
if ((item.parent as Item) != null)
cellRect.xMin += kDependencyAssetXOffset;
else
cellRect.xMin += kMainAssetXOffset;
}
if (column == 0)
{
if (item.entry != null)
{
if ((item.parent as Item) != null)
item.enabled = (item.parent as Item).enabled;
else
item.enabled = EditorGUI.Toggle(cellRect, item.enabled);
}
}
else if (column == 1)
{
EditorGUI.LabelField(cellRect, item.entry.address);
}
else if (column == 2)
{
EditorGUI.LabelField(cellRect, item.entry.AssetPath);
}
else if (column == 3)
{
EditorGUI.LabelField(cellRect, item.entry.parentGroup.Name);
}
}
internal static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState()
{
var retVal = new MultiColumnHeaderState.Column[]
{
new MultiColumnHeaderState.Column()
{
headerContent = new GUIContent("Include", "Include change in Update"),
minWidth = 50,
width = 50,
maxWidth = 50,
headerTextAlignment = TextAlignment.Left,
canSort = true,
autoResize = true
},
new MultiColumnHeaderState.Column()
{
headerContent = new GUIContent("Address", "Data Value"),
minWidth = 300,
width = 300,
maxWidth = 1000,
headerTextAlignment = TextAlignment.Left,
canSort = true,
autoResize = true
},
new MultiColumnHeaderState.Column()
{
headerContent = new GUIContent("Path", "Asset Path"),
minWidth = 300,
width = 300,
maxWidth = 1000,
headerTextAlignment = TextAlignment.Left,
canSort = true,
autoResize = true
},
new MultiColumnHeaderState.Column()
{
headerContent = new GUIContent("Modified Group", "The modified Addressable group"),
minWidth = 300,
width = 300,
maxWidth = 1000,
headerTextAlignment = TextAlignment.Left,
canSort = true,
autoResize = true
}
};
return new MultiColumnHeaderState(retVal);
}
}
string m_GroupName = "Content Update";
AddressableAssetSettings m_Settings;
Dictionary<AddressableAssetEntry, List<AddressableAssetEntry>> m_DepEntriesMap;
Action m_ApplyChangesCallback;
Vector2 m_ScrollPosition;
ContentUpdateTreeView m_Tree;
[FormerlySerializedAs("treeState")]
[SerializeField]
TreeViewState m_TreeState;
[FormerlySerializedAs("mchs")]
[SerializeField]
MultiColumnHeaderState m_Mchs;
bool m_LogOutcomeAnalytics = false;
public void Show(AddressableAssetSettings settings, Dictionary<AddressableAssetEntry, List<AddressableAssetEntry>> entryDependencies, Action applyChangesCallback = null,
bool logAnalytics = false)
{
m_Settings = settings;
m_DepEntriesMap = entryDependencies;
m_ApplyChangesCallback = applyChangesCallback;
m_LogOutcomeAnalytics = logAnalytics;
Show();
}
public void OnGUI()
{
if (m_DepEntriesMap == null)
return;
Rect toolbarRect = new Rect(16, 5, position.width - 32, 70);
Rect contentRect = new Rect(16, 75, position.width - 32, position.height - 55);
if (m_Tree == null)
{
if (m_TreeState == null)
m_TreeState = new TreeViewState();
var headerState = ContentUpdateTreeView.CreateDefaultMultiColumnHeaderState();
if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_Mchs, headerState))
MultiColumnHeaderState.OverwriteSerializedFields(m_Mchs, headerState);
m_Mchs = headerState;
m_Tree = new ContentUpdateTreeView(this, m_TreeState, m_Mchs);
m_Tree.Reload();
}
if (m_DepEntriesMap.Count == 0)
{
Rect emptyContentRect = new Rect(0, 0, position.width, position.height - 50);
GUILayout.BeginArea(emptyContentRect);
GUILayout.BeginVertical();
GUILayout.Label("No Addressable groups with a BundledAssetGroupSchema and ContentUpdateGroupSchema (with Prevent Updates enabled) appear to have been modified.");
GUILayout.EndVertical();
GUILayout.EndArea();
}
else
{
GUILayout.BeginArea(toolbarRect);
GUILayout.BeginVertical();
EditorGUILayout.HelpBox("Modified assets that are part of a group with Prevent Update enabled have been detected during this content update build. " +
"Applying the changes moves all selected items into a new group that has Prevent Updates disabled.", MessageType.Info);
GUILayout.Space(12f);
GUILayout.BeginHorizontal();
GUILayout.Label(new GUIContent("New Group Name: ", "This value is used to set the name of the new group that is created as part of applying the changes from " +
"this tool. If the group already exists, a number is appended to the group name."));
m_GroupName = GUILayout.TextArea(m_GroupName, GUILayout.MinWidth(400f));
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.EndArea();
m_Tree.OnGUI(contentRect);
}
GUILayout.BeginArea(new Rect(0, position.height - 50, position.width, 50));
GUILayout.BeginHorizontal();
bool hasPostApplyCallback = m_ApplyChangesCallback != null;
string cancelButtonName = hasPostApplyCallback ? "Cancel build" : "Cancel";
if (GUILayout.Button(cancelButtonName))
{
if (m_LogOutcomeAnalytics)
AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.ContentUpdateCancelled);
Close();
}
bool showApplyChanges = m_Tree.GetEnabledEntries().Count != 0;
if (showApplyChanges)
{
string buttonName = hasPostApplyCallback ? "Apply and Continue" : "Apply Changes";
m_ApplyChangesGUIContent.text = buttonName;
if (GUILayout.Button(m_ApplyChangesGUIContent))
{
if (m_LogOutcomeAnalytics)
AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.ContentUpdateHasChangesInUpdateRestrictionWindow);
string groupName = string.IsNullOrEmpty(m_GroupName) ? "Content Update" : m_GroupName;
var enabledEntries = m_Tree.GetEnabledEntries();
HashSet<AddressableAssetGroup> clearedGroups = new HashSet<AddressableAssetGroup>();
foreach (var entry in enabledEntries)
{
if (clearedGroups.Contains(entry.parentGroup))
continue;
entry.parentGroup.FlaggedDuringContentUpdateRestriction = false;
clearedGroups.Add(entry.parentGroup);
}
ContentUpdateScript.CreateContentUpdateGroup(m_Settings, enabledEntries, groupName);
m_ApplyChangesCallback?.Invoke();
Close();
}
}
else
{
using (new EditorGUI.DisabledScope(m_ApplyChangesCallback == null))
{
string buttonName = m_ApplyChangesCallback == null ? "Apply Changes" : "Continue without changes";
if (GUILayout.Button(buttonName))
{
if (m_LogOutcomeAnalytics)
AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.ContentUpdateContinuesWithoutChanges);
m_ApplyChangesCallback?.Invoke();
Close();
}
}
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
}