Wasabi Engine initialisation and initial layout.
MODIFY
WalletWasabi.Fluent.Desktop/Program.cs
WalletWasabi.Fluent.Desktop/Program.cs
using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Dialogs;
using Avalonia.ReactiveUI;
+using Avalonia.Threading;
+using Splat;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using WalletWasabi.Fluent.ViewModels;
+using WalletWasabi.Gui;
+using WalletWasabi.Gui.CommandLine;
+using WalletWasabi.Gui.CrashReport;
+using WalletWasabi.Gui.ViewModels;
+using WalletWasabi.Helpers;
+using WalletWasabi.Logging;
+using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.Desktop
{
public class Program
{
+ private static Global Global;
+
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
- public static void Main(string[] args) => BuildAvaloniaApp()
+ public static void Main(string[] args)
+ {
+ bool runGui = false;
+ try
+ {
+ Global = CreateGlobal();
+
+ Locator.CurrentMutable.RegisterConstant(Global);
+
+ //Platform.BaseDirectory = Path.Combine(Global.DataDir, "Gui");
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+ TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
+
+ runGui = ShouldRunGui(args);
+
+ if (Global.CrashReporter.IsReport)
+ {
+ StartCrashReporter(args);
+ return;
+ }
+
+ if (runGui)
+ {
+ Logger.LogSoftwareStarted("Wasabi GUI");
+
+ BuildAvaloniaApp()
+ .AfterSetup(_ =>
+ {
+ AppMainAsync(args);
+ })
.StartWithClassicDesktopLifetime(args);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogCritical(ex);
+ Global.CrashReporter.SetException(ex);
+ throw;
+ }
+ finally
+ {
+ DisposeAsync().GetAwaiter().GetResult();
+ }
+ }
+
+ private static Global CreateGlobal()
+ {
+ string dataDir = EnvironmentHelpers.GetDataDir(Path.Combine("WalletWasabi", "Client"));
+ Directory.CreateDirectory(dataDir);
+ string torLogsFile = Path.Combine(dataDir, "TorLogs.txt");
+
+ var uiConfig = new UiConfig(Path.Combine(dataDir, "UiConfig.json"));
+ uiConfig.LoadOrCreateDefaultFile();
+ var config = new Config(Path.Combine(dataDir, "Config.json"));
+ config.LoadOrCreateDefaultFile();
+ config.CorrectMixUntilAnonymitySet();
+ var walletManager = new WalletManager(config.Network, new WalletDirectories(dataDir));
+
+ return new Global(dataDir, torLogsFile, config, uiConfig, walletManager);
+ }
+
+ private static bool ShouldRunGui(string[] args)
+ {
+ var daemon = new Daemon(Global);
+ var interpreter = new CommandInterpreter(Console.Out, Console.Error);
+ var executionTask = interpreter.ExecuteCommandsAsync(
+ args,
+ new MixerCommand(daemon),
+ new PasswordFinderCommand(Global.WalletManager),
+ new CrashReportCommand(Global.CrashReporter));
+ return executionTask.GetAwaiter().GetResult();
+ }
+
+ private static async void AppMainAsync(string[] args)
+ {
+ try
+ {
+ var statusBarViewModel = new StatusBarViewModel(Global.DataDir, Global.Network, Global.Config, Global.HostedServices, Global.BitcoinStore.SmartHeaderChain, Global.Synchronizer, Global.LegalDocuments);
+ //MainWindowViewModel.Instance = new MainWindowViewModel(Global.Network, Global.UiConfig, Global.WalletManager, statusBarViewModel, IoC.Get<IShell>());
+
+ await Global.InitializeNoWalletAsync();
+
+ MainViewModel.Instance.Initialize();
+
+ Dispatcher.UIThread.Post(GC.Collect);
+ }
+ catch (Exception ex)
+ {
+ if (!(ex is OperationCanceledException))
+ {
+ Logger.LogCritical(ex);
+ Global.CrashReporter.SetException(ex);
+ }
+
+ await DisposeAsync();
+
+ // There is no other way to stop the creation of the WasabiWindow.
+ Environment.Exit(1);
+ }
+ }
+
+ private static async Task DisposeAsync()
+ {
+ var disposeGui = MainWindowViewModel.Instance is { };
+ if (disposeGui)
+ {
+ MainWindowViewModel.Instance.Dispose();
+ }
+
+ if (Global?.CrashReporter?.IsInvokeRequired is true)
+ {
+ // Trigger the CrashReport process.
+ Global.CrashReporter.TryInvokeCrashReport();
+ }
+
+ if (Global is { } global)
+ {
+ await global.DisposeAsync().ConfigureAwait(false);
+ }
+
+ AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
+ TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException;
+
+ if (disposeGui)
+ {
+ Logger.LogSoftwareStopped("Wasabi GUI");
+ }
+ }
+
+ private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
+ {
+ Logger.LogWarning(e?.Exception);
+ }
+
+ private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ Logger.LogWarning(e?.ExceptionObject as Exception);
+ }
+
+ private static void StartCrashReporter(string[] args)
+ {
+ var result = AppBuilder.Configure<CrashReportApp>().UseReactiveUI();
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ result
+ .UseWin32()
+ .UseSkia();
+ }
+ else
+ {
+ result.UsePlatformDetect();
+ }
+
+ result
+ .With(new Win32PlatformOptions { AllowEglInitialization = false, UseDeferredRendering = true })
+ .With(new X11PlatformOptions { UseGpu = false, WmClass = "Wasabi Wallet Crash Reporting" })
+ .With(new AvaloniaNativePlatformOptions { UseDeferredRendering = true, UseGpu = false })
+ .With(new MacOSPlatformOptions { ShowInDock = true });
+
+ result.StartWithClassicDesktopLifetime(args);
+ }
// Avalonia configuration, don't remove; also used by visual designer.
- public static AppBuilder BuildAvaloniaApp()
- => AppBuilder.Configure<App>()
- .UsePlatformDetect()
- .LogToDebug()
- .UseReactiveUI();
+ private static AppBuilder BuildAvaloniaApp()
+ {
+ bool useGpuLinux = true;
+
+ var result = AppBuilder.Configure<App>(()=>new App(Global));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ result
+ .UseWin32()
+ .UseSkia();
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ result.UsePlatformDetect()
+ .UseManagedSystemDialogs<AppBuilder, Window>();
+ }
+ else
+ {
+ result.UsePlatformDetect();
+ }
+
+ return result
+ .With(new Win32PlatformOptions { AllowEglInitialization = true, UseDeferredRendering = true })
+ .With(new X11PlatformOptions { UseGpu = useGpuLinux, WmClass = "Wasabi Wallet" })
+ .With(new AvaloniaNativePlatformOptions { UseDeferredRendering = true, UseGpu = true })
+ .With(new MacOSPlatformOptions { ShowInDock = true });
+ }
}
}

