mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
feat: 自动战斗滑块动画效果
This commit is contained in:
@@ -42,37 +42,70 @@
|
||||
Padding="2"
|
||||
Background="{DynamicResource MouseOverRegionBrushOpacity75}"
|
||||
CornerRadius="4">
|
||||
<ListBox
|
||||
HorizontalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Padding="0"
|
||||
BorderThickness="0"
|
||||
IsEnabled="{Binding Idle}"
|
||||
SelectedIndex="{Binding CopilotTabIndex}">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel IsItemsHost="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource TransparentListBoxItemStyle}" TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="MinHeight" Value="28" />
|
||||
<Setter Property="Padding" Value="12,2" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource RegionBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBoxItem Content="{DynamicResource MainStageStoryCollectionSideStory}" />
|
||||
<ListBoxItem Content="{DynamicResource SSS}" />
|
||||
<ListBoxItem Content="{DynamicResource ParadoxSimulation}" />
|
||||
<ListBoxItem Content="{DynamicResource OtherActivityStage}" />
|
||||
</ListBox>
|
||||
<Grid x:Name="CopilotTabHost">
|
||||
<Border
|
||||
x:Name="CopilotTabIndicator"
|
||||
Width="0"
|
||||
Height="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{DynamicResource RegionBrush}"
|
||||
CornerRadius="4"
|
||||
IsHitTestVisible="False"
|
||||
Opacity="0">
|
||||
<Border.RenderTransform>
|
||||
<TranslateTransform />
|
||||
</Border.RenderTransform>
|
||||
</Border>
|
||||
<ListBox
|
||||
x:Name="CopilotTabList"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
IsEnabled="{Binding Idle}"
|
||||
Loaded="CopilotTabList_Loaded"
|
||||
SelectedIndex="{Binding CopilotTabIndex}"
|
||||
SelectionChanged="CopilotTabList_SelectionChanged"
|
||||
SizeChanged="CopilotTabList_SizeChanged">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel IsItemsHost="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource NoSelectedHighlightListBoxItemStyle}" TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="MinHeight" Value="28" />
|
||||
<Setter Property="Padding" Value="12,2" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<EventSetter Event="Loaded" Handler="CopilotTabItem_Loaded" />
|
||||
<EventSetter Event="SizeChanged" Handler="CopilotTabItem_SizeChanged" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsSelected" Value="True" />
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</MultiTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBoxItem Content="{DynamicResource MainStageStoryCollectionSideStory}" />
|
||||
<ListBoxItem Content="{DynamicResource SSS}" />
|
||||
<ListBoxItem Content="{DynamicResource ParadoxSimulation}" />
|
||||
<ListBoxItem Content="{DynamicResource OtherActivityStage}" />
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Grid Margin="0,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -11,10 +11,17 @@
|
||||
// but WITHOUT ANY WARRANTY
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
using MaaWpfGui.Models;
|
||||
using MaaWpfGui.ViewModels.UI;
|
||||
using Point = System.Windows.Point;
|
||||
using Rect = System.Windows.Rect;
|
||||
|
||||
namespace MaaWpfGui.Views.UI;
|
||||
|
||||
@@ -23,11 +30,149 @@ namespace MaaWpfGui.Views.UI;
|
||||
/// </summary>
|
||||
public partial class CopilotView
|
||||
{
|
||||
private static readonly Duration CopilotTabAnimationDuration = new(TimeSpan.FromMilliseconds(180));
|
||||
|
||||
public CopilotView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void CopilotTabList_Loaded(object sender, RoutedEventArgs e) => QueueCopilotTabIndicatorUpdate(false);
|
||||
|
||||
private void CopilotTabList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Source == sender)
|
||||
{
|
||||
QueueCopilotTabIndicatorUpdate(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CopilotTabList_SizeChanged(object sender, SizeChangedEventArgs e) => QueueCopilotTabIndicatorUpdate(false);
|
||||
|
||||
private void CopilotTabItem_Loaded(object sender, RoutedEventArgs e) => QueueCopilotTabIndicatorUpdate(false);
|
||||
|
||||
private void CopilotTabItem_SizeChanged(object sender, SizeChangedEventArgs e) => QueueCopilotTabIndicatorUpdate(false);
|
||||
|
||||
private void QueueCopilotTabIndicatorUpdate(bool animate) => Dispatcher.BeginInvoke(() => UpdateCopilotTabIndicator(animate), DispatcherPriority.Loaded);
|
||||
|
||||
private void UpdateCopilotTabIndicator(bool animate)
|
||||
{
|
||||
if (!TryGetSelectedCopilotTabBounds(out var bounds))
|
||||
{
|
||||
if (!IsLoaded || CopilotTabList.SelectedItem is null)
|
||||
{
|
||||
HideCopilotTabIndicator();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CopilotTabIndicator.Opacity = 1;
|
||||
TranslateTransform translateTransform = EnsureCopilotTabIndicatorTransform();
|
||||
bool shouldAnimate = animate && CopilotTabIndicator.Width > 0 && CopilotTabIndicator.Height > 0;
|
||||
if (!shouldAnimate)
|
||||
{
|
||||
StopCopilotTabIndicatorAnimations();
|
||||
SetCopilotTabIndicatorBounds(translateTransform, bounds);
|
||||
return;
|
||||
}
|
||||
|
||||
AnimateCopilotTabIndicator(translateTransform, TranslateTransform.XProperty, bounds.X);
|
||||
AnimateCopilotTabIndicator(translateTransform, TranslateTransform.YProperty, bounds.Y);
|
||||
AnimateCopilotTabIndicator(CopilotTabIndicator, WidthProperty, bounds.Width);
|
||||
AnimateCopilotTabIndicator(CopilotTabIndicator, HeightProperty, bounds.Height);
|
||||
}
|
||||
|
||||
private void HideCopilotTabIndicator()
|
||||
{
|
||||
StopCopilotTabIndicatorAnimations();
|
||||
CopilotTabIndicator.Opacity = 0;
|
||||
}
|
||||
|
||||
private bool TryGetSelectedCopilotTabBounds(out Rect bounds)
|
||||
{
|
||||
bounds = default;
|
||||
if (!IsLoaded || CopilotTabList.SelectedItem is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CopilotTabList.ItemContainerGenerator.ContainerFromItem(CopilotTabList.SelectedItem) is not ListBoxItem item ||
|
||||
!item.IsLoaded ||
|
||||
item.ActualWidth <= 0 ||
|
||||
item.ActualHeight <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Point topLeft = item.TransformToAncestor(CopilotTabHost).Transform(new Point(0, 0));
|
||||
bounds = new Rect(topLeft.X, topLeft.Y, item.ActualWidth, item.ActualHeight);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private TranslateTransform EnsureCopilotTabIndicatorTransform()
|
||||
{
|
||||
if (CopilotTabIndicator.RenderTransform is TranslateTransform translateTransform)
|
||||
{
|
||||
return translateTransform;
|
||||
}
|
||||
|
||||
translateTransform = new TranslateTransform();
|
||||
CopilotTabIndicator.RenderTransform = translateTransform;
|
||||
return translateTransform;
|
||||
}
|
||||
|
||||
private void SetCopilotTabIndicatorBounds(TranslateTransform translateTransform, Rect bounds)
|
||||
{
|
||||
translateTransform.X = bounds.X;
|
||||
translateTransform.Y = bounds.Y;
|
||||
CopilotTabIndicator.Width = bounds.Width;
|
||||
CopilotTabIndicator.Height = bounds.Height;
|
||||
}
|
||||
|
||||
private void StopCopilotTabIndicatorAnimations()
|
||||
{
|
||||
if (CopilotTabIndicator.RenderTransform is TranslateTransform translateTransform)
|
||||
{
|
||||
StopCopilotTabIndicatorAnimations(translateTransform);
|
||||
}
|
||||
|
||||
CopilotTabIndicator.BeginAnimation(WidthProperty, null);
|
||||
CopilotTabIndicator.BeginAnimation(HeightProperty, null);
|
||||
}
|
||||
|
||||
private static void StopCopilotTabIndicatorAnimations(TranslateTransform translateTransform)
|
||||
{
|
||||
translateTransform.BeginAnimation(TranslateTransform.XProperty, null);
|
||||
translateTransform.BeginAnimation(TranslateTransform.YProperty, null);
|
||||
}
|
||||
|
||||
private static void AnimateCopilotTabIndicator(TranslateTransform target, DependencyProperty property, double toValue)
|
||||
{
|
||||
target.BeginAnimation(property, CreateCopilotTabIndicatorAnimation(toValue));
|
||||
}
|
||||
|
||||
private static void AnimateCopilotTabIndicator(Border target, DependencyProperty property, double toValue)
|
||||
{
|
||||
target.BeginAnimation(property, CreateCopilotTabIndicatorAnimation(toValue));
|
||||
}
|
||||
|
||||
private static DoubleAnimation CreateCopilotTabIndicatorAnimation(double toValue)
|
||||
{
|
||||
return new DoubleAnimation {
|
||||
To = toValue,
|
||||
Duration = CopilotTabAnimationDuration,
|
||||
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut },
|
||||
};
|
||||
}
|
||||
|
||||
private void FileTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
if (DataContext is CopilotViewModel viewModel && e.NewValue is CopilotFileItem fileItem && !fileItem.IsFolder)
|
||||
|
||||
Reference in New Issue
Block a user