Screenie/Ui/Viewer.cs

117 lines
3.5 KiB
C#

using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility;
using ImGuiNET;
using Screenie.Util;
namespace Screenie.Ui;
internal class Viewer : IDrawable {
private Plugin Plugin { get; }
private Guid Id { get; } = Guid.NewGuid();
private IDalamudTextureWrap? Image { get; set; }
private Exception? Error { get; set; }
private bool _disposed;
private bool _visible = true;
internal string ImagePath { get; }
internal Vector2? DotPosition { get; set; }
internal Viewer(Plugin plugin, string path) {
this.Plugin = plugin;
this.ImagePath = path;
Task.Factory.StartNew(async () => {
try {
var bytes = await File.ReadAllBytesAsync(this.ImagePath);
this.Image = await ImageHelper.LoadImageAsync(this.Plugin.Interface.UiBuilder, bytes);
} catch (Exception ex) {
this.Error = ex;
Plugin.Log.Warning(ex, $"Failed to load image at {this.ImagePath}");
}
});
}
public void Dispose() {
if (this._disposed) {
return;
}
this._disposed = true;
// if (this.Image != null) {
// this.Plugin.Framework.RunOnTick(this.Image.Dispose);
// }
this.Image?.Dispose();
}
public DrawStatus Draw()
{
if (!this._visible)
{
return DrawStatus.Finished;
}
ImGui.PushID($"viewer-{this.ImagePath}-{this.Id}");
using var popId = new OnDispose(ImGui.PopID);
using var end = new OnDispose(ImGui.End);
if (!ImGui.Begin($"View {Path.GetFileName(this.ImagePath)}", ref this._visible, ImGuiWindowFlags.NoSavedSettings))
{
return DrawStatus.Continuing;
}
var viewport = ImGui.GetWindowViewport();
var viewportSize = viewport.Size;
ImGui.SetWindowSize(viewportSize * new Vector2(0.20f), ImGuiCond.Appearing);
if (this.Error != null)
{
ImGuiHelpers.CenteredText("An error ocurred loading the image.");
ImGui.PushFont(UiBuilder.MonoFont);
using var popFont = new OnDispose(ImGui.PopFont);
ImGui.TextUnformatted(this.Error.Message);
}
if (this.Image == null) {
return DrawStatus.Continuing;
}
var beforeImage = ImGui.GetCursorScreenPos();
var avail = ImGui.GetContentRegionAvail();
var imageSize = this.Image.Size;
var constrainedX = avail.X < imageSize.X;
var constrainedY = avail.Y < imageSize.Y;
var ratio = 1f;
var sizeToUse = imageSize;
if (constrainedX || constrainedY) {
var dividend = avail / imageSize;
// scale the image based on the more-constrained dimension
ratio = dividend.Y > dividend.X
? dividend.X // X is more constrained
: dividend.Y; // Y is more constrained
sizeToUse = new Vector2(
imageSize.X * ratio,
imageSize.Y * ratio
);
}
ImGui.Image(this.Image.ImGuiHandle, sizeToUse);
if (this.DotPosition is { } pos) {
var scaledPos = pos * ratio;
var posCoord = beforeImage + scaledPos;
ImGui.GetWindowDrawList().AddCircleFilled(posCoord, 6 * ImGuiHelpers.GlobalScale, 0xFF000000);
ImGui.GetWindowDrawList().AddCircleFilled(posCoord, 4 * ImGuiHelpers.GlobalScale, 0xFFFFFFFF);
}
return DrawStatus.Continuing;
}
}