mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Compare commits
105 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b6517aae8 | ||
|
|
aadcf771e7 | ||
|
|
bf4673a1d9 | ||
|
|
76b214c643 | ||
|
|
434a5a809e | ||
|
|
88fe25f69e | ||
|
|
bef1e39ac3 | ||
|
|
c604d5dbe5 | ||
|
|
a0d912a395 | ||
|
|
a56852f918 | ||
|
|
4228fc1b89 | ||
|
|
e644b8da28 | ||
|
|
ace3a8f755 | ||
|
|
76ed347cbf | ||
|
|
c3469a1687 | ||
|
|
0a9693daea | ||
|
|
414bd8bee7 | ||
|
|
8e1745d67a | ||
|
|
889f01a724 | ||
|
|
6e62905fa7 | ||
|
|
654787fa0d | ||
|
|
835ba23935 | ||
|
|
389a8781d6 | ||
|
|
3eabe591df | ||
|
|
487d3b9399 | ||
|
|
4d4e4669dd | ||
|
|
fb065549e9 | ||
|
|
2c34154915 | ||
|
|
3704051b0f | ||
|
|
b2b8f2b6eb | ||
|
|
22e6c0655b | ||
|
|
bb2ba0cf11 | ||
|
|
e854386b23 | ||
|
|
49d24df2e7 | ||
|
|
c9b291c2f3 | ||
|
|
65f789880d | ||
|
|
abf998a727 | ||
|
|
4cc191cb25 | ||
|
|
dc431c10a5 | ||
|
|
26862ba78f | ||
|
|
e4374337f2 | ||
|
|
240c889fff | ||
|
|
612cd31c3e | ||
|
|
304b362002 | ||
|
|
8f34f197d0 | ||
|
|
1c97266a93 | ||
|
|
a9caddafd5 | ||
|
|
34bf95dddb | ||
|
|
4761b8f584 | ||
|
|
0d94aae732 | ||
|
|
e83f328cdc | ||
|
|
52fd29c478 | ||
|
|
a8b79993df | ||
|
|
98574558e5 | ||
|
|
557cbf23ce | ||
|
|
56753ae7ba | ||
|
|
b66df624f7 | ||
|
|
be78f1447b | ||
|
|
97e32a3cb7 | ||
|
|
4472920536 | ||
|
|
ac6a726f57 | ||
|
|
00d550f4fe | ||
|
|
0f98fac157 | ||
|
|
c25f0f72db | ||
|
|
72e05e23bc | ||
|
|
2c3bed6ba5 | ||
|
|
d6df9885dc | ||
|
|
e7936500e0 | ||
|
|
4ef4e65d46 | ||
|
|
40b4a8fd7a | ||
|
|
8a1f03c272 | ||
|
|
8ed479eddf | ||
|
|
c0a278ca2c | ||
|
|
2e9a7004c6 | ||
|
|
75c76a92b9 | ||
|
|
282935c6d6 | ||
|
|
d7b189b714 | ||
|
|
e3da3f356c | ||
|
|
66bed4217f | ||
|
|
56bbf6593a | ||
|
|
b8e1e7c384 | ||
|
|
a0d2c39f45 | ||
|
|
07df3186c2 | ||
|
|
5b59e74417 | ||
|
|
b4485f028d | ||
|
|
74674cfa0c | ||
|
|
f192c17c9b | ||
|
|
aa1ac29182 | ||
|
|
081ac6bf8b | ||
|
|
e4b32343ae | ||
|
|
c93370ec92 | ||
|
|
9abd7f2767 | ||
|
|
8a9877bb01 | ||
|
|
c1e1476fa6 | ||
|
|
b1abbb8e77 | ||
|
|
fcb0660def | ||
|
|
a6073e2a42 | ||
|
|
2c87077918 | ||
|
|
4e0a9f62b9 | ||
|
|
39636f5293 | ||
|
|
155a9d6266 | ||
|
|
5ca151b675 | ||
|
|
67fd65d366 | ||
|
|
45981f2fee | ||
|
|
cf308fc118 |
140 changed files with 1770 additions and 447 deletions
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -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 2158bd4bbcb6cefe3ce48e6d8b32e134cbee9a91
|
||||
Subproject commit 59a7ab5fa9941eb754757b62e4cb189e455e9514
|
||||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -2,19 +2,31 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.State;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Services;
|
||||
|
||||
namespace Glamourer.Api;
|
||||
|
||||
public class DesignsApi(ApiHelpers helpers, DesignManager designs, StateManager stateManager, DesignFileSystem fileSystem, DesignColors color)
|
||||
public class DesignsApi(
|
||||
ApiHelpers helpers,
|
||||
DesignManager designs,
|
||||
StateManager stateManager,
|
||||
DesignFileSystem fileSystem,
|
||||
DesignColors color,
|
||||
DesignConverter converter)
|
||||
: IGlamourerApiDesigns, IApiService
|
||||
{
|
||||
public Dictionary<Guid, string> GetDesignList()
|
||||
=> designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text);
|
||||
|
||||
public Dictionary<Guid, (string DisplayName, string FullPath, uint DisplayColor, bool ShownInQdb)> GetDesignListExtended()
|
||||
=> designs.Designs.ToDictionary(d => d.Identifier,
|
||||
d => (d.Name.Text, fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : d.Name.Text, color.GetColor(d), d.QuickDesign));
|
||||
=> fileSystem.ToDictionary(kvp => kvp.Key.Identifier,
|
||||
kvp => (kvp.Key.Name.Text, kvp.Value.FullName(), color.GetColor(kvp.Key), kvp.Key.QuickDesign));
|
||||
|
||||
public (string DisplayName, string FullPath, uint DisplayColor, bool ShowInQdb) GetExtendedDesignData(Guid designId)
|
||||
=> designs.Designs.ByIdentifier(designId) is { } d
|
||||
? (d.Name.Text, fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : d.Name.Text, color.GetColor(d), d.QuickDesign)
|
||||
: (string.Empty, string.Empty, 0, false);
|
||||
|
||||
public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags)
|
||||
{
|
||||
|
|
@ -71,4 +83,56 @@ public class DesignsApi(ApiHelpers helpers, DesignManager designs, StateManager
|
|||
|
||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public (GlamourerApiEc, Guid) AddDesign(string designInput, string name)
|
||||
{
|
||||
var args = ApiHelpers.Args("DesignData", designInput, "Name", name);
|
||||
|
||||
if (converter.FromBase64(designInput, true, true, out _) is not { } designBase)
|
||||
try
|
||||
{
|
||||
var jObj = JObject.Parse(designInput);
|
||||
designBase = converter.FromJObject(jObj, true, true);
|
||||
if (designBase is null)
|
||||
return (ApiHelpers.Return(GlamourerApiEc.CouldNotParse, args), Guid.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Failure parsing data for AddDesign due to\n{ex}");
|
||||
return (ApiHelpers.Return(GlamourerApiEc.CouldNotParse, args), Guid.Empty);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var design = designBase is Design d
|
||||
? designs.CreateClone(d, name, true)
|
||||
: designs.CreateClone(designBase, name, true);
|
||||
return (ApiHelpers.Return(GlamourerApiEc.Success, args), design.Identifier);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Unknown error creating design via IPC:\n{ex}");
|
||||
return (ApiHelpers.Return(GlamourerApiEc.UnknownError, args), Guid.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public GlamourerApiEc DeleteDesign(Guid designId)
|
||||
{
|
||||
var args = ApiHelpers.Args("DesignId", designId);
|
||||
if (designs.Designs.ByIdentifier(designId) is not { } design)
|
||||
return ApiHelpers.Return(GlamourerApiEc.NothingDone, args);
|
||||
|
||||
designs.Delete(design);
|
||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public string? GetDesignBase64(Guid designId)
|
||||
=> designs.Designs.ByIdentifier(designId) is { } design
|
||||
? converter.ShareBase64(design)
|
||||
: null;
|
||||
|
||||
public JObject? GetDesignJObject(Guid designId)
|
||||
=> designs.Designs.ByIdentifier(designId) is { } design
|
||||
? converter.ShareJObject(design)
|
||||
: null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = 5;
|
||||
public const int CurrentApiVersionMinor = 7;
|
||||
|
||||
public (int Major, int Minor) ApiVersion
|
||||
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,13 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
|
||||
IpcSubscribers.GetDesignList.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignListExtended.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetExtendedDesignData.Provider(pi, api.Designs),
|
||||
IpcSubscribers.ApplyDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.ApplyDesignName.Provider(pi, api.Designs),
|
||||
IpcSubscribers.AddDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.DeleteDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignBase64.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignJObject.Provider(pi, api.Designs),
|
||||
|
||||
IpcSubscribers.SetItem.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetItemName.Provider(pi, api.Items),
|
||||
|
|
@ -37,6 +42,8 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
(a, b, c, d, e, f) => (int)api.Items.SetItemName(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f)),
|
||||
IpcSubscribers.SetBonusItem.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetBonusItemName.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetMetaState.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetMetaStateName.Provider(pi, api.Items),
|
||||
IpcSubscribers.GetState.Provider(pi, api.State),
|
||||
IpcSubscribers.GetStateName.Provider(pi, api.State),
|
||||
IpcSubscribers.GetStateBase64.Provider(pi, api.State),
|
||||
|
|
@ -47,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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,33 +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 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;
|
||||
|
|
@ -80,7 +85,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New;
|
||||
|
||||
public QdbButtons QdbButtons { get; set; } =
|
||||
QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvanced;
|
||||
QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvancedDyes;
|
||||
|
||||
[JsonConverter(typeof(SortModeConverter))]
|
||||
[JsonProperty(Order = int.MaxValue)]
|
||||
|
|
@ -157,7 +162,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
|
||||
public static class Constants
|
||||
{
|
||||
public const int CurrentVersion = 7;
|
||||
public const int CurrentVersion = 8;
|
||||
|
||||
public static readonly ISortMode<Design>[] ValidSortModes =
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
@ -114,14 +114,14 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
return;
|
||||
case DesignChanged.Type.Deleted:
|
||||
if (FindLeaf(design, out var leaf1))
|
||||
if (TryGetValue(design, out var leaf1))
|
||||
Delete(leaf1);
|
||||
return;
|
||||
case DesignChanged.Type.ReloadedAll:
|
||||
Reload();
|
||||
return;
|
||||
case DesignChanged.Type.Renamed when (data as RenameTransaction?)?.Old is { } oldName:
|
||||
if (!FindLeaf(design, out var leaf2))
|
||||
if (!TryGetValue(design, out var leaf2))
|
||||
return;
|
||||
|
||||
var old = oldName.FixName();
|
||||
|
|
@ -150,15 +150,6 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
? (string.Empty, false)
|
||||
: (DesignToIdentifier(design), true);
|
||||
|
||||
// Search the entire filesystem for the leaf corresponding to a design.
|
||||
public bool FindLeaf(Design design, [NotNullWhen(true)] out Leaf? leaf)
|
||||
{
|
||||
leaf = Root.GetAllDescendants(ISortMode<Design>.Lexicographical)
|
||||
.OfType<Leaf>()
|
||||
.FirstOrDefault(l => l.Value == design);
|
||||
return leaf != null;
|
||||
}
|
||||
|
||||
internal static void MigrateOldPaths(SaveService saveService, Dictionary<string, string> oldPaths)
|
||||
{
|
||||
if (oldPaths.Count == 0)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public class EditorHistory : IDisposable, IService
|
|||
{
|
||||
if (!_stateEntries.TryGetValue(state, out var list))
|
||||
{
|
||||
list = new Queue();
|
||||
list = [];
|
||||
_stateEntries.Add(state, list);
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ public class EditorHistory : IDisposable, IService
|
|||
{
|
||||
if (!_designEntries.TryGetValue(design, out var list))
|
||||
{
|
||||
list = new Queue();
|
||||
list = [];
|
||||
_designEntries.Add(design, list);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
using OtterGui.Services;
|
||||
using OtterGui;
|
||||
using OtterGui.Services;
|
||||
|
||||
namespace Glamourer.Designs.Special;
|
||||
|
||||
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem) : IService
|
||||
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration config) : IService
|
||||
{
|
||||
private readonly Random _rng = new();
|
||||
private readonly Random _rng = new();
|
||||
private readonly WeakReference<Design> _lastDesign = new(null!, false);
|
||||
|
||||
public Design? Design(IReadOnlyList<Design> localDesigns)
|
||||
{
|
||||
if (localDesigns.Count == 0)
|
||||
if (localDesigns.Count is 0)
|
||||
return null;
|
||||
|
||||
var idx = _rng.Next(0, localDesigns.Count);
|
||||
Glamourer.Log.Verbose($"[Random Design] Chose design {idx + 1} out of {localDesigns.Count}: {localDesigns[idx].Incognito}.");
|
||||
return localDesigns[idx];
|
||||
if (localDesigns.Count is 1)
|
||||
{
|
||||
_lastDesign.SetTarget(localDesigns[idx]);
|
||||
return localDesigns[idx];
|
||||
}
|
||||
|
||||
if (config.PreventRandomRepeats && _lastDesign.TryGetTarget(out var lastDesign))
|
||||
while (lastDesign == localDesigns[idx])
|
||||
idx = _rng.Next(0, localDesigns.Count);
|
||||
|
||||
var design = localDesigns[idx];
|
||||
Glamourer.Log.Verbose($"[Random Design] Chose design {idx + 1} out of {localDesigns.Count}: {design.Incognito}.");
|
||||
_lastDesign.SetTarget(design);
|
||||
return design;
|
||||
}
|
||||
|
||||
public Design? Design()
|
||||
|
|
@ -24,12 +38,12 @@ public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileS
|
|||
|
||||
public Design? Design(IReadOnlyList<IDesignPredicate> predicates)
|
||||
{
|
||||
if (predicates.Count == 0)
|
||||
return Design();
|
||||
if (predicates.Count == 1)
|
||||
return Design(predicates[0]);
|
||||
|
||||
return Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList());
|
||||
return predicates.Count switch
|
||||
{
|
||||
0 => Design(),
|
||||
1 => Design(predicates[0]),
|
||||
_ => Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList()),
|
||||
};
|
||||
}
|
||||
|
||||
public Design? Design(string restrictions)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public interface IDesignPredicate
|
|||
: designs;
|
||||
|
||||
private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d, DesignFileSystem fs)
|
||||
=> (d, d.Name.Lower, d.Identifier.ToString(), fs.FindLeaf(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty);
|
||||
=> (d, d.Name.Lower, d.Identifier.ToString(), fs.TryGetValue(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty);
|
||||
}
|
||||
|
||||
public static class RandomPredicate
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ public class EphemeralConfig : ISavable
|
|||
public Guid SelectedQuickDesign { get; set; } = Guid.Empty;
|
||||
public int LastSeenVersion { get; set; } = GlamourerChangelog.LastChangelogVersion;
|
||||
|
||||
public float CurrentDesignSelectorWidth { get; set; } = 200f;
|
||||
public float DesignSelectorMinimumScale { get; set; } = 0.1f;
|
||||
public float DesignSelectorMaximumScale { get; set; } = 0.5f;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
private readonly SaveService _saveService;
|
||||
|
|
|
|||
|
|
@ -15,5 +15,8 @@ public sealed class PenumbraReloaded()
|
|||
|
||||
/// <seealso cref="Interop.VisorService.Restore"/>
|
||||
VisorService = 0,
|
||||
|
||||
/// <seealso cref="Interop.VieraEarService.Restore"/>
|
||||
VieraEarService = 0,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
Glamourer/Events/VieraEarStateChanged.cs
Normal file
22
Glamourer/Events/VieraEarStateChanged.cs
Normal 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,
|
||||
}
|
||||
}
|
||||
|
|
@ -19,4 +19,4 @@ public sealed class VisorStateChanged()
|
|||
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
||||
StateListener = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ public class Glamourer : IDalamudPlugin
|
|||
|
||||
public static readonly Logger Log = new();
|
||||
public static MessageService Messager { get; private set; } = null!;
|
||||
public static DynamisIpc Dynamis { get; private set; } = null!;
|
||||
|
||||
private readonly ServiceManager _services;
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ public class Glamourer : IDalamudPlugin
|
|||
{
|
||||
_services = StaticServiceManager.CreateProvider(pluginInterface, Log, this);
|
||||
Messager = _services.GetService<MessageService>();
|
||||
Dynamis = _services.GetService<DynamisIpc>();
|
||||
_services.EnsureRequiredServices();
|
||||
|
||||
_services.GetService<VisorService>();
|
||||
|
|
@ -69,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");
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,83 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.GameData;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using System;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
private CustomizeValue _draggedColorValue;
|
||||
private CustomizeIndex _draggedColorType;
|
||||
|
||||
|
||||
private void DrawDragDropSource(CustomizeIndex index, CustomizeData custom)
|
||||
{
|
||||
using var dragDropSource = ImUtf8.DragDropSource();
|
||||
if (!dragDropSource)
|
||||
return;
|
||||
|
||||
if (!DragDropSource.SetPayload("##colorDragDrop"u8))
|
||||
_draggedColorValue = _customize[index];
|
||||
ImUtf8.Text(
|
||||
$"Dragging {(custom.Color == 0 ? $"{_currentOption} (NPC)" : _currentOption)} #{_draggedColorValue.Value}...");
|
||||
_draggedColorType = index;
|
||||
}
|
||||
|
||||
private void DrawDragDropTarget(CustomizeIndex index)
|
||||
{
|
||||
using var dragDropTarget = ImUtf8.DragDropTarget();
|
||||
if (!dragDropTarget.Success || !dragDropTarget.IsDropping("##colorDragDrop"u8))
|
||||
return;
|
||||
|
||||
var idx = _set.DataByValue(_draggedColorType, _draggedColorValue, out var draggedData, _customize.Face);
|
||||
var bestMatch = _draggedColorValue;
|
||||
if (draggedData.HasValue)
|
||||
{
|
||||
var draggedColor = draggedData.Value.Color;
|
||||
var targetData = _set.Data(index, idx);
|
||||
if (targetData.Color != draggedColor)
|
||||
{
|
||||
var bestDiff = Diff(targetData.Color, draggedColor);
|
||||
var count = _set.Count(index);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
targetData = _set.Data(index, i);
|
||||
if (targetData.Color == draggedColor)
|
||||
{
|
||||
UpdateValue(_draggedColorValue);
|
||||
return;
|
||||
}
|
||||
|
||||
var diff = Diff(targetData.Color, draggedColor);
|
||||
if (diff >= bestDiff)
|
||||
continue;
|
||||
|
||||
bestDiff = diff;
|
||||
bestMatch = (CustomizeValue)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateValue(bestMatch);
|
||||
return;
|
||||
|
||||
static uint Diff(uint color1, uint color2)
|
||||
{
|
||||
var r = (color1 & 0xFF) - (color2 & 0xFF);
|
||||
var g = ((color1 >> 8) & 0xFF) - ((color2 >> 8) & 0xFF);
|
||||
var b = ((color1 >> 16) & 0xFF) - ((color2 >> 16) & 0xFF);
|
||||
return 30 * r * r + 59 * g * g + 11 * b * b;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawColorPicker(CustomizeIndex index)
|
||||
{
|
||||
|
|
@ -21,7 +88,7 @@ public partial class CustomizationDrawer
|
|||
|
||||
using (_ = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale, current < 0))
|
||||
{
|
||||
if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.None, _framedIconSize))
|
||||
if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.NoDragDrop, _framedIconSize))
|
||||
{
|
||||
ImGui.OpenPopup(ColorPickerPopupName);
|
||||
}
|
||||
|
|
@ -30,6 +97,9 @@ public partial class CustomizationDrawer
|
|||
var data = _set.Data(_currentIndex, current, _customize.Face);
|
||||
UpdateValue(data.Value);
|
||||
}
|
||||
|
||||
DrawDragDropSource(index, custom);
|
||||
DrawDragDropTarget(index);
|
||||
}
|
||||
|
||||
var npc = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGuiInternal;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -22,6 +22,7 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
protected readonly TabSelected TabSelected;
|
||||
protected float InnerWidth;
|
||||
private IDesignStandIn? _currentDesign;
|
||||
private bool _isCurrentSelectionDirty;
|
||||
|
||||
protected DesignComboBase(Func<IReadOnlyList<Tuple<IDesignStandIn, string>>> generator, Logger log, DesignChanged designChanged,
|
||||
TabSelected tabSelected, EphemeralConfig config, DesignColors designColors)
|
||||
|
|
@ -84,17 +85,11 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
DrawRightAligned(quickDesign.ResolveName(false), "[Nothing]", DesignColors.MissingColor);
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(p => _currentDesign == p.Item1);
|
||||
UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null);
|
||||
return CurrentSelectionIdx;
|
||||
}
|
||||
|
||||
protected bool Draw(IDesignStandIn? currentDesign, string? label, float width)
|
||||
{
|
||||
_currentDesign = currentDesign;
|
||||
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
|
||||
UpdateCurrentSelection();
|
||||
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
|
||||
var name = label ?? "Select Design Here...";
|
||||
bool ret;
|
||||
using (_ = currentDesign != null ? ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(currentDesign as Design)) : null)
|
||||
|
|
@ -128,37 +123,60 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
return filter.IsContained(path) || filter.IsContained(design.ResolveName(false));
|
||||
}
|
||||
|
||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _ = null)
|
||||
protected override void OnMouseWheel(string preview, ref int _2, int steps)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DesignChanged.Type.Created:
|
||||
case DesignChanged.Type.Renamed:
|
||||
case DesignChanged.Type.ChangedColor:
|
||||
case DesignChanged.Type.Deleted:
|
||||
case DesignChanged.Type.QuickDesignBar:
|
||||
var priorState = IsInitialized;
|
||||
if (priorState)
|
||||
Cleanup();
|
||||
CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1));
|
||||
if (CurrentSelectionIdx >= 0)
|
||||
{
|
||||
UpdateSelection(Items[CurrentSelectionIdx]);
|
||||
}
|
||||
else if (Items.Count > 0)
|
||||
{
|
||||
CurrentSelectionIdx = 0;
|
||||
UpdateSelection(Items[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSelection(null);
|
||||
}
|
||||
if (!ReferenceEquals(_currentDesign, CurrentSelection?.Item1))
|
||||
CurrentSelectionIdx = -1;
|
||||
|
||||
if (!priorState)
|
||||
Cleanup();
|
||||
break;
|
||||
base.OnMouseWheel(preview, ref _2, steps);
|
||||
}
|
||||
|
||||
private void UpdateCurrentSelection()
|
||||
{
|
||||
if (!_isCurrentSelectionDirty)
|
||||
return;
|
||||
|
||||
var priorState = IsInitialized;
|
||||
if (priorState)
|
||||
Cleanup();
|
||||
CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1));
|
||||
if (CurrentSelectionIdx >= 0)
|
||||
{
|
||||
UpdateSelection(Items[CurrentSelectionIdx]);
|
||||
}
|
||||
else if (Items.Count > 0)
|
||||
{
|
||||
CurrentSelectionIdx = 0;
|
||||
UpdateSelection(Items[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSelection(null);
|
||||
}
|
||||
|
||||
if (!priorState)
|
||||
Cleanup();
|
||||
_isCurrentSelectionDirty = false;
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(p => _currentDesign == p.Item1);
|
||||
UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null);
|
||||
return CurrentSelectionIdx;
|
||||
}
|
||||
|
||||
private void OnDesignChanged(DesignChanged.Type type, Design? _1, ITransaction? _2 = null)
|
||||
{
|
||||
_isCurrentSelectionDirty = type switch
|
||||
{
|
||||
DesignChanged.Type.Created => true,
|
||||
DesignChanged.Type.Renamed => true,
|
||||
DesignChanged.Type.ChangedColor => true,
|
||||
DesignChanged.Type.Deleted => true,
|
||||
DesignChanged.Type.QuickDesignBar => true,
|
||||
_ => _isCurrentSelectionDirty,
|
||||
};
|
||||
}
|
||||
|
||||
private void QuickSelectedDesignTooltip(IDesignStandIn? design)
|
||||
|
|
@ -176,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
|
||||
{
|
||||
|
|
@ -226,8 +244,7 @@ public abstract class DesignCombo : DesignComboBase
|
|||
|
||||
public sealed class QuickDesignCombo : DesignCombo
|
||||
{
|
||||
public QuickDesignCombo(DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
public QuickDesignCombo(DesignFileSystem fileSystem,
|
||||
Logger log,
|
||||
DesignChanged designChanged,
|
||||
TabSelected tabSelected,
|
||||
|
|
@ -235,9 +252,9 @@ public sealed class QuickDesignCombo : DesignCombo
|
|||
DesignColors designColors)
|
||||
: base(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Where(d => d.QuickDesign)
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Where(kvp => kvp.Key.QuickDesign)
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
])
|
||||
{
|
||||
|
|
@ -278,7 +295,6 @@ public sealed class QuickDesignCombo : DesignCombo
|
|||
}
|
||||
|
||||
public sealed class LinkDesignCombo(
|
||||
DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
Logger log,
|
||||
DesignChanged designChanged,
|
||||
|
|
@ -287,8 +303,8 @@ public sealed class LinkDesignCombo(
|
|||
DesignColors designColors)
|
||||
: DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
]);
|
||||
|
||||
|
|
@ -302,8 +318,8 @@ public sealed class RandomDesignCombo(
|
|||
DesignColors designColors)
|
||||
: DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
])
|
||||
{
|
||||
|
|
@ -329,7 +345,6 @@ public sealed class RandomDesignCombo(
|
|||
}
|
||||
|
||||
public sealed class SpecialDesignCombo(
|
||||
DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
TabSelected tabSelected,
|
||||
DesignColors designColors,
|
||||
|
|
@ -339,8 +354,8 @@ public sealed class SpecialDesignCombo(
|
|||
EphemeralConfig config,
|
||||
RandomDesignGenerator rng,
|
||||
QuickSelectedDesign quickSelectedDesign)
|
||||
: DesignComboBase(() => designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
: DesignComboBase(() => fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2)
|
||||
.Prepend(new Tuple<IDesignStandIn, string>(new RandomDesign(rng), string.Empty))
|
||||
.Prepend(new Tuple<IDesignStandIn, string>(quickSelectedDesign, string.Empty))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -19,14 +19,15 @@ namespace Glamourer.Gui;
|
|||
[Flags]
|
||||
public enum QdbButtons
|
||||
{
|
||||
ApplyDesign = 0x01,
|
||||
RevertAll = 0x02,
|
||||
RevertAutomation = 0x04,
|
||||
RevertAdvanced = 0x08,
|
||||
RevertEquip = 0x10,
|
||||
RevertCustomize = 0x20,
|
||||
ReapplyAutomation = 0x40,
|
||||
ResetSettings = 0x80,
|
||||
ApplyDesign = 0x01,
|
||||
RevertAll = 0x02,
|
||||
RevertAutomation = 0x04,
|
||||
RevertAdvancedDyes = 0x08,
|
||||
RevertEquip = 0x10,
|
||||
RevertCustomize = 0x20,
|
||||
ReapplyAutomation = 0x40,
|
||||
ResetSettings = 0x80,
|
||||
RevertAdvancedCustomization = 0x100,
|
||||
}
|
||||
|
||||
public sealed class DesignQuickBar : Window, IDisposable
|
||||
|
|
@ -63,6 +64,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
IsOpen = _config.Ephemeral.ShowDesignQuickBar;
|
||||
DisableWindowSounds = true;
|
||||
Size = Vector2.Zero;
|
||||
RespectCloseHotkey = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -124,6 +126,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
DrawRevertEquipButton(buttonSize);
|
||||
DrawRevertCustomizeButton(buttonSize);
|
||||
DrawRevertAdvancedCustomization(buttonSize);
|
||||
DrawRevertAdvancedDyes(buttonSize);
|
||||
DrawRevertAutomationButton(buttonSize);
|
||||
DrawReapplyAutomationButton(buttonSize);
|
||||
DrawResetSettingsButton(buttonSize);
|
||||
|
|
@ -318,7 +321,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
|
||||
private void DrawRevertAdvancedCustomization(Vector2 buttonSize)
|
||||
{
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization))
|
||||
return;
|
||||
|
||||
var available = 0;
|
||||
|
|
@ -327,7 +330,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid)
|
||||
{
|
||||
available |= 1;
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced customizations and dyes of the player character to their game state.");
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced customizations of the player character to their game state.");
|
||||
}
|
||||
|
||||
if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid)
|
||||
|
|
@ -335,7 +338,40 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (available != 0)
|
||||
_tooltipBuilder.Append('\n');
|
||||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced customizations and dyes of ")
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced customizations of ")
|
||||
.Append(_targetIdentifier)
|
||||
.Append(" to their game state.");
|
||||
}
|
||||
|
||||
if (available == 0)
|
||||
_tooltipBuilder.Append("Neither player character nor target are available or their state is locked.");
|
||||
|
||||
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.PaintBrush, buttonSize, available);
|
||||
ImGui.SameLine();
|
||||
if (clicked)
|
||||
_stateManager.ResetAdvancedCustomizations(state!, StateSource.Manual);
|
||||
}
|
||||
|
||||
private void DrawRevertAdvancedDyes(Vector2 buttonSize)
|
||||
{
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedDyes))
|
||||
return;
|
||||
|
||||
var available = 0;
|
||||
_tooltipBuilder.Clear();
|
||||
|
||||
if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid)
|
||||
{
|
||||
available |= 1;
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced dyes of the player character to their game state.");
|
||||
}
|
||||
|
||||
if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid)
|
||||
{
|
||||
if (available != 0)
|
||||
_tooltipBuilder.Append('\n');
|
||||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced dyes of ")
|
||||
.Append(_targetIdentifier)
|
||||
.Append(" to their game state.");
|
||||
}
|
||||
|
|
@ -346,7 +382,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.Palette, buttonSize, available);
|
||||
ImGui.SameLine();
|
||||
if (clicked)
|
||||
_stateManager.ResetAdvancedState(state!, StateSource.Manual);
|
||||
_stateManager.ResetAdvancedDyes(state!, StateSource.Manual);
|
||||
}
|
||||
|
||||
private void DrawRevertCustomizeButton(Vector2 buttonSize)
|
||||
|
|
@ -501,7 +537,9 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
++_numButtons;
|
||||
}
|
||||
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization))
|
||||
++_numButtons;
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedDyes))
|
||||
++_numButtons;
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertCustomize))
|
||||
++_numButtons;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData)
|
|||
public readonly void SetStains(StainIds stains)
|
||||
=> _editor.ChangeStains(_object, Slot, stains, ApplySettings.Manual);
|
||||
|
||||
public readonly void SetStain(int which, StainId stain)
|
||||
=> _editor.ChangeStains(_object, Slot, CurrentStains.With(which, stain), ApplySettings.Manual);
|
||||
|
||||
public readonly void SetApplyItem(bool value)
|
||||
{
|
||||
var manager = (DesignManager)_editor;
|
||||
|
|
|
|||
83
Glamourer/Gui/Equipment/EquipItemSlotCache.cs
Normal file
83
Glamourer/Gui/Equipment/EquipItemSlotCache.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using Glamourer.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
[InlineArray(13)]
|
||||
public struct EquipItemSlotCache
|
||||
{
|
||||
private EquipItem _element;
|
||||
|
||||
public EquipItem Dragged
|
||||
{
|
||||
get => this[^1];
|
||||
set => this[^1] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
=> ((Span<EquipItem>)this).Clear();
|
||||
|
||||
public EquipItem this[EquipSlot slot]
|
||||
{
|
||||
get => this[(int)slot.ToIndex()];
|
||||
set => this[(int)slot.ToIndex()] = value;
|
||||
}
|
||||
|
||||
public void Update(ItemManager items, in EquipItem item, EquipSlot startSlot)
|
||||
{
|
||||
if (item.Id == Dragged.Id && item.Type == Dragged.Type)
|
||||
return;
|
||||
|
||||
switch (startSlot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
{
|
||||
Clear();
|
||||
this[EquipSlot.MainHand] = item;
|
||||
if (item.Type is FullEquipType.Sword)
|
||||
this[EquipSlot.OffHand] = items.FindClosestShield(item.ItemId, out var shield) ? shield : default;
|
||||
else
|
||||
this[EquipSlot.OffHand] = items.ItemData.Secondary.GetValueOrDefault(item.ItemId);
|
||||
break;
|
||||
}
|
||||
case EquipSlot.OffHand:
|
||||
{
|
||||
Clear();
|
||||
if (item.Type is FullEquipType.Shield)
|
||||
this[EquipSlot.MainHand] = items.FindClosestSword(item.ItemId, out var sword) ? sword : default;
|
||||
else
|
||||
this[EquipSlot.MainHand] = items.ItemData.Primary.GetValueOrDefault(item.ItemId);
|
||||
this[EquipSlot.OffHand] = item;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this[EquipSlot.MainHand] = default;
|
||||
this[EquipSlot.OffHand] = default;
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
if (startSlot == slot)
|
||||
{
|
||||
this[slot] = item;
|
||||
continue;
|
||||
}
|
||||
|
||||
var slotItem = items.Identify(slot, item.PrimaryId, item.Variant);
|
||||
if (!slotItem.Valid || slotItem.ItemId.Id is not 0 != item.ItemId.Id is not 0)
|
||||
{
|
||||
slotItem = items.Identify(EquipSlot.OffHand, item.PrimaryId, item.SecondaryId, 1, item.Type);
|
||||
if (slotItem.ItemId.Id is not 0 != item.ItemId.Id is not 0)
|
||||
slotItem = default;
|
||||
}
|
||||
|
||||
this[slot] = slotItem;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Dragged = item;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,16 +3,15 @@ using Dalamud.Interface.Utility;
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Gui.Materials;
|
||||
using Glamourer.Interop.Material;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
@ -33,20 +32,24 @@ public class EquipmentDrawer
|
|||
private readonly Configuration _config;
|
||||
private readonly GPoseService _gPose;
|
||||
private readonly AdvancedDyePopup _advancedDyes;
|
||||
private readonly ItemCopyService _itemCopy;
|
||||
|
||||
private float _requiredComboWidthUnscaled;
|
||||
private float _requiredComboWidth;
|
||||
|
||||
private Stain? _draggedStain;
|
||||
private Stain? _draggedStain;
|
||||
private EquipItemSlotCache _draggedItem;
|
||||
private EquipSlot _dragTarget;
|
||||
|
||||
public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures,
|
||||
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes)
|
||||
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy)
|
||||
{
|
||||
_items = items;
|
||||
_textures = textures;
|
||||
_config = config;
|
||||
_gPose = gPose;
|
||||
_advancedDyes = advancedDyes;
|
||||
_itemCopy = itemCopy;
|
||||
_stainData = items.Stains;
|
||||
_stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites);
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
|
||||
|
|
@ -79,6 +82,7 @@ public class EquipmentDrawer
|
|||
|
||||
_requiredComboWidth = _requiredComboWidthUnscaled * ImGuiHelpers.GlobalScale;
|
||||
_advancedMaterialColor = ColorId.AdvancedDyeActive.Value();
|
||||
_dragTarget = EquipSlot.Unknown;
|
||||
}
|
||||
|
||||
private bool VerifyRestrictedGear(EquipDrawData data)
|
||||
|
|
@ -184,6 +188,7 @@ public class EquipmentDrawer
|
|||
return change;
|
||||
}
|
||||
|
||||
|
||||
#region Small
|
||||
|
||||
private void DrawEquipSmall(in EquipDrawData equipDrawData)
|
||||
|
|
@ -402,6 +407,7 @@ public class EquipmentDrawer
|
|||
? _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss)
|
||||
: _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width);
|
||||
|
||||
_itemCopy.HandleCopyPaste(data, index);
|
||||
if (!change)
|
||||
DrawStainDragDrop(data, index, stain, found);
|
||||
|
||||
|
|
@ -426,8 +432,8 @@ public class EquipmentDrawer
|
|||
using var dragSource = ImUtf8.DragDropSource();
|
||||
if (dragSource.Success)
|
||||
{
|
||||
if (DragDropSource.SetPayload("stainDragDrop"u8))
|
||||
_draggedStain = stain;
|
||||
DragDropSource.SetPayload("stainDragDrop"u8);
|
||||
_draggedStain = stain;
|
||||
ImUtf8.Text($"Dragging {stain.Name}...");
|
||||
}
|
||||
}
|
||||
|
|
@ -452,10 +458,12 @@ public class EquipmentDrawer
|
|||
using var disabled = ImRaii.Disabled(data.Locked);
|
||||
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth);
|
||||
DrawGearDragDrop(data);
|
||||
if (change)
|
||||
data.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0)
|
||||
data.SetItem(_items.Identify(data.Slot, combo.CustomSetId, combo.CustomVariant));
|
||||
_itemCopy.HandleCopyPaste(data);
|
||||
|
||||
if (ResetOrClear(data.Locked, clear, data.AllowRevert, true, data.CurrentItem, data.GameItem, ItemManager.NothingItem(data.Slot),
|
||||
out var item))
|
||||
|
|
@ -473,6 +481,14 @@ public class EquipmentDrawer
|
|||
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem,
|
||||
small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth);
|
||||
if (ImGui.IsItemHovered() && ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsKeyPressed(ImGuiKey.C))
|
||||
_itemCopy.Copy(combo.CurrentSelection);
|
||||
else if (ImGui.IsKeyPressed(ImGuiKey.V))
|
||||
_itemCopy.Paste(data.Slot.ToEquipType(), data.SetItem);
|
||||
}
|
||||
|
||||
if (change)
|
||||
data.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0)
|
||||
|
|
@ -483,6 +499,50 @@ public class EquipmentDrawer
|
|||
data.SetItem(item);
|
||||
}
|
||||
|
||||
private void DrawGearDragDrop(in EquipDrawData data)
|
||||
{
|
||||
if (data.CurrentItem.Valid)
|
||||
{
|
||||
using var dragSource = ImUtf8.DragDropSource();
|
||||
if (dragSource.Success)
|
||||
{
|
||||
DragDropSource.SetPayload("equipDragDrop"u8);
|
||||
_draggedItem.Update(_items, data.CurrentItem, data.Slot);
|
||||
}
|
||||
}
|
||||
|
||||
using var dragTarget = ImUtf8.DragDropTarget();
|
||||
if (!dragTarget)
|
||||
return;
|
||||
|
||||
var item = _draggedItem[data.Slot];
|
||||
if (!item.Valid)
|
||||
return;
|
||||
|
||||
_dragTarget = data.Slot;
|
||||
if (!dragTarget.IsDropping("equipDragDrop"u8))
|
||||
return;
|
||||
|
||||
data.SetItem(item);
|
||||
_draggedItem.Clear();
|
||||
}
|
||||
|
||||
public unsafe void DrawDragDropTooltip()
|
||||
{
|
||||
var payload = ImGui.GetDragDropPayload().Handle;
|
||||
if (payload is null)
|
||||
return;
|
||||
|
||||
if (!MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)Unsafe.AsPointer(ref payload->DataType_0)).SequenceEqual("equipDragDrop"u8))
|
||||
return;
|
||||
|
||||
using var tt = ImUtf8.Tooltip();
|
||||
if (_dragTarget is EquipSlot.Unknown)
|
||||
ImUtf8.Text($"Dragging {_draggedItem.Dragged.Name}...");
|
||||
else
|
||||
ImUtf8.Text($"Converting to {_draggedItem[_dragTarget].Name}...");
|
||||
}
|
||||
|
||||
private static bool ResetOrClear<T>(bool locked, bool clicked, bool allowRevert, bool allowClear,
|
||||
in T currentItem, in T revertItem, in T clearItem, out T? item) where T : IEquatable<T>
|
||||
{
|
||||
|
|
@ -531,8 +591,13 @@ public class EquipmentDrawer
|
|||
if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth))
|
||||
changedItem = combo.CurrentSelection;
|
||||
else if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
|
||||
default, out var c))
|
||||
else if (combo.CustomVariant.Id > 0 && (drawAll || ItemData.ConvertWeaponId(combo.CustomSetId) == mainhand.CurrentItem.Type))
|
||||
changedItem = _items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant);
|
||||
_itemCopy.HandleCopyPaste(mainhand);
|
||||
DrawGearDragDrop(mainhand);
|
||||
|
||||
if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
|
||||
default, out var c))
|
||||
changedItem = c;
|
||||
|
||||
if (changedItem != null)
|
||||
|
|
@ -549,7 +614,8 @@ public class EquipmentDrawer
|
|||
}
|
||||
|
||||
if (unknown)
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled,
|
||||
"The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
|
||||
}
|
||||
|
||||
private void DrawOffhand(in EquipDrawData mainhand, in EquipDrawData offhand, out string label, bool small, bool clear, bool open)
|
||||
|
|
@ -569,6 +635,10 @@ public class EquipmentDrawer
|
|||
if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth))
|
||||
offhand.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0 && ItemData.ConvertWeaponId(combo.CustomSetId) == offhand.CurrentItem.Type)
|
||||
offhand.SetItem(_items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant));
|
||||
_itemCopy.HandleCopyPaste(offhand);
|
||||
DrawGearDragDrop(offhand);
|
||||
|
||||
var defaultOffhand = _items.GetDefaultOffhand(mainhand.CurrentItem);
|
||||
if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item))
|
||||
|
|
@ -623,6 +693,7 @@ public class EquipmentDrawer
|
|||
{
|
||||
ImUtf8.Text(label);
|
||||
}
|
||||
|
||||
if (hasAdvancedDyes)
|
||||
ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
73
Glamourer/Gui/Equipment/ItemCopyService.cs
Normal file
73
Glamourer/Gui/Equipment/ItemCopyService.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using Glamourer.Services;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
public class ItemCopyService(ItemManager items, DictStain stainData) : IUiService
|
||||
{
|
||||
public EquipItem? Item { get; private set; }
|
||||
public Stain? Stain { get; private set; }
|
||||
|
||||
public void Copy(in EquipItem item)
|
||||
=> Item = item;
|
||||
|
||||
public void Copy(in Stain stain)
|
||||
=> Stain = stain;
|
||||
|
||||
public void Paste(int which, Action<int, StainId> setter)
|
||||
{
|
||||
if (Stain is { } stain)
|
||||
setter(which, stain.RowIndex);
|
||||
}
|
||||
|
||||
public void Paste(FullEquipType type, Action<EquipItem> setter)
|
||||
{
|
||||
if (Item is not { } item)
|
||||
return;
|
||||
|
||||
if (type != item.Type)
|
||||
{
|
||||
if (type.IsBonus())
|
||||
item = items.Identify(type.ToBonus(), item.PrimaryId, item.Variant);
|
||||
else if (type.IsEquipment() || type.IsAccessory())
|
||||
item = items.Identify(type.ToSlot(), item.PrimaryId, item.Variant);
|
||||
else
|
||||
item = items.Identify(type.ToSlot(), item.PrimaryId, item.SecondaryId, item.Variant);
|
||||
}
|
||||
|
||||
if (item.Valid && item.Type == type)
|
||||
setter(item);
|
||||
}
|
||||
|
||||
public void HandleCopyPaste(in EquipDrawData data)
|
||||
{
|
||||
if (ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
Paste(data.CurrentItem.Type, data.SetItem);
|
||||
}
|
||||
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled) && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
{
|
||||
Copy(data.CurrentItem);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleCopyPaste(in EquipDrawData data, int which)
|
||||
{
|
||||
if (ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
Paste(which, data.SetStain);
|
||||
}
|
||||
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)
|
||||
&& ImGui.IsMouseClicked(ImGuiMouseButton.Middle)
|
||||
&& stainData.TryGetValue(data.CurrentStains[which].Id, out var stain))
|
||||
{
|
||||
Copy(stain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
|
|
@ -20,6 +19,10 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
private ItemId _currentItem;
|
||||
private float _innerWidth;
|
||||
|
||||
public PrimaryId CustomSetId { get; private set; }
|
||||
public SecondaryId CustomWeaponId { get; private set; }
|
||||
public Variant CustomVariant { get; private set; }
|
||||
|
||||
public WeaponCombo(ItemManager items, FullEquipType type, Logger log, FavoriteManager favorites)
|
||||
: base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log)
|
||||
{
|
||||
|
|
@ -47,8 +50,9 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
|
||||
public bool Draw(string previewName, ItemId previewIdx, float width, float innerWidth)
|
||||
{
|
||||
_innerWidth = innerWidth;
|
||||
_currentItem = previewIdx;
|
||||
_innerWidth = innerWidth;
|
||||
_currentItem = previewIdx;
|
||||
CustomVariant = 0;
|
||||
return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +79,24 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
return ret;
|
||||
}
|
||||
|
||||
protected override void OnClosePopup()
|
||||
{
|
||||
// If holding control while the popup closes, try to parse the input as a full tuple of set id, weapon id and variant, and set a custom item for that.
|
||||
if (!ImGui.GetIO().KeyCtrl)
|
||||
return;
|
||||
|
||||
var split = Filter.Text.Split('-', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
if (split.Length != 3
|
||||
|| !ushort.TryParse(split[0], out var setId)
|
||||
|| !ushort.TryParse(split[1], out var weaponId)
|
||||
|| !byte.TryParse(split[2], out var variant))
|
||||
return;
|
||||
|
||||
CustomSetId = setId;
|
||||
CustomWeaponId = weaponId;
|
||||
CustomVariant = variant;
|
||||
}
|
||||
|
||||
protected override bool IsVisible(int globalIndex, LowerString filter)
|
||||
=> base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ public class GlamourerChangelog
|
|||
Add1_3_6_0(Changelog);
|
||||
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()
|
||||
|
|
@ -62,6 +65,54 @@ 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.")
|
||||
.RegisterEntry("The current behavior may not be final, let me know if you have any comments.", 1)
|
||||
.RegisterEntry("Regular customization colors can now be dragged & dropped onto other customizations.")
|
||||
.RegisterEntry(
|
||||
"If no identical color is available in the target slot, the most similar color available (for certain values of similar) will be chosen instead.",
|
||||
1)
|
||||
.RegisterEntry("Resetting advanced dyes and customizations has been split into two buttons for the quick design bar.")
|
||||
.RegisterEntry("Weapons now also support custom ID input in the combo search box.")
|
||||
.RegisterEntry("Added new IPC methods GetExtendedDesignData, AddDesign, DeleteDesign, GetDesignBase64, GetDesignJObject.")
|
||||
.RegisterEntry("Added the option to prevent immediate repeats for random design selection (Thanks Diorik!).")
|
||||
.RegisterEntry("Optimized some multi-design changes when selecting many designs and changing them at once.")
|
||||
.RegisterEntry("Fixed item combos not starting from the currently selected item when scrolling them via mouse wheel.")
|
||||
.RegisterEntry("Fixed some issue with Glamourer not searching mods by name for mod associations in some cases.")
|
||||
.RegisterEntry("Fixed the IPC methods SetMetaState and SetMetaStateName not working (Thanks Caraxi!).")
|
||||
.RegisterEntry("Added new IPC method GetDesignListExtended. (1.3.8.6)")
|
||||
.RegisterEntry(
|
||||
"Improved the naming of NPCs for identifiers by using Haselnussbombers new naming functionality (Thanks Hasel!). (1.3.8.6)")
|
||||
.RegisterEntry(
|
||||
"Added a modifier key separate from the delete modifier key that is used for less important key-checks, specifically toggling incognito mode. (1.3.8.5)")
|
||||
.RegisterEntry("Used better Penumbra IPC for some things. (1.3.8.5)")
|
||||
.RegisterEntry("Fixed an issue with advanced dyes for weapons. (1.3.8.5)")
|
||||
.RegisterEntry("Fixed an issue with NPC automation due to missing job detection. (1.3.8.1)");
|
||||
|
||||
private static void Add1_3_8_0(Changelog log)
|
||||
=> log.NextVersion("Version 1.3.8.0")
|
||||
.RegisterImportant("Updated Glamourer for update 7.20 and Dalamud API 12.")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -238,6 +238,7 @@ public class ActorPanel
|
|||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawEquipmentMetaToggles();
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
_equipmentDrawer.DrawDragDropTooltip();
|
||||
}
|
||||
|
||||
private void DrawParameterHeader()
|
||||
|
|
@ -304,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()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.ActorTab;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -278,7 +278,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
|||
private void LookupTooltip(IEnumerable<Design> designs)
|
||||
{
|
||||
using var _ = ImRaii.Tooltip();
|
||||
var tt = string.Join('\n', designs.Select(d => _designFileSystem.FindLeaf(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t));
|
||||
var tt = string.Join('\n', designs.Select(d => _designFileSystem.TryGetValue(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t));
|
||||
ImGui.TextUnformatted(tt.Length == 0
|
||||
? "Matches no currently existing designs."
|
||||
: "Matches the following designs:");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Automation;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Widgets;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||
using ImGuiNET;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
|
@ -36,6 +35,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
|||
provider.GetRequiredService<ModelEvaluationPanel>(),
|
||||
provider.GetRequiredService<ObjectManagerPanel>(),
|
||||
provider.GetRequiredService<PenumbraPanel>(),
|
||||
provider.GetRequiredService<DynamisPanel>(),
|
||||
provider.GetRequiredService<IpcTesterPanel>(),
|
||||
provider.GetRequiredService<DatFilePanel>(),
|
||||
provider.GetRequiredService<GlamourPlatePanel>(),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Filesystem;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
|
|
@ -19,6 +21,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
DrawButtons();
|
||||
foreach (var (design, idx) in _designManager.Designs.WithIndex())
|
||||
{
|
||||
using var t = ImRaii.TreeNode($"{design.Name}##{idx}");
|
||||
|
|
@ -26,7 +29,8 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
continue;
|
||||
|
||||
DrawDesign(design, _designFileSystem);
|
||||
var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, design.Application.Meta,
|
||||
var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize,
|
||||
design.Application.Meta,
|
||||
design.WriteProtected());
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
ImGuiUtil.TextWrapped(base64);
|
||||
|
|
@ -35,6 +39,26 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawButtons()
|
||||
{
|
||||
if (ImUtf8.Button("Generate 500 Test Designs"u8))
|
||||
for (var i = 0; i < 500; ++i)
|
||||
{
|
||||
var design = _designManager.CreateEmpty($"Test Designs/Test Design {i}", true);
|
||||
_designManager.AddTag(design, "_DebugTest");
|
||||
}
|
||||
|
||||
ImUtf8.SameLineInner();
|
||||
if (ImUtf8.Button("Remove All Test Designs"u8))
|
||||
{
|
||||
var designs = _designManager.Designs.Where(d => d.Tags.Contains("_DebugTest")).ToArray();
|
||||
foreach (var design in designs)
|
||||
_designManager.Delete(design);
|
||||
if (_designFileSystem.Find("Test Designs", out var path) && path is DesignFileSystem.Folder { TotalChildren: 0 })
|
||||
_designFileSystem.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawDesign(DesignBase design, DesignFileSystem? fileSystem)
|
||||
{
|
||||
using var table = ImRaii.Table("##equip", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit);
|
||||
|
|
@ -53,7 +77,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
ImGui.TableNextRow();
|
||||
ImGuiUtil.DrawTableColumn("Design File System Path");
|
||||
if (fileSystem != null)
|
||||
ImGuiUtil.DrawTableColumn(fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : "No Path Known");
|
||||
ImGuiUtil.DrawTableColumn(fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : "No Path Known");
|
||||
ImGui.TableNextRow();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Creation");
|
||||
|
|
@ -90,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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
16
Glamourer/Gui/Tabs/DebugTab/DynamisPanel.cs
Normal file
16
Glamourer/Gui/Tabs/DebugTab/DynamisPanel.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class DynamisPanel(DynamisIpc dynamis) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Dynamis Interop";
|
||||
|
||||
public void Draw()
|
||||
=> dynamis.DrawDebugInfo();
|
||||
|
||||
public bool Disabled
|
||||
=> false;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ 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;
|
||||
using OtterGui.Text;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
private Dictionary<Guid, string> _designs = [];
|
||||
private int _gameObjectIndex;
|
||||
private string _gameObjectName = string.Empty;
|
||||
private string _designName = string.Empty;
|
||||
private uint _key;
|
||||
private ApplyFlag _flags = ApplyFlagEx.DesignDefault;
|
||||
private Guid? _design;
|
||||
|
|
@ -30,6 +32,7 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
IpcTesterHelpers.IndexInput(ref _gameObjectIndex);
|
||||
IpcTesterHelpers.KeyInput(ref _key);
|
||||
IpcTesterHelpers.NameInput(ref _gameObjectName);
|
||||
ImUtf8.InputText("##designName"u8, ref _designName, "Design Name..."u8);
|
||||
ImGuiUtil.GuidInput("##identifier", "Design Identifier...", string.Empty, ref _design, ref _designText,
|
||||
ImGui.GetContentRegionAvail().X);
|
||||
IpcTesterHelpers.DrawFlagInput(ref _flags);
|
||||
|
|
@ -54,6 +57,48 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
IpcTesterHelpers.DrawIntro(ApplyDesignName.Label);
|
||||
if (ImGuiUtil.DrawDisabledButton("Apply##Name", Vector2.Zero, string.Empty, !_design.HasValue))
|
||||
_lastError = new ApplyDesignName(pluginInterface).Invoke(_design!.Value, _gameObjectName, _key, _flags);
|
||||
|
||||
IpcTesterHelpers.DrawIntro(GetExtendedDesignData.Label);
|
||||
if (_design.HasValue)
|
||||
{
|
||||
var (display, path, color, draw) = new GetExtendedDesignData(pluginInterface).Invoke(_design.Value);
|
||||
if (path.Length > 0)
|
||||
ImUtf8.Text($"{display} ({path}){(draw ? " in QDB"u8 : ""u8)}", color);
|
||||
else
|
||||
ImUtf8.Text("No Data"u8);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImUtf8.Text("No Data"u8);
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(GetDesignBase64.Label);
|
||||
if (ImUtf8.Button("To Clipboard##Base64"u8) && _design.HasValue)
|
||||
{
|
||||
var data = new GetDesignBase64(pluginInterface).Invoke(_design.Value);
|
||||
ImUtf8.SetClipboardText(data);
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(AddDesign.Label);
|
||||
if (ImUtf8.Button("Add from Clipboard"u8))
|
||||
try
|
||||
{
|
||||
var data = ImUtf8.GetClipboardText();
|
||||
_lastError = new AddDesign(pluginInterface).Invoke(data, _designName, out var newDesign);
|
||||
if (_lastError is GlamourerApiEc.Success)
|
||||
{
|
||||
_design = newDesign;
|
||||
_designText = newDesign.ToString();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_lastError = GlamourerApiEc.UnknownError;
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(DeleteDesign.Label);
|
||||
if (ImUtf8.Button("Delete##Design"u8) && _design.HasValue)
|
||||
_lastError = new DeleteDesign(pluginInterface).Invoke(_design.Value);
|
||||
}
|
||||
|
||||
private void DrawDesignsPopup()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -45,9 +46,10 @@ public unsafe class ModelEvaluationPanel(
|
|||
|
||||
ImGuiUtil.DrawTableColumn("Address");
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(actor.ToString());
|
||||
|
||||
Glamourer.Dynamis.DrawPointer(actor);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(model.ToString());
|
||||
Glamourer.Dynamis.DrawPointer(model);
|
||||
ImGui.TableNextColumn();
|
||||
if (actor.IsCharacter)
|
||||
{
|
||||
|
|
@ -83,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);
|
||||
|
|
@ -134,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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Actors;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -61,7 +61,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputInt("##CutsceneIndex", ref _gameObjectIndex, 0, 0);
|
||||
ImGuiUtil.DrawTableColumn(_penumbra.Available
|
||||
? _penumbra.CutsceneParent((ushort) _gameObjectIndex).ToString()
|
||||
? _penumbra.CutsceneParent((ushort)_gameObjectIndex).ToString()
|
||||
: "Penumbra Unavailable");
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Redraw Object");
|
||||
|
|
@ -76,7 +76,9 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Last Tooltip Date");
|
||||
ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue ? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})" : "Never");
|
||||
ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue
|
||||
? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})"
|
||||
: "Never");
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Last Click Date");
|
||||
|
|
@ -87,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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
|
|
@ -13,13 +12,6 @@ public sealed class DesignColorCombo(DesignColors _designColors, bool _skipAutom
|
|||
: _designColors.Keys.OrderBy(k => k).Prepend(DesignColors.AutomaticName),
|
||||
MouseWheelType.Control, Glamourer.Log)
|
||||
{
|
||||
protected override void OnMouseWheel(string preview, ref int current, int steps)
|
||||
{
|
||||
if (CurrentSelectionIdx < 0)
|
||||
CurrentSelectionIdx = Items.IndexOf(preview);
|
||||
base.OnMouseWheel(preview, ref current, steps);
|
||||
}
|
||||
|
||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
||||
{
|
||||
var isAutomatic = !_skipAutomatic && globalIdx == 0;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ 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;
|
||||
using OtterGui.FileSystem.Selector;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||
|
||||
|
|
@ -45,6 +46,29 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
|
|||
public record struct DesignState(uint Color)
|
||||
{ }
|
||||
|
||||
protected override float CurrentWidth
|
||||
=> _config.Ephemeral.CurrentDesignSelectorWidth * ImUtf8.GlobalScale;
|
||||
|
||||
protected override float MinimumAbsoluteRemainder
|
||||
=> 470 * ImUtf8.GlobalScale;
|
||||
|
||||
protected override float MinimumScaling
|
||||
=> _config.Ephemeral.DesignSelectorMinimumScale;
|
||||
|
||||
protected override float MaximumScaling
|
||||
=> _config.Ephemeral.DesignSelectorMaximumScale;
|
||||
|
||||
protected override void SetSize(Vector2 size)
|
||||
{
|
||||
base.SetSize(size);
|
||||
var adaptedSize = MathF.Round(size.X / ImUtf8.GlobalScale);
|
||||
if (adaptedSize == _config.Ephemeral.CurrentDesignSelectorWidth)
|
||||
return;
|
||||
|
||||
_config.Ephemeral.CurrentDesignSelectorWidth = adaptedSize;
|
||||
_config.Ephemeral.Save();
|
||||
}
|
||||
|
||||
public DesignFileSystemSelector(DesignManager designManager, DesignFileSystem fileSystem, IKeyState keyState, DesignChanged @event,
|
||||
Configuration config, DesignConverter converter, TabSelected selectionEvent, Logger log, DesignColors designColors,
|
||||
DesignApplier designApplier)
|
||||
|
|
@ -151,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -130,6 +130,7 @@ public class DesignPanel
|
|||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawEquipmentMetaToggles();
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
_equipmentDrawer.DrawDragDropTooltip();
|
||||
}
|
||||
|
||||
private void DrawEquipmentMetaToggles()
|
||||
|
|
@ -153,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()
|
||||
|
|
@ -264,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)
|
||||
|
|
@ -310,6 +315,9 @@ public class DesignPanel
|
|||
|
||||
ImUtf8.IconDummy();
|
||||
DrawParameterApplication();
|
||||
|
||||
ImUtf8.IconDummy();
|
||||
DrawBonusSlotApplication();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,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))
|
||||
|
|
@ -396,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)
|
||||
|
|
@ -408,6 +417,7 @@ public class DesignPanel
|
|||
"Apply Hat Visibility",
|
||||
"Apply Visor State",
|
||||
"Apply Weapon Visibility",
|
||||
"Apply Viera Ear Visibility",
|
||||
];
|
||||
|
||||
private void DrawMetaApplication()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ public class DesignTab(DesignFileSystemSelector _selector, DesignPanel _panel, I
|
|||
|
||||
public void DrawContent()
|
||||
{
|
||||
_selector.Draw(GetDesignSelectorSize());
|
||||
_selector.Draw();
|
||||
if (_importService.CreateCharaTarget(out var designBase, out var name))
|
||||
{
|
||||
var newDesign = _manager.CreateClone(designBase, name, true);
|
||||
|
|
@ -27,7 +27,4 @@ public class DesignTab(DesignFileSystemSelector _selector, DesignPanel _panel, I
|
|||
_panel.Draw();
|
||||
_importService.CreateCharaSource();
|
||||
}
|
||||
|
||||
public float GetDesignSelectorSize()
|
||||
=> 200f * ImGuiHelpers.GlobalScale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop.Material;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -11,7 +10,11 @@ using static Glamourer.Gui.Tabs.HeaderDrawer;
|
|||
|
||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||
|
||||
public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager editor, DesignColors colors, Configuration config)
|
||||
public class MultiDesignPanel(
|
||||
DesignFileSystemSelector selector,
|
||||
DesignManager editor,
|
||||
DesignColors colors,
|
||||
Configuration config)
|
||||
{
|
||||
private readonly Button[] _leftButtons = [];
|
||||
private readonly Button[] _rightButtons = [new IncognitoButton(config)];
|
||||
|
|
@ -201,16 +204,21 @@ public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager e
|
|||
? $"All {_numDesigns} selected designs are already displayed in the quick design bar."
|
||||
: $"Display all {_numDesigns} selected designs in the quick design bar. Changes {diff} designs.";
|
||||
if (ImUtf8.ButtonEx("Display Selected Designs in QDB"u8, tt, buttonWidth, diff == 0))
|
||||
{
|
||||
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
|
||||
editor.SetQuickDesign(design.Value, true);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
tt = _numQuickDesignEnabled == 0
|
||||
? $"All {_numDesigns} selected designs are already hidden in the quick design bar."
|
||||
: $"Hide all {_numDesigns} selected designs in the quick design bar. Changes {_numQuickDesignEnabled} designs.";
|
||||
if (ImUtf8.ButtonEx("Hide Selected Designs in QDB"u8, tt, buttonWidth, _numQuickDesignEnabled == 0))
|
||||
{
|
||||
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
|
||||
editor.SetQuickDesign(design.Value, false);
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
}
|
||||
|
||||
|
|
@ -327,8 +335,10 @@ public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager e
|
|||
: $"Set the color of {_addDesigns.Count} designs to \"{_colorCombo.CurrentSelection}\"\n\n\t{string.Join("\n\t", _addDesigns.Select(m => m.Name.Text))}";
|
||||
ImGui.SameLine();
|
||||
if (ImUtf8.ButtonEx(label, tooltip, width, _addDesigns.Count == 0))
|
||||
{
|
||||
foreach (var design in _addDesigns)
|
||||
editor.ChangeColor(design, _colorCombo.CurrentSelection!);
|
||||
}
|
||||
|
||||
label = _removeDesigns.Count > 0
|
||||
? $"Unset {_removeDesigns.Count} Designs"
|
||||
|
|
@ -338,8 +348,10 @@ public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager e
|
|||
: $"Set {_removeDesigns.Count} designs to use automatic color again:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name.Text))}";
|
||||
ImGui.SameLine();
|
||||
if (ImUtf8.ButtonEx(label, tooltip, width, _removeDesigns.Count == 0))
|
||||
{
|
||||
foreach (var (design, _) in _removeDesigns)
|
||||
editor.ChangeColor(design, string.Empty);
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
}
|
||||
|
|
@ -455,7 +467,8 @@ public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager e
|
|||
|
||||
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>().Select(l => l.Value))
|
||||
{
|
||||
editor.ChangeApplyMulti(design, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null, equip, equip, equip);
|
||||
editor.ChangeApplyMulti(design, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null, equip, equip,
|
||||
equip);
|
||||
if (equip.HasValue)
|
||||
{
|
||||
editor.ChangeApplyMeta(design, MetaIndex.HatState, equip.Value);
|
||||
|
|
@ -477,7 +490,7 @@ public class MultiDesignPanel(DesignFileSystemSelector selector, DesignManager e
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.GameData;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue