started adding navigation
This commit is contained in:
parent
32781b1462
commit
468e0a7246
20 changed files with 844 additions and 31 deletions
|
|
@ -14,5 +14,6 @@
|
|||
<conv:ActiveOpacityConverter x:Key="ActiveOpacity" />
|
||||
<conv:CellBorderConverter x:Key="CellBorderConverter" />
|
||||
<conv:BoolToOverlayBrushConverter x:Key="OccupiedOverlayBrush" />
|
||||
<conv:MapRequirementsConverter x:Key="MapRequirementsText" />
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public partial class App : Application
|
|||
services.AddSingleton<MainWindowViewModel>();
|
||||
services.AddSingleton<DebugViewModel>();
|
||||
services.AddSingleton<SettingsViewModel>();
|
||||
services.AddSingleton<MappingViewModel>();
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ public partial class App : Application
|
|||
var mainVm = provider.GetRequiredService<MainWindowViewModel>();
|
||||
mainVm.DebugVm = provider.GetRequiredService<DebugViewModel>();
|
||||
mainVm.SettingsVm = provider.GetRequiredService<SettingsViewModel>();
|
||||
mainVm.MappingVm = provider.GetRequiredService<MappingViewModel>();
|
||||
|
||||
var window = new MainWindow { DataContext = mainVm };
|
||||
window.SetConfigStore(store);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,23 @@ public class BoolToOverlayBrushConverter : IValueConverter
|
|||
=> throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public class MapRequirementsConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
MapType.TrialOfChaos => "Trial Token x1",
|
||||
MapType.Temple => "Identity Scroll x20",
|
||||
MapType.Endgame => "Identity Scroll x20",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public class CellBorderConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||
using CommunityToolkit.Mvvm.Input;
|
||||
using Poe2Trade.Bot;
|
||||
using Poe2Trade.Core;
|
||||
using Poe2Trade.Navigation;
|
||||
using Serilog;
|
||||
|
||||
namespace Poe2Trade.Ui.ViewModels;
|
||||
|
|
@ -42,6 +43,9 @@ public partial class MainWindowViewModel : ObservableObject
|
|||
private bool _isStarted;
|
||||
|
||||
[ObservableProperty] private Bitmap? _inventoryImage;
|
||||
[ObservableProperty] private Bitmap? _minimapImage;
|
||||
[ObservableProperty] private string _navigationStateText = "";
|
||||
private long _lastMinimapUpdate;
|
||||
|
||||
[ObservableProperty] private string _newUrl = "";
|
||||
[ObservableProperty] private string _newLinkName = "";
|
||||
|
|
@ -49,13 +53,16 @@ public partial class MainWindowViewModel : ObservableObject
|
|||
[ObservableProperty] private int _tradesCompleted;
|
||||
[ObservableProperty] private int _tradesFailed;
|
||||
[ObservableProperty] private int _activeLinksCount;
|
||||
[ObservableProperty] private BotMode _botMode;
|
||||
|
||||
public static LinkMode[] LinkModes { get; } = [LinkMode.Live, LinkMode.Scrap];
|
||||
public static BotMode[] BotModes { get; } = [BotMode.Trading, BotMode.Mapping];
|
||||
|
||||
public MainWindowViewModel(BotOrchestrator bot)
|
||||
{
|
||||
_bot = bot;
|
||||
_isPaused = bot.IsPaused;
|
||||
_botMode = bot.Mode;
|
||||
|
||||
for (var i = 0; i < 60; i++)
|
||||
InventoryCells.Add(new CellState());
|
||||
|
|
@ -66,12 +73,14 @@ public partial class MainWindowViewModel : ObservableObject
|
|||
{
|
||||
State = bot.State;
|
||||
IsPaused = bot.IsPaused;
|
||||
BotMode = bot.Mode;
|
||||
var status = bot.GetStatus();
|
||||
TradesCompleted = status.TradesCompleted;
|
||||
TradesFailed = status.TradesFailed;
|
||||
ActiveLinksCount = status.Links.Count(l => l.Active);
|
||||
OnPropertyChanged(nameof(Links));
|
||||
UpdateInventoryGrid();
|
||||
UpdateMinimapImage();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -99,6 +108,12 @@ public partial class MainWindowViewModel : ObservableObject
|
|||
// Sub-ViewModels for tabs
|
||||
public DebugViewModel? DebugVm { get; set; }
|
||||
public SettingsViewModel? SettingsVm { get; set; }
|
||||
public MappingViewModel? MappingVm { get; set; }
|
||||
|
||||
partial void OnBotModeChanged(BotMode value)
|
||||
{
|
||||
_bot.Mode = value;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanStart))]
|
||||
private async Task Start()
|
||||
|
|
@ -198,4 +213,39 @@ public partial class MainWindowViewModel : ObservableObject
|
|||
|
||||
OnPropertyChanged(nameof(InventoryFreeCells));
|
||||
}
|
||||
|
||||
private void UpdateMinimapImage()
|
||||
{
|
||||
var nav = _bot.Navigation;
|
||||
var navState = nav.State;
|
||||
NavigationStateText = navState == NavigationState.Idle ? "" : navState.ToString();
|
||||
|
||||
if (navState == NavigationState.Idle)
|
||||
{
|
||||
if (MinimapImage != null)
|
||||
{
|
||||
var old = MinimapImage;
|
||||
MinimapImage = null;
|
||||
old.Dispose();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Throttle: update at most once per second
|
||||
var now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
if (now - _lastMinimapUpdate < 1000) return;
|
||||
_lastMinimapUpdate = now;
|
||||
|
||||
try
|
||||
{
|
||||
var bytes = nav.GetViewportSnapshot();
|
||||
var old = MinimapImage;
|
||||
MinimapImage = new Bitmap(new MemoryStream(bytes));
|
||||
old?.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Debug(ex, "Failed to update minimap image");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
src/Poe2Trade.Ui/ViewModels/MappingViewModel.cs
Normal file
25
src/Poe2Trade.Ui/ViewModels/MappingViewModel.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Poe2Trade.Bot;
|
||||
using Poe2Trade.Core;
|
||||
|
||||
namespace Poe2Trade.Ui.ViewModels;
|
||||
|
||||
public partial class MappingViewModel : ObservableObject
|
||||
{
|
||||
private readonly BotOrchestrator _bot;
|
||||
|
||||
[ObservableProperty] private MapType _selectedMapType;
|
||||
|
||||
public static MapType[] MapTypes { get; } = [MapType.TrialOfChaos, MapType.Temple, MapType.Endgame];
|
||||
|
||||
public MappingViewModel(BotOrchestrator bot)
|
||||
{
|
||||
_bot = bot;
|
||||
_selectedMapType = bot.Config.MapType;
|
||||
}
|
||||
|
||||
partial void OnSelectedMapTypeChanged(MapType value)
|
||||
{
|
||||
_bot.Store.UpdateSettings(s => s.MapType = value);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +56,10 @@
|
|||
</StackPanel>
|
||||
|
||||
<!-- Controls -->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="8">
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="8"
|
||||
VerticalAlignment="Center">
|
||||
<ComboBox ItemsSource="{x:Static vm:MainWindowViewModel.BotModes}"
|
||||
SelectedItem="{Binding BotMode}" Width="110" />
|
||||
<Button Content="Start" Command="{Binding StartCommand}" />
|
||||
<Button Content="{Binding PauseButtonText}" Command="{Binding PauseCommand}" />
|
||||
</StackPanel>
|
||||
|
|
@ -70,36 +73,61 @@
|
|||
<TabItem Header="State">
|
||||
<Grid RowDefinitions="Auto,*" Margin="0,6,0,0">
|
||||
|
||||
<!-- Inventory Grid (12x5) -->
|
||||
<Border Grid.Row="0" Background="#161b22" BorderBrush="#30363d"
|
||||
BorderThickness="1" CornerRadius="8" Padding="8" Margin="0,0,0,6">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,4">
|
||||
<TextBlock Text="INVENTORY" FontSize="11" FontWeight="SemiBold"
|
||||
Foreground="#8b949e" />
|
||||
<TextBlock Text="{Binding InventoryFreeCells, StringFormat='{}{0}/60 free'}"
|
||||
FontSize="11" Foreground="#8b949e" Margin="12,0,0,0" />
|
||||
</StackPanel>
|
||||
<Grid MaxHeight="170">
|
||||
<Image Source="{Binding InventoryImage}" Stretch="Uniform" />
|
||||
<ItemsControl ItemsSource="{Binding InventoryCells}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<UniformGrid Columns="12" Rows="5" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:CellState">
|
||||
<Border Margin="1" CornerRadius="2"
|
||||
Background="{Binding IsOccupied, Converter={StaticResource OccupiedOverlayBrush}}"
|
||||
BorderBrush="#3fb950"
|
||||
BorderThickness="{Binding Converter={StaticResource CellBorderConverter}}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<!-- Top row: Inventory + Minimap side by side -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Margin="0,0,0,6">
|
||||
|
||||
<!-- Inventory Grid (12x5) -->
|
||||
<Border Grid.Column="0" Background="#161b22" BorderBrush="#30363d"
|
||||
BorderThickness="1" CornerRadius="8" Padding="8" Margin="0,0,6,0">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,4">
|
||||
<TextBlock Text="INVENTORY" FontSize="11" FontWeight="SemiBold"
|
||||
Foreground="#8b949e" />
|
||||
<TextBlock Text="{Binding InventoryFreeCells, StringFormat='{}{0}/60 free'}"
|
||||
FontSize="11" Foreground="#8b949e" Margin="12,0,0,0" />
|
||||
</StackPanel>
|
||||
<Grid MaxHeight="170">
|
||||
<Image Source="{Binding InventoryImage}" Stretch="Uniform" />
|
||||
<ItemsControl ItemsSource="{Binding InventoryCells}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<UniformGrid Columns="12" Rows="5" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:CellState">
|
||||
<Border Margin="1" CornerRadius="2"
|
||||
Background="{Binding IsOccupied, Converter={StaticResource OccupiedOverlayBrush}}"
|
||||
BorderBrush="#3fb950"
|
||||
BorderThickness="{Binding Converter={StaticResource CellBorderConverter}}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Minimap -->
|
||||
<Border Grid.Column="1" Background="#161b22" BorderBrush="#30363d"
|
||||
BorderThickness="1" CornerRadius="8" Padding="8" Width="200">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,4">
|
||||
<TextBlock Text="MINIMAP" FontSize="11" FontWeight="SemiBold"
|
||||
Foreground="#8b949e" />
|
||||
<TextBlock Text="{Binding NavigationStateText}"
|
||||
FontSize="11" Foreground="#8b949e" Margin="8,0,0,0" />
|
||||
</StackPanel>
|
||||
<Grid>
|
||||
<Image Source="{Binding MinimapImage}" Stretch="Uniform"
|
||||
RenderOptions.BitmapInterpolationMode="None" />
|
||||
<TextBlock Text="Idle"
|
||||
IsVisible="{Binding MinimapImage, Converter={x:Static ObjectConverters.IsNull}}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="12" Foreground="#484f58" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Logs -->
|
||||
<Border Grid.Row="1" Background="#0d1117" BorderBrush="#30363d"
|
||||
|
|
@ -178,6 +206,24 @@
|
|||
</Border>
|
||||
</TabItem>
|
||||
|
||||
<!-- ========== MAPPING TAB ========== -->
|
||||
<TabItem Header="Mapping">
|
||||
<Border DataContext="{Binding MappingVm}" Background="#161b22"
|
||||
BorderBrush="#30363d" BorderThickness="1" CornerRadius="8"
|
||||
Padding="10" Margin="0,6,0,0">
|
||||
<StackPanel Spacing="8" x:DataType="vm:MappingViewModel">
|
||||
<TextBlock Text="MAP TYPE" FontSize="11" FontWeight="SemiBold"
|
||||
Foreground="#8b949e" />
|
||||
<ComboBox ItemsSource="{x:Static vm:MappingViewModel.MapTypes}"
|
||||
SelectedItem="{Binding SelectedMapType}" Width="200" />
|
||||
<TextBlock Text="REQUIRED ITEMS" FontSize="11" FontWeight="SemiBold"
|
||||
Foreground="#8b949e" Margin="0,8,0,0" />
|
||||
<TextBlock Text="{Binding SelectedMapType, Converter={StaticResource MapRequirementsText}}"
|
||||
FontSize="13" Foreground="#e6edf3" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</TabItem>
|
||||
|
||||
<!-- ========== DEBUG TAB ========== -->
|
||||
<TabItem Header="Debug">
|
||||
<ScrollViewer DataContext="{Binding DebugVm}" Margin="0,6,0,0">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue