Compare commits

..

No commits in common. "main" and "1.3.7.1" have entirely different histories.

165 changed files with 1210 additions and 2388 deletions

View file

@ -15,12 +15,12 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '9.x.x' dotnet-version: '8.x.x'
- name: Restore dependencies - name: Restore dependencies
run: dotnet restore run: dotnet restore
- name: Download Dalamud - name: Download Dalamud
run: | run: |
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip
Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev"
- name: Build - name: Build
run: | run: |

View file

@ -15,7 +15,7 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '9.x.x' dotnet-version: '8.x.x'
- name: Restore dependencies - name: Restore dependencies
run: dotnet restore run: dotnet restore
- name: Download Dalamud - name: Download Dalamud

@ -1 +1 @@
Subproject commit 59a7ab5fa9941eb754757b62e4cb189e455e9514 Subproject commit 9f9bdf0873899d2e45fabaca446bb1624303b418

View file

@ -7,7 +7,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
.github\workflows\release.yml = .github\workflows\release.yml .github\workflows\release.yml = .github\workflows\release.yml
Glamourer\Glamourer.json = Glamourer\Glamourer.json
repo.json = repo.json repo.json = repo.json
.github\workflows\test_release.yml = .github\workflows\test_release.yml .github\workflows\test_release.yml = .github\workflows\test_release.yml
EndProjectSection EndProjectSection
@ -30,30 +29,30 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.ActiveCfg = Debug|x64 {01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.Build.0 = Debug|x64 {01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.ActiveCfg = Release|x64 {01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.Build.0 = Release|x64 {01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.Build.0 = Release|Any CPU
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.ActiveCfg = Debug|x64 {29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.Build.0 = Debug|x64 {29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.ActiveCfg = Release|x64 {29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.Build.0 = Release|x64 {29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.Build.0 = Release|Any CPU
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.ActiveCfg = Debug|x64 {C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.Build.0 = Debug|x64 {C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.ActiveCfg = Release|x64 {C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.Build.0 = Release|x64 {C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.Build.0 = Release|Any CPU
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.ActiveCfg = Debug|x64 {AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.Build.0 = Debug|x64 {AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.ActiveCfg = Release|x64 {AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|x64 {AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|Any CPU
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.ActiveCfg = Debug|x64 {EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.Build.0 = Debug|x64 {EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.ActiveCfg = Release|x64 {EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.Build.0 = Release|x64 {EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.Build.0 = Release|Any CPU
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|x64 {9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|x64 {9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.ActiveCfg = Release|x64 {9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.Build.0 = Release|x64 {9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -1,43 +1,33 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Extensions; using OtterGui;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
using Penumbra.String; using Penumbra.String;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Api; namespace Glamourer.Api;
public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal IEnumerable<ActorState> FindExistingStates(string actorName, ushort worldId = ushort.MaxValue) internal IEnumerable<ActorState> FindExistingStates(string actorName)
{ {
if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString)) if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString))
yield break; yield break;
if (worldId == WorldId.AnyWorld.Id) foreach (var state in stateManager.Values.Where(state
{ => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
foreach (var state in stateManager.Values.Where(state yield return 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)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state) internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
{ {
var actor = objects.Objects[objectIndex]; var actor = objects[objectIndex];
var identifier = actor.GetIdentifier(actors); var identifier = actor.GetIdentifier(actors);
if (!identifier.IsValid) if (!identifier.IsValid)
{ {
@ -52,7 +42,7 @@ public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, A
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal ActorState? FindState(int objectIndex) internal ActorState? FindState(int objectIndex)
{ {
var actor = objects.Objects[objectIndex]; var actor = objects[objectIndex];
var identifier = actor.GetIdentifier(actors); var identifier = actor.GetIdentifier(actors);
if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var state)) if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var state))
return state; return state;
@ -83,8 +73,10 @@ public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, A
if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString)) if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString))
return []; return [];
objects.Update();
return stateManager.Values.Where(state => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString) return stateManager.Values.Where(state => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString)
.Concat(objects .Concat(objects.Identifiers
.Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString) .Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString)
.SelectWhere(kvp => .SelectWhere(kvp =>
{ {

View file

@ -2,32 +2,15 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.State; using Glamourer.State;
using Newtonsoft.Json.Linq;
using OtterGui.Services; using OtterGui.Services;
namespace Glamourer.Api; namespace Glamourer.Api;
public class DesignsApi( public class DesignsApi(ApiHelpers helpers, DesignManager designs, StateManager stateManager) : IGlamourerApiDesigns, IApiService
ApiHelpers helpers,
DesignManager designs,
StateManager stateManager,
DesignFileSystem fileSystem,
DesignColors color,
DesignConverter converter)
: IGlamourerApiDesigns, IApiService
{ {
public Dictionary<Guid, string> GetDesignList() public Dictionary<Guid, string> GetDesignList()
=> designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text); => designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text);
public Dictionary<Guid, (string DisplayName, string FullPath, uint DisplayColor, bool ShownInQdb)> GetDesignListExtended()
=> 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) public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags)
{ {
var args = ApiHelpers.Args("Design", designId, "Index", objectIndex, "Key", key, "Flags", flags); var args = ApiHelpers.Args("Design", designId, "Index", objectIndex, "Key", key, "Flags", flags);
@ -83,56 +66,4 @@ public class DesignsApi(
return ApiHelpers.Return(GlamourerApiEc.Success, args); 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;
} }

View file

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

View file

@ -24,14 +24,8 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.ApiVersion.Provider(pi, api), IpcSubscribers.ApiVersion.Provider(pi, api),
IpcSubscribers.GetDesignList.Provider(pi, api.Designs), 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.ApplyDesign.Provider(pi, api.Designs),
IpcSubscribers.ApplyDesignName.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.SetItem.Provider(pi, api.Items),
IpcSubscribers.SetItemName.Provider(pi, api.Items), IpcSubscribers.SetItemName.Provider(pi, api.Items),
@ -42,8 +36,6 @@ public sealed class IpcProviders : IDisposable, IApiService
(a, b, c, d, e, f) => (int)api.Items.SetItemName(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f)), (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.SetBonusItem.Provider(pi, api.Items),
IpcSubscribers.SetBonusItemName.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.GetState.Provider(pi, api.State),
IpcSubscribers.GetStateName.Provider(pi, api.State), IpcSubscribers.GetStateName.Provider(pi, api.State),
IpcSubscribers.GetStateBase64.Provider(pi, api.State), IpcSubscribers.GetStateBase64.Provider(pi, api.State),
@ -54,7 +46,6 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.RevertStateName.Provider(pi, api.State), IpcSubscribers.RevertStateName.Provider(pi, api.State),
IpcSubscribers.UnlockState.Provider(pi, api.State), IpcSubscribers.UnlockState.Provider(pi, api.State),
IpcSubscribers.UnlockStateName.Provider(pi, api.State), IpcSubscribers.UnlockStateName.Provider(pi, api.State),
IpcSubscribers.DeletePlayerState.Provider(pi, api.State),
IpcSubscribers.UnlockAll.Provider(pi, api.State), IpcSubscribers.UnlockAll.Provider(pi, api.State),
IpcSubscribers.RevertToAutomation.Provider(pi, api.State), IpcSubscribers.RevertToAutomation.Provider(pi, api.State),
IpcSubscribers.RevertToAutomationName.Provider(pi, api.State), IpcSubscribers.RevertToAutomationName.Provider(pi, api.State),

View file

@ -4,31 +4,34 @@ using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.History; using Glamourer.Designs.History;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using ObjectManager = Glamourer.Interop.ObjectManager;
using StateChanged = Glamourer.Events.StateChanged; using StateChanged = Glamourer.Events.StateChanged;
namespace Glamourer.Api; namespace Glamourer.Api;
public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
{ {
private readonly ApiHelpers _helpers; private readonly ApiHelpers _helpers;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly AutoDesignApplier _autoDesigns; private readonly Configuration _config;
private readonly ActorObjectManager _objects; private readonly AutoDesignApplier _autoDesigns;
private readonly StateChanged _stateChanged; private readonly ObjectManager _objects;
private readonly StateFinalized _stateFinalized; private readonly StateChanged _stateChanged;
private readonly GPoseService _gPose; private readonly StateFinalized _stateFinalized;
private readonly GPoseService _gPose;
public StateApi(ApiHelpers helpers, public StateApi(ApiHelpers helpers,
StateManager stateManager, StateManager stateManager,
DesignConverter converter, DesignConverter converter,
Configuration config,
AutoDesignApplier autoDesigns, AutoDesignApplier autoDesigns,
ActorObjectManager objects, ObjectManager objects,
StateChanged stateChanged, StateChanged stateChanged,
StateFinalized stateFinalized, StateFinalized stateFinalized,
GPoseService gPose) GPoseService gPose)
@ -36,6 +39,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
_helpers = helpers; _helpers = helpers;
_stateManager = stateManager; _stateManager = stateManager;
_converter = converter; _converter = converter;
_config = config;
_autoDesigns = autoDesigns; _autoDesigns = autoDesigns;
_objects = objects; _objects = objects;
_stateChanged = stateChanged; _stateChanged = stateChanged;
@ -200,27 +204,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
return ApiHelpers.Return(GlamourerApiEc.Success, args); 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) public int UnlockAll(uint key)
=> _stateManager.Values.Count(state => state.Unlock(key)); => _stateManager.Values.Count(state => state.Unlock(key));
@ -236,7 +219,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
if (!state.CanUnlock(key)) if (!state.CanUnlock(key))
return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args); return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args);
RevertToAutomation(_objects.Objects[objectIndex], state, key, flags); RevertToAutomation(_objects[objectIndex], state, key, flags);
return ApiHelpers.Return(GlamourerApiEc.Success, args); return ApiHelpers.Return(GlamourerApiEc.Success, args);
} }
@ -289,9 +272,15 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
var source = (flags & ApplyFlag.Once) != 0 ? StateSource.IpcManual : StateSource.IpcFixed; var source = (flags & ApplyFlag.Once) != 0 ? StateSource.IpcManual : StateSource.IpcFixed;
switch (flags & (ApplyFlag.Equipment | ApplyFlag.Customization)) switch (flags & (ApplyFlag.Equipment | ApplyFlag.Customization))
{ {
case ApplyFlag.Equipment: _stateManager.ResetEquip(state, source, key); break; case ApplyFlag.Equipment:
case ApplyFlag.Customization: _stateManager.ResetCustomize(state, source, key); break; _stateManager.ResetEquip(state, source, key);
case ApplyFlag.Equipment | ApplyFlag.Customization: _stateManager.ResetState(state, source, key, true); break; break;
case ApplyFlag.Customization:
_stateManager.ResetCustomize(state, source, key);
break;
case ApplyFlag.Equipment | ApplyFlag.Customization:
_stateManager.ResetState(state, source, key);
break;
} }
ApiHelpers.Lock(state, key, flags); ApiHelpers.Lock(state, key, flags);
@ -299,6 +288,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
private GlamourerApiEc RevertToAutomation(ActorState state, uint key, ApplyFlag flags) private GlamourerApiEc RevertToAutomation(ActorState state, uint key, ApplyFlag flags)
{ {
_objects.Update();
if (!_objects.TryGetValue(state.Identifier, out var actors) || !actors.Valid) if (!_objects.TryGetValue(state.Identifier, out var actors) || !actors.Valid)
return GlamourerApiEc.ActorNotFound; return GlamourerApiEc.ActorNotFound;

View file

@ -38,7 +38,7 @@ public static class ApplicationTypeExtensions
var customizeFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeFlagExtensions.All : 0; var customizeFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeFlagExtensions.All : 0;
var parameterFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeParameterExtensions.All : 0; var parameterFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeParameterExtensions.All : 0;
var crestFlags = type.HasFlag(ApplicationType.GearCustomization) ? CrestExtensions.AllRelevant : 0; var crestFlags = type.HasFlag(ApplicationType.GearCustomization) ? CrestExtensions.AllRelevant : 0;
var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.EarState : 0) var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState : 0)
| (type.HasFlag(ApplicationType.Weapons) ? MetaFlag.WeaponState : 0) | (type.HasFlag(ApplicationType.Weapons) ? MetaFlag.WeaponState : 0)
| (type.HasFlag(ApplicationType.Customizations) ? MetaFlag.Wetness : 0); | (type.HasFlag(ApplicationType.Customizations) ? MetaFlag.Wetness : 0);
var bonusFlags = type.HasFlag(ApplicationType.Armor) ? BonusExtensions.All : 0; var bonusFlags = type.HasFlag(ApplicationType.Armor) ? BonusExtensions.All : 0;
@ -47,13 +47,7 @@ public static class ApplicationTypeExtensions
} }
public static ApplicationCollection ApplyWhat(this ApplicationType type, IDesignStandIn designStandIn) public static ApplicationCollection ApplyWhat(this ApplicationType type, IDesignStandIn designStandIn)
{ => designStandIn is not DesignBase design ? type.Collection() : type.Collection().Restrict(design.Application);
if(designStandIn is not DesignBase design)
return type.Collection();
var ret = type.Collection().Restrict(design.Application);
ret.CustomizeRaw = ret.CustomizeRaw.FixApplication(design.CustomizeSet);
return ret;
}
public const EquipFlag WeaponFlags = EquipFlag.Mainhand | EquipFlag.Offhand; public const EquipFlag WeaponFlags = EquipFlag.Mainhand | EquipFlag.Offhand;
public const EquipFlag ArmorFlags = EquipFlag.Head | EquipFlag.Body | EquipFlag.Hands | EquipFlag.Legs | EquipFlag.Feet; public const EquipFlag ArmorFlags = EquipFlag.Head | EquipFlag.Body | EquipFlag.Hands | EquipFlag.Legs | EquipFlag.Feet;

View file

@ -11,28 +11,29 @@ using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Automation; namespace Glamourer.Automation;
public sealed class AutoDesignApplier : IDisposable public sealed class AutoDesignApplier : IDisposable
{ {
private readonly Configuration _config; private readonly Configuration _config;
private readonly AutoDesignManager _manager; private readonly AutoDesignManager _manager;
private readonly StateManager _state; private readonly StateManager _state;
private readonly JobService _jobs; private readonly JobService _jobs;
private readonly EquippedGearset _equippedGearset; private readonly EquippedGearset _equippedGearset;
private readonly ActorManager _actors; private readonly ActorManager _actors;
private readonly AutomationChanged _event; private readonly AutomationChanged _event;
private readonly ActorObjectManager _objects; private readonly ObjectManager _objects;
private readonly WeaponLoading _weapons; private readonly WeaponLoading _weapons;
private readonly HumanModelList _humans; private readonly HumanModelList _humans;
private readonly DesignMerger _designMerger; private readonly DesignMerger _designMerger;
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly JobChangeState _jobChangeState; private readonly JobChangeState _jobChangeState;
public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors, public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors,
AutomationChanged @event, ActorObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState, AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState) EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState)
{ {
_config = config; _config = config;
@ -153,6 +154,7 @@ public sealed class AutoDesignApplier : IDisposable
if (newSet is not { Enabled: true }) if (newSet is not { Enabled: true })
return; return;
_objects.Update();
foreach (var id in newSet.Identifiers) foreach (var id in newSet.Identifiers)
{ {
if (_objects.TryGetValue(id, out var data)) if (_objects.TryGetValue(id, out var data))

View file

@ -10,7 +10,6 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;

View file

@ -8,7 +8,6 @@ using Glamourer.Services;
using Newtonsoft.Json; using Newtonsoft.Json;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using OtterGui.Widgets; using OtterGui.Widgets;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
@ -32,7 +31,6 @@ public class DefaultDesignSettings
public bool ResetAdvancedDyes = false; public bool ResetAdvancedDyes = false;
public bool ShowQuickDesignBar = true; public bool ShowQuickDesignBar = true;
public bool ResetTemporarySettings = false; public bool ResetTemporarySettings = false;
public bool Locked = false;
} }
public class Configuration : IPluginConfiguration, ISavable public class Configuration : IPluginConfiguration, ISavable
@ -40,37 +38,33 @@ public class Configuration : IPluginConfiguration, ISavable
[JsonIgnore] [JsonIgnore]
public readonly EphemeralConfig Ephemeral; public readonly EphemeralConfig Ephemeral;
public bool AttachToPcp { get; set; } = true; public bool UseRestrictedGearProtection { get; set; } = false;
public bool UseRestrictedGearProtection { get; set; } = false; public bool OpenFoldersByDefault { get; set; } = false;
public bool OpenFoldersByDefault { get; set; } = false; public bool AutoRedrawEquipOnChanges { get; set; } = false;
public bool AutoRedrawEquipOnChanges { get; set; } = false; public bool EnableAutoDesigns { get; set; } = true;
public bool EnableAutoDesigns { get; set; } = true; public bool HideApplyCheckmarks { get; set; } = false;
public bool HideApplyCheckmarks { get; set; } = false; public bool SmallEquip { get; set; } = false;
public bool SmallEquip { get; set; } = false; public bool UnlockedItemMode { get; set; } = false;
public bool UnlockedItemMode { get; set; } = false; public byte DisableFestivals { get; set; } = 1;
public byte DisableFestivals { get; set; } = 1; public bool EnableGameContextMenu { get; set; } = true;
public bool EnableGameContextMenu { get; set; } = true; public bool HideWindowInCutscene { get; set; } = false;
public bool HideWindowInCutscene { get; set; } = false; public bool ShowAutomationSetEditing { get; set; } = true;
public bool ShowAutomationSetEditing { get; set; } = true; public bool ShowAllAutomatedApplicationRules { get; set; } = true;
public bool ShowAllAutomatedApplicationRules { get; set; } = true; public bool ShowUnlockedItemWarnings { get; set; } = true;
public bool ShowUnlockedItemWarnings { get; set; } = true; public bool RevertManualChangesOnZoneChange { get; set; } = false;
public bool RevertManualChangesOnZoneChange { get; set; } = false; public bool ShowQuickBarInTabs { get; set; } = true;
public bool ShowQuickBarInTabs { get; set; } = true; public bool OpenWindowAtStart { get; set; } = false;
public bool OpenWindowAtStart { get; set; } = false; public bool ShowWindowWhenUiHidden { get; set; } = false;
public bool ShowWindowWhenUiHidden { get; set; } = false; public bool KeepAdvancedDyesAttached { get; set; } = true;
public bool KeepAdvancedDyesAttached { get; set; } = true; public bool ShowPalettePlusImport { get; set; } = true;
public bool ShowPalettePlusImport { get; set; } = true; public bool UseFloatForColors { get; set; } = true;
public bool UseFloatForColors { get; set; } = true; public bool UseRgbForColors { get; set; } = true;
public bool UseRgbForColors { get; set; } = true; public bool ShowColorConfig { get; set; } = true;
public bool ShowColorConfig { get; set; } = true; public bool ChangeEntireItem { get; set; } = false;
public bool ChangeEntireItem { get; set; } = false; public bool AlwaysApplyAssociatedMods { get; set; } = false;
public bool AlwaysApplyAssociatedMods { get; set; } = true; public bool UseTemporarySettings { get; set; } = true;
public bool UseTemporarySettings { get; set; } = true; public bool AllowDoubleClickToApply { get; set; } = false;
public bool AllowDoubleClickToApply { get; set; } = false; public bool RespectManualOnAutomationUpdate { 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 HideDesignPanel { get; set; } = 0;
public DesignPanelFlag AutoExpandDesignPanel { get; set; } = 0; public DesignPanelFlag AutoExpandDesignPanel { get; set; } = 0;
@ -81,11 +75,10 @@ public class Configuration : IPluginConfiguration, ISavable
public RenameField ShowRename { get; set; } = RenameField.BothDataPrio; public RenameField ShowRename { get; set; } = RenameField.BothDataPrio;
public ModifiableHotkey ToggleQuickDesignBar { get; set; } = new(VirtualKey.NO_KEY); public ModifiableHotkey ToggleQuickDesignBar { get; set; } = new(VirtualKey.NO_KEY);
public DoubleModifier DeleteDesignModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift); public DoubleModifier DeleteDesignModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift);
public DoubleModifier IncognitoModifier { get; set; } = new(ModifierHotkey.Control);
public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New; public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New;
public QdbButtons QdbButtons { get; set; } = public QdbButtons QdbButtons { get; set; } =
QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvancedDyes; QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvanced;
[JsonConverter(typeof(SortModeConverter))] [JsonConverter(typeof(SortModeConverter))]
[JsonProperty(Order = int.MaxValue)] [JsonProperty(Order = int.MaxValue)]
@ -162,7 +155,7 @@ public class Configuration : IPluginConfiguration, ISavable
public static class Constants public static class Constants
{ {
public const int CurrentVersion = 8; public const int CurrentVersion = 7;
public static readonly ISortMode<Design>[] ValidSortModes = public static readonly ISortMode<Design>[] ValidSortModes =
[ [

View file

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

View file

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

View file

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

View file

@ -100,7 +100,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
public new JObject JsonSerialize() public new JObject JsonSerialize()
{ {
var ret = new JObject var ret = new JObject()
{ {
["FileVersion"] = FileVersion, ["FileVersion"] = FileVersion,
["Identifier"] = Identifier, ["Identifier"] = Identifier,
@ -131,17 +131,12 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
var ret = new JArray(); var ret = new JArray();
foreach (var (mod, settings) in AssociatedMods) foreach (var (mod, settings) in AssociatedMods)
{ {
var obj = new JObject var obj = new JObject()
{ {
["Name"] = mod.Name, ["Name"] = mod.Name,
["Directory"] = mod.DirectoryName, ["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) if (settings.Enabled)
{ {
obj["Priority"] = settings.Priority; obj["Priority"] = settings.Priority;

View file

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

View file

@ -1,7 +1,6 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Services; using Glamourer.Services;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;

View file

@ -3,12 +3,11 @@ using Dalamud.Interface.ImGuiNotification;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Glamourer.Gui; using Glamourer.Gui;
using Glamourer.Services; using Glamourer.Services;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
namespace Glamourer.Designs; namespace Glamourer.Designs;

View file

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

View file

@ -41,11 +41,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
public struct CreationDate : ISortMode<Design> public struct CreationDate : ISortMode<Design>
{ {
public ReadOnlySpan<byte> Name public string Name
=> "Creation Date (Older First)"u8; => "Creation Date (Older First)";
public ReadOnlySpan<byte> Description public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date."u8; => "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date.";
public IEnumerable<IPath> GetChildren(Folder f) public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.CreationDate)); => 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 struct UpdateDate : ISortMode<Design>
{ {
public ReadOnlySpan<byte> Name public string Name
=> "Update Date (Older First)"u8; => "Update Date (Older First)";
public ReadOnlySpan<byte> Description public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date."u8; => "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date.";
public IEnumerable<IPath> GetChildren(Folder f) public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.LastEdit)); => 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 struct InverseCreationDate : ISortMode<Design>
{ {
public ReadOnlySpan<byte> Name public string Name
=> "Creation Date (Newer First)"u8; => "Creation Date (Newer First)";
public ReadOnlySpan<byte> Description public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date."u8; => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date.";
public IEnumerable<IPath> GetChildren(Folder f) public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.CreationDate)); => 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 struct InverseUpdateDate : ISortMode<Design>
{ {
public ReadOnlySpan<byte> Name public string Name
=> "Update Date (Newer First)"u8; => "Update Date (Newer First)";
public ReadOnlySpan<byte> Description public string Description
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date."u8; => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date.";
public IEnumerable<IPath> GetChildren(Folder f) public IEnumerable<IPath> GetChildren(Folder f)
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.LastEdit)); => 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; return;
case DesignChanged.Type.Deleted: case DesignChanged.Type.Deleted:
if (TryGetValue(design, out var leaf1)) if (FindLeaf(design, out var leaf1))
Delete(leaf1); Delete(leaf1);
return; return;
case DesignChanged.Type.ReloadedAll: case DesignChanged.Type.ReloadedAll:
Reload(); Reload();
return; return;
case DesignChanged.Type.Renamed when (data as RenameTransaction?)?.Old is { } oldName: case DesignChanged.Type.Renamed when (data as RenameTransaction?)?.Old is { } oldName:
if (!TryGetValue(design, out var leaf2)) if (!FindLeaf(design, out var leaf2))
return; return;
var old = oldName.FixName(); var old = oldName.FixName();
@ -150,6 +150,15 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
? (string.Empty, false) ? (string.Empty, false)
: (DesignToIdentifier(design), true); : (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) internal static void MigrateOldPaths(SaveService saveService, Dictionary<string, string> oldPaths)
{ {
if (oldPaths.Count == 0) if (oldPaths.Count == 0)

View file

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

View file

@ -1,8 +1,8 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Interop;
namespace Glamourer.Designs.History; namespace Glamourer.Designs.History;
@ -152,7 +152,7 @@ public class EditorHistory : IDisposable, IService
{ {
if (!_stateEntries.TryGetValue(state, out var list)) if (!_stateEntries.TryGetValue(state, out var list))
{ {
list = []; list = new Queue();
_stateEntries.Add(state, list); _stateEntries.Add(state, list);
} }
@ -163,7 +163,7 @@ public class EditorHistory : IDisposable, IService
{ {
if (!_designEntries.TryGetValue(design, out var list)) if (!_designEntries.TryGetValue(design, out var list))
{ {
list = []; list = new Queue();
_designEntries.Add(design, list); _designEntries.Add(design, list);
} }

View file

@ -1,6 +1,6 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Services; using OtterGui.Services;
using Notification = OtterGui.Classes.Notification; using Notification = OtterGui.Classes.Notification;

View file

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

View file

@ -1,33 +1,19 @@
using OtterGui; using OtterGui.Services;
using OtterGui.Services;
namespace Glamourer.Designs.Special; namespace Glamourer.Designs.Special;
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration config) : IService public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem) : 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) public Design? Design(IReadOnlyList<Design> localDesigns)
{ {
if (localDesigns.Count is 0) if (localDesigns.Count == 0)
return null; return null;
var idx = _rng.Next(0, localDesigns.Count); var idx = _rng.Next(0, localDesigns.Count);
if (localDesigns.Count is 1) Glamourer.Log.Verbose($"[Random Design] Chose design {idx + 1} out of {localDesigns.Count}: {localDesigns[idx].Incognito}.");
{ return localDesigns[idx];
_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() public Design? Design()
@ -38,12 +24,12 @@ public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileS
public Design? Design(IReadOnlyList<IDesignPredicate> predicates) public Design? Design(IReadOnlyList<IDesignPredicate> predicates)
{ {
return predicates.Count switch if (predicates.Count == 0)
{ return Design();
0 => Design(), if (predicates.Count == 1)
1 => Design(predicates[0]), return Design(predicates[0]);
_ => Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList()),
}; return Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList());
} }
public Design? Design(string restrictions) public Design? Design(string restrictions)

View file

@ -22,7 +22,7 @@ public interface IDesignPredicate
: designs; : designs;
private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d, DesignFileSystem fs) private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d, DesignFileSystem fs)
=> (d, d.Name.Lower, d.Identifier.ToString(), fs.TryGetValue(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty); => (d, d.Name.Lower, d.Identifier.ToString(), fs.FindLeaf(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty);
} }
public static class RandomPredicate public static class RandomPredicate

View file

@ -20,10 +20,6 @@ public class EphemeralConfig : ISavable
public Guid SelectedQuickDesign { get; set; } = Guid.Empty; public Guid SelectedQuickDesign { get; set; } = Guid.Empty;
public int LastSeenVersion { get; set; } = GlamourerChangelog.LastChangelogVersion; 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] [JsonIgnore]
private readonly SaveService _saveService; private readonly SaveService _saveService;

View file

@ -11,7 +11,7 @@ namespace Glamourer.Events;
/// </list> /// </list>
/// </summary> /// </summary>
public sealed class GearsetDataLoaded() public sealed class GearsetDataLoaded()
: EventWrapper<Actor, Model, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded)) : EventWrapper<Model, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded))
{ {
public enum Priority public enum Priority
{ {

View file

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

View file

@ -3,7 +3,6 @@ using Glamourer.Designs.History;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Classes; using OtterGui.Classes;
using Penumbra.GameData.Interop;
namespace Glamourer.Events; namespace Glamourer.Events;

View file

@ -2,7 +2,6 @@ using Glamourer.Api;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using OtterGui.Classes; using OtterGui.Classes;
using Penumbra.GameData.Interop;
namespace Glamourer.Events; namespace Glamourer.Events;

View file

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

View file

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

View file

@ -1,5 +1,4 @@
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using Race = Penumbra.GameData.Enums.Race; using Race = Penumbra.GameData.Enums.Race;

View file

@ -6,10 +6,12 @@ using Glamourer.Gui;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Interop; using Penumbra.GameData.Enums;
using Penumbra.GameData.Files;
namespace Glamourer; namespace Glamourer;
@ -26,7 +28,6 @@ public class Glamourer : IDalamudPlugin
public static readonly Logger Log = new(); public static readonly Logger Log = new();
public static MessageService Messager { get; private set; } = null!; public static MessageService Messager { get; private set; } = null!;
public static DynamisIpc Dynamis { get; private set; } = null!;
private readonly ServiceManager _services; private readonly ServiceManager _services;
@ -36,7 +37,6 @@ public class Glamourer : IDalamudPlugin
{ {
_services = StaticServiceManager.CreateProvider(pluginInterface, Log, this); _services = StaticServiceManager.CreateProvider(pluginInterface, Log, this);
Messager = _services.GetService<MessageService>(); Messager = _services.GetService<MessageService>();
Dynamis = _services.GetService<DynamisIpc>();
_services.EnsureRequiredServices(); _services.EnsureRequiredServices();
_services.GetService<VisorService>(); _services.GetService<VisorService>();
@ -71,7 +71,6 @@ public class Glamourer : IDalamudPlugin
sb.Append($"> **`Festival Easter-Eggs: `** {config.DisableFestivals}\n"); sb.Append($"> **`Festival Easter-Eggs: `** {config.DisableFestivals}\n");
sb.Append($"> **`Apply Entire Weapon: `** {config.ChangeEntireItem}\n"); sb.Append($"> **`Apply Entire Weapon: `** {config.ChangeEntireItem}\n");
sb.Append($"> **`Apply Associated Mods:`** {config.AlwaysApplyAssociatedMods}\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($"> **`Hidden Panels: `** {config.HideDesignPanel}\n");
sb.Append($"> **`Show QDB: `** {config.Ephemeral.ShowDesignQuickBar}\n"); sb.Append($"> **`Show QDB: `** {config.Ephemeral.ShowDesignQuickBar}\n");
sb.Append($"> **`QDB Hotkey: `** {config.ToggleQuickDesignBar}\n"); sb.Append($"> **`QDB Hotkey: `** {config.ToggleQuickDesignBar}\n");
@ -83,7 +82,7 @@ public class Glamourer : IDalamudPlugin
var designManager = _services.GetService<DesignManager>(); var designManager = _services.GetService<DesignManager>();
var autoManager = _services.GetService<AutoDesignManager>(); var autoManager = _services.GetService<AutoDesignManager>();
var stateManager = _services.GetService<StateManager>(); var stateManager = _services.GetService<StateManager>();
var objectManager = _services.GetService<ActorObjectManager>(); var objectManager = _services.GetService<ObjectManager>();
var currentPlayer = objectManager.PlayerData.Identifier; var currentPlayer = objectManager.PlayerData.Identifier;
var states = stateManager.Where(kvp => objectManager.ContainsKey(kvp.Key)).ToList(); var states = stateManager.Where(kvp => objectManager.ContainsKey(kvp.Key)).ToList();

View file

@ -1,32 +1,92 @@
<Project Sdk="Dalamud.NET.Sdk/13.1.0"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<LangVersion>preview</LangVersion>
<PlatformTarget>x64</PlatformTarget>
<RootNamespace>Glamourer</RootNamespace> <RootNamespace>Glamourer</RootNamespace>
<AssemblyName>Glamourer</AssemblyName> <AssemblyName>Glamourer</AssemblyName>
<FileVersion>9.0.0.1</FileVersion> <FileVersion>9.0.0.1</FileVersion>
<AssemblyVersion>9.0.0.1</AssemblyVersion> <AssemblyVersion>9.0.0.1</AssemblyVersion>
<Company>SoftOtter</Company>
<Product>Glamourer</Product> <Product>Glamourer</Product>
<Copyright>Copyright © 2025</Copyright> <Copyright>Copyright © 2023</Copyright>
<Deterministic>true</Deterministic>
<OutputType>Library</OutputType>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<OutputPath>bin\$(Configuration)\</OutputPath> <OutputPath>bin\$(Configuration)\</OutputPath>
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="LegacyTattoo.raw" /> <None Remove="LegacyTattoo.raw" />
<None Include="Glamourer.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="LegacyTattoo.raw" /> <EmbeddedResource Include="LegacyTattoo.raw" />
</ItemGroup> </ItemGroup>
<PropertyGroup>
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dalamud">
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImGuiScene">
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" /> <ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" />
<ProjectReference Include="..\OtterGui\OtterGui.csproj" /> <ProjectReference Include="..\OtterGui\OtterGui.csproj" />
<ProjectReference Include="..\Penumbra.Api\Penumbra.Api.csproj" /> <ProjectReference Include="..\Penumbra.Api\Penumbra.Api.csproj" />
<ProjectReference Include="..\Penumbra.String\Penumbra.String.csproj" /> <ProjectReference Include="..\Penumbra.String\Penumbra.string.csproj" />
<ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" /> <ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" />
<PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" /> <PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" />
</ItemGroup> </ItemGroup>
@ -56,4 +116,14 @@
<InformationalVersion>$(GitCommitHash)</InformationalVersion> <InformationalVersion>$(GitCommitHash)</InformationalVersion>
</PropertyGroup> </PropertyGroup>
</Target> </Target>
<ItemGroup>
<None Update="Glamourer.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="if $(Configuration) == Release powershell Copy-Item -Force $(TargetDir)$(SolutionName).json -Destination $(SolutionDir)" />
</Target>
</Project> </Project>

View file

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

View file

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

View file

@ -1,83 +1,16 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Glamourer.GameData; using Glamourer.GameData;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text;
using OtterGui.Text.EndObjects;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using System;
namespace Glamourer.Gui.Customization; namespace Glamourer.Gui.Customization;
public partial class CustomizationDrawer 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) private void DrawColorPicker(CustomizeIndex index)
{ {
@ -88,7 +21,7 @@ public partial class CustomizationDrawer
using (_ = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale, current < 0)) using (_ = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale, current < 0))
{ {
if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.NoDragDrop, _framedIconSize)) if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.None, _framedIconSize))
{ {
ImGui.OpenPopup(ColorPickerPopupName); ImGui.OpenPopup(ColorPickerPopupName);
} }
@ -97,9 +30,6 @@ public partial class CustomizationDrawer
var data = _set.Data(_currentIndex, current, _customize.Face); var data = _set.Data(_currentIndex, current, _customize.Face);
UpdateValue(data.Value); UpdateValue(data.Value);
} }
DrawDragDropSource(index, custom);
DrawDragDropTarget(index);
} }
var npc = false; var npc = false;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,10 +5,9 @@ using Glamourer.Designs;
using Glamourer.Designs.History; using Glamourer.Designs.History;
using Glamourer.Designs.Special; using Glamourer.Designs.Special;
using Glamourer.Events; using Glamourer.Events;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Widgets; using OtterGui.Widgets;
@ -22,7 +21,6 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
protected readonly TabSelected TabSelected; protected readonly TabSelected TabSelected;
protected float InnerWidth; protected float InnerWidth;
private IDesignStandIn? _currentDesign; private IDesignStandIn? _currentDesign;
private bool _isCurrentSelectionDirty;
protected DesignComboBase(Func<IReadOnlyList<Tuple<IDesignStandIn, string>>> generator, Logger log, DesignChanged designChanged, protected DesignComboBase(Func<IReadOnlyList<Tuple<IDesignStandIn, string>>> generator, Logger log, DesignChanged designChanged,
TabSelected tabSelected, EphemeralConfig config, DesignColors designColors) TabSelected tabSelected, EphemeralConfig config, DesignColors designColors)
@ -85,11 +83,17 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
DrawRightAligned(quickDesign.ResolveName(false), "[Nothing]", DesignColors.MissingColor); 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) protected bool Draw(IDesignStandIn? currentDesign, string? label, float width)
{ {
_currentDesign = currentDesign; _currentDesign = currentDesign;
UpdateCurrentSelection(); InnerWidth = 400 * ImGuiHelpers.GlobalScale;
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
var name = label ?? "Select Design Here..."; var name = label ?? "Select Design Here...";
bool ret; bool ret;
using (_ = currentDesign != null ? ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(currentDesign as Design)) : null) using (_ = currentDesign != null ? ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(currentDesign as Design)) : null)
@ -123,60 +127,37 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
return filter.IsContained(path) || filter.IsContained(design.ResolveName(false)); return filter.IsContained(path) || filter.IsContained(design.ResolveName(false));
} }
protected override void OnMouseWheel(string preview, ref int _2, int steps) private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _ = null)
{ {
if (!ReferenceEquals(_currentDesign, CurrentSelection?.Item1)) switch (type)
CurrentSelectionIdx = -1;
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]); 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 (!priorState)
Cleanup();
break;
} }
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) private void QuickSelectedDesignTooltip(IDesignStandIn? design)
@ -194,7 +175,7 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
ImGui.TextUnformatted("Currently resolving to "); ImGui.TextUnformatted("Currently resolving to ");
using var color = ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(linkedDesign)); using var color = ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(linkedDesign));
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
ImGui.TextUnformatted(linkedDesign.Name.Text); ImGui.TextUnformatted(linkedDesign.Name);
} }
else else
{ {
@ -244,7 +225,8 @@ public abstract class DesignCombo : DesignComboBase
public sealed class QuickDesignCombo : DesignCombo public sealed class QuickDesignCombo : DesignCombo
{ {
public QuickDesignCombo(DesignFileSystem fileSystem, public QuickDesignCombo(DesignManager designs,
DesignFileSystem fileSystem,
Logger log, Logger log,
DesignChanged designChanged, DesignChanged designChanged,
TabSelected tabSelected, TabSelected tabSelected,
@ -252,9 +234,9 @@ public sealed class QuickDesignCombo : DesignCombo
DesignColors designColors) DesignColors designColors)
: base(log, designChanged, tabSelected, config, designColors, () => : base(log, designChanged, tabSelected, config, designColors, () =>
[ [
.. fileSystem .. designs.Designs
.Where(kvp => kvp.Key.QuickDesign) .Where(d => d.QuickDesign)
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName())) .Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2), .OrderBy(d => d.Item2),
]) ])
{ {
@ -295,6 +277,7 @@ public sealed class QuickDesignCombo : DesignCombo
} }
public sealed class LinkDesignCombo( public sealed class LinkDesignCombo(
DesignManager designs,
DesignFileSystem fileSystem, DesignFileSystem fileSystem,
Logger log, Logger log,
DesignChanged designChanged, DesignChanged designChanged,
@ -303,8 +286,8 @@ public sealed class LinkDesignCombo(
DesignColors designColors) DesignColors designColors)
: DesignCombo(log, designChanged, tabSelected, config, designColors, () => : DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
[ [
.. fileSystem .. designs.Designs
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName())) .Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2), .OrderBy(d => d.Item2),
]); ]);
@ -318,8 +301,8 @@ public sealed class RandomDesignCombo(
DesignColors designColors) DesignColors designColors)
: DesignCombo(log, designChanged, tabSelected, config, designColors, () => : DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
[ [
.. fileSystem .. designs.Designs
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName())) .Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2), .OrderBy(d => d.Item2),
]) ])
{ {
@ -345,6 +328,7 @@ public sealed class RandomDesignCombo(
} }
public sealed class SpecialDesignCombo( public sealed class SpecialDesignCombo(
DesignManager designs,
DesignFileSystem fileSystem, DesignFileSystem fileSystem,
TabSelected tabSelected, TabSelected tabSelected,
DesignColors designColors, DesignColors designColors,
@ -354,8 +338,8 @@ public sealed class SpecialDesignCombo(
EphemeralConfig config, EphemeralConfig config,
RandomDesignGenerator rng, RandomDesignGenerator rng,
QuickSelectedDesign quickSelectedDesign) QuickSelectedDesign quickSelectedDesign)
: DesignComboBase(() => fileSystem : DesignComboBase(() => designs.Designs
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName())) .Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2) .OrderBy(d => d.Item2)
.Prepend(new Tuple<IDesignStandIn, string>(new RandomDesign(rng), string.Empty)) .Prepend(new Tuple<IDesignStandIn, string>(new RandomDesign(rng), string.Empty))
.Prepend(new Tuple<IDesignStandIn, string>(quickSelectedDesign, string.Empty)) .Prepend(new Tuple<IDesignStandIn, string>(quickSelectedDesign, string.Empty))

View file

@ -6,28 +6,28 @@ using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui; namespace Glamourer.Gui;
[Flags] [Flags]
public enum QdbButtons public enum QdbButtons
{ {
ApplyDesign = 0x01, ApplyDesign = 0x01,
RevertAll = 0x02, RevertAll = 0x02,
RevertAutomation = 0x04, RevertAutomation = 0x04,
RevertAdvancedDyes = 0x08, RevertAdvanced = 0x08,
RevertEquip = 0x10, RevertEquip = 0x10,
RevertCustomize = 0x20, RevertCustomize = 0x20,
ReapplyAutomation = 0x40, ReapplyAutomation = 0x40,
ResetSettings = 0x80, ResetSettings = 0x80,
RevertAdvancedCustomization = 0x100,
} }
public sealed class DesignQuickBar : Window, IDisposable public sealed class DesignQuickBar : Window, IDisposable
@ -37,21 +37,21 @@ public sealed class DesignQuickBar : Window, IDisposable
? ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoMove ? ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoMove
: ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing; : ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing;
private readonly Configuration _config; private readonly Configuration _config;
private readonly QuickDesignCombo _designCombo; private readonly QuickDesignCombo _designCombo;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly ActorObjectManager _objects; private readonly ObjectManager _objects;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly IKeyState _keyState; private readonly IKeyState _keyState;
private readonly ImRaii.Style _windowPadding = new(); private readonly ImRaii.Style _windowPadding = new();
private readonly ImRaii.Color _windowColor = new(); private readonly ImRaii.Color _windowColor = new();
private DateTime _keyboardToggle = DateTime.UnixEpoch; private DateTime _keyboardToggle = DateTime.UnixEpoch;
private int _numButtons; private int _numButtons;
private readonly StringBuilder _tooltipBuilder = new(512); private readonly StringBuilder _tooltipBuilder = new(512);
public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState, public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState,
ActorObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra) ObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra)
: base("Glamourer Quick Bar", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking) : base("Glamourer Quick Bar", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking)
{ {
_config = config; _config = config;
@ -64,7 +64,6 @@ public sealed class DesignQuickBar : Window, IDisposable
IsOpen = _config.Ephemeral.ShowDesignQuickBar; IsOpen = _config.Ephemeral.ShowDesignQuickBar;
DisableWindowSounds = true; DisableWindowSounds = true;
Size = Vector2.Zero; Size = Vector2.Zero;
RespectCloseHotkey = false;
} }
public void Dispose() public void Dispose()
@ -126,7 +125,6 @@ public sealed class DesignQuickBar : Window, IDisposable
DrawRevertEquipButton(buttonSize); DrawRevertEquipButton(buttonSize);
DrawRevertCustomizeButton(buttonSize); DrawRevertCustomizeButton(buttonSize);
DrawRevertAdvancedCustomization(buttonSize); DrawRevertAdvancedCustomization(buttonSize);
DrawRevertAdvancedDyes(buttonSize);
DrawRevertAutomationButton(buttonSize); DrawRevertAutomationButton(buttonSize);
DrawReapplyAutomationButton(buttonSize); DrawReapplyAutomationButton(buttonSize);
DrawResetSettingsButton(buttonSize); DrawResetSettingsButton(buttonSize);
@ -175,7 +173,7 @@ public sealed class DesignQuickBar : Window, IDisposable
available |= 2; available |= 2;
_tooltipBuilder.Append("Right-Click: Apply ") _tooltipBuilder.Append("Right-Click: Apply ")
.Append(design.ResolveName(_config.Ephemeral.IncognitoMode)) .Append(design.ResolveName(_config.Ephemeral.IncognitoMode))
.Append(" to ").Append(_config.Ephemeral.IncognitoMode ? _targetIdentifier.Incognito(null) : _targetIdentifier.ToName()); .Append(" to {_targetIdentifier}.");
} }
if (available == 0) if (available == 0)
@ -224,8 +222,7 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append( _tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.UndoAlt, buttonSize, available); var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.UndoAlt, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
@ -261,10 +258,9 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append( _tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.SyncAlt, buttonSize, available); var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.SyncAlt, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
if (!clicked) if (!clicked)
return; return;
@ -304,8 +300,7 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append( _tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.Repeat, buttonSize, available); var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.Repeat, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
@ -321,7 +316,7 @@ public sealed class DesignQuickBar : Window, IDisposable
private void DrawRevertAdvancedCustomization(Vector2 buttonSize) private void DrawRevertAdvancedCustomization(Vector2 buttonSize)
{ {
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization)) if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
return; return;
var available = 0; var available = 0;
@ -330,7 +325,7 @@ public sealed class DesignQuickBar : Window, IDisposable
if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid) if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid)
{ {
available |= 1; available |= 1;
_tooltipBuilder.Append("Left-Click: Revert the advanced customizations of the player character to their game state."); _tooltipBuilder.Append("Left-Click: Revert the advanced customizations and dyes of the player character to their game state.");
} }
if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid) if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid)
@ -338,40 +333,7 @@ public sealed class DesignQuickBar : Window, IDisposable
if (available != 0) if (available != 0)
_tooltipBuilder.Append('\n'); _tooltipBuilder.Append('\n');
available |= 2; available |= 2;
_tooltipBuilder.Append("Right-Click: Revert the advanced customizations of ") _tooltipBuilder.Append("Right-Click: Revert the advanced customizations and dyes 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(_targetIdentifier)
.Append(" to their game state."); .Append(" to their game state.");
} }
@ -382,7 +344,7 @@ public sealed class DesignQuickBar : Window, IDisposable
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.Palette, buttonSize, available); var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.Palette, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
if (clicked) if (clicked)
_stateManager.ResetAdvancedDyes(state!, StateSource.Manual); _stateManager.ResetAdvancedState(state!, StateSource.Manual);
} }
private void DrawRevertCustomizeButton(Vector2 buttonSize) private void DrawRevertCustomizeButton(Vector2 buttonSize)
@ -462,9 +424,7 @@ public sealed class DesignQuickBar : Window, IDisposable
if (_playerIdentifier.IsValid && _playerData.Valid) if (_playerIdentifier.IsValid && _playerData.Valid)
{ {
available |= 1; available |= 1;
_tooltipBuilder _tooltipBuilder.Append("Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(
"Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(_playerIdentifier) .Append(_playerIdentifier)
.Append('.'); .Append('.');
} }
@ -474,9 +434,7 @@ public sealed class DesignQuickBar : Window, IDisposable
if (available != 0) if (available != 0)
_tooltipBuilder.Append('\n'); _tooltipBuilder.Append('\n');
available |= 2; available |= 2;
_tooltipBuilder _tooltipBuilder.Append("Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(
"Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(_targetIdentifier) .Append(_targetIdentifier)
.Append('.'); .Append('.');
} }
@ -537,9 +495,7 @@ public sealed class DesignQuickBar : Window, IDisposable
++_numButtons; ++_numButtons;
} }
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization)) if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
++_numButtons;
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedDyes))
++_numButtons; ++_numButtons;
if (_config.QdbButtons.HasFlag(QdbButtons.RevertCustomize)) if (_config.QdbButtons.HasFlag(QdbButtons.RevertCustomize))
++_numButtons; ++_numButtons;

View file

@ -1,11 +1,10 @@
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;

View file

@ -27,9 +27,6 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData)
public readonly void SetStains(StainIds stains) public readonly void SetStains(StainIds stains)
=> _editor.ChangeStains(_object, Slot, stains, ApplySettings.Manual); => _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) public readonly void SetApplyItem(bool value)
{ {
var manager = (DesignManager)_editor; var manager = (DesignManager)_editor;

View file

@ -1,83 +0,0 @@
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;
}
}

View file

@ -3,15 +3,15 @@ using Dalamud.Interface.Utility;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Gui.Materials; using Glamourer.Gui.Materials;
using Glamourer.Interop.Material;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui.Extensions; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using OtterGui.Text.EndObjects; using OtterGui.Text.EndObjects;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.GameData.Data;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
@ -32,24 +32,20 @@ public class EquipmentDrawer
private readonly Configuration _config; private readonly Configuration _config;
private readonly GPoseService _gPose; private readonly GPoseService _gPose;
private readonly AdvancedDyePopup _advancedDyes; private readonly AdvancedDyePopup _advancedDyes;
private readonly ItemCopyService _itemCopy;
private float _requiredComboWidthUnscaled; private float _requiredComboWidthUnscaled;
private float _requiredComboWidth; 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, public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures,
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy) Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes)
{ {
_items = items; _items = items;
_textures = textures; _textures = textures;
_config = config; _config = config;
_gPose = gPose; _gPose = gPose;
_advancedDyes = advancedDyes; _advancedDyes = advancedDyes;
_itemCopy = itemCopy;
_stainData = items.Stains; _stainData = items.Stains;
_stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites); _stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites);
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray(); _itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
@ -82,7 +78,6 @@ public class EquipmentDrawer
_requiredComboWidth = _requiredComboWidthUnscaled * ImGuiHelpers.GlobalScale; _requiredComboWidth = _requiredComboWidthUnscaled * ImGuiHelpers.GlobalScale;
_advancedMaterialColor = ColorId.AdvancedDyeActive.Value(); _advancedMaterialColor = ColorId.AdvancedDyeActive.Value();
_dragTarget = EquipSlot.Unknown;
} }
private bool VerifyRestrictedGear(EquipDrawData data) private bool VerifyRestrictedGear(EquipDrawData data)
@ -188,7 +183,6 @@ public class EquipmentDrawer
return change; return change;
} }
#region Small #region Small
private void DrawEquipSmall(in EquipDrawData equipDrawData) private void DrawEquipSmall(in EquipDrawData equipDrawData)
@ -407,7 +401,6 @@ 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)
: _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width); : _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width);
_itemCopy.HandleCopyPaste(data, index);
if (!change) if (!change)
DrawStainDragDrop(data, index, stain, found); DrawStainDragDrop(data, index, stain, found);
@ -432,8 +425,8 @@ public class EquipmentDrawer
using var dragSource = ImUtf8.DragDropSource(); using var dragSource = ImUtf8.DragDropSource();
if (dragSource.Success) if (dragSource.Success)
{ {
DragDropSource.SetPayload("stainDragDrop"u8); if (DragDropSource.SetPayload("stainDragDrop"u8))
_draggedStain = stain; _draggedStain = stain;
ImUtf8.Text($"Dragging {stain.Name}..."); ImUtf8.Text($"Dragging {stain.Name}...");
} }
} }
@ -458,12 +451,10 @@ public class EquipmentDrawer
using var disabled = ImRaii.Disabled(data.Locked); using var disabled = ImRaii.Disabled(data.Locked);
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth); _requiredComboWidth);
DrawGearDragDrop(data);
if (change) if (change)
data.SetItem(combo.CurrentSelection); data.SetItem(combo.CurrentSelection);
else if (combo.CustomVariant.Id > 0) else if (combo.CustomVariant.Id > 0)
data.SetItem(_items.Identify(data.Slot, combo.CustomSetId, combo.CustomVariant)); 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), if (ResetOrClear(data.Locked, clear, data.AllowRevert, true, data.CurrentItem, data.GameItem, ItemManager.NothingItem(data.Slot),
out var item)) out var item))
@ -481,14 +472,6 @@ public class EquipmentDrawer
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem, var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem,
small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth); _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) if (change)
data.SetItem(combo.CurrentSelection); data.SetItem(combo.CurrentSelection);
else if (combo.CustomVariant.Id > 0) else if (combo.CustomVariant.Id > 0)
@ -499,50 +482,6 @@ public class EquipmentDrawer
data.SetItem(item); 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, 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> in T currentItem, in T revertItem, in T clearItem, out T? item) where T : IEquatable<T>
{ {
@ -591,13 +530,8 @@ public class EquipmentDrawer
if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth)) _requiredComboWidth))
changedItem = combo.CurrentSelection; changedItem = combo.CurrentSelection;
else if (combo.CustomVariant.Id > 0 && (drawAll || ItemData.ConvertWeaponId(combo.CustomSetId) == mainhand.CurrentItem.Type)) else if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
changedItem = _items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant); default, out var c))
_itemCopy.HandleCopyPaste(mainhand);
DrawGearDragDrop(mainhand);
if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
default, out var c))
changedItem = c; changedItem = c;
if (changedItem != null) if (changedItem != null)
@ -614,8 +548,7 @@ public class EquipmentDrawer
} }
if (unknown) if (unknown)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
"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) private void DrawOffhand(in EquipDrawData mainhand, in EquipDrawData offhand, out string label, bool small, bool clear, bool open)
@ -635,10 +568,6 @@ public class EquipmentDrawer
if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
_requiredComboWidth)) _requiredComboWidth))
offhand.SetItem(combo.CurrentSelection); 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); var defaultOffhand = _items.GetDefaultOffhand(mainhand.CurrentItem);
if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item)) if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item))
@ -693,7 +622,6 @@ public class EquipmentDrawer
{ {
ImUtf8.Text(label); ImUtf8.Text(label);
} }
if (hasAdvancedDyes) if (hasAdvancedDyes)
ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8); ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8);
} }

View file

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

View file

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

View file

@ -1,73 +0,0 @@
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);
}
}
}

View file

@ -1,8 +1,8 @@
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
@ -19,10 +19,6 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
private ItemId _currentItem; private ItemId _currentItem;
private float _innerWidth; 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) public WeaponCombo(ItemManager items, FullEquipType type, Logger log, FavoriteManager favorites)
: base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log) : base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log)
{ {
@ -50,9 +46,8 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
public bool Draw(string previewName, ItemId previewIdx, float width, float innerWidth) public bool Draw(string previewName, ItemId previewIdx, float width, float innerWidth)
{ {
_innerWidth = innerWidth; _innerWidth = innerWidth;
_currentItem = previewIdx; _currentItem = previewIdx;
CustomVariant = 0;
return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing()); return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
} }
@ -79,24 +74,6 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
return ret; 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) protected override bool IsVisible(int globalIndex, LowerString filter)
=> base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower); => base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower);

View file

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

View file

@ -41,10 +41,6 @@ public class GlamourerChangelog
Add1_3_5_0(Changelog); Add1_3_5_0(Changelog);
Add1_3_6_0(Changelog); Add1_3_6_0(Changelog);
Add1_3_7_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() private (int, ChangeLogDisplayType) ConfigData()
@ -65,66 +61,6 @@ 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.")
.RegisterEntry(
"This is not thoroughly tested, but I decided to push to stable instead of testing because otherwise a lot of people would just go to testing just for early access again despite having no business doing so.",
1)
.RegisterEntry(
"I also do not use most of the functionality of Glamourer myself, so I am unable to even encounter most issues myself.", 1)
.RegisterEntry("If you encounter any issues, please report them quickly on the discord.", 1)
.RegisterEntry("Added a chat command to clear temporary settings applied by Glamourer to Penumbra.")
.RegisterEntry("Fixed small issues with customizations not applicable to your race still applying.");
private static void Add1_3_7_0(Changelog log) private static void Add1_3_7_0(Changelog log)
=> log.NextVersion("Version 1.3.7.0") => log.NextVersion("Version 1.3.7.0")
.RegisterImportant( .RegisterImportant(

View file

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

View file

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

View file

@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop.Material; using Glamourer.Interop.Material;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Services; using OtterGui.Services;
using OtterGui.Text; using OtterGui.Text;
@ -18,6 +18,7 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
public const float GlossWidth = 100; public const float GlossWidth = 100;
public const float SpecularStrengthWidth = 125; public const float SpecularStrengthWidth = 125;
private EquipSlot _newSlot = EquipSlot.Head;
private int _newMaterialIdx; private int _newMaterialIdx;
private int _newRowIdx; private int _newRowIdx;
private MaterialValueIndex _newKey = MaterialValueIndex.FromSlot(EquipSlot.Head); private MaterialValueIndex _newKey = MaterialValueIndex.FromSlot(EquipSlot.Head);
@ -177,42 +178,14 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
public sealed class MaterialSlotCombo; 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) public void DrawNew(Design design)
{ {
DrawSlotCombo(); 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,
};
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
DrawMaterialIdxDrag(); DrawMaterialIdxDrag();
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();

View file

@ -1,40 +1,39 @@
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui; namespace Glamourer.Gui;
public sealed class PenumbraChangedItemTooltip : IDisposable public sealed class PenumbraChangedItemTooltip : IDisposable
{ {
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly ActorObjectManager _objects; private readonly ObjectManager _objects;
private readonly CustomizeService _customize; private readonly CustomizeService _customize;
private readonly GPoseService _gpose; private readonly GPoseService _gpose;
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2 + BonusExtensions.AllFlags.Count]; private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2];
public IEnumerable<KeyValuePair<object, EquipItem>> LastItems public IEnumerable<KeyValuePair<EquipSlot, EquipItem>> LastItems
=> EquipSlotExtensions.EqdpSlots.Cast<object>().Append(EquipSlot.MainHand).Append(EquipSlot.OffHand) => EquipSlotExtensions.EqdpSlots.Append(EquipSlot.MainHand).Append(EquipSlot.OffHand).Zip(_lastItems)
.Concat(BonusExtensions.AllFlags.Cast<object>()).Zip(_lastItems) .Select(p => new KeyValuePair<EquipSlot, EquipItem>(p.First, p.Second));
.Select(p => new KeyValuePair<object, EquipItem>(p.First, p.Second));
public ChangedItemType LastType { get; private set; } = ChangedItemType.None; public ChangedItemType LastType { get; private set; } = ChangedItemType.None;
public uint LastId { get; private set; } public uint LastId { get; private set; } = 0;
public DateTime LastTooltip { get; private set; } = DateTime.MinValue; public DateTime LastTooltip { get; private set; } = DateTime.MinValue;
public DateTime LastClick { get; private set; } = DateTime.MinValue; public DateTime LastClick { get; private set; } = DateTime.MinValue;
public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ActorObjectManager objects, public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ObjectManager objects,
CustomizeService customize, GPoseService gpose) CustomizeService customize, GPoseService gpose)
{ {
_penumbra = penumbra; _penumbra = penumbra;
@ -73,21 +72,6 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
if (!Player()) if (!Player())
return; 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 slot = item.Type.ToSlot();
var last = _lastItems[slot.ToIndex()]; var last = _lastItems[slot.ToIndex()];
switch (slot) switch (slot)
@ -125,27 +109,6 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
public void ApplyItem(ActorState state, EquipItem item) 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 slot = item.Type.ToSlot();
var last = _lastItems[slot.ToIndex()]; var last = _lastItems[slot.ToIndex()];
switch (slot) switch (slot)
@ -302,22 +265,7 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
{ {
var oldItem = state.ModelData.Item(slot); var oldItem = state.ModelData.Item(slot);
if (oldItem.Id != item.Id) if (oldItem.Id != item.Id)
last = oldItem; _lastItems[slot.ToIndex()] = oldItem;
}
}
private void SetLastItem(BonusItemFlag slot, EquipItem item, ActorState state)
{
ref var last = ref _lastItems[slot.ToSlot() + 2];
if (!item.Valid)
{
last = default;
}
else
{
var oldItem = state.ModelData.BonusItem(slot);
if (oldItem.Id != item.Id)
last = oldItem;
} }
} }

