Screenie/Ui/Viewer.cs

109 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) {
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 sizeToUse = imageSize;
if (constrainedX || constrainedY) {
// var dividend = imageSize / avail;
// var inv = Vector2.One / dividend;
// scale the image based on the more-constrained dimension
// var ratio = dividend.X > dividend.Y
// ? inv.X // X is more constrained
// : inv.Y; // Y is more constrained
var dividend = avail / imageSize;
// scale the image based on the more-constrained dimension
var 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);
}
return DrawStatus.Continuing;
}
}