156 lines
7.3 KiB
C#
156 lines
7.3 KiB
C#
|
#if UNITY_2022_2_OR_NEWER
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using UnityEditor;
|
||
|
using UnityEditor.AddressableAssets.Build.Layout;
|
||
|
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.UIElements;
|
||
|
namespace UnityEditor.AddressableAssets.BuildReportVisualizer
|
||
|
{
|
||
|
internal class MainPanelSummaryTab : IAddressableView, IBuildReportConsumer
|
||
|
{
|
||
|
BuildLayout m_Report;
|
||
|
public VisualElement tabRootElement;
|
||
|
internal ScrollView scrollbarElement;
|
||
|
|
||
|
BuildReportWindow m_Window;
|
||
|
|
||
|
class SummaryRow
|
||
|
{
|
||
|
private TextElement m_LabelElement;
|
||
|
private TextElement m_SizeElement;
|
||
|
private string m_TypeName;
|
||
|
|
||
|
public SummaryRow(VisualElement root, string typeName)
|
||
|
{
|
||
|
m_TypeName = typeName;
|
||
|
m_LabelElement = root.Q<TextElement>(string.Format(BuildReportUtility.SummaryTabLabelElementNameFormat, typeName));
|
||
|
m_SizeElement = root.Q<TextElement>(string.Format(BuildReportUtility.SummaryTabSizeElementNameFormat, typeName));
|
||
|
}
|
||
|
|
||
|
public void Display(AssetSummary info)
|
||
|
{
|
||
|
m_LabelElement.text = $"{m_TypeName} ({info.Count})";
|
||
|
m_SizeElement.text = BuildReportUtility.GetDenominatedBytesString(info.SizeInBytes);
|
||
|
}
|
||
|
public void Display(BundleSummary info)
|
||
|
{
|
||
|
m_LabelElement.text = $"{m_TypeName} ({info.Count})";
|
||
|
m_SizeElement.text = BuildReportUtility.GetDenominatedBytesString(info.TotalCompressedSize);
|
||
|
}
|
||
|
|
||
|
public void Reset()
|
||
|
{
|
||
|
m_LabelElement.text = $"{m_TypeName} (0)";
|
||
|
m_SizeElement.text = "0 B";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BuildReportHelperConsumer m_HelperConsumer;
|
||
|
|
||
|
internal MainPanelSummaryTab(BuildReportWindow window, BuildReportHelperConsumer helperConsumer)
|
||
|
{
|
||
|
m_HelperConsumer = helperConsumer;
|
||
|
m_Window = window;
|
||
|
}
|
||
|
|
||
|
public void Consume(BuildLayout buildReport)
|
||
|
{
|
||
|
m_Report = buildReport;
|
||
|
ClearGUI();
|
||
|
|
||
|
BuildLayoutSummary summary = BuildLayoutSummary.GetSummaryWithoutAssetTypes(buildReport);
|
||
|
|
||
|
//This is a little overengineered, but if we do building multiple catalogs then this should help.
|
||
|
HashSet<string> remoteCatalogNames = new HashSet<string>();
|
||
|
HashSet<string> localCatalogNames = new HashSet<string>();
|
||
|
|
||
|
foreach (var catalog in buildReport.AddressablesRuntimeSettings.CatalogLoadPaths)
|
||
|
{
|
||
|
string name = Path.GetFileName(catalog);
|
||
|
if (name.EndsWith(".hash"))
|
||
|
remoteCatalogNames.Add(name.Replace(".hash", ".json"));
|
||
|
else
|
||
|
localCatalogNames.Add(name);
|
||
|
}
|
||
|
|
||
|
SummaryRowBuilder generalInfo = new SummaryRowBuilder("General Information");
|
||
|
if (localCatalogNames.Count > 0)
|
||
|
generalInfo.With("Local Catalog(s)", string.Join(", ", localCatalogNames));
|
||
|
if (remoteCatalogNames.Count > 0)
|
||
|
generalInfo.With("Remote Catalog(s)", string.Join(", ", remoteCatalogNames));
|
||
|
|
||
|
generalInfo.With("Local catalog build location", buildReport.LocalCatalogBuildPath)
|
||
|
.With("Remote catalog build location", string.IsNullOrEmpty(buildReport.RemoteCatalogBuildPath) ? "No remote catalog built" : buildReport.RemoteCatalogBuildPath)
|
||
|
.With("Profile", buildReport.AddressablesEditorSettings.ActiveProfile.Name)
|
||
|
.With("Platform", buildReport.BuildTarget.ToString())
|
||
|
.With("Player Build Version", buildReport.PlayerBuildVersion)
|
||
|
.With("Build Duration", TimeSpan.FromSeconds(buildReport.Duration).ToString("g"))
|
||
|
.With("Package Version", buildReport.PackageVersion)
|
||
|
.With("Unity Editor Version", buildReport.UnityVersion);
|
||
|
|
||
|
scrollbarElement.Add(generalInfo.Build());
|
||
|
|
||
|
if (buildReport.DuplicatedAssets.Count > 0)
|
||
|
{
|
||
|
ulong duplicatedSize = 0;
|
||
|
foreach (var dupeAsset in m_HelperConsumer.GUIDToDuplicateAssets.Values)
|
||
|
{
|
||
|
int duplicationCount = dupeAsset.Bundles.Count;
|
||
|
if (duplicationCount > 1)
|
||
|
duplicatedSize += (ulong) (duplicationCount - 1) * dupeAsset.Asset.SerializedSize;
|
||
|
}
|
||
|
|
||
|
SummaryRowBuilder duplicatedAssets = new SummaryRowBuilder("Potential Issues")
|
||
|
.With(new PotentialIssuesCard($"{buildReport.DuplicatedAssets.Count} Duplicate Assets were detected in the build. \n\n" +
|
||
|
$"Removing duplicated Assets could result in up to {BuildReportUtility.GetDenominatedBytesString(duplicatedSize)} reduced build size.",
|
||
|
() => m_Window.NavigateToView(BuildReportWindow.PotentialIssuesType.DuplicatedAssetsView)));
|
||
|
|
||
|
scrollbarElement.Add(duplicatedAssets.Build());
|
||
|
}
|
||
|
|
||
|
SummaryRowBuilder aggregateInfo = new SummaryRowBuilder("Aggregate Information")
|
||
|
.With("Number of bundles", summary.BundleSummary.Count.ToString())
|
||
|
.With("Total size of all bundles", BuildReportUtility.GetDenominatedBytesString(summary.BundleSummary.TotalCompressedSize))
|
||
|
.With("Total number of assets", summary.TotalAssetCount.ToString())
|
||
|
.With("Addressables", $"{summary.ExplicitAssetCount} ({String.Format("{0:0.##}", ((float)summary.ExplicitAssetCount/(float)summary.TotalAssetCount) * 100f)}%)")
|
||
|
.With("Assets pulled into a build by an Addressable", $"{summary.ImplicitAssetCount} ({String.Format("{0:0.##}", ((float)summary.ImplicitAssetCount/(float)summary.TotalAssetCount) * 100f)}%)", FontStyle.Italic);
|
||
|
|
||
|
scrollbarElement.Add(aggregateInfo.Build());
|
||
|
|
||
|
tabRootElement.visible = true;
|
||
|
tabRootElement.MarkDirtyRepaint();
|
||
|
scrollbarElement.visible = true;
|
||
|
scrollbarElement.MarkDirtyRepaint();
|
||
|
}
|
||
|
|
||
|
public void CreateGUI(VisualElement rootVisualElement)
|
||
|
{
|
||
|
tabRootElement = rootVisualElement.Q<VisualElement>(BuildReportUtility.SummaryTab);
|
||
|
|
||
|
// clear out the style sheets defined in the template uxml file so they can be applied from here in the order of: 1. theming, 2. base
|
||
|
tabRootElement.styleSheets.Clear();
|
||
|
var themeStyle = AssetDatabase.LoadAssetAtPath(EditorGUIUtility.isProSkin ? BuildReportUtility.SummaryTabDarkUssPath : BuildReportUtility.SummaryTabLightUssPath, typeof(StyleSheet)) as StyleSheet;
|
||
|
tabRootElement.styleSheets.Add(themeStyle);
|
||
|
scrollbarElement = new ScrollView();
|
||
|
scrollbarElement.verticalScrollerVisibility = ScrollerVisibility.Auto;
|
||
|
tabRootElement.Add(scrollbarElement);
|
||
|
|
||
|
var ribbonStyle = AssetDatabase.LoadAssetAtPath(BuildReportUtility.SummaryTabUssPath, typeof(StyleSheet)) as StyleSheet;
|
||
|
tabRootElement.styleSheets.Add(ribbonStyle);
|
||
|
|
||
|
tabRootElement.visible = false;
|
||
|
}
|
||
|
|
||
|
public void ClearGUI()
|
||
|
{
|
||
|
scrollbarElement.Clear();
|
||
|
scrollbarElement.visible = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|