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

515 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.AddressableAssets.HostingServices;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Serialization;
namespace UnityEditor.AddressableAssets.GUI
{
using Object = UnityEngine.Object;
/// <summary>
/// Configuration GUI for <see cref="T:UnityEditor.AddressableAssets.HostingServices.HostingServicesManager" />
/// </summary>
[DefaultExecutionOrder(-1)]
public class HostingServicesWindow : EditorWindow, ISerializationCallbackReceiver, ILogHandler
{
const float k_DefaultVerticalSplitterRatio = 0.67f;
const float k_DefaultHorizontalSplitterRatio = 0.33f;
const int k_SplitterThickness = 2;
const int k_ToolbarHeight = 20;
const int k_ItemRectPadding = 15;
const int k_LogRectPadding = 5;
GUIStyle m_ItemRectPadding;
GUIStyle m_LogRectPadding;
[FormerlySerializedAs("m_logText")]
[SerializeField]
string m_LogText;
[FormerlySerializedAs("m_logScrollPos")]
[SerializeField]
Vector2 m_LogScrollPos;
[FormerlySerializedAs("m_servicesScrollPos")]
[SerializeField]
Vector2 m_ServicesScrollPos;
[FormerlySerializedAs("m_splitterRatio")]
[SerializeField]
float m_VerticalSplitterRatio = k_DefaultVerticalSplitterRatio;
float m_HorizontalSplitterRatio = k_DefaultHorizontalSplitterRatio;
[FormerlySerializedAs("m_settings")]
[SerializeField]
AddressableAssetSettings m_Settings;
ILogger m_Logger;
bool m_NewLogContent;
bool m_IsResizingVerticalSplitter;
bool m_IsResizingHorizontalSplitter;
bool m_Reload = false;
int m_serviceIndex = -1;
/// <summary>
/// Returns the index of the currently selected hosting service.
/// </summary>
public int ServiceIndex
{
get { return m_serviceIndex; }
set { m_serviceIndex = value; }
}
readonly Dictionary<object, HostingServicesProfileVarsTreeView> m_ProfileVarTables =
new Dictionary<object, HostingServicesProfileVarsTreeView>();
readonly Dictionary<object, Dictionary<string, string>> m_TablePrevData =
new Dictionary<object, Dictionary<string, string>>();
private readonly Dictionary<object, Dictionary<string, string>> m_TablePrevManagerVariables =
new Dictionary<object, Dictionary<string, string>>();
readonly List<IHostingService> m_RemovalQueue = new List<IHostingService>();
HostingServicesProfileVarsTreeView m_GlobalProfileVarTable;
HostingServicesListTreeView m_ServicesList;
Type[] m_ServiceTypes;
Type[] ServiceTypes
{
get
{
if (m_ServiceTypes == null || m_ServiceTypes.Length == 0)
PopulateServiceTypes();
return m_ServiceTypes;
}
}
string[] m_ServiceTypeNames;
private GUIContent m_CreateServiceGUIContent = new GUIContent("Create", "Create a new hosting service");
private GUIContent m_ServiceNameGUIContent = new GUIContent("Service Name", "Name of the hosting service");
private GUIContent m_ServiceTypeAndIdGUIContent = new GUIContent("Service Type (ID)", "Type and identifier for the hosting service");
private GUIContent m_EnableServiceGUIContent = new GUIContent("Enable", "Starts the hosting service");
private GUIContent m_HostingServiceVariablesGUIContent = new GUIContent("Hosting Service Variables",
"Stores information about the actively running service. Hosting Service Variables can be referenced by a Profile variable");
private GUIContent m_RefreshVariablesGUIContent = new GUIContent("Refresh", "Reloads information about the service. Useful when the network changed");
private GUIContent m_PingTimeoutGUIContent = new GUIContent("IP Ping Timeout (ms)", "Timeout in milliseconds for filtering ip addresses for the hosting service. Default value is 5000ms (5s).");
/// <summary>
/// Show the <see cref="HostingServicesWindow"/>, initialized with the given <see cref="AddressableAssetSettings"/>
/// </summary>
/// <param name="settings"></param>
public void Show(AddressableAssetSettings settings)
{
Initialize(settings);
Show();
}
void Initialize(AddressableAssetSettings settings)
{
if (m_Logger == null)
m_Logger = new Logger(this);
if (m_Settings == null)
m_Settings = settings;
if (m_Settings != null)
m_Settings.HostingServicesManager.Logger = m_Logger;
}
void OnEnable()
{
if (m_Settings == null)
Initialize(AddressableAssetSettingsDefaultObject.Settings);
else if (m_Logger == null)
Initialize(m_Settings);
AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.OpenHostingWindow, true);
PopulateServiceTypes();
m_ItemRectPadding = new GUIStyle();
m_ItemRectPadding.padding = new RectOffset(k_ItemRectPadding, k_ItemRectPadding, k_ItemRectPadding, k_ItemRectPadding);
m_LogRectPadding = new GUIStyle();
m_LogRectPadding.padding = new RectOffset(k_LogRectPadding, k_LogRectPadding, k_LogRectPadding, k_LogRectPadding);
}
[MenuItem("Window/Asset Management/Addressables/Hosting", priority = 2052)]
static void InitializeWithDefaultSettings()
{
AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.OpenHostingWindow);
var defaultSettings = AddressableAssetSettingsDefaultObject.Settings;
if (defaultSettings == null)
{
EditorUtility.DisplayDialog("Error",
"Attempting to open Addressables Hosting window, but no Addressables Settings file exists. \n\nOpen 'Window/Asset Management/Addressables/Groups' for more info.", "Ok");
return;
}
GetWindow<HostingServicesWindow>().Show(defaultSettings);
}
void PopulateServiceTypes()
{
if (m_Settings == null) return;
m_ServiceTypes = m_Settings.HostingServicesManager.RegisteredServiceTypes;
m_ServiceTypeNames = new string[m_ServiceTypes.Length];
for (var i = 0; i < m_ServiceTypes.Length; i++)
{
m_ServiceTypeNames[i] = m_ServiceTypes[i].Name;
}
}
void Awake()
{
titleContent = new GUIContent("Addressables Hosting");
Initialize(m_Settings);
}
internal static void DrawOutline(Rect rect, float size)
{
Color color = new Color(0.6f, 0.6f, 0.6f, 1.333f);
if (EditorGUIUtility.isProSkin)
{
color.r = 0.12f;
color.g = 0.12f;
color.b = 0.12f;
}
if (Event.current.type != EventType.Repaint)
return;
Color orgColor = UnityEngine.GUI.color;
UnityEngine.GUI.color = UnityEngine.GUI.color * color;
UnityEngine.GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, size), EditorGUIUtility.whiteTexture);
UnityEngine.GUI.DrawTexture(new Rect(rect.x, rect.yMax - size, rect.width, size), EditorGUIUtility.whiteTexture);
UnityEngine.GUI.DrawTexture(new Rect(rect.x, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture);
UnityEngine.GUI.DrawTexture(new Rect(rect.xMax - size, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture);
UnityEngine.GUI.color = orgColor;
}
[UnityEngine.TestTools.ExcludeFromCoverage]
void OnGUI()
{
if (m_Settings == null)
{
if (AddressableAssetSettingsDefaultObject.Settings == null)
return;
InitializeWithDefaultSettings();
}
if (m_IsResizingVerticalSplitter)
m_VerticalSplitterRatio = Mathf.Clamp(Event.current.mousePosition.y / position.height, 0.2f, 0.9f);
if (m_IsResizingHorizontalSplitter)
m_HorizontalSplitterRatio = Mathf.Clamp(Event.current.mousePosition.x / position.width, 0.15f, 0.6f);
var toolbarRect = new Rect(0, 0, position.width, position.height);
var servicesRect = new Rect(0, k_ToolbarHeight, (position.width * m_HorizontalSplitterRatio), position.height);
var itemRect = new Rect(servicesRect.width + k_SplitterThickness, k_ToolbarHeight, position.width - servicesRect.width - k_SplitterThickness,
(position.height * m_VerticalSplitterRatio) - k_ToolbarHeight);
var logRect = new Rect(servicesRect.width + k_SplitterThickness, k_ToolbarHeight + itemRect.height + k_SplitterThickness, position.width - servicesRect.width - k_SplitterThickness,
position.height - itemRect.height - k_SplitterThickness);
var verticalSplitterRect = new Rect(servicesRect.width + k_SplitterThickness, k_ToolbarHeight + itemRect.height, position.width, k_SplitterThickness);
var horizontalSplitterRect = new Rect(servicesRect.width, k_ToolbarHeight, k_SplitterThickness, position.height - k_ToolbarHeight);
//EditorGUI.LabelField(splitterRect, string.Empty, UnityEngine.GUI.skin.horizontalSlider);
EditorGUIUtility.AddCursorRect(verticalSplitterRect, MouseCursor.ResizeVertical);
EditorGUIUtility.AddCursorRect(horizontalSplitterRect, MouseCursor.ResizeHorizontal);
if (Event.current.type == EventType.MouseDown && verticalSplitterRect.Contains(Event.current.mousePosition))
m_IsResizingVerticalSplitter = true;
else if (Event.current.type == EventType.MouseDown && horizontalSplitterRect.Contains(Event.current.mousePosition))
m_IsResizingHorizontalSplitter = true;
else if (Event.current.type == EventType.MouseUp)
{
m_IsResizingVerticalSplitter = false;
m_IsResizingHorizontalSplitter = false;
}
GUILayout.BeginArea(toolbarRect);
GUILayout.BeginHorizontal(EditorStyles.toolbar);
{
var guiMode = new GUIContent(m_CreateServiceGUIContent);
Rect rMode = GUILayoutUtility.GetRect(guiMode, EditorStyles.toolbarDropDown);
if (EditorGUI.DropdownButton(rMode, guiMode, FocusType.Passive, EditorStyles.toolbarDropDown))
{
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Local Hosting"), false, () => AddService(0, "Local Hosting"));
menu.AddItem(new GUIContent("Custom Service"), false, () => GetWindow<HostingServicesAddServiceWindow>(true, "Custom Service").Initialize(m_Settings));
menu.DropDown(rMode);
}
GUILayout.FlexibleSpace();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
DrawOutline(servicesRect, 1);
GUILayout.BeginArea(servicesRect);
{
Rect r = new Rect(servicesRect);
r.y = 0;
DrawServicesList(r);
}
GUILayout.EndArea();
DrawOutline(itemRect, 1);
GUILayout.BeginArea(itemRect, m_ItemRectPadding);
{
EditorGUILayout.Space();
DrawServicesArea();
EditorGUILayout.Space();
}
GUILayout.EndArea();
DrawOutline(logRect, 1);
GUILayout.BeginArea(logRect, m_LogRectPadding);
{
DrawLogArea(logRect);
}
GUILayout.EndArea();
if (m_IsResizingVerticalSplitter || m_IsResizingHorizontalSplitter)
Repaint();
}
void DrawServicesList(Rect rect)
{
var manager = m_Settings.HostingServicesManager;
var svcList = manager.HostingServices;
// Do removal queue
if (m_RemovalQueue.Count > 0)
{
foreach (var svc in m_RemovalQueue)
manager.RemoveHostingService(svc);
m_RemovalQueue.Clear();
}
if (svcList.Count == 0)
{
m_Reload = true;
return;
}
if (m_ServicesList == null || m_ServicesList.Names.Count != svcList.Count || m_Reload)
{
m_ServicesList = new HostingServicesListTreeView(new TreeViewState(), manager, this, HostingServicesListTreeView.CreateHeader());
if (m_Reload)
m_Reload = false;
}
m_ServicesList.OnGUI(rect);
}
void DrawServicesArea()
{
var manager = m_Settings.HostingServicesManager;
m_ServicesScrollPos = EditorGUILayout.BeginScrollView(m_ServicesScrollPos);
var svcList = manager.HostingServices;
List<IHostingService> lst = new List<IHostingService>(svcList);
if (lst.Count == 0)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("No Hosting Services configured.");
GUILayout.EndScrollView();
return;
}
else if (m_serviceIndex >= lst.Count)
{
m_serviceIndex = lst.Count - 1;
}
DrawServiceElement(lst[m_serviceIndex], lst);
GUILayout.EndScrollView();
}
/// <summary>
/// Add a new hosting service to the HostingServicesManager. The service at index <paramref name="typeIndex"/> in ServiceTypes must implement the <see cref="IHostingService"/> interface, or an <see cref="ArgumentException"/> is thrown.
/// </summary>
/// <param name="typeIndex">The index of the service stored in ServiceTypes. The service at this index must implement <see cref="IHostingService"/></param>
/// <param name="serviceName">A descriptive name for the new service instance.</param>
public void AddService(int typeIndex, string serviceName)
{
string hostingName = string.Format("{0} {1}", serviceName, m_Settings.HostingServicesManager.NextInstanceId);
m_Settings.HostingServicesManager.AddHostingService(ServiceTypes[typeIndex], hostingName);
}
/// <summary>
/// Add a hosting service to the removal queue.
/// </summary>
/// <param name="svc">The service type to be removed.</param>
/// <param name="showDialog">Indicates whether or not a warning dialogue box is shown.</param>
public void RemoveService(IHostingService svc, bool showDialog = true)
{
if (!showDialog)
m_RemovalQueue.Add(svc);
else if (EditorUtility.DisplayDialog("Remove Service", "Are you sure you want to remove " + svc.DescriptiveName + "? This action cannot be undone.", "Ok", "Cancel"))
m_RemovalQueue.Add(svc);
}
void DrawServiceElement(IHostingService svc, List<IHostingService> svcList)
{
bool isDirty = false;
string newName = EditorGUILayout.DelayedTextField(m_ServiceNameGUIContent, svc.DescriptiveName);
if (svcList.Find(s => s.DescriptiveName == newName) == default(IHostingService))
{
svc.DescriptiveName = newName;
m_ServicesList.Reload();
isDirty = true;
}
var typeAndId = string.Format("{0} ({1})", svc.GetType().Name, svc.InstanceId.ToString());
EditorGUILayout.LabelField(m_ServiceTypeAndIdGUIContent, new GUIContent(typeAndId), GUILayout.MinWidth(225f));
// Allow service to provide additional GUI configuration elements
svc.OnGUI();
var newIsServiceEnabled = EditorGUILayout.Toggle(m_EnableServiceGUIContent, svc.IsHostingServiceRunning);
if (newIsServiceEnabled != svc.IsHostingServiceRunning)
{
if (newIsServiceEnabled)
svc.StartHostingService();
else
svc.StopHostingService();
isDirty = true;
}
EditorGUILayout.Space();
var manager = m_Settings.HostingServicesManager;
using (new EditorGUI.DisabledScope(!svc.IsHostingServiceRunning))
{
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField(m_HostingServiceVariablesGUIContent);
if (GUILayout.Button(m_RefreshVariablesGUIContent, GUILayout.ExpandWidth(false)))
manager.RefreshGlobalProfileVariables();
GUILayout.EndHorizontal();
DrawProfileVarTable(svc);
}
EditorGUILayout.Space();
var newPing = EditorGUILayout.DelayedIntField(m_PingTimeoutGUIContent, manager.PingTimeoutInMilliseconds);
if (newPing != manager.PingTimeoutInMilliseconds && newPing >= 0)
{
manager.PingTimeoutInMilliseconds = newPing;
isDirty = true;
}
if (isDirty && m_Settings != null)
m_Settings.SetDirty(AddressableAssetSettings.ModificationEvent.HostingServicesManagerModified, this, false, true);
}
void DrawLogArea(Rect rect)
{
if (m_NewLogContent)
{
var height = UnityEngine.GUI.skin.GetStyle("Label").CalcHeight(new GUIContent(m_LogText), rect.width);
m_LogScrollPos = new Vector2(0f, height);
m_NewLogContent = false;
}
m_LogScrollPos = EditorGUILayout.BeginScrollView(m_LogScrollPos);
GUILayout.Label(m_LogText);
EditorGUILayout.EndScrollView();
}
internal static bool DictsAreEqual(Dictionary<string, string> a, Dictionary<string, string> b)
{
return a.Count == b.Count && !a.Except(b).Any();
}
void DrawProfileVarTable(IHostingService tableKey)
{
var manager = m_Settings.HostingServicesManager;
var data = tableKey.ProfileVariables;
HostingServicesProfileVarsTreeView table;
if (!m_ProfileVarTables.TryGetValue(tableKey, out table))
{
table = new HostingServicesProfileVarsTreeView(new TreeViewState(),
HostingServicesProfileVarsTreeView.CreateHeader());
m_ProfileVarTables[tableKey] = table;
m_TablePrevData[tableKey] = new Dictionary<string, string>(data);
m_TablePrevManagerVariables[tableKey] = new Dictionary<string, string>(manager.GlobalProfileVariables);
}
else if (!DictsAreEqual(data, m_TablePrevData[tableKey]) || !DictsAreEqual(manager.GlobalProfileVariables, m_TablePrevManagerVariables[tableKey]))
{
table.ClearItems();
m_TablePrevData[tableKey] = new Dictionary<string, string>(data);
m_TablePrevManagerVariables[tableKey] = new Dictionary<string, string>(manager.GlobalProfileVariables);
}
if (table.Count == 0)
{
foreach (var globalVar in manager.GlobalProfileVariables)
table.AddOrUpdateItem(globalVar.Key, globalVar.Value);
foreach (var kvp in data)
table.AddOrUpdateItem(kvp.Key, kvp.Value);
}
var rowHeight = table.RowHeight;
var tableHeight = table.multiColumnHeader.height + rowHeight + (rowHeight * (data.Count() + manager.GlobalProfileVariables.Count)); // header + 1 extra line
table.OnGUI(EditorGUILayout.GetControlRect(false, tableHeight));
}
/// <inheritdoc/>
public void LogFormat(LogType logType, Object context, string format, params object[] args)
{
IHostingService svc = null;
if (args.Length > 0)
svc = args[args.Length - 1] as IHostingService;
if (svc != null)
{
m_LogText += string.Format("[{0}] ", svc.DescriptiveName) + string.Format(format, args) + "\n";
m_NewLogContent = true;
}
Debug.unityLogger.LogFormat(logType, context, format, args);
}
/// <inheritdoc/>
public void LogException(Exception exception, Object context)
{
Debug.unityLogger.LogException(exception, context);
}
/// <inheritdoc/>
public void OnBeforeSerialize()
{
// No implementation
}
/// <inheritdoc/>
public void OnAfterDeserialize()
{
// No implementation
}
}
}