View file

@ -10,8 +10,9 @@ using Glamourer.Gui.Customization;
using Glamourer.Gui.Equipment; using Glamourer.Gui.Equipment;
using Glamourer.Gui.Materials; using Glamourer.Gui.Materials;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
@ -21,6 +22,7 @@ using Penumbra.GameData.Actors;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Gui.Tabs.ActorTab; namespace Glamourer.Gui.Tabs.ActorTab;
@ -33,7 +35,7 @@ public class ActorPanel
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly Configuration _config; private readonly Configuration _config;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly ActorObjectManager _objects; private readonly ObjectManager _objects;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly ImportService _importService; private readonly ImportService _importService;
private readonly ICondition _conditions; private readonly ICondition _conditions;
@ -51,7 +53,7 @@ public class ActorPanel
AutoDesignApplier autoDesignApplier, AutoDesignApplier autoDesignApplier,
Configuration config, Configuration config,
DesignConverter converter, DesignConverter converter,
ActorObjectManager objects, ObjectManager objects,
DesignManager designManager, DesignManager designManager,
ImportService importService, ImportService importService,
ICondition conditions, ICondition conditions,
@ -85,7 +87,7 @@ public class ActorPanel
_rightButtons = _rightButtons =
[ [
new LockedButton(this), new LockedButton(this),
new HeaderDrawer.IncognitoButton(_config), new HeaderDrawer.IncognitoButton(_config.Ephemeral),
]; ];
} }
@ -104,7 +106,7 @@ public class ActorPanel
{ {
using var group = ImRaii.Group(); using var group = ImRaii.Group();
(_identifier, _data) = _selector.Selection; (_identifier, _data) = _selector.Selection;
_lockedRedraw = _identifier.Type is IdentifierType.Special || _objects.IsInLobby _lockedRedraw = _identifier.Type is IdentifierType.Special
|| _conditions[ConditionFlag.OccupiedInCutSceneEvent]; || _conditions[ConditionFlag.OccupiedInCutSceneEvent];
(_actorName, _actor) = GetHeaderName(); (_actorName, _actor) = GetHeaderName();
DrawHeader(); DrawHeader();
@ -238,7 +240,6 @@ public class ActorPanel
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
DrawEquipmentMetaToggles(); DrawEquipmentMetaToggles();
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
_equipmentDrawer.DrawDragDropTooltip();
} }
private void DrawParameterHeader() private void DrawParameterHeader()
@ -305,12 +306,6 @@ public class ActorPanel
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.WeaponState, _stateManager, _state!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.WeaponState, _stateManager, _state!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromState(CrestFlag.OffHand, _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() private void DrawMonsterPanel()

View file

@ -1,17 +1,19 @@
using Dalamud.Interface; using System.Security.AccessControl;
using Dalamud.Bindings.ImGui; using Dalamud.Interface;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.ActorTab; namespace Glamourer.Gui.Tabs.ActorTab;
public class ActorSelector(ActorObjectManager objects, ActorManager actors, EphemeralConfig config) public class ActorSelector(ObjectManager objects, ActorManager actors, EphemeralConfig config)
{ {
private ActorIdentifier _identifier = ActorIdentifier.Invalid; private ActorIdentifier _identifier = ActorIdentifier.Invalid;
@ -87,10 +89,11 @@ public class ActorSelector(ActorObjectManager objects, ActorManager actors, Ephe
if (!child) if (!child)
return; return;
objects.Update();
_world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0); _world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0);
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
var remainder = ImGuiClip.FilteredClippedDraw(objects.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter, var remainder = ImGuiClip.FilteredClippedDraw(objects.Identifiers.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter,
DrawSelectable); DrawSelectable);
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@ using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.Special; using Glamourer.Designs.Special;
using Glamourer.Events; using Glamourer.Events;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Services; using OtterGui.Services;
@ -278,7 +278,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
private void LookupTooltip(IEnumerable<Design> designs) private void LookupTooltip(IEnumerable<Design> designs)
{ {
using var _ = ImRaii.Tooltip(); using var _ = ImRaii.Tooltip();
var tt = string.Join('\n', designs.Select(d => _designFileSystem.TryGetValue(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t)); var tt = string.Join('\n', designs.Select(d => _designFileSystem.FindLeaf(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t));
ImGui.TextUnformatted(tt.Length == 0 ImGui.TextUnformatted(tt.Length == 0
? "Matches no currently existing designs." ? "Matches no currently existing designs."
: "Matches the following designs:"); : "Matches the following designs:");

View file

@ -6,9 +6,8 @@ using Glamourer.Designs.Special;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
@ -32,7 +31,7 @@ public class SetPanel(
RandomRestrictionDrawer _randomDrawer) RandomRestrictionDrawer _randomDrawer)
{ {
private readonly JobGroupCombo _jobGroupCombo = new(_manager, _jobs, Glamourer.Log); private readonly JobGroupCombo _jobGroupCombo = new(_manager, _jobs, Glamourer.Log);
private readonly HeaderDrawer.Button[] _rightButtons = [new HeaderDrawer.IncognitoButton(_config)]; private readonly HeaderDrawer.Button[] _rightButtons = [new HeaderDrawer.IncognitoButton(_config.Ephemeral)];
private string? _tempName; private string? _tempName;
private int _dragIndex = -1; private int _dragIndex = -1;
@ -432,10 +431,10 @@ public class SetPanel(
if (source) if (source)
{ {
ImUtf8.Text($"Moving design #{index + 1:D2}..."); ImUtf8.Text($"Moving design #{index + 1:D2}...");
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0)) if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
{ {
_dragIndex = index; _dragIndex = index;
_selector.DragDesignIndex = index; _selector._dragDesignIndex = index;
} }
} }
} }

View file

@ -2,12 +2,12 @@
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Events; using Glamourer.Events;
using Dalamud.Bindings.ImGui; using Glamourer.Interop;
using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Extensions;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Interop; using Penumbra.GameData.Actors;
using Penumbra.String; using Penumbra.String;
using ImGuiClip = OtterGui.ImGuiClip; using ImGuiClip = OtterGui.ImGuiClip;
@ -18,7 +18,8 @@ public class SetSelector : IDisposable
private readonly Configuration _config; private readonly Configuration _config;
private readonly AutoDesignManager _manager; private readonly AutoDesignManager _manager;
private readonly AutomationChanged _event; private readonly AutomationChanged _event;
private readonly ActorObjectManager _objects; private readonly ActorManager _actors;
private readonly ObjectManager _objects;
private readonly List<(AutoDesignSet, int)> _list = []; private readonly List<(AutoDesignSet, int)> _list = [];
public AutoDesignSet? Selection { get; private set; } public AutoDesignSet? Selection { get; private set; }
@ -37,13 +38,14 @@ public class SetSelector : IDisposable
private int _dragIndex = -1; private int _dragIndex = -1;
private Action? _endAction; private Action? _endAction;
internal int DragDesignIndex = -1; internal int _dragDesignIndex = -1;
public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorObjectManager objects) public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorManager actors, ObjectManager objects)
{ {
_manager = manager; _manager = manager;
_event = @event; _event = @event;
_config = config; _config = config;
_actors = actors;
_objects = objects; _objects = objects;
_event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector); _event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector);
} }
@ -92,7 +94,7 @@ public class SetSelector : IDisposable
} }
private LowerString _filter = LowerString.Empty; private LowerString _filter = LowerString.Empty;
private uint _enabledFilter; private uint _enabledFilter = 0;
private float _width; private float _width;
private Vector2 _defaultItemSpacing; private Vector2 _defaultItemSpacing;
private Vector2 _selectableSize; private Vector2 _selectableSize;
@ -144,7 +146,7 @@ public class SetSelector : IDisposable
ImGui.SameLine(); ImGui.SameLine();
var f = _enabledFilter; var f = _enabledFilter;
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3u)) if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3))
{ {
_enabledFilter = _enabledFilter switch _enabledFilter = _enabledFilter switch
{ {
@ -175,6 +177,7 @@ public class SetSelector : IDisposable
UpdateList(); UpdateList();
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
_selectableSize = new Vector2(0, 2 * ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y); _selectableSize = new Vector2(0, 2 * ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
_objects.Update();
ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * ImGui.GetStyle().ItemSpacing.Y); ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * ImGui.GetStyle().ItemSpacing.Y);
_endAction?.Invoke(); _endAction?.Invoke();
_endAction = null; _endAction = null;
@ -183,7 +186,7 @@ public class SetSelector : IDisposable
private void DrawSetSelectable((AutoDesignSet Set, int Index) pair) private void DrawSetSelectable((AutoDesignSet Set, int Index) pair)
{ {
using var id = ImRaii.PushId(pair.Index); using var id = ImRaii.PushId(pair.Index);
using (ImRaii.PushColor(ImGuiCol.Text, pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value())) using (var color = ImRaii.PushColor(ImGuiCol.Text, pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value()))
{ {
if (ImGui.Selectable(GetSetName(pair.Set, pair.Index), pair.Set == Selection, ImGuiSelectableFlags.None, _selectableSize)) if (ImGui.Selectable(GetSetName(pair.Set, pair.Index), pair.Set == Selection, ImGuiSelectableFlags.None, _selectableSize))
{ {
@ -282,9 +285,9 @@ public class SetSelector : IDisposable
private void NewSetButton(Vector2 size) private void NewSetButton(Vector2 size)
{ {
var id = _objects.Actors.GetCurrentPlayer(); var id = _actors.GetCurrentPlayer();
if (!id.IsValid) if (!id.IsValid)
id = _objects.Actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue); id = _actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue);
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), size, if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), size,
$"Create a new Automatic Design Set for {id}. The associated player can be changed later.", !id.IsValid, true)) $"Create a new Automatic Design Set for {id}. The associated player can be changed later.", !id.IsValid, true))
_manager.AddDesignSet("New Automation Set", id); _manager.AddDesignSet("New Automation Set", id);
@ -329,15 +332,15 @@ public class SetSelector : IDisposable
} }
else if (ImGuiUtil.IsDropping("DesignDragDrop")) else if (ImGuiUtil.IsDropping("DesignDragDrop"))
{ {
if (DragDesignIndex >= 0) if (_dragDesignIndex >= 0)
{ {
var idx = DragDesignIndex; var idx = _dragDesignIndex;
var setTo = set; var setTo = set;
var setFrom = Selection!; var setFrom = Selection!;
_endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo); _endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo);
} }
DragDesignIndex = -1; _dragDesignIndex = -1;
} }
} }
} }
@ -347,7 +350,7 @@ public class SetSelector : IDisposable
if (source) if (source)
{ {
ImGui.TextUnformatted($"Moving design set {GetSetName(set, index)} from position {index + 1}..."); ImGui.TextUnformatted($"Moving design set {GetSetName(set, index)} from position {index + 1}...");
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0)) if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
_dragIndex = index; _dragIndex = index;
} }
} }

View file

@ -1,17 +1,18 @@
using Dalamud.Interface; using Dalamud.Interface;
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer
{ {
public string Label public string Label
=> $"Active Actors ({_stateManager.Count})###Active Actors"; => $"Active Actors ({_stateManager.Count})###Active Actors";
@ -21,7 +22,8 @@ public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _ob
public void Draw() public void Draw()
{ {
foreach (var (identifier, actors) in _objectManager) _objectManager.Update();
foreach (var (identifier, actors) in _objectManager.Identifiers)
{ {
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()), if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()),
string.Empty, !_stateManager.ContainsKey(identifier), true)) string.Empty, !_stateManager.ContainsKey(identifier), true))
@ -64,15 +66,13 @@ public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _ob
static string ItemString(in DesignData data, EquipSlot slot) static string ItemString(in DesignData data, EquipSlot slot)
{ {
var item = data.Item(slot); var item = data.Item(slot);
return return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
$"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
} }
static string BonusItemString(in DesignData data, BonusItemFlag slot) static string BonusItemString(in DesignData data, BonusItemFlag slot)
{ {
var item = data.BonusItem(slot); var item = data.BonusItem(slot);
return return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
$"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
} }
PrintRow("Model ID", state.BaseData.ModelId, state.ModelData.ModelId, state.Sources[MetaIndex.ModelId]); PrintRow("Model ID", state.BaseData.ModelId, state.ModelData.ModelId, state.Sources[MetaIndex.ModelId]);
@ -87,9 +87,6 @@ public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _ob
PrintRow("Visor Toggled", state.BaseData.IsVisorToggled(), state.ModelData.IsVisorToggled(), PrintRow("Visor Toggled", state.BaseData.IsVisorToggled(), state.ModelData.IsVisorToggled(),
state.Sources[MetaIndex.VisorState]); state.Sources[MetaIndex.VisorState]);
ImGui.TableNextRow(); 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(), PrintRow("Weapon Visible", state.BaseData.IsWeaponVisible(), state.ModelData.IsWeaponVisible(),
state.Sources[MetaIndex.WeaponState]); state.Sources[MetaIndex.WeaponState]);
ImGui.TableNextRow(); ImGui.TableNextRow();

View file

@ -1,13 +1,13 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using Dalamud.Bindings.ImGui; using Glamourer.Interop;
using ImGuiNET;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class AdvancedCustomizationDrawer(ActorObjectManager objects) : IGameDataDrawer public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDataDrawer
{ {
public string Label public string Label
=> "Advanced Customizations"; => "Advanced Customizations";
@ -31,8 +31,8 @@ public unsafe class AdvancedCustomizationDrawer(ActorObjectManager objects) : IG
return; return;
} }
DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0); DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0);
DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1); DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1);
DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2); DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2);
DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3); DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3);
} }

View file

@ -1,7 +1,6 @@
using Glamourer.Automation; using Glamourer.Automation;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
using Glamourer.Gui.Tabs.DebugTab.IpcTester; using Glamourer.Gui.Tabs.DebugTab.IpcTester;
using ImGuiNET;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
@ -35,7 +36,6 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
provider.GetRequiredService<ModelEvaluationPanel>(), provider.GetRequiredService<ModelEvaluationPanel>(),
provider.GetRequiredService<ObjectManagerPanel>(), provider.GetRequiredService<ObjectManagerPanel>(),
provider.GetRequiredService<PenumbraPanel>(), provider.GetRequiredService<PenumbraPanel>(),
provider.GetRequiredService<DynamisPanel>(),
provider.GetRequiredService<IpcTesterPanel>(), provider.GetRequiredService<IpcTesterPanel>(),
provider.GetRequiredService<DatFilePanel>(), provider.GetRequiredService<DatFilePanel>(),
provider.GetRequiredService<GlamourPlatePanel>(), provider.GetRequiredService<GlamourPlatePanel>(),

View file

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

View file

@ -1,11 +1,8 @@
using Dalamud.Interface; using Dalamud.Interface;
using Glamourer.Designs; using Glamourer.Designs;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using OtterGui.Filesystem;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
@ -21,7 +18,6 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
public void Draw() public void Draw()
{ {
DrawButtons();
foreach (var (design, idx) in _designManager.Designs.WithIndex()) foreach (var (design, idx) in _designManager.Designs.WithIndex())
{ {
using var t = ImRaii.TreeNode($"{design.Name}##{idx}"); using var t = ImRaii.TreeNode($"{design.Name}##{idx}");
@ -29,8 +25,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
continue; continue;
DrawDesign(design, _designFileSystem); DrawDesign(design, _designFileSystem);
var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, design.Application.Meta,
design.Application.Meta,
design.WriteProtected()); design.WriteProtected());
using var font = ImRaii.PushFont(UiBuilder.MonoFont); using var font = ImRaii.PushFont(UiBuilder.MonoFont);
ImGuiUtil.TextWrapped(base64); ImGuiUtil.TextWrapped(base64);
@ -39,26 +34,6 @@ 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) public static void DrawDesign(DesignBase design, DesignFileSystem? fileSystem)
{ {
using var table = ImRaii.Table("##equip", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit); using var table = ImRaii.Table("##equip", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit);
@ -77,7 +52,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
ImGui.TableNextRow(); ImGui.TableNextRow();
ImGuiUtil.DrawTableColumn("Design File System Path"); ImGuiUtil.DrawTableColumn("Design File System Path");
if (fileSystem != null) if (fileSystem != null)
ImGuiUtil.DrawTableColumn(fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : "No Path Known"); ImGuiUtil.DrawTableColumn(fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : "No Path Known");
ImGui.TableNextRow(); ImGui.TableNextRow();
ImGuiUtil.DrawTableColumn("Creation"); ImGuiUtil.DrawTableColumn("Creation");
@ -114,7 +89,6 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
ImGuiUtil.DrawTableColumn(index.ToName()); ImGuiUtil.DrawTableColumn(index.ToName());
ImGuiUtil.DrawTableColumn(design.DesignData.GetMeta(index).ToString()); ImGuiUtil.DrawTableColumn(design.DesignData.GetMeta(index).ToString());
ImGuiUtil.DrawTableColumn(design.DoApplyMeta(index) ? "Apply" : "Keep"); ImGuiUtil.DrawTableColumn(design.DoApplyMeta(index) ? "Apply" : "Keep");
ImGui.TableNextRow();
} }
ImGuiUtil.DrawTableColumn("Model ID"); ImGuiUtil.DrawTableColumn("Model ID");

View file

@ -1,9 +1,8 @@
using Dalamud.Interface; using Dalamud.Interface;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Services; using Glamourer.Services;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;

View file

@ -1,16 +0,0 @@
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;
}

View file

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

View file

@ -3,26 +3,24 @@ using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Extensions;
using OtterGui.Text;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class GlamourPlatePanel : IGameDataDrawer public unsafe class GlamourPlatePanel : IGameDataDrawer
{ {
private readonly DesignManager _design; private readonly DesignManager _design;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ActorObjectManager _objects; private readonly ObjectManager _objects;
public string Label public string Label
=> "Glamour Plates"; => "Glamour Plates";
@ -30,8 +28,7 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
public bool Disabled public bool Disabled
=> false; => false;
public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state, public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state, ObjectManager objects)
ActorObjectManager objects)
{ {
_items = items; _items = items;
_design = design; _design = design;
@ -45,24 +42,24 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
var manager = MirageManager.Instance(); var manager = MirageManager.Instance();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
ImUtf8.Text("Address:"u8); ImGui.TextUnformatted("Address:");
ImUtf8.Text("Number of Glamour Plates:"u8); ImGui.TextUnformatted("Number of Glamour Plates:");
ImUtf8.Text("Glamour Plates Requested:"u8); ImGui.TextUnformatted("Glamour Plates Requested:");
ImUtf8.Text("Glamour Plates Loaded:"u8); ImGui.TextUnformatted("Glamour Plates Loaded:");
ImUtf8.Text("Is Applying Glamour Plates:"u8); ImGui.TextUnformatted("Is Applying Glamour Plates:");
} }
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
ImUtf8.CopyOnClickSelectable($"0x{(ulong)manager:X}"); ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)manager:X}");
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlates.Length.ToString()); ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesRequested.ToString()); ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
ImGui.SameLine(); ImGui.SameLine();
if (ImUtf8.SmallButton("Request Update"u8)) if (ImGui.SmallButton("Request Update"))
RequestGlamour(); RequestGlamour();
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString()); ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
ImUtf8.Text(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString()); ImGui.TextUnformatted(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
} }
if (manager == null) if (manager == null)
@ -74,12 +71,12 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
for (var i = 0; i < manager->GlamourPlates.Length; ++i) for (var i = 0; i < manager->GlamourPlates.Length; ++i)
{ {
using var tree = ImUtf8.TreeNode($"Plate #{i + 1:D2}"); using var tree = ImRaii.TreeNode($"Plate #{i + 1:D2}");
if (!tree) if (!tree)
continue; continue;
ref var plate = ref manager->GlamourPlates[i]; ref var plate = ref manager->GlamourPlates[i];
if (ImUtf8.ButtonEx("Apply to Player"u8, ""u8, Vector2.Zero, !enabled)) if (ImGuiUtil.DrawDisabledButton("Apply to Player", Vector2.Zero, string.Empty, !enabled))
{ {
var design = CreateDesign(plate); var design = CreateDesign(plate);
_state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true }); _state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true });
@ -88,14 +85,14 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
using (ImRaii.Group()) using (ImRaii.Group())
{ {
foreach (var slot in EquipSlotExtensions.FullSlots) foreach (var slot in EquipSlotExtensions.FullSlots)
ImUtf8.Text(slot.ToName()); ImGui.TextUnformatted(slot.ToName());
} }
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex()) foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex())
ImUtf8.Text($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}"); ImGui.TextUnformatted($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}");
} }
} }
} }

View file

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

View file

@ -3,11 +3,10 @@ using Dalamud.Interface.Utility;
using Dalamud.Plugin; using Dalamud.Plugin;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Services; using OtterGui.Services;
using OtterGui.Text;
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester; namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
@ -16,7 +15,6 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
private Dictionary<Guid, string> _designs = []; private Dictionary<Guid, string> _designs = [];
private int _gameObjectIndex; private int _gameObjectIndex;
private string _gameObjectName = string.Empty; private string _gameObjectName = string.Empty;
private string _designName = string.Empty;
private uint _key; private uint _key;
private ApplyFlag _flags = ApplyFlagEx.DesignDefault; private ApplyFlag _flags = ApplyFlagEx.DesignDefault;
private Guid? _design; private Guid? _design;
@ -32,7 +30,6 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
IpcTesterHelpers.IndexInput(ref _gameObjectIndex); IpcTesterHelpers.IndexInput(ref _gameObjectIndex);
IpcTesterHelpers.KeyInput(ref _key); IpcTesterHelpers.KeyInput(ref _key);
IpcTesterHelpers.NameInput(ref _gameObjectName); IpcTesterHelpers.NameInput(ref _gameObjectName);
ImUtf8.InputText("##designName"u8, ref _designName, "Design Name..."u8);
ImGuiUtil.GuidInput("##identifier", "Design Identifier...", string.Empty, ref _design, ref _designText, ImGuiUtil.GuidInput("##identifier", "Design Identifier...", string.Empty, ref _design, ref _designText,
ImGui.GetContentRegionAvail().X); ImGui.GetContentRegionAvail().X);
IpcTesterHelpers.DrawFlagInput(ref _flags); IpcTesterHelpers.DrawFlagInput(ref _flags);
@ -57,48 +54,6 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
IpcTesterHelpers.DrawIntro(ApplyDesignName.Label); IpcTesterHelpers.DrawIntro(ApplyDesignName.Label);
if (ImGuiUtil.DrawDisabledButton("Apply##Name", Vector2.Zero, string.Empty, !_design.HasValue)) if (ImGuiUtil.DrawDisabledButton("Apply##Name", Vector2.Zero, string.Empty, !_design.HasValue))
_lastError = new ApplyDesignName(pluginInterface).Invoke(_design!.Value, _gameObjectName, _key, _flags); _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() private void DrawDesignsPopup()

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
@ -11,13 +11,13 @@ using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class ModelEvaluationPanel( public unsafe class ModelEvaluationPanel(
ActorObjectManager _objectManager, ObjectManager _objectManager,
VisorService _visorService, VisorService _visorService,
VieraEarService _vieraEarService,
UpdateSlotService _updateSlotService, UpdateSlotService _updateSlotService,
ChangeCustomizeService _changeCustomizeService, ChangeCustomizeService _changeCustomizeService,
CrestService _crestService, CrestService _crestService,
@ -34,7 +34,7 @@ public unsafe class ModelEvaluationPanel(
public void Draw() public void Draw()
{ {
ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0); ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0);
var actor = _objectManager.Objects[_gameObjectIndex]; var actor = _objectManager[_gameObjectIndex];
var model = actor.Model; var model = actor.Model;
using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -46,10 +46,9 @@ public unsafe class ModelEvaluationPanel(
ImGuiUtil.DrawTableColumn("Address"); ImGuiUtil.DrawTableColumn("Address");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiUtil.CopyOnClickSelectable(actor.ToString());
Glamourer.Dynamis.DrawPointer(actor);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
Glamourer.Dynamis.DrawPointer(model); ImGuiUtil.CopyOnClickSelectable(model.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (actor.IsCharacter) if (actor.IsCharacter)
{ {
@ -85,7 +84,6 @@ public unsafe class ModelEvaluationPanel(
ImGuiUtil.CopyOnClickSelectable(offhand.ToString()); ImGuiUtil.CopyOnClickSelectable(offhand.ToString());
DrawVisor(actor, model); DrawVisor(actor, model);
DrawVieraEars(actor, model);
DrawHatState(actor, model); DrawHatState(actor, model);
DrawWeaponState(actor, model); DrawWeaponState(actor, model);
DrawWetness(actor, model); DrawWetness(actor, model);
@ -137,26 +135,6 @@ public unsafe class ModelEvaluationPanel(
_visorService.SetVisorState(model, !VisorService.GetVisorState(model)); _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) private void DrawHatState(Actor actor, Model model)
{ {
using var id = ImRaii.PushId("HatState"); using var id = ImRaii.PushId("HatState");

View file

@ -3,18 +3,18 @@ using Dalamud.Interface.Utility;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Interop;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using ImGuiClip = OtterGui.ImGuiClip; using ImGuiClip = OtterGui.ImGuiClip;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, ActorObjectManager objectManager, DesignConverter designConverter) public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectManager _objectManager, DesignConverter _designConverter)
: IGameDataDrawer : IGameDataDrawer
{ {
public string Label public string Label
@ -28,9 +28,9 @@ public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, Ac
public void Draw() public void Draw()
{ {
ImUtf8.Checkbox("Compare Customize (or Gear)"u8, ref _customizeOrGear); ImGui.Checkbox("Compare Customize (or Gear)", ref _customizeOrGear);
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
var resetScroll = ImUtf8.InputText("##npcFilter"u8, ref _npcFilter, "Filter..."u8); var resetScroll = ImGui.InputTextWithHint("##npcFilter", "Filter...", ref _npcFilter, 64);
using var table = ImRaii.Table("npcs", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit, using var table = ImRaii.Table("npcs", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit,
new Vector2(-1, 400 * ImGuiHelpers.GlobalScale)); new Vector2(-1, 400 * ImGuiHelpers.GlobalScale));
@ -40,19 +40,19 @@ public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, Ac
if (resetScroll) if (resetScroll)
ImGui.SetScrollY(0); ImGui.SetScrollY(0);
ImUtf8.TableSetupColumn("Button"u8, ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Button", ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Name"u8, ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300); ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
ImUtf8.TableSetupColumn("Kind"u8, ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Kind", ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Id"u8, ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Model"u8, ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Visor"u8, ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Visor", ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Compare"u8, ImGuiTableColumnFlags.WidthStretch); ImGui.TableSetupColumn("Compare", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing());
ImGui.TableNextRow(); ImGui.TableNextRow();
var idx = 0; var idx = 0;
var remainder = ImGuiClip.FilteredClippedDraw(npcCombo.Items, skips, var remainder = ImGuiClip.FilteredClippedDraw(_npcCombo.Items, skips,
d => d.Name.Contains(_npcFilter, StringComparison.OrdinalIgnoreCase), DrawData); d => d.Name.Contains(_npcFilter, StringComparison.OrdinalIgnoreCase), DrawData);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing());
@ -61,31 +61,43 @@ public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, Ac
void DrawData(NpcData data) void DrawData(NpcData data)
{ {
using var id = ImRaii.PushId(idx++); using var id = ImRaii.PushId(idx++);
var disabled = !stateManager.GetOrCreate(objectManager.Player, out var state); var disabled = !_state.GetOrCreate(_objectManager.Player, out var state);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (ImUtf8.ButtonEx("Apply"u8, ""u8, Vector2.Zero, disabled)) if (ImGuiUtil.DrawDisabledButton("Apply", Vector2.Zero, string.Empty, disabled))
{ {
foreach (var (slot, item, stain) in designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true)) foreach (var (slot, item, stain) in _designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true))
stateManager.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual); _state.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
stateManager.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual); _state.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
stateManager.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual); _state.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
} }
ImUtf8.DrawFrameColumn(data.Name); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Name);
ImUtf8.DrawFrameColumn(data.Kind is ObjectKind.BattleNpc ? "B" : "E"); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
ImUtf8.DrawFrameColumn(data.Id.Id.ToString()); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Id.Id.ToString());
ImUtf8.DrawFrameColumn(data.ModelId.ToString()); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.ModelId.ToString());
using (_ = ImRaii.PushFont(UiBuilder.IconFont)) using (_ = ImRaii.PushFont(UiBuilder.IconFont))
{ {
ImUtf8.DrawFrameColumn(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString()); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
} }
using var mono = ImRaii.PushFont(UiBuilder.MonoFont); using var mono = ImRaii.PushFont(UiBuilder.MonoFont);
ImUtf8.DrawFrameColumn(_customizeOrGear ? data.Customize.ToString() : data.WriteGear()); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
} }
} }
} }

