mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-23 08:17:59 +01:00
Merge branch 'master' into luna
# Conflicts: # Penumbra/Api/Api/RedrawApi.cs # Penumbra/Api/Api/ResolveApi.cs # Penumbra/Api/Api/UiApi.cs # Penumbra/Interop/Services/TextureArraySlicer.cs # Penumbra/UI/CollectionTab/CollectionPanel.cs # Penumbra/UI/Tabs/CollectionsTab.cs # Penumbra/UI/Tabs/Debug/DebugTab.cs # Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs # Penumbra/UI/Tabs/ModsTab.cs # Penumbra/UI/Tabs/ResourceTab.cs # Penumbra/packages.lock.json
This commit is contained in:
commit
f035073966
26 changed files with 378 additions and 140 deletions
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
|
|
@ -10,13 +10,15 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
dotnet-version: '9.x.x'
|
dotnet-version: |
|
||||||
|
10.x.x
|
||||||
|
9.x.x
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
- name: Download Dalamud
|
- name: Download Dalamud
|
||||||
|
|
|
||||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
|
|
@ -9,13 +9,15 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
dotnet-version: '9.x.x'
|
dotnet-version: |
|
||||||
|
10.x.x
|
||||||
|
9.x.x
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
- name: Download Dalamud
|
- name: Download Dalamud
|
||||||
|
|
|
||||||
8
.github/workflows/test_release.yml
vendored
8
.github/workflows/test_release.yml
vendored
|
|
@ -9,13 +9,15 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
dotnet-version: '9.x.x'
|
dotnet-version: |
|
||||||
|
10.x.x
|
||||||
|
9.x.x
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
- name: Download Dalamud
|
- name: Download Dalamud
|
||||||
|
|
|
||||||
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1459e2b8f5e1687f659836709e23571235d4206c
|
Subproject commit ff1e6543845e3b8c53a5f8b240bc38faffb1b3bf
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 66a11d4c886d64da6ecb1a0ec4c8306b99167be1
|
Subproject commit 1750c41b53e1000c99a7fb9d8a0f082aef639a41
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"net9.0-windows7.0": {
|
"net10.0-windows7.0": {
|
||||||
"DotNet.ReproducibleBuilds": {
|
"DotNet.ReproducibleBuilds": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[1.2.25, )",
|
"requested": "[1.2.39, )",
|
||||||
"resolved": "1.2.25",
|
"resolved": "1.2.39",
|
||||||
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
|
"contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 462afac558becebbe06b4e5be9b1b3c3f5a9b6d6
|
Subproject commit 9bd016fbef5fb2de467dd42165267fdd93cd9592
|
||||||
|
|
@ -2,11 +2,14 @@ using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
|
using Penumbra.Collections;
|
||||||
|
using Penumbra.Collections.Manager;
|
||||||
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.Interop.Services;
|
using Penumbra.Interop.Services;
|
||||||
|
|
||||||
namespace Penumbra.Api.Api;
|
namespace Penumbra.Api.Api;
|
||||||
|
|
||||||
public class RedrawApi(RedrawService redrawService, IFramework framework) : IPenumbraApiRedraw, IApiService
|
public class RedrawApi(RedrawService redrawService, IFramework framework, CollectionManager collections, ObjectManager objects, ApiHelpers helpers) : IPenumbraApiRedraw, IApiService
|
||||||
{
|
{
|
||||||
public void RedrawObject(int gameObjectIndex, RedrawType setting)
|
public void RedrawObject(int gameObjectIndex, RedrawType setting)
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +33,19 @@ public class RedrawApi(RedrawService redrawService, IFramework framework) : IPen
|
||||||
|
|
||||||
public void RedrawCollectionMembers(Guid collectionId, RedrawType setting)
|
public void RedrawCollectionMembers(Guid collectionId, RedrawType setting)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (!collections.Storage.ById(collectionId, out var collection))
|
||||||
|
collection = ModCollection.Empty;
|
||||||
|
framework.RunOnFrameworkThread(() =>
|
||||||
|
{
|
||||||
|
foreach (var actor in objects.Objects)
|
||||||
|
{
|
||||||
|
helpers.AssociatedCollection(actor.ObjectIndex, out var modCollection);
|
||||||
|
if (collection == modCollection)
|
||||||
|
{
|
||||||
|
redrawService.RedrawObject(actor.ObjectIndex, setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public event GameObjectRedrawnDelegate? GameObjectRedrawn
|
public event GameObjectRedrawnDelegate? GameObjectRedrawn
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,28 @@
|
||||||
using FFXIVClientStructs.FFXIV.Common.Lua;
|
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI;
|
using Penumbra.UI;
|
||||||
using Penumbra.UI.MainWindow;
|
using Penumbra.UI.MainWindow;
|
||||||
|
using Penumbra.UI.Integration;
|
||||||
|
using Penumbra.UI.Tabs;
|
||||||
|
|
||||||
namespace Penumbra.Api.Api;
|
namespace Penumbra.Api.Api;
|
||||||
|
|
||||||
public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable
|
public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable
|
||||||
{
|
{
|
||||||
private readonly CommunicatorService _communicator;
|
private readonly CommunicatorService _communicator;
|
||||||
private readonly MainWindow _mainWindow;
|
private readonly MainWindow _mainWindow;
|
||||||
private readonly ModManager _modManager;
|
private readonly ModManager _modManager;
|
||||||
|
private readonly IntegrationSettingsRegistry _integrationSettings;
|
||||||
|
|
||||||
public UiApi(CommunicatorService communicator, MainWindow mainWindow, ModManager modManager)
|
public UiApi(CommunicatorService communicator, MainWindow mainWindow, ModManager modManager, IntegrationSettingsRegistry integrationSettings)
|
||||||
{
|
{
|
||||||
_communicator = communicator;
|
_communicator = communicator;
|
||||||
_mainWindow = mainWindow;
|
_mainWindow = mainWindow;
|
||||||
_modManager = modManager;
|
_modManager = modManager;
|
||||||
|
_integrationSettings = integrationSettings;
|
||||||
|
|
||||||
_communicator.ChangedItemHover.Subscribe(OnChangedItemHover, ChangedItemHover.Priority.Default);
|
_communicator.ChangedItemHover.Subscribe(OnChangedItemHover, ChangedItemHover.Priority.Default);
|
||||||
_communicator.ChangedItemClick.Subscribe(OnChangedItemClick, ChangedItemClick.Priority.Default);
|
_communicator.ChangedItemClick.Subscribe(OnChangedItemClick, ChangedItemClick.Priority.Default);
|
||||||
_communicator.PreSettingsTabBarDraw.Subscribe(OnPreSettingsTabBarDraw, Communication.PreSettingsTabBarDraw.Priority.Default);
|
_communicator.PreSettingsTabBarDraw.Subscribe(OnPreSettingsTabBarDraw, Communication.PreSettingsTabBarDraw.Priority.Default);
|
||||||
|
|
@ -103,4 +107,12 @@ public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable
|
||||||
var (type, id) = arguments.Data.ToApiObject();
|
var (type, id) = arguments.Data.ToApiObject();
|
||||||
ChangedItemTooltip.Invoke(type, id);
|
ChangedItemTooltip.Invoke(type, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RegisterSettingsSection(Action draw)
|
||||||
|
=> _integrationSettings.RegisterSection(draw);
|
||||||
|
|
||||||
|
public PenumbraApiEc UnregisterSettingsSection(Action draw)
|
||||||
|
=> _integrationSettings.UnregisterSection(draw)
|
||||||
|
? PenumbraApiEc.Success
|
||||||
|
: PenumbraApiEc.NothingChanged;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ public sealed class IpcProviders : IDisposable, IApiService, IRequiredService
|
||||||
IpcSubscribers.RedrawObject.Provider(pi, api.Redraw),
|
IpcSubscribers.RedrawObject.Provider(pi, api.Redraw),
|
||||||
IpcSubscribers.RedrawAll.Provider(pi, api.Redraw),
|
IpcSubscribers.RedrawAll.Provider(pi, api.Redraw),
|
||||||
IpcSubscribers.GameObjectRedrawn.Provider(pi, api.Redraw),
|
IpcSubscribers.GameObjectRedrawn.Provider(pi, api.Redraw),
|
||||||
|
IpcSubscribers.RedrawCollectionMembers.Provider(pi, api.Redraw),
|
||||||
|
|
||||||
IpcSubscribers.ResolveDefaultPath.Provider(pi, api.Resolve),
|
IpcSubscribers.ResolveDefaultPath.Provider(pi, api.Resolve),
|
||||||
IpcSubscribers.ResolveInterfacePath.Provider(pi, api.Resolve),
|
IpcSubscribers.ResolveInterfacePath.Provider(pi, api.Resolve),
|
||||||
|
|
@ -132,6 +133,8 @@ public sealed class IpcProviders : IDisposable, IApiService, IRequiredService
|
||||||
IpcSubscribers.PostSettingsDraw.Provider(pi, api.Ui),
|
IpcSubscribers.PostSettingsDraw.Provider(pi, api.Ui),
|
||||||
IpcSubscribers.OpenMainWindow.Provider(pi, api.Ui),
|
IpcSubscribers.OpenMainWindow.Provider(pi, api.Ui),
|
||||||
IpcSubscribers.CloseMainWindow.Provider(pi, api.Ui),
|
IpcSubscribers.CloseMainWindow.Provider(pi, api.Ui),
|
||||||
|
IpcSubscribers.RegisterSettingsSection.Provider(pi, api.Ui),
|
||||||
|
IpcSubscribers.UnregisterSettingsSection.Provider(pi, api.Ui),
|
||||||
];
|
];
|
||||||
if (_characterUtility.Ready)
|
if (_characterUtility.Ready)
|
||||||
_initializedProvider.Invoke();
|
_initializedProvider.Invoke();
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,10 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
||||||
Im.Popup.Open("Changed Item List"u8);
|
Im.Popup.Open("Changed Item List"u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
IpcTester.DrawIntro(RedrawCollectionMembers.Label, "Redraw Collection Members");
|
||||||
|
if (ImGui.Button("Redraw##ObjectCollection"))
|
||||||
|
new RedrawCollectionMembers(pi).Invoke(collectionList[0].Id, RedrawType.Redraw);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawChangedItemPopup()
|
private void DrawChangedItemPopup()
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ using Dalamud.Plugin.Services;
|
||||||
using Lumina.Data.Files;
|
using Lumina.Data.Files;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterTex;
|
using OtterTex;
|
||||||
using SharpDX.Direct3D11;
|
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
using SixLabors.ImageSharp.Formats.Tga;
|
using SixLabors.ImageSharp.Formats.Tga;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using DxgiDevice = SharpDX.DXGI.Device;
|
using TerraFX.Interop.DirectX;
|
||||||
|
using TerraFX.Interop.Windows;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
using Image = SixLabors.ImageSharp.Image;
|
||||||
|
|
||||||
namespace Penumbra.Import.Textures;
|
namespace Penumbra.Import.Textures;
|
||||||
|
|
@ -123,11 +123,11 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
case TextureType.Png:
|
case TextureType.Png:
|
||||||
data?.SaveAsync(_outputPath, new PngEncoder() { CompressionLevel = PngCompressionLevel.NoCompression }, cancel)
|
data?.SaveAsync(_outputPath, new PngEncoder { CompressionLevel = PngCompressionLevel.NoCompression }, cancel)
|
||||||
.Wait(cancel);
|
.Wait(cancel);
|
||||||
return;
|
return;
|
||||||
case TextureType.Targa:
|
case TextureType.Targa:
|
||||||
data?.SaveAsync(_outputPath, new TgaEncoder()
|
data?.SaveAsync(_outputPath, new TgaEncoder
|
||||||
{
|
{
|
||||||
Compression = TgaCompression.None,
|
Compression = TgaCompression.None,
|
||||||
BitsPerPixel = TgaBitsPerPixel.Pixel32,
|
BitsPerPixel = TgaBitsPerPixel.Pixel32,
|
||||||
|
|
@ -202,11 +202,16 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
rgba, width, height),
|
rgba, width, height),
|
||||||
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
|
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
|
||||||
CombinedTexture.TextureSaveType.Bitmap => ConvertToRgbaDds(image, _mipMaps, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.Bitmap => ConvertToRgbaDds(image, _mipMaps, cancel, rgba, width, height),
|
||||||
CombinedTexture.TextureSaveType.BC1 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC1UNorm, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.BC1 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC1UNorm, cancel, rgba,
|
||||||
CombinedTexture.TextureSaveType.BC3 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC3UNorm, cancel, rgba, width, height),
|
width, height),
|
||||||
CombinedTexture.TextureSaveType.BC4 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC4UNorm, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.BC3 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC3UNorm, cancel, rgba,
|
||||||
CombinedTexture.TextureSaveType.BC5 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC5UNorm, cancel, rgba, width, height),
|
width, height),
|
||||||
CombinedTexture.TextureSaveType.BC7 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC7UNorm, cancel, rgba, width, height),
|
CombinedTexture.TextureSaveType.BC4 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC4UNorm, cancel, rgba,
|
||||||
|
width, height),
|
||||||
|
CombinedTexture.TextureSaveType.BC5 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC5UNorm, cancel, rgba,
|
||||||
|
width, height),
|
||||||
|
CombinedTexture.TextureSaveType.BC7 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC7UNorm, cancel, rgba,
|
||||||
|
width, height),
|
||||||
_ => throw new Exception("Wrong save type."),
|
_ => throw new Exception("Wrong save type."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -388,7 +393,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Create a BC3 or BC7 block-compressed .dds from the input (optionally with mipmaps). Returns input (+ mipmaps) if it is already the correct format. </summary>
|
/// <summary> Create a BC3 or BC7 block-compressed .dds from the input (optionally with mipmaps). Returns input (+ mipmaps) if it is already the correct format. </summary>
|
||||||
public ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel)
|
public unsafe ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
if (input.Meta.Format == format)
|
if (input.Meta.Format == format)
|
||||||
return input;
|
return input;
|
||||||
|
|
@ -404,11 +409,58 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
// See https://github.com/microsoft/DirectXTex/wiki/Compress#parameters for the format condition.
|
// See https://github.com/microsoft/DirectXTex/wiki/Compress#parameters for the format condition.
|
||||||
if (format is DXGIFormat.BC6HUF16 or DXGIFormat.BC6HSF16 or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB)
|
if (format is DXGIFormat.BC6HUF16 or DXGIFormat.BC6HSF16 or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB)
|
||||||
{
|
{
|
||||||
var device = new Device(uiBuilder.DeviceHandle);
|
ref var device = ref *(ID3D11Device*)uiBuilder.DeviceHandle;
|
||||||
var dxgiDevice = device.QueryInterface<DxgiDevice>();
|
IDXGIDevice* dxgiDevice;
|
||||||
|
Marshal.ThrowExceptionForHR(device.QueryInterface(TerraFX.Interop.Windows.Windows.__uuidof<IDXGIDevice>(), (void**)&dxgiDevice));
|
||||||
|
|
||||||
using var deviceClone = new Device(dxgiDevice.Adapter, device.CreationFlags, device.FeatureLevel);
|
try
|
||||||
return input.Compress(deviceClone.NativePointer, format, CompressFlags.Parallel);
|
{
|
||||||
|
IDXGIAdapter* adapter = null;
|
||||||
|
Marshal.ThrowExceptionForHR(dxgiDevice->GetAdapter(&adapter));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dxgiDevice->Release();
|
||||||
|
dxgiDevice = null;
|
||||||
|
|
||||||
|
ID3D11Device* deviceClone = null;
|
||||||
|
ID3D11DeviceContext* contextClone = null;
|
||||||
|
var featureLevel = device.GetFeatureLevel();
|
||||||
|
Marshal.ThrowExceptionForHR(DirectX.D3D11CreateDevice(
|
||||||
|
adapter,
|
||||||
|
D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
HMODULE.NULL,
|
||||||
|
device.GetCreationFlags(),
|
||||||
|
&featureLevel,
|
||||||
|
1,
|
||||||
|
D3D11.D3D11_SDK_VERSION,
|
||||||
|
&deviceClone,
|
||||||
|
null,
|
||||||
|
&contextClone));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
adapter->Release();
|
||||||
|
adapter = null;
|
||||||
|
return input.Compress((nint)deviceClone, format, CompressFlags.Parallel);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (contextClone is not null)
|
||||||
|
contextClone->Release();
|
||||||
|
if (deviceClone is not null)
|
||||||
|
deviceClone->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (adapter is not null)
|
||||||
|
adapter->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (dxgiDevice is not null)
|
||||||
|
dxgiDevice->Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return input.Compress(format, CompressFlags.BC7Quick | CompressFlags.Parallel);
|
return input.Compress(format, CompressFlags.BC7Quick | CompressFlags.Parallel);
|
||||||
|
|
@ -454,7 +506,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
GC.KeepAlive(input);
|
GC.KeepAlive(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly struct ImageInputData
|
private readonly struct ImageInputData : IEquatable<ImageInputData>
|
||||||
{
|
{
|
||||||
private readonly string? _inputPath;
|
private readonly string? _inputPath;
|
||||||
|
|
||||||
|
|
@ -522,5 +574,8 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> _inputPath != null ? _inputPath.ToLowerInvariant().GetHashCode() : HashCode.Combine(_width, _height);
|
=> _inputPath != null ? _inputPath.ToLowerInvariant().GetHashCode() : HashCode.Combine(_width, _height);
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
=> obj is ImageInputData o && Equals(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using SharpDX.Direct3D;
|
using TerraFX.Interop.DirectX;
|
||||||
using SharpDX.Direct3D11;
|
|
||||||
|
|
||||||
namespace Penumbra.Interop.Services;
|
namespace Penumbra.Interop.Services;
|
||||||
|
|
||||||
|
|
@ -21,46 +20,78 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable
|
||||||
if (texture == null)
|
if (texture == null)
|
||||||
throw new ArgumentNullException(nameof(texture));
|
throw new ArgumentNullException(nameof(texture));
|
||||||
if (sliceIndex >= texture->ArraySize)
|
if (sliceIndex >= texture->ArraySize)
|
||||||
throw new ArgumentOutOfRangeException(nameof(sliceIndex), $"Slice index ({sliceIndex}) is greater than or equal to the texture array size ({texture->ArraySize})");
|
throw new ArgumentOutOfRangeException(nameof(sliceIndex),
|
||||||
|
$"Slice index ({sliceIndex}) is greater than or equal to the texture array size ({texture->ArraySize})");
|
||||||
|
|
||||||
if (_activeSlices.TryGetValue(((nint)texture, sliceIndex), out var state))
|
if (_activeSlices.TryGetValue(((nint)texture, sliceIndex), out var state))
|
||||||
{
|
{
|
||||||
state.Refresh();
|
state.Refresh();
|
||||||
return new ImTextureId((nint)state.ShaderResourceView);
|
return new ImTextureId((nint)state.ShaderResourceView);
|
||||||
}
|
}
|
||||||
var srv = (ShaderResourceView)(nint)texture->D3D11ShaderResourceView;
|
|
||||||
var description = srv.Description;
|
ref var srv = ref *(ID3D11ShaderResourceView*)(nint)texture->D3D11ShaderResourceView;
|
||||||
switch (description.Dimension)
|
srv.AddRef();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
case ShaderResourceViewDimension.Texture1D:
|
D3D11_SHADER_RESOURCE_VIEW_DESC description;
|
||||||
case ShaderResourceViewDimension.Texture2D:
|
srv.GetDesc(&description);
|
||||||
case ShaderResourceViewDimension.Texture2DMultisampled:
|
switch (description.ViewDimension)
|
||||||
case ShaderResourceViewDimension.Texture3D:
|
{
|
||||||
case ShaderResourceViewDimension.TextureCube:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE1D:
|
||||||
// This function treats these as single-slice arrays.
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D:
|
||||||
// As per the range check above, the only valid slice (i. e. 0) has been requested, therefore there is nothing to do.
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DMS:
|
||||||
break;
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE3D:
|
||||||
case ShaderResourceViewDimension.Texture1DArray:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURECUBE:
|
||||||
description.Texture1DArray.FirstArraySlice = sliceIndex;
|
// This function treats these as single-slice arrays.
|
||||||
description.Texture2DArray.ArraySize = 1;
|
// As per the range check above, the only valid slice (i. e. 0) has been requested, therefore there is nothing to do.
|
||||||
break;
|
break;
|
||||||
case ShaderResourceViewDimension.Texture2DArray:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
|
||||||
description.Texture2DArray.FirstArraySlice = sliceIndex;
|
description.Texture1DArray.FirstArraySlice = sliceIndex;
|
||||||
description.Texture2DArray.ArraySize = 1;
|
description.Texture1DArray.ArraySize = 1;
|
||||||
break;
|
break;
|
||||||
case ShaderResourceViewDimension.Texture2DMultisampledArray:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
|
||||||
description.Texture2DMSArray.FirstArraySlice = sliceIndex;
|
description.Texture2DArray.FirstArraySlice = sliceIndex;
|
||||||
description.Texture2DMSArray.ArraySize = 1;
|
description.Texture2DArray.ArraySize = 1;
|
||||||
break;
|
break;
|
||||||
case ShaderResourceViewDimension.TextureCubeArray:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
||||||
description.TextureCubeArray.First2DArrayFace = sliceIndex * 6;
|
description.Texture2DMSArray.FirstArraySlice = sliceIndex;
|
||||||
description.TextureCubeArray.CubeCount = 1;
|
description.Texture2DMSArray.ArraySize = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
|
||||||
throw new NotSupportedException($"{nameof(TextureArraySlicer)} does not support dimension {description.Dimension}");
|
description.TextureCubeArray.First2DArrayFace = sliceIndex * 6u;
|
||||||
|
description.TextureCubeArray.NumCubes = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"{nameof(TextureArraySlicer)} does not support dimension {description.ViewDimension}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11Device* device = null;
|
||||||
|
srv.GetDevice(&device);
|
||||||
|
ID3D11Resource* resource = null;
|
||||||
|
srv.GetResource(&resource);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ID3D11ShaderResourceView* slicedSrv = null;
|
||||||
|
Marshal.ThrowExceptionForHR(device->CreateShaderResourceView(resource, &description, &slicedSrv));
|
||||||
|
resource->Release();
|
||||||
|
device->Release();
|
||||||
|
|
||||||
|
state = new SliceState(slicedSrv);
|
||||||
|
_activeSlices.Add(((nint)texture, sliceIndex), state);
|
||||||
|
return new ImTextureId((nint)state.ShaderResourceView);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (resource is not null)
|
||||||
|
resource->Release();
|
||||||
|
if (device is not null)
|
||||||
|
device->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
srv.Release();
|
||||||
}
|
}
|
||||||
state = new SliceState(new ShaderResourceView(srv.Device, srv.Resource, description));
|
|
||||||
_activeSlices.Add(((nint)texture, sliceIndex), state);
|
|
||||||
return new ImTextureId((nint)state.ShaderResourceView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
|
|
@ -72,10 +103,9 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable
|
||||||
if (!slice.Tick())
|
if (!slice.Tick())
|
||||||
_expiredKeys.Add(key);
|
_expiredKeys.Add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var key in _expiredKeys)
|
foreach (var key in _expiredKeys)
|
||||||
{
|
|
||||||
_activeSlices.Remove(key);
|
_activeSlices.Remove(key);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -86,14 +116,12 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (var slice in _activeSlices.Values)
|
foreach (var slice in _activeSlices.Values)
|
||||||
{
|
|
||||||
slice.Dispose();
|
slice.Dispose();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SliceState(ShaderResourceView shaderResourceView) : IDisposable
|
private sealed class SliceState(ID3D11ShaderResourceView* shaderResourceView) : IDisposable
|
||||||
{
|
{
|
||||||
public readonly ShaderResourceView ShaderResourceView = shaderResourceView;
|
public readonly ID3D11ShaderResourceView* ShaderResourceView = shaderResourceView;
|
||||||
|
|
||||||
private uint _timeToLive = InitialTimeToLive;
|
private uint _timeToLive = InitialTimeToLive;
|
||||||
|
|
||||||
|
|
@ -107,13 +135,15 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable
|
||||||
if (unchecked(_timeToLive--) > 0)
|
if (unchecked(_timeToLive--) > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ShaderResourceView.Dispose();
|
if (ShaderResourceView is not null)
|
||||||
|
ShaderResourceView->Release();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
ShaderResourceView.Dispose();
|
if (ShaderResourceView is not null)
|
||||||
|
ShaderResourceView->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AssemblyTitle>Penumbra</AssemblyTitle>
|
<AssemblyTitle>Penumbra</AssemblyTitle>
|
||||||
<Company>absolute gangstas</Company>
|
<Company>absolute gangstas</Company>
|
||||||
|
|
@ -39,16 +39,8 @@
|
||||||
<HintPath>$(DalamudLibPath)Iced.dll</HintPath>
|
<HintPath>$(DalamudLibPath)Iced.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpDX">
|
<Reference Include="TerraFX.Interop.Windows">
|
||||||
<HintPath>$(DalamudLibPath)SharpDX.dll</HintPath>
|
<HintPath>$(DalamudLibPath)TerraFX.Interop.Windows.dll</HintPath>
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SharpDX.Direct3D11">
|
|
||||||
<HintPath>$(DalamudLibPath)SharpDX.Direct3D11.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SharpDX.DXGI">
|
|
||||||
<HintPath>$(DalamudLibPath)SharpDX.DXGI.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OtterTex.dll">
|
<Reference Include="OtterTex.dll">
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"Tags": [ "modding" ],
|
"Tags": [ "modding" ],
|
||||||
"DalamudApiLevel": 13,
|
"DalamudApiLevel": 14,
|
||||||
"LoadPriority": 69420,
|
"LoadPriority": 69420,
|
||||||
"LoadRequiredState": 2,
|
"LoadRequiredState": 2,
|
||||||
"LoadSync": true,
|
"LoadSync": true,
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ public static class StaticServiceManager
|
||||||
.AddDalamudService<ICommandManager>(pi)
|
.AddDalamudService<ICommandManager>(pi)
|
||||||
.AddDalamudService<IDataManager>(pi)
|
.AddDalamudService<IDataManager>(pi)
|
||||||
.AddDalamudService<IClientState>(pi)
|
.AddDalamudService<IClientState>(pi)
|
||||||
|
.AddDalamudService<IPlayerState>(pi)
|
||||||
.AddDalamudService<IChatGui>(pi)
|
.AddDalamudService<IChatGui>(pi)
|
||||||
.AddDalamudService<IFramework>(pi)
|
.AddDalamudService<IFramework>(pi)
|
||||||
.AddDalamudService<ICondition>(pi)
|
.AddDalamudService<ICondition>(pi)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Plugin.Services;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
|
|
|
||||||
115
Penumbra/UI/Integration/IntegrationSettingsRegistry.cs
Normal file
115
Penumbra/UI/Integration/IntegrationSettingsRegistry.cs
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Text;
|
||||||
|
using Penumbra.Api.Enums;
|
||||||
|
|
||||||
|
namespace Penumbra.UI.Integration;
|
||||||
|
|
||||||
|
public sealed class IntegrationSettingsRegistry : IService, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
|
|
||||||
|
private readonly List<(string InternalName, string Name, Action Draw)> _sections = [];
|
||||||
|
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
public IntegrationSettingsRegistry(IDalamudPluginInterface pluginInterface)
|
||||||
|
{
|
||||||
|
_pluginInterface = pluginInterface;
|
||||||
|
|
||||||
|
_pluginInterface.ActivePluginsChanged += OnActivePluginsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
_pluginInterface.ActivePluginsChanged -= OnActivePluginsChanged;
|
||||||
|
|
||||||
|
_sections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
foreach (var (internalName, name, draw) in _sections)
|
||||||
|
{
|
||||||
|
if (!ImUtf8.CollapsingHeader($"Integration with {name}###IntegrationSettingsHeader.{internalName}"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
using var id = ImUtf8.PushId($"IntegrationSettings.{internalName}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Penumbra.Log.Error($"Error while drawing {internalName} integration settings: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RegisterSection(Action draw)
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
return PenumbraApiEc.SystemDisposed;
|
||||||
|
|
||||||
|
var plugin = GetPlugin(draw);
|
||||||
|
if (plugin is null)
|
||||||
|
return PenumbraApiEc.InvalidArgument;
|
||||||
|
|
||||||
|
var section = (plugin.InternalName, plugin.Name, draw);
|
||||||
|
|
||||||
|
var index = FindSectionIndex(plugin.InternalName);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
if (_sections[index] == section)
|
||||||
|
return PenumbraApiEc.NothingChanged;
|
||||||
|
_sections[index] = section;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_sections.Add(section);
|
||||||
|
_sections.Sort((lhs, rhs) => string.Compare(lhs.Name, rhs.Name, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
return PenumbraApiEc.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UnregisterSection(Action draw)
|
||||||
|
{
|
||||||
|
var index = FindSectionIndex(draw);
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_sections.RemoveAt(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnActivePluginsChanged(IActivePluginsChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Kind is PluginListInvalidationKind.Loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var internalName in args.AffectedInternalNames)
|
||||||
|
{
|
||||||
|
var index = FindSectionIndex(internalName);
|
||||||
|
if (index >= 0 && GetPlugin(_sections[index].Draw) is null)
|
||||||
|
{
|
||||||
|
_sections.RemoveAt(index);
|
||||||
|
Penumbra.Log.Warning($"Removed stale integration setting section of {internalName} (reason: {args.Kind})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IExposedPlugin? GetPlugin(Delegate @delegate)
|
||||||
|
=> @delegate.Method.DeclaringType
|
||||||
|
switch
|
||||||
|
{
|
||||||
|
null => null,
|
||||||
|
var type => _pluginInterface.GetPlugin(type.Assembly),
|
||||||
|
};
|
||||||
|
|
||||||
|
private int FindSectionIndex(string internalName)
|
||||||
|
=> _sections.FindIndex(section => section.InternalName.Equals(internalName, StringComparison.Ordinal));
|
||||||
|
|
||||||
|
private int FindSectionIndex(Action draw)
|
||||||
|
=> _sections.FindIndex(section => section.Draw == draw);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using ImSharp;
|
||||||
using Penumbra.Interop.Services;
|
using Penumbra.Interop.Services;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
|
using Penumbra.Util;
|
||||||
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
||||||
|
|
||||||
namespace Penumbra.UI.Tabs.Debug;
|
namespace Penumbra.UI.Tabs.Debug;
|
||||||
|
|
@ -169,10 +170,10 @@ public unsafe class GlobalVariablesDrawer(
|
||||||
if (_schedulerFilterMap.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterMap.Span) >= 0)
|
if (_schedulerFilterMap.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterMap.Span) >= 0)
|
||||||
{
|
{
|
||||||
table.DrawColumn($"[{total:D4}]");
|
table.DrawColumn($"[{total:D4}]");
|
||||||
table.DrawColumn($"{resource->Name.Unk1}");
|
table.DrawColumn($"{resource->Name.GetField<ushort, SchedulerResource.ResourceName>(16)}"); // Unk1
|
||||||
table.DrawColumn(new CiByteString(resource->Name.Buffer).Span);
|
table.DrawColumn(new CiByteString(resource->Name.Buffer).Span);
|
||||||
table.DrawColumn($"{resource->Consumers}");
|
table.DrawColumn($"{resource->Consumers}");
|
||||||
table.DrawColumn($"{resource->Unk1}"); // key
|
table.DrawColumn($"{PointerExtensions.GetField<uint, SchedulerResource>(resource, 120)}"); // key, Unk1
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
Penumbra.Dynamis.DrawPointer(resource);
|
Penumbra.Dynamis.DrawPointer(resource);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
|
|
@ -215,10 +216,10 @@ public unsafe class GlobalVariablesDrawer(
|
||||||
if (_schedulerFilterList.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterList.Span) >= 0)
|
if (_schedulerFilterList.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterList.Span) >= 0)
|
||||||
{
|
{
|
||||||
table.DrawColumn($"[{total:D4}]");
|
table.DrawColumn($"[{total:D4}]");
|
||||||
table.DrawColumn($"{resource->Name.Unk1}");
|
table.DrawColumn($"{resource->Name.GetField<ushort, SchedulerResource.ResourceName>(16)}"); // Unk1
|
||||||
table.DrawColumn(new CiByteString(resource->Name.Buffer).Span);
|
table.DrawColumn(new CiByteString(resource->Name.Buffer).Span);
|
||||||
table.DrawColumn($"{resource->Consumers}");
|
table.DrawColumn($"{resource->Consumers}");
|
||||||
table.DrawColumn($"{resource->Unk1}"); // key
|
table.DrawColumn($"{PointerExtensions.GetField<uint, SchedulerResource>(resource, 120)}"); // key, Unk1
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
Penumbra.Dynamis.DrawPointer(resource);
|
Penumbra.Dynamis.DrawPointer(resource);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ using Penumbra.Interop.Services;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
using Penumbra.UI.Integration;
|
||||||
using Penumbra.UI.ModsTab;
|
using Penumbra.UI.ModsTab;
|
||||||
using Penumbra.UI.ModsTab.Selector;
|
using Penumbra.UI.ModsTab.Selector;
|
||||||
|
|
||||||
|
|
@ -51,6 +52,7 @@ public sealed class SettingsTab : ITab<TabType>
|
||||||
private readonly CleanupService _cleanupService;
|
private readonly CleanupService _cleanupService;
|
||||||
private readonly AttributeHook _attributeHook;
|
private readonly AttributeHook _attributeHook;
|
||||||
private readonly PcpService _pcpService;
|
private readonly PcpService _pcpService;
|
||||||
|
private readonly IntegrationSettingsRegistry _integrationSettings;
|
||||||
|
|
||||||
private string _lastCloudSyncTestedPath = string.Empty;
|
private string _lastCloudSyncTestedPath = string.Empty;
|
||||||
private bool _lastCloudSyncTestResult;
|
private bool _lastCloudSyncTestResult;
|
||||||
|
|
@ -62,7 +64,7 @@ public sealed class SettingsTab : ITab<TabType>
|
||||||
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
|
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
|
||||||
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
|
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
|
||||||
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
|
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
|
||||||
AttributeHook attributeHook, PcpService pcpService)
|
AttributeHook attributeHook, PcpService pcpService, IntegrationSettingsRegistry integrationSettings)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
@ -90,6 +92,7 @@ public sealed class SettingsTab : ITab<TabType>
|
||||||
_cleanupService = cleanupService;
|
_cleanupService = cleanupService;
|
||||||
_attributeHook = attributeHook;
|
_attributeHook = attributeHook;
|
||||||
_pcpService = pcpService;
|
_pcpService = pcpService;
|
||||||
|
_integrationSettings = integrationSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostTabButton()
|
public void PostTabButton()
|
||||||
|
|
@ -120,6 +123,7 @@ public sealed class SettingsTab : ITab<TabType>
|
||||||
DrawColorSettings();
|
DrawColorSettings();
|
||||||
DrawPredefinedTagsSection();
|
DrawPredefinedTagsSection();
|
||||||
DrawAdvancedSettings();
|
DrawAdvancedSettings();
|
||||||
|
_integrationSettings.Draw();
|
||||||
DrawSupportButtons();
|
DrawSupportButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
Penumbra/Util/PointerExtensions.cs
Normal file
20
Penumbra/Util/PointerExtensions.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace Penumbra.Util;
|
||||||
|
|
||||||
|
public static class PointerExtensions
|
||||||
|
{
|
||||||
|
public static unsafe ref TField GetField<TField, TPointer>(this ref TPointer reference, int offset)
|
||||||
|
where TPointer : unmanaged
|
||||||
|
where TField : unmanaged
|
||||||
|
{
|
||||||
|
var pointer = (byte*)Unsafe.AsPointer(ref reference) + offset;
|
||||||
|
return ref *(TField*)pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe ref TField GetField<TField, TPointer>(TPointer* itemPointer, int offset)
|
||||||
|
where TPointer : unmanaged
|
||||||
|
where TField : unmanaged
|
||||||
|
{
|
||||||
|
var pointer = (byte*)itemPointer + offset;
|
||||||
|
return ref *(TField*)pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
"net10.0-windows7.0": {
|
"net10.0-windows7.0": {
|
||||||
"DotNet.ReproducibleBuilds": {
|
"DotNet.ReproducibleBuilds": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[1.2.25, )",
|
"requested": "[1.2.39, )",
|
||||||
"resolved": "1.2.25",
|
"resolved": "1.2.39",
|
||||||
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
|
"contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
|
||||||
},
|
},
|
||||||
"EmbedIO": {
|
"EmbedIO": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
"resolved": "0.40.0",
|
"resolved": "0.40.0",
|
||||||
"contentHash": "yP/aFX1jqGikVF7u2f05VEaWN4aCaKNLxSas82UgA2GGVECxq/BcqZx3STHCJ78qilo1azEOk1XpBglIuGMb7w==",
|
"contentHash": "yP/aFX1jqGikVF7u2f05VEaWN4aCaKNLxSas82UgA2GGVECxq/BcqZx3STHCJ78qilo1azEOk1XpBglIuGMb7w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Buffers": "4.6.0",
|
|
||||||
"ZstdSharp.Port": "0.8.5"
|
"ZstdSharp.Port": "0.8.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -66,10 +65,7 @@
|
||||||
"FlatSharp.Runtime": {
|
"FlatSharp.Runtime": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "7.9.0",
|
"resolved": "7.9.0",
|
||||||
"contentHash": "Bm8+WqzEsWNpxqrD5x4x+zQ8dyINlToCreM5FI2oNSfUVc9U9ZB+qztX/jd8rlJb3r0vBSlPwVLpw0xBtPa3Vw==",
|
"contentHash": "Bm8+WqzEsWNpxqrD5x4x+zQ8dyINlToCreM5FI2oNSfUVc9U9ZB+qztX/jd8rlJb3r0vBSlPwVLpw0xBtPa3Vw=="
|
||||||
"dependencies": {
|
|
||||||
"System.Memory": "4.5.5"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"JetBrains.Annotations": {
|
"JetBrains.Annotations": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
|
|
@ -134,38 +130,20 @@
|
||||||
"SharpGLTF.Core": "1.0.5"
|
"SharpGLTF.Core": "1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.Buffers": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "4.6.0",
|
|
||||||
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
|
|
||||||
},
|
|
||||||
"System.IO.Hashing": {
|
"System.IO.Hashing": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "9.0.8",
|
"resolved": "9.0.8",
|
||||||
"contentHash": "5TJUS9EIYrp0VEcm06EPYxXmLmsVUakewFnM/CAxQfvlasI9fGkTKM9afSf2dodZcMCzFna/o7Fn+gYRt3uTiA=="
|
"contentHash": "5TJUS9EIYrp0VEcm06EPYxXmLmsVUakewFnM/CAxQfvlasI9fGkTKM9afSf2dodZcMCzFna/o7Fn+gYRt3uTiA=="
|
||||||
},
|
},
|
||||||
"System.Memory": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "4.5.5",
|
|
||||||
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
|
|
||||||
},
|
|
||||||
"System.Security.Cryptography.Pkcs": {
|
"System.Security.Cryptography.Pkcs": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "8.0.1",
|
"resolved": "8.0.1",
|
||||||
"contentHash": "CoCRHFym33aUSf/NtWSVSZa99dkd0Hm7OCZUxORBjRB16LNhIEOf8THPqzIYlvKM0nNDAPTRBa1FxEECrgaxxA=="
|
"contentHash": "CoCRHFym33aUSf/NtWSVSZa99dkd0Hm7OCZUxORBjRB16LNhIEOf8THPqzIYlvKM0nNDAPTRBa1FxEECrgaxxA=="
|
||||||
},
|
},
|
||||||
"System.ValueTuple": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "4.5.0",
|
|
||||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
|
||||||
},
|
|
||||||
"Unosquare.Swan.Lite": {
|
"Unosquare.Swan.Lite": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "3.1.0",
|
"resolved": "3.1.0",
|
||||||
"contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ==",
|
"contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ=="
|
||||||
"dependencies": {
|
|
||||||
"System.ValueTuple": "4.5.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"ZstdSharp.Port": {
|
"ZstdSharp.Port": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
|
|
@ -200,7 +178,7 @@
|
||||||
"FlatSharp.Runtime": "[7.9.0, )",
|
"FlatSharp.Runtime": "[7.9.0, )",
|
||||||
"Luna": "[1.0.0, )",
|
"Luna": "[1.0.0, )",
|
||||||
"Penumbra.Api": "[5.13.0, )",
|
"Penumbra.Api": "[5.13.0, )",
|
||||||
"Penumbra.String": "[1.0.6, )"
|
"Penumbra.String": "[1.0.7, )"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"penumbra.string": {
|
"penumbra.string": {
|
||||||
|
|
|
||||||
14
repo.json
14
repo.json
|
|
@ -5,12 +5,12 @@
|
||||||
"Punchline": "Runtime mod loader and manager.",
|
"Punchline": "Runtime mod loader and manager.",
|
||||||
"Description": "Runtime mod loader and manager.",
|
"Description": "Runtime mod loader and manager.",
|
||||||
"InternalName": "Penumbra",
|
"InternalName": "Penumbra",
|
||||||
"AssemblyVersion": "1.5.1.6",
|
"AssemblyVersion": "1.5.1.9",
|
||||||
"TestingAssemblyVersion": "1.5.1.7",
|
"TestingAssemblyVersion": "1.5.1.9",
|
||||||
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"DalamudApiLevel": 13,
|
"DalamudApiLevel": 14,
|
||||||
"TestingDalamudApiLevel": 13,
|
"TestingDalamudApiLevel": 14,
|
||||||
"IsHide": "False",
|
"IsHide": "False",
|
||||||
"IsTestingExclusive": "False",
|
"IsTestingExclusive": "False",
|
||||||
"DownloadCount": 0,
|
"DownloadCount": 0,
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
"LoadPriority": 69420,
|
"LoadPriority": 69420,
|
||||||
"LoadRequiredState": 2,
|
"LoadRequiredState": 2,
|
||||||
"LoadSync": true,
|
"LoadSync": true,
|
||||||
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.6/Penumbra.zip",
|
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.9/Penumbra.zip",
|
||||||
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/testing_1.5.1.7/Penumbra.zip",
|
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.9/Penumbra.zip",
|
||||||
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.6/Penumbra.zip",
|
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.9/Penumbra.zip",
|
||||||
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue