mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Use IDesignEditor for designs.
This commit is contained in:
parent
46fcac6c7d
commit
b92dc03eb5
6 changed files with 448 additions and 337 deletions
314
Glamourer/Designs/DesignEditor.cs
Normal file
314
Glamourer/Designs/DesignEditor.cs
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
using Glamourer.Designs.Links;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
public class DesignEditor(
|
||||
SaveService saveService,
|
||||
DesignChanged designChanged,
|
||||
CustomizeService customizations,
|
||||
ItemManager items,
|
||||
Configuration config)
|
||||
: IDesignEditor
|
||||
{
|
||||
protected readonly DesignChanged DesignChanged = designChanged;
|
||||
protected readonly SaveService SaveService = saveService;
|
||||
protected readonly ItemManager Items = items;
|
||||
protected readonly CustomizeService Customizations = customizations;
|
||||
protected readonly Configuration Config = config;
|
||||
protected readonly Dictionary<Guid, DesignData> UndoStore = [];
|
||||
|
||||
private bool _forceFullItemOff = false;
|
||||
|
||||
/// <summary> Whether an Undo for the given design is possible. </summary>
|
||||
public bool CanUndo(Design? design)
|
||||
=> design != null && UndoStore.ContainsKey(design.Identifier);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeCustomize(object data, CustomizeIndex idx, CustomizeValue value, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
var oldValue = design.DesignData.Customize[idx];
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case CustomizeIndex.Race:
|
||||
case CustomizeIndex.BodyType:
|
||||
Glamourer.Log.Error("Somehow race or body type was changed in a design. This should not happen.");
|
||||
return;
|
||||
case CustomizeIndex.Clan:
|
||||
{
|
||||
var customize = design.DesignData.Customize;
|
||||
if (Customizations.ChangeClan(ref customize, (SubRace)value.Value) == 0)
|
||||
return;
|
||||
if (!design.SetCustomize(Customizations, customize))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
case CustomizeIndex.Gender:
|
||||
{
|
||||
var customize = design.DesignData.Customize;
|
||||
if (Customizations.ChangeGender(ref customize, (Gender)(value.Value + 1)) == 0)
|
||||
return;
|
||||
if (!design.SetCustomize(Customizations, customize))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!Customizations.IsCustomizationValid(design.DesignData.Customize.Clan, design.DesignData.Customize.Gender,
|
||||
design.DesignData.Customize.Face, idx, value)
|
||||
|| !design.GetDesignDataRef().Customize.Set(idx, value))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Changed customize {idx.ToDefaultName()} in design {design.Identifier} from {oldValue.Value} to {value.Value}.");
|
||||
SaveService.QueueSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Customize, design, (oldValue, value, idx));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeEntireCustomize(object data, in CustomizeArray customize, CustomizeFlag apply, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
var (newCustomize, applied, changed) = Customizations.Combine(design.DesignData.Customize, customize, apply, true);
|
||||
if (changed == 0)
|
||||
return;
|
||||
|
||||
var oldCustomize = design.DesignData.Customize;
|
||||
design.SetCustomize(Customizations, newCustomize);
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Changed entire customize with resulting flags {applied} and {changed}.");
|
||||
SaveService.QueueSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.EntireCustomize, design, (oldCustomize, applied, changed));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeCustomizeParameter(object data, CustomizeParameterFlag flag, CustomizeParameterValue value, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
var old = design.DesignData.Parameters[flag];
|
||||
if (!design.GetDesignDataRef().Parameters.Set(flag, value))
|
||||
return;
|
||||
|
||||
var @new = design.DesignData.Parameters[flag];
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Set customize parameter {flag} in design {design.Identifier} from {old} to {@new}.");
|
||||
SaveService.QueueSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Parameter, design, (old, @new, flag));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeItem(object data, EquipSlot slot, EquipItem item, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
switch (slot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
{
|
||||
var currentMain = design.DesignData.Item(EquipSlot.MainHand);
|
||||
var currentOff = design.DesignData.Item(EquipSlot.OffHand);
|
||||
if (!Items.IsItemValid(EquipSlot.MainHand, item.ItemId, out item))
|
||||
return;
|
||||
|
||||
if (!ChangeMainhandPeriphery(design, currentMain, currentOff, item, out var newOff, out var newGauntlets))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {EquipSlot.MainHand.ToName()} weapon in design {design.Identifier} from {currentMain.Name} ({currentMain.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
DesignChanged.Invoke(DesignChanged.Type.Weapon, design, (currentMain, currentOff, item, newOff, newGauntlets));
|
||||
return;
|
||||
}
|
||||
case EquipSlot.OffHand:
|
||||
{
|
||||
var currentMain = design.DesignData.Item(EquipSlot.MainHand);
|
||||
var currentOff = design.DesignData.Item(EquipSlot.OffHand);
|
||||
if (!Items.IsOffhandValid(currentOff.Type, item.ItemId, out item))
|
||||
return;
|
||||
|
||||
if (!design.GetDesignDataRef().SetItem(EquipSlot.OffHand, item))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {EquipSlot.OffHand.ToName()} weapon in design {design.Identifier} from {currentOff.Name} ({currentOff.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
DesignChanged.Invoke(DesignChanged.Type.Weapon, design, (currentMain, currentOff, currentMain, item));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!Items.IsItemValid(slot, item.Id, out item))
|
||||
return;
|
||||
|
||||
var old = design.DesignData.Item(slot);
|
||||
if (!design.GetDesignDataRef().SetItem(slot, item))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {slot.ToName()} equipment piece in design {design.Identifier} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
SaveService.QueueSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Equip, design, (old, item, slot));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeStain(object data, EquipSlot slot, StainId stain, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
if (Items.ValidateStain(stain, out var _, false).Length > 0)
|
||||
return;
|
||||
|
||||
var oldStain = design.DesignData.Stain(slot);
|
||||
if (!design.GetDesignDataRef().SetStain(slot, stain))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stain.Id}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.Stain, design, (oldStain, stain, slot));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainId? stain, ApplySettings _ = default)
|
||||
{
|
||||
if (item.HasValue)
|
||||
ChangeItem(data, slot, item.Value, _);
|
||||
if (stain.HasValue)
|
||||
ChangeStain(data, slot, stain.Value, _);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeCrest(object data, CrestFlag slot, bool crest, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
var oldCrest = design.DesignData.Crest(slot);
|
||||
if (!design.GetDesignDataRef().SetCrest(slot, crest))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set crest visibility of {slot} equipment piece to {crest}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.Crest, design, (oldCrest, crest, slot));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeMetaState(object data, MetaIndex metaIndex, bool value, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
if (!design.GetDesignDataRef().SetMeta(metaIndex, value))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set value of {metaIndex} to {value}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.Other, design, (metaIndex, false, value));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ApplyDesign(object data, MergedDesign other, ApplySettings _ = default)
|
||||
=> ApplyDesign(data, other.Design);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ApplyDesign(object data, DesignBase other, ApplySettings _ = default)
|
||||
{
|
||||
if (data is not Design design)
|
||||
return;
|
||||
|
||||
UndoStore[design.Identifier] = design.DesignData;
|
||||
foreach (var index in MetaExtensions.AllRelevant.Where(other.DoApplyMeta))
|
||||
design.GetDesignDataRef().SetMeta(index, other.DesignData.GetMeta(index));
|
||||
|
||||
if (!design.DesignData.IsHuman)
|
||||
return;
|
||||
|
||||
ChangeEntireCustomize(design, other.DesignData.Customize, other.ApplyCustomize);
|
||||
|
||||
_forceFullItemOff = true;
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
if (other.DoApplyEquip(slot))
|
||||
ChangeItem(design, slot, other.DesignData.Item(slot));
|
||||
|
||||
if (other.DoApplyStain(slot))
|
||||
ChangeStain(design, slot, other.DesignData.Stain(slot));
|
||||
}
|
||||
_forceFullItemOff = false;
|
||||
|
||||
foreach (var slot in Enum.GetValues<CrestFlag>().Where(other.DoApplyCrest))
|
||||
ChangeCrest(design, slot, other.DesignData.Crest(slot));
|
||||
|
||||
foreach (var parameter in CustomizeParameterExtensions.AllFlags.Where(other.DoApplyParameter))
|
||||
ChangeCustomizeParameter(design, parameter, other.DesignData.Parameters[parameter]);
|
||||
}
|
||||
|
||||
/// <summary> Change a mainhand weapon and either fix or apply appropriate offhand and potentially gauntlets. </summary>
|
||||
private bool ChangeMainhandPeriphery(Design design, EquipItem currentMain, EquipItem currentOff, EquipItem newMain, out EquipItem? newOff,
|
||||
out EquipItem? newGauntlets)
|
||||
{
|
||||
newOff = null;
|
||||
newGauntlets = null;
|
||||
if (newMain.Type != currentMain.Type)
|
||||
{
|
||||
var defaultOffhand = Items.GetDefaultOffhand(newMain);
|
||||
if (!Items.IsOffhandValid(newMain, defaultOffhand.ItemId, out var o))
|
||||
return false;
|
||||
|
||||
newOff = o;
|
||||
}
|
||||
else if (!_forceFullItemOff && Config.ChangeEntireItem)
|
||||
{
|
||||
var defaultOffhand = Items.GetDefaultOffhand(newMain);
|
||||
if (Items.IsOffhandValid(newMain, defaultOffhand.ItemId, out var o))
|
||||
newOff = o;
|
||||
|
||||
if (newMain.Type is FullEquipType.Fists && Items.ItemData.Tertiary.TryGetValue(newMain.ItemId, out var g))
|
||||
newGauntlets = g;
|
||||
}
|
||||
|
||||
if (!design.GetDesignDataRef().SetItem(EquipSlot.MainHand, newMain))
|
||||
return false;
|
||||
|
||||
if (newOff.HasValue && !design.GetDesignDataRef().SetItem(EquipSlot.OffHand, newOff.Value))
|
||||
{
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.MainHand, currentMain);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newGauntlets.HasValue && !design.GetDesignDataRef().SetItem(EquipSlot.Hands, newGauntlets.Value))
|
||||
{
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.MainHand, currentMain);
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.OffHand, currentOff);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,32 +9,20 @@ using Newtonsoft.Json.Linq;
|
|||
using OtterGui;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
public class DesignManager
|
||||
public class DesignManager : DesignEditor
|
||||
{
|
||||
private readonly CustomizeService _customizations;
|
||||
private readonly Configuration _config;
|
||||
private readonly ItemManager _items;
|
||||
private readonly HumanModelList _humans;
|
||||
private readonly SaveService _saveService;
|
||||
private readonly DesignChanged _event;
|
||||
private readonly Dictionary<Guid, DesignData> _undoStore = [];
|
||||
|
||||
public DesignStorage Designs { get; }
|
||||
public readonly DesignStorage Designs;
|
||||
private readonly HumanModelList _humans;
|
||||
|
||||
public DesignManager(SaveService saveService, ItemManager items, CustomizeService customizations,
|
||||
DesignChanged @event, HumanModelList humans, DesignStorage storage, DesignLinkLoader designLinkLoader, Configuration config)
|
||||
: base(saveService, @event, customizations, items, config)
|
||||
{
|
||||
Designs = storage;
|
||||
_config = config;
|
||||
_saveService = saveService;
|
||||
_items = items;
|
||||
_customizations = customizations;
|
||||
_event = @event;
|
||||
_humans = humans;
|
||||
Designs = storage;
|
||||
_humans = humans;
|
||||
|
||||
LoadDesigns(designLinkLoader);
|
||||
CreateDesignFolder(saveService);
|
||||
|
|
@ -42,27 +30,29 @@ public class DesignManager
|
|||
designLinkLoader.SetAllObjects();
|
||||
}
|
||||
|
||||
#region Design Management
|
||||
|
||||
/// <summary>
|
||||
/// Clear currently loaded designs and load all designs anew from file.
|
||||
/// Invalid data is fixed, but changes are not saved until manual changes.
|
||||
/// </summary>
|
||||
public void LoadDesigns(DesignLinkLoader linkLoader)
|
||||
private void LoadDesigns(DesignLinkLoader linkLoader)
|
||||
{
|
||||
_humans.Awaiter.Wait();
|
||||
_customizations.Awaiter.Wait();
|
||||
_items.ItemData.Awaiter.Wait();
|
||||
Customizations.Awaiter.Wait();
|
||||
Items.ItemData.Awaiter.Wait();
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
Designs.Clear();
|
||||
var skipped = 0;
|
||||
ThreadLocal<List<(Design, string)>> designs = new(() => [], true);
|
||||
Parallel.ForEach(_saveService.FileNames.Designs(), (f, _) =>
|
||||
Parallel.ForEach(SaveService.FileNames.Designs(), (f, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(f.FullName);
|
||||
var data = JObject.Parse(text);
|
||||
var design = Design.LoadDesign(_customizations, _items, linkLoader, data);
|
||||
var design = Design.LoadDesign(Customizations, Items, linkLoader, data);
|
||||
designs.Value!.Add((design, f.FullName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -95,22 +85,18 @@ public class DesignManager
|
|||
|
||||
Glamourer.Log.Information(
|
||||
$"Loaded {Designs.Count} designs in {stopwatch.ElapsedMilliseconds} ms.{(skipped > 0 ? $" Skipped loading {skipped} designs due to errors." : string.Empty)}");
|
||||
_event.Invoke(DesignChanged.Type.ReloadedAll, null!, null);
|
||||
DesignChanged.Invoke(DesignChanged.Type.ReloadedAll, null!, null);
|
||||
}
|
||||
|
||||
/// <summary> Whether an Undo for the given design is possible. </summary>
|
||||
public bool CanUndo(Design? design)
|
||||
=> design != null && _undoStore.ContainsKey(design.Identifier);
|
||||
|
||||
/// <summary> Create a new temporary design without adding it to the manager. </summary>
|
||||
public DesignBase CreateTemporary()
|
||||
=> new(_customizations, _items);
|
||||
=> new(Customizations, Items);
|
||||
|
||||
/// <summary> Create a new design of a given name. </summary>
|
||||
public Design CreateEmpty(string name, bool handlePath)
|
||||
{
|
||||
var (actualName, path) = ParseName(name, handlePath);
|
||||
var design = new Design(_customizations, _items)
|
||||
var design = new Design(Customizations, Items)
|
||||
{
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
|
|
@ -120,8 +106,8 @@ public class DesignManager
|
|||
};
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
||||
_saveService.ImmediateSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Created, design, path);
|
||||
SaveService.ImmediateSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, path);
|
||||
return design;
|
||||
}
|
||||
|
||||
|
|
@ -140,8 +126,8 @@ public class DesignManager
|
|||
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug($"Added new design {design.Identifier} by cloning Temporary Design.");
|
||||
_saveService.ImmediateSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Created, design, path);
|
||||
SaveService.ImmediateSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, path);
|
||||
return design;
|
||||
}
|
||||
|
||||
|
|
@ -160,8 +146,8 @@ public class DesignManager
|
|||
Designs.Add(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Added new design {design.Identifier} by cloning {clone.Identifier.ToString()}.");
|
||||
_saveService.ImmediateSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Created, design, path);
|
||||
SaveService.ImmediateSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, path);
|
||||
return design;
|
||||
}
|
||||
|
||||
|
|
@ -171,10 +157,14 @@ public class DesignManager
|
|||
foreach (var d in Designs.Skip(design.Index + 1))
|
||||
--d.Index;
|
||||
Designs.RemoveAt(design.Index);
|
||||
_saveService.ImmediateDelete(design);
|
||||
_event.Invoke(DesignChanged.Type.Deleted, design, null);
|
||||
SaveService.ImmediateDelete(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Deleted, design, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Edit Information
|
||||
|
||||
/// <summary> Rename a design. </summary>
|
||||
public void Rename(Design design, string newName)
|
||||
{
|
||||
|
|
@ -184,9 +174,9 @@ public class DesignManager
|
|||
|
||||
design.Name = newName;
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Renamed design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.Renamed, design, oldName);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Renamed, design, oldName);
|
||||
}
|
||||
|
||||
/// <summary> Change the description of a design. </summary>
|
||||
|
|
@ -198,9 +188,9 @@ public class DesignManager
|
|||
|
||||
design.Description = description;
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Changed description of design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.ChangedDescription, design, oldDescription);
|
||||
DesignChanged.Invoke(DesignChanged.Type.ChangedDescription, design, oldDescription);
|
||||
}
|
||||
|
||||
public void ChangeColor(Design design, string newColor)
|
||||
|
|
@ -211,9 +201,9 @@ public class DesignManager
|
|||
|
||||
design.Color = newColor;
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Changed color of design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.ChangedColor, design, oldColor);
|
||||
DesignChanged.Invoke(DesignChanged.Type.ChangedColor, design, oldColor);
|
||||
}
|
||||
|
||||
/// <summary> Add a new tag to a design. The tags remain sorted. </summary>
|
||||
|
|
@ -225,15 +215,11 @@ public class DesignManager
|
|||
design.Tags = design.Tags.Append(tag).OrderBy(t => t).ToArray();
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
var idx = design.Tags.IndexOf(tag);
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Added tag {tag} at {idx} to design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.AddedTag, design, (tag, idx));
|
||||
DesignChanged.Invoke(DesignChanged.Type.AddedTag, design, (tag, idx));
|
||||
}
|
||||
|
||||
/// <summary> Remove a tag from a design if it exists. </summary>
|
||||
public void RemoveTag(Design design, string tag)
|
||||
=> RemoveTag(design, design.Tags.IndexOf(tag));
|
||||
|
||||
/// <summary> Remove a tag from a design by its index. </summary>
|
||||
public void RemoveTag(Design design, int tagIdx)
|
||||
{
|
||||
|
|
@ -243,9 +229,9 @@ public class DesignManager
|
|||
var oldTag = design.Tags[tagIdx];
|
||||
design.Tags = design.Tags.Take(tagIdx).Concat(design.Tags.Skip(tagIdx + 1)).ToArray();
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Removed tag {oldTag} at {tagIdx} from design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.RemovedTag, design, (oldTag, tagIdx));
|
||||
DesignChanged.Invoke(DesignChanged.Type.RemovedTag, design, (oldTag, tagIdx));
|
||||
}
|
||||
|
||||
/// <summary> Rename a tag from a design by its index. The tags stay sorted.</summary>
|
||||
|
|
@ -258,9 +244,9 @@ public class DesignManager
|
|||
design.Tags[tagIdx] = newTag;
|
||||
Array.Sort(design.Tags);
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Renamed tag {oldTag} at {tagIdx} to {newTag} in design {design.Identifier} and reordered tags.");
|
||||
_event.Invoke(DesignChanged.Type.ChangedTag, design, (oldTag, newTag, tagIdx));
|
||||
DesignChanged.Invoke(DesignChanged.Type.ChangedTag, design, (oldTag, newTag, tagIdx));
|
||||
}
|
||||
|
||||
/// <summary> Add an associated mod to a design. </summary>
|
||||
|
|
@ -270,9 +256,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Added associated mod {mod.DirectoryName} to design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.AddedMod, design, (mod, settings));
|
||||
DesignChanged.Invoke(DesignChanged.Type.AddedMod, design, (mod, settings));
|
||||
}
|
||||
|
||||
/// <summary> Remove an associated mod from a design. </summary>
|
||||
|
|
@ -282,9 +268,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Removed associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.RemovedMod, design, (mod, settings));
|
||||
DesignChanged.Invoke(DesignChanged.Type.RemovedMod, design, (mod, settings));
|
||||
}
|
||||
|
||||
/// <summary> Set the write protection status of a design. </summary>
|
||||
|
|
@ -293,56 +279,14 @@ public class DesignManager
|
|||
if (!design.SetWriteProtected(value))
|
||||
return;
|
||||
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set design {design.Identifier} to {(value ? "no longer be " : string.Empty)} write-protected.");
|
||||
_event.Invoke(DesignChanged.Type.WriteProtection, design, value);
|
||||
DesignChanged.Invoke(DesignChanged.Type.WriteProtection, design, value);
|
||||
}
|
||||
|
||||
/// <summary> Change a customization value. </summary>
|
||||
public void ChangeCustomize(Design design, CustomizeIndex idx, CustomizeValue value)
|
||||
{
|
||||
var oldValue = design.DesignData.Customize[idx];
|
||||
#endregion
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case CustomizeIndex.Race:
|
||||
case CustomizeIndex.BodyType:
|
||||
Glamourer.Log.Error("Somehow race or body type was changed in a design. This should not happen.");
|
||||
return;
|
||||
case CustomizeIndex.Clan:
|
||||
{
|
||||
var customize = design.DesignData.Customize;
|
||||
if (_customizations.ChangeClan(ref customize, (SubRace)value.Value) == 0)
|
||||
return;
|
||||
if (!design.SetCustomize(_customizations, customize))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
case CustomizeIndex.Gender:
|
||||
{
|
||||
var customize = design.DesignData.Customize;
|
||||
if (_customizations.ChangeGender(ref customize, (Gender)(value.Value + 1)) == 0)
|
||||
return;
|
||||
if (!design.SetCustomize(_customizations, customize))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!_customizations.IsCustomizationValid(design.DesignData.Customize.Clan, design.DesignData.Customize.Gender,
|
||||
design.DesignData.Customize.Face, idx, value)
|
||||
|| !design.GetDesignDataRef().Customize.Set(idx, value))
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Changed customize {idx.ToDefaultName()} in design {design.Identifier} from {oldValue.Value} to {value.Value}.");
|
||||
_saveService.QueueSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Customize, design, (oldValue, value, idx));
|
||||
}
|
||||
#region Edit Application Rules
|
||||
|
||||
/// <summary> Change whether to apply a specific customize value. </summary>
|
||||
public void ChangeApplyCustomize(Design design, CustomizeIndex idx, bool value)
|
||||
|
|
@ -351,79 +295,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of customization {idx.ToDefaultName()} to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.ApplyCustomize, design, idx);
|
||||
}
|
||||
|
||||
/// <summary> Change a non-weapon equipment piece. </summary>
|
||||
public void ChangeEquip(Design design, EquipSlot slot, EquipItem item)
|
||||
{
|
||||
if (!_items.IsItemValid(slot, item.Id, out item))
|
||||
return;
|
||||
|
||||
var old = design.DesignData.Item(slot);
|
||||
if (!design.GetDesignDataRef().SetItem(slot, item))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {slot.ToName()} equipment piece in design {design.Identifier} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
_saveService.QueueSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Equip, design, (old, item, slot));
|
||||
}
|
||||
|
||||
/// <summary> Change a weapon. </summary>
|
||||
public void ChangeWeapon(Design design, EquipSlot slot, EquipItem item)
|
||||
{
|
||||
var currentMain = design.DesignData.Item(EquipSlot.MainHand);
|
||||
var currentOff = design.DesignData.Item(EquipSlot.OffHand);
|
||||
switch (slot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
|
||||
if (!_items.IsItemValid(EquipSlot.MainHand, item.ItemId, out item))
|
||||
return;
|
||||
|
||||
if (!ChangeMainhandPeriphery(design, currentMain, currentOff, item, out var newOff, out var newGauntlets))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {EquipSlot.MainHand.ToName()} weapon in design {design.Identifier} from {currentMain.Name} ({currentMain.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
_event.Invoke(DesignChanged.Type.Weapon, design, (currentMain, currentOff, item, newOff, newGauntlets));
|
||||
|
||||
return;
|
||||
case EquipSlot.OffHand:
|
||||
if (!_items.IsOffhandValid(currentOff.Type, item.ItemId, out item))
|
||||
return;
|
||||
|
||||
if (!design.GetDesignDataRef().SetItem(EquipSlot.OffHand, item))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Set {EquipSlot.OffHand.ToName()} weapon in design {design.Identifier} from {currentOff.Name} ({currentOff.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||
_event.Invoke(DesignChanged.Type.Weapon, design, (currentMain, currentOff, currentMain, item, (EquipItem?)null));
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Change a customize parameter. </summary>
|
||||
public void ChangeCustomizeParameter(Design design, CustomizeParameterFlag flag, CustomizeParameterValue value)
|
||||
{
|
||||
var old = design.DesignData.Parameters[flag];
|
||||
if (!design.GetDesignDataRef().Parameters.Set(flag, value))
|
||||
return;
|
||||
|
||||
var @new = design.DesignData.Parameters[flag];
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Set customize parameter {flag} in design {design.Identifier} from {old} to {@new}.");
|
||||
_saveService.QueueSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Parameter, design, (old, @new, flag));
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyCustomize, design, idx);
|
||||
}
|
||||
|
||||
/// <summary> Change whether to apply a specific equipment piece. </summary>
|
||||
|
|
@ -433,25 +307,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of {slot} equipment piece to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.ApplyEquip, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change the stain for any equipment piece. </summary>
|
||||
public void ChangeStain(Design design, EquipSlot slot, StainId stain)
|
||||
{
|
||||
if (_items.ValidateStain(stain, out _, false).Length > 0)
|
||||
return;
|
||||
|
||||
var oldStain = design.DesignData.Stain(slot);
|
||||
if (!design.GetDesignDataRef().SetStain(slot, stain))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stain.Id}.");
|
||||
_event.Invoke(DesignChanged.Type.Stain, design, (oldStain, stain, slot));
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyEquip, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change whether to apply a specific stain. </summary>
|
||||
|
|
@ -461,22 +319,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of stain of {slot} equipment piece to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.ApplyStain, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change the crest visibility for any equipment piece. </summary>
|
||||
public void ChangeCrest(Design design, CrestFlag slot, bool crest)
|
||||
{
|
||||
var oldCrest = design.DesignData.Crest(slot);
|
||||
if (!design.GetDesignDataRef().SetCrest(slot, crest))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set crest visibility of {slot} equipment piece to {crest}.");
|
||||
_event.Invoke(DesignChanged.Type.Crest, design, (oldCrest, crest, slot));
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyStain, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change whether to apply a specific crest visibility. </summary>
|
||||
|
|
@ -486,21 +331,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of crest visibility of {slot} equipment piece to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.ApplyCrest, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change the bool value of one of the meta flags. </summary>
|
||||
public void ChangeMeta(Design design, MetaIndex metaIndex, bool value)
|
||||
{
|
||||
if (!design.GetDesignDataRef().SetMeta(metaIndex, value))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set value of {metaIndex} to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.Other, design, (metaIndex, false, value));
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyCrest, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change the application value of one of the meta flags. </summary>
|
||||
|
|
@ -510,9 +343,9 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of {metaIndex} to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.Other, design, (metaIndex, true, value));
|
||||
DesignChanged.Invoke(DesignChanged.Type.Other, design, (metaIndex, true, value));
|
||||
}
|
||||
|
||||
/// <summary> Change the application value of a customize parameter. </summary>
|
||||
|
|
@ -522,68 +355,26 @@ public class DesignManager
|
|||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
_saveService.QueueSave(design);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of parameter {flag} to {value}.");
|
||||
_event.Invoke(DesignChanged.Type.ApplyParameter, design, flag);
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyParameter, design, flag);
|
||||
}
|
||||
|
||||
/// <summary> Apply an entire design based on its appliance rules piece by piece. </summary>
|
||||
public void ApplyDesign(Design design, DesignBase other)
|
||||
{
|
||||
_undoStore[design.Identifier] = design.DesignData;
|
||||
foreach (var index in MetaExtensions.AllRelevant.Where(other.DoApplyMeta))
|
||||
design.GetDesignDataRef().SetMeta(index, other.DesignData.GetMeta(index));
|
||||
|
||||
if (design.DesignData.IsHuman)
|
||||
{
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
if (other.DoApplyCustomize(index))
|
||||
ChangeCustomize(design, index, other.DesignData.Customize[index]);
|
||||
}
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
if (other.DoApplyEquip(slot))
|
||||
ChangeEquip(design, slot, other.DesignData.Item(slot));
|
||||
|
||||
if (other.DoApplyStain(slot))
|
||||
ChangeStain(design, slot, other.DesignData.Stain(slot));
|
||||
}
|
||||
|
||||
foreach (var slot in Enum.GetValues<CrestFlag>())
|
||||
{
|
||||
if (other.DoApplyCrest(slot))
|
||||
ChangeCrest(design, slot, other.DesignData.Crest(slot));
|
||||
}
|
||||
}
|
||||
|
||||
if (other.DoApplyEquip(EquipSlot.MainHand))
|
||||
ChangeWeapon(design, EquipSlot.MainHand, other.DesignData.Item(EquipSlot.MainHand));
|
||||
|
||||
if (other.DoApplyEquip(EquipSlot.OffHand))
|
||||
ChangeWeapon(design, EquipSlot.OffHand, other.DesignData.Item(EquipSlot.OffHand));
|
||||
|
||||
if (other.DoApplyStain(EquipSlot.MainHand))
|
||||
ChangeStain(design, EquipSlot.MainHand, other.DesignData.Stain(EquipSlot.MainHand));
|
||||
|
||||
if (other.DoApplyStain(EquipSlot.OffHand))
|
||||
ChangeStain(design, EquipSlot.OffHand, other.DesignData.Stain(EquipSlot.OffHand));
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void UndoDesignChange(Design design)
|
||||
{
|
||||
if (!_undoStore.Remove(design.Identifier, out var otherData))
|
||||
if (!UndoStore.Remove(design.Identifier, out var otherData))
|
||||
return;
|
||||
|
||||
var other = CreateTemporary();
|
||||
other.SetDesignData(_customizations, otherData);
|
||||
other.SetDesignData(Customizations, otherData);
|
||||
ApplyDesign(design, other);
|
||||
}
|
||||
|
||||
private void MigrateOldDesigns()
|
||||
{
|
||||
if (!File.Exists(_saveService.FileNames.MigrationDesignFile))
|
||||
if (!File.Exists(SaveService.FileNames.MigrationDesignFile))
|
||||
return;
|
||||
|
||||
var errors = 0;
|
||||
|
|
@ -592,7 +383,7 @@ public class DesignManager
|
|||
var oldDesigns = Designs.ToList();
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(_saveService.FileNames.MigrationDesignFile);
|
||||
var text = File.ReadAllText(SaveService.FileNames.MigrationDesignFile);
|
||||
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>();
|
||||
var migratedFileSystemPaths = new Dictionary<string, string>(dict.Count);
|
||||
foreach (var (name, base64) in dict)
|
||||
|
|
@ -600,14 +391,14 @@ public class DesignManager
|
|||
try
|
||||
{
|
||||
var actualName = Path.GetFileName(name);
|
||||
var design = new Design(_customizations, _items)
|
||||
var design = new Design(Customizations, Items)
|
||||
{
|
||||
CreationDate = File.GetCreationTimeUtc(_saveService.FileNames.MigrationDesignFile),
|
||||
LastEdit = File.GetLastWriteTimeUtc(_saveService.FileNames.MigrationDesignFile),
|
||||
CreationDate = File.GetCreationTimeUtc(SaveService.FileNames.MigrationDesignFile),
|
||||
LastEdit = File.GetLastWriteTimeUtc(SaveService.FileNames.MigrationDesignFile),
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
};
|
||||
design.MigrateBase64(_customizations, _items, _humans, base64);
|
||||
design.MigrateBase64(Customizations, Items, _humans, base64);
|
||||
if (!oldDesigns.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate))
|
||||
{
|
||||
Add(design, $"Migrated old design to {design.Identifier}.");
|
||||
|
|
@ -628,24 +419,24 @@ public class DesignManager
|
|||
}
|
||||
}
|
||||
|
||||
DesignFileSystem.MigrateOldPaths(_saveService, migratedFileSystemPaths);
|
||||
DesignFileSystem.MigrateOldPaths(SaveService, migratedFileSystemPaths);
|
||||
Glamourer.Log.Information(
|
||||
$"Successfully migrated {successes} old designs. Skipped {skips} already migrated designs. Failed to migrate {errors} designs.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Glamourer.Log.Error($"Could not migrate old design file {_saveService.FileNames.MigrationDesignFile}:\n{e}");
|
||||
Glamourer.Log.Error($"Could not migrate old design file {SaveService.FileNames.MigrationDesignFile}:\n{e}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Move(_saveService.FileNames.MigrationDesignFile,
|
||||
Path.ChangeExtension(_saveService.FileNames.MigrationDesignFile, ".json.bak"));
|
||||
Glamourer.Log.Information($"Moved migrated design file {_saveService.FileNames.MigrationDesignFile} to backup file.");
|
||||
File.Move(SaveService.FileNames.MigrationDesignFile,
|
||||
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"));
|
||||
Glamourer.Log.Information($"Moved migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Could not move migrated design file {_saveService.FileNames.MigrationDesignFile} to backup file:\n{ex}");
|
||||
Glamourer.Log.Error($"Could not move migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -675,7 +466,7 @@ public class DesignManager
|
|||
{
|
||||
try
|
||||
{
|
||||
var correctName = _saveService.FileNames.DesignFile(design);
|
||||
var correctName = SaveService.FileNames.DesignFile(design);
|
||||
File.Move(name, correctName, false);
|
||||
Glamourer.Log.Information($"Moved invalid design file from {Path.GetFileName(name)} to {Path.GetFileName(correctName)}.");
|
||||
}
|
||||
|
|
@ -705,18 +496,17 @@ public class DesignManager
|
|||
/// Returns false if the design is already contained or if the identifier is already in use.
|
||||
/// The design is treated as newly created and invokes an event.
|
||||
/// </summary>
|
||||
private bool Add(Design design, string? message)
|
||||
private void Add(Design design, string? message)
|
||||
{
|
||||
if (Designs.Any(d => d == design || d.Identifier == design.Identifier))
|
||||
return false;
|
||||
return;
|
||||
|
||||
design.Index = Designs.Count;
|
||||
Designs.Add(design);
|
||||
if (!message.IsNullOrEmpty())
|
||||
Glamourer.Log.Debug(message);
|
||||
_saveService.ImmediateSave(design);
|
||||
_event.Invoke(DesignChanged.Type.Created, design, null);
|
||||
return true;
|
||||
SaveService.ImmediateSave(design);
|
||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, null);
|
||||
}
|
||||
|
||||
/// <summary> Split a given string into its folder path and its name, if <paramref name="handlePath"/> is true. </summary>
|
||||
|
|
@ -736,47 +526,4 @@ public class DesignManager
|
|||
|
||||
return (actualName, path);
|
||||
}
|
||||
|
||||
/// <summary> Change a mainhand weapon and either fix or apply appropriate offhand and potentially gauntlets. </summary>
|
||||
private bool ChangeMainhandPeriphery(Design design, EquipItem currentMain, EquipItem currentOff, EquipItem newMain, out EquipItem? newOff,
|
||||
out EquipItem? newGauntlets)
|
||||
{
|
||||
newOff = null;
|
||||
newGauntlets = null;
|
||||
if (newMain.Type != currentMain.Type)
|
||||
{
|
||||
var defaultOffhand = _items.GetDefaultOffhand(newMain);
|
||||
if (!_items.IsOffhandValid(newMain, defaultOffhand.ItemId, out var o))
|
||||
return false;
|
||||
|
||||
newOff = o;
|
||||
}
|
||||
else if (_config.ChangeEntireItem)
|
||||
{
|
||||
var defaultOffhand = _items.GetDefaultOffhand(newMain);
|
||||
if (_items.IsOffhandValid(newMain, defaultOffhand.ItemId, out var o))
|
||||
newOff = o;
|
||||
|
||||
if (newMain.Type is FullEquipType.Fists && _items.ItemData.Tertiary.TryGetValue(newMain.ItemId, out var g))
|
||||
newGauntlets = g;
|
||||
}
|
||||
|
||||
if (!design.GetDesignDataRef().SetItem(EquipSlot.MainHand, newMain))
|
||||
return false;
|
||||
|
||||
if (newOff.HasValue && !design.GetDesignDataRef().SetItem(EquipSlot.OffHand, newOff.Value))
|
||||
{
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.MainHand, currentMain);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newGauntlets.HasValue && !design.GetDesignDataRef().SetItem(EquipSlot.Hands, newGauntlets.Value))
|
||||
{
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.MainHand, currentMain);
|
||||
design.GetDesignDataRef().SetItem(EquipSlot.OffHand, currentOff);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
49
Glamourer/Designs/IDesignEditor.cs
Normal file
49
Glamourer/Designs/IDesignEditor.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using Glamourer.Designs.Links;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.State;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
public readonly record struct ApplySettings(
|
||||
uint Key = 0,
|
||||
StateSource Source = StateSource.Manual,
|
||||
bool RespectManual = false,
|
||||
bool FromJobChange = false,
|
||||
bool UseSingleSource = false);
|
||||
|
||||
public interface IDesignEditor
|
||||
{
|
||||
/// <summary> Change a customization value. </summary>
|
||||
public void ChangeCustomize(object data, CustomizeIndex idx, CustomizeValue value, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change an entire customize array according to the given flags. </summary>
|
||||
public void ChangeEntireCustomize(object data, in CustomizeArray customizeInput, CustomizeFlag apply, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change a customize parameter. </summary>
|
||||
public void ChangeCustomizeParameter(object data, CustomizeParameterFlag flag, CustomizeParameterValue v, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change an equipment piece. </summary>
|
||||
public void ChangeItem(object data, EquipSlot slot, EquipItem item, ApplySettings settings = default)
|
||||
=> ChangeEquip(data, slot, item, null, settings);
|
||||
|
||||
/// <summary> Change the stain for any equipment piece. </summary>
|
||||
public void ChangeStain(object data, EquipSlot slot, StainId stain, ApplySettings settings = default)
|
||||
=> ChangeEquip(data, slot, null, stain, settings);
|
||||
|
||||
/// <summary> Change an equipment piece and its stain at the same time. </summary>
|
||||
public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainId? stain, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change the crest visibility for any equipment piece. </summary>
|
||||
public void ChangeCrest(object data, CrestFlag slot, bool crest, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change the bool value of one of the meta flags. </summary>
|
||||
public void ChangeMetaState(object data, MetaIndex slot, bool value, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change all values applies from the given design. </summary>
|
||||
public void ApplyDesign(object data, MergedDesign design, ApplySettings settings = default);
|
||||
|
||||
/// <summary> Change all values applies from the given design. </summary>
|
||||
public void ApplyDesign(object data, DesignBase design, ApplySettings settings = default);
|
||||
}
|
||||
|
|
@ -56,6 +56,9 @@ public sealed class DesignChanged()
|
|||
/// <summary> An existing design had a customization changed. Data is the old value, the new value and the type [(CustomizeValue, CustomizeValue, CustomizeIndex)]. </summary>
|
||||
Customize,
|
||||
|
||||
/// <summary> An existing design had its entire customize array changed. Data is the old array, the applied flags and the changed flags. [(CustomizeArray, CustomizeFlag, CustomizeFlag)]. </summary>
|
||||
EntireCustomize,
|
||||
|
||||
/// <summary> An existing design had an equipment piece changed. Data is the old value, the new value and the slot [(EquipItem, EquipItem, EquipSlot)]. </summary>
|
||||
Equip,
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,7 @@ public ref struct EquipDrawData(EquipSlot slot, in DesignData designData)
|
|||
public static EquipDrawData FromDesign(DesignManager manager, Design design, EquipSlot slot)
|
||||
=> new(slot, design.DesignData)
|
||||
{
|
||||
ItemSetter = slot.IsEquipment() || slot.IsAccessory()
|
||||
? i => manager.ChangeEquip(design, slot, i)
|
||||
: i => manager.ChangeWeapon(design, slot, i),
|
||||
ItemSetter = i => manager.ChangeItem(design, slot, i),
|
||||
StainSetter = i => manager.ChangeStain(design, slot, i),
|
||||
ApplySetter = b => manager.ChangeApplyEquip(design, slot, b),
|
||||
ApplyStainSetter = b => manager.ChangeApplyStain(design, slot, b),
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public ref struct ToggleDrawData
|
|||
DisplayApplication = true,
|
||||
CurrentValue = design.DesignData.GetMeta(index),
|
||||
CurrentApply = design.DoApplyMeta(index),
|
||||
SetValue = b => manager.ChangeMeta(design, index, b),
|
||||
SetValue = b => manager.ChangeMetaState(design, index, b),
|
||||
SetApply = b => manager.ChangeApplyMeta(design, index, b),
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue