mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Move some stuff to shared things, improve some filesystem rename handling.
This commit is contained in:
parent
8ea6893fc3
commit
00bc17c57a
11 changed files with 67 additions and 136 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
|||
Subproject commit adce3030c9dc125f2ebbaefbef6c756977c047c3
|
||||
Subproject commit d43be3287a4782be091635e81ef2ec64849ba462
|
||||
44
Penumbra.GameData/Data/HumanModelList.cs
Normal file
44
Penumbra.GameData/Data/HumanModelList.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using System.Collections;
|
||||
using System.Linq;
|
||||
using Dalamud;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Plugin;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace Penumbra.GameData.Data;
|
||||
|
||||
public sealed class HumanModelList : DataSharer
|
||||
{
|
||||
public const string Tag = "HumanModels";
|
||||
public const int CurrentVersion = 1;
|
||||
|
||||
private readonly BitArray _humanModels;
|
||||
|
||||
public HumanModelList(DalamudPluginInterface pluginInterface, DataManager gameData)
|
||||
: base(pluginInterface, ClientLanguage.English, CurrentVersion)
|
||||
{
|
||||
_humanModels = TryCatchData(Tag, () => GetValidHumanModels(gameData));
|
||||
}
|
||||
|
||||
public bool IsHuman(uint modelId)
|
||||
=> modelId < _humanModels.Count && _humanModels[(int)modelId];
|
||||
|
||||
protected override void DisposeInternal()
|
||||
{
|
||||
DisposeTag(Tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go through all ModelChara rows and return a bitfield of those that resolve to human models.
|
||||
/// </summary>
|
||||
private static BitArray GetValidHumanModels(DataManager gameData)
|
||||
{
|
||||
var sheet = gameData.GetExcelSheet<ModelChara>()!;
|
||||
var ret = new BitArray((int)sheet.RowCount, false);
|
||||
foreach (var (_, idx) in sheet.Select((m, i) => (m, i)).Where(p => p.m.Type == (byte)CharacterBase.ModelType.Human))
|
||||
ret[idx] = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Interface.Internal.Notifications;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Custom;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using OtterGui.Custom;
|
||||
using OtterGui.Filesystem;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.Services;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.Gui;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using OtterGui;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.Util;
|
||||
|
|
@ -23,7 +19,7 @@ public unsafe class CollectionResolver
|
|||
{
|
||||
private readonly PerformanceTracker _performance;
|
||||
private readonly IdentifiedCollectionCache _cache;
|
||||
private readonly BitArray _validHumanModels;
|
||||
private readonly HumanModelList _humanModels;
|
||||
|
||||
private readonly ClientState _clientState;
|
||||
private readonly GameGui _gameGui;
|
||||
|
|
@ -36,8 +32,8 @@ public unsafe class CollectionResolver
|
|||
private readonly DrawObjectState _drawObjectState;
|
||||
|
||||
public CollectionResolver(PerformanceTracker performance, IdentifiedCollectionCache cache, ClientState clientState, GameGui gameGui,
|
||||
DataManager gameData, ActorService actors, CutsceneService cutscenes, Configuration config, CollectionManager collectionManager,
|
||||
TempCollectionManager tempCollections, DrawObjectState drawObjectState)
|
||||
ActorService actors, CutsceneService cutscenes, Configuration config, CollectionManager collectionManager,
|
||||
TempCollectionManager tempCollections, DrawObjectState drawObjectState, HumanModelList humanModels)
|
||||
{
|
||||
_performance = performance;
|
||||
_cache = cache;
|
||||
|
|
@ -49,7 +45,7 @@ public unsafe class CollectionResolver
|
|||
_collectionManager = collectionManager;
|
||||
_tempCollections = tempCollections;
|
||||
_drawObjectState = drawObjectState;
|
||||
_validHumanModels = GetValidHumanModels(gameData);
|
||||
_humanModels = humanModels;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -115,7 +111,7 @@ public unsafe class CollectionResolver
|
|||
|
||||
/// <summary> Return whether the given ModelChara id refers to a human-type model. </summary>
|
||||
public bool IsModelHuman(uint modelCharaId)
|
||||
=> modelCharaId < _validHumanModels.Length && _validHumanModels[(int)modelCharaId];
|
||||
=> _humanModels.IsHuman(modelCharaId);
|
||||
|
||||
/// <summary> Return whether the given character has a human model. </summary>
|
||||
public bool IsModelHuman(Character* character)
|
||||
|
|
@ -254,17 +250,4 @@ public unsafe class CollectionResolver
|
|||
return CheckYourself(id, owner)
|
||||
?? CollectionByAttributes(owner, ref notYetReady);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go through all ModelChara rows and return a bitfield of those that resolve to human models.
|
||||
/// </summary>
|
||||
private static BitArray GetValidHumanModels(DataManager gameData)
|
||||
{
|
||||
var sheet = gameData.GetExcelSheet<ModelChara>()!;
|
||||
var ret = new BitArray((int)sheet.RowCount, false);
|
||||
foreach (var (_, idx) in sheet.WithIndex().Where(p => p.Value.Type == (byte)CharacterBase.ModelType.Human))
|
||||
ret[idx] = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Dalamud.Data;
|
|||
using Dalamud.Game.ClientState.Objects;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using Penumbra.GameData;
|
||||
using OtterGui.Custom;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Services;
|
||||
|
|
|
|||
|
|
@ -83,12 +83,12 @@ public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable
|
|||
// Update sort order when defaulted mod names change.
|
||||
private void OnDataChange(ModDataChangeType type, Mod mod, string? oldName)
|
||||
{
|
||||
if (type.HasFlag(ModDataChangeType.Name) && oldName != null)
|
||||
{
|
||||
var old = oldName.FixName();
|
||||
if (Find(old, out var child) && child is not Folder)
|
||||
Rename(child, mod.Name.Text);
|
||||
}
|
||||
if (!type.HasFlag(ModDataChangeType.Name) || oldName == null || !FindLeaf(mod, out var leaf))
|
||||
return;
|
||||
|
||||
var old = oldName.FixName();
|
||||
if (old == leaf.Name || leaf.Name.IsDuplicateName(out var baseName, out _) && baseName == old)
|
||||
RenameWithDuplicates(leaf, mod.Name.Text);
|
||||
}
|
||||
|
||||
// Update the filesystem if a mod has been added or removed.
|
||||
|
|
@ -98,13 +98,7 @@ public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable
|
|||
switch (type)
|
||||
{
|
||||
case ModPathChangeType.Added:
|
||||
var originalName = mod.Name.Text.FixName();
|
||||
var name = originalName;
|
||||
var counter = 1;
|
||||
while (Find(name, out _))
|
||||
name = $"{originalName} ({++counter})";
|
||||
|
||||
CreateLeaf(Root, name, mod);
|
||||
CreateDuplicateLeaf(Root, mod.Name.Text, mod);
|
||||
break;
|
||||
case ModPathChangeType.Deleted:
|
||||
if (FindLeaf(mod, out var leaf))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System.Collections.Concurrent;
|
||||
using Dalamud.Plugin;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OtterGui.Classes;
|
||||
|
|
@ -18,7 +17,7 @@ using Penumbra.Mods.Editor;
|
|||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.UI;
|
||||
using Penumbra.UI.AdvancedWindow;
|
||||
using Penumbra.UI.Classes;
|
||||
using Penumbra.UI.Classes;
|
||||
using Penumbra.UI.ModsTab;
|
||||
using Penumbra.UI.Tabs;
|
||||
|
||||
|
|
@ -70,7 +69,8 @@ public static class ServiceManager
|
|||
.AddSingleton<IdentifierService>()
|
||||
.AddSingleton<StainService>()
|
||||
.AddSingleton<ItemService>()
|
||||
.AddSingleton<ActorService>();
|
||||
.AddSingleton<ActorService>()
|
||||
.AddSingleton<HumanModelList>();
|
||||
|
||||
private static IServiceCollection AddInterop(this IServiceCollection services)
|
||||
=> services.AddSingleton<GameEventManager>()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Custom;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Communication;
|
||||
|
|
@ -63,22 +63,8 @@ public class IndividualAssignmentUi : IDisposable
|
|||
|
||||
public void DrawObjectKindCombo(float width)
|
||||
{
|
||||
if (!_ready)
|
||||
return;
|
||||
|
||||
ImGui.SetNextItemWidth(width);
|
||||
using var combo = ImRaii.Combo("##newKind", _newKind.ToName());
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
foreach (var kind in ObjectKinds)
|
||||
{
|
||||
if (!ImGui.Selectable(kind.ToName(), _newKind == kind))
|
||||
continue;
|
||||
|
||||
_newKind = kind;
|
||||
if (_ready && IndividualHelpers.DrawObjectKindCombo(width, _newKind, out _newKind, ObjectKinds))
|
||||
UpdateIdentifiersInternal();
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawNewPlayerCollection(float width)
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Penumbra.UI.CollectionTab;
|
||||
|
||||
public sealed class NpcCombo : FilterComboCache<(string Name, uint[] Ids)>
|
||||
{
|
||||
private readonly string _label;
|
||||
|
||||
public NpcCombo(string label, IReadOnlyDictionary<uint, string> names)
|
||||
: base(() => names.GroupBy(kvp => kvp.Value).Select(g => (g.Key, g.Select(g => g.Key).ToArray())).OrderBy(g => g.Key, Comparer)
|
||||
.ToList())
|
||||
=> _label = label;
|
||||
|
||||
protected override string ToString((string Name, uint[] Ids) obj)
|
||||
=> obj.Name;
|
||||
|
||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
||||
{
|
||||
var (name, ids) = Items[globalIdx];
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(string.Join('\n', ids.Select(i => i.ToString())));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool Draw(float width)
|
||||
=> Draw(_label, CurrentSelection.Name, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
|
||||
|
||||
/// <summary> Compare strings in a way that letters and numbers are sorted before any special symbols. </summary>
|
||||
private class NameComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string? x, string? y)
|
||||
{
|
||||
if (x.IsNullOrEmpty() || y.IsNullOrEmpty())
|
||||
return StringComparer.OrdinalIgnoreCase.Compare(x, y);
|
||||
|
||||
return (char.IsAsciiLetterOrDigit(x[0]), char.IsAsciiLetterOrDigit(y[0])) switch
|
||||
{
|
||||
(true, false) => -1,
|
||||
(false, true) => 1,
|
||||
_ => StringComparer.OrdinalIgnoreCase.Compare(x, y),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly NameComparer Comparer = new();
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Penumbra.UI.CollectionTab;
|
||||
|
||||
public sealed class WorldCombo : FilterComboCache<KeyValuePair<ushort, string>>
|
||||
{
|
||||
private static readonly KeyValuePair<ushort, string> AllWorldPair = new(ushort.MaxValue, "Any World");
|
||||
|
||||
public WorldCombo(IReadOnlyDictionary<ushort, string> worlds)
|
||||
: base(worlds.OrderBy(kvp => kvp.Value).Prepend(AllWorldPair))
|
||||
{
|
||||
CurrentSelection = AllWorldPair;
|
||||
CurrentSelectionIdx = 0;
|
||||
}
|
||||
|
||||
protected override string ToString(KeyValuePair<ushort, string> obj)
|
||||
=> obj.Value;
|
||||
|
||||
public bool Draw(float width)
|
||||
=> Draw("##worldCombo", CurrentSelection.Value, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue