Compare commits

...

74 commits

Author SHA1 Message Date
Actions User
5b6517aae8 [CI] Updating repo.json for 1.5.1.5 2025-11-28 22:09:08 +00:00
Ottermandias
aadcf771e7 1.5.1.5 2025-11-28 23:06:53 +01:00
Ottermandias
bf4673a1d9 Save Remove and Inherit for mod associations. 2025-11-07 23:30:18 +01:00
Ottermandias
76b214c643 Fix try-on interaction with Penumbra for facewear. 2025-11-07 23:30:18 +01:00
Ottermandias
434a5a809e Make old backup files overwrite instead of throwing. 2025-11-07 23:30:18 +01:00
Actions User
88fe25f69e [CI] Updating repo.json for testing_1.5.1.4 2025-10-23 15:40:25 +00:00
Ottermandias
bef1e39ac3 Update Libraries. 2025-10-23 17:37:27 +02:00
Ottermandias
c604d5dbe5 Add DeletePlayerState. 2025-10-23 17:25:59 +02:00
Ottermandias
a0d912a395 Fix issue with reverting state of unavailable actors. 2025-10-23 17:25:59 +02:00
Actions User
a56852f918 [CI] Updating repo.json for 1.5.1.3 2025-10-07 11:02:02 +00:00
Ottermandias
4228fc1b89 fu 2025-10-07 12:59:39 +02:00
Ottermandias
e644b8da28 Fix span issue. 2025-10-07 12:53:55 +02:00
Ottermandias
ace3a8f755 Again. 2025-10-07 12:43:40 +02:00
Ottermandias
76ed347cbf Update signatures. 2025-10-07 12:28:18 +02:00
Ottermandias
c3469a1687 Fix facewear advanced dyes, fix backup service not running in task, update libraries. 2025-09-28 23:55:44 +02:00
Ottermandias
0a9693daea
Update CodeService.cs 2025-09-15 20:29:13 +02:00
Actions User
414bd8bee7 [CI] Updating repo.json for 1.5.1.2 2025-08-28 16:52:43 +00:00
Ottermandias
8e1745d67a Once more with feeling 2025-08-28 18:47:57 +02:00
Actions User
889f01a724 [CI] Updating repo.json for 1.5.1.1 2025-08-26 09:58:08 +00:00
Ottermandias
6e62905fa7 Fix staging incompatibility with CS. 2025-08-26 11:55:00 +02:00
Actions User
654787fa0d [CI] Updating repo.json for 1.5.1.0 2025-08-25 08:45:28 +00:00
Ottermandias
835ba23935 1.5.1.0 2025-08-25 10:43:14 +02:00
Ottermandias
389a8781d6 Update library. 2025-08-25 10:39:38 +02:00
Actions User
3eabe591df [CI] Updating repo.json for testing_1.5.0.9 2025-08-24 13:59:02 +00:00
Ottermandias
487d3b9399 Update PCP Service. 2025-08-24 15:49:29 +02:00
Actions User
4d4e4669dd [CI] Updating repo.json for testing_1.5.0.8 2025-08-22 18:34:49 +00:00
Ottermandias
fb065549e9 Add PCP Service. 2025-08-22 20:32:32 +02:00
Ottermandias
2c34154915 Update API. 2025-08-22 20:32:32 +02:00
Actions User
3704051b0f [CI] Updating repo.json for 1.5.0.7 2025-08-17 08:45:55 +00:00
Ottermandias
b2b8f2b6eb Make glamourers visor toggle trigger static visors. (?!?) 2025-08-17 10:43:26 +02:00
Ottermandias
22e6c0655b Add ear state when toggling meta application via button. 2025-08-16 11:59:08 +02:00
Ottermandias
bb2ba0cf11 Add glasses to advanced dye slot combo. 2025-08-16 11:59:08 +02:00
Ottermandias
e854386b23 Update OtterGui 2025-08-16 11:59:08 +02:00
Actions User
49d24df2e7 [CI] Updating repo.json for 1.5.0.6 2025-08-12 12:53:44 +00:00
Ottermandias
c9b291c2f3 Add new parameter to LoadWeapon hook. 2025-08-12 14:47:09 +02:00
Actions User
65f789880d [CI] Updating repo.json for 1.5.0.5 2025-08-12 10:32:03 +00:00
Ottermandias
abf998a727 Update GameData 2025-08-12 12:29:55 +02:00
Ottermandias
4cc191cb25 Add viera ear visibility to application rules. 2025-08-11 20:53:44 +02:00
Ottermandias
dc431c10a5 Add chat command to toggle automation. 2025-08-11 19:59:27 +02:00
Ottermandias
26862ba78f Update ChangedEquipData. 2025-08-11 19:59:27 +02:00
Actions User
e4374337f2 [CI] Updating repo.json for 1.5.0.4 2025-08-09 18:50:50 +00:00
Ottermandias
240c889fff Fix changed equipment access to use new size. 2025-08-09 20:48:46 +02:00
Ottermandias
612cd31c3e Fix some caravans. 2025-08-09 19:02:32 +02:00
Actions User
304b362002 [CI] Updating repo.json for 1.5.0.3 2025-08-09 16:55:27 +00:00
Ottermandias
8f34f197d0 Another try. 2025-08-09 18:53:22 +02:00
Actions User
1c97266a93 [CI] Updating repo.json for 1.5.0.2 2025-08-09 16:41:32 +00:00
Ottermandias
a9caddafd5 Maybe fix design crashes. 2025-08-09 18:39:14 +02:00
Actions User
34bf95dddb [CI] Updating repo.json for 1.5.0.1 2025-08-09 11:03:48 +00:00
Ottermandias
4761b8f584 Need staging again... 2025-08-09 13:01:48 +02:00
Ottermandias
0d94aae732 Fix popups not working early. 2025-08-09 12:11:42 +02:00
Ottermandias
e83f328cdc Fix resizable child. 2025-08-09 11:58:52 +02:00
Ottermandias
52fd29c478 Woops 2025-08-09 11:52:17 +02:00
Ottermandias
a8b79993df Make QDB ignore close hotkey. 2025-08-09 11:47:11 +02:00
Ottermandias
98574558e5 Set Repo API level to 13 and remove stg from future releases. 2025-08-08 23:07:08 +02:00
Actions User
557cbf23ce [CI] Updating repo.json for 1.5.0.0 2025-08-08 21:06:10 +00:00
Ottermandias
56753ae7ba Use staging for release. 2025-08-08 23:03:58 +02:00
Ottermandias
b66df624f7 Update Gamedata. 2025-08-08 23:01:54 +02:00
Ottermandias
be78f1447b 1.5.0.0 2025-08-08 15:56:08 +02:00
Ottermandias
97e32a3cb7 Update GameData. 2025-08-08 15:48:19 +02:00
Ottermandias
4472920536 Move Viera Ears sig to gamedata. 2025-08-08 15:46:24 +02:00
Ottermandias
ac6a726f57 Remaining API13 updates. 2025-08-08 15:39:05 +02:00
Ottermandias
00d550f4fe Add viera ear flags 2025-08-08 15:38:51 +02:00
Ottermandias
0f98fac157 Add auto-locking to design defaults. 2025-08-08 15:36:47 +02:00
Ottermandias
c25f0f72db Update for ottergui. 2025-08-08 15:36:14 +02:00
Karou
72e05e23bc stupid detached head.... 2025-08-07 21:53:01 -04:00
Karou
2c3bed6ba5 Api 13 grunt work 2025-08-07 21:50:23 -04:00
Ottermandias
d6df9885dc Update GameData. 2025-08-02 00:07:38 +02:00
Ottermandias
e7936500e0
Merge pull request #111 from CordeliaMist/Fix-RevertNotFiringFinalize
Correct StateFinalized not invoking in certain areas
2025-07-28 18:00:26 +02:00
Cordelia Mist
4ef4e65d46 Ensure that reverts called by API invoke their StateFinalizationType upon completing a reset state. 2025-07-28 08:43:13 -07:00
Cordelia Mist
40b4a8fd7a Ensure Revert via Command invokes a StateFinalization type for Reset 2025-07-28 08:37:57 -07:00
Actions User
8a1f03c272 [CI] Updating repo.json for 1.4.0.3 2025-07-14 15:12:49 +00:00
Ottermandias
8ed479eddf Fix issue with invalid bonus items. 2025-07-14 17:09:42 +02:00
Ottermandias
c0a278ca2c Make designs update on mousewheel. 2025-06-15 23:34:00 +02:00
Actions User
2e9a7004c6 [CI] Updating repo.json for 1.4.0.2 2025-06-13 15:21:04 +00:00
130 changed files with 933 additions and 289 deletions

View file

@ -20,7 +20,7 @@ jobs:
run: dotnet restore
- name: Download Dalamud
run: |
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip
Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev"
- name: Build
run: |

@ -1 +1 @@
Subproject commit 64897c069d3b6c3fe027b3ae0e832828728b9108
Subproject commit 59a7ab5fa9941eb754757b62e4cb189e455e9514

View file

@ -1,13 +1,13 @@
using Glamourer.Api.Enums;
using Glamourer.Designs;
using Glamourer.State;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Log;
using OtterGui.Services;
using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
using Penumbra.String;
namespace Glamourer.Api;
@ -15,14 +15,23 @@ namespace Glamourer.Api;
public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal IEnumerable<ActorState> FindExistingStates(string actorName)
internal IEnumerable<ActorState> FindExistingStates(string actorName, ushort worldId = ushort.MaxValue)
{
if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString))
yield break;
foreach (var state in stateManager.Values.Where(state
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
yield return state;
if (worldId == WorldId.AnyWorld.Id)
{
foreach (var state in stateManager.Values.Where(state
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
yield return state;
}
else
{
var identifier = actors.CreatePlayer(byteString, worldId);
if (stateManager.TryGetValue(identifier, out var state))
yield return state;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]

View file

@ -6,7 +6,7 @@ namespace Glamourer.Api;
public class GlamourerApi(DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
{
public const int CurrentApiVersionMajor = 1;
public const int CurrentApiVersionMinor = 6;
public const int CurrentApiVersionMinor = 7;
public (int Major, int Minor) ApiVersion
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);

View file

@ -54,6 +54,7 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.RevertStateName.Provider(pi, api.State),
IpcSubscribers.UnlockState.Provider(pi, api.State),
IpcSubscribers.UnlockStateName.Provider(pi, api.State),
IpcSubscribers.DeletePlayerState.Provider(pi, api.State),
IpcSubscribers.UnlockAll.Provider(pi, api.State),
IpcSubscribers.RevertToAutomation.Provider(pi, api.State),
IpcSubscribers.RevertToAutomationName.Provider(pi, api.State),

View file

@ -8,6 +8,7 @@ using Glamourer.State;
using Newtonsoft.Json.Linq;
using OtterGui.Services;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
using StateChanged = Glamourer.Events.StateChanged;
namespace Glamourer.Api;
@ -17,7 +18,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
private readonly ApiHelpers _helpers;
private readonly StateManager _stateManager;
private readonly DesignConverter _converter;
private readonly Configuration _config;
private readonly AutoDesignApplier _autoDesigns;
private readonly ActorObjectManager _objects;
private readonly StateChanged _stateChanged;
@ -27,7 +27,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
public StateApi(ApiHelpers helpers,
StateManager stateManager,
DesignConverter converter,
Configuration config,
AutoDesignApplier autoDesigns,
ActorObjectManager objects,
StateChanged stateChanged,
@ -37,7 +36,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
_helpers = helpers;
_stateManager = stateManager;
_converter = converter;
_config = config;
_autoDesigns = autoDesigns;
_objects = objects;
_stateChanged = stateChanged;
@ -202,6 +200,27 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
return ApiHelpers.Return(GlamourerApiEc.Success, args);
}
public GlamourerApiEc DeletePlayerState(string playerName, ushort worldId, uint key)
{
var args = ApiHelpers.Args("Name", playerName, "World", worldId, "Key", key);
var states = _helpers.FindExistingStates(playerName).ToList();
if (states.Count is 0)
return ApiHelpers.Return(GlamourerApiEc.NothingDone, args);
var anyLocked = false;
foreach (var state in states)
{
if (state.CanUnlock(key))
_stateManager.DeleteState(state.Identifier);
else
anyLocked = true;
}
return ApiHelpers.Return(anyLocked
? GlamourerApiEc.InvalidKey
: GlamourerApiEc.Success, args);
}
public int UnlockAll(uint key)
=> _stateManager.Values.Count(state => state.Unlock(key));
@ -272,7 +291,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
{
case ApplyFlag.Equipment: _stateManager.ResetEquip(state, source, key); break;
case ApplyFlag.Customization: _stateManager.ResetCustomize(state, source, key); break;
case ApplyFlag.Equipment | ApplyFlag.Customization: _stateManager.ResetState(state, source, key); break;
case ApplyFlag.Equipment | ApplyFlag.Customization: _stateManager.ResetState(state, source, key, true); break;
}
ApiHelpers.Lock(state, key, flags);

View file

@ -38,7 +38,7 @@ public static class ApplicationTypeExtensions
var customizeFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeFlagExtensions.All : 0;
var parameterFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeParameterExtensions.All : 0;
var crestFlags = type.HasFlag(ApplicationType.GearCustomization) ? CrestExtensions.AllRelevant : 0;
var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState : 0)
var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.EarState : 0)
| (type.HasFlag(ApplicationType.Weapons) ? MetaFlag.WeaponState : 0)
| (type.HasFlag(ApplicationType.Customizations) ? MetaFlag.Wetness : 0);
var bonusFlags = type.HasFlag(ApplicationType.Armor) ? BonusExtensions.All : 0;

View file

@ -32,6 +32,7 @@ public class DefaultDesignSettings
public bool ResetAdvancedDyes = false;
public bool ShowQuickDesignBar = true;
public bool ResetTemporarySettings = false;
public bool Locked = false;
}
public class Configuration : IPluginConfiguration, ISavable
@ -39,34 +40,37 @@ public class Configuration : IPluginConfiguration, ISavable
[JsonIgnore]
public readonly EphemeralConfig Ephemeral;
public bool UseRestrictedGearProtection { get; set; } = false;
public bool OpenFoldersByDefault { get; set; } = false;
public bool AutoRedrawEquipOnChanges { get; set; } = false;
public bool EnableAutoDesigns { get; set; } = true;
public bool HideApplyCheckmarks { get; set; } = false;
public bool SmallEquip { get; set; } = false;
public bool UnlockedItemMode { get; set; } = false;
public byte DisableFestivals { get; set; } = 1;
public bool EnableGameContextMenu { get; set; } = true;
public bool HideWindowInCutscene { get; set; } = false;
public bool ShowAutomationSetEditing { get; set; } = true;
public bool ShowAllAutomatedApplicationRules { get; set; } = true;
public bool ShowUnlockedItemWarnings { get; set; } = true;
public bool RevertManualChangesOnZoneChange { get; set; } = false;
public bool ShowQuickBarInTabs { get; set; } = true;
public bool OpenWindowAtStart { get; set; } = false;
public bool ShowWindowWhenUiHidden { get; set; } = false;
public bool KeepAdvancedDyesAttached { get; set; } = true;
public bool ShowPalettePlusImport { get; set; } = true;
public bool UseFloatForColors { get; set; } = true;
public bool UseRgbForColors { get; set; } = true;
public bool ShowColorConfig { get; set; } = true;
public bool ChangeEntireItem { get; set; } = false;
public bool AlwaysApplyAssociatedMods { get; set; } = false;
public bool UseTemporarySettings { get; set; } = true;
public bool AllowDoubleClickToApply { get; set; } = false;
public bool RespectManualOnAutomationUpdate { get; set; } = false;
public bool PreventRandomRepeats { get; set; } = false;
public bool AttachToPcp { get; set; } = true;
public bool UseRestrictedGearProtection { get; set; } = false;
public bool OpenFoldersByDefault { get; set; } = false;
public bool AutoRedrawEquipOnChanges { get; set; } = false;
public bool EnableAutoDesigns { get; set; } = true;
public bool HideApplyCheckmarks { get; set; } = false;
public bool SmallEquip { get; set; } = false;
public bool UnlockedItemMode { get; set; } = false;
public byte DisableFestivals { get; set; } = 1;
public bool EnableGameContextMenu { get; set; } = true;
public bool HideWindowInCutscene { get; set; } = false;
public bool ShowAutomationSetEditing { get; set; } = true;
public bool ShowAllAutomatedApplicationRules { get; set; } = true;
public bool ShowUnlockedItemWarnings { get; set; } = true;
public bool RevertManualChangesOnZoneChange { get; set; } = false;
public bool ShowQuickBarInTabs { get; set; } = true;
public bool OpenWindowAtStart { get; set; } = false;
public bool ShowWindowWhenUiHidden { get; set; } = false;
public bool KeepAdvancedDyesAttached { get; set; } = true;
public bool ShowPalettePlusImport { get; set; } = true;
public bool UseFloatForColors { get; set; } = true;
public bool UseRgbForColors { get; set; } = true;
public bool ShowColorConfig { get; set; } = true;
public bool ChangeEntireItem { get; set; } = false;
public bool AlwaysApplyAssociatedMods { get; set; } = true;
public bool UseTemporarySettings { get; set; } = true;
public bool AllowDoubleClickToApply { get; set; } = false;
public bool RespectManualOnAutomationUpdate { get; set; } = false;
public bool PreventRandomRepeats { get; set; } = false;
public string PcpFolder { get; set; } = "PCP";
public string PcpColor { get; set; } = "";
public DesignPanelFlag HideDesignPanel { get; set; } = 0;
public DesignPanelFlag AutoExpandDesignPanel { get; set; } = 0;

View file

@ -1,5 +1,5 @@
using Glamourer.Designs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Text;
using OtterGui.Text.EndObjects;

View file

@ -1,6 +1,6 @@
using Glamourer.Api.Enums;
using Glamourer.GameData;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Penumbra.GameData.Enums;
namespace Glamourer.Designs;
@ -19,13 +19,13 @@ public record struct ApplicationCollection(
public static readonly ApplicationCollection None = new(0, 0, CustomizeFlag.BodyType, 0, 0, 0);
public static readonly ApplicationCollection Equipment = new(EquipFlagExtensions.All, BonusExtensions.All,
CustomizeFlag.BodyType, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.WeaponState | MetaFlag.VisorState);
CustomizeFlag.BodyType, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.WeaponState | MetaFlag.VisorState | MetaFlag.EarState);
public static readonly ApplicationCollection Customizations = new(0, 0, CustomizeFlagExtensions.AllRelevant, 0,
CustomizeParameterExtensions.All, MetaFlag.Wetness);
public static readonly ApplicationCollection Default = new(EquipFlagExtensions.All, BonusExtensions.All,
CustomizeFlagExtensions.AllRelevant, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState);
CustomizeFlagExtensions.AllRelevant, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState);
public static ApplicationCollection FromKeys()
=> (ImGui.GetIO().KeyCtrl, ImGui.GetIO().KeyShift) switch
@ -47,7 +47,7 @@ public record struct ApplicationCollection(
Equip = 0;
BonusItem = 0;
Crest = 0;
Meta &= ~(MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState);
Meta &= ~(MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState);
}
public void RemoveCustomize()

View file

@ -1,7 +1,7 @@
using Glamourer.Api.Enums;
using Glamourer.GameData;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Penumbra.GameData.Enums;
namespace Glamourer.Designs;

View file

@ -100,7 +100,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
public new JObject JsonSerialize()
{
var ret = new JObject()
var ret = new JObject
{
["FileVersion"] = FileVersion,
["Identifier"] = Identifier,
@ -131,12 +131,17 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
var ret = new JArray();
foreach (var (mod, settings) in AssociatedMods)
{
var obj = new JObject()
var obj = new JObject
{
["Name"] = mod.Name,
["Directory"] = mod.DirectoryName,
["Enabled"] = settings.Enabled,
};
if (settings.Remove)
obj["Remove"] = true;
else if (settings.ForceInherit)
obj["Inherit"] = true;
else
obj["Enabled"] = settings.Enabled;
if (settings.Enabled)
{
obj["Priority"] = settings.Priority;

View file

@ -40,7 +40,8 @@ public class DesignBase
}
/// <summary> Used when importing .cma or .chara files. </summary>
internal DesignBase(CustomizeService customize, in DesignData designData, EquipFlag equipFlags, CustomizeFlag customizeFlags, BonusItemFlag bonusFlags)
internal DesignBase(CustomizeService customize, in DesignData designData, EquipFlag equipFlags, CustomizeFlag customizeFlags,
BonusItemFlag bonusFlags)
{
_designData = designData;
ApplyCustomize = customizeFlags & CustomizeFlagExtensions.AllRelevant;
@ -254,9 +255,10 @@ public class DesignBase
ret[slot.ToString()] = Serialize(item.Id, stains, crest, DoApplyEquip(slot), DoApplyStain(slot), DoApplyCrest(crestSlot));
}
ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply");
ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyMeta(MetaIndex.VisorState)).ToJObject("IsToggled", "Apply");
ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyMeta(MetaIndex.WeaponState)).ToJObject("Show", "Apply");
ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply");
ret["VieraEars"] = new QuadBool(_designData.AreEarsVisible(), DoApplyMeta(MetaIndex.EarState)).ToJObject("Show", "Apply");
ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyMeta(MetaIndex.VisorState)).ToJObject("IsToggled", "Apply");
ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyMeta(MetaIndex.WeaponState)).ToJObject("Show", "Apply");
}
else
{
@ -603,6 +605,10 @@ public class DesignBase
metaValue = QuadBool.FromJObject(equip["Visor"], "IsToggled", "Apply", QuadBool.NullFalse);
design.SetApplyMeta(MetaIndex.VisorState, metaValue.Enabled);
design._designData.SetVisor(metaValue.ForcedValue);
metaValue = QuadBool.FromJObject(equip["VieraEars"], "Show", "Apply", QuadBool.NullTrue);
design.SetApplyMeta(MetaIndex.EarState, metaValue.Enabled);
design._designData.SetEarsVisible(metaValue.ForcedValue);
return;
void PrintWarning(string msg)

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.ImGuiNotification;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Gui;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;

View file

@ -287,6 +287,7 @@ public unsafe struct DesignData
MetaIndex.HatState => IsHatVisible(),
MetaIndex.VisorState => IsVisorToggled(),
MetaIndex.WeaponState => IsWeaponVisible(),
MetaIndex.EarState => AreEarsVisible(),
_ => false,
};
@ -297,6 +298,7 @@ public unsafe struct DesignData
MetaIndex.HatState => SetHatVisible(value),
MetaIndex.VisorState => SetVisor(value),
MetaIndex.WeaponState => SetWeaponVisible(value),
MetaIndex.EarState => SetEarsVisible(value),
_ => false,
};
@ -340,6 +342,9 @@ public unsafe struct DesignData
public readonly bool IsWeaponVisible()
=> (_states & 0x08) == 0x08;
public readonly bool AreEarsVisible()
=> (_states & 0x10) == 0x00;
public bool SetWeaponVisible(bool value)
{
if (value == IsWeaponVisible())
@ -349,6 +354,15 @@ public unsafe struct DesignData
return true;
}
public bool SetEarsVisible(bool value)
{
if (value == AreEarsVisible())
return false;
_states = (byte)(value ? _states & ~0x10 : _states | 0x10);
return true;
}
public void SetDefaultEquipment(ItemManager items)
{
foreach (var slot in EquipSlotExtensions.EqdpSlots)
@ -386,6 +400,7 @@ public unsafe struct DesignData
SetHatVisible(true);
SetWeaponVisible(true);
SetEarsVisible(true);
SetVisor(false);
fixed (uint* ptr = _itemIds)
{

View file

@ -41,11 +41,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
public struct CreationDate : ISortMode<Design>
{
public string Name
=> "Creation Date (Older First)";
public ReadOnlySpan<byte> Name
=> "Creation Date (Older First)"u8;
public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date.";
public ReadOnlySpan<byte> Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date."u8;
public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.CreationDate));
@ -53,11 +53,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
public struct UpdateDate : ISortMode<Design>
{
public string Name
=> "Update Date (Older First)";
public ReadOnlySpan<byte> Name
=> "Update Date (Older First)"u8;
public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date.";
public ReadOnlySpan<byte> Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date."u8;
public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.LastEdit));
@ -65,11 +65,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
public struct InverseCreationDate : ISortMode<Design>
{
public string Name
=> "Creation Date (Newer First)";
public ReadOnlySpan<byte> Name
=> "Creation Date (Newer First)"u8;
public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date.";
public ReadOnlySpan<byte> Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date."u8;
public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.CreationDate));
@ -77,11 +77,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
public struct InverseUpdateDate : ISortMode<Design>
{
public string Name
=> "Update Date (Newer First)";
public ReadOnlySpan<byte> Name
=> "Update Date (Newer First)"u8;
public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date.";
public ReadOnlySpan<byte> Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date."u8;
public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.LastEdit));

View file

@ -6,12 +6,13 @@ using Glamourer.GameData;
using Glamourer.Interop.Material;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using OtterGui.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Extensions;
using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums;
namespace Glamourer.Designs;
public sealed class DesignManager : DesignEditor
@ -110,6 +111,7 @@ public sealed class DesignManager : DesignEditor
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
};
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
Designs.Add(design);
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
SaveService.ImmediateSave(design);
@ -134,6 +136,7 @@ public sealed class DesignManager : DesignEditor
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
};
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
Designs.Add(design);
Glamourer.Log.Debug($"Added new design {design.Identifier} by cloning Temporary Design.");
SaveService.ImmediateSave(design);
@ -153,6 +156,7 @@ public sealed class DesignManager : DesignEditor
Name = actualName,
Index = Designs.Count,
};
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
Designs.Add(design);
Glamourer.Log.Debug(
$"Added new design {design.Identifier} by cloning {clone.Identifier.ToString()}.");
@ -225,7 +229,7 @@ public sealed class DesignManager : DesignEditor
design.Tags = design.Tags.Append(tag).OrderBy(t => t).ToArray();
design.LastEdit = DateTimeOffset.UtcNow;
var idx = design.Tags.IndexOf(tag);
var idx = design.Tags.AsEnumerable().IndexOf(tag);
SaveService.QueueSave(design);
Glamourer.Log.Debug($"Added tag {tag} at {idx} to design {design.Identifier}.");
DesignChanged.Invoke(DesignChanged.Type.AddedTag, design, new TagAddedTransaction(tag, idx));
@ -258,7 +262,7 @@ public sealed class DesignManager : DesignEditor
SaveService.QueueSave(design);
Glamourer.Log.Debug($"Renamed tag {oldTag} at {tagIdx} to {newTag} in design {design.Identifier} and reordered tags.");
DesignChanged.Invoke(DesignChanged.Type.ChangedTag, design,
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.IndexOf(newTag)));
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.AsEnumerable().IndexOf(newTag)));
}
/// <summary> Add an associated mod to a design. </summary>
@ -553,7 +557,7 @@ public sealed class DesignManager : DesignEditor
try
{
File.Move(SaveService.FileNames.MigrationDesignFile,
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"));
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"), true);
Glamourer.Log.Information($"Moved migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file.");
}
catch (Exception ex)

View file

@ -10,14 +10,15 @@ public enum MetaIndex
VisorState = StateIndex.MetaVisorState,
WeaponState = StateIndex.MetaWeaponState,
ModelId = StateIndex.MetaModelId,
EarState = StateIndex.MetaEarState,
}
public static class MetaExtensions
{
public static readonly IReadOnlyList<MetaIndex> AllRelevant =
[MetaIndex.Wetness, MetaIndex.HatState, MetaIndex.VisorState, MetaIndex.WeaponState];
[MetaIndex.Wetness, MetaIndex.HatState, MetaIndex.VisorState, MetaIndex.WeaponState, MetaIndex.EarState];
public const MetaFlag All = MetaFlag.Wetness | MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState;
public const MetaFlag All = MetaFlag.Wetness | MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState;
public static MetaFlag ToFlag(this MetaIndex index)
=> index switch
@ -26,6 +27,7 @@ public static class MetaExtensions
MetaIndex.HatState => MetaFlag.HatState,
MetaIndex.VisorState => MetaFlag.VisorState,
MetaIndex.WeaponState => MetaFlag.WeaponState,
MetaIndex.EarState => MetaFlag.EarState,
_ => (MetaFlag)byte.MaxValue,
};
@ -36,7 +38,8 @@ public static class MetaExtensions
MetaFlag.HatState => MetaIndex.HatState,
MetaFlag.VisorState => MetaIndex.VisorState,
MetaFlag.WeaponState => MetaIndex.WeaponState,
_ => (MetaIndex)byte.MaxValue,
MetaFlag.EarState => MetaIndex.EarState,
_ => (MetaIndex)byte.MaxValue,
};
public static IEnumerable<MetaIndex> ToIndices(this MetaFlag index)
@ -49,6 +52,8 @@ public static class MetaExtensions
yield return MetaIndex.VisorState;
if (index.HasFlag(MetaFlag.WeaponState))
yield return MetaIndex.WeaponState;
if (index.HasFlag(MetaFlag.EarState))
yield return MetaIndex.EarState;
}
public static string ToName(this MetaIndex index)
@ -58,6 +63,7 @@ public static class MetaExtensions
MetaIndex.VisorState => "Visor Toggled",
MetaIndex.WeaponState => "Weapon Visible",
MetaIndex.Wetness => "Force Wetness",
MetaIndex.EarState => "Ears Visible",
_ => "Unknown Meta",
};
@ -68,6 +74,7 @@ public static class MetaExtensions
MetaIndex.VisorState => "Toggle the visor state of the characters head gear.",
MetaIndex.WeaponState => "Hide or show the characters weapons when not drawn.",
MetaIndex.Wetness => "Force the character to be wet or not.",
MetaIndex.EarState => "Hide or show the characters ears through the head gear. (Viera only)",
_ => string.Empty,
};
}

View file

@ -15,5 +15,8 @@ public sealed class PenumbraReloaded()
/// <seealso cref="Interop.VisorService.Restore"/>
VisorService = 0,
/// <seealso cref="Interop.VieraEarService.Restore"/>
VieraEarService = 0,
}
}

View file

@ -0,0 +1,22 @@
using OtterGui.Classes;
using Penumbra.GameData.Interop;
namespace Glamourer.Events;
/// <summary>
/// Triggered when the state of viera ear visibility for any draw object is changed.
/// <list type="number">
/// <item>Parameter is the model with a changed viera ear visibility state. </item>
/// <item>Parameter is the new state. </item>
/// <item>Parameter is whether to call the original function. </item>
/// </list>
/// </summary>
public sealed class VieraEarStateChanged()
: EventWrapperRef2<Actor, bool, VieraEarStateChanged.Priority>(nameof(VieraEarStateChanged))
{
public enum Priority
{
/// <seealso cref="State.StateListener.OnVieraEarChange"/>
StateListener = 0,
}
}

View file

@ -19,4 +19,4 @@ public sealed class VisorStateChanged()
/// <seealso cref="State.StateListener.OnVisorChange"/>
StateListener = 0,
}
}
}

View file

@ -71,6 +71,7 @@ public class Glamourer : IDalamudPlugin
sb.Append($"> **`Festival Easter-Eggs: `** {config.DisableFestivals}\n");
sb.Append($"> **`Apply Entire Weapon: `** {config.ChangeEntireItem}\n");
sb.Append($"> **`Apply Associated Mods:`** {config.AlwaysApplyAssociatedMods}\n");
sb.Append($"> **`Attach to PCP: `** {config.AttachToPcp}\n");
sb.Append($"> **`Hidden Panels: `** {config.HideDesignPanel}\n");
sb.Append($"> **`Show QDB: `** {config.Ephemeral.ShowDesignQuickBar}\n");
sb.Append($"> **`QDB Hotkey: `** {config.ToggleQuickDesignBar}\n");

View file

@ -1,4 +1,4 @@
<Project Sdk="Dalamud.NET.Sdk/12.0.2">
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
<PropertyGroup>
<RootNamespace>Glamourer</RootNamespace>
<AssemblyName>Glamourer</AssemblyName>

View file

@ -8,7 +8,7 @@
"AssemblyVersion": "9.0.0.1",
"RepoUrl": "https://github.com/Ottermandias/Glamourer",
"ApplicableVersion": "any",
"DalamudApiLevel": 12,
"DalamudApiLevel": 13,
"ImageUrls": null,
"IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/master/images/icon.png"
}

View file

@ -1,4 +1,4 @@
using ImGuiNET;
using Dalamud.Bindings.ImGui;
namespace Glamourer.Gui;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Glamourer.GameData;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;

View file

@ -1,5 +1,5 @@
using Dalamud.Interface;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface.Textures.TextureWraps;
using Glamourer.GameData;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii;
@ -35,7 +35,7 @@ public partial class CustomizationDrawer
var hasIcon = icon.TryGetWrap(out var wrap, out _);
using (_ = ImRaii.Disabled(_locked || _currentIndex is CustomizeIndex.Face && _lockedRedraw))
{
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize))
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize))
{
ImGui.OpenPopup(IconSelectorPopup);
}
@ -89,7 +89,7 @@ public partial class CustomizationDrawer
: ImRaii.PushColor(ImGuiCol.Button, ColorId.FavoriteStarOn.Value(), isFavorite);
var hasIcon = icon.TryGetWrap(out var wrap, out var _);
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize))
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize))
{
UpdateValue(custom.Value);
ImGui.CloseCurrentPopup();
@ -215,7 +215,7 @@ public partial class CustomizationDrawer
hasIcon = icon.TryGetWrap(out wrap, out _);
}
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize, Vector2.Zero, Vector2.One,
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize, Vector2.Zero, Vector2.One,
(int)ImGui.GetStyle().FramePadding.X, Vector4.Zero, enabled ? Vector4.One : _redTint))
{
_customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max);

View file

@ -1,4 +1,4 @@
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGuiInternal;

View file

@ -4,7 +4,7 @@ using Dalamud.Plugin.Services;
using Glamourer.GameData;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;

View file

@ -3,7 +3,7 @@ using Glamourer.Designs;
using Glamourer.GameData;
using Glamourer.Interop.PalettePlus;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
@ -287,13 +287,13 @@ public class CustomizeParameterDrawer(Configuration config, PaletteImport import
}
private ImGuiColorEditFlags GetFlags()
=> Format | Display | ImGuiColorEditFlags.HDR | ImGuiColorEditFlags.NoOptions;
=> Format | Display | ImGuiColorEditFlags.Hdr | ImGuiColorEditFlags.NoOptions;
private ImGuiColorEditFlags Format
=> config.UseFloatForColors ? ImGuiColorEditFlags.Float : ImGuiColorEditFlags.Uint8;
private ImGuiColorEditFlags Display
=> config.UseRgbForColors ? ImGuiColorEditFlags.DisplayRGB : ImGuiColorEditFlags.DisplayHSV;
=> config.UseRgbForColors ? ImGuiColorEditFlags.DisplayRgb : ImGuiColorEditFlags.DisplayHsv;
private ImRaii.IEndObject EnsureSize()
{

View file

@ -5,7 +5,7 @@ using Glamourer.Designs;
using Glamourer.Designs.History;
using Glamourer.Designs.Special;
using Glamourer.Events;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Extensions;
@ -123,6 +123,14 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
return filter.IsContained(path) || filter.IsContained(design.ResolveName(false));
}
protected override void OnMouseWheel(string preview, ref int _2, int steps)
{
if (!ReferenceEquals(_currentDesign, CurrentSelection?.Item1))
CurrentSelectionIdx = -1;
base.OnMouseWheel(preview, ref _2, steps);
}
private void UpdateCurrentSelection()
{
if (!_isCurrentSelectionDirty)
@ -186,7 +194,7 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
ImGui.TextUnformatted("Currently resolving to ");
using var color = ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(linkedDesign));
ImGui.SameLine(0, 0);
ImGui.TextUnformatted(linkedDesign.Name);
ImGui.TextUnformatted(linkedDesign.Name.Text);
}
else
{

View file

@ -8,7 +8,7 @@ using Glamourer.Automation;
using Glamourer.Designs;
using Glamourer.Interop.Penumbra;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Classes;
using OtterGui.Text;
using Penumbra.GameData.Actors;
@ -64,6 +64,7 @@ public sealed class DesignQuickBar : Window, IDisposable
IsOpen = _config.Ephemeral.ShowDesignQuickBar;
DisableWindowSounds = true;
Size = Vector2.Zero;
RespectCloseHotkey = false;
}
public void Dispose()

View file

@ -1,7 +1,7 @@
using Dalamud.Plugin.Services;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Lumina.Excel.Sheets;
using OtterGui;
using OtterGui.Classes;

View file

@ -5,7 +5,7 @@ using Glamourer.Events;
using Glamourer.Gui.Materials;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Extensions;
using OtterGui.Raii;
using OtterGui.Text;
@ -529,11 +529,11 @@ public class EquipmentDrawer
public unsafe void DrawDragDropTooltip()
{
var payload = ImGui.GetDragDropPayload().NativePtr;
var payload = ImGui.GetDragDropPayload().Handle;
if (payload is null)
return;
if (!MemoryMarshal.CreateReadOnlySpanFromNullTerminated(payload->DataType).SequenceEqual("equipDragDrop"u8))
if (!MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)Unsafe.AsPointer(ref payload->DataType_0)).SequenceEqual("equipDragDrop"u8))
return;
using var tt = ImUtf8.Tooltip();

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Widgets;
using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Structs;

View file

@ -1,7 +1,7 @@
using Dalamud.Plugin.Services;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Lumina.Excel.Sheets;
using OtterGui.Classes;
using OtterGui.Extensions;

View file

@ -1,5 +1,5 @@
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Services;
using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums;

View file

@ -1,6 +1,6 @@
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Log;

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Services;
using Glamourer.Gui.Materials;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;

View file

@ -43,6 +43,8 @@ public class GlamourerChangelog
Add1_3_7_0(Changelog);
Add1_3_8_0(Changelog);
Add1_4_0_0(Changelog);
Add1_5_0_0(Changelog);
Add1_5_1_0(Changelog);
}
private (int, ChangeLogDisplayType) ConfigData()
@ -63,6 +65,29 @@ public class GlamourerChangelog
}
}
private static void Add1_5_1_0(Changelog log)
=> log.NextVersion("Version 1.5.1.0")
.RegisterHighlight("Added support for Penumbras PCP functionality to add the current state of the character as a design.")
.RegisterEntry("On import, a design for the PCP is created and, if possible, applied to the character.", 1)
.RegisterEntry("No automation is assigned.", 1)
.RegisterEntry("Finer control about this can be found in the settings.", 1)
.RegisterEntry("Fixed an issue with static visors not toggling through Glamourer (1.5.0.7).")
.RegisterEntry("The advanced dye slot combo now contains glasses (1.5.0.7).")
.RegisterEntry("Several fixes for patch-related issues (1.5.0.1 - 1.5.0.6");
private static void Add1_5_0_0(Changelog log)
=> log.NextVersion("Version 1.5.0.0")
.RegisterImportant("Updated for game version 7.30 and Dalamud API13, which uses a new GUI backend. Some things may not work as expected. Please let me know any issues you encounter.")
.RegisterHighlight("Added the new Viera Ears state to designs. Old designs will not apply the state.")
.RegisterHighlight("Added the option to make newly created designs write-protected by default to the design defaults.")
.RegisterEntry("Fixed issues with reverting state and IPC.")
.RegisterEntry("Fixed an issue when using the mousewheel to scroll through designs (1.4.0.3).")
.RegisterEntry("Fixed an issue with invalid bonus items (1.4.0.3).")
.RegisterHighlight("Added drag & drop of equipment pieces which will try to match the corresponding model IDs in other slots if possible (1.4.0.2).")
.RegisterEntry("Heavily optimized some issues when having many designs and creating new ones or updating them (1.4.0.2)")
.RegisterEntry("Fixed an issue with staining templates (1.4.0.1).")
.RegisterEntry("Fixed an issue with the QDB buttons not counting correctly (1.4.0.1).");
private static void Add1_4_0_0(Changelog log)
=> log.NextVersion("Version 1.4.0.0")
.RegisterHighlight("The design selector width is now draggable within certain restrictions that depend on the total window width.")

View file

@ -12,7 +12,7 @@ using Glamourer.Gui.Tabs.NpcTab;
using Glamourer.Gui.Tabs.SettingsTab;
using Glamourer.Gui.Tabs.UnlocksTab;
using Glamourer.Interop.Penumbra;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Custom;

View file

@ -8,7 +8,7 @@ using FFXIVClientStructs.Interop;
using Glamourer.Designs;
using Glamourer.Interop.Material;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui.Services;
using OtterGui.Text;
@ -91,7 +91,7 @@ public sealed unsafe class AdvancedDyePopup(
var modelHandle = model == null ? null : model->ModelResourceHandle;
var path = materialHandle == null
? string.Empty
: ByteString.FromSpanUnsafe(materialHandle->ResourceHandle.FileName.AsSpan(), true).ToString();
: ByteString.FromSpanUnsafe(materialHandle->FileName.AsSpan(), true).ToString();
var gamePath = modelHandle == null
? string.Empty
: modelHandle->GetMaterialFileNameBySlot(index.MaterialIndex).ToString();

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Designs;
using Glamourer.Interop.Material;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Services;
using OtterGui.Text;
@ -18,7 +18,6 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
public const float GlossWidth = 100;
public const float SpecularStrengthWidth = 125;
private EquipSlot _newSlot = EquipSlot.Head;
private int _newMaterialIdx;
private int _newRowIdx;
private MaterialValueIndex _newKey = MaterialValueIndex.FromSlot(EquipSlot.Head);
@ -178,14 +177,42 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
public sealed class MaterialSlotCombo;
private void DrawSlotCombo()
{
var width = ImUtf8.CalcTextSize(EquipSlot.OffHand.ToName()).X + ImGui.GetFrameHeightWithSpacing();
ImGui.SetNextItemWidth(width);
using var combo = ImUtf8.Combo("##slot"u8, _newKey.SlotName());
if (combo)
{
var currentSlot = _newKey.ToEquipSlot();
foreach (var tmpSlot in EquipSlotExtensions.FullSlots)
{
if (ImUtf8.Selectable(tmpSlot.ToName(), tmpSlot == currentSlot) && currentSlot != tmpSlot)
_newKey = MaterialValueIndex.FromSlot(tmpSlot) with
{
MaterialIndex = (byte)_newMaterialIdx,
RowIndex = (byte)_newRowIdx,
};
}
var currentBonus = _newKey.ToBonusSlot();
foreach (var bonusSlot in BonusExtensions.AllFlags)
{
if (ImUtf8.Selectable(bonusSlot.ToName(), bonusSlot == currentBonus) && bonusSlot != currentBonus)
_newKey = MaterialValueIndex.FromSlot(bonusSlot) with
{
MaterialIndex = (byte)_newMaterialIdx,
RowIndex = (byte)_newRowIdx,
};
}
}
ImUtf8.HoverTooltip("Choose a slot for an advanced dye row."u8);
}
public void DrawNew(Design design)
{
if (EquipSlotCombo.Draw("##slot", "Choose a slot for an advanced dye row.", ref _newSlot))
_newKey = MaterialValueIndex.FromSlot(_newSlot) with
{
MaterialIndex = (byte)_newMaterialIdx,
RowIndex = (byte)_newRowIdx,
};
DrawSlotCombo();
ImUtf8.SameLineInner();
DrawMaterialIdxDrag();
ImUtf8.SameLineInner();

View file

@ -3,7 +3,7 @@ using Glamourer.Events;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using Penumbra.Api.Enums;
using Penumbra.GameData.Data;
@ -22,11 +22,12 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
private readonly CustomizeService _customize;
private readonly GPoseService _gpose;
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2];
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2 + BonusExtensions.AllFlags.Count];
public IEnumerable<KeyValuePair<EquipSlot, EquipItem>> LastItems
=> EquipSlotExtensions.EqdpSlots.Append(EquipSlot.MainHand).Append(EquipSlot.OffHand).Zip(_lastItems)
.Select(p => new KeyValuePair<EquipSlot, EquipItem>(p.First, p.Second));
public IEnumerable<KeyValuePair<object, EquipItem>> LastItems
=> EquipSlotExtensions.EqdpSlots.Cast<object>().Append(EquipSlot.MainHand).Append(EquipSlot.OffHand)
.Concat(BonusExtensions.AllFlags.Cast<object>()).Zip(_lastItems)
.Select(p => new KeyValuePair<object, EquipItem>(p.First, p.Second));
public ChangedItemType LastType { get; private set; } = ChangedItemType.None;
public uint LastId { get; private set; }
@ -72,6 +73,21 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
if (!Player())
return;
var bonusSlot = item.Type.ToBonus();
if (bonusSlot is not BonusItemFlag.Unknown)
{
// + 2 due to weapons.
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
using (_ = !openTooltip ? null : ImRaii.Tooltip())
{
ImGui.TextUnformatted($"{prefix}Right-Click to apply to current actor.");
if (glasses.Valid)
ImGui.TextUnformatted($"{prefix}Control + Right-Click to re-apply {glasses.Name} to current actor.");
}
return;
}
var slot = item.Type.ToSlot();
var last = _lastItems[slot.ToIndex()];
switch (slot)
@ -109,6 +125,27 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
public void ApplyItem(ActorState state, EquipItem item)
{
var bonusSlot = item.Type.ToBonus();
if (bonusSlot is not BonusItemFlag.Unknown)
{
// + 2 due to weapons.
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
if (ImGui.GetIO().KeyCtrl && glasses.Valid)
{
Glamourer.Log.Debug($"Re-Applying {glasses.Name} to {bonusSlot.ToName()}.");
SetLastItem(bonusSlot, default, state);
_stateManager.ChangeBonusItem(state, bonusSlot, glasses, ApplySettings.Manual);
}
else
{
Glamourer.Log.Debug($"Applying {item.Name} to {bonusSlot.ToName()}.");
SetLastItem(bonusSlot, item, state);
_stateManager.ChangeBonusItem(state, bonusSlot, item, ApplySettings.Manual);
}
return;
}
var slot = item.Type.ToSlot();
var last = _lastItems[slot.ToIndex()];
switch (slot)
@ -265,7 +302,22 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
{
var oldItem = state.ModelData.Item(slot);
if (oldItem.Id != item.Id)
_lastItems[slot.ToIndex()] = oldItem;
last = oldItem;
}
}
private void SetLastItem(BonusItemFlag slot, EquipItem item, ActorState state)
{
ref var last = ref _lastItems[slot.ToSlot() + 2];
if (!item.Valid)
{
last = default;
}
else
{
var oldItem = state.ModelData.BonusItem(slot);
if (oldItem.Id != item.Id)
last = oldItem;
}
}

View file

@ -11,7 +11,7 @@ using Glamourer.Gui.Equipment;
using Glamourer.Gui.Materials;
using Glamourer.Interop;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;
@ -305,6 +305,12 @@ public class ActorPanel
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.WeaponState, _stateManager, _state!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromState(CrestFlag.OffHand, _stateManager, _state!));
}
ImGui.SameLine();
using (_ = ImRaii.Group())
{
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.EarState, _stateManager, _state!));
}
}
private void DrawMonsterPanel()

View file

@ -1,5 +1,5 @@
using Dalamud.Interface;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;

View file

@ -1,5 +1,5 @@
using Dalamud.Interface.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Widgets;
namespace Glamourer.Gui.Tabs.ActorTab;

View file

@ -1,5 +1,5 @@
using Dalamud.Interface.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Widgets;
namespace Glamourer.Gui.Tabs.AutomationTab;

View file

@ -1,12 +1,12 @@
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Custom;
using OtterGui.Extensions;
using OtterGui.Log;
using OtterGui.Widgets;
using Penumbra.GameData.DataContainers;
using OtterGui.Custom;
namespace Glamourer.Gui.Tabs.AutomationTab;

View file

@ -1,5 +1,5 @@
using Dalamud.Game.ClientState.Objects.Enums;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Penumbra.GameData.Actors;
using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Gui;

View file

@ -4,7 +4,7 @@ using Glamourer.Automation;
using Glamourer.Designs;
using Glamourer.Designs.Special;
using Glamourer.Events;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;

View file

@ -6,7 +6,7 @@ using Glamourer.Designs.Special;
using Glamourer.Interop;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Log;
@ -432,7 +432,7 @@ public class SetPanel(
if (source)
{
ImUtf8.Text($"Moving design #{index + 1:D2}...");
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
{
_dragIndex = index;
_selector.DragDesignIndex = index;

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.Utility;
using Glamourer.Automation;
using Glamourer.Events;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Extensions;
@ -144,7 +144,7 @@ public class SetSelector : IDisposable
ImGui.SameLine();
var f = _enabledFilter;
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3))
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3u))
{
_enabledFilter = _enabledFilter switch
{
@ -347,7 +347,7 @@ public class SetSelector : IDisposable
if (source)
{
ImGui.TextUnformatted($"Moving design set {GetSetName(set, index)} from position {index + 1}...");
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
_dragIndex = index;
}
}

View file

@ -2,7 +2,7 @@
using Glamourer.GameData;
using Glamourer.Designs;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;
@ -87,6 +87,9 @@ public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _ob
PrintRow("Visor Toggled", state.BaseData.IsVisorToggled(), state.ModelData.IsVisorToggled(),
state.Sources[MetaIndex.VisorState]);
ImGui.TableNextRow();
PrintRow("Viera Ears Visible", state.BaseData.AreEarsVisible(), state.ModelData.AreEarsVisible(),
state.Sources[MetaIndex.EarState]);
ImGui.TableNextRow();
PrintRow("Weapon Visible", state.BaseData.IsWeaponVisible(), state.ModelData.IsWeaponVisible(),
state.Sources[MetaIndex.WeaponState]);
ImGui.TableNextRow();

View file

@ -1,5 +1,5 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Gui.Debug;

View file

@ -1,5 +1,5 @@
using Glamourer.Automation;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Glamourer.GameData;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;

View file

@ -1,5 +1,5 @@
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;

View file

@ -1,5 +1,5 @@
using Glamourer.Interop;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using Penumbra.GameData.Files;
using Penumbra.GameData.Gui.Debug;

View file

@ -1,4 +1,4 @@
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui.Services;
using OtterGui.Widgets;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Glamourer.Designs;
using Glamourer.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Raii;

View file

@ -1,6 +1,6 @@
using Dalamud.Interface;
using Glamourer.Designs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Filesystem;
@ -114,6 +114,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
ImGuiUtil.DrawTableColumn(index.ToName());
ImGuiUtil.DrawTableColumn(design.DesignData.GetMeta(index).ToString());
ImGuiUtil.DrawTableColumn(design.DoApplyMeta(index) ? "Apply" : "Keep");
ImGui.TableNextRow();
}
ImGuiUtil.DrawTableColumn("Model ID");

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Glamourer.Designs;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii;

View file

@ -1,5 +1,5 @@
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Penumbra.GameData.Gui.Debug;
namespace Glamourer.Gui.Tabs.DebugTab;

View file

@ -5,7 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
using Glamourer.Designs;
using Glamourer.Services;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Text;

View file

@ -1,5 +1,5 @@
using FFXIVClientStructs.FFXIV.Client.Game;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Gui.Debug;

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using Glamourer.Api.Enums;
using Glamourer.Api.IpcSubscribers;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;

View file

@ -1,6 +1,6 @@
using Glamourer.Api.Enums;
using Glamourer.Designs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using static Penumbra.GameData.Files.ShpkFile;

View file

@ -1,7 +1,7 @@
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using Glamourer.Api.IpcSubscribers;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Penumbra.GameData.Gui.Debug;
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;

View file

@ -1,7 +1,7 @@
using Dalamud.Plugin;
using Glamourer.Api.Enums;
using Glamourer.Api.IpcSubscribers;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;

View file

@ -5,7 +5,7 @@ using Glamourer.Api.Enums;
using Glamourer.Api.Helpers;
using Glamourer.Api.IpcSubscribers;
using Glamourer.Designs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface.Utility;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;

View file

@ -2,7 +2,7 @@
using Glamourer.GameData;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;
@ -17,6 +17,7 @@ namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class ModelEvaluationPanel(
ActorObjectManager _objectManager,
VisorService _visorService,
VieraEarService _vieraEarService,
UpdateSlotService _updateSlotService,
ChangeCustomizeService _changeCustomizeService,
CrestService _crestService,
@ -84,6 +85,7 @@ public unsafe class ModelEvaluationPanel(
ImGuiUtil.CopyOnClickSelectable(offhand.ToString());
DrawVisor(actor, model);
DrawVieraEars(actor, model);
DrawHatState(actor, model);
DrawWeaponState(actor, model);
DrawWetness(actor, model);
@ -135,6 +137,26 @@ public unsafe class ModelEvaluationPanel(
_visorService.SetVisorState(model, !VisorService.GetVisorState(model));
}
private void DrawVieraEars(Actor actor, Model model)
{
using var id = ImRaii.PushId("Viera Ears");
ImGuiUtil.DrawTableColumn("Viera Ears");
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.ShowVieraEars.ToString() : "No Character");
ImGuiUtil.DrawTableColumn(model.IsHuman ? model.VieraEarsVisible.ToString() : "No Human");
ImGui.TableNextColumn();
if (!model.IsHuman)
return;
if (ImGui.SmallButton("Set True"))
_vieraEarService.SetVieraEarState(model, true);
ImGui.SameLine();
if (ImGui.SmallButton("Set False"))
_vieraEarService.SetVieraEarState(model, false);
ImGui.SameLine();
if (ImGui.SmallButton("Toggle"))
_vieraEarService.SetVieraEarState(model, !model.VieraEarsVisible);
}
private void DrawHatState(Actor actor, Model model)
{
using var id = ImRaii.PushId("HatState");

View file

@ -4,7 +4,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Glamourer.Designs;
using Glamourer.GameData;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums;

View file

@ -1,4 +1,4 @@
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Text;
using Penumbra.GameData.Actors;

View file

@ -1,6 +1,6 @@
using Dalamud.Interface.Utility;
using Glamourer.Interop.Penumbra;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.Api.Enums;
@ -49,7 +49,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
ImGui.TableNextColumn();
var address = _drawObject.Address;
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, (nint)(&address), nint.Zero, nint.Zero, "%llx",
if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, ref address, nint.Zero, nint.Zero, "%llx",
ImGuiInputTextFlags.CharsHexadecimal))
_drawObject = address;
ImGuiUtil.DrawTableColumn(_penumbra.Available
@ -89,7 +89,13 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
ImGui.Separator();
foreach (var (slot, item) in _penumbraTooltip.LastItems)
{
ImGuiUtil.DrawTableColumn($"{slot.ToName()} Revert-Item");
switch (slot)
{
case EquipSlot e: ImGuiUtil.DrawTableColumn($"{e.ToName()} Revert-Item"); break;
case BonusItemFlag f: ImGuiUtil.DrawTableColumn($"{f.ToName()} Revert-Item"); break;
default: ImGuiUtil.DrawTableColumn("Unk Revert-Item"); break;
}
ImGuiUtil.DrawTableColumn(item.Valid ? item.Name : "None");
ImGui.TableNextColumn();
}

View file

@ -1,7 +1,7 @@
using Dalamud.Interface.Utility;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;

View file

@ -1,5 +1,5 @@
using Glamourer.Designs;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Widgets;

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.ImGuiNotification;
using Glamourer.Designs;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;
@ -189,10 +189,7 @@ public class DesignDetailTab
else if (_selector.Selected!.Color.Length != 0)
{
ImGui.SameLine();
var size = new Vector2(ImGui.GetFrameHeight());
using var font = ImRaii.PushFont(UiBuilder.IconFont);
ImGuiUtil.DrawTextButton(FontAwesomeIcon.ExclamationCircle.ToIconString(), size, 0, _colors.MissingColor);
ImUtf8.HoverTooltip("The color associated with this design does not exist."u8);
ImUtf8.Icon(FontAwesomeIcon.ExclamationCircle, "The color associated with this design does not exist."u8, _colors.MissingColor);
}
ImUtf8.DrawFrameColumn("Creation Date"u8);

View file

@ -5,7 +5,7 @@ using Glamourer.Designs;
using Glamourer.Designs.History;
using Glamourer.Events;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Filesystem;
@ -175,7 +175,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);
using var _ = ImRaii.TreeNode(name, flag);
using var _ = ImUtf8.TreeNode(name, flag);
if (_config.AllowDoubleClickToApply && ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(ImGuiMouseButton.Left))
_designApplier.ApplyToPlayer(leaf.Value);
}

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
using Glamourer.Automation;
using Glamourer.Designs;
using Glamourer.Designs.Links;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
@ -195,7 +195,7 @@ public class DesignLinkDrawer(
{
if (source)
{
ImGui.SetDragDropPayload("DraggingLink", IntPtr.Zero, 0);
ImGui.SetDragDropPayload("DraggingLink", null, 0);
ImGui.TextUnformatted($"Reordering {design.Name}...");
_dragDropIndex = index;
_dragDropOrder = order;

View file

@ -12,7 +12,7 @@ using Glamourer.Gui.Equipment;
using Glamourer.Gui.Materials;
using Glamourer.Interop;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;
@ -154,6 +154,12 @@ public class DesignPanel
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.WeaponState, _manager, _selector.Selected!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.OffHand, _manager, _selector.Selected!));
}
ImGui.SameLine();
using (var _ = ImRaii.Group())
{
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.EarState, _manager, _selector.Selected!));
}
}
private void DrawCustomize()
@ -265,11 +271,9 @@ public class DesignPanel
DrawCrestApplication();
ImUtf8.IconDummy();
DrawMetaApplication();
ImUtf8.IconDummy();
DrawBonusSlotApplication();
}
ImGui.SameLine(ImGui.GetContentRegionAvail().X / 2);
ImGui.SameLine(210 * ImUtf8.GlobalScale + ImGui.GetStyle().ItemSpacing.X);
using (var _ = ImRaii.Group())
{
void ApplyEquip(string label, EquipFlag allFlags, bool stain, IEnumerable<EquipSlot> slots)
@ -311,6 +315,9 @@ public class DesignPanel
ImUtf8.IconDummy();
DrawParameterApplication();
ImUtf8.IconDummy();
DrawBonusSlotApplication();
}
}
@ -319,7 +326,7 @@ public class DesignPanel
var enabled = _config.DeleteDesignModifier.IsActive();
bool? equip = null;
bool? customize = null;
var size = new Vector2(200 * ImUtf8.GlobalScale, 0);
var size = new Vector2(210 * ImUtf8.GlobalScale, 0);
if (ImUtf8.ButtonEx("Disable Everything"u8,
"Disable application of everything, including any existing advanced dyes, advanced customizations, crests and wetness."u8, size,
!enabled))
@ -397,6 +404,7 @@ public class DesignPanel
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.HatState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.VisorState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.WeaponState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.EarState, equip.Value);
}
if (customize.HasValue)
@ -409,6 +417,7 @@ public class DesignPanel
"Apply Hat Visibility",
"Apply Visor State",
"Apply Weapon Visibility",
"Apply Viera Ear Visibility",
];
private void DrawMetaApplication()

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.Utility;
using Glamourer.Designs;
using Glamourer.Interop;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Classes;
using OtterGui.Widgets;

View file

@ -5,7 +5,7 @@ using Dalamud.Utility;
using Glamourer.Designs;
using Glamourer.Interop.Penumbra;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Extensions;
@ -71,6 +71,8 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
private void DrawApplyAllButton()
{
var (id, name) = penumbra.CurrentCollection;
if (config.Ephemeral.IncognitoMode)
name = id.ShortGuid();
if (ImGuiUtil.DrawDisabledButton($"Try Applying All Associated Mods to {name}##applyAll",
new Vector2(ImGui.GetContentRegionAvail().X, 0), string.Empty, id == Guid.Empty))
ApplyAll();

View file

@ -1,6 +1,6 @@
using Dalamud.Interface.Utility;
using Glamourer.Interop.Penumbra;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Classes;
using OtterGui.Log;
using OtterGui.Raii;

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.Utility;
using Glamourer.Designs;
using Glamourer.Interop.Material;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Extensions;
using OtterGui.Raii;
using OtterGui.Text;
@ -490,7 +490,7 @@ public class MultiDesignPanel(
foreach (var leaf in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
{
var index = leaf.Value.Tags.IndexOf(_tag);
var index = leaf.Value.Tags.AsEnumerable().IndexOf(_tag);
if (index >= 0)
_removeDesigns.Add((leaf.Value, index));
else

View file

@ -1,6 +1,6 @@
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;

View file

@ -2,7 +2,7 @@
using Glamourer.Designs;
using Glamourer.GameData;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

View file

@ -6,7 +6,7 @@ using Glamourer.Gui.Customization;
using Glamourer.Gui.Equipment;
using Glamourer.Gui.Tabs.DesignTab;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;

View file

@ -1,5 +1,5 @@
using Glamourer.GameData;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii;

View file

@ -1,5 +1,5 @@
using Dalamud.Interface.Utility;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Widgets;
namespace Glamourer.Gui.Tabs.NpcTab;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Glamourer.Services;
using Glamourer.State;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Filesystem;
using OtterGui.Raii;
using OtterGui.Services;

View file

@ -1,6 +1,6 @@
using Dalamud.Interface;
using Glamourer.Interop.Penumbra;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Log;
using OtterGui.Raii;

View file

@ -1,7 +1,7 @@
using Dalamud.Interface;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
@ -123,7 +123,7 @@ public class CollectionOverrideDrawer(
{
if (source)
{
ImGui.SetDragDropPayload("DraggingOverride", nint.Zero, 0);
ImGui.SetDragDropPayload("DraggingOverride", null, 0);
ImGui.TextUnformatted($"Reordering Override #{idx + 1}...");
_dragDropIndex = idx;
}

View file

@ -1,4 +1,5 @@
using Dalamud.Game.ClientState.Keys;
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility;
@ -8,7 +9,8 @@ using Glamourer.Designs;
using Glamourer.Gui.Tabs.DesignTab;
using Glamourer.Interop;
using Glamourer.Interop.PalettePlus;
using ImGuiNET;
using Glamourer.Services;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;
using OtterGui.Widgets;
@ -27,7 +29,8 @@ public class SettingsTab(
CollectionOverrideDrawer overrides,
CodeDrawer codeDrawer,
Glamourer glamourer,
AutoDesignApplier autoDesignApplier)
AutoDesignApplier autoDesignApplier,
PcpService pcpService)
: ITab
{
private readonly VirtualKey[] _validKeys = keys.GetValidVirtualKeys().Prepend(VirtualKey.NO_KEY).ToArray();
@ -89,6 +92,15 @@ public class SettingsTab(
Checkbox("Auto-Reload Gear"u8,
"Automatically reload equipment pieces on your own character when changing any mod options in Penumbra in their associated collection."u8,
config.AutoRedrawEquipOnChanges, v => config.AutoRedrawEquipOnChanges = v);
Checkbox("Attach to PCP-Handling"u8,
"Add the actor's glamourer state when a PCP is created by Penumbra, and create a design and apply it if possible when a PCP is installed by Penumbra."u8,
config.AttachToPcp, pcpService.Set);
var active = config.DeleteDesignModifier.IsActive();
ImGui.SameLine();
if (ImUtf8.ButtonEx("Delete all PCP Designs"u8, "Deletes all designs tagged with 'PCP' from the design list."u8, disabled: !active))
pcpService.CleanPcpDesigns();
if (!active)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"\nHold {config.DeleteDesignModifier} while clicking.");
Checkbox("Revert Manual Changes on Zone Change"u8,
"Restores the old behaviour of reverting your character to its game or automation base whenever you change the zone."u8,
config.RevertManualChangesOnZoneChange, v => config.RevertManualChangesOnZoneChange = v);
@ -113,6 +125,8 @@ public class SettingsTab(
if (!ImUtf8.CollapsingHeader("Design Defaults"))
return;
Checkbox("Locked Designs"u8, "Newly created designs will be locked to prevent unintended changes."u8,
config.DefaultDesignSettings.Locked, v => config.DefaultDesignSettings.Locked = v);
Checkbox("Show in Quick Design Bar"u8, "Newly created designs will be shown in the quick design bar by default."u8,
config.DefaultDesignSettings.ShowQuickDesignBar, v => config.DefaultDesignSettings.ShowQuickDesignBar = v);
Checkbox("Reset Advanced Dyes"u8, "Newly created designs will be configured to reset advanced dyes on application by default."u8,
@ -122,6 +136,28 @@ public class SettingsTab(
Checkbox("Reset Temporary Settings"u8,
"Newly created designs will be configured to clear all advanced settings applied by Glamourer to the collection by default."u8,
config.DefaultDesignSettings.ResetTemporarySettings, v => config.DefaultDesignSettings.ResetTemporarySettings = v);
var tmp = config.PcpFolder;
ImGui.SetNextItemWidth(0.4f * ImGui.GetContentRegionAvail().X);
if (ImUtf8.InputText("##pcpFolder"u8, ref tmp))
config.PcpFolder = tmp;
if (ImGui.IsItemDeactivatedAfterEdit())
config.Save();
ImGuiUtil.LabeledHelpMarker("Default PCP Organizational Folder",
"The folder any designs created due to penumbra character packs are moved to on creation.\nLeave blank to import into Root.");
tmp = config.PcpColor;
ImGui.SetNextItemWidth(0.4f * ImGui.GetContentRegionAvail().X);
if (ImUtf8.InputText("##pcpColor"u8, ref tmp))
config.PcpColor = tmp;
if (ImGui.IsItemDeactivatedAfterEdit())
config.Save();
ImGuiUtil.LabeledHelpMarker("Default PCP Design Color",
"The name of the color group any designs created due to penumbra character packs are assigned.\nLeave blank for no specific color assignment.");
}
private void DrawInterfaceSettings()

View file

@ -5,7 +5,7 @@ using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums;
@ -123,7 +123,7 @@ public class UnlockOverview(
var unlocked = customizeUnlocks.IsUnlocked(customize, out var time);
var icon = customizations.Manager.GetIcon(customize.IconId);
var hasIcon = icon.TryGetWrap(out var wrap, out _);
ImGui.Image(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, iconSize, Vector2.Zero, Vector2.One,
ImGui.Image(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, iconSize, Vector2.Zero, Vector2.One,
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
if (favorites.Contains(_selected3, _selected2, customize.Index, customize.Value))
@ -135,7 +135,7 @@ public class UnlockOverview(
using var tt = ImRaii.Tooltip();
var size = new Vector2(wrap!.Width, wrap.Height);
if (size.X >= iconSize.X && size.Y >= iconSize.Y)
ImGui.Image(wrap.ImGuiHandle, size);
ImGui.Image(wrap.Handle, size);
ImGui.TextUnformatted(unlockData.Name);
ImGui.TextUnformatted($"{customize.Index.ToDefaultName()} {customize.Value.Value}");
ImGui.TextUnformatted(unlocked ? $"Unlocked on {time:g}" : "Not unlocked.");
@ -194,7 +194,7 @@ public class UnlockOverview(
if (!textures.TryLoadIcon(item.IconId.Id, out var iconHandle))
return;
var (icon, size) = (iconHandle.ImGuiHandle, new Vector2(iconHandle.Width, iconHandle.Height));
var (icon, size) = (iconHandle.Handle, new Vector2(iconHandle.Width, iconHandle.Height));
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One,
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
@ -265,7 +265,7 @@ public class UnlockOverview(
if (!textures.TryLoadIcon(item.IconId.Id, out var iconHandle))
return;
var (icon, size) = (iconHandle.ImGuiHandle, new Vector2(iconHandle.Width, iconHandle.Height));
var (icon, size) = (iconHandle.Handle, new Vector2(iconHandle.Width, iconHandle.Height));
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One,
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);

View file

@ -6,7 +6,7 @@ using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Table;

View file

@ -1,6 +1,6 @@
using Dalamud.Interface;
using Dalamud.Interface.Windowing;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using OtterGui.Raii;
using OtterGui;
using OtterGui.Widgets;

View file

@ -2,7 +2,7 @@ using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using Dalamud.Bindings.ImGui;
using Lumina.Misc;
using OtterGui;
using OtterGui.Raii;

Some files were not shown because too many files have changed in this diff Show more