mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-29 03:49:19 +01:00
cleanup
This commit is contained in:
parent
c04ce36b9c
commit
e1bdba06de
6 changed files with 245 additions and 164 deletions
|
|
@ -53,6 +53,8 @@ internal class TexWidget : IDataWindowWidget
|
|||
private FileDialogManager fileDialogManager = null!;
|
||||
private ExistingTextureModificationArgs existingTextureModificationArgs;
|
||||
|
||||
private ImGuiViewportTextureArgs viewportTextureArgs;
|
||||
private int viewportIndexInt;
|
||||
private string[]? supportedRenderTargetFormatNames;
|
||||
private DXGI_FORMAT[]? supportedRenderTargetFormats;
|
||||
private int renderTargetChoiceInt;
|
||||
|
|
@ -84,6 +86,7 @@ internal class TexWidget : IDataWindowWidget
|
|||
this.inputManifestResourceNameIndex = 0;
|
||||
this.supportedRenderTargetFormats = null;
|
||||
this.supportedRenderTargetFormatNames = null;
|
||||
this.renderTargetChoiceInt = 0;
|
||||
this.fileDialogManager = new();
|
||||
this.existingTextureModificationArgs = new()
|
||||
{
|
||||
|
|
@ -92,6 +95,8 @@ internal class TexWidget : IDataWindowWidget
|
|||
NewWidth = 320,
|
||||
NewHeight = 240,
|
||||
};
|
||||
this.viewportTextureArgs = default;
|
||||
this.viewportIndexInt = 0;
|
||||
this.Ready = true;
|
||||
}
|
||||
|
||||
|
|
@ -135,57 +140,41 @@ internal class TexWidget : IDataWindowWidget
|
|||
|
||||
ImGui.Dummy(new(ImGui.GetTextLineHeightWithSpacing()));
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Capture: ");
|
||||
if (ImGui.Button("Game"))
|
||||
this.addedTextures.Add(new() { Api10 = this.textureManager.CreateFromGameScreen() });
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Game (Auto)"))
|
||||
this.addedTextures.Add(new() { Api10 = this.textureManager.CreateFromGameScreen(true) });
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Main Viewport"))
|
||||
{
|
||||
this.addedTextures.Add(
|
||||
new() { Api10 = this.textureManager.CreateFromImGuiViewport(ImGui.GetMainViewport().ID) });
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Main Viewport (Auto)"))
|
||||
{
|
||||
this.addedTextures.Add(
|
||||
new() { Api10 = this.textureManager.CreateFromImGuiViewport(ImGui.GetMainViewport().ID, true) });
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGameIcon), ImGuiTreeNodeFlags.DefaultOpen))
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGameIcon)))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawGetFromGameIcon));
|
||||
this.DrawGetFromGameIcon();
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGame), ImGuiTreeNodeFlags.DefaultOpen))
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGame)))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawGetFromGame));
|
||||
this.DrawGetFromGame();
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromFile), ImGuiTreeNodeFlags.DefaultOpen))
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromFile)))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawGetFromFile));
|
||||
this.DrawGetFromFile();
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromManifestResource), ImGuiTreeNodeFlags.DefaultOpen))
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromManifestResource)))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawGetFromManifestResource));
|
||||
this.DrawGetFromManifestResource();
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader(nameof(ITextureProvider.CreateFromImGuiViewportAsync)))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawCreateFromImGuiViewportAsync));
|
||||
this.DrawCreateFromImGuiViewportAsync();
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader("UV"))
|
||||
{
|
||||
ImGui.PushID(nameof(this.DrawUvInput));
|
||||
|
|
@ -574,6 +563,57 @@ internal class TexWidget : IDataWindowWidget
|
|||
ImGuiHelpers.ScaledDummy(10);
|
||||
}
|
||||
|
||||
private void DrawCreateFromImGuiViewportAsync()
|
||||
{
|
||||
var viewports = ImGui.GetPlatformIO().Viewports;
|
||||
if (ImGui.BeginCombo(
|
||||
nameof(this.viewportTextureArgs.ViewportId),
|
||||
$"{this.viewportIndexInt}. {viewports[this.viewportIndexInt].ID:X08}"))
|
||||
{
|
||||
for (var i = 0; i < viewports.Size; i++)
|
||||
{
|
||||
var sel = this.viewportIndexInt == i;
|
||||
if (ImGui.Selectable($"#{i}: {viewports[i].ID:X08}", ref sel))
|
||||
{
|
||||
this.viewportIndexInt = i;
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
var b = this.viewportTextureArgs.KeepTransparency;
|
||||
if (ImGui.Checkbox(nameof(this.viewportTextureArgs.KeepTransparency), ref b))
|
||||
this.viewportTextureArgs.KeepTransparency = b;
|
||||
|
||||
b = this.viewportTextureArgs.AutoUpdate;
|
||||
if (ImGui.Checkbox(nameof(this.viewportTextureArgs.AutoUpdate), ref b))
|
||||
this.viewportTextureArgs.AutoUpdate = b;
|
||||
|
||||
b = this.viewportTextureArgs.TakeBeforeImGuiRender;
|
||||
if (ImGui.Checkbox(nameof(this.viewportTextureArgs.TakeBeforeImGuiRender), ref b))
|
||||
this.viewportTextureArgs.TakeBeforeImGuiRender = b;
|
||||
|
||||
var vec2 = this.viewportTextureArgs.Uv0;
|
||||
if (ImGui.InputFloat2(nameof(this.viewportTextureArgs.Uv0), ref vec2))
|
||||
this.viewportTextureArgs.Uv0 = vec2;
|
||||
|
||||
vec2 = this.viewportTextureArgs.Uv1;
|
||||
if (ImGui.InputFloat2(nameof(this.viewportTextureArgs.Uv1), ref vec2))
|
||||
this.viewportTextureArgs.Uv1 = vec2;
|
||||
|
||||
if (ImGui.Button("Create") && this.viewportIndexInt >= 0 && this.viewportIndexInt < viewports.Size)
|
||||
{
|
||||
this.addedTextures.Add(
|
||||
new()
|
||||
{
|
||||
Api10 = this.textureManager.CreateFromImGuiViewportAsync(
|
||||
this.viewportTextureArgs with { ViewportId = viewports[this.viewportIndexInt].ID }),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawUvInput()
|
||||
{
|
||||
ImGui.InputFloat2("UV0", ref this.inputTexUv0);
|
||||
|
|
@ -586,25 +626,8 @@ internal class TexWidget : IDataWindowWidget
|
|||
|
||||
private void DrawExistingTextureModificationArgs()
|
||||
{
|
||||
var vec2 = this.existingTextureModificationArgs.Uv0;
|
||||
if (ImGui.InputFloat2("UV0", ref vec2))
|
||||
this.existingTextureModificationArgs.Uv0 = vec2;
|
||||
|
||||
vec2 = this.existingTextureModificationArgs.Uv1;
|
||||
if (ImGui.InputFloat2("UV1", ref vec2))
|
||||
this.existingTextureModificationArgs.Uv1 = vec2;
|
||||
|
||||
Span<int> wh = stackalloc int[2];
|
||||
wh[0] = this.existingTextureModificationArgs.NewWidth;
|
||||
wh[1] = this.existingTextureModificationArgs.NewHeight;
|
||||
if (ImGui.InputInt2("New Size", ref wh[0]))
|
||||
{
|
||||
this.existingTextureModificationArgs.NewWidth = wh[0];
|
||||
this.existingTextureModificationArgs.NewHeight = wh[1];
|
||||
}
|
||||
|
||||
var b = this.existingTextureModificationArgs.MakeOpaque;
|
||||
if (ImGui.Checkbox("Make Opaque", ref b))
|
||||
if (ImGui.Checkbox(nameof(this.existingTextureModificationArgs.MakeOpaque), ref b))
|
||||
this.existingTextureModificationArgs.MakeOpaque = b;
|
||||
|
||||
if (this.supportedRenderTargetFormats is null)
|
||||
|
|
@ -619,11 +642,30 @@ internal class TexWidget : IDataWindowWidget
|
|||
|
||||
this.supportedRenderTargetFormatNames ??= this.supportedRenderTargetFormats.Select(Enum.GetName).ToArray();
|
||||
ImGui.Combo(
|
||||
"Format",
|
||||
nameof(this.existingTextureModificationArgs.DxgiFormat),
|
||||
ref this.renderTargetChoiceInt,
|
||||
this.supportedRenderTargetFormatNames,
|
||||
this.supportedRenderTargetFormatNames.Length);
|
||||
|
||||
|
||||
Span<int> wh = stackalloc int[2];
|
||||
wh[0] = this.existingTextureModificationArgs.NewWidth;
|
||||
wh[1] = this.existingTextureModificationArgs.NewHeight;
|
||||
if (ImGui.InputInt2(
|
||||
$"{nameof(this.existingTextureModificationArgs.NewWidth)}/{nameof(this.existingTextureModificationArgs.NewHeight)}",
|
||||
ref wh[0]))
|
||||
{
|
||||
this.existingTextureModificationArgs.NewWidth = wh[0];
|
||||
this.existingTextureModificationArgs.NewHeight = wh[1];
|
||||
}
|
||||
|
||||
var vec2 = this.existingTextureModificationArgs.Uv0;
|
||||
if (ImGui.InputFloat2(nameof(this.existingTextureModificationArgs.Uv0), ref vec2))
|
||||
this.existingTextureModificationArgs.Uv0 = vec2;
|
||||
|
||||
vec2 = this.existingTextureModificationArgs.Uv1;
|
||||
if (ImGui.InputFloat2(nameof(this.existingTextureModificationArgs.Uv1), ref vec2))
|
||||
this.existingTextureModificationArgs.Uv1 = vec2;
|
||||
|
||||
ImGuiHelpers.ScaledDummy(10);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,15 +9,18 @@ namespace Dalamud.Interface.Textures;
|
|||
/// <summary>Describes how to modify an existing texture.</summary>
|
||||
public record struct ExistingTextureModificationArgs()
|
||||
{
|
||||
/// <summary>Gets or sets the left top coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
public Vector2 Uv0 { get; set; } = Vector2.Zero;
|
||||
/// <summary>Gets or sets a value indicating whether to make the texture opaque.</summary>
|
||||
/// <remarks>If <c>true</c>, then the alpha channel values will be filled with 1.0.</remarks>
|
||||
public bool MakeOpaque { get; set; } = false;
|
||||
|
||||
/// <summary>Gets or sets the right bottom coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
/// <remarks>If set to <see cref="Vector2.Zero"/>, then it will be interpreted as <see cref="Vector2.One"/>,
|
||||
/// to accommodate the use of default value of this record struct.</remarks>
|
||||
public Vector2 Uv1 { get; set; } = Vector2.One;
|
||||
/// <summary>Gets or sets the new DXGI format.</summary>
|
||||
/// <remarks>
|
||||
/// <para>Set to 0 (<see cref="DXGI_FORMAT.DXGI_FORMAT_UNKNOWN"/>) to use the source pixel format.</para>
|
||||
/// <para>Supported values can be queried with
|
||||
/// <see cref="ITextureProvider.IsDxgiFormatSupportedForCreateFromExistingTextureAsync"/>. This may not necessarily
|
||||
/// match <see cref="ITextureProvider.IsDxgiFormatSupported"/>.
|
||||
/// </para></remarks>
|
||||
public int DxgiFormat { get; set; } = (int)DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
/// <summary>Gets or sets the new width.</summary>
|
||||
/// <remarks>Set to 0 to automatically calculate according to the original texture size, <see cref="Uv0"/>, and
|
||||
|
|
@ -29,18 +32,15 @@ public record struct ExistingTextureModificationArgs()
|
|||
/// <see cref="Uv1"/>.</remarks>
|
||||
public int NewHeight { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether to make the texture opaque.</summary>
|
||||
/// <remarks>Alpha channel values will be filled with 1.0.</remarks>
|
||||
public bool MakeOpaque { get; set; } = false;
|
||||
/// <summary>Gets or sets the left top coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
public Vector2 Uv0 { get; set; } = Vector2.Zero;
|
||||
|
||||
/// <summary>Gets or sets the new DXGI format.</summary>
|
||||
/// <remarks>
|
||||
/// <para>Set to 0 (<see cref="DXGI_FORMAT.DXGI_FORMAT_UNKNOWN"/>) to use the source pixel format.</para>
|
||||
/// <para>Supported values can be queried with
|
||||
/// <see cref="ITextureProvider.IsDxgiFormatSupportedForCreateFromExistingTextureAsync"/>. This may not necessarily
|
||||
/// match <see cref="ITextureProvider.IsDxgiFormatSupported"/>.
|
||||
/// </para></remarks>
|
||||
public int DxgiFormat { get; set; } = (int)DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
/// <summary>Gets or sets the right bottom coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
/// <remarks>If set to <see cref="Vector2.Zero"/>, then it will be interpreted as <see cref="Vector2.One"/>,
|
||||
/// to accommodate the use of default value of this record struct.</remarks>
|
||||
public Vector2 Uv1 { get; set; } = Vector2.One;
|
||||
|
||||
/// <summary>Gets or sets the format (typed).</summary>
|
||||
internal DXGI_FORMAT Format
|
||||
|
|
|
|||
68
Dalamud/Interface/Textures/ImGuiViewportTextureArgs.cs
Normal file
68
Dalamud/Interface/Textures/ImGuiViewportTextureArgs.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
using System.Numerics;
|
||||
|
||||
using Dalamud.Interface.Internal;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Dalamud.Interface.Textures;
|
||||
|
||||
/// <summary>Describes how to take a texture of an existing ImGui viewport.</summary>
|
||||
public record struct ImGuiViewportTextureArgs()
|
||||
{
|
||||
/// <summary>Gets or sets the ImGui Viewport ID to capture.</summary>
|
||||
/// <remarks>Use <see cref="ImGuiViewport.ID"/> from <see cref="ImGui.GetMainViewport"/> to take the main viewport,
|
||||
/// where the game renders to.</remarks>
|
||||
public uint ViewportId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether to automatically update the texture.</summary>
|
||||
/// <remarks>Enabling this will also update <see cref="IDalamudTextureWrap.Size"/> as needed.</remarks>
|
||||
public bool AutoUpdate { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether to get the texture before rendering ImGui.</summary>
|
||||
/// <remarks>It probably makes no sense to enable this unless <see cref="ViewportId"/> points to the main viewport.
|
||||
/// </remarks>
|
||||
public bool TakeBeforeImGuiRender { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether to keep the transparency.</summary>
|
||||
/// <remarks>
|
||||
/// <para>If <c>true</c>, then the alpha channel values will be filled with 1.0.</para>
|
||||
/// <para>Keep in mind that screen captures generally do not need alpha values.</para>
|
||||
/// </remarks>
|
||||
// Intentionally not "MakeOpaque", to accommodate the use of default value of this record struct.
|
||||
public bool KeepTransparency { get; set; } = false;
|
||||
|
||||
/// <summary>Gets or sets the left top coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
public Vector2 Uv0 { get; set; } = Vector2.Zero;
|
||||
|
||||
/// <summary>Gets or sets the right bottom coordinates relative to the size of the source texture.</summary>
|
||||
/// <para>Coordinates should be in range between 0 and 1.</para>
|
||||
/// <remarks>If set to <see cref="Vector2.Zero"/>, then it will be interpreted as <see cref="Vector2.One"/>,
|
||||
/// to accommodate the use of default value of this record struct.</remarks>
|
||||
public Vector2 Uv1 { get; set; } = Vector2.One;
|
||||
|
||||
/// <summary>Gets the effective value of <see cref="Uv1"/>.</summary>
|
||||
internal Vector2 Uv1Effective => this.Uv1 == Vector2.Zero ? Vector2.One : this.Uv1;
|
||||
|
||||
/// <summary>Checks the properties and throws an exception if values are invalid.</summary>
|
||||
internal void ThrowOnInvalidValues()
|
||||
{
|
||||
if (this.Uv0.X is < 0 or > 1 or float.NaN)
|
||||
throw new ArgumentException($"{nameof(this.Uv0)}.X is out of range.");
|
||||
|
||||
if (this.Uv0.Y is < 0 or > 1 or float.NaN)
|
||||
throw new ArgumentException($"{nameof(this.Uv0)}.Y is out of range.");
|
||||
|
||||
if (this.Uv1Effective.X is < 0 or > 1 or float.NaN)
|
||||
throw new ArgumentException($"{nameof(this.Uv1)}.X is out of range.");
|
||||
|
||||
if (this.Uv1Effective.Y is < 0 or > 1 or float.NaN)
|
||||
throw new ArgumentException($"{nameof(this.Uv1)}.Y is out of range.");
|
||||
|
||||
if (this.Uv0.X >= this.Uv1Effective.X || this.Uv0.Y >= this.Uv1Effective.Y)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
$"{nameof(this.Uv0)} must be strictly less than {nameof(this.Uv1)} in a componentwise way.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,6 @@ using Dalamud.Interface.Internal;
|
|||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
|
|
@ -85,47 +83,15 @@ internal sealed partial class TextureManager
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<IDalamudTextureWrap> CreateFromGameScreen(
|
||||
bool autoUpdate = false,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
this.interfaceManager.RunBeforeImGuiRender(
|
||||
() =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var t = new ViewportTextureWrap(ImGui.GetMainViewport().ID, true, autoUpdate, cancellationToken);
|
||||
t.Update();
|
||||
try
|
||||
{
|
||||
return t.FirstUpdateTask.Result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
t.Dispose();
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<IDalamudTextureWrap> CreateFromImGuiViewport(
|
||||
uint viewportId,
|
||||
bool autoUpdate = false,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
this.interfaceManager.RunBeforeImGuiRender(
|
||||
() =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var t = new ViewportTextureWrap(viewportId, false, autoUpdate, cancellationToken);
|
||||
t.Update();
|
||||
try
|
||||
{
|
||||
return t.FirstUpdateTask.Result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
t.Dispose();
|
||||
throw;
|
||||
}
|
||||
});
|
||||
public async Task<IDalamudTextureWrap> CreateFromImGuiViewportAsync(
|
||||
ImGuiViewportTextureArgs args,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// This constructor may throw; keep the function "async", to wrap the exception as a Task.
|
||||
var t = new ViewportTextureWrap(args, cancellationToken);
|
||||
t.QueueUpdate();
|
||||
return await t.FirstUpdateTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<(RawImageSpecification Specification, byte[] RawData)> GetRawDataFromExistingTextureAsync(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -19,33 +18,25 @@ namespace Dalamud.Interface.Textures.Internal;
|
|||
/// <summary>A texture wrap that takes its buffer from the frame buffer (of swap chain).</summary>
|
||||
internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDisposable
|
||||
{
|
||||
private readonly uint viewportId;
|
||||
private readonly bool beforeImGuiRender;
|
||||
private readonly CancellationToken cancellationToken;
|
||||
private readonly TaskCompletionSource<IDalamudTextureWrap> firstUpdateTaskCompletionSource = new();
|
||||
|
||||
private ImGuiViewportTextureArgs args;
|
||||
private D3D11_TEXTURE2D_DESC desc;
|
||||
private ComPtr<ID3D11Texture2D> tex;
|
||||
private ComPtr<ID3D11ShaderResourceView> srv;
|
||||
private ComPtr<ID3D11RenderTargetView> rtv;
|
||||
|
||||
private bool autoUpdate;
|
||||
private bool disposed;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="ViewportTextureWrap"/> class.</summary>
|
||||
/// <param name="viewportId">The source viewport ID.</param>
|
||||
/// <param name="beforeImGuiRender">Capture before calling <see cref="ImGui.Render"/>.</param>
|
||||
/// <param name="autoUpdate">If <c>true</c>, automatically update the underlying texture.</param>
|
||||
/// <param name="args">The arguments for creating a texture.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public ViewportTextureWrap(
|
||||
uint viewportId,
|
||||
bool beforeImGuiRender,
|
||||
bool autoUpdate,
|
||||
CancellationToken cancellationToken)
|
||||
public ViewportTextureWrap(ImGuiViewportTextureArgs args, CancellationToken cancellationToken)
|
||||
{
|
||||
this.viewportId = viewportId;
|
||||
this.beforeImGuiRender = beforeImGuiRender;
|
||||
this.autoUpdate = autoUpdate;
|
||||
args.ThrowOnInvalidValues();
|
||||
|
||||
this.args = args;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +68,7 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
{
|
||||
ThreadSafety.AssertMainThread();
|
||||
|
||||
using var backBuffer = GetImGuiViewportBackBuffer(this.viewportId);
|
||||
using var backBuffer = GetImGuiViewportBackBuffer(this.args.ViewportId);
|
||||
D3D11_TEXTURE2D_DESC newDesc;
|
||||
backBuffer.Get()->GetDesc(&newDesc);
|
||||
|
||||
|
|
@ -90,14 +81,24 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
using var context = default(ComPtr<ID3D11DeviceContext>);
|
||||
device.Get()->GetImmediateContext(context.GetAddressOf());
|
||||
|
||||
if (this.desc.Width != newDesc.Width
|
||||
|| this.desc.Height != newDesc.Height
|
||||
var copyBox = new D3D11_BOX
|
||||
{
|
||||
left = (uint)MathF.Round(newDesc.Width * this.args.Uv0.X),
|
||||
top = (uint)MathF.Round(newDesc.Height * this.args.Uv0.Y),
|
||||
right = (uint)MathF.Round(newDesc.Width * this.args.Uv1Effective.X),
|
||||
bottom = (uint)MathF.Round(newDesc.Height * this.args.Uv1Effective.Y),
|
||||
front = 0,
|
||||
back = 1,
|
||||
};
|
||||
|
||||
if (this.desc.Width != copyBox.right - copyBox.left
|
||||
|| this.desc.Height != copyBox.bottom - copyBox.top
|
||||
|| this.desc.Format != newDesc.Format)
|
||||
{
|
||||
var texDesc = new D3D11_TEXTURE2D_DESC
|
||||
{
|
||||
Width = newDesc.Width,
|
||||
Height = newDesc.Height,
|
||||
Width = copyBox.right - copyBox.left,
|
||||
Height = copyBox.bottom - copyBox.top,
|
||||
MipLevels = 1,
|
||||
ArraySize = 1,
|
||||
Format = newDesc.Format,
|
||||
|
|
@ -131,19 +132,32 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
srvTemp.GetAddressOf())
|
||||
.ThrowOnError();
|
||||
|
||||
this.desc = newDesc;
|
||||
this.desc = texDesc;
|
||||
srvTemp.Swap(ref this.srv);
|
||||
rtvTemp.Swap(ref this.rtv);
|
||||
texTemp.Swap(ref this.tex);
|
||||
}
|
||||
|
||||
context.Get()->CopyResource((ID3D11Resource*)this.tex.Get(), (ID3D11Resource*)backBuffer.Get());
|
||||
var rtvLocal = this.rtv.Get();
|
||||
context.Get()->OMSetRenderTargets(1u, &rtvLocal, null);
|
||||
Service<TextureManager>.Get().SimpleDrawer.StripAlpha(context.Get());
|
||||
// context.Get()->CopyResource((ID3D11Resource*)this.tex.Get(), (ID3D11Resource*)backBuffer.Get());
|
||||
context.Get()->CopySubresourceRegion(
|
||||
(ID3D11Resource*)this.tex.Get(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(ID3D11Resource*)backBuffer.Get(),
|
||||
0,
|
||||
©Box);
|
||||
|
||||
var dummy = default(ID3D11RenderTargetView*);
|
||||
context.Get()->OMSetRenderTargets(1u, &dummy, null);
|
||||
if (!this.args.KeepTransparency)
|
||||
{
|
||||
var rtvLocal = this.rtv.Get();
|
||||
context.Get()->OMSetRenderTargets(1u, &rtvLocal, null);
|
||||
Service<TextureManager>.Get().SimpleDrawer.StripAlpha(context.Get());
|
||||
|
||||
var dummy = default(ID3D11RenderTargetView*);
|
||||
context.Get()->OMSetRenderTargets(1u, &dummy, null);
|
||||
}
|
||||
|
||||
this.firstUpdateTaskCompletionSource.TrySetResult(this);
|
||||
}
|
||||
|
|
@ -152,20 +166,22 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
this.firstUpdateTaskCompletionSource.TrySetException(e);
|
||||
}
|
||||
|
||||
if (this.autoUpdate)
|
||||
{
|
||||
Service<Framework>.Get().RunOnTick(
|
||||
() =>
|
||||
{
|
||||
if (this.beforeImGuiRender)
|
||||
Service<InterfaceManager>.Get().RunBeforeImGuiRender(this.Update);
|
||||
else
|
||||
Service<InterfaceManager>.Get().RunAfterImGuiRender(this.Update);
|
||||
},
|
||||
cancellationToken: this.cancellationToken);
|
||||
}
|
||||
if (this.args.AutoUpdate)
|
||||
this.QueueUpdate();
|
||||
}
|
||||
|
||||
/// <summary>Queues a call to <see cref="Update"/>.</summary>
|
||||
public void QueueUpdate() =>
|
||||
Service<Framework>.Get().RunOnTick(
|
||||
() =>
|
||||
{
|
||||
if (this.args.TakeBeforeImGuiRender)
|
||||
Service<InterfaceManager>.Get().RunBeforeImGuiRender(this.Update);
|
||||
else
|
||||
Service<InterfaceManager>.Get().RunAfterImGuiRender(this.Update);
|
||||
},
|
||||
cancellationToken: this.cancellationToken);
|
||||
|
||||
/// <summary>Queue the texture to be disposed once the frame ends. </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
@ -230,7 +246,7 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
private void Dispose(bool disposing)
|
||||
{
|
||||
this.disposed = true;
|
||||
this.autoUpdate = false;
|
||||
this.args.AutoUpdate = false;
|
||||
if (disposing)
|
||||
Service<InterfaceManager>.GetNullable()?.EnqueueDeferredDispose(this);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -45,27 +45,16 @@ public partial interface ITextureProvider
|
|||
bool leaveWrapOpen = false,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>Creates a texture from the game screen, before rendering Dalamud.</summary>
|
||||
/// <param name="autoUpdate">If <c>true</c>, automatically update the underlying texture.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> containing the copied texture on success. Dispose after use.</returns>
|
||||
/// <remarks><para>This function may throw an exception.</para></remarks>
|
||||
Task<IDalamudTextureWrap> CreateFromGameScreen(
|
||||
bool autoUpdate = false,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>Creates a texture from the game screen, before rendering Dalamud.</summary>
|
||||
/// <param name="viewportId">The viewport ID.</param>
|
||||
/// <param name="autoUpdate">If <c>true</c>, automatically update the underlying texture.</param>
|
||||
/// <summary>Creates a texture from an ImGui viewport.</summary>
|
||||
/// <param name="args">The arguments for creating a texture.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> containing the copied texture on success. Dispose after use.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Use <c>ImGui.GetMainViewport().ID</c> to capture the game screen with Dalamud rendered.</para>
|
||||
/// <para>This function may throw an exception.</para>
|
||||
/// </remarks>
|
||||
Task<IDalamudTextureWrap> CreateFromImGuiViewport(
|
||||
uint viewportId,
|
||||
bool autoUpdate = false,
|
||||
Task<IDalamudTextureWrap> CreateFromImGuiViewportAsync(
|
||||
ImGuiViewportTextureArgs args,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>Gets a texture from the given bytes, trying to interpret it as a .tex file or other well-known image
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue