Map Editor - Tiles' filters multiple selection

This commit is contained in:
rob-v
2018-12-31 17:18:54 +01:00
committed by Paul Chote
parent f18d874524
commit 8c94f262b6
5 changed files with 83 additions and 126 deletions

View File

@@ -38,26 +38,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
} }
readonly DropDownButtonWidget ownersDropDown; readonly DropDownButtonWidget ownersDropDown;
readonly ScrollPanelWidget panel;
readonly ScrollItemWidget itemTemplate;
readonly Ruleset mapRules; readonly Ruleset mapRules;
readonly ActorSelectorActor[] allActors; readonly ActorSelectorActor[] allActors;
PlayerReference selectedOwner; PlayerReference selectedOwner;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ActorSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer) public ActorSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer)
: base(widget, world, worldRenderer) : base(widget, world, worldRenderer, "ACTORTEMPLATE_LIST", "ACTORPREVIEW_TEMPLATE")
{ {
mapRules = world.Map.Rules; mapRules = world.Map.Rules;
ownersDropDown = widget.Get<DropDownButtonWidget>("OWNERS_DROPDOWN"); ownersDropDown = widget.Get<DropDownButtonWidget>("OWNERS_DROPDOWN");
panel = widget.Get<ScrollPanelWidget>("ACTORTEMPLATE_LIST");
itemTemplate = panel.Get<ScrollItemWidget>("ACTORPREVIEW_TEMPLATE");
panel.Layout = new GridLayout(panel);
var editorLayer = world.WorldActor.Trait<EditorActorLayer>(); var editorLayer = world.WorldActor.Trait<EditorActorLayer>();
selectedOwner = editorLayer.Players.Players.Values.First(); selectedOwner = editorLayer.Players.Players.Values.First();
@@ -136,10 +127,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
FilteredCategories.Add(c); FilteredCategories.Add(c);
} }
var searchTextField = widget.Get<TextFieldWidget>("SEARCH_TEXTFIELD"); SearchTextField.OnTextEdited = () =>
searchTextField.OnTextEdited = () =>
{ {
searchFilter = searchTextField.Text.Trim(); searchFilter = SearchTextField.Text.Trim();
FilteredCategories.Clear(); FilteredCategories.Clear();
if (!string.IsNullOrEmpty(searchFilter)) if (!string.IsNullOrEmpty(searchFilter))
@@ -155,40 +145,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
InitializePreviews(); InitializePreviews();
}; };
searchTextField.OnEscKey = () =>
{
searchTextField.Text = "";
searchTextField.YieldKeyboardFocus();
return true;
};
var actorCategorySelector = widget.Get<DropDownButtonWidget>("CATEGORIES_DROPDOWN");
actorCategorySelector.GetText = () =>
{
if (SelectedCategories.Count == 0)
return "None";
if (!string.IsNullOrEmpty(searchFilter))
return "Search Results";
if (SelectedCategories.Count == 1)
return SelectedCategories.First();
if (SelectedCategories.Count == allCategories.Length)
return "All";
return "Multiple";
};
actorCategorySelector.OnMouseDown = _ =>
{
if (searchTextField != null)
searchTextField.YieldKeyboardFocus();
actorCategorySelector.RemovePanel();
actorCategorySelector.AttachPanel(CreateCategoriesPanel(panel));
};
InitializePreviews(); InitializePreviews();
} }
@@ -202,7 +158,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
protected override void InitializePreviews() protected override void InitializePreviews()
{ {
panel.RemoveChildren(); Panel.RemoveChildren();
if (!SelectedCategories.Any()) if (!SelectedCategories.Any())
return; return;
@@ -224,7 +180,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
try try
{ {
var item = ScrollItemWidget.Setup(itemTemplate, var item = ScrollItemWidget.Setup(ItemTemplate,
() => { var brush = Editor.CurrentBrush as EditorActorBrush; return brush != null && brush.Actor == actor; }, () => { var brush = Editor.CurrentBrush as EditorActorBrush; return brush != null && brush.Actor == actor; },
() => Editor.SetBrush(new EditorActorBrush(Editor, actor, selectedOwner, WorldRenderer))); () => Editor.SetBrush(new EditorActorBrush(Editor, actor, selectedOwner, WorldRenderer)));
@@ -233,8 +189,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Scale templates to fit within the panel // Scale templates to fit within the panel
var scale = 1f; var scale = 1f;
if (scale * preview.IdealPreviewSize.X > itemTemplate.Bounds.Width) if (scale * preview.IdealPreviewSize.X > ItemTemplate.Bounds.Width)
scale = (itemTemplate.Bounds.Width - panel.ItemSpacing) / (float)preview.IdealPreviewSize.X; scale = (ItemTemplate.Bounds.Width - Panel.ItemSpacing) / (float)preview.IdealPreviewSize.X;
preview.GetScale = () => scale; preview.GetScale = () => scale;
preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.X); preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.X);
@@ -246,7 +202,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
item.GetTooltipText = () => a.Tooltip; item.GetTooltipText = () => a.Tooltip;
panel.AddChild(item); Panel.AddChild(item);
} }
catch catch
{ {

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Widgets; using OpenRA.Widgets;
@@ -19,9 +20,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public abstract class CommonSelectorLogic : ChromeLogic public abstract class CommonSelectorLogic : ChromeLogic
{ {
protected readonly Widget Widget; protected readonly Widget Widget;
protected readonly TextFieldWidget SearchTextField;
protected readonly World World; protected readonly World World;
protected readonly WorldRenderer WorldRenderer; protected readonly WorldRenderer WorldRenderer;
protected readonly EditorViewportControllerWidget Editor; protected readonly EditorViewportControllerWidget Editor;
protected readonly ScrollPanelWidget Panel;
protected readonly ScrollItemWidget ItemTemplate;
protected readonly HashSet<string> SelectedCategories = new HashSet<string>(); protected readonly HashSet<string> SelectedCategories = new HashSet<string>();
protected readonly List<string> FilteredCategories = new List<string>(); protected readonly List<string> FilteredCategories = new List<string>();
@@ -29,17 +33,55 @@ namespace OpenRA.Mods.Common.Widgets.Logic
protected string[] allCategories; protected string[] allCategories;
protected string searchFilter; protected string searchFilter;
public CommonSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer) public CommonSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer, string templateListId, string previewTemplateId)
{ {
this.Widget = widget; this.Widget = widget;
this.World = world; this.World = world;
this.WorldRenderer = worldRenderer; this.WorldRenderer = worldRenderer;
Editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR"); Editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
Panel = widget.Get<ScrollPanelWidget>(templateListId);
ItemTemplate = Panel.Get<ScrollItemWidget>(previewTemplateId);
Panel.Layout = new GridLayout(Panel);
SearchTextField = widget.Get<TextFieldWidget>("SEARCH_TEXTFIELD");
SearchTextField.OnEscKey = () =>
{
SearchTextField.Text = "";
SearchTextField.YieldKeyboardFocus();
return true;
};
var categorySelector = widget.Get<DropDownButtonWidget>("CATEGORIES_DROPDOWN");
categorySelector.GetText = () =>
{
if (SelectedCategories.Count == 0)
return "None";
if (!string.IsNullOrEmpty(searchFilter))
return "Search Results";
if (SelectedCategories.Count == 1)
return SelectedCategories.First();
if (SelectedCategories.Count == allCategories.Length)
return "All";
return "Multiple";
};
categorySelector.OnMouseDown = _ =>
{
if (SearchTextField != null)
SearchTextField.YieldKeyboardFocus();
categorySelector.RemovePanel();
categorySelector.AttachPanel(CreateCategoriesPanel(Panel));
};
} }
protected Widget CreateCategoriesPanel(ScrollPanelWidget panel) protected Widget CreateCategoriesPanel(ScrollPanelWidget panel)
{ {
var categoriesPanel = Ui.LoadWidget("ACTOR_CATEGORY_FILTER_PANEL", null, new WidgetArgs()); var categoriesPanel = Ui.LoadWidget("CATEGORY_FILTER_PANEL", null, new WidgetArgs());
var categoryTemplate = categoriesPanel.Get<CheckboxWidget>("CATEGORY_TEMPLATE"); var categoryTemplate = categoriesPanel.Get<CheckboxWidget>("CATEGORY_TEMPLATE");
var selectButtons = categoriesPanel.Get<ContainerWidget>("SELECT_CATEGORIES_BUTTONS"); var selectButtons = categoriesPanel.Get<ContainerWidget>("SELECT_CATEGORIES_BUTTONS");

View File

@@ -35,87 +35,44 @@ namespace OpenRA.Mods.Common.Widgets.Logic
} }
readonly TileSet tileset; readonly TileSet tileset;
readonly ScrollPanelWidget panel;
readonly ScrollItemWidget itemTemplate;
readonly TileSelectorTemplate[] allTemplates; readonly TileSelectorTemplate[] allTemplates;
string selectedCategory;
string userSelectedCategory;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public TileSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer) : public TileSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer)
base(widget, world, worldRenderer) : base(widget, world, worldRenderer, "TILETEMPLATE_LIST", "TILEPREVIEW_TEMPLATE")
{ {
tileset = world.Map.Rules.TileSet; tileset = world.Map.Rules.TileSet;
panel = widget.Get<ScrollPanelWidget>("TILETEMPLATE_LIST");
itemTemplate = panel.Get<ScrollItemWidget>("TILEPREVIEW_TEMPLATE");
panel.Layout = new GridLayout(panel);
allTemplates = tileset.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray(); allTemplates = tileset.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray();
var orderedCategories = allTemplates.SelectMany(t => t.Categories) allCategories = allTemplates.SelectMany(t => t.Categories)
.Distinct() .Distinct()
.OrderBy(CategoryOrder) .OrderBy(CategoryOrder)
.ToArray(); .ToArray();
var searchTextField = widget.Get<TextFieldWidget>("SEARCH_TEXTFIELD"); foreach (var c in allCategories)
searchTextField.OnTextEdited = () =>
{ {
searchFilter = searchTextField.Text.Trim(); SelectedCategories.Add(c);
selectedCategory = string.IsNullOrEmpty(searchFilter) ? userSelectedCategory : null; FilteredCategories.Add(c);
}
InitializePreviews(); SearchTextField.OnTextEdited = () =>
};
searchTextField.OnEscKey = () =>
{ {
searchTextField.Text = ""; searchFilter = SearchTextField.Text.Trim();
searchTextField.YieldKeyboardFocus(); FilteredCategories.Clear();
return true;
};
Func<string, string> categoryTitle = s => s != null ? s : "Search Results";
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
{
var item = ScrollItemWidget.Setup(template, () => selectedCategory == option, () =>
{
selectedCategory = option;
if (option != null)
userSelectedCategory = option;
InitializePreviews();
});
var title = categoryTitle(option);
item.Get<LabelWidget>("LABEL").GetText = () => title;
return item;
};
var tileCategorySelector = widget.Get<DropDownButtonWidget>("CATEGORIES_DROPDOWN");
tileCategorySelector.OnClick = () =>
{
if (searchTextField != null)
searchTextField.YieldKeyboardFocus();
var categories = orderedCategories.AsEnumerable();
if (!string.IsNullOrEmpty(searchFilter)) if (!string.IsNullOrEmpty(searchFilter))
{ FilteredCategories.AddRange(
var filteredCategories = allTemplates.Where(t => t.SearchTerms.Any( allTemplates.Where(t => t.SearchTerms.Any(
s => s.IndexOf(searchFilter, StringComparison.OrdinalIgnoreCase) >= 0)) s => s.IndexOf(searchFilter, StringComparison.OrdinalIgnoreCase) >= 0))
.SelectMany(t => t.Categories) .SelectMany(t => t.Categories)
.Distinct() .Distinct()
.OrderBy(CategoryOrder); .OrderBy(CategoryOrder));
categories = new string[] { null }.Concat(filteredCategories); else
} FilteredCategories.AddRange(allCategories);
tileCategorySelector.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, categories, setupItem); InitializePreviews();
}; };
var actorCategorySelector = widget.Get<DropDownButtonWidget>("CATEGORIES_DROPDOWN");
actorCategorySelector.GetText = () => categoryTitle(selectedCategory);
selectedCategory = userSelectedCategory = orderedCategories.First();
InitializePreviews(); InitializePreviews();
} }
@@ -127,18 +84,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
protected override void InitializePreviews() protected override void InitializePreviews()
{ {
panel.RemoveChildren(); Panel.RemoveChildren();
if (!SelectedCategories.Any())
return;
foreach (var t in allTemplates) foreach (var t in allTemplates)
{ {
if (selectedCategory != null && !t.Categories.Contains(selectedCategory)) if (!SelectedCategories.Overlaps(t.Categories))
continue; continue;
if (!string.IsNullOrEmpty(searchFilter) && !t.SearchTerms.Any(s => s.IndexOf(searchFilter, StringComparison.OrdinalIgnoreCase) >= 0)) if (!string.IsNullOrEmpty(searchFilter) && !t.SearchTerms.Any(s => s.IndexOf(searchFilter, StringComparison.OrdinalIgnoreCase) >= 0))
continue; continue;
var tileId = t.Template.Id; var tileId = t.Template.Id;
var item = ScrollItemWidget.Setup(itemTemplate, var item = ScrollItemWidget.Setup(ItemTemplate,
() => { var brush = Editor.CurrentBrush as EditorTileBrush; return brush != null && brush.Template == tileId; }, () => { var brush = Editor.CurrentBrush as EditorTileBrush; return brush != null && brush.Template == tileId; },
() => Editor.SetBrush(new EditorTileBrush(Editor, tileId, WorldRenderer))); () => Editor.SetBrush(new EditorTileBrush(Editor, tileId, WorldRenderer)));
@@ -149,7 +108,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Scale templates to fit within the panel // Scale templates to fit within the panel
var scale = 1f; var scale = 1f;
while (scale * bounds.Width > itemTemplate.Bounds.Width) while (scale * bounds.Width > ItemTemplate.Bounds.Width)
scale /= 2; scale /= 2;
preview.Template = template; preview.Template = template;
@@ -162,7 +121,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
item.IsVisible = () => true; item.IsVisible = () => true;
item.GetTooltipText = () => t.Tooltip; item.GetTooltipText = () => t.Tooltip;
panel.AddChild(item); Panel.AddChild(item);
} }
} }
} }

View File

@@ -569,7 +569,7 @@ Container@EDITOR_WORLD_ROOT:
Font: Bold Font: Bold
Contrast: true Contrast: true
ScrollPanel@ACTOR_CATEGORY_FILTER_PANEL: ScrollPanel@CATEGORY_FILTER_PANEL:
Width: 190 Width: 190
Children: Children:
Container@SELECT_CATEGORIES_BUTTONS: Container@SELECT_CATEGORIES_BUTTONS:

View File

@@ -548,7 +548,7 @@ Container@EDITOR_WORLD_ROOT:
Font: Bold Font: Bold
Contrast: true Contrast: true
ScrollPanel@ACTOR_CATEGORY_FILTER_PANEL: ScrollPanel@CATEGORY_FILTER_PANEL:
Width: 170 Width: 170
Children: Children:
Container@SELECT_CATEGORIES_BUTTONS: Container@SELECT_CATEGORIES_BUTTONS: