feat: add new filtering system

Add system to allow for filtering by job and level.
This commit is contained in:
Anna 2021-12-13 04:03:01 -05:00
parent c9b92d0e25
commit 6e3e0f1d7f
Signed by: anna
GPG Key ID: 0B391D8F06FCD9E0
1 changed files with 98 additions and 3 deletions

View File

@ -40,6 +40,8 @@ namespace Glamaholic.Ui {
private List<Item> FilteredItems { get; set; }
private Dictionary<string, byte> Stains { get; }
private FilterInfo? PlateFilter { get; set; }
private bool _visible;
private int _dragging = -1;
private int _selectedPlate = -1;
@ -308,15 +310,18 @@ namespace Glamaholic.Ui {
}
ImGui.SetNextItemWidth(-1);
ImGui.InputText("##plate-filter", ref this._plateFilter, 512, ImGuiInputTextFlags.AutoSelectAll);
if (ImGui.InputText("##plate-filter", ref this._plateFilter, 512, ImGuiInputTextFlags.AutoSelectAll)) {
this.PlateFilter = this._plateFilter.Length == 0
? null
: new FilterInfo(this.Ui.Plugin.DataManager, this._plateFilter);
}
var filter = this._plateFilter.ToLowerInvariant();
(int src, int dst)? drag = null;
if (ImGui.BeginChild("plate list actual", Vector2.Zero, false, ImGuiWindowFlags.HorizontalScrollbar)) {
for (var i = 0; i < this.Ui.Plugin.Config.Plates.Count; i++) {
var plate = this.Ui.Plugin.Config.Plates[i];
if (filter.Length != 0 && !plate.Name.ToLowerInvariant().Contains(filter)) {
if (this.PlateFilter != null && !this.PlateFilter.Matches(plate)) {
continue;
}
@ -871,5 +876,95 @@ namespace Glamaholic.Ui {
.Where(item => this._itemFilter.Length == 0 || item.Name.RawString.ToLowerInvariant().Contains(filter))
.ToList();
}
private class FilterInfo {
private DataManager Data { get; }
private uint MaxLevel { get; }
private string Query { get; }
private HashSet<ClassJob> WantedJobs { get; } = new();
internal FilterInfo(DataManager data, string filter) {
this.Data = data;
var queryWords = new List<string>();
foreach (var word in filter.Split(' ')) {
if (word.StartsWith("j:")) {
var abbr = word[2..].ToLowerInvariant();
var job = this.Data.GetExcelSheet<ClassJob>()!.FirstOrDefault(row => row.Abbreviation.RawString.ToLowerInvariant() == abbr);
if (job != null) {
this.WantedJobs.Add(job);
}
continue;
}
if (word.StartsWith("lvl:")) {
if (uint.TryParse(word[4..], out var level)) {
this.MaxLevel = level;
}
continue;
}
queryWords.Add(word);
}
this.Query = string.Join(' ', queryWords).ToLowerInvariant();
}
internal bool Matches(SavedPlate plate) {
// if the name doesn't match the query, it's not a match, obviously
if (this.Query.Length != 0 && !plate.Name.ToLowerInvariant().Contains(this.Query)) {
return false;
}
// if there's nothing custom about this filter, this is a match
if (this.MaxLevel == 0 && this.WantedJobs.Count == 0) {
return true;
}
foreach (var mirage in plate.Items.Values) {
var item = this.Data.GetExcelSheet<Item>()!.GetRow(mirage.ItemId % Util.HqItemOffset);
if (item == null) {
continue;
}
if (this.MaxLevel != 0 && item.LevelEquip > this.MaxLevel) {
return false;
}
foreach (var job in this.WantedJobs) {
var category = item.ClassJobCategory.Value;
if (category == null) {
continue;
}
if (!this.CanWear(category, job)) {
return false;
}
}
}
return true;
}
private bool CanWear(ClassJobCategory category, ClassJob classJob) {
// get english version
var job = this.Data.GetExcelSheet<ClassJob>(ClientLanguage.English)!.GetRow(classJob.RowId)!;
var getter = category.GetType().GetProperty(job.Abbreviation.RawString, BindingFlags.Public | BindingFlags.Instance);
if (getter == null) {
return false;
}
var value = getter.GetValue(category);
if (value is bool res) {
return res;
}
return false;
}
}
}
}