View file

@ -1,13 +1,13 @@
using Dalamud.Bindings.ImGui; using Glamourer.Interop;
using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Text; using OtterGui.Raii;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class ObjectManagerPanel(ActorObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer
{ {
public string Label public string Label
=> "Object Manager"; => "Object Manager";
@ -19,45 +19,44 @@ public class ObjectManagerPanel(ActorObjectManager _objectManager, ActorManager
public void Draw() public void Draw()
{ {
_objectManager.Objects.DrawDebug(); _objectManager.Update();
using (var table = ImRaii.Table("##data", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
using (var table = ImUtf8.Table("##data"u8, 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
{ {
if (!table) if (!table)
return; return;
ImUtf8.DrawTableColumn("World"u8); ImGuiUtil.DrawTableColumn("Last Update");
ImUtf8.DrawTableColumn(_actors.Finished ? _actors.Data.ToWorldName(_objectManager.World) : "Service Missing"); ImGuiUtil.DrawTableColumn(_objectManager.LastUpdate.ToString(CultureInfo.InvariantCulture));
ImUtf8.DrawTableColumn(_objectManager.World.ToString());
ImUtf8.DrawTableColumn("Player Character"u8);
ImUtf8.DrawTableColumn($"{_objectManager.Player.Utf8Name} ({_objectManager.Player.Index})");
ImGui.TableNextColumn();
ImUtf8.CopyOnClickSelectable(_objectManager.Player.ToString());
ImUtf8.DrawTableColumn("In GPose"u8);
ImUtf8.DrawTableColumn(_objectManager.IsInGPose.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImUtf8.DrawTableColumn("In Lobby"u8); ImGuiUtil.DrawTableColumn("World");
ImUtf8.DrawTableColumn(_objectManager.IsInLobby.ToString()); ImGuiUtil.DrawTableColumn(_actors.Finished ? _actors.Data.ToWorldName(_objectManager.World) : "Service Missing");
ImGuiUtil.DrawTableColumn(_objectManager.World.ToString());
ImGuiUtil.DrawTableColumn("Player Character");
ImGuiUtil.DrawTableColumn($"{_objectManager.Player.Utf8Name} ({_objectManager.Player.Index})");
ImGui.TableNextColumn();
ImGuiUtil.CopyOnClickSelectable(_objectManager.Player.ToString());
ImGuiUtil.DrawTableColumn("In GPose");
ImGuiUtil.DrawTableColumn(_objectManager.IsInGPose.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (_objectManager.IsInGPose) if (_objectManager.IsInGPose)
{ {
ImUtf8.DrawTableColumn("GPose Player"u8); ImGuiUtil.DrawTableColumn("GPose Player");
ImUtf8.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})"); ImGuiUtil.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImUtf8.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString()); ImGuiUtil.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString());
} }
ImUtf8.DrawTableColumn("Number of Players"u8); ImGuiUtil.DrawTableColumn("Number of Players");
ImUtf8.DrawTableColumn(_objectManager.Count.ToString()); ImGuiUtil.DrawTableColumn(_objectManager.Count.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
} }
var filterChanged = ImUtf8.InputText("##Filter"u8, ref _objectFilter, "Filter..."u8); var filterChanged = ImGui.InputTextWithHint("##Filter", "Filter...", ref _objectFilter, 64);
using var table2 = ImUtf8.Table("##data2"u8, 3, using var table2 = ImRaii.Table("##data2", 3,
ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY,
new Vector2(-1, 20 * ImGui.GetTextLineHeightWithSpacing())); new Vector2(-1, 20 * ImGui.GetTextLineHeightWithSpacing()));
if (!table2) if (!table2)
@ -70,13 +69,13 @@ public class ObjectManagerPanel(ActorObjectManager _objectManager, ActorManager
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
ImGui.TableNextRow(); ImGui.TableNextRow();
var remainder = ImGuiClip.FilteredClippedDraw(_objectManager, skips, var remainder = ImGuiClip.FilteredClippedDraw(_objectManager.Identifiers, skips,
p => p.Value.Label.Contains(_objectFilter, StringComparison.OrdinalIgnoreCase), p p => p.Value.Label.Contains(_objectFilter, StringComparison.OrdinalIgnoreCase), p
=> =>
{ {
ImUtf8.DrawTableColumn(p.Key.ToString()); ImGuiUtil.DrawTableColumn(p.Key.ToString());
ImUtf8.DrawTableColumn(p.Value.Label); ImGuiUtil.DrawTableColumn(p.Value.Label);
ImUtf8.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString()))); ImGuiUtil.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString())));
}); });
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeightWithSpacing()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeightWithSpacing());
} }

View file

@ -1,6 +1,6 @@
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
@ -49,7 +49,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var address = _drawObject.Address; var address = _drawObject.Address;
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale); ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, ref address, nint.Zero, nint.Zero, "%llx", if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, (nint)(&address), nint.Zero, nint.Zero, "%llx",
ImGuiInputTextFlags.CharsHexadecimal)) ImGuiInputTextFlags.CharsHexadecimal))
_drawObject = address; _drawObject = address;
ImGuiUtil.DrawTableColumn(_penumbra.Available ImGuiUtil.DrawTableColumn(_penumbra.Available
@ -61,7 +61,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale); ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
ImGui.InputInt("##CutsceneIndex", ref _gameObjectIndex, 0, 0); ImGui.InputInt("##CutsceneIndex", ref _gameObjectIndex, 0, 0);
ImGuiUtil.DrawTableColumn(_penumbra.Available ImGuiUtil.DrawTableColumn(_penumbra.Available
? _penumbra.CutsceneParent((ushort)_gameObjectIndex).ToString() ? _penumbra.CutsceneParent((ushort) _gameObjectIndex).ToString()
: "Penumbra Unavailable"); : "Penumbra Unavailable");
ImGuiUtil.DrawTableColumn("Redraw Object"); ImGuiUtil.DrawTableColumn("Redraw Object");
@ -76,9 +76,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
} }
ImGuiUtil.DrawTableColumn("Last Tooltip Date"); ImGuiUtil.DrawTableColumn("Last Tooltip Date");
ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue ? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})" : "Never");
? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})"
: "Never");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiUtil.DrawTableColumn("Last Click Date"); ImGuiUtil.DrawTableColumn("Last Click Date");
@ -89,13 +87,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
ImGui.Separator(); ImGui.Separator();
foreach (var (slot, item) in _penumbraTooltip.LastItems) foreach (var (slot, item) in _penumbraTooltip.LastItems)
{ {
switch (slot) ImGuiUtil.DrawTableColumn($"{slot.ToName()} Revert-Item");
{
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"); ImGuiUtil.DrawTableColumn(item.Valid ? item.Name : "None");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
} }

View file

@ -3,11 +3,10 @@ using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class RetainedStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer public class RetainedStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer
{ {
public string Label public string Label
=> "Retained States (Inactive Actors)"; => "Retained States (Inactive Actors)";

View file

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

View file

@ -1,5 +1,5 @@
using Glamourer.Designs; using Glamourer.Designs;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
@ -12,6 +12,13 @@ public sealed class DesignColorCombo(DesignColors _designColors, bool _skipAutom
: _designColors.Keys.OrderBy(k => k).Prepend(DesignColors.AutomaticName), : _designColors.Keys.OrderBy(k => k).Prepend(DesignColors.AutomaticName),
MouseWheelType.Control, Glamourer.Log) 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) protected override bool DrawSelectable(int globalIdx, bool selected)
{ {
var isAutomatic = !_skipAutomatic && globalIdx == 0; var isAutomatic = !_skipAutomatic && globalIdx == 0;

View file

@ -2,7 +2,7 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Services; using Glamourer.Services;
using Dalamud.Bindings.ImGui; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
@ -189,7 +189,10 @@ public class DesignDetailTab
else if (_selector.Selected!.Color.Length != 0) else if (_selector.Selected!.Color.Length != 0)
{ {
ImGui.SameLine(); ImGui.SameLine();
ImUtf8.Icon(FontAwesomeIcon.ExclamationCircle, "The color associated with this design does not exist."u8, _colors.MissingColor); 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.DrawFrameColumn("Creation Date"u8); ImUtf8.DrawFrameColumn("Creation Date"u8);

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