#nullable enable
using System.Diagnostics;
using ImGuiNET;
using SharpDX.DXGI;
using T3.Core.DataTypes;
using T3.Core.Resource;
using T3.Editor.Gui.Interaction;
using T3.Editor.Gui.OutputUi;
using T3.Editor.Gui.Styling;
using T3.Editor.Gui.UiHelpers;
using T3.SystemUi;
namespace T3.Editor.Gui.Windows;
internal sealed class ImageOutputCanvas : ScalableCanvas
{
public void Update(T3Ui.EditingFlags editingFlags = T3Ui.EditingFlags.None)
{
UpdateCanvas(out var interactionState, editingFlags);
UpdateViewMode(interactionState);
}
public void SetAsCurrent()
{
Current = this;
}
public static void Deactivate()
{
Current = null;
}
///
/// The image canvas that is currently being drawn from the UI.
/// Note that is NOT a singleton so you can't rely on this to be valid outside of the Draw()ing context.
/// It is used by to draw its content.
///
public static ImageOutputCanvas? Current;
protected override ScalableCanvas? Parent => null;
public Texture2D? LastTexture;
public void DrawTexture(Texture2D? texture)
{
CustomComponents.FillWithStripes(ImGui.GetWindowDrawList(), DrawUtils.GetContentRegionArea(), Scale.X);
LastTexture = texture;
Debug.Assert(Current != null);
if (texture == null || texture.IsDisposed)
return;
var size = new Vector2(texture.Description.Width, texture.Description.Height);
var area = new ImRect(0, 0, size.X, size.Y);
if (_viewMode == Modes.Fitted)
{
Current.FitAreaOnCanvas(area);
if (DisableDamping)
{
Scale = ScaleTarget;
}
}
var topLeft = Vector2.Zero;
var topLeftOnScreen = Current.TransformPosition(topLeft);
ImGui.SetCursorScreenPos(topLeftOnScreen);
var sizeOnScreen = Current.TransformDirection(size);
var srv = SrvManager.GetSrvForTexture(texture);
ImGui.Image((IntPtr)srv, sizeOnScreen);
if (ImGui.IsMouseHoveringRect(topLeftOnScreen, topLeftOnScreen + sizeOnScreen))
{
var relativePosition = (ImGui.GetMousePos() - topLeftOnScreen) / sizeOnScreen;
MouseInput.Set(relativePosition, ImGui.IsMouseDown(ImGuiMouseButton.Left));
}
if (UserSettings.Config.ShowToolbar)
{
string format;
if (srv == null || srv.IsDisposed)
{
format = "null?";
}
else if (UserSettings.Config.ShowExplicitTextureFormatInOutputWindow)
{
format = srv.Description.Format.ToString();
}
else
{
switch (srv.Description.Format)
{
case Format.R16G16B16A16_Float:
format = "RGBA:16";
break;
case Format.R8G8B8A8_SNorm:
format = "RGBA:8";
break;
default:
format = srv.Description.Format.ToString();
break;
}
}
ImGui.PushFont(Fonts.FontSmall);
var zoom = Math.Abs(Scale.X) < 0.001f ? "" : $" ×{Scale.X:G2}";
var description = $"{size.X}x{size.Y} {format} {zoom}";
var descriptionWidth = ImGui.CalcTextSize(description).X;
var textPos = new Vector2(WindowPos.X + (WindowSize.X - descriptionWidth) / 2,
WindowPos.Y + WindowSize.Y - 14 * T3Ui.UiScaleFactor);
var drawList = ImGui.GetWindowDrawList();
var shadowColor = UiColors.BackgroundFull.Fade(0.5f);
drawList.AddText(textPos + new Vector2(1,0), shadowColor, description );
drawList.AddText(textPos + new Vector2(-1,0), shadowColor, description );
drawList.AddText(textPos + new Vector2(0,1), shadowColor, description );
drawList.AddText(textPos + new Vector2(0,-1), shadowColor, description );
drawList.AddText(textPos, UiColors.ForegroundFull, description );
ImGui.PopFont();
}
}
//private static readonly Color ShadowColor = new Color(0.0f, 0.0f, 0.0f, 0.6f);
public void SetViewMode(Modes newMode)
{
_viewMode = newMode;
switch (newMode)
{
case Modes.Pixel:
SetScaleToMatchPixels();
// UserZoomedView = false;
break;
case Modes.Fitted:
// UserZoomedView = false;
// UserPannedView = false;
break;
}
}
///
/// Updated the view mode if user interacted
///
private void UpdateViewMode(InteractionState interactionState)
{
// UserZoomedView |= interactionState.UserZoomedCanvas;
// UserPannedView |= interactionState.UserPannedCanvas;
switch (_viewMode)
{
case Modes.Fitted:
if (interactionState.UserPannedCanvas || interactionState.UserZoomedCanvas)
{
_viewMode = Modes.Custom;
}
break;
case Modes.Pixel:
if (interactionState.UserZoomedCanvas)
_viewMode = Modes.Custom;
break;
}
}
public enum Modes
{
Fitted,
Pixel,
Custom,
}
public Modes ViewMode => _viewMode;
private Modes _viewMode = Modes.Fitted;
public bool DisableDamping = false;
// public bool UserPannedView;
// public bool UserZoomedView;
}