Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Controls/MySlider.xaml.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

298 lines
10 KiB
C#

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using PCL.Core.App.Localization;
namespace PCL;
public partial class MySlider
{
public delegate void ChangeEventHandler(object sender, bool user);
public delegate void PreviewChangeEventHandler(object sender, ModBase.RouteEventArgs e);
// 自定义属性
private int _Value;
private bool changeByKey;
// 拖动
public Delegate getHintText;
// 基础
public int Uuid = ModBase.GetUuid();
public MySlider()
{
InitializeComponent();
SizeChanged += RefreshWidth;
MouseLeftButtonDown += DragStart;
IsEnabledChanged += (_, _) => RefreshColor();
MouseEnter += (_, _) => RefreshColor();
MouseLeave += (_, _) => RefreshColor();
MouseEnter += (_, _) => MySlider_MouseEnter();
KeyDown += MySlider_KeyDown;
}
public int MaxValue
{
get => field;
set
{
if (value == field)
return;
field = value;
RefreshWidth(null, null);
}
} = 100;
public int Value
{
get => _Value;
set
{
try
{
value = (int)Math.Round(ModBase.MathClamp(value, 0d, MaxValue));
if (_Value == value)
return;
// 触发 Preview 事件,修改新值
var oldValue = _Value;
_Value = value;
if (ModAnimation.AniControlEnabled == 0)
{
var e = new ModBase.RouteEventArgs();
PreviewChange?.Invoke(this, e);
if (e.handled)
{
_Value = oldValue;
DragStop();
return;
}
}
if (IsLoaded && ModAnimation.AniControlEnabled == 0)
{
if (ActualWidth < ShapeDot.Width)
return;
var newWidth = _Value / (double)MaxValue * (ActualWidth - ShapeDot.Width);
var deltaProcess =
Math.Abs(LineFore.Width / (ActualWidth - ShapeDot.Width) - _Value / (double)MaxValue);
var time = (1d - Math.Pow(1d - deltaProcess, 3d)) * 300d + (changeByKey ? 100 : 0);
ModAnimation.AniStart(
new[]
{
ModAnimation.AaWidth(LineFore,
Math.Max(0d, newWidth + (newWidth < 0.5d ? 0d : 0.5d)) - LineFore.Width,
(int)Math.Round(time),
ease: time > 50d
? new ModAnimation.AniEaseOutFluent()
: new ModAnimation.AniEaseLinear()),
ModAnimation.AaWidth(LineBack,
Math.Max(0d,
ActualWidth - ShapeDot.Width - newWidth +
(ActualWidth - ShapeDot.Width - newWidth < 0.5d ? 0d : 0.5d)) - LineBack.Width,
(int)Math.Round(time),
ease: time > 50d
? new ModAnimation.AniEaseOutFluent()
: new ModAnimation.AniEaseLinear()),
ModAnimation.AaX(ShapeDot, newWidth - ShapeDot.Margin.Left, (int)Math.Round(time),
ease: time > 50d
? new ModAnimation.AniEaseOutFluent()
: new ModAnimation.AniEaseLinear())
}, "MySlider Progress " + Uuid);
}
else
{
RefreshWidth(null, null);
}
if (ModAnimation.AniControlEnabled == 0)
Change?.Invoke(this, false);
}
catch (Exception ex)
{
ModBase.Log(
ex,
"滑动条进度改变出错",
ModBase.LogLevel.Hint,
userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
}
}
}
// 按键改变
public uint ValueByKey { get; set; } = 1U;
public event ChangeEventHandler? Change;
public event PreviewChangeEventHandler? PreviewChange;
private void RefreshWidth(object sender, SizeChangedEventArgs? e)
{
if (e is not null)
PanMain.Width = e.NewSize.Width;
ModAnimation.AniStop("MySlider Progress " + Uuid);
var newWidth = _Value / (double)MaxValue * (ActualWidth - ShapeDot.Width);
LineFore.Width = Math.Max(0d, newWidth + (newWidth < 0.5d ? 0d : 0.5d));
LineBack.Width = Math.Max(0d,
ActualWidth - ShapeDot.Width - newWidth + (ActualWidth - ShapeDot.Width - newWidth < 0.5d ? 0d : 0.5d));
ModBase.SetLeft(ShapeDot, newWidth);
}
private void DragStart(object sender, MouseButtonEventArgs e)
{
CaptureMouse();
MouseMove += OnDragMouseMove;
e.Handled = true; // 防止 ScrollViewer 失焦问题
ModMain.dragControl = this;
RefreshColor();
ModMain.frmMain.DragDoing();
ModAnimation.AniStart(
ModAnimation.AaScaleTransform(ShapeDot, 1.3d - ((ScaleTransform)ShapeDot.RenderTransform).ScaleX, 40,
ease: new ModAnimation.AniEaseOutFluent()), "MySlider Scale " + Uuid);
RefreshPopup();
ModAnimation.AniStop("MySlider KeyPopup " + Uuid);
}
public void DragDoing()
{
var percent =
ModBase.MathClamp((Mouse.GetPosition(PanMain).X - ShapeDot.Width / 2d) / (ActualWidth - ShapeDot.Width), 0d,
1d);
var newValue = (int)Math.Round(percent * MaxValue);
if (newValue != Value) Value = newValue;
RefreshPopup();
}
private void OnDragMouseMove(object sender, MouseEventArgs e)
{
DragDoing();
}
public void DragStop()
{
MouseMove -= OnDragMouseMove;
if (IsMouseCaptured) ReleaseMouseCapture();
RefreshColor();
ModAnimation.AniStart(
ModAnimation.AaScaleTransform(ShapeDot, 1d - ((ScaleTransform)ShapeDot.RenderTransform).ScaleX, 200,
ease: new ModAnimation.AniEaseOutFluent()), "MySlider Scale " + Uuid);
Popup.IsOpen = false;
}
public void RefreshPopup()
{
if (getHintText is null)
return;
Popup.IsOpen = true;
TextHint.Text = getHintText.DynamicInvoke(Value)?.ToString() ?? "";
var typeface = new Typeface(TextHint.FontFamily, TextHint.FontStyle, TextHint.FontWeight, TextHint.FontStretch);
var formattedText = new FormattedText(TextHint.Text, Thread.CurrentThread.CurrentCulture,
TextHint.FlowDirection, typeface, TextHint.FontSize, TextHint.Foreground, ModBase.dpi);
TextHint.Width = formattedText.Width; // 使用手动测量的宽度修复 #1057
}
// 指向动画
private void RefreshColor()
{
try
{
// 判断当前颜色
string foregroundName;
string dotFillName;
int animationTime;
if (IsEnabled)
{
if (ModMain.dragControl is not null && ModMain.dragControl.Equals(this) || IsMouseOver)
{
foregroundName = "ColorBrush3";
dotFillName = "ColorBrush3";
animationTime = 40;
}
else
{
foregroundName = "ColorBrushBg0";
dotFillName = "ColorBrushBg0";
animationTime = 100;
}
}
else
{
foregroundName = "ColorBrushGray5";
dotFillName = "ColorBrushGray5";
animationTime = 200;
}
// 触发颜色动画
if (IsLoaded && ModAnimation.AniControlEnabled == 0) // 防止默认属性变更触发动画
{
// 有动画
ModAnimation.AniStart(
new[]
{
ModAnimation.AaColor(this, BorderBrushProperty, foregroundName, animationTime),
ModAnimation.AaColor(ShapeDot, Shape.FillProperty, dotFillName, animationTime)
}, "MySlider Color " + Uuid);
}
else
{
// 无动画
ModAnimation.AniStop("MySlider Color " + Uuid);
SetResourceReference(BorderBrushProperty, foregroundName);
ShapeDot.SetResourceReference(Shape.FillProperty, dotFillName);
}
}
catch (Exception ex)
{
ModBase.Log(ex, "滑动条颜色改变出错");
}
}
private void MySlider_MouseEnter()
{
Focus(); // 确保按键能改变值
}
private void MySlider_KeyDown(object sender, KeyEventArgs e)
{
// 拒绝一边拖动一边用按键改变
if (ReferenceEquals(this, ModMain.dragControl))
return;
// 改变值
if (e.Key == Key.Left)
{
changeByKey = true;
Value = (int)(Value - ValueByKey);
changeByKey = false;
e.Handled = true;
}
else if (e.Key == Key.Right)
{
changeByKey = true;
Value = (int)(Value + ValueByKey);
changeByKey = false;
e.Handled = true;
}
else
{
return;
}
// 更新 Popup
if (getHintText is not null)
{
RefreshPopup();
ModAnimation.AniStop("MySlider KeyPopup " + Uuid);
ModAnimation.AniStart(
ModAnimation.AaCode(() => Popup.IsOpen = false, (int)Math.Round(700d * ModAnimation.aniSpeed)),
"MySlider KeyPopup " + Uuid);
}
}
}