feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
CI / Go Backend (push) Canceled after 0s

初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

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

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

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
xyou
2026-08-08 14:07:56 +08:00
parent 9500c4c80a
commit f70b061d1a
1972 changed files with 159760 additions and 6 deletions
@@ -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, "刷新带图标按钮颜色出错");
}
}
}