1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-11-21 21:30:12 +00:00

Started development v3.4.2

This commit is contained in:
Stanley 2022-08-01 19:21:42 -04:00
parent c42f2703b7
commit d7a8ddfa8f
17 changed files with 123 additions and 96 deletions

View file

@ -6,13 +6,13 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
public class FlightSimData : ObservableObject public class FlightSimData : ObservableObject
{ {
public event PropertyChangedEventHandler CurrentMsfsPlaneTitleChanged; public event PropertyChangedEventHandler CurrentMsfsAircraftChanged;
public string CurrentMsfsPlaneTitle { get; set; } public string CurrentMsfsAircraft { get; set; }
public bool HasCurrentMsfsPlaneTitle public bool HasCurrentMsfsAircraft
{ {
get { return !String.IsNullOrEmpty(CurrentMsfsPlaneTitle); } get { return !String.IsNullOrEmpty(CurrentMsfsAircraft); }
} }
public bool ElectricalMasterBatteryStatus { get; set; } public bool ElectricalMasterBatteryStatus { get; set; }
@ -25,8 +25,8 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
if (oldValue != newValue) if (oldValue != newValue)
{ {
if (propertyName == "CurrentMsfsPlaneTitle") if (propertyName == "CurrentMsfsAircraft")
CurrentMsfsPlaneTitleChanged?.Invoke(this, null); CurrentMsfsAircraftChanged?.Invoke(this, null);
base.OnPropertyChanged(propertyName, oldValue, newValue); base.OnPropertyChanged(propertyName, oldValue, newValue);
} }
@ -34,7 +34,7 @@ namespace MSFSPopoutPanelManager.Orchestration
public void ClearData() public void ClearData()
{ {
CurrentMsfsPlaneTitle = null; CurrentMsfsAircraft = null;
ElectricalMasterBatteryStatus = false; ElectricalMasterBatteryStatus = false;
IsEnteredFlight = false; IsEnteredFlight = false;
} }

View file

@ -43,14 +43,15 @@ namespace MSFSPopoutPanelManager.Orchestration
}; };
_simConnectProvider.OnSimConnectDataRefreshed += (sender, e) => _simConnectProvider.OnSimConnectDataRefreshed += (sender, e) =>
{ {
var title = Convert.ToString(e.Find(d => d.PropName == "Title").Value); var aircraftName = Convert.ToString(e.Find(d => d.PropName == "AircraftName").Value);
aircraftName = String.IsNullOrEmpty(aircraftName) ? null : aircraftName;
var electricalMasterBattery = Convert.ToBoolean(e.Find(d => d.PropName == "ElectricalMasterBattery").Value); var electricalMasterBattery = Convert.ToBoolean(e.Find(d => d.PropName == "ElectricalMasterBattery").Value);
// Automatic switching of active profile when SimConnect active aircraft livery changes // Automatic switching of active profile when SimConnect active aircraft change
if (FlightSimData.CurrentMsfsPlaneTitle != title) if (FlightSimData.CurrentMsfsAircraft != aircraftName)
{ {
FlightSimData.CurrentMsfsPlaneTitle = title; FlightSimData.CurrentMsfsAircraft = aircraftName;
ProfileData.AutoSwitchProfile(title); ProfileData.AutoSwitchProfile(aircraftName);
} }
if (electricalMasterBattery != FlightSimData.ElectricalMasterBatteryStatus) if (electricalMasterBattery != FlightSimData.ElectricalMasterBatteryStatus)

View file

@ -20,7 +20,7 @@ namespace MSFSPopoutPanelManager.Orchestration
TouchPanel = new TouchPanelOrchestrator(); TouchPanel = new TouchPanelOrchestrator();
FlightSimData = new FlightSimData(); FlightSimData = new FlightSimData();
FlightSimData.CurrentMsfsPlaneTitleChanged += (sernder, e) => ProfileData.RefreshProfile(); FlightSimData.CurrentMsfsAircraftChanged += (sernder, e) => ProfileData.RefreshProfile();
AppSettingData = new AppSettingData(); AppSettingData = new AppSettingData();
AppSettingData.AutoPopOutPanelsChanged += (sender, e) => FlightSim.AutoPanelPopOutActivation(e); AppSettingData.AutoPopOutPanelsChanged += (sender, e) => FlightSim.AutoPanelPopOutActivation(e);

View file

@ -55,14 +55,14 @@ namespace MSFSPopoutPanelManager.Orchestration
if (ActiveProfile == null) if (ActiveProfile == null)
return; return;
ProfileData.AutoSwitchProfile(FlightSimData.CurrentMsfsPlaneTitle); ProfileData.AutoSwitchProfile(FlightSimData.CurrentMsfsAircraft);
FlightSimData.IsEnteredFlight = true; FlightSimData.IsEnteredFlight = true;
// find the profile with the matching binding plane title // find the profile with the matching binding aircraft
var profile = ProfileData.Profiles.FirstOrDefault(p => p.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle)); var profile = ProfileData.Profiles.FirstOrDefault(p => p.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft));
// Do not do auto pop out if no profile matches the current livery // Do not do auto pop out if no profile matches the current aircraft
if (profile == null) if (profile == null)
return; return;

View file

@ -47,21 +47,21 @@ namespace MSFSPopoutPanelManager.Orchestration
return true; return true;
} }
public void AddProfileBinding(string planeTitle, int activeProfileId) public void AddProfileBinding(string aircraft, int activeProfileId)
{ {
if (ActiveProfile == null) if (ActiveProfile == null)
return; return;
ProfileManager.AddProfileBinding(planeTitle, activeProfileId, Profiles); ProfileManager.AddProfileBinding(aircraft, activeProfileId, Profiles);
RefreshProfile(); RefreshProfile();
} }
public void DeleteProfileBinding(string planeTitle, int activeProfileId) public void DeleteProfileBinding(string aircraft, int activeProfileId)
{ {
if (ActiveProfile == null) if (ActiveProfile == null)
return; return;
ProfileManager.DeleteProfileBinding(planeTitle, activeProfileId, Profiles); ProfileManager.DeleteProfileBinding(aircraft, activeProfileId, Profiles);
RefreshProfile(); RefreshProfile();
} }
@ -111,7 +111,7 @@ namespace MSFSPopoutPanelManager.Orchestration
if (ActiveProfile == null) if (ActiveProfile == null)
return false; return false;
return ActiveProfile.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle); return ActiveProfile.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft);
} }
} }
@ -119,14 +119,14 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
get get
{ {
if (ActiveProfile == null || !FlightSimData.HasCurrentMsfsPlaneTitle) if (ActiveProfile == null || !FlightSimData.HasCurrentMsfsAircraft)
return false; return false;
var uProfile = Profiles.FirstOrDefault(u => u.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle)); var uProfile = Profiles.FirstOrDefault(u => u.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft));
if (uProfile != null && uProfile.ProfileId != ActiveProfile.ProfileId) if (uProfile != null && uProfile.ProfileId != ActiveProfile.ProfileId)
return false; return false;
return ActiveProfile.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle); return ActiveProfile.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft);
} }
} }
@ -134,17 +134,17 @@ namespace MSFSPopoutPanelManager.Orchestration
{ {
get get
{ {
if (ActiveProfile == null || !FlightSimData.HasCurrentMsfsPlaneTitle) if (ActiveProfile == null || !FlightSimData.HasCurrentMsfsAircraft)
return false; return false;
var uProfile = Profiles.FirstOrDefault(u => u.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle)); var uProfile = Profiles.FirstOrDefault(u => u.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft));
if (uProfile != null && uProfile.ProfileId != ActiveProfile.ProfileId) if (uProfile != null && uProfile.ProfileId != ActiveProfile.ProfileId)
return false; return false;
if (FlightSimData == null || ActiveProfile.BindingAircraftLiveries == null) if (FlightSimData == null || ActiveProfile.BindingAircrafts == null)
return false; return false;
return ActiveProfile == null ? false : !ActiveProfile.BindingAircraftLiveries.Any(p => p == FlightSimData.CurrentMsfsPlaneTitle); return ActiveProfile == null ? false : !ActiveProfile.BindingAircrafts.Any(p => p == FlightSimData.CurrentMsfsAircraft);
} }
} }
@ -160,12 +160,12 @@ namespace MSFSPopoutPanelManager.Orchestration
UpdateActiveProfile(currentProfileId); UpdateActiveProfile(currentProfileId);
} }
public void AutoSwitchProfile(string activeAircraftTitle) public void AutoSwitchProfile(string activeAircraft)
{ {
// Automatic switching of active profile when SimConnect active aircraft livery changes // Automatic switching of active profile when SimConnect active aircraft changes
if (Profiles != null) if (Profiles != null)
{ {
var matchedProfile = Profiles.FirstOrDefault(p => p.BindingAircraftLiveries.Any(t => t == activeAircraftTitle)); var matchedProfile = Profiles.FirstOrDefault(p => p.BindingAircrafts.Any(t => t == activeAircraft));
if (matchedProfile != null) if (matchedProfile != null)
UpdateActiveProfile(matchedProfile.ProfileId); UpdateActiveProfile(matchedProfile.ProfileId);
} }

View file

@ -26,16 +26,16 @@ namespace MSFSPopoutPanelManager.Orchestration
ProfileData.UpdateActiveProfile(profileId); ProfileData.UpdateActiveProfile(profileId);
} }
public void AddProfileBinding(string bindingLiveryName) public void AddProfileBinding(string bindingAircraft)
{ {
if (ProfileData.ActiveProfile != null) if (ProfileData.ActiveProfile != null)
ProfileData.AddProfileBinding(bindingLiveryName, ProfileData.ActiveProfile.ProfileId); ProfileData.AddProfileBinding(bindingAircraft, ProfileData.ActiveProfile.ProfileId);
} }
public void DeleteProfileBinding(string bindingLiveryName) public void DeleteProfileBinding(string bindingAircraft)
{ {
if (ProfileData.ActiveProfile != null) if (ProfileData.ActiveProfile != null)
ProfileData.DeleteProfileBinding(bindingLiveryName, ProfileData.ActiveProfile.ProfileId); ProfileData.DeleteProfileBinding(bindingAircraft, ProfileData.ActiveProfile.ProfileId);
} }
} }
} }

View file

@ -37,7 +37,7 @@ If using SpaceDesk to host pop out panel display, since there is a latency for t
* Intuitive user interface to defined location of panels to be popped out. * Intuitive user interface to defined location of panels to be popped out.
* [Auto Pop Out](#auto-pop-out-feature) feature. The application will detect active aircraft by livery and activate the corresponding profile on start of new flight session. * [Auto Pop Out](#auto-pop-out-feature) feature. The application will detect active aircraft and activate the corresponding profile on start of new flight session.
* [Cold Start feature](#auto-pop-out-feature). Instrumentation panels can be popped out even when they're not powered on (for G1000 / / G1000 NXi planes only). * [Cold Start feature](#auto-pop-out-feature). Instrumentation panels can be popped out even when they're not powered on (for G1000 / / G1000 NXi planes only).
@ -96,7 +96,7 @@ What if you can do the setup once by defining on screen where the pop out panels
<img src="assets/readme/images/add_profile.png" width="900" hspace="10"/> <img src="assets/readme/images/add_profile.png" width="900" hspace="10"/>
</p> </p>
2. For step 2, if you want to associate the profile to the current aircraft livery to use in [Auto Pop Out](#auto-pop-out-feature) feature or for automatic profile switching when selecting a different aircraft, click the "plus" button next to the aircraft livery name. The aircraft livery title will become green once the livery is bound to the profile. Your chosen livery may not be available to select in the application for your newly selected plane until a flight is started. 2. For step 2, if you want to associate the profile to the current aircraft to use in [Auto Pop Out](#auto-pop-out-feature) feature or for automatic profile switching when selecting a different aircraft, click the "plus" button next to the aircraft name. The aircraft title will become green once the it is bound to the profile. Your chosen aircraft may not be available to select in the application for your newly selected plane until a flight is started.
<p align="center"> <p align="center">
<img src="assets/readme/images/bind_profile_to_livery.png" width="900" hspace="10"/> <img src="assets/readme/images/bind_profile_to_livery.png" width="900" hspace="10"/>
@ -134,19 +134,17 @@ What if you can do the setup once by defining on screen where the pop out panels
[Online Video - How to enable auto pop out panels](https://vimeo.com/723165248) [Online Video - How to enable auto pop out panels](https://vimeo.com/723165248)
The app will try to find a matching profile with the current selected aircraft livery. It will then detect when a flight is starting and automatically click the "Ready to Fly" button. It will also power on instrumentation for cold start (for G1000/NXi equipped plane only), and then pop out all panels. This feature allows panels to be popped out without the need of user interaction. If profiles are set and bound to your frequently used aircraft livery, you can auto-start the app minimized in system tray and as you start your flight, panels will automatically pop out for you for the selected aircraft. The app will try to find a matching profile with the current selected aircraft. It will then detect when a flight is starting and automatically click the "Ready to Fly" button. It will also power on instrumentation for cold start (for G1000/NXi equipped plane only), and then pop out all panels. This feature allows panels to be popped out without the need of user interaction. If profiles are set and bound to your frequently used aircraft, you can auto-start the app minimized in system tray and as you start your flight, panels will automatically pop out for you for the selected aircraft.
* In File->Preferences->Auto Pop Out Panel Settings, "Enable Auto Pop Out Panels" option is turned on. You can also adjust wait delay settings if you've a fast computer. * In File->Preferences->Auto Pop Out Panel Settings, "Enable Auto Pop Out Panels" option is turned on. You can also adjust wait delay settings if you've a fast computer.
* For existing profile to use Auto Pop Out feature, just click the plus sign in the bind active aircraft livery to profile section. This will bind the active aircraft livery being displayed to the profile. Any bound aircraft livery will appear in GREEN color. Unbound ones will be in WHITE, and bound livery in another profile will be in RED. You can bind as many liveries to a profile as you desire but a livery can only bind to a single profile so Auto Pop Out knows which profile to start when a flight session starts. * For existing profile to use Auto Pop Out feature, just click the plus sign in the bind active aircraft to profile section. This will bind the active aircraft being displayed to the profile. Any bound aircraft will appear in GREEN color. Unbound ones will be in WHITE, and bound aircraft in another profile will be in RED. You can bind as many liveries to a profile as you desire but an aircraft can only bind to a single profile so Auto Pop Out knows which profile to start when a flight session starts.
* During my testing, instrumentations only need to be powered on for Auto Pop Out to work for G1000/G1000 NXi plane during cold start. (There seems to be a bug in the game that you can't do Alt-Right click to pop out cold start panel for this particular plane variant). For other plane instrumentations I've tested (G3000, CJ4, Aerosoft CRJ 550/700, FBW A32NX), panels can be popped out without powering on. So please make sure the checkbox "Power on required to pop out panels on cold start" is checked for G1000 related profiles. * During my testing, instrumentations only need to be powered on for Auto Pop Out to work for G1000/G1000 NXi plane during cold start. (There seems to be a bug in the game that you can't do Alt-Right click to pop out cold start panel for this particular plane variant). For other plane instrumentations I've tested (G3000, CJ4, Aerosoft CRJ 550/700, FBW A32NX), panels can be popped out without powering on. So please make sure the checkbox "Power on required to pop out panels on cold start" is checked for G1000 related profiles.
* **TIPS:** If you want to fly an aircraft with different livery, just add the aircraft livery binding to your desire profile when you switch livery.
* **TIPS:** You can go to the preference settings to configure the time delay for each steps for the Auto Pop Out process based on the speed of your computer if things do not work correctly or if you want to speed up the Auto Pop Out process. * **TIPS:** You can go to the preference settings to configure the time delay for each steps for the Auto Pop Out process based on the speed of your computer if things do not work correctly or if you want to speed up the Auto Pop Out process.
* **TIPS:** One trick to force SimConnect to update the current selected aircraft livery so you can do the binding immediately after selecting a new livery in the World Map is to click the "Go Back" button at the lower left of your screen. You should see aircraft title changes to the active ones. Or you can wait until the flight is almost fully loaded and you will see the current aircraft livery name gets updated. * **TIPS:** One trick to force SimConnect to update the current selected aircraft so you can do the binding immediately after selecting a new aircraft in the World Map is to click the "Go Back" button at the lower left of your screen. You should see aircraft title changes to the active ones. Or you can wait until the flight is almost fully loaded and you will see the current aircraft name gets updated.
<hr/> <hr/>

View file

@ -13,6 +13,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "TrackIREnable", VariableName = "TRACK IR ENABLE", SimConnectUnit = "Bool", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null }); definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "TrackIREnable", VariableName = "TRACK IR ENABLE", SimConnectUnit = "Bool", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null });
definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "PlaneInParkingSpot", VariableName = "ATC ON PARKING SPOT", SimConnectUnit = "Bool", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null }); definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "PlaneInParkingSpot", VariableName = "ATC ON PARKING SPOT", SimConnectUnit = "Bool", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null });
definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "CameraState", VariableName = "CAMERA STATE", SimConnectUnit = "Number", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null }); definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimConnect, PropName = "CameraState", VariableName = "CAMERA STATE", SimConnectUnit = "Number", DataType = DataType.Float64, DefaultValue = String.Empty, JavaScriptFormatting = null });
definitions.Add(new SimConnectDataDefinition() { DataDefinitionType = DataDefinitionType.SimEvent, PropName = "AircraftName", VariableName = "", SimConnectUnit = "", DataType = DataType.String, DefaultValue = String.Empty, JavaScriptFormatting = null });
return definitions; return definitions;
} }
} }

