mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Test state done.
This commit is contained in:
parent
129f9e070f
commit
b37167f2dd
18 changed files with 521 additions and 156 deletions
|
|
@ -77,7 +77,11 @@ public partial class GlamourerIpc
|
|||
continue;
|
||||
}
|
||||
|
||||
_stateManager.ApplyDesign(design, state, StateChanged.Source.Ipc);
|
||||
if (state.CanUnlock(0xDEADBEEF))
|
||||
{
|
||||
_stateManager.ApplyDesign(design, state, StateChanged.Source.Ipc, 0xDEADBEEF);
|
||||
state.Lock(0xDEADBEEF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ public partial class GlamourerIpc
|
|||
foreach (var id in actors)
|
||||
{
|
||||
if (_stateManager.TryGetValue(id, out var state))
|
||||
_stateManager.ResetState(state);
|
||||
{
|
||||
_stateManager.ResetState(state, 0xDEADBEEF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
public bool IncognitoMode { get; set; } = false;
|
||||
public bool UnlockDetailMode { get; set; } = true;
|
||||
public bool SkipInvalidCustomizations { get; set; } = false;
|
||||
public bool HideApplyCheckmarks { get; set; } = false;
|
||||
public MainWindow.TabType SelectedTab { get; set; } = MainWindow.TabType.Settings;
|
||||
public DoubleModifier DeleteDesignModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Glamourer.Gui;
|
|||
|
||||
public enum ColorId
|
||||
{
|
||||
NormalDesign,
|
||||
CustomizationDesign,
|
||||
StateDesign,
|
||||
EquipmentDesign,
|
||||
|
|
@ -25,8 +26,9 @@ public static class Colors
|
|||
=> color switch
|
||||
{
|
||||
// @formatter:off
|
||||
ColorId.NormalDesign => (0xFFFFFFFF, "Normal Design", "A design with no specific traits." ),
|
||||
ColorId.CustomizationDesign => (0xFFC000C0, "Customization Design", "A design that only changes customizations on a character." ),
|
||||
ColorId.StateDesign => (0xFF00C0C0, "State Design", "A design that only changes meta state on a character." ),
|
||||
ColorId.StateDesign => (0xFF00C0C0, "State Design", "A design that does not change equipment or customizations on a character." ),
|
||||
ColorId.EquipmentDesign => (0xFF00C000, "Equipment Design", "A design that only changes equipment on a character." ),
|
||||
ColorId.ActorAvailable => (0xFF18C018, "Actor Available", "The header in the Actor tab panel if the currently selected actor exists in the game world at least once." ),
|
||||
ColorId.ActorUnavailable => (0xFF1818C0, "Actor Unavailable", "The Header in the Actor tab panel if the currently selected actor does not exist in the game world." ),
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@ public partial class CustomizationDrawer
|
|||
using (var group = ImRaii.Group())
|
||||
{
|
||||
DataInputInt(current);
|
||||
if (_withApply)
|
||||
{
|
||||
ApplyCheckbox();
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(custom.Color == 0 ? $"{_currentOption} (Custom #{custom.Value})" : _currentOption);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Customization;
|
||||
|
|
@ -19,6 +20,17 @@ public partial class CustomizationDrawer
|
|||
DrawRaceCombo();
|
||||
var gender = _service.AwaitedService.GetName(CustomName.Gender);
|
||||
var clan = _service.AwaitedService.GetName(CustomName.Clan);
|
||||
if (_withApply)
|
||||
{
|
||||
if (UiHelpers.DrawCheckbox("##applyGender", "Apply gender of this design.", _currentApply, out var applyGender, _locked))
|
||||
ChangeApply = applyGender ? ChangeApply | CustomizeFlag.Gender : ChangeApply & ~CustomizeFlag.Gender;
|
||||
ImGui.SameLine();
|
||||
if (UiHelpers.DrawCheckbox("##applyClan", "Apply clan of this design.", _currentApply, out var applyClan, _locked))
|
||||
ChangeApply = applyClan ? ChangeApply | CustomizeFlag.Clan : ChangeApply & ~CustomizeFlag.Clan;
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted($"{gender} & {clan}");
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +44,8 @@ public partial class CustomizationDrawer
|
|||
_ => FontAwesomeIcon.Question,
|
||||
};
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, icon is not FontAwesomeIcon.Mars and not FontAwesomeIcon.Venus, true))
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty,
|
||||
icon is not FontAwesomeIcon.Mars and not FontAwesomeIcon.Venus, true))
|
||||
return;
|
||||
|
||||
Changed |= _service.ChangeGender(ref _customize, icon is FontAwesomeIcon.Mars ? Gender.Female : Gender.Male);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ public partial class CustomizationDrawer
|
|||
else
|
||||
DataInputInt(current);
|
||||
|
||||
if (_withApply)
|
||||
{
|
||||
ApplyCheckbox();
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
}
|
||||
|
||||
|
|
@ -115,16 +121,45 @@ public partial class CustomizationDrawer
|
|||
DrawMultiIcons();
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.Dummy(new Vector2(0, ImGui.GetTextLineHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y / 2));
|
||||
|
||||
_currentCount = 256;
|
||||
PercentageInputInt();
|
||||
if (_withApply)
|
||||
{
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature1);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + _spacing.X);
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature2);
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature3);
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature4);
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(_set.Option(CustomizeIndex.LegacyTattoo));
|
||||
PercentageInputInt();
|
||||
if (_set.DataByValue(CustomizeIndex.Face, _customize.Face, out _, _customize.Face) < 0)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("(Using Face 1)");
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + _spacing.Y);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(_set.Option(CustomizeIndex.LegacyTattoo));
|
||||
|
||||
if (_withApply)
|
||||
{
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature5);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + _spacing.X);
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature6);
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox(CustomizeIndex.FacialFeature7);
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox(CustomizeIndex.LegacyTattoo);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMultiIcons()
|
||||
{
|
||||
var options = _set.Order[CharaMakeParams.MenuType.IconCheckmark];
|
||||
|
|
|
|||
|
|
@ -16,7 +16,14 @@ public partial class CustomizationDrawer
|
|||
DrawPercentageSlider();
|
||||
ImGui.SameLine();
|
||||
PercentageInputInt();
|
||||
if (_withApply)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +67,14 @@ public partial class CustomizationDrawer
|
|||
ListCombo();
|
||||
ImGui.SameLine();
|
||||
ListInputInt();
|
||||
if (_withApply)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ApplyCheckbox();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
|
|
@ -93,10 +107,41 @@ public partial class CustomizationDrawer
|
|||
{
|
||||
using var id = SetId(idx);
|
||||
var tmp = _currentByte != CustomizeValue.Zero;
|
||||
if (ImGui.Checkbox(_currentOption, ref tmp))
|
||||
if (_withApply)
|
||||
{
|
||||
switch (UiHelpers.DrawMetaToggle(_currentOption, string.Empty, tmp, _currentApply, out var newValue, out var newApply, _locked))
|
||||
{
|
||||
case DataChange.Item:
|
||||
ChangeApply = newApply ? ChangeApply | _currentFlag : ChangeApply & ~_currentFlag;
|
||||
_customize.Set(idx, tmp ? CustomizeValue.Max : CustomizeValue.Zero);
|
||||
Changed |= _currentFlag;
|
||||
break;
|
||||
case DataChange.ApplyItem:
|
||||
ChangeApply = newApply ? ChangeApply | _currentFlag : ChangeApply & ~_currentFlag;
|
||||
break;
|
||||
case DataChange.Item | DataChange.ApplyItem:
|
||||
_customize.Set(idx, tmp ? CustomizeValue.Max : CustomizeValue.Zero);
|
||||
Changed |= _currentFlag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ImGui.Checkbox(_currentOption, ref tmp))
|
||||
{
|
||||
_customize.Set(idx, tmp ? CustomizeValue.Max : CustomizeValue.Zero);
|
||||
Changed |= _currentFlag;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyCheckbox()
|
||||
{
|
||||
if (UiHelpers.DrawCheckbox("##apply", $"Apply the {_currentOption} customization in this design.", _currentApply, out _, _locked))
|
||||
ToggleApply();
|
||||
}
|
||||
|
||||
private void ApplyCheckbox(CustomizeIndex index)
|
||||
{
|
||||
SetId(index);
|
||||
if (UiHelpers.DrawCheckbox("##apply", $"Apply the {_currentOption} customization in this design.", _currentApply, out _, _locked))
|
||||
ToggleApply();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace Glamourer.Gui.Customization;
|
|||
public partial class CustomizationDrawer : IDisposable
|
||||
{
|
||||
private readonly CodeService _codes;
|
||||
private readonly Configuration _config;
|
||||
|
||||
private readonly Vector4 _redTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
private readonly ImGuiScene.TextureWrap? _legacyTattoo;
|
||||
|
|
@ -29,23 +30,28 @@ public partial class CustomizationDrawer : IDisposable
|
|||
|
||||
public CustomizeFlag CurrentFlag { get; private set; }
|
||||
public CustomizeFlag Changed { get; private set; }
|
||||
public CustomizeFlag ChangeApply { get; private set; }
|
||||
|
||||
public bool RequiresRedraw
|
||||
=> Changed.RequiresRedraw();
|
||||
|
||||
private bool _locked = false;
|
||||
private Vector2 _defaultSpacing;
|
||||
private Vector2 _spacing;
|
||||
private Vector2 _iconSize;
|
||||
private Vector2 _framedIconSize;
|
||||
private float _inputIntSize;
|
||||
private float _comboSelectorSize;
|
||||
private float _raceSelectorWidth;
|
||||
private bool _withApply;
|
||||
|
||||
private readonly CustomizationService _service;
|
||||
|
||||
public CustomizationDrawer(DalamudPluginInterface pi, CustomizationService service, CodeService codes)
|
||||
public CustomizationDrawer(DalamudPluginInterface pi, CustomizationService service, CodeService codes, Configuration config)
|
||||
{
|
||||
_service = service;
|
||||
_codes = codes;
|
||||
_config = config;
|
||||
_legacyTattoo = GetLegacyTattooIcon(pi);
|
||||
_customize = Customize.Default;
|
||||
}
|
||||
|
|
@ -58,6 +64,17 @@ public partial class CustomizationDrawer : IDisposable
|
|||
public bool Draw(Customize current, bool locked)
|
||||
{
|
||||
CurrentFlag = CustomizeFlagExtensions.All;
|
||||
_withApply = false;
|
||||
Init(current, locked);
|
||||
|
||||
return DrawInternal();
|
||||
}
|
||||
|
||||
public bool Draw(Customize current, CustomizeFlag apply, bool locked)
|
||||
{
|
||||
CurrentFlag = CustomizeFlagExtensions.All;
|
||||
ChangeApply = apply;
|
||||
_withApply = !_config.HideApplyCheckmarks;
|
||||
Init(current, locked);
|
||||
return DrawInternal();
|
||||
}
|
||||
|
|
@ -75,6 +92,7 @@ public partial class CustomizationDrawer : IDisposable
|
|||
private CustomizeIndex _currentIndex;
|
||||
private CustomizeFlag _currentFlag;
|
||||
private CustomizeValue _currentByte = CustomizeValue.Zero;
|
||||
private bool _currentApply;
|
||||
private int _currentCount;
|
||||
private string _currentOption = string.Empty;
|
||||
|
||||
|
|
@ -83,6 +101,7 @@ public partial class CustomizationDrawer : IDisposable
|
|||
{
|
||||
_currentIndex = index;
|
||||
_currentFlag = index.ToFlag();
|
||||
_currentApply = ChangeApply.HasFlag(_currentFlag);
|
||||
_currentByte = _customize[index];
|
||||
_currentCount = _set.Count(index, _customize.Face);
|
||||
_currentOption = _set.Option(index);
|
||||
|
|
@ -99,8 +118,23 @@ public partial class CustomizationDrawer : IDisposable
|
|||
Changed |= _currentFlag;
|
||||
}
|
||||
|
||||
// Update the current Apply value.
|
||||
private void ToggleApply()
|
||||
{
|
||||
_currentApply = !_currentApply;
|
||||
ChangeApply = _currentApply ? ChangeApply | _currentFlag : ChangeApply & ~_currentFlag;
|
||||
}
|
||||
|
||||
public bool DrawWetnessState(bool currentValue, out bool newValue, bool locked)
|
||||
=> UiHelpers.DrawCheckbox("Force Wetness", "Force the character to be wet or not.", currentValue, out newValue, locked);
|
||||
|
||||
public DataChange DrawWetnessState(bool currentValue, bool currentApply, out bool newValue, out bool newApply, bool locked)
|
||||
=> UiHelpers.DrawMetaToggle("Force Wetness", "Change the characters forced wetness state: Disabled, Enabled or Don't Apply.",
|
||||
currentValue, currentApply, out newValue, out newApply, locked);
|
||||
|
||||
private bool DrawInternal()
|
||||
{
|
||||
using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _spacing);
|
||||
using var disabled = ImRaii.Disabled(_locked);
|
||||
|
||||
try
|
||||
|
|
@ -124,7 +158,7 @@ public partial class CustomizationDrawer : IDisposable
|
|||
Functions.IteratePairwise(_set.Order[CharaMakeParams.MenuType.ColorPicker], DrawColorPicker, ImGui.SameLine);
|
||||
|
||||
Functions.IteratePairwise(_set.Order[CharaMakeParams.MenuType.Checkmark], DrawCheckbox,
|
||||
() => ImGui.SameLine(_inputIntSize + _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X));
|
||||
() => ImGui.SameLine(_comboSelectorSize - _framedIconSize.X + _spacing.X));
|
||||
return Changed != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -144,9 +178,8 @@ public partial class CustomizationDrawer : IDisposable
|
|||
using var id = ImRaii.PushId(i);
|
||||
int value = _customize.Data.Data[i];
|
||||
ImGui.SetNextItemWidth(40 * ImGuiHelpers.GlobalScale);
|
||||
if (!ImGui.InputInt(string.Empty, ref value, 0, 0))
|
||||
continue;
|
||||
|
||||
if (ImGui.InputInt(string.Empty, ref value, 0, 0))
|
||||
{
|
||||
var newValue = (byte)Math.Clamp(value, 0, byte.MaxValue);
|
||||
if (newValue != _customize.Data.Data[i])
|
||||
foreach (var flag in Enum.GetValues<CustomizeIndex>())
|
||||
|
|
@ -158,16 +191,19 @@ public partial class CustomizationDrawer : IDisposable
|
|||
|
||||
_customize.Data.Data[i] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
return Changed != 0;
|
||||
}
|
||||
|
||||
private void UpdateSizes()
|
||||
{
|
||||
_iconSize = new Vector2(ImGui.GetTextLineHeightWithSpacing() * 2);
|
||||
_defaultSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
_spacing = ImGui.GetStyle().ItemSpacing with { X = ImGui.GetStyle().ItemInnerSpacing.X };
|
||||
_iconSize = new Vector2(ImGui.GetTextLineHeight() * 2 + ImGui.GetStyle().ItemSpacing.Y + 2 * ImGui.GetStyle().FramePadding.Y);
|
||||
_framedIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding;
|
||||
_inputIntSize = 2 * _framedIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
||||
_comboSelectorSize = 4 * _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
_inputIntSize = 2 * _framedIconSize.X + 1 * _spacing.X;
|
||||
_comboSelectorSize = 4 * _framedIconSize.X + 3 * _spacing.X;
|
||||
_raceSelectorWidth = _inputIntSize + _comboSelectorSize - _framedIconSize.X;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ namespace Glamourer.Gui.Equipment;
|
|||
|
||||
public class EquipmentDrawer
|
||||
{
|
||||
private const float DefaultWidth = 280;
|
||||
|
||||
private readonly ItemManager _items;
|
||||
private readonly FilterComboColors _stainCombo;
|
||||
private readonly StainData _stainData;
|
||||
|
|
@ -27,14 +29,16 @@ public class EquipmentDrawer
|
|||
private readonly Dictionary<FullEquipType, WeaponCombo> _weaponCombo;
|
||||
private readonly CodeService _codes;
|
||||
private readonly TextureService _textures;
|
||||
private readonly Configuration _config;
|
||||
|
||||
public EquipmentDrawer(DataManager gameData, ItemManager items, CodeService codes, TextureService textures)
|
||||
public EquipmentDrawer(DataManager gameData, ItemManager items, CodeService codes, TextureService textures, Configuration config)
|
||||
{
|
||||
_items = items;
|
||||
_codes = codes;
|
||||
_textures = textures;
|
||||
_config = config;
|
||||
_stainData = items.Stains;
|
||||
_stainCombo = new FilterComboColors(280,
|
||||
_stainCombo = new FilterComboColors(DefaultWidth - 20,
|
||||
_stainData.Data.Prepend(new KeyValuePair<byte, (string Name, uint Dye, bool Gloss)>(0, ("None", 0, false))));
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, textures)).ToArray();
|
||||
_weaponCombo = new Dictionary<FullEquipType, WeaponCombo>(FullEquipTypeExtensions.WeaponTypes.Count * 2);
|
||||
|
|
@ -55,7 +59,7 @@ public class EquipmentDrawer
|
|||
public void Prepare()
|
||||
{
|
||||
_iconSize = new Vector2(2 * ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y);
|
||||
_comboLength = 300 * ImGuiHelpers.GlobalScale;
|
||||
_comboLength = DefaultWidth * ImGuiHelpers.GlobalScale;
|
||||
}
|
||||
|
||||
private bool VerifyRestrictedGear(EquipSlot slot, EquipItem gear, Gender gender, Race race)
|
||||
|
|
@ -67,45 +71,35 @@ public class EquipmentDrawer
|
|||
return changed;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum EquipChange : byte
|
||||
{
|
||||
None = 0x00,
|
||||
Item = 0x01,
|
||||
Stain = 0x02,
|
||||
ApplyItem = 0x04,
|
||||
ApplyStain = 0x08,
|
||||
Item2 = 0x10,
|
||||
Stain2 = 0x20,
|
||||
ApplyItem2 = 0x40,
|
||||
ApplyStain2 = 0x80,
|
||||
}
|
||||
|
||||
public EquipChange DrawEquip(EquipSlot slot, in DesignData designData, out EquipItem rArmor, out StainId rStain, EquipFlag? cApply,
|
||||
public DataChange DrawEquip(EquipSlot slot, in DesignData designData, out EquipItem rArmor, out StainId rStain, EquipFlag? cApply,
|
||||
out bool rApply, out bool rApplyStain, bool locked)
|
||||
=> DrawEquip(slot, designData.Item(slot), out rArmor, designData.Stain(slot), out rStain, cApply, out rApply, out rApplyStain, locked,
|
||||
designData.Customize.Gender, designData.Customize.Race);
|
||||
|
||||
public EquipChange DrawEquip(EquipSlot slot, EquipItem cArmor, out EquipItem rArmor, StainId cStain, out StainId rStain, EquipFlag? cApply,
|
||||
public DataChange DrawEquip(EquipSlot slot, EquipItem cArmor, out EquipItem rArmor, StainId cStain, out StainId rStain, EquipFlag? cApply,
|
||||
out bool rApply, out bool rApplyStain, bool locked, Gender gender = Gender.Unknown, Race race = Race.Unknown)
|
||||
{
|
||||
if (_config.HideApplyCheckmarks)
|
||||
cApply = null;
|
||||
|
||||
if (!locked && _codes.EnabledArtisan)
|
||||
return DrawEquipArtisan(slot, cArmor, out rArmor, cStain, out rStain, cApply, out rApply, out rApplyStain);
|
||||
|
||||
var spacing = ImGui.GetStyle().ItemInnerSpacing with { Y = ImGui.GetStyle().ItemSpacing.Y };
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
|
||||
|
||||
var changes = EquipChange.None;
|
||||
var changes = DataChange.None;
|
||||
cArmor.DrawIcon(_textures, _iconSize);
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
if (DrawItem(slot, cArmor, out rArmor, out var label, locked))
|
||||
changes |= EquipChange.Item;
|
||||
changes |= DataChange.Item;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApply(slot, cApply.Value, out rApply, locked))
|
||||
changes |= EquipChange.ApplyItem;
|
||||
changes |= DataChange.ApplyItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -115,12 +109,12 @@ public class EquipmentDrawer
|
|||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(label);
|
||||
if (DrawStain(slot, cStain, out rStain, locked))
|
||||
changes |= EquipChange.Stain;
|
||||
changes |= DataChange.Stain;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApplyStain(slot, cApply.Value, out rApplyStain, locked))
|
||||
changes |= EquipChange.ApplyStain;
|
||||
changes |= DataChange.ApplyStain;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -136,18 +130,21 @@ public class EquipmentDrawer
|
|||
return changes;
|
||||
}
|
||||
|
||||
public EquipChange DrawWeapons(in DesignData designData, out EquipItem rMainhand, out EquipItem rOffhand, out StainId rMainhandStain,
|
||||
public DataChange DrawWeapons(in DesignData designData, out EquipItem rMainhand, out EquipItem rOffhand, out StainId rMainhandStain,
|
||||
out StainId rOffhandStain, EquipFlag? cApply, out bool rApplyMainhand, out bool rApplyMainhandStain, out bool rApplyOffhand,
|
||||
out bool rApplyOffhandStain, bool locked)
|
||||
=> DrawWeapons(designData.Item(EquipSlot.MainHand), out rMainhand, designData.Item(EquipSlot.OffHand), out rOffhand,
|
||||
designData.Stain(EquipSlot.MainHand), out rMainhandStain, designData.Stain(EquipSlot.OffHand), out rOffhandStain, cApply,
|
||||
out rApplyMainhand, out rApplyMainhandStain, out rApplyOffhand, out rApplyOffhandStain, locked);
|
||||
|
||||
public EquipChange DrawWeapons(EquipItem cMainhand, out EquipItem rMainhand, EquipItem cOffhand, out EquipItem rOffhand,
|
||||
public DataChange DrawWeapons(EquipItem cMainhand, out EquipItem rMainhand, EquipItem cOffhand, out EquipItem rOffhand,
|
||||
StainId cMainhandStain, out StainId rMainhandStain, StainId cOffhandStain, out StainId rOffhandStain, EquipFlag? cApply,
|
||||
out bool rApplyMainhand, out bool rApplyMainhandStain, out bool rApplyOffhand, out bool rApplyOffhandStain, bool locked)
|
||||
{
|
||||
var changes = EquipChange.None;
|
||||
if (_config.HideApplyCheckmarks)
|
||||
cApply = null;
|
||||
|
||||
var changes = DataChange.None;
|
||||
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
|
||||
ImGui.GetStyle().ItemInnerSpacing with { Y = ImGui.GetStyle().ItemSpacing.Y });
|
||||
|
|
@ -159,11 +156,11 @@ public class EquipmentDrawer
|
|||
rOffhand = cOffhand;
|
||||
if (DrawMainhand(cMainhand, cApply.HasValue, out rMainhand, out var mainhandLabel, locked))
|
||||
{
|
||||
changes |= EquipChange.Item;
|
||||
changes |= DataChange.Item;
|
||||
if (rMainhand.Type.ValidOffhand() != cMainhand.Type.ValidOffhand())
|
||||
{
|
||||
rOffhand = _items.GetDefaultOffhand(rMainhand);
|
||||
changes |= EquipChange.Item2;
|
||||
changes |= DataChange.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +168,7 @@ public class EquipmentDrawer
|
|||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApply(EquipSlot.MainHand, cApply.Value, out rApplyMainhand, locked))
|
||||
changes |= EquipChange.ApplyItem;
|
||||
changes |= DataChange.ApplyItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -182,12 +179,12 @@ public class EquipmentDrawer
|
|||
ImGui.TextUnformatted(mainhandLabel);
|
||||
|
||||
if (DrawStain(EquipSlot.MainHand, cMainhandStain, out rMainhandStain, locked))
|
||||
changes |= EquipChange.Stain;
|
||||
changes |= DataChange.Stain;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApplyStain(EquipSlot.MainHand, cApply.Value, out rApplyMainhandStain, locked))
|
||||
changes |= EquipChange.ApplyStain;
|
||||
changes |= DataChange.ApplyStain;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -208,12 +205,12 @@ public class EquipmentDrawer
|
|||
using (var group = ImRaii.Group())
|
||||
{
|
||||
if (DrawOffhand(rMainhand, rOffhand, out rOffhand, out var offhandLabel, locked))
|
||||
changes |= EquipChange.Item2;
|
||||
changes |= DataChange.Item2;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApply(EquipSlot.OffHand, cApply.Value, out rApplyOffhand, locked))
|
||||
changes |= EquipChange.ApplyItem2;
|
||||
changes |= DataChange.ApplyItem2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -224,12 +221,12 @@ public class EquipmentDrawer
|
|||
ImGui.TextUnformatted(offhandLabel);
|
||||
|
||||
if (DrawStain(EquipSlot.OffHand, cOffhandStain, out rOffhandStain, locked))
|
||||
changes |= EquipChange.Stain2;
|
||||
changes |= DataChange.Stain2;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApplyStain(EquipSlot.OffHand, cApply.Value, out rApplyOffhandStain, locked))
|
||||
changes |= EquipChange.ApplyStain2;
|
||||
changes |= DataChange.ApplyStain2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -240,8 +237,29 @@ public class EquipmentDrawer
|
|||
return changes;
|
||||
}
|
||||
|
||||
public bool DrawHatState(bool currentValue, out bool newValue, bool locked)
|
||||
=> UiHelpers.DrawCheckbox("Hat Visible", "Hide or show the characters head gear.", currentValue, out newValue, locked);
|
||||
|
||||
public bool DrawMainhand(EquipItem current, bool drawAll, out EquipItem weapon, out string label, bool locked)
|
||||
public DataChange DrawHatState(bool currentValue, bool currentApply, out bool newValue, out bool newApply, bool locked)
|
||||
=> UiHelpers.DrawMetaToggle("Hat Visible", "Change the visibility of the characters head gear: Hidden, Visible or Don't Apply.",
|
||||
currentValue, currentApply, out newValue, out newApply, locked);
|
||||
|
||||
public bool DrawVisorState(bool currentValue, out bool newValue, bool locked)
|
||||
=> UiHelpers.DrawCheckbox("Visor Toggled", "Toggle the visor state of the characters head gear.", currentValue, out newValue, locked);
|
||||
|
||||
public DataChange DrawVisorState(bool currentValue, bool currentApply, out bool newValue, out bool newApply, bool locked)
|
||||
=> UiHelpers.DrawMetaToggle("Visor Toggled", "Change the toggled state of the characters head gear: Normal, Toggled or Don't Apply.",
|
||||
currentValue, currentApply, out newValue, out newApply, locked);
|
||||
|
||||
public bool DrawWeaponState(bool currentValue, out bool newValue, bool locked)
|
||||
=> UiHelpers.DrawCheckbox("Weapon Visible", "Hide or show the characters weapons when not drawn.", currentValue, out newValue, locked);
|
||||
|
||||
public DataChange DrawWeaponState(bool currentValue, bool currentApply, out bool newValue, out bool newApply, bool locked)
|
||||
=> UiHelpers.DrawMetaToggle("Weapon Visible",
|
||||
"Change the visibility of the characters weapons when not drawn: Hidden, Visible or Don't Apply.", currentValue, currentApply,
|
||||
out newValue, out newApply, locked);
|
||||
|
||||
private bool DrawMainhand(EquipItem current, bool drawAll, out EquipItem weapon, out string label, bool locked)
|
||||
{
|
||||
weapon = current;
|
||||
if (!_weaponCombo.TryGetValue(drawAll ? FullEquipType.Unknown : current.Type, out var combo))
|
||||
|
|
@ -259,7 +277,7 @@ public class EquipmentDrawer
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool DrawOffhand(EquipItem mainhand, EquipItem current, out EquipItem weapon, out string label, bool locked)
|
||||
private bool DrawOffhand(EquipItem mainhand, EquipItem current, out EquipItem weapon, out string label, bool locked)
|
||||
{
|
||||
weapon = current;
|
||||
if (!_weaponCombo.TryGetValue(current.Type, out var combo))
|
||||
|
|
@ -291,11 +309,11 @@ public class EquipmentDrawer
|
|||
return change;
|
||||
}
|
||||
|
||||
public bool DrawApply(EquipSlot slot, EquipFlag flags, out bool enabled, bool locked)
|
||||
private bool DrawApply(EquipSlot slot, EquipFlag flags, out bool enabled, bool locked)
|
||||
=> UiHelpers.DrawCheckbox($"##apply{slot}", "Apply this item when applying the Design.", flags.HasFlag(slot.ToFlag()), out enabled,
|
||||
locked);
|
||||
|
||||
public bool DrawApplyStain(EquipSlot slot, EquipFlag flags, out bool enabled, bool locked)
|
||||
private bool DrawApplyStain(EquipSlot slot, EquipFlag flags, out bool enabled, bool locked)
|
||||
=> UiHelpers.DrawCheckbox($"##applyStain{slot}", "Apply this dye when applying the Design.", flags.HasFlag(slot.ToStainFlag()),
|
||||
out enabled, locked);
|
||||
|
||||
|
|
@ -397,23 +415,23 @@ public class EquipmentDrawer
|
|||
return false;
|
||||
}
|
||||
|
||||
private EquipChange DrawEquipArtisan(EquipSlot slot, EquipItem cArmor, out EquipItem rArmor, StainId cStain, out StainId rStain,
|
||||
private DataChange DrawEquipArtisan(EquipSlot slot, EquipItem cArmor, out EquipItem rArmor, StainId cStain, out StainId rStain,
|
||||
EquipFlag? cApply, out bool rApply, out bool rApplyStain)
|
||||
{
|
||||
var changes = EquipChange.None;
|
||||
var changes = DataChange.None;
|
||||
if (DrawStainArtisan(slot, cStain, out rStain))
|
||||
changes |= EquipChange.Stain;
|
||||
changes |= DataChange.Stain;
|
||||
ImGui.SameLine();
|
||||
if (DrawArmorArtisan(slot, cArmor, out rArmor))
|
||||
changes |= EquipChange.Item;
|
||||
changes |= DataChange.Item;
|
||||
if (cApply.HasValue)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (DrawApply(slot, cApply.Value, out rApply, false))
|
||||
changes |= EquipChange.ApplyItem;
|
||||
changes |= DataChange.ApplyItem;
|
||||
ImGui.SameLine();
|
||||
if (DrawApplyStain(slot, cApply.Value, out rApplyStain, false))
|
||||
changes |= EquipChange.ApplyStain;
|
||||
changes |= DataChange.ApplyStain;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,46 +107,77 @@ public class ActorPanel
|
|||
|
||||
private void DrawHumanPanel()
|
||||
{
|
||||
if (_customizationDrawer.Draw(_state!.ModelData.Customize, false))
|
||||
DrawCustomizationsHeader();
|
||||
DrawEquipmentHeader();
|
||||
}
|
||||
|
||||
private void DrawCustomizationsHeader()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Customizations"))
|
||||
return;
|
||||
|
||||
if (_customizationDrawer.Draw(_state!.ModelData.Customize, _state.IsLocked))
|
||||
_stateManager.ChangeCustomize(_state, _customizationDrawer.Customize, _customizationDrawer.Changed, StateChanged.Source.Manual);
|
||||
|
||||
if (_customizationDrawer.DrawWetnessState(_state!.ModelData.IsWet(), out var newWetness, _state.IsLocked))
|
||||
_stateManager.ChangeWetness(_state, newWetness, StateChanged.Source.Manual);
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
}
|
||||
|
||||
private void DrawEquipmentHeader()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Equipment"))
|
||||
return;
|
||||
|
||||
_equipmentDrawer.Prepare();
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
var changes = _equipmentDrawer.DrawEquip(slot, _state.ModelData, out var newArmor, out var newStain, null, out _, out _,
|
||||
var changes = _equipmentDrawer.DrawEquip(slot, _state!.ModelData, out var newArmor, out var newStain, null, out _, out _,
|
||||
_state.IsLocked);
|
||||
switch (changes)
|
||||
{
|
||||
case EquipmentDrawer.EquipChange.Item:
|
||||
case DataChange.Item:
|
||||
_stateManager.ChangeItem(_state, slot, newArmor, StateChanged.Source.Manual);
|
||||
break;
|
||||
case EquipmentDrawer.EquipChange.Stain:
|
||||
case DataChange.Stain:
|
||||
_stateManager.ChangeStain(_state, slot, newStain, StateChanged.Source.Manual);
|
||||
break;
|
||||
case EquipmentDrawer.EquipChange.Item | EquipmentDrawer.EquipChange.Stain:
|
||||
case DataChange.Item | DataChange.Stain:
|
||||
_stateManager.ChangeEquip(_state, slot, newArmor, newStain, StateChanged.Source.Manual);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var weaponChanges = _equipmentDrawer.DrawWeapons(_state.ModelData, out var newMainhand, out var newOffhand, out var newMainhandStain,
|
||||
var weaponChanges = _equipmentDrawer.DrawWeapons(_state!.ModelData, out var newMainhand, out var newOffhand,
|
||||
out var newMainhandStain,
|
||||
out var newOffhandStain, null, out _, out _, out _, out _, _state.IsLocked);
|
||||
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Item))
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain))
|
||||
if (weaponChanges.HasFlag(DataChange.Item))
|
||||
if (weaponChanges.HasFlag(DataChange.Stain))
|
||||
_stateManager.ChangeEquip(_state, EquipSlot.MainHand, newMainhand, newMainhandStain, StateChanged.Source.Manual);
|
||||
else
|
||||
_stateManager.ChangeItem(_state, EquipSlot.MainHand, newMainhand, StateChanged.Source.Manual);
|
||||
else if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain))
|
||||
else if (weaponChanges.HasFlag(DataChange.Stain))
|
||||
_stateManager.ChangeStain(_state, EquipSlot.MainHand, newMainhandStain, StateChanged.Source.Manual);
|
||||
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Item2))
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain2))
|
||||
if (weaponChanges.HasFlag(DataChange.Item2))
|
||||
if (weaponChanges.HasFlag(DataChange.Stain2))
|
||||
_stateManager.ChangeEquip(_state, EquipSlot.OffHand, newOffhand, newOffhandStain, StateChanged.Source.Manual);
|
||||
else
|
||||
_stateManager.ChangeItem(_state, EquipSlot.OffHand, newOffhand, StateChanged.Source.Manual);
|
||||
else if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain2))
|
||||
else if (weaponChanges.HasFlag(DataChange.Stain2))
|
||||
_stateManager.ChangeStain(_state, EquipSlot.OffHand, newOffhandStain, StateChanged.Source.Manual);
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
if (_equipmentDrawer.DrawHatState(_state!.ModelData.IsHatVisible(), out var newHatState, _state!.IsLocked))
|
||||
_stateManager.ChangeHatState(_state, newHatState, StateChanged.Source.Manual);
|
||||
ImGui.SameLine();
|
||||
if (_equipmentDrawer.DrawVisorState(_state!.ModelData.IsVisorToggled(), out var newVisorState, _state!.IsLocked))
|
||||
_stateManager.ChangeVisorState(_state, newVisorState, StateChanged.Source.Manual);
|
||||
ImGui.SameLine();
|
||||
if (_equipmentDrawer.DrawWeaponState(_state!.ModelData.IsWeaponVisible(), out var newWeaponState, _state!.IsLocked))
|
||||
_stateManager.ChangeWeaponState(_state, newWeaponState, StateChanged.Source.Manual);
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
}
|
||||
|
||||
private void DrawMonsterPanel()
|
||||
|
|
@ -217,6 +248,7 @@ public class ActorPanel
|
|||
Icon = FontAwesomeIcon.Clipboard,
|
||||
OnClick = SetFromClipboard,
|
||||
Visible = _state != null,
|
||||
Disabled = _state?.IsLocked ?? true,
|
||||
};
|
||||
|
||||
private HeaderDrawer.Button ExportToClipboardButton()
|
||||
|
|
@ -301,15 +333,19 @@ public class ActorPanel
|
|||
|
||||
private void RevertButtons()
|
||||
{
|
||||
if (ImGui.Button("Revert to Game"))
|
||||
if (ImGuiUtil.DrawDisabledButton("Revert to Game", Vector2.Zero, "Revert the character to its actual state in the game.",
|
||||
_state!.IsLocked))
|
||||
_stateManager.ResetState(_state!);
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Reapply State"))
|
||||
if (ImGuiUtil.DrawDisabledButton("Reapply State", Vector2.Zero, "Try to reapply the configured state if something went wrong.",
|
||||
_state!.IsLocked))
|
||||
_stateManager.ReapplyState(_actor);
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGuiUtil.DrawDisabledButton("Reapply Automation", Vector2.Zero, string.Empty, !_config.EnableAutoDesigns))
|
||||
if (ImGuiUtil.DrawDisabledButton("Reapply Automation", Vector2.Zero,
|
||||
"Try to revert the character to the state it would have using automated designs.",
|
||||
!_config.EnableAutoDesigns || _state!.IsLocked))
|
||||
{
|
||||
_autoDesignApplier.ReapplyAutomation(_actor, _identifier, _state!);
|
||||
_stateManager.ReapplyState(_actor);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.ClientState.Keys;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Internal.Notifications;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Events;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Filesystem;
|
||||
using OtterGui.FileSystem.Selector;
|
||||
using OtterGui.Raii;
|
||||
|
|
@ -39,7 +41,9 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
=> base.SelectedLeaf;
|
||||
|
||||
public struct DesignState
|
||||
{ }
|
||||
{
|
||||
public ColorId Color;
|
||||
}
|
||||
|
||||
public DesignFileSystemSelector(DesignManager designManager, DesignFileSystem fileSystem, KeyState keyState, DesignChanged @event,
|
||||
Configuration config, DesignConverter converter)
|
||||
|
|
@ -55,6 +59,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
AddButton(ImportDesignButton, 10);
|
||||
AddButton(CloneDesignButton, 20);
|
||||
AddButton(DeleteButton, 1000);
|
||||
SetFilterTooltip();
|
||||
}
|
||||
|
||||
protected override void DrawPopups()
|
||||
|
|
@ -66,6 +71,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
{
|
||||
var flag = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags;
|
||||
var name = IncognitoMode ? leaf.Value.Incognito : leaf.Value.Name.Text;
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, state.Color.Value());
|
||||
using var _ = ImRaii.TreeNode(name, flag);
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +109,8 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
case DesignChanged.Type.RemovedMod:
|
||||
case DesignChanged.Type.Created:
|
||||
case DesignChanged.Type.Deleted:
|
||||
case DesignChanged.Type.ApplyCustomize:
|
||||
case DesignChanged.Type.ApplyEquip:
|
||||
SetFilterDirty();
|
||||
break;
|
||||
}
|
||||
|
|
@ -188,4 +196,91 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
|
||||
_newName = string.Empty;
|
||||
}
|
||||
|
||||
#region Filters
|
||||
|
||||
private const StringComparison IgnoreCase = StringComparison.OrdinalIgnoreCase;
|
||||
private LowerString _designFilter = LowerString.Empty;
|
||||
private int _filterType = -1;
|
||||
|
||||
private void SetFilterTooltip()
|
||||
{
|
||||
FilterTooltip = "Filter designs for those where their full paths or names contain the given substring.\n"
|
||||
+ "Enter m:[string] to filter for designs with with a mod association containing the string.\n"
|
||||
+ "Enter t:[string] to filter for designs set to specific tags.\n"
|
||||
+ "Enter n:[string] to filter only for design names and no paths.";
|
||||
}
|
||||
|
||||
/// <summary> Appropriately identify and set the string filter and its type. </summary>
|
||||
protected override bool ChangeFilter(string filterValue)
|
||||
{
|
||||
(_designFilter, _filterType) = filterValue.Length switch
|
||||
{
|
||||
0 => (LowerString.Empty, -1),
|
||||
> 1 when filterValue[1] == ':' =>
|
||||
filterValue[0] switch
|
||||
{
|
||||
'n' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 1),
|
||||
'N' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 1),
|
||||
'm' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 2),
|
||||
'M' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 2),
|
||||
't' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 3),
|
||||
'T' => filterValue.Length == 2 ? (LowerString.Empty, -1) : (new LowerString(filterValue[2..]), 3),
|
||||
_ => (new LowerString(filterValue), 0),
|
||||
},
|
||||
_ => (new LowerString(filterValue), 0),
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The overwritten filter method also computes the state.
|
||||
/// Folders have default state and are filtered out on the direct string instead of the other options.
|
||||
/// If any filter is set, they should be hidden by default unless their children are visible,
|
||||
/// or they contain the path search string.
|
||||
/// </summary>
|
||||
protected override bool ApplyFiltersAndState(FileSystem<Design>.IPath path, out DesignState state)
|
||||
{
|
||||
if (path is DesignFileSystem.Folder f)
|
||||
{
|
||||
state = default;
|
||||
return FilterValue.Length > 0 && !f.FullName().Contains(FilterValue, IgnoreCase);
|
||||
}
|
||||
|
||||
return ApplyFiltersAndState((DesignFileSystem.Leaf)path, out state);
|
||||
}
|
||||
|
||||
/// <summary> Apply the string filters. </summary>
|
||||
private bool ApplyStringFilters(DesignFileSystem.Leaf leaf, Design design)
|
||||
{
|
||||
return _filterType switch
|
||||
{
|
||||
-1 => false,
|
||||
0 => !(_designFilter.IsContained(leaf.FullName()) || design.Name.Contains(_designFilter)),
|
||||
1 => !design.Name.Contains(_designFilter),
|
||||
2 => !design.AssociatedMods.Any(kvp => _designFilter.IsContained(kvp.Key.Name)),
|
||||
3 => !design.Tags.Any(_designFilter.IsContained),
|
||||
_ => false, // Should never happen
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary> Combined wrapper for handling all filters and setting state. </summary>
|
||||
private bool ApplyFiltersAndState(DesignFileSystem.Leaf leaf, out DesignState state)
|
||||
{
|
||||
var applyEquip = leaf.Value.ApplyEquip != 0;
|
||||
var applyCustomize = (leaf.Value.ApplyCustomize & ~(CustomizeFlag.BodyType | CustomizeFlag.Race)) != 0;
|
||||
|
||||
state.Color = (applyEquip, applyCustomize) switch
|
||||
{
|
||||
(false, false) => ColorId.StateDesign,
|
||||
(false, true) => ColorId.CustomizationDesign,
|
||||
(true, false) => ColorId.EquipmentDesign,
|
||||
(true, true) => ColorId.NormalDesign,
|
||||
};
|
||||
|
||||
return ApplyStringFilters(leaf, leaf.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,36 +95,6 @@ public class DesignPanel
|
|||
private string SelectionName
|
||||
=> _selector.Selected == null ? "No Selection" : _selector.IncognitoMode ? _selector.Selected.Incognito : _selector.Selected.Name.Text;
|
||||
|
||||
private void DrawMetaData()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("MetaData"))
|
||||
return;
|
||||
|
||||
using (var group1 = ImRaii.Group())
|
||||
{
|
||||
var apply = _selector.Selected!.DesignData.IsHatVisible();
|
||||
if (ImGui.Checkbox("Hat Visible", ref apply))
|
||||
_manager.ChangeMeta(_selector.Selected, ActorState.MetaIndex.HatState, apply);
|
||||
|
||||
apply = _selector.Selected.DesignData.IsWeaponVisible();
|
||||
if (ImGui.Checkbox("Weapon Visible", ref apply))
|
||||
_manager.ChangeMeta(_selector.Selected, ActorState.MetaIndex.WeaponState, apply);
|
||||
}
|
||||
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X / 2);
|
||||
|
||||
using (var group2 = ImRaii.Group())
|
||||
{
|
||||
var apply = _selector.Selected.DesignData.IsVisorToggled();
|
||||
if (ImGui.Checkbox("Visor Toggled", ref apply))
|
||||
_manager.ChangeMeta(_selector.Selected, ActorState.MetaIndex.VisorState, apply);
|
||||
|
||||
apply = _selector.Selected.DesignData.IsWet();
|
||||
if (ImGui.Checkbox("Force Wetness", ref apply))
|
||||
_manager.ChangeMeta(_selector.Selected, ActorState.MetaIndex.Wetness, apply);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEquipment()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Equipment"))
|
||||
|
|
@ -135,41 +105,82 @@ public class DesignPanel
|
|||
{
|
||||
var changes = _equipmentDrawer.DrawEquip(slot, _selector.Selected!.DesignData, out var newArmor, out var newStain,
|
||||
_selector.Selected.ApplyEquip, out var newApply, out var newApplyStain, _selector.Selected!.WriteProtected());
|
||||
if (changes.HasFlag(EquipmentDrawer.EquipChange.Item))
|
||||
if (changes.HasFlag(DataChange.Item))
|
||||
_manager.ChangeEquip(_selector.Selected, slot, newArmor);
|
||||
if (changes.HasFlag(EquipmentDrawer.EquipChange.Stain))
|
||||
if (changes.HasFlag(DataChange.Stain))
|
||||
_manager.ChangeStain(_selector.Selected, slot, newStain);
|
||||
if (changes.HasFlag(EquipmentDrawer.EquipChange.ApplyItem))
|
||||
if (changes.HasFlag(DataChange.ApplyItem))
|
||||
_manager.ChangeApplyEquip(_selector.Selected, slot, newApply);
|
||||
if (changes.HasFlag(EquipmentDrawer.EquipChange.ApplyStain))
|
||||
if (changes.HasFlag(DataChange.ApplyStain))
|
||||
_manager.ChangeApplyStain(_selector.Selected, slot, newApplyStain);
|
||||
}
|
||||
|
||||
var weaponChanges = _equipmentDrawer.DrawWeapons(_selector.Selected!.DesignData, out var newMainhand, out var newOffhand,
|
||||
out var newMainhandStain, out var newOffhandStain, _selector.Selected.ApplyEquip, out var applyMain, out var applyMainStain,
|
||||
out var applyOff, out var applyOffStain, _selector.Selected!.WriteProtected());
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Item))
|
||||
|
||||
if (weaponChanges.HasFlag(DataChange.Item))
|
||||
_manager.ChangeWeapon(_selector.Selected, EquipSlot.MainHand, newMainhand);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain))
|
||||
if (weaponChanges.HasFlag(DataChange.Stain))
|
||||
_manager.ChangeStain(_selector.Selected, EquipSlot.MainHand, newMainhandStain);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.ApplyItem))
|
||||
if (weaponChanges.HasFlag(DataChange.ApplyItem))
|
||||
_manager.ChangeApplyEquip(_selector.Selected, EquipSlot.MainHand, applyMain);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.ApplyStain))
|
||||
if (weaponChanges.HasFlag(DataChange.ApplyStain))
|
||||
_manager.ChangeApplyStain(_selector.Selected, EquipSlot.MainHand, applyMainStain);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Item2))
|
||||
if (weaponChanges.HasFlag(DataChange.Item2))
|
||||
_manager.ChangeWeapon(_selector.Selected, EquipSlot.OffHand, newOffhand);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.Stain2))
|
||||
if (weaponChanges.HasFlag(DataChange.Stain2))
|
||||
_manager.ChangeStain(_selector.Selected, EquipSlot.OffHand, newOffhandStain);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.ApplyItem2))
|
||||
if (weaponChanges.HasFlag(DataChange.ApplyItem2))
|
||||
_manager.ChangeApplyEquip(_selector.Selected, EquipSlot.OffHand, applyOff);
|
||||
if (weaponChanges.HasFlag(EquipmentDrawer.EquipChange.ApplyStain2))
|
||||
if (weaponChanges.HasFlag(DataChange.ApplyStain2))
|
||||
_manager.ChangeApplyStain(_selector.Selected, EquipSlot.OffHand, applyOffStain);
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawEquipmentMetaToggles();
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
}
|
||||
|
||||
private void DrawEquipmentMetaToggles()
|
||||
{
|
||||
var hatChanges = _equipmentDrawer.DrawHatState(_selector.Selected!.DesignData.IsHatVisible(),
|
||||
_selector.Selected.DoApplyHatVisible(),
|
||||
out var newHatState, out var newHatApply, _selector.Selected.WriteProtected());
|
||||
ApplyChanges(ActorState.MetaIndex.HatState, hatChanges, newHatState, newHatApply);
|
||||
|
||||
ImGui.SameLine();
|
||||
var visorChanges = _equipmentDrawer.DrawVisorState(_selector.Selected!.DesignData.IsVisorToggled(),
|
||||
_selector.Selected.DoApplyVisorToggle(),
|
||||
out var newVisorState, out var newVisorApply, _selector.Selected.WriteProtected());
|
||||
ApplyChanges(ActorState.MetaIndex.VisorState, visorChanges, newVisorState, newVisorApply);
|
||||
|
||||
ImGui.SameLine();
|
||||
var weaponChanges = _equipmentDrawer.DrawWeaponState(_selector.Selected!.DesignData.IsWeaponVisible(),
|
||||
_selector.Selected.DoApplyWeaponVisible(),
|
||||
out var newWeaponState, out var newWeaponApply, _selector.Selected.WriteProtected());
|
||||
ApplyChanges(ActorState.MetaIndex.WeaponState, weaponChanges, newWeaponState, newWeaponApply);
|
||||
}
|
||||
|
||||
private void DrawCustomize()
|
||||
{
|
||||
if (ImGui.CollapsingHeader("Customization"))
|
||||
_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected!.WriteProtected());
|
||||
if (!ImGui.CollapsingHeader("Customization"))
|
||||
return;
|
||||
|
||||
_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected.ApplyCustomize,
|
||||
_selector.Selected!.WriteProtected());
|
||||
|
||||
if (_customizationDrawer.ChangeApply != _selector.Selected.ApplyCustomize)
|
||||
foreach (var idx in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
var flag = idx.ToFlag();
|
||||
var newValue = _customizationDrawer.ChangeApply.HasFlag(flag);
|
||||
_manager.ChangeApplyCustomize(_selector.Selected, idx, newValue);
|
||||
}
|
||||
|
||||
var wetnessChanges = _customizationDrawer.DrawWetnessState(_selector.Selected!.DesignData.IsWet(),
|
||||
_selector.Selected!.DoApplyWetness(), out var newWetnessState, out var newWetnessApply, _selector.Selected!.WriteProtected());
|
||||
ApplyChanges(ActorState.MetaIndex.Wetness, wetnessChanges, newWetnessState, newWetnessApply);
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
}
|
||||
|
||||
private void DrawApplicationRules()
|
||||
|
|
@ -285,7 +296,6 @@ public class DesignPanel
|
|||
return;
|
||||
|
||||
DrawButtonRow();
|
||||
DrawMetaData();
|
||||
DrawCustomize();
|
||||
DrawEquipment();
|
||||
_designDetails.Draw();
|
||||
|
|
@ -354,4 +364,21 @@ public class DesignPanel
|
|||
if (_state.GetOrCreate(id, data.Objects[0], out var state))
|
||||
_state.ApplyDesign(_selector.Selected!, state, StateChanged.Source.Manual);
|
||||
}
|
||||
|
||||
private void ApplyChanges(ActorState.MetaIndex index, DataChange change, bool value, bool apply)
|
||||
{
|
||||
switch (change)
|
||||
{
|
||||
case DataChange.Item:
|
||||
_manager.ChangeMeta(_selector.Selected!, index, value);
|
||||
break;
|
||||
case DataChange.ApplyItem:
|
||||
_manager.ChangeApplyMeta(_selector.Selected!, index, apply);
|
||||
break;
|
||||
case DataChange.Item | DataChange.ApplyItem:
|
||||
_manager.ChangeApplyMeta(_selector.Selected!, index, apply);
|
||||
_manager.ChangeMeta(_selector.Selected!, index, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ public class SettingsTab : ITab
|
|||
Checkbox("Auto-Reload Gear",
|
||||
"Automatically reload equipment pieces on your own character when changing any mod options in Penumbra in their associated collection.",
|
||||
_config.AutoRedrawEquipOnChanges, _autoRedraw.SetState);
|
||||
|
||||
Checkbox("Hide Application Checkboxes",
|
||||
"Hide the application checkboxes in the Customization and Equipment panels of the design tab, and only show them under Application Rules.",
|
||||
_config.HideApplyCheckmarks, v => _config.HideApplyCheckmarks = v);
|
||||
if (Widget.DoubleModifierSelector("Design Deletion Modifier",
|
||||
"A modifier you need to hold while clicking the Delete Design button for it to take effect.", 100 * ImGuiHelpers.GlobalScale,
|
||||
_config.DeleteDesignModifier, v => _config.DeleteDesignModifier = v))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Services;
|
||||
|
|
@ -8,6 +9,20 @@ using Penumbra.GameData.Structs;
|
|||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
[Flags]
|
||||
public enum DataChange : byte
|
||||
{
|
||||
None = 0x00,
|
||||
Item = 0x01,
|
||||
Stain = 0x02,
|
||||
ApplyItem = 0x04,
|
||||
ApplyStain = 0x08,
|
||||
Item2 = 0x10,
|
||||
Stain2 = 0x20,
|
||||
ApplyItem2 = 0x40,
|
||||
ApplyStain2 = 0x80,
|
||||
}
|
||||
|
||||
public static class UiHelpers
|
||||
{
|
||||
public static void DrawIcon(this EquipItem item, TextureService textures, Vector2 size)
|
||||
|
|
@ -40,15 +55,32 @@ public static class UiHelpers
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static bool DrawVisor(bool current, out bool on, bool locked)
|
||||
=> DrawCheckbox("##visorToggled", string.Empty, current, out on, locked);
|
||||
|
||||
public static bool DrawHat(bool current, out bool on, bool locked)
|
||||
=> DrawCheckbox("##hatVisible", string.Empty, current, out on, locked);
|
||||
|
||||
public static bool DrawWeapon(bool current, out bool on, bool locked)
|
||||
=> DrawCheckbox("##weaponVisible", string.Empty, current, out on, locked);
|
||||
|
||||
public static bool DrawWetness(bool current, out bool on, bool locked)
|
||||
=> DrawCheckbox("##wetness", string.Empty, current, out on, locked);
|
||||
public static DataChange DrawMetaToggle(string label, string tooltip, bool currentValue, bool currentApply, out bool newValue, out bool newApply,
|
||||
bool locked)
|
||||
{
|
||||
var flags = currentApply ? currentValue ? 3 : 0 : 2;
|
||||
bool ret;
|
||||
using (var disabled = ImRaii.Disabled(locked))
|
||||
{
|
||||
ret = ImGui.CheckboxFlags(label, ref flags, 3);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
(newValue, newApply, var change) = (currentValue, currentApply) switch
|
||||
{
|
||||
(false, false) => (false, true, DataChange.ApplyItem),
|
||||
(false, true) => (true, true, DataChange.Item),
|
||||
(true, false) => (false, false, DataChange.Item), // Should not happen
|
||||
(true, true) => (false, false, DataChange.Item | DataChange.ApplyItem),
|
||||
};
|
||||
return change;
|
||||
}
|
||||
|
||||
newValue = currentValue;
|
||||
newApply = currentApply;
|
||||
return DataChange.None;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public unsafe class WeaponService : IDisposable
|
|||
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4);
|
||||
if (tmpWeapon.Value != weapon.Value)
|
||||
_loadWeaponHook.Original(drawData, slot, tmpWeapon.Value, 1, unk2, 1, unk4);
|
||||
Glamourer.Log.Information(
|
||||
Glamourer.Log.Excessive(
|
||||
$"Weapon reloaded for 0x{actor.Address:X} ({actor.Utf8Name}) with attributes {slot} {weapon.Value:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,10 +165,10 @@ public class StateEditor
|
|||
{
|
||||
(var setter, oldValue) = index switch
|
||||
{
|
||||
ActorState.MetaIndex.Wetness => ((Func<bool, bool>)state.ModelData.SetIsWet, state.ModelData.IsWet()),
|
||||
ActorState.MetaIndex.HatState => ((Func<bool, bool>)state.ModelData.SetHatVisible, state.ModelData.IsHatVisible()),
|
||||
ActorState.MetaIndex.VisorState => ((Func<bool, bool>)state.ModelData.SetVisor, state.ModelData.IsVisorToggled()),
|
||||
ActorState.MetaIndex.WeaponState => ((Func<bool, bool>)state.ModelData.SetWeaponVisible, state.ModelData.IsWeaponVisible()),
|
||||
ActorState.MetaIndex.Wetness => ((Func<bool, bool>) (v => state.ModelData.SetIsWet(v)), state.ModelData.IsWet()),
|
||||
ActorState.MetaIndex.HatState => ((Func<bool, bool>) (v => state.ModelData.SetHatVisible(v)), state.ModelData.IsHatVisible()),
|
||||
ActorState.MetaIndex.VisorState => ((Func<bool, bool>) (v => state.ModelData.SetVisor(v)), state.ModelData.IsVisorToggled()),
|
||||
ActorState.MetaIndex.WeaponState => ((Func<bool, bool>) (v => state.ModelData.SetWeaponVisible(v)), state.ModelData.IsWeaponVisible()),
|
||||
_ => throw new Exception("Invalid MetaIndex."),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
|||
if (!_editor.ChangeMetaState(state, ActorState.MetaIndex.Wetness, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeVisor(state, true);
|
||||
var actors = _applier.ChangeWetness(state, true);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set Wetness in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Other, state[ActorState.MetaIndex.Wetness], state, actors, (old, value, ActorState.MetaIndex.Wetness));
|
||||
|
|
@ -382,21 +382,29 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
|
|||
else
|
||||
{
|
||||
_applier.ChangeCustomize(actors, state.ModelData.Customize);
|
||||
_applier.ChangeHatState(actors, state.ModelData.IsHatVisible());
|
||||
_applier.ChangeWeaponState(actors, state.ModelData.IsWeaponVisible());
|
||||
_applier.ChangeVisor(actors, state.ModelData.IsVisorToggled());
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
_applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state.ModelData.IsHatVisible());
|
||||
foreach (var slot in EquipSlotExtensions.WeaponSlots)
|
||||
_applier.ChangeWeapon(actors, slot, state.ModelData.Item(slot), state.ModelData.Stain(slot));
|
||||
}
|
||||
|
||||
if (state.ModelData.IsHuman)
|
||||
{
|
||||
_applier.ChangeHatState(actors, state.ModelData.IsHatVisible());
|
||||
_applier.ChangeWeaponState(actors, state.ModelData.IsWeaponVisible());
|
||||
_applier.ChangeVisor(actors, state.ModelData.IsVisorToggled());
|
||||
}
|
||||
|
||||
return actors;
|
||||
}
|
||||
|
||||
public void ResetState(ActorState state)
|
||||
public void ResetState(ActorState state, uint key = 0)
|
||||
{
|
||||
var redraw = state.ModelData.ModelId != state.BaseData.ModelId || !state.ModelData.IsHuman
|
||||
if (!state.Unlock(key))
|
||||
return;
|
||||
|
||||
var redraw = state.ModelData.ModelId != state.BaseData.ModelId
|
||||
|| !state.ModelData.IsHuman
|
||||
|| Customize.Compare(state.ModelData.Customize, state.BaseData.Customize).RequiresRedraw();
|
||||
state.ModelData = state.BaseData;
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue