diff --git a/DomainModel/DomainModel.csproj b/DomainModel/DomainModel.csproj index 591a6a0..6848d72 100644 --- a/DomainModel/DomainModel.csproj +++ b/DomainModel/DomainModel.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.DomainModel x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/DomainModel/Profile/FloatingPanel.cs b/DomainModel/Profile/FloatingPanel.cs index 8c91a7a..2a6767e 100644 --- a/DomainModel/Profile/FloatingPanel.cs +++ b/DomainModel/Profile/FloatingPanel.cs @@ -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) diff --git a/DomainModel/Profile/PanelConfig.cs b/DomainModel/Profile/PanelConfig.cs index 26fe447..d39a010 100644 --- a/DomainModel/Profile/PanelConfig.cs +++ b/DomainModel/Profile/PanelConfig.cs @@ -127,5 +127,8 @@ namespace MSFSPopoutPanelManager.DomainModel.Profile return $"Left: {PanelSource.X} / Top: {PanelSource.Y}"; } } + + [JsonIgnore] + public MonitorInfo FullScreenMonitorInfo { get; set; } } } diff --git a/MainApp/AppUserControl/ProfileCard.xaml b/MainApp/AppUserControl/ProfileCard.xaml index 954dce7..e7dc75b 100644 --- a/MainApp/AppUserControl/ProfileCard.xaml +++ b/MainApp/AppUserControl/ProfileCard.xaml @@ -256,6 +256,7 @@ Include in-game menu bar panels for pop out management and touch screen support + { Topmost = e; }; MouseLeftButtonDown += (_, _) => DragMove(); + } private void AppWindow_Loaded(object sender, RoutedEventArgs e) diff --git a/MainApp/MainApp.csproj b/MainApp/MainApp.csproj index 4e2fcfc..7e2be53 100644 --- a/MainApp/MainApp.csproj +++ b/MainApp/MainApp.csproj @@ -14,9 +14,9 @@ MSFSPopoutPanelManager.MainApp logo.ico x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 embedded en diff --git a/MainApp/Properties/PublishProfiles/FolderProfile.pubxml b/MainApp/Properties/PublishProfiles/FolderProfile.pubxml index 118e0a6..18dfaa2 100644 --- a/MainApp/Properties/PublishProfiles/FolderProfile.pubxml +++ b/MainApp/Properties/PublishProfiles/FolderProfile.pubxml @@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - Local + Release x64 ..\..\..\publish\master FileSystem diff --git a/Orchestration/DynamicLodOrchestrator.cs b/Orchestration/DynamicLodOrchestrator.cs index ff0c937..f304014 100644 --- a/Orchestration/DynamicLodOrchestrator.cs +++ b/Orchestration/DynamicLodOrchestrator.cs @@ -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(_addressTlod) + OFFSET_POINTER_TLOD_VR; _addressTlod = ReadMemory(_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(isVr ? _addressTlodVr : _addressTlod) * 100.0f); + return Convert.ToInt32(ReadMemory(_addressTlod) * 100.0f); } - public int ReadOlod(bool isVr = false) + public int ReadOlod() { - return Convert.ToInt32(ReadMemory(isVr ? _addressOlodVr : _addressOlod) * 100.0f); + return Convert.ToInt32(ReadMemory(_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(isVr ? _addressCloudQVr : _addressCloudQ)); + return Convert.ToInt32(ReadMemory(_addressCloudQ)); } - public bool ReadIsVr() + public bool ReadIsFg() { - return ReadMemory(_addressVrMode) == 1; - } - - public bool ReadIsFg(bool isVr) - { - if (isVr) - return false; - return ReadMemory(_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(_addressVrMode) < 0 || ReadMemory(_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(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) < 1 || ReadMemory(_addressTlod + OFFSET_POINTER_ANSIO_FILTER) > 16 || !(ReadMemory(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 128 || ReadMemory(_addressTlod + OFFSET_POINTER_WATER_WAVES) == 256 || ReadMemory(_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); } } } diff --git a/Orchestration/FlightSimOrchestrator.cs b/Orchestration/FlightSimOrchestrator.cs index b195575..5a977b5 100644 --- a/Orchestration/FlightSimOrchestrator.cs +++ b/Orchestration/FlightSimOrchestrator.cs @@ -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 simData, bool isVr) + private void MapDynamicLodSimConnectData(List 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; diff --git a/Orchestration/Orchestration.csproj b/Orchestration/Orchestration.csproj index 6cf921a..fac2f5f 100644 --- a/Orchestration/Orchestration.csproj +++ b/Orchestration/Orchestration.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.Orchestration x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/Orchestration/PanelConfigurationOrchestrator.cs b/Orchestration/PanelConfigurationOrchestrator.cs index 7589b03..2c554c7 100644 --- a/Orchestration/PanelConfigurationOrchestrator.cs +++ b/Orchestration/PanelConfigurationOrchestrator.cs @@ -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) { diff --git a/Orchestration/PanelPopOutOrchestrator.cs b/Orchestration/PanelPopOutOrchestrator.cs index 2dfc340..749890f 100644 --- a/Orchestration/PanelPopOutOrchestrator.cs +++ b/Orchestration/PanelPopOutOrchestrator.cs @@ -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) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5ad2bc7..c0a1df8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -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. diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 08c68ae..1c410bb 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.Shared x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/SimconnectAgent/FpsCalc.cs b/SimconnectAgent/FpsCalc.cs index 6aff9e5..ddee248 100644 --- a/SimconnectAgent/FpsCalc.cs +++ b/SimconnectAgent/FpsCalc.cs @@ -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; } } } diff --git a/SimconnectAgent/SimconnectAgent.csproj b/SimconnectAgent/SimconnectAgent.csproj index 818840d..7ca62cf 100644 --- a/SimconnectAgent/SimconnectAgent.csproj +++ b/SimconnectAgent/SimconnectAgent.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.SimConnectAgent x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local diff --git a/VERSION.md b/VERSION.md index 1eabd21..ce54ff0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1,6 +1,15 @@ # Version History
+## 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. diff --git a/WindowsAgent/PInvoke.cs b/WindowsAgent/PInvoke.cs index 97a7909..fb74e56 100644 --- a/WindowsAgent/PInvoke.cs +++ b/WindowsAgent/PInvoke.cs @@ -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 diff --git a/WindowsAgent/TouchEventManager.cs b/WindowsAgent/TouchEventManager.cs index 99c7640..8260e40 100644 --- a/WindowsAgent/TouchEventManager.cs +++ b/WindowsAgent/TouchEventManager.cs @@ -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; + } } } diff --git a/WindowsAgent/WindowActionManager.cs b/WindowsAgent/WindowActionManager.cs index ffd5a8c..2a1ffa6 100644 --- a/WindowsAgent/WindowActionManager.cs +++ b/WindowsAgent/WindowActionManager.cs @@ -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 + }; + } + } } } diff --git a/WindowsAgent/WindowsAgent.csproj b/WindowsAgent/WindowsAgent.csproj index 337f6b8..c8f4d3d 100644 --- a/WindowsAgent/WindowsAgent.csproj +++ b/WindowsAgent/WindowsAgent.csproj @@ -11,9 +11,9 @@ https://github.com/hawkeye-stan/msfs-popout-panel-manager MSFSPopoutPanelManager.WindowsAgent x64 - 4.1.1.0 - 4.1.1.0 - 4.1.1.0 + 4.1.2.0 + 4.1.2.0 + 4.1.2.0 win-x64 Embedded Debug;Release;Local