127 lines
5.5 KiB
C#
127 lines
5.5 KiB
C#
#nullable enable
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Runtime.InteropServices;
|
||
using ImGuiNET;
|
||
using SilkWindows;
|
||
using T3.Core.Resource;
|
||
using T3.Editor.App;
|
||
using T3.Editor.Gui;
|
||
using T3.Editor.Gui.Styling;
|
||
using T3.Editor.Gui.UiHelpers;
|
||
|
||
namespace T3.Editor.UiContentDrawing;
|
||
|
||
internal static class UiContentUpdate
|
||
{
|
||
public static void SetupResourcesAndFontsWithScaling()
|
||
{
|
||
if (_hasSetScaling && Math.Abs(UserSettings.Config.UiScaleFactor - _lastUiScale) <= 0.005f)
|
||
return;
|
||
|
||
Log.Debug("Setup editor resources...");
|
||
// Prevent scale factor from being "actually" 0.0
|
||
if (UserSettings.Config.UiScaleFactor < 0.1f)
|
||
UserSettings.Config.UiScaleFactor = 0.1f;
|
||
|
||
// Update font atlas texture if UI-Scale changed
|
||
GenerateFontsWithScaleFactor(UserSettings.Config.UiScaleFactor);
|
||
|
||
Program.UiContentContentDrawer?.CreateDeviceObjectsAndFonts();
|
||
|
||
_lastUiScale = UserSettings.Config.UiScaleFactor;
|
||
_hasSetScaling = true;
|
||
}
|
||
|
||
private static void GenerateFontsWithScaleFactor(float scaleFactor)
|
||
{
|
||
// See https://stackoverflow.com/a/5977638
|
||
var displayScaleFactor = ProgramWindows.Main.GetDpi().X / 96f;
|
||
var dpiAwareScale = scaleFactor * displayScaleFactor;
|
||
|
||
T3Ui.UiScaleFactor = dpiAwareScale;
|
||
|
||
var fontAtlasPtr = ImGui.GetIO().Fonts;
|
||
fontAtlasPtr.Clear();
|
||
const string fontName = "Inter";
|
||
var rootFilePath = Path.Combine(SharedResources.EditorResourcesDirectory, SharedResources.EditorResourcesDirectory, "fonts", fontName + '-');
|
||
|
||
const string fileExtension = ".ttf";
|
||
var format = $"{rootFilePath}{{0}}{fileExtension}";
|
||
|
||
var normalFont = new TtfFont(string.Format(format, "Regular"), 18f * dpiAwareScale);
|
||
var boldFont = new TtfFont(string.Format(format, "SemiBold"), 18f * dpiAwareScale);
|
||
var smallFont = new TtfFont(string.Format(format, "Regular"), 14f * dpiAwareScale);
|
||
var largeFont = new TtfFont(string.Format(format, "Light"), 30f * dpiAwareScale);
|
||
|
||
var ranges = GetExtendedGlyphRanges();
|
||
Fonts.FontNormal = fontAtlasPtr.AddFontFromFileTTF(normalFont.Path, normalFont.PixelSize, default, ranges);
|
||
Fonts.FontBold = fontAtlasPtr.AddFontFromFileTTF(boldFont.Path, boldFont.PixelSize, default, ranges);
|
||
Fonts.FontSmall = fontAtlasPtr.AddFontFromFileTTF(smallFont.Path, smallFont.PixelSize, default, ranges);
|
||
Fonts.FontLarge = fontAtlasPtr.AddFontFromFileTTF(largeFont.Path, largeFont.PixelSize, default, ranges);
|
||
|
||
var codeFontPath = Path.Combine(SharedResources.EditorResourcesDirectory, SharedResources.EditorResourcesDirectory,"fonts", "JetBrainsMono-Regular.ttf");
|
||
var codeFont = new TtfFont(codeFontPath, 18f * dpiAwareScale);
|
||
Fonts.Code = fontAtlasPtr.AddFontFromFileTTF(codeFont.Path, codeFont.PixelSize, default, ranges);
|
||
|
||
ImGuiWindowService.Instance.SetFonts(new FontPack(normalFont, boldFont, smallFont, largeFont));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Extended glyph ranges for the editor's TTF fonts. Default ImGui only
|
||
/// rasterizes 0x0020-0x00FF (basic Latin); we additionally pull in common
|
||
/// punctuation used by the markdown renderer (bullet •, dashes – —, smart
|
||
/// quotes ' ' " ", ellipsis …), arrows (→ ← ↑ ↓), miscellaneous symbols
|
||
/// (warning ⚠, gear ⚙), and dingbats (check ✓, cross ✗).
|
||
///
|
||
/// The returned pointer references a static, GC-pinned array — ImGui only
|
||
/// reads from it during atlas Build(), so the pin can live for the
|
||
/// process lifetime.
|
||
/// </summary>
|
||
private static IntPtr GetExtendedGlyphRanges()
|
||
{
|
||
if (_glyphRangesPtr != IntPtr.Zero)
|
||
return _glyphRangesPtr;
|
||
|
||
// Pairs of (first, last), terminated with 0.
|
||
_extendedGlyphRanges = new ushort[]
|
||
{
|
||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||
0x2010, 0x205E, // General punctuation
|
||
0x2190, // ←
|
||
0x21FF, // ⇿
|
||
0x2192, // → Right arrow
|
||
0x2600, 0x26FF, // Miscellaneous symbols (⚠ ⚙ ☆ …)
|
||
0x2700, 0x27BF, // Dingbats (✓ ✗ ✱ …)
|
||
0,
|
||
};
|
||
_glyphRangesHandle = GCHandle.Alloc(_extendedGlyphRanges, GCHandleType.Pinned);
|
||
_glyphRangesPtr = _glyphRangesHandle.AddrOfPinnedObject();
|
||
return _glyphRangesPtr;
|
||
}
|
||
|
||
private static ushort[]? _extendedGlyphRanges;
|
||
private static GCHandle _glyphRangesHandle;
|
||
private static IntPtr _glyphRangesPtr;
|
||
|
||
private static long _lastElapsedTicks;
|
||
private static readonly Stopwatch _stopwatch = new();
|
||
|
||
private static float _lastUiScale = 1;
|
||
|
||
private static bool _hasSetScaling;
|
||
|
||
public static void StartMeasureFrame()
|
||
{
|
||
_stopwatch.Start();
|
||
_lastElapsedTicks = _stopwatch.ElapsedTicks;
|
||
}
|
||
|
||
public static void TakeMeasurement()
|
||
{
|
||
Int64 ticks = _stopwatch.ElapsedTicks;
|
||
Int64 ticksDiff = ticks - _lastElapsedTicks;
|
||
_lastElapsedTicks = ticks;
|
||
ImGui.GetIO().DeltaTime = (float)((double)(ticksDiff) / Stopwatch.Frequency);
|
||
}
|
||
} |