#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; }