View file

@ -51,6 +51,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
SIMSTART, SIMSTART,
SIMSTOP, SIMSTOP,
FLIGHTLOADED, FLIGHTLOADED,
AIRCRAFTLOADED,
PAUSED, PAUSED,
VIEW, VIEW,
NONE NONE

View file

@ -38,7 +38,8 @@
{ {
AVar, AVar,
LVar, LVar,
SimConnect SimConnect,
SimEvent
} }
public enum DataType public enum DataType

View file

@ -152,6 +152,7 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
_simConnect.OnRecvException += HandleOnRecvException; _simConnect.OnRecvException += HandleOnRecvException;
_simConnect.OnRecvEvent += HandleOnReceiveSystemEvent; _simConnect.OnRecvEvent += HandleOnReceiveSystemEvent;
_simConnect.OnRecvSimobjectDataBytype += HandleOnRecvSimobjectDataBytype; _simConnect.OnRecvSimobjectDataBytype += HandleOnRecvSimobjectDataBytype;
_simConnect.OnRecvEventFilename += HandleOnRecvEventFilename;
// Register simConnect system events // Register simConnect system events
_simConnect.UnsubscribeFromSystemEvent(SimConnectSystemEvent.SIMSTART); _simConnect.UnsubscribeFromSystemEvent(SimConnectSystemEvent.SIMSTART);
@ -160,6 +161,8 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
_simConnect.SubscribeToSystemEvent(SimConnectSystemEvent.SIMSTOP, "SimStop"); _simConnect.SubscribeToSystemEvent(SimConnectSystemEvent.SIMSTOP, "SimStop");
_simConnect.UnsubscribeFromSystemEvent(SimConnectSystemEvent.VIEW); _simConnect.UnsubscribeFromSystemEvent(SimConnectSystemEvent.VIEW);
_simConnect.SubscribeToSystemEvent(SimConnectSystemEvent.VIEW, "View"); _simConnect.SubscribeToSystemEvent(SimConnectSystemEvent.VIEW, "View");
_simConnect.UnsubscribeFromSystemEvent(SimConnectSystemEvent.AIRCRAFTLOADED);
_simConnect.SubscribeToSystemEvent(SimConnectSystemEvent.AIRCRAFTLOADED, "AircraftLoaded");
System.Threading.Thread.Sleep(5000); System.Threading.Thread.Sleep(5000);
ReceiveMessage(); ReceiveMessage();
@ -171,6 +174,20 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
StatusMessageWriter.WriteMessage("MSFS is connected", StatusMessageType.Info, false); StatusMessageWriter.WriteMessage("MSFS is connected", StatusMessageType.Info, false);
} }
private void HandleOnRecvEventFilename(SimConnect sender, SIMCONNECT_RECV_EVENT_FILENAME data)
{
switch (data.uEventID)
{
case (uint)SimConnectSystemEvent.AIRCRAFTLOADED:
var filePathToken = data.szFileName.Split(@"\");
var aircraftName = filePathToken[filePathToken.Length - 2];
aircraftName = aircraftName.Replace("_", " ").ToUpper();
SimConnectDataDefinitions.Find(s => s.PropName == "AircraftName").Value = aircraftName;
break;
}
}
private void AddDataDefinitions() private void AddDataDefinitions()
{ {
int definitionId = 1; int definitionId = 1;
@ -180,33 +197,36 @@ namespace MSFSPopoutPanelManager.SimConnectAgent
foreach (var definition in SimConnectDataDefinitions) foreach (var definition in SimConnectDataDefinitions)
{ {
SIMCONNECT_DATATYPE simmConnectDataType; if (definition.DataDefinitionType == DataDefinitionType.SimConnect)
switch (definition.DataType)
{ {
case DataType.String: SIMCONNECT_DATATYPE simmConnectDataType;
simmConnectDataType = SIMCONNECT_DATATYPE.STRING256; switch (definition.DataType)
break; {
case DataType.Float64: case DataType.String:
simmConnectDataType = SIMCONNECT_DATATYPE.FLOAT64; simmConnectDataType = SIMCONNECT_DATATYPE.STRING256;
break; break;
default: case DataType.Float64:
simmConnectDataType = SIMCONNECT_DATATYPE.FLOAT64; simmConnectDataType = SIMCONNECT_DATATYPE.FLOAT64;
break; break;
default:
simmConnectDataType = SIMCONNECT_DATATYPE.FLOAT64;
break;
}
_simConnect.AddToDataDefinition((SIMCONNECT_DEFINE_ID)definitionId, definition.VariableName, definition.SimConnectUnit, simmConnectDataType, 0.0f, SimConnect.SIMCONNECT_UNUSED);
// Assign definition id and request id back into definition object
definition.DefineId = (SIMCONNECT_DEFINE_ID)definitionId;
definition.RequestId = (SIMCONNECT_REQUEST)requestId;
if (definition.DataType == DataType.String)
_simConnect.RegisterDataDefineStruct<SimConnectStruct>(definition.DefineId);
else
_simConnect.RegisterDataDefineStruct<double>(definition.DefineId);
definitionId++;
requestId++;
} }
_simConnect.AddToDataDefinition((SIMCONNECT_DEFINE_ID)definitionId, definition.VariableName, definition.SimConnectUnit, simmConnectDataType, 0.0f, SimConnect.SIMCONNECT_UNUSED);
// Assign definition id and request id back into definition object
definition.DefineId = (SIMCONNECT_DEFINE_ID)definitionId;
definition.RequestId = (SIMCONNECT_REQUEST)requestId;
if (definition.DataType == DataType.String)
_simConnect.RegisterDataDefineStruct<SimConnectStruct>(definition.DefineId);
else
_simConnect.RegisterDataDefineStruct<double>(definition.DefineId);
definitionId++;
requestId++;
} }
// Setup SimEvent mapping // Setup SimEvent mapping

View file

@ -9,7 +9,7 @@ namespace MSFSPopoutPanelManager.UserDataAgent
{ {
public Profile() public Profile()
{ {
BindingAircraftLiveries = new ObservableCollection<string>(); BindingAircrafts = new ObservableCollection<string>();
PanelConfigs = new ObservableCollection<PanelConfig>(); PanelConfigs = new ObservableCollection<PanelConfig>();
PanelSourceCoordinates = new ObservableCollection<PanelSourceCoordinate>(); PanelSourceCoordinates = new ObservableCollection<PanelSourceCoordinate>();
TouchPanelBindings = new ObservableCollection<TouchPanelBinding>(); TouchPanelBindings = new ObservableCollection<TouchPanelBinding>();
@ -21,7 +21,7 @@ namespace MSFSPopoutPanelManager.UserDataAgent
public string ProfileName { get; set; } public string ProfileName { get; set; }
[JsonConverter(typeof(SingleValueArrayConvertor<string>))] [JsonConverter(typeof(SingleValueArrayConvertor<string>))]
public ObservableCollection<string> BindingAircraftLiveries { get; set; } public ObservableCollection<string> BindingAircrafts { get; set; }
public ObservableCollection<PanelSourceCoordinate> PanelSourceCoordinates { get; set; } public ObservableCollection<PanelSourceCoordinate> PanelSourceCoordinates { get; set; }
@ -37,14 +37,14 @@ namespace MSFSPopoutPanelManager.UserDataAgent
public bool IsActive { get; set; } public bool IsActive { get; set; }
[JsonIgnore] [JsonIgnore]
public bool HasBindingAircraftLiveries public bool HasBindingAircrafts
{ {
get get
{ {
if (BindingAircraftLiveries == null) if (BindingAircrafts == null)
return false; return false;
return BindingAircraftLiveries.Count > 0; return BindingAircrafts.Count > 0;
} }
} }

View file

@ -28,7 +28,7 @@ namespace MSFSPopoutPanelManager.UserDataAgent
var matchedProfile = profiles.FirstOrDefault(p => p.ProfileId == copyProfileId); var matchedProfile = profiles.FirstOrDefault(p => p.ProfileId == copyProfileId);
var copiedProfile = matchedProfile.Copy<Profile>(); // Using Shared/ObjectExtensions.cs extension method var copiedProfile = matchedProfile.Copy<Profile>(); // Using Shared/ObjectExtensions.cs extension method
copiedProfile.BindingAircraftLiveries = new ObservableCollection<string>(); copiedProfile.BindingAircrafts = new ObservableCollection<string>();
return AddProfile(copiedProfile, newProfileName, profiles); return AddProfile(copiedProfile, newProfileName, profiles);
} }
@ -46,24 +46,24 @@ namespace MSFSPopoutPanelManager.UserDataAgent
return true; return true;
} }
public static void AddProfileBinding(string planeTitle, int activeProfileId, IList<Profile> profiles) public static void AddProfileBinding(string aircraft, int activeProfileId, IList<Profile> profiles)
{ {
var boundProfile = profiles.FirstOrDefault(p => p.BindingAircraftLiveries.Any(p => p == planeTitle)); var boundProfile = profiles.FirstOrDefault(p => p.BindingAircrafts.Any(p => p == aircraft));
if (boundProfile != null) if (boundProfile != null)
{ {
StatusMessageWriter.WriteMessage($"Unable to add binding to the profile because '{planeTitle}' was already bound to profile '{boundProfile.ProfileName}'.", StatusMessageType.Error, false); StatusMessageWriter.WriteMessage($"Unable to add binding to the profile because '{aircraft}' was already bound to profile '{boundProfile.ProfileName}'.", StatusMessageType.Error, false);
return; return;
} }
profiles.First(p => p.ProfileId == activeProfileId).BindingAircraftLiveries.Add(planeTitle); profiles.First(p => p.ProfileId == activeProfileId).BindingAircrafts.Add(aircraft);
WriteProfiles(profiles); WriteProfiles(profiles);
StatusMessageWriter.WriteMessage($"Binding for the profile has been added successfully.", StatusMessageType.Info, false); StatusMessageWriter.WriteMessage($"Binding for the profile has been added successfully.", StatusMessageType.Info, false);
} }
public static void DeleteProfileBinding(string planeTitle, int activeProfileId, IList<Profile> profiles) public static void DeleteProfileBinding(string aircraft, int activeProfileId, IList<Profile> profiles)
{ {
profiles.First(p => p.ProfileId == activeProfileId).BindingAircraftLiveries.Remove(planeTitle); profiles.First(p => p.ProfileId == activeProfileId).BindingAircrafts.Remove(aircraft);
WriteProfiles(profiles); WriteProfiles(profiles);
StatusMessageWriter.WriteMessage($"Binding for the profile has been deleted successfully.", StatusMessageType.Info, false); StatusMessageWriter.WriteMessage($"Binding for the profile has been deleted successfully.", StatusMessageType.Info, false);

View file

@ -3,16 +3,16 @@
## Version 3.4.1 ## Version 3.4.1
This release is solely focus on addressing issues regarding touch panel capabilities as well as making improvements to touch feature. Panels I used for testing are This release is solely focused on addressing issues regarding touch panel capabilities as well as making improvements to touch feature. Panels I used for testing are
PMT GTN750, WT G3X mod, PMS GTN530, FBW A32NX EFB, King Air 350 PFD/MFD touch screen. PMT GTN750, WT G3X mod, PMS GTN530, FBW A32NX EFB, King Air 350 PFD/MFD touch screen.
When using SpaceDesk, please increase touch down touch up delay to 25ms in preference touch settings to improve sensitivity in registering touch input. When using SpaceDesk, please increase touch down touch up delay to 25ms in preference touch settings to improve sensitivity for touch input.
* Implemented new algorithm to improve general performance for touch panel. * Implemented new algorithm to improve general performance for touch panel.
* Button touches are now more responsive. On touch monitor, lag after touch had been minimized and is now performing much closer to a mouse click. On SpaceDesk, the lag is more in line with latency of remote display technology. When using SpaceDesk, you can increase touch delay to 25ms in preference settings to account for the latency if your touch is not register consistently. * Button touches are now more responsive. On touch monitor, lag after touch had been minimized and is now performing much closer to a mouse click. On SpaceDesk, the lag is more in line with latency of remote display technology. When using SpaceDesk, you can increase touch delay to 25ms in preference settings to account for the latency if your touch is not register consistently.
* You can now slide your finger to pan the map in panel. There is still a slight delay but touch response is much improved. * You can now slide your finger to pan map in panel. There is still a slight delay but touch response is much improved.
* Full screen mode for touch panel can now be turned on. * Full screen mode for touch panel can now be turned on.

View file

@ -15,6 +15,7 @@ namespace MSFSPopoutPanelManager.WindowsAgent
const uint VK_RMENU = 0xA5; const uint VK_RMENU = 0xA5;
const uint VK_LMENU = 0xA4; const uint VK_LMENU = 0xA4;
const uint VK_LCONTROL = 0xA2; const uint VK_LCONTROL = 0xA2;
const uint VK_RCONTROL = 0xA3;
const uint VK_SPACE = 0x20; const uint VK_SPACE = 0x20;
const uint VK_ENT = 0x0D; const uint VK_ENT = 0x0D;
const uint KEY_0 = 0x30; const uint KEY_0 = 0x30;
@ -102,6 +103,11 @@ namespace MSFSPopoutPanelManager.WindowsAgent
if (simualatorProcess == null) if (simualatorProcess == null)
return; return;
CenterView(simualatorProcess);
}
public static void CenterView(WindowProcess simualatorProcess)
{
Rectangle rectangle; Rectangle rectangle;
PInvoke.GetWindowRect(simualatorProcess.Handle, out rectangle); PInvoke.GetWindowRect(simualatorProcess.Handle, out rectangle);
@ -113,14 +119,13 @@ namespace MSFSPopoutPanelManager.WindowsAgent
PInvoke.SetForegroundWindow(simualatorProcess.Handle); PInvoke.SetForegroundWindow(simualatorProcess.Handle);
LeftClick(x, y); LeftClick(x, y);
Thread.Sleep(200);
// First center view using Ctrl-Space // First center view using Ctrl-Space
PInvoke.keybd_event(Convert.ToByte(VK_LCONTROL), 0, KEYEVENTF_KEYDOWN, 0); PInvoke.keybd_event(Convert.ToByte(VK_RCONTROL), 0, KEYEVENTF_KEYDOWN, 0);
PInvoke.keybd_event(Convert.ToByte(VK_SPACE), 0, KEYEVENTF_KEYDOWN, 0); PInvoke.keybd_event(Convert.ToByte(VK_SPACE), 0, KEYEVENTF_KEYDOWN, 0);
Thread.Sleep(200); Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(VK_SPACE), 0, KEYEVENTF_KEYUP, 0); PInvoke.keybd_event(Convert.ToByte(VK_SPACE), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LCONTROL), 0, KEYEVENTF_KEYUP, 0); PInvoke.keybd_event(Convert.ToByte(VK_RCONTROL), 0, KEYEVENTF_KEYUP, 0);
Thread.Sleep(200); Thread.Sleep(200);
} }

View file

@ -45,12 +45,12 @@
<Separator Margin="5,10,5,5"/> <Separator Margin="5,10,5,5"/>
<Label HorizontalAlignment="Left" Margin="0,0,0,0" > <Label HorizontalAlignment="Left" Margin="0,0,0,0" >
<TextBlock TextWrapping="WrapWithOverflow"> <TextBlock TextWrapping="WrapWithOverflow">
2. Bind active aircraft livery to the selected profile to automatically activate profile and to automatically pop out panels when a flight session starts. 2. Bind active aircraft to the selected profile to automatically activate profile and automatically pop out panels when a flight session starts.
</TextBlock> </TextBlock>
</Label> </Label>
<WrapPanel Orientation="Vertical" Margin="15,0,0,0" HorizontalAlignment="Left"> <WrapPanel Orientation="Vertical" Margin="15,0,0,0" HorizontalAlignment="Left">
<WrapPanel Orientation="Horizontal" Margin="5,5,0,0" HorizontalAlignment="Left"> <WrapPanel Orientation="Horizontal" Margin="5,5,0,0" HorizontalAlignment="Left">
<Label Content="{c:Binding 'FlightSimData.CurrentMsfsPlaneTitle == null ? &quot;Active aircraft livery is unavailable&quot; : FlightSimData.CurrentMsfsPlaneTitle'}" HorizontalContentAlignment="Left" HorizontalAlignment="Left" FontStyle="Italic" Width="447"> <Label Content="{c:Binding 'FlightSimData.CurrentMsfsAircraft == null ? &quot;Active aircraft is unavailable&quot; : FlightSimData.CurrentMsfsAircraft'}" HorizontalContentAlignment="Left" HorizontalAlignment="Left" FontStyle="Italic" FontSize="16" Width="447">
<Label.Style> <Label.Style>
<Style TargetType="{x:Type Label}"> <Style TargetType="{x:Type Label}">
<Style.Triggers> <Style.Triggers>
@ -62,7 +62,7 @@
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{c:Binding '!ProfileData.IsAllowedAddAircraftBinding and !ProfileData.IsAllowedDeleteAircraftBinding'}" Value="True"> <DataTrigger Binding="{c:Binding '!ProfileData.IsAllowedAddAircraftBinding and !ProfileData.IsAllowedDeleteAircraftBinding'}" Value="True">
<Setter Property="Foreground" Value="Red" ></Setter> <Setter Property="Foreground" Value="Red" ></Setter>
<Setter Property="ToolTip" Value="Aircraft Livery is currently bound to another profile"></Setter> <Setter Property="ToolTip" Value="Aircraft is currently bound to another profile"></Setter>
</DataTrigger> </DataTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>

View file

@ -21,17 +21,17 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
ChangeProfileCommand = new DelegateCommand<object>(OnChangeProfile); ChangeProfileCommand = new DelegateCommand<object>(OnChangeProfile);
AddProfileBindingCommand = new DelegateCommand(OnAddProfileBinding, () => ProfileData.HasActiveProfile && FlightSimData.HasCurrentMsfsPlaneTitle && ProfileData.IsAllowedAddAircraftBinding && FlightSimData.IsSimulatorStarted) AddProfileBindingCommand = new DelegateCommand(OnAddProfileBinding, () => ProfileData.HasActiveProfile && FlightSimData.HasCurrentMsfsAircraft && ProfileData.IsAllowedAddAircraftBinding && FlightSimData.IsSimulatorStarted)
.ObservesProperty(() => ProfileData.ActiveProfile) .ObservesProperty(() => ProfileData.ActiveProfile)
.ObservesProperty(() => FlightSimData.HasCurrentMsfsPlaneTitle) .ObservesProperty(() => FlightSimData.HasCurrentMsfsAircraft)
.ObservesProperty(() => ProfileData.HasActiveProfile) .ObservesProperty(() => ProfileData.HasActiveProfile)
.ObservesProperty(() => ProfileData.IsAllowedAddAircraftBinding) .ObservesProperty(() => ProfileData.IsAllowedAddAircraftBinding)
.ObservesProperty(() => FlightSimData.IsSimulatorStarted); .ObservesProperty(() => FlightSimData.IsSimulatorStarted);
DeleteProfileBindingCommand = new DelegateCommand(OnDeleteProfileBinding, () => ProfileData.HasActiveProfile && ProfileData.IsAllowedDeleteAircraftBinding && ProfileData.ActiveProfile.BindingAircraftLiveries.Count > 0 && FlightSimData.IsSimulatorStarted) DeleteProfileBindingCommand = new DelegateCommand(OnDeleteProfileBinding, () => ProfileData.HasActiveProfile && ProfileData.IsAllowedDeleteAircraftBinding && ProfileData.ActiveProfile.BindingAircrafts.Count > 0 && FlightSimData.IsSimulatorStarted)
.ObservesProperty(() => ProfileData.HasActiveProfile) .ObservesProperty(() => ProfileData.HasActiveProfile)
.ObservesProperty(() => ProfileData.IsAllowedDeleteAircraftBinding) .ObservesProperty(() => ProfileData.IsAllowedDeleteAircraftBinding)
.ObservesProperty(() => ProfileData.ActiveProfile.BindingAircraftLiveries.Count) .ObservesProperty(() => ProfileData.ActiveProfile.BindingAircrafts.Count)
.ObservesProperty(() => FlightSimData.IsSimulatorStarted); .ObservesProperty(() => FlightSimData.IsSimulatorStarted);
SetPowerOnRequiredCommand = new DelegateCommand(() => ProfileData.WriteProfiles(), () => ProfileData.HasActiveProfile && FlightSimData.IsSimulatorStarted) SetPowerOnRequiredCommand = new DelegateCommand(() => ProfileData.WriteProfiles(), () => ProfileData.HasActiveProfile && FlightSimData.IsSimulatorStarted)
@ -124,12 +124,12 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
private void OnAddProfileBinding() private void OnAddProfileBinding()
{ {
_orchestrator.Profile.AddProfileBinding(FlightSimData.CurrentMsfsPlaneTitle); _orchestrator.Profile.AddProfileBinding(FlightSimData.CurrentMsfsAircraft);
} }
private void OnDeleteProfileBinding() private void OnDeleteProfileBinding()
{ {
_orchestrator.Profile.DeleteProfileBinding(FlightSimData.CurrentMsfsPlaneTitle); _orchestrator.Profile.DeleteProfileBinding(FlightSimData.CurrentMsfsAircraft);
} }
private void OnStartPanelSelection() private void OnStartPanelSelection()