Better handling of application rules.

This commit is contained in:
Ottermandias 2024-01-30 16:04:56 +01:00
parent cb45221be2
commit 962c4e53ad
8 changed files with 130 additions and 51 deletions

View file

@ -1,4 +1,5 @@
using Glamourer.Events;
using Glamourer.Designs;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State;
using Penumbra.Api.Helpers;
@ -18,7 +19,7 @@ public partial class GlamourerIpc
private void OnStateChanged(StateChanged.Type type, StateSource source, ActorState state, ActorData actors, object? data = null)
{
foreach (var actor in actors.Objects)
_stateChangedProvider.Invoke(type, actor.Address, new Lazy<string>(() => _designConverter.ShareBase64(state)));
_stateChangedProvider.Invoke(type, actor.Address, new Lazy<string>(() => _designConverter.ShareBase64(state, ApplicationRules.AllButParameters(state))));
}
private void OnGPoseChanged(bool value)

View file

@ -1,5 +1,6 @@
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin;
using Glamourer.Designs;
using Penumbra.Api.Helpers;
using Penumbra.GameData.Actors;
@ -40,6 +41,6 @@ public partial class GlamourerIpc
return null;
}
return _designConverter.ShareBase64(state);
return _designConverter.ShareBase64(state, ApplicationRules.AllButParameters(state));
}
}

View file

@ -0,0 +1,84 @@
using Glamourer.GameData;
using Glamourer.State;
using ImGuiNET;
using Penumbra.GameData.Enums;
namespace Glamourer.Designs;
public readonly struct ApplicationRules(
EquipFlag equip,
CustomizeFlag customize,
CrestFlag crest,
CustomizeParameterFlag parameters,
MetaFlag meta)
{
public static readonly ApplicationRules All = new(EquipFlagExtensions.All, CustomizeFlagExtensions.AllRelevant,
CrestExtensions.AllRelevant, CustomizeParameterExtensions.All, MetaExtensions.All);
public static ApplicationRules FromModifiers(ActorState state)
=> FromModifiers(state, ImGui.GetIO().KeyCtrl, ImGui.GetIO().KeyShift);
public static ApplicationRules NpcFromModifiers()
=> NpcFromModifiers(ImGui.GetIO().KeyCtrl, ImGui.GetIO().KeyShift);
public static ApplicationRules AllButParameters(ActorState state)
=> new(All.Equip, All.Customize, All.Crest, ComputeParameters(state.ModelData, state.BaseData, All.Parameters), All.Meta);
public static ApplicationRules NpcFromModifiers(bool ctrl, bool shift)
=> new(ctrl || !shift ? EquipFlagExtensions.All : 0,
!ctrl || shift ? CustomizeFlagExtensions.AllRelevant : 0,
0,
0,
ctrl || !shift ? MetaFlag.VisorState : 0);
public static ApplicationRules FromModifiers(ActorState state, bool ctrl, bool shift)
{
var equip = ctrl || !shift ? EquipFlagExtensions.All : 0;
var customize = !ctrl || shift ? CustomizeFlagExtensions.AllRelevant : 0;
var crest = equip == 0 ? 0 : CrestExtensions.AllRelevant;
var parameters = customize == 0 ? 0 : CustomizeParameterExtensions.All;
var meta = state.ModelData.IsWet() ? MetaFlag.Wetness : 0;
if (equip != 0)
meta |= MetaFlag.HatState | MetaFlag.WeaponState | MetaFlag.VisorState;
return new ApplicationRules(equip, customize, crest, ComputeParameters(state.ModelData, state.BaseData, parameters), meta);
}
public void Apply(DesignBase design)
{
design.ApplyEquip = Equip;
design.ApplyCustomize = Customize;
design.ApplyCrest = Crest;
design.ApplyParameters = Parameters;
design.ApplyMeta = Meta;
}
public EquipFlag Equip
=> equip & EquipFlagExtensions.All;
public CustomizeFlag Customize
=> customize & CustomizeFlagExtensions.AllRelevant;
public CrestFlag Crest
=> crest & CrestExtensions.AllRelevant;
public CustomizeParameterFlag Parameters
=> parameters & CustomizeParameterExtensions.All;
public MetaFlag Meta
=> meta & MetaExtensions.All;
public static CustomizeParameterFlag ComputeParameters(in DesignData model, in DesignData game,
CustomizeParameterFlag baseFlags = CustomizeParameterExtensions.All)
{
foreach (var flag in baseFlags.Iterate())
{
var modelValue = model.Parameters[flag];
var gameValue = game.Parameters[flag];
if ((modelValue.InternalQuadruple - gameValue.InternalQuadruple).LengthSquared() > 1e-9f)
baseFlags &= ~flag;
}
return baseFlags;
}
}

View file

