1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-12-26 22:32:01 +00:00

Merge pull request #131 from hawkeye-stan/4.1.2

4.1.2
This commit is contained in:
Stanley 2024-10-22 23:22:58 -04:00 committed by GitHub
commit d85f43e67f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 225 additions and 135 deletions

View file

@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.DomainModel</RootNamespace>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>Embedded</DebugType>
<Configurations>Debug;Release;Local</Configurations>

View file

@ -8,7 +8,7 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile
{
public FloatingPanel()
{
PropertyChanged += FloatingPanel_PropertyChanged; ;
PropertyChanged += FloatingPanel_PropertyChanged;
}
private void FloatingPanel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

View file

@ -127,5 +127,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile
return $"Left: {PanelSource.X} / Top: {PanelSource.Y}";
}
}
[JsonIgnore]
public MonitorInfo FullScreenMonitorInfo { get; set; }
}
}

View file

@ -256,6 +256,7 @@
<TextBlock Style="{StaticResource TxtBlockDisableWhenLocked}" ToolTip="Add in-game menu bar panels such as VFR Map, Checklist, ATC, etc. to profile to enable panel size and location management and touch support">Include in-game menu bar panels for pop out management and touch screen support</TextBlock>
</WrapPanel>
<WrapPanel Margin="0,8,0,0">
<ToggleButton
IsChecked="{Binding ActiveProfile.ProfileSetting.NumPadConfig.IsEnabled, Mode=TwoWay, NotifyOnTargetUpdated=True}"

View file

@ -46,22 +46,22 @@ namespace MSFSPopoutPanelManager.MainApp.AppUserControl
private void IncludeInGamePanel_TargetUpdated(object sender, DataTransferEventArgs e)
{
_viewModel.IncludeInGamePanelUpdatedCommand.Execute(null);
_viewModel.IncludeInGamePanelUpdatedCommand?.Execute(null);
}
private void AddHudBar_TargetUpdated(object sender, DataTransferEventArgs e)
{
_viewModel.AddHudBarUpdatedCommand.Execute(null);
_viewModel.AddHudBarUpdatedCommand?.Execute(null);
}
private void AddRefocusDisplay_TargetUpdated(object sender, DataTransferEventArgs e)
{
_viewModel.RefocusDisplayUpdatedCommand.Execute(null);
_viewModel.RefocusDisplayUpdatedCommand?.Execute(null);
}
private void AddNumPad_TargetUpdated(object sender, DataTransferEventArgs e)
{
_viewModel.AddNumPadUpdatedCommand.Execute(null);
_viewModel.AddNumPadUpdatedCommand?.Execute(null);
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Interop;
using Microsoft.Extensions.DependencyInjection;
@ -26,6 +27,7 @@ namespace MSFSPopoutPanelManager.MainApp.AppWindow
StateChanged += AppWindow_StateChanged;
WindowActionManager.OnPopOutManagerAlwaysOnTopChanged += (_, e) => { Topmost = e; };
MouseLeftButtonDown += (_, _) => DragMove();
}
private void AppWindow_Loaded(object sender, RoutedEventArgs e)

View file

@ -14,9 +14,9 @@
<RootNamespace>MSFSPopoutPanelManager.MainApp</RootNamespace>
<ApplicationIcon>logo.ico</ApplicationIcon>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<DebugType>embedded</DebugType>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<!-- Publishing options -->

View file

@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Local</Configuration>
<Configuration>Release</Configuration>
<Platform>x64</Platform>
<PublishDir>..\..\..\publish\master</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>

View file

@ -1,7 +1,6 @@
using MSFSPopoutPanelManager.DomainModel.DynamicLod;
using MSFSPopoutPanelManager.DomainModel.Setting;
using MSFSPopoutPanelManager.Shared;
using MSFSPopoutPanelManager.SimConnectAgent;
using MSFSPopoutPanelManager.WindowsAgent;
using System;
using System.Diagnostics;
@ -17,12 +16,9 @@ namespace MSFSPopoutPanelManager.Orchestration
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_CLOUD_QUALITY = 0x44;
private const long OFFSET_POINTER_FG_MODE = 0x4A;
private const long OFFSET_POINTER_ANSIO_FILTER = -0x18;
private const long OFFSET_POINTER_WATER_WAVES = 0x3C;
@ -34,19 +30,15 @@ namespace MSFSPopoutPanelManager.Orchestration
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 DynamicLodSimData DynamicLodSimData => FlightSimData.DynamicLodSimData;
private DateTime _lastLodUpdateTime = DateTime.Now;
private bool _isDecreasedCloudQualityActive = false;
private bool _isDecreasedCloudQualityActive;
public DynamicLodOrchestrator(SharedStorage sharedStorage) : base(sharedStorage) {}
@ -70,13 +62,9 @@ namespace MSFSPopoutPanelManager.Orchestration
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;
_addressCloudQ = _addressTlod + OFFSET_POINTER_CLOUD_QUALITY;
_addressFgMode = _addressTlod - OFFSET_POINTER_FG_MODE;
if (!MemoryBoundaryTest())
@ -99,9 +87,8 @@ namespace MSFSPopoutPanelManager.Orchestration
if (DynamicLodSetting.ResetEnabled)
{
var isVr = ReadIsVr();
WriteMemory(isVr ? _addressTlodVr : _addressTlod, DynamicLodSetting.ResetTlod / 100.0f);
WriteMemory(isVr ? _addressOlodVr : _addressOlod, DynamicLodSetting.ResetOlod / 100.0f);
WriteMemory(_addressTlod, DynamicLodSetting.ResetTlod / 100.0f);
WriteMemory(_addressOlod, DynamicLodSetting.ResetOlod / 100.0f);
}
_isActive = false;
@ -109,19 +96,19 @@ namespace MSFSPopoutPanelManager.Orchestration
Debug.WriteLine($"Reset to custom LOD: TLOD: {DynamicLodSetting.ResetTlod}, OLOD: {DynamicLodSetting.ResetOlod}");
}
public int ReadTlod(bool isVr = false)
public int ReadTlod()
{
return Convert.ToInt32(ReadMemory<float>(isVr ? _addressTlodVr : _addressTlod) * 100.0f);
return Convert.ToInt32(ReadMemory<float>(_addressTlod) * 100.0f);
}
public int ReadOlod(bool isVr = false)
public int ReadOlod()
{
return Convert.ToInt32(ReadMemory<float>(isVr ? _addressOlodVr : _addressOlod) * 100.0f);
return Convert.ToInt32(ReadMemory<float>(_addressOlod) * 100.0f);
}
public string ReadCloudQuality(bool isVr = false)
public string ReadCloudQuality()
{
return ReadCloudQualitySimValue(isVr) switch
return ReadCloudQualitySimValue() switch
{
0 => "Low",
1 => "Medium",
@ -131,33 +118,25 @@ namespace MSFSPopoutPanelManager.Orchestration
};
}
public int ReadCloudQualitySimValue(bool isVr = false)
public int ReadCloudQualitySimValue()
{
return Convert.ToInt32(ReadMemory<int>(isVr ? _addressCloudQVr : _addressCloudQ));
return Convert.ToInt32(ReadMemory<int>(_addressCloudQ));
}
public bool ReadIsVr()
public bool ReadIsFg()
{
return ReadMemory<int>(_addressVrMode) == 1;
}
public bool ReadIsFg(bool isVr)
{
if (isVr)
return false;
return ReadMemory<byte>(_addressFgMode) == 1;
}
public void UpdateLod(bool isVr)
public void UpdateLod()
{
if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(1))
if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit)
return;
if (DateTime.Now - _lastLodUpdateTime <= TimeSpan.FromSeconds(3))
return;
if (!FlightSimData.IsFlightStarted || !FlightSimData.IsInCockpit || (DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState != CameraState.Cockpit))
return;
var deltaFps = SimData.Fps - DynamicLodSetting.TargetedFps;
var deltaFps = DynamicLodSimData.Fps - DynamicLodSetting.TargetedFps;
if (Math.Abs(deltaFps) < DynamicLodSetting.TargetedFps * DynamicLodSetting.FpsTolerance / 100.0) // within FPS tolerance
return;
@ -246,10 +225,9 @@ namespace MSFSPopoutPanelManager.Orchestration
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
if (ReadTlod() < 10 || ReadTlod() > 1000 || ReadTlod() < 10 || ReadTlod() > 1000
|| ReadOlod() < 10 || ReadOlod() > 1000 || ReadOlod() < 10 || ReadOlod() > 1000
|| ReadCloudQuality() == "N/A" || ReadCloudQuality() == "N/A"
|| 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))
{
@ -259,12 +237,12 @@ namespace MSFSPopoutPanelManager.Orchestration
return true;
}
private void SetTlod(int deltaFps, bool isVr = false)
private void SetTlod(int deltaFps)
{
var tlodStep = Math.Max(5, Math.Abs(deltaFps / 2));
var newTlod = SimData.Tlod + Math.Sign(deltaFps) * tlodStep;
var tlodStep = Math.Max(10, Math.Abs(deltaFps / 2));
var newTlod = DynamicLodSimData.Tlod + Math.Sign(deltaFps) * tlodStep;
if (DynamicLodSetting.TlodMinOnGround && SimData.AltAboveGround <= DynamicLodSetting.AltTlodBase)
if (DynamicLodSetting.TlodMinOnGround && DynamicLodSimData.AltAboveGround <= DynamicLodSetting.AltTlodBase)
{
newTlod = DynamicLodSetting.TlodMin;
}
@ -277,17 +255,17 @@ namespace MSFSPopoutPanelManager.Orchestration
newTlod = DynamicLodSetting.TlodMax;
}
if (ReadTlod(isVr) == newTlod)
if (ReadTlod() == newTlod)
return;
// Adjust cloud quality if applicable
if (DynamicLodSetting.DecreaseCloudQuality && (!DynamicLodSetting.TlodMinOnGround && !(SimData.AltAboveGround <= DynamicLodSetting.AltTlodBase)))
if (DynamicLodSetting.DecreaseCloudQuality && (!DynamicLodSetting.TlodMinOnGround && !(DynamicLodSimData.AltAboveGround <= DynamicLodSetting.AltTlodBase)))
{
switch (deltaFps)
{
case < 0 when newTlod < DynamicLodSetting.CloudRecoveryTlod && !_isDecreasedCloudQualityActive:
_isDecreasedCloudQualityActive = true;
WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) - 1);
WriteMemory(_addressCloudQ, ReadCloudQualitySimValue() - 1);
_lastLodUpdateTime =
_lastLodUpdateTime.AddSeconds(2); // Add extra delay for cloud setting to take effect
@ -296,7 +274,7 @@ namespace MSFSPopoutPanelManager.Orchestration
return;
case > 0 when newTlod >= DynamicLodSetting.CloudRecoveryTlod && _isDecreasedCloudQualityActive:
_isDecreasedCloudQualityActive = false;
WriteMemory(isVr ? _addressCloudQVr : _addressCloudQ, ReadCloudQualitySimValue(isVr) + 1);
WriteMemory(_addressCloudQ, ReadCloudQualitySimValue() + 1);
_lastLodUpdateTime = _lastLodUpdateTime.AddSeconds(2);
Debug.WriteLine("New Cloud Quality written - 3.");
@ -306,31 +284,31 @@ namespace MSFSPopoutPanelManager.Orchestration
}
Debug.WriteLine($"New TLOD written - {newTlod}.");
WriteMemory(isVr ? _addressTlodVr : _addressTlod, newTlod / 100.0f);
WriteMemory(_addressTlod, newTlod / 100.0f);
}
private void SetOlod(bool isVr = false)
private void SetOlod()
{
int newOlod;
if (SimData.AltAboveGround < DynamicLodSetting.AltOlodBase)
if (DynamicLodSimData.AltAboveGround < DynamicLodSetting.AltOlodBase)
{
newOlod = DynamicLodSetting.OlodBase;
}
else if (SimData.AltAboveGround > DynamicLodSetting.AltOlodTop)
else if (DynamicLodSimData.AltAboveGround > DynamicLodSetting.AltOlodTop)
{
newOlod = DynamicLodSetting.OlodTop;
}
else
{
newOlod = Convert.ToInt32(DynamicLodSetting.OlodBase - (DynamicLodSetting.OlodBase - DynamicLodSetting.OlodTop) * (SimData.AltAboveGround - DynamicLodSetting.AltOlodBase) / (DynamicLodSetting.AltOlodTop - DynamicLodSetting.AltOlodBase));
newOlod = Convert.ToInt32(DynamicLodSetting.OlodBase - (DynamicLodSetting.OlodBase - DynamicLodSetting.OlodTop) * (DynamicLodSimData.AltAboveGround - DynamicLodSetting.AltOlodBase) / (DynamicLodSetting.AltOlodTop - DynamicLodSetting.AltOlodBase));
}
if (ReadOlod(isVr) == newOlod)
if (ReadOlod() == newOlod)
return;
Debug.WriteLine($"New OLOD written - {newOlod}.");
WriteMemory(isVr ? _addressOlodVr : _addressOlod, newOlod / 100.0f);
WriteMemory(_addressOlod, newOlod / 100.0f);
}
}
}

View file

@ -15,7 +15,7 @@ namespace MSFSPopoutPanelManager.Orchestration
private System.Timers.Timer _msfsGameExitDetectionTimer;
private SimConnectProvider _simConnectProvider;
private DynamicLodOrchestrator _dynamicLodOrchestrator;
private readonly DynamicLodOrchestrator _dynamicLodOrchestrator;
private bool _isTurnedOnPower;
private bool _isTurnedOnAvionics;
@ -72,22 +72,39 @@ namespace MSFSPopoutPanelManager.Orchestration
MapHudBarSimConnectData(e);
};
var _lastDynamicLodPause = DateTime.Now;
var _isDynamicLodPausePrevously = true;
var _lastDyanmicLodUpdatedTime = DateTime.Now;
_simConnectProvider.OnSimConnectDataDynamicLodRefreshed += (_, e) =>
{
if (!AppSettingData.ApplicationSetting.DynamicLodSetting.IsEnabled || !FlightSimData.IsFlightStarted)
return;
var isVr = _dynamicLodOrchestrator.ReadIsVr();
MapDynamicLodSimConnectData(e, isVr);
var isPaused = (AppSettingData.ApplicationSetting.DynamicLodSetting.PauseWhenMsfsLoseFocus && !WindowActionManager.IsMsfsInFocus()) ||
(AppSettingData.ApplicationSetting.DynamicLodSetting.PauseOutsideCockpitView && FlightSimData.CameraState != CameraState.Cockpit);
if (isPaused)
if (_isDynamicLodPausePrevously && !isPaused)
{
if (DateTime.Now - _lastDynamicLodPause <= TimeSpan.FromSeconds(3))
return;
_lastDynamicLodPause = DateTime.Now;
_isDynamicLodPausePrevously = false;
}
else if (isPaused)
{
_isDynamicLodPausePrevously = true;
return;
FlightSimData.DynamicLodSimData.Fps = FpsCalc.GetAverageFps(_dynamicLodOrchestrator.ReadIsFg(isVr) ? _currentFps * 2 : _currentFps);
_dynamicLodOrchestrator.UpdateLod(isVr);
}
if (DateTime.Now - _lastDyanmicLodUpdatedTime <= TimeSpan.FromSeconds(0.4)) // take FPS sample every 0.4 seconds
return;
_lastDyanmicLodUpdatedTime = DateTime.Now;
MapDynamicLodSimConnectData(e);
_dynamicLodOrchestrator.UpdateLod();
};
_simConnectProvider.OnSimConnectDataEventFrameRefreshed += (_, e) =>
@ -393,6 +410,7 @@ namespace MSFSPopoutPanelManager.Orchestration
FlightSimData.IsFlightStarted = false;
StopDynamicLod();
FpsCalc.Reset();
FlightSimData.DynamicLodSimData.Clear();
}
@ -492,7 +510,7 @@ namespace MSFSPopoutPanelManager.Orchestration
FlightSimData.HudBarData.SimRate = newValue;
}
private void MapDynamicLodSimConnectData(List<SimDataItem> simData, bool isVr)
private void MapDynamicLodSimConnectData(List<SimDataItem> simData)
{
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.PlaneAltAboveGround, FlightSimData.DynamicLodSimData.Agl, out var newValue))
FlightSimData.DynamicLodSimData.Agl = newValue;
@ -509,17 +527,19 @@ namespace MSFSPopoutPanelManager.Orchestration
if (CompareSimConnectData(simData, SimDataDefinitions.PropName.SimOnGround, 1.0f, out newValue))
FlightSimData.DynamicLodSimData.PlaneOnGround = Convert.ToBoolean(newValue);
var tlod = _dynamicLodOrchestrator.ReadTlod(isVr);
var tlod = _dynamicLodOrchestrator.ReadTlod();
if (FlightSimData.DynamicLodSimData.Tlod != tlod)
FlightSimData.DynamicLodSimData.Tlod = tlod;
var olod = _dynamicLodOrchestrator.ReadOlod(isVr);
var olod = _dynamicLodOrchestrator.ReadOlod();
if (FlightSimData.DynamicLodSimData.Olod != olod)
FlightSimData.DynamicLodSimData.Olod = olod;
var cloudQuality = _dynamicLodOrchestrator.ReadCloudQuality(isVr);
var cloudQuality = _dynamicLodOrchestrator.ReadCloudQuality();
if (FlightSimData.DynamicLodSimData.CloudQuality != cloudQuality)
FlightSimData.DynamicLodSimData.CloudQuality = cloudQuality;
FlightSimData.DynamicLodSimData.Fps = FpsCalc.GetAverageFps(_dynamicLodOrchestrator.ReadIsFg() ? _currentFps * 2 : _currentFps);
}
private int _currentFps;

