From edccafec706ff5f71d09fc43055aedbb0a642bcf Mon Sep 17 00:00:00 2001
From: uye <99072975+ABA2396@users.noreply.github.com>
Date: Wed, 23 Jul 2025 18:42:27 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=AC=E6=8B=9B=E7=BB=93=E6=9E=9C?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BD=A9=E8=89=B2=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
fix #12458
---
src/MaaWpfGui/Constants/UILogColor.cs | 30 ++++
src/MaaWpfGui/Helper/ToolTipHelper.cs | 32 ++++
src/MaaWpfGui/Main/AsstProxy.cs | 2 +-
src/MaaWpfGui/Res/Themes/Dark.xaml | 6 +
src/MaaWpfGui/Res/Themes/Light.xaml | 6 +
src/MaaWpfGui/Styles/Controls/TextBlock.cs | 34 +++++
.../ViewModels/UI/RecognizerViewModel.cs | 140 ++++++++++++------
src/MaaWpfGui/Views/UI/RecognizerView.xaml | 18 ++-
8 files changed, 216 insertions(+), 52 deletions(-)
diff --git a/src/MaaWpfGui/Constants/UILogColor.cs b/src/MaaWpfGui/Constants/UILogColor.cs
index 9a5b22f853..f47489f9ca 100644
--- a/src/MaaWpfGui/Constants/UILogColor.cs
+++ b/src/MaaWpfGui/Constants/UILogColor.cs
@@ -56,6 +56,36 @@ namespace MaaWpfGui.Constants
[UsedImplicitly]
public const string RobotOperator = "RobotOperatorLogBrush";
+ ///
+ /// The recommended color for 1-star operators (also used for robot operators).
+ ///
+ public const string Star1Operator = "Star1OperatorLogBrush";
+
+ ///
+ /// The recommended color for 2-star operators.
+ ///
+ public const string Star2Operator = "Star2OperatorLogBrush";
+
+ ///
+ /// The recommended color for 3-star operators.
+ ///
+ public const string Star3Operator = "Star3OperatorLogBrush";
+
+ ///
+ /// The recommended color for 4-star operators.
+ ///
+ public const string Star4Operator = "Star4OperatorLogBrush";
+
+ ///
+ /// The recommended color for 5-star operators.
+ ///
+ public const string Star5Operator = "Star5OperatorLogBrush";
+
+ ///
+ /// The recommended color for 6-star operators.
+ ///
+ public const string Star6Operator = "Star6OperatorLogBrush";
+
///
/// The recommended color for file downloading or downloaded or download failed.
///
diff --git a/src/MaaWpfGui/Helper/ToolTipHelper.cs b/src/MaaWpfGui/Helper/ToolTipHelper.cs
index 816e216c4c..2b8370f313 100644
--- a/src/MaaWpfGui/Helper/ToolTipHelper.cs
+++ b/src/MaaWpfGui/Helper/ToolTipHelper.cs
@@ -76,6 +76,38 @@ namespace MaaWpfGui.Helper
return tb.CreateTooltip(placementMode);
}
+ public static ToolTip CreateTooltip(this IEnumerable inlines, PlacementMode? placementMode = null, int maxWidth = 750)
+ {
+ var tb = new TextBlock
+ {
+ TextWrapping = TextWrapping.Wrap,
+ Margin = new(4),
+ MaxWidth = maxWidth,
+ };
+
+ foreach (var inline in inlines)
+ {
+ tb.Inlines.Add(CloneInline(inline));
+ }
+
+ return tb.CreateTooltip(placementMode);
+
+ Inline CloneInline(Inline inline)
+ {
+ return inline switch
+ {
+ Run run => new Run(run.Text)
+ {
+ Foreground = run.Foreground,
+ FontWeight = run.FontWeight,
+ FontStyle = run.FontStyle,
+ },
+ LineBreak => new LineBreak(),
+ _ => new Run(),
+ };
+ }
+ }
+
#region 创建日志 Tooltip 的辅助方法
///
diff --git a/src/MaaWpfGui/Main/AsstProxy.cs b/src/MaaWpfGui/Main/AsstProxy.cs
index 6a392670ba..534dbd0c4a 100644
--- a/src/MaaWpfGui/Main/AsstProxy.cs
+++ b/src/MaaWpfGui/Main/AsstProxy.cs
@@ -1593,7 +1593,7 @@ namespace MaaWpfGui.Main
case "RecruitResult":
{
int level = (int)subTaskDetails!["level"]!;
- var tooltip = $"{Instances.RecognizerViewModel.RecruitInfo}\n\n{Instances.RecognizerViewModel.RecruitResult}".CreateTooltip(PlacementMode.Center);
+ var tooltip = Instances.RecognizerViewModel.RecruitResultInlines.CreateTooltip(PlacementMode.Center);
if (level >= 5)
{
using (var toast = new ToastNotification(string.Format(LocalizationHelper.GetString("RecruitmentOfStar"), level)))
diff --git a/src/MaaWpfGui/Res/Themes/Dark.xaml b/src/MaaWpfGui/Res/Themes/Dark.xaml
index 97f8ddbd1b..274fdf7351 100644
--- a/src/MaaWpfGui/Res/Themes/Dark.xaml
+++ b/src/MaaWpfGui/Res/Themes/Dark.xaml
@@ -85,6 +85,12 @@
+
+
+
+
+
+
diff --git a/src/MaaWpfGui/Res/Themes/Light.xaml b/src/MaaWpfGui/Res/Themes/Light.xaml
index fea509183f..42a7d4afbf 100644
--- a/src/MaaWpfGui/Res/Themes/Light.xaml
+++ b/src/MaaWpfGui/Res/Themes/Light.xaml
@@ -65,6 +65,12 @@
+
+
+
+
+
+
diff --git a/src/MaaWpfGui/Styles/Controls/TextBlock.cs b/src/MaaWpfGui/Styles/Controls/TextBlock.cs
index f751cf0f3b..64c0abb066 100644
--- a/src/MaaWpfGui/Styles/Controls/TextBlock.cs
+++ b/src/MaaWpfGui/Styles/Controls/TextBlock.cs
@@ -11,7 +11,9 @@
// but WITHOUT ANY WARRANTY
//
+using System.Collections.Generic;
using System.Windows;
+using System.Windows.Documents;
using System.Windows.Media;
using MaaWpfGui.Helper;
@@ -69,5 +71,37 @@ namespace MaaWpfGui.Styles.Controls
SetValue(ForegroundProperty, brush);
}
}
+
+ public static readonly DependencyProperty BindableInlinesProperty =
+ DependencyProperty.RegisterAttached(
+ "BindableInlines",
+ typeof(IEnumerable),
+ typeof(TextBlock),
+ new PropertyMetadata(null, OnBindableInlinesChanged));
+
+ public static void SetBindableInlines(DependencyObject element, IEnumerable value)
+ => element.SetValue(BindableInlinesProperty, value);
+
+ public static IEnumerable GetBindableInlines(DependencyObject element)
+ => (IEnumerable)element.GetValue(BindableInlinesProperty);
+
+ private static void OnBindableInlinesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not TextBlock tb)
+ {
+ return;
+ }
+
+ tb.Inlines.Clear();
+ if (e.NewValue is not IEnumerable inlines)
+ {
+ return;
+ }
+
+ foreach (var inline in inlines)
+ {
+ tb.Inlines.Add(inline);
+ }
+ }
}
}
diff --git a/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs b/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs
index db600974f0..c5dcea81df 100644
--- a/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs
+++ b/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs
@@ -20,6 +20,8 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Documents;
+using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using HandyControl.Controls;
@@ -99,15 +101,100 @@ namespace MaaWpfGui.ViewModels.UI
set => SetAndNotify(ref _recruitInfo, value);
}
- private string _recruitResult = string.Empty;
+ private ObservableCollection _recruitResultInlines = [];
- ///
- /// Gets or sets the recruit result.
- ///
- public string RecruitResult
+ public ObservableCollection RecruitResultInlines
{
- get => _recruitResult;
- set => SetAndNotify(ref _recruitResult, value);
+ get => _recruitResultInlines;
+ set => SetAndNotify(ref _recruitResultInlines, value);
+ }
+
+ public void UpdateRecruitResult(JArray? resultArray)
+ {
+ ObservableCollection recruitResultInlines = [];
+
+ foreach (var combs in resultArray ?? [])
+ {
+ int tagLevel = (int)(combs["level"] ?? -1);
+ recruitResultInlines.Add(new Run($"{tagLevel}★ Tags: "));
+
+ foreach (var tag in (JArray?)combs["tags"] ?? [])
+ {
+ recruitResultInlines.Add(new Run($"{tag} "));
+ }
+
+ recruitResultInlines.Add(new LineBreak());
+
+ foreach (var oper in (JArray?)combs["opers"] ?? [])
+ {
+ int operLevel = (int)(oper["level"] ?? -1);
+ var operId = oper["id"]?.ToString();
+ var operName = DataHelper.GetLocalizedCharacterName(oper["name"]?.ToString());
+
+ bool isMaxPot = false;
+ string potentialText = string.Empty;
+
+ if (RecruitmentShowPotential && OperBoxPotential != null && operId != null && (tagLevel >= 4 || operLevel == 1))
+ {
+ if (OperBoxPotential.TryGetValue(operId, out var pot))
+ {
+ potentialText = $" ( {pot} )";
+ if (pot == 6)
+ {
+ isMaxPot = true;
+ potentialText = " ( MAX )";
+ }
+ }
+ else
+ {
+ potentialText = " ( !!! NEW !!! )";
+ }
+ }
+
+ var run = new Run($"{operName}{potentialText} ");
+ var foreground = GetColorByStarWithOpacity(operLevel, isMaxPot ? 0.4 : 1.0);
+ if (foreground != null)
+ {
+ run.Foreground = foreground;
+ }
+
+ recruitResultInlines.Add(run);
+ }
+
+ recruitResultInlines.Add(new LineBreak());
+ recruitResultInlines.Add(new LineBreak());
+ }
+
+ RecruitResultInlines = recruitResultInlines;
+ return;
+
+ SolidColorBrush GetBrushWithOpacity(Color baseColor, double opacity)
+ {
+ byte alpha = (byte)(opacity * 255);
+ return new(Color.FromArgb(alpha, baseColor.R, baseColor.G, baseColor.B));
+ }
+
+ Brush? GetColorByStarWithOpacity(int level, double opacity = 1.0)
+ {
+ var brushKey = level switch
+ {
+ >= 6 => UiLogColor.Star6Operator,
+ 5 => UiLogColor.Star5Operator,
+ 4 => UiLogColor.Star4Operator,
+ 3 => UiLogColor.Star3Operator,
+ 2 => UiLogColor.Star2Operator,
+ _ => UiLogColor.Star1Operator,
+ };
+
+ var brush = Application.Current.TryFindResource(brushKey) as SolidColorBrush;
+ if (brush == null)
+ {
+ return null;
+ }
+
+ var baseColor = brush.Color;
+ return GetBrushWithOpacity(baseColor, opacity);
+ }
}
private bool _chooseLevel3 = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.ChooseLevel3, bool.FalseString));
@@ -205,7 +292,6 @@ namespace MaaWpfGui.ViewModels.UI
}
RecruitInfo = LocalizationHelper.GetString("Identifying");
- RecruitResult = string.Empty;
var levelList = new List();
@@ -277,44 +363,8 @@ namespace MaaWpfGui.ViewModels.UI
case "RecruitResult":
{
- string resultContent = string.Empty;
JArray? resultArray = (JArray?)subTaskDetails?["result"];
- /* int level = (int)subTaskDetails["level"]; */
- foreach (var combs in resultArray ?? [])
- {
- int tagLevel = (int)(combs["level"] ?? -1);
- resultContent += tagLevel + "★ Tags: ";
- resultContent = (((JArray?)combs["tags"]) ?? []).Aggregate(resultContent, (current, tag) => current + (tag + " "));
-
- resultContent += "\n\t";
- foreach (var oper in (JArray?)combs["opers"] ?? [])
- {
- int operLevel = (int)(oper["level"] ?? -1);
- var operId = oper["id"]?.ToString();
- var operName = DataHelper.GetLocalizedCharacterName(oper["name"]?.ToString());
-
- string potential = string.Empty;
-
- if (RecruitmentShowPotential && OperBoxPotential != null && operId != null
- && (tagLevel >= 4 || operLevel == 1))
- {
- if (OperBoxPotential.ContainsKey(operId))
- {
- potential = " ( " + OperBoxPotential[operId] + " )";
- }
- else
- {
- potential = " ( !!! NEW !!! )";
- }
- }
-
- resultContent += operLevel + "★ " + operName + potential + " ";
- }
-
- resultContent += "\n\n";
- }
-
- RecruitResult = resultContent;
+ UpdateRecruitResult(resultArray);
}
break;
diff --git a/src/MaaWpfGui/Views/UI/RecognizerView.xaml b/src/MaaWpfGui/Views/UI/RecognizerView.xaml
index fbf8c2af86..dc947192fe 100644
--- a/src/MaaWpfGui/Views/UI/RecognizerView.xaml
+++ b/src/MaaWpfGui/Views/UI/RecognizerView.xaml
@@ -41,15 +41,21 @@
VerticalAlignment="Top"
Focusable="True"
FontSize="14"
+ ForceCursor="False"
Style="{StaticResource TextBlockDefaultBold}"
Text="{Binding RecruitInfo}"
TextWrapping="Wrap" />
-
+
+
+