mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Compare commits
143 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b6517aae8 | ||
|
|
aadcf771e7 | ||
|
|
bf4673a1d9 | ||
|
|
76b214c643 | ||
|
|
434a5a809e | ||
|
|
88fe25f69e | ||
|
|
bef1e39ac3 | ||
|
|
c604d5dbe5 | ||
|
|
a0d912a395 | ||
|
|
a56852f918 | ||
|
|
4228fc1b89 | ||
|
|
e644b8da28 | ||
|
|
ace3a8f755 | ||
|
|
76ed347cbf | ||
|
|
c3469a1687 | ||
|
|
0a9693daea | ||
|
|
414bd8bee7 | ||
|
|
8e1745d67a | ||
|
|
889f01a724 | ||
|
|
6e62905fa7 | ||
|
|
654787fa0d | ||
|
|
835ba23935 | ||
|
|
389a8781d6 | ||
|
|
3eabe591df | ||
|
|
487d3b9399 | ||
|
|
4d4e4669dd | ||
|
|
fb065549e9 | ||
|
|
2c34154915 | ||
|
|
3704051b0f | ||
|
|
b2b8f2b6eb | ||
|
|
22e6c0655b | ||
|
|
bb2ba0cf11 | ||
|
|
e854386b23 | ||
|
|
49d24df2e7 | ||
|
|
c9b291c2f3 | ||
|
|
65f789880d | ||
|
|
abf998a727 | ||
|
|
4cc191cb25 | ||
|
|
dc431c10a5 | ||
|
|
26862ba78f | ||
|
|
e4374337f2 | ||
|
|
240c889fff | ||
|
|
612cd31c3e | ||
|
|
304b362002 | ||
|
|
8f34f197d0 | ||
|
|
1c97266a93 | ||
|
|
a9caddafd5 | ||
|
|
34bf95dddb | ||
|
|
4761b8f584 | ||
|
|
0d94aae732 | ||
|
|
e83f328cdc | ||
|
|
52fd29c478 | ||
|
|
a8b79993df | ||
|
|
98574558e5 | ||
|
|
557cbf23ce | ||
|
|
56753ae7ba | ||
|
|
b66df624f7 | ||
|
|
be78f1447b | ||
|
|
97e32a3cb7 | ||
|
|
4472920536 | ||
|
|
ac6a726f57 | ||
|
|
00d550f4fe | ||
|
|
0f98fac157 | ||
|
|
c25f0f72db | ||
|
|
72e05e23bc | ||
|
|
2c3bed6ba5 | ||
|
|
d6df9885dc | ||
|
|
e7936500e0 | ||
|
|
4ef4e65d46 | ||
|
|
40b4a8fd7a | ||
|
|
8a1f03c272 | ||
|
|
8ed479eddf | ||
|
|
c0a278ca2c | ||
|
|
2e9a7004c6 | ||
|
|
75c76a92b9 | ||
|
|
282935c6d6 | ||
|
|
d7b189b714 | ||
|
|
e3da3f356c | ||
|
|
66bed4217f | ||
|
|
56bbf6593a | ||
|
|
b8e1e7c384 | ||
|
|
a0d2c39f45 | ||
|
|
07df3186c2 | ||
|
|
5b59e74417 | ||
|
|
b4485f028d | ||
|
|
74674cfa0c | ||
|
|
f192c17c9b | ||
|
|
aa1ac29182 | ||
|
|
081ac6bf8b | ||
|
|
e4b32343ae | ||
|
|
c93370ec92 | ||
|
|
9abd7f2767 | ||
|
|
8a9877bb01 | ||
|
|
c1e1476fa6 | ||
|
|
b1abbb8e77 | ||
|
|
fcb0660def | ||
|
|
a6073e2a42 | ||
|
|
2c87077918 | ||
|
|
4e0a9f62b9 | ||
|
|
39636f5293 | ||
|
|
b53124e708 | ||
|
|
9a684c9ff5 | ||
|
|
c7d1620c1e | ||
|
|
325b54031c | ||
|
|
155a9d6266 | ||
|
|
4f6fb44f79 | ||
|
|
bfce99859f | ||
|
|
6c556d6a61 | ||
|
|
7ed42005dd | ||
|
|
aad978f5f6 | ||
|
|
c0ad4aab51 | ||
|
|
8fe0ac8195 | ||
|
|
46f8818cee | ||
|
|
118f51cc64 | ||
|
|
096d82741d | ||
|
|
b98cb31fd2 | ||
|
|
90813ce030 | ||
|
|
95bc52b2bc | ||
|
|
d79e4b5853 | ||
|
|
a40a6905be | ||
|
|
6b3a64ce14 | ||
|
|
4fca1600ca | ||
|
|
b1e65e6f9d | ||
|
|
381b23fe0c | ||
|
|
782c4446b2 | ||
|
|
76eaa75d04 | ||
|
|
361ed536a3 | ||
|
|
b1d00e9812 | ||
|
|
b0abf865cb | ||
|
|
d398381b52 | ||
|
|
d75d70bee5 | ||
|
|
296f1e90b5 | ||
|
|
9d3dfbbece | ||
|
|
d6d592f099 | ||
|
|
00cb1b6643 | ||
|
|
22babad789 | ||
|
|
18ff905746 | ||
|
|
fd0d761b92 | ||
|
|
750d4f9eca | ||
|
|
5ca151b675 | ||
|
|
67fd65d366 | ||
|
|
45981f2fee | ||
|
|
cf308fc118 |
165 changed files with 2388 additions and 1210 deletions
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
|
@ -15,12 +15,12 @@ jobs:
|
|||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '8.x.x'
|
||||
dotnet-version: '9.x.x'
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Download Dalamud
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip
|
||||
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip
|
||||
Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev"
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
|
|||
2
.github/workflows/test_release.yml
vendored
2
.github/workflows/test_release.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '8.x.x'
|
||||
dotnet-version: '9.x.x'
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Download Dalamud
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9f9bdf0873899d2e45fabaca446bb1624303b418
|
||||
Subproject commit 59a7ab5fa9941eb754757b62e4cb189e455e9514
|
||||
|
|
@ -7,6 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.github\workflows\release.yml = .github\workflows\release.yml
|
||||
Glamourer\Glamourer.json = Glamourer\Glamourer.json
|
||||
repo.json = repo.json
|
||||
.github\workflows\test_release.yml = .github\workflows\test_release.yml
|
||||
EndProjectSection
|
||||
|
|
@ -29,30 +30,30 @@ Global
|
|||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{01EB903D-871F-4285-A8CF-6486561D5B5B}.Release|Any CPU.Build.0 = Release|x64
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{29C589ED-7AF1-4DE9-82EF-33EBEF19AAFA}.Release|Any CPU.Build.0 = Release|x64
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{C0A2FAF8-C3AE-4B7B-ADDB-4AAC1A855428}.Release|Any CPU.Build.0 = Release|x64
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|x64
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.Build.0 = Release|x64
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Release|Any CPU.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -1,33 +1,43 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.State;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.String;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
|
||||
namespace Glamourer.Api;
|
||||
|
||||
public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
|
||||
public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal IEnumerable<ActorState> FindExistingStates(string actorName)
|
||||
internal IEnumerable<ActorState> FindExistingStates(string actorName, ushort worldId = ushort.MaxValue)
|
||||
{
|
||||
if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString))
|
||||
yield break;
|
||||
|
||||
foreach (var state in stateManager.Values.Where(state
|
||||
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
|
||||
yield return state;
|
||||
if (worldId == WorldId.AnyWorld.Id)
|
||||
{
|
||||
foreach (var state in stateManager.Values.Where(state
|
||||
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
|
||||
yield return state;
|
||||
}
|
||||
else
|
||||
{
|
||||
var identifier = actors.CreatePlayer(byteString, worldId);
|
||||
if (stateManager.TryGetValue(identifier, out var state))
|
||||
yield return state;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
|
||||
{
|
||||
var actor = objects[objectIndex];
|
||||
var actor = objects.Objects[objectIndex];
|
||||
var identifier = actor.GetIdentifier(actors);
|
||||
if (!identifier.IsValid)
|
||||
{
|
||||
|
|
@ -42,7 +52,7 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal ActorState? FindState(int objectIndex)
|
||||
{
|
||||
var actor = objects[objectIndex];
|
||||
var actor = objects.Objects[objectIndex];
|
||||
var identifier = actor.GetIdentifier(actors);
|
||||
if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var state))
|
||||
return state;
|
||||
|
|
@ -73,10 +83,8 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
|
|||
if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString))
|
||||
return [];
|
||||
|
||||
objects.Update();
|
||||
|
||||
return stateManager.Values.Where(state => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString)
|
||||
.Concat(objects.Identifiers
|
||||
.Concat(objects
|
||||
.Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString)
|
||||
.SelectWhere(kvp =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,15 +2,32 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.State;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Services;
|
||||
|
||||
namespace Glamourer.Api;
|
||||
|
||||
public class DesignsApi(ApiHelpers helpers, DesignManager designs, StateManager stateManager) : IGlamourerApiDesigns, IApiService
|
||||
public class DesignsApi(
|
||||
ApiHelpers helpers,
|
||||
DesignManager designs,
|
||||
StateManager stateManager,
|
||||
DesignFileSystem fileSystem,
|
||||
DesignColors color,
|
||||
DesignConverter converter)
|
||||
: IGlamourerApiDesigns, IApiService
|
||||
{
|
||||
public Dictionary<Guid, string> GetDesignList()
|
||||
=> designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text);
|
||||
|
||||
public Dictionary<Guid, (string DisplayName, string FullPath, uint DisplayColor, bool ShownInQdb)> GetDesignListExtended()
|
||||
=> 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)
|
||||
{
|
||||
var args = ApiHelpers.Args("Design", designId, "Index", objectIndex, "Key", key, "Flags", flags);
|
||||
|
|
@ -66,4 +83,56 @@ public class DesignsApi(ApiHelpers helpers, DesignManager designs, StateManager
|
|||
|
||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public (GlamourerApiEc, Guid) AddDesign(string designInput, string name)
|
||||
{
|
||||
var args = ApiHelpers.Args("DesignData", designInput, "Name", name);
|
||||
|
||||
if (converter.FromBase64(designInput, true, true, out _) is not { } designBase)
|
||||
try
|
||||
{
|
||||
var jObj = JObject.Parse(designInput);
|
||||
designBase = converter.FromJObject(jObj, true, true);
|
||||
if (designBase is null)
|
||||
return (ApiHelpers.Return(GlamourerApiEc.CouldNotParse, args), Guid.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Failure parsing data for AddDesign due to\n{ex}");
|
||||
return (ApiHelpers.Return(GlamourerApiEc.CouldNotParse, args), Guid.Empty);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var design = designBase is Design d
|
||||
? designs.CreateClone(d, name, true)
|
||||
: designs.CreateClone(designBase, name, true);
|
||||
return (ApiHelpers.Return(GlamourerApiEc.Success, args), design.Identifier);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Unknown error creating design via IPC:\n{ex}");
|
||||
return (ApiHelpers.Return(GlamourerApiEc.UnknownError, args), Guid.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public GlamourerApiEc DeleteDesign(Guid designId)
|
||||
{
|
||||
var args = ApiHelpers.Args("DesignId", designId);
|
||||
if (designs.Designs.ByIdentifier(designId) is not { } design)
|
||||
return ApiHelpers.Return(GlamourerApiEc.NothingDone, args);
|
||||
|
||||
designs.Delete(design);
|
||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public string? GetDesignBase64(Guid designId)
|
||||
=> designs.Designs.ByIdentifier(designId) is { } design
|
||||
? converter.ShareBase64(design)
|
||||
: null;
|
||||
|
||||
public JObject? GetDesignJObject(Guid designId)
|
||||
=> designs.Designs.ByIdentifier(designId) is { } design
|
||||
? converter.ShareJObject(design)
|
||||
: null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Glamourer.Api;
|
|||
public class GlamourerApi(DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
|
||||
{
|
||||
public const int CurrentApiVersionMajor = 1;
|
||||
public const int CurrentApiVersionMinor = 4;
|
||||
public const int CurrentApiVersionMinor = 7;
|
||||
|
||||
public (int Major, int Minor) ApiVersion
|
||||
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,14 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
IpcSubscribers.ApiVersion.Provider(pi, api),
|
||||
|
||||
IpcSubscribers.GetDesignList.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignListExtended.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetExtendedDesignData.Provider(pi, api.Designs),
|
||||
IpcSubscribers.ApplyDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.ApplyDesignName.Provider(pi, api.Designs),
|
||||
IpcSubscribers.AddDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.DeleteDesign.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignBase64.Provider(pi, api.Designs),
|
||||
IpcSubscribers.GetDesignJObject.Provider(pi, api.Designs),
|
||||
|
||||
IpcSubscribers.SetItem.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetItemName.Provider(pi, api.Items),
|
||||
|
|
@ -36,6 +42,8 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
(a, b, c, d, e, f) => (int)api.Items.SetItemName(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f)),
|
||||
IpcSubscribers.SetBonusItem.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetBonusItemName.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetMetaState.Provider(pi, api.Items),
|
||||
IpcSubscribers.SetMetaStateName.Provider(pi, api.Items),
|
||||
IpcSubscribers.GetState.Provider(pi, api.State),
|
||||
IpcSubscribers.GetStateName.Provider(pi, api.State),
|
||||
IpcSubscribers.GetStateBase64.Provider(pi, api.State),
|
||||
|
|
@ -46,6 +54,7 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
IpcSubscribers.RevertStateName.Provider(pi, api.State),
|
||||
IpcSubscribers.UnlockState.Provider(pi, api.State),
|
||||
IpcSubscribers.UnlockStateName.Provider(pi, api.State),
|
||||
IpcSubscribers.DeletePlayerState.Provider(pi, api.State),
|
||||
IpcSubscribers.UnlockAll.Provider(pi, api.State),
|
||||
IpcSubscribers.RevertToAutomation.Provider(pi, api.State),
|
||||
IpcSubscribers.RevertToAutomationName.Provider(pi, api.State),
|
||||
|
|
|
|||
|
|
@ -4,34 +4,31 @@ using Glamourer.Automation;
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Designs.History;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Interop;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
using Penumbra.GameData.Structs;
|
||||
using StateChanged = Glamourer.Events.StateChanged;
|
||||
|
||||
namespace Glamourer.Api;
|
||||
|
||||
public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||
{
|
||||
private readonly ApiHelpers _helpers;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly DesignConverter _converter;
|
||||
private readonly Configuration _config;
|
||||
private readonly AutoDesignApplier _autoDesigns;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly StateChanged _stateChanged;
|
||||
private readonly StateFinalized _stateFinalized;
|
||||
private readonly GPoseService _gPose;
|
||||
private readonly ApiHelpers _helpers;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly DesignConverter _converter;
|
||||
private readonly AutoDesignApplier _autoDesigns;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly StateChanged _stateChanged;
|
||||
private readonly StateFinalized _stateFinalized;
|
||||
private readonly GPoseService _gPose;
|
||||
|
||||
public StateApi(ApiHelpers helpers,
|
||||
StateManager stateManager,
|
||||
DesignConverter converter,
|
||||
Configuration config,
|
||||
AutoDesignApplier autoDesigns,
|
||||
ObjectManager objects,
|
||||
ActorObjectManager objects,
|
||||
StateChanged stateChanged,
|
||||
StateFinalized stateFinalized,
|
||||
GPoseService gPose)
|
||||
|
|
@ -39,7 +36,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
|||
_helpers = helpers;
|
||||
_stateManager = stateManager;
|
||||
_converter = converter;
|
||||
_config = config;
|
||||
_autoDesigns = autoDesigns;
|
||||
_objects = objects;
|
||||
_stateChanged = stateChanged;
|
||||
|
|
@ -204,6 +200,27 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
|||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public GlamourerApiEc DeletePlayerState(string playerName, ushort worldId, uint key)
|
||||
{
|
||||
var args = ApiHelpers.Args("Name", playerName, "World", worldId, "Key", key);
|
||||
var states = _helpers.FindExistingStates(playerName).ToList();
|
||||
if (states.Count is 0)
|
||||
return ApiHelpers.Return(GlamourerApiEc.NothingDone, args);
|
||||
|
||||
var anyLocked = false;
|
||||
foreach (var state in states)
|
||||
{
|
||||
if (state.CanUnlock(key))
|
||||
_stateManager.DeleteState(state.Identifier);
|
||||
else
|
||||
anyLocked = true;
|
||||
}
|
||||
|
||||
return ApiHelpers.Return(anyLocked
|
||||
? GlamourerApiEc.InvalidKey
|
||||
: GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
public int UnlockAll(uint key)
|
||||
=> _stateManager.Values.Count(state => state.Unlock(key));
|
||||
|
||||
|
|
@ -219,7 +236,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
|||
if (!state.CanUnlock(key))
|
||||
return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args);
|
||||
|
||||
RevertToAutomation(_objects[objectIndex], state, key, flags);
|
||||
RevertToAutomation(_objects.Objects[objectIndex], state, key, flags);
|
||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||
}
|
||||
|
||||
|
|
@ -272,15 +289,9 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
|||
var source = (flags & ApplyFlag.Once) != 0 ? StateSource.IpcManual : StateSource.IpcFixed;
|
||||
switch (flags & (ApplyFlag.Equipment | ApplyFlag.Customization))
|
||||
{
|
||||
case ApplyFlag.Equipment:
|
||||
_stateManager.ResetEquip(state, source, key);
|
||||
break;
|
||||
case ApplyFlag.Customization:
|
||||
_stateManager.ResetCustomize(state, source, key);
|
||||
break;
|
||||
case ApplyFlag.Equipment | ApplyFlag.Customization:
|
||||
_stateManager.ResetState(state, source, key);
|
||||
break;
|
||||
case ApplyFlag.Equipment: _stateManager.ResetEquip(state, source, key); break;
|
||||
case ApplyFlag.Customization: _stateManager.ResetCustomize(state, source, key); break;
|
||||
case ApplyFlag.Equipment | ApplyFlag.Customization: _stateManager.ResetState(state, source, key, true); break;
|
||||
}
|
||||
|
||||
ApiHelpers.Lock(state, key, flags);
|
||||
|
|
@ -288,7 +299,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
|||
|
||||
private GlamourerApiEc RevertToAutomation(ActorState state, uint key, ApplyFlag flags)
|
||||
{
|
||||
_objects.Update();
|
||||
if (!_objects.TryGetValue(state.Identifier, out var actors) || !actors.Valid)
|
||||
return GlamourerApiEc.ActorNotFound;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public static class ApplicationTypeExtensions
|
|||
var customizeFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeFlagExtensions.All : 0;
|
||||
var parameterFlags = type.HasFlag(ApplicationType.Customizations) ? CustomizeParameterExtensions.All : 0;
|
||||
var crestFlags = type.HasFlag(ApplicationType.GearCustomization) ? CrestExtensions.AllRelevant : 0;
|
||||
var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState : 0)
|
||||
var metaFlags = (type.HasFlag(ApplicationType.Armor) ? MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.EarState : 0)
|
||||
| (type.HasFlag(ApplicationType.Weapons) ? MetaFlag.WeaponState : 0)
|
||||
| (type.HasFlag(ApplicationType.Customizations) ? MetaFlag.Wetness : 0);
|
||||
var bonusFlags = type.HasFlag(ApplicationType.Armor) ? BonusExtensions.All : 0;
|
||||
|
|
@ -47,7 +47,13 @@ public static class ApplicationTypeExtensions
|
|||
}
|
||||
|
||||
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 ArmorFlags = EquipFlag.Head | EquipFlag.Body | EquipFlag.Hands | EquipFlag.Legs | EquipFlag.Feet;
|
||||
|
|
|
|||
|
|
@ -11,29 +11,28 @@ using Penumbra.GameData.DataContainers;
|
|||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
|
||||
namespace Glamourer.Automation;
|
||||
|
||||
public sealed class AutoDesignApplier : IDisposable
|
||||
{
|
||||
private readonly Configuration _config;
|
||||
private readonly AutoDesignManager _manager;
|
||||
private readonly StateManager _state;
|
||||
private readonly JobService _jobs;
|
||||
private readonly EquippedGearset _equippedGearset;
|
||||
private readonly ActorManager _actors;
|
||||
private readonly AutomationChanged _event;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly WeaponLoading _weapons;
|
||||
private readonly HumanModelList _humans;
|
||||
private readonly DesignMerger _designMerger;
|
||||
private readonly IClientState _clientState;
|
||||
private readonly Configuration _config;
|
||||
private readonly AutoDesignManager _manager;
|
||||
private readonly StateManager _state;
|
||||
private readonly JobService _jobs;
|
||||
private readonly EquippedGearset _equippedGearset;
|
||||
private readonly ActorManager _actors;
|
||||
private readonly AutomationChanged _event;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly WeaponLoading _weapons;
|
||||
private readonly HumanModelList _humans;
|
||||
private readonly DesignMerger _designMerger;
|
||||
private readonly IClientState _clientState;
|
||||
|
||||
private readonly JobChangeState _jobChangeState;
|
||||
|
||||
public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors,
|
||||
AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
|
||||
AutomationChanged @event, ActorObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
|
||||
EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState)
|
||||
{
|
||||
_config = config;
|
||||
|
|
@ -154,7 +153,6 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
if (newSet is not { Enabled: true })
|
||||
return;
|
||||
|
||||
_objects.Update();
|
||||
foreach (var id in newSet.Identifiers)
|
||||
{
|
||||
if (_objects.TryGetValue(id, out var data))
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Newtonsoft.Json;
|
|||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Filesystem;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using Glamourer.Services;
|
|||
using Newtonsoft.Json;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Filesystem;
|
||||
using OtterGui.Widgets;
|
||||
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||
|
|
@ -31,6 +32,7 @@ public class DefaultDesignSettings
|
|||
public bool ResetAdvancedDyes = false;
|
||||
public bool ShowQuickDesignBar = true;
|
||||
public bool ResetTemporarySettings = false;
|
||||
public bool Locked = false;
|
||||
}
|
||||
|
||||
public class Configuration : IPluginConfiguration, ISavable
|
||||
|
|
@ -38,33 +40,37 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
[JsonIgnore]
|
||||
public readonly EphemeralConfig Ephemeral;
|
||||
|
||||
public bool UseRestrictedGearProtection { get; set; } = false;
|
||||
public bool OpenFoldersByDefault { get; set; } = false;
|
||||
public bool AutoRedrawEquipOnChanges { get; set; } = false;
|
||||
public bool EnableAutoDesigns { get; set; } = true;
|
||||
public bool HideApplyCheckmarks { get; set; } = false;
|
||||
public bool SmallEquip { get; set; } = false;
|
||||
public bool UnlockedItemMode { get; set; } = false;
|
||||
public byte DisableFestivals { get; set; } = 1;
|
||||
public bool EnableGameContextMenu { get; set; } = true;
|
||||
public bool HideWindowInCutscene { get; set; } = false;
|
||||
public bool ShowAutomationSetEditing { get; set; } = true;
|
||||
public bool ShowAllAutomatedApplicationRules { get; set; } = true;
|
||||
public bool ShowUnlockedItemWarnings { get; set; } = true;
|
||||
public bool RevertManualChangesOnZoneChange { get; set; } = false;
|
||||
public bool ShowQuickBarInTabs { get; set; } = true;
|
||||
public bool OpenWindowAtStart { get; set; } = false;
|
||||
public bool ShowWindowWhenUiHidden { get; set; } = false;
|
||||
public bool KeepAdvancedDyesAttached { get; set; } = true;
|
||||
public bool ShowPalettePlusImport { get; set; } = true;
|
||||
public bool UseFloatForColors { get; set; } = true;
|
||||
public bool UseRgbForColors { get; set; } = true;
|
||||
public bool ShowColorConfig { get; set; } = true;
|
||||
public bool ChangeEntireItem { get; set; } = false;
|
||||
public bool AlwaysApplyAssociatedMods { get; set; } = false;
|
||||
public bool UseTemporarySettings { get; set; } = true;
|
||||
public bool AllowDoubleClickToApply { get; set; } = false;
|
||||
public bool RespectManualOnAutomationUpdate { get; set; } = false;
|
||||
public bool AttachToPcp { get; set; } = true;
|
||||
public bool UseRestrictedGearProtection { get; set; } = false;
|
||||
public bool OpenFoldersByDefault { get; set; } = false;
|
||||
public bool AutoRedrawEquipOnChanges { get; set; } = false;
|
||||
public bool EnableAutoDesigns { get; set; } = true;
|
||||
public bool HideApplyCheckmarks { get; set; } = false;
|
||||
public bool SmallEquip { get; set; } = false;
|
||||
public bool UnlockedItemMode { get; set; } = false;
|
||||
public byte DisableFestivals { get; set; } = 1;
|
||||
public bool EnableGameContextMenu { get; set; } = true;
|
||||
public bool HideWindowInCutscene { get; set; } = false;
|
||||
public bool ShowAutomationSetEditing { get; set; } = true;
|
||||
public bool ShowAllAutomatedApplicationRules { get; set; } = true;
|
||||
public bool ShowUnlockedItemWarnings { get; set; } = true;
|
||||
public bool RevertManualChangesOnZoneChange { get; set; } = false;
|
||||
public bool ShowQuickBarInTabs { get; set; } = true;
|
||||
public bool OpenWindowAtStart { get; set; } = false;
|
||||
public bool ShowWindowWhenUiHidden { get; set; } = false;
|
||||
public bool KeepAdvancedDyesAttached { get; set; } = true;
|
||||
public bool ShowPalettePlusImport { get; set; } = true;
|
||||
public bool UseFloatForColors { get; set; } = true;
|
||||
public bool UseRgbForColors { get; set; } = true;
|
||||
public bool ShowColorConfig { get; set; } = true;
|
||||
public bool ChangeEntireItem { get; set; } = false;
|
||||
public bool AlwaysApplyAssociatedMods { get; set; } = true;
|
||||
public bool UseTemporarySettings { get; set; } = true;
|
||||
public bool AllowDoubleClickToApply { get; set; } = false;
|
||||
public bool RespectManualOnAutomationUpdate { get; set; } = false;
|
||||
public bool PreventRandomRepeats { get; set; } = false;
|
||||
public string PcpFolder { get; set; } = "PCP";
|
||||
public string PcpColor { get; set; } = "";
|
||||
|
||||
public DesignPanelFlag HideDesignPanel { get; set; } = 0;
|
||||
public DesignPanelFlag AutoExpandDesignPanel { get; set; } = 0;
|
||||
|
|
@ -75,10 +81,11 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
public RenameField ShowRename { get; set; } = RenameField.BothDataPrio;
|
||||
public ModifiableHotkey ToggleQuickDesignBar { get; set; } = new(VirtualKey.NO_KEY);
|
||||
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 QdbButtons QdbButtons { get; set; } =
|
||||
QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvanced;
|
||||
QdbButtons.ApplyDesign | QdbButtons.RevertAll | QdbButtons.RevertAutomation | QdbButtons.RevertAdvancedDyes;
|
||||
|
||||
[JsonConverter(typeof(SortModeConverter))]
|
||||
[JsonProperty(Order = int.MaxValue)]
|
||||
|
|
@ -155,7 +162,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
|
||||
public static class Constants
|
||||
{
|
||||
public const int CurrentVersion = 7;
|
||||
public const int CurrentVersion = 8;
|
||||
|
||||
public static readonly ISortMode<Design>[] ValidSortModes =
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.GameData;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
|
@ -19,13 +19,13 @@ public record struct ApplicationCollection(
|
|||
public static readonly ApplicationCollection None = new(0, 0, CustomizeFlag.BodyType, 0, 0, 0);
|
||||
|
||||
public static readonly ApplicationCollection Equipment = new(EquipFlagExtensions.All, BonusExtensions.All,
|
||||
CustomizeFlag.BodyType, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.WeaponState | MetaFlag.VisorState);
|
||||
CustomizeFlag.BodyType, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.WeaponState | MetaFlag.VisorState | MetaFlag.EarState);
|
||||
|
||||
public static readonly ApplicationCollection Customizations = new(0, 0, CustomizeFlagExtensions.AllRelevant, 0,
|
||||
CustomizeParameterExtensions.All, MetaFlag.Wetness);
|
||||
|
||||
public static readonly ApplicationCollection Default = new(EquipFlagExtensions.All, BonusExtensions.All,
|
||||
CustomizeFlagExtensions.AllRelevant, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState);
|
||||
CustomizeFlagExtensions.AllRelevant, CrestExtensions.AllRelevant, 0, MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState);
|
||||
|
||||
public static ApplicationCollection FromKeys()
|
||||
=> (ImGui.GetIO().KeyCtrl, ImGui.GetIO().KeyShift) switch
|
||||
|
|
@ -47,7 +47,7 @@ public record struct ApplicationCollection(
|
|||
Equip = 0;
|
||||
BonusItem = 0;
|
||||
Crest = 0;
|
||||
Meta &= ~(MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState);
|
||||
Meta &= ~(MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState);
|
||||
}
|
||||
|
||||
public void RemoveCustomize()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
|
||||
public new JObject JsonSerialize()
|
||||
{
|
||||
var ret = new JObject()
|
||||
var ret = new JObject
|
||||
{
|
||||
["FileVersion"] = FileVersion,
|
||||
["Identifier"] = Identifier,
|
||||
|
|
@ -131,12 +131,17 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
var ret = new JArray();
|
||||
foreach (var (mod, settings) in AssociatedMods)
|
||||
{
|
||||
var obj = new JObject()
|
||||
var obj = new JObject
|
||||
{
|
||||
["Name"] = mod.Name,
|
||||
["Directory"] = mod.DirectoryName,
|
||||
["Enabled"] = settings.Enabled,
|
||||
};
|
||||
if (settings.Remove)
|
||||
obj["Remove"] = true;
|
||||
else if (settings.ForceInherit)
|
||||
obj["Inherit"] = true;
|
||||
else
|
||||
obj["Enabled"] = settings.Enabled;
|
||||
if (settings.Enabled)
|
||||
{
|
||||
obj["Priority"] = settings.Priority;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ public class DesignBase
|
|||
}
|
||||
|
||||
/// <summary> Used when importing .cma or .chara files. </summary>
|
||||
internal DesignBase(CustomizeService customize, in DesignData designData, EquipFlag equipFlags, CustomizeFlag customizeFlags, BonusItemFlag bonusFlags)
|
||||
internal DesignBase(CustomizeService customize, in DesignData designData, EquipFlag equipFlags, CustomizeFlag customizeFlags,
|
||||
BonusItemFlag bonusFlags)
|
||||
{
|
||||
_designData = designData;
|
||||
ApplyCustomize = customizeFlags & CustomizeFlagExtensions.AllRelevant;
|
||||
|
|
@ -254,9 +255,10 @@ public class DesignBase
|
|||
ret[slot.ToString()] = Serialize(item.Id, stains, crest, DoApplyEquip(slot), DoApplyStain(slot), DoApplyCrest(crestSlot));
|
||||
}
|
||||
|
||||
ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply");
|
||||
ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyMeta(MetaIndex.VisorState)).ToJObject("IsToggled", "Apply");
|
||||
ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyMeta(MetaIndex.WeaponState)).ToJObject("Show", "Apply");
|
||||
ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply");
|
||||
ret["VieraEars"] = new QuadBool(_designData.AreEarsVisible(), DoApplyMeta(MetaIndex.EarState)).ToJObject("Show", "Apply");
|
||||
ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyMeta(MetaIndex.VisorState)).ToJObject("IsToggled", "Apply");
|
||||
ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyMeta(MetaIndex.WeaponState)).ToJObject("Show", "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -603,6 +605,10 @@ public class DesignBase
|
|||
metaValue = QuadBool.FromJObject(equip["Visor"], "IsToggled", "Apply", QuadBool.NullFalse);
|
||||
design.SetApplyMeta(MetaIndex.VisorState, metaValue.Enabled);
|
||||
design._designData.SetVisor(metaValue.ForcedValue);
|
||||
|
||||
metaValue = QuadBool.FromJObject(equip["VieraEars"], "Show", "Apply", QuadBool.NullTrue);
|
||||
design.SetApplyMeta(MetaIndex.EarState, metaValue.Enabled);
|
||||
design._designData.SetEarsVisible(metaValue.ForcedValue);
|
||||
return;
|
||||
|
||||
void PrintWarning(string msg)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Services;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ using Dalamud.Interface.ImGuiNotification;
|
|||
using Dalamud.Interface.Utility.Raii;
|
||||
using Glamourer.Gui;
|
||||
using Glamourer.Services;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ public unsafe struct DesignData
|
|||
MetaIndex.HatState => IsHatVisible(),
|
||||
MetaIndex.VisorState => IsVisorToggled(),
|
||||
MetaIndex.WeaponState => IsWeaponVisible(),
|
||||
MetaIndex.EarState => AreEarsVisible(),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
@ -297,6 +298,7 @@ public unsafe struct DesignData
|
|||
MetaIndex.HatState => SetHatVisible(value),
|
||||
MetaIndex.VisorState => SetVisor(value),
|
||||
MetaIndex.WeaponState => SetWeaponVisible(value),
|
||||
MetaIndex.EarState => SetEarsVisible(value),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
@ -340,6 +342,9 @@ public unsafe struct DesignData
|
|||
public readonly bool IsWeaponVisible()
|
||||
=> (_states & 0x08) == 0x08;
|
||||
|
||||
public readonly bool AreEarsVisible()
|
||||
=> (_states & 0x10) == 0x00;
|
||||
|
||||
public bool SetWeaponVisible(bool value)
|
||||
{
|
||||
if (value == IsWeaponVisible())
|
||||
|
|
@ -349,6 +354,15 @@ public unsafe struct DesignData
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool SetEarsVisible(bool value)
|
||||
{
|
||||
if (value == AreEarsVisible())
|
||||
return false;
|
||||
|
||||
_states = (byte)(value ? _states & ~0x10 : _states | 0x10);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetDefaultEquipment(ItemManager items)
|
||||
{
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
|
|
@ -386,6 +400,7 @@ public unsafe struct DesignData
|
|||
|
||||
SetHatVisible(true);
|
||||
SetWeaponVisible(true);
|
||||
SetEarsVisible(true);
|
||||
SetVisor(false);
|
||||
fixed (uint* ptr = _itemIds)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
public struct CreationDate : ISortMode<Design>
|
||||
{
|
||||
public string Name
|
||||
=> "Creation Date (Older First)";
|
||||
public ReadOnlySpan<byte> Name
|
||||
=> "Creation Date (Older First)"u8;
|
||||
|
||||
public string Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date.";
|
||||
public ReadOnlySpan<byte> Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their creation date."u8;
|
||||
|
||||
public IEnumerable<IPath> GetChildren(Folder f)
|
||||
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.CreationDate));
|
||||
|
|
@ -53,11 +53,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
public struct UpdateDate : ISortMode<Design>
|
||||
{
|
||||
public string Name
|
||||
=> "Update Date (Older First)";
|
||||
public ReadOnlySpan<byte> Name
|
||||
=> "Update Date (Older First)"u8;
|
||||
|
||||
public string Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date.";
|
||||
public ReadOnlySpan<byte> Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their last update date."u8;
|
||||
|
||||
public IEnumerable<IPath> GetChildren(Folder f)
|
||||
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderBy(l => l.Value.LastEdit));
|
||||
|
|
@ -65,11 +65,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
public struct InverseCreationDate : ISortMode<Design>
|
||||
{
|
||||
public string Name
|
||||
=> "Creation Date (Newer First)";
|
||||
public ReadOnlySpan<byte> Name
|
||||
=> "Creation Date (Newer First)"u8;
|
||||
|
||||
public string Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date.";
|
||||
public ReadOnlySpan<byte> Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse creation date."u8;
|
||||
|
||||
public IEnumerable<IPath> GetChildren(Folder f)
|
||||
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.CreationDate));
|
||||
|
|
@ -77,11 +77,11 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
public struct InverseUpdateDate : ISortMode<Design>
|
||||
{
|
||||
public string Name
|
||||
=> "Update Date (Newer First)";
|
||||
public ReadOnlySpan<byte> Name
|
||||
=> "Update Date (Newer First)"u8;
|
||||
|
||||
public string Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date.";
|
||||
public ReadOnlySpan<byte> Description
|
||||
=> "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse last update date."u8;
|
||||
|
||||
public IEnumerable<IPath> GetChildren(Folder f)
|
||||
=> f.GetSubFolders().Cast<IPath>().Concat(f.GetLeaves().OrderByDescending(l => l.Value.LastEdit));
|
||||
|
|
@ -114,14 +114,14 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
|
||||
return;
|
||||
case DesignChanged.Type.Deleted:
|
||||
if (FindLeaf(design, out var leaf1))
|
||||
if (TryGetValue(design, out var leaf1))
|
||||
Delete(leaf1);
|
||||
return;
|
||||
case DesignChanged.Type.ReloadedAll:
|
||||
Reload();
|
||||
return;
|
||||
case DesignChanged.Type.Renamed when (data as RenameTransaction?)?.Old is { } oldName:
|
||||
if (!FindLeaf(design, out var leaf2))
|
||||
if (!TryGetValue(design, out var leaf2))
|
||||
return;
|
||||
|
||||
var old = oldName.FixName();
|
||||
|
|
@ -150,15 +150,6 @@ public sealed class DesignFileSystem : FileSystem<Design>, IDisposable, ISavable
|
|||
? (string.Empty, false)
|
||||
: (DesignToIdentifier(design), true);
|
||||
|
||||
// Search the entire filesystem for the leaf corresponding to a design.
|
||||
public bool FindLeaf(Design design, [NotNullWhen(true)] out Leaf? leaf)
|
||||
{
|
||||
leaf = Root.GetAllDescendants(ISortMode<Design>.Lexicographical)
|
||||
.OfType<Leaf>()
|
||||
.FirstOrDefault(l => l.Value == design);
|
||||
return leaf != null;
|
||||
}
|
||||
|
||||
internal static void MigrateOldPaths(SaveService saveService, Dictionary<string, string> oldPaths)
|
||||
{
|
||||
if (oldPaths.Count == 0)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ using Glamourer.GameData;
|
|||
using Glamourer.Interop.Material;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.Services;
|
||||
using OtterGui.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
|
||||
namespace Glamourer.Designs;
|
||||
|
||||
public sealed class DesignManager : DesignEditor
|
||||
|
|
@ -110,6 +111,7 @@ public sealed class DesignManager : DesignEditor
|
|||
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
|
||||
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
|
||||
};
|
||||
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
||||
SaveService.ImmediateSave(design);
|
||||
|
|
@ -134,6 +136,7 @@ public sealed class DesignManager : DesignEditor
|
|||
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
|
||||
};
|
||||
|
||||
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug($"Added new design {design.Identifier} by cloning Temporary Design.");
|
||||
SaveService.ImmediateSave(design);
|
||||
|
|
@ -153,6 +156,7 @@ public sealed class DesignManager : DesignEditor
|
|||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
};
|
||||
design.SetWriteProtected(Config.DefaultDesignSettings.Locked);
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug(
|
||||
$"Added new design {design.Identifier} by cloning {clone.Identifier.ToString()}.");
|
||||
|
|
@ -225,7 +229,7 @@ public sealed class DesignManager : DesignEditor
|
|||
|
||||
design.Tags = design.Tags.Append(tag).OrderBy(t => t).ToArray();
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
var idx = design.Tags.IndexOf(tag);
|
||||
var idx = design.Tags.AsEnumerable().IndexOf(tag);
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Added tag {tag} at {idx} to design {design.Identifier}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.AddedTag, design, new TagAddedTransaction(tag, idx));
|
||||
|
|
@ -258,7 +262,7 @@ public sealed class DesignManager : DesignEditor
|
|||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Renamed tag {oldTag} at {tagIdx} to {newTag} in design {design.Identifier} and reordered tags.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.ChangedTag, design,
|
||||
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.IndexOf(newTag)));
|
||||
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.AsEnumerable().IndexOf(newTag)));
|
||||
}
|
||||
|
||||
/// <summary> Add an associated mod to a design. </summary>
|
||||
|
|
@ -553,7 +557,7 @@ public sealed class DesignManager : DesignEditor
|
|||
try
|
||||
{
|
||||
File.Move(SaveService.FileNames.MigrationDesignFile,
|
||||
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"));
|
||||
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"), true);
|
||||
Glamourer.Log.Information($"Moved migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Designs.History;
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ public class EditorHistory : IDisposable, IService
|
|||
{
|
||||
if (!_stateEntries.TryGetValue(state, out var list))
|
||||
{
|
||||
list = new Queue();
|
||||
list = [];
|
||||
_stateEntries.Add(state, list);
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ public class EditorHistory : IDisposable, IService
|
|||
{
|
||||
if (!_designEntries.TryGetValue(design, out var list))
|
||||
{
|
||||
list = new Queue();
|
||||
list = [];
|
||||
_designEntries.Add(design, list);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Dalamud.Interface.ImGuiNotification;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Services;
|
||||
using Notification = OtterGui.Classes.Notification;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,15 @@ public enum MetaIndex
|
|||
VisorState = StateIndex.MetaVisorState,
|
||||
WeaponState = StateIndex.MetaWeaponState,
|
||||
ModelId = StateIndex.MetaModelId,
|
||||
EarState = StateIndex.MetaEarState,
|
||||
}
|
||||
|
||||
public static class MetaExtensions
|
||||
{
|
||||
public static readonly IReadOnlyList<MetaIndex> AllRelevant =
|
||||
[MetaIndex.Wetness, MetaIndex.HatState, MetaIndex.VisorState, MetaIndex.WeaponState];
|
||||
[MetaIndex.Wetness, MetaIndex.HatState, MetaIndex.VisorState, MetaIndex.WeaponState, MetaIndex.EarState];
|
||||
|
||||
public const MetaFlag All = MetaFlag.Wetness | MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState;
|
||||
public const MetaFlag All = MetaFlag.Wetness | MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState | MetaFlag.EarState;
|
||||
|
||||
public static MetaFlag ToFlag(this MetaIndex index)
|
||||
=> index switch
|
||||
|
|
@ -26,6 +27,7 @@ public static class MetaExtensions
|
|||
MetaIndex.HatState => MetaFlag.HatState,
|
||||
MetaIndex.VisorState => MetaFlag.VisorState,
|
||||
MetaIndex.WeaponState => MetaFlag.WeaponState,
|
||||
MetaIndex.EarState => MetaFlag.EarState,
|
||||
_ => (MetaFlag)byte.MaxValue,
|
||||
};
|
||||
|
||||
|
|
@ -36,7 +38,8 @@ public static class MetaExtensions
|
|||
MetaFlag.HatState => MetaIndex.HatState,
|
||||
MetaFlag.VisorState => MetaIndex.VisorState,
|
||||
MetaFlag.WeaponState => MetaIndex.WeaponState,
|
||||
_ => (MetaIndex)byte.MaxValue,
|
||||
MetaFlag.EarState => MetaIndex.EarState,
|
||||
_ => (MetaIndex)byte.MaxValue,
|
||||
};
|
||||
|
||||
public static IEnumerable<MetaIndex> ToIndices(this MetaFlag index)
|
||||
|
|
@ -49,6 +52,8 @@ public static class MetaExtensions
|
|||
yield return MetaIndex.VisorState;
|
||||
if (index.HasFlag(MetaFlag.WeaponState))
|
||||
yield return MetaIndex.WeaponState;
|
||||
if (index.HasFlag(MetaFlag.EarState))
|
||||
yield return MetaIndex.EarState;
|
||||
}
|
||||
|
||||
public static string ToName(this MetaIndex index)
|
||||
|
|
@ -58,6 +63,7 @@ public static class MetaExtensions
|
|||
MetaIndex.VisorState => "Visor Toggled",
|
||||
MetaIndex.WeaponState => "Weapon Visible",
|
||||
MetaIndex.Wetness => "Force Wetness",
|
||||
MetaIndex.EarState => "Ears Visible",
|
||||
_ => "Unknown Meta",
|
||||
};
|
||||
|
||||
|
|
@ -68,6 +74,7 @@ public static class MetaExtensions
|
|||
MetaIndex.VisorState => "Toggle the visor state of the characters head gear.",
|
||||
MetaIndex.WeaponState => "Hide or show the characters weapons when not drawn.",
|
||||
MetaIndex.Wetness => "Force the character to be wet or not.",
|
||||
MetaIndex.EarState => "Hide or show the characters ears through the head gear. (Viera only)",
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
using OtterGui.Services;
|
||||
using OtterGui;
|
||||
using OtterGui.Services;
|
||||
|
||||
namespace Glamourer.Designs.Special;
|
||||
|
||||
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem) : IService
|
||||
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration config) : IService
|
||||
{
|
||||
private readonly Random _rng = new();
|
||||
private readonly Random _rng = new();
|
||||
private readonly WeakReference<Design> _lastDesign = new(null!, false);
|
||||
|
||||
public Design? Design(IReadOnlyList<Design> localDesigns)
|
||||
{
|
||||
if (localDesigns.Count == 0)
|
||||
if (localDesigns.Count is 0)
|
||||
return null;
|
||||
|
||||
var idx = _rng.Next(0, localDesigns.Count);
|
||||
Glamourer.Log.Verbose($"[Random Design] Chose design {idx + 1} out of {localDesigns.Count}: {localDesigns[idx].Incognito}.");
|
||||
return localDesigns[idx];
|
||||
if (localDesigns.Count is 1)
|
||||
{
|
||||
_lastDesign.SetTarget(localDesigns[idx]);
|
||||
return localDesigns[idx];
|
||||
}
|
||||
|
||||
if (config.PreventRandomRepeats && _lastDesign.TryGetTarget(out var lastDesign))
|
||||
while (lastDesign == localDesigns[idx])
|
||||
idx = _rng.Next(0, localDesigns.Count);
|
||||
|
||||
var design = localDesigns[idx];
|
||||
Glamourer.Log.Verbose($"[Random Design] Chose design {idx + 1} out of {localDesigns.Count}: {design.Incognito}.");
|
||||
_lastDesign.SetTarget(design);
|
||||
return design;
|
||||
}
|
||||
|
||||
public Design? Design()
|
||||
|
|
@ -24,12 +38,12 @@ public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileS
|
|||
|
||||
public Design? Design(IReadOnlyList<IDesignPredicate> predicates)
|
||||
{
|
||||
if (predicates.Count == 0)
|
||||
return Design();
|
||||
if (predicates.Count == 1)
|
||||
return Design(predicates[0]);
|
||||
|
||||
return Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList());
|
||||
return predicates.Count switch
|
||||
{
|
||||
0 => Design(),
|
||||
1 => Design(predicates[0]),
|
||||
_ => Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList()),
|
||||
};
|
||||
}
|
||||
|
||||
public Design? Design(string restrictions)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public interface IDesignPredicate
|
|||
: designs;
|
||||
|
||||
private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d, DesignFileSystem fs)
|
||||
=> (d, d.Name.Lower, d.Identifier.ToString(), fs.FindLeaf(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty);
|
||||
=> (d, d.Name.Lower, d.Identifier.ToString(), fs.TryGetValue(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty);
|
||||
}
|
||||
|
||||
public static class RandomPredicate
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ public class EphemeralConfig : ISavable
|
|||
public Guid SelectedQuickDesign { get; set; } = Guid.Empty;
|
||||
public int LastSeenVersion { get; set; } = GlamourerChangelog.LastChangelogVersion;
|
||||
|
||||
public float CurrentDesignSelectorWidth { get; set; } = 200f;
|
||||
public float DesignSelectorMinimumScale { get; set; } = 0.1f;
|
||||
public float DesignSelectorMaximumScale { get; set; } = 0.5f;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
private readonly SaveService _saveService;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Glamourer.Events;
|
|||
/// </list>
|
||||
/// </summary>
|
||||
public sealed class GearsetDataLoaded()
|
||||
: EventWrapper<Model, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded))
|
||||
: EventWrapper<Actor, Model, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded))
|
||||
{
|
||||
public enum Priority
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,5 +15,8 @@ public sealed class PenumbraReloaded()
|
|||
|
||||
/// <seealso cref="Interop.VisorService.Restore"/>
|
||||
VisorService = 0,
|
||||
|
||||
/// <seealso cref="Interop.VieraEarService.Restore"/>
|
||||
VieraEarService = 0,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Glamourer.Designs.History;
|
|||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Events;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using Glamourer.Api;
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Interop.Structs;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Events;
|
||||
|
||||
|
|
|
|||
22
Glamourer/Events/VieraEarStateChanged.cs
Normal file
22
Glamourer/Events/VieraEarStateChanged.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the state of viera ear visibility for any draw object is changed.
|
||||
/// <list type="number">
|
||||
/// <item>Parameter is the model with a changed viera ear visibility state. </item>
|
||||
/// <item>Parameter is the new state. </item>
|
||||
/// <item>Parameter is whether to call the original function. </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public sealed class VieraEarStateChanged()
|
||||
: EventWrapperRef2<Actor, bool, VieraEarStateChanged.Priority>(nameof(VieraEarStateChanged))
|
||||
{
|
||||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="State.StateListener.OnVieraEarChange"/>
|
||||
StateListener = 0,
|
||||
}
|
||||
}
|
||||
|
|
@ -19,4 +19,4 @@ public sealed class VisorStateChanged()
|
|||
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
||||
StateListener = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Race = Penumbra.GameData.Enums.Race;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ using Glamourer.Gui;
|
|||
using Glamourer.Interop;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.State;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer;
|
||||
|
||||
|
|
@ -28,6 +26,7 @@ public class Glamourer : IDalamudPlugin
|
|||
|
||||
public static readonly Logger Log = new();
|
||||
public static MessageService Messager { get; private set; } = null!;
|
||||
public static DynamisIpc Dynamis { get; private set; } = null!;
|
||||
|
||||
private readonly ServiceManager _services;
|
||||
|
||||
|
|
@ -37,6 +36,7 @@ public class Glamourer : IDalamudPlugin
|
|||
{
|
||||
_services = StaticServiceManager.CreateProvider(pluginInterface, Log, this);
|
||||
Messager = _services.GetService<MessageService>();
|
||||
Dynamis = _services.GetService<DynamisIpc>();
|
||||
_services.EnsureRequiredServices();
|
||||
|
||||
_services.GetService<VisorService>();
|
||||
|
|
@ -71,6 +71,7 @@ public class Glamourer : IDalamudPlugin
|
|||
sb.Append($"> **`Festival Easter-Eggs: `** {config.DisableFestivals}\n");
|
||||
sb.Append($"> **`Apply Entire Weapon: `** {config.ChangeEntireItem}\n");
|
||||
sb.Append($"> **`Apply Associated Mods:`** {config.AlwaysApplyAssociatedMods}\n");
|
||||
sb.Append($"> **`Attach to PCP: `** {config.AttachToPcp}\n");
|
||||
sb.Append($"> **`Hidden Panels: `** {config.HideDesignPanel}\n");
|
||||
sb.Append($"> **`Show QDB: `** {config.Ephemeral.ShowDesignQuickBar}\n");
|
||||
sb.Append($"> **`QDB Hotkey: `** {config.ToggleQuickDesignBar}\n");
|
||||
|
|
@ -82,7 +83,7 @@ public class Glamourer : IDalamudPlugin
|
|||
var designManager = _services.GetService<DesignManager>();
|
||||
var autoManager = _services.GetService<AutoDesignManager>();
|
||||
var stateManager = _services.GetService<StateManager>();
|
||||
var objectManager = _services.GetService<ObjectManager>();
|
||||
var objectManager = _services.GetService<ActorObjectManager>();
|
||||
var currentPlayer = objectManager.PlayerData.Identifier;
|
||||
var states = stateManager.Where(kvp => objectManager.ContainsKey(kvp.Key)).ToList();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,92 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RootNamespace>Glamourer</RootNamespace>
|
||||
<AssemblyName>Glamourer</AssemblyName>
|
||||
<FileVersion>9.0.0.1</FileVersion>
|
||||
<AssemblyVersion>9.0.0.1</AssemblyVersion>
|
||||
<Company>SoftOtter</Company>
|
||||
<Product>Glamourer</Product>
|
||||
<Copyright>Copyright © 2023</Copyright>
|
||||
<Deterministic>true</Deterministic>
|
||||
<OutputType>Library</OutputType>
|
||||
<Copyright>Copyright © 2025</Copyright>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
<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>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="LegacyTattoo.raw" />
|
||||
|
||||
<None Include="Glamourer.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="LegacyTattoo.raw" />
|
||||
</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>
|
||||
<ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" />
|
||||
<ProjectReference Include="..\OtterGui\OtterGui.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" />
|
||||
<PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" />
|
||||
</ItemGroup>
|
||||
|
|
@ -116,14 +56,4 @@
|
|||
<InformationalVersion>$(GitCommitHash)</InformationalVersion>
|
||||
</PropertyGroup>
|
||||
</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>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
"AssemblyVersion": "9.0.0.1",
|
||||
"RepoUrl": "https://github.com/Ottermandias/Glamourer",
|
||||
"ApplicableVersion": "any",
|
||||
"DalamudApiLevel": 11,
|
||||
"DalamudApiLevel": 13,
|
||||
"ImageUrls": null,
|
||||
"IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/master/images/icon.png"
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,83 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.GameData;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using System;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
private CustomizeValue _draggedColorValue;
|
||||
private CustomizeIndex _draggedColorType;
|
||||
|
||||
|
||||
private void DrawDragDropSource(CustomizeIndex index, CustomizeData custom)
|
||||
{
|
||||
using var dragDropSource = ImUtf8.DragDropSource();
|
||||
if (!dragDropSource)
|
||||
return;
|
||||
|
||||
if (!DragDropSource.SetPayload("##colorDragDrop"u8))
|
||||
_draggedColorValue = _customize[index];
|
||||
ImUtf8.Text(
|
||||
$"Dragging {(custom.Color == 0 ? $"{_currentOption} (NPC)" : _currentOption)} #{_draggedColorValue.Value}...");
|
||||
_draggedColorType = index;
|
||||
}
|
||||
|
||||
private void DrawDragDropTarget(CustomizeIndex index)
|
||||
{
|
||||
using var dragDropTarget = ImUtf8.DragDropTarget();
|
||||
if (!dragDropTarget.Success || !dragDropTarget.IsDropping("##colorDragDrop"u8))
|
||||
return;
|
||||
|
||||
var idx = _set.DataByValue(_draggedColorType, _draggedColorValue, out var draggedData, _customize.Face);
|
||||
var bestMatch = _draggedColorValue;
|
||||
if (draggedData.HasValue)
|
||||
{
|
||||
var draggedColor = draggedData.Value.Color;
|
||||
var targetData = _set.Data(index, idx);
|
||||
if (targetData.Color != draggedColor)
|
||||
{
|
||||
var bestDiff = Diff(targetData.Color, draggedColor);
|
||||
var count = _set.Count(index);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
targetData = _set.Data(index, i);
|
||||
if (targetData.Color == draggedColor)
|
||||
{
|
||||
UpdateValue(_draggedColorValue);
|
||||
return;
|
||||
}
|
||||
|
||||
var diff = Diff(targetData.Color, draggedColor);
|
||||
if (diff >= bestDiff)
|
||||
continue;
|
||||
|
||||
bestDiff = diff;
|
||||
bestMatch = (CustomizeValue)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateValue(bestMatch);
|
||||
return;
|
||||
|
||||
static uint Diff(uint color1, uint color2)
|
||||
{
|
||||
var r = (color1 & 0xFF) - (color2 & 0xFF);
|
||||
var g = ((color1 >> 8) & 0xFF) - ((color2 >> 8) & 0xFF);
|
||||
var b = ((color1 >> 16) & 0xFF) - ((color2 >> 16) & 0xFF);
|
||||
return 30 * r * r + 59 * g * g + 11 * b * b;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawColorPicker(CustomizeIndex index)
|
||||
{
|
||||
|
|
@ -21,7 +88,7 @@ public partial class CustomizationDrawer
|
|||
|
||||
using (_ = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale, current < 0))
|
||||
{
|
||||
if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.None, _framedIconSize))
|
||||
if (ImGui.ColorButton($"{_customize[index].Value}##color", color, ImGuiColorEditFlags.NoDragDrop, _framedIconSize))
|
||||
{
|
||||
ImGui.OpenPopup(ColorPickerPopupName);
|
||||
}
|
||||
|
|
@ -30,6 +97,9 @@ public partial class CustomizationDrawer
|
|||
var data = _set.Data(_currentIndex, current, _customize.Face);
|
||||
UpdateValue(data.Value);
|
||||
}
|
||||
|
||||
DrawDragDropSource(index, custom);
|
||||
DrawDragDropTarget(index);
|
||||
}
|
||||
|
||||
var npc = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Dalamud.Interface.Textures.TextureWraps;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
@ -34,7 +35,7 @@ public partial class CustomizationDrawer
|
|||
var hasIcon = icon.TryGetWrap(out var wrap, out _);
|
||||
using (_ = ImRaii.Disabled(_locked || _currentIndex is CustomizeIndex.Face && _lockedRedraw))
|
||||
{
|
||||
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize))
|
||||
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize))
|
||||
{
|
||||
ImGui.OpenPopup(IconSelectorPopup);
|
||||
}
|
||||
|
|
@ -88,7 +89,7 @@ public partial class CustomizationDrawer
|
|||
: ImRaii.PushColor(ImGuiCol.Button, ColorId.FavoriteStarOn.Value(), isFavorite);
|
||||
var hasIcon = icon.TryGetWrap(out var wrap, out var _);
|
||||
|
||||
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize))
|
||||
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize))
|
||||
{
|
||||
UpdateValue(custom.Value);
|
||||
ImGui.CloseCurrentPopup();
|
||||
|
|
@ -214,7 +215,7 @@ public partial class CustomizationDrawer
|
|||
hasIcon = icon.TryGetWrap(out wrap, out _);
|
||||
}
|
||||
|
||||
if (ImGui.ImageButton(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, _iconSize, Vector2.Zero, Vector2.One,
|
||||
if (ImGui.ImageButton(wrap?.Handle ?? icon.GetWrapOrEmpty().Handle, _iconSize, Vector2.Zero, Vector2.One,
|
||||
(int)ImGui.GetStyle().FramePadding.X, Vector4.Zero, enabled ? Vector4.One : _redTint))
|
||||
{
|
||||
_customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGuiInternal;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Dalamud.Plugin.Services;
|
|||
using Glamourer.GameData;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Glamourer.Designs;
|
|||
using Glamourer.GameData;
|
||||
using Glamourer.Interop.PalettePlus;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
|
|
@ -287,13 +287,13 @@ public class CustomizeParameterDrawer(Configuration config, PaletteImport import
|
|||
}
|
||||
|
||||
private ImGuiColorEditFlags GetFlags()
|
||||
=> Format | Display | ImGuiColorEditFlags.HDR | ImGuiColorEditFlags.NoOptions;
|
||||
=> Format | Display | ImGuiColorEditFlags.Hdr | ImGuiColorEditFlags.NoOptions;
|
||||
|
||||
private ImGuiColorEditFlags Format
|
||||
=> config.UseFloatForColors ? ImGuiColorEditFlags.Float : ImGuiColorEditFlags.Uint8;
|
||||
|
||||
private ImGuiColorEditFlags Display
|
||||
=> config.UseRgbForColors ? ImGuiColorEditFlags.DisplayRGB : ImGuiColorEditFlags.DisplayHSV;
|
||||
=> config.UseRgbForColors ? ImGuiColorEditFlags.DisplayRgb : ImGuiColorEditFlags.DisplayHsv;
|
||||
|
||||
private ImRaii.IEndObject EnsureSize()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ using Glamourer.Designs;
|
|||
using Glamourer.Designs.History;
|
||||
using Glamourer.Designs.Special;
|
||||
using Glamourer.Events;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
protected readonly TabSelected TabSelected;
|
||||
protected float InnerWidth;
|
||||
private IDesignStandIn? _currentDesign;
|
||||
private bool _isCurrentSelectionDirty;
|
||||
|
||||
protected DesignComboBase(Func<IReadOnlyList<Tuple<IDesignStandIn, string>>> generator, Logger log, DesignChanged designChanged,
|
||||
TabSelected tabSelected, EphemeralConfig config, DesignColors designColors)
|
||||
|
|
@ -83,17 +85,11 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
DrawRightAligned(quickDesign.ResolveName(false), "[Nothing]", DesignColors.MissingColor);
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(p => _currentDesign == p.Item1);
|
||||
UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null);
|
||||
return CurrentSelectionIdx;
|
||||
}
|
||||
|
||||
protected bool Draw(IDesignStandIn? currentDesign, string? label, float width)
|
||||
{
|
||||
_currentDesign = currentDesign;
|
||||
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
|
||||
UpdateCurrentSelection();
|
||||
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
|
||||
var name = label ?? "Select Design Here...";
|
||||
bool ret;
|
||||
using (_ = currentDesign != null ? ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(currentDesign as Design)) : null)
|
||||
|
|
@ -127,37 +123,60 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
return filter.IsContained(path) || filter.IsContained(design.ResolveName(false));
|
||||
}
|
||||
|
||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _ = null)
|
||||
protected override void OnMouseWheel(string preview, ref int _2, int steps)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DesignChanged.Type.Created:
|
||||
case DesignChanged.Type.Renamed:
|
||||
case DesignChanged.Type.ChangedColor:
|
||||
case DesignChanged.Type.Deleted:
|
||||
case DesignChanged.Type.QuickDesignBar:
|
||||
var priorState = IsInitialized;
|
||||
if (priorState)
|
||||
Cleanup();
|
||||
CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1));
|
||||
if (CurrentSelectionIdx >= 0)
|
||||
{
|
||||
UpdateSelection(Items[CurrentSelectionIdx]);
|
||||
}
|
||||
else if (Items.Count > 0)
|
||||
{
|
||||
CurrentSelectionIdx = 0;
|
||||
UpdateSelection(Items[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSelection(null);
|
||||
}
|
||||
if (!ReferenceEquals(_currentDesign, CurrentSelection?.Item1))
|
||||
CurrentSelectionIdx = -1;
|
||||
|
||||
if (!priorState)
|
||||
Cleanup();
|
||||
break;
|
||||
base.OnMouseWheel(preview, ref _2, steps);
|
||||
}
|
||||
|
||||
private void UpdateCurrentSelection()
|
||||
{
|
||||
if (!_isCurrentSelectionDirty)
|
||||
return;
|
||||
|
||||
var priorState = IsInitialized;
|
||||
if (priorState)
|
||||
Cleanup();
|
||||
CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1));
|
||||
if (CurrentSelectionIdx >= 0)
|
||||
{
|
||||
UpdateSelection(Items[CurrentSelectionIdx]);
|
||||
}
|
||||
else if (Items.Count > 0)
|
||||
{
|
||||
CurrentSelectionIdx = 0;
|
||||
UpdateSelection(Items[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSelection(null);
|
||||
}
|
||||
|
||||
if (!priorState)
|
||||
Cleanup();
|
||||
_isCurrentSelectionDirty = false;
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(p => _currentDesign == p.Item1);
|
||||
UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null);
|
||||
return CurrentSelectionIdx;
|
||||
}
|
||||
|
||||
private void OnDesignChanged(DesignChanged.Type type, Design? _1, ITransaction? _2 = null)
|
||||
{
|
||||
_isCurrentSelectionDirty = type switch
|
||||
{
|
||||
DesignChanged.Type.Created => true,
|
||||
DesignChanged.Type.Renamed => true,
|
||||
DesignChanged.Type.ChangedColor => true,
|
||||
DesignChanged.Type.Deleted => true,
|
||||
DesignChanged.Type.QuickDesignBar => true,
|
||||
_ => _isCurrentSelectionDirty,
|
||||
};
|
||||
}
|
||||
|
||||
private void QuickSelectedDesignTooltip(IDesignStandIn? design)
|
||||
|
|
@ -175,7 +194,7 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, s
|
|||
ImGui.TextUnformatted("Currently resolving to ");
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(linkedDesign));
|
||||
ImGui.SameLine(0, 0);
|
||||
ImGui.TextUnformatted(linkedDesign.Name);
|
||||
ImGui.TextUnformatted(linkedDesign.Name.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -225,8 +244,7 @@ public abstract class DesignCombo : DesignComboBase
|
|||
|
||||
public sealed class QuickDesignCombo : DesignCombo
|
||||
{
|
||||
public QuickDesignCombo(DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
public QuickDesignCombo(DesignFileSystem fileSystem,
|
||||
Logger log,
|
||||
DesignChanged designChanged,
|
||||
TabSelected tabSelected,
|
||||
|
|
@ -234,9 +252,9 @@ public sealed class QuickDesignCombo : DesignCombo
|
|||
DesignColors designColors)
|
||||
: base(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Where(d => d.QuickDesign)
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Where(kvp => kvp.Key.QuickDesign)
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
])
|
||||
{
|
||||
|
|
@ -277,7 +295,6 @@ public sealed class QuickDesignCombo : DesignCombo
|
|||
}
|
||||
|
||||
public sealed class LinkDesignCombo(
|
||||
DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
Logger log,
|
||||
DesignChanged designChanged,
|
||||
|
|
@ -286,8 +303,8 @@ public sealed class LinkDesignCombo(
|
|||
DesignColors designColors)
|
||||
: DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
]);
|
||||
|
||||
|
|
@ -301,8 +318,8 @@ public sealed class RandomDesignCombo(
|
|||
DesignColors designColors)
|
||||
: DesignCombo(log, designChanged, tabSelected, config, designColors, () =>
|
||||
[
|
||||
.. designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
.. fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2),
|
||||
])
|
||||
{
|
||||
|
|
@ -328,7 +345,6 @@ public sealed class RandomDesignCombo(
|
|||
}
|
||||
|
||||
public sealed class SpecialDesignCombo(
|
||||
DesignManager designs,
|
||||
DesignFileSystem fileSystem,
|
||||
TabSelected tabSelected,
|
||||
DesignColors designColors,
|
||||
|
|
@ -338,8 +354,8 @@ public sealed class SpecialDesignCombo(
|
|||
EphemeralConfig config,
|
||||
RandomDesignGenerator rng,
|
||||
QuickSelectedDesign quickSelectedDesign)
|
||||
: DesignComboBase(() => designs.Designs
|
||||
.Select(d => new Tuple<IDesignStandIn, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
|
||||
: DesignComboBase(() => fileSystem
|
||||
.Select(kvp => new Tuple<IDesignStandIn, string>(kvp.Key, kvp.Value.FullName()))
|
||||
.OrderBy(d => d.Item2)
|
||||
.Prepend(new Tuple<IDesignStandIn, string>(new RandomDesign(rng), string.Empty))
|
||||
.Prepend(new Tuple<IDesignStandIn, string>(quickSelectedDesign, string.Empty))
|
||||
|
|
|
|||
|
|
@ -6,28 +6,28 @@ using Dalamud.Interface.Windowing;
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Automation;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
[Flags]
|
||||
public enum QdbButtons
|
||||
{
|
||||
ApplyDesign = 0x01,
|
||||
RevertAll = 0x02,
|
||||
RevertAutomation = 0x04,
|
||||
RevertAdvanced = 0x08,
|
||||
RevertEquip = 0x10,
|
||||
RevertCustomize = 0x20,
|
||||
ReapplyAutomation = 0x40,
|
||||
ResetSettings = 0x80,
|
||||
ApplyDesign = 0x01,
|
||||
RevertAll = 0x02,
|
||||
RevertAutomation = 0x04,
|
||||
RevertAdvancedDyes = 0x08,
|
||||
RevertEquip = 0x10,
|
||||
RevertCustomize = 0x20,
|
||||
ReapplyAutomation = 0x40,
|
||||
ResetSettings = 0x80,
|
||||
RevertAdvancedCustomization = 0x100,
|
||||
}
|
||||
|
||||
public sealed class DesignQuickBar : Window, IDisposable
|
||||
|
|
@ -37,21 +37,21 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
? ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoMove
|
||||
: ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing;
|
||||
|
||||
private readonly Configuration _config;
|
||||
private readonly QuickDesignCombo _designCombo;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly AutoDesignApplier _autoDesignApplier;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly PenumbraService _penumbra;
|
||||
private readonly IKeyState _keyState;
|
||||
private readonly ImRaii.Style _windowPadding = new();
|
||||
private readonly ImRaii.Color _windowColor = new();
|
||||
private DateTime _keyboardToggle = DateTime.UnixEpoch;
|
||||
private int _numButtons;
|
||||
private readonly StringBuilder _tooltipBuilder = new(512);
|
||||
private readonly Configuration _config;
|
||||
private readonly QuickDesignCombo _designCombo;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly AutoDesignApplier _autoDesignApplier;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly PenumbraService _penumbra;
|
||||
private readonly IKeyState _keyState;
|
||||
private readonly ImRaii.Style _windowPadding = new();
|
||||
private readonly ImRaii.Color _windowColor = new();
|
||||
private DateTime _keyboardToggle = DateTime.UnixEpoch;
|
||||
private int _numButtons;
|
||||
private readonly StringBuilder _tooltipBuilder = new(512);
|
||||
|
||||
public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState,
|
||||
ObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra)
|
||||
ActorObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra)
|
||||
: base("Glamourer Quick Bar", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking)
|
||||
{
|
||||
_config = config;
|
||||
|
|
@ -64,6 +64,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
IsOpen = _config.Ephemeral.ShowDesignQuickBar;
|
||||
DisableWindowSounds = true;
|
||||
Size = Vector2.Zero;
|
||||
RespectCloseHotkey = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -125,6 +126,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
DrawRevertEquipButton(buttonSize);
|
||||
DrawRevertCustomizeButton(buttonSize);
|
||||
DrawRevertAdvancedCustomization(buttonSize);
|
||||
DrawRevertAdvancedDyes(buttonSize);
|
||||
DrawRevertAutomationButton(buttonSize);
|
||||
DrawReapplyAutomationButton(buttonSize);
|
||||
DrawResetSettingsButton(buttonSize);
|
||||
|
|
@ -173,7 +175,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Apply ")
|
||||
.Append(design.ResolveName(_config.Ephemeral.IncognitoMode))
|
||||
.Append(" to {_targetIdentifier}.");
|
||||
.Append(" to ").Append(_config.Ephemeral.IncognitoMode ? _targetIdentifier.Incognito(null) : _targetIdentifier.ToName());
|
||||
}
|
||||
|
||||
if (available == 0)
|
||||
|
|
@ -222,7 +224,8 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
}
|
||||
|
||||
if (available == 0)
|
||||
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
|
||||
_tooltipBuilder.Append(
|
||||
"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);
|
||||
ImGui.SameLine();
|
||||
|
|
@ -258,9 +261,10 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
}
|
||||
|
||||
if (available == 0)
|
||||
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
|
||||
_tooltipBuilder.Append(
|
||||
"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();
|
||||
if (!clicked)
|
||||
return;
|
||||
|
|
@ -300,7 +304,8 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
}
|
||||
|
||||
if (available == 0)
|
||||
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
|
||||
_tooltipBuilder.Append(
|
||||
"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);
|
||||
ImGui.SameLine();
|
||||
|
|
@ -316,7 +321,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
|
||||
private void DrawRevertAdvancedCustomization(Vector2 buttonSize)
|
||||
{
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization))
|
||||
return;
|
||||
|
||||
var available = 0;
|
||||
|
|
@ -325,7 +330,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid)
|
||||
{
|
||||
available |= 1;
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced customizations and dyes of the player character to their game state.");
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced customizations of the player character to their game state.");
|
||||
}
|
||||
|
||||
if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid)
|
||||
|
|
@ -333,7 +338,40 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (available != 0)
|
||||
_tooltipBuilder.Append('\n');
|
||||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced customizations and dyes of ")
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced customizations of ")
|
||||
.Append(_targetIdentifier)
|
||||
.Append(" to their game state.");
|
||||
}
|
||||
|
||||
if (available == 0)
|
||||
_tooltipBuilder.Append("Neither player character nor target are available or their state is locked.");
|
||||
|
||||
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.PaintBrush, buttonSize, available);
|
||||
ImGui.SameLine();
|
||||
if (clicked)
|
||||
_stateManager.ResetAdvancedCustomizations(state!, StateSource.Manual);
|
||||
}
|
||||
|
||||
private void DrawRevertAdvancedDyes(Vector2 buttonSize)
|
||||
{
|
||||
if (!_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedDyes))
|
||||
return;
|
||||
|
||||
var available = 0;
|
||||
_tooltipBuilder.Clear();
|
||||
|
||||
if (_playerIdentifier.IsValid && _playerState is { IsLocked: false } && _playerData.Valid)
|
||||
{
|
||||
available |= 1;
|
||||
_tooltipBuilder.Append("Left-Click: Revert the advanced dyes of the player character to their game state.");
|
||||
}
|
||||
|
||||
if (_targetIdentifier.IsValid && _targetState is { IsLocked: false } && _targetData.Valid)
|
||||
{
|
||||
if (available != 0)
|
||||
_tooltipBuilder.Append('\n');
|
||||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Revert the advanced dyes of ")
|
||||
.Append(_targetIdentifier)
|
||||
.Append(" to their game state.");
|
||||
}
|
||||
|
|
@ -344,7 +382,7 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.Palette, buttonSize, available);
|
||||
ImGui.SameLine();
|
||||
if (clicked)
|
||||
_stateManager.ResetAdvancedState(state!, StateSource.Manual);
|
||||
_stateManager.ResetAdvancedDyes(state!, StateSource.Manual);
|
||||
}
|
||||
|
||||
private void DrawRevertCustomizeButton(Vector2 buttonSize)
|
||||
|
|
@ -424,7 +462,9 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (_playerIdentifier.IsValid && _playerData.Valid)
|
||||
{
|
||||
available |= 1;
|
||||
_tooltipBuilder.Append("Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
|
||||
_tooltipBuilder
|
||||
.Append(
|
||||
"Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
|
||||
.Append(_playerIdentifier)
|
||||
.Append('.');
|
||||
}
|
||||
|
|
@ -434,7 +474,9 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
if (available != 0)
|
||||
_tooltipBuilder.Append('\n');
|
||||
available |= 2;
|
||||
_tooltipBuilder.Append("Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
|
||||
_tooltipBuilder
|
||||
.Append(
|
||||
"Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
|
||||
.Append(_targetIdentifier)
|
||||
.Append('.');
|
||||
}
|
||||
|
|
@ -495,7 +537,9 @@ public sealed class DesignQuickBar : Window, IDisposable
|
|||
++_numButtons;
|
||||
}
|
||||
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvanced))
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedCustomization))
|
||||
++_numButtons;
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertAdvancedDyes))
|
||||
++_numButtons;
|
||||
if (_config.QdbButtons.HasFlag(QdbButtons.RevertCustomize))
|
||||
++_numButtons;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Lumina.Excel.Sheets;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData)
|
|||
public readonly void SetStains(StainIds stains)
|
||||
=> _editor.ChangeStains(_object, Slot, stains, ApplySettings.Manual);
|
||||
|
||||
public readonly void SetStain(int which, StainId stain)
|
||||
=> _editor.ChangeStains(_object, Slot, CurrentStains.With(which, stain), ApplySettings.Manual);
|
||||
|
||||
public readonly void SetApplyItem(bool value)
|
||||
{
|
||||
var manager = (DesignManager)_editor;
|
||||
|
|
|
|||
83
Glamourer/Gui/Equipment/EquipItemSlotCache.cs
Normal file
83
Glamourer/Gui/Equipment/EquipItemSlotCache.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using Glamourer.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
[InlineArray(13)]
|
||||
public struct EquipItemSlotCache
|
||||
{
|
||||
private EquipItem _element;
|
||||
|
||||
public EquipItem Dragged
|
||||
{
|
||||
get => this[^1];
|
||||
set => this[^1] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
=> ((Span<EquipItem>)this).Clear();
|
||||
|
||||
public EquipItem this[EquipSlot slot]
|
||||
{
|
||||
get => this[(int)slot.ToIndex()];
|
||||
set => this[(int)slot.ToIndex()] = value;
|
||||
}
|
||||
|
||||
public void Update(ItemManager items, in EquipItem item, EquipSlot startSlot)
|
||||
{
|
||||
if (item.Id == Dragged.Id && item.Type == Dragged.Type)
|
||||
return;
|
||||
|
||||
switch (startSlot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
{
|
||||
Clear();
|
||||
this[EquipSlot.MainHand] = item;
|
||||
if (item.Type is FullEquipType.Sword)
|
||||
this[EquipSlot.OffHand] = items.FindClosestShield(item.ItemId, out var shield) ? shield : default;
|
||||
else
|
||||
this[EquipSlot.OffHand] = items.ItemData.Secondary.GetValueOrDefault(item.ItemId);
|
||||
break;
|
||||
}
|
||||
case EquipSlot.OffHand:
|
||||
{
|
||||
Clear();
|
||||
if (item.Type is FullEquipType.Shield)
|
||||
this[EquipSlot.MainHand] = items.FindClosestSword(item.ItemId, out var sword) ? sword : default;
|
||||
else
|
||||
this[EquipSlot.MainHand] = items.ItemData.Primary.GetValueOrDefault(item.ItemId);
|
||||
this[EquipSlot.OffHand] = item;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this[EquipSlot.MainHand] = default;
|
||||
this[EquipSlot.OffHand] = default;
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
if (startSlot == slot)
|
||||
{
|
||||
this[slot] = item;
|
||||
continue;
|
||||
}
|
||||
|
||||
var slotItem = items.Identify(slot, item.PrimaryId, item.Variant);
|
||||
if (!slotItem.Valid || slotItem.ItemId.Id is not 0 != item.ItemId.Id is not 0)
|
||||
{
|
||||
slotItem = items.Identify(EquipSlot.OffHand, item.PrimaryId, item.SecondaryId, 1, item.Type);
|
||||
if (slotItem.ItemId.Id is not 0 != item.ItemId.Id is not 0)
|
||||
slotItem = default;
|
||||
}
|
||||
|
||||
this[slot] = slotItem;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Dragged = item;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,15 @@ using Dalamud.Interface.Utility;
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Gui.Materials;
|
||||
using Glamourer.Interop.Material;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Text.EndObjects;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
@ -32,20 +32,24 @@ public class EquipmentDrawer
|
|||
private readonly Configuration _config;
|
||||
private readonly GPoseService _gPose;
|
||||
private readonly AdvancedDyePopup _advancedDyes;
|
||||
private readonly ItemCopyService _itemCopy;
|
||||
|
||||
private float _requiredComboWidthUnscaled;
|
||||
private float _requiredComboWidth;
|
||||
|
||||
private Stain? _draggedStain;
|
||||
private Stain? _draggedStain;
|
||||
private EquipItemSlotCache _draggedItem;
|
||||
private EquipSlot _dragTarget;
|
||||
|
||||
public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures,
|
||||
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes)
|
||||
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy)
|
||||
{
|
||||
_items = items;
|
||||
_textures = textures;
|
||||
_config = config;
|
||||
_gPose = gPose;
|
||||
_advancedDyes = advancedDyes;
|
||||
_itemCopy = itemCopy;
|
||||
_stainData = items.Stains;
|
||||
_stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites);
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
|
||||
|
|
@ -78,6 +82,7 @@ public class EquipmentDrawer
|
|||
|
||||
_requiredComboWidth = _requiredComboWidthUnscaled * ImGuiHelpers.GlobalScale;
|
||||
_advancedMaterialColor = ColorId.AdvancedDyeActive.Value();
|
||||
_dragTarget = EquipSlot.Unknown;
|
||||
}
|
||||
|
||||
private bool VerifyRestrictedGear(EquipDrawData data)
|
||||
|
|
@ -183,6 +188,7 @@ public class EquipmentDrawer
|
|||
return change;
|
||||
}
|
||||
|
||||
|
||||
#region Small
|
||||
|
||||
private void DrawEquipSmall(in EquipDrawData equipDrawData)
|
||||
|
|
@ -401,6 +407,7 @@ public class EquipmentDrawer
|
|||
? _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss)
|
||||
: _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width);
|
||||
|
||||
_itemCopy.HandleCopyPaste(data, index);
|
||||
if (!change)
|
||||
DrawStainDragDrop(data, index, stain, found);
|
||||
|
||||
|
|
@ -425,8 +432,8 @@ public class EquipmentDrawer
|
|||
using var dragSource = ImUtf8.DragDropSource();
|
||||
if (dragSource.Success)
|
||||
{
|
||||
if (DragDropSource.SetPayload("stainDragDrop"u8))
|
||||
_draggedStain = stain;
|
||||
DragDropSource.SetPayload("stainDragDrop"u8);
|
||||
_draggedStain = stain;
|
||||
ImUtf8.Text($"Dragging {stain.Name}...");
|
||||
}
|
||||
}
|
||||
|
|
@ -451,10 +458,12 @@ public class EquipmentDrawer
|
|||
using var disabled = ImRaii.Disabled(data.Locked);
|
||||
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth);
|
||||
DrawGearDragDrop(data);
|
||||
if (change)
|
||||
data.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0)
|
||||
data.SetItem(_items.Identify(data.Slot, combo.CustomSetId, combo.CustomVariant));
|
||||
_itemCopy.HandleCopyPaste(data);
|
||||
|
||||
if (ResetOrClear(data.Locked, clear, data.AllowRevert, true, data.CurrentItem, data.GameItem, ItemManager.NothingItem(data.Slot),
|
||||
out var item))
|
||||
|
|
@ -472,6 +481,14 @@ public class EquipmentDrawer
|
|||
var change = combo.Draw(data.CurrentItem.Name, data.CurrentItem.Id.BonusItem,
|
||||
small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth);
|
||||
if (ImGui.IsItemHovered() && ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsKeyPressed(ImGuiKey.C))
|
||||
_itemCopy.Copy(combo.CurrentSelection);
|
||||
else if (ImGui.IsKeyPressed(ImGuiKey.V))
|
||||
_itemCopy.Paste(data.Slot.ToEquipType(), data.SetItem);
|
||||
}
|
||||
|
||||
if (change)
|
||||
data.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0)
|
||||
|
|
@ -482,6 +499,50 @@ public class EquipmentDrawer
|
|||
data.SetItem(item);
|
||||
}
|
||||
|
||||
private void DrawGearDragDrop(in EquipDrawData data)
|
||||
{
|
||||
if (data.CurrentItem.Valid)
|
||||
{
|
||||
using var dragSource = ImUtf8.DragDropSource();
|
||||
if (dragSource.Success)
|
||||
{
|
||||
DragDropSource.SetPayload("equipDragDrop"u8);
|
||||
_draggedItem.Update(_items, data.CurrentItem, data.Slot);
|
||||
}
|
||||
}
|
||||
|
||||
using var dragTarget = ImUtf8.DragDropTarget();
|
||||
if (!dragTarget)
|
||||
return;
|
||||
|
||||
var item = _draggedItem[data.Slot];
|
||||
if (!item.Valid)
|
||||
return;
|
||||
|
||||
_dragTarget = data.Slot;
|
||||
if (!dragTarget.IsDropping("equipDragDrop"u8))
|
||||
return;
|
||||
|
||||
data.SetItem(item);
|
||||
_draggedItem.Clear();
|
||||
}
|
||||
|
||||
public unsafe void DrawDragDropTooltip()
|
||||
{
|
||||
var payload = ImGui.GetDragDropPayload().Handle;
|
||||
if (payload is null)
|
||||
return;
|
||||
|
||||
if (!MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)Unsafe.AsPointer(ref payload->DataType_0)).SequenceEqual("equipDragDrop"u8))
|
||||
return;
|
||||
|
||||
using var tt = ImUtf8.Tooltip();
|
||||
if (_dragTarget is EquipSlot.Unknown)
|
||||
ImUtf8.Text($"Dragging {_draggedItem.Dragged.Name}...");
|
||||
else
|
||||
ImUtf8.Text($"Converting to {_draggedItem[_dragTarget].Name}...");
|
||||
}
|
||||
|
||||
private static bool ResetOrClear<T>(bool locked, bool clicked, bool allowRevert, bool allowClear,
|
||||
in T currentItem, in T revertItem, in T clearItem, out T? item) where T : IEquatable<T>
|
||||
{
|
||||
|
|
@ -530,8 +591,13 @@ public class EquipmentDrawer
|
|||
if (combo.Draw(mainhand.CurrentItem.Name, mainhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth))
|
||||
changedItem = combo.CurrentSelection;
|
||||
else if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
|
||||
default, out var c))
|
||||
else if (combo.CustomVariant.Id > 0 && (drawAll || ItemData.ConvertWeaponId(combo.CustomSetId) == mainhand.CurrentItem.Type))
|
||||
changedItem = _items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant);
|
||||
_itemCopy.HandleCopyPaste(mainhand);
|
||||
DrawGearDragDrop(mainhand);
|
||||
|
||||
if (ResetOrClear(mainhand.Locked || unknown, open, mainhand.AllowRevert, false, mainhand.CurrentItem, mainhand.GameItem,
|
||||
default, out var c))
|
||||
changedItem = c;
|
||||
|
||||
if (changedItem != null)
|
||||
|
|
@ -548,7 +614,8 @@ public class EquipmentDrawer
|
|||
}
|
||||
|
||||
if (unknown)
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled,
|
||||
"The weapon type could not be identified, thus changing it to other weapons of that type is not possible."u8);
|
||||
}
|
||||
|
||||
private void DrawOffhand(in EquipDrawData mainhand, in EquipDrawData offhand, out string label, bool small, bool clear, bool open)
|
||||
|
|
@ -568,6 +635,10 @@ public class EquipmentDrawer
|
|||
if (combo.Draw(offhand.CurrentItem.Name, offhand.CurrentItem.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength,
|
||||
_requiredComboWidth))
|
||||
offhand.SetItem(combo.CurrentSelection);
|
||||
else if (combo.CustomVariant.Id > 0 && ItemData.ConvertWeaponId(combo.CustomSetId) == offhand.CurrentItem.Type)
|
||||
offhand.SetItem(_items.Identify(mainhand.Slot, combo.CustomSetId, combo.CustomWeaponId, combo.CustomVariant));
|
||||
_itemCopy.HandleCopyPaste(offhand);
|
||||
DrawGearDragDrop(offhand);
|
||||
|
||||
var defaultOffhand = _items.GetDefaultOffhand(mainhand.CurrentItem);
|
||||
if (ResetOrClear(locked, clear, offhand.AllowRevert, true, offhand.CurrentItem, offhand.GameItem, defaultOffhand, out var item))
|
||||
|
|
@ -622,6 +693,7 @@ public class EquipmentDrawer
|
|||
{
|
||||
ImUtf8.Text(label);
|
||||
}
|
||||
|
||||
if (hasAdvancedDyes)
|
||||
ImUtf8.HoverTooltip("This design has advanced dyes setup for this slot."u8);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Lumina.Excel.Sheets;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
|
|||
73
Glamourer/Gui/Equipment/ItemCopyService.cs
Normal file
73
Glamourer/Gui/Equipment/ItemCopyService.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using Glamourer.Services;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
public class ItemCopyService(ItemManager items, DictStain stainData) : IUiService
|
||||
{
|
||||
public EquipItem? Item { get; private set; }
|
||||
public Stain? Stain { get; private set; }
|
||||
|
||||
public void Copy(in EquipItem item)
|
||||
=> Item = item;
|
||||
|
||||
public void Copy(in Stain stain)
|
||||
=> Stain = stain;
|
||||
|
||||
public void Paste(int which, Action<int, StainId> setter)
|
||||
{
|
||||
if (Stain is { } stain)
|
||||
setter(which, stain.RowIndex);
|
||||
}
|
||||
|
||||
public void Paste(FullEquipType type, Action<EquipItem> setter)
|
||||
{
|
||||
if (Item is not { } item)
|
||||
return;
|
||||
|
||||
if (type != item.Type)
|
||||
{
|
||||
if (type.IsBonus())
|
||||
item = items.Identify(type.ToBonus(), item.PrimaryId, item.Variant);
|
||||
else if (type.IsEquipment() || type.IsAccessory())
|
||||
item = items.Identify(type.ToSlot(), item.PrimaryId, item.Variant);
|
||||
else
|
||||
item = items.Identify(type.ToSlot(), item.PrimaryId, item.SecondaryId, item.Variant);
|
||||
}
|
||||
|
||||
if (item.Valid && item.Type == type)
|
||||
setter(item);
|
||||
}
|
||||
|
||||
public void HandleCopyPaste(in EquipDrawData data)
|
||||
{
|
||||
if (ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
Paste(data.CurrentItem.Type, data.SetItem);
|
||||
}
|
||||
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled) && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
{
|
||||
Copy(data.CurrentItem);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleCopyPaste(in EquipDrawData data, int which)
|
||||
{
|
||||
if (ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
|
||||
Paste(which, data.SetStain);
|
||||
}
|
||||
else if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)
|
||||
&& ImGui.IsMouseClicked(ImGuiMouseButton.Middle)
|
||||
&& stainData.TryGetValue(data.CurrentStains[which].Id, out var stain))
|
||||
{
|
||||
Copy(stain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -19,6 +19,10 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
private ItemId _currentItem;
|
||||
private float _innerWidth;
|
||||
|
||||
public PrimaryId CustomSetId { get; private set; }
|
||||
public SecondaryId CustomWeaponId { get; private set; }
|
||||
public Variant CustomVariant { get; private set; }
|
||||
|
||||
public WeaponCombo(ItemManager items, FullEquipType type, Logger log, FavoriteManager favorites)
|
||||
: base(() => GetWeapons(favorites, items, type), MouseWheelType.Control, log)
|
||||
{
|
||||
|
|
@ -46,8 +50,9 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
|
||||
public bool Draw(string previewName, ItemId previewIdx, float width, float innerWidth)
|
||||
{
|
||||
_innerWidth = innerWidth;
|
||||
_currentItem = previewIdx;
|
||||
_innerWidth = innerWidth;
|
||||
_currentItem = previewIdx;
|
||||
CustomVariant = 0;
|
||||
return Draw($"##{Label}", previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
||||
|
|
@ -74,6 +79,24 @@ public sealed class WeaponCombo : FilterComboCache<EquipItem>
|
|||
return ret;
|
||||
}
|
||||
|
||||
protected override void OnClosePopup()
|
||||
{
|
||||
// If holding control while the popup closes, try to parse the input as a full tuple of set id, weapon id and variant, and set a custom item for that.
|
||||
if (!ImGui.GetIO().KeyCtrl)
|
||||
return;
|
||||
|
||||
var split = Filter.Text.Split('-', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
if (split.Length != 3
|
||||
|| !ushort.TryParse(split[0], out var setId)
|
||||
|| !ushort.TryParse(split[1], out var weaponId)
|
||||
|| !byte.TryParse(split[2], out var variant))
|
||||
return;
|
||||
|
||||
CustomSetId = setId;
|
||||
CustomWeaponId = weaponId;
|
||||
CustomVariant = variant;
|
||||
}
|
||||
|
||||
protected override bool IsVisible(int globalIndex, LowerString filter)
|
||||
=> base.IsVisible(globalIndex, filter) || Items[globalIndex].ModelString.StartsWith(filter.Lower);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
|
|||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Gui.Materials;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ public class GlamourerChangelog
|
|||
Add1_3_5_0(Changelog);
|
||||
Add1_3_6_0(Changelog);
|
||||
Add1_3_7_0(Changelog);
|
||||
Add1_3_8_0(Changelog);
|
||||
Add1_4_0_0(Changelog);
|
||||
Add1_5_0_0(Changelog);
|
||||
Add1_5_1_0(Changelog);
|
||||
}
|
||||
|
||||
private (int, ChangeLogDisplayType) ConfigData()
|
||||
|
|
@ -61,6 +65,66 @@ 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)
|
||||
=> log.NextVersion("Version 1.3.7.0")
|
||||
.RegisterImportant(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ using Glamourer.Gui.Tabs.NpcTab;
|
|||
using Glamourer.Gui.Tabs.SettingsTab;
|
||||
using Glamourer.Gui.Tabs.UnlocksTab;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Custom;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using FFXIVClientStructs.Interop;
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Interop.Material;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -91,10 +91,10 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
var modelHandle = model == null ? null : model->ModelResourceHandle;
|
||||
var path = materialHandle == null
|
||||
? string.Empty
|
||||
: ByteString.FromSpanUnsafe(materialHandle->ResourceHandle.FileName.AsSpan(), true).ToString();
|
||||
: ByteString.FromSpanUnsafe(materialHandle->FileName.AsSpan(), true).ToString();
|
||||
var gamePath = modelHandle == null
|
||||
? string.Empty
|
||||
: modelHandle->GetMaterialFileNameBySlotAsString(index.MaterialIndex);
|
||||
: modelHandle->GetMaterialFileNameBySlot(index.MaterialIndex).ToString();
|
||||
return (path, gamePath);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Dalamud.Interface.Utility;
|
|||
using Dalamud.Interface.Utility.Raii;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop.Material;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -18,7 +18,6 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
|
|||
public const float GlossWidth = 100;
|
||||
public const float SpecularStrengthWidth = 125;
|
||||
|
||||
private EquipSlot _newSlot = EquipSlot.Head;
|
||||
private int _newMaterialIdx;
|
||||
private int _newRowIdx;
|
||||
private MaterialValueIndex _newKey = MaterialValueIndex.FromSlot(EquipSlot.Head);
|
||||
|
|
@ -178,14 +177,42 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
|
|||
|
||||
public sealed class MaterialSlotCombo;
|
||||
|
||||
private void DrawSlotCombo()
|
||||
{
|
||||
var width = ImUtf8.CalcTextSize(EquipSlot.OffHand.ToName()).X + ImGui.GetFrameHeightWithSpacing();
|
||||
ImGui.SetNextItemWidth(width);
|
||||
using var combo = ImUtf8.Combo("##slot"u8, _newKey.SlotName());
|
||||
if (combo)
|
||||
{
|
||||
var currentSlot = _newKey.ToEquipSlot();
|
||||
foreach (var tmpSlot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
if (ImUtf8.Selectable(tmpSlot.ToName(), tmpSlot == currentSlot) && currentSlot != tmpSlot)
|
||||
_newKey = MaterialValueIndex.FromSlot(tmpSlot) with
|
||||
{
|
||||
MaterialIndex = (byte)_newMaterialIdx,
|
||||
RowIndex = (byte)_newRowIdx,
|
||||
};
|
||||
}
|
||||
|
||||
var currentBonus = _newKey.ToBonusSlot();
|
||||
foreach (var bonusSlot in BonusExtensions.AllFlags)
|
||||
{
|
||||
if (ImUtf8.Selectable(bonusSlot.ToName(), bonusSlot == currentBonus) && bonusSlot != currentBonus)
|
||||
_newKey = MaterialValueIndex.FromSlot(bonusSlot) with
|
||||
{
|
||||
MaterialIndex = (byte)_newMaterialIdx,
|
||||
RowIndex = (byte)_newRowIdx,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ImUtf8.HoverTooltip("Choose a slot for an advanced dye row."u8);
|
||||
}
|
||||
|
||||
public void DrawNew(Design design)
|
||||
{
|
||||
if (EquipSlotCombo.Draw("##slot", "Choose a slot for an advanced dye row.", ref _newSlot))
|
||||
_newKey = MaterialValueIndex.FromSlot(_newSlot) with
|
||||
{
|
||||
MaterialIndex = (byte)_newMaterialIdx,
|
||||
RowIndex = (byte)_newRowIdx,
|
||||
};
|
||||
DrawSlotCombo();
|
||||
ImUtf8.SameLineInner();
|
||||
DrawMaterialIdxDrag();
|
||||
ImUtf8.SameLineInner();
|
||||
|
|
|
|||
|
|
@ -1,39 +1,40 @@
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
public sealed class PenumbraChangedItemTooltip : IDisposable
|
||||
{
|
||||
private readonly PenumbraService _penumbra;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly ItemManager _items;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly CustomizeService _customize;
|
||||
private readonly GPoseService _gpose;
|
||||
private readonly PenumbraService _penumbra;
|
||||
private readonly StateManager _stateManager;
|
||||
private readonly ItemManager _items;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly CustomizeService _customize;
|
||||
private readonly GPoseService _gpose;
|
||||
|
||||
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2];
|
||||
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2 + BonusExtensions.AllFlags.Count];
|
||||
|
||||
public IEnumerable<KeyValuePair<EquipSlot, EquipItem>> LastItems
|
||||
=> EquipSlotExtensions.EqdpSlots.Append(EquipSlot.MainHand).Append(EquipSlot.OffHand).Zip(_lastItems)
|
||||
.Select(p => new KeyValuePair<EquipSlot, EquipItem>(p.First, p.Second));
|
||||
public IEnumerable<KeyValuePair<object, EquipItem>> LastItems
|
||||
=> EquipSlotExtensions.EqdpSlots.Cast<object>().Append(EquipSlot.MainHand).Append(EquipSlot.OffHand)
|
||||
.Concat(BonusExtensions.AllFlags.Cast<object>()).Zip(_lastItems)
|
||||
.Select(p => new KeyValuePair<object, EquipItem>(p.First, p.Second));
|
||||
|
||||
public ChangedItemType LastType { get; private set; } = ChangedItemType.None;
|
||||
public uint LastId { get; private set; } = 0;
|
||||
public uint LastId { get; private set; }
|
||||
public DateTime LastTooltip { get; private set; } = DateTime.MinValue;
|
||||
public DateTime LastClick { get; private set; } = DateTime.MinValue;
|
||||
|
||||
public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ObjectManager objects,
|
||||
public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ActorObjectManager objects,
|
||||
CustomizeService customize, GPoseService gpose)
|
||||
{
|
||||
_penumbra = penumbra;
|
||||
|
|
@ -72,6 +73,21 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
|||
if (!Player())
|
||||
return;
|
||||
|
||||
var bonusSlot = item.Type.ToBonus();
|
||||
if (bonusSlot is not BonusItemFlag.Unknown)
|
||||
{
|
||||
// + 2 due to weapons.
|
||||
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
|
||||
using (_ = !openTooltip ? null : ImRaii.Tooltip())
|
||||
{
|
||||
ImGui.TextUnformatted($"{prefix}Right-Click to apply to current actor.");
|
||||
if (glasses.Valid)
|
||||
ImGui.TextUnformatted($"{prefix}Control + Right-Click to re-apply {glasses.Name} to current actor.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var slot = item.Type.ToSlot();
|
||||
var last = _lastItems[slot.ToIndex()];
|
||||
switch (slot)
|
||||
|
|
@ -109,6 +125,27 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
|||
|
||||
public void ApplyItem(ActorState state, EquipItem item)
|
||||
{
|
||||
var bonusSlot = item.Type.ToBonus();
|
||||
if (bonusSlot is not BonusItemFlag.Unknown)
|
||||
{
|
||||
// + 2 due to weapons.
|
||||
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
|
||||
if (ImGui.GetIO().KeyCtrl && glasses.Valid)
|
||||
{
|
||||
Glamourer.Log.Debug($"Re-Applying {glasses.Name} to {bonusSlot.ToName()}.");
|
||||
SetLastItem(bonusSlot, default, state);
|
||||
_stateManager.ChangeBonusItem(state, bonusSlot, glasses, ApplySettings.Manual);
|
||||
}
|
||||
else
|
||||
{
|
||||
Glamourer.Log.Debug($"Applying {item.Name} to {bonusSlot.ToName()}.");
|
||||
SetLastItem(bonusSlot, item, state);
|
||||
_stateManager.ChangeBonusItem(state, bonusSlot, item, ApplySettings.Manual);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var slot = item.Type.ToSlot();
|
||||
var last = _lastItems[slot.ToIndex()];
|
||||
switch (slot)
|
||||
|
|
@ -265,7 +302,22 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
|||
{
|
||||
var oldItem = state.ModelData.Item(slot);
|
||||
if (oldItem.Id != item.Id)
|
||||
_lastItems[slot.ToIndex()] = oldItem;
|
||||
last = oldItem;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetLastItem(BonusItemFlag slot, EquipItem item, ActorState state)
|
||||
{
|
||||
ref var last = ref _lastItems[slot.ToSlot() + 2];
|
||||
if (!item.Valid)
|
||||
{
|
||||
last = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldItem = state.ModelData.BonusItem(slot);
|
||||
if (oldItem.Id != item.Id)
|
||||
last = oldItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ using Glamourer.Gui.Customization;
|
|||
using Glamourer.Gui.Equipment;
|
||||
using Glamourer.Gui.Materials;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
|
|
@ -22,7 +21,6 @@ using Penumbra.GameData.Actors;
|
|||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Interop;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.ActorTab;
|
||||
|
||||
|
|
@ -35,7 +33,7 @@ public class ActorPanel
|
|||
private readonly AutoDesignApplier _autoDesignApplier;
|
||||
private readonly Configuration _config;
|
||||
private readonly DesignConverter _converter;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly DesignManager _designManager;
|
||||
private readonly ImportService _importService;
|
||||
private readonly ICondition _conditions;
|
||||
|
|
@ -53,7 +51,7 @@ public class ActorPanel
|
|||
AutoDesignApplier autoDesignApplier,
|
||||
Configuration config,
|
||||
DesignConverter converter,
|
||||
ObjectManager objects,
|
||||
ActorObjectManager objects,
|
||||
DesignManager designManager,
|
||||
ImportService importService,
|
||||
ICondition conditions,
|
||||
|
|
@ -87,7 +85,7 @@ public class ActorPanel
|
|||
_rightButtons =
|
||||
[
|
||||
new LockedButton(this),
|
||||
new HeaderDrawer.IncognitoButton(_config.Ephemeral),
|
||||
new HeaderDrawer.IncognitoButton(_config),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +104,7 @@ public class ActorPanel
|
|||
{
|
||||
using var group = ImRaii.Group();
|
||||
(_identifier, _data) = _selector.Selection;
|
||||
_lockedRedraw = _identifier.Type is IdentifierType.Special
|
||||
_lockedRedraw = _identifier.Type is IdentifierType.Special || _objects.IsInLobby
|
||||
|| _conditions[ConditionFlag.OccupiedInCutSceneEvent];
|
||||
(_actorName, _actor) = GetHeaderName();
|
||||
DrawHeader();
|
||||
|
|
@ -240,6 +238,7 @@ public class ActorPanel
|
|||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawEquipmentMetaToggles();
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
_equipmentDrawer.DrawDragDropTooltip();
|
||||
}
|
||||
|
||||
private void DrawParameterHeader()
|
||||
|
|
@ -306,6 +305,12 @@ public class ActorPanel
|
|||
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.WeaponState, _stateManager, _state!));
|
||||
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromState(CrestFlag.OffHand, _stateManager, _state!));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using (_ = ImRaii.Group())
|
||||
{
|
||||
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromState(MetaIndex.EarState, _stateManager, _state!));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMonsterPanel()
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
using System.Security.AccessControl;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Structs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.ActorTab;
|
||||
|
||||
public class ActorSelector(ObjectManager objects, ActorManager actors, EphemeralConfig config)
|
||||
public class ActorSelector(ActorObjectManager objects, ActorManager actors, EphemeralConfig config)
|
||||
{
|
||||
private ActorIdentifier _identifier = ActorIdentifier.Invalid;
|
||||
|
||||
|
|
@ -89,11 +87,10 @@ public class ActorSelector(ObjectManager objects, ActorManager actors, Ephemeral
|
|||
if (!child)
|
||||
return;
|
||||
|
||||
objects.Update();
|
||||
_world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(objects.Identifiers.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter,
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(objects.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter,
|
||||
DrawSelectable);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.ActorTab;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Custom;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using OtterGui.Custom;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Gui;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Glamourer.Automation;
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Designs.Special;
|
||||
using Glamourer.Events;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
|
|
@ -278,7 +278,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
|||
private void LookupTooltip(IEnumerable<Design> designs)
|
||||
{
|
||||
using var _ = ImRaii.Tooltip();
|
||||
var tt = string.Join('\n', designs.Select(d => _designFileSystem.FindLeaf(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t));
|
||||
var tt = string.Join('\n', designs.Select(d => _designFileSystem.TryGetValue(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t));
|
||||
ImGui.TextUnformatted(tt.Length == 0
|
||||
? "Matches no currently existing designs."
|
||||
: "Matches the following designs:");
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ using Glamourer.Designs.Special;
|
|||
using Glamourer.Interop;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Log;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -31,7 +32,7 @@ public class SetPanel(
|
|||
RandomRestrictionDrawer _randomDrawer)
|
||||
{
|
||||
private readonly JobGroupCombo _jobGroupCombo = new(_manager, _jobs, Glamourer.Log);
|
||||
private readonly HeaderDrawer.Button[] _rightButtons = [new HeaderDrawer.IncognitoButton(_config.Ephemeral)];
|
||||
private readonly HeaderDrawer.Button[] _rightButtons = [new HeaderDrawer.IncognitoButton(_config)];
|
||||
private string? _tempName;
|
||||
private int _dragIndex = -1;
|
||||
|
||||
|
|
@ -431,10 +432,10 @@ public class SetPanel(
|
|||
if (source)
|
||||
{
|
||||
ImUtf8.Text($"Moving design #{index + 1:D2}...");
|
||||
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
|
||||
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
|
||||
{
|
||||
_dragIndex = index;
|
||||
_selector._dragDesignIndex = index;
|
||||
_selector.DragDesignIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Automation;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.String;
|
||||
using ImGuiClip = OtterGui.ImGuiClip;
|
||||
|
||||
|
|
@ -18,8 +18,7 @@ public class SetSelector : IDisposable
|
|||
private readonly Configuration _config;
|
||||
private readonly AutoDesignManager _manager;
|
||||
private readonly AutomationChanged _event;
|
||||
private readonly ActorManager _actors;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly ActorObjectManager _objects;
|
||||
private readonly List<(AutoDesignSet, int)> _list = [];
|
||||
|
||||
public AutoDesignSet? Selection { get; private set; }
|
||||
|
|
@ -38,14 +37,13 @@ public class SetSelector : IDisposable
|
|||
private int _dragIndex = -1;
|
||||
private Action? _endAction;
|
||||
|
||||
internal int _dragDesignIndex = -1;
|
||||
internal int DragDesignIndex = -1;
|
||||
|
||||
public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorManager actors, ObjectManager objects)
|
||||
public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorObjectManager objects)
|
||||
{
|
||||
_manager = manager;
|
||||
_event = @event;
|
||||
_config = config;
|
||||
_actors = actors;
|
||||
_objects = objects;
|
||||
_event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector);
|
||||
}
|
||||
|
|
@ -94,7 +92,7 @@ public class SetSelector : IDisposable
|
|||
}
|
||||
|
||||
private LowerString _filter = LowerString.Empty;
|
||||
private uint _enabledFilter = 0;
|
||||
private uint _enabledFilter;
|
||||
private float _width;
|
||||
private Vector2 _defaultItemSpacing;
|
||||
private Vector2 _selectableSize;
|
||||
|
|
@ -146,7 +144,7 @@ public class SetSelector : IDisposable
|
|||
ImGui.SameLine();
|
||||
var f = _enabledFilter;
|
||||
|
||||
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3))
|
||||
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3u))
|
||||
{
|
||||
_enabledFilter = _enabledFilter switch
|
||||
{
|
||||
|
|
@ -177,7 +175,6 @@ public class SetSelector : IDisposable
|
|||
UpdateList();
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
|
||||
_selectableSize = new Vector2(0, 2 * ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
|
||||
_objects.Update();
|
||||
ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * ImGui.GetStyle().ItemSpacing.Y);
|
||||
_endAction?.Invoke();
|
||||
_endAction = null;
|
||||
|
|
@ -186,7 +183,7 @@ public class SetSelector : IDisposable
|
|||
private void DrawSetSelectable((AutoDesignSet Set, int Index) pair)
|
||||
{
|
||||
using var id = ImRaii.PushId(pair.Index);
|
||||
using (var color = ImRaii.PushColor(ImGuiCol.Text, pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value()))
|
||||
using (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))
|
||||
{
|
||||
|
|
@ -285,9 +282,9 @@ public class SetSelector : IDisposable
|
|||
|
||||
private void NewSetButton(Vector2 size)
|
||||
{
|
||||
var id = _actors.GetCurrentPlayer();
|
||||
var id = _objects.Actors.GetCurrentPlayer();
|
||||
if (!id.IsValid)
|
||||
id = _actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue);
|
||||
id = _objects.Actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue);
|
||||
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))
|
||||
_manager.AddDesignSet("New Automation Set", id);
|
||||
|
|
@ -332,15 +329,15 @@ public class SetSelector : IDisposable
|
|||
}
|
||||
else if (ImGuiUtil.IsDropping("DesignDragDrop"))
|
||||
{
|
||||
if (_dragDesignIndex >= 0)
|
||||
if (DragDesignIndex >= 0)
|
||||
{
|
||||
var idx = _dragDesignIndex;
|
||||
var idx = DragDesignIndex;
|
||||
var setTo = set;
|
||||
var setFrom = Selection!;
|
||||
_endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo);
|
||||
}
|
||||
|
||||
_dragDesignIndex = -1;
|
||||
DragDesignIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -350,7 +347,7 @@ public class SetSelector : IDisposable
|
|||
if (source)
|
||||
{
|
||||
ImGui.TextUnformatted($"Moving design set {GetSetName(set, index)} from position {index + 1}...");
|
||||
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
|
||||
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
|
||||
_dragIndex = index;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer
|
||||
public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> $"Active Actors ({_stateManager.Count})###Active Actors";
|
||||
|
|
@ -22,8 +21,7 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
_objectManager.Update();
|
||||
foreach (var (identifier, actors) in _objectManager.Identifiers)
|
||||
foreach (var (identifier, actors) in _objectManager)
|
||||
{
|
||||
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()),
|
||||
string.Empty, !_stateManager.ContainsKey(identifier), true))
|
||||
|
|
@ -66,13 +64,15 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
|
|||
static string ItemString(in DesignData data, EquipSlot slot)
|
||||
{
|
||||
var item = data.Item(slot);
|
||||
return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
|
||||
return
|
||||
$"{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)
|
||||
{
|
||||
var item = data.BonusItem(slot);
|
||||
return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
|
||||
return
|
||||
$"{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]);
|
||||
|
|
@ -87,6 +87,9 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
|
|||
PrintRow("Visor Toggled", state.BaseData.IsVisorToggled(), state.ModelData.IsVisorToggled(),
|
||||
state.Sources[MetaIndex.VisorState]);
|
||||
ImGui.TableNextRow();
|
||||
PrintRow("Viera Ears Visible", state.BaseData.AreEarsVisible(), state.ModelData.AreEarsVisible(),
|
||||
state.Sources[MetaIndex.EarState]);
|
||||
ImGui.TableNextRow();
|
||||
PrintRow("Weapon Visible", state.BaseData.IsWeaponVisible(), state.ModelData.IsWeaponVisible(),
|
||||
state.Sources[MetaIndex.WeaponState]);
|
||||
ImGui.TableNextRow();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDataDrawer
|
||||
public unsafe class AdvancedCustomizationDrawer(ActorObjectManager objects) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Advanced Customizations";
|
||||
|
|
@ -31,8 +31,8 @@ public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDa
|
|||
return;
|
||||
}
|
||||
|
||||
DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0);
|
||||
DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1);
|
||||
DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0);
|
||||
DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1);
|
||||
DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2);
|
||||
DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Glamourer.Automation;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Services;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Widgets;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||
using ImGuiNET;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
|
@ -36,6 +35,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
|||
provider.GetRequiredService<ModelEvaluationPanel>(),
|
||||
provider.GetRequiredService<ObjectManagerPanel>(),
|
||||
provider.GetRequiredService<PenumbraPanel>(),
|
||||
provider.GetRequiredService<DynamisPanel>(),
|
||||
provider.GetRequiredService<IpcTesterPanel>(),
|
||||
provider.GetRequiredService<DatFilePanel>(),
|
||||
provider.GetRequiredService<GlamourPlatePanel>(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Utility;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Filesystem;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
|
|
@ -18,6 +21,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
DrawButtons();
|
||||
foreach (var (design, idx) in _designManager.Designs.WithIndex())
|
||||
{
|
||||
using var t = ImRaii.TreeNode($"{design.Name}##{idx}");
|
||||
|
|
@ -25,7 +29,8 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
continue;
|
||||
|
||||
DrawDesign(design, _designFileSystem);
|
||||
var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, design.Application.Meta,
|
||||
var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize,
|
||||
design.Application.Meta,
|
||||
design.WriteProtected());
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
ImGuiUtil.TextWrapped(base64);
|
||||
|
|
@ -34,6 +39,26 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawButtons()
|
||||
{
|
||||
if (ImUtf8.Button("Generate 500 Test Designs"u8))
|
||||
for (var i = 0; i < 500; ++i)
|
||||
{
|
||||
var design = _designManager.CreateEmpty($"Test Designs/Test Design {i}", true);
|
||||
_designManager.AddTag(design, "_DebugTest");
|
||||
}
|
||||
|
||||
ImUtf8.SameLineInner();
|
||||
if (ImUtf8.Button("Remove All Test Designs"u8))
|
||||
{
|
||||
var designs = _designManager.Designs.Where(d => d.Tags.Contains("_DebugTest")).ToArray();
|
||||
foreach (var design in designs)
|
||||
_designManager.Delete(design);
|
||||
if (_designFileSystem.Find("Test Designs", out var path) && path is DesignFileSystem.Folder { TotalChildren: 0 })
|
||||
_designFileSystem.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawDesign(DesignBase design, DesignFileSystem? fileSystem)
|
||||
{
|
||||
using var table = ImRaii.Table("##equip", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit);
|
||||
|
|
@ -52,7 +77,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
ImGui.TableNextRow();
|
||||
ImGuiUtil.DrawTableColumn("Design File System Path");
|
||||
if (fileSystem != null)
|
||||
ImGuiUtil.DrawTableColumn(fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : "No Path Known");
|
||||
ImGuiUtil.DrawTableColumn(fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : "No Path Known");
|
||||
ImGui.TableNextRow();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Creation");
|
||||
|
|
@ -89,6 +114,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _
|
|||
ImGuiUtil.DrawTableColumn(index.ToName());
|
||||
ImGuiUtil.DrawTableColumn(design.DesignData.GetMeta(index).ToString());
|
||||
ImGuiUtil.DrawTableColumn(design.DoApplyMeta(index) ? "Apply" : "Keep");
|
||||
ImGui.TableNextRow();
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Model ID");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Services;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
16
Glamourer/Gui/Tabs/DebugTab/DynamisPanel.cs
Normal file
16
Glamourer/Gui/Tabs/DebugTab/DynamisPanel.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class DynamisPanel(DynamisIpc dynamis) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Dynamis Interop";
|
||||
|
||||
public void Draw()
|
||||
=> dynamis.DrawDebugInfo();
|
||||
|
||||
public bool Disabled
|
||||
=> false;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
|
|
|||
|
|
@ -3,24 +3,26 @@ using Dalamud.Plugin.Services;
|
|||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Extensions;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public unsafe class GlamourPlatePanel : IGameDataDrawer
|
||||
{
|
||||
private readonly DesignManager _design;
|
||||
private readonly ItemManager _items;
|
||||
private readonly StateManager _state;
|
||||
private readonly ObjectManager _objects;
|
||||
private readonly DesignManager _design;
|
||||
private readonly ItemManager _items;
|
||||
private readonly StateManager _state;
|
||||
private readonly ActorObjectManager _objects;
|
||||
|
||||
public string Label
|
||||
=> "Glamour Plates";
|
||||
|
|
@ -28,7 +30,8 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
|
|||
public bool Disabled
|
||||
=> false;
|
||||
|
||||
public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state, ObjectManager objects)
|
||||
public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state,
|
||||
ActorObjectManager objects)
|
||||
{
|
||||
_items = items;
|
||||
_design = design;
|
||||
|
|
@ -42,24 +45,24 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
|
|||
var manager = MirageManager.Instance();
|
||||
using (ImRaii.Group())
|
||||
{
|
||||
ImGui.TextUnformatted("Address:");
|
||||
ImGui.TextUnformatted("Number of Glamour Plates:");
|
||||
ImGui.TextUnformatted("Glamour Plates Requested:");
|
||||
ImGui.TextUnformatted("Glamour Plates Loaded:");
|
||||
ImGui.TextUnformatted("Is Applying Glamour Plates:");
|
||||
ImUtf8.Text("Address:"u8);
|
||||
ImUtf8.Text("Number of Glamour Plates:"u8);
|
||||
ImUtf8.Text("Glamour Plates Requested:"u8);
|
||||
ImUtf8.Text("Glamour Plates Loaded:"u8);
|
||||
ImUtf8.Text("Is Applying Glamour Plates:"u8);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.Group())
|
||||
{
|
||||
ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)manager:X}");
|
||||
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
|
||||
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
|
||||
ImUtf8.CopyOnClickSelectable($"0x{(ulong)manager:X}");
|
||||
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
|
||||
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Request Update"))
|
||||
if (ImUtf8.SmallButton("Request Update"u8))
|
||||
RequestGlamour();
|
||||
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
|
||||
ImGui.TextUnformatted(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
|
||||
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
|
||||
ImUtf8.Text(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
|
||||
}
|
||||
|
||||
if (manager == null)
|
||||
|
|
@ -71,12 +74,12 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
|
|||
|
||||
for (var i = 0; i < manager->GlamourPlates.Length; ++i)
|
||||
{
|
||||
using var tree = ImRaii.TreeNode($"Plate #{i + 1:D2}");
|
||||
using var tree = ImUtf8.TreeNode($"Plate #{i + 1:D2}");
|
||||
if (!tree)
|
||||
continue;
|
||||
|
||||
ref var plate = ref manager->GlamourPlates[i];
|
||||
if (ImGuiUtil.DrawDisabledButton("Apply to Player", Vector2.Zero, string.Empty, !enabled))
|
||||
if (ImUtf8.ButtonEx("Apply to Player"u8, ""u8, Vector2.Zero, !enabled))
|
||||
{
|
||||
var design = CreateDesign(plate);
|
||||
_state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true });
|
||||
|
|
@ -85,14 +88,14 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
|
|||
using (ImRaii.Group())
|
||||
{
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
ImGui.TextUnformatted(slot.ToName());
|
||||
ImUtf8.Text(slot.ToName());
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.Group())
|
||||
{
|
||||
foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex())
|
||||
ImGui.TextUnformatted($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}");
|
||||
ImUtf8.Text($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ using Dalamud.Interface.Utility;
|
|||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.IpcSubscribers;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Text;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
private Dictionary<Guid, string> _designs = [];
|
||||
private int _gameObjectIndex;
|
||||
private string _gameObjectName = string.Empty;
|
||||
private string _designName = string.Empty;
|
||||
private uint _key;
|
||||
private ApplyFlag _flags = ApplyFlagEx.DesignDefault;
|
||||
private Guid? _design;
|
||||
|
|
@ -30,6 +32,7 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
IpcTesterHelpers.IndexInput(ref _gameObjectIndex);
|
||||
IpcTesterHelpers.KeyInput(ref _key);
|
||||
IpcTesterHelpers.NameInput(ref _gameObjectName);
|
||||
ImUtf8.InputText("##designName"u8, ref _designName, "Design Name..."u8);
|
||||
ImGuiUtil.GuidInput("##identifier", "Design Identifier...", string.Empty, ref _design, ref _designText,
|
||||
ImGui.GetContentRegionAvail().X);
|
||||
IpcTesterHelpers.DrawFlagInput(ref _flags);
|
||||
|
|
@ -54,6 +57,48 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
|
|||
IpcTesterHelpers.DrawIntro(ApplyDesignName.Label);
|
||||
if (ImGuiUtil.DrawDisabledButton("Apply##Name", Vector2.Zero, string.Empty, !_design.HasValue))
|
||||
_lastError = new ApplyDesignName(pluginInterface).Invoke(_design!.Value, _gameObjectName, _key, _flags);
|
||||
|
||||
IpcTesterHelpers.DrawIntro(GetExtendedDesignData.Label);
|
||||
if (_design.HasValue)
|
||||
{
|
||||
var (display, path, color, draw) = new GetExtendedDesignData(pluginInterface).Invoke(_design.Value);
|
||||
if (path.Length > 0)
|
||||
ImUtf8.Text($"{display} ({path}){(draw ? " in QDB"u8 : ""u8)}", color);
|
||||
else
|
||||
ImUtf8.Text("No Data"u8);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImUtf8.Text("No Data"u8);
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(GetDesignBase64.Label);
|
||||
if (ImUtf8.Button("To Clipboard##Base64"u8) && _design.HasValue)
|
||||
{
|
||||
var data = new GetDesignBase64(pluginInterface).Invoke(_design.Value);
|
||||
ImUtf8.SetClipboardText(data);
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(AddDesign.Label);
|
||||
if (ImUtf8.Button("Add from Clipboard"u8))
|
||||
try
|
||||
{
|
||||
var data = ImUtf8.GetClipboardText();
|
||||
_lastError = new AddDesign(pluginInterface).Invoke(data, _designName, out var newDesign);
|
||||
if (_lastError is GlamourerApiEc.Success)
|
||||
{
|
||||
_design = newDesign;
|
||||
_designText = newDesign.ToString();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_lastError = GlamourerApiEc.UnknownError;
|
||||
}
|
||||
|
||||
IpcTesterHelpers.DrawIntro(DeleteDesign.Label);
|
||||
if (ImUtf8.Button("Delete##Design"u8) && _design.HasValue)
|
||||
_lastError = new DeleteDesign(pluginInterface).Invoke(_design.Value);
|
||||
}
|
||||
|
||||
private void DrawDesignsPopup()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using static Penumbra.GameData.Files.ShpkFile;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Api.IpcSubscribers;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.IpcSubscribers;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using Glamourer.Api.Enums;
|
|||
using Glamourer.Api.Helpers;
|
||||
using Glamourer.Api.IpcSubscribers;
|
||||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using Glamourer.GameData;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Structs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
|
|
@ -11,13 +11,13 @@ using Penumbra.GameData.Enums;
|
|||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public unsafe class ModelEvaluationPanel(
|
||||
ObjectManager _objectManager,
|
||||
ActorObjectManager _objectManager,
|
||||
VisorService _visorService,
|
||||
VieraEarService _vieraEarService,
|
||||
UpdateSlotService _updateSlotService,
|
||||
ChangeCustomizeService _changeCustomizeService,
|
||||
CrestService _crestService,
|
||||
|
|
@ -34,7 +34,7 @@ public unsafe class ModelEvaluationPanel(
|
|||
public void Draw()
|
||||
{
|
||||
ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0);
|
||||
var actor = _objectManager[_gameObjectIndex];
|
||||
var actor = _objectManager.Objects[_gameObjectIndex];
|
||||
var model = actor.Model;
|
||||
using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
||||
ImGui.TableNextColumn();
|
||||
|
|
@ -46,9 +46,10 @@ public unsafe class ModelEvaluationPanel(
|
|||
|
||||
ImGuiUtil.DrawTableColumn("Address");
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(actor.ToString());
|
||||
|
||||
Glamourer.Dynamis.DrawPointer(actor);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(model.ToString());
|
||||
Glamourer.Dynamis.DrawPointer(model);
|
||||
ImGui.TableNextColumn();
|
||||
if (actor.IsCharacter)
|
||||
{
|
||||
|
|
@ -84,6 +85,7 @@ public unsafe class ModelEvaluationPanel(
|
|||
ImGuiUtil.CopyOnClickSelectable(offhand.ToString());
|
||||
|
||||
DrawVisor(actor, model);
|
||||
DrawVieraEars(actor, model);
|
||||
DrawHatState(actor, model);
|
||||
DrawWeaponState(actor, model);
|
||||
DrawWetness(actor, model);
|
||||
|
|
@ -135,6 +137,26 @@ public unsafe class ModelEvaluationPanel(
|
|||
_visorService.SetVisorState(model, !VisorService.GetVisorState(model));
|
||||
}
|
||||
|
||||
private void DrawVieraEars(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Viera Ears");
|
||||
ImGuiUtil.DrawTableColumn("Viera Ears");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.ShowVieraEars.ToString() : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(model.IsHuman ? model.VieraEarsVisible.ToString() : "No Human");
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman)
|
||||
return;
|
||||
|
||||
if (ImGui.SmallButton("Set True"))
|
||||
_vieraEarService.SetVieraEarState(model, true);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Set False"))
|
||||
_vieraEarService.SetVieraEarState(model, false);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Toggle"))
|
||||
_vieraEarService.SetVieraEarState(model, !model.VieraEarsVisible);
|
||||
}
|
||||
|
||||
private void DrawHatState(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("HatState");
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@ using Dalamud.Interface.Utility;
|
|||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
using ImGuiClip = OtterGui.ImGuiClip;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectManager _objectManager, DesignConverter _designConverter)
|
||||
public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, ActorObjectManager objectManager, DesignConverter designConverter)
|
||||
: IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
|
|
@ -28,9 +28,9 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
ImGui.Checkbox("Compare Customize (or Gear)", ref _customizeOrGear);
|
||||
ImUtf8.Checkbox("Compare Customize (or Gear)"u8, ref _customizeOrGear);
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
var resetScroll = ImGui.InputTextWithHint("##npcFilter", "Filter...", ref _npcFilter, 64);
|
||||
var resetScroll = ImUtf8.InputText("##npcFilter"u8, ref _npcFilter, "Filter..."u8);
|
||||
|
||||
using var table = ImRaii.Table("npcs", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit,
|
||||
new Vector2(-1, 400 * ImGuiHelpers.GlobalScale));
|
||||
|
|
@ -40,19 +40,19 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
|
|||
if (resetScroll)
|
||||
ImGui.SetScrollY(0);
|
||||
|
||||
ImGui.TableSetupColumn("Button", ImGuiTableColumnFlags.WidthFixed);
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
|
||||
ImGui.TableSetupColumn("Kind", ImGuiTableColumnFlags.WidthFixed);
|
||||
ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed);
|
||||
ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed);
|
||||
ImGui.TableSetupColumn("Visor", ImGuiTableColumnFlags.WidthFixed);
|
||||
ImGui.TableSetupColumn("Compare", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImUtf8.TableSetupColumn("Button"u8, ImGuiTableColumnFlags.WidthFixed);
|
||||
ImUtf8.TableSetupColumn("Name"u8, ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
|
||||
ImUtf8.TableSetupColumn("Kind"u8, ImGuiTableColumnFlags.WidthFixed);
|
||||
ImUtf8.TableSetupColumn("Id"u8, ImGuiTableColumnFlags.WidthFixed);
|
||||
ImUtf8.TableSetupColumn("Model"u8, ImGuiTableColumnFlags.WidthFixed);
|
||||
ImUtf8.TableSetupColumn("Visor"u8, ImGuiTableColumnFlags.WidthFixed);
|
||||
ImUtf8.TableSetupColumn("Compare"u8, ImGuiTableColumnFlags.WidthStretch);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing());
|
||||
ImGui.TableNextRow();
|
||||
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);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing());
|
||||
|
|
@ -61,43 +61,31 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
|
|||
void DrawData(NpcData data)
|
||||
{
|
||||
using var id = ImRaii.PushId(idx++);
|
||||
var disabled = !_state.GetOrCreate(_objectManager.Player, out var state);
|
||||
var disabled = !stateManager.GetOrCreate(objectManager.Player, out var state);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGuiUtil.DrawDisabledButton("Apply", Vector2.Zero, string.Empty, disabled))
|
||||
if (ImUtf8.ButtonEx("Apply"u8, ""u8, Vector2.Zero, disabled))
|
||||
{
|
||||
foreach (var (slot, item, stain) in _designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true))
|
||||
_state.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
|
||||
_state.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
|
||||
_state.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
|
||||
foreach (var (slot, item, stain) in designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true))
|
||||
stateManager.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
|
||||
stateManager.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
|
||||
stateManager.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(data.Name);
|
||||
ImUtf8.DrawFrameColumn(data.Name);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
|
||||
ImUtf8.DrawFrameColumn(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(data.Id.Id.ToString());
|
||||
ImUtf8.DrawFrameColumn(data.Id.Id.ToString());
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(data.ModelId.ToString());
|
||||
ImUtf8.DrawFrameColumn(data.ModelId.ToString());
|
||||
|
||||
using (_ = ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
|
||||
ImUtf8.DrawFrameColumn(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
|
||||
}
|
||||
|
||||
using var mono = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
|
||||
ImUtf8.DrawFrameColumn(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer
|
||||
public class ObjectManagerPanel(ActorObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Object Manager";
|
||||
|
|
@ -19,44 +19,45 @@ public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _acto
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
_objectManager.Update();
|
||||
using (var table = ImRaii.Table("##data", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
|
||||
_objectManager.Objects.DrawDebug();
|
||||
|
||||
using (var table = ImUtf8.Table("##data"u8, 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
|
||||
{
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Last Update");
|
||||
ImGuiUtil.DrawTableColumn(_objectManager.LastUpdate.ToString(CultureInfo.InvariantCulture));
|
||||
ImUtf8.DrawTableColumn("World"u8);
|
||||
ImUtf8.DrawTableColumn(_actors.Finished ? _actors.Data.ToWorldName(_objectManager.World) : "Service Missing");
|
||||
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();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("World");
|
||||
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());
|
||||
ImUtf8.DrawTableColumn("In Lobby"u8);
|
||||
ImUtf8.DrawTableColumn(_objectManager.IsInLobby.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (_objectManager.IsInGPose)
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn("GPose Player");
|
||||
ImGuiUtil.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})");
|
||||
ImUtf8.DrawTableColumn("GPose Player"u8);
|
||||
ImUtf8.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})");
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString());
|
||||
ImUtf8.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString());
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Number of Players");
|
||||
ImGuiUtil.DrawTableColumn(_objectManager.Count.ToString());
|
||||
ImUtf8.DrawTableColumn("Number of Players"u8);
|
||||
ImUtf8.DrawTableColumn(_objectManager.Count.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
|
||||
var filterChanged = ImGui.InputTextWithHint("##Filter", "Filter...", ref _objectFilter, 64);
|
||||
using var table2 = ImRaii.Table("##data2", 3,
|
||||
var filterChanged = ImUtf8.InputText("##Filter"u8, ref _objectFilter, "Filter..."u8);
|
||||
using var table2 = ImUtf8.Table("##data2"u8, 3,
|
||||
ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY,
|
||||
new Vector2(-1, 20 * ImGui.GetTextLineHeightWithSpacing()));
|
||||
if (!table2)
|
||||
|
|
@ -69,13 +70,13 @@ public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _acto
|
|||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
|
||||
ImGui.TableNextRow();
|
||||
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(_objectManager.Identifiers, skips,
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(_objectManager, skips,
|
||||
p => p.Value.Label.Contains(_objectFilter, StringComparison.OrdinalIgnoreCase), p
|
||||
=>
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(p.Key.ToString());
|
||||
ImGuiUtil.DrawTableColumn(p.Value.Label);
|
||||
ImGuiUtil.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString())));
|
||||
ImUtf8.DrawTableColumn(p.Key.ToString());
|
||||
ImUtf8.DrawTableColumn(p.Value.Label);
|
||||
ImUtf8.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString())));
|
||||
});
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.Api.Enums;
|
||||
|
|
@ -49,7 +49,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
ImGui.TableNextColumn();
|
||||
var address = _drawObject.Address;
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, (nint)(&address), nint.Zero, nint.Zero, "%llx",
|
||||
if (ImGui.InputScalar("##drawObjectPtr", ImGuiDataType.U64, ref address, nint.Zero, nint.Zero, "%llx",
|
||||
ImGuiInputTextFlags.CharsHexadecimal))
|
||||
_drawObject = address;
|
||||
ImGuiUtil.DrawTableColumn(_penumbra.Available
|
||||
|
|
@ -61,7 +61,7 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputInt("##CutsceneIndex", ref _gameObjectIndex, 0, 0);
|
||||
ImGuiUtil.DrawTableColumn(_penumbra.Available
|
||||
? _penumbra.CutsceneParent((ushort) _gameObjectIndex).ToString()
|
||||
? _penumbra.CutsceneParent((ushort)_gameObjectIndex).ToString()
|
||||
: "Penumbra Unavailable");
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Redraw Object");
|
||||
|
|
@ -76,7 +76,9 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Last Tooltip Date");
|
||||
ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue ? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})" : "Never");
|
||||
ImGuiUtil.DrawTableColumn(_penumbraTooltip.LastTooltip > DateTime.MinValue
|
||||
? $"{_penumbraTooltip.LastTooltip.ToLongTimeString()} ({_penumbraTooltip.LastType} {_penumbraTooltip.LastId})"
|
||||
: "Never");
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Last Click Date");
|
||||
|
|
@ -87,7 +89,13 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
|||
ImGui.Separator();
|
||||
foreach (var (slot, item) in _penumbraTooltip.LastItems)
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn($"{slot.ToName()} Revert-Item");
|
||||
switch (slot)
|
||||
{
|
||||
case EquipSlot e: ImGuiUtil.DrawTableColumn($"{e.ToName()} Revert-Item"); break;
|
||||
case BonusItemFlag f: ImGuiUtil.DrawTableColumn($"{f.ToName()} Revert-Item"); break;
|
||||
default: ImGuiUtil.DrawTableColumn("Unk Revert-Item"); break;
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn(item.Valid ? item.Name : "None");
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ using Glamourer.Interop.Structs;
|
|||
using Glamourer.State;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public class RetainedStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer
|
||||
public class RetainedStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Retained States (Inactive Actors)";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Glamourer.Designs;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
|
|
@ -12,13 +12,6 @@ public sealed class DesignColorCombo(DesignColors _designColors, bool _skipAutom
|
|||
: _designColors.Keys.OrderBy(k => k).Prepend(DesignColors.AutomaticName),
|
||||
MouseWheelType.Control, Glamourer.Log)
|
||||
{
|
||||
protected override void OnMouseWheel(string preview, ref int current, int steps)
|
||||
{
|
||||
if (CurrentSelectionIdx < 0)
|
||||
CurrentSelectionIdx = Items.IndexOf(preview);
|
||||
base.OnMouseWheel(preview, ref current, steps);
|
||||
}
|
||||
|
||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
||||
{
|
||||
var isAutomatic = !_skipAutomatic && globalIdx == 0;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using Dalamud.Interface.ImGuiNotification;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Services;
|
||||
using ImGuiNET;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
|
|
@ -189,10 +189,7 @@ public class DesignDetailTab
|
|||
else if (_selector.Selected!.Color.Length != 0)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
var size = new Vector2(ImGui.GetFrameHeight());
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
ImGuiUtil.DrawTextButton(FontAwesomeIcon.ExclamationCircle.ToIconString(), size, 0, _colors.MissingColor);
|
||||
ImUtf8.HoverTooltip("The color associated with this design does not exist."u8);
|
||||
ImUtf8.Icon(FontAwesomeIcon.ExclamationCircle, "The color associated with this design does not exist."u8, _colors.MissingColor);
|
||||
}
|
||||
|
||||
ImUtf8.DrawFrameColumn("Creation Date"u8);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue