初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace PCL;
|
||||
|
||||
[ContentProperty("Inlines")]
|
||||
public partial class MyIconTextButton
|
||||
{
|
||||
public delegate void ChangeEventHandler(object sender, bool raiseByMouse);
|
||||
|
||||
public delegate void CheckEventHandler(object sender, bool raiseByMouse);
|
||||
|
||||
public delegate void ClickEventHandler(object sender, ModBase.RouteEventArgs e);
|
||||
|
||||
public enum ColorState
|
||||
{
|
||||
Black,
|
||||
Highlight
|
||||
}
|
||||
|
||||
// 动画
|
||||
|
||||
private const int animationTimeOfMouseIn = 100; // 鼠标指向动画长度
|
||||
private const int animationTimeOfMouseOut = 150; // 鼠标移出动画长度
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string),
|
||||
typeof(MyIconTextButton), new PropertyMetadata((sender, e) =>
|
||||
{
|
||||
if (sender is not null) ((MyIconTextButton)sender).LabText.Text = (string)e.NewValue;
|
||||
}));
|
||||
|
||||
public static readonly DependencyProperty ColorTypeProperty = DependencyProperty.Register("ColorType",
|
||||
typeof(ColorState), typeof(MyIconTextButton), new PropertyMetadata(ColorState.Black));
|
||||
|
||||
private bool _hasLegacyLogo;
|
||||
private bool isMouseDown;
|
||||
|
||||
// 基础
|
||||
|
||||
public int Uuid = ModBase.GetUuid();
|
||||
|
||||
public MyIconTextButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
RefreshLogoHostVisibility();
|
||||
|
||||
MouseLeftButtonUp += (_, _) => MyIconTextButton_MouseUp();
|
||||
MouseLeftButtonDown += (_, _) => MyIconTextButton_MouseDown();
|
||||
MouseLeave += (_, _) => MyIconTextButton_MouseLeave();
|
||||
MouseEnter += RefreshColor;
|
||||
Loaded += RefreshColor;
|
||||
IsEnabledChanged += (_, _) => RefreshColor();
|
||||
}
|
||||
|
||||
// 自定义属性
|
||||
|
||||
public string Logo
|
||||
{
|
||||
get => ShapeLogo.Data?.ToString() ?? string.Empty;
|
||||
set
|
||||
{
|
||||
if (ShapeLogo is null) return;
|
||||
_hasLegacyLogo = !string.IsNullOrWhiteSpace(value);
|
||||
ShapeLogo.Data = _hasLegacyLogo
|
||||
? (Geometry)new GeometryConverter().ConvertFromString(value)!
|
||||
: null;
|
||||
SvgIconControlHelper.ApplyVisibility(ShapeLogo, ShapeSvgIcon, IsUsingSvgIcon);
|
||||
RefreshLogoHostVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
public string SvgIcon
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
value ??= string.Empty;
|
||||
if (value == field)
|
||||
return;
|
||||
field = value;
|
||||
if (ShapeLogo is null || ShapeSvgIcon is null)
|
||||
return;
|
||||
SvgIconControlHelper.ApplyIcon(ShapeLogo, ShapeSvgIcon, field);
|
||||
ApplyLogoScale();
|
||||
RefreshLogoHostVisibility();
|
||||
RefreshColor();
|
||||
}
|
||||
} = string.Empty;
|
||||
|
||||
private bool IsUsingSvgIcon => SvgIconControlHelper.HasSvgIcon(SvgIcon);
|
||||
|
||||
private double EffectiveLogoScale => IsUsingSvgIcon ? 1D : LogoScale;
|
||||
|
||||
private bool HasAnyIcon => IsUsingSvgIcon || _hasLegacyLogo;
|
||||
|
||||
private void ApplyLogoScale()
|
||||
{
|
||||
LogoHost?.RenderTransform = new ScaleTransform
|
||||
{
|
||||
ScaleX = EffectiveLogoScale,
|
||||
ScaleY = EffectiveLogoScale
|
||||
};
|
||||
}
|
||||
|
||||
private void RefreshLogoHostVisibility()
|
||||
{
|
||||
if (LogoHost is null || LabText is null)
|
||||
return;
|
||||
|
||||
if (HasAnyIcon)
|
||||
{
|
||||
LogoHost.Visibility = Visibility.Visible;
|
||||
LogoHost.Width = 16;
|
||||
LogoHost.Height = 16;
|
||||
LogoHost.Margin = new Thickness(12, 0, 0, 0);
|
||||
LabText.Margin = new Thickness(7, 0, 12, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogoHost.Visibility = Visibility.Collapsed;
|
||||
LogoHost.Width = 0;
|
||||
LogoHost.Height = 16;
|
||||
LogoHost.Margin = new Thickness(0);
|
||||
LabText.Margin = new Thickness(12, 0, 12, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public double LogoScale
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = value;
|
||||
ApplyLogoScale();
|
||||
}
|
||||
} = 1d;
|
||||
|
||||
public InlineCollection Inlines => LabText.Inlines;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
} // 内容
|
||||
|
||||
public ColorState ColorType
|
||||
{
|
||||
get => (ColorState)GetValue(ColorTypeProperty);
|
||||
set
|
||||
{
|
||||
if (ColorType == value)
|
||||
return;
|
||||
SetValue(ColorTypeProperty, value);
|
||||
RefreshColor();
|
||||
}
|
||||
} // 颜色类别
|
||||
|
||||
public event CheckEventHandler? Check;
|
||||
public event ChangeEventHandler? Change;
|
||||
|
||||
private string CheckedAnimationKey => "MyIconTextButton Checked " + Uuid;
|
||||
private string ColorAnimationKey => "MyIconTextButton Color " + Uuid;
|
||||
|
||||
// 点击事件
|
||||
|
||||
public event ClickEventHandler? Click;
|
||||
|
||||
private string GetDefaultForegroundResourceKey()
|
||||
{
|
||||
return ColorType == ColorState.Highlight ? "ColorBrush3" : "ColorBrush1";
|
||||
}
|
||||
|
||||
private void StartForegroundAnimation(string resourceKey, int duration)
|
||||
{
|
||||
if (IsUsingSvgIcon)
|
||||
{
|
||||
SvgIconControlHelper.AnimateSvgIconBrushTo(ShapeSvgIcon, resourceKey, duration, CheckedAnimationKey);
|
||||
ModAnimation.AniStart(
|
||||
ModAnimation.AaColor(LabText, TextBlock.ForegroundProperty, resourceKey, duration),
|
||||
CheckedAnimationKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModAnimation.AniStart(
|
||||
new[]
|
||||
{
|
||||
ModAnimation.AaColor(ShapeLogo, Shape.FillProperty, resourceKey, duration),
|
||||
ModAnimation.AaColor(LabText, TextBlock.ForegroundProperty, resourceKey, duration)
|
||||
}, CheckedAnimationKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartBackgroundAnimation(string resourceKey, int duration)
|
||||
{
|
||||
ModAnimation.AniStart(ModAnimation.AaColor(this, BackgroundProperty, resourceKey, duration), ColorAnimationKey);
|
||||
}
|
||||
|
||||
private void StartBackgroundAnimation(ModBase.MyColor delta, int duration)
|
||||
{
|
||||
ModAnimation.AniStart(ModAnimation.AaColor(this, BackgroundProperty, delta, duration), ColorAnimationKey);
|
||||
}
|
||||
|
||||
private void MyIconTextButton_MouseUp()
|
||||
{
|
||||
if (!isMouseDown)
|
||||
return;
|
||||
ModBase.Log("[Control] 按下带图标按钮:" + Text);
|
||||
isMouseDown = false;
|
||||
Click?.Invoke(this, new ModBase.RouteEventArgs(true));
|
||||
ModMain.RaiseCustomEvent(this);
|
||||
RefreshColor();
|
||||
}
|
||||
|
||||
private void MyIconTextButton_MouseDown()
|
||||
{
|
||||
isMouseDown = true;
|
||||
RefreshColor();
|
||||
}
|
||||
|
||||
private void MyIconTextButton_MouseLeave()
|
||||
{
|
||||
isMouseDown = false;
|
||||
RefreshColor();
|
||||
}
|
||||
|
||||
private void RefreshColor(object? obj = null, object? e = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ControlVisualHelpers.ShouldAnimate(this, e)) // 防止默认属性变更触发动画,若强制不执行动画,则 e 为 False
|
||||
{
|
||||
if (isMouseDown)
|
||||
{
|
||||
StartBackgroundAnimation("ColorBrush6", 70);
|
||||
}
|
||||
else if (IsMouseOver)
|
||||
{
|
||||
StartForegroundAnimation("ColorBrush3", animationTimeOfMouseIn);
|
||||
StartBackgroundAnimation("ColorBrushBg1", animationTimeOfMouseIn);
|
||||
}
|
||||
else if (IsEnabled)
|
||||
{
|
||||
StartForegroundAnimation(GetDefaultForegroundResourceKey(), animationTimeOfMouseOut);
|
||||
StartBackgroundAnimation(ThemeManager.colorSemiTransparent - Background, animationTimeOfMouseOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
StartForegroundAnimation("ColorBrushGray5", 100);
|
||||
StartBackgroundAnimation(ThemeManager.colorSemiTransparent - Background, animationTimeOfMouseOut);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// 不使用动画
|
||||
ModAnimation.AniStop(CheckedAnimationKey);
|
||||
ModAnimation.AniStop(ColorAnimationKey);
|
||||
Background = ThemeManager.colorSemiTransparent;
|
||||
var foregroundKey = IsEnabled ? GetDefaultForegroundResourceKey() : "ColorBrushGray5";
|
||||
SvgIconControlHelper.SetIconResource(ShapeLogo, ShapeSvgIcon, IsUsingSvgIcon, foregroundKey);
|
||||
LabText.SetResourceReference(TextBlock.ForegroundProperty, foregroundKey);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(ex, "刷新带图标按钮颜色出错");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user