Skip to content

Commit c8b4561

Browse files
refactor(core): share dropdown helpers and refresh Panel on focus
Extract WithNoneOption / ResolveDropdownValue / NormalizeDropdownSelection plus the NoneDropdownOption constant into EditorUtils so the three package-dropdown call sites (SettingsUIBuilder, BootstrapEditorUI, PanelUI) no longer each reimplement the same sentinel / fallback / clear-on-None logic. Additionally override Panel.OnFocus to rebuild its content when the window regains focus, so the Package dropdown reflects renames made in the AssetBundle Collector window without having to close and reopen the Panel. Skipped while a build is in progress to avoid losing BuildManager state and the log view contents. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
1 parent 6fdbad2 commit c8b4561

3 files changed

Lines changed: 58 additions & 12 deletions

File tree

UnityProject/Packages/com.jasonxudeveloper.jengine.core/Editor/CustomEditor/Panel.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ private void CreateGUI()
7373
CreateDefaultGUI();
7474
}
7575

76+
/// <summary>
77+
/// Rebuilds the panel when it regains focus so dropdown choices (e.g. YooAsset
78+
/// packages, hot scenes) reflect changes made in other editor windows. Skipped mid-build
79+
/// to avoid losing <see cref="BuildManager"/> state or the log view contents.
80+
/// </summary>
81+
private void OnFocus()
82+
{
83+
if (_root == null) return;
84+
if (_buildManager != null && _buildManager.IsBuilding) return;
85+
86+
_root.Clear();
87+
CreateGUI();
88+
}
89+
7690
private void CreateDefaultGUI()
7791
{
7892
// Load stylesheets - Panel first, then Common to override

UnityProject/Packages/com.jasonxudeveloper.jengine.core/Editor/CustomEditor/SettingsUIBuilder.cs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,26 +46,19 @@ public static VisualElement CreatePackageSettingsGroup(Settings settings)
4646
// Package Name field (dropdown or text field based on useDropdown)
4747
var packageNameRow = EditorUIUtils.CreateFormRow("Package");
4848

49-
// Use PopupField for Panel (with available packages). Prepend a "None" sentinel so
50-
// the dropdown always has >=2 entries and renamed/missing packages surface as "None"
51-
// instead of silently desyncing with the serialized value.
52-
const string noneOption = "None";
53-
var packageOptions = new List<string> { noneOption };
54-
packageOptions.AddRange(EditorUtils.GetAvailableYooAssetPackages());
55-
var currentPackage = string.IsNullOrEmpty(settings.packageName) ||
56-
!packageOptions.Contains(settings.packageName)
57-
? noneOption
58-
: settings.packageName;
49+
// Prepend a "None" sentinel so renamed/missing packages surface as "None" instead of
50+
// silently desyncing with the serialized value.
51+
var packageOptions = EditorUtils.WithNoneOption(EditorUtils.GetAvailableYooAssetPackages());
5952
var packageNameField = new PopupField<string>()
6053
{
6154
choices = packageOptions,
62-
value = currentPackage
55+
value = EditorUtils.ResolveDropdownValue(settings.packageName, packageOptions)
6356
};
6457
packageNameField.AddToClassList("form-control");
6558
EditorUIUtils.MakeTextResponsive(packageNameField);
6659
packageNameField.RegisterValueChangedCallback(evt =>
6760
{
68-
settings.packageName = evt.newValue == noneOption ? string.Empty : evt.newValue;
61+
settings.packageName = EditorUtils.NormalizeDropdownSelection(evt.newValue);
6962
settings.Save();
7063
});
7164
packageNameRow.Add(packageNameField);

UnityProject/Packages/com.jasonxudeveloper.jengine.core/Editor/EditorUtils.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,45 @@ namespace JEngine.Core.Editor
3636
{
3737
public static class EditorUtils
3838
{
39+
/// <summary>
40+
/// Sentinel shown in dropdowns when the stored value is missing or no longer in the
41+
/// available choices (e.g. a YooAsset package was renamed). Guarantees >=2 entries and
42+
/// gives the user an explicit "clear" option.
43+
/// </summary>
44+
public const string NoneDropdownOption = "None";
45+
46+
/// <summary>
47+
/// Returns a new list with <see cref="NoneDropdownOption"/> prepended to the given
48+
/// choices. Safe to call with a null choices list.
49+
/// </summary>
50+
public static List<string> WithNoneOption(IList<string> choices)
51+
{
52+
var options = new List<string> { NoneDropdownOption };
53+
if (choices != null) options.AddRange(choices);
54+
return options;
55+
}
56+
57+
/// <summary>
58+
/// Returns the value that should be displayed in a dropdown. Falls back to
59+
/// <see cref="NoneDropdownOption"/> when the stored value is empty or no longer present
60+
/// in the current options.
61+
/// </summary>
62+
public static string ResolveDropdownValue(string storedValue, List<string> options)
63+
{
64+
return string.IsNullOrEmpty(storedValue) || options == null || !options.Contains(storedValue)
65+
? NoneDropdownOption
66+
: storedValue;
67+
}
68+
69+
/// <summary>
70+
/// Converts a dropdown selection into the value to persist. The sentinel
71+
/// <see cref="NoneDropdownOption"/> is mapped to an empty string.
72+
/// </summary>
73+
public static string NormalizeDropdownSelection(string value)
74+
{
75+
return value == NoneDropdownOption ? string.Empty : value;
76+
}
77+
3978
public static List<string> GetAvailableYooAssetPackages()
4079
{
4180
var packages = new List<string>();

0 commit comments

Comments
 (0)