diff --git a/ComponentSelectorAdditions/Events/EnumerateCategoriesEvent.cs b/ComponentSelectorAdditions/Events/EnumerateCategoriesEvent.cs index 0dc1188..6351ed2 100644 --- a/ComponentSelectorAdditions/Events/EnumerateCategoriesEvent.cs +++ b/ComponentSelectorAdditions/Events/EnumerateCategoriesEvent.cs @@ -6,7 +6,7 @@ namespace ComponentSelectorAdditions.Events { - public sealed class EnumerateCategoriesEvent : CancelableSortedItemsEvent> + public sealed class EnumerateCategoriesEvent : CancelableSortedItemsEvent>, IEnumerateSelectorResultEvent { public override IEnumerable> Items => sortableItems.OrderBy(entry => entry.Value) diff --git a/ComponentSelectorAdditions/Events/EnumerateComponentsEvent.cs b/ComponentSelectorAdditions/Events/EnumerateComponentsEvent.cs index 82b08d8..bd14af6 100644 --- a/ComponentSelectorAdditions/Events/EnumerateComponentsEvent.cs +++ b/ComponentSelectorAdditions/Events/EnumerateComponentsEvent.cs @@ -7,7 +7,7 @@ namespace ComponentSelectorAdditions.Events { - public sealed class EnumerateComponentsEvent : CancelableSortedItemsEvent + public sealed class EnumerateComponentsEvent : CancelableSortedItemsEvent, IEnumerateSelectorResultEvent { public Predicate ComponentFilter { get; } diff --git a/ComponentSelectorAdditions/Events/IEnumerateSelectorResultEvent.cs b/ComponentSelectorAdditions/Events/IEnumerateSelectorResultEvent.cs new file mode 100644 index 0000000..3344bf0 --- /dev/null +++ b/ComponentSelectorAdditions/Events/IEnumerateSelectorResultEvent.cs @@ -0,0 +1,14 @@ +using FrooxEngine; +using System; +using System.Collections.Generic; +using System.Text; + +namespace ComponentSelectorAdditions.Events +{ + public interface IEnumerateSelectorResultEvent + { + public SelectorPath Path { get; } + public CategoryNode RootCategory { get; } + public ComponentSelector Selector { get; } + } +} \ No newline at end of file diff --git a/ComponentSelectorAdditions/Injector.cs b/ComponentSelectorAdditions/Injector.cs index b03fbce..2165854 100644 --- a/ComponentSelectorAdditions/Injector.cs +++ b/ComponentSelectorAdditions/Injector.cs @@ -107,7 +107,7 @@ private static void BuildCategoryUI(ComponentSelector selector, UIBuilder ui, Se if (rootCategory is null) { - selector._rootPath.Value = null; + selector._rootPath.Value = null!; selectorData.CurrentPath = new SelectorPath("/", selectorData.CurrentPath.Search, false, null, true); rootCategory = WorkerInitializer.ComponentLibrary; } @@ -224,7 +224,7 @@ private static bool BuildUIPrefix(ComponentSelector __instance, string path, boo __instance._uiRoot.Target.DestroyChildren(); __instance._customGenericArguments.Clear(); - __instance._genericType.Value = null; + __instance._genericType.Value = null!; var ui = SetupStyle(new UIBuilder(__instance._uiRoot.Target)); @@ -314,8 +314,8 @@ private static BuildCustomGenericBuilder OnBuildCustomGenericBuilder(ComponentSe if (!eventData.AddsCreateCustomTypeButton) Logger.Warn(() => "No event handler handled adding a create custom type button!"); - selector._customGenericTypeLabel.Target = eventData.CreateCustomTypeButton?.Label.Content; - selector._customGenericTypeColor.Target = eventData.CreateCustomTypeButton?.BaseColor; + selector._customGenericTypeLabel.Target = eventData.CreateCustomTypeButton?.Label.Content!; + selector._customGenericTypeColor.Target = eventData.CreateCustomTypeButton?.BaseColor!; return eventData; } @@ -465,7 +465,7 @@ private static bool SetupUIPrefix(ComponentSelector __instance, LocaleString tit if (selectorData.HasSearchBar) selectorData.SearchBar.Text.Content.OnValueChange += MakeBuildUICall(__instance, selectorData); - __instance.BuildUI(null); + __instance.BuildUI(null!); return false; } diff --git a/ComponentSelectorAdditions/SearchBar.cs b/ComponentSelectorAdditions/SearchBar.cs index d2c3ccb..fb48c80 100644 --- a/ComponentSelectorAdditions/SearchBar.cs +++ b/ComponentSelectorAdditions/SearchBar.cs @@ -18,6 +18,7 @@ namespace ComponentSelectorAdditions internal sealed class SearchBar : ConfiguredResoniteMonkey, IEventHandler, ICancelableEventHandler, ICancelableEventHandler { + private const string ProtoFluxPath = "/ProtoFlux/Runtimes/Execution/Nodes"; private static readonly char[] _searchSplits = new[] { ' ', ',', '+', '|' }; public override bool CanBeDisabled => true; public int Priority => HarmonyLib.Priority.VeryHigh; @@ -39,7 +40,7 @@ public void Handle(BuildSelectorHeaderEvent eventData) searchLayout.DestroyWhenLocalUserLeaves(); ui.Style.FlexibleWidth = 1; - var textField = ui.TextField(null, parseRTF: false); + var textField = ui.TextField(null!, parseRTF: false); var details = new SelectorSearchBar(searchLayout, textField.Editor.Target, () => ConfigSection.SearchRefreshDelay); eventData.SearchBar = details; @@ -48,7 +49,10 @@ public void Handle(BuildSelectorHeaderEvent eventData) ui.Style.FlexibleWidth = -1; ui.Style.ButtonTextAlignment = Alignment.MiddleCenter; - ui.LocalActionButton("∅", _ => details.Content = null); + + var clearButton = ui.Button("∅"); + var clearAction = clearButton.Slot.AttachComponent>(); + clearAction.TargetValue.Target = details.Text.Content; ui.PopStyle(); ui.NestOut(); @@ -56,12 +60,12 @@ public void Handle(BuildSelectorHeaderEvent eventData) public void Handle(EnumerateCategoriesEvent eventData) { - if (!eventData.Path.HasSearch || (eventData.Path.IsSelectorRoot && eventData.Path.Search.Length < 3)) + if (!eventData.Path.HasSearch || ((eventData.Path.IsSelectorRoot || ConfigSection.AlwaysSearchRoot) && eventData.Path.Search.Length < 3)) return; var search = eventData.Path.Search.Split(_searchSplits, StringSplitOptions.RemoveEmptyEntries); - foreach (var category in SearchCategories(eventData.RootCategory, search)) + foreach (var category in SearchCategories(PickSearchCategory(eventData), search)) eventData.AddItem(category); eventData.Canceled = true; @@ -73,10 +77,12 @@ public void Handle(EnumerateComponentsEvent eventData) return; var search = eventData.Path.Search.Split(_searchSplits, StringSplitOptions.RemoveEmptyEntries); - var results = eventData.RootCategory.Elements - .Select(type => (Category: eventData.RootCategory, Type: type, Matches: SearchContains(type.Name, search))) + var searchCategory = PickSearchCategory(eventData); + + var results = searchCategory.Elements + .Select(type => (Category: searchCategory, Type: type, Matches: SearchContains(type.Name, search))) .Concat( - SearchCategories(eventData.RootCategory) + SearchCategories(searchCategory) .SelectMany(category => category.Elements .Select(type => (Category: category, Type: type, Matches: SearchContains(type.Name, search))))) .Where(match => match.Matches > 0) @@ -141,5 +147,16 @@ private static IEnumerable> SearchCategories(CategoryNode needles.Count(needle => CultureInfo.InvariantCulture.CompareInfo.IndexOf(haystack, needle, CompareOptions.IgnoreCase) >= 0); + + private CategoryNode PickSearchCategory(IEnumerateSelectorResultEvent eventData) + { + var isProtoFlux = eventData.Path.Path.StartsWith(ProtoFluxPath); + + return ConfigSection.AlwaysSearchRoot + ? (isProtoFlux + ? WorkerInitializer.ComponentLibrary.GetSubcategory(ProtoFluxPath) + : WorkerInitializer.ComponentLibrary) + : eventData.RootCategory; + } } } \ No newline at end of file diff --git a/ComponentSelectorAdditions/SearchConfig.cs b/ComponentSelectorAdditions/SearchConfig.cs index e68a168..5a39cca 100644 --- a/ComponentSelectorAdditions/SearchConfig.cs +++ b/ComponentSelectorAdditions/SearchConfig.cs @@ -20,6 +20,7 @@ namespace ComponentSelectorAdditions /// public sealed class SearchConfig : ConfigSection { + private static readonly DefiningConfigKey _alwaysSearchRoot = new("AlwaysSearchRoot", "Always starts searching from the root category, regardless of the current one.", () => false); private static readonly Dictionary _excludedCategories = new(StringComparer.OrdinalIgnoreCase); private static readonly DefiningConfigKey _maxResultCount = new("MaxResultCount", "The maximum number of component / node results to display. 'Better' results are listed first. Categories don't count.", () => 64) @@ -49,6 +50,7 @@ public sealed class SearchConfig : ConfigSection /// public override Version Version { get; } = new(1, 0, 0); + internal bool AlwaysSearchRoot => _alwaysSearchRoot; internal int MaxResultCount => _maxResultCount; internal int SearchRefreshDelay => (int)(1000 * _searchRefreshDelay); diff --git a/ComponentSelectorAdditions/SelectorSearchBar.cs b/ComponentSelectorAdditions/SelectorSearchBar.cs index 69f2e8a..64d8eb3 100644 --- a/ComponentSelectorAdditions/SelectorSearchBar.cs +++ b/ComponentSelectorAdditions/SelectorSearchBar.cs @@ -33,7 +33,7 @@ public bool Active public string? Content { get => Active ? Text.Content.Value : null; - set => Text.Content.Value = value; + set => Text.Content.Value = value!; } ///