View file

@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.Orchestration</RootNamespace>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>Embedded</DebugType>
<Configurations>Debug;Release;Local</Configurations>

View file

@ -130,8 +130,15 @@ namespace MSFSPopoutPanelManager.Orchestration
{
InputEmulationManager.ToggleFullScreenPanel(panelConfig.PanelHandle);
if (!panelConfig.FullScreen)
if (panelConfig.FullScreen)
{
WindowActionManager.SetHostMonitor(panelConfig);
}
else
{
WindowActionManager.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
panelConfig.FullScreenMonitorInfo = null;
}
}
else if (configPropertyName == PanelConfigPropertyName.PanelName)
{

View file

@ -122,7 +122,7 @@ namespace MSFSPopoutPanelManager.Orchestration
StepAddHudBar();
StepAddNumPad();
SetupRefocusDisplay();
StepApplyPanelConfig();
@ -412,12 +412,6 @@ namespace MSFSPopoutPanelManager.Orchestration
foreach (var panelConfig in ActiveProfile.PanelConfigs)
{
ApplyPanelConfig(panelConfig);
// Set title bar color
if (AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.IsEnabled && !panelConfig.FullScreen)
{
WindowActionManager.SetWindowTitleBarColor(panelConfig.PanelHandle, AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.HexColor);
}
}
}
@ -516,11 +510,10 @@ namespace MSFSPopoutPanelManager.Orchestration
if (!panel.FullScreen)
{
// Apply always on top
if (panel.AlwaysOnTop)
// Set title bar color
if (AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.IsEnabled)
{
WindowActionManager.ApplyAlwaysOnTop(panel.PanelHandle, panel.PanelType, panel.AlwaysOnTop);
Thread.Sleep(250);
WindowActionManager.SetWindowTitleBarColor(panel.PanelHandle, AppSettingData.ApplicationSetting.PopOutSetting.PopOutTitleBarCustomization.HexColor);
}
// Apply hide title bar
@ -529,6 +522,13 @@ namespace MSFSPopoutPanelManager.Orchestration
WindowActionManager.ApplyHidePanelTitleBar(panel.PanelHandle, true);
Thread.Sleep(250);
}
// Apply always on top (must apply this last)
if (panel.AlwaysOnTop)
{
WindowActionManager.ApplyAlwaysOnTop(panel.PanelHandle, panel.PanelType, panel.AlwaysOnTop);
Thread.Sleep(250);
}
}
if (panel.FullScreen && !panel.AlwaysOnTop && !panel.HideTitlebar)
@ -536,6 +536,9 @@ namespace MSFSPopoutPanelManager.Orchestration
Thread.Sleep(500);
InputEmulationManager.ToggleFullScreenPanel(panel.PanelHandle);
Thread.Sleep(250);
if (panel.TouchEnabled)
WindowActionManager.SetHostMonitor(panel); // Set full screen coordinate for touch
}
if (panel.FloatingPanel.IsEnabled && panel.FloatingPanel.HasKeyboardBinding && panel.FloatingPanel.IsHiddenOnStart)