@ -1,7 +1,7 @@
using Dalamud.Interface.Internal.Notifications;
using Glamourer.GameData;
using Glamourer.Interop.Material;
using Glamourer.Services;
using Glamourer.State;
using Newtonsoft.Json.Linq;
using OtterGui.Classes;
using Penumbra.GameData.Enums;
@ -14,7 +14,16 @@ public class DesignBase
{
public const int FileVersion = 1;
private DesignData _designData = new();
private DesignData _designData = new();
private readonly DesignMaterialManager _materials = new();
/// <summary> For read-only information about custom material color changes. </summary>
public IReadOnlyList<(uint, MaterialValueDesign)> Materials
=> _materials.Values;
/// <summary> To make it clear something is edited here. </summary>
public DesignMaterialManager GetMaterialDataRef()
=> _materials;
/// <summary> For read-only information about the actual design. </summary>
public ref readonly DesignData DesignData
@ -30,6 +39,7 @@ public class DesignBase
CustomizeSet = SetCustomizationSet(customize);
}
/// <summary> Used when importing .cma or .chara files. </summary>
internal DesignBase(CustomizeService customize, in DesignData designData, EquipFlag equipFlags, CustomizeFlag customizeFlags)
{
_designData = designData;
@ -42,6 +52,7 @@ public class DesignBase
internal DesignBase(DesignBase clone)
{
_designData = clone._designData;
_materials = clone._materials.Clone();
CustomizeSet = clone.CustomizeSet;
ApplyCustomize = clone.ApplyCustomizeRaw;
ApplyEquip = clone.ApplyEquip & EquipFlagExtensions.All;

View file

@ -1,5 +1,4 @@
using Glamourer.Designs.Links;
using Glamourer.GameData;
using Glamourer.Services;
using Glamourer.State;
using Glamourer.Utility;
@ -11,7 +10,12 @@ using Penumbra.GameData.Structs;
namespace Glamourer.Designs;
public class DesignConverter(ItemManager _items, DesignManager _designs, CustomizeService _customize, HumanModelList _humans, DesignLinkLoader _linkLoader)
public class DesignConverter(
ItemManager _items,
DesignManager _designs,
CustomizeService _customize,
HumanModelList _humans,
DesignLinkLoader _linkLoader)
{
public const byte Version = 6;
@ -21,9 +25,9 @@ public class DesignConverter(ItemManager _items, DesignManager _designs, Customi
public JObject ShareJObject(Design design)
=> design.JsonSerialize();
public JObject ShareJObject(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags, CrestFlag crestFlags, CustomizeParameterFlag parameterFlags)
public JObject ShareJObject(ActorState state, in ApplicationRules rules)
{
var design = Convert(state, equipFlags, customizeFlags, crestFlags, parameterFlags);
var design = Convert(state, rules);
return ShareJObject(design);
}
@ -33,32 +37,22 @@ public class DesignConverter(ItemManager _items, DesignManager _designs, Customi
public string ShareBase64(DesignBase design)
=> ShareBase64(ShareJObject(design));
public string ShareBase64(ActorState state)
=> ShareBase64(state, EquipFlagExtensions.All, CustomizeFlagExtensions.All, CrestExtensions.All, CustomizeParameterExtensions.All);
public string ShareBase64(ActorState state, in ApplicationRules rules)
=> ShareBase64(state.ModelData, rules);
public string ShareBase64(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags, CrestFlag crestFlags, CustomizeParameterFlag parameterFlags)
=> ShareBase64(state.ModelData, equipFlags, customizeFlags, crestFlags, parameterFlags);
public string ShareBase64(in DesignData data, EquipFlag equipFlags, CustomizeFlag customizeFlags, CrestFlag crestFlags, CustomizeParameterFlag parameterFlags)
public string ShareBase64(in DesignData data, in ApplicationRules rules)
{
var design = Convert(data, equipFlags, customizeFlags, crestFlags, parameterFlags);
var design = Convert(data, rules);
return ShareBase64(ShareJObject(design));
}
public DesignBase Convert(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags, CrestFlag crestFlags, CustomizeParameterFlag parameterFlags)
=> Convert(state.ModelData, equipFlags, customizeFlags, crestFlags, parameterFlags);
public DesignBase Convert(ActorState state, in ApplicationRules rules)
=> Convert(state.ModelData, rules);
public DesignBase Convert(in DesignData data, EquipFlag equipFlags, CustomizeFlag customizeFlags, CrestFlag crestFlags, CustomizeParameterFlag parameterFlags)
public DesignBase Convert(in DesignData data, in ApplicationRules rules)
{
var design = _designs.CreateTemporary();
design.ApplyEquip = equipFlags & EquipFlagExtensions.All;
design.ApplyCustomize = customizeFlags & CustomizeFlagExtensions.AllRelevant;
design.ApplyCrest = crestFlags & CrestExtensions.All;
design.ApplyParameters = parameterFlags & CustomizeParameterExtensions.All;
design.SetApplyMeta(MetaIndex.HatState, design.DoApplyEquip(EquipSlot.Head));
design.SetApplyMeta(MetaIndex.VisorState, design.DoApplyEquip(EquipSlot.Head));
design.SetApplyMeta(MetaIndex.WeaponState, design.DoApplyEquip(EquipSlot.MainHand) || design.DoApplyEquip(EquipSlot.OffHand));
design.SetApplyMeta(MetaIndex.Wetness, true);
rules.Apply(design);
design.SetDesignData(_customize, data);
return design;
}
@ -139,7 +133,7 @@ public class DesignConverter(ItemManager _items, DesignManager _designs, Customi
return ret;
}
private static string ShareBase64(JObject jObject)
private static string ShareBase64(JToken jObject)
{
var json = jObject.ToString(Formatting.None);
var compressed = json.Compress(Version);

View file

@ -356,8 +356,7 @@ public class ActorPanel(
{
ImGui.OpenPopup("Save as Design");
_newName = _state!.Identifier.ToName();
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
_newDesign = _converter.Convert(_state, applyGear, applyCustomize, applyCrest, applyParameters);
_newDesign = _converter.Convert(_state, ApplicationRules.FromModifiers(_state));
}
private void SaveDesignDrawPopup()
@ -392,8 +391,7 @@ public class ActorPanel(
{
try
{
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
var text = _converter.ShareBase64(_state!, applyGear, applyCustomize, applyCrest, applyParameters);
var text = _converter.ShareBase64(_state!, ApplicationRules.FromModifiers(_state!));
ImGui.SetClipboardText(text);
}
catch (Exception ex)
@ -432,9 +430,8 @@ public class ActorPanel(
!data.Valid || id == _identifier || _state!.ModelData.ModelId != 0))
return;
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
if (_stateManager.GetOrCreate(id, data.Objects[0], out var state))
_stateManager.ApplyDesign(state, _converter.Convert(_state!, applyGear, applyCustomize, applyCrest, applyParameters),
_stateManager.ApplyDesign(state, _converter.Convert(_state!, ApplicationRules.FromModifiers(_state!)),
ApplySettings.Manual);
}
@ -450,9 +447,8 @@ public class ActorPanel(
!data.Valid || id == _identifier || _state!.ModelData.ModelId != 0))
return;
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
if (_stateManager.GetOrCreate(id, data.Objects[0], out var state))
_stateManager.ApplyDesign(state, _converter.Convert(_state!, applyGear, applyCustomize, applyCrest, applyParameters),
_stateManager.ApplyDesign(state, _converter.Convert(_state!, ApplicationRules.FromModifiers(_state!)),
ApplySettings.Manual);
}
}

View file

@ -84,9 +84,8 @@ public class NpcPanel(
{
try
{
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
var data = ToDesignData();
var text = _converter.ShareBase64(data, applyGear, applyCustomize, applyCrest, applyParameters);
var text = _converter.ShareBase64(data, ApplicationRules.NpcFromModifiers());
ImGui.SetClipboardText(text);
}
catch (Exception ex)
@ -100,11 +99,9 @@ public class NpcPanel(
private void SaveDesignOpen()
{
ImGui.OpenPopup("Save as Design");
_newName = _selector.Selection.Name;
var (applyGear, applyCustomize, applyCrest, applyParameters) = UiHelpers.ConvertKeysToFlags();
_newName = _selector.Selection.Name;
var data = ToDesignData();
_newDesign = _converter.Convert(data, applyGear, applyCustomize, applyCrest, applyParameters);
_newDesign = _converter.Convert(data, ApplicationRules.NpcFromModifiers());
}
private void SaveDesignDrawPopup()
@ -198,8 +195,7 @@ public class NpcPanel(
if (_state.GetOrCreate(id, data.Objects[0], out var state))
{
var (applyGear, applyCustomize, _, _) = UiHelpers.ConvertKeysToFlags();
var design = _converter.Convert(ToDesignData(), applyGear, applyCustomize, 0, 0);
var design = _converter.Convert(ToDesignData(), ApplicationRules.NpcFromModifiers());
_state.ApplyDesign(state, design, ApplySettings.Manual);
}
}
@ -217,8 +213,7 @@ public class NpcPanel(
if (_state.GetOrCreate(id, data.Objects[0], out var state))
{
var (applyGear, applyCustomize, _, _) = UiHelpers.ConvertKeysToFlags();
var design = _converter.Convert(ToDesignData(), applyGear, applyCustomize, 0, 0);
var design = _converter.Convert(ToDesignData(), ApplicationRules.NpcFromModifiers());
_state.ApplyDesign(state, design, ApplySettings.Manual);
}
}

View file

@ -3,8 +3,6 @@ using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using Glamourer.Automation;
using Glamourer.Designs;
using Glamourer.Events;
using Glamourer.GameData;
using Glamourer.Gui;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
@ -509,7 +507,7 @@ public class CommandService : IDisposable
try
{
var text = _converter.ShareBase64(state);
var text = _converter.ShareBase64(state, ApplicationRules.AllButParameters(state));
ImGui.SetClipboardText(text);
return true;
}
@ -548,8 +546,7 @@ public class CommandService : IDisposable
&& _stateManager.GetOrCreate(identifier, data.Objects[0], out state)))
continue;
var design = _converter.Convert(state, EquipFlagExtensions.All, CustomizeFlagExtensions.AllRelevant, CrestExtensions.All,
CustomizeParameterExtensions.All);
var design = _converter.Convert(state, ApplicationRules.FromModifiers(state));
_designManager.CreateClone(design, split[0], true);
return true;
}