mirror of
https://github.com/hawkeye-stan/msfs-popout-panel-manager.git
synced 2024-12-04 03:30:10 +00:00
Added dynamic lod with auto fps
This commit is contained in:
parent
b0a6079800
commit
c68ec210d1
28 changed files with 1066 additions and 1166 deletions
|
@ -11,9 +11,9 @@
|
||||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||||
<RootNamespace>MSFSPopoutPanelManager.DomainModel</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.DomainModel</RootNamespace>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<DebugType>Embedded</DebugType>
|
<DebugType>Embedded</DebugType>
|
||||||
<Configurations>Debug;Release;Local</Configurations>
|
<Configurations>Debug;Release;Local</Configurations>
|
||||||
|
|
38
DomainModel/DynamicLod/DynamicLodSimData.cs
Normal file
38
DomainModel/DynamicLod/DynamicLodSimData.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using MSFSPopoutPanelManager.Shared;
|
||||||
|
|
||||||
|
namespace MSFSPopoutPanelManager.DomainModel.DynamicLod
|
||||||
|
{
|
||||||
|
public class DynamicLodSimData : ObservableObject
|
||||||
|
{
|
||||||
|
public int Fps { get; set; }
|
||||||
|
|
||||||
|
public int Tlod { get; set; }
|
||||||
|
|
||||||
|
public int Olod { get; set; }
|
||||||
|
|
||||||
|
public double Agl { get; set; }
|
||||||
|
|
||||||
|
public string CloudQuality { get; set; } = "N/A";
|
||||||
|
|
||||||
|
public double AltAboveGround { get; set; }
|
||||||
|
|
||||||
|
public double AltAboveGroundMinusCg { get; set; }
|
||||||
|
|
||||||
|
public double GroundVelocity { get; set; }
|
||||||
|
|
||||||
|
public bool PlaneOnGround { get; set; } = true;
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Fps = 0;
|
||||||
|
Tlod = 0;
|
||||||
|
Olod = 0;
|
||||||
|
Agl = 0;
|
||||||
|
CloudQuality = "N/A";
|
||||||
|
AltAboveGround = 0;
|
||||||
|
AltAboveGroundMinusCg = 0;
|
||||||
|
GroundVelocity = 0;
|
||||||
|
PlaneOnGround = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
using MSFSPopoutPanelManager.Shared;
|
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.DomainModel.DynamicLod
|
|
||||||
{
|
|
||||||
public class LodConfig : ObservableObject
|
|
||||||
{
|
|
||||||
public int Agl { get; set; }
|
|
||||||
|
|
||||||
public int Lod { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.DomainModel.DynamicLod
|
|
||||||
{
|
|
||||||
public class ObservableLodConfigLinkedList : LinkedList<LodConfig>, INotifyCollectionChanged
|
|
||||||
{
|
|
||||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
||||||
public void OnNotifyCollectionChanged(NotifyCollectionChangedAction action, LodConfig item)
|
|
||||||
{
|
|
||||||
if (CollectionChanged == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case NotifyCollectionChangedAction.Add:
|
|
||||||
case NotifyCollectionChangedAction.Remove:
|
|
||||||
case NotifyCollectionChangedAction.Reset:
|
|
||||||
CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void AddFirst(LodConfig item)
|
|
||||||
{
|
|
||||||
base.AddFirst(item);
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void AddLast(LodConfig item)
|
|
||||||
{
|
|
||||||
base.AddLast(item);
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void AddBefore(LinkedListNode<LodConfig> node, LinkedListNode<LodConfig> newNode)
|
|
||||||
{
|
|
||||||
base.AddBefore(node, newNode);
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, newNode.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void AddAfter(LinkedListNode<LodConfig> node, LinkedListNode<LodConfig> newNode)
|
|
||||||
{
|
|
||||||
base.AddAfter(node, newNode);
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, newNode.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void Remove(LodConfig item)
|
|
||||||
{
|
|
||||||
base.Remove(item);
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Remove, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void RemoveFirst()
|
|
||||||
{
|
|
||||||
if (First == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
base.RemoveFirst();
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Remove, First.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void RemoveLast()
|
|
||||||
{
|
|
||||||
if (Last == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
base.RemoveLast();
|
|
||||||
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Remove, Last.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,4 @@
|
||||||
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
|
using MSFSPopoutPanelManager.Shared;
|
||||||
using MSFSPopoutPanelManager.Shared;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||||
{
|
{
|
||||||
|
@ -11,31 +7,13 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||||
public DynamicLodSetting()
|
public DynamicLodSetting()
|
||||||
{
|
{
|
||||||
InitializeChildPropertyChangeBinding();
|
InitializeChildPropertyChangeBinding();
|
||||||
|
|
||||||
TlodConfigs.CollectionChanged += (_, e) =>
|
|
||||||
{
|
|
||||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
|
||||||
{
|
|
||||||
if (e.NewItems?[0] is LodConfig item)
|
|
||||||
item.PropertyChanged += (_, _) => TlodConfigs.OnNotifyCollectionChanged(NotifyCollectionChangedAction.Reset, item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
OlodConfigs.CollectionChanged += (_, e) =>
|
|
||||||
{
|
|
||||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
|
||||||
{
|
|
||||||
if (e.NewItems?[0] is LodConfig item)
|
|
||||||
item.PropertyChanged += (_, _) => OlodConfigs.OnNotifyCollectionChanged(NotifyCollectionChangedAction.Reset, item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEnabled { get; set; } = false;
|
public bool IsEnabled { get; set; } = false;
|
||||||
|
|
||||||
public ObservableLodConfigLinkedList TlodConfigs { get; set; } = new();
|
public bool PauseWhenMsfsLoseFocus { get; set; } = true;
|
||||||
|
|
||||||
public ObservableLodConfigLinkedList OlodConfigs { get; set; } = new();
|
public bool PauseOutsideCockpitView { get; set; } = true;
|
||||||
|
|
||||||
public bool ResetEnabled { get; set; } = false;
|
public bool ResetEnabled { get; set; } = false;
|
||||||
|
|
||||||
|
@ -43,29 +21,28 @@ namespace MSFSPopoutPanelManager.DomainModel.Setting
|
||||||
|
|
||||||
public int ResetOlod { get; set; } = 100;
|
public int ResetOlod { get; set; } = 100;
|
||||||
|
|
||||||
public void AddDefaultTLodConfigs()
|
public int TargetedFps { get; set; } = 60;
|
||||||
{
|
|
||||||
TlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 0, Lod = 100 }));
|
|
||||||
TlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 5000, Lod = 200 }));
|
|
||||||
TlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 10000, Lod = 300 }));
|
|
||||||
TlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 20000, Lod = 400 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddDefaultOLodConfigs()
|
public int FpsTolerance { get; set; } = 5;
|
||||||
{
|
|
||||||
OlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 0, Lod = 200 }));
|
|
||||||
OlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 1000, Lod = 150 }));
|
|
||||||
OlodConfigs.AddLast(new LinkedListNode<LodConfig>(new LodConfig { Agl = 5000, Lod = 100 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
[OnDeserialized]
|
public bool TlodMinOnGround { get; set; } = true;
|
||||||
private void OnDeserialization(StreamingContext context)
|
|
||||||
{
|
|
||||||
foreach (var item in TlodConfigs)
|
|
||||||
item.PropertyChanged += (_, _) => TlodConfigs.OnNotifyCollectionChanged(NotifyCollectionChangedAction.Reset, item);
|
|
||||||
|
|
||||||
foreach (var item in OlodConfigs)
|
public int AltTlodBase { get; set; } = 1000;
|
||||||
item.PropertyChanged += (_, _) => OlodConfigs.OnNotifyCollectionChanged(NotifyCollectionChangedAction.Reset, item);
|
|
||||||
}
|
public int TlodMin { get; set; } = 50;
|
||||||
|
|
||||||
|
public int TlodMax { get; set; } = 400;
|
||||||
|
|
||||||
|
public int CloudRecoveryTlod { get; set; } = 100;
|
||||||
|
|
||||||
|
public bool DecreaseCloudQuality { get; set; } = true;
|
||||||
|
|
||||||
|
public int OlodTop { get; set; } = 20;
|
||||||
|
|
||||||
|
public int OlodBase { get; set; } = 200;
|
||||||
|
|
||||||
|
public int AltOlodBase { get; set; } = 1000;
|
||||||
|
|
||||||
|
public int AltOlodTop { get; set; } = 10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,11 @@ namespace MSFSPopoutPanelManager.MainApp
|
||||||
|
|
||||||
services.AddSingleton(s => new AppOrchestrator(SharedStorage, s.GetRequiredService<PanelConfigurationOrchestrator>(), s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<HelpOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
services.AddSingleton(s => new AppOrchestrator(SharedStorage, s.GetRequiredService<PanelConfigurationOrchestrator>(), s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<HelpOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
||||||
services.AddSingleton(_ => new ProfileOrchestrator(SharedStorage));
|
services.AddSingleton(_ => new ProfileOrchestrator(SharedStorage));
|
||||||
|
services.AddSingleton(_ => new DynamicLodOrchestrator(SharedStorage));
|
||||||
services.AddSingleton(s => new PanelSourceOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>()));
|
services.AddSingleton(s => new PanelSourceOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>()));
|
||||||
services.AddSingleton(s => new PanelPopOutOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<PanelSourceOrchestrator>(), s.GetRequiredService<PanelConfigurationOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
services.AddSingleton(s => new PanelPopOutOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<PanelSourceOrchestrator>(), s.GetRequiredService<PanelConfigurationOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
||||||
services.AddSingleton(s => new PanelConfigurationOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
services.AddSingleton(s => new PanelConfigurationOrchestrator(SharedStorage, s.GetRequiredService<FlightSimOrchestrator>(), s.GetRequiredService<KeyboardOrchestrator>()));
|
||||||
services.AddSingleton(_ => new FlightSimOrchestrator(SharedStorage));
|
services.AddSingleton(s => new FlightSimOrchestrator(SharedStorage, s.GetRequiredService<DynamicLodOrchestrator>()));
|
||||||
services.AddSingleton(_ => new KeyboardOrchestrator(SharedStorage));
|
services.AddSingleton(_ => new KeyboardOrchestrator(SharedStorage));
|
||||||
services.AddSingleton(_ => new HelpOrchestrator());
|
services.AddSingleton(_ => new HelpOrchestrator());
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
x:Class="MSFSPopoutPanelManager.MainApp.AppUserControl.Dialog.AddProfileDialog"
|
x:Class="MSFSPopoutPanelManager.MainApp.AppUserControl.Dialog.AddProfileDialog"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:converter="clr-namespace:MSFSPopoutPanelManager.MainApp.Converter"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
xmlns:local="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
xmlns:viewmodel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||||
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
|
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
|
||||||
xmlns:converter="clr-namespace:MSFSPopoutPanelManager.MainApp.Converter"
|
|
||||||
Width="400"
|
Width="400"
|
||||||
Height="210"
|
Height="210"
|
||||||
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
|
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
|
||||||
|
|
|
@ -3,26 +3,33 @@
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mainApp="clr-namespace:MSFSPopoutPanelManager.MainApp"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||||
xmlns:viewModel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
xmlns:viewModel="clr-namespace:MSFSPopoutPanelManager.MainApp.ViewModel"
|
||||||
xmlns:appUserControl="clr-namespace:MSFSPopoutPanelManager.MainApp.AppUserControl"
|
|
||||||
d:DesignHeight="800"
|
d:DesignHeight="800"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<system:Double x:Key="IconSize">22</system:Double>
|
<system:Double x:Key="IconSize">22</system:Double>
|
||||||
<system:Double x:Key="ButtonSize">22</system:Double>
|
<system:Double x:Key="ButtonSize">22</system:Double>
|
||||||
|
<Style
|
||||||
|
x:Key="TextBlockHeading"
|
||||||
|
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||||
|
TargetType="TextBlock">
|
||||||
|
<Setter Property="TextWrapping" Value="Wrap" />
|
||||||
|
<Setter Property="Width" Value="Auto" />
|
||||||
|
<Setter Property="Margin" Value="0,5,0,0" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="FontWeight" Value="Bold" />
|
||||||
|
</Style>
|
||||||
<Style
|
<Style
|
||||||
x:Key="TextBlockLabel"
|
x:Key="TextBlockLabel"
|
||||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||||
TargetType="TextBlock">
|
TargetType="TextBlock">
|
||||||
<Setter Property="FontSize" Value="14" />
|
<Setter Property="FontSize" Value="12" />
|
||||||
<Setter Property="TextWrapping" Value="Wrap" />
|
<Setter Property="TextWrapping" Value="Wrap" />
|
||||||
<Setter Property="Width" Value="650" />
|
<Setter Property="Margin" Value="0,7,0,0" />
|
||||||
<Setter Property="Margin" Value="5,0,0,0" />
|
|
||||||
<Setter Property="LineHeight" Value="20" />
|
<Setter Property="LineHeight" Value="20" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style
|
<Style
|
||||||
|
@ -33,522 +40,238 @@
|
||||||
</Style>
|
</Style>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Grid d:DataContext="{d:DesignInstance viewModel:ApplicationViewModel}">
|
<Grid d:DataContext="{d:DesignInstance viewModel:ApplicationViewModel}">
|
||||||
<WrapPanel Margin="30,10,0,0">
|
<WrapPanel Orientation="Vertical">
|
||||||
<!-- Terrain level of detail -->
|
<WrapPanel Margin="120,10,0,0">
|
||||||
<WrapPanel Margin="20,0,0,0" Orientation="Vertical">
|
<GroupBox
|
||||||
<TextBlock
|
|
||||||
Margin="0,0,0,5"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
FontSize="16"
|
|
||||||
FontWeight="Bold">
|
|
||||||
Terrain Level of Detail (TLOD)
|
|
||||||
</TextBlock>
|
|
||||||
<DataGrid
|
|
||||||
Name="TlodGrid"
|
|
||||||
Width="272"
|
|
||||||
Height="248"
|
|
||||||
Margin="0"
|
Margin="0"
|
||||||
HorizontalAlignment="Center"
|
Padding="5,2,5,2"
|
||||||
AutoGenerateColumns="False"
|
Header="Sim Values"
|
||||||
BorderThickness="1"
|
Style="{StaticResource MaterialDesignGroupBox}">
|
||||||
CanUserAddRows="False"
|
<GroupBox.HeaderTemplate>
|
||||||
CanUserDeleteRows="False"
|
<HierarchicalDataTemplate>
|
||||||
CanUserReorderColumns="False"
|
<Label
|
||||||
CanUserResizeColumns="False"
|
Height="12"
|
||||||
CanUserResizeRows="False"
|
Margin="10,1,1,1"
|
||||||
CanUserSortColumns="False"
|
Padding="0"
|
||||||
GridLinesVisibility="None"
|
FontSize="12">
|
||||||
HeadersVisibility="Column"
|
Sim Values
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
</Label>
|
||||||
ItemsSource="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs}"
|
</HierarchicalDataTemplate>
|
||||||
SelectionUnit="FullRow"
|
</GroupBox.HeaderTemplate>
|
||||||
VerticalGridLinesBrush="#B9B9B9">
|
<WrapPanel Margin="3">
|
||||||
<DataGrid.RowStyle>
|
<TextBox
|
||||||
<Style TargetType="DataGridRow">
|
Width="75"
|
||||||
<Setter Property="Background" Value="{x:Null}" />
|
Margin="20,0,0,0"
|
||||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
</Style>
|
materialDesign:HintAssist.Hint="FPS"
|
||||||
</DataGrid.RowStyle>
|
IsHitTestVisible="False"
|
||||||
<DataGrid.ColumnHeaderStyle>
|
IsReadOnly="True"
|
||||||
<Style TargetType="DataGridColumnHeader">
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
<Setter Property="ContentTemplate">
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
<Setter.Value>
|
Text="{Binding FlightSimData.DynamicLodSimData.Fps, StringFormat='{}{0:0}'}" />
|
||||||
<DataTemplate>
|
<TextBox
|
||||||
<TextBlock
|
Width="75"
|
||||||
FontSize="14"
|
Margin="20,0,0,0"
|
||||||
Text="{Binding}"
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
TextAlignment="Center"
|
materialDesign:HintAssist.Hint="TLOD"
|
||||||
TextWrapping="Wrap" />
|
IsHitTestVisible="False"
|
||||||
</DataTemplate>
|
IsReadOnly="True"
|
||||||
</Setter.Value>
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
</Setter>
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
Text="{Binding FlightSimData.DynamicLodSimData.Tlod}" />
|
||||||
<Setter Property="Height" Value="30" />
|
<TextBox
|
||||||
<Setter Property="Background" Value="#FF576573" />
|
Width="75"
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
Margin="20,0,0,0"
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
</Style>
|
materialDesign:HintAssist.Hint="OLOD"
|
||||||
</DataGrid.ColumnHeaderStyle>
|
IsHitTestVisible="False"
|
||||||
<DataGrid.CellStyle>
|
IsReadOnly="True"
|
||||||
<Style TargetType="DataGridCell">
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
<Setter Property="TextBlock.TextAlignment" Value="Center" />
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
Text="{Binding FlightSimData.DynamicLodSimData.Olod}" />
|
||||||
<Setter Property="Background" Value="Transparent" />
|
<TextBox
|
||||||
<Setter Property="Foreground" Value="White" />
|
Width="75"
|
||||||
</Style>
|
Margin="20,0,0,0"
|
||||||
</DataGrid.CellStyle>
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
<DataGrid.Columns>
|
materialDesign:HintAssist.Hint="AGL"
|
||||||
<DataGridTemplateColumn Width="100" Header="AGL">
|
IsHitTestVisible="False"
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
IsReadOnly="True"
|
||||||
<DataTemplate>
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
<TextBox
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
Width="100"
|
Text="{Binding FlightSimData.DynamicLodSimData.Agl, StringFormat='{}{0:0}'}" />
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
<TextBox
|
||||||
BorderThickness="0"
|
Width="75"
|
||||||
FontSize="14">
|
Margin="20,0,0,0"
|
||||||
<TextBox.Text>
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
<Binding
|
materialDesign:HintAssist.Hint="Clouds"
|
||||||
Mode="TwoWay"
|
IsHitTestVisible="False"
|
||||||
Path="Agl"
|
IsReadOnly="True"
|
||||||
UpdateSourceTrigger="LostFocus">
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
<Binding.ValidationRules>
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
<appUserControl:AglValidationRule />
|
Text="{Binding FlightSimData.DynamicLodSimData.CloudQuality}" />
|
||||||
</Binding.ValidationRules>
|
</WrapPanel>
|
||||||
</Binding>
|
</GroupBox>
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="LOD">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
Path="Lod"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:LodValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="70" Header="">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Button
|
|
||||||
Width="{StaticResource ButtonSize}"
|
|
||||||
Height="{StaticResource ButtonSize}"
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Click="TLodDelete_Click"
|
|
||||||
KeyboardNavigation.AcceptsReturn="False"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
ToolTip="Delete TLOD configuration">
|
|
||||||
<materialDesign:PackIcon
|
|
||||||
Width="{StaticResource IconSize}"
|
|
||||||
Height="{StaticResource IconSize}"
|
|
||||||
Kind="Delete" />
|
|
||||||
</Button>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
</DataGrid.Columns>
|
|
||||||
</DataGrid>
|
|
||||||
<WrapPanel Margin="0,5,0,0">
|
|
||||||
<DataGrid
|
|
||||||
Name="AddTlodGrid"
|
|
||||||
Width="272"
|
|
||||||
Height="50"
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
AutoGenerateColumns="False"
|
|
||||||
BorderThickness="0"
|
|
||||||
CanUserAddRows="False"
|
|
||||||
CanUserDeleteRows="False"
|
|
||||||
CanUserReorderColumns="False"
|
|
||||||
CanUserResizeColumns="False"
|
|
||||||
CanUserResizeRows="False"
|
|
||||||
CanUserSortColumns="False"
|
|
||||||
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
|
|
||||||
GridLinesVisibility="None"
|
|
||||||
HeadersVisibility="None"
|
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
|
||||||
ItemsSource="{Binding AddTlodConfigs}"
|
|
||||||
SelectionUnit="FullRow"
|
|
||||||
VerticalGridLinesBrush="#B9B9B9"
|
|
||||||
VerticalScrollBarVisibility="Disabled">
|
|
||||||
<DataGrid.RowStyle>
|
|
||||||
<Style TargetType="DataGridRow">
|
|
||||||
<Setter Property="Background" Value="{x:Null}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.RowStyle>
|
|
||||||
<DataGrid.CellStyle>
|
|
||||||
<Style TargetType="DataGridCell">
|
|
||||||
<Setter Property="TextBlock.TextAlignment" Value="Center" />
|
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
|
||||||
<Setter Property="Background" Value="Transparent" />
|
|
||||||
<Setter Property="Foreground" Value="White" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.CellStyle>
|
|
||||||
<DataGrid.Columns>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="AGL">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:HintAssist.Hint="New AGL"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14"
|
|
||||||
SourceUpdated="AddTlod_SourceUpdated">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
NotifyOnSourceUpdated="True"
|
|
||||||
Path="Agl"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:AglValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="LOD">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:HintAssist.Hint="New LOD"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14"
|
|
||||||
SourceUpdated="AddTlod_SourceUpdated">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
NotifyOnSourceUpdated="True"
|
|
||||||
Path="Lod"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:LodValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="70" Header="">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<materialDesign:PackIcon
|
|
||||||
Width="{StaticResource IconSize}"
|
|
||||||
Height="{StaticResource IconSize}"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Foreground="White"
|
|
||||||
Kind="Add" />
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
</DataGrid.Columns>
|
|
||||||
</DataGrid>
|
|
||||||
</WrapPanel>
|
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
|
<WrapPanel Margin="47,10,0,0" Orientation="Vertical">
|
||||||
<!-- Object level of detail -->
|
<WrapPanel Margin="0,0,0,0">
|
||||||
<WrapPanel Margin="50,0,0,0" Orientation="Vertical">
|
<TextBlock Style="{StaticResource TextBlockHeading}">General Options</TextBlock>
|
||||||
<TextBlock
|
<Line
|
||||||
Margin="0,0,0,5"
|
Stretch="Fill"
|
||||||
HorizontalAlignment="Center"
|
Stroke="Gray"
|
||||||
FontSize="16"
|
X2="1" />
|
||||||
FontWeight="Bold">
|
|
||||||
Object Level of Detail (OLOD)
|
|
||||||
</TextBlock>
|
|
||||||
<DataGrid
|
|
||||||
Name="OlodGrid"
|
|
||||||
Width="272"
|
|
||||||
Height="248"
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
AutoGenerateColumns="False"
|
|
||||||
BorderThickness="1"
|
|
||||||
CanUserAddRows="False"
|
|
||||||
CanUserDeleteRows="False"
|
|
||||||
CanUserReorderColumns="False"
|
|
||||||
CanUserResizeColumns="False"
|
|
||||||
CanUserResizeRows="False"
|
|
||||||
CanUserSortColumns="False"
|
|
||||||
GridLinesVisibility="None"
|
|
||||||
HeadersVisibility="Column"
|
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
|
||||||
ItemsSource="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs}"
|
|
||||||
SelectionUnit="FullRow"
|
|
||||||
VerticalGridLinesBrush="#B9B9B9">
|
|
||||||
<DataGrid.RowStyle>
|
|
||||||
<Style TargetType="DataGridRow">
|
|
||||||
<Setter Property="Background" Value="{x:Null}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.RowStyle>
|
|
||||||
<DataGrid.ColumnHeaderStyle>
|
|
||||||
<Style TargetType="DataGridColumnHeader">
|
|
||||||
<Setter Property="ContentTemplate">
|
|
||||||
<Setter.Value>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBlock
|
|
||||||
FontSize="14"
|
|
||||||
Text="{Binding}"
|
|
||||||
TextAlignment="Center"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</DataTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
|
||||||
<Setter Property="Height" Value="30" />
|
|
||||||
<Setter Property="Background" Value="#FF576573" />
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.ColumnHeaderStyle>
|
|
||||||
<DataGrid.CellStyle>
|
|
||||||
<Style TargetType="DataGridCell">
|
|
||||||
<Setter Property="TextBlock.TextAlignment" Value="Center" />
|
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
|
||||||
<Setter Property="Background" Value="Transparent" />
|
|
||||||
<Setter Property="Foreground" Value="White" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.CellStyle>
|
|
||||||
<DataGrid.Columns>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="AGL">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
Path="Agl"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:AglValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="LOD">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
Path="Lod"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:LodValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="70" Header="">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Button
|
|
||||||
Width="{StaticResource ButtonSize}"
|
|
||||||
Height="{StaticResource ButtonSize}"
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Click="OLodDelete_Click"
|
|
||||||
KeyboardNavigation.AcceptsReturn="False"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
ToolTip="Delete OLOD configuration">
|
|
||||||
<materialDesign:PackIcon
|
|
||||||
Width="{StaticResource IconSize}"
|
|
||||||
Height="{StaticResource IconSize}"
|
|
||||||
Kind="Delete" />
|
|
||||||
</Button>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
</DataGrid.Columns>
|
|
||||||
</DataGrid>
|
|
||||||
<WrapPanel Margin="0,5,0,0">
|
|
||||||
<DataGrid
|
|
||||||
Name="AddOlodGrid"
|
|
||||||
Width="272"
|
|
||||||
Height="50"
|
|
||||||
Margin="0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
AutoGenerateColumns="False"
|
|
||||||
BorderThickness="0"
|
|
||||||
CanUserAddRows="False"
|
|
||||||
CanUserDeleteRows="False"
|
|
||||||
CanUserReorderColumns="False"
|
|
||||||
CanUserResizeColumns="False"
|
|
||||||
CanUserResizeRows="False"
|
|
||||||
CanUserSortColumns="False"
|
|
||||||
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
|
|
||||||
GridLinesVisibility="None"
|
|
||||||
HeadersVisibility="None"
|
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
|
||||||
ItemsSource="{Binding AddOlodConfigs}"
|
|
||||||
SelectionUnit="FullRow"
|
|
||||||
VerticalGridLinesBrush="#B9B9B9"
|
|
||||||
VerticalScrollBarVisibility="Disabled">
|
|
||||||
<DataGrid.RowStyle>
|
|
||||||
<Style TargetType="DataGridRow">
|
|
||||||
<Setter Property="Background" Value="{x:Null}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{x:Null}" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.RowStyle>
|
|
||||||
<DataGrid.CellStyle>
|
|
||||||
<Style TargetType="DataGridCell">
|
|
||||||
<Setter Property="TextBlock.TextAlignment" Value="Center" />
|
|
||||||
<Setter Property="BorderBrush" Value="#FFB9B9B9" />
|
|
||||||
<Setter Property="Background" Value="Transparent" />
|
|
||||||
<Setter Property="Foreground" Value="White" />
|
|
||||||
</Style>
|
|
||||||
</DataGrid.CellStyle>
|
|
||||||
<DataGrid.Columns>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="AGL">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:HintAssist.Hint="New AGL"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14"
|
|
||||||
SourceUpdated="AddOlod_SourceUpdated">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
NotifyOnSourceUpdated="True"
|
|
||||||
Path="Agl"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:AglValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="100" Header="LOD">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBox
|
|
||||||
Width="100"
|
|
||||||
materialDesign:HintAssist.Hint="New LOD"
|
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
|
||||||
BorderThickness="0"
|
|
||||||
FontSize="14"
|
|
||||||
SourceUpdated="AddOlod_SourceUpdated">
|
|
||||||
<TextBox.Text>
|
|
||||||
<Binding
|
|
||||||
Mode="TwoWay"
|
|
||||||
NotifyOnSourceUpdated="True"
|
|
||||||
Path="Lod"
|
|
||||||
UpdateSourceTrigger="LostFocus">
|
|
||||||
<Binding.ValidationRules>
|
|
||||||
<appUserControl:LodValidationRule />
|
|
||||||
</Binding.ValidationRules>
|
|
||||||
</Binding>
|
|
||||||
</TextBox.Text>
|
|
||||||
</TextBox>
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
<DataGridTemplateColumn Width="70" Header="">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<materialDesign:PackIcon
|
|
||||||
Width="{StaticResource IconSize}"
|
|
||||||
Height="{StaticResource IconSize}"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Foreground="White"
|
|
||||||
Kind="Add" />
|
|
||||||
</DataTemplate>
|
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
|
||||||
</DataGridTemplateColumn>
|
|
||||||
</DataGrid.Columns>
|
|
||||||
</DataGrid>
|
|
||||||
</WrapPanel>
|
|
||||||
</WrapPanel>
|
|
||||||
<WrapPanel Margin="0,20,0,0" Orientation="Horizontal">
|
|
||||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.ResetEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
|
||||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
|
||||||
Enable reset of TLOD and OLOD to the following values when flight session ends.
|
|
||||||
</TextBlock>
|
|
||||||
<WrapPanel IsEnabled="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.ResetEnabled}" Orientation="Horizontal">
|
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="100"
|
Width="100"
|
||||||
Height="40"
|
Margin="0,0,0,0"
|
||||||
Margin="45,5,0,0"
|
Padding="5,5,0,0"
|
||||||
VerticalAlignment="Center"
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
HorizontalContentAlignment="Center"
|
materialDesign:HintAssist.Foreground="White"
|
||||||
materialDesign:HintAssist.Hint="Reset TLOD"
|
materialDesign:HintAssist.Hint="Targeted FPS"
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
Background="#607D8B"
|
||||||
BorderThickness="1"
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
FontSize="14"
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}">
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.TargetedFps, Mode=TwoWay}" />
|
||||||
<TextBox.Text>
|
<TextBox
|
||||||
<Binding Mode="TwoWay" Path="AppSettingData.ApplicationSetting.DynamicLodSetting.ResetTlod">
|
Width="75"
|
||||||
<Binding.ValidationRules>
|
Margin="40,0,0,0"
|
||||||
<appUserControl:LodValidationRule />
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
</Binding.ValidationRules>
|
materialDesign:HintAssist.Hint="FPS Tolerance"
|
||||||
</Binding>
|
materialDesign:TextFieldAssist.SuffixText="%"
|
||||||
</TextBox.Text>
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
</TextBox>
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.FpsTolerance, Mode=TwoWay}" />
|
||||||
|
<WrapPanel Margin="40,10,0,0">
|
||||||
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.PauseWhenMsfsLoseFocus, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
|
<TextBlock Style="{StaticResource TextBlockLabel}">Pause when MSFS loses focus</TextBlock>
|
||||||
|
</WrapPanel>
|
||||||
|
<WrapPanel Margin="20,10,0,0">
|
||||||
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.PauseOutsideCockpitView, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
|
<TextBlock Style="{StaticResource TextBlockLabel}">Pause when not in cockpit view</TextBlock>
|
||||||
|
</WrapPanel>
|
||||||
|
</WrapPanel>
|
||||||
|
<WrapPanel Margin="0,15,0,0">
|
||||||
|
<TextBlock Style="{StaticResource TextBlockHeading}">TLOD Options</TextBlock>
|
||||||
|
<Line
|
||||||
|
Stretch="Fill"
|
||||||
|
Stroke="Gray"
|
||||||
|
X2="1" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="0,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="TLOD Minimum"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.TlodMin, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="TLOD Maximum"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.TlodMax, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="TLOD Base Alt"
|
||||||
|
materialDesign:TextFieldAssist.SuffixText="ft"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.AltTlodBase, Mode=TwoWay}" />
|
||||||
|
<WrapPanel Margin="40,10,0,0">
|
||||||
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.TlodMinOnGround, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
|
<TextBlock Style="{StaticResource TextBlockLabel}">TLOD minimum on ground/TLOD Base Altitude</TextBlock>
|
||||||
|
</WrapPanel>
|
||||||
|
</WrapPanel>
|
||||||
|
<WrapPanel Margin="0,15,0,0">
|
||||||
|
<TextBlock Style="{StaticResource TextBlockHeading}">OLOD Options</TextBlock>
|
||||||
|
<Line
|
||||||
|
Stretch="Fill"
|
||||||
|
Stroke="Gray"
|
||||||
|
X2="1" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="0,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="OLOD at Base Alt"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.OlodBase, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="OLOD at Top Alt"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.OlodTop, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="OLOD Base Alt"
|
||||||
|
materialDesign:TextFieldAssist.SuffixText="ft"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.AltOlodBase, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="OLOD Top Alt"
|
||||||
|
materialDesign:TextFieldAssist.SuffixText="ft"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.AltOlodTop, Mode=TwoWay}" />
|
||||||
|
</WrapPanel>
|
||||||
|
<WrapPanel Margin="0,15,0,0">
|
||||||
|
<TextBlock Style="{StaticResource TextBlockHeading}">Cloud Options</TextBlock>
|
||||||
|
<Line
|
||||||
|
Stretch="Fill"
|
||||||
|
Stroke="Gray"
|
||||||
|
X2="1" />
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="100"
|
Width="100"
|
||||||
Height="40"
|
Margin="0,0,0,0"
|
||||||
Margin="20,5,0,0"
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
VerticalAlignment="Center"
|
materialDesign:HintAssist.Hint="Cloud Adjust at TLOD"
|
||||||
HorizontalContentAlignment="Center"
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
materialDesign:HintAssist.Hint="Reset OLOD"
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
materialDesign:ValidationAssist.HorizontalAlignment="Center"
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.CloudRecoveryTlod, Mode=TwoWay}" />
|
||||||
BorderThickness="1"
|
<WrapPanel Margin="20,10,0,0">
|
||||||
FontSize="14"
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.DecreaseCloudQuality, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}">
|
<TextBlock Style="{StaticResource TextBlockLabel}">Decrease cloud quality by one level to archive desired FPS</TextBlock>
|
||||||
<TextBox.Text>
|
</WrapPanel>
|
||||||
<Binding Mode="TwoWay" Path="AppSettingData.ApplicationSetting.DynamicLodSetting.ResetOlod">
|
</WrapPanel>
|
||||||
<Binding.ValidationRules>
|
<WrapPanel Margin="0,15,0,0">
|
||||||
<appUserControl:LodValidationRule />
|
<TextBlock Style="{StaticResource TextBlockHeading}">Reset TLOD and OLOD on Exit</TextBlock>
|
||||||
</Binding.ValidationRules>
|
<Line
|
||||||
</Binding>
|
Stretch="Fill"
|
||||||
</TextBox.Text>
|
Stroke="Gray"
|
||||||
</TextBox>
|
X2="1" />
|
||||||
|
<WrapPanel Margin="0,0,0,0">
|
||||||
|
<WrapPanel Margin="0,7,0,0">
|
||||||
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.ResetEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
|
<TextBlock Style="{StaticResource TextBlockLabel}">Reset on Exit</TextBlock>
|
||||||
|
</WrapPanel>
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="TLOD"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.ResetTlod, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
Width="75"
|
||||||
|
Margin="40,0,0,0"
|
||||||
|
materialDesign:HintAssist.FloatingScale="0.75"
|
||||||
|
materialDesign:HintAssist.Hint="OLOD"
|
||||||
|
PreviewTextInput="TxtBox_NumbersOnly"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||||
|
Text="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.ResetOlod, Mode=TwoWay}" />
|
||||||
|
</WrapPanel>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
using System;
|
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Input;
|
||||||
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
|
|
||||||
using MSFSPopoutPanelManager.MainApp.ViewModel;
|
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.MainApp.AppUserControl
|
namespace MSFSPopoutPanelManager.MainApp.AppUserControl
|
||||||
{
|
{
|
||||||
public partial class DynamicLodPreference
|
public partial class DynamicLodPreference
|
||||||
{
|
{
|
||||||
private ObservableLodConfigLinkedList _tlodConfigs;
|
|
||||||
private ObservableLodConfigLinkedList _olodConfigs;
|
|
||||||
|
|
||||||
public DynamicLodPreference()
|
public DynamicLodPreference()
|
||||||
{
|
{
|
||||||
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
|
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
|
||||||
|
@ -24,146 +16,21 @@ namespace MSFSPopoutPanelManager.MainApp.AppUserControl
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTlodConfigs = new ObservableCollection<TempLodConfig>() { new () };
|
|
||||||
AddOlodConfigs = new ObservableCollection<TempLodConfig>() { new () };
|
|
||||||
|
|
||||||
Loaded += (_, _) =>
|
Loaded += (_, _) =>
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
var dataContext = DataContext as ApplicationViewModel;
|
var dataContext = DataContext as ApplicationViewModel;
|
||||||
_tlodConfigs = dataContext?.AppSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs;
|
|
||||||
_olodConfigs = dataContext?.AppSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<TempLodConfig> AddTlodConfigs { get; set; }
|
|
||||||
|
|
||||||
public ObservableCollection<TempLodConfig> AddOlodConfigs { get; set; }
|
private void TxtBox_NumbersOnly(object sender, TextCompositionEventArgs e)
|
||||||
|
|
||||||
private void AddTlod_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
||||||
{
|
{
|
||||||
var textBox = sender as TextBox;
|
e.Handled = !(int.TryParse(e.Text, out _) || (e.Text.Trim() == "-"));
|
||||||
|
|
||||||
var lodConfig = textBox?.DataContext as TempLodConfig;
|
|
||||||
|
|
||||||
if (lodConfig?.Agl == null || lodConfig.Lod == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (UpdateTlodDuplicate(lodConfig))
|
|
||||||
{
|
|
||||||
RebindTLodGrid();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetLodConfig = _tlodConfigs.LastOrDefault(x => lodConfig.Agl >= x.Agl);
|
|
||||||
var newLodConfig = new LodConfig { Agl = (int)lodConfig.Agl, Lod = (int)lodConfig.Lod };
|
|
||||||
|
|
||||||
if (targetLodConfig == null)
|
|
||||||
_tlodConfigs.AddFirst(newLodConfig);
|
|
||||||
else
|
|
||||||
_tlodConfigs.AddAfter(_tlodConfigs.Find(targetLodConfig), new LinkedListNode<LodConfig>(newLodConfig));
|
|
||||||
|
|
||||||
RebindTLodGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TLodDelete_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var button = e.Source as Button;
|
|
||||||
|
|
||||||
if(button?.DataContext is not LodConfig lodConfig)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_tlodConfigs.Remove(lodConfig);
|
|
||||||
|
|
||||||
RebindTLodGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RebindTLodGrid()
|
|
||||||
{
|
|
||||||
this.TlodGrid.ItemsSource = null;
|
|
||||||
this.TlodGrid.ItemsSource = _tlodConfigs.ToList();
|
|
||||||
|
|
||||||
AddTlodConfigs.Clear();
|
|
||||||
AddTlodConfigs.Add(new TempLodConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool UpdateTlodDuplicate(TempLodConfig lodConfig)
|
|
||||||
{
|
|
||||||
var tlodConfig = _tlodConfigs.FirstOrDefault(x => x.Agl == lodConfig.Agl);
|
|
||||||
|
|
||||||
if(tlodConfig == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
tlodConfig.Lod = Convert.ToInt32(lodConfig.Lod);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddOlod_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
||||||
{
|
|
||||||
var textBox = sender as TextBox;
|
|
||||||
|
|
||||||
var lodConfig = textBox?.DataContext as TempLodConfig;
|
|
||||||
|
|
||||||
if (lodConfig?.Agl == null || lodConfig.Lod == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (UpdateOlodDuplicate(lodConfig))
|
|
||||||
{
|
|
||||||
RebindOLodGrid();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetLodConfig = _olodConfigs.LastOrDefault(x => lodConfig.Agl >= x.Agl);
|
|
||||||
var newLodConfig = new LodConfig() { Agl = (int)lodConfig.Agl, Lod = (int)lodConfig.Lod };
|
|
||||||
|
|
||||||
if (targetLodConfig == null)
|
|
||||||
_olodConfigs.AddFirst(newLodConfig);
|
|
||||||
else
|
|
||||||
_olodConfigs.AddAfter(_olodConfigs.Find(targetLodConfig), new LinkedListNode<LodConfig>(newLodConfig));
|
|
||||||
|
|
||||||
RebindOLodGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OLodDelete_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var button = e.Source as Button;
|
|
||||||
|
|
||||||
if (button?.DataContext is not LodConfig lodConfig)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_olodConfigs.Remove(lodConfig);
|
|
||||||
|
|
||||||
RebindOLodGrid();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RebindOLodGrid()
|
|
||||||
{
|
|
||||||
this.OlodGrid.ItemsSource = null;
|
|
||||||
this.OlodGrid.ItemsSource = _olodConfigs.ToList();
|
|
||||||
|
|
||||||
AddOlodConfigs.Clear();
|
|
||||||
AddOlodConfigs.Add(new TempLodConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool UpdateOlodDuplicate(TempLodConfig lodConfig)
|
|
||||||
{
|
|
||||||
var olodConfig = _olodConfigs.FirstOrDefault(x => x.Agl == lodConfig.Agl);
|
|
||||||
|
|
||||||
if (olodConfig == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
olodConfig.Lod = Convert.ToInt32(lodConfig.Lod);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TempLodConfig
|
|
||||||
{
|
|
||||||
public int? Agl { get; set; }
|
|
||||||
|
|
||||||
public int? Lod { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AglValidationRule : ValidationRule
|
public class AglValidationRule : ValidationRule
|
||||||
{
|
{
|
||||||
|
|
|
@ -633,21 +633,23 @@
|
||||||
<WrapPanel Visibility="{c:Binding LocalCompileOnly}">
|
<WrapPanel Visibility="{c:Binding LocalCompileOnly}">
|
||||||
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
<WrapPanel Orientation="Vertical" Visibility="{Binding ElementName=CategoryDynamicLodSettings, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||||
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
<WrapPanel Margin="0,0,20,20" Orientation="Vertical">
|
||||||
<TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details (Not Supported)</TextBlock>
|
<WrapPanel>
|
||||||
|
<TextBlock
|
||||||
|
Padding="0,0,5,0"
|
||||||
|
Foreground="Red"
|
||||||
|
Style="{StaticResource TextBlockHeading}">
|
||||||
|
(Unsupported Feature)
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource TextBlockHeading}">Dynamically adjust Terrain and Object Level of Details</TextBlock>
|
||||||
|
</WrapPanel>
|
||||||
<Line
|
<Line
|
||||||
Stretch="Fill"
|
Stretch="Fill"
|
||||||
Stroke="Gray"
|
Stroke="Gray"
|
||||||
X2="1" />
|
X2="1" />
|
||||||
<TextBlock
|
|
||||||
Margin="0,10,0,10"
|
|
||||||
Foreground="Red"
|
|
||||||
Style="{StaticResource TextBlockLabel}">
|
|
||||||
*** Experimental and not supported. Use at your own risk since this feature directly modifies MSFS memory. ***
|
|
||||||
</TextBlock>
|
|
||||||
<WrapPanel>
|
<WrapPanel>
|
||||||
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
<ToggleButton IsChecked="{Binding AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Mode=TwoWay}" Style="{StaticResource ToggleButton}" />
|
||||||
<TextBlock Style="{StaticResource TextBlockLabel}">
|
<TextBlock Style="{StaticResource TextBlockLabel}">
|
||||||
Enable automatic adjustment of terrain level of detail (TLOD) and object level of detail (OLOD) based on current aircraft's above ground level (in feet).
|
Enable automatic adjustments of TLOD and OLOD to get the desired targeted frame rate (FPS).
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
<WrapPanel Visibility="{Binding Path=AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
<RootNamespace>MSFSPopoutPanelManager.MainApp</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.MainApp</RootNamespace>
|
||||||
<ApplicationIcon>logo.ico</ApplicationIcon>
|
<ApplicationIcon>logo.ico</ApplicationIcon>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||||
<!-- Publishing options -->
|
<!-- Publishing options -->
|
||||||
|
|
|
@ -33,15 +33,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
// Add default dynamic LOD configs
|
|
||||||
if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled &&
|
|
||||||
AppSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.Count == 0 &&
|
|
||||||
AppSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.Count == 0)
|
|
||||||
{
|
|
||||||
AppSettingData.ApplicationSetting.DynamicLodSetting.AddDefaultTLodConfigs();
|
|
||||||
AppSettingData.ApplicationSetting.DynamicLodSetting.AddDefaultOLodConfigs();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AppSettingData.ApplicationSetting.GeneralSetting.CheckForUpdate)
|
if (AppSettingData.ApplicationSetting.GeneralSetting.CheckForUpdate)
|
||||||
CheckForAutoUpdate();
|
CheckForAutoUpdate();
|
||||||
|
|
||||||
|
|
|
@ -38,17 +38,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ApplicationSetting.DynamicLodSetting.TlodConfigs.CollectionChanged += (_, e) =>
|
|
||||||
{
|
|
||||||
if (e.Action == NotifyCollectionChangedAction.Reset)
|
|
||||||
AppSettingDataManager.WriteAppSetting(ApplicationSetting);
|
|
||||||
};
|
|
||||||
|
|
||||||
ApplicationSetting.DynamicLodSetting.OlodConfigs.CollectionChanged += (_, _) =>
|
|
||||||
{
|
|
||||||
AppSettingDataManager.WriteAppSetting(ApplicationSetting);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,257 +0,0 @@
|
||||||
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
|
|
||||||
using MSFSPopoutPanelManager.WindowsAgent;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.Orchestration
|
|
||||||
{
|
|
||||||
public class DynamicLodManager
|
|
||||||
{
|
|
||||||
private const string SIMMODULE_NAME = "WwiseLibPCx64P.dll";
|
|
||||||
private const int PROCESS_VM_OPERATION = 0x0008;
|
|
||||||
private const int PROCESS_VM_READ = 0x0010;
|
|
||||||
private const int PROCESS_VM_WRITE = 0x0020;
|
|
||||||
private const long OFFSET_MODULE_BASE =0x004B2368;
|
|
||||||
private const long OFFSET_POINTER_MAIN = 0x3D0;
|
|
||||||
private const long OFFSET_POINTER_TLOD_VR = 0x114;
|
|
||||||
private const long OFFSET_POINTER_TLOD = 0xC;
|
|
||||||
private const long OFFSET_POINTER_OLOD = 0xC;
|
|
||||||
|
|
||||||
private static bool _isActive;
|
|
||||||
private static WindowProcess _process;
|
|
||||||
private static IntPtr _processHandle;
|
|
||||||
private static long _processModuleAddress;
|
|
||||||
|
|
||||||
private static long _addressMain;
|
|
||||||
private static long _addressTlod;
|
|
||||||
private static long _addressOlod;
|
|
||||||
private static long _addressTlodVr;
|
|
||||||
private static long _addressOlodVr;
|
|
||||||
|
|
||||||
private static FlightSimData _flightSimData;
|
|
||||||
private static AppSettingData _appSettingData;
|
|
||||||
private static LinkedListNode<LodConfig> _nextTlod;
|
|
||||||
private static LinkedListNode<LodConfig> _nextOlod;
|
|
||||||
private static LinkedListNode<LodConfig> _currentTlod;
|
|
||||||
private static LinkedListNode<LodConfig> _currentOlod;
|
|
||||||
|
|
||||||
public static void Attach(FlightSimData flightSimData, AppSettingData appSettingData)
|
|
||||||
{
|
|
||||||
if (appSettingData == null || _isActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_flightSimData = flightSimData;
|
|
||||||
_appSettingData = appSettingData;
|
|
||||||
_flightSimData.OnAltAboveGroundChanged -= HandleOnAltAboveGroundChanged;
|
|
||||||
_flightSimData.OnAltAboveGroundChanged += HandleOnAltAboveGroundChanged;
|
|
||||||
|
|
||||||
_process = WindowProcessManager.SimulatorProcess;
|
|
||||||
_processModuleAddress = GetSimModuleAddress();
|
|
||||||
|
|
||||||
if (_process == null || _processModuleAddress == IntPtr.Zero)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_processHandle = PInvoke.OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, _process.ProcessId);
|
|
||||||
|
|
||||||
if (_processHandle == IntPtr.Zero)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_addressMain = ReadMemory<long>(_processModuleAddress + OFFSET_MODULE_BASE) + OFFSET_POINTER_MAIN;
|
|
||||||
_addressTlod = ReadMemory<long>(_addressMain) + OFFSET_POINTER_TLOD;
|
|
||||||
_addressTlodVr = ReadMemory<long>(_addressMain) + OFFSET_POINTER_TLOD_VR;
|
|
||||||
_addressOlod = _addressTlod + OFFSET_POINTER_OLOD;
|
|
||||||
_addressOlodVr = _addressTlodVr + OFFSET_POINTER_OLOD;
|
|
||||||
|
|
||||||
// Set initial LOD if already in cockpit
|
|
||||||
InitializeData();
|
|
||||||
|
|
||||||
_isActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Detach()
|
|
||||||
{
|
|
||||||
if (_appSettingData == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_appSettingData.ApplicationSetting.DynamicLodSetting.ResetEnabled)
|
|
||||||
{
|
|
||||||
WriteTlod(_appSettingData.ApplicationSetting.DynamicLodSetting.ResetTlod);
|
|
||||||
WriteOlod(_appSettingData.ApplicationSetting.DynamicLodSetting.ResetOlod);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isActive = false;
|
|
||||||
|
|
||||||
Debug.WriteLine($"Reset to custom LOD: TLOD: {_appSettingData.ApplicationSetting.DynamicLodSetting.ResetTlod}, OLOD: {_appSettingData.ApplicationSetting.DynamicLodSetting.ResetOlod}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void HandleOnAltAboveGroundChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (!_flightSimData.IsFlightStarted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var agl = _flightSimData.PlaneAltAboveGround < 0 ? 0 : _flightSimData.PlaneAltAboveGround;
|
|
||||||
|
|
||||||
if (_nextTlod != null && _nextTlod.Value.Agl <= agl)
|
|
||||||
{
|
|
||||||
_currentTlod = _nextTlod;
|
|
||||||
_nextTlod = _currentTlod.Next;
|
|
||||||
DynamicLodManager.WriteTlod(_currentTlod.Value.Lod);
|
|
||||||
}
|
|
||||||
else if (_currentTlod is { Previous: not null } && _currentTlod.Value.Agl > agl)
|
|
||||||
{
|
|
||||||
_currentTlod = _currentTlod.Previous;
|
|
||||||
|
|
||||||
if (_currentTlod != null)
|
|
||||||
{
|
|
||||||
_nextTlod = _currentTlod.Next;
|
|
||||||
DynamicLodManager.WriteTlod(_currentTlod.Value.Lod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_nextOlod != null && _nextOlod.Value.Agl <= agl)
|
|
||||||
{
|
|
||||||
_currentOlod = _nextOlod;
|
|
||||||
_nextOlod = _currentOlod.Next;
|
|
||||||
DynamicLodManager.WriteOlod(_currentOlod.Value.Lod);
|
|
||||||
}
|
|
||||||
else if (_currentOlod is { Previous: not null } && _currentOlod.Value.Agl > agl)
|
|
||||||
{
|
|
||||||
_currentOlod = _currentOlod.Previous;
|
|
||||||
|
|
||||||
if (_currentOlod != null)
|
|
||||||
{
|
|
||||||
_nextOlod = _currentOlod.Next;
|
|
||||||
DynamicLodManager.WriteOlod(_currentOlod.Value.Lod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_currentTlod != null && _currentOlod != null)
|
|
||||||
Debug.WriteLine($"Altitude: {agl}, TLOD: {_currentTlod.Value.Lod}, OLOD: {_currentOlod.Value.Lod}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteTlod(int value, bool isVr = false)
|
|
||||||
{
|
|
||||||
WriteMemory(isVr ? _addressTlodVr : _addressTlod, value / 100.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteOlod(int value, bool isVr = false)
|
|
||||||
{
|
|
||||||
WriteMemory(isVr ? _addressOlodVr : _addressOlod, value / 100.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long GetSimModuleAddress()
|
|
||||||
{
|
|
||||||
if (_process == null)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
foreach (ProcessModule processModule in _process.Modules)
|
|
||||||
{
|
|
||||||
if (processModule.ModuleName == SIMMODULE_NAME)
|
|
||||||
return processModule.BaseAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteMemory(long address, object value)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var buffer = StructureToByteArray(value);
|
|
||||||
PInvoke.NtWriteVirtualMemory(checked((int)_processHandle), address, buffer, buffer.Length, out _);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static T ReadMemory<T>(long address) where T : struct
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var byteSize = Marshal.SizeOf(typeof(T));
|
|
||||||
var buffer = new byte[byteSize];
|
|
||||||
PInvoke.NtReadVirtualMemory(checked((int)_processHandle), address, buffer, buffer.Length, out _);
|
|
||||||
return ByteArrayToStructure<T>(buffer);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
return default(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] StructureToByteArray(object obj)
|
|
||||||
{
|
|
||||||
var length = Marshal.SizeOf(obj);
|
|
||||||
var array = new byte[length];
|
|
||||||
var pointer = Marshal.AllocHGlobal(length);
|
|
||||||
|
|
||||||
Marshal.StructureToPtr(obj, pointer, true);
|
|
||||||
Marshal.Copy(pointer, array, 0, length);
|
|
||||||
Marshal.FreeHGlobal(pointer);
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
|
|
||||||
{
|
|
||||||
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
|
||||||
|
|
||||||
if(result != null)
|
|
||||||
return (T)result;
|
|
||||||
|
|
||||||
return default(T);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
handle.Free();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitializeData()
|
|
||||||
{
|
|
||||||
var agl = _flightSimData.PlaneAltAboveGround < 0 ? 0 : _flightSimData.PlaneAltAboveGround;
|
|
||||||
|
|
||||||
var tlod = _appSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.FirstOrDefault(x => x.Agl > agl);
|
|
||||||
_nextTlod = _appSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.Find(tlod);
|
|
||||||
|
|
||||||
tlod = _appSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.LastOrDefault(x => x.Agl <= agl);
|
|
||||||
_currentTlod = _appSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.Find(tlod) ?? _appSettingData.ApplicationSetting.DynamicLodSetting.TlodConfigs.Last;
|
|
||||||
|
|
||||||
if (_currentTlod != null)
|
|
||||||
DynamicLodManager.WriteTlod(_currentTlod.Value.Lod);
|
|
||||||
|
|
||||||
var olod = _appSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.FirstOrDefault(x => x.Agl > agl);
|
|
||||||
_nextOlod = _appSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.Find(olod);
|
|
||||||
|
|
||||||
olod = _appSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.LastOrDefault(x => x.Agl <= agl);
|
|
||||||
_currentOlod = _appSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.Find(olod) ?? _appSettingData.ApplicationSetting.DynamicLodSetting.OlodConfigs.Last;
|
|
||||||
|
|
||||||
if (_currentOlod != null)
|
|
||||||
DynamicLodManager.WriteOlod(_currentOlod.Value.Lod);
|
|
||||||
|
|
||||||
if (_currentTlod != null && _currentOlod != null)
|
|
||||||
Debug.WriteLine($"Initialize Altitude: {agl}, TLOD: {_currentTlod.Value.Lod}, OLOD: {_currentOlod.Value.Lod}");
|
|
||||||
}
|
|
||||||
|
|
||||||
//private static int ReadTlod(bool isVr = false)
|
|
||||||
//{
|
|
||||||
// return Convert.ToInt32(ReadMemory<float>(isVr ? _addressTlodVr : _addressTlod) * 100.0f);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private static int ReadOlod(bool isVr = false)
|
|
||||||
//{
|
|
||||||
// return Convert.ToInt32(ReadMemory<float>(isVr ? _addressOlodVr : _addressOlod) * 100.0f);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
336
Orchestration/DynamicLodOrchestrator.cs
Normal file
336
Orchestration/DynamicLodOrchestrator.cs
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
|
||||||
|
using MSFSPopoutPanelManager.DomainModel.Setting;
|
||||||
|
using MSFSPopoutPanelManager.Shared;
|
||||||
|
using MSFSPopoutPanelManager.SimConnectAgent;
|
||||||
|
using MSFSPopoutPanelManager.WindowsAgent;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
{
|
||||||
|
public class DynamicLodOrchestrator : BaseOrchestrator
|
||||||
|
{
|
||||||
|
private const string SIMMODULE_NAME = "WwiseLibPCx64P.dll";
|
||||||
|
private const int PROCESS_VM_OPERATION = 0x0008;
|
||||||
|
private const int PROCESS_VM_READ = 0x0010;
|
||||||
|
private const int PROCESS_VM_WRITE = 0x0020;
|
||||||
|
private const long OFFSET_MODULE_BASE =0x004B2368;
|
||||||
|
private const long OFFSET_POINTER_MAIN = 0x3D0;
|
||||||
|
private const long OFFSET_POINTER_TLOD_VR = 0x114;
|
||||||
|
private const long OFFSET_POINTER_TLOD = 0xC;
|
||||||
|
private const long OFFSET_POINTER_OLOD = 0xC;
|
||||||
|
private const long OFFSET_POINTER_CLOUDQ = 0x44;
|
||||||
|
private const long OFFSET_POINTER_CLOUDQ_VR = 0x108;
|
||||||
|
private const long OFFSET_POINTER_VR_MODE = 0x1C;
|
||||||
|
private const long OFFSET_POINTER_FG_MODE = 0x4A;
|
||||||
|
private const long OFFSET_POINTER_ANSIO_FILTER = -0x18;
|
||||||
|
private const long OFFSET_POINTER_WATER_WAVES = 0x3C;
|
||||||
|
|
||||||
|
private bool _isActive;
|
||||||
|
private WindowProcess _process;
|
||||||
|
private IntPtr _processHandle;
|
||||||
|
private long _processModuleAddress;
|
||||||
|
|
||||||
|
private long _addressTlod;
|
||||||
|
private long _addressOlod;
|
||||||
|
private long _addressTlodVr;
|
||||||
|
private long _addressOlodVr;
|
||||||
|
private long _addressCloudQ;
|
||||||
|
private long _addressCloudQVr;
|
||||||
|
private long _addressVrMode;
|
||||||
|
private long _addressFgMode;
|
||||||
|
|
||||||
|
private DynamicLodSetting DynamicLodSetting => AppSettingData.ApplicationSetting.DynamicLodSetting;
|
||||||
|
|
||||||
|
private DynamicLodSimData SimData => FlightSimData.DynamicLodSimData;
|
||||||
|
|
||||||
|
private DateTime _lastLodUpdateTime = DateTime.Now;
|
||||||
|
private bool _isDecreasedCloudQualityActive = false;
|
||||||
|
|
||||||
|
public DynamicLodOrchestrator(SharedStorage sharedStorage) : base(sharedStorage) {}
|
||||||
|
|
||||||
|
public void Attach()
|
||||||
|
{
|
||||||
|
if (AppSettingData == null || _isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_process = WindowProcessManager.SimulatorProcess;
|
||||||
|
_processModuleAddress = GetSimModuleAddress();
|
||||||
|
|
||||||
|
if (_process == null || _processModuleAddress == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_processHandle = PInvoke.OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, _process.ProcessId);
|
||||||
|
|
||||||
|
if (_processHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_addressTlod = ReadMemory<long>(_processModuleAddress + OFFSET_MODULE_BASE) + OFFSET_POINTER_MAIN;
|
||||||
|
|
||||||
|
if (_addressTlod > 0)
|
||||||
|
{
|
||||||
|
_addressTlodVr = ReadMemory<long>(_addressTlod) + OFFSET_POINTER_TLOD_VR;
|
||||||
|
_addressTlod = ReadMemory<long>(_addressTlod) + OFFSET_POINTER_TLOD;
|
||||||
|
_addressOlod = _addressTlod + OFFSET_POINTER_OLOD;
|
||||||
|
_addressOlodVr = _addressTlodVr + OFFSET_POINTER_OLOD;
|
||||||
|
_addressCloudQ = _addressTlod + OFFSET_POINTER_CLOUDQ;
|
||||||
|
_addressCloudQVr = _addressCloudQ + OFFSET_POINTER_CLOUDQ_VR;
|
||||||
|
_addressVrMode = _addressTlod - OFFSET_POINTER_VR_MODE;
|
||||||
|
_addressFgMode = _addressTlod - OFFSET_POINTER_FG_MODE;
|
||||||
|
|
||||||
|
if (!MemoryBoundaryTest())
|
||||||
|
{
|
||||||
|
FileLogger.WriteLog("Unable to validate memory space for Dynamic LOD", StatusMessageType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_isActive = true;
|
||||||
|
|
||||||
|
_lastLodUpdateTime = DateTime.Now;
|
||||||
|
_isDecreasedCloudQualityActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Detach()
|
||||||
|
{
|
||||||
|
if (DynamicLodSetting == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (DynamicLodSetting.ResetEnabled)
|
||||||
|
{
|
||||||
|
var isVr = ReadIsVr();
|
||||||
|
WriteMemory(isVr ? _addressTlodVr : _addressTlod, DynamicLodSetting.ResetTlod / 100.0f);
|
||||||
|
WriteMemory(isVr ? _addressOlodVr : _addressOlod, DynamicLodSetting.ResetOlod / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isActive = false;
|
||||||
|
|
||||||
|
Debug.WriteLine($"Reset to custom LOD: TLOD: {DynamicLodSetting.ResetTlod}, OLOD: {DynamicLodSetting.ResetOlod}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadTlod(bool isVr = false)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(ReadMemory<float>(isVr ? _addressTlodVr : _addressTlod) * 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadOlod(bool isVr = false)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(ReadMemory<float>(isVr ? _addressOlodVr : _addressOlod) * 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadCloudQuality(bool isVr = false)
|
||||||
|
{
|
||||||
|
return ReadCloudQualitySimValue(isVr) switch
|
||||||
|
{
|
||||||
|
0 => "Low",
|
||||||
|
1 => "Medium",
|
||||||
|
2 => "High",
|
||||||
|
3 => "Ultra",
|
||||||
|
_ => "N/A"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadCloudQualitySimValue(bool isVr = false)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(ReadMemory<int>(isVr ? _addressCloudQVr : _addressCloudQ));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ReadIsVr()
|
||||||
|
{
|
||||||
|
return ReadMemory<int>(_addressVrMode) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ReadIsFg(bool isVr)
|
||||||
|
{
|
||||||
|
if (isVr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ReadMemory<byte>(_addressFgMode) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateLod(bool isVr)
|
||||||
|
{
|
||||||
|
if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit || (DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState != CameraState.Cockpit))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var deltaFps = SimData.Fps - DynamicLodSetting.TargetedFps;
|
||||||
|
if (Math.Abs(deltaFps) < DynamicLodSetting.TargetedFps * DynamicLodSetting.FpsTolerance / 100.0) // within FPS tolerance
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lastLodUpdateTime = DateTime.Now;
|
||||||
|
|
||||||
|
SetTlod(deltaFps);
|
||||||
|
SetOlod();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long GetSimModuleAddress()
|
||||||
|
{
|
||||||
|
if (_process == null)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
foreach (ProcessModule processModule in _process.Modules)
|
||||||
|
{
|
||||||
|
if (processModule.ModuleName == SIMMODULE_NAME)
|
||||||
|
return processModule.BaseAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteMemory(long address, object value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var buffer = StructureToByteArray(value);
|
||||||
|
PInvoke.NtWriteVirtualMemory(checked((int)_processHandle), address, buffer, buffer.Length, out _);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private T ReadMemory<T>(long address) where T : struct
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var byteSize = Marshal.SizeOf(typeof(T));
|
||||||
|
var buffer = new byte[byteSize];
|
||||||
|
PInvoke.NtReadVirtualMemory(checked((int)_processHandle), address, buffer, buffer.Length, out _);
|
||||||
|
return ByteArrayToStructure<T>(buffer);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] StructureToByteArray(object obj)
|
||||||
|
{
|
||||||
|
var length = Marshal.SizeOf(obj);
|
||||||
|
var array = new byte[length];
|
||||||
|
var pointer = Marshal.AllocHGlobal(length);
|
||||||
|
|
||||||
|
Marshal.StructureToPtr(obj, pointer, true);
|
||||||
|
Marshal.Copy(pointer, array, 0, length);
|
||||||
|
Marshal.FreeHGlobal(pointer);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T ByteArrayToStructure<T>(byte[] bytes) where T : struct
|
||||||
|
{
|
||||||
|
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
||||||
|
|
||||||
|
if(result != null)
|
||||||
|
return (T)result;
|
||||||
|
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
handle.Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool MemoryBoundaryTest()
|
||||||
|
{
|
||||||
|
// Boundary check a few known setting memory addresses to see if any fail which likely indicates MSFS memory map has changed
|
||||||
|
if (ReadTlod() < 10 || ReadTlod() > 1000 || ReadTlod(true) < 10 || ReadTlod(true) > 1000
|
||||||
|
|| ReadOlod() < 10 || ReadOlod() > 1000 || ReadOlod(true) < 10 || ReadOlod(true) > 1000
|
||||||
|
|| ReadCloudQuality() == "N/A" || ReadCloudQuality(true) == "N/A"
|
||||||
|
|| ReadMemory<int>(_addressVrMode) < 0 || ReadMemory<int>(_addressVrMode) > 1
|
||||||
|
|| ReadMemory<int>(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) < 1 || ReadMemory<int>(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) > 16
|
||||||
|
|| !(ReadMemory<int>(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 128 || ReadMemory<int>(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 256 || ReadMemory<int>(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 512))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTlod(int deltaFps, bool isVr = false)
|
||||||
|
{
|
||||||
|
var tlodStep = Math.Max(5, Math.Abs(deltaFps / 2));
|
||||||
|
var newTlod = SimData.Tlod + Math.Sign(deltaFps) * tlodStep;
|
||||||
|
|
||||||
|
if (DynamicLodSetting.TlodMinOnGround && SimData.AltAboveGround <= DynamicLodSetting.AltTlodBase)
|
||||||
|
{
|
||||||
|
newTlod = DynamicLodSetting.TlodMin;
|
||||||
|
}
|
||||||
|
else if (newTlod < DynamicLodSetting.TlodMin)
|
||||||
|
{
|
||||||
|
newTlod = DynamicLodSetting.TlodMin;
|
||||||
|
}
|
||||||
|
else if (newTlod > DynamicLodSetting.TlodMax)
|
||||||
|
{
|
||||||
|
newTlod = DynamicLodSetting.TlodMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadTlod(isVr) == newTlod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Adjust cloud quality if applicable
|
||||||
|
if (deltaFps < 0 && newTlod < DynamicLodSetting.CloudRecoveryTlod && !_isDecreasedCloudQualityActive)
|
||||||
|
{
|
||||||
|
_isDecreasedCloudQualityActive = true;
|
||||||
|
WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) - 1); // High
|
||||||
|
|
||||||
|
_lastLodUpdateTime = _lastLodUpdateTime.AddSeconds(2); // Add extra delay for cloud setting to take effect
|
||||||
|
Debug.WriteLine("New Cloud Quality written - 2.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltaFps > 0 && newTlod >= DynamicLodSetting.CloudRecoveryTlod && _isDecreasedCloudQualityActive)
|
||||||
|
{
|
||||||
|
_isDecreasedCloudQualityActive = false;
|
||||||
|
WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) + 1); // Ultra
|
||||||
|
|
||||||
|
_lastLodUpdateTime = _lastLodUpdateTime.AddSeconds(2);
|
||||||
|
Debug.WriteLine("New Cloud Quality written - 3.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine($"New TLOD written - {newTlod}.");
|
||||||
|
WriteMemory(isVr ? _addressTlodVr : _addressTlod, newTlod / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetOlod(bool isVr = false)
|
||||||
|
{
|
||||||
|
int newOlod;
|
||||||
|
|
||||||
|
if (SimData.AltAboveGround < DynamicLodSetting.AltOlodBase)
|
||||||
|
{
|
||||||
|
newOlod = DynamicLodSetting.OlodBase;
|
||||||
|
}
|
||||||
|
else if (SimData.AltAboveGround > DynamicLodSetting.AltOlodTop)
|
||||||
|
{
|
||||||
|
newOlod = DynamicLodSetting.OlodTop;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newOlod = Convert.ToInt32(DynamicLodSetting.OlodBase - (DynamicLodSetting.OlodBase - DynamicLodSetting.OlodTop) * (SimData.AltAboveGround - DynamicLodSetting.AltOlodBase) / (DynamicLodSetting.AltOlodTop - DynamicLodSetting.AltOlodBase));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadOlod(isVr) == newOlod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Debug.WriteLine($"New OLOD written - {newOlod}.");
|
||||||
|
WriteMemory(isVr ? _addressOlodVr : _addressOlod, newOlod / 100.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using MSFSPopoutPanelManager.Shared;
|
using MSFSPopoutPanelManager.Shared;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
|
||||||
using MSFSPopoutPanelManager.SimConnectAgent;
|
using MSFSPopoutPanelManager.SimConnectAgent;
|
||||||
|
|
||||||
namespace MSFSPopoutPanelManager.Orchestration
|
namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
@ -15,8 +16,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
IsSimConnectActive = false;
|
IsSimConnectActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler OnAltAboveGroundChanged;
|
|
||||||
|
|
||||||
public bool IsSimConnectActive { get; set; }
|
public bool IsSimConnectActive { get; set; }
|
||||||
|
|
||||||
public string AircraftName { get; set; }
|
public string AircraftName { get; set; }
|
||||||
|
@ -43,8 +42,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
public bool PlaneInParkingSpot { get; set; }
|
public bool PlaneInParkingSpot { get; set; }
|
||||||
|
|
||||||
public int PlaneAltAboveGround { get; set; }
|
|
||||||
|
|
||||||
public bool IsSimulatorStarted { get; set; }
|
public bool IsSimulatorStarted { get; set; }
|
||||||
|
|
||||||
public bool IsSimConnectDataReceived { get; set; }
|
public bool IsSimConnectDataReceived { get; set; }
|
||||||
|
@ -55,6 +52,8 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
public IHudBarData HudBarData { get; set; }
|
public IHudBarData HudBarData { get; set; }
|
||||||
|
|
||||||
|
public DynamicLodSimData DynamicLodSimData { get; set; } = new();
|
||||||
|
|
||||||
[IgnorePropertyChanged]
|
[IgnorePropertyChanged]
|
||||||
internal ProfileData ProfileDataRef { get; set; }
|
internal ProfileData ProfileDataRef { get; set; }
|
||||||
|
|
||||||
|
@ -65,9 +64,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
// Automatic switching of active profile when SimConnect active aircraft change
|
// Automatic switching of active profile when SimConnect active aircraft change
|
||||||
if (e.PropertyName == "AircraftName")
|
if (e.PropertyName == "AircraftName")
|
||||||
ProfileDataRef.AutoSwitchProfile();
|
ProfileDataRef.AutoSwitchProfile();
|
||||||
|
|
||||||
if(e.PropertyName == "PlaneAltAboveGround")
|
|
||||||
OnAltAboveGroundChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
|
@ -85,7 +81,6 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
PlaneInParkingSpot = false;
|
PlaneInParkingSpot = false;
|
||||||
CameraState = CameraState.Unknown;
|
CameraState = CameraState.Unknown;
|
||||||
IsSimulatorStarted = false;
|
IsSimulatorStarted = false;
|
||||||
PlaneAltAboveGround = 0;
|
|
||||||
CameraViewTypeAndIndex1Max = 0;
|
CameraViewTypeAndIndex1Max = 0;
|
||||||
CameraViewTypeAndIndex2Max = 0;
|
CameraViewTypeAndIndex2Max = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
private System.Timers.Timer _msfsGameExitDetectionTimer;
|
private System.Timers.Timer _msfsGameExitDetectionTimer;
|
||||||
private SimConnectProvider _simConnectProvider;
|
private SimConnectProvider _simConnectProvider;
|
||||||
|
|
||||||
|
private DynamicLodOrchestrator _dynamicLodOrchestrator;
|
||||||
private bool _isTurnedOnPower;
|
private bool _isTurnedOnPower;
|
||||||
private bool _isTurnedOnAvionics;
|
private bool _isTurnedOnAvionics;
|
||||||
|
|
||||||
public FlightSimOrchestrator(SharedStorage sharedStorage) : base(sharedStorage)
|
public FlightSimOrchestrator(SharedStorage sharedStorage, DynamicLodOrchestrator dynamicLodOrchestrator) : base(sharedStorage)
|
||||||
{
|
{
|
||||||
|
_dynamicLodOrchestrator = dynamicLodOrchestrator;
|
||||||
_simConnectProvider = new SimConnectProvider();
|
_simConnectProvider = new SimConnectProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +42,7 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
WindowProcessManager.GetSimulatorProcess(); // refresh simulator process
|
WindowProcessManager.GetSimulatorProcess(); // refresh simulator process
|
||||||
DetectMsfsExit();
|
DetectMsfsExit();
|
||||||
|
|
||||||
// Attach in memory override for Dynamic LOD
|
StartDynamicLod();
|
||||||
if (AppSettingData != null && AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
|
||||||
DynamicLodManager.Attach(FlightSimData, AppSettingData);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_simConnectProvider.OnDisconnected += (_, _) =>
|
_simConnectProvider.OnDisconnected += (_, _) =>
|
||||||
|
@ -61,61 +61,39 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
_simConnectProvider.OnSimConnectDataRequiredRefreshed += (_, e) =>
|
_simConnectProvider.OnSimConnectDataRequiredRefreshed += (_, e) =>
|
||||||
{
|
{
|
||||||
var electricalMasterBattery = Convert.ToBoolean(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.ElectricalMasterBattery).Value);
|
MapRequiredSimConnectData(e);
|
||||||
if (electricalMasterBattery != FlightSimData.ElectricalMasterBatteryStatus)
|
|
||||||
FlightSimData.ElectricalMasterBatteryStatus = electricalMasterBattery;
|
|
||||||
|
|
||||||
var avionicsMasterSwitch = Convert.ToBoolean(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.AvionicsMasterSwitch).Value);
|
|
||||||
if (avionicsMasterSwitch != FlightSimData.AvionicsMasterSwitchStatus)
|
|
||||||
FlightSimData.AvionicsMasterSwitchStatus = avionicsMasterSwitch;
|
|
||||||
|
|
||||||
var trackIR = Convert.ToBoolean(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.TrackIREnable).Value);
|
|
||||||
if (trackIR != FlightSimData.TrackIRStatus)
|
|
||||||
FlightSimData.TrackIRStatus = trackIR;
|
|
||||||
|
|
||||||
var cameraStateInt = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraState).Value);
|
|
||||||
var result = Enum.TryParse<CameraState>(cameraStateInt.ToString(), out var cameraState);
|
|
||||||
if (!result)
|
|
||||||
cameraState = CameraState.Unknown;
|
|
||||||
if (cameraState != FlightSimData.CameraState)
|
|
||||||
FlightSimData.CameraState = cameraState;
|
|
||||||
|
|
||||||
var cockpitCameraZoom = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CockpitCameraZoom).Value);
|
|
||||||
if (cockpitCameraZoom != FlightSimData.CockpitCameraZoom)
|
|
||||||
FlightSimData.CockpitCameraZoom = cockpitCameraZoom;
|
|
||||||
|
|
||||||
var planeAltAboveGround = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.PlaneAltAboveGround).Value);
|
|
||||||
if (planeAltAboveGround != FlightSimData.PlaneAltAboveGround)
|
|
||||||
FlightSimData.PlaneAltAboveGround = planeAltAboveGround;
|
|
||||||
|
|
||||||
var cameraViewTypeAndIndex0 = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex0).Value);
|
|
||||||
if (cameraViewTypeAndIndex0 != FlightSimData.CameraViewTypeAndIndex0)
|
|
||||||
FlightSimData.CameraViewTypeAndIndex0 = cameraViewTypeAndIndex0;
|
|
||||||
|
|
||||||
var cameraViewTypeAndIndex1 = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex1).Value);
|
|
||||||
if (cameraViewTypeAndIndex1 != FlightSimData.CameraViewTypeAndIndex1)
|
|
||||||
FlightSimData.CameraViewTypeAndIndex1 = cameraViewTypeAndIndex1;
|
|
||||||
|
|
||||||
var cameraViewTypeAndIndex1Max = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex1Max).Value);
|
|
||||||
if (cameraViewTypeAndIndex1Max != FlightSimData.CameraViewTypeAndIndex1Max)
|
|
||||||
FlightSimData.CameraViewTypeAndIndex1Max = cameraViewTypeAndIndex1Max;
|
|
||||||
|
|
||||||
var cameraViewTypeAndIndex2Max = Convert.ToInt32(e.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex2Max).Value);
|
|
||||||
if (cameraViewTypeAndIndex2Max != FlightSimData.CameraViewTypeAndIndex2Max)
|
|
||||||
FlightSimData.CameraViewTypeAndIndex2Max = cameraViewTypeAndIndex2Max;
|
|
||||||
|
|
||||||
FlightSimData.IsSimConnectDataReceived = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_simConnectProvider.OnSimConnectDataHudBarRefreshed += (_, e) =>
|
_simConnectProvider.OnSimConnectDataHudBarRefreshed += (_, e) =>
|
||||||
{
|
{
|
||||||
if (ProfileData.ActiveProfile.ProfileSetting.HudBarConfig.IsEnabled)
|
if (!ProfileData.ActiveProfile.ProfileSetting.HudBarConfig.IsEnabled || !FlightSimData.IsFlightStarted)
|
||||||
MapHudBarSimConnectData(e);
|
return;
|
||||||
|
|
||||||
|
MapHudBarSimConnectData(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
_simConnectProvider.OnSimConnectDataDynamicLodRefreshed += (_, e) =>
|
||||||
|
{
|
||||||
|
if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled || !FlightSimData.IsFlightStarted || !WindowActionManager.IsMsfsInFocus())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var isVr = _dynamicLodOrchestrator.ReadIsVr();
|
||||||
|
|
||||||
|
MapDynamicLodSimConnectData(e, isVr);
|
||||||
|
_dynamicLodOrchestrator.UpdateLod(isVr);
|
||||||
|
};
|
||||||
|
|
||||||
|
_simConnectProvider.OnSimConnectDataEventFrameRefreshed += (_, e) =>
|
||||||
|
{
|
||||||
|
if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled || !FlightSimData.IsFlightStarted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MapEventFrameData(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
_simConnectProvider.OnActiveAircraftChanged += (_, e) =>
|
_simConnectProvider.OnActiveAircraftChanged += (_, e) =>
|
||||||
{
|
{
|
||||||
var aircraftName = String.IsNullOrEmpty(e) ? null : e;
|
var aircraftName = string.IsNullOrEmpty(e) ? null : e;
|
||||||
if (FlightSimData.AircraftName != aircraftName)
|
if (FlightSimData.AircraftName != aircraftName)
|
||||||
{
|
{
|
||||||
FlightSimData.AircraftName = aircraftName;
|
FlightSimData.AircraftName = aircraftName;
|
||||||
|
@ -392,9 +370,7 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
FlightSimData.IsFlightStarted = true;
|
FlightSimData.IsFlightStarted = true;
|
||||||
|
|
||||||
// Attach in memory override for Dynamic LOD
|
StartDynamicLod();
|
||||||
if (AppSettingData != null && AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
|
||||||
DynamicLodManager.Attach(FlightSimData, AppSettingData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnFlightStopped(object sender, EventArgs e)
|
private void HandleOnFlightStopped(object sender, EventArgs e)
|
||||||
|
@ -409,9 +385,8 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
|
|
||||||
FlightSimData.IsFlightStarted = false;
|
FlightSimData.IsFlightStarted = false;
|
||||||
|
|
||||||
// Detach in memory override for Dynamic LOD
|
StopDynamicLod();
|
||||||
if (AppSettingData != null && AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
FlightSimData.DynamicLodSimData.Clear();
|
||||||
DynamicLodManager.Detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DetectMsfsExit()
|
private void DetectMsfsExit()
|
||||||
|
@ -436,6 +411,50 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MapRequiredSimConnectData(List<SimDataItem> simData)
|
||||||
|
{
|
||||||
|
var electricalMasterBattery = Convert.ToBoolean(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.ElectricalMasterBattery).Value);
|
||||||
|
if (electricalMasterBattery != FlightSimData.ElectricalMasterBatteryStatus)
|
||||||
|
FlightSimData.ElectricalMasterBatteryStatus = electricalMasterBattery;
|
||||||
|
|
||||||
|
var avionicsMasterSwitch = Convert.ToBoolean(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.AvionicsMasterSwitch).Value);
|
||||||
|
if (avionicsMasterSwitch != FlightSimData.AvionicsMasterSwitchStatus)
|
||||||
|
FlightSimData.AvionicsMasterSwitchStatus = avionicsMasterSwitch;
|
||||||
|
|
||||||
|
var trackIR = Convert.ToBoolean(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.TrackIREnable).Value);
|
||||||
|
if (trackIR != FlightSimData.TrackIRStatus)
|
||||||
|
FlightSimData.TrackIRStatus = trackIR;
|
||||||
|
|
||||||
|
var cameraStateInt = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraState).Value);
|
||||||
|
var result = Enum.TryParse<CameraState>(cameraStateInt.ToString(), out var cameraState);
|
||||||
|
if (!result)
|
||||||
|
cameraState = CameraState.Unknown;
|
||||||
|
if (cameraState != FlightSimData.CameraState)
|
||||||
|
FlightSimData.CameraState = cameraState;
|
||||||
|
|
||||||
|
var cockpitCameraZoom = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CockpitCameraZoom).Value);
|
||||||
|
if (cockpitCameraZoom != FlightSimData.CockpitCameraZoom)
|
||||||
|
FlightSimData.CockpitCameraZoom = cockpitCameraZoom;
|
||||||
|
|
||||||
|
var cameraViewTypeAndIndex0 = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex0).Value);
|
||||||
|
if (cameraViewTypeAndIndex0 != FlightSimData.CameraViewTypeAndIndex0)
|
||||||
|
FlightSimData.CameraViewTypeAndIndex0 = cameraViewTypeAndIndex0;
|
||||||
|
|
||||||
|
var cameraViewTypeAndIndex1 = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex1).Value);
|
||||||
|
if (cameraViewTypeAndIndex1 != FlightSimData.CameraViewTypeAndIndex1)
|
||||||
|
FlightSimData.CameraViewTypeAndIndex1 = cameraViewTypeAndIndex1;
|
||||||
|
|
||||||
|
var cameraViewTypeAndIndex1Max = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex1Max).Value);
|
||||||
|
if (cameraViewTypeAndIndex1Max != FlightSimData.CameraViewTypeAndIndex1Max)
|
||||||
|
FlightSimData.CameraViewTypeAndIndex1Max = cameraViewTypeAndIndex1Max;
|
||||||
|
|
||||||
|
var cameraViewTypeAndIndex2Max = Convert.ToInt32(simData.Find(d => d.PropertyName == SimDataDefinitions.PropName.CameraViewTypeAndIndex2Max).Value);
|
||||||
|
if (cameraViewTypeAndIndex2Max != FlightSimData.CameraViewTypeAndIndex2Max)
|
||||||
|
FlightSimData.CameraViewTypeAndIndex2Max = cameraViewTypeAndIndex2Max;
|
||||||
|
|
||||||
|
FlightSimData.IsSimConnectDataReceived = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void MapHudBarSimConnectData(List<SimDataItem> simData)
|
private void MapHudBarSimConnectData(List<SimDataItem> simData)
|
||||||
{
|
{
|
||||||
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.ElevatorTrim, FlightSimData.HudBarData.ElevatorTrim, out var newValue))
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.ElevatorTrim, FlightSimData.HudBarData.ElevatorTrim, out var newValue))
|
||||||
|
@ -466,6 +485,49 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
FlightSimData.HudBarData.SimRate = newValue;
|
FlightSimData.HudBarData.SimRate = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MapDynamicLodSimConnectData(List<SimDataItem> simData, bool isVr)
|
||||||
|
{
|
||||||
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.PlaneAltAboveGround, FlightSimData.DynamicLodSimData.Agl, out var newValue))
|
||||||
|
FlightSimData.DynamicLodSimData.Agl = newValue;
|
||||||
|
|
||||||
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.PlaneAltAboveGround, FlightSimData.DynamicLodSimData.AltAboveGround, out newValue))
|
||||||
|
FlightSimData.DynamicLodSimData.AltAboveGround = newValue;
|
||||||
|
|
||||||
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.PlaneAltAboveGroundMinusCg, FlightSimData.DynamicLodSimData.AltAboveGroundMinusCg, out newValue))
|
||||||
|
FlightSimData.DynamicLodSimData.AltAboveGroundMinusCg = newValue;
|
||||||
|
|
||||||
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.GroundVelocity, FlightSimData.DynamicLodSimData.GroundVelocity, out newValue))
|
||||||
|
FlightSimData.DynamicLodSimData.GroundVelocity = newValue;
|
||||||
|
|
||||||
|
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.SimOnGround, 1.0f, out newValue))
|
||||||
|
FlightSimData.DynamicLodSimData.PlaneOnGround = Convert.ToBoolean(newValue);
|
||||||
|
|
||||||
|
var tlod = _dynamicLodOrchestrator.ReadTlod(isVr);
|
||||||
|
if (FlightSimData.DynamicLodSimData.Tlod != tlod)
|
||||||
|
FlightSimData.DynamicLodSimData.Tlod = tlod;
|
||||||
|
|
||||||
|
var olod = _dynamicLodOrchestrator.ReadOlod(isVr);
|
||||||
|
if (FlightSimData.DynamicLodSimData.Olod != olod)
|
||||||
|
FlightSimData.DynamicLodSimData.Olod = olod;
|
||||||
|
|
||||||
|
var cloudQuality = _dynamicLodOrchestrator.ReadCloudQuality(isVr);
|
||||||
|
if (FlightSimData.DynamicLodSimData.CloudQuality != cloudQuality)
|
||||||
|
FlightSimData.DynamicLodSimData.CloudQuality = cloudQuality;
|
||||||
|
|
||||||
|
if (FlightSimData.IsFlightStarted && FlightSimData.IsInCockpit &&
|
||||||
|
(!AppSettingData.ApplicationSetting.DynamicLodSetting.PauseOutsideCockpitView || (AppSettingData.ApplicationSetting.DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState == CameraState.Cockpit)))
|
||||||
|
FlightSimData.DynamicLodSimData.Fps = FpsCalc.GetAverageFps(_dynamicLodOrchestrator.ReadIsFg(isVr) ? _currentFps * 2 : _currentFps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _currentFps;
|
||||||
|
private void MapEventFrameData(int fps)
|
||||||
|
{
|
||||||
|
if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_currentFps = fps;
|
||||||
|
}
|
||||||
|
|
||||||
private bool CompareSimConnectData(List<SimDataItem> simData, string propName, double source, out double newValue)
|
private bool CompareSimConnectData(List<SimDataItem> simData, string propName, double source, out double newValue)
|
||||||
{
|
{
|
||||||
var propData = simData.Find(d => d.PropertyName == propName);
|
var propData = simData.Find(d => d.PropertyName == propName);
|
||||||
|
@ -486,5 +548,26 @@ namespace MSFSPopoutPanelManager.Orchestration
|
||||||
newValue = 0;
|
newValue = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StartDynamicLod()
|
||||||
|
{
|
||||||
|
if (_simConnectProvider != null)
|
||||||
|
{
|
||||||
|
// Attach in memory override for Dynamic LOD
|
||||||
|
if (AppSettingData != null && AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
||||||
|
_dynamicLodOrchestrator.Attach();
|
||||||
|
|
||||||
|
_simConnectProvider.StartDynamicLod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopDynamicLod()
|
||||||
|
{
|
||||||
|
// Detach in memory override for Dynamic LOD
|
||||||
|
if (AppSettingData != null && AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled)
|
||||||
|
_dynamicLodOrchestrator.Detach();
|
||||||
|
|
||||||
|
_simConnectProvider.StopDynamicLod();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||||
<RootNamespace>MSFSPopoutPanelManager.Orchestration</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.Orchestration</RootNamespace>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<DebugType>Embedded</DebugType>
|
<DebugType>Embedded</DebugType>
|
||||||
<Configurations>Debug;Release;Local</Configurations>
|
<Configurations>Debug;Release;Local</Configurations>
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||||
<RootNamespace>MSFSPopoutPanelManager.Shared</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.Shared</RootNamespace>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<DebugType>Embedded</DebugType>
|
<DebugType>Embedded</DebugType>
|
||||||
<Configurations>Debug;Release;Local</Configurations>
|
<Configurations>Debug;Release;Local</Configurations>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
{
|
{
|
||||||
REQUIRED_DEFINITION = 0,
|
REQUIRED_DEFINITION = 0,
|
||||||
HUDBAR_DEFINITION,
|
HUDBAR_DEFINITION,
|
||||||
|
DYNAMICLOD_DEFINITION,
|
||||||
WRITABLE_TRACK_IR_DEFINITION,
|
WRITABLE_TRACK_IR_DEFINITION,
|
||||||
WRITABLE_COCKPIT_CAMERA_ZOOM_DEFINITION,
|
WRITABLE_COCKPIT_CAMERA_ZOOM_DEFINITION,
|
||||||
WRITABLE_COCKPIT_CAMERA_STATE_DEFINITION,
|
WRITABLE_COCKPIT_CAMERA_STATE_DEFINITION,
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
{
|
{
|
||||||
REQUIRED_REQUEST = 0,
|
REQUIRED_REQUEST = 0,
|
||||||
HUDBAR_REQUEST,
|
HUDBAR_REQUEST,
|
||||||
|
DYNAMICLOD_REQUEST,
|
||||||
NA
|
NA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
SimconnectAgent/FpsCalc.cs
Normal file
36
SimconnectAgent/FpsCalc.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
|
{
|
||||||
|
public class FpsCalc
|
||||||
|
{
|
||||||
|
private const int FpsLen = 50;
|
||||||
|
private static readonly float[] FpsStatistic = new float[FpsLen];
|
||||||
|
private static int _fpsIndex = -1;
|
||||||
|
|
||||||
|
public static int GetAverageFps(int newValue)
|
||||||
|
{
|
||||||
|
if (_fpsIndex == -1)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < FpsLen; i++)
|
||||||
|
FpsStatistic[i] = newValue;
|
||||||
|
|
||||||
|
_fpsIndex = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FpsStatistic[_fpsIndex] = newValue;
|
||||||
|
_fpsIndex++;
|
||||||
|
if (_fpsIndex >= FpsLen)
|
||||||
|
_fpsIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fps = 0;
|
||||||
|
if (_fpsIndex != -1)
|
||||||
|
fps = Convert.ToInt32(FpsStatistic.Sum() / FpsLen);
|
||||||
|
|
||||||
|
return fps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,15 +5,17 @@
|
||||||
SIM_START,
|
SIM_START,
|
||||||
SIM_STOP,
|
SIM_STOP,
|
||||||
AIRCRAFT_LOADED,
|
AIRCRAFT_LOADED,
|
||||||
VIEW
|
VIEW,
|
||||||
|
FRAME
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ActionEvent
|
public enum ActionEvent
|
||||||
{
|
{
|
||||||
DUMMY1, // must register 4 dummy events to reserve space for SimConnectEvent above
|
DUMMY1, // must register 5 dummy events to reserve space for SimConnectEvent above
|
||||||
DUMMY2,
|
DUMMY2,
|
||||||
DUMMY3,
|
DUMMY3,
|
||||||
DUMMY4,
|
DUMMY4,
|
||||||
|
DUMMY5,
|
||||||
MASTER_BATTERY_SET,
|
MASTER_BATTERY_SET,
|
||||||
AVIONICS_MASTER_SET,
|
AVIONICS_MASTER_SET,
|
||||||
PAUSE_SET,
|
PAUSE_SET,
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
{
|
{
|
||||||
private const int MSFS_DATA_REFRESH_TIMEOUT = 500;
|
private const int MSFS_DATA_REFRESH_TIMEOUT = 500;
|
||||||
private const int MSFS_HUDBAR_DATA_REFRESH_TIMEOUT = 200;
|
private const int MSFS_HUDBAR_DATA_REFRESH_TIMEOUT = 200;
|
||||||
|
private const int MSFS_DYNAMICLOD_DATA_REFRESH_TIMEOUT = 300;
|
||||||
|
|
||||||
private readonly SimConnector _simConnector;
|
private readonly SimConnector _simConnector;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
|
|
||||||
private System.Timers.Timer _requiredRequestDataTimer;
|
private System.Timers.Timer _requiredRequestDataTimer;
|
||||||
private System.Timers.Timer _hudBarRequestDataTimer;
|
private System.Timers.Timer _hudBarRequestDataTimer;
|
||||||
|
private System.Timers.Timer _dynamicLodRequestDataTimer;
|
||||||
private bool _isPowerOnForPopOut;
|
private bool _isPowerOnForPopOut;
|
||||||
private bool _isAvionicsOnForPopOut;
|
private bool _isAvionicsOnForPopOut;
|
||||||
private bool _isTrackIRManaged;
|
private bool _isTrackIRManaged;
|
||||||
|
@ -33,6 +35,8 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
public event EventHandler OnException;
|
public event EventHandler OnException;
|
||||||
public event EventHandler<List<SimDataItem>> OnSimConnectDataRequiredRefreshed;
|
public event EventHandler<List<SimDataItem>> OnSimConnectDataRequiredRefreshed;
|
||||||
public event EventHandler<List<SimDataItem>> OnSimConnectDataHudBarRefreshed;
|
public event EventHandler<List<SimDataItem>> OnSimConnectDataHudBarRefreshed;
|
||||||
|
public event EventHandler<List<SimDataItem>> OnSimConnectDataDynamicLodRefreshed;
|
||||||
|
public event EventHandler<int> OnSimConnectDataEventFrameRefreshed;
|
||||||
public event EventHandler<string> OnActiveAircraftChanged;
|
public event EventHandler<string> OnActiveAircraftChanged;
|
||||||
|
|
||||||
public SimConnectProvider()
|
public SimConnectProvider()
|
||||||
|
@ -43,7 +47,9 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
_simConnector.OnException += HandleSimException;
|
_simConnector.OnException += HandleSimException;
|
||||||
_simConnector.OnReceiveSystemEvent += HandleReceiveSystemEvent;
|
_simConnector.OnReceiveSystemEvent += HandleReceiveSystemEvent;
|
||||||
_simConnector.OnReceivedRequiredData += HandleRequiredDataReceived;
|
_simConnector.OnReceivedRequiredData += HandleRequiredDataReceived;
|
||||||
_simConnector.OnReceivedHudBarData += HandleHudBarDataReceived;
|
_simConnector.OnReceivedHudBarData += (_, e) => OnSimConnectDataHudBarRefreshed?.Invoke(this, e);
|
||||||
|
_simConnector.OnReceivedDynamicLodData += (_, e) => OnSimConnectDataDynamicLodRefreshed?.Invoke(this, e);
|
||||||
|
_simConnector.OnReceivedEventFrameData += (_, e) => OnSimConnectDataEventFrameRefreshed?.Invoke(this, e);
|
||||||
_simConnector.OnActiveAircraftChanged += (_, e) => OnActiveAircraftChanged?.Invoke(this, e);
|
_simConnector.OnActiveAircraftChanged += (_, e) => OnActiveAircraftChanged?.Invoke(this, e);
|
||||||
|
|
||||||
_isHandlingCriticalError = false;
|
_isHandlingCriticalError = false;
|
||||||
|
@ -108,6 +114,29 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
_hudBarRequestDataTimer.Stop();
|
_hudBarRequestDataTimer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StartDynamicLod()
|
||||||
|
{
|
||||||
|
if (_dynamicLodRequestDataTimer.Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// shut down data request and wait for the last request to be completed
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
|
Thread.Sleep(MSFS_DYNAMICLOD_DATA_REFRESH_TIMEOUT);
|
||||||
|
|
||||||
|
_simConnector.SetSimConnectDynamicLodDataDefinition();
|
||||||
|
|
||||||
|
_dynamicLodRequestDataTimer.Start();
|
||||||
|
|
||||||
|
_simConnector.StartReceiveFrameData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopDynamicLod()
|
||||||
|
{
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
|
_simConnector.StopReceiveFrameData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void TurnOnPower(bool isRequiredForColdStart)
|
public void TurnOnPower(bool isRequiredForColdStart)
|
||||||
{
|
{
|
||||||
if (!isRequiredForColdStart || _requiredSimData == null)
|
if (!isRequiredForColdStart || _requiredSimData == null)
|
||||||
|
@ -295,10 +324,29 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_isHudBarDataActive)
|
if (_isHudBarDataActive)
|
||||||
SetHudBarConfig(_activeHudBarType);
|
SetHudBarConfig(_activeHudBarType);
|
||||||
|
|
||||||
|
// Setup dynamic data request timer
|
||||||
|
_dynamicLodRequestDataTimer = new()
|
||||||
|
{
|
||||||
|
Interval = MSFS_DYNAMICLOD_DATA_REFRESH_TIMEOUT,
|
||||||
|
};
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
|
_dynamicLodRequestDataTimer.Elapsed += (_, _) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_simConnector.RequestDynamicLodData();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
OnConnected?.Invoke(this, EventArgs.Empty);
|
OnConnected?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +354,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
{
|
{
|
||||||
_requiredRequestDataTimer.Stop();
|
_requiredRequestDataTimer.Stop();
|
||||||
_hudBarRequestDataTimer.Stop();
|
_hudBarRequestDataTimer.Stop();
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
OnDisconnected?.Invoke(this, EventArgs.Empty);
|
OnDisconnected?.Invoke(this, EventArgs.Empty);
|
||||||
StopAndReconnect();
|
StopAndReconnect();
|
||||||
}
|
}
|
||||||
|
@ -316,6 +365,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
|
|
||||||
_requiredRequestDataTimer.Stop();
|
_requiredRequestDataTimer.Stop();
|
||||||
_hudBarRequestDataTimer.Stop();
|
_hudBarRequestDataTimer.Stop();
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
|
|
||||||
if (!_isHandlingCriticalError)
|
if (!_isHandlingCriticalError)
|
||||||
{
|
{
|
||||||
|
@ -332,11 +382,6 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
OnSimConnectDataRequiredRefreshed?.Invoke(this, e);
|
OnSimConnectDataRequiredRefreshed?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleHudBarDataReceived(object sender, List<SimDataItem> e)
|
|
||||||
{
|
|
||||||
OnSimConnectDataHudBarRefreshed?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CameraState _currentCameraState = CameraState.Unknown;
|
private CameraState _currentCameraState = CameraState.Unknown;
|
||||||
|
|
||||||
private void DetectFlightStartedOrStopped(List<SimDataItem> simData)
|
private void DetectFlightStartedOrStopped(List<SimDataItem> simData)
|
||||||
|
@ -375,6 +420,8 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
|
|
||||||
_isHudBarDataActive = false;
|
_isHudBarDataActive = false;
|
||||||
_hudBarRequestDataTimer.Stop();
|
_hudBarRequestDataTimer.Stop();
|
||||||
|
|
||||||
|
_dynamicLodRequestDataTimer.Stop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,18 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
private bool _isDisabledReconnect;
|
private bool _isDisabledReconnect;
|
||||||
|
|
||||||
private readonly List<SimConnectDataDefinition> _simConnectRequiredDataDefinitions = SimDataDefinitions.GetRequiredDefinitions();
|
private readonly List<SimConnectDataDefinition> _simConnectRequiredDataDefinitions = SimDataDefinitions.GetRequiredDefinitions();
|
||||||
|
private readonly List<SimConnectDataDefinition> _simConnectDynamicLodDataDefinitions = SimDataDefinitions.GetDynamicLodDefinitions();
|
||||||
private List<SimConnectDataDefinition> _simConnectHudBarDataDefinitions;
|
private List<SimConnectDataDefinition> _simConnectHudBarDataDefinitions;
|
||||||
private readonly FieldInfo[] _simConnectStructFields = typeof(SimConnectStruct).GetFields(BindingFlags.Public | BindingFlags.Instance);
|
private readonly FieldInfo[] _simConnectStructFields = typeof(SimConnectStruct).GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
||||||
public event EventHandler<string> OnException;
|
public event EventHandler<string> OnException;
|
||||||
public event EventHandler<List<SimDataItem>> OnReceivedRequiredData;
|
public event EventHandler<List<SimDataItem>> OnReceivedRequiredData;
|
||||||
public event EventHandler<List<SimDataItem>> OnReceivedHudBarData;
|
public event EventHandler<List<SimDataItem>> OnReceivedHudBarData;
|
||||||
|
public event EventHandler<List<SimDataItem>> OnReceivedDynamicLodData;
|
||||||
public event EventHandler OnConnected;
|
public event EventHandler OnConnected;
|
||||||
public event EventHandler OnDisconnected;
|
public event EventHandler OnDisconnected;
|
||||||
public event EventHandler<SimConnectEvent> OnReceiveSystemEvent;
|
public event EventHandler<SimConnectEvent> OnReceiveSystemEvent;
|
||||||
|
public event EventHandler<int> OnReceivedEventFrameData;
|
||||||
public event EventHandler<string> OnActiveAircraftChanged;
|
public event EventHandler<string> OnActiveAircraftChanged;
|
||||||
|
|
||||||
public bool Connected { get; set; }
|
public bool Connected { get; set; }
|
||||||
|
@ -66,6 +69,11 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
AddHudBarDataDefinitions();
|
AddHudBarDataDefinitions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetSimConnectDynamicLodDataDefinition()
|
||||||
|
{
|
||||||
|
AddDynamicLodDataDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleOnRecvOpen(SimConnect sender, SIMCONNECT_RECV_OPEN data)
|
private void HandleOnRecvOpen(SimConnect sender, SIMCONNECT_RECV_OPEN data)
|
||||||
{
|
{
|
||||||
ReceiveMessage();
|
ReceiveMessage();
|
||||||
|
@ -124,6 +132,26 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RequestDynamicLodData()
|
||||||
|
{
|
||||||
|
if (_simConnect == null || !Connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_simConnectDynamicLodDataDefinitions != null)
|
||||||
|
_simConnect.RequestDataOnSimObjectType(DataRequest.DYNAMICLOD_REQUEST, DataDefinition.DYNAMICLOD_DEFINITION, 0, SIMCONNECT_SIMOBJECT_TYPE.USER);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (!_isDisabledReconnect)
|
||||||
|
_isDisabledReconnect = true;
|
||||||
|
|
||||||
|
OnException?.Invoke(this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ReceiveMessage()
|
public void ReceiveMessage()
|
||||||
{
|
{
|
||||||
if (_simConnect == null)
|
if (_simConnect == null)
|
||||||
|
@ -208,6 +236,25 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StartReceiveFrameData()
|
||||||
|
{
|
||||||
|
if (_simConnect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_simConnect.OnRecvEventFrame -= HandleOnRecvEventFrame;
|
||||||
|
_simConnect.OnRecvEventFrame += HandleOnRecvEventFrame;
|
||||||
|
|
||||||
|
_simConnect.UnsubscribeFromSystemEvent(SimConnectEvent.FRAME);
|
||||||
|
_simConnect.SubscribeToSystemEvent(SimConnectEvent.FRAME, "Frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopReceiveFrameData()
|
||||||
|
{
|
||||||
|
_simConnect.OnRecvEventFrame -= HandleOnRecvEventFrame;
|
||||||
|
|
||||||
|
_simConnect.UnsubscribeFromSystemEvent(SimConnectEvent.FRAME);
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeSimConnect()
|
private void InitializeSimConnect()
|
||||||
{
|
{
|
||||||
Debug.WriteLine("Trying to start simConnect");
|
Debug.WriteLine("Trying to start simConnect");
|
||||||
|
@ -234,8 +281,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
_simConnect.SubscribeToSystemEvent(SimConnectEvent.VIEW, "View");
|
_simConnect.SubscribeToSystemEvent(SimConnectEvent.VIEW, "View");
|
||||||
_simConnect.UnsubscribeFromSystemEvent(SimConnectEvent.AIRCRAFT_LOADED);
|
_simConnect.UnsubscribeFromSystemEvent(SimConnectEvent.AIRCRAFT_LOADED);
|
||||||
_simConnect.SubscribeToSystemEvent(SimConnectEvent.AIRCRAFT_LOADED, "AircraftLoaded");
|
_simConnect.SubscribeToSystemEvent(SimConnectEvent.AIRCRAFT_LOADED, "AircraftLoaded");
|
||||||
|
|
||||||
|
|
||||||
AddRequiredDataDefinitions();
|
AddRequiredDataDefinitions();
|
||||||
SetupActionEvents();
|
SetupActionEvents();
|
||||||
|
|
||||||
|
@ -256,6 +302,14 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
Connected = true;
|
Connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleOnRecvEventFrame(SimConnect sender, SIMCONNECT_RECV_EVENT_FRAME data)
|
||||||
|
{
|
||||||
|
if (data == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnReceivedEventFrameData?.Invoke(this, Convert.ToInt32(data.fFrameRate));
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleOnRecvSystemState(SimConnect sender, SIMCONNECT_RECV_SYSTEM_STATE data)
|
private void HandleOnRecvSystemState(SimConnect sender, SIMCONNECT_RECV_SYSTEM_STATE data)
|
||||||
{
|
{
|
||||||
switch ((SystemStateRequestId)Enum.Parse(typeof(SystemStateRequestId), data.dwRequestID.ToString()))
|
switch ((SystemStateRequestId)Enum.Parse(typeof(SystemStateRequestId), data.dwRequestID.ToString()))
|
||||||
|
@ -361,6 +415,41 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
_simConnect.RegisterDataDefineStruct<SimConnectStruct>(DataDefinition.HUDBAR_DEFINITION);
|
_simConnect.RegisterDataDefineStruct<SimConnectStruct>(DataDefinition.HUDBAR_DEFINITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddDynamicLodDataDefinitions()
|
||||||
|
{
|
||||||
|
if (_simConnect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_simConnect.ClearDataDefinition(DataDefinition.DYNAMICLOD_DEFINITION);
|
||||||
|
|
||||||
|
if (_simConnectDynamicLodDataDefinitions == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var definition in _simConnectDynamicLodDataDefinitions)
|
||||||
|
{
|
||||||
|
if (definition.DefinitionId != DataDefinition.DYNAMICLOD_DEFINITION ||
|
||||||
|
definition.DataDefinitionType != DataDefinitionType.SimConnect) continue;
|
||||||
|
|
||||||
|
SIMCONNECT_DATATYPE simConnectDataType;
|
||||||
|
switch (definition.DataType)
|
||||||
|
{
|
||||||
|
case DataType.String:
|
||||||
|
simConnectDataType = SIMCONNECT_DATATYPE.STRING256;
|
||||||
|
break;
|
||||||
|
case DataType.Float64:
|
||||||
|
simConnectDataType = SIMCONNECT_DATATYPE.FLOAT64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
simConnectDataType = SIMCONNECT_DATATYPE.FLOAT64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_simConnect.AddToDataDefinition(definition.DefinitionId, definition.VariableName, definition.SimConnectUnit, simConnectDataType, 0.0f, SimConnect.SIMCONNECT_UNUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
_simConnect.RegisterDataDefineStruct<SimConnectStruct>(DataDefinition.DYNAMICLOD_DEFINITION);
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleOnRecvQuit(SimConnect sender, SIMCONNECT_RECV data)
|
private void HandleOnRecvQuit(SimConnect sender, SIMCONNECT_RECV data)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
|
@ -404,6 +493,9 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
case (int)DataRequest.HUDBAR_REQUEST:
|
case (int)DataRequest.HUDBAR_REQUEST:
|
||||||
ParseHudBarReceivedSimData(data);
|
ParseHudBarReceivedSimData(data);
|
||||||
break;
|
break;
|
||||||
|
case (int)DataRequest.DYNAMICLOD_REQUEST:
|
||||||
|
ParseDynamicLodReceivedSimData(data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,6 +575,46 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ParseDynamicLodReceivedSimData(SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_simConnectDynamicLodDataDefinitions == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var simData = new List<SimDataItem>();
|
||||||
|
var simDataStruct = (SimConnectStruct)data.dwData[0];
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
lock (_simConnectDynamicLodDataDefinitions)
|
||||||
|
{
|
||||||
|
foreach (var definition in _simConnectDynamicLodDataDefinitions)
|
||||||
|
{
|
||||||
|
if (definition.DataDefinitionType != DataDefinitionType.SimConnect)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var dataValue = _simConnectStructFields[i].GetValue(simDataStruct);
|
||||||
|
var simDataItem = new SimDataItem
|
||||||
|
{
|
||||||
|
PropertyName = definition.PropName,
|
||||||
|
Value = dataValue == null ? 0 : (double)dataValue
|
||||||
|
};
|
||||||
|
|
||||||
|
simData.Add(simDataItem);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnReceivedDynamicLodData?.Invoke(this, simData);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
FileLogger.WriteException($"SimConnector: SimConnect received dynamic lod data exception - {ex.Message}", ex);
|
||||||
|
StopAndReconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetActiveAircraftTitle(string aircraftFilePath)
|
private void SetActiveAircraftTitle(string aircraftFilePath)
|
||||||
{
|
{
|
||||||
var filePathToken = aircraftFilePath.Split(@"\");
|
var filePathToken = aircraftFilePath.Split(@"\");
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.PlaneInParkingSpot, VariableName = "ATC ON PARKING SPOT", SimConnectUnit = "Bool", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.PlaneInParkingSpot, VariableName = "ATC ON PARKING SPOT", SimConnectUnit = "Bool", DataType = DataType.Float64 },
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraState, VariableName = "CAMERA STATE", SimConnectUnit = "Number", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraState, VariableName = "CAMERA STATE", SimConnectUnit = "Number", DataType = DataType.Float64 },
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CockpitCameraZoom, VariableName = "COCKPIT CAMERA ZOOM", SimConnectUnit = "Percentage", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CockpitCameraZoom, VariableName = "COCKPIT CAMERA ZOOM", SimConnectUnit = "Percentage", DataType = DataType.Float64 },
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.PlaneAltAboveGround, VariableName = "PLANE ALT ABOVE GROUND", SimConnectUnit = "Feet", DataType = DataType.Float64 },
|
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex0, VariableName = "CAMERA VIEW TYPE AND INDEX:0", SimConnectUnit = "Enum", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex0, VariableName = "CAMERA VIEW TYPE AND INDEX:0", SimConnectUnit = "Enum", DataType = DataType.Float64 },
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex1, VariableName = "CAMERA VIEW TYPE AND INDEX:1", SimConnectUnit = "Enum", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex1, VariableName = "CAMERA VIEW TYPE AND INDEX:1", SimConnectUnit = "Enum", DataType = DataType.Float64 },
|
||||||
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex1Max, VariableName = "CAMERA VIEW TYPE AND INDEX MAX:1", SimConnectUnit = "Number", DataType = DataType.Float64 },
|
new() { DefinitionId = DataDefinition.REQUIRED_DEFINITION, RequestId = DataRequest.REQUIRED_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.CameraViewTypeAndIndex1Max, VariableName = "CAMERA VIEW TYPE AND INDEX MAX:1", SimConnectUnit = "Number", DataType = DataType.Float64 },
|
||||||
|
@ -44,6 +43,18 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<SimConnectDataDefinition> GetDynamicLodDefinitions()
|
||||||
|
{
|
||||||
|
var definitions = new List<SimConnectDataDefinition>
|
||||||
|
{
|
||||||
|
new() { DefinitionId = DataDefinition.DYNAMICLOD_DEFINITION, RequestId = DataRequest.DYNAMICLOD_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.PlaneAltAboveGround, VariableName = "PLANE ALT ABOVE GROUND", SimConnectUnit = "feet", DataType = DataType.Float64 },
|
||||||
|
new() { DefinitionId = DataDefinition.DYNAMICLOD_DEFINITION, RequestId = DataRequest.DYNAMICLOD_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.PlaneAltAboveGroundMinusCg, VariableName = "PLANE ALT ABOVE GROUND MINUS CG", SimConnectUnit = "feet", DataType = DataType.Float64 },
|
||||||
|
new() { DefinitionId = DataDefinition.DYNAMICLOD_DEFINITION, RequestId = DataRequest.DYNAMICLOD_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.SimOnGround, VariableName = "SIM ON GROUND", SimConnectUnit = "Bool", DataType = DataType.Float64 },
|
||||||
|
new() { DefinitionId = DataDefinition.DYNAMICLOD_DEFINITION, RequestId = DataRequest.DYNAMICLOD_REQUEST, DataDefinitionType = DataDefinitionType.SimConnect, PropName = PropName.GroundVelocity, VariableName = "GROUND VELOCITY", SimConnectUnit = "knots", DataType = DataType.Float64 }
|
||||||
|
};
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<SimConnectDataDefinition> GetSharedHudBarDefinitions()
|
private static List<SimConnectDataDefinition> GetSharedHudBarDefinitions()
|
||||||
{
|
{
|
||||||
var definitions = new List<SimConnectDataDefinition>
|
var definitions = new List<SimConnectDataDefinition>
|
||||||
|
@ -80,7 +91,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
};
|
};
|
||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PropName
|
public static class PropName
|
||||||
{
|
{
|
||||||
public static string ElectricalMasterBattery = "ElectricalMasterBattery";
|
public static string ElectricalMasterBattery = "ElectricalMasterBattery";
|
||||||
|
@ -96,6 +107,9 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
|
||||||
|
|
||||||
// Dynamic LOD
|
// Dynamic LOD
|
||||||
public static string PlaneAltAboveGround = "PlaneAltAboveGround";
|
public static string PlaneAltAboveGround = "PlaneAltAboveGround";
|
||||||
|
public static string PlaneAltAboveGroundMinusCg = "PlaneAltAboveGroundMinusCg";
|
||||||
|
public static string SimOnGround = "SimOnGround";
|
||||||
|
public static string GroundVelocity = "GroundVelocity";
|
||||||
|
|
||||||
// Hud Bar data
|
// Hud Bar data
|
||||||
public static string ElevatorTrim = "ElevatorTrim";
|
public static string ElevatorTrim = "ElevatorTrim";
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||||
<RootNamespace>MSFSPopoutPanelManager.SimConnectAgent</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.SimConnectAgent</RootNamespace>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<DebugType>Embedded</DebugType>
|
<DebugType>Embedded</DebugType>
|
||||||
<Configurations>Debug;Release;Local</Configurations>
|
<Configurations>Debug;Release;Local</Configurations>
|
||||||
|
|
|
@ -293,7 +293,12 @@ namespace MSFSPopoutPanelManager.WindowsAgent
|
||||||
var bottomEdge = rect.Y + rect.Height;
|
var bottomEdge = rect.Y + rect.Height;
|
||||||
|
|
||||||
return point.X >= rect.X && point.X <= rightEdge && point.Y >= rect.Y && point.Y <= bottomEdge;
|
return point.X >= rect.X && point.X <= rightEdge && point.Y >= rect.Y && point.Y <= bottomEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsMsfsInFocus()
|
||||||
|
{
|
||||||
|
var handle = PInvoke.GetForegroundWindow();
|
||||||
|
return PInvoke.GetWindowText(handle).Substring(0, 26).Equals("Microsoft Flight Simulator", StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
|
||||||
<RootNamespace>MSFSPopoutPanelManager.WindowsAgent</RootNamespace>
|
<RootNamespace>MSFSPopoutPanelManager.WindowsAgent</RootNamespace>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<Version>4.1.0.4</Version>
|
<Version>4.1.1.0</Version>
|
||||||
<AssemblyVersion>4.1.0.4</AssemblyVersion>
|
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||||
<FileVersion>4.1.0.4</FileVersion>
|
<FileVersion>4.1.1.0</FileVersion>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<DebugType>Embedded</DebugType>
|
<DebugType>Embedded</DebugType>
|
||||||
<Configurations>Debug;Release;Local</Configurations>
|
<Configurations>Debug;Release;Local</Configurations>
|
||||||
|
|
Loading…
Reference in a new issue