项目文件夹

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

171 行
5.7 KiB
C#

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
using ImGuiNET;
using T3.Core.DataTypes.Vector;
using T3.Core.Utils;
using T3.Editor.Gui.Styling;
namespace T3.Editor.Gui.Interaction;
/// <summary>
/// Draws a range of virtual slider overlays
/// </summary>
internal static class SliderLadder
{
private sealed class RangeDef
{
// public readonly float YMin;
// public readonly float YMax;
public readonly float ScaleFactor;
public readonly string Label;
public RangeDef(float scaleFactor, string label)
{
ScaleFactor = scaleFactor;
Label = label;
}
}
private static readonly RangeDef[] Ranges =
{
new(1000, "1000"),
new(100, "100"),
new(10, "10"),
new(1, "1"),
new(0.1f, "0.1"),
new(0.01f, "0.01"),
new(0.001f, "0.001"),
};
private static RangeDef _lockedRange;
private const float LockDistance = 100;
public static void Draw(ref double editValue, double min, double max, float scale, float timeSinceVisible, bool clampMin, bool clampMax, Vector2 center)
{
var io = ImGui.GetIO();
var foreground = ImGui.GetForegroundDrawList();
const double initialDelay = 0.2;
var pNow = io.MousePos - center;
if (timeSinceVisible < initialDelay)
{
_lockedRange = null;
_hasExceededDragThreshold = false;
_lastX = 0f;
}
var x = MathF.Floor(pNow.X / PixelsPerStep);
_hasExceededDragThreshold |= MathF.Abs(pNow.X) > PixelsPerStep * 4;
var dx = x - _lastX;
var activeScaleFactor = 0.0;
var usingCenterRange = false;
// Find center range index
int centerRangeIndex;
for (centerRangeIndex = 0; centerRangeIndex < Ranges.Length; centerRangeIndex++)
{
var range = Ranges[centerRangeIndex];
if (range.ScaleFactor < scale * 1.5f)
break;
}
for (var rangeIndex = 0; rangeIndex < Ranges.Length; rangeIndex++)
{
var yMin = OuterRangeHeight * (rangeIndex - centerRangeIndex-1 + 0.5f);
var yMax = OuterRangeHeight * (rangeIndex - centerRangeIndex + 0.5f);
var range = Ranges[rangeIndex];
var isVerticalMatch = pNow.Y > yMin && pNow.Y < yMax;
var isWithinLockRange = Math.Abs(pNow.X) < LockDistance;
var isActiveRange = isVerticalMatch && isWithinLockRange
|| _lockedRange == null && isVerticalMatch
|| _lockedRange == range;
if (isActiveRange)
{
activeScaleFactor = range.ScaleFactor;
_lockedRange = isWithinLockRange ? null : range;
}
var isCenterRange = rangeIndex == centerRangeIndex;
if (isCenterRange)
{
usingCenterRange = isActiveRange;
continue;
}
// Draw
var isLookedRange = _lockedRange == range;
var centerColor = !isActiveRange
? _rangeFillColor
: isLookedRange
? _lockedRangeFillColor
: _activeRangeFillColor;
var bMin = new Vector2(-RangeWidth, yMin) + center;
var bMax = new Vector2(RangeWidth, yMax) + center;
foreground.AddRectFilled(bMin, bMax, centerColor);
foreground.AddRect(bMin, bMax, UiColors.BackgroundFull);
var labelSize = ImGui.CalcTextSize(range.Label);
var pText = (bMin + bMax) / 2 - labelSize / 2;
foreground.AddText(pText,
isActiveRange ? UiColors.BackgroundFull : UiColors.ForegroundFull,
range.Label);
}
if (Math.Abs(dx) < 0.0001f)
return;
if (_hasExceededDragThreshold)
{
var delta = dx;
if (io.KeyAlt)
{
ImGui.PushFont(Fonts.FontSmall);
foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "×0.01");
ImGui.PopFont();
scale *= 0.01f;
}
else if (io.KeyShift)
{
ImGui.PushFont(Fonts.FontSmall);
foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "×10");
ImGui.PopFont();
scale *= 10f;
}
var scaling = (usingCenterRange)
? scale
: activeScaleFactor;
editValue += delta * scaling;
if (activeScaleFactor != 0 && (!usingCenterRange && ImGui.GetIO().KeyCtrl))
{
editValue = Math.Round(editValue / (activeScaleFactor)) * (activeScaleFactor);
}
editValue = MathUtils.OptionalClamp(editValue, min, clampMin, max, clampMax);
}
_lastX = x;
}
private const float PixelsPerStep = 10;
private const float RangeWidth = 40;
private const float OuterRangeHeight = 50;
private static readonly Color _rangeFillColor = new(0.3f, 0.3f, 0.3f);
private static readonly Color _activeRangeFillColor = new(0.8f, 0.8f, 0.8f);
private static readonly Color _lockedRangeFillColor = new(1f, 0.6f, 0.6f);
private static bool _hasExceededDragThreshold;
private static float _lastX;
}