MODIFY
WalletWasabi.Fluent.Desktop/WalletWasabi.Fluent.Desktop.csproj
WalletWasabi.Fluent.Desktop/WalletWasabi.Fluent.Desktop.csproj
<Authors>nopara73;lontivero;danwalmsley</Authors>
<Company>zkSNACKs</Company>
<NeutralLanguage>en-US</NeutralLanguage>
- <AssemblyTitle>Wasabi Wallet</AssemblyTitle>
+ <AssemblyTitle>Wasabi Wallet Fluent</AssemblyTitle>
<Description>
Open-source, non-custodial, privacy focused Bitcoin wallet for Windows, Linux, and Mac. Built-in Tor, CoinJoin, PayJoin and coin control features.
</Description>
<Copyright>MIT</Copyright>
- <PackageId>Wasabi Wallet</PackageId>
+ <PackageId>Wasabi Wallet Fluent</PackageId>
<AssemblyTitle>Privacy focused Bitcoin wallet.</AssemblyTitle>
<Company>zkSNACKs</Company>
<PackageTags>bitcoin-wallet;privacy;bitcoin;dotnet;nbitcoin;cross-platform;zerolink;wallet;tumbler;coin;tor</PackageTags>
<RepositoryUrl>https://github.com/zkSNACKs/WalletWasabi/</RepositoryUrl>
<ApplicationIcon>Assets\WasabiLogo.ico</ApplicationIcon>
<PackageIcon>Assets\WasabiLogo.ico</PackageIcon>
- <Product>Wasabi Wallet</Product>
+ <Product>Wasabi Wallet Fluent</Product>
<!-- owners is not supported in MSBuild -->
</PropertyGroup>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WalletWasabi.Fluent\WalletWasabi.Fluent.csproj" />
+ <ProjectReference Include="..\WalletWasabi.Gui\WalletWasabi.Gui.csproj" />
+ <ProjectReference Include="..\WalletWasabi\WalletWasabi.csproj" />
</ItemGroup>
</Project>

MODIFY
WalletWasabi.Fluent/App.xaml.cs
WalletWasabi.Fluent/App.xaml.cs
using Avalonia;
+using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using WalletWasabi.Fluent.ViewModels;
using WalletWasabi.Fluent.Views;
+using Global = WalletWasabi.Gui.Global;
namespace WalletWasabi.Fluent
{
public class App : Application
{
+ private Global _global;
+
+ public App()
+ {
+ Name = "Wasabi Wallet";
+ }
+
+ public App(Global global) : this()
+ {
+ _global = global;
+ }
+
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@@ -15,13 +29,18 @@ namespace WalletWasabi.Fluent
public override void OnFrameworkInitializationCompleted()
{
+ if (!Design.IsDesignMode)
+ {
+ MainViewModel.Instance = new MainViewModel(_global);
+
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
- DataContext = new MainWindowViewModel(),
+ DataContext = MainViewModel.Instance
};
}
+ }
base.OnFrameworkInitializationCompleted();
}

ADD
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
+using NBitcoin;
+using NBitcoin.Protocol;
+using ReactiveUI;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using WalletWasabi.Gui.ViewModels;
+using Global = WalletWasabi.Gui.Global;
+
+namespace WalletWasabi.Fluent.ViewModels
+{
+ public class MainViewModel : ViewModelBase
+ {
+ private Global _global;
+ private StatusBarViewModel _statusBar;
+ private string _title = "Wasabi Wallet";
+
+ public static MainViewModel Instance { get; internal set; }
+
+ public MainViewModel(Global global)
+ {
+ _global = global;
+
+ Network = global.Network;
+
+ StatusBar = new StatusBarViewModel(global.DataDir, global.Network, global.Config, global.HostedServices, global.BitcoinStore.SmartHeaderChain, global.Synchronizer, global.LegalDocuments);
+ }
+
+ public void Initialize()
+ {
+ StatusBar.Initialize(_global.Nodes.ConnectedNodes);
+
+ if (Network != Network.Main)
+ {
+ Title += $" - {Network}";
+ }
+ }
+
+ public Network Network { get; }
+
+ public StatusBarViewModel StatusBar
+ {
+ get { return _statusBar; }
+ set { this.RaiseAndSetIfChanged(ref _statusBar, value); }
+ }
+
+ public string Title
+ {
+ get => _title;
+ internal set => this.RaiseAndSetIfChanged(ref _title, value);
+ }
+ }
+}

MODIFY
WalletWasabi.Fluent/Views/MainView.axaml
WalletWasabi.Fluent/Views/MainView.axaml
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:local="clr-namespace:WalletWasabi.Fluent.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="WalletWasabi.Fluent.Views.MainView">
- <TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
+ x:Class="WalletWasabi.Fluent.Views.MainView" TextBlock.Foreground="#A3A3A3">
+ <SplitView OpenPaneLength="220" CompactPaneLength="20" IsPaneOpen="True" DisplayMode="CompactInline">
+ <SplitView.Pane>
+ <ExperimentalAcrylicBorder DockPanel.Dock="Left">
+ <ExperimentalAcrylicBorder.Material>
+ <ExperimentalAcrylicMaterial BackgroundSource="Digger"
+ TintColor="Black"
+ TintOpacity="1"
+ FallbackColor="#1F1F1F"
+ MaterialOpacity="0.6" />
+ </ExperimentalAcrylicBorder.Material>
+
+ <Panel>
+ <!-- TODO Move to SideBar -->
+ <StackPanel Margin="20">
+ <TextBlock Text=" " Foreground="White" FontSize="22" />
+ <TextBlock Text="Wasabi Wallet" Foreground="White" FontSize="16" />
+ </StackPanel>
+ </Panel>
+ </ExperimentalAcrylicBorder>
+ </SplitView.Pane>
+ <DockPanel>
+ <local:StatusBar DockPanel.Dock="Bottom" DataContext="{Binding StatusBar}" VerticalAlignment="Bottom" Height="32" TextBlock.FontSize="12" />
+ <Border Background="#212121" BoxShadow="0 1 4 #131313" />
+ </DockPanel>
+ </SplitView>
</UserControl>

MODIFY
WalletWasabi.Fluent/Views/MainWindow.xaml
WalletWasabi.Fluent/Views/MainWindow.xaml
ExtendClientAreaChromeHints="PreferSystemChrome"
Title="Wasabi Wallet">
- <Design.DataContext>
- <vm:MainWindowViewModel/>
- </Design.DataContext>
+ <Window.Resources>
+ <FontFamily x:Key="ContentControlThemeFontFamily">Segoe UI</FontFamily>
+ </Window.Resources>
<Panel Margin="{Binding #MainWindow.OffScreenMargin}">
<local:MainView />

ADD
WalletWasabi.Fluent/Views/StatusBar.axaml
+<UserControl xmlns="https://github.com/avaloniaui"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:behaviors="clr-namespace:WalletWasabi.Gui.Behaviors;assembly=WalletWasabi.Gui"
+ xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
+ xmlns:converters="clr-namespace:WalletWasabi.Gui.Converters;assembly=WalletWasabi.Gui"
+ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ x:Class="WalletWasabi.Fluent.Views.StatusBar">
+ <UserControl.Resources>
+ <converters:FilterLeftStatusConverter x:Key="FilterLeftStatusConverter" />
+ <converters:ShowCursorConverter x:Key="ShowCursorConverter" />
+ <converters:ShouldDisplayValueConverter x:Key="ShouldDisplayValueConverter" />
+ <converters:PascalToPhraseConverter x:Key="PascalToPhraseConverter" />
+ <converters:RpcStatusStringConverter x:Key="RpcStatusStringConverter" />
+ </UserControl.Resources>
+ <Panel Background="#191919" Cursor="{Binding UpdateAvailable, Converter={StaticResource ShowCursorConverter}}">
+ <!--
+ <i:Interaction.Behaviors>
+ <behaviors:CommandOnClickBehavior Command="{Binding UpdateCommand}" />
+ </i:Interaction.Behaviors>-->
+
+ <!--
+ <Panel Background="IndianRed" IsVisible="{Binding CriticalUpdateAvailable}" />-->
+
+ <DockPanel LastChildFill="True" Margin="20 0" VerticalAlignment="Center">
+ <StackPanel Orientation="Horizontal" Spacing="20" DockPanel.Dock="Right" IsVisible="{Binding !CriticalUpdateAvailable}">
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <TextBlock Text="{Binding ShowNetwork}" />
+ </StackPanel>
+ <Panel IsVisible="{Binding DownloadingBlock}">
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_DownloadingBlock}" />
+ </Panel>
+ <TextBlock Text="Downloading a block..." />
+ </StackPanel>
+ </Panel>
+ <Panel IsVisible="{Binding FiltersLeft, Converter={StaticResource ShouldDisplayValueConverter}}">
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_Filter}" />
+ </Panel>
+ <TextBlock Text="{Binding FiltersLeft, Converter={StaticResource FilterLeftStatusConverter}}" />
+ </StackPanel>
+ </Panel>
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_GlobeCheckedShield}" />
+ </Panel>
+ <TextBlock Text="{Binding Tor, StringFormat=Tor is \{0\}, Converter={StaticResource PascalToPhraseConverter}}" />
+ </StackPanel>
+ <Panel IsVisible="{Binding UseBitcoinCore}">
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_ServerGlobe}" />
+ </Panel>
+ <TextBlock Text="{Binding BitcoinCoreStatus, Converter={StaticResource RpcStatusStringConverter}}" />
+ </StackPanel>
+ </Panel>
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_ServerGlobe}" />
+ </Panel>
+ <TextBlock Text="{Binding Backend, StringFormat=Backend is \{0\}, Converter={StaticResource PascalToPhraseConverter}}" />
+ </StackPanel>
+ <Panel IsVisible="{Binding !UseBitcoinCore}">
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel Height="10" Width="10">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_Peer}" />
+ </Panel>
+ <TextBlock Text="{Binding Peers, StringFormat=Peers: \{0\}}" />
+ </StackPanel>
+ </Panel>
+ <StackPanel IsVisible="{Binding IsExchangeRateAvailable}" Orientation="Horizontal" Spacing="0">
+ <TextBlock Text="BTC/USD: " />
+ <TextBlock Text="{Binding ExchangeRate}" />
+ </StackPanel>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Spacing="4">
+ <Panel IsVisible="{Binding !CriticalUpdateAvailable}">
+ <Panel Height="10" Width="10" IsVisible="{Binding UpdateAvailable}">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_GreenFlag}" />
+ </Panel>
+ </Panel>
+ <Panel Height="10" Width="10" IsVisible="{Binding CriticalUpdateAvailable}">
+ <DrawingPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Drawing="{DynamicResource StatusBar_YellowFlag}" />
+ </Panel>
+ <TextBlock Text="{Binding Status}" />
+ </StackPanel>
+ </DockPanel>
+ </Panel>
+</UserControl>

MODIFY
WalletWasabi.Fluent/WalletWasabi.Fluent.csproj
WalletWasabi.Fluent/WalletWasabi.Fluent.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFramework>netstandard2.0</TargetFramework>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Update="**\*.xaml.cs">
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.999-cibuild0010848-beta" />
+ <PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.0-preview5" />
+ <PackageReference Include="Avalonia.Xaml.Interactions.Custom" Version="0.10.0-preview5" />
+ <PackageReference Include="Avalonia.Xaml.Interactivity" Version="0.10.0-preview5" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\WalletWasabi.Gui\WalletWasabi.Gui.csproj" />
+ <ProjectReference Include="..\WalletWasabi\WalletWasabi.csproj" />
</ItemGroup>
</Project>

MODIFY
WalletWasabi.sln
WalletWasabi.sln
@@ -32,6 +32,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalletWasabi.Packager", "Wa
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "WalletWasabi.WindowsInstaller", "WalletWasabi.WindowsInstaller\WalletWasabi.WindowsInstaller.wixproj", "{54654468-4F58-4253-84BD-6F53A8D3D2C4}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalletWasabi.Fluent", "WalletWasabi.Fluent\WalletWasabi.Fluent.csproj", "{F82339B4-DADE-4C95-9FD1-C4EB53623B5E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalletWasabi.Fluent.Desktop", "WalletWasabi.Fluent.Desktop\WalletWasabi.Fluent.Desktop.csproj", "{9E31DD9E-2E33-4FE7-991E-7A4054460E14}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -84,7 +88,23 @@ Global
{54654468-4F58-4253-84BD-6F53A8D3D2C4}.Debug|x64.ActiveCfg = Release|x64
{54654468-4F58-4253-84BD-6F53A8D3D2C4}.Release|Any CPU.ActiveCfg = Release|x64
{54654468-4F58-4253-84BD-6F53A8D3D2C4}.Release|x64.ActiveCfg = Release|x64
- {54654468-4F58-4253-84BD-6F53A8D3D2C4}.Release|x64.Build.0 = Debug|x64
+ {54654468-4F58-4253-84BD-6F53A8D3D2C4}.Release|x64.Build.0 = Release|x64
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Debug|x64.Build.0 = Debug|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Release|x64.ActiveCfg = Release|Any CPU
+ {F82339B4-DADE-4C95-9FD1-C4EB53623B5E}.Release|x64.Build.0 = Release|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Debug|x64.Build.0 = Debug|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Release|x64.ActiveCfg = Release|Any CPU
+ {9E31DD9E-2E33-4FE7-991E-7A4054460E14}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Wasabi Engine initialisation and initial layout.