Compare commits

..

No commits in common. "master" and "testing_1.5.1.7" have entirely different histories.

32 changed files with 148 additions and 448 deletions

View file

@ -10,15 +10,13 @@ jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
10.x.x
9.x.x
dotnet-version: '9.x.x'
- name: Restore dependencies
run: dotnet restore
- name: Download Dalamud

View file

@ -9,15 +9,13 @@ jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
10.x.x
9.x.x
dotnet-version: '9.x.x'
- name: Restore dependencies
run: dotnet restore
- name: Download Dalamud

View file

@ -9,15 +9,13 @@ jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
10.x.x
9.x.x
dotnet-version: '9.x.x'
- name: Restore dependencies
run: dotnet restore
- name: Download Dalamud

@ -1 +1 @@
Subproject commit ff1e6543845e3b8c53a5f8b240bc38faffb1b3bf
Subproject commit a63f6735cf4bed4f7502a022a10378607082b770

@ -1 +1 @@
Subproject commit 1750c41b53e1000c99a7fb9d8a0f082aef639a41
Subproject commit c23ee05c1e9fa103eaa52e6aa7e855ef568ee669

View file

@ -1,4 +1,4 @@
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>

View file

@ -1,12 +1,12 @@
{
"version": 1,
"dependencies": {
"net10.0-windows7.0": {
"net9.0-windows7.0": {
"DotNet.ReproducibleBuilds": {
"type": "Direct",
"requested": "[1.2.39, )",
"resolved": "1.2.39",
"contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
"requested": "[1.2.25, )",
"resolved": "1.2.25",
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
}
}
}

@ -1 +1 @@
Subproject commit 0e973ed6eace6afd31cd298f8c58f76fa8d5ef60
Subproject commit d889f9ef918514a46049725052d378b441915b00

@ -1 +1 @@
Subproject commit 9bd016fbef5fb2de467dd42165267fdd93cd9592
Subproject commit c8611a0c546b6b2ec29214ab319fc2c38fe74793

View file

@ -73,27 +73,6 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable
return (ret.Item1, (ret.Item2.Value.Item1, ret.Item2.Value.Item2, ret.Item2.Value.Item3, ret.Item2.Value.Item4));
}
public PenumbraApiEc GetSettingsInAllCollections(string modDirectory, string modName,
out Dictionary<Guid, (bool, int, Dictionary<string, List<string>>, bool, bool)> settings,
bool ignoreTemporaryCollections = false)
{
settings = [];
if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
return PenumbraApiEc.ModMissing;
var collections = ignoreTemporaryCollections
? _collectionManager.Storage.Where(c => c != ModCollection.Empty)
: _collectionManager.Storage.Where(c => c != ModCollection.Empty).Concat(_collectionManager.Temp.Values);
settings = [];
foreach (var collection in collections)
{
if (GetCurrentSettings(collection, mod, false, false, 0) is { } s)
settings.Add(collection.Identity.Id, s);
}
return PenumbraApiEc.Success;
}
public (PenumbraApiEc, (bool, int, Dictionary<string, List<string>>, bool, bool)?) GetCurrentModSettingsWithTemp(Guid collectionId,
string modDirectory, string modName, bool ignoreInheritance, bool ignoreTemporary, int key)
{

View file

@ -17,7 +17,7 @@ public class PenumbraApi(
UiApi ui) : IDisposable, IApiService, IPenumbraApi
{
public const int BreakingVersion = 5;
public const int FeatureVersion = 13;
public const int FeatureVersion = 12;
public void Dispose()
{

View file

@ -2,14 +2,11 @@ using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using OtterGui.Services;
using Penumbra.Api.Enums;
using Penumbra.Collections;
using Penumbra.Collections.Manager;
using Penumbra.GameData.Interop;
using Penumbra.Interop.Services;
namespace Penumbra.Api.Api;
public class RedrawApi(RedrawService redrawService, IFramework framework, CollectionManager collections, ObjectManager objects, ApiHelpers helpers) : IPenumbraApiRedraw, IApiService
namespace Penumbra.Api.Api;
public class RedrawApi(RedrawService redrawService, IFramework framework) : IPenumbraApiRedraw, IApiService
{
public void RedrawObject(int gameObjectIndex, RedrawType setting)
{
@ -31,27 +28,9 @@ public class RedrawApi(RedrawService redrawService, IFramework framework, Collec
framework.RunOnFrameworkThread(() => redrawService.RedrawAll(setting));
}
public void RedrawCollectionMembers(Guid collectionId, RedrawType setting)
{
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
{
add => redrawService.GameObjectRedrawn += value;
remove => redrawService.GameObjectRedrawn -= value;
}
}
}

View file

@ -1,6 +1,5 @@
using Dalamud.Plugin.Services;
using OtterGui.Services;
using Penumbra.Api.Enums;
using Penumbra.Collections;
using Penumbra.Collections.Manager;
using Penumbra.Interop.PathResolving;
@ -42,19 +41,6 @@ public class ResolveApi(
return ret.Select(r => r.ToString()).ToArray();
}
public PenumbraApiEc ResolvePath(Guid collectionId, string gamePath, out string resolvedPath)
{
resolvedPath = gamePath;
if (!collectionManager.Storage.ById(collectionId, out var collection))
return PenumbraApiEc.CollectionMissing;
if (!collection.HasCache)
return PenumbraApiEc.CollectionInactive;
resolvedPath = ResolvePath(gamePath, modManager, collection);
return PenumbraApiEc.Success;
}
public string[] ReverseResolvePlayerPath(string moddedPath)
{
if (!config.EnableMods)
@ -78,26 +64,6 @@ public class ResolveApi(
return (resolved, reverseResolved.Select(a => a.Select(p => p.ToString()).ToArray()).ToArray());
}
public PenumbraApiEc ResolvePaths(Guid collectionId, string[] forward, string[] reverse, out string[] resolvedForward,
out string[][] resolvedReverse)
{
resolvedForward = forward;
resolvedReverse = [];
if (!config.EnableMods)
return PenumbraApiEc.Success;
if (!collectionManager.Storage.ById(collectionId, out var collection))
return PenumbraApiEc.CollectionMissing;
if (!collection.HasCache)
return PenumbraApiEc.CollectionInactive;
resolvedForward = forward.Select(p => ResolvePath(p, modManager, collection)).ToArray();
var reverseResolved = collection.ReverseResolvePaths(reverse);
resolvedReverse = reverseResolved.Select(a => a.Select(p => p.ToString()).ToArray()).ToArray();
return PenumbraApiEc.Success;
}
public async Task<(string[], string[][])> ResolvePlayerPathsAsync(string[] forward, string[] reverse)
{
if (!config.EnableMods)

View file

@ -5,24 +5,20 @@ using Penumbra.GameData.Data;
using Penumbra.Mods.Manager;
using Penumbra.Services;
using Penumbra.UI;
using Penumbra.UI.Integration;
using Penumbra.UI.Tabs;
namespace Penumbra.Api.Api;
public class UiApi : IPenumbraApiUi, IApiService, IDisposable
{
private readonly CommunicatorService _communicator;
private readonly ConfigWindow _configWindow;
private readonly ModManager _modManager;
private readonly IntegrationSettingsRegistry _integrationSettings;
private readonly CommunicatorService _communicator;
private readonly ConfigWindow _configWindow;
private readonly ModManager _modManager;
public UiApi(CommunicatorService communicator, ConfigWindow configWindow, ModManager modManager, IntegrationSettingsRegistry integrationSettings)
public UiApi(CommunicatorService communicator, ConfigWindow configWindow, ModManager modManager)
{
_communicator = communicator;
_configWindow = configWindow;
_modManager = modManager;
_integrationSettings = integrationSettings;
_communicator = communicator;
_configWindow = configWindow;
_modManager = modManager;
_communicator.ChangedItemHover.Subscribe(OnChangedItemHover, ChangedItemHover.Priority.Default);
_communicator.ChangedItemClick.Subscribe(OnChangedItemClick, ChangedItemClick.Priority.Default);
}
@ -102,12 +98,4 @@ public class UiApi : IPenumbraApiUi, IApiService, IDisposable
var (type, id) = data.ToApiObject();
ChangedItemTooltip.Invoke(type, id);
}
public PenumbraApiEc RegisterSettingsSection(Action draw)
=> _integrationSettings.RegisterSection(draw);
public PenumbraApiEc UnregisterSettingsSection(Action draw)
=> _integrationSettings.UnregisterSection(draw)
? PenumbraApiEc.Success
: PenumbraApiEc.NothingChanged;
}

View file

@ -66,7 +66,6 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.GetCurrentModSettings.Provider(pi, api.ModSettings),
IpcSubscribers.GetCurrentModSettingsWithTemp.Provider(pi, api.ModSettings),
IpcSubscribers.GetAllModSettings.Provider(pi, api.ModSettings),
IpcSubscribers.GetSettingsInAllCollections.Provider(pi, api.ModSettings),
IpcSubscribers.TryInheritMod.Provider(pi, api.ModSettings),
IpcSubscribers.TrySetMod.Provider(pi, api.ModSettings),
IpcSubscribers.TrySetModPriority.Provider(pi, api.ModSettings),
@ -89,7 +88,6 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.RedrawObject.Provider(pi, api.Redraw),
IpcSubscribers.RedrawAll.Provider(pi, api.Redraw),
IpcSubscribers.GameObjectRedrawn.Provider(pi, api.Redraw),
IpcSubscribers.RedrawCollectionMembers.Provider(pi, api.Redraw),
IpcSubscribers.ResolveDefaultPath.Provider(pi, api.Resolve),
IpcSubscribers.ResolveInterfacePath.Provider(pi, api.Resolve),
@ -99,8 +97,6 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.ReverseResolvePlayerPath.Provider(pi, api.Resolve),
IpcSubscribers.ResolvePlayerPaths.Provider(pi, api.Resolve),
IpcSubscribers.ResolvePlayerPathsAsync.Provider(pi, api.Resolve),
IpcSubscribers.ResolvePath.Provider(pi, api.Resolve),
IpcSubscribers.ResolvePaths.Provider(pi, api.Resolve),
IpcSubscribers.GetGameObjectResourcePaths.Provider(pi, api.ResourceTree),
IpcSubscribers.GetPlayerResourcePaths.Provider(pi, api.ResourceTree),
@ -133,8 +129,6 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.PostSettingsDraw.Provider(pi, api.Ui),
IpcSubscribers.OpenMainWindow.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)
_initializedProvider.Invoke();

View file

@ -121,10 +121,6 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
}).ToArray();
ImGui.OpenPopup("Changed Item List");
}
IpcTester.DrawIntro(RedrawCollectionMembers.Label, "Redraw Collection Members");
if (ImGui.Button("Redraw##ObjectCollection"))
new RedrawCollectionMembers(pi).Invoke(collectionList[0].Id, RedrawType.Redraw);
}
private void DrawChangedItemPopup()

View file

@ -7,12 +7,12 @@ using OtterGui.Log;
using OtterGui.Services;
using OtterGui.Tasks;
using OtterTex;
using SharpDX.Direct3D11;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
using DxgiDevice = SharpDX.DXGI.Device;
using Image = SixLabors.ImageSharp.Image;
namespace Penumbra.Import.Textures;
@ -125,11 +125,11 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
switch (_type)
{
case TextureType.Png:
data?.SaveAsync(_outputPath, new PngEncoder { CompressionLevel = PngCompressionLevel.NoCompression }, cancel)
data?.SaveAsync(_outputPath, new PngEncoder() { CompressionLevel = PngCompressionLevel.NoCompression }, cancel)
.Wait(cancel);
return;
case TextureType.Targa:
data?.SaveAsync(_outputPath, new TgaEncoder
data?.SaveAsync(_outputPath, new TgaEncoder()
{
Compression = TgaCompression.None,
BitsPerPixel = TgaBitsPerPixel.Pixel32,
@ -204,16 +204,11 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
rgba, width, height),
CombinedTexture.TextureSaveType.AsIs when imageTypeBehaviour is TextureType.Dds => AddMipMaps(image.AsDds!, _mipMaps),
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.BC3 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC3UNorm, 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),
CombinedTexture.TextureSaveType.BC1 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC1UNorm, cancel, rgba, width, height),
CombinedTexture.TextureSaveType.BC3 => _textures.ConvertToCompressedDds(image, _mipMaps, DXGIFormat.BC3UNorm, 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."),
};
@ -395,7 +390,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>
public unsafe ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel)
public ScratchImage CreateCompressed(ScratchImage input, bool mipMaps, DXGIFormat format, CancellationToken cancel)
{
if (input.Meta.Format == format)
return input;
@ -411,58 +406,11 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
// 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)
{
ref var device = ref *(ID3D11Device*)uiBuilder.DeviceHandle;
IDXGIDevice* dxgiDevice;
Marshal.ThrowExceptionForHR(device.QueryInterface(TerraFX.Interop.Windows.Windows.__uuidof<IDXGIDevice>(), (void**)&dxgiDevice));
var device = new Device(uiBuilder.DeviceHandle);
var dxgiDevice = device.QueryInterface<DxgiDevice>();
try
{
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();
}
using var deviceClone = new Device(dxgiDevice.Adapter, device.CreationFlags, device.FeatureLevel);
return input.Compress(deviceClone.NativePointer, format, CompressFlags.Parallel);
}
return input.Compress(format, CompressFlags.BC7Quick | CompressFlags.Parallel);
@ -508,7 +456,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
GC.KeepAlive(input);
}
private readonly struct ImageInputData : IEquatable<ImageInputData>
private readonly struct ImageInputData
{
private readonly string? _inputPath;
@ -576,8 +524,5 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur
public override int GetHashCode()
=> _inputPath != null ? _inputPath.ToLowerInvariant().GetHashCode() : HashCode.Combine(_width, _height);
public override bool Equals(object? obj)
=> obj is ImageInputData o && Equals(o);
}
}

View file

@ -1,7 +1,8 @@
using Dalamud.Bindings.ImGui;
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using OtterGui.Services;
using TerraFX.Interop.DirectX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
namespace Penumbra.Interop.Services;
@ -21,78 +22,46 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
if (texture == null)
throw new ArgumentNullException(nameof(texture));
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))
{
state.Refresh();
return new ImTextureID((nint)state.ShaderResourceView);
}
ref var srv = ref *(ID3D11ShaderResourceView*)(nint)texture->D3D11ShaderResourceView;
srv.AddRef();
try
var srv = (ShaderResourceView)(nint)texture->D3D11ShaderResourceView;
var description = srv.Description;
switch (description.Dimension)
{
D3D11_SHADER_RESOURCE_VIEW_DESC description;
srv.GetDesc(&description);
switch (description.ViewDimension)
{
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE1D:
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D:
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DMS:
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE3D:
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURECUBE:
// This function treats these as single-slice arrays.
// As per the range check above, the only valid slice (i. e. 0) has been requested, therefore there is nothing to do.
break;
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
description.Texture1DArray.FirstArraySlice = sliceIndex;
description.Texture1DArray.ArraySize = 1;
break;
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
description.Texture2DArray.FirstArraySlice = sliceIndex;
description.Texture2DArray.ArraySize = 1;
break;
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
description.Texture2DMSArray.FirstArraySlice = sliceIndex;
description.Texture2DMSArray.ArraySize = 1;
break;
case D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
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();
case ShaderResourceViewDimension.Texture1D:
case ShaderResourceViewDimension.Texture2D:
case ShaderResourceViewDimension.Texture2DMultisampled:
case ShaderResourceViewDimension.Texture3D:
case ShaderResourceViewDimension.TextureCube:
// This function treats these as single-slice arrays.
// As per the range check above, the only valid slice (i. e. 0) has been requested, therefore there is nothing to do.
break;
case ShaderResourceViewDimension.Texture1DArray:
description.Texture1DArray.FirstArraySlice = sliceIndex;
description.Texture2DArray.ArraySize = 1;
break;
case ShaderResourceViewDimension.Texture2DArray:
description.Texture2DArray.FirstArraySlice = sliceIndex;
description.Texture2DArray.ArraySize = 1;
break;
case ShaderResourceViewDimension.Texture2DMultisampledArray:
description.Texture2DMSArray.FirstArraySlice = sliceIndex;
description.Texture2DMSArray.ArraySize = 1;
break;
case ShaderResourceViewDimension.TextureCubeArray:
description.TextureCubeArray.First2DArrayFace = sliceIndex * 6;
description.TextureCubeArray.CubeCount = 1;
break;
default:
throw new NotSupportedException($"{nameof(TextureArraySlicer)} does not support dimension {description.Dimension}");
}
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()
@ -104,9 +73,10 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
if (!slice.Tick())
_expiredKeys.Add(key);
}
foreach (var key in _expiredKeys)
{
_activeSlices.Remove(key);
}
}
finally
{
@ -117,12 +87,14 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
public void Dispose()
{
foreach (var slice in _activeSlices.Values)
{
slice.Dispose();
}
}
private sealed class SliceState(ID3D11ShaderResourceView* shaderResourceView) : IDisposable
private sealed class SliceState(ShaderResourceView shaderResourceView) : IDisposable
{
public readonly ID3D11ShaderResourceView* ShaderResourceView = shaderResourceView;
public readonly ShaderResourceView ShaderResourceView = shaderResourceView;
private uint _timeToLive = InitialTimeToLive;
@ -136,15 +108,13 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable
if (unchecked(_timeToLive--) > 0)
return true;
if (ShaderResourceView is not null)
ShaderResourceView->Release();
ShaderResourceView.Dispose();
return false;
}
public void Dispose()
{
if (ShaderResourceView is not null)
ShaderResourceView->Release();
ShaderResourceView.Dispose();
}
}
}

View file

@ -1,4 +1,4 @@
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
<PropertyGroup>
<AssemblyTitle>Penumbra</AssemblyTitle>
<Company>absolute gangstas</Company>
@ -38,8 +38,16 @@
<HintPath>$(DalamudLibPath)Iced.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="TerraFX.Interop.Windows">
<HintPath>$(DalamudLibPath)TerraFX.Interop.Windows.dll</HintPath>
<Reference Include="SharpDX">
<HintPath>$(DalamudLibPath)SharpDX.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>
</Reference>
<Reference Include="OtterTex.dll">

View file

@ -8,7 +8,7 @@
"RepoUrl": "https://github.com/xivdev/Penumbra",
"ApplicableVersion": "any",
"Tags": [ "modding" ],
"DalamudApiLevel": 14,
"DalamudApiLevel": 13,
"LoadPriority": 69420,
"LoadRequiredState": 2,
"LoadSync": true,

View file

@ -48,7 +48,6 @@ public static class StaticServiceManager
.AddDalamudService<ICommandManager>(pi)
.AddDalamudService<IDataManager>(pi)
.AddDalamudService<IClientState>(pi)
.AddDalamudService<IPlayerState>(pi)
.AddDalamudService<IChatGui>(pi)
.AddDalamudService<IFramework>(pi)
.AddDalamudService<ICondition>(pi)

View file

@ -7,7 +7,6 @@ using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.Services;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Extensions;
@ -18,6 +17,7 @@ using Penumbra.Collections.Manager;
using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums;
using Penumbra.Mods.Manager;
using Penumbra.Mods.Settings;
using Penumbra.Services;
using Penumbra.UI.Classes;

View file

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

View file

@ -1,6 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using OtterGui.Raii;
using OtterGui.Services;
using OtterGui.Widgets;

View file

@ -9,7 +9,6 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Interface.Colors;
using Microsoft.Extensions.DependencyInjection;
using OtterGui;
@ -1034,7 +1033,7 @@ public class DebugTab : Window, ITab, IUiService
/// <summary> Draw information about the models, materials and resources currently loaded by the local player. </summary>
private unsafe void DrawPlayerModelInfo()
{
var player = _objects.Objects.LocalPlayer;
var player = _clientState.LocalPlayer;
var name = player?.Name.ToString() ?? "NULL";
if (!ImGui.CollapsingHeader($"Player Model Info: {name}##Draw") || player == null)
return;

View file

@ -9,7 +9,6 @@ using OtterGui.Text;
using Penumbra.Interop.Services;
using Penumbra.Interop.Structs;
using Penumbra.String;
using Penumbra.Util;
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
namespace Penumbra.UI.Tabs.Debug;
@ -179,10 +178,10 @@ public unsafe class GlobalVariablesDrawer(
if (_schedulerFilterMap.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterMapU8.Span) >= 0)
{
ImUtf8.DrawTableColumn($"[{total:D4}]");
ImUtf8.DrawTableColumn($"{resource->Name.GetField<ushort, SchedulerResource.ResourceName>(16)}"); // Unk1
ImUtf8.DrawTableColumn($"{resource->Name.Unk1}");
ImUtf8.DrawTableColumn(new CiByteString(resource->Name.Buffer, MetaDataComputation.None).Span);
ImUtf8.DrawTableColumn($"{resource->Consumers}");
ImUtf8.DrawTableColumn($"{PointerExtensions.GetField<uint, SchedulerResource>(resource, 120)}"); // key, Unk1
ImUtf8.DrawTableColumn($"{resource->Unk1}"); // key
ImGui.TableNextColumn();
Penumbra.Dynamis.DrawPointer(resource);
ImGui.TableNextColumn();
@ -228,10 +227,10 @@ public unsafe class GlobalVariablesDrawer(
if (_schedulerFilterList.Length is 0 || resource->Name.Buffer.IndexOf(_schedulerFilterListU8.Span) >= 0)
{
ImUtf8.DrawTableColumn($"[{total:D4}]");
ImUtf8.DrawTableColumn($"{resource->Name.GetField<ushort, SchedulerResource.ResourceName>(16)}"); // Unk1
ImUtf8.DrawTableColumn($"{resource->Name.Unk1}");
ImUtf8.DrawTableColumn(new CiByteString(resource->Name.Buffer, MetaDataComputation.None).Span);
ImUtf8.DrawTableColumn($"{resource->Consumers}");
ImUtf8.DrawTableColumn($"{PointerExtensions.GetField<uint, SchedulerResource>(resource, 120)}"); // key, Unk1
ImUtf8.DrawTableColumn($"{resource->Unk1}"); // key
ImGui.TableNextColumn();
Penumbra.Dynamis.DrawPointer(resource);
ImGui.TableNextColumn();

View file

@ -27,6 +27,7 @@ public class ModsTab(
TutorialService tutorial,
RedrawService redrawService,
Configuration config,
IClientState clientState,
CollectionSelectHeader collectionHeader,
ITargetManager targets,
ObjectManager objects)
@ -112,7 +113,7 @@ public class ModsTab(
ImGui.SetTooltip($"The supported modifiers for '/penumbra redraw' are:\n{TutorialService.SupportedRedrawModifiers}");
using var id = ImRaii.PushId("Redraw");
using var disabled = ImRaii.Disabled(objects.Objects.LocalPlayer is null);
using var disabled = ImRaii.Disabled(clientState.LocalPlayer == null);
ImGui.SameLine();
var buttonWidth = frameHeight with { X = ImGui.GetContentRegionAvail().X / 5 };
var tt = !objects[0].Valid

View file

@ -1,5 +1,5 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.Services;
using Dalamud.Game;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using FFXIVClientStructs.Interop;

View file

@ -20,7 +20,6 @@ using Penumbra.Interop.Services;
using Penumbra.Mods.Manager;
using Penumbra.Services;
using Penumbra.UI.Classes;
using Penumbra.UI.Integration;
using Penumbra.UI.ModsTab;
namespace Penumbra.UI.Tabs;
@ -56,7 +55,6 @@ public class SettingsTab : ITab, IUiService
private readonly CleanupService _cleanupService;
private readonly AttributeHook _attributeHook;
private readonly PcpService _pcpService;
private readonly IntegrationSettingsRegistry _integrationSettings;
private int _minimumX = int.MaxValue;
private int _minimumY = int.MaxValue;
@ -73,7 +71,7 @@ public class SettingsTab : ITab, IUiService
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
AttributeHook attributeHook, PcpService pcpService, IntegrationSettingsRegistry integrationSettings)
AttributeHook attributeHook, PcpService pcpService)
{
_pluginInterface = pluginInterface;
_config = config;
@ -101,7 +99,6 @@ public class SettingsTab : ITab, IUiService
_cleanupService = cleanupService;
_attributeHook = attributeHook;
_pcpService = pcpService;
_integrationSettings = integrationSettings;
}
public void DrawHeader()
@ -132,7 +129,6 @@ public class SettingsTab : ITab, IUiService
DrawColorSettings();
DrawPredefinedTagsSection();
DrawAdvancedSettings();
_integrationSettings.Draw();
DrawSupportButtons();
}
@ -1137,7 +1133,7 @@ public class SettingsTab : ITab, IUiService
}
#endregion
/// <summary> Draw the support button group on the right-hand side of the window. </summary>
private void DrawSupportButtons()
{

View file

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

View file

@ -1,12 +1,12 @@
{
"version": 1,
"dependencies": {
"net10.0-windows7.0": {
"net9.0-windows7.0": {
"DotNet.ReproducibleBuilds": {
"type": "Direct",
"requested": "[1.2.39, )",
"resolved": "1.2.39",
"contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
"requested": "[1.2.25, )",
"resolved": "1.2.25",
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
},
"EmbedIO": {
"type": "Direct",
@ -33,6 +33,7 @@
"resolved": "0.40.0",
"contentHash": "yP/aFX1jqGikVF7u2f05VEaWN4aCaKNLxSas82UgA2GGVECxq/BcqZx3STHCJ78qilo1azEOk1XpBglIuGMb7w==",
"dependencies": {
"System.Buffers": "4.6.0",
"ZstdSharp.Port": "0.8.5"
}
},
@ -65,7 +66,10 @@
"FlatSharp.Runtime": {
"type": "Transitive",
"resolved": "7.9.0",
"contentHash": "Bm8+WqzEsWNpxqrD5x4x+zQ8dyINlToCreM5FI2oNSfUVc9U9ZB+qztX/jd8rlJb3r0vBSlPwVLpw0xBtPa3Vw=="
"contentHash": "Bm8+WqzEsWNpxqrD5x4x+zQ8dyINlToCreM5FI2oNSfUVc9U9ZB+qztX/jd8rlJb3r0vBSlPwVLpw0xBtPa3Vw==",
"dependencies": {
"System.Memory": "4.5.5"
}
},
"JetBrains.Annotations": {
"type": "Transitive",
@ -98,15 +102,33 @@
"SharpGLTF.Core": "1.0.5"
}
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
},
"System.Security.Cryptography.Pkcs": {
"type": "Transitive",
"resolved": "8.0.1",
"contentHash": "CoCRHFym33aUSf/NtWSVSZa99dkd0Hm7OCZUxORBjRB16LNhIEOf8THPqzIYlvKM0nNDAPTRBa1FxEECrgaxxA=="
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"Unosquare.Swan.Lite": {
"type": "Transitive",
"resolved": "3.1.0",
"contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ=="
"contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ==",
"dependencies": {
"System.ValueTuple": "4.5.0"
}
},
"ZstdSharp.Port": {
"type": "Transitive",
@ -132,7 +154,7 @@
"FlatSharp.Compiler": "[7.9.0, )",
"FlatSharp.Runtime": "[7.9.0, )",
"OtterGui": "[1.0.0, )",
"Penumbra.Api": "[5.13.0, )",
"Penumbra.Api": "[5.10.0, )",
"Penumbra.String": "[1.0.6, )"
}
},

View file

@ -5,12 +5,12 @@
"Punchline": "Runtime mod loader and manager.",
"Description": "Runtime mod loader and manager.",
"InternalName": "Penumbra",
"AssemblyVersion": "1.5.1.9",
"TestingAssemblyVersion": "1.5.1.9",
"AssemblyVersion": "1.5.1.6",
"TestingAssemblyVersion": "1.5.1.6",
"RepoUrl": "https://github.com/xivdev/Penumbra",
"ApplicableVersion": "any",
"DalamudApiLevel": 14,
"TestingDalamudApiLevel": 14,
"DalamudApiLevel": 13,
"TestingDalamudApiLevel": 13,
"IsHide": "False",
"IsTestingExclusive": "False",
"DownloadCount": 0,
@ -18,9 +18,9 @@
"LoadPriority": 69420,
"LoadRequiredState": 2,
"LoadSync": true,
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.9/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.9/Penumbra.zip",
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.6/Penumbra.zip",
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.6/Penumbra.zip",
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.6/Penumbra.zip",
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
}
]