项目文件夹

文件
2026-07-13 13:13:17 +08:00

335 行
17 KiB
C#

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
using ImGuiNET;
using T3.Core.Animation;
using T3.Core.Utils;
using T3.Editor.Gui.Styling;
using T3.SystemUi;
namespace T3.Editor.Gui.UiHelpers;
public static class KeyboardAndMouseOverlay
{
public static void Draw()
{
if (!UserSettings.Config.ShowInteractionOverlay)
{
return;
}
_widgetFade = 1-(float)((Playback.RunTimeInSecs - _lastInteractionTime) / FadeoutDuration).Clamp(0, 1);
var dl = ImGui.GetForegroundDrawList();
var pos = ImGui.GetMousePos() + new Vector2(30, -100) * T3Ui.UiScaleFactor;
if(pos.X + 120 > ImGui.GetIO().DisplaySize.X)
pos.X = ImGui.GetIO().DisplaySize.X - 120;
if (pos.Y + 90 > ImGui.GetIO().DisplaySize.Y)
{
var dy = 90 + pos.Y - ImGui.GetIO().DisplaySize.Y;
pos.Y -= dy;
pos.X += dy/2;
}
var panelSize = new Vector2(120, 90) * T3Ui.UiScaleFactor;
dl.AddRectFilled(pos, pos + panelSize, UiColors.BackgroundFull.Fade(0.7f * _widgetFade), 10);
UpdatePressedKeys();
DrawKeys(pos, dl);
var radius = 20f * T3Ui.UiScaleFactor;
var thickness = 26f * T3Ui.UiScaleFactor;
var center = pos + new Vector2(panelSize.X / 2, 65 * T3Ui.UiScaleFactor);
var spacing = 2f * T3Ui.UiScaleFactor;
var halfspace = spacing * 0.5f;
const float radspace = 22f;
const int segments = 12;
if (ImGui.IsMouseDown(ImGuiMouseButton.Left)
|| ImGui.IsMouseDown(ImGuiMouseButton.Middle)
|| ImGui.IsMouseDown(ImGuiMouseButton.Right))
{
_lastInteractionTime = Playback.RunTimeInSecs;
}
// Left mouse
{
var color = ImGui.IsMouseDown(ImGuiMouseButton.Left) ? UiColors.ForegroundFull.Fade(_widgetFade) : UiColors.ForegroundFull.Fade(0.1f * _widgetFade);
dl.PathClear();
dl.PathLineTo(center + new Vector2(-halfspace, -radius));
dl.PathArcTo(center - new Vector2(spacing, 0), radius, -MathF.PI / 2, -MathF.PI, segments);
dl.PathLineTo(center + new Vector2(-radspace, 15) * T3Ui.UiScaleFactor);
dl.PathStroke(color, ImDrawFlags.None, thickness);
// Check for double click
if (ImGui.IsMouseDoubleClicked(ImGuiMouseButton.Left))
{
_lastDoubleClickTime = Playback.RunTimeInSecs;
}
else if (ImGui.IsMouseClicked(ImGuiMouseButton.Left) && _lastDoubleClickTime >= 0)
{
_lastDoubleClickTime = 0;
}
}
DrawDoubleClickIndicator(center + new Vector2(-radspace - 12, -11) * T3Ui.UiScaleFactor, dl);
// right mouse
{
var color = ImGui.IsMouseDown(ImGuiMouseButton.Right) ? UiColors.ForegroundFull.Fade(_widgetFade) : UiColors.ForegroundFull.Fade(0.1f * _widgetFade);
dl.PathClear();
dl.PathLineTo(center + new Vector2(halfspace, -radius));
dl.PathArcTo(center + new Vector2(spacing, 0), radius, -MathF.PI / 2, 0, segments);
dl.PathLineTo(center + new Vector2(radspace, 15) * T3Ui.UiScaleFactor);
dl.PathStroke(color, ImDrawFlags.None, thickness);
}
// middle mouse
{
var color = ImGui.IsMouseDown(ImGuiMouseButton.Middle) ? UiColors.ForegroundFull.Fade(_widgetFade) : UiColors.ForegroundFull.Fade(0.1f * _widgetFade);
var size = new Vector2(14, 24) * T3Ui.UiScaleFactor;
var min = center - size * 0.5f + new Vector2(0, 7) * T3Ui.UiScaleFactor;
dl.AddRectFilled(min, min + size, color, 4 * T3Ui.UiScaleFactor);
}
// mouse wheel
{
var fadeFromTime = 1-(float)((Playback.RunTimeInSecs - _lastMouseWheelInteractionTime) / FadeoutDuration).Clamp(0, 1);
var mouseDelta = ImGui.GetIO().MouseWheel;
if (mouseDelta != 0)
{
_lastMouseWheelInteractionTime = Playback.RunTimeInSecs;
_lastInteractionTime = Playback.RunTimeInSecs;
_wheelSpin -= mouseDelta;
}
_dampedWheelSpin = DampFunctions.DampenFloat(_wheelSpin, _dampedWheelSpin, 0.001f, ref _dampedWheelSpinVelocity, DampFunctions.Methods.DampedSpring);
if (double.IsInfinity(_dampedWheelSpin) || double.IsNaN(_dampedWheelSpin))
{
_dampedWheelSpin = 0;
}
const int lineCount = 5;
var height = 34 * T3Ui.UiScaleFactor;
var size = new Vector2(12, 1) * T3Ui.UiScaleFactor;
var min = center - size * 0.5f + new Vector2(0, -10) * T3Ui.UiScaleFactor;
float step = height / (lineCount + 1);
for (int i = 0; i < lineCount; i++)
{
var f = (float)i / lineCount;
var fadeEdge =1- MathF.Abs((f - 0.5f) * 2).Clamp(0, 1);
var offset = new Vector2(0, step * i + step * MathUtils.Fmod(_dampedWheelSpin + 0.5f, 1));
var color = UiColors.ForegroundFull.Fade(fadeFromTime * fadeEdge);
dl.AddRectFilled(min + offset, min + size + offset, color, 10);
}
}
}
private static void DrawKeys(Vector2 pos, ImDrawListPtr dl)
{
var keyPos = pos + new Vector2(4, 4);
foreach (var k in _previousKeys)
{
var label = k.Label;
var labelSize = ImGui.CalcTextSize(label);
var rectMin = keyPos;
var size = labelSize + new Vector2(8, 2);
var fade = MathF.Pow((1 - k.FadeProgress).Clamp(0f, 1f), 4);
dl.AddRectFilled(rectMin,
rectMin + size,
UiColors.ForegroundFull.Fade(fade * _widgetFade),
3);
dl.AddText(rectMin + new Vector2(4, 0), UiColors.BackgroundFull.Fade(_widgetFade), label);
keyPos.X += (size.X + 3);
}
}
private static void UpdatePressedKeys()
{
var time = Playback.RunTimeInSecs;
for (var index = 0; index < KeyHandler.PressedKeys.Count; index++)
{
var pressed = KeyHandler.PressedKeys[index];
var status = _keyStates[index];
if (status == null)
continue;
if (pressed != status.IsPressed)
{
if (pressed)
{
_previousKeys.Remove(status);
_previousKeys.Add(status);
}
status.IsPressed = pressed;
}
if (pressed)
{
status.ReleaseTime = time;
_lastInteractionTime = time;
}
else
{
if(status.FadeProgress > 1 )
_previousKeys.Remove(status);
}
}
}
private static void DrawDoubleClickIndicator(Vector2 position, ImDrawListPtr dl)
{
var timeSince = (float)(Playback.RunTimeInSecs - _lastDoubleClickTime);
if (timeSince > FadeoutDuration)
return;
var textColor = UiColors.ForegroundFull.Fade(_widgetFade);
dl.AddText(Fonts.FontLarge, Fonts.FontLarge.FontSize, position, textColor, "×2");
}
private static readonly List<KeyStatus> _previousKeys = new();
private static double _lastInteractionTime = double.NegativeInfinity;
private static float _widgetFade = 0;
private static double _lastMouseWheelInteractionTime;
private static double _lastDoubleClickTime = double.NegativeInfinity;
private sealed class KeyStatus
{
public KeyStatus(int keyIndex, string label, Icon icon = Icon.None )
{
if (keyIndex >= KeyLookupCount)
return;
Icon = icon;
Label = label;
_keyStates[keyIndex] = this;
}
public float FadeProgress
{
get
{
var timeSinceRelease = (float)(Playback.RunTimeInSecs - ReleaseTime);
return timeSinceRelease / FadeoutDuration;
}
}
public bool IsPressed;
public readonly string Label;
public Icon Icon;
public double ReleaseTime = double.NegativeInfinity;
}
private const float FadeoutDuration = 2;
private const int KeyLookupCount = 512;
private static float _wheelSpin;
private static float _dampedWheelSpin;
private static float _dampedWheelSpinVelocity;
private static readonly KeyStatus[] _keyStates = new KeyStatus[KeyLookupCount];
// ReSharper disable once UnusedMember.Local
private static readonly KeyStatus[] _keyDefinitions = {
new(8, "Backspace"),
new(9, "Tab"),
new(13, "Return"),
new(16, "Shift"),
new(17, "Ctrl"),
new(18, "Alt"),
new(20, "Caps"),
new(27, "Esc"),
new(32, "Space"),
new(33, "PageUp"),
new(34, "PageDown"),
new(35, "End"),
new(36, "Home"),
new(37, "Left", Icon.ChevronLeft),
new(38, "Up", Icon.ChevronUp),
new(39, "Right", Icon.ChevronRight),
new(40, "Down", Icon.ChevronDown),
new(45, "Ins"),
new(46, "Del"),
new(48, "0"),
new(49, "1"),
new(50, "2"),
new(51, "3"),
new(52, "4"),
new(53, "5"),
new(54, "6"),
new(55, "7"),
new(56, "8"),
new(57, "9"),
new(65, "A"),
new(66, "B"),
new(67, "C"),
new(68, "D"),
new(69, "E"),
new(70, "F"),
new(71, "G"),
new(72, "H"),
new(73, "I"),
new(74, "J"),
new(75, "K"),
new(76, "L"),
new(77, "M"),
new(78, "N"),
new(79, "O"),
new(80, "P"),
new(81, "Q"),
new(82, "R"),
new(83, "S"),
new(84, "T"),
new(85, "U"),
new(86, "V"),
new(87, "W"),
new(88, "X"),
new(89, "Y"),
new(90, "Z"),
new(112, "F1"),
new(113, "F2"),
new(114, "F3"),
new(115, "F4"),
new(116, "F5"),
new(117, "F6"),
new(118, "F7"),
new(119, "F8"),
new(120, "F9"),
new(121, "F10"),
new(122, "F11"),
new(123, "F12"),
new(124, "F13"),
new(125, "F14"),
new(126, "F15"),
new(127, "F16"),
new(128, "F17"),
new(129, "F18"),
new(130, "F19"),
new(131, "F20"),
new(132, "F21"),
new(133, "F22"),
new(134, "F23"),
new(135, "F24"),
new(187, "+"),
new(187, "="),
new(189, "-"),
new(219, "["),
new(221, "]"),
new(188, ","),
new(190, "."),
new(191, "/"),
new(192, "|"),
new(186, ";"),
new(226, "`"),
new(220, "#"),
};
}