// Draw all rows respecting filters and using clipping. private void DrawEffectiveRows(ModCollection active, int skips, float height, bool hasFilters) { // We can use the known counts if no filters are active. var stop = hasFilters ? ImGuiClip.FilteredClippedDraw(active.ResolvedFiles, skips, CheckFilters, DrawLine) : ImGuiClip.ClippedDraw(active.ResolvedFiles, skips, DrawLine, active.ResolvedFiles.Count); var m = active.MetaCache; // If no meta manipulations are active, we can just draw the end dummy. if (m is { Count : > 0 })
// A simple clipped list of changed items. private void DrawChangedItemsTab() { using var tab = DrawTab(ChangedItemsTabHeader, Tabs.ChangedItems); if (!tab) { return; } using var list = ImRaii.ListBox("##changedItems", -Vector2.One); if (!list) { return; } var zipList = ZipList.FromSortedList(_mod.ChangedItems); var height = ImGui.GetTextLineHeight(); ImGuiClip.ClippedDraw(zipList, kvp => _window.DrawChangedItem(kvp.Item1, kvp.Item2, true), height); }
// Draw a simple clipped table containing all changed items. private void DrawChangedItemTab() { // Functions in here for less pollution. bool FilterChangedItem(KeyValuePair <string, (SingleArray <IMod>, object?)> item) => (_changedItemFilter.IsEmpty || ChangedItemName(item.Key, item.Value.Item2) .Contains(_changedItemFilter.Lower, StringComparison.InvariantCultureIgnoreCase)) && (_changedItemModFilter.IsEmpty || item.Value.Item1.Any(m => m.Name.Contains(_changedItemModFilter))); void DrawChangedItemColumn(KeyValuePair <string, (SingleArray <IMod>, object?)> item) { ImGui.TableNextColumn(); DrawChangedItem(item.Key, item.Value.Item2, false); ImGui.TableNextColumn(); if (item.Value.Item1.Count > 0) { ImGui.TextUnformatted(item.Value.Item1[0].Name); if (item.Value.Item1.Count > 1) { ImGuiUtil.HoverTooltip(string.Join("\n", item.Value.Item1.Skip(1).Select(m => m.Name))); } } ImGui.TableNextColumn(); if (item.Value.Item2 is Item it) { using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value()); ImGuiUtil.RightAlign($"({( ( Quad )it.ModelMain ).A})"); } } using var tab = ImRaii.TabItem("Changed Items"); if (!tab) { return; } // Draw filters. var varWidth = ImGui.GetContentRegionAvail().X - 400 * ImGuiHelpers.GlobalScale - ImGui.GetStyle().ItemSpacing.X; ImGui.SetNextItemWidth(400 * ImGuiHelpers.GlobalScale); LowerString.InputWithHint("##changedItemsFilter", "Filter Item...", ref _changedItemFilter, 128); ImGui.SameLine(); ImGui.SetNextItemWidth(varWidth); LowerString.InputWithHint("##changedItemsModFilter", "Filter Mods...", ref _changedItemModFilter, 128); using var child = ImRaii.Child("##changedItemsChild", -Vector2.One); if (!child) { return; } // Draw table of changed items. var height = ImGui.GetTextLineHeightWithSpacing() + 2 * ImGui.GetStyle().CellPadding.Y; var skips = ImGuiClip.GetNecessarySkips(height); using var list = ImRaii.Table("##changedItems", 3, ImGuiTableFlags.RowBg, -Vector2.One); if (!list) { return; } const ImGuiTableColumnFlags flags = ImGuiTableColumnFlags.NoResize | ImGuiTableColumnFlags.WidthFixed; ImGui.TableSetupColumn("items", flags, 400 * ImGuiHelpers.GlobalScale); ImGui.TableSetupColumn("mods", flags, varWidth - 100 * ImGuiHelpers.GlobalScale); ImGui.TableSetupColumn("id", flags, 100 * ImGuiHelpers.GlobalScale); var items = Penumbra.CollectionManager.Current.ChangedItems; var rest = _changedItemFilter.IsEmpty && _changedItemModFilter.IsEmpty ? ImGuiClip.ClippedDraw(items, skips, DrawChangedItemColumn, items.Count) : ImGuiClip.FilteredClippedDraw(items, skips, FilterChangedItem, DrawChangedItemColumn); ImGuiClip.DrawEndDummy(rest, height); }