View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0005177 | NoesisGUI | Unity | public | 2026-08-20 19:23 | 2026-08-20 20:16 |
| Reporter | stonstad | Assigned To | |||
| Priority | normal | Severity | major | ||
| Status | new | Resolution | open | ||
| Product Version | 4.0 | ||||
| Summary | 0005177: 4.0 RC5. AssetDependency Fails After Subsequent Stop/Play Cycle | ||||
| Description | I am seeing AssetDependency attribute resolution fail after Unity playback stops and is restarted. 1) Play -> Stop -> Play generates XAML errors. Note that first time playback works and no XAML errors are generated on Unity import. These are runtime errors that occur on second playback only. [NOESIS] Xaml not found 'Assets/User Interface/Screens/Title/TitleScreen.xaml' Unity 6.5.7f1. | ||||
| Attached Files | TitleScreen.xaml (6,445 bytes)
<UserControl
x:Class="StellarConquest.Presentation.Unity.UI.TitleScreen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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" mc:Ignorable="d"
xmlns:noesis="clr-namespace:NoesisGUIExtensions"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:StellarConquest.Presentation.Unity.UI"
d:DesignWidth="1280" d:DesignHeight="720">
<Grid>
<Viewbox x:Name="LoginScreenViewBox">
<local:ViewboxGridControl x:Name="_LayoutRoot">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="6*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="_LoginStackPanel" Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<local:ButtonPanelControl x:Name="_ButtonPanelControl" VerticalAlignment="Center" Margin="0, -35, 20, 0"/>
<StackPanel x:Name="_NewsStackPanel1" Orientation="Vertical" VerticalAlignment="Center">
<local:NewsControl x:Name="_NewsControl1" Margin="0, 0, 0, 20"/>
<local:SocialMediaPanelControl x:Name="_SocialMediaPanelControl"/>
</StackPanel>
<StackPanel x:Name="_NewsStackPanel2" Orientation="Vertical" VerticalAlignment="Center" Visibility="Collapsed">
<local:NewsControl x:Name="_NewsControl2" Margin="0, 0, 0, 20"/>
<Grid Height="50"/>
</StackPanel>
</StackPanel>
<TextBlock x:Name="_Handle" Grid.Row="2" HorizontalAlignment="Right" FontFamily="{StaticResource Teko}" FontSize="35" VerticalAlignment="Bottom" Foreground="White" Opacity="0.9" Margin="0, 0, 60, 35"/>
<TextBlock x:Name="_VersionTextBlock" Grid.Row="2" HorizontalAlignment="Center" FontFamily="{StaticResource Teko}" FontSize="22" VerticalAlignment="Bottom" Foreground="White" Opacity="0.7" Margin="0, 0, 0, 40"/>
</Grid>
<StackPanel x:Name="_SecondaryScreenStackPanel" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Grid x:Name="_PreviewGrid" Background="Transparent" Opacity="0" Visibility="Collapsed">
<Grid Background="#99000000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Grid HorizontalAlignment="Center" VerticalAlignment="Stretch">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<b:Interaction.Behaviors>
<noesis:BackgroundEffectBehavior Source="{DynamicResource BaseBlurSource}">
<BlurEffect Radius="{Binding Radius, Source={StaticResource TopBlurRadius}}"/>
</noesis:BackgroundEffectBehavior>
</b:Interaction.Behaviors>
</Border>
<Grid Background="#AA000000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Rectangle Fill="#66777777" Width="2" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
<Rectangle Fill="#66777777" Width="2" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="50, -50, 50, 50">
<Viewbox Width="600" Margin="-10, 0, -10, 15">
<Grid>
<Grid.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="3" Opacity="1"/>
</Grid.Effect>
<Image x:Name="_LogoEllipse" Source="{StaticResource ellipse}" Width="550" Stretch="Uniform" Margin="0, 0, 0, 100"/>
<TextBlock x:Name="_LogoText" HorizontalAlignment="Center" FontFamily="{StaticResource Agency}" FontSize="95" VerticalAlignment="Bottom" Margin="0, 0, 0, 0" Foreground="White" Opacity="0.9" noesis:Text.CharacterSpacing="350" Text="STELLAR CONQUEST"/>
</Grid>
</Viewbox>
<StackPanel Orientation="Vertical" MaxWidth="500" Effect="{StaticResource UIDropShadow}">
<TextBlock FontFamily="{StaticResource Teko}" FontSize="40" FontWeight="Normal" HorizontalAlignment="Center" Margin="0, 0, 0, 95">PREVIEW</TextBlock>
<TextBlock FontFamily="{StaticResource DefaultFontFamily}" FontSize="30" FontWeight="Normal" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Margin="0, 0, 0, 35">This is an unfinished version of the game. You might encounter broken or missing parts.</TextBlock>
<TextBlock FontFamily="{StaticResource DefaultFontFamily}" FontSize="30" FontWeight="Normal" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Margin="0, 0, 0, 35">Saved galaxies won't work with the final release version.</TextBlock>
<TextBlock FontFamily="{StaticResource HeadingFontFamily}" FontSize="30" FontWeight="Bold" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" Margin="0, 0, 0, 0">Press any key or button to start</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</Grid>
</local:ViewboxGridControl>
</Viewbox>
</Grid>
</UserControl> TitleScreen.xaml.cs (15,733 bytes)
using Noesis;
using StellarConquest.Model.Actions;
using StellarConquest.Model.Authentication;
using StellarConquest.Model.Core;
using StellarConquest.Model.Performance;
using StellarConquest.Model.Platform;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using EventArgs = Noesis.EventArgs;
using Grid = Noesis.Grid;
using GUI = Noesis.GUI;
using Task = System.Threading.Tasks.Task;
namespace StellarConquest.Presentation.Unity.UI
{
[AssetDependency]
public partial class TitleScreen : UserControl, IGameScreenPrimary, IGameScreenInputProvider
{
private bool _IsPlayerServerError = false;
private bool _IsGameServerError = false;
private bool _IsSystemServerError = false;
private bool _IsServiceAuthenticationError = false;
private string _GameNews;
private Statistics _Statistics = new Statistics();
public List<AuthenticatedPlayer> _Players = null;
private FrameworkElement _Root;
private Grid _LayoutRoot;
private StackPanel _NewsStackPanel1;
private NewsControl _NewsControl1;
private StackPanel _NewsStackPanel2;
private NewsControl _NewsControl2;
private StackPanel _SecondaryScreenStackPanel;
private ServerControl _ServerControl;
private ServerListControl _ServerListControl;
private LocalizationControl _LocalizationControl;
private ButtonPanelControl _ButtonPanelControl;
private TextBlock _VersionTextBlock;
private TextBlock _Handle;
public bool IsCursorOverUI { get { return false; } }
private Grid _PreviewGrid;
private static bool _PreviewGridShown = false;
public TitleScreen()
{
Initialized += OnInitialized;
InitializeComponent();
}
private void InitializeComponent()
{
GUI.LoadComponent(this, "Assets/User Interface/Screens/Title/TitleScreen.xaml");
_Root = Content as FrameworkElement;
_LayoutRoot = _Root.FindName(nameof(_LayoutRoot)) as Grid;
_NewsStackPanel1 = _Root.FindName(nameof(_NewsStackPanel1)) as StackPanel;
_NewsControl1 = _Root.FindName(nameof(_NewsControl1)) as NewsControl;
_NewsStackPanel2 = _Root.FindName(nameof(_NewsStackPanel2)) as StackPanel;
_NewsControl2 = _Root.FindName(nameof(_NewsControl2)) as NewsControl;
_SecondaryScreenStackPanel = _Root.FindName(nameof(_SecondaryScreenStackPanel)) as StackPanel;
_ButtonPanelControl = _Root.FindName(nameof(_ButtonPanelControl)) as ButtonPanelControl;
_VersionTextBlock = _Root.FindName(nameof(_VersionTextBlock)) as TextBlock;
_Handle = _Root.FindName(nameof(_Handle)) as TextBlock;
_PreviewGrid = _Root.FindName(nameof(_PreviewGrid)) as Grid;
_LayoutRoot.Visibility = Visibility.Collapsed;
}
private void OnInitialized(object sender, EventArgs args)
{
if (!Application.isPlaying)
return;
RegisterEvents();
// TODO: enable and test account id caching feature when Steam is down.
//var result = PlayerPreferences.Instance.GetPreviousAccount();
//if (result.Item1 != null && result.Item2.HasValue)
//{
// SessionState.Instance.AuthenticationToken = new AuthenticationToken(result.Item1);
// SessionState.Instance.AccountId = result.Item2.Value;
//}
_ = Initialize(PlayerPreferences.Instance.ConquestEnvironment, Application.isEditor);
//https://howtomarketagame.com/2021/06/21/neat-ideas-for-your-games-demo/
//TutorialControl tutorialControl = new TutorialControl();
//string text = "Thank you for playing this alpha build of Stellar Conquest. Please join us on our Discord channel for news about the next play test. See you for the next update!" + Environment.NewLine + Environment.NewLine;
//tutorialControl.SetText("Build Expired", false, text);
//tutorialControl.Show();
if (!_PreviewGridShown)
{
_PreviewGrid.Visibility = Visibility.Visible;
_PreviewGrid.FadeInScreen(this);
_PreviewGridShown = true;
}
}
public async Task Initialize(EnvironmentType cloudEnvironment, bool isEditor)
{
UnityDispatcher.Instance.Invoke(() =>
{
_Handle.Text = string.Empty;
ChatBuffer.Instance.Execute(new ChatAction() { Clear = true });
});
_IsSystemServerError = false;
_IsGameServerError = false;
try
{
await NetworkClient.Instance.Initialize(cloudEnvironment, true, isEditor);
_IsSystemServerError = !await NetworkClient.Instance.TestSystemServerHttpConnection(GameStateMachine.Instance.CancellationTokenSource.Token);
if (!_IsSystemServerError)
{
var taskA = GameServices.Instance.InitializeGameService(); // initialize Steam or XBL and create Stellar Conquest authorization token
var taskB = GetGameServerVersion();
var taskC = GetGameNewsAsync();
// initialize game services
await taskA;
_IsServiceAuthenticationError = !taskA.Result;
if (!_IsServiceAuthenticationError && !_IsSystemServerError)
{
var taskD = GetCloudLicenseAsync(); // get license using game service authorization token
await taskD;
}
if (taskB != null)
await taskB;
if (taskC != null)
await taskC;
}
UnityDispatcher.Instance.Invoke(() => FadeInUI());
}
catch (TaskCanceledException)
{
}
catch (Exception e)
{
Debug.LogError(e);
_IsSystemServerError = true;
}
#if (UNITY_STANDALONE_WIN)
if (!Application.isEditor && Constants.System.Build == "Debug")
UIStateMachine.Instance.UIShowMessage("Build Error", "Warning: DEBUG library detected in RELEASE build.");
#endif
if (_IsServiceAuthenticationError)
{
UnityDispatcher.Instance.Invoke(() =>
{
#if(UNITY_STANDALONE_WIN)
_NewsControl1.ShowError("Please launch Steam before playing Stellar Conquest and ensure you have access to this game.");
#else
_NewsControl1.ShowError("A problem occurred while authenticating your account Xbox Live.");
#endif
_ButtonPanelControl.SetPlayButtonText("RETRY");
});
}
else if (_IsSystemServerError)
{
UnityDispatcher.Instance.Invoke(() =>
{
FadeInUI();
_NewsControl1.ShowError($"Stellar Conquest ({PlayerPreferences.Instance.ConquestEnvironment}) " +
"is down for maintenance and will be back up shortly. Please retry again.");
_ButtonPanelControl.SetPlayButtonText("RETRY");
});
}
else if (!_IsSystemServerError)
{
UnityDispatcher.Instance.Invoke(() =>
{
_NewsControl1.Update(_Statistics, _GameNews, null);
if (SessionState.Instance.ClientVersion == SessionState.Instance.ServerVersion)
_ButtonPanelControl.SetConquestButtonEnabled(SessionState.Instance.HasLicense && !_IsSystemServerError && !_IsGameServerError);
else
_ButtonPanelControl.SetConquestButtonEnabled(false);
});
}
}
private async Task Login()
{
CheckedResponse<List<AuthenticatedPlayer>> result = null;
try
{
// get players
result = await NetworkClient.Instance.GetPlayers();
// get price list
_ = GetPriceListAsync();
}
catch (Exception e)
{
Debug.LogError(e);
result = new CheckedResponse<List<AuthenticatedPlayer>>(null, e.Message);
}
UnityDispatcher.Instance.Invoke(() =>
{
PlayerPreferences.Instance.FPSLogin = Mathf.RoundToInt(GameState.Instance.FrameRateCounter.FPS);
PlayerPreferences.Instance.SavePreferences();
if (result != null && result.Result != null)
{
SessionState.Instance.AuthenticatedPlayers = result.Result;
if (result.Result.Count == 0)
GameStateMachine.Instance.SetState(GameStateType.CharacterCreation);
else
GameStateMachine.Instance.SetState(GameStateType.CharacterSelection);
RuntimeSettings.Instance.SendTelemetry();
}
else if (result == null || result.Result == null || !string.IsNullOrEmpty(result.Error))
{
ShowPlayOptions();
if (result != null && !string.IsNullOrEmpty(result.Error))
_NewsControl2.ShowError("Login Error: " + result.Error);
else
_NewsControl2.ShowError("Login Error: unable to access account.");
}
});
}
private void ShowPlayOptions()
{
UIStateMachine.Instance.TransitionLayer.ShowLoadingImage(false, false);
_ServerControl = null;
_ServerListControl = null;
_LocalizationControl = null;
_SecondaryScreenStackPanel.Children.Clear();
_ButtonPanelControl.SetPlayButtonEnabled(true);
_ButtonPanelControl.SetPlayButtonText("PLAY");
_NewsStackPanel1.Visibility = Visibility.Collapsed;
_NewsStackPanel2.Visibility = Visibility.Visible;
_ButtonPanelControl.Visibility = Visibility.Visible;
_ButtonPanelControl.ShowPlayOptions();
_Handle.Visibility = Visibility.Collapsed;
_VersionTextBlock.Visibility = Visibility.Collapsed;
}
private void ShowTitleOptions()
{
UIStateMachine.Instance.TransitionLayer.ShowLoadingImage(false, false);
_NewsStackPanel1.Visibility = Visibility.Visible;
_NewsStackPanel2.Visibility = Visibility.Collapsed;
_ButtonPanelControl.Visibility = Visibility.Visible;
if (_ServerControl != null)
_ServerControl.Visibility = Visibility.Collapsed;
if (_ServerListControl != null)
_ServerListControl.Visibility = Visibility.Collapsed;
_ButtonPanelControl.ShowTitleOptions();
_Handle.Visibility = Visibility.Visible;
_VersionTextBlock.Visibility = Visibility.Visible;
}
private void FadeInUI()
{
if (_LayoutRoot.Visibility == Visibility.Collapsed)
{
_LayoutRoot.Visibility = Visibility.Visible;
_LayoutRoot.FadeInScreen(this);
}
}
private void Shutdown()
{
if (!Application.isEditor)
{
IsHitTestVisible = false;
_ = Task.Run(async () =>
{
try
{
await GameServices.Instance.ShutdownGameService();
if (ServerBootstrap.Instance.IsServerRunning && !ServerBootstrap.Instance.IsDedicatedServer)
await NetworkClient.Instance.GracefulPlayerServerShutdown();
ServerBootstrap.Instance.StopServer(false);
}
catch (Exception e)
{
Debug.Log(e);
}
finally
{
UnityDispatcher.Instance.Invoke(() => Application.Quit());
}
});
}
}
public void UpdateInput()
{
if (_PreviewGrid.Visibility == Visibility.Visible)
if (Input.anyKeyDown || Input.GetMouseButtonDown(0) || Input.GetButton(InputNames.GamePad.A) || Input.GetButton(InputNames.GamePad.B))
{
if (_PreviewGrid.Visibility == Visibility.Visible)
{
_PreviewGrid.FadeOutScreen(this, () => _PreviewGrid.Visibility = Visibility.Collapsed);
return;
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameServerCancellationTokenSource != null)
GameServerCancellationTokenSource.Cancel(false);
else
{
if (_ServerControl != null)
{
_SecondaryScreenStackPanel.Children.Remove(_ServerControl);
_ServerControl = null;
ShowPlayOptions();
}
else if (_ServerListControl != null)
{
_SecondaryScreenStackPanel.Children.Remove(_ServerListControl);
_ServerListControl = null;
ShowPlayOptions();
}
else if (_LocalizationControl != null)
{
_SecondaryScreenStackPanel.Children.Remove(_LocalizationControl);
_LocalizationControl = null;
ShowPlayOptions();
}
else if (_ButtonPanelControl.Visibility == Visibility.Visible && _NewsStackPanel2.Visibility == Visibility.Visible)
{
ShowTitleOptions();
}
else
{
InputControl inputControl = new InputControl("Quit", "Quit Stellar Conquest?", null, InputControlButtonTypes.Yes | InputControlButtonTypes.No);
inputControl.Hidden += (sender, e) =>
{
if (inputControl.Response == InputControlButtonTypes.Yes)
Shutdown();
else
this.FadeInScreen(this);
};
this.FadeOutScreen(this);
inputControl.Show();
}
}
}
#if (UNITY_GAMECORE_XBOXSERIES)
if (Input.GetKeyDown(KeyCode.Alpha1))
_ = Login();
#endif
}
public void UpdateUserInterface()
{
}
}
}
| ||||
| Platform | Any | ||||
|
It is strange. I get these XAML not found errors for two files (TitleScreen and SettingsControl). I can't seem to determine what causes the errors to persist versus go away. Restarting Unity and/or reloading the assets via Import does not resolve the behavior. Second Error: SettingsControl.xaml (64,271 bytes)
<UserControl
x:Class="StellarConquest.Presentation.Unity.UI.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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" mc:Ignorable="d"
xmlns:local="clr-namespace:StellarConquest.Presentation.Unity.UI">
<UserControl.Resources>
<Thickness x:Key="GroupMargin">0, 20, 0, 0</Thickness>
<Thickness x:Key="ScrollViewerMargin">15, 8, 15, 15</Thickness>
<SolidColorBrush x:Key="HeadingBrush" Color="#AAFFFFFF"/>
</UserControl.Resources>
<Grid x:Name="_LayoutRoot">
<local:BorderControlTitle x:Name="_BorderControl" HorizontalAlignment="Center" VerticalAlignment="Center" TitleText="Settings" BlurLayer="{DynamicResource OverlayBlurSource}">
<TabControl x:Name="_TabControl" MinWidth="700" Height="600" Background="#00000000" BorderBrush="#00000000" Margin="30, 20, 25, 20">
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="GAMEPLAY" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Margin="{StaticResource ScrollViewerMargin}" >
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Gameplay Assistance"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_GameHelpUIEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Game Help"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_DesignerHelpUIEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Designer Help"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}" Visibility="Collapsed"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Notifications" Visibility="Collapsed"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" Visibility="Collapsed">
<CheckBox x:Name="_WarnSafeParkingEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Warn if Parking Unsafe"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" Visibility="Collapsed">
<CheckBox x:Name="_WarnEvilEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Warn if Committing Evil"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}" Visibility="Visible"/>
<StackPanel x:Name="_GenerativeAIStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Generative AI"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_GenerativeTextDialogue" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Generative Text Dialogue"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_GenerativeAudioDialogue" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Generative Audio Dialogue"/>
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}" Visibility="Visible"/>
<StackPanel x:Name="_UnitsStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Measurement Units"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="140" Margin="0, 0, 5, 0" Text="Temperature"/>
<ComboBox x:Name="_TemperatureUnits" Width="210">
<ComboBoxItem>Celsius</ComboBoxItem>
<ComboBoxItem>Fahrenheit</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="INPUT" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer VerticalScrollBarVisibility="Visible">
<StackPanel Margin="{StaticResource ScrollViewerMargin}">
<StackPanel x:Name="_DevicesStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Devices"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_GamepadEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Gamepad Enabled"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_MouseConfined" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Confine Mouse"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
</StackPanel>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Character"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Camera Control"/>
<ComboBox x:Name="_CharacterControl" Width="210">
<ComboBoxItem>Default</ComboBoxItem>
<ComboBoxItem>Pivot</ComboBoxItem>
<ComboBoxItem>Cinematic</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Interior Camera"/>
<ComboBox x:Name="_InteriorCamera" Width="210">
<ComboBoxItem>Over the Shoulder</ComboBoxItem>
<ComboBoxItem>First Person</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_CharacterInvertUpEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Character Invert Up"/>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Look Sensitivity"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_CharacterLookSensitivity" Minimum="0.2" Maximum="1.8" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="0.2" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Starship"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_ShipInvertUpEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Starship Invert Up"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="DISPLAY" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<StackPanel x:Name="_ResolutionStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Resolution"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Display"/>
<ComboBox x:Name="_Displays" Width="220"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Resolution"/>
<ComboBox x:Name="_WindowMode" Width="220">
<ComboBoxItem>Fullscreen Exclusive</ComboBoxItem>
<ComboBoxItem>Fullscreen Windowed</ComboBoxItem>
<ComboBoxItem Visibility="Collapsed">Windowed Maximized</ComboBoxItem>
<!-- MacOS -->
<ComboBoxItem>Windowed</ComboBoxItem>
</ComboBox>
<StackPanel x:Name="_DisplayResolutionStackPanel" Width="220" Margin="15, 0, 0, 0">
<ComboBox x:Name="_DisplayResolution"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Upscaling"/>
<ComboBox x:Name="_ResolutionUpscaler" Width="220">
<ComboBoxItem>Off</ComboBoxItem>
<ComboBoxItem>DLSS</ComboBoxItem>
<ComboBoxItem>FSR 3</ComboBoxItem>
<ComboBoxItem>XeSS</ComboBoxItem>
</ComboBox>
<StackPanel x:Name="_UpscalerQualityStackPanel" Width="220" Margin="15, 0, 0, 0">
<ComboBox x:Name="_ResolutionUpscalerQuality" Width="220">
<ComboBoxItem>Ultra Quality</ComboBoxItem>
<ComboBoxItem>Quality</ComboBoxItem>
<ComboBoxItem>Balanced</ComboBoxItem>
<ComboBoxItem>Performance</ComboBoxItem>
<ComboBoxItem>Ultra Performance</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Frame Rate Limit"/>
<ComboBox x:Name="_VSync" Width="220">
<ComboBoxItem>Monitor vSync Off</ComboBoxItem>
<ComboBoxItem>Monitor vSync On</ComboBoxItem>
</ComboBox>
<ComboBox x:Name="_FrameRateLimit" Width="220" Margin="15, 0, 0, 0">
<ComboBoxItem>Unlimited</ComboBoxItem>
<ComboBoxItem>60 FPS</ComboBoxItem>
<ComboBoxItem>120 FPS</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" Visibility="Collapsed">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Motion Blur"/>
<ComboBox x:Name="_MotionBlur" Width="80">
<ComboBoxItem>Off</ComboBoxItem>
<ComboBoxItem>On</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Show FPS"/>
<ComboBox x:Name="_ShowFPS" Width="80">
<ComboBoxItem>Off</ComboBoxItem>
<ComboBoxItem>On</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
</StackPanel>
<StackPanel x:Name="_QualityStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Quality"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Preset"/>
<ToggleButton x:Name="_QualityLow" Content="Low"/>
<ToggleButton x:Name="_QualityMedium" Content="Medium"/>
<ToggleButton x:Name="_QualityHigh" Content="High"/>
<ToggleButton x:Name="_QualityEpic" Content="Epic"/>
<ToggleButton x:Name="_QualityAuto" Content="Auto" Visibility="Collapsed"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="View Distance"/>
<ToggleButton x:Name="_ViewNear" Content="Near"/>
<ToggleButton x:Name="_ViewMedium" Content="Medium"/>
<ToggleButton x:Name="_ViewFar" Content="Far"/>
<ToggleButton x:Name="_ViewEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Shadow Quality"/>
<ToggleButton x:Name="_ShadowsLow" Content="Low"/>
<ToggleButton x:Name="_ShadowsMedium" Content="Medium"/>
<ToggleButton x:Name="_ShadowsHigh" Content="High"/>
<ToggleButton x:Name="_ShadowsEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Shadow Distance"/>
<ToggleButton x:Name="_ShadowDistanceNear" Content="Near"/>
<ToggleButton x:Name="_ShadowDistanceMedium" Content="Medium"/>
<ToggleButton x:Name="_ShadowDistanceFar" Content="Far"/>
<ToggleButton x:Name="_ShadowDistanceEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Textures"/>
<ToggleButton x:Name="_TexturesLow" Content="Low"/>
<ToggleButton x:Name="_TexturesMedium" Content="Medium"/>
<ToggleButton x:Name="_TexturesHigh" Content="High"/>
<ToggleButton x:Name="_TexturesEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Reflections"/>
<ToggleButton x:Name="_ReflectionsOff" Content="Off"/>
<ToggleButton x:Name="_ReflectionsMedium" Content="Medium"/>
<ToggleButton x:Name="_ReflectionsHigh" Content="High"/>
<ToggleButton x:Name="_ReflectionsEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Detail"/>
<ToggleButton x:Name="_DetailLow" Content="Low"/>
<ToggleButton x:Name="_DetailMedium" Content="Medium"/>
<ToggleButton x:Name="_DetailHigh" Content="High"/>
<ToggleButton x:Name="_DetailEpic" Content="Epic"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="145" Margin="15, 0, 5, 0" Text="Post Processing"/>
<ToggleButton x:Name="_PostProcessingLow" Content="Low"/>
<ToggleButton x:Name="_PostProcessingMedium" Content="Medium"/>
<ToggleButton x:Name="_PostProcessingHigh" Content="High"/>
<ToggleButton x:Name="_PostProcessingEpic" Content="Epic"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
</StackPanel>
<StackPanel x:Name="_FieldOfViewStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Field of View"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Character"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_CharacterFieldOfView" Minimum="40" Maximum="120" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="10" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Starship Cockpit"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_CockpitFieldOfView" Minimum="40" Maximum="120" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="10" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Starship External"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_ExternalFieldOfView" Minimum="40" Maximum="120" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="10" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5, 0, 0, 12">
<Button x:Name="_ResetFieldOfViewButton" HorizontalAlignment="Left">
<TextBlock Style="{StaticResource Heading3Primary}">Reset</TextBlock>
</Button>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
</StackPanel>
<StackPanel x:Name="_ColorCorrectionStackPanel">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Color Correction"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Brightness"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_BrightnessSlider" Minimum="-50" Maximum="50" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Contrast"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_ContrastSlider" Minimum="-50" Maximum="50" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5, 0, 0, 12">
<Button x:Name="_ResetColorCorrectionButton" HorizontalAlignment="Left">
<TextBlock Style="{StaticResource Heading3Primary}">Reset</TextBlock>
</Button>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="UI" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Configuration"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_UIEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show User Interface"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_GameMenuEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Game Menu"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_WindowDragEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Allow Window Dragging"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_TargetingEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Targeting"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Scale"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12" VerticalAlignment="Center">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="User Interface"/>
<ToggleButton x:Name="_UISmallest" Content="Smallest"/>
<ToggleButton x:Name="_UISmaller" Content="Smaller"/>
<ToggleButton x:Name="_UINormal" Content="Normal"/>
<ToggleButton x:Name="_UILarger" Content="Larger"/>
<ToggleButton x:Name="_UILargest" Content="Largest"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Effects"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Blur Effects"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_BlurEffectsEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Top Blur"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_TopBlurSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Bottom Blur"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_BottomBlurSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="AUDIO" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Master"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Volume"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_MasterVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_MasterVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Mixer"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Music"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_MusicVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_MusicVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Effects"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_EffectsVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_EffectsVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Voice"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_VoiceVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_VoiceVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="User Interface"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_UIVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_UIVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Text="Ambient"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<CheckBox x:Name="_AmbientVolumeEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center" Width="35"/>
<Slider x:Name="_AmbientVolumeSlider" Minimum="0" Maximum="100" IsSnapToTickEnabled="False" IsMoveToPointEnabled="True" TickFrequency="25" TickPlacement="BottomRight" Width="380" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="_NetworkTab">
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="NETWORK" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Environment"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Right" VerticalAlignment="Center" Width="160" Margin="0, 0, 5, 0" Text="Conquest Server"/>
<ComboBox x:Name="_Environment">
<ComboBoxItem>Developer</ComboBoxItem>
<ComboBoxItem>Preview</ComboBoxItem>
<ComboBoxItem>Release</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Update Rate"/>
<StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock x:Name="_ClientToServerRateTextBlock" Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Margin="0, 0, 0, 2" Text="Client"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_ClientToServerSlider" Minimum="0.0" Maximum="1.0" IsSnapToTickEnabled="true" IsMoveToPointEnabled="True" TickFrequency="0.05" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock x:Name="_ServerToClientRateTextBlock" Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Margin="0, 0, 0, 2" Text="Server"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_ServerToClientSlider" Minimum="0.0" Maximum="1.0" IsSnapToTickEnabled="true" IsMoveToPointEnabled="True" TickFrequency="0.05" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="_CorsairTab">
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="CORSAIR" FontSize="20" Margin="5"/>
</TabItem.Header>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Corsair Lighting"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_RGBLightingEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="RGB Lighting Enabled"/>
</StackPanel>
<TextBlock x:Name="_CorsairNotFoundTextBlock" Margin="0, 16, 0, 0" Style="{StaticResource Heading3Primary}"
Visibility="Collapsed" HorizontalAlignment="Left" Width="625" TextWrapping="Wrap">
Corsair devices could not be detected. Please ensure that iCUE is running and that both iCUE and Game SDK control is enabled.
</TextBlock>
<StackPanel x:Name="_RGBStackPanel">
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Keyboard"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_TutorialKeysEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Tutorial Keys"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 12">
<CheckBox x:Name="_InputKeysEnabled" Margin="0, 0, 5, 0" VerticalAlignment="Center">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Show Input Keys"/>
</StackPanel>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Assignment"/>
<StackPanel x:Name="_CorsairStackPanel" Orientation="Vertical" Margin="0, 0, 0, 0"/>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Color Correction"/>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Margin="0, 0, 0, 2" Text="Hue"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_RGBHueSlider" Minimum="-180" Maximum="180" IsSnapToTickEnabled="false" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Margin="0, 0, 0, 2" Text="Saturation"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_RGBSaturationSlider" Minimum="-100" Maximum="100" IsSnapToTickEnabled="false" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0, 0, 0, 12">
<TextBlock Style="{StaticResource Heading4Primary}" HorizontalAlignment="Left" Margin="0, 0, 0, 2" Text="Brightness"/>
<StackPanel Orientation="Horizontal" Margin="0, 0, 10, 0">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</StackPanel.LayoutTransform>
<Slider x:Name="_RGBBrightnessSlider" Minimum="-100" Maximum="100" IsSnapToTickEnabled="false" IsMoveToPointEnabled="True" TickFrequency="20" TickPlacement="BottomRight" Width="420" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 0, 0, 0"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5, 0, 0, 12">
<Button x:Name="_ResetCorsairColorCorrectionButton" HorizontalAlignment="Left">
<TextBlock Style="{StaticResource Heading3Primary}">Reset</TextBlock>
</Button>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="AboutTab">
<TabItem.Header>
<TextBlock Style="{StaticResource Heading2Primary}" Text="ABOUT" FontSize="20" Margin="5"/>
</TabItem.Header>
<StackPanel Orientation="Vertical" Margin="{StaticResource ScrollViewerMargin}">
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Version"/>
<TextBlock x:Name="_VersionTextBlock" Margin="0, 0, 0, 10" Style="{StaticResource Heading3Primary}"/>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="AI Notice"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" Width="625" TextWrapping="Wrap">
<Run>Stellar Conquest</Run>
<Run FontWeight="Bold">does not</Run>
<Run>use AI for art and music content. If enabled, generative AI is used to create NPC memories and dialogue.</Run>
</TextBlock>
<StackPanel Margin="{StaticResource GroupMargin}"/>
<TextBlock Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3" Margin="0, 0, 0, 12" MinWidth="625"
Foreground="Black" Background="{StaticResource HeadingBrush}" Text="Legal Notice"/>
<TextBlock Style="{StaticResource Heading3Primary}">
<Run FontWeight="Bold">Stellar Conquest</Run>
<Run>© 2026 Stellar Studio</Run></TextBlock>
<TextBlock Margin="0, 16, 0, 0" Style="{StaticResource Heading3Primary}" HorizontalAlignment="Left" Width="625" TextWrapping="Wrap">
<Run>All trademarked names and copyrights are protected by law. The Stellar Conquest®</Run>
<Run>name and the Stellar Conquest Logo are registered trademarks and/or service brand names, slogans, logos and emblems of Shaun C Tonstad. All rights reserved.</Run></TextBlock>
<TextBlock Margin="0, 16, 0, 0">
<Hyperlink x:Name="_HyperLinkButton" FontSize="{StaticResource Heading3FontSize}">Third-Party Notices</Hyperlink>
</TextBlock>
</StackPanel>
</TabItem>
</TabControl>
</local:BorderControlTitle>
</Grid>
</UserControl> SettingsControl.xaml.cs (69,999 bytes)
using Noesis;
using StellarConquest.Model.Core;
using StellarConquest.Model.Platform;
using StellarConquest.RGB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using GUI = Noesis.GUI;
using NoesisEventArgs = Noesis.EventArgs;
namespace StellarConquest.Presentation.Unity.UI
{
[AssetDependency]
public partial class SettingsControl : OverlayControl
{
private FrameworkElement _Root;
private BorderControlTitle _BorderControl;
private TabControl _TabControl;
// gameplay
private CheckBox _WarnSafeParkingEnabled;
private CheckBox _WarnEvilEnabled;
private CheckBox _GameMenuEnabled;
private CheckBox _TargetingEnabled;
private CheckBox _WindowDragEnabled;
private CheckBox _UIEnabled;
private ComboBox _TemperatureUnits;
// control
private StackPanel _DevicesStackPanel;
private CheckBox _MouseConfined;
private CheckBox _GamepadEnabled;
private TextBlock _CockpitHeadingTextBlock;
private CheckBox _CharacterInvertUpEnabled;
private Slider _CharacterLookSensitivity;
private CheckBox _ShipInvertUpEnabled;
private ComboBox _CharacterControl;
private ComboBox _InteriorCamera;
// display
private bool _DisplayInitialized = false;
private StackPanel _ResolutionStackPanel;
private ComboBox _WindowMode;
private StackPanel _DisplayResolutionStackPanel;
private ComboBox _Displays;
private ComboBox _DisplayResolution;
private ComboBox _ResolutionUpscaler;
private ComboBox _ResolutionUpscalerQuality;
private ComboBox _FrameRateLimit;
private ComboBox _VSync;
private ComboBox _MotionBlur;
private ComboBox _ShowFPS;
private StackPanel _QualityStackPanel;
private ToggleButton _QualityLow;
private ToggleButton _QualityMedium;
private ToggleButton _QualityHigh;
private ToggleButton _QualityEpic;
private ToggleButton _QualityAuto;
private ToggleButton _ViewNear;
private ToggleButton _ViewMedium;
private ToggleButton _ViewFar;
private ToggleButton _ViewEpic;
private ToggleButton _ShadowsLow;
private ToggleButton _ShadowsMedium;
private ToggleButton _ShadowsHigh;
private ToggleButton _ShadowsEpic;
private ToggleButton _ShadowDistanceNear;
private ToggleButton _ShadowDistanceMedium;
private ToggleButton _ShadowDistanceFar;
private ToggleButton _ShadowDistanceEpic;
private ToggleButton _TexturesLow;
private ToggleButton _TexturesMedium;
private ToggleButton _TexturesHigh;
private ToggleButton _TexturesEpic;
private ToggleButton _ReflectionsOff;
private ToggleButton _ReflectionsMedium;
private ToggleButton _ReflectionsHigh;
private ToggleButton _ReflectionsEpic;
private ToggleButton _PostProcessingLow;
private ToggleButton _PostProcessingMedium;
private ToggleButton _PostProcessingHigh;
private ToggleButton _PostProcessingEpic;
private ToggleButton _DetailLow;
private ToggleButton _DetailMedium;
private ToggleButton _DetailHigh;
private ToggleButton _DetailEpic;
private StackPanel _FieldOfViewStackPanel;
private Slider _CharacterFieldOfView;
private Slider _CockpitFieldOfView;
private Slider _ExternalFieldOfView;
private Button _ResetFieldOfViewButton;
private Slider _BrightnessSlider;
private Slider _ContrastSlider;
private Button _ResetColorCorrectionButton;
// ui
private ToggleButton _UISmallest;
private ToggleButton _UISmaller;
private ToggleButton _UINormal;
private ToggleButton _UILarger;
private ToggleButton _UILargest;
private CheckBox _BlurEffectsEnabled;
private Slider _TopBlurSlider;
private Slider _BottomBlurSlider;
private CheckBox _DesignerHelpUIEnabled;
private CheckBox _GameHelpUIEnabled;
// sound
private CheckBox _MasterVolumeEnabled;
private Slider _MasterVolumeSlider;
private CheckBox _MusicVolumeEnabled;
private Slider _MusicVolumeSlider;
private CheckBox _EffectsVolumeEnabled;
private Slider _EffectsVolumeSlider;
private CheckBox _VoiceVolumeEnabled;
private Slider _VoiceVolumeSlider;
private CheckBox _UIVolumeEnabled;
private Slider _UIVolumeSlider;
private CheckBox _AmbientVolumeEnabled;
private Slider _AmbientVolumeSlider;
// network
private TabItem _NetworkTab;
private ComboBox _Environment;
private Slider _ClientToServerSlider;
private Slider _ServerToClientSlider;
private TextBlock _ClientToServerRateTextBlock;
private TextBlock _ServerToClientRateTextBlock;
// generative AI
private StackPanel _GenerativeAIStackPanel;
private CheckBox _GenerativeTextDialogue;
private CheckBox _GenerativeAudioDialogue;
// corsair
private TabItem _CorsairTab;
private StackPanel _RGBStackPanel;
private CheckBox _RGBLightingEnabled;
private CheckBox _TutorialKeysEnabled;
private CheckBox _InputKeysEnabled;
private Slider _RGBHueSlider;
private Slider _RGBSaturationSlider;
private Slider _RGBBrightnessSlider;
private Button _ResetCorsairColorCorrectionButton;
private StackPanel _CorsairStackPanel;
private TextBlock _CorsairNotFoundTextBlock;
// about
private Hyperlink _HyperlinkButton;
private TextBlock _VersionTextBlock;
private bool _ApplyEnabled = true;
private List<Resolution> _SupportedResolutions;
public SettingsControl()
{
Name = nameof(SettingsControl);
IsBlurEnabled = false;
IsDragAllowed = true;
Initialized += OnInitialized;
InitializeComponent();
}
protected override void InitializeComponent()
{
base.InitializeComponent();
GUI.LoadComponent(this, "Assets/User Interface/Screens/Game/Overlay/Settings/SettingsControl.xaml");
_Root = Content as FrameworkElement;
_TabControl = _Root.FindName("_TabControl") as TabControl;
_BorderControl = _Root.FindName("_BorderControl") as BorderControlTitle;
// bind controls: gameplay
_WarnSafeParkingEnabled = _Root.FindName("_WarnSafeParkingEnabled") as CheckBox;
_WarnEvilEnabled = _Root.FindName("_WarnEvilEnabled") as CheckBox;
_GameMenuEnabled = _Root.FindName("_GameMenuEnabled") as CheckBox;
_TargetingEnabled = _Root.FindName("_TargetingEnabled") as CheckBox;
_WindowDragEnabled = _Root.FindName("_WindowDragEnabled") as CheckBox;
_UIEnabled = _Root.FindName("_UIEnabled") as CheckBox;
_TemperatureUnits = _Root.FindName(nameof(_TemperatureUnits)) as ComboBox;
// bind controls: input
_DevicesStackPanel = _Root.FindName(nameof(_DevicesStackPanel)) as StackPanel;
_MouseConfined = _Root.FindName("_MouseConfined") as CheckBox;
_GamepadEnabled = _Root.FindName("_GamepadEnabled") as CheckBox;
_CockpitHeadingTextBlock = _Root.FindName("_CockpitHeadingTextBlock") as TextBlock;
_CharacterInvertUpEnabled = _Root.FindName("_CharacterInvertUpEnabled") as CheckBox;
_ShipInvertUpEnabled = _Root.FindName("_ShipInvertUpEnabled") as CheckBox;
_CharacterControl = _Root.FindName("_CharacterControl") as ComboBox;
_InteriorCamera = _Root.FindName("_InteriorCamera") as ComboBox;
_CharacterLookSensitivity = _Root.FindName("_CharacterLookSensitivity") as Slider;
// bind controls: video
_ResolutionStackPanel = _Root.FindName(nameof(_ResolutionStackPanel)) as StackPanel;
_WindowMode = _Root.FindName("_WindowMode") as ComboBox;
_DisplayResolutionStackPanel = _Root.FindName("_DisplayResolutionStackPanel") as StackPanel;
_Displays = _Root.FindName("_Displays") as ComboBox;
_DisplayResolution = _Root.FindName("_DisplayResolution") as ComboBox;
_ResolutionUpscaler = _Root.FindName(nameof(_ResolutionUpscaler)) as ComboBox;
_ResolutionUpscalerQuality = _Root.FindName(nameof(_ResolutionUpscalerQuality)) as ComboBox;
_FrameRateLimit = _Root.FindName("_FrameRateLimit") as ComboBox;
_VSync = _Root.FindName("_VSync") as ComboBox;
_MotionBlur = _Root.FindName("_MotionBlur") as ComboBox;
_ShowFPS = _Root.FindName("_ShowFPS") as ComboBox;
_QualityStackPanel = _Root.FindName(nameof(_QualityStackPanel)) as StackPanel;
_QualityLow = _Root.FindName("_QualityLow") as ToggleButton;
_QualityMedium = _Root.FindName("_QualityMedium") as ToggleButton;
_QualityHigh = _Root.FindName("_QualityHigh") as ToggleButton;
_QualityEpic = _Root.FindName("_QualityEpic") as ToggleButton;
_QualityAuto = _Root.FindName("_QualityAuto") as ToggleButton;
_ViewNear = _Root.FindName("_ViewNear") as ToggleButton;
_ViewMedium = _Root.FindName("_ViewMedium") as ToggleButton;
_ViewFar = _Root.FindName("_ViewFar") as ToggleButton;
_ViewEpic = _Root.FindName("_ViewEpic") as ToggleButton;
_ShadowsLow = _Root.FindName("_ShadowsLow") as ToggleButton;
_ShadowsMedium = _Root.FindName("_ShadowsMedium") as ToggleButton;
_ShadowsHigh = _Root.FindName("_ShadowsHigh") as ToggleButton;
_ShadowsEpic = _Root.FindName("_ShadowsEpic") as ToggleButton;
_ShadowDistanceNear = _Root.FindName("_ShadowDistanceNear") as ToggleButton;
_ShadowDistanceMedium = _Root.FindName("_ShadowDistanceMedium") as ToggleButton;
_ShadowDistanceFar = _Root.FindName("_ShadowDistanceFar") as ToggleButton;
_ShadowDistanceEpic = _Root.FindName("_ShadowDistanceEpic") as ToggleButton;
_TexturesLow = _Root.FindName("_TexturesLow") as ToggleButton;
_TexturesMedium = _Root.FindName("_TexturesMedium") as ToggleButton;
_TexturesHigh = _Root.FindName("_TexturesHigh") as ToggleButton;
_TexturesEpic = _Root.FindName("_TexturesEpic") as ToggleButton;
_ReflectionsOff = _Root.FindName("_ReflectionsOff") as ToggleButton;
_ReflectionsMedium = _Root.FindName("_ReflectionsMedium") as ToggleButton;
_ReflectionsHigh = _Root.FindName("_ReflectionsHigh") as ToggleButton;
_ReflectionsEpic = _Root.FindName("_ReflectionsEpic") as ToggleButton;
_PostProcessingLow = _Root.FindName("_PostProcessingLow") as ToggleButton;
_PostProcessingMedium = _Root.FindName("_PostProcessingMedium") as ToggleButton;
_PostProcessingHigh = _Root.FindName("_PostProcessingHigh") as ToggleButton;
_PostProcessingEpic = _Root.FindName("_PostProcessingEpic") as ToggleButton;
_DetailLow = _Root.FindName("_DetailLow") as ToggleButton;
_DetailMedium = _Root.FindName("_DetailMedium") as ToggleButton;
_DetailHigh = _Root.FindName("_DetailHigh") as ToggleButton;
_DetailEpic = _Root.FindName("_DetailEpic") as ToggleButton;
_FieldOfViewStackPanel = _Root.FindName(nameof(_FieldOfViewStackPanel)) as StackPanel;
_CharacterFieldOfView = _Root.FindName("_CharacterFieldOfView") as Slider;
_CockpitFieldOfView = _Root.FindName("_CockpitFieldOfView") as Slider;
_ExternalFieldOfView = _Root.FindName("_ExternalFieldOfView") as Slider;
_ResetFieldOfViewButton = _Root.FindName("_ResetFieldOfViewButton") as Button;
_BrightnessSlider = _Root.FindName("_BrightnessSlider") as Slider;
_ContrastSlider = _Root.FindName("_ContrastSlider") as Slider;
_ResetColorCorrectionButton = _Root.FindName("_ResetColorCorrectionButton") as Button;
// UI
_UISmallest = _Root.FindName("_UISmallest") as ToggleButton;
_UISmaller = _Root.FindName("_UISmaller") as ToggleButton;
_UINormal = _Root.FindName("_UINormal") as ToggleButton;
_UILarger = _Root.FindName("_UILarger") as ToggleButton;
_UILargest = _Root.FindName("_UILargest") as ToggleButton;
_BlurEffectsEnabled = _Root.FindName("_BlurEffectsEnabled") as CheckBox;
_TopBlurSlider = _Root.FindName("_TopBlurSlider") as Slider;
_BottomBlurSlider = _Root.FindName("_BottomBlurSlider") as Slider;
_DesignerHelpUIEnabled = _Root.FindName("_DesignerHelpUIEnabled") as CheckBox;
_GameHelpUIEnabled = _Root.FindName("_GameHelpUIEnabled") as CheckBox;
// bind controls: audio
_MasterVolumeEnabled = _Root.FindName("_MasterVolumeEnabled") as CheckBox;
_MasterVolumeSlider = _Root.FindName("_MasterVolumeSlider") as Slider;
_MusicVolumeEnabled = _Root.FindName("_MusicVolumeEnabled") as CheckBox;
_MusicVolumeSlider = _Root.FindName("_MusicVolumeSlider") as Slider;
_EffectsVolumeEnabled = _Root.FindName("_EffectsVolumeEnabled") as CheckBox;
_EffectsVolumeSlider = _Root.FindName("_EffectsVolumeSlider") as Slider;
_VoiceVolumeEnabled = _Root.FindName("_VoiceVolumeEnabled") as CheckBox;
_VoiceVolumeSlider = _Root.FindName("_VoiceVolumeSlider") as Slider;
_UIVolumeEnabled = _Root.FindName("_UIVolumeEnabled") as CheckBox;
_UIVolumeSlider = _Root.FindName("_UIVolumeSlider") as Slider;
_AmbientVolumeEnabled = _Root.FindName("_AmbientVolumeEnabled") as CheckBox;
_AmbientVolumeSlider = _Root.FindName("_AmbientVolumeSlider") as Slider;
// network
_NetworkTab = _Root.FindName("_NetworkTab") as TabItem;
_Environment = _Root.FindName("_Environment") as ComboBox;
_ClientToServerSlider = _Root.FindName("_ClientToServerSlider") as Slider;
_ServerToClientSlider = _Root.FindName("_ServerToClientSlider") as Slider;
_ClientToServerRateTextBlock = _Root.FindName(nameof(_ClientToServerRateTextBlock)) as TextBlock;
_ServerToClientRateTextBlock = _Root.FindName(nameof(_ServerToClientRateTextBlock)) as TextBlock;
// generative AI
_GenerativeAIStackPanel = _Root.FindName(nameof(_GenerativeAIStackPanel)) as StackPanel;
_GenerativeTextDialogue = _Root.FindName(nameof(_GenerativeTextDialogue)) as CheckBox;
_GenerativeAudioDialogue = _Root.FindName(nameof(_GenerativeAudioDialogue)) as CheckBox;
// corsair
_CorsairTab = _Root.FindName(nameof(_CorsairTab)) as TabItem;
_RGBStackPanel = _Root.FindName(nameof(_RGBStackPanel)) as StackPanel;
_RGBLightingEnabled = _Root.FindName(nameof(_RGBLightingEnabled)) as CheckBox;
_TutorialKeysEnabled = _Root.FindName("_TutorialKeysEnabled") as CheckBox;
_InputKeysEnabled = _Root.FindName("_InputKeysEnabled") as CheckBox;
_RGBHueSlider = _Root.FindName("_RGBHueSlider") as Slider;
_RGBSaturationSlider = _Root.FindName("_RGBSaturationSlider") as Slider;
_RGBBrightnessSlider = _Root.FindName("_RGBBrightnessSlider") as Slider;
_ResetCorsairColorCorrectionButton = _Root.FindName("_ResetCorsairColorCorrectionButton") as Button;
_CorsairStackPanel = _Root.FindName("_CorsairStackPanel") as StackPanel;
_CorsairNotFoundTextBlock = _Root.FindName("_CorsairNotFoundTextBlock") as TextBlock;
// about
_HyperlinkButton = _Root.FindName("_HyperLinkButton") as Hyperlink;
_VersionTextBlock = _Root.FindName("_VersionTextBlock") as TextBlock;
}
private void WireEvents(Action<int> action, int defaultIndex, params ToggleButton[] buttons)
{
buttons[defaultIndex].IsChecked = true;
foreach (ToggleButton button in buttons)
{
button.Checked += (sender, e) =>
{
int index = 0;
for (int i = 0; i < buttons.Length; i++)
{
if (buttons[i].Equals(sender))
index = i;
else if (!buttons[i].Equals(sender))
buttons[i].IsChecked = false;
}
action?.Invoke(index);
};
}
}
protected override void OnInitialized(object sender, NoesisEventArgs args)
{
base.OnInitialized(sender, args);
if (!Application.isPlaying)
return;
if (PlayerPreferences.Instance == null)
return;
Update(true);
}
public void Update(bool wireEvents)
{
_ApplyEnabled = false;
// initialize values: gameplay
_WarnSafeParkingEnabled.IsChecked = PlayerPreferences.Instance.WarnSafeParkingEnabled;
_WarnEvilEnabled.IsChecked = PlayerPreferences.Instance.WarnEvilEnabled;
// initialize values: controls
_MouseConfined.IsChecked = PlayerPreferences.Instance.MouseConfined;
_GamepadEnabled.IsChecked = PlayerPreferences.Instance.GamepadEnabled;
_CharacterInvertUpEnabled.IsChecked = PlayerPreferences.Instance.CharacterInvertUpEnabled;
_ShipInvertUpEnabled.IsChecked = PlayerPreferences.Instance.ShipInvertUpEnabled;
_CharacterControl.SelectedIndex = (int)PlayerPreferences.Instance.CharacterControl;
_InteriorCamera.SelectedIndex = (int)PlayerPreferences.Instance.DefaultInteriorCamera;
_CharacterLookSensitivity.Value = PlayerPreferences.Instance.CharacterLookSensitivity;
// initialize values: display
_WindowMode.SelectedIndex = (int)PlayerPreferences.Instance.FullScreenMode;
_FrameRateLimit.SelectedIndex = (int)PlayerPreferences.Instance.FrameRateLimit;
_VSync.SelectedIndex = (int)PlayerPreferences.Instance.VSync;
_MotionBlur.SelectedIndex = (int)PlayerPreferences.Instance.MotionBlur;
_ShowFPS.SelectedIndex = PlayerPreferences.Instance.ShowFPS ? 1 : 0;
// diplays
List<DisplayInfo> displays = new List<DisplayInfo>();
Screen.GetDisplayLayout(displays);
string FilterName(string displayName)
{
if (string.IsNullOrEmpty(displayName))
return string.Empty;
return displayName.Replace("\\", string.Empty);
}
for (int i = 0; i < displays.Count; i++)
{
DisplayInfo displayInfo = displays[i];
ComboBoxItem comboBoxItem = new ComboBoxItem();
comboBoxItem.Content = $"{i + 1}: {FilterName(displayInfo.name)}";
comboBoxItem.Tag = displayInfo;
_Displays.Items.Add(comboBoxItem);
}
_Displays.SelectedIndex = PlayerPreferences.Instance.SelectedDisplayIndex;
UpdateScreeenResolutions(false);
switch (PlayerPreferences.Instance.ResolutionUpscaler)
{
case ResolutionUpscalerType.DLSS:
_ResolutionUpscaler.SelectedIndex = 1;
break;
case ResolutionUpscalerType.FSR:
_ResolutionUpscaler.SelectedIndex = 2;
break;
case ResolutionUpscalerType.XeSS:
_ResolutionUpscaler.SelectedIndex = 3;
break;
case ResolutionUpscalerType.TAA:
case ResolutionUpscalerType.None:
default:
_ResolutionUpscaler.SelectedIndex = 0;
break;
}
_ResolutionUpscalerQuality.SelectedIndex = (int)(PlayerPreferences.Instance.ResolutionUpscalerQuality - 2);
_CharacterFieldOfView.Value = PlayerPreferences.Instance.CharacterFieldOfView;
_CockpitFieldOfView.Value = PlayerPreferences.Instance.CockpitFieldOfView;
_ExternalFieldOfView.Value = PlayerPreferences.Instance.ExternalFieldOfView;
_BrightnessSlider.Value = PlayerPreferences.Instance.Brightness;
_ContrastSlider.Value = PlayerPreferences.Instance.Contrast;
// initialize values: ui
_BlurEffectsEnabled.IsChecked = PlayerPreferences.Instance.BlurEffectsEnabled;
_TopBlurSlider.Value = PlayerPreferences.Instance.TopBlurRadius;
_BottomBlurSlider.Value = PlayerPreferences.Instance.BottomBlurRadius;
_GameMenuEnabled.IsChecked = PlayerPreferences.Instance.GameMenuEnabled;
_TargetingEnabled.IsChecked = PlayerPreferences.Instance.TargetingEnabled;
_WindowDragEnabled.IsChecked = PlayerPreferences.Instance.WindowDragEnabled;
_UIEnabled.IsChecked = PlayerPreferences.Instance.UIEnabled;
_DesignerHelpUIEnabled.IsChecked = PlayerPreferences.Instance.DesignerHelpUIEnabled;
_GameHelpUIEnabled.IsChecked = PlayerPreferences.Instance.GameHelpUIEnabled;
_TemperatureUnits.SelectedIndex = (int)PlayerPreferences.Instance.TemperatureUnits;
// initialize values: sound
_MasterVolumeEnabled.IsChecked = PlayerPreferences.Instance.MasterVolumeEnabled;
_MasterVolumeSlider.Value = PlayerPreferences.Instance.MasterVolume * 100.0f;
_MusicVolumeEnabled.IsChecked = PlayerPreferences.Instance.MusicVolumeEnabled;
_MusicVolumeSlider.Value = PlayerPreferences.Instance.MusicVolume * 100.0f;
_EffectsVolumeEnabled.IsChecked = PlayerPreferences.Instance.EffectsVolumeEnabled;
_EffectsVolumeSlider.Value = PlayerPreferences.Instance.EffectsVolume * 100.0f;
_VoiceVolumeEnabled.IsChecked = PlayerPreferences.Instance.VoiceVolumeEnabled;
_VoiceVolumeSlider.Value = PlayerPreferences.Instance.VoiceVolume * 100.0f;
_UIVolumeEnabled.IsChecked = PlayerPreferences.Instance.UIVolumeEnabled;
_UIVolumeSlider.Value = PlayerPreferences.Instance.UIVolume * 100.0f;
_AmbientVolumeEnabled.IsChecked = PlayerPreferences.Instance.AmbientVolumeEnabled;
_AmbientVolumeSlider.Value = PlayerPreferences.Instance.AmbientVolume * 100.0f;
// generative ai
_GenerativeTextDialogue.IsChecked = PlayerPreferences.Instance.GenerativeTextDialogue;
_GenerativeAudioDialogue.IsChecked = PlayerPreferences.Instance.GenerativeAudioDialogue;
// initialize values: rgb
_RGBLightingEnabled.IsChecked = PlayerPreferences.Instance.RGBLightingEnabled;
_TutorialKeysEnabled.IsChecked = PlayerPreferences.Instance.RGBConfiguration.TutorialKeysEnabled;
_InputKeysEnabled.IsChecked = PlayerPreferences.Instance.RGBConfiguration.InputKeysEnabled;
_Environment.SelectedIndex = (int)PlayerPreferences.Instance.ConquestEnvironment;
_ClientToServerSlider.Value = PlayerPreferences.Instance.ClientToServerNetworkUpdateRate;
_ServerToClientSlider.Value = PlayerPreferences.Instance.ServerToClientNetworkUpdateRate;
_RGBHueSlider.Value = PlayerPreferences.Instance.RGBConfiguration.Hue * 100.0f;
_RGBSaturationSlider.Value = PlayerPreferences.Instance.RGBConfiguration.Saturation * 100.0f;
_RGBBrightnessSlider.Value = PlayerPreferences.Instance.RGBConfiguration.Brightness * 100.0f;
// about
_VersionTextBlock.Text = $"Version {VersionUtility.GetVersion()}{Environment.NewLine}{VersionUtility.GetBuildDate()}";
if (!wireEvents)
{
_ApplyEnabled = true;
return;
}
// events: gameplay
_WarnSafeParkingEnabled.Checked += (sender2, e2) => PlayerPreferences.Instance.WarnSafeParkingEnabled = true;
_WarnSafeParkingEnabled.Unchecked += (sender2, e2) => PlayerPreferences.Instance.WarnSafeParkingEnabled = false;
_WarnEvilEnabled.Checked += (sender2, e2) => PlayerPreferences.Instance.WarnEvilEnabled = true;
_WarnEvilEnabled.Unchecked += (sender2, e2) => PlayerPreferences.Instance.WarnEvilEnabled = false;
_GameMenuEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.GameMenuEnabled = true;
Apply();
};
_GameMenuEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.GameMenuEnabled = false;
Apply();
};
_TargetingEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.TargetingEnabled = true;
Apply();
};
_TargetingEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.TargetingEnabled = false;
Apply();
};
// UI
_WindowDragEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.WindowDragEnabled = true;
Apply();
UpdateWindowDragBehavior();
};
_WindowDragEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.WindowDragEnabled = false;
Apply();
UpdateWindowDragBehavior();
};
_TemperatureUnits.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.TemperatureUnits = (TemperatureUnitType)_TemperatureUnits.SelectedIndex;
};
_UIEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.UIEnabled = true;
Apply();
};
_UIEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.UIEnabled = false;
Apply();
};
_DesignerHelpUIEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.DesignerHelpUIEnabled = true;
Apply();
};
_DesignerHelpUIEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.DesignerHelpUIEnabled = false;
Apply();
};
_GameHelpUIEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.GameHelpUIEnabled = true;
Apply();
};
_GameHelpUIEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.GameHelpUIEnabled = false;
Apply();
};
// events: input
_MouseConfined.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.MouseConfined = true;
};
_MouseConfined.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.MouseConfined = false;
};
_GamepadEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.GamepadEnabled = true;
};
_GamepadEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.GamepadEnabled = false;
};
_CharacterInvertUpEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.CharacterInvertUpEnabled = true;
};
_CharacterInvertUpEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.CharacterInvertUpEnabled = false;
};
_ShipInvertUpEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.ShipInvertUpEnabled = true;
};
_ShipInvertUpEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.ShipInvertUpEnabled = false;
};
_CharacterControl.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.CharacterControl = (CharacterControlType)_CharacterControl.SelectedIndex;
};
_InteriorCamera.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.DefaultInteriorCamera = (DefaultInteriorCameraType)_InteriorCamera.SelectedIndex;
};
_CharacterLookSensitivity.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.CharacterLookSensitivity = e2.NewValue;
};
// events: sound
// master
_MasterVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.MasterVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_MasterVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.MasterVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_MasterVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.MasterVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
// music
_MusicVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.MusicVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_MusicVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.MusicVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_MusicVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.MusicVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
// effects
_EffectsVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.EffectsVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_EffectsVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.EffectsVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_EffectsVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.EffectsVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
// ambient
_AmbientVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.AmbientVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_AmbientVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.AmbientVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_AmbientVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.AmbientVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
// voice
_VoiceVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.VoiceVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_VoiceVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.VoiceVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_VoiceVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.VoiceVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
// ui
_UIVolumeEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.UIVolumeEnabled = true;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_UIVolumeEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.UIVolumeEnabled = false;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
UpdateButtonVisibility();
};
_UIVolumeSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.UIVolume = e2.NewValue / 100.0f;
Apply(updateUI: false, updateAudio: true, updateDisplay: false);
};
void OnResolutionChanged()
{
if (!_ApplyEnabled)
return;
if (_DisplayResolution.SelectedIndex == -1)
return;
Resolution selectedResolution = _SupportedResolutions[_DisplayResolution.SelectedIndex];
if (PlayerPreferences.Instance.FullScreenMode == FullScreenMode.Windowed)
{
// use system (window) resolution and system refresh rate
PlayerPreferences.Instance.DisplayResolution = new Vector2Int(Screen.width, Screen.height); // causes maximized screen to reset to screen width and height?
//PlayerPreferences.Instance.DisplayResolution = new Vector2Int(selectedResolution.width, selectedResolution.height);
PlayerPreferences.Instance.DisplayRefreshRate = (float)Screen.currentResolution.refreshRateRatio.value; // ignore selected refreshrate
}
else if (PlayerPreferences.Instance.FullScreenMode == FullScreenMode.FullScreenWindow)
{
// use selected resolution and system refresh rate
PlayerPreferences.Instance.DisplayResolution = new Vector2Int(selectedResolution.width, selectedResolution.height);
PlayerPreferences.Instance.DisplayRefreshRate = (float)Screen.currentResolution.refreshRateRatio.value; // ignore selected refreshrate
}
else if (PlayerPreferences.Instance.FullScreenMode == FullScreenMode.ExclusiveFullScreen)
{
// use selected resolution and selected refresh rate
PlayerPreferences.Instance.DisplayResolution = new Vector2Int(selectedResolution.width, selectedResolution.height);
PlayerPreferences.Instance.DisplayRefreshRate = (float)Math.Round(selectedResolution.refreshRateRatio.value, 2);
}
Apply(updateDisplay: true);
}
void OnFullScreenModeChanged()
{
PlayerPreferences.Instance.FullScreenMode = (FullScreenMode)_WindowMode.SelectedIndex;
UpdateScreeenResolutions(true);
if (_ApplyEnabled)
{
UpdateButtonVisibility();
if (PlayerPreferences.Instance.FullScreenMode == FullScreenMode.FullScreenWindow || PlayerPreferences.Instance.FullScreenMode == FullScreenMode.ExclusiveFullScreen)
{
_DisplayResolution.SelectedIndex = 0;
OnResolutionChanged(); // will invoke Apply()
}
else
Apply(updateDisplay: true);
}
}
void OnDisplayChanged()
{
PlayerPreferences.Instance.SelectedDisplayIndex = _Displays.SelectedIndex;
if (_ApplyEnabled)
{
Apply(updateDisplay: true, completed: () =>
{
UpdateScreeenResolutions(resetSelection: true); // updates display and resets Resolutions combobox
Apply(updateDisplay: true); // applies resolution ^1
});
}
}
_Displays.SelectionChanged += (sender, e) => OnDisplayChanged();
_WindowMode.SelectionChanged += (sender, e) => OnFullScreenModeChanged();
_DisplayResolution.SelectionChanged += (sender2, e2) => OnResolutionChanged();
_ResolutionUpscaler.SelectionChanged += (sender2, e2) =>
{
if (_ResolutionUpscaler.SelectedIndex == 0)
PlayerPreferences.Instance.ResolutionUpscaler = ResolutionUpscalerType.TAA;
else if (_ResolutionUpscaler.SelectedIndex == 1)
PlayerPreferences.Instance.ResolutionUpscaler = ResolutionUpscalerType.DLSS;
else if (_ResolutionUpscaler.SelectedIndex == 2)
PlayerPreferences.Instance.ResolutionUpscaler = ResolutionUpscalerType.FSR;
else if (_ResolutionUpscaler.SelectedIndex == 3)
PlayerPreferences.Instance.ResolutionUpscaler = ResolutionUpscalerType.XeSS;
else
throw new ArgumentOutOfRangeException();
Apply(updateDisplay: true);
};
_ResolutionUpscalerQuality.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.ResolutionUpscalerQuality = (ResolutionUpscalerQualityType)_ResolutionUpscalerQuality.SelectedIndex + 2;
Apply(updateDisplay: true);
};
_VSync.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.VSync = (VSyncType)_VSync.SelectedIndex;
if (PlayerPreferences.Instance.VSync == VSyncType.On)
_FrameRateLimit.Visibility = Visibility.Collapsed;
else
_FrameRateLimit.Visibility = Visibility.Visible;
Apply();
};
if (PlayerPreferences.Instance.VSync == VSyncType.On)
_FrameRateLimit.Visibility = Visibility.Collapsed;
else
_FrameRateLimit.Visibility = Visibility.Visible;
_FrameRateLimit.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.FrameRateLimit = (FrameRateLimitType)_FrameRateLimit.SelectedIndex;
Apply();
};
// motion blur
_MotionBlur.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.MotionBlur = (MotionBlurType)_MotionBlur.SelectedIndex;
Apply();
};
// show FPS
_ShowFPS.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.ShowFPS = _ShowFPS.SelectedIndex == 1;
Apply();
};
// quality
Action<int> updateAction = null;
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.Quality = (QualityType)value;
if (_DisplayInitialized)
ApplyQualitySetting(PlayerPreferences.Instance.Quality);
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.Quality, _QualityLow, _QualityMedium, _QualityHigh, _QualityEpic, _QualityAuto);
// view distance
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.ViewDistance = (ViewDistanceType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.ViewDistance, _ViewNear, _ViewMedium, _ViewFar, _ViewEpic);
// shadows
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.Shadows = (ShadowsQualityType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.Shadows, _ShadowsLow, _ShadowsMedium, _ShadowsHigh, _ShadowsEpic);
// shadow distance
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.ShadowDistance = (ShadowDistanceType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.ShadowDistance, _ShadowDistanceNear, _ShadowDistanceMedium, _ShadowDistanceFar, _ShadowDistanceEpic);
// textures
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.Textures = (TexturesType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.Textures, _TexturesLow, _TexturesMedium, _TexturesHigh, _TexturesEpic);
// reflections
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.Reflections = (ReflectionsType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.Reflections, _ReflectionsOff, _ReflectionsMedium, _ReflectionsHigh, _ReflectionsEpic);
// post processing
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.PostProcessing = (PostProcessingType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.PostProcessing, _PostProcessingLow, _PostProcessingMedium, _PostProcessingHigh, _PostProcessingEpic);
// detail
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.Detail = (DetailType)value;
Apply();
});
WireEvents(updateAction, (int)PlayerPreferences.Instance.Detail, _DetailLow, _DetailMedium, _DetailHigh, _DetailEpic);
// field of view
_CharacterFieldOfView.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.CharacterFieldOfView = (int)e2.NewValue;
Apply();
};
_CockpitFieldOfView.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.CockpitFieldOfView = (int)e2.NewValue;
Apply();
};
_ExternalFieldOfView.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.ExternalFieldOfView = (int)e2.NewValue;
Apply();
};
_ResetFieldOfViewButton.Click += (sender2, e2) =>
{
_CockpitFieldOfView.Value = 60;
_CharacterFieldOfView.Value = 60;
_ExternalFieldOfView.Value = 40;
};
_BrightnessSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.Brightness = (int)e2.NewValue;
Apply();
};
_ContrastSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.Contrast = (int)e2.NewValue;
Apply();
};
_ResetColorCorrectionButton.Click += (sender2, e2) =>
{
_BrightnessSlider.Value = 0;
_ContrastSlider.Value = 0;
};
// ui
// UI size
updateAction = new Action<int>((value) =>
{
PlayerPreferences.Instance.UserInterfaceSize = AspectRatioUtility.DefaultAspectRatioIndex - 2 + value;
Apply();
});
WireEvents(updateAction, PlayerPreferences.Instance.UserInterfaceSize, _UISmallest, _UISmaller, _UINormal, _UILarger, _UILargest);
_BlurEffectsEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.BlurEffectsEnabled = _BlurEffectsEnabled.IsChecked.Value;
Apply();
};
_BlurEffectsEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.BlurEffectsEnabled = _BlurEffectsEnabled.IsChecked.Value;
Apply();
};
_TopBlurSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.TopBlurRadius = (int)e2.NewValue;
Apply();
};
_BottomBlurSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.BottomBlurRadius = (int)e2.NewValue;
Apply();
};
// generative AI
_GenerativeTextDialogue.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.GenerativeTextDialogue = true;
};
_GenerativeTextDialogue.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.GenerativeTextDialogue = false;
};
_GenerativeAudioDialogue.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.GenerativeAudioDialogue = true;
};
_GenerativeAudioDialogue.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.GenerativeAudioDialogue = false;
};
// corsair
_RGBLightingEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBLightingEnabled = true;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
UpdateButtonVisibility();
};
_RGBLightingEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBLightingEnabled = false;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
UpdateButtonVisibility();
};
_TutorialKeysEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.TutorialKeysEnabled = true;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
};
_TutorialKeysEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.TutorialKeysEnabled = false;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
};
_InputKeysEnabled.Checked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.InputKeysEnabled = true;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
};
_InputKeysEnabled.Unchecked += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.InputKeysEnabled = false;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
};
_RGBHueSlider.ValueChanged += (sender2, e2) =>
{
float value = e2.NewValue / 180.0f;
if (value < 0)
value = 1 - value;
PlayerPreferences.Instance.RGBConfiguration.Hue = value;
RGBBehavior.Instance.SetDirty(true, true);
};
_RGBSaturationSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.Saturation = e2.NewValue / 100.0f;
RGBBehavior.Instance.SetDirty(true, true);
};
_RGBBrightnessSlider.ValueChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.RGBConfiguration.Brightness = e2.NewValue / 100.0f;
RGBBehavior.Instance.SetDirty(true, true);
};
_ResetCorsairColorCorrectionButton.Click += (sender2, e2) =>
{
_RGBHueSlider.Value = 0;
_RGBSaturationSlider.Value = 0;
_RGBBrightnessSlider.Value = 0;
};
if (PlayerPreferences.Instance.RGBLightingEnabled && RGBBehavior.Instance.IsAvailable)
CreateRGBLightingUI();
_DisplayInitialized = true;
// global
UpdateButtonVisibility();
// network
_Environment.SelectionChanged += (sender2, e2) =>
{
PlayerPreferences.Instance.ConquestEnvironment = (EnvironmentType)_Environment.SelectedIndex;
};
_ClientToServerRateTextBlock.Text = $"Client ({(int)(1000 / Mathf.Lerp(Constants.Network.SpatialUpdateDelayMaxMS, Constants.Network.SpatialUpdateDelayMinMS, PlayerPreferences.Instance.ClientToServerNetworkUpdateRate))} Hz)";
_ServerToClientRateTextBlock.Text = $"Server ({(int)(1000 / Mathf.Lerp(Constants.Network.SpatialUpdateDelayMaxMS, Constants.Network.SpatialUpdateDelayMinMS, PlayerPreferences.Instance.ServerToClientNetworkUpdateRate))} Hz)";
_ClientToServerSlider.ValueChanged += (sender2, e2) =>
{
_ClientToServerRateTextBlock.Text = $"Client ({(int)(1000 / Mathf.Lerp(Constants.Network.SpatialUpdateDelayMaxMS, Constants.Network.SpatialUpdateDelayMinMS, e2.NewValue))} Hz)";
};
_ServerToClientSlider.ValueChanged += (sender2, e2) =>
{
_ServerToClientRateTextBlock.Text = $"Server ({(int)(1000 / Mathf.Lerp(Constants.Network.SpatialUpdateDelayMaxMS, Constants.Network.SpatialUpdateDelayMinMS, e2.NewValue))} Hz)";
};
// about
_HyperlinkButton.Click += (sender2, e2) => ShowSoftwareLicenseAttribution();
_ApplyEnabled = true;
}
private void UpdateScreeenResolutions(bool resetSelection)
{
bool applyEnabled = _ApplyEnabled;
_ApplyEnabled = false;
void AddResolution(List<Resolution> resolutions, float scalar)
{
Resolution resolution = new Resolution()
{
width = Mathf.RoundToInt(resolutions[0].width * scalar),
height = Mathf.RoundToInt(resolutions[0].height * scalar),
refreshRateRatio = resolutions[0].refreshRateRatio
};
if (!resolutions.Where(a => a.width == resolution.width && a.height == resolution.height).Any())
resolutions.Add(resolution);
}
List<Resolution> resolutions = Screen.resolutions
.Where(a => a.width >= 1024 && a.height >= 1024 && a.refreshRateRatio.value >= 50)
.OrderByDescending(a => a.width)
.ThenByDescending(a => a.height)
.ThenByDescending(a => a.refreshRateRatio.value).ToList();
if (PlayerPreferences.Instance.FullScreenMode == FullScreenMode.FullScreenWindow)
{
AddResolution(resolutions, 0.90f);
AddResolution(resolutions, 0.80f);
AddResolution(resolutions, 0.70f);
AddResolution(resolutions, 0.60f);
AddResolution(resolutions, 0.50f);
}
_SupportedResolutions = resolutions
.OrderByDescending(a => a.width)
.ThenByDescending(a => a.height)
.ThenByDescending(a => a.refreshRateRatio.value)
.ToList();
Resolution highestScreenResolution = _SupportedResolutions[0];
var nativeAspectRatio = UIUtility.GetAspectRatio(highestScreenResolution.width, highestScreenResolution.height);
_DisplayResolution.Items.Clear();
foreach (Resolution resolution in _SupportedResolutions)
{
var selectedAspectRatio = UIUtility.GetAspectRatio(resolution.width, resolution.height);
ComboBoxItem i = new ComboBoxItem();
if (selectedAspectRatio == nativeAspectRatio)
{
i.Content = $"{resolution.width,4} x {resolution.height,-4} @ {Math.Round(resolution.refreshRateRatio.value, 2)}Hz 📐 ";
i.FontFamily = FindResource("HeadingFontFamily") as FontFamily;
}
else
i.Content = $"{resolution.width,4} x {resolution.height,-4} @ {Math.Round(resolution.refreshRateRatio.value, 2)}Hz";
i.Tag = resolution;
_DisplayResolution.Items.Add(i);
}
if (resetSelection)
_DisplayResolution.SelectedIndex = 0;
else
{
int selectedResolutionIndex = -1;
for (int i = 0; i < _SupportedResolutions.Count; i++)
if (_SupportedResolutions[i].width == PlayerPreferences.Instance.DisplayResolution.x &&
_SupportedResolutions[i].height == PlayerPreferences.Instance.DisplayResolution.y &&
(PlayerPreferences.Instance.FullScreenMode != FullScreenMode.ExclusiveFullScreen ||
(Math.Round(_SupportedResolutions[i].refreshRateRatio.value, 2) == Math.Round(PlayerPreferences.Instance.DisplayRefreshRate, 2))))
{
selectedResolutionIndex = i;
break;
}
int currentScreenResolutionIndex = -1;
for (int i = 0; i < _SupportedResolutions.Count; i++)
{
if (_SupportedResolutions[i].width == Screen.currentResolution.width &&
_SupportedResolutions[i].height == Screen.currentResolution.height &&
(PlayerPreferences.Instance.FullScreenMode != FullScreenMode.ExclusiveFullScreen ||
(_SupportedResolutions[i].refreshRateRatio.numerator == Screen.currentResolution.refreshRateRatio.numerator &&
_SupportedResolutions[i].refreshRateRatio.denominator == Screen.currentResolution.refreshRateRatio.denominator)))
{
currentScreenResolutionIndex = i;
break;
}
}
if (selectedResolutionIndex != -1)
_DisplayResolution.SelectedIndex = selectedResolutionIndex;
else if (currentScreenResolutionIndex != -1)
_DisplayResolution.SelectedIndex = currentScreenResolutionIndex;
else
_DisplayResolution.SelectedIndex = 0;
}
_ApplyEnabled = applyEnabled;
}
private void ApplyQualitySetting(QualityType value)
{
_ApplyEnabled = false;
switch (value)
{
case QualityType.Low:
_ViewNear.IsChecked = true;
_ShadowsMedium.IsChecked = true;
_ShadowDistanceMedium.IsChecked = true;
_TexturesLow.IsChecked = true;
_ReflectionsMedium.IsChecked = true;
_PostProcessingLow.IsChecked = true;
_DetailLow.IsChecked = true;
break;
case QualityType.Medium:
_ViewMedium.IsChecked = true;
_ShadowsMedium.IsChecked = true;
_ShadowDistanceMedium.IsChecked = true;
_TexturesMedium.IsChecked = true;
_ReflectionsMedium.IsChecked = true;
_PostProcessingMedium.IsChecked = true;
_DetailMedium.IsChecked = true;
break;
case QualityType.High:
_ViewFar.IsChecked = true;
_ShadowsHigh.IsChecked = true;
_ShadowDistanceFar.IsChecked = true;
_TexturesHigh.IsChecked = true;
_ReflectionsMedium.IsChecked = true;
_PostProcessingHigh.IsChecked = true;
_DetailHigh.IsChecked = true;
break;
case QualityType.Epic:
_ViewEpic.IsChecked = true;
_ShadowsEpic.IsChecked = true;
_ShadowDistanceEpic.IsChecked = true;
_TexturesHigh.IsChecked = true;
_ReflectionsHigh.IsChecked = true;
_PostProcessingEpic.IsChecked = true;
_DetailEpic.IsChecked = true;
break;
case QualityType.Auto:
PlayerPreferences.Instance.VSync = 0;
UnityDispatcher.Instance.Invoke(TimeSpan.FromMilliseconds(250), () =>
{
float fps = GameState.Instance.FrameRateCounter.FPS;
PlayerPreferences.Instance.VSync = (VSyncType)_VSync.SelectedIndex;
if (fps > 125)
ApplyQualitySetting(QualityType.Epic);
else if (fps > 100)
ApplyQualitySetting(QualityType.High);
else if (fps > 75)
ApplyQualitySetting(QualityType.Medium);
else
ApplyQualitySetting(QualityType.Low);
});
return;
default:
break;
}
_ApplyEnabled = true;
Apply();
}
public override void Show()
{
base.Show();
if (Application.isEditor || RuntimeSettings.Instance.IsDeveloperMode || PlayerPreferences.Instance.ConquestEnvironment == EnvironmentType.LocalDevelopment)
_NetworkTab.Visibility = Visibility.Visible;
else
_NetworkTab.Visibility = Visibility.Collapsed;
#if (UNITY_GAMECORE)
_CorsairTab.Visibility = Visibility.Collapsed;
_DevicesStackPanel.Visibility = Visibility.Collapsed;
_ResolutionStackPanel.Visibility = Visibility.Collapsed;
_QualityStackPanel.Visibility = Visibility.Collapsed;
_FieldOfViewStackPanel.Visibility = Visibility.Collapsed;
_WindowDragEnabled.Parent.Visibility = Visibility.Collapsed;
_UIEnabled.Parent.Visibility = Visibility.Collapsed;
_GameMenuEnabled.Parent.Visibility = Visibility.Collapsed;
_GenerativeAIStackPanel.Visibility = Visibility.Collapsed;
#endif
InputHelpManager.Instance.UpdateRGBKeysForUI();
}
public override void Hide()
{
base.Hide();
// update preferences that should change only once, upon save
PlayerPreferences.Instance.ClientToServerNetworkUpdateRate = _ClientToServerSlider.Value;
PlayerPreferences.Instance.ServerToClientNetworkUpdateRate = _ServerToClientSlider.Value;
// save preferences
PlayerPreferences.Instance.SaveRGB();
PlayerPreferences.Instance.SavePreferences();
}
public void Apply(bool updateUI = true, bool updateAudio = true, bool updateDisplay = true, bool updateRGB = true, bool updateWorld = true, Action completed = null)
{
if (_ApplyEnabled)
{
if (updateRGB)
{
// RGB state
if (_RGBLightingEnabled.IsChecked.Value)
{
// create device UI if it does not exist, and Corsair RGB is ready
if (_CorsairStackPanel.Children.Count == 0)
UnityDispatcher.Instance.Invoke(async () =>
{
int tries = 0;
while (tries++ < 4)
{
if (RGBBehavior.Instance.IsAvailable)
{
CreateRGBLightingUI();
break;
}
else
await Task.Delay(50);
}
if (RGBBehavior.Instance.IsAvailable)
{
_RGBStackPanel.Visibility = Visibility.Visible;
_CorsairNotFoundTextBlock.Visibility = Visibility.Collapsed;
}
else
{
_RGBStackPanel.Visibility = Visibility.Collapsed;
_CorsairNotFoundTextBlock.Visibility = Visibility.Visible;
}
});
}
else
{
_RGBStackPanel.Visibility = Visibility.Collapsed;
_CorsairNotFoundTextBlock.Visibility = Visibility.Collapsed;
_CorsairStackPanel.Children.Clear();
}
}
PlayerPreferences.Instance.Apply(updateUI, updateAudio, updateDisplay, updateRGB, updateWorld, completed);
if (RGBBehavior.Instance.IsAvailable && updateRGB)
RGBBehavior.Instance.LoadDevices();
}
}
private void UpdateButtonVisibility()
{
if (_MasterVolumeEnabled.IsChecked.Value)
{
_MasterVolumeSlider.IsEnabled = true;
_MasterVolumeSlider.Opacity = 1.0f;
}
else
{
_MasterVolumeSlider.IsEnabled = false;
_MasterVolumeSlider.Opacity = 0.5f;
}
if (_MusicVolumeEnabled.IsChecked.Value)
{
_MusicVolumeSlider.IsEnabled = true;
_MusicVolumeSlider.Opacity = 1.0f;
}
else
{
_MusicVolumeSlider.IsEnabled = false;
_MusicVolumeSlider.Opacity = 0.5f;
}
if (_EffectsVolumeEnabled.IsChecked.Value)
{
_EffectsVolumeSlider.IsEnabled = true;
_EffectsVolumeSlider.Opacity = 1.0f;
}
else
{
_EffectsVolumeSlider.IsEnabled = false;
_EffectsVolumeSlider.Opacity = 0.5f;
}
if (_AmbientVolumeEnabled.IsChecked.Value)
{
_AmbientVolumeSlider.IsEnabled = true;
_AmbientVolumeSlider.Opacity = 1.0f;
}
else
{
_AmbientVolumeSlider.IsEnabled = false;
_AmbientVolumeSlider.Opacity = 0.5f;
}
if (!_RGBLightingEnabled.IsChecked.Value)
{
_RGBStackPanel.Visibility = Visibility.Collapsed;
_CorsairNotFoundTextBlock.Visibility = Visibility.Collapsed;
}
if (_WindowMode.SelectedIndex == (int)FullScreenMode.ExclusiveFullScreen || _WindowMode.SelectedIndex == (int)FullScreenMode.FullScreenWindow)
_DisplayResolutionStackPanel.Visibility = Visibility.Visible;
else
_DisplayResolutionStackPanel.Visibility = Visibility.Hidden;
}
private void CreateRGBLightingUI()
{
if (RGBBehavior.Instance.IsAvailable)
foreach (RGBDeviceMetadata metadata in RGBBehavior.Instance.Devices)
{
string deviceName = RGBConfiguration.SantitizeDeviceName(metadata.Device.DeviceInfo.DeviceName);
StackPanel stackPanel = new StackPanel();
stackPanel.Orientation = Orientation.Horizontal;
stackPanel.Margin = new Thickness(0, 0, 0, 12);
_CorsairStackPanel.Children.Add(stackPanel);
TextBlock textBlock = new TextBlock();
textBlock.Style = (Style)_Root.FindResource("Heading4Primary");
textBlock.HorizontalAlignment = HorizontalAlignment.Right;
textBlock.VerticalAlignment = VerticalAlignment.Center;
textBlock.Width = 250;
textBlock.Margin = new Thickness(0, 0, 5, 0);
textBlock.Text = deviceName;
ToolTipService.SetToolTip(textBlock, textBlock.Text);
stackPanel.Children.Add(textBlock);
ComboBox comboBox = new ComboBox();
comboBox.Width = 315;
stackPanel.Children.Add(comboBox);
Array values = Enum.GetValues(typeof(LightingAssignmentType));
for (int i = 0; i < values.Length; i++)
{
LightingAssignmentType lightingAssignmentType = (LightingAssignmentType)i;
ComboBoxItem comboBoxItem = new ComboBoxItem();
comboBoxItem.Tag = lightingAssignmentType;
comboBoxItem.Content = lightingAssignmentType.ToString().Replace("_", " ");
comboBox.Items.Add(comboBoxItem);
}
comboBox.SelectedIndex = (int)metadata.Binding.Assignment;
comboBox.SelectionChanged += (sender, e) =>
{
ComboBoxItem selectedItem = (ComboBoxItem)e.AddedItems[0];
LightingAssignmentType assignment = (LightingAssignmentType)selectedItem.Tag;
metadata.Binding.Assignment = assignment;
Apply(updateUI: false, updateAudio: false, updateDisplay: false, updateRGB: true);
};
}
}
private void ShowSoftwareLicenseAttribution()
{
Hide();
LicenseAttributionControl control = new LicenseAttributionControl();
control.Hidden += (sender, e) => Show();
control.Show();
}
public override void UpdateInput()
{
if (OpenFrame != Time.frameCount)
{
if (Input.GetKeyDown(KeyCode.Escape) ||
Input.GetButtonDown(InputNames.GamePad.B) ||
Input.GetButtonDown(InputNames.GamePad.Start) ||
Input.GetKeyDown(KeyCode.F1))
{
Hide();
}
}
}
}
} OverlayControl.cs (9,635 bytes)
using Noesis;
using Noesis.Interactivity;
using System;
using UnityEngine;
using Color = Noesis.Color;
using Grid = Noesis.Grid;
using NoesisEventArgs = Noesis.EventArgs;
namespace StellarConquest.Presentation.Unity.UI
{
public enum HideReasonType
{
None,
Programmatic,
LightDismiss,
}
[AssetDependency]
public partial class OverlayControl : UserControl, IGameScreenInputProvider
{
public event EventHandler<NoesisEventArgs> Shown;
public event EventHandler<NoesisEventArgs> Hidden;
public bool IsOverlayVisible { get; private set; }
public bool IsLightDismissExteriorEnabled { get; set; } = true;
public bool IsLightDismissInteriorEnabled { get; set; } = false;
public bool IsBlurEnabled { get; set; } = false;
public bool IsBackgroundSourceBlendEnabled { get; set; } = true;
public bool IsModal { get; set; } = true;
public bool IsFadeEnabled { get; set; } = true;
public bool IsUnscaled { get; set; } = false;
public bool IsAnimatedShow { get; set; } = false;
public bool IsAlternateKeyToCloseEnabled { get; set; } = false;
public KeyCode AlternateCloseKey { get; set; } = KeyCode.F;
public bool IsDragAllowed { get; set; } = false;
public bool IsDragEnabled { get; set; } = false;
public bool IsEscapeToCloseEnabled { get; set; } = false;
public OverlayLayerType Layer { get; set; } = OverlayLayerType.Primary;
public HorizontalAlignment ParentHorizontalAlignment { get; set; } = HorizontalAlignment.Center;
public VerticalAlignment ParentVerticalAlignment { get; set; } = VerticalAlignment.Center;
public HideReasonType HideReason { get; private set; } = HideReasonType.None;
public bool AllowSubsequentPopupDelay { get; protected set; } = true;
private Grid _ParentGrid;
private OverlayLayer _OverlayLayer;
public int OpenFrame { get; private set; } = -1;
public int CloseFrame { get; private set; } = -1;
public static int CloseFrameGlobal { get; private set; } = -1;
public bool UseKeyUpEvent;
public OverlayControl()
{
}
protected virtual void InitializeComponent()
{
if (!Application.isPlaying)
return;
_OverlayLayer = UIStateMachine.Instance.OverlayLayer;
_ParentGrid = new Grid();
_ParentGrid.Name = Name + "_ParentGrid";
_ParentGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
_ParentGrid.VerticalAlignment = VerticalAlignment.Stretch;
if (IsModal)
_ParentGrid.Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)); // transparent but interactive
else
_ParentGrid.Background = null;
_ParentGrid.Children.Add(this);
}
protected virtual void OnInitialized(object sender, NoesisEventArgs args)
{
if (!Application.isPlaying)
return;
UpdateLightDismiss();
}
public virtual void Show()
{
_OverlayLayer.Tag = this;
PickingManager.Instance.InteractionFired = true;
OpenFrame = Time.frameCount;
HideReason = HideReasonType.None;
if (IsUnscaled)
_OverlayLayer.ShowUnscaled(_ParentGrid, Layer, IsBlurEnabled, IsBackgroundSourceBlendEnabled, IsFadeEnabled, IsModal, ParentHorizontalAlignment, ParentVerticalAlignment);
else
_OverlayLayer.Show(_ParentGrid, Layer, IsBlurEnabled, IsBackgroundSourceBlendEnabled, IsFadeEnabled, IsModal, ParentHorizontalAlignment, ParentVerticalAlignment);
if (IsAnimatedShow)
this.Grow(_OverlayLayer, TimeSpan.FromMilliseconds(160));
if (Layer == OverlayLayerType.Primary)
{
IsOverlayVisible = true;
UIStateMachine.Instance.AddInputProvider(this);
}
UpdateWindowDragBehavior();
Shown?.Invoke(this, NoesisEventArgs.Empty);
}
public virtual void Hide()
{
_OverlayLayer.Tag = null;
PickingManager.Instance.InteractionFired = true;
CloseFrame = Time.frameCount;
CloseFrameGlobal = CloseFrame;
if (HideReason == HideReasonType.None)
HideReason = HideReasonType.Programmatic;
if (IsUnscaled)
_OverlayLayer.HideUnscaled(_ParentGrid, Layer);
else
_OverlayLayer.Hide(_ParentGrid, Layer, AllowSubsequentPopupDelay);
if (Layer == OverlayLayerType.Primary)
{
IsOverlayVisible = false;
UIStateMachine.Instance.RemoveInputProvider(this);
}
if (UIStateMachine.Instance.IsGameScreenOpen)
{
if (this == UIStateMachine.Instance.GameScreen.TargetingControl.SelectedTargetMenu)
UIStateMachine.Instance.GameScreen.TargetingControl.SelectedTargetMenu = null;
}
Hidden?.Invoke(this, NoesisEventArgs.Empty);
}
public bool Toggle()
{
if (IsOverlayVisible)
{
Hide();
return false;
}
else
{
Show();
return true;
}
}
protected void UpdateWindowDragBehavior()
{
if (IsDragAllowed && PlayerPreferences.Instance.WindowDragEnabled || IsDragEnabled)
{
if (Interaction.GetBehaviors(this).Count == 0)
{
ParentHorizontalAlignment = HorizontalAlignment.Stretch;
ParentVerticalAlignment = VerticalAlignment.Stretch;
HorizontalAlignment = HorizontalAlignment.Center;
VerticalAlignment = VerticalAlignment.Center;
MouseDragElementBehavior dragBehavior = new MouseDragElementBehavior();
dragBehavior.ConstrainToParentBounds = true;
Interaction.GetBehaviors(this).Add(dragBehavior);
}
}
else
{
if (Interaction.GetBehaviors(this).Count > 0)
Interaction.GetBehaviors(this).Clear();
}
}
public Vector2 GetViewboxScale()
{
return _OverlayLayer.GetViewboxScale();
}
protected void UpdateLightDismiss()
{
// Noesis MouseUp event processing runs independent of PickingManager MouseDown processing. The Show() method
// is invoked from InteractionEventManager. For this reason, it is possible for PickingManager to request Show() AND
// for _ParentGrid.MouseUp to fire immediately thereafter. Variable _InteractionFrame tracks the frame for Show(), and
// subsequently ignores mouse events occuring on this same frame. While unfortunate, this is necessary logic to accomodate
// parallel threads which have access to the same data structure. The alternative, using Noesis for all UI or Unity for all UI
// (ray casting), is not tennable due to the inherent disconnect between 2D (Noesis) and 3D (Picking).
_ParentGrid.MouseLeftButtonUp -= LightDismissExteriorMouseUp;
if (IsLightDismissExteriorEnabled)
_ParentGrid.MouseLeftButtonUp += LightDismissExteriorMouseUp;
MouseLeftButtonUp -= LightDismissInteriorMouseUp;
if (!IsLightDismissInteriorEnabled)
MouseLeftButtonUp += LightDismissInteriorMouseUp;
}
private void LightDismissExteriorMouseUp(object sender, MouseButtonEventArgs args)
{
if (OpenFrame != Time.frameCount && !PickingManager.Instance.InteractionFired)
{
HideReason = HideReasonType.LightDismiss;
Hide();
}
}
private void LightDismissInteriorMouseUp(object sender, MouseButtonEventArgs args)
{
if (OpenFrame != Time.frameCount && !PickingManager.Instance.InteractionFired)
args.Handled = true;
}
public virtual void UpdateInput()
{
if (OpenFrame != Time.frameCount)
if (!PickingManager.Instance.InteractionFired)
if (IsLightDismissExteriorEnabled || IsLightDismissInteriorEnabled || IsEscapeToCloseEnabled)
{
if (UseKeyUpEvent)
{
if (Input.GetButtonUp(InputNames.GamePad.B) || Input.GetKeyUp(KeyCode.Escape) ||
(IsAlternateKeyToCloseEnabled && Input.GetKeyDown(AlternateCloseKey)))
Hide();
}
else
{
if (Input.GetButtonDown(InputNames.GamePad.B) || Input.GetKeyDown(KeyCode.Escape) ||
(IsAlternateKeyToCloseEnabled && Input.GetKeyDown(AlternateCloseKey)))
Hide();
}
}
}
}
} |
|
|
Edited initial issue above to note that the behavior manifests after every edit to a CS file. |
|
|
OK, I likely misunderstood our previous issue. I thought adding [AssetDependency] was sufficient to resolve dependencies. I have learned that I need to either define asset dependencies in code using the attribute or in XAML using the deprecated Dependencies tag. I am now using the Dependencies tag in XAML and the above behaviors are resolved. Candidate for closure. Thanks! |
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-08-20 19:23 | stonstad | New Issue | |
| 2026-08-20 19:23 | stonstad | File Added: TitleScreen.xaml | |
| 2026-08-20 19:23 | stonstad | File Added: TitleScreen.xaml.cs | |
| 2026-08-20 19:23 | stonstad | Summary | AssetDependency Fails After Subsequent Stop/Play Cycle => 4.0 RC5. AssetDependency Fails After Subsequent Stop/Play Cycle |
| 2026-08-20 19:28 | stonstad | Description Updated | |
| 2026-08-20 19:43 | stonstad | Note Added: 0012538 | |
| 2026-08-20 19:43 | stonstad | File Added: SettingsControl.xaml | |
| 2026-08-20 19:43 | stonstad | File Added: SettingsControl.xaml.cs | |
| 2026-08-20 19:43 | stonstad | File Added: OverlayControl.cs | |
| 2026-08-20 19:45 | stonstad | Description Updated | |
| 2026-08-20 19:46 | stonstad | Note Added: 0012539 | |
| 2026-08-20 19:47 | stonstad | Note Edited: 0012539 | |
| 2026-08-20 20:16 | stonstad | Note Added: 0012540 | |
| 2026-08-20 20:16 | stonstad | Note Edited: 0012540 |