mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Dupidu
This commit is contained in:
parent
9c6256bf1b
commit
6e7e6530cf
12 changed files with 360 additions and 203 deletions
|
|
@ -24,8 +24,8 @@ public readonly struct Item
|
||||||
public bool IsBothHand
|
public bool IsBothHand
|
||||||
=> (EquipSlot)Base.EquipSlotCategory.Row == EquipSlot.BothHand;
|
=> (EquipSlot)Base.EquipSlotCategory.Row == EquipSlot.BothHand;
|
||||||
|
|
||||||
public WeaponCategory WeaponCategory
|
public FullEquipType WeaponCategory
|
||||||
=> (WeaponCategory?) Base.ItemUICategory?.Row ?? WeaponCategory.Unknown;
|
=> ((WeaponCategory) (Base.ItemUICategory?.Row ?? 0)).ToEquipType();
|
||||||
|
|
||||||
// Create a new item from its sheet list with the given name and either the inferred equip slot or the given one.
|
// Create a new item from its sheet list with the given name and either the inferred equip slot or the given one.
|
||||||
public Item(Lumina.Excel.GeneratedSheets.Item item, string name, EquipSlot slot = EquipSlot.Unknown)
|
public Item(Lumina.Excel.GeneratedSheets.Item item, string name, EquipSlot slot = EquipSlot.Unknown)
|
||||||
|
|
|
||||||
BIN
Glamourer.zip
BIN
Glamourer.zip
Binary file not shown.
301
Glamourer/Designs/Design.Manager.cs
Normal file
301
Glamourer/Designs/Design.Manager.cs
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using ImGuizmoNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Filesystem;
|
||||||
|
|
||||||
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
|
public sealed class DesignFileSystem : FileSystem<Design>, IDisposable
|
||||||
|
{
|
||||||
|
public readonly string DesignFileSystemFile;
|
||||||
|
private readonly Design.Manager _designManager;
|
||||||
|
|
||||||
|
public DesignFileSystem(Design.Manager designManager, DalamudPluginInterface pi)
|
||||||
|
{
|
||||||
|
DesignFileSystemFile = Path.Combine(pi.GetPluginConfigDirectory(), "sort_order.json");
|
||||||
|
_designManager = designManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct CreationDate : ISortMode<Design>
|
||||||
|
{
|
||||||
|
public string Name
|
||||||
|
=> "Creation Date (Older First)";
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date.";
|
||||||
|
|
||||||
|
public IEnumerable<IPath> GetChildren(Folder f)
|
||||||
|
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.CreationDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct InverseCreationDate : ISortMode<Design>
|
||||||
|
{
|
||||||
|
public string Name
|
||||||
|
=> "Creation Date (Newer First)";
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date.";
|
||||||
|
|
||||||
|
public IEnumerable<IPath> GetChildren(Folder f)
|
||||||
|
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.CreationDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChange(FileSystemChangeType type, IPath _1, IPath? _2, IPath? _3)
|
||||||
|
{
|
||||||
|
if (type != FileSystemChangeType.Reload)
|
||||||
|
{
|
||||||
|
SaveFilesystem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveFilesystem()
|
||||||
|
{
|
||||||
|
SaveToFile(new FileInfo(DesignFileSystemFile), SaveDesign, true);
|
||||||
|
Glamourer.Log.Verbose($"Saved design filesystem.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save()
|
||||||
|
=> Glamourer.Framework.RegisterDelayed(nameof(SaveFilesystem), SaveFilesystem);
|
||||||
|
|
||||||
|
private void OnDataChange(Design.Manager.DesignChangeType type, Design design, string? oldName, string? _2, int _3)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
if (type == Design.Manager.DesignChangeType.Renamed && oldName != null)
|
||||||
|
{
|
||||||
|
var old = oldName.FixName();
|
||||||
|
if (Find(old, out var child) && child is not Folder)
|
||||||
|
{
|
||||||
|
Rename(child, design.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for saving and loading.
|
||||||
|
private static string DesignToIdentifier(Design design)
|
||||||
|
=> design.Identifier.ToString();
|
||||||
|
|
||||||
|
private static string DesignToName(Design design)
|
||||||
|
=> design.Name.FixName();
|
||||||
|
|
||||||
|
private static bool DesignHasDefaultPath(Design design, string fullPath)
|
||||||
|
{
|
||||||
|
var regex = new Regex($@"^{Regex.Escape(DesignToName(design))}( \(\d+\))?$");
|
||||||
|
return regex.IsMatch(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string, bool) SaveDesign(Design design, string fullPath)
|
||||||
|
// Only save pairs with non-default paths.
|
||||||
|
=> DesignHasDefaultPath(design, fullPath)
|
||||||
|
? (string.Empty, false)
|
||||||
|
: (DesignToName(design), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Design
|
||||||
|
{
|
||||||
|
public partial class Manager
|
||||||
|
{
|
||||||
|
public const string DesignFolderName = "designs";
|
||||||
|
public readonly string DesignFolder;
|
||||||
|
|
||||||
|
private readonly List<Design> _designs = new();
|
||||||
|
|
||||||
|
public enum DesignChangeType
|
||||||
|
{
|
||||||
|
Created,
|
||||||
|
Deleted,
|
||||||
|
ReloadedAll,
|
||||||
|
Renamed,
|
||||||
|
ChangedDescription,
|
||||||
|
AddedTag,
|
||||||
|
RemovedTag,
|
||||||
|
ChangedTag,
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void DesignChangeDelegate(DesignChangeType type, int designIdx, string? oldData = null, string? newData = null,
|
||||||
|
int tagIdx = -1);
|
||||||
|
|
||||||
|
public event DesignChangeDelegate? DesignChange;
|
||||||
|
|
||||||
|
public IReadOnlyList<Design> Designs
|
||||||
|
=> _designs;
|
||||||
|
|
||||||
|
public Manager(DalamudPluginInterface pi)
|
||||||
|
=> DesignFolder = SetDesignFolder(pi);
|
||||||
|
|
||||||
|
private static string SetDesignFolder(DalamudPluginInterface pi)
|
||||||
|
{
|
||||||
|
var ret = Path.Combine(pi.GetPluginConfigDirectory(), DesignFolderName);
|
||||||
|
if (Directory.Exists(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ret);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Error($"Could not create design folder directory at {ret}:\n{ex}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateFileName(Design design)
|
||||||
|
=> Path.Combine(DesignFolder, $"{design.Name.RemoveInvalidPathSymbols()}_{design.Identifier}.json");
|
||||||
|
|
||||||
|
public void SaveDesign(Design design)
|
||||||
|
{
|
||||||
|
var fileName = CreateFileName(design);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = design.JsonSerialize().ToString(Formatting.Indented);
|
||||||
|
File.WriteAllText(fileName, data);
|
||||||
|
Glamourer.Log.Debug($"Saved design {design.Identifier}.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Error($"Could not save design {design.Identifier} to file:\n{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadDesigns()
|
||||||
|
{
|
||||||
|
_designs.Clear();
|
||||||
|
foreach (var file in new DirectoryInfo(DesignFolder).EnumerateFiles("*.json", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var text = File.ReadAllText(file.FullName);
|
||||||
|
var data = JObject.Parse(text);
|
||||||
|
var design = LoadDesign(data);
|
||||||
|
design.Index = _designs.Count;
|
||||||
|
_designs.Add(design);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Error($"Could not load design, skipped:\n{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Glamourer.Log.Information($"Loaded {_designs.Count} designs.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.ReloadedAll, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Design Create(string name)
|
||||||
|
{
|
||||||
|
var design = new Design()
|
||||||
|
{
|
||||||
|
CreationDate = DateTimeOffset.UtcNow,
|
||||||
|
Identifier = Guid.NewGuid(),
|
||||||
|
Index = _designs.Count,
|
||||||
|
Name = name,
|
||||||
|
};
|
||||||
|
_designs.Add(design);
|
||||||
|
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.Created, design.Index);
|
||||||
|
return design;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(Design design)
|
||||||
|
{
|
||||||
|
_designs.RemoveAt(design.Index);
|
||||||
|
foreach (var d in _designs.Skip(design.Index + 1))
|
||||||
|
--d.Index;
|
||||||
|
var fileName = CreateFileName(design);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(fileName);
|
||||||
|
Glamourer.Log.Debug($"Deleted design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.Deleted, design.Index);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Error($"Could not delete design file for {design.Identifier}:\n{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rename(Design design, string newName)
|
||||||
|
{
|
||||||
|
var oldName = design.Name;
|
||||||
|
var oldFileName = CreateFileName(design);
|
||||||
|
if (File.Exists(oldFileName))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(oldFileName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Error($"Could not delete old design file for rename from {design.Identifier}:\n{ex}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
design.Name = newName;
|
||||||
|
SaveDesign(design);
|
||||||
|
Glamourer.Log.Debug($"Renamed design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.Renamed, design.Index, oldName, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeDescription(Design design, string description)
|
||||||
|
{
|
||||||
|
var oldDescription = design.Description;
|
||||||
|
design.Description = description;
|
||||||
|
SaveDesign(design);
|
||||||
|
Glamourer.Log.Debug($"Renamed design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.ChangedDescription, design.Index, oldDescription, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTag(Design design, string tag)
|
||||||
|
{
|
||||||
|
if (design.Tags.Contains(tag))
|
||||||
|
return;
|
||||||
|
|
||||||
|
design.Tags = design.Tags.Append(tag).OrderBy(t => t).ToArray();
|
||||||
|
var idx = design.Tags.IndexOf(tag);
|
||||||
|
SaveDesign(design);
|
||||||
|
Glamourer.Log.Debug($"Added tag at {idx} to design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.AddedTag, design.Index, null, tag, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveTag(Design design, string tag)
|
||||||
|
{
|
||||||
|
var idx = design.Tags.IndexOf(tag);
|
||||||
|
if (idx >= 0)
|
||||||
|
RemoveTag(design, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveTag(Design design, int tagIdx)
|
||||||
|
{
|
||||||
|
var oldTag = design.Tags[tagIdx];
|
||||||
|
design.Tags = design.Tags.Take(tagIdx).Concat(design.Tags.Skip(tagIdx + 1)).ToArray();
|
||||||
|
SaveDesign(design);
|
||||||
|
Glamourer.Log.Debug($"Removed tag at {tagIdx} from design {design.Identifier}.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.RemovedTag, design.Index, oldTag, null, tagIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RenameTag(Design design, int tagIdx, string newTag)
|
||||||
|
{
|
||||||
|
var oldTag = design.Tags[tagIdx];
|
||||||
|
if (oldTag == newTag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
design.Tags[tagIdx] = newTag;
|
||||||
|
Array.Sort(design.Tags);
|
||||||
|
SaveDesign(design);
|
||||||
|
Glamourer.Log.Debug($"Renamed tag at {tagIdx} in design {design.Identifier} and resorted tags.");
|
||||||
|
DesignChange?.Invoke(DesignChangeType.ChangedTag, design.Index, oldTag, newTag, tagIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
Glamourer/Designs/Design.cs
Normal file
44
Glamourer/Designs/Design.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
|
public partial class Design
|
||||||
|
{
|
||||||
|
public Guid Identifier { get; private init; }
|
||||||
|
public DateTimeOffset CreationDate { get; private init; }
|
||||||
|
public string Name { get; private set; } = string.Empty;
|
||||||
|
public string Description { get; private set; } = string.Empty;
|
||||||
|
public string[] Tags { get; private set; } = Array.Empty<string>();
|
||||||
|
public int Index { get; private set; }
|
||||||
|
|
||||||
|
public JObject JsonSerialize()
|
||||||
|
{
|
||||||
|
var ret = new JObject
|
||||||
|
{
|
||||||
|
[nameof(Identifier)] = Identifier,
|
||||||
|
[nameof(CreationDate)] = CreationDate,
|
||||||
|
[nameof(Name)] = Name,
|
||||||
|
[nameof(Description)] = Description,
|
||||||
|
[nameof(Tags)] = JArray.FromObject(Tags),
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Design LoadDesign(JObject json)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
CreationDate = json[nameof(CreationDate)]?.ToObject<DateTimeOffset>() ?? throw new ArgumentNullException(nameof(CreationDate)),
|
||||||
|
Identifier = json[nameof(Identifier)]?.ToObject<Guid>() ?? throw new ArgumentNullException(nameof(Identifier)),
|
||||||
|
Name = json[nameof(Name)]?.ToObject<string>() ?? throw new ArgumentNullException(nameof(Name)),
|
||||||
|
Description = json[nameof(Description)]?.ToObject<string>() ?? string.Empty,
|
||||||
|
Tags = ParseTags(json),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static string[] ParseTags(JObject json)
|
||||||
|
{
|
||||||
|
var tags = json[nameof(Tags)]?.ToObject<string[]>() ?? Array.Empty<string>();
|
||||||
|
return tags.OrderBy(t => t).Distinct().ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,174 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Dalamud.Logging;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
|
||||||
|
|
||||||
public class DesignManager
|
|
||||||
{
|
|
||||||
//public const string FileName = "Designs.json";
|
|
||||||
//private readonly FileInfo _saveFile;
|
|
||||||
//
|
|
||||||
//public SortedList<string, CharacterSave> Designs = null!;
|
|
||||||
//public FileSystem.FileSystem FileSystem { get; } = new();
|
|
||||||
//
|
|
||||||
//public DesignManager()
|
|
||||||
//{
|
|
||||||
// var saveFolder = new DirectoryInfo(Dalamud.PluginInterface.GetPluginConfigDirectory());
|
|
||||||
// if (!saveFolder.Exists)
|
|
||||||
// Directory.CreateDirectory(saveFolder.FullName);
|
|
||||||
//
|
|
||||||
// _saveFile = new FileInfo(Path.Combine(saveFolder.FullName, FileName));
|
|
||||||
//
|
|
||||||
// LoadFromFile();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//private void BuildStructure()
|
|
||||||
//{
|
|
||||||
// FileSystem.Clear();
|
|
||||||
// var anyChanges = false;
|
|
||||||
// foreach (var (path, save) in Designs.ToArray())
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var (folder, name) = FileSystem.CreateAllFolders(path);
|
|
||||||
// var design = new Design(folder, name) { Data = save };
|
|
||||||
// folder.FindOrAddChild(design);
|
|
||||||
// var fixedPath = design.FullName();
|
|
||||||
// if (string.Equals(fixedPath, path, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// Designs.Remove(path);
|
|
||||||
// Designs[fixedPath] = save;
|
|
||||||
// anyChanges = true;
|
|
||||||
// PluginLog.Debug($"Problem loading saved designs, {path} was renamed to {fixedPath}.");
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// PluginLog.Error($"Problem loading saved designs, {path} was removed because:\n{e}");
|
|
||||||
// Designs.Remove(path);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (anyChanges)
|
|
||||||
// SaveToFile();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//private bool UpdateRoot(string oldPath, Design child)
|
|
||||||
//{
|
|
||||||
// var newPath = child.FullName();
|
|
||||||
// if (string.Equals(newPath, oldPath, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
// return false;
|
|
||||||
//
|
|
||||||
// Designs.Remove(oldPath);
|
|
||||||
// Designs[child.FullName()] = child.Data;
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//private void UpdateChild(string oldRootPath, string newRootPath, Design child)
|
|
||||||
//{
|
|
||||||
// var newPath = child.FullName();
|
|
||||||
// var oldPath = $"{oldRootPath}{newPath.Remove(0, newRootPath.Length)}";
|
|
||||||
// Designs.Remove(oldPath);
|
|
||||||
// Designs[newPath] = child.Data;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//public void DeleteAllChildren(IFileSystemBase root, bool deleteEmpty)
|
|
||||||
//{
|
|
||||||
// if (root is Folder f)
|
|
||||||
// foreach (var child in f.AllLeaves(SortMode.Lexicographical))
|
|
||||||
// Designs.Remove(child.FullName());
|
|
||||||
// var fullPath = root.FullName();
|
|
||||||
// root.Parent.RemoveChild(root, deleteEmpty);
|
|
||||||
// Designs.Remove(fullPath);
|
|
||||||
//
|
|
||||||
// SaveToFile();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//public void UpdateAllChildren(string oldPath, IFileSystemBase root)
|
|
||||||
//{
|
|
||||||
// var changes = false;
|
|
||||||
// switch (root)
|
|
||||||
// {
|
|
||||||
// case Design d:
|
|
||||||
// changes |= UpdateRoot(oldPath, d);
|
|
||||||
// break;
|
|
||||||
// case Folder f:
|
|
||||||
// {
|
|
||||||
// var newRootPath = root.FullName();
|
|
||||||
// if (!string.Equals(oldPath, newRootPath, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
// {
|
|
||||||
// changes = true;
|
|
||||||
// foreach (var descendant in f.AllLeaves(SortMode.Lexicographical).Where(l => l is Design).Cast<Design>())
|
|
||||||
// UpdateChild(oldPath, newRootPath, descendant);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (changes)
|
|
||||||
// SaveToFile();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//public void SaveToFile()
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var data = JsonConvert.SerializeObject(Designs, Formatting.Indented);
|
|
||||||
// File.WriteAllText(_saveFile.FullName, data);
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// PluginLog.Error($"Could not write to save file {_saveFile.FullName}:\n{e}");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//public void LoadFromFile()
|
|
||||||
//{
|
|
||||||
// _saveFile.Refresh();
|
|
||||||
// Designs = new SortedList<string, CharacterSave>();
|
|
||||||
// var changes = false;
|
|
||||||
// if (_saveFile.Exists)
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var data = File.ReadAllText(_saveFile.FullName);
|
|
||||||
// var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
|
||||||
// if (json == null)
|
|
||||||
// {
|
|
||||||
// PluginLog.Error($"Save file {_saveFile.FullName} corrupted.");
|
|
||||||
// json = new Dictionary<string, string>();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// foreach (var (name, saveString) in json)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var save = CharacterSave.FromString(saveString, out var oldVersion);
|
|
||||||
// changes |= oldVersion;
|
|
||||||
// changes |= !Designs.TryAdd(name, save);
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// PluginLog.Error($"Character Save for {name} is invalid:\n{e}");
|
|
||||||
// changes = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// PluginLog.Error($"Could not load save file {_saveFile.FullName}:\n{e}");
|
|
||||||
// changes = true;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// changes = true;
|
|
||||||
|
|
||||||
// if (changes)
|
|
||||||
// SaveToFile();
|
|
||||||
|
|
||||||
// BuildStructure();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
@ -96,7 +96,6 @@ public class Glamourer : IDalamudPlugin
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
||||||
Dalamud.PluginInterface.RelinquishData("test1");
|
|
||||||
RedrawManager?.Dispose();
|
RedrawManager?.Dispose();
|
||||||
Penumbra?.Dispose();
|
Penumbra?.Dispose();
|
||||||
if (_windowSystem != null)
|
if (_windowSystem != null)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,6 @@
|
||||||
using System;
|
namespace Glamourer.Gui.Designs;
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
|
||||||
using Dalamud.Interface;
|
|
||||||
using Dalamud.Logging;
|
|
||||||
using Glamourer.Designs;
|
|
||||||
using Glamourer.Structs;
|
|
||||||
using ImGuiNET;
|
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Raii;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
|
||||||
|
|
||||||
//internal partial class Interface
|
//internal partial class Interface
|
||||||
//{
|
//{
|
||||||
|
|
@ -91,7 +91,7 @@ public partial class EquipmentDrawer
|
||||||
private CharacterWeapon _lastWeapon = new(ulong.MaxValue);
|
private CharacterWeapon _lastWeapon = new(ulong.MaxValue);
|
||||||
private string _lastPreview = string.Empty;
|
private string _lastPreview = string.Empty;
|
||||||
private int _lastIndex;
|
private int _lastIndex;
|
||||||
public WeaponCategory LastCategory { get; private set; }
|
public FullEquipType LastCategory { get; private set; }
|
||||||
private bool _drawAll;
|
private bool _drawAll;
|
||||||
|
|
||||||
public WeaponCombo(EquipSlot slot)
|
public WeaponCombo(EquipSlot slot)
|
||||||
|
|
@ -124,12 +124,12 @@ public partial class EquipmentDrawer
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateItem(weapon);
|
UpdateItem(weapon);
|
||||||
UpdateCategory((WeaponCategory?)LastItem!.ItemUICategory?.Row ?? WeaponCategory.Unknown);
|
UpdateCategory(((WeaponCategory) (LastItem!.ItemUICategory?.Row ?? 0)).ToEquipType());
|
||||||
newIdx = _lastIndex;
|
newIdx = _lastIndex;
|
||||||
return Draw(Label, _lastPreview, ref newIdx, ItemComboWidth * ImGuiHelpers.GlobalScale, ImGui.GetTextLineHeight());
|
return Draw(Label, _lastPreview, ref newIdx, ItemComboWidth * ImGuiHelpers.GlobalScale, ImGui.GetTextLineHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Draw(CharacterWeapon weapon, WeaponCategory category, out int newIdx)
|
public bool Draw(CharacterWeapon weapon, FullEquipType category, out int newIdx)
|
||||||
{
|
{
|
||||||
if (_drawAll)
|
if (_drawAll)
|
||||||
{
|
{
|
||||||
|
|
@ -166,7 +166,7 @@ public partial class EquipmentDrawer
|
||||||
_lastPreview = _lastIndex >= 0 ? Items[_lastIndex].Name : LastItem.Name.ToString();
|
_lastPreview = _lastIndex >= 0 ? Items[_lastIndex].Name : LastItem.Name.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCategory(WeaponCategory category)
|
private void UpdateCategory(FullEquipType category)
|
||||||
{
|
{
|
||||||
if (category == LastCategory)
|
if (category == LastCategory)
|
||||||
return;
|
return;
|
||||||
|
|
@ -225,7 +225,7 @@ public partial class EquipmentDrawer
|
||||||
Glamourer.RedrawManager.LoadWeapon(actor, _currentSlot, mainHand);
|
Glamourer.RedrawManager.LoadWeapon(actor, _currentSlot, mainHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawOffHandSelector(ref CharacterWeapon offHand, WeaponCategory category)
|
private void DrawOffHandSelector(ref CharacterWeapon offHand, FullEquipType category)
|
||||||
{
|
{
|
||||||
var change = OffHandCombo.Draw(offHand, category, out var newIdx);
|
var change = OffHandCombo.Draw(offHand, category, out var newIdx);
|
||||||
var newWeapon = change ? ToWeapon(OffHandCombo.Items[newIdx], offHand.Stain) : CharacterWeapon.Empty;
|
var newWeapon = change ? ToWeapon(OffHandCombo.Items[newIdx], offHand.Stain) : CharacterWeapon.Empty;
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,8 @@ public partial class EquipmentDrawer
|
||||||
DrawStainCombo();
|
DrawStainCombo();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawMainHandSelector(ref mainHand);
|
DrawMainHandSelector(ref mainHand);
|
||||||
var offhand = MainHandCombo.LastCategory.AllowsOffHand();
|
var offhand = MainHandCombo.LastCategory.Offhand();
|
||||||
if (offhand != WeaponCategory.Unknown)
|
if (offhand != FullEquipType.Unknown)
|
||||||
{
|
{
|
||||||
_currentSlot = EquipSlot.OffHand;
|
_currentSlot = EquipSlot.OffHand;
|
||||||
DrawStainCombo();
|
DrawStainCombo();
|
||||||
|
|
@ -128,8 +128,8 @@ public partial class EquipmentDrawer
|
||||||
DrawStainCombo();
|
DrawStainCombo();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawMainHandSelector(ref mainHand);
|
DrawMainHandSelector(ref mainHand);
|
||||||
var offhand = MainHandCombo.LastCategory.AllowsOffHand();
|
var offhand = MainHandCombo.LastCategory.Offhand();
|
||||||
if (offhand != WeaponCategory.Unknown)
|
if (offhand != FullEquipType.Unknown)
|
||||||
{
|
{
|
||||||
_currentSlot = EquipSlot.OffHand;
|
_currentSlot = EquipSlot.OffHand;
|
||||||
DrawCheckbox(ref flags);
|
DrawCheckbox(ref flags);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public unsafe partial struct Actor : IEquatable<Actor>, IDesignable
|
||||||
=> actor.Pointer == null ? IntPtr.Zero : (IntPtr)actor.Pointer;
|
=> actor.Pointer == null ? IntPtr.Zero : (IntPtr)actor.Pointer;
|
||||||
|
|
||||||
public ActorIdentifier GetIdentifier()
|
public ActorIdentifier GetIdentifier()
|
||||||
=> Glamourer.Actors.FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Pointer);
|
=> Glamourer.Actors.FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Pointer, out _, true, true);
|
||||||
|
|
||||||
public bool Identifier(out ActorIdentifier ident)
|
public bool Identifier(out ActorIdentifier ident)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ public unsafe partial class RedrawManager
|
||||||
// redrawOnEquality controls whether the game does anything if the new weapon is identical to the old one.
|
// redrawOnEquality controls whether the game does anything if the new weapon is identical to the old one.
|
||||||
// skipGameObject seems to control whether the new weapons are written to the game object or just influence the draw object. (1 = skip, 0 = change)
|
// skipGameObject seems to control whether the new weapons are written to the game object or just influence the draw object. (1 = skip, 0 = change)
|
||||||
// unk4 seemed to be the same as unk1.
|
// unk4 seemed to be the same as unk1.
|
||||||
[Signature("E8 ?? ?? ?? ?? 44 8B 9F", DetourName = nameof(LoadWeaponDetour))]
|
[Signature(Penumbra.GameData.Sigs.WeaponReload, DetourName = nameof(LoadWeaponDetour))]
|
||||||
private readonly Hook<LoadWeaponDelegate> _loadWeaponHook = null!;
|
private readonly Hook<LoadWeaponDelegate> _loadWeaponHook = null!;
|
||||||
|
|
||||||
private void LoadWeaponDetour(IntPtr characterOffset, uint slot, ulong weapon, byte redrawOnEquality, byte unk2, byte skipGameObject,
|
private void LoadWeaponDetour(IntPtr characterOffset, uint slot, ulong weapon, byte redrawOnEquality, byte unk2, byte skipGameObject,
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,5 @@ public unsafe partial class RedrawManager : IDisposable
|
||||||
private static void OnCharacterRedrawFinished(IntPtr gameObject, string collection, IntPtr drawObject)
|
private static void OnCharacterRedrawFinished(IntPtr gameObject, string collection, IntPtr drawObject)
|
||||||
{
|
{
|
||||||
//SetVisor((Human*)drawObject, true);
|
//SetVisor((Human*)drawObject, true);
|
||||||
if (Glamourer.Models.FromCharacterBase((CharacterBase*)drawObject, out var data))
|
|
||||||
PluginLog.Information($"Name: {data.FirstName} ({data.Id})");
|
|
||||||
else
|
|
||||||
PluginLog.Information($"Key: {Glamourer.Models.KeyFromCharacterBase((CharacterBase*)drawObject):X16}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue