Skip to content

Commit

Permalink
Merge pull request #1862 from insomnious/1860-add-game-store-to-game-…
Browse files Browse the repository at this point in the history
…widget

Add game store to game tiles and update design
  • Loading branch information
Al12rs authored Aug 12, 2024
2 parents 5b560e4 + 514b1bf commit 40276e1
Show file tree
Hide file tree
Showing 14 changed files with 339 additions and 158 deletions.
126 changes: 66 additions & 60 deletions src/NexusMods.App.UI/Controls/GameWidget/GameWidget.axaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<reactiveUi:ReactiveUserControl
d:DesignHeight="240"
d:DesignWidth="200"
d:DesignHeight="320"
d:DesignWidth="220"
mc:Ignorable="d"
x:Class="NexusMods.App.UI.Controls.GameWidget.GameWidget"
x:TypeArguments="gameWidget:IGameWidgetViewModel"
Expand All @@ -19,51 +19,61 @@
</Design.DataContext>

<Border
Height="228"
Width="180"
Height="293"
Width="184"
x:Name="GameWidgetBorder">
<Border x:Name="MainBorder"
Height="228"
Width="180">
<Grid RowDefinitions="106, *">
<Image
Grid.Row="0"
Grid.RowSpan="2"
Height="228"
Stretch="UniformToFill"
Width="180"
x:Name="BlurryImage" />
<Image
Grid.Row="0"
Width="180"
x:Name="GameImage" />
<Border Grid.Row="1">
<Grid RowDefinitions="Auto, 1, *"
Margin="16,0,16,0"
VerticalAlignment="Top"
Width="148">
<TextBlock
Grid.Row="0"
Height="34"
Margin="0,8"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
x:Name="NameTextBlock" />
<Border
BorderThickness="0,0,0,1"
Grid.Row="1"
Margin="0"
x:Name="SeparationLine"/>

<!-- DetectedGame -->

<StackPanel Spacing="12">

<!-- image section -->

<Border x:Name="ImageSectionBorder">
<Grid RowDefinitions="Auto" Height="184" x:Name="ImageGrid">
<Image Grid.Row="0"
x:Name="GameImage"
/>
<Border Grid.Row="0"
Height="36"
Width="36"
VerticalAlignment="Top"
HorizontalAlignment="Left"
x:Name="StoreBackground">
<icons:UnifiedIcon Size="24" x:Name="GameStoreIcon"/>
<ToolTip.Tip>
<TextBlock x:Name="GameStoreToolTipTextBlock" />
</ToolTip.Tip>
</Border>
</Grid>
</Border>

<!-- details section -->

<StackPanel x:Name="DetailsSectionStackPanel">
<TextBlock
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
x:Name="NameTextBlock" />
<TextBlock
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
x:Name="VersionTextBlock" />
</StackPanel>

<!-- buttons section -->

<StackPanel>

<!-- DetectedGame -->
<StackPanel x:Name="DetectedGameStackPanel"
Grid.Row="2"
Margin="0,16,0,0"
Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
IsVisible="False">
<Button Classes="Rounded Primary" x:Name="AddGameButton">
<Button Classes="Standard Secondary" x:Name="AddGameButton" HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal">
<icons:UnifiedIcon Classes="Add" />
<TextBlock Classes="BodyMDNormal"
Expand All @@ -74,30 +84,26 @@

<!-- AddingGame -->
<StackPanel x:Name="AddingGameStackPanel"
Grid.Row="2"
Margin="0,16,0,0"
Orientation="Horizontal"
VerticalAlignment="Center"
Classes="Spacing-1"
Spacing="8"
IsVisible="False">
<progressRing:ProgressRing Height="24" Width="24"
VerticalAlignment="Center"/>
<TextBlock Classes="BodyMDNormal"
<TextBlock x:Name="AddingGameTextBlock"
VerticalAlignment="Center"
Text="{x:Static resources:Language.GameWidget__Adding_game}"/>
</StackPanel>

<!-- ManagedGame -->
<Grid x:Name="ManagedGameGrid"
ColumnDefinitions="*, Auto, Auto"
Grid.Row="2"
ColumnDefinitions="*, 12, Auto"
IsVisible="False"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Classes="Spacing-1"
Margin="4,16,-6,0">
<Button Classes="Rounded Primary" x:Name="ViewGameButton"
Margin="-6,0,8,0"
Classes="Spacing-2">
<Button Classes="Standard Tertiary Weak" x:Name="ViewGameButton"
HorizontalAlignment="Stretch"
Grid.Column="0">
<StackPanel Orientation="Horizontal">
Expand All @@ -106,7 +112,7 @@
Text="{x:Static resources:Language.GameWidget__View}"/>
</StackPanel>
</Button>
<Button Classes="Rounded Primary"
<Button Classes="Standard Tertiary Weak"
HorizontalAlignment="Right"
x:Name="RemoveGameButton"
Grid.Column="2">
Expand All @@ -116,22 +122,22 @@

<!-- RemovingGame -->
<StackPanel x:Name="RemovingGameStackPanel"
Grid.Row="2"
Margin="0,16,0,0"
Orientation="Horizontal"
VerticalAlignment="Center"
Classes="Spacing-1"
Spacing="8"
IsVisible="False">
<progressRing:ProgressRing Height="24" Width="24"
VerticalAlignment="Center"/>
<TextBlock Classes="BodyMDNormal"
<TextBlock x:Name="RemovingGameTextBlock"
VerticalAlignment="Center"
Text="{x:Static resources:Language.GameWidget__Removing_game}"/>
</StackPanel>

</Grid>
</Border>
</Grid>


</StackPanel>

</StackPanel>
</Border>
</Border>

</reactiveUi:ReactiveUserControl>
56 changes: 20 additions & 36 deletions src/NexusMods.App.UI/Controls/GameWidget/GameWidget.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using System.Reactive.Linq;
using Avalonia.Media.Imaging;
using Avalonia.ReactiveUI;
using NexusMods.Abstractions.GameLocators;
using NexusMods.App.UI.Extensions;
using NexusMods.Icons;
using ReactiveUI;
using SkiaSharp;

Expand All @@ -19,58 +21,40 @@ public GameWidget()
{
this.WhenAnyValue(view => view.ViewModel!.State)
.Subscribe(state =>
{
DetectedGameStackPanel.IsVisible = state == GameWidgetState.DetectedGame;
AddingGameStackPanel.IsVisible = state == GameWidgetState.AddingGame;
ManagedGameGrid.IsVisible = state == GameWidgetState.ManagedGame;
RemovingGameStackPanel.IsVisible = state == GameWidgetState.RemovingGame;
GameWidgetBorder.Classes.ToggleIf("Disabled", state is GameWidgetState.AddingGame or GameWidgetState.RemovingGame);
})
{
DetectedGameStackPanel.IsVisible = state == GameWidgetState.DetectedGame;
AddingGameStackPanel.IsVisible = state == GameWidgetState.AddingGame;
ManagedGameGrid.IsVisible = state == GameWidgetState.ManagedGame;
RemovingGameStackPanel.IsVisible = state == GameWidgetState.RemovingGame;
GameWidgetBorder.Classes.ToggleIf("Disabled", state is GameWidgetState.AddingGame or GameWidgetState.RemovingGame);
}
)
.DisposeWith(d);

this.OneWayBind(ViewModel, vm => vm.Image, v => v.GameImage.Source)
this.OneWayBind(ViewModel, vm => vm.Store, v => v.GameStoreToolTipTextBlock.Text)
.DisposeWith(d);

this.WhenAnyValue(view => view.ViewModel!.Image)
.WhereNotNull()
.OffUi()
.Select(BlurAvaloniaImage)
.OnUI()
.BindToView(this, view => view.BlurryImage.Source)
this.OneWayBind(ViewModel, vm => vm.Image, v => v.GameImage.Source)
.DisposeWith(d);

this.OneWayBind(ViewModel, vm => vm.Name, v => v.NameTextBlock.Text)
.DisposeWith(d);

this.OneWayBind(ViewModel, vm => vm.Version, v => v.VersionTextBlock.Text)
.DisposeWith(d);

this.OneWayBind(ViewModel, vm => vm.GameStoreIcon, v => v.GameStoreIcon.Value)
.DisposeWith(d);

this.BindCommand(ViewModel, vm => vm.AddGameCommand, v => v.AddGameButton)
.DisposeWith(d);

this.BindCommand(ViewModel, vm => vm.RemoveAllLoadoutsCommand, v => v.RemoveGameButton)
.DisposeWith(d);

this.BindCommand(ViewModel, vm => vm.ViewGameCommand, v => v.ViewGameButton)
.DisposeWith(d);
}
);
}

private static Bitmap BlurAvaloniaImage(Bitmap bitmap)
{
using var inputSkBitmap = bitmap.ToSkiaBitmap();
using var outputSkBitmap = new SKBitmap(inputSkBitmap.Info, SKBitmapAllocFlags.ZeroPixels);

using (var skCanvas = new SKCanvas(outputSkBitmap))
using (var skPaint = new SKPaint())
{
skPaint.ImageFilter = SKImageFilter.CreateBlur(
sigmaX: 100f,
sigmaY: 100f
);

var skRect = inputSkBitmap.Info.Rect;
skCanvas.DrawBitmap(inputSkBitmap, skRect, skPaint);
}

return outputSkBitmap.ToAvaloniaImage();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using NexusMods.Abstractions.GameLocators;
using NexusMods.Icons;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

Expand All @@ -10,8 +11,11 @@ namespace NexusMods.App.UI.Controls.GameWidget;
public class GameWidgetDesignViewModel : AViewModel<IGameWidgetViewModel>, IGameWidgetViewModel
{
[Reactive]
public GameInstallation Installation { get; set; } = GameInstallation.Empty;
public GameInstallation Installation { get; set; } = new GameInstallation() { Store = GameStore.XboxGamePass, Version = new Version(1,0,0) };
public string Name { get; } = "SOME CYBERPUNK GAME WITH A LONG NAME";
public string Version { get; set; }
public string Store { get; set; }
public IconValue GameStoreIcon { get; set; }
public Bitmap Image { get; }
public ReactiveCommand<Unit,Unit> AddGameCommand { get; set; } = ReactiveCommand.Create(() => { });
public ReactiveCommand<Unit, Unit> ViewGameCommand { get; set; } = ReactiveCommand.Create(() => { });
Expand All @@ -24,5 +28,9 @@ public GameWidgetDesignViewModel()
{
Image = new Bitmap(AssetLoader.Open(new Uri("avares://NexusMods.App.UI/Assets/DesignTime/cyberpunk_game.png")));
State = GameWidgetState.DetectedGame;

Version = $"Version: {Installation.Version}";
Store = Installation.Store.Value;
GameStoreIcon = GameWidgetViewModel.MapGameStoreToIcon(Installation.Store);
}
}
Loading

0 comments on commit 40276e1

Please sign in to comment.