FMSUtility
From X-Plane SDK
Revision as of 18:53, 13 December 2012 by Sbarbour (Talk | contribs) (Code updated for 64 bit compatibility)
- Download FMSUtility as project for X-Code 3.2 or newer, 32 and 64-bit Intel
- Download FMSUtility as project for Microsoft Visual Studio 2010 (32 and 64-bit)
- Download FMSUtility as makefile for GCC 4.x/Linux (32 and 64-bit)
/* FMSUtility Example Written by Sandy Barbour - 21/01/2005 This examples shows how to access the FMS */ #include "XPLMPlugin.h" #include "XPLMUtilities.h" #include "XPLMProcessing.h" #include "XPLMMenus.h" #include "XPLMGraphics.h" #include "XPLMPlanes.h" #include "XPLMDataAccess.h" #include "XPLMNavigation.h" #include "XPWidgets.h" #include "XPStandardWidgets.h" #include <string.h> #include <stdio.h> #include <stdlib.h> #if IBM #include <windows.h> #endif #define MAX_NAV_TYPES 13 #define MAX_FMS_ENTRIES 100 static int MenuItem1, NavTypeLinePosition; /// Widgets static XPWidgetID FMSUtilityWidget = NULL, FMSUtilityWindow1 = NULL, FMSUtilityWindow2 = NULL; static XPWidgetID GetFMSEntryButton, ClearEntryButton; static XPWidgetID GetEntryIndexButton, SetEntryIndexButton, GetDestinationEntryButton, SetDestinationEntryButton; static XPWidgetID EntryIndexEdit, DestinationEntryIndexEdit; static XPWidgetID GetNumberOfEntriesButton, GetNumberOfEntriesText; static XPWidgetID IndexCaption, IndexEdit, SegmentCaption, SegmentCaption2, AirportIDCaption, AirportIDEdit, AltitudeCaption, AltitudeEdit; static XPWidgetID NavTypeCaption, NavTypeEdit, NavTypeText, UpArrow, DownArrow, SetFMSEntryButton; static XPWidgetID LatCaption, LatEdit, LonCaption, LonEdit, SetLatLonButton; /// Structure for the nav types and a more meaningful description typedef struct _NAVTYPE { char Description[80]; XPLMNavType EnumValue; } NAVTYPE; static NAVTYPE NavTypeLookup[MAX_NAV_TYPES] = {{"Unknown", xplm_Nav_Unknown}, {"Airport", xplm_Nav_Airport}, {"NDB", xplm_Nav_NDB}, {"VOR", xplm_Nav_VOR}, {"ILS", xplm_Nav_ILS}, {"Localizer", xplm_Nav_Localizer}, {"Glide Slope", xplm_Nav_GlideSlope}, {"Outer Marker", xplm_Nav_OuterMarker}, {"Middle Marker", xplm_Nav_MiddleMarker}, {"Inner Marker", xplm_Nav_InnerMarker}, {"Fix", xplm_Nav_Fix}, {"DME", xplm_Nav_DME}, {"Lat/Lon", xplm_Nav_LatLon}}; /// Utility functions and callbacks /// This is used to get around a sprintf float bug with codewarrior on the mac inline float HACKFLOAT(float val) { return val; } /* #if IBM || LIN inline float HACKFLOAT(float val) { return val; } #else inline long long HACKFLOAT(float val) { double d = val; long long temp; temp = *((long long *) &d); return temp; } #endif */ static void FMSUtilityMenuHandler(void *, void *); static void CreateFMSUtilityWidget(int x1, int y1, int w, int h); static int GetCBIndex(int Type); static int FMSUtilityHandler( XPWidgetMessage inMessage, XPWidgetID inWidget, intptr_t inParam1, intptr_t inParam2); PLUGIN_API int XPluginStart( char * outName, char * outSig, char * outDesc) { XPLMMenuID id; int item; strcpy(outName, "FMS Utility"); strcpy(outSig, "xpsdk.experimental.FMSUtility"); strcpy(outDesc, "A plug-in that accesses the FMS."); // Create our menu item = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "FMSUtility", NULL, 1); id = XPLMCreateMenu("FMSUtility", XPLMFindPluginsMenu(), item, FMSUtilityMenuHandler, NULL); XPLMAppendMenuItem(id, "Utility Panel", (void *)"FMSUtility", 1); // Flag to tell us if the widget is being displayed. MenuItem1 = 0; NavTypeLinePosition = 0; return 1; } PLUGIN_API void XPluginStop(void) { if (MenuItem1 == 1) { XPDestroyWidget(FMSUtilityWidget, 1); MenuItem1 = 0; } } PLUGIN_API int XPluginEnable(void) { return 1; } PLUGIN_API void XPluginDisable(void) { } PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam) { } // This will create our widget from menu selection. // MenuItem1 flag stops it from being created more than once. void FMSUtilityMenuHandler(void * mRef, void * iRef) { // If menu selected create our widget dialog if (!strcmp((char *) iRef, "FMSUtility")) { if (MenuItem1 == 0) { CreateFMSUtilityWidget(221, 640, 420, 290); MenuItem1 = 1; } else if(!XPIsWidgetVisible(FMSUtilityWidget)) XPShowWidget(FMSUtilityWidget); } } // This will create our widget dialog. // I have made all child widgets relative to the input paramter. // This makes it easy to position the dialog void CreateFMSUtilityWidget(int x, int y, int w, int h) { int x2 = x + w; int y2 = y - h; char Buffer[255]; strcpy(Buffer, "FMS Example by Sandy Barbour - 2005"); // Create the Main Widget window FMSUtilityWidget = XPCreateWidget(x, y, x2, y2, 1, // Visible Buffer, // desc 1, // root NULL, // no container xpWidgetClass_MainWindow); // Add Close Box decorations to the Main Widget XPSetWidgetProperty(FMSUtilityWidget, xpProperty_MainWindowHasCloseBoxes, 1); // Create the Sub Widget1 window FMSUtilityWindow1 = XPCreateWidget(x+10, y-30, x+160, y2+10, 1, // Visible "", // desc 0, // root FMSUtilityWidget, xpWidgetClass_SubWindow); // Set the style to sub window XPSetWidgetProperty(FMSUtilityWindow1, xpProperty_SubWindowType, xpSubWindowStyle_SubWindow); // Create the Sub Widget2 window FMSUtilityWindow2 = XPCreateWidget(x+170, y-30, x2-10, y2+10, 1, // Visible "", // desc 0, // root FMSUtilityWidget, xpWidgetClass_SubWindow); // Set the style to sub window XPSetWidgetProperty(FMSUtilityWindow2, xpProperty_SubWindowType, xpSubWindowStyle_SubWindow); /// Entry Index GetEntryIndexButton = XPCreateWidget(x+20, y-40, x+110, y-62, 1, " Get Entry Index", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(GetEntryIndexButton, xpProperty_ButtonType, xpPushButton); EntryIndexEdit = XPCreateWidget(x+120, y-40, x+150, y-62, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(EntryIndexEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(EntryIndexEdit, xpProperty_Enabled, 1); SetEntryIndexButton = XPCreateWidget(x+20, y-70, x+110, y-92, 1, " Set Entry Index", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(SetEntryIndexButton, xpProperty_ButtonType, xpPushButton); /// Destination Index GetDestinationEntryButton = XPCreateWidget(x+20, y-100, x+110, y-122, 1, " Get Dest Index", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(GetDestinationEntryButton, xpProperty_ButtonType, xpPushButton); DestinationEntryIndexEdit = XPCreateWidget(x+120, y-100, x+150, y-122, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(DestinationEntryIndexEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(DestinationEntryIndexEdit, xpProperty_Enabled, 1); SetDestinationEntryButton = XPCreateWidget(x+20, y-130, x+110, y-152, 1, " Set Dest Index", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(SetDestinationEntryButton, xpProperty_ButtonType, xpPushButton); /// Number of Entries GetNumberOfEntriesButton = XPCreateWidget(x+20, y-160, x+110, y-182, 1, " Get No. Entries", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(GetNumberOfEntriesButton, xpProperty_ButtonType, xpPushButton); GetNumberOfEntriesText = XPCreateWidget(x+120, y-160, x+150, y-182, 1, "", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(GetNumberOfEntriesText, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(GetNumberOfEntriesText, xpProperty_Enabled, 0); /// Clear Entry ClearEntryButton = XPCreateWidget(x+20, y-190, x+110, y-212, 1, " Clear Entry", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(ClearEntryButton, xpProperty_ButtonType, xpPushButton); /// Index (Segment - 1) IndexCaption = XPCreateWidget(x+180, y-40, x+230, y-62, 1, "Index", 0, FMSUtilityWidget, xpWidgetClass_Caption); IndexEdit = XPCreateWidget(x+240, y-40, x+290, y-62, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(IndexEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(IndexEdit, xpProperty_Enabled, 1); SegmentCaption = XPCreateWidget(x+300, y-40, x+350, y-62, 1, "Segment", 0, FMSUtilityWidget, xpWidgetClass_Caption); SegmentCaption2 = XPCreateWidget(x+360, y-40, x+410, y-62, 1, "1", 0, FMSUtilityWidget, xpWidgetClass_Caption); /// Airport ID AirportIDCaption = XPCreateWidget(x+180, y-70, x+230, y-92, 1, "Airport ID", 0, FMSUtilityWidget, xpWidgetClass_Caption); AirportIDEdit = XPCreateWidget(x+240, y-70, x+290, y-92, 1, "----", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(AirportIDEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(AirportIDEdit, xpProperty_Enabled, 1); /// Altitude AltitudeCaption = XPCreateWidget(x+180, y-100, x+230, y-122, 1, "Altitude", 0, FMSUtilityWidget, xpWidgetClass_Caption); AltitudeEdit = XPCreateWidget(x+240, y-100, x+290, y-122, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(AltitudeEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(AltitudeEdit, xpProperty_Enabled, 1); /// Nav Type NavTypeCaption = XPCreateWidget(x+180, y-130, x+230, y-152, 1, "Nav Type", 0, FMSUtilityWidget, xpWidgetClass_Caption); sprintf(Buffer, "%s", NavTypeLookup[0].Description); NavTypeEdit = XPCreateWidget(x+240, y-130, x+340, y-152, 1, Buffer, 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(NavTypeEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(NavTypeEdit, xpProperty_Enabled, 0); // Used for selecting Nav Type UpArrow = XPCreateWidget(x+340, y-130, x+362, y-141, 1, "", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(UpArrow, xpProperty_ButtonType, xpLittleUpArrow); // Used for selecting Nav Type DownArrow = XPCreateWidget(x+340, y-141, x+362, y-152, 1, "", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(DownArrow, xpProperty_ButtonType, xpLittleDownArrow); NavTypeText = XPCreateWidget(x+362, y-130, x+400, y-152, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(NavTypeText, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(NavTypeText, xpProperty_Enabled, 0); /// Get FMS Entry Info GetFMSEntryButton = XPCreateWidget(x+180, y-160, x+270, y-182, 1, " Get FMS Entry", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(GetFMSEntryButton, xpProperty_ButtonType, xpPushButton); /// Set FMS Entry Info SetFMSEntryButton = XPCreateWidget(x+280, y-160, x+370, y-182, 1, " Set FMS Entry", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(SetFMSEntryButton, xpProperty_ButtonType, xpPushButton); /// Lat / Lon LatCaption = XPCreateWidget(x+180, y-190, x+230, y-212, 1, "Latitude", 0, FMSUtilityWidget, xpWidgetClass_Caption); LatEdit = XPCreateWidget(x+240, y-190, x+310, y-212, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(LatEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(LatEdit, xpProperty_Enabled, 1); LonCaption = XPCreateWidget(x+180, y-220, x+230, y-242, 1, "Longitude", 0, FMSUtilityWidget, xpWidgetClass_Caption); LonEdit = XPCreateWidget(x+240, y-220, x+310, y-242, 1, "0", 0, FMSUtilityWidget, xpWidgetClass_TextField); XPSetWidgetProperty(LonEdit, xpProperty_TextFieldType, xpTextEntryField); XPSetWidgetProperty(LonEdit, xpProperty_Enabled, 1); SetLatLonButton = XPCreateWidget(x+180, y-250, x+270, y-272, 1, " Set Lat/Lon", 0, FMSUtilityWidget, xpWidgetClass_Button); XPSetWidgetProperty(SetLatLonButton, xpProperty_ButtonType, xpPushButton); // Register our widget handler XPAddWidgetCallback(FMSUtilityWidget, FMSUtilityHandler); } // This is the handler for our widget // It can be used to process button presses etc. // In this example we are only interested when the close box is pressed int FMSUtilityHandler( XPWidgetMessage inMessage, XPWidgetID inWidget, intptr_t inParam1, intptr_t inParam2) { void *Param; Param = 0; char Buffer[255]; // Close button will get rid of our main widget // All child widgets will get the bullet as well if (inMessage == xpMessage_CloseButtonPushed) { if (MenuItem1 == 1) { XPHideWidget(FMSUtilityWidget); } return 1; } // Handle any button pushes if (inMessage == xpMsg_PushButtonPressed) { /// Most of these handlers get a value. /// It then has to be converted to a string using sprintf. /// This is because "XPSetWidgetDescriptor" expects a string as its second parameter. if (inParam1 == (intptr_t)ClearEntryButton) { XPLMClearFMSEntry(XPLMGetDisplayedFMSEntry()); return 1; } if (inParam1 == (intptr_t)GetEntryIndexButton) { int Index = XPLMGetDisplayedFMSEntry(); sprintf(Buffer, "%d", Index); XPSetWidgetDescriptor(EntryIndexEdit, Buffer); return 1; } if (inParam1 == (intptr_t)SetEntryIndexButton) { XPGetWidgetDescriptor(EntryIndexEdit, Buffer, sizeof(Buffer)); int Index = atoi(Buffer); XPLMSetDisplayedFMSEntry(Index); return 1; } if (inParam1 == (intptr_t)GetDestinationEntryButton) { int Index = XPLMGetDestinationFMSEntry(); sprintf(Buffer, "%d", Index); XPSetWidgetDescriptor(DestinationEntryIndexEdit, Buffer); return 1; } if (inParam1 == (intptr_t)SetDestinationEntryButton) { XPGetWidgetDescriptor(DestinationEntryIndexEdit, Buffer, sizeof(Buffer)); int Index = atoi(Buffer); XPLMSetDestinationFMSEntry(Index); return 1; } if (inParam1 == (intptr_t)GetNumberOfEntriesButton) { int Count = XPLMCountFMSEntries(); sprintf(Buffer, "%d", Count); XPSetWidgetDescriptor(GetNumberOfEntriesText, Buffer); return 1; } if (inParam1 == (intptr_t)GetFMSEntryButton) { int Index = XPLMGetDisplayedFMSEntry(); XPLMNavType outType; char outID[80]; XPLMNavRef outRef; int outAltitude; float outLat; float outLon; XPLMGetFMSEntryInfo(Index, &outType, outID, &outRef, &outAltitude, &outLat, &outLon); sprintf(Buffer, "%d", Index); XPSetWidgetDescriptor(IndexEdit, Buffer); sprintf(Buffer, "%d", Index+1); XPSetWidgetDescriptor(SegmentCaption2, Buffer); if (outType == xplm_Nav_LatLon) XPSetWidgetDescriptor(AirportIDEdit, "----"); else XPSetWidgetDescriptor(AirportIDEdit, outID); sprintf(Buffer, "%d", outAltitude); XPSetWidgetDescriptor(AltitudeEdit, Buffer); XPSetWidgetDescriptor(NavTypeEdit, NavTypeLookup[GetCBIndex(outType)].Description); sprintf(Buffer, "%d", NavTypeLookup[GetCBIndex(outType)].EnumValue); XPSetWidgetDescriptor(NavTypeText, Buffer); sprintf(Buffer, "%+05.2f", HACKFLOAT(outLat)); XPSetWidgetDescriptor(LatEdit, Buffer); sprintf(Buffer, "%+05.2f", HACKFLOAT(outLon)); XPSetWidgetDescriptor(LonEdit, Buffer); return 1; } if (inParam1 == (intptr_t)SetFMSEntryButton) { XPGetWidgetDescriptor(IndexEdit, Buffer, sizeof(Buffer)); int Index = atoi(Buffer); sprintf(Buffer, "%d", Index+1); XPSetWidgetDescriptor(SegmentCaption2, Buffer); XPGetWidgetDescriptor(AltitudeEdit, Buffer, sizeof(Buffer)); int Altitude = atoi(Buffer); XPGetWidgetDescriptor(NavTypeText, Buffer, sizeof(Buffer)); int NavType = atoi(Buffer); XPGetWidgetDescriptor(AirportIDEdit, Buffer, sizeof(Buffer)); XPLMSetFMSEntryInfo(Index, XPLMFindNavAid(NULL, Buffer, NULL, NULL, NULL, NavType), Altitude); return 1; } if (inParam1 == (intptr_t)SetLatLonButton) { XPGetWidgetDescriptor(IndexEdit, Buffer, sizeof(Buffer)); int Index = atoi(Buffer); sprintf(Buffer, "%d", Index+1); XPSetWidgetDescriptor(SegmentCaption2, Buffer); XPGetWidgetDescriptor(AltitudeEdit, Buffer, sizeof(Buffer)); int Altitude = atoi(Buffer); XPGetWidgetDescriptor(LatEdit, Buffer, sizeof(Buffer)); float Lat = atof(Buffer); XPGetWidgetDescriptor(LonEdit, Buffer, sizeof(Buffer)); float Lon = atof(Buffer); XPLMSetFMSEntryLatLon(Index, Lat, Lon, Altitude); return 1; } // Up Arrow is used to modify the NavTypeLookup Array Index if (inParam1 == (intptr_t)UpArrow) { NavTypeLinePosition--; if (NavTypeLinePosition < 0) NavTypeLinePosition = MAX_NAV_TYPES-1; XPSetWidgetDescriptor(NavTypeEdit, NavTypeLookup[NavTypeLinePosition].Description); sprintf(Buffer, "%d", NavTypeLookup[NavTypeLinePosition].EnumValue); XPSetWidgetDescriptor(NavTypeText, Buffer); return 1; } // Down Arrow is used to modify the NavTypeLookup Array Index if (inParam1 == (intptr_t)DownArrow) { NavTypeLinePosition++; if (NavTypeLinePosition > MAX_NAV_TYPES-1) NavTypeLinePosition = 0; XPSetWidgetDescriptor(NavTypeEdit, NavTypeLookup[NavTypeLinePosition].Description); sprintf(Buffer, "%d", NavTypeLookup[NavTypeLinePosition].EnumValue); XPSetWidgetDescriptor(NavTypeText, Buffer); return 1; } } return 0; } /// This function takes an XPLMNavType and /// returns the index into the NavTypeLookup array. /// We can then use that index to access the description or enum. int GetCBIndex(int Type) { int CBIndex = 0; for (int Index=0; Index<MAX_NAV_TYPES; Index++) { if (NavTypeLookup[Index].EnumValue == Type) { CBIndex = Index; break; } } return CBIndex; }