Skip to content

Commit 21d4736

Browse files
Moving Panzerfaust from Console to UI Application (#337)
* Architecture et configuration de base * Delete tamplate folder in View folder * Added a button named "Launch Example Project" that wraps the existing editor execution logic with the examples\projectConfig.json file. * Refactoring and adding a splash screen * Delete CommunityToolkit.Labs.Extensions.DependencyInjection
1 parent d9152f1 commit 21d4736

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1063
-37
lines changed

Panzerfaust/App.axaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Application xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
x:Class="Panzerfaust.App"
4+
xmlns:panzerfaust="clr-namespace:Panzerfaust"
5+
RequestedThemeVariant="Dark">
6+
7+
<Application.DataTemplates>
8+
<panzerfaust:ViewLocator/>
9+
</Application.DataTemplates>
10+
11+
<Application.Styles>
12+
<FluentTheme />
13+
<StyleInclude Source="avares://Panzerfaust/Assets/Icons.axaml" />
14+
<StyleInclude Source="avares://Panzerfaust/Templates/ContentExample.axaml" />
15+
</Application.Styles>
16+
</Application>

Panzerfaust/App.axaml.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
3+
using Avalonia;
4+
using Avalonia.Controls.ApplicationLifetimes;
5+
using Avalonia.Markup.Xaml;
6+
using Panzerfaust.ViewModels;
7+
using Panzerfaust.Views;
8+
using CommunityToolkit.Mvvm.DependencyInjection;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Panzerfaust.Extensions;
11+
12+
namespace Panzerfaust
13+
{
14+
public partial class App : Application
15+
{
16+
public override void Initialize()
17+
{
18+
AvaloniaXamlLoader.Load(this);
19+
}
20+
21+
public override async void OnFrameworkInitializationCompleted()
22+
{
23+
var locator = new ViewLocator();
24+
DataTemplates.Add(locator);
25+
26+
var services = new ServiceCollection();
27+
services.AddCommonServices();
28+
29+
var provider = services.BuildServiceProvider();
30+
31+
Ioc.Default.ConfigureServices(provider);
32+
33+
var vm = Ioc.Default.GetRequiredService<MainViewModel>();
34+
35+
36+
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
37+
{
38+
var splashScreenVM = new CustomSplashScreenViewModel();
39+
var splashScreen = new CustomSplashScreenView
40+
{
41+
DataContext = splashScreenVM
42+
};
43+
44+
desktop.MainWindow = splashScreen;
45+
46+
splashScreen.Show();
47+
48+
try
49+
{
50+
splashScreenVM.StartupMessage = "Searching for devices...";
51+
await Task.Delay(1000, splashScreenVM.CancellationToken);
52+
splashScreenVM.StartupMessage = "Connecting to device ...";
53+
await Task.Delay(2000, splashScreenVM.CancellationToken);
54+
splashScreenVM.StartupMessage = "Configuring device...";
55+
await Task.Delay(2000, splashScreenVM.CancellationToken);
56+
}
57+
catch (TaskCanceledException)
58+
{
59+
splashScreen.Close();
60+
return;
61+
}
62+
63+
var mainWin = new MainWindow
64+
{
65+
DataContext = new MainViewModel(),
66+
};
67+
desktop.MainWindow = mainWin;
68+
mainWin.Show();
69+
70+
splashScreen.Close();
71+
}
72+
73+
base.OnFrameworkInitializationCompleted();
74+
75+
}
76+
}
77+
}

Panzerfaust/Assets/Icons.axaml

Lines changed: 17 additions & 0 deletions
Large diffs are not rendered by default.

Panzerfaust/Assets/avalonia-logo.ico

172 KB
Binary file not shown.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Reflection;
4+
using Avalonia.Data.Converters;
5+
using Avalonia.Media.Imaging;
6+
using Avalonia.Platform;
7+
8+
namespace Panzerfaust.Converters
9+
{
10+
public class BitmapAssetValueConverter : IValueConverter
11+
{
12+
public static BitmapAssetValueConverter Instance { get; } = new();
13+
14+
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
15+
{
16+
if (value == null) return null;
17+
18+
if (value is not string rawUri || !targetType.IsAssignableFrom(typeof(Bitmap)))
19+
{
20+
throw new NotSupportedException();
21+
}
22+
23+
Uri uri;
24+
25+
// Allow for assembly overrides
26+
if (rawUri.StartsWith("avares://"))
27+
{
28+
uri = new Uri(rawUri);
29+
}
30+
else
31+
{
32+
var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name;
33+
uri = new Uri($"avares://{assemblyName}/{rawUri.TrimStart('/')}");
34+
}
35+
36+
var asset = AssetLoader.Open(uri);
37+
38+
return new Bitmap(asset);
39+
}
40+
41+
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
42+
{
43+
throw new NotImplementedException();
44+
}
45+
}
46+
47+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Avalonia;
2+
using Avalonia.Controls;
3+
using Avalonia.Data.Converters;
4+
using Avalonia.Media;
5+
6+
namespace Panzerfaust.Converters
7+
{
8+
public class TypeConverters
9+
{
10+
private const string StreamGeometryNotFound =
11+
"M24 4C35.0457 4 44 12.9543 44 24C44 35.0457 35.0457 44 24 44C12.9543 44 4 35.0457 4 24C4 12.9543 12.9543 4 24 4ZM24 6.5C14.335 6.5 6.5 14.335 6.5 24C6.5 33.665 14.335 41.5 24 41.5C33.665 41.5 41.5 33.665 41.5 24C41.5 14.335 33.665 6.5 24 6.5ZM24.25 32C25.0784 32 25.75 32.6716 25.75 33.5C25.75 34.3284 25.0784 35 24.25 35C23.4216 35 22.75 34.3284 22.75 33.5C22.75 32.6716 23.4216 32 24.25 32ZM24.25 13C27.6147 13 30.5 15.8821 30.5 19.2488C30.502 21.3691 29.7314 22.7192 27.8216 24.7772L26.8066 25.8638C25.7842 27.0028 25.3794 27.7252 25.3409 28.5793L25.3379 28.7411L25.3323 28.8689L25.3143 28.9932C25.2018 29.5636 24.7009 29.9957 24.0968 30.0001C23.4065 30.0049 22.8428 29.4493 22.8379 28.7589C22.8251 26.9703 23.5147 25.7467 25.1461 23.9739L26.1734 22.8762C27.5312 21.3837 28.0012 20.503 28 19.25C28 17.2634 26.2346 15.5 24.25 15.5C22.3307 15.5 20.6142 17.1536 20.5055 19.0587L20.4935 19.3778C20.4295 20.0081 19.8972 20.5 19.25 20.5C18.5596 20.5 18 19.9404 18 19.25C18 15.8846 20.8864 13 24.25 13Z";
12+
13+
public static FuncValueConverter<string, StreamGeometry> IconConverter { get; } =
14+
new(iconKey =>
15+
{
16+
if (iconKey is null) return StreamGeometry.Parse(StreamGeometryNotFound);
17+
18+
Application.Current!.TryFindResource(iconKey, out var resource);
19+
return resource as StreamGeometry ?? StreamGeometry.Parse(StreamGeometryNotFound);
20+
});
21+
}
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using CommunityToolkit.Mvvm.Messaging;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Panzerfaust.Service.Engine;
4+
using Panzerfaust.ViewModels;
5+
using Panzerfaust.Views;
6+
7+
namespace Panzerfaust.Extensions
8+
{
9+
public static class ServiceCollectionExtensions
10+
{
11+
public static void AddCommonServices(this IServiceCollection collection)
12+
{
13+
//Services
14+
collection.AddSingleton<IMessenger>(WeakReferenceMessenger.Default);
15+
collection.AddSingleton<IEngineService, EngineService>();
16+
17+
//ViewModels
18+
collection.AddTransient<CustomSplashScreenViewModel>();
19+
collection.AddSingleton<MainViewModel>();
20+
collection.AddTransient<HomePageViewModel>();
21+
collection.AddTransient<SettingsViewModel>();
22+
23+
// Views
24+
collection.AddTransient<CustomSplashScreenView>();
25+
collection.AddSingleton<MainView>();
26+
collection.AddTransient<HomePageView>();
27+
collection.AddTransient<SettingsView>();
28+
}
29+
}
30+
}

Panzerfaust/Helpers/ImageHelper.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.IO;
3+
using System.Net.Http;
4+
using System.Net.Http.Headers;
5+
using System.Reflection;
6+
using System.Threading.Tasks;
7+
using Avalonia.Media.Imaging;
8+
using Avalonia.Platform;
9+
10+
namespace Panzerfaust.Helpers
11+
{
12+
public static class ImageHelper
13+
{
14+
public static Bitmap LoadFromResource(string resourcePath)
15+
{
16+
Uri resourceUri;
17+
if (!resourcePath.StartsWith("avares://"))
18+
{
19+
var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name;
20+
resourceUri = new Uri($"avares://{assemblyName}/{resourcePath.TrimStart('/')}");
21+
}
22+
else
23+
{
24+
resourceUri = new Uri(resourcePath);
25+
}
26+
return new Bitmap(AssetLoader.Open(resourceUri));
27+
}
28+
29+
public static async Task<Bitmap?> LoadFromWeb(string resourcePath)
30+
{
31+
var uri = new Uri(resourcePath);
32+
using var httpClient = new HttpClient();
33+
try
34+
{
35+
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AvaloniaTest", "0.1"));
36+
var data = await httpClient.GetByteArrayAsync(uri);
37+
return new Bitmap(new MemoryStream(data));
38+
}
39+
catch (HttpRequestException ex)
40+
{
41+
Console.WriteLine($"An error occurred while downloading image '{uri}' : {ex.Message}");
42+
return null;
43+
}
44+
}
45+
}
46+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Panzerfaust.Models
9+
{
10+
public class DefaultImportDir
11+
{
12+
13+
[JsonProperty("textureDir")]
14+
public string TextureDir { get; set; }
15+
16+
[JsonProperty("soundDir")]
17+
public string SoundDir { get; set; }
18+
}
19+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Panzerfaust.Models
8+
{
9+
public record ListItemTemplate(Type ModelType, string IconKey, string Label);
10+
}

Panzerfaust/Models/Project.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Panzerfaust.Models
9+
{
10+
public class Project
11+
{
12+
[JsonProperty("projectName")]
13+
public string ProjectName { get; set; }
14+
15+
[JsonProperty("version")]
16+
public string Version { get; set; }
17+
18+
[JsonProperty("workingSpace")]
19+
public string WorkingSpace { get; set; }
20+
21+
[JsonProperty("defaultImportDir")]
22+
public DefaultImportDir DefaultImportDir { get; set; }
23+
24+
[JsonProperty("sceneDir")]
25+
public string SceneDir { get; set; }
26+
27+
[JsonProperty("sceneDataDir")]
28+
public string SceneDataDir { get; set; }
29+
30+
[JsonProperty("sceneList")]
31+
public IList<SceneList> SceneList { get; set; }
32+
}
33+
}

Panzerfaust/Models/SceneList.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Panzerfaust.Models
9+
{
10+
public class SceneList
11+
{
12+
13+
[JsonProperty("name")]
14+
public string Name { get; set; }
15+
16+
[JsonProperty("isDefault")]
17+
public bool IsDefault { get; set; }
18+
}
19+
}

Panzerfaust/Panzerfaust.csproj

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup Condition= " $([MSBuild]::IsOSPlatform('Windows')) == 'true' ">
4-
<OutputType>Exe</OutputType>
3+
<PropertyGroup Condition=" $([MSBuild]::IsOSPlatform('Windows')) == 'true' ">
4+
<OutputType>WinExe</OutputType>
55
<TargetFramework>net8.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
<BaseOutputPath>..\Result.Windows.x64.MultiConfig\Panzerfaust</BaseOutputPath>
9+
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
10+
<ApplicationIcon>./Assets/avalonia-logo.ico</ApplicationIcon>
911
</PropertyGroup>
1012
<PropertyGroup Condition=" $([MSBuild]::IsOSPlatform('Windows')) == 'true' AND '$(Configuration)|$(Platform)' == 'Debug|x64' ">
1113
<PlatformTarget>x64</PlatformTarget>
@@ -23,4 +25,31 @@
2325
<OutputPath>..\Result.Windows.$(Platform).MultiConfig\Panzerfaust\$(Configuration)</OutputPath>
2426
<DefineConstants>TRACE</DefineConstants>
2527
</PropertyGroup>
28+
<PropertyGroup>
29+
<ApplicationManifest>app.manifest</ApplicationManifest>
30+
</PropertyGroup>
31+
32+
<ItemGroup>
33+
<PackageReference Include="Avalonia" Version="11.0.2" />
34+
<PackageReference Include="Avalonia.Desktop" Version="11.0.2" />
35+
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.2" />
36+
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.2" />
37+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
38+
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.2" />
39+
40+
41+
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
42+
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.2" />
43+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
44+
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc2" />
45+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
46+
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
47+
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc2" />
48+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
49+
50+
</ItemGroup>
51+
52+
<ItemGroup>
53+
<Folder Include="Assets\Images\" />
54+
</ItemGroup>
2655
</Project>

0 commit comments

Comments
 (0)