View file

@ -1,15 +1,7 @@
## Version 4.1.1
## Version 4.1.2
* Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files.
* Added touch support for pop out when in full screen mode.
* Fixed POPM inability to close correctly when Keyboard Shortcuts preference is disabled.
* Fixed pop out always on top issue where it sometimes does not work.
* Fixed issue where auto start option failed to retain CommandLine arguments in exe.xml file.
* Fixed issue where auto start does not work correctly for Steam version of MSFS since exe.xml file location has been moved by Steam installation.
* Added ability for full screen panel to work as floating panel. An example use case is to show and hide EFB as full screen using keyboard shortcut.
* Added dynamic LOD (my own implementation of AutoFPS) - this is totally experimental and unsupported. If you decide to use this version of dynamic LOD, you don't have to run multiple apps.
* Fixed various smaller bugs.
* Improved dynamic LOD FPS detection and logic.

View file

@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.Shared</RootNamespace>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>Embedded</DebugType>
<Configurations>Debug;Release;Local</Configurations>

View file

@ -5,32 +5,57 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
{
public class FpsCalc
{
private const int FpsLen = 25;
private static readonly float[] FpsStatistic = new float[FpsLen];
private const int FPS_LEN = 5;
private static readonly float[] FpsStatistic = new float[FPS_LEN];
private static int _fpsIndex = -1;
private static int _avgFps;
private static int _ignoreFpsSpikeCount = 0;
public static int GetAverageFps(int newValue)
{
if (_fpsIndex == -1)
{
for (var i = 0; i < FpsLen; i++)
// initialize FpsStatistic array
for (var i = 0; i < FPS_LEN; i++)
FpsStatistic[i] = newValue;
_avgFps = Convert.ToInt32(newValue);
_fpsIndex = 1;
}
else
{
var isSpike = Math.Abs(newValue - _avgFps) / (_avgFps * 1.0) > 0.1;
if (_ignoreFpsSpikeCount != 3 && isSpike) // if new FPS spikes more than 10%, ignore the value
{
_ignoreFpsSpikeCount++;
return _avgFps;
}
_ignoreFpsSpikeCount = 0;
var deltaFps = newValue - _avgFps;
if (deltaFps < 0 && Math.Abs(deltaFps) > _avgFps * 0.1) // FPS suddenly drops more than 10%
{
newValue += Math.Abs(deltaFps) / 2; // Let the new FPS to be only half the delta drop
}
FpsStatistic[_fpsIndex] = newValue;
_fpsIndex++;
if (_fpsIndex >= FpsLen)
if (_fpsIndex >= FPS_LEN)
_fpsIndex = 0;
_avgFps = Convert.ToInt32(FpsStatistic.Sum() / FPS_LEN);
}
return _avgFps;
}
var fps = 0;
if (_fpsIndex != -1)
fps = Convert.ToInt32(FpsStatistic.Sum() / FpsLen);
return fps;
public static void Reset()
{
_fpsIndex = -1;
_avgFps = 0;
}
}
}

View file

@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.SimConnectAgent</RootNamespace>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>Embedded</DebugType>
<Configurations>Debug;Release;Local</Configurations>

View file

@ -1,6 +1,15 @@
# Version History
<hr/>
## Version 4.1.2
* Added touch support for pop out when in full screen mode.
* Fixed pop out always on top issue where it sometimes does not work.
* Improved dynamic LOD FPS detection and logic.
## Version 4.1.1
* Added option to store POPM profiles and configuration files in your user's AppData Roaming folder instead of Documents folder. Hopefully, this solved the issue where OneDrive users are having issue with POPM files.

View file

@ -193,6 +193,23 @@ namespace MSFSPopoutPanelManager.WindowsAgent
return new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
}
public static IntPtr GetWindowHandle(string windowCaption)
{
IntPtr windowHandle = IntPtr.Zero;
EnumWindows((hwnd, _) =>
{
var caption = GetWindowText(hwnd);
if (caption == windowCaption)
windowHandle = hwnd;
return true;
}, 0);
return windowHandle;
}
}
public struct RECT

View file

@ -92,10 +92,8 @@ namespace MSFSPopoutPanelManager.WindowsAgent
// If touch point is within pop out panel boundaries and have touch enabled
var panelConfig = ActiveProfile.PanelConfigs.FirstOrDefault(p => p.TouchEnabled &&
(info.pt.X > p.Left
&& info.pt.X < p.Left + p.Width
&& info.pt.Y > p.Top + (p.HideTitlebar ? 5 : PANEL_MENUBAR_HEIGHT)
&& info.pt.Y < p.Top + p.Height));
((p.FullScreen && CheckWithinFullScreenCoordinate(p, info)) || CheckWithinWindowCoordinate(p, info)));
if (panelConfig == null)
return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam);
@ -218,5 +216,21 @@ namespace MSFSPopoutPanelManager.WindowsAgent
return PInvoke.CallNextHookEx(_hHook, code, wParam, lParam);
}
private static bool CheckWithinWindowCoordinate(PanelConfig panelConfig, MSLLHOOKSTRUCT coor)
{
return coor.pt.X > panelConfig.Left
&& coor.pt.X < panelConfig.Left + panelConfig.Width
&& coor.pt.Y > panelConfig.Top + (panelConfig.HideTitlebar ? 5 : PANEL_MENUBAR_HEIGHT)
&& coor.pt.Y < panelConfig.Top + panelConfig.Height;
}
private static bool CheckWithinFullScreenCoordinate(PanelConfig panelConfig, MSLLHOOKSTRUCT coor)
{
return coor.pt.X > panelConfig.FullScreenMonitorInfo.X
&& coor.pt.X < panelConfig.FullScreenMonitorInfo.X + panelConfig.FullScreenMonitorInfo.Width
&& coor.pt.Y > panelConfig.FullScreenMonitorInfo.Y
&& coor.pt.Y < panelConfig.FullScreenMonitorInfo.Y + panelConfig.FullScreenMonitorInfo.Height;
}
}
}

View file

@ -49,6 +49,8 @@ namespace MSFSPopoutPanelManager.WindowsAgent
if (panelType == PanelType.PopOutManager)
{
OnPopOutManagerAlwaysOnTopChanged?.Invoke(null, alwaysOnTop);
if(alwaysOnTop)
PInvoke.SetWindowPos(hwnd, new IntPtr(PInvokeConstant.HWND_TOPMOST), 0, 0, 0, 0, PInvokeConstant.SWP_ALWAYS_ON_TOP);
return;
}
@ -309,5 +311,22 @@ namespace MSFSPopoutPanelManager.WindowsAgent
return text.Substring(0, 26).Equals("Microsoft Flight Simulator", StringComparison.InvariantCultureIgnoreCase);
}
public static void SetHostMonitor(PanelConfig panelConfig)
{
foreach (var screen in System.Windows.Forms.Screen.AllScreens)
{
if (screen.Bounds.IntersectsWith(new Rectangle(panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height)))
panelConfig.FullScreenMonitorInfo =
new MonitorInfo
{
Name = screen.DeviceName.Substring(screen.DeviceName.LastIndexOf("\\", StringComparison.Ordinal) + 1),
X = screen.Bounds.X,
Y = screen.Bounds.Y,
Width = screen.Bounds.Width,
Height = screen.Bounds.Height
};
}
}
}
}

View file

@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.WindowsAgent</RootNamespace>
<Platforms>x64</Platforms>
<Version>4.1.1.0</Version>
<AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.1.1.0</FileVersion>
<Version>4.1.2.0</Version>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<FileVersion>4.1.2.0</FileVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>Embedded</DebugType>
<Configurations>Debug;Release;Local</Configurations>