using System; using System.Collections.Generic; using UnityEditor.AddressableAssets.Settings; using UnityEditor.IMGUI.Controls; using UnityEngine; using UnityEngine.AddressableAssets; #if (ENABLE_CCD && UNITY_2019_4_OR_NEWER) using Unity.Services.Ccd.Management.Models; #endif namespace UnityEditor.AddressableAssets.GUI { internal class ProfileWindow : EditorWindow { //Min and Max proportion of the window that ProfilePane can take up const float k_MinProfilePaneWidth = 0.10f; const float k_MaxProfilePaneWidth = 0.6f; private const float k_MinLabelWidth = 155f; private const float k_ApproxCharWidth = 8.5f; const float k_DefaultHorizontalSplitterRatio = 0.33f; const int k_SplitterThickness = 2; const int k_ToolbarHeight = 20; const int k_ItemRectPadding = 15; //amount of padding between variable items const float k_VariableItemPadding = 5f; //Default length of the Label within the Variables Pane private float m_LabelWidth = 155f; private float m_FieldBufferWidth = 0f; GUIStyle m_ItemRectPadding; float m_HorizontalSplitterRatio = k_DefaultHorizontalSplitterRatio; private ProfileDataSourceSettings m_ProfileDataSource; internal AddressableAssetSettings settings { get { return AddressableAssetSettingsDefaultObject.Settings; } } internal ProfileDataSourceSettings dataSourceSettings { get { if (m_ProfileDataSource == null) m_ProfileDataSource = ProfileDataSourceSettings.GetSettings(); return m_ProfileDataSource; } } private ProfileTreeView m_ProfileTreeView; private bool m_IsResizingHorizontalSplitter; internal static bool m_Reload = false; private Vector2 m_ProfilesPaneScrollPosition; private Vector2 m_VariablesPaneScrollPosition; private int m_ProfileIndex = -1; public int ProfileIndex { get { return m_ProfileIndex; } set { m_ProfileIndex = value; } } private GUIStyle m_ButtonStyle; private GUIContent m_CreateNewProfileOrVariablesGUIContent = new GUIContent("Create", "Create a new profile or profile variable(s)"); private Dictionary m_foldouts = new Dictionary(); private Dictionary m_CustomGroupTypes = new Dictionary(); [MenuItem("Window/Asset Management/Addressables/Profiles", priority = 2051)] internal static void ShowWindow() { AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.OpenProfilesWindow); var settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { EditorUtility.DisplayDialog("Error", "Attempting to open Addressables Profiles window, but no Addressables Settings file exists. \n\nOpen 'Window/Asset Management/Addressables/Groups' for more info.", "Ok"); return; } GetWindow().Show(); } 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; } #if (ENABLE_CCD && UNITY_2019_4_OR_NEWER) private async void Awake() { if (CloudProjectSettings.projectId != String.Empty) await ProfileDataSourceSettings.UpdateCCDDataSourcesAsync(CloudProjectSettings.projectId, false); } #endif private void OnEnable() { AddressableAnalytics.ReportUsageEvent(AddressableAnalytics.UsageEventType.OpenProfilesWindow, true); Undo.undoRedoPerformed += MarkForReload; titleContent = new GUIContent("Addressables Profiles"); m_ItemRectPadding = new GUIStyle(); m_ItemRectPadding.padding = new RectOffset(k_ItemRectPadding, k_ItemRectPadding, k_ItemRectPadding, k_ItemRectPadding); } private void OnDisable() { Undo.undoRedoPerformed -= MarkForReload; } internal static void MarkForReload() { m_Reload = true; } GUIStyle GetStyle(string styleName) { GUIStyle s = UnityEngine.GUI.skin.FindStyle(styleName); if (s == null) s = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle(styleName); if (s == null) { Addressables.LogError("Missing built-in guistyle " + styleName); s = new GUIStyle(); } return s; } void TopToolbar(Rect toolbarPos) { if (m_ButtonStyle == null) m_ButtonStyle = GetStyle("ToolbarButton"); m_ButtonStyle.alignment = TextAnchor.MiddleLeft; GUILayout.BeginArea(new Rect(0, 0, toolbarPos.width, k_ToolbarHeight)); GUILayout.BeginHorizontal(EditorStyles.toolbar); { Rect rMode = GUILayoutUtility.GetRect(m_CreateNewProfileOrVariablesGUIContent, EditorStyles.toolbarDropDown); if (EditorGUI.DropdownButton(rMode, m_CreateNewProfileOrVariablesGUIContent, FocusType.Passive, EditorStyles.toolbarDropDown)) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("Profile"), false, NewProfile); menu.AddItem(new GUIContent("Variable (All Profiles)"), false, () => NewVariable(rMode)); menu.AddItem(new GUIContent("Build and Load Path Variables (All Profiles)"), false, () => NewPathPair(rMode)); menu.DropDown(rMode); } GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); GUILayout.EndArea(); } void NewVariable(Rect displayRect) { try { displayRect.y += 22f; PopupWindow.Show(displayRect, new ProfileNewVariablePopup(position.width, position.height, 0, m_ProfileTreeView, settings)); } catch (ExitGUIException) { // Exception not being caught through OnGUI call } } void NewPathPair(Rect displayRect) { try { displayRect.y += 22f; PopupWindow.Show(displayRect, new ProfileNewPathPairPopup(position.width, position.height, 0, m_ProfileTreeView, settings)); } catch (ExitGUIException) { // Exception not being caught through OnGUI call } } //Contains all of the profile names, primarily implemented in ProfileTreeView void ProfilesPane(Rect profilesPaneRect) { DrawOutline(profilesPaneRect, 1); GUILayout.BeginArea(profilesPaneRect); { m_ProfilesPaneScrollPosition = GUILayout.BeginScrollView(m_ProfilesPaneScrollPosition); Rect r = new Rect(profilesPaneRect); r.y = 0; var profiles = settings.profileSettings.profiles; if (m_ProfileTreeView == null || m_ProfileTreeView.Names.Count != profiles.Count || m_Reload) { m_Reload = false; m_ProfileTreeView = new ProfileTreeView(new TreeViewState(), profiles, this, ProfileTreeView.CreateHeader()); } m_ProfileTreeView.OnGUI(r); GUILayout.EndScrollView(); } GUILayout.EndArea(); } //Displays all variables for the currently selected profile and initializes each variable's context menu void VariablesPane(Rect variablesPaneRect) { DrawOutline(variablesPaneRect, 1); Event evt = Event.current; AddressableAssetProfileSettings.BuildProfile selectedProfile = GetSelectedProfile(); if (selectedProfile == null) return; if (evt.isMouse || evt.isKey) { m_ProfileTreeView.lastClickedProfile = ProfileIndex; } //ensures amount of visible text is not affected by label width float fieldWidth = variablesPaneRect.width - (2 * k_ItemRectPadding) + m_FieldBufferWidth; if (!EditorGUIUtility.labelWidth.Equals(m_LabelWidth)) EditorGUIUtility.labelWidth = m_LabelWidth; int maxLabelLen = 0; int maxFieldLen = 0; GUILayout.BeginArea(variablesPaneRect); EditorGUI.indentLevel++; List groupTypes = ProfileGroupType.CreateGroupTypes(selectedProfile, settings); HashSet drawnGroupTypes = new HashSet(); //Displaying Path Groups foreach (ProfileGroupType groupType in groupTypes) { bool? foldout; m_foldouts.TryGetValue(groupType.GroupTypePrefix, out foldout); GUILayout.Space(5); Rect pathPairRect = EditorGUILayout.BeginHorizontal(new GUILayoutOption[] {GUILayout.Width(fieldWidth + k_VariableItemPadding - k_SplitterThickness), GUILayout.MinWidth(fieldWidth + k_VariableItemPadding - k_SplitterThickness)}); m_foldouts[groupType.GroupTypePrefix] = EditorGUILayout.Foldout(foldout != null ? foldout.Value : true, new GUIContent(groupType.GroupTypePrefix, "A pair of profile variables used for AssetBundles Build and Load Paths"), true); Rect dsDropdownRect = EditorGUILayout.BeginHorizontal(new GUILayoutOption[] {GUILayout.Width(fieldWidth - m_LabelWidth), GUILayout.MinWidth(fieldWidth - m_LabelWidth)}); string dropdownText = DetermineOptionString(groupType); bool dsDropdown = EditorGUILayout.DropdownButton(new GUIContent(dropdownText, "Location type"), FocusType.Keyboard, new GUILayoutOption[] {GUILayout.Width(fieldWidth - m_LabelWidth)}); if (evt.type == EventType.ContextClick) CreatePairPrefixContextMenu(variablesPaneRect, pathPairRect, groupType, evt); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal(); DrawDataSourceDropDowns(dsDropdownRect, groupType, dsDropdown); //Specific Grouped variables List pathVariables = new List(); pathVariables.Add(groupType.GetVariableBySuffix(AddressableAssetSettings.kBuildPath)); drawnGroupTypes.Add(groupType.GetName(groupType.GetVariableBySuffix(AddressableAssetSettings.kBuildPath))); pathVariables.Add(groupType.GetVariableBySuffix(AddressableAssetSettings.kLoadPath)); drawnGroupTypes.Add(groupType.GetName(groupType.GetVariableBySuffix(AddressableAssetSettings.kLoadPath))); if (m_foldouts[groupType.GroupTypePrefix].Value) { bool custom; m_CustomGroupTypes.TryGetValue(groupType.GroupTypePrefix, out custom); EditorGUI.BeginDisabledGroup(!custom); EditorGUI.indentLevel++; //Displaying Path Groups foreach (var variable in pathVariables) { Rect newPathRect = EditorGUILayout.BeginVertical(); string newPath = EditorGUILayout.TextField(new GUIContent(groupType.GetName(variable), "Profile variable representing a file path or url"), variable.Value, new GUILayoutOption[] {GUILayout.Width(fieldWidth)}); EditorGUILayout.EndVertical(); if (newPath != variable.Value && ProfileIndex == m_ProfileTreeView.lastClickedProfile) { Undo.RecordObject(settings, "Variable value changed"); settings.profileSettings.SetValue(selectedProfile.id, groupType.GetName(variable), newPath); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); } } EditorGUI.indentLevel--; EditorGUI.EndDisabledGroup(); } } //Display all other variables for (var i = 0; i < settings.profileSettings.profileEntryNames.Count; i++) { AddressableAssetProfileSettings.ProfileIdData curVariable = settings.profileSettings.profileEntryNames[i]; if (!drawnGroupTypes.Contains(curVariable.ProfileName)) { GUILayout.Space(5); Rect newValueRect = EditorGUILayout.BeginVertical(); string newValue = EditorGUILayout.TextField(new GUIContent(curVariable.ProfileName, "Profile variable"), selectedProfile.values[i].value, new GUILayoutOption[] {GUILayout.Width(fieldWidth)}); EditorGUILayout.EndVertical(); if (newValue != selectedProfile.values[i].value && ProfileIndex == m_ProfileTreeView.lastClickedProfile) { Undo.RecordObject(settings, "Variable value changed"); settings.profileSettings.SetValue(selectedProfile.id, settings.profileSettings.profileEntryNames[i].ProfileName, newValue); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); } if (evt.type == EventType.ContextClick) { CreateVariableContextMenu(variablesPaneRect, newValueRect, curVariable, evt); } } maxLabelLen = Math.Max(maxLabelLen, curVariable.ProfileName.Length); } EditorGUI.indentLevel--; GUILayout.EndArea(); //Update the label width to the maximum of the minimum acceptable label width and the amount of //space required to contain the longest variable name m_LabelWidth = Mathf.Max(maxLabelLen * k_ApproxCharWidth, k_MinLabelWidth); m_FieldBufferWidth = Mathf.Clamp((maxFieldLen * k_ApproxCharWidth) - fieldWidth, 0f, float.MaxValue); } void DrawDataSourceDropDowns(Rect dsDropdownRect, ProfileGroupType groupType, bool showDropdown) { Rect fixedDropdownRect = new Rect( //Determine correct position for dropdown window new Vector2( dsDropdownRect.x, dsDropdownRect.y ), new Vector2(dsDropdownRect.width, 120) ); if (showDropdown) { ProfileDataSourceDropdownWindow dataSourceDropdownWindow = new ProfileDataSourceDropdownWindow(fixedDropdownRect, groupType); //TODO: Add Event Handler Here dataSourceDropdownWindow.ValueChanged += DataSourceDropdownValueChanged; PopupWindow.Show(dsDropdownRect, dataSourceDropdownWindow); } } internal void DataSourceDropdownValueChanged(object sender, ProfileDataSourceDropdownWindow.DropdownWindowEventArgs e) { m_CustomGroupTypes[e.GroupType.GroupTypePrefix] = e.IsCustom; if (!e.IsCustom) { var selectedProfile = GetSelectedProfile(); Undo.RecordObject(settings, "Variable value changed"); settings.profileSettings.SetValue(selectedProfile.id, e.GroupType.GetName(e.GroupType.GetVariableBySuffix(AddressableAssetSettings.kBuildPath)), e.Option.BuildPath); settings.profileSettings.SetValue(selectedProfile.id, e.GroupType.GetName(e.GroupType.GetVariableBySuffix(AddressableAssetSettings.kLoadPath)), e.Option.LoadPath); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); } } private string DetermineOptionString(ProfileGroupType groupType) { ProfileGroupType selectedGroupType = dataSourceSettings.FindGroupType(groupType); if (selectedGroupType != null) { bool custom; m_CustomGroupTypes.TryGetValue(groupType.GroupTypePrefix, out custom); if (custom && ProfileIndex == m_ProfileTreeView.lastClickedProfile) return "Custom"; m_CustomGroupTypes[groupType.GroupTypePrefix] = false; #if (ENABLE_CCD && UNITY_2019_4_OR_NEWER) //Could ERR if user has group type prefix that starts with CCD if (selectedGroupType.GroupTypePrefix.StartsWith("CCD", StringComparison.Ordinal)) { var parts = selectedGroupType.GroupTypePrefix.Split(ProfileGroupType.k_PrefixSeparator); var badgeName = String.Join(ProfileGroupType.k_PrefixSeparator.ToString(), parts, 4, parts.Length - 4); var bucketName = selectedGroupType.GetVariableBySuffix($"{nameof(CcdBucket)}{nameof(CcdBucket.Name)}").Value; var environmentName = selectedGroupType.GetVariableBySuffix($"{nameof(ProfileDataSourceSettings.Environment)}{nameof(ProfileDataSourceSettings.Environment.name)}").Value; return String.Join(ProfileGroupType.k_PrefixSeparator.ToString(), new string[] { "CCD", environmentName, bucketName, badgeName }); } if (selectedGroupType.GroupTypePrefix == AddressableAssetSettings.CcdManagerGroupTypePrefix) { return $"{selectedGroupType.GroupTypePrefix} ({m_ProfileDataSource.currentEnvironment.name})"; } #endif return selectedGroupType.GroupTypePrefix; } else { m_CustomGroupTypes[groupType.GroupTypePrefix] = true; return "Custom"; } } void CreatePairPrefixContextMenu(Rect parentWindow, Rect menuRect, ProfileGroupType groupType, Event evt) { if (menuRect.Contains(evt.mousePosition)) { GenericMenu menu = new GenericMenu(); menu.AddDisabledItem(new GUIContent(groupType.GroupTypePrefix)); menu.AddSeparator(""); menu.AddItem(new GUIContent("Rename Path Prefix (All Profiles)"), false, () => { RenamePathPair(groupType, parentWindow, menuRect); }); menu.AddItem(new GUIContent("Delete Path Pair (All Profiles)"), false, () => { DeletePathPair(groupType); }); menu.ShowAsContext(); evt.Use(); } } //Creates the context menu for the selected variable void CreateVariableContextMenu(Rect parentWindow, Rect menuRect, AddressableAssetProfileSettings.ProfileIdData variable, Event evt) { if (menuRect.Contains(evt.mousePosition)) { GenericMenu menu = new GenericMenu(); //Displays name of selected variable so user can be confident they're deleting/renaming the right one menu.AddDisabledItem(new GUIContent(variable.ProfileName)); menu.AddSeparator(""); menu.AddItem(new GUIContent("Rename Variable (All Profiles)"), false, () => { RenameVariable(variable, parentWindow, menuRect); }); menu.AddItem(new GUIContent("Delete Variable (All Profiles)"), false, () => { DeleteVariable(variable); }); menu.ShowAsContext(); evt.Use(); } } void RenamePathPair(ProfileGroupType groupType, Rect parentWindow, Rect displayRect) { try { //Determines the current variable rect location Rect variableRect = new Rect(parentWindow.x + 2.5f, displayRect.y + 1.5f, m_LabelWidth, k_ToolbarHeight * 2); PopupWindow.Show(variableRect, new PathPairRenamePopup(m_LabelWidth, groupType, settings)); } catch (ExitGUIException) { // Exception not being caught through OnGUI call } } //Opens ProfileRenameVariablePopup void RenameVariable(AddressableAssetProfileSettings.ProfileIdData profileVariable, Rect parentWindow, Rect displayRect) { try { //Determines the current variable rect location Rect variableRect = new Rect(parentWindow.x + 2.5f, displayRect.y + 1.5f, m_LabelWidth, k_ToolbarHeight * 2); PopupWindow.Show(variableRect, new ProfileRenameVariablePopup(m_LabelWidth, profileVariable, settings)); } catch (ExitGUIException) { // Exception not being caught through OnGUI call } } void DeletePathPair(ProfileGroupType groupType) { var buildPathData = settings.profileSettings.GetProfileDataByName(groupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kBuildPath); var loadPathData = settings.profileSettings.GetProfileDataByName(groupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kLoadPath); if (loadPathData == default(AddressableAssetProfileSettings.ProfileIdData) || buildPathData == default(AddressableAssetProfileSettings.ProfileIdData)) { Debug.LogError("An error occured while getting one of the path pair variables."); return; } Undo.RecordObject(settings, "Profile Variable Deleted"); settings.profileSettings.RemoveValue(buildPathData.Id); settings.profileSettings.RemoveValue(loadPathData.Id); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); } void DeleteVariable(AddressableAssetProfileSettings.ProfileIdData toBeDeleted) { Undo.RecordObject(settings, "Profile Variable Deleted"); settings.profileSettings.RemoveValue(toBeDeleted.Id); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); } //Returns the BuildProfile currently selected in the ProfilesPane AddressableAssetProfileSettings.BuildProfile GetSelectedProfile() { return m_ProfileTreeView.GetSelectedProfile(); } //Creates a new BuildProfile and reloads the ProfilesPane void NewProfile() { var uniqueProfileName = settings.profileSettings.GetUniqueProfileName("New Profile"); if (!string.IsNullOrEmpty(uniqueProfileName)) { Undo.RecordObject(settings, "New Profile Created"); //Either copy values from the selected profile, or if there is no selected profile, copy from the default string idToCopyFrom = GetSelectedProfile() != null ? GetSelectedProfile().id : settings.profileSettings.profiles[0].id; settings.profileSettings.AddProfile(uniqueProfileName, idToCopyFrom); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); m_ProfileTreeView.Reload(); } } private void OnGUI() { if (settings == null) return; if (m_IsResizingHorizontalSplitter) m_HorizontalSplitterRatio = Mathf.Clamp(Event.current.mousePosition.x / position.width, k_MinProfilePaneWidth, k_MaxProfilePaneWidth); var toolbarRect = new Rect(0, 0, position.width, position.height); var profilesPaneRect = new Rect(0, k_ToolbarHeight, (position.width * m_HorizontalSplitterRatio), position.height); var variablesPaneRect = new Rect(profilesPaneRect.width + k_SplitterThickness, k_ToolbarHeight, position.width - profilesPaneRect.width - k_SplitterThickness, position.height - k_ToolbarHeight); var horizontalSplitterRect = new Rect(profilesPaneRect.width, k_ToolbarHeight, k_SplitterThickness, position.height - k_ToolbarHeight); EditorGUIUtility.AddCursorRect(horizontalSplitterRect, MouseCursor.ResizeHorizontal); if (Event.current.type == EventType.MouseDown && horizontalSplitterRect.Contains(Event.current.mousePosition)) m_IsResizingHorizontalSplitter = true; else if (Event.current.type == EventType.MouseUp) m_IsResizingHorizontalSplitter = false; TopToolbar(toolbarRect); ProfilesPane(profilesPaneRect); VariablesPane(variablesPaneRect); if (m_IsResizingHorizontalSplitter) Repaint(); } class PathPairRenamePopup : PopupWindowContent { internal Rect m_WindowRect; internal ProfileGroupType m_ProfileGroupType; internal List m_AllProfileGroupTypes; internal AddressableAssetSettings m_Settings; internal string m_NewName; internal float m_LabelWidth; public PathPairRenamePopup(float labelWidth, ProfileGroupType profileGroupType, AddressableAssetSettings settings) { m_LabelWidth = labelWidth; m_ProfileGroupType = profileGroupType; m_Settings = settings; m_NewName = profileGroupType.GroupTypePrefix; UnityEngine.GUI.enabled = true; } public override Vector2 GetWindowSize() { return new Vector2(m_LabelWidth, 40); } public override void OnGUI(Rect windowRect) { GUILayout.BeginArea(windowRect); Event evt = Event.current; bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); m_NewName = GUILayout.TextField(m_NewName); if (GUILayout.Button("Save") || hitEnter) { if (string.IsNullOrEmpty(m_NewName)) Debug.LogError("Path pair prefix cannot be empty."); else if (m_NewName == m_ProfileGroupType.GroupTypePrefix) editorWindow.Close(); else if (VariableWithNewPrefixAlreadyExists()) Debug.LogError("One or more build or load path variables with prefix '" + m_NewName + "' already exist. Please rename them or pick a different prefix."); else if (m_NewName.Trim().Length == 0) // new name cannot only contain spaces Debug.LogError("Path pair prefix cannot be only spaces"); else { var loadPathVariableData = m_Settings.profileSettings.GetProfileDataByName(m_ProfileGroupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kLoadPath); var buildPathVariableData = m_Settings.profileSettings.GetProfileDataByName(m_ProfileGroupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kBuildPath); if (loadPathVariableData == default(AddressableAssetProfileSettings.ProfileIdData) || buildPathVariableData == default(AddressableAssetProfileSettings.ProfileIdData)) Debug.LogError("Valid path pair to rename not found."); else { Undo.RecordObject(m_Settings, "Path pair prefix Renamed"); m_ProfileGroupType.GroupTypePrefix = m_NewName; loadPathVariableData.SetName(m_ProfileGroupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kLoadPath, m_Settings.profileSettings); buildPathVariableData.SetName(m_ProfileGroupType.GroupTypePrefix + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kBuildPath, m_Settings.profileSettings); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(m_Settings, true); editorWindow.Close(); } } } GUILayout.EndArea(); } bool VariableWithNewPrefixAlreadyExists() { bool loadPathAlreadyExists = m_Settings.profileSettings.GetProfileDataByName(m_NewName + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kLoadPath) != default(AddressableAssetProfileSettings.ProfileIdData); bool buildPathAlreadyExists = m_Settings.profileSettings.GetProfileDataByName(m_NewName + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kBuildPath) != default(AddressableAssetProfileSettings.ProfileIdData); return loadPathAlreadyExists || buildPathAlreadyExists; } } class ProfileRenameVariablePopup : PopupWindowContent { internal float m_LabelWidth; internal AddressableAssetProfileSettings.ProfileIdData m_ProfileVariable; internal AddressableAssetSettings m_Settings; internal string m_NewName; public ProfileRenameVariablePopup(float labelWidth, AddressableAssetProfileSettings.ProfileIdData profileVariable, AddressableAssetSettings settings) { m_LabelWidth = labelWidth; m_ProfileVariable = profileVariable; m_Settings = settings; m_NewName = m_ProfileVariable.ProfileName; UnityEngine.GUI.enabled = true; } public override Vector2 GetWindowSize() { return new Vector2(m_LabelWidth, 40); } public override void OnGUI(Rect windowRect) { GUILayout.BeginArea(windowRect); Event evt = Event.current; bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); m_NewName = GUILayout.TextField(m_NewName); if (GUILayout.Button("Save") || hitEnter) { if (string.IsNullOrEmpty(m_NewName)) Debug.LogError("Variable name cannot be empty."); else if (m_NewName == m_ProfileVariable.ProfileName) editorWindow.Close(); else if (m_NewName != m_Settings.profileSettings.GetUniqueProfileEntryName(m_NewName)) Debug.LogError("Profile variable '" + m_NewName + "' already exists."); else if (m_NewName.Trim().Length == 0) // new name cannot only contain spaces Debug.LogError("Name cannot be only spaces"); else { Undo.RecordObject(m_Settings, "Profile Variable Renamed"); m_ProfileVariable.SetName(m_NewName, m_Settings.profileSettings); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(m_Settings, true); editorWindow.Close(); } } GUILayout.EndArea(); } } class ProfileNewVariablePopup : PopupWindowContent { internal float m_WindowWidth; internal float m_WindowHeight; internal float m_xOffset; internal string m_Name; internal string m_Value; internal bool m_NeedsFocus = true; internal AddressableAssetSettings m_Settings; ProfileTreeView m_ProfileTreeView; public ProfileNewVariablePopup(float width, float height, float xOffset, ProfileTreeView profileTreeView, AddressableAssetSettings settings) { m_WindowWidth = width; m_WindowHeight = height; m_xOffset = xOffset; m_Settings = settings; m_Name = m_Settings.profileSettings.GetUniqueProfileEntryName("New Entry"); m_Value = Application.dataPath; m_ProfileTreeView = profileTreeView; } public override Vector2 GetWindowSize() { float width = Mathf.Clamp(m_WindowWidth * 0.375f, Mathf.Min(600, m_WindowWidth - m_xOffset), m_WindowWidth); float height = Mathf.Clamp(65, Mathf.Min(65, m_WindowHeight), m_WindowHeight); return new Vector2(width, height); } public override void OnGUI(Rect windowRect) { GUILayout.Space(5); Event evt = Event.current; bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); EditorGUIUtility.labelWidth = 90; m_Name = EditorGUILayout.TextField("Variable Name", m_Name); m_Value = EditorGUILayout.TextField("Default Value", m_Value); UnityEngine.GUI.enabled = m_Name.Length != 0; if (GUILayout.Button("Save") || hitEnter) { if (string.IsNullOrEmpty(m_Name)) Debug.LogError("Variable name cannot be empty."); else if (m_Name != m_Settings.profileSettings.GetUniqueProfileEntryName(m_Name)) Debug.LogError("Profile variable '" + m_Name + "' already exists."); else { Undo.RecordObject(m_Settings, "Profile Variable " + m_Name + " Created"); m_Settings.profileSettings.CreateValue(m_Name, m_Value); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(m_Settings); m_ProfileTreeView.Reload(); editorWindow.Close(); } } } } class ProfileNewPathPairPopup : PopupWindowContent { internal float m_WindowWidth; internal float m_WindowHeight; internal float m_xOffset; internal string m_Name; internal string m_BuildPath; internal string m_LoadPath; internal bool m_NeedsFocus = true; internal AddressableAssetSettings m_Settings; ProfileTreeView m_ProfileTreeView; public ProfileNewPathPairPopup(float width, float height, float xOffset, ProfileTreeView profileTreeView, AddressableAssetSettings settings) { m_WindowWidth = width; m_WindowHeight = height; m_xOffset = xOffset; m_Settings = settings; m_Name = m_Settings.profileSettings.GetUniqueProfileEntryName("New Entry"); m_BuildPath = Application.dataPath; m_LoadPath = Application.dataPath; m_ProfileTreeView = profileTreeView; } public override Vector2 GetWindowSize() { float width = Mathf.Clamp(m_WindowWidth * 0.375f, Mathf.Min(600, m_WindowWidth - m_xOffset), m_WindowWidth); float height = Mathf.Clamp(85, Mathf.Min(85, m_WindowHeight), m_WindowHeight); return new Vector2(width, height); } public override void OnGUI(Rect windowRect) { GUILayout.Space(5); Event evt = Event.current; bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); EditorGUIUtility.labelWidth = 120; m_Name = EditorGUILayout.TextField("Prefix Name", m_Name); m_BuildPath = EditorGUILayout.TextField("Build Path Value", m_BuildPath); m_LoadPath = EditorGUILayout.TextField("Load Path Value", m_LoadPath); UnityEngine.GUI.enabled = m_Name.Length != 0; if (GUILayout.Button("Save") || hitEnter) { string buildPathName = m_Name + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kBuildPath; string loadPathName = m_Name + ProfileGroupType.k_PrefixSeparator + AddressableAssetSettings.kLoadPath; if (string.IsNullOrEmpty(m_Name)) Debug.LogError("Variable name cannot be empty."); else if (buildPathName != m_Settings.profileSettings.GetUniqueProfileEntryName(buildPathName)) Debug.LogError("Profile variable '" + buildPathName + "' already exists."); else if (loadPathName != m_Settings.profileSettings.GetUniqueProfileEntryName(loadPathName)) Debug.LogError("Profile variable '" + loadPathName + "' already exists."); else { Undo.RecordObject(m_Settings, "Profile Path Pair Created"); m_Settings.profileSettings.CreateValue(buildPathName, m_BuildPath); m_Settings.profileSettings.CreateValue(loadPathName, m_LoadPath); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(m_Settings); m_ProfileTreeView.Reload(); editorWindow.Close(); } } } } } }