/*
* Camera.c
*
* This plugin registers a new view with the sim that orbits the aircraft. We do this by:
*
* 1. Registering a hotkey to engage the view.
* 2. Setting the view to external when we are engaged.
* 3. Registering a new camera control funcioin that ends when a new view is picked.
*
*/
#include <string.h>
#include "XPLMDisplay.h"
#include "XPLMUtilities.h"
#include "XPLMCamera.h"
#include "XPLMDataAccess.h"
#include "XPLMDisplay.h"
#include <stdio.h>
#include <math.h>
static XPLMHotKeyID gHotKey = NULL;
static XPLMDataRef gPlaneX = NULL;
static XPLMDataRef gPlaneY = NULL;
static XPLMDataRef gPlaneZ = NULL;
static void MyHotKeyCallback(void * inRefcon);
static int MyOrbitPlaneFunc(
XPLMCameraPosition_t * outCameraPosition,
int inIsLosingControl,
void * inRefcon);
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "Camera");
strcpy(outSig, "xplanesdk.examples.camera");
strcpy(outDesc, "A plugin that adds a camera view.");
/* Prefetch the sim variables we will use. */
gPlaneX = XPLMFindDataRef("sim/flightmodel/position/local_x");
gPlaneY = XPLMFindDataRef("sim/flightmodel/position/local_y");
gPlaneZ = XPLMFindDataRef("sim/flightmodel/position/local_z");
/* Register our hot key for the new view. */
gHotKey = XPLMRegisterHotKey(XPLM_VK_F8, xplm_DownFlag,
"Circling External View",
MyHotKeyCallback,
NULL);
return 1;
}
PLUGIN_API void XPluginStop(void)
{
XPLMUnregisterHotKey(gHotKey);
}
PLUGIN_API void XPluginDisable(void)
{
}
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
PLUGIN_API void XPluginReceiveMessage(
XPLMPluginID inFromWho,
int inMessage,
void * inParam)
{
}
void MyHotKeyCallback(void * inRefcon)
{
/* This is the hotkey callback. First we simulate a joystick press and
* release to put us in 'free view 1'. This guarantees that no panels
* are showing and we are an external view. */
XPLMCommandButtonPress(xplm_joy_v_fr1);
XPLMCommandButtonRelease(xplm_joy_v_fr1);
/* Now we control the camera until the view changes. */
XPLMControlCamera(xplm_ControlCameraUntilViewChanges, MyOrbitPlaneFunc, NULL);
}
/*
* MyOrbitPlaneFunc
*
* This is the actual camera control function, the real worker of the plugin. It is
* called each time X-Plane needs to draw a frame.
*
*/
int MyOrbitPlaneFunc(
XPLMCameraPosition_t * outCameraPosition,
int inIsLosingControl,
void * inRefcon)
{
if (outCameraPosition && !inIsLosingControl)
{
int w, h, x, y;
float dx, dz, dy, heading, pitch;
char buf[256];
/* First get the screen size and mouse location. We will use this to decide
* what part of the orbit we are in. The mouse will move us up-down and around. */
XPLMGetScreenSize(&w, &h);
XPLMGetMouseLocation(&x, &y);
heading = 360.0 * (float) x / (float) w;
pitch = 20.0 * (((float) y / (float) h) * 2.0 - 1.0);
/* Now calculate where the camera should be positioned to be 200
* meters from the plane and pointing at the plane at the pitch and
* heading we wanted above. */
dx = -200.0 * sin(heading * 3.1415 / 180.0);
dz = 200.0 * cos(heading * 3.1415 / 180.0);
dy = -200 * tan(pitch * 3.1415 / 180.0);
/* Fill out the camera position info. */
outCameraPosition->x = XPLMGetDataf(gPlaneX) + dx;
outCameraPosition->y = XPLMGetDataf(gPlaneY) + dy;
outCameraPosition->z = XPLMGetDataf(gPlaneZ) + dz;
outCameraPosition->pitch = pitch;
outCameraPosition->heading = heading;
outCameraPosition->roll = 0;
}
/* Return 1 to indicate we want to keep controlling the camera. */
return 1;
}
A discussion of custom beacons and strobes for authors can be found here.
/*
/*
Beacon and strobe example plugin.
This plugin overrides X-Plane's default flash patterns for the beacons and strobes. It provides a multi-part pulse for the strobes,
and sets the beacons to run at different rates.
*/
#include "XPLMDataAccess.h"
#include "XPLMProcessing.h"
#include "XPLMUtilities.h"
#include <string.h>
#include <math.h>
// The time stamp that the strobes last fired.
float strobe1_t = 0.0, strobe2_t = 0.0;
/* This is the period of the entire strobe sequence. */
#define STROBE_TIME 1.0
/* This is the time between the first and second strobe firing. */
#define STROBE_OFFSET 0.2
static XPLMDataRef override_beacons_and_strobes = NULL;
// These tell us if the strobes and beacons are really on. They take into consideration both the switch positions and electrical failures.
static XPLMDataRef beacon_lights_on = NULL;
static XPLMDataRef strobe_lights_on = NULL;
// When we are overriding beacons and strobes, we are responsible for writing each of these per frame.
// These are four-item arrays, so we can make multiple strobe flash patterns and separately running beacons.
static XPLMDataRef beacon_brightness_ratio = NULL;
static XPLMDataRef strobe_brightness_ratio = NULL;
// Set this to 1 if ANY strobe is on - this is what makes the clouds light up, etc.
static XPLMDataRef strobe_flash_now = NULL;
// Deferred init. Plugins should wait until the sim is really running to do final
// initialization. See http://www.xsquawkbox.net/xpsdk/mediawiki/DeferredInitialization
// for more info.
static float deferred_init(
float inElapsedSinceLastCall,
float inElapsedTimeSinceLastFlightLoop,
int inCounter,
void * inRefcon)
{
XPLMSetDatai(override_beacons_and_strobes,1);
strobe1_t = XPLMGetElapsedTime();
strobe2_t = strobe1_t + STROBE_OFFSET;
return 0;
}
// This is our main per-frame lighting function. This is where we do the work X-plane would normally
// do to calculate what the beacons and strobes are doing.
static float lights_per_frame(
float inElapsedSinceLastCall,
float inElapsedTimeSinceLastFlightLoop,
int inCounter,
void * inRefcon)
{
float now = XPLMGetElapsedTime();
float beacons[4] = { 0 };
float flash[4] = { 0 };
int any_flash = 0;
int strobes_on = XPLMGetDatai(strobe_lights_on);
if(beacon_lights_on == NULL || strobe_lights_on == NULL || beacon_brightness_ratio == NULL)
{
XPLMDebugString("We are missing our datarefs.\n");
return 0.0f;
}
// Beacon lighting calculation. If the beacons are on, use sine and cosine for the two
// beacons...and use a slightly different scale so they run at different spededs.
if(XPLMGetDatai(beacon_lights_on))
{
beacons[0] = sin(now * 1.5);
beacons[1] = cos(now);
}
XPLMSetDatavf(beacon_brightness_ratio,beacons,0,4);
// Strobes. Each time we are past our "strobe time", flash for one frame, then go out again.
// Note that this is a TERRIBLE strobing algorithm: at high fps the strobes are on for TINY amounts of time.
// In your strobing algorithm, make sure the strobes are on for the longer of one frame or a certain minimum time.
// Some users do run at 80+ fps!
if ((now - strobe1_t) > STROBE_TIME)
{
flash[0] = strobes_on;
any_flash |= strobes_on;
strobe1_t += STROBE_TIME;
}
if ((now - strobe2_t) > STROBE_TIME)
{
flash[1] = strobes_on;
any_flash |= strobes_on;
strobe2_t += STROBE_TIME;
}
XPLMSetDatavf(strobe_brightness_ratio,flash,0,4);
XPLMSetDatai(strobe_flash_now, any_flash);
return -1.0;
}
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "Custom Beacons/Strobes Example");
strcpy(outSig, "xplanesdk.examples.custom_beacons_strobes");
strcpy(outDesc, "A plugin that demonstrates custom beacon/strobe patterns.");
override_beacons_and_strobes = XPLMFindDataRef("sim/flightmodel2/lights/override_beacons_and_strobes");
if(override_beacons_and_strobes == NULL)
{
XPLMDebugString("Beacon and strobe plugin disabled - this version of x-plane doesn't support the feature.\n");
return 0;
}
beacon_lights_on = XPLMFindDataRef("sim/cockpit/electrical/beacon_lights_on");
strobe_lights_on = XPLMFindDataRef("sim/cockpit/electrical/strobe_lights_on");
beacon_brightness_ratio = XPLMFindDataRef("sim/flightmodel2/lights/beacon_brightness_ratio");
strobe_brightness_ratio = XPLMFindDataRef("sim/flightmodel2/lights/strobe_brightness_ratio");
strobe_flash_now = XPLMFindDataRef("sim/flightmodel2/lights/strobe_flash_now");
XPLMRegisterFlightLoopCallback(deferred_init, -1.0, NULL);
XPLMRegisterFlightLoopCallback(lights_per_frame, -2.0, NULL);
return 1;
}
PLUGIN_API void XPluginStop(void)
{
XPLMUnregisterFlightLoopCallback(deferred_init,NULL);
XPLMUnregisterFlightLoopCallback(lights_per_frame,NULL);
XPLMSetDatai(override_beacons_and_strobes,0);
}
PLUGIN_API void XPluginDisable(void)
{
}
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
PLUGIN_API void XPluginReceiveMessage(
XPLMPluginID inFromWho,
int inMessage,
void * inParam)
{
}
/*
SDK210Tests Example
Tests the new SDK 2.10 functions.
Version 1.0.0.1 Intitial Sandy Barbour 25/01/2012
NOTES
1.
This example will only work with the new plugin SDK 2.10 and will only run in X-Plane V10.
2.
The 2.10 plugin SDK now has 64 bit safe variables.
Unfortunately early Micrsoft Visual Studio products do not have the required header files to support this.
I know that VS6 does not and I believe that 2003 does not either.
VS2008 onwards is fine and that is what I tested this example with on windows.
So, any VS6 users will need to try and located a header that will allow the example to compile.
This is a MS problem and not an SDK problem.
I did find this header that worked.
http://www.azillionmonkeys.com/qed/pstdint.h
But we will not be supporting it or any other headers usage in this example.
*/
//---------------------------------------------------------------------------
#include "XPLMPlugin.h"
#include "XPLMDisplay.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMMenus.h"
#include "XPLMUtilities.h"
#include "XPWidgets.h"
#include "XPStandardWidgets.h"
#include "XPLMScenery.h"
#include "XPLMPlanes.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#if IBM
#include <windows.h>
#include <stdio.h>
#endif
#if LIN
#include <GL/gl.h>
#else
#if __GNUC__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#endif
//---------------------------------------------------------------------------
enum
{
/*0*/ MAIN_FLCB = 0,
/*1*/ TEMP_FLCB,
/*2*/ INFO,
/*3*/ MENU_2,
/*4*/ DRAWING
};
enum
{
/*0*/ USER_AIRCRAFT = 0,
/*1*/ AI_AIRCRAFT
};
char SDK210TestsVersionNumber[] = "v1.00";
char SDK210Tests_Buffer[256];
XPLMFlightLoopID SDK210Tests_XPLMTempFlightLoopID = NULL;
XPLMObjectRef SDK210Tests_Windsock=NULL;
XPLMProbeRef SDK210Tests_Windsock_Probe=NULL;
// Number of edit boxes in widget
#define SDK210TESTS_MAX_ITEMS 5
// Description text for widget edit boxes
char SDK210TestsDataDesc[SDK210TESTS_MAX_ITEMS][255] = {"Main FLCB", "Temp FLCB", "Info", "Menu 2", "Drawing"};
// Used as interlock for widget
int SDK210TestsMenuItem1;
// Used by menus
XPLMMenuID SDK210TestsMenuId = NULL, SDK210TestsMenuId2 = NULL;
int SDK210TestsMenuIndex1 = 0, SDK210TestsMenuIndex2 = 0, SDK210TestsMenuIndex3 = 0;
int SDK210TestsMenuItem = 0, SDK210TestsMenuItem2 = 0;
int SDK210TestsCreateFLCB = 0;
int SDK210TestsDestroyFLCB = 0;
// Datarefs
XPLMDataRef SDK210Tests_refx = NULL;
XPLMDataRef SDK210Tests_refy = NULL;
XPLMDataRef SDK210Tests_refz = NULL;
XPLMDataRef SDK210Tests_wrl_type = NULL;
// Widgets
XPWidgetID SDK210TestsWidget = NULL, SDK210TestsWindow = NULL;
XPWidgetID SDK210TestsButton1 = NULL, SDK210TestsButton2 = NULL, SDK210TestsButton3 = NULL, SDK210TestsButton4 = NULL;
XPWidgetID SDK210TestsButton5 = NULL, SDK210TestsButton6 = NULL, SDK210TestsButton7 = NULL, SDK210TestsButton8 = NULL;
XPWidgetID SDK210TestsText[SDK210TESTS_MAX_ITEMS] = {NULL};
XPWidgetID SDK210TestsEdit[SDK210TESTS_MAX_ITEMS] = {NULL};
// Used by the Draw Objects test
XPLMObjectRef SDK210TestsObject=NULL;
int SDK210TestsDrawingEnabled = 0;
// Used by the FLCB test
int SDK210TestsMainLoopCBCounter = 0;
int SDK210TestsTempLoopCBCounter = 0;
char *pSDK210TestsAircraft[2];
char SDK210TestsAircraftPath[2][512];
//---------------------------------------------------------------------------
// Displays data in widget
float SDK210TestsMainLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon);;
float SDK210TestsTempLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon);;
// Callback for Error Tests
void SDK210TestsErrorCB(const char * msg)
{
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: SDK210TestsErrorCB - error CB called: ");
XPLMDebugString(msg);
XPLMDebugString("\n");
XPLMDebugString("----------------------------------------------------------------\n");
}
// Menu Prototypes
void SDK210TestsMenuHandler(void *, void *);
void SDK210TestsMenuHandler2(void *, void *);
// Widget prototypes
void CreateSDK210Tests(int x1, int y1, int w, int h);
int SDK210TestsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2);
// Prototype for Draw Object tests
int SDK210TestsDrawWindsock(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon);
void SDK210TestsNativePaths(void);
void SDK210TestsAcquireAircraft(void);
void SDK210TestsLoadAircraft(int Mode);
//---------------------------------------------------------------------------
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "SDK210Tests");
strcpy(outSig, "sandybarbour.projects.SDK210Tests");
strcpy(outDesc, "A plug-in to test the new SDK210 API's.");
// Register the callback for errors
XPLMSetErrorCallback(SDK210TestsErrorCB);
// Datarefs to get the aicraft position
SDK210Tests_refx = XPLMFindDataRef("sim/flightmodel/position/local_x");
SDK210Tests_refy = XPLMFindDataRef("sim/flightmodel/position/local_y");
SDK210Tests_refz = XPLMFindDataRef("sim/flightmodel/position/local_z");
SDK210Tests_wrl_type = XPLMFindDataRef("sim/graphics/view/world_render_type");
// Create the menus
SDK210TestsMenuItem = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "SDK210Tests", NULL, 1);
SDK210TestsMenuId = XPLMCreateMenu("SDK210Tests", XPLMFindPluginsMenu(), SDK210TestsMenuItem, SDK210TestsMenuHandler, NULL);
SDK210TestsMenuItem2 = XPLMAppendMenuItem(SDK210TestsMenuId, "SDK210Tests", (void *)"SDK210Tests", 1);
SDK210TestsMenuItem1 = 0;
XPLMRegisterFlightLoopCallback(SDK210TestsMainLoopCB, 1.0, NULL);
// This used for the Draw Objects tests
XPLMRegisterDrawCallback( SDK210TestsDrawWindsock, xplm_Phase_Objects, 0, 0 );
return 1;
}
PLUGIN_API void XPluginStop(void)
{
// Clean up
if(SDK210Tests_Windsock) XPLMUnloadObject(SDK210Tests_Windsock);
if(SDK210Tests_Windsock_Probe) XPLMDestroyProbe(SDK210Tests_Windsock_Probe);
XPLMDestroyMenu(SDK210TestsMenuId);
XPLMUnregisterDrawCallback(SDK210TestsDrawWindsock, xplm_Phase_Objects, 0, 0);
XPLMUnregisterFlightLoopCallback(SDK210TestsMainLoopCB, NULL);
}
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
PLUGIN_API void XPluginDisable(void)
{
}
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam)
{
switch(inMsg)
{
case XPLM_MSG_WILL_WRITE_PREFS:
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: XPluginReceiveMessage - Will write prefs.\n");
XPLMDebugString("----------------------------------------------------------------\n");
break;
case XPLM_MSG_LIVERY_LOADED:
XPLMDebugString("================================================================\n");
sprintf(SDK210Tests_Buffer,"SDK210Tests: XPluginReceiveMessage - Livery loaded for plane %d.\n", inParam);
XPLMDebugString(SDK210Tests_Buffer);
XPLMDebugString("----------------------------------------------------------------\n");
break;
}
}
//---------------------------------------------------------------------------
// Used to test the creation and destruction of a Flightloop Callback from within a Flightloop Callback.
float SDK210TestsMainLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon)
{
SDK210TestsMainLoopCBCounter++;
if (SDK210TestsMainLoopCBCounter>100)
SDK210TestsMainLoopCBCounter=0;
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Main FLCB Counter = %d\n", SDK210TestsMainLoopCBCounter);
XPSetWidgetDescriptor(SDK210TestsEdit[MAIN_FLCB], SDK210Tests_Buffer);
}
if (SDK210TestsCreateFLCB)
{
XPLMCreateFlightLoop_t SDK210Tests_XPLMCreateFlightLoop_t_ptr = { sizeof(XPLMCreateFlightLoop_t), xplm_FlightLoop_Phase_AfterFlightModel, SDK210TestsTempLoopCB, NULL };
SDK210Tests_XPLMTempFlightLoopID = XPLMCreateFlightLoop(&SDK210Tests_XPLMCreateFlightLoop_t_ptr);
SDK210TestsCreateFLCB = 0;
}
if (SDK210TestsDestroyFLCB)
{
XPLMDestroyFlightLoop(SDK210Tests_XPLMTempFlightLoopID);
SDK210TestsDestroyFLCB = 0;
XPSetWidgetDescriptor(SDK210TestsEdit[TEMP_FLCB], "");
}
return 1.0;
}
// Temporary Flightloop Callback
float SDK210TestsTempLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon)
{
SDK210TestsTempLoopCBCounter++;
if (SDK210TestsTempLoopCBCounter>100)
SDK210TestsTempLoopCBCounter=0;
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Temp FLCB Counter = %d\n", SDK210TestsTempLoopCBCounter);
XPSetWidgetDescriptor(SDK210TestsEdit[TEMP_FLCB], SDK210Tests_Buffer);
}
return 1.0;
}
//---------------------------------------------------------------------------
// Process Menu 1 selections
void SDK210TestsMenuHandler(void * mRef, void * iRef)
{
// Menu selected for widget
if (!strcmp((char *) iRef, "SDK210Tests"))
{
if (SDK210TestsMenuItem1 == 0)
{
CreateSDK210Tests(100, 550, 650, 330);
SDK210TestsMenuItem1 = 1;
}
}
}
// Process Menu 2 selections
void SDK210TestsMenuHandler2(void * mRef, void * iRef)
{
// Menu Index 1 Selected
if (!strcmp((char *) iRef, "1"))
{
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Menu 2 : Item 1 : mRef = %x, iRef = %x\n", mRef, iRef);
XPSetWidgetDescriptor(SDK210TestsEdit[MENU_2], SDK210Tests_Buffer);
}
}
// Menu Index 2 Selected
if (!strcmp((char *) iRef, "2"))
{
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Menu 2 : Item 2 : mRef = %x, iRef = %x\n", mRef, iRef);
XPSetWidgetDescriptor(SDK210TestsEdit[MENU_2], SDK210Tests_Buffer);
}
}
// Menu Index 3 Selected
if (!strcmp((char *) iRef, "3"))
{
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Menu 2 : Item 3 : mRef = %x, iRef = %x\n", mRef, iRef);
XPSetWidgetDescriptor(SDK210TestsEdit[MENU_2], SDK210Tests_Buffer);
}
}
}
//---------------------------------------------------------------------------
// Creates the widget with buttons for test and edit boxes for info
void CreateSDK210Tests(int x, int y, int w, int h)
{
int Item;
int x2 = x + w;
int y2 = y - h;
char Buffer[255];
sprintf(Buffer, "%s %s %s", "SDK210Tests", SDK210TestsVersionNumber, "- Sandy Barbour 2012");
SDK210TestsWidget = XPCreateWidget(x, y, x2, y2,
1, // Visible
Buffer, // desc
1, // root
NULL, // no container
xpWidgetClass_MainWindow);
XPSetWidgetProperty(SDK210TestsWidget, xpProperty_MainWindowHasCloseBoxes, 1);
SDK210TestsWindow = XPCreateWidget(x+50, y-50, x2-50, y2+50,
1, // Visible
"", // desc
0, // root
SDK210TestsWidget,
xpWidgetClass_SubWindow);
XPSetWidgetProperty(SDK210TestsWindow, xpProperty_SubWindowType, xpSubWindowStyle_SubWindow);
SDK210TestsButton1 = XPCreateWidget(x+60, y-60, x+180, y-82,
1, " Create Temp FLCB", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton1, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton2 = XPCreateWidget(x+190, y-60, x+330, y-82,
1, " Schedule Temp FLCB", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton2, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton3 = XPCreateWidget(x+340, y-60, x+470, y-82,
1, " Destroy Temp FLCB", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton3, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton4 = XPCreateWidget(x+480, y-60, x+580, y-82,
1, " Native Paths", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton4, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton5 = XPCreateWidget(x+60, y-90, x+180, y-112,
1, " Append Menu Item", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton5, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton6 = XPCreateWidget(x+190, y-90, x+330, y-112,
1, " Remove Menu Item", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton6, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton7 = XPCreateWidget(x+340, y-90, x+470, y-112,
1, " Drawing Enable", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton7, xpProperty_ButtonType, xpPushButton);
SDK210TestsButton8 = XPCreateWidget(x+480, y-90, x+580, y-112,
1, " Drawing Disable", 0, SDK210TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK210TestsButton8, xpProperty_ButtonType, xpPushButton);
for (Item=0; Item<SDK210TESTS_MAX_ITEMS; Item++)
{
SDK210TestsText[Item] = XPCreateWidget(x+60, y-(120 + (Item*30)), x+160, y-(142 + (Item*30)),
1, // Visible
SDK210TestsDataDesc[Item],// desc
0, // root
SDK210TestsWidget,
xpWidgetClass_Caption);
SDK210TestsEdit[Item] = XPCreateWidget(x+170, y-(120 + (Item*30)), x+570, y-(142 + (Item*30)),
1, "", 0, SDK210TestsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(SDK210TestsEdit[Item], xpProperty_TextFieldType, xpTextEntryField);
}
XPAddWidgetCallback(SDK210TestsWidget, SDK210TestsHandler);
XPSetWidgetProperty(SDK210TestsButton1, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton2, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton3, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton5, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton6, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton7, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton8, xpProperty_Enabled, 0);
}
//Handle the widget messages
int SDK210TestsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2)
{
// When widget close cross is clicked we only hide the widget
if (inMessage == xpMessage_CloseButtonPushed)
{
if (SDK210TestsMenuItem1 == 1)
{
XPDestroyWidget(SDK210TestsWidget, 1);
SDK210TestsMenuItem1 = 0;
}
return 1;
}
// Process when a button on the widget is pressed
if (inMessage == xpMsg_PushButtonPressed)
{
if (inParam1 == (intptr_t)SDK210TestsButton1)
{
SDK210TestsTempLoopCBCounter = 0;
SDK210TestsCreateFLCB = 1;
SDK210TestsDestroyFLCB = 0;
XPSetWidgetProperty(SDK210TestsButton1, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton2, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton3, xpProperty_Enabled, 1);
XPSetWidgetDescriptor(SDK210TestsEdit[INFO], "Click on [Schedule Temp FLCB]");
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton2)
{
XPLMScheduleFlightLoop(SDK210Tests_XPLMTempFlightLoopID, 1.0, true);
XPSetWidgetProperty(SDK210TestsButton2, xpProperty_Enabled, 0);
XPSetWidgetDescriptor(SDK210TestsEdit[INFO], "");
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton3)
{
SDK210TestsDestroyFLCB = 1;
SDK210TestsCreateFLCB = 0;
XPSetWidgetProperty(SDK210TestsButton3, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton2, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton1, xpProperty_Enabled, 1);
XPSetWidgetDescriptor(SDK210TestsEdit[TEMP_FLCB], "");
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton4)
{
XPSetWidgetProperty(SDK210TestsButton4, xpProperty_Enabled, 0);
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: SDK210TestsHandler - Native Paths Feature Enabled.\n");
XPLMDebugString("----------------------------------------------------------------\n");
XPLMEnableFeature("XPLM_USE_NATIVE_PATHS",1);
SDK210TestsNativePaths();
XPLMReleasePlanes();
XPLMEnableFeature("XPLM_USE_NATIVE_PATHS",0);
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: SDK210TestsHandler - Native Paths Feature Disabled.\n");
XPLMDebugString("----------------------------------------------------------------\n");
SDK210TestsNativePaths();
XPLMReleasePlanes();
XPLMDebugString("================================================================\n");
XPSetWidgetProperty(SDK210TestsButton4, xpProperty_Enabled, 1);
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton5)
{
SDK210TestsMenuId2 = XPLMCreateMenu("Test Menu 1", SDK210TestsMenuId, SDK210TestsMenuItem2, SDK210TestsMenuHandler2, NULL);
SDK210TestsMenuIndex1 = XPLMAppendMenuItem(SDK210TestsMenuId2, "Test Menu Item 1", (void *)"1", 1);
SDK210TestsMenuIndex2 = XPLMAppendMenuItem(SDK210TestsMenuId2, "Test Menu Item 2", (void *)"2", 1);
SDK210TestsMenuIndex3 = XPLMAppendMenuItem(SDK210TestsMenuId2, "Test Menu Item 3", (void *)"3", 1);
XPSetWidgetProperty(SDK210TestsButton5, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton6, xpProperty_Enabled, 1);
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton6)
{
XPLMRemoveMenuItem(SDK210TestsMenuId2, SDK210TestsMenuIndex3);
XPLMRemoveMenuItem(SDK210TestsMenuId2, SDK210TestsMenuIndex2);
XPLMRemoveMenuItem(SDK210TestsMenuId2, SDK210TestsMenuIndex1);
XPLMDestroyMenu(SDK210TestsMenuId2);
XPSetWidgetProperty(SDK210TestsButton5, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton6, xpProperty_Enabled, 0);
XPSetWidgetDescriptor(SDK210TestsEdit[MENU_2], "");
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton7)
{
SDK210TestsDrawingEnabled = 1;
XPSetWidgetProperty(SDK210TestsButton7, xpProperty_Enabled, 0);
XPSetWidgetProperty(SDK210TestsButton8, xpProperty_Enabled, 1);
return 1;
}
if (inParam1 == (intptr_t)SDK210TestsButton8)
{
SDK210TestsDrawingEnabled = 0;
XPSetWidgetDescriptor(SDK210TestsEdit[DRAWING], "");
XPSetWidgetProperty(SDK210TestsButton7, xpProperty_Enabled, 1);
XPSetWidgetProperty(SDK210TestsButton8, xpProperty_Enabled, 0);
return 1;
}
}
return 0;
}
//---------------------------------------------------------------------------
// Function for Draw Object tests
void SDK210TestsGotWindsock(XPLMObjectRef obj, void * ref)
{
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: - SDK210TestsGotWindsock Callback called.\n");
XPLMDebugString("----------------------------------------------------------------\n");
SDK210Tests_Windsock = obj;
}
void SDK210TestsLoadWindsock(const char * fname, void * ref)
{
XPLMDebugString("================================================================\n");
XPLMDebugString("SDK210Tests: - SDK210TestsLoadWindsock : Before XPLMLoadObjectAsync Call.\n");
XPLMLoadObjectAsync(fname, SDK210TestsGotWindsock, NULL);
XPLMDebugString("SDK210Tests: - SDK210TestsLoadWindsock : After XPLMLoadObjectAsync Call.\n");
XPLMDebugString("----------------------------------------------------------------\n");
}
int SDK210TestsDrawWindsock(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon)
{
static bool LookedForWindsock = false;
if (SDK210TestsDrawingEnabled)
{
if (SDK210Tests_Windsock == NULL && !LookedForWindsock)
{
XPLMLookupObjects("lib/airport/landscape/windsock.obj", 0, 0, SDK210TestsLoadWindsock, NULL);
LookedForWindsock = true;
}
if (SDK210Tests_Windsock && !SDK210Tests_Windsock_Probe)
SDK210Tests_Windsock_Probe = XPLMCreateProbe(xplm_ProbeY);
if (SDK210Tests_Windsock && SDK210Tests_refx && SDK210Tests_refy && SDK210Tests_refz && SDK210Tests_Windsock_Probe)
{
XPLMProbeInfo_t info;
info.structSize = sizeof(info);
XPLMProbeResult result = XPLMProbeTerrainXYZ(
SDK210Tests_Windsock_Probe,
XPLMGetDataf(SDK210Tests_refx),
XPLMGetDataf(SDK210Tests_refy),
XPLMGetDataf(SDK210Tests_refz),
&info);
if(result == xplm_ProbeHitTerrain)
{
XPLMDrawInfo_t DrawInfo_t = { 0 };
DrawInfo_t.structSize = sizeof(DrawInfo_t);
DrawInfo_t.x = info.locationX;
DrawInfo_t.y = info.locationY;
DrawInfo_t.z = info.locationZ;
if(info.is_wet)DrawInfo_t.pitch += 20.0;
if (XPLMGetDatai(SDK210Tests_wrl_type))
DrawInfo_t.heading += 30.0;
XPLMDrawObjects(SDK210Tests_Windsock, 1, &DrawInfo_t, 0, 1);
if (SDK210TestsMenuItem1 == 1)
{
sprintf(SDK210Tests_Buffer,"Drawing Enabled : X = %f, Y = %f, Z = %f\n", info.locationX, info.locationY, info.locationZ);
XPSetWidgetDescriptor(SDK210TestsEdit[DRAWING], SDK210Tests_Buffer);
}
}
}
}
return 1;
}
//---------------------------------------------------------------------------
void SDK210TestsNativePaths(void)
{
char PluginPath[512], Name[256], FilePath[512], Signature[256], Description[256];
char PrefsPath[512];
XPLMPluginID PluginID = NULL;
char NameBuffer[4096];
char *Indices[4096];
int ReturnFile;
int TotalFile;
int ReturnValue;
int Offset = 0;
#if IBM
#define PLUGIN_ADMIN_NAME "win.xpl"
#elif APL
#define PLUGIN_ADMIN_NAME "mac.xpl"
#elif LIN
#define PLUGIN_ADMIN_NAME "lin.xpl"
#else
#error Platform not defined!
#endif
XPLMGetSystemPath(PluginPath);
strcat(PluginPath, "Resources");
strcat(PluginPath, XPLMGetDirectorySeparator());
strcat(PluginPath, "plugins");
strcat(PluginPath, XPLMGetDirectorySeparator());
strcat(PluginPath, "PluginAdmin");
strcat(PluginPath, XPLMGetDirectorySeparator());
ReturnValue = XPLMGetDirectoryContents(PluginPath, Offset, NameBuffer, sizeof(NameBuffer), Indices, sizeof(Indices) / sizeof(char *), &TotalFile, &ReturnFile);
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMGetDirectoryContents - PluginPath = %s.\n", PluginPath);
XPLMDebugString(SDK210Tests_Buffer);
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMGetDirectoryContents - TotalFile = %d.\n", TotalFile);
XPLMDebugString(SDK210Tests_Buffer);
strcat(PluginPath, PLUGIN_ADMIN_NAME);
PluginID = XPLMFindPluginByPath(PluginPath);
XPLMGetPluginInfo(PluginID, Name, FilePath, Signature, Description);
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMGetPluginInfo - Name = %s, FilePath = %s, Signature = %s, Description = %s.\n", Name, FilePath, Signature, Description);
XPLMDebugString(SDK210Tests_Buffer);
XPLMGetPrefsPath(PrefsPath);
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMGetPrefsPath - PrefsPath = %s.\n", PrefsPath);
XPLMDebugString(SDK210Tests_Buffer);
strcpy(FilePath, "Output");
strcat(FilePath, XPLMGetDirectorySeparator());
strcat(FilePath, "situations");
strcat(FilePath, XPLMGetDirectorySeparator());
strcat(FilePath, "SDK210Test.sit");
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMSaveDataFile - FilePath = %s.\n", FilePath);
XPLMDebugString(SDK210Tests_Buffer);
XPLMSaveDataFile(xplm_DataFile_Situation, FilePath);
///XPLMLoadDataFile(xplm_DataFile_Situation, FilePath);
strcpy(FilePath, "Output");
strcat(FilePath, XPLMGetDirectorySeparator());
strcat(FilePath, "replays");
strcat(FilePath, XPLMGetDirectorySeparator());
strcat(FilePath, "SDK210Test.rep");
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsNativePaths - XPLMSaveDataFile - FilePath = %s.\n", FilePath);
XPLMDebugString(SDK210Tests_Buffer);
XPLMSaveDataFile(xplm_DataFile_ReplayMovie, FilePath);
///XPLMLoadDataFile(xplm_DataFile_ReplayMovie, FilePath);
SDK210TestsLoadAircraft(USER_AIRCRAFT);
SDK210TestsAcquireAircraft();
}
//---------------------------------------------------------------------------
void SDK210TestsAcquireAircraft(void)
{
int PlaneCount;
int Index;
char FileName[256], AircraftPath[256];
XPLMCountAircraft(&PlaneCount, 0, 0);
if (PlaneCount > 1)
{
for (Index = 1; Index < PlaneCount; Index++)
{
XPLMGetNthAircraftModel(Index, FileName, AircraftPath);
strcpy(SDK210TestsAircraftPath[Index-1], AircraftPath);
pSDK210TestsAircraft[Index-1] = (char *)SDK210TestsAircraftPath[Index-1];
}
if (XPLMAcquirePlanes((char **)&pSDK210TestsAircraft, NULL, NULL))
{
XPLMDebugString("SDK210Tests: SDK210TestsAcquireAircraft - Aircraft Acquired successfully\n");
SDK210TestsLoadAircraft(AI_AIRCRAFT);
}
else
{
XPLMDebugString("SDK210Tests: SDK210TestsAcquireAircraft - Aircraft not Acquired\n");
}
}
}
//---------------------------------------------------------------------------
void SDK210TestsLoadAircraft(int AircraftType)
{
char AircraftPath[512];
XPLMGetSystemPath(AircraftPath);
///strcat(AircraftPath, XPLMGetDirectorySeparator());
strcat(AircraftPath, "Aircraft");
strcat(AircraftPath, XPLMGetDirectorySeparator());
strcat(AircraftPath, "General Aviation");
strcat(AircraftPath, XPLMGetDirectorySeparator());
strcat(AircraftPath, "Cirrus TheJet");
strcat(AircraftPath, XPLMGetDirectorySeparator());
strcat(AircraftPath, "c4.acf");
sprintf(SDK210Tests_Buffer,"SDK210Tests: SDK210TestsLoadAircraft - AircraftPath = %s.\n", AircraftPath);
XPLMDebugString(SDK210Tests_Buffer);
if (AircraftType == USER_AIRCRAFT)
XPLMSetUsersAircraft(AircraftPath);
if (AircraftType == AI_AIRCRAFT)
XPLMSetAircraftModel(1, AircraftPath);
}
//---------------------------------------------------------------------------
/*
Plugin to show how to derive motion platform data from our datarefs
Thanks to Austin for allowing us to use the original Xplane conversion code.
Version 1.0.0.1 Intitial Sandy Barbour - 05/08/2007
*/
#include <stdio.h>
#include <string.h>
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
// Globals.
// Use MPD_ as a prefix for the global variables
// Used to store data for display
char MPD_Buffer[6][80];
// Used to store calculated motion data
float MPD_MotionData[6];
// Window ID
XPLMWindowID MPD_Window = NULL;
// Datarefs
XPLMDataRef MPD_DR_groundspeed = NULL;
XPLMDataRef MPD_DR_fnrml_prop = NULL;
XPLMDataRef MPD_DR_fside_prop = NULL;
XPLMDataRef MPD_DR_faxil_prop = NULL;
XPLMDataRef MPD_DR_fnrml_aero = NULL;
XPLMDataRef MPD_DR_fside_aero = NULL;
XPLMDataRef MPD_DR_faxil_aero = NULL;
XPLMDataRef MPD_DR_fnrml_gear = NULL;
XPLMDataRef MPD_DR_fside_gear = NULL;
XPLMDataRef MPD_DR_faxil_gear = NULL;
XPLMDataRef MPD_DR_m_total = NULL;
XPLMDataRef MPD_DR_the = NULL;
XPLMDataRef MPD_DR_psi = NULL;
XPLMDataRef MPD_DR_phi = NULL;
//---------------------------------------------------------------------------
// Function prototypes
float MotionPlatformDataLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon);
void MotionPlatformDataDrawWindowCallback(
XPLMWindowID inWindowID,
void * inRefcon);
void MotionPlatformDataHandleKeyCallback(
XPLMWindowID inWindowID,
char inKey,
XPLMKeyFlags inFlags,
char inVirtualKey,
void * inRefcon,
int losingFocus);
int MotionPlatformDataHandleMouseClickCallback(
XPLMWindowID inWindowID,
int x,
int y,
XPLMMouseStatus inMouse,
void * inRefcon);
float MPD_fallout(float data, float low, float high);
float MPD_fltlim(float data, float min, float max);
float MPD_fltmax2 (float x1,const float x2);
void MPD_CalculateMotionData(void);
//---------------------------------------------------------------------------
// SDK Mandatory Callbacks
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "MotionPlatformData");
strcpy(outSig, "xplanesdk.examples.motiondplatformdata");
strcpy(outDesc, "A plug-in that derives motion platform data from datarefs.");
MPD_Window = XPLMCreateWindow(
50, 600, 200, 500, /* Area of the window. */
1, /* Start visible. */
MotionPlatformDataDrawWindowCallback, /* Callbacks */
MotionPlatformDataHandleKeyCallback,
MotionPlatformDataHandleMouseClickCallback,
NULL); /* Refcon - not used. */
XPLMRegisterFlightLoopCallback(MotionPlatformDataLoopCB, 1.0, NULL);
MPD_DR_groundspeed = XPLMFindDataRef("sim/flightmodel/position/groundspeed");
MPD_DR_fnrml_prop = XPLMFindDataRef("sim/flightmodel/forces/fnrml_prop");
MPD_DR_fside_prop = XPLMFindDataRef("sim/flightmodel/forces/fside_prop");
MPD_DR_faxil_prop = XPLMFindDataRef("sim/flightmodel/forces/faxil_prop");
MPD_DR_fnrml_aero = XPLMFindDataRef("sim/flightmodel/forces/fnrml_aero");
MPD_DR_fside_aero = XPLMFindDataRef("sim/flightmodel/forces/fside_aero");
MPD_DR_faxil_aero = XPLMFindDataRef("sim/flightmodel/forces/faxil_aero");
MPD_DR_fnrml_gear = XPLMFindDataRef("sim/flightmodel/forces/fnrml_gear");
MPD_DR_fside_gear = XPLMFindDataRef("sim/flightmodel/forces/fside_gear");
MPD_DR_faxil_gear = XPLMFindDataRef("sim/flightmodel/forces/faxil_gear");
MPD_DR_m_total = XPLMFindDataRef("sim/flightmodel/weight/m_total");
MPD_DR_the = XPLMFindDataRef("sim/flightmodel/position/theta");
MPD_DR_psi = XPLMFindDataRef("sim/flightmodel/position/psi");
MPD_DR_phi = XPLMFindDataRef("sim/flightmodel/position/phi");
memset(MPD_Buffer, 0, sizeof(MPD_Buffer));
return 1;
}
//---------------------------------------------------------------------------
PLUGIN_API void XPluginStop(void)
{
XPLMDestroyWindow(MPD_Window);
XPLMUnregisterFlightLoopCallback(MotionPlatformDataLoopCB, NULL);
}
//---------------------------------------------------------------------------
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
//---------------------------------------------------------------------------
PLUGIN_API void XPluginDisable(void)
{
}
//---------------------------------------------------------------------------
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam)
{
}
//---------------------------------------------------------------------------
// Mandatory callback for SDK 2D Window
// Used to display the data to the screen
void MotionPlatformDataDrawWindowCallback(
XPLMWindowID inWindowID,
void * inRefcon)
{
float rgb [] = { 1.0, 1.0, 1.0 };
int l, t, r, b;
XPLMGetWindowGeometry(inWindowID, &l, &t, &r, &b);
XPLMDrawTranslucentDarkBox(l, t, r, b);
for (int i=0; i<6; i++)
XPLMDrawString(rgb, l+10, (t-20) - (10*i), MPD_Buffer[i], NULL, xplmFont_Basic);
}
//---------------------------------------------------------------------------
// Mandatory callback for SDK 2D Window
// Not used in this plugin
void MotionPlatformDataHandleKeyCallback(
XPLMWindowID inWindowID,
char inKey,
XPLMKeyFlags inFlags,
char inVirtualKey,
void * inRefcon,
int losingFocus)
{
}
//---------------------------------------------------------------------------
// Mandatory callback for SDK 2D Window
// Not used in this plugin
int MotionPlatformDataHandleMouseClickCallback(
XPLMWindowID inWindowID,
int x,
int y,
XPLMMouseStatus inMouse,
void * inRefcon)
{
return 1;
}
//---------------------------------------------------------------------------
// FlightLoop callback to calculate motion data and store it in our buffers
float MotionPlatformDataLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon)
{
MPD_CalculateMotionData();
sprintf(MPD_Buffer[0], "the = %f", MPD_MotionData[0]);
sprintf(MPD_Buffer[1], "psi = %f", MPD_MotionData[1]);
sprintf(MPD_Buffer[2], "phi = %f", MPD_MotionData[2]);
sprintf(MPD_Buffer[3], "a_side = %f", MPD_MotionData[3]);
sprintf(MPD_Buffer[4], "a_nrml = %f", MPD_MotionData[4]);
sprintf(MPD_Buffer[5], "a_axil = %f", MPD_MotionData[5]);
return (float)0.1;
}
//---------------------------------------------------------------------------
// Original function used in the Xplane code.
float MPD_fallout(float data, float low, float high)
{
if (data < low) return data;
if (data > high) return data;
if (data < ((low + high) * 0.5)) return low;
return high;
}
//---------------------------------------------------------------------------
// Original function used in the Xplane code.
float MPD_fltlim(float data, float min, float max)
{
if (data < min) return min;
if (data > max) return max;
return data;
}
//---------------------------------------------------------------------------
// Original function used in the Xplane code.
float MPD_fltmax2 (float x1,const float x2)
{
return (x1 > x2) ? x1 : x2;
}
//---------------------------------------------------------------------------
// This is original Xplane code converted to use
// our datarefs instead of the Xplane variables
void MPD_CalculateMotionData(void)
{
float groundspeed = XPLMGetDataf(MPD_DR_groundspeed);
float fnrml_prop = XPLMGetDataf(MPD_DR_fnrml_prop);
float fside_prop = XPLMGetDataf(MPD_DR_fside_prop);
float faxil_prop = XPLMGetDataf(MPD_DR_faxil_prop);
float fnrml_aero = XPLMGetDataf(MPD_DR_fnrml_aero);
float fside_aero = XPLMGetDataf(MPD_DR_fside_aero);
float faxil_aero = XPLMGetDataf(MPD_DR_faxil_aero);
float fnrml_gear = XPLMGetDataf(MPD_DR_fnrml_gear);
float fside_gear = XPLMGetDataf(MPD_DR_fside_gear);
float faxil_gear = XPLMGetDataf(MPD_DR_faxil_gear);
float m_total = XPLMGetDataf(MPD_DR_m_total);
float the = XPLMGetDataf(MPD_DR_the);
float psi = XPLMGetDataf(MPD_DR_psi);
float phi = XPLMGetDataf(MPD_DR_phi);
float ratio = MPD_fltlim(groundspeed*0.2,0.0,1.0);
float a_nrml= MPD_fallout(fnrml_prop+fnrml_aero+fnrml_gear,-0.1,0.1)/MPD_fltmax2(m_total,1.0);
float a_side= (fside_prop+fside_aero+fside_gear)/MPD_fltmax2(m_total,1.0)*ratio;
float a_axil= (faxil_prop+faxil_aero+faxil_gear)/MPD_fltmax2(m_total,1.0)*ratio;
// Store the results in an array so that we can easily display it.
MPD_MotionData[0] = the;
MPD_MotionData[1] = psi;
MPD_MotionData[2] = phi;
MPD_MotionData[3] = a_side;
MPD_MotionData[4] = a_nrml;
MPD_MotionData[5] = a_axil;
}
//---------------------------------------------------------------------------
/*
SDK200Tests Example
Tests the new SDK 2.00 functions.
Version 1.0.0.1 Intitial Sandy Barbour 20/11/2007
Version 1.1.0.1 Added Load/Save sit/smo files test
Added Map Drawing Tests - Sandy Barbour 02/12/2009
NOTES
1.
This code also draws a custom X-Plane OBJ (3-d model).
You will need to add your own OBJ and change the code to reflect this.
Copy your OBJ to the XPlane V9 application directory.
The line below, which is in the SDK200TestsDrawObject(..) callback is the line to change.
SDK200TestsObject = XPLMLoadObject("dummy.obj");
An alternative is to just rename you .obj file to dummy.obj
2.
The code draws 2 objects each time, so you are not seeing double. :-)
*/
#include "XPLMPlugin.h"
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMMenus.h"
#include "XPLMUtilities.h"
#include "XPWidgets.h"
#include "XPStandardWidgets.h"
#include "XPLMScenery.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#if IBM
#include <windows.h>
#include <stdio.h>
#endif
#if LIN
#include <GL/gl.h>
#else
#if __GNUC__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#endif
// Number of edit boxes in widget
#define MAX_ITEMS 5
// Number of Xplane objects
#define MAX_OBJECT_ITEMS 6
char SDK200TestsVersionNumber[] = "v1.10";
// Description text for widget edit boxes
char SDK200TestsDataDesc[MAX_ITEMS][255] = {"Probe Test", "Command Test", "Mouse Wheel", "Cursor", "Objects"};
// Used as interlock for widget
int SDK200TestsMenuItem1;
// Used by menus
XPLMMenuID SDK200TestsId;
int SDK200TestsItem;
// Used for the text window
XPLMWindowID SDK200TestsTestWindow;
// Used to test Command API
XPLMCommandRef SDK200TestsCommand1 = NULL;
// Indexers
int SDK200TestsCursorStatusIndex = 0;
int SDK200TestsCurrentFontIndex = 0;
int SDK200TestsCurrentObjectIndex = 0;
int SDK200TestsDrawWindowEnabled = 0;
// Used by the cursor test
XPLMCursorStatus SDK200TestsCursorStatus[4] = {xplm_CursorDefault, xplm_CursorHidden, xplm_CursorArrow, xplm_CursorCustom};
// Used by the Draw Objects test
char SDK200TestsObjectPath[MAX_OBJECT_ITEMS][255] = {
"lib/ships/Frigate.obj", "lib/airport/landscape/radar.obj", "lib/dynamic/balloon.obj",
"lib/airport/landscape/windsock_pole.obj", "lib/airport/NAVAIDS/glideslope.obj",
"lib/airport/aircraft/regional_prop/ATR42-500_FedEx.obj"
};
// Used for GetVersion tests
char SDK200TestsXPLMFindSymbolBuffer[256], SDK200TestsXPLMGetVersionsBuffer[256];
// Datarefs
XPLMDataRef SDK200Tests_refx = NULL;
XPLMDataRef SDK200Tests_refy = NULL;
XPLMDataRef SDK200Tests_refz = NULL;
XPLMDataRef SDK200Tests_ref_render_type = NULL;
XPLMDataRef SDK200Tests_ref_wrl_type = NULL;
XPLMDataRef SDK200Tests_ref_vl = NULL;
XPLMDataRef SDK200Tests_ref_vb = NULL;
XPLMDataRef SDK200Tests_ref_vr = NULL;
XPLMDataRef SDK200Tests_ref_vt = NULL;
XPLMDataRef SDK200Tests_ref_mode_time = NULL;
XPLMDataRef SDK200Tests_ref_x_scale = NULL;
XPLMDataRef SDK200Tests_ref_y_scale = NULL;
XPLMDataRef SDK200Tests_ref_t_scale = NULL;
// Widgets
XPWidgetID SDK200TestsWidget, SDK200TestsWindow;
XPWidgetID SDK200TestsButton1, SDK200TestsButton2, SDK200TestsButton3, SDK200TestsButton4, SDK200TestsButton5;
XPWidgetID SDK200TestsButton6, SDK200TestsButton7, SDK200TestsButton8, SDK200TestsButton9;
XPWidgetID SDK200TestsText[MAX_ITEMS];
XPWidgetID SDK200TestsEdit[MAX_ITEMS];
XPLMProbeRef SDK200TestsProbe=NULL;
// Used by the Draw Objects test
XPLMObjectRef SDK200TestsObject=NULL;
XPLMProbeRef SDK200TestsObjectProbe=NULL;
// Prototype for the XPLMFindSymbol test
typedef void (* XPLMGetVersions_f)(
int * outXPlaneVersion,
int * outXPLMVersion,
XPLMHostApplicationID * outHostID);
// Displays data in widget
float SDK200TestsLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon);;
// Menu Prototype
void SDK200TestsMenuHandler(void *, void *);
// Draw Text window callbacks
void SDK200TestsWindowDraw(XPLMWindowID inWindowID, void * inRefcon);
void SDK200TestsWindowKey(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char vkey, void * inRefcon, int losingFocus);
int SDK200TestsWindowMouse(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus isDown, void * inRefcon);
int SDK200TestsWindowMouseWheel(XPLMWindowID inWindowID,
int x,
int y,
int wheel,
int clicks,
void * inRefcon);
XPLMCursorStatus SDK200TestsWindowCursor(XPLMWindowID inWindowID,
int x,
int y,
void * inRefcon);
// Widget prototypes
void CreateSDK200Tests(int x1, int y1, int w, int h);
int SDK200TestsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2);
// Callback for the Command API Tests
int SDK200TestsCommandHandler1(XPLMCommandRef inCommand,
XPLMCommandPhase inPhase,
void * inRefcon)
{
char Buffer[256];
sprintf(Buffer,"Cmdh handler: 0x%08x, %d, 0x%08x\n", inCommand, inPhase, inRefcon);
XPSetWidgetDescriptor(SDK200TestsEdit[1], Buffer);
return 0;
}
// Prototype for Draw Object tests
int SDK200TestsDrawObject(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon);
// Callback for Error Tests
void SDK200TestsErrorCB(const char * msg)
{
XPLMDebugString("SDK200Tests -:- error CB called: ");
XPLMDebugString(msg);
XPLMDebugString("\n");
}
// Callback or Feature API Tests
void SDK200TestsFeatureEnum(const char * msg, void * inRefcon)
{
XPLMDebugString("SDK200Tests -:- SUPPORTED FEATURE TEST: ");
XPLMDebugString(msg);
XPLMDebugString("\n");
}
// Prototype for Map Draw tests
int SDK200TestsMapCB(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon);
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
int DataRefItem;
int XPlaneVersion, XPLMVersion, HostID;
char Buffer[256];
strcpy(outName, "SDK200Tests");
strcpy(outSig, "sandybarbour.projects.sdk200tests");
strcpy(outDesc, "A plug-in to test the new SDK200 API's.");
// Get the aicraft position
SDK200Tests_refx = XPLMFindDataRef("sim/flightmodel/position/local_x");
SDK200Tests_refy = XPLMFindDataRef("sim/flightmodel/position/local_y");
SDK200Tests_refz = XPLMFindDataRef("sim/flightmodel/position/local_z");
SDK200Tests_ref_render_type = XPLMFindDataRef("sim/graphics/view/panel_render_type");
SDK200Tests_ref_wrl_type = XPLMFindDataRef("sim/graphics/view/world_render_type");
SDK200Tests_ref_vl = XPLMFindDataRef("sim/graphics/view/local_map_l");
SDK200Tests_ref_vb = XPLMFindDataRef("sim/graphics/view/local_map_b");
SDK200Tests_ref_vr = XPLMFindDataRef("sim/graphics/view/local_map_r");
SDK200Tests_ref_vt = XPLMFindDataRef("sim/graphics/view/local_map_t");
SDK200Tests_ref_mode_time = XPLMFindDataRef("sim/graphics/settings/local_map/profile_view_is_time");
SDK200Tests_ref_x_scale = XPLMFindDataRef("sim/graphics/view/local_profile_scale_x");
SDK200Tests_ref_y_scale = XPLMFindDataRef("sim/graphics/view/local_profile_scale_y");
SDK200Tests_ref_t_scale = XPLMFindDataRef("sim/graphics/view/local_profile_scale_t");
// Create function pointer
XPLMGetVersions_f XPLMGetVersionsTemp;
// Find the real XPLMGetVersions function and copy to function pointer
XPLMGetVersionsTemp = (XPLMGetVersions_f) XPLMFindSymbol("XPLMGetVersions");
// Call the function
XPLMGetVersionsTemp(&XPlaneVersion, &XPLMVersion, &HostID);
// Display the results
sprintf(SDK200TestsXPLMFindSymbolBuffer, "SDK200Tests -:- XPLMFindSymbol returned [XPlaneVersion = %d, XPLMVersion = %d, HostID = %d\n", XPlaneVersion, XPLMVersion, HostID);
XPLMDebugString(SDK200TestsXPLMFindSymbolBuffer);
// Call the real XPLMGetVersions as a comparison for the above
XPLMGetVersions(&XPlaneVersion, &XPLMVersion, &HostID);
// Display the results
sprintf(SDK200TestsXPLMGetVersionsBuffer, "SDK200Tests -:- XPLMGetVersions returned [XPlaneVersion = %d, XPLMVersion = %d, HostID = %d\n", XPlaneVersion, XPLMVersion, HostID);
XPLMDebugString(SDK200TestsXPLMGetVersionsBuffer);
// Create the menus
SDK200TestsItem = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "SDK200Tests", NULL, 1);
SDK200TestsId = XPLMCreateMenu("SDK200Tests", XPLMFindPluginsMenu(), SDK200TestsItem, SDK200TestsMenuHandler, NULL);
XPLMAppendMenuItem(SDK200TestsId, "SDK200Tests", (void *)"SDK200Tests", 1);
XPLMAppendMenuItem(SDK200TestsId, "Show Window", (void *)"Show Window", 1);
XPLMAppendMenuItem(SDK200TestsId, "Hide Window", (void *)"Hide Window", 1);
// Register the callback for errors
XPLMSetErrorCallback(SDK200TestsErrorCB);
// Test enumaration of features
XPLMEnumerateFeatures(SDK200TestsFeatureEnum, NULL);
// Enable a valid feature, which trigger the SDK200TestsFeatureEnum callback
XPLMEnableFeature("XPLM_WANTS_REFLECTIONS", 1);
// Try to enable an invalid feature, error will be reported in the SDK200TestsErrorCB callback
XPLMEnableFeature("SANDY_WANTS_REFLECTIONS", 1);
SDK200TestsMenuItem1 = 0;
SDK200TestsDrawWindowEnabled = 0;
// This is used to create a text window using the new XPLMCreateWindowEx function.
XPLMCreateWindow_t TestWindowData;
TestWindowData.structSize = sizeof(TestWindowData);
TestWindowData.left = 50;
TestWindowData.top = 450;
TestWindowData.right = 600;
TestWindowData.bottom = 350;
TestWindowData.visible= 1;
TestWindowData.drawWindowFunc = SDK200TestsWindowDraw;
TestWindowData.handleKeyFunc = SDK200TestsWindowKey;
TestWindowData.handleMouseClickFunc = SDK200TestsWindowMouse;
TestWindowData.handleMouseWheelFunc = SDK200TestsWindowMouseWheel;
TestWindowData.handleCursorFunc = SDK200TestsWindowCursor;
TestWindowData.refcon = NULL;
SDK200TestsTestWindow = XPLMCreateWindowEx(&TestWindowData);
sprintf(Buffer, "SDK200Tests -:- Creating window with XPLMCreateWindowEx: returned XPLMWindowID = %x\n", SDK200TestsTestWindow);
XPLMDebugString(Buffer);
XPLMRegisterFlightLoopCallback(SDK200TestsLoopCB, 1.0, NULL);
// Create the test command, this will save the screen to a file.
SDK200TestsCommand1 = XPLMCreateCommand("sim/operation/screenshot", "Test screenshot");
// Register it
XPLMRegisterCommandHandler(SDK200TestsCommand1, SDK200TestsCommandHandler1, 0, (void *) 0);
// This used for the Draw Objects tests
XPLMRegisterDrawCallback( SDK200TestsDrawObject, xplm_Phase_Objects, 0, 0 );
// This used for the Draw Map tests
XPLMRegisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMap2D, 0, 0);
XPLMRegisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMap3D, 0, 0);
XPLMRegisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMapProfile, 0, 0);
// Create a Y probe
SDK200TestsObjectProbe = XPLMCreateProbe(xplm_ProbeY);
SDK200TestsProbe = XPLMCreateProbe(xplm_ProbeY);
return 1;
}
PLUGIN_API void XPluginStop(void)
{
// Clean up
XPLMUnregisterDrawCallback( SDK200TestsDrawObject, xplm_Phase_Objects, 0, 0 );
XPLMUnregisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMap2D, 0, 0);
XPLMUnregisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMap3D, 0, 0);
XPLMUnregisterDrawCallback( SDK200TestsMapCB, xplm_Phase_LocalMapProfile, 0, 0);
if(SDK200TestsObject) XPLMUnloadObject(SDK200TestsObject);
XPLMDestroyProbe(SDK200TestsObjectProbe);
XPLMDestroyProbe(SDK200TestsProbe);
XPLMDestroyWindow(SDK200TestsTestWindow);
XPLMUnregisterCommandHandler(SDK200TestsCommand1, SDK200TestsCommandHandler1, 0, 0);
XPLMUnregisterFlightLoopCallback(SDK200TestsLoopCB, NULL);
XPLMDestroyMenu(SDK200TestsId);
}
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
PLUGIN_API void XPluginDisable(void)
{
}
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam)
{
}
// Displays data in widget
float SDK200TestsLoopCB(float elapsedMe, float elapsedSim, int counter, void * refcon)
{
char Buffer[256];
float x = XPLMGetDatad(SDK200Tests_refx);
float y = XPLMGetDatad(SDK200Tests_refy);
float z = XPLMGetDatad(SDK200Tests_refz);
XPLMProbeInfo_t info = { 0 };
info.structSize = sizeof(info);
// If we have a hit then display the data in the widget
if (XPLMProbeTerrainXYZ(SDK200TestsProbe,x,y,z,&info) == xplm_ProbeHitTerrain)
{
sprintf(Buffer,"Y gap is: %f v=%f,%f,%f\n", y - info.locationY, info.velocityX, info.velocityY, info.velocityZ);
if (SDK200TestsMenuItem1 == 1)
XPSetWidgetDescriptor(SDK200TestsEdit[0], Buffer);
}
return 0.1;
}
// Process the menu selections
void SDK200TestsMenuHandler(void * mRef, void * iRef)
{
// Menu selected for widget
if (!strcmp((char *) iRef, "SDK200Tests"))
{
if (SDK200TestsMenuItem1 == 0)
{
CreateSDK200Tests(100, 550, 650, 330);
SDK200TestsMenuItem1 = 1;
}
}
// Menu selected to enable text window
if (!strcmp((char *) iRef, "Show Window"))
{
SDK200TestsDrawWindowEnabled = 1;
}
// Menu selected to disable text window
if (!strcmp((char *) iRef, "Hide Window"))
{
SDK200TestsDrawWindowEnabled = 0;
}
}
// Used to draw various test info to the text window
void SDK200TestsWindowDraw(XPLMWindowID inWindowID, void * inRefcon)
{
float rgb [] = { 1.0, 1.0, 1.0 };
int Left, Top, Right, Bottom;
char Buffer[256];
// Used by the Font test
XPLMFontID TestFont[2] = {xplmFont_Basic, xplmFont_Proportional};
char TestFontDesc[2][80] = {"xplmFont_Basic", "xplmFont_Proportional"};
// Only draw if enabled through the menu
if (SDK200TestsDrawWindowEnabled)
{
sprintf(Buffer, "Current font is %d : %s", TestFont[SDK200TestsCurrentFontIndex], TestFontDesc[SDK200TestsCurrentFontIndex]);
XPLMGetWindowGeometry(inWindowID, &Left, &Top, &Right, &Bottom);
XPLMDrawTranslucentDarkBox(Left, Top, Right, Bottom);
XPLMDrawString(rgb, Left+10, Top-10, SDK200TestsXPLMFindSymbolBuffer, NULL, TestFont[SDK200TestsCurrentFontIndex]);
XPLMDrawString(rgb, Left+10, Top-20, SDK200TestsXPLMGetVersionsBuffer, NULL, TestFont[SDK200TestsCurrentFontIndex]);
XPLMDrawString(rgb, Left+10, Top-50, Buffer, NULL, xplmFont_Basic);
int render_type = XPLMGetDatai(SDK200Tests_ref_render_type);
sprintf(Buffer, "Current Render Type is %d", render_type);
XPLMDrawString(rgb, Left+10, Top-70, Buffer, NULL, xplmFont_Basic);
sprintf(Buffer, "Test Feature - XPLMHasFeature is %d : XPLMIsFeatureEnabled is %d", XPLMHasFeature("XPLM_WANTS_REFLECTIONS"), XPLMIsFeatureEnabled("XPLM_WANTS_REFLECTIONS"));
XPLMDrawString(rgb, Left+10, Top-90, Buffer, 0, xplmFont_Basic);
}
}
// Not used
void SDK200TestsWindowKey(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char vkey, void * inRefcon, int losingFocus)
{
}
// Not used
int SDK200TestsWindowMouse(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus isDown, void * inRefcon)
{
return 1;
}
// Using the mouse wheel in the text window will increase the throttle
int SDK200TestsWindowMouseWheel(XPLMWindowID inWindowID,
int x,
int y,
int wheel,
int clicks,
void * inRefcon)
{
XPLMCommandOnce(XPLMFindCommand("sim/engines/throttle_up_1"));
return 1;
}
// This will change the type of cursor
XPLMCursorStatus SDK200TestsWindowCursor(XPLMWindowID inWindowID,
int x,
int y,
void * inRefcon)
{
return SDK200TestsCursorStatus[SDK200TestsCursorStatusIndex];
}
// Function for Draw Object tests
void SDK200TestsLoadObject(const char * fname, void * ref)
{
if(SDK200TestsObject == NULL)
SDK200TestsObject = XPLMLoadObject(fname);
}
// Function for Draw Object tests
int SDK200TestsDrawObject(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon)
{
// If NULL then first time or reset by widget button press
if (SDK200TestsObject == NULL)
{
if (SDK200TestsCurrentObjectIndex < MAX_OBJECT_ITEMS)
// Xplane object so do lookup, will invoke callback if found which will load object
XPLMLookupObjects(SDK200TestsObjectPath[SDK200TestsCurrentObjectIndex], 0, 0, SDK200TestsLoadObject, NULL);
else
// Load the imported object
// NOTE - Change this line with the name of your .obj file.
SDK200TestsObject = XPLMLoadObject("dummy.obj");
}
// Only do this if we have everything we need
if (SDK200TestsObject && SDK200Tests_refx && SDK200Tests_refy && SDK200Tests_refz && SDK200TestsObjectProbe)
{
XPLMProbeInfo_t info;
info.structSize = sizeof(info);
// Probe the terrain
XPLMProbeResult result = XPLMProbeTerrainXYZ(
SDK200TestsObjectProbe,
XPLMGetDatad(SDK200Tests_refx),
XPLMGetDatad(SDK200Tests_refy),
XPLMGetDatad(SDK200Tests_refz),
&info);
// If we have a hit
if(result == xplm_ProbeHitTerrain)
{
XPLMDrawInfo_t locations[2] = { 0 };
locations[0].structSize = sizeof(XPLMDrawInfo_t);
locations[0].x = info.locationX;
locations[0].y = info.locationY;
locations[0].z = info.locationZ;
if(info.is_wet)locations[0].pitch += 20.0;
if(XPLMGetDatai(SDK200Tests_ref_wrl_type)) locations[0].heading += 30.0;
locations[1].structSize = sizeof(XPLMDrawInfo_t);
locations[1].x = XPLMGetDatad(SDK200Tests_refx) + 20;
locations[1].y = XPLMGetDatad(SDK200Tests_refy);
locations[1].z = XPLMGetDatad(SDK200Tests_refz) + 20;
locations[1].pitch = 0;
locations[1].heading = 0;
locations[1].roll = 0;
// Draw the object
XPLMDrawObjects(SDK200TestsObject, 2, locations, 0, 1);
}
}
return 1;
}
// Function for Map Draw tests
int SDK200TestsMapCB(
XPLMDrawingPhase inPhase,
int inIsBefore,
void * inRefcon)
{
if(inPhase == xplm_Phase_LocalMap3D)
{
float lx = XPLMGetDataf(SDK200Tests_refx);
float ly = XPLMGetDataf(SDK200Tests_refy);
float lz = XPLMGetDataf(SDK200Tests_refz);
XPLMSetGraphicsState(0, 0, 0, 0, 0, 0, 0);
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex3f(lx,ly,lz-10.0);
glVertex3f(lx,ly,lz+10.0);
glVertex3f(lx,ly-10.0,lz);
glVertex3f(lx,ly+10.0,lz);
glVertex3f(lx-10.0,ly,lz);
glVertex3f(lx+10.0,ly,lz);
glEnd();
}
else
{
float vl = XPLMGetDataf(SDK200Tests_ref_vl);
float vb = XPLMGetDataf(SDK200Tests_ref_vb);
float vr = XPLMGetDataf(SDK200Tests_ref_vr);
float vt = XPLMGetDataf(SDK200Tests_ref_vt);
XPLMSetGraphicsState(0, 0, 0, 0, 0, 0, 0);
glColor3f(0, 1, 0);
glBegin(GL_LINE_LOOP);
glVertex2f(vl+2, vb+2);
glVertex2f(vl+2, vt-2);
glVertex2f(vr-2, vt-2);
glVertex2f(vr-2, vb+2);
glEnd();
if(inPhase == xplm_Phase_LocalMapProfile)
{
int mode_time = XPLMGetDatai(SDK200Tests_ref_mode_time);
float x_scale = XPLMGetDataf(SDK200Tests_ref_x_scale);
float y_scale = XPLMGetDataf(SDK200Tests_ref_y_scale);
float t_scale = XPLMGetDataf(SDK200Tests_ref_t_scale);
glColor3f(1,0,0);
glBegin(GL_LINES);
glVertex2f(vl,vb);
if(mode_time)
glVertex2f(vl+60.0*t_scale,vb+50.0*t_scale);
else
glVertex2f(vl+1000.0*x_scale,vb+50.0*y_scale);
glEnd();
}
}
return 1;
}
// Creates the widget with buttons for test and edit boxes for info
void CreateSDK200Tests(int x, int y, int w, int h)
{
int Item;
int x2 = x + w;
int y2 = y - h;
char Buffer[255];
sprintf(Buffer, "%s %s %s", "SDK200Tests", SDK200TestsVersionNumber, "- Sandy Barbour 2007");
SDK200TestsWidget = XPCreateWidget(x, y, x2, y2,
1, // Visible
Buffer, // desc
1, // root
NULL, // no container
xpWidgetClass_MainWindow);
XPSetWidgetProperty(SDK200TestsWidget, xpProperty_MainWindowHasCloseBoxes, 1);
SDK200TestsWindow = XPCreateWidget(x+50, y-50, x2-50, y2+50,
1, // Visible
"", // desc
0, // root
SDK200TestsWidget,
xpWidgetClass_SubWindow);
XPSetWidgetProperty(SDK200TestsWindow, xpProperty_SubWindowType, xpSubWindowStyle_SubWindow);
SDK200TestsButton1 = XPCreateWidget(x+60, y-60, x+140, y-82,
1, " Cmd Test 1", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton1, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton2 = XPCreateWidget(x+150, y-60, x+230, y-82,
1, " Cmd Test 2", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton2, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton3 = XPCreateWidget(x+240, y-60, x+320, y-82,
1, " Cursor", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton3, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton4 = XPCreateWidget(x+330, y-60, x+410, y-82,
1, " Font", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton4, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton5 = XPCreateWidget(x+420, y-60, x+500, y-82,
1, " Objects", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton5, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton6 = XPCreateWidget(x+60, y-90, x+140, y-112,
1, " Load SIT", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton6, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton7 = XPCreateWidget(x+150, y-90, x+230, y-112,
1, " Save SIT", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton7, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton8 = XPCreateWidget(x+240, y-90, x+320, y-112,
1, " Load SMO", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton8, xpProperty_ButtonType, xpPushButton);
SDK200TestsButton9 = XPCreateWidget(x+330, y-90, x+410, y-112,
1, " Save SMO", 0, SDK200TestsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(SDK200TestsButton9, xpProperty_ButtonType, xpPushButton);
for (Item=0; Item<MAX_ITEMS; Item++)
{
SDK200TestsText[Item] = XPCreateWidget(x+60, y-(120 + (Item*30)), x+160, y-(142 + (Item*30)),
1, // Visible
SDK200TestsDataDesc[Item],// desc
0, // root
SDK200TestsWidget,
xpWidgetClass_Caption);
SDK200TestsEdit[Item] = XPCreateWidget(x+170, y-(120 + (Item*30)), x+570, y-(142 + (Item*30)),
1, "", 0, SDK200TestsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(SDK200TestsEdit[Item], xpProperty_TextFieldType, xpTextEntryField);
}
sprintf(Buffer,"Object Index = %d : %s", SDK200TestsCurrentObjectIndex, SDK200TestsObjectPath[SDK200TestsCurrentObjectIndex]);
XPSetWidgetDescriptor(SDK200TestsEdit[4], Buffer);
XPAddWidgetCallback(SDK200TestsWidget, SDK200TestsHandler);
}
//Handle the widget messages
int SDK200TestsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2)
{
char Buffer[256];
XPLMCommandRef Command1Ref;
char CursorStatusDesc[4][80] = {"xplm_CursorDefault", "xplm_CursorHidden", "xplm_CursorArrow", "xplm_CursorCustom"};
// Get the mouse wheel messages and display in widget
if (inMessage == xpMsg_MouseWheel)
{
XPMouseState_t *pXPMouseState = (XPMouseState_t *) inParam1;
sprintf(Buffer,"x = %d, y = %d, button = %d, delta = %d", pXPMouseState->x, pXPMouseState->y, pXPMouseState->button, pXPMouseState->delta);
XPSetWidgetDescriptor(SDK200TestsEdit[2], Buffer);
return 1;
}
// Get the cursor status message and display in widget
if (inMessage == xpMsg_CursorAdjust)
{
inParam2 = (intptr_t) SDK200TestsCursorStatus[SDK200TestsCursorStatusIndex];
sprintf(Buffer,"New Cursor Status = %d : %s", inParam2, CursorStatusDesc[SDK200TestsCursorStatusIndex]);
XPSetWidgetDescriptor(SDK200TestsEdit[3], Buffer);
return 1;
}
// When widget close cross is clicked we only hide the widget
if (inMessage == xpMessage_CloseButtonPushed)
{
if (SDK200TestsMenuItem1 == 1)
{
XPDestroyWidget(SDK200TestsWidget, 1);
SDK200TestsMenuItem1 = 0;
}
return 1;
}
// Process when a button on the widget is pressed
if (inMessage == xpMsg_PushButtonPressed)
{
// Tests the Command API, will find command
if (inParam1 == (intptr_t)SDK200TestsButton1)
{
Command1Ref = XPLMFindCommand("sim/operation/screenshot");
if(Command1Ref)
{
// Separate the command action
XPLMCommandBegin(Command1Ref);
XPLMCommandEnd(Command1Ref);
}
return 1;
}
if (inParam1 == (intptr_t)SDK200TestsButton2)
{
// Tests the Command API, will create the command
Command1Ref = XPLMCreateCommand("sim/operation/screenshot", "Test screenshot");
if(Command1Ref)
{
// Used the function to combine the command action
XPLMCommandOnce(Command1Ref);
}
return 1;
}
// Index is increased every button press
if (inParam1 == (intptr_t)SDK200TestsButton3)
{
SDK200TestsCursorStatusIndex++;
// Wrap around
if (SDK200TestsCursorStatusIndex > 3)
SDK200TestsCursorStatusIndex = 0;
return 1;
}
// Index is increased every button press
if (inParam1 == (intptr_t)SDK200TestsButton4)
{
SDK200TestsCurrentFontIndex++;
// Wrap around
if (SDK200TestsCurrentFontIndex > 1)
SDK200TestsCurrentFontIndex = 0;
return 1;
}
// Index is increased every button press
if (inParam1 == (intptr_t)SDK200TestsButton5)
{
SDK200TestsCurrentObjectIndex++;
// Wrap around
if (SDK200TestsCurrentObjectIndex > MAX_OBJECT_ITEMS)
SDK200TestsCurrentObjectIndex = 0;
// Reset so that draw is invoked
SDK200TestsObject = NULL;
// If less than MAX_OBJECT_ITEMS then it is an xplane object
if (SDK200TestsCurrentObjectIndex < MAX_OBJECT_ITEMS)
sprintf(Buffer,"Object Index = %d : %s", SDK200TestsCurrentObjectIndex, SDK200TestsObjectPath[SDK200TestsCurrentObjectIndex]);
// Otherwise use the user supplied object
else
sprintf(Buffer,"Object Index = %d : %s", SDK200TestsCurrentObjectIndex, "User Supplied Object");
XPSetWidgetDescriptor(SDK200TestsEdit[4], Buffer);
return 1;
}
if (inParam1 == (intptr_t)SDK200TestsButton6)
{
if (XPLMLoadDataFile(xplm_DataFile_Situation, "Output/situations/test.sit"))
XPLMDebugString("XPLMLoadDataFile (.sit) successful\n");
else
XPLMDebugString("XPLMLoadDataFile (.sit) failed\n");
return 1;
}
if (inParam1 == (intptr_t)SDK200TestsButton7)
{
if (XPLMSaveDataFile(xplm_DataFile_Situation, "Output/situations/test.sit"))
XPLMDebugString("XPLMSaveDataFile (.sit) successful\n");
else
XPLMDebugString("XPLMSaveDataFile (.sit) failed\n");
return 1;
}
if (inParam1 == (intptr_t)SDK200TestsButton8)
{
if (XPLMLoadDataFile(xplm_DataFile_ReplayMovie, "Output/replays/test.rep"))
XPLMDebugString("XPLMLoadDataFile (.smo) successful\n");
else
XPLMDebugString("XPLMLoadDataFile (.smo) failed\n");
return 1;
}
if (inParam1 == (intptr_t)SDK200TestsButton9)
{
if (XPLMSaveDataFile(xplm_DataFile_ReplayMovie, "Output/replays/test.rep"))
XPLMDebugString("XPLMSaveDataFile (.smo) successful\n");
else
XPLMDebugString("XPLMSaveDataFile (.smo) failed\n");
return 1;
}
}
return 0;
}
//---------------------------------------------------------------------------
/*
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;
}
/*
Reload Plugin
Written by Sandy Barbour - 24/02/2004
This examples shows how reload plugins
This is handy for debugging as you don't have to stop XPlane
*/
#if IBM
#include <windows.h>
#endif
#include <string.h>
#include <stdio.h>
#include "XPLMPlugin.h"
#include "XPLMMenus.h"
static void ReloadPluginsMenuHandler(void * mRef, void * iRef);
/*
* XPluginStart
*
* Our start routine registers our window and does any other initialization we
* must do.
*
*/
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
/* First we must fill in the passed in buffers to describe our
* plugin to the plugin-system. */
XPLMMenuID id;
int item;
strcpy(outName, "ReloadPlugins");
strcpy(outSig, "xplanesdk.sandybarbour.ReloadPlugins");
strcpy(outDesc, "A plugin that allows plugins to be reloaded.");
item = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "ReloadPlugins", NULL, 1);
id = XPLMCreateMenu("ReloadPlugins", XPLMFindPluginsMenu(), item, ReloadPluginsMenuHandler, NULL);
XPLMAppendMenuItem(id, "Reload", (void *)"Reload plugins",1);
/* We must return 1 to indicate successful initialization, otherwise we
* will not be called back again. */
return 1;
}
/*
* XPluginStop
*
* Our cleanup routine deallocates our window.
*
*/
PLUGIN_API void XPluginStop(void)
{
}
/*
* XPluginDisable
*
* We do not need to do anything when we are disabled, but we must provide the handler.
*
*/
PLUGIN_API void XPluginDisable(void)
{
}
/*
* XPluginEnable.
*
* We don't do any enable-specific initialization, but we must return 1 to indicate
* that we may be enabled at this time.
*
*/
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
/*
* XPluginReceiveMessage
*
* We don't have to do anything in our receive message handler, but we must provide one.
*
*/
PLUGIN_API void XPluginReceiveMessage(
XPLMPluginID inFromWho,
int inMessage,
void * inParam)
{
}
void ReloadPluginsMenuHandler(void * mRef, void * iRef)
{
if (!strcmp((char *) iRef, "Reload plugins"))
{
XPLMReloadPlugins();
}
}
/*
TestWidgets Example
Written by Sandy Barbour - 21/02/2003
Modified by Sandy Barbour - 08/12/2009 // How time flies when you are having fun. :-)
Combined example plugin with the Custom Widget creation code.
This example shows how to create 2 custom widgets.
These are then used by the example plugin.
*/
#if IBM
#include <windows.h>
#endif
#if LIN
#include <GL/gl.h>
#else
#if __GNUC__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#endif
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMMenus.h"
#include "XPLMUtilities.h"
#include "XPWidgets.h"
#include "XPStandardWidgets.h"
#include "XPLMCamera.h"
#include "XPUIGraphics.h"
#include "XPWidgetUtils.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <string>
/*------------------------------------------------------------------------*/
/*
* XPWidgetsEx.h
*
* Copyright 2005 Sandy Barbour and Ben Supnik
*
* All rights reserved. See license.txt for usage.
*
* X-Plane SDK Version: 1.0.2
*
*/
/************************************************************************
* POPUP MENU PICKS
************************************************************************
*
* This code helps do a popup menu item pick. Since x-plane must be
* running to track the mouse, this popup menu pick is effectively
* asynchronous and non-modal to the code...you call the function and
* some time later your callback is called.
*
* However, due to the way the popup pick is structured, it will appear to
* be somewhat modal to the user in that the next click after the popup
* is called must belong to it.
*
*/
/*
* XPPopupPick_f
*
* This function is called when your popup is picked. inChoice will be the number
* of the item picked, or -1 if no item was picked. (You should almost always ignore
* a -1.
*
*/
typedef void (* XPPopupPick_f)(int inChoice, void * inRefcon);
/*
* XPPickPopup
*
* This routine creates a dynamic 'popup menu' on the fly. If inCurrentItem is
* non-negative, it is the item that will be under the mouse. In this case, the
* mouse X and Y should be the top left of a popup box if there is such a thing.
* If inCurrentItem is -1, the popup menu appears at exactly inMouseX and inMouseY.
*
* You pass in the items, newline terminated ('\n') as well as a callback that is
* called when an item is picked, and a ref con for that function.
*
*/
static void XPPickPopup(
int inMouseX,
int inMouseY,
const char * inItems,
int inCurrentItem,
XPPopupPick_f inCallback,
void * inRefcon);
/* Impl notes: we can dispose from the mouse up. So...on mouse up
* we first call the popup func but then we nuke ourselves. Internally
* there is a data structure that is in the refcon of the xplm window that
* contains the callback for the user and the text, etc. */
/************************************************************************
* POPUP MENU BUTTON WIDGET
************************************************************************
*
* This widget implements a stanard pick-one-from-many-style popup menu
* button. The text is taken from the current item. The descriptor is
* the items, newline-terminated.
*
* A message is sent whenever a new item is picked by the user.
*
*/
#define xpWidgetClass_Popup 9
enum {
// This is the item number of the current item, starting at 0.
xpProperty_PopupCurrentItem = 1800
};
enum {
// This message is sent when an item is picked.
// param 1 is the widget that was picked, param 2
// is the item number.
xpMessage_PopupNewItemPicked = 1800
};
/*
* XPCreatePopup
*
* This routine makes a popup widget for you. You must provide
* a container for this widget, like a window for it to sit in.
*
*/
static XPWidgetID XPCreatePopup(
int inLeft,
int inTop,
int inRight,
int inBottom,
int inVisible,
const char * inDescriptor,
XPWidgetID inContainer);
static int XPPopupButtonProc(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2);
/************************************************************************
* LISTBOX
************************************************************************
*
* This code helps do a listbox. Since x-plane must be
* running to track the mouse, this listbox is effectively
* asynchronous and non-modal to the code...you call the function and
* some time later your callback is called.
*
* However, due to the way the listbox is structured, it will appear to
* be somewhat modal to the user in that the next click after the listbox
* is called must belong to it.
*
*/
/************************************************************************
* LISTBOX SELECTION WIDGET
************************************************************************
*
* This widget implements a standard pick-one-from-many-style selection menu
* button. The text is taken from the current item. The descriptor is
* the items, newline-terminated.
*
* A message is sent whenever a new item is picked by the user.
*
*/
#define xpWidgetClass_ListBox 10
enum {
// This is the item number of the current item, starting at 0.
xpProperty_ListBoxCurrentItem = 1900,
// This will add an item to the list box at the end.
xpProperty_ListBoxAddItem = 1901,
// This will clear the list box and then add the items.
xpProperty_ListBoxAddItemsWithClear = 1902,
// This will clear the list box.
xpProperty_ListBoxClear = 1903,
// This will insert an item into the list box at the index.
xpProperty_ListBoxInsertItem = 1904,
// This will delete an item from the list box at the index.
xpProperty_ListBoxDeleteItem = 1905,
// This stores the pointer to the listbox data.
xpProperty_ListBoxData = 1906,
// This stores the max Listbox Items.
xpProperty_ListBoxMaxListBoxItems = 1907,
// This stores the highlight state.
xpProperty_ListBoxHighlighted = 1908,
// This stores the scrollbar Min.
xpProperty_ListBoxScrollBarMin = 1909,
// This stores the scrollbar Max.
xpProperty_ListBoxScrollBarMax = 1910,
// This stores the scrollbar SliderPosition.
xpProperty_ListBoxScrollBarSliderPosition = 1911,
// This stores the scrollbar ScrollBarPageAmount.
xpProperty_ListBoxScrollBarPageAmount = 1912
};
enum {
// This message is sent when an item is picked.
// param 1 is the widget that was picked, param 2
// is the item number.
xpMessage_ListBoxItemSelected = 1900
};
/*
* XPCreateListBox
*
* This routine makes a listbox widget for you. You must provide
* a container for this widget, like a window for it to sit in.
*
*/
static XPWidgetID XPCreateListBox(
int inLeft,
int inTop,
int inRight,
int inBottom,
int inVisible,
const char * inDescriptor,
XPWidgetID inContainer);
static int XPListBoxProc(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2);
/*------------------------------------------------------------------------*/
static int MenuItem1;
static XPWidgetID TestWidgetsWidget, TestWidgetsWindow;
static XPWidgetID TestWidgetsPopup, TestWidgetsListBox;
static XPWidgetID ListboxInfoText1, ListboxInfoText2, ListboxAddItemButton, ListboxFillButton, ListboxClearButton, ListboxInsertButton, ListboxDeleteItemButton, ListboxInputTextEdit;
static XPWidgetID PopupInfoText, PopupInputTextEdit, PopupSetIndexButton;
static XPLMMenuID id;
static char szPopupText[4096];
static char szListBoxText[4096];
static void TestWidgetsMenuHandler(void *, void *);
static void CreateTestWidgets(int x1, int y1, int w, int h);
// Handle any widget messages
static int TestWidgetsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2);
/*------------------------------------------------------------------------*/
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
int item;
strcpy(outName, "TestWidgets");
strcpy(outSig, "xpsdk.examples.TestWidgets");
strcpy(outDesc, "A plug-in that tests new widgets.");
// Build menu
item = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "Test Widgets", NULL, 1);
id = XPLMCreateMenu("Test Widgets", XPLMFindPluginsMenu(), item, TestWidgetsMenuHandler, NULL);
XPLMAppendMenuItem(id, "Open", (void *)"Open", 1);
// Used by widget to make sure only one widgets instance created
MenuItem1 = 0;
// Preload Popup
szPopupText[0] = '\0';
strcat( szPopupText, "Some longer text line 1");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 2");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 3");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 4");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 5");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 6");
strcat( szPopupText, ";" );
strcat( szPopupText, "Some longer text line 7");
strcat( szPopupText, ";" );
// Preload Listbox
szListBoxText[0] = '\0';
strcat( szListBoxText, "1234567890123456789012345678901234567890123456789012345678901234567890");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 2");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 3");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 4");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 5");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 6");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 7");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 8");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 9");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 10");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 11");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 12");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 13");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 14");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 15");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 16");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 17");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 18");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 19");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 20");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 21");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 22");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 23");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 24");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 25");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 26");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 27");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 28");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 29");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 30");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 31");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 32");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 33");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 34");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 35");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 36");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 37");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 38");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 39");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 40");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 41");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 42");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 43");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 44");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 45");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 46");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 47");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 48");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 49");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 50");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 51");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 52");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 53");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 54");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 55");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 56");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 57");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 58");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 59");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 60");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 61");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 62");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 63");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 64");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 65");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 66");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 67");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 68");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 69");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 70");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 71");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 72");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 73");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 74");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 75");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 76");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 77");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 78");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 79");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 80");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 81");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 82");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 83");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 84");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 85");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 86");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 87");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 88");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 89");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 90");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 91");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 92");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 93");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 94");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 95");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 96");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 97");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 98");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 99");
strcat( szListBoxText, ";" );
strcat( szListBoxText, "Item 100");
strcat( szListBoxText, ";" );
return 1;
}
/*------------------------------------------------------------------------*/
PLUGIN_API void XPluginStop(void)
{
// Clean up
XPLMDestroyMenu(id);
if (MenuItem1 == 1)
{
XPDestroyWidget(TestWidgetsWidget, 1);
MenuItem1 = 0;
}
}
/*------------------------------------------------------------------------*/
PLUGIN_API void XPluginDisable(void)
{
}
/*------------------------------------------------------------------------*/
PLUGIN_API int XPluginEnable(void)
{
return 1;
}
/*------------------------------------------------------------------------*/
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam)
{
}
/*------------------------------------------------------------------------*/
// Handle any menu messages, only one, to created widget dialog
void TestWidgetsMenuHandler(void * mRef, void * iRef)
{
if (!strcmp((char *) iRef, "Open"))
{
if (MenuItem1 == 0)
{
CreateTestWidgets(300, 650, 450, 600);
MenuItem1 = 1;
}
else
if(!XPIsWidgetVisible(TestWidgetsWidget))
XPShowWidget(TestWidgetsWidget);
}
}
/*------------------------------------------------------------------------*/
// This creates the widgets dialog and any controls
void CreateTestWidgets(int x, int y, int w, int h)
{
int x2 = x + w;
int y2 = y - h;
TestWidgetsWidget = XPCreateWidget(x, y, x2, y2,
1, // Visible
"Test Widgets", // desc
1, // root
NULL, // no container
xpWidgetClass_MainWindow);
XPSetWidgetProperty(TestWidgetsWidget, xpProperty_MainWindowHasCloseBoxes, 1);
TestWidgetsWindow = XPCreateWidget(x+50, y-40, x2-50, y2+30,
1, // Visible
"", // desc
0, // root
TestWidgetsWidget,
xpWidgetClass_SubWindow);
XPSetWidgetProperty(TestWidgetsWindow, xpProperty_SubWindowType, xpSubWindowStyle_SubWindow);
TestWidgetsPopup = XPCreatePopup( x+70, y-50, x2-70, y-72,
1, szPopupText, TestWidgetsWidget );
PopupInfoText = XPCreateWidget(x+70, y-80, x2-70, y-102,
1, "Popup Index 0", 0, TestWidgetsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(PopupInfoText, xpProperty_TextFieldType, xpTextEntryField);
PopupSetIndexButton = XPCreateWidget(x+70, y-110, x+170, y-132,
1, " Set Popup Index", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(PopupSetIndexButton, xpProperty_ButtonType, xpPushButton);
PopupInputTextEdit = XPCreateWidget(x+180, y-110, x2-70, y-132,
1, "0", 0, TestWidgetsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(PopupInputTextEdit, xpProperty_TextFieldType, xpTextEntryField);
TestWidgetsListBox = XPCreateListBox( x+70, y-140, x2-70, y-340,
1, szListBoxText, TestWidgetsWidget );
ListboxInfoText1 = XPCreateWidget(x+70, y-350, x2-70, y-372,
1, "", 0, TestWidgetsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(ListboxInfoText1, xpProperty_TextFieldType, xpTextEntryField);
ListboxInfoText2 = XPCreateWidget(x+70, y-390, x2-70, y-392,
1, "", 0, TestWidgetsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(ListboxInfoText2, xpProperty_TextFieldType, xpTextEntryField);
ListboxAddItemButton = XPCreateWidget(x+70, y-400, x+130, y-422,
1, " Add Item", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(ListboxAddItemButton, xpProperty_ButtonType, xpPushButton);
ListboxFillButton = XPCreateWidget(x+140, y-400, x+200, y-422,
1, " Fill LB", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(ListboxFillButton, xpProperty_ButtonType, xpPushButton);
ListboxClearButton = XPCreateWidget(x+210, y-400, x+270, y-422,
1, " Clear LB", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(ListboxClearButton, xpProperty_ButtonType, xpPushButton);
ListboxInsertButton = XPCreateWidget(x+70, y-430, x+140, y-452,
1, " Insert Item", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(ListboxInsertButton, xpProperty_ButtonType, xpPushButton);
ListboxDeleteItemButton = XPCreateWidget(x+150, y-430, x+220, y-452,
1, " Delete Item", 0, TestWidgetsWidget,
xpWidgetClass_Button);
XPSetWidgetProperty(ListboxDeleteItemButton, xpProperty_ButtonType, xpPushButton);
ListboxInputTextEdit = XPCreateWidget(x+70, y-460, x2-70, y-492,
1, "Add Me", 0, TestWidgetsWidget,
xpWidgetClass_TextField);
XPSetWidgetProperty(ListboxInputTextEdit, xpProperty_TextFieldType, xpTextEntryField);
XPAddWidgetCallback(TestWidgetsWidget, TestWidgetsHandler);
}
/*------------------------------------------------------------------------*/
// Handle any widget messages
int TestWidgetsHandler(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2)
{
char Buffer[256];
// Close button pressed, only hide the widget, rather than destropying it.
if (inMessage == xpMessage_CloseButtonPushed)
{
if (MenuItem1 == 1)
{
XPHideWidget(TestWidgetsWidget);
}
return 1;
}
// Test for a button pressed
if (inMessage == xpMsg_PushButtonPressed)
{
// This test adds three items to the listbox
if (inParam1 == (intptr_t)ListboxAddItemButton)
{
strcpy(Buffer, "Line 1");
XPSetWidgetDescriptor(TestWidgetsListBox, Buffer);
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxAddItem, 1);
strcpy(Buffer, "Line 2");
XPSetWidgetDescriptor(TestWidgetsListBox, Buffer);
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxAddItem, 1);
strcpy(Buffer, "Line 3");
XPSetWidgetDescriptor(TestWidgetsListBox, Buffer);
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxAddItem, 1);
return 1;
}
// This test clears the list box and then adds the test items
if (inParam1 == (intptr_t)ListboxFillButton)
{
XPSetWidgetDescriptor(TestWidgetsListBox, szListBoxText);
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxAddItemsWithClear, 1);
return 1;
}
// This test clears the listbox
if (inParam1 == (intptr_t)ListboxClearButton)
{
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxClear, 1);
return 1;
}
// This test inserts the text entered into ListboxInputTextEdit at the
// current selected listbox item position
if (inParam1 == (intptr_t)ListboxInsertButton)
{
XPGetWidgetDescriptor(ListboxInputTextEdit, Buffer, sizeof(Buffer));
XPSetWidgetDescriptor(TestWidgetsListBox, Buffer);
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxInsertItem, 1);
return 1;
}
// This test deletes the current selected listbox item
if (inParam1 == (intptr_t)ListboxDeleteItemButton)
{
XPSetWidgetProperty(TestWidgetsListBox, xpProperty_ListBoxDeleteItem, 1);
return 1;
}
// This test set the popup index to the number
// entered into the PopupInputTextEdit edit box
if (inParam1 == (intptr_t)PopupSetIndexButton)
{
XPGetWidgetDescriptor(PopupInputTextEdit, Buffer, sizeof(Buffer));
int curItem = atoi(Buffer);
XPSetWidgetProperty(TestWidgetsPopup, xpProperty_PopupCurrentItem, curItem);
XPGetWidgetDescriptor(TestWidgetsPopup, Buffer, sizeof(Buffer));
curItem = XPGetWidgetProperty(TestWidgetsPopup, xpProperty_PopupCurrentItem, NULL);
sprintf(Buffer, "Popup Index %d", curItem);
XPSetWidgetDescriptor(PopupInfoText, Buffer);
return 1;
}
}
// This handles the listbox item selected message
// i.e. when you click on an item
if (inMessage == xpMessage_ListBoxItemSelected)
{
XPGetWidgetDescriptor(TestWidgetsListBox, Buffer, sizeof(Buffer));
XPSetWidgetDescriptor(ListboxInfoText1, Buffer);
sprintf(Buffer, "ListBox Index %d", inParam2);
XPSetWidgetDescriptor(ListboxInfoText2, Buffer);
return 1;
}
// This handles the popup item picked message
// i.e. when you selecte another popup entry.
if (inMessage == xpMessage_PopupNewItemPicked)
{
XPGetWidgetDescriptor(TestWidgetsPopup, Buffer, sizeof(Buffer));
int curItem = XPGetWidgetProperty(TestWidgetsPopup, xpProperty_PopupCurrentItem, NULL);
sprintf(Buffer, "Popup Index %d", curItem);
XPSetWidgetDescriptor(PopupInfoText, Buffer);
return 1;
}
return 0;
}
/*------------------------------------------------------------------------*/
/*
* XPListBox.cpp
*
* Copyright 2005 Sandy Barbour and Ben Supnik
*
* All rights reserved. See license.txt for usage.
*
* X-Plane SDK Version: 1.0.2
*
*/
#define LISTBOX_ITEM_HEIGHT 12
#define IN_RECT(x, y, l, t, r, b) \
(((x) >= (l)) && ((x) <= (r)) && ((y) >= (b)) && ((y) <= (t)))
#if IBM
static double round(double InValue)
{
int WholeValue;
double Fraction;
WholeValue = InValue;
Fraction = InValue - (double) WholeValue;
if (Fraction >= 0.5)
WholeValue++;
return (double) WholeValue;
}
#endif
/************************************************************************
* X-PLANE UI INFRASTRUCTURE CODE
************************************************************************
*
* This code helps provde an x-plane compatible look. It is copied from
* the source code from the widgets DLL; someday listyboxes will be part of
* this, so our listboxes are written off of the same APIs.
*
*/
// Enums for x-plane native colors.
enum {
xpColor_MenuDarkTinge = 0,
xpColor_MenuBkgnd,
xpColor_MenuHilite,
xpColor_MenuLiteTinge,
xpColor_MenuText,
xpColor_MenuTextDisabled,
xpColor_SubTitleText,
xpColor_TabFront,
xpColor_TabBack,
xpColor_CaptionText,
xpColor_ListText,
xpColor_GlassText,
xpColor_Count
};
// Enums for the datarefs we get them from.
static const char * kXPlaneColorNames[] = {
"sim/graphics/colors/menu_dark_rgb",
"sim/graphics/colors/menu_bkgnd_rgb",
"sim/graphics/colors/menu_hilite_rgb",
"sim/graphics/colors/menu_lite_rgb",
"sim/graphics/colors/menu_text_rgb",
"sim/graphics/colors/menu_text_disabled_rgb",
"sim/graphics/colors/subtitle_text_rgb",
"sim/graphics/colors/tab_front_rgb",
"sim/graphics/colors/tab_back_rgb",
"sim/graphics/colors/caption_text_rgb",
"sim/graphics/colors/list_text_rgb",
"sim/graphics/colors/glass_text_rgb"
};
// Those datarefs are only XP7; if we can't find one,
// fall back to this table of X-Plane 6 colors.
static const float kBackupColors[xpColor_Count][3] =
{
{ (const float)(33.0/256.0), (const float)(41.0/256.0), (const float)(44.0/256.0) },
{ (const float)(53.0/256.0), (const float)(64.0/256.0), (const float)(68.0/256.0) },
{ (const float)(65.0/256.0), (const float)(83.0/256.0), (const float)(89.0/256.0) },
{ (const float)(65.0/256.0), (const float)(83.0/256.0), (const float)(89.0/256.0) },
{ (const float)0.8, (const float)0.8, (const float)0.8 },
{ (const float)0.4, (const float)0.4, (const float)0.4 }
};
// This array contains the resolved datarefs
static XPLMDataRef gColorRefs[xpColor_Count];
// Current alpha levels to blit at.
static float gAlphaLevel = 1.0;
// This routine sets up a color from the above table. Pass
// in a float[3] to get the color; pass in NULL to have the
// OpenGL color be set immediately.
static void SetupAmbientColor(int inColorID, float * outColor)
{
// If we're running the first time, resolve all of our datarefs just once.
static bool firstTime = true;
if (firstTime)
{
firstTime = false;
for (int n = 0; n <xpColor_Count; ++n)
{
gColorRefs[n] = XPLMFindDataRef(kXPlaneColorNames[n]);
}
}
// If being asked to set the color immediately, allocate some storage.
float theColor[4];
float * target = outColor ? outColor : theColor;
// If we have a dataref, just fetch the color from the ref.
if (gColorRefs[inColorID])
XPLMGetDatavf(gColorRefs[inColorID], target, 0, 3);
else {
// If we didn't have a dataref, fetch the ambient cabin lighting,
// since XP6 dims the UI with night.
static XPLMDataRef ambient_r = XPLMFindDataRef("sim/graphics/misc/cockpit_light_level_r");
static XPLMDataRef ambient_g = XPLMFindDataRef("sim/graphics/misc/cockpit_light_level_g");
static XPLMDataRef ambient_b = XPLMFindDataRef("sim/graphics/misc/cockpit_light_level_b");
// Use a backup color but dim it.
target[0] = kBackupColors[inColorID][0] * XPLMGetDataf(ambient_r);
target[1] = kBackupColors[inColorID][1] * XPLMGetDataf(ambient_g);
target[2] = kBackupColors[inColorID][2] * XPLMGetDataf(ambient_b);
}
// If the user passed NULL, set the color now using the alpha level.
if (!outColor)
{
theColor[3] = gAlphaLevel;
glColor4fv(theColor);
}
}
// Just remember alpha levels for later.
static void SetAlphaLevels(float inAlphaLevel)
{
gAlphaLevel = inAlphaLevel;
}
#ifndef _WINDOWS
#pragma mark -
#endif
/************************************************************************
* LISTBOX DATA IMPLEMENTATION
************************************************************************/
// This structure represents a listbox internally...it consists of arrays
// per item and some general stuff.
struct XPListBoxData_t {
// Per item:
std::vector<std::string> Items; // The name of the item
std::vector<int> Lefts; // The rectangle of the item, relative to the top left corner of the listbox/
std::vector<int> Rights;
};
static XPListBoxData_t *pListBoxData;
// This routine finds the item that is in a given point, or returns -1 if there is none.
// It simply trolls through all the items.
static int XPListBoxGetItemNumber(XPListBoxData_t * pListBoxData, int inX, int inY)
{
for (unsigned int n = 0; n < pListBoxData->Items.size(); ++n)
{
if ((inX >= pListBoxData->Lefts[n]) && (inX < pListBoxData->Rights[n]) &&
(inY >= (n * LISTBOX_ITEM_HEIGHT)) && (inY < ((n * LISTBOX_ITEM_HEIGHT) + LISTBOX_ITEM_HEIGHT)))
{
return n;
}
}
return -1;
}
static void XPListBoxFillWithData(XPListBoxData_t *pListBoxData, const char *inItems, int Width)
{
std::string Items(inItems);
while (!Items.empty())
{
std::string::size_type split = Items.find(';');
if (split == Items.npos)
{
split = Items.size();
}
std::string Item = Items.substr(0, split);
pListBoxData->Items.push_back(Item);
pListBoxData->Lefts.push_back(0);
pListBoxData->Rights.push_back(Width);
if (Item.size() == Items.size())
break;
else
Items = Items.substr(split+1);
}
}
static void XPListBoxAddItem(XPListBoxData_t *pListBoxData, char *pBuffer, int Width)
{
std::string Item(pBuffer);
pListBoxData->Items.push_back(Item);
pListBoxData->Lefts.push_back(0);
pListBoxData->Rights.push_back(Width);
}
static void XPListBoxClear(XPListBoxData_t *pListBoxData)
{
pListBoxData->Items.clear();
pListBoxData->Lefts.clear();
pListBoxData->Rights.clear();
}
static void XPListBoxInsertItem(XPListBoxData_t *pListBoxData, char *pBuffer, int Width, int CurrentItem)
{
std::string Item(pBuffer);
pListBoxData->Items.insert(pListBoxData->Items.begin() + CurrentItem, Item);
pListBoxData->Lefts.insert(pListBoxData->Lefts.begin() + CurrentItem, 0);
pListBoxData->Rights.insert(pListBoxData->Rights.begin() + CurrentItem, Width);
}
static void XPListBoxDeleteItem(XPListBoxData_t *pListBoxData, int CurrentItem)
{
pListBoxData->Items.erase(pListBoxData->Items.begin() + CurrentItem);
pListBoxData->Lefts.erase(pListBoxData->Lefts.begin() + CurrentItem);
pListBoxData->Rights.erase(pListBoxData->Rights.begin() + CurrentItem);
}
#ifndef _WINDOWS
#pragma mark -
#endif
// This widget Proc implements the actual listbox.
static int XPListBoxProc(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2)
{
static int ScrollBarSlop;
// Select if we're in the background.
if (XPUSelectIfNeeded(inMessage, inWidget, inParam1, inParam2, 1/*eat*/)) return 1;
int Left, Top, Right, Bottom, x, y, ListBoxDataOffset, ListBoxIndex;
char Buffer[4096];
int IsVertical, DownBtnSize, DownPageSize, ThumbSize, UpPageSize, UpBtnSize;
bool UpBtnSelected, DownBtnSelected, ThumbSelected, UpPageSelected, DownPageSelected;
XPGetWidgetGeometry(inWidget, &Left, &Top, &Right, &Bottom);
int SliderPosition = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, NULL);
int Min = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMin, NULL);
int Max = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, NULL);
int ScrollBarPageAmount = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarPageAmount, NULL);
int CurrentItem = XPGetWidgetProperty(inWidget, xpProperty_ListBoxCurrentItem, NULL);
int MaxListBoxItems = XPGetWidgetProperty(inWidget, xpProperty_ListBoxMaxListBoxItems, NULL);
int Highlighted = XPGetWidgetProperty(inWidget, xpProperty_ListBoxHighlighted, NULL);
XPListBoxData_t *pListBoxData = (XPListBoxData_t*) XPGetWidgetProperty(inWidget, xpProperty_ListBoxData, NULL);
switch(inMessage)
{
case xpMsg_Create:
// Allocate mem for the structure.
pListBoxData = new XPListBoxData_t;
XPGetWidgetDescriptor(inWidget, Buffer, sizeof(Buffer));
XPListBoxFillWithData(pListBoxData, Buffer, (Right - Left - 20));
XPSetWidgetProperty(inWidget, xpProperty_ListBoxData, (intptr_t)pListBoxData);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxCurrentItem, 0);
Min = 0;
Max = pListBoxData->Items.size();
ScrollBarSlop = 0;
Highlighted = false;
SliderPosition = Max;
MaxListBoxItems = (Top - Bottom) / LISTBOX_ITEM_HEIGHT;
ScrollBarPageAmount = MaxListBoxItems;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMin, Min);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, Max);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarPageAmount, ScrollBarPageAmount);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxMaxListBoxItems, MaxListBoxItems);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxHighlighted, Highlighted);
return 1;
case xpMsg_DescriptorChanged:
return 1;
case xpMsg_PropertyChanged:
if (XPGetWidgetProperty(inWidget, xpProperty_ListBoxAddItem, NULL))
{
XPSetWidgetProperty(inWidget, xpProperty_ListBoxAddItem, 0);
XPGetWidgetDescriptor(inWidget, Buffer, sizeof(Buffer));
XPListBoxAddItem(pListBoxData, Buffer, (Right - Left - 20));
Max = pListBoxData->Items.size();
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, Max);
}
if (XPGetWidgetProperty(inWidget, xpProperty_ListBoxAddItemsWithClear, NULL))
{
XPSetWidgetProperty(inWidget, xpProperty_ListBoxAddItemsWithClear, 0);
XPGetWidgetDescriptor(inWidget, Buffer, sizeof(Buffer));
XPListBoxClear(pListBoxData);
XPListBoxFillWithData(pListBoxData, Buffer, (Right - Left - 20));
Max = pListBoxData->Items.size();
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, Max);
}
if (XPGetWidgetProperty(inWidget, xpProperty_ListBoxClear, NULL))
{
XPSetWidgetProperty(inWidget, xpProperty_ListBoxClear, 0);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxCurrentItem, 0);
XPListBoxClear(pListBoxData);
Max = pListBoxData->Items.size();
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, Max);
}
if (XPGetWidgetProperty(inWidget, xpProperty_ListBoxInsertItem, NULL))
{
XPSetWidgetProperty(inWidget, xpProperty_ListBoxInsertItem, 0);
XPGetWidgetDescriptor(inWidget, Buffer, sizeof(Buffer));
XPListBoxInsertItem(pListBoxData, Buffer, (Right - Left - 20), CurrentItem);
}
if (XPGetWidgetProperty(inWidget, xpProperty_ListBoxDeleteItem, NULL))
{
XPSetWidgetProperty(inWidget, xpProperty_ListBoxDeleteItem, 0);
if ((pListBoxData->Items.size() > 0) && (pListBoxData->Items.size() > CurrentItem))
XPListBoxDeleteItem(pListBoxData, CurrentItem);
}
return 1;
case xpMsg_Draw:
{
int x, y;
XPLMGetMouseLocation(&x, &y);
XPDrawWindow(Left, Bottom, Right-20, Top, xpWindow_ListView);
XPDrawTrack(Right-20, Bottom, Right, Top, Min, Max, SliderPosition, xpTrack_ScrollBar, Highlighted);
XPLMSetGraphicsState(0, 1, 0, 0, 1, 0, 0);
XPLMBindTexture2d(XPLMGetTexture(xplm_Tex_GeneralInterface), 0);
glColor4f(1.0, 1.0, 1.0, 1.0);
unsigned int ItemNumber;
XPLMSetGraphicsState(0, 0, 0, 0, 0, 0, 0);
// Now draw each item.
ListBoxIndex = Max - SliderPosition;
ItemNumber = 0;
while (ItemNumber < MaxListBoxItems)
{
if (ListBoxIndex < pListBoxData->Items.size())
{
// Calculate the item rect in global coordinates.
int ItemTop = Top - (ItemNumber * LISTBOX_ITEM_HEIGHT);
int ItemBottom = Top - ((ItemNumber * LISTBOX_ITEM_HEIGHT) + LISTBOX_ITEM_HEIGHT);
// If we are hilited, draw the hilite bkgnd.
if (CurrentItem == ListBoxIndex)
{
SetAlphaLevels(0.25);
XPLMSetGraphicsState(0, 0, 0, 0, 1, 0, 0);
SetupAmbientColor(xpColor_MenuHilite, NULL);
SetAlphaLevels(1.0);
glBegin(GL_QUADS);
glVertex2i(Left, ItemTop);
glVertex2i(Right-20, ItemTop);
glVertex2i(Right-20, ItemBottom);
glVertex2i(Left, ItemBottom);
glEnd();
}
float text[3];
SetupAmbientColor(xpColor_ListText, text);
char Buffer[512];
int FontWidth, FontHeight;
int ListBoxWidth = (Right - 20) - Left;
strcpy(Buffer, pListBoxData->Items[ListBoxIndex++].c_str());
XPLMGetFontDimensions(xplmFont_Basic, &FontWidth, &FontHeight, NULL);
int MaxChars = ListBoxWidth / FontWidth;
Buffer[MaxChars] = 0;
XPLMDrawString(text,
Left, ItemBottom + 2,
const_cast<char *>(Buffer), NULL, xplmFont_Basic);
}
ItemNumber++;
}
}
return 1;
case xpMsg_MouseUp:
if (IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Top, Right, Bottom))
{
Highlighted = false;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxHighlighted, Highlighted);
}
if (IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Left, Top, Right-20, Bottom))
{
if (pListBoxData->Items.size() > 0)
{
if (CurrentItem != -1)
XPSetWidgetDescriptor(inWidget, pListBoxData->Items[CurrentItem].c_str());
else
XPSetWidgetDescriptor(inWidget, "");
XPSendMessageToWidget(inWidget, xpMessage_ListBoxItemSelected, xpMode_UpChain, (intptr_t) inWidget, (intptr_t) CurrentItem);
}
}
return 1;
case xpMsg_MouseDown:
if (IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Left, Top, Right-20, Bottom))
{
if (pListBoxData->Items.size() > 0)
{
XPLMGetMouseLocation(&x, &y);
ListBoxDataOffset = XPListBoxGetItemNumber(pListBoxData, x - Left, Top - y);
if (ListBoxDataOffset != -1)
{
ListBoxDataOffset += (Max - SliderPosition);
if (ListBoxDataOffset < pListBoxData->Items.size())
XPSetWidgetProperty(inWidget, xpProperty_ListBoxCurrentItem, ListBoxDataOffset);
}
}
}
if (IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Top, Right, Bottom))
{
XPGetTrackMetrics(Right-20, Bottom, Right, Top, Min, Max, SliderPosition, xpTrack_ScrollBar, &IsVertical, &DownBtnSize, &DownPageSize, &ThumbSize, &UpPageSize, &UpBtnSize);
int Min = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMin, NULL);
int Max = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, NULL);
if (IsVertical)
{
UpBtnSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Top, Right, Top - UpBtnSize);
DownBtnSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Bottom + DownBtnSize, Right, Bottom);
UpPageSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, (Top - UpBtnSize), Right, (Bottom + DownBtnSize + DownPageSize + ThumbSize));
DownPageSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, (Top - UpBtnSize - UpPageSize - ThumbSize), Right, (Bottom + DownBtnSize));
ThumbSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, (Top - UpBtnSize - UpPageSize), Right, (Bottom + DownBtnSize + DownPageSize));
}
else
{
DownBtnSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Top, Right-20 + UpBtnSize, Bottom);
UpBtnSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20 - DownBtnSize, Top, Right, Bottom);
DownPageSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20 + DownBtnSize, Top, Right - UpBtnSize - UpPageSize - ThumbSize, Bottom);
UpPageSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20 + DownBtnSize + DownPageSize + ThumbSize, Top, Right - UpBtnSize, Bottom);
ThumbSelected = IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20 + DownBtnSize + DownPageSize, Top, Right - UpBtnSize - UpPageSize, Bottom);
}
if (UpPageSelected)
{
SliderPosition+=ScrollBarPageAmount;
if (SliderPosition > Max)
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
}
else if (DownPageSelected)
{
SliderPosition-=ScrollBarPageAmount;
if (SliderPosition < Min)
SliderPosition = Min;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
}
else if (UpBtnSelected)
{
SliderPosition++;
if (SliderPosition > Max)
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
}
else if (DownBtnSelected)
{
SliderPosition--;
if (SliderPosition < Min)
SliderPosition = Min;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
}
else if (ThumbSelected)
{
if (IsVertical)
ScrollBarSlop = Bottom + DownBtnSize + DownPageSize + (ThumbSize/2) - MOUSE_Y(inParam1);
else
ScrollBarSlop = Right-20 + DownBtnSize + DownPageSize + (ThumbSize/2) - MOUSE_X(inParam1);
Highlighted = true;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxHighlighted, Highlighted);
}
else
{
Highlighted = false;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxHighlighted, Highlighted);
}
}
return 1;
case xpMsg_MouseDrag:
if (IN_RECT(MOUSE_X(inParam1), MOUSE_Y(inParam1), Right-20, Top, Right, Bottom))
{
XPGetTrackMetrics(Right-20, Bottom, Right, Top, Min, Max, SliderPosition, xpTrack_ScrollBar, &IsVertical, &DownBtnSize, &DownPageSize, &ThumbSize, &UpPageSize, &UpBtnSize);
int Min = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMin, NULL);
int Max = XPGetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarMax, NULL);
ThumbSelected = Highlighted;
if (ThumbSelected)
{
if (inParam1 != 0)
{
if (IsVertical)
{
y = MOUSE_Y(inParam1) + ScrollBarSlop;
SliderPosition = round((float)((float)(y - (Bottom + DownBtnSize + ThumbSize/2)) /
(float)((Top - UpBtnSize - ThumbSize/2) - (Bottom + DownBtnSize + ThumbSize/2))) * Max);
}
else
{
x = MOUSE_X(inParam1) + ScrollBarSlop;
SliderPosition = round((float)((float)(x - (Right-20 + DownBtnSize + ThumbSize/2)) / (float)((Right - UpBtnSize - ThumbSize/2) - (Right-20 + DownBtnSize + ThumbSize/2))) * Max);
}
}
else
SliderPosition = 0;
if (SliderPosition < Min)
SliderPosition = Min;
if (SliderPosition > Max)
SliderPosition = Max;
XPSetWidgetProperty(inWidget, xpProperty_ListBoxScrollBarSliderPosition, SliderPosition);
}
}
return 1;
default:
return 0;
}
}
// To create a listbox, make a new widget with our listbox proc as the widget proc.
static XPWidgetID XPCreateListBox(
int inLeft,
int inTop,
int inRight,
int inBottom,
int inVisible,
const char * inDescriptor,
XPWidgetID inContainer)
{
return XPCreateCustomWidget(
inLeft,
inTop,
inRight,
inBottom,
inVisible,
inDescriptor,
0,
inContainer,
XPListBoxProc);
}
/*------------------------------------------------------------------------*/
/*
* XPPopups.cpp
*
* Copyright 2005 Sandy Barbour and Ben Supnik
*
* All rights reserved. See license.txt for usage.
*
* X-Plane SDK Version: 1.0.2
*
*/
/************************************************************************
* X-PLANE UI INFRASTRUCTURE CODE
************************************************************************
*
* This code helps provde an x-plane compatible look. It is copied from
* the source code from the widgets DLL; someday popups will be part of
* this, so our popups are written off of the same APIs.
*
*/
enum {
// These are for caching, do not use!!
xpProperty_OffsetToCurrentItem = 1898,
xpProperty_CurrentItemLen = 1899
};
#ifndef _WINDOWS
#pragma mark -
#endif
/************************************************************************
* POPUP MENU IMPLEMENTATION
************************************************************************/
// This structure represents a popup menu internally...it consists of arrays
// per item and some general stuff. It is implemented as a giant window; that
// window has a ptr to this struct as its refcon. While the whole window isn't
// drawn in, we make the window full screen so if the user clicks outside the
// popup, we capture the click and dismiss the popup.
struct XPPopupMenu_t {
XPLMWindowID window; // The window that implements us.
// Per item:
std::vector<std::string> items; // The name of the item
std::vector<bool> enabled; // Is it enabled?
std::vector<int> lefts; // The rectangle of the item, relative to the top left corner of the menu/
std::vector<int> rights;
std::vector<int> bottoms;
std::vector<int> tops;
std::vector<int> vstripes; // An array of vertical stripes (relative to the left of the menu
// for really big menus.
int left; // The overall bounds of the menu in global screen coordinates.
int top;
int right;
int bottom;
XPPopupPick_f function; // Info for our callback function.
void * ref;
};
// This routine finds the item that is in a given point, or returns -1 if there is none.
// It simply trolls through all the items.
static int XPItemForHeight(XPPopupMenu_t * pmenu, int inX, int inY)
{
inX -= pmenu->left;
inY -= pmenu->top;
for (unsigned int n = 0; n < pmenu->items.size(); ++n)
{
if ((inX >= pmenu->lefts[n]) && (inX < pmenu->rights[n]) &&
(inY >= pmenu->bottoms[n]) && (inY < pmenu->tops[n]))
{
return n;
}
}
return -1;
}
// This is the drawing hook for a popup menu.
static void XPPopupDrawWindowCB(
XPLMWindowID inWindowID,
void * inRefcon)
{
XPPopupMenu_t * pmenu = (XPPopupMenu_t *) inRefcon;
int x, y;
XPLMGetMouseLocation(&x, &y);
// This is the index number of the currently selected item, based
// on where the mouse is.
int menu_offset = XPItemForHeight(pmenu, x, y);
int item_top = pmenu->top;
unsigned int n;
XPLMSetGraphicsState(0, 0, 0, 0, 0, 0, 0);
// Draw any vertical stripes that must be drawn for multi-column menus.
for (n = 0; n < pmenu->vstripes.size(); ++n)
{
SetupAmbientColor(xpColor_MenuDarkTinge, NULL);
glBegin(GL_LINES);
glVertex2i(pmenu->left + pmenu->vstripes[n] - 1, pmenu->top);
glVertex2i(pmenu->left + pmenu->vstripes[n] - 1, pmenu->bottom);
glEnd();
SetupAmbientColor(xpColor_MenuLiteTinge, NULL);
glBegin(GL_LINES);
glVertex2i(pmenu->left + pmenu->vstripes[n], pmenu->top);
glVertex2i(pmenu->left + pmenu->vstripes[n], pmenu->bottom);
glEnd();
}
// Now draw each item.
for (n = 0; n < pmenu->items.size(); ++n)
{
// Calcualte the item rect in global coordinates.
int item_bottom = pmenu->bottoms[n] + pmenu->top;
int item_top = pmenu->tops[n] + pmenu->top;
int item_left = pmenu->lefts[n] + pmenu->left;
int item_right = pmenu->rights[n] + pmenu->left;
XPDrawElement( item_left,
item_bottom,
item_right,
item_top,
(menu_offset == n && pmenu->enabled[n])? xpElement_PushButtonLit : xpElement_PushButton, 0);
if (!pmenu->enabled[n] && pmenu->items[n] == "-")
{
// Draw two lines for dividers.
XPLMSetGraphicsState(0, 0, 0, 0, 0, 0, 0);
SetupAmbientColor(xpColor_MenuLiteTinge, NULL);
glBegin(GL_LINE_STRIP);
glVertex2i(item_left, item_top - 1);
glVertex2i(item_right, item_top - 1);
glEnd();
SetupAmbientColor(xpColor_MenuDarkTinge, NULL);
glBegin(GL_LINE_STRIP);
glVertex2i(item_left, item_top);
glVertex2i(item_right, item_top);
glEnd();
} else {
// If we are hilited, draw the hilite bkgnd.
if (menu_offset == n && pmenu->enabled[n])
{
SetAlphaLevels(0.25);
XPLMSetGraphicsState(0, 0, 0, 0, 1, 0, 0);
SetupAmbientColor(xpColor_MenuHilite, NULL);
SetAlphaLevels(1.0);
glBegin(GL_QUADS);
glVertex2i(item_left, item_top);
glVertex2i(item_right, item_top);
glVertex2i(item_right, item_bottom);
glVertex2i(item_left, item_bottom);
glEnd();
}
// Draw the text for the menu item, taking into account
// disabling as a color.
float text[3];
SetupAmbientColor(pmenu->enabled[n] ? xpColor_MenuText : xpColor_MenuTextDisabled, text);
int XPlaneVersion, XPLMVersion, HostID;
XPLMGetVersions(&XPlaneVersion, &XPLMVersion, &HostID);
int yOffset = 2;
if (XPlaneVersion < 9400)
yOffset = 2;
else
yOffset = 5;
XPLMDrawString(text,
item_left + 18, item_bottom + yOffset,
const_cast<char *>(pmenu->items[n].c_str()), NULL, xplmFont_Menus);
}
}
}
static void XPPopupHandleKeyCB(
XPLMWindowID inWindowID,
char inKey,
XPLMKeyFlags inFlags,
char inVirtualKey,
void * inRefcon,
int losingFocus)
{
// Nothing to do when a key is pressed; popup menus don't use keys.
}
// This is the mouse click handler.
static int XPPopupHandleMouseClickCB(
XPLMWindowID inWindowID,
int x,
int y,
XPLMMouseStatus inMouse,
void * inRefcon)
{
// Normally we do nothing. But when we get an up click we dismiss.
if (inMouse == xplm_MouseUp)
{
XPPopupMenu_t * pmenu = (XPPopupMenu_t *) inRefcon;
int menu_offset = XPItemForHeight(pmenu, x, y);
// If we got an item click and it is not enabled,
// pretend nothing was picked.
if (menu_offset >= 0 && !pmenu->enabled[menu_offset])
menu_offset = -1;
// Call the callback
if (pmenu->function)
pmenu->function(menu_offset, pmenu->ref);
// cleanup
delete pmenu;
XPLMDestroyWindow(inWindowID);
}
return 1;
}
// This routine just has to build the popup and then the window takes care of itself.
static void XPPickPopup(
int inMouseX,
int inMouseY,
const char * inItems,
int inCurrentItem,
XPPopupPick_f inCallback,
void * inRefcon)
{
int screenWidth, screenHeight;
int fontWidth, fontHeight;
screenWidth = 1024;
screenHeight = 768;
XPLMGetFontDimensions(xplmFont_Menus, &fontWidth, &fontHeight, NULL);
// Allocate mem for the structure and build a new window as big as teh screen.
XPPopupMenu_t * info = new XPPopupMenu_t;
XPLMWindowID windID = XPLMCreateWindow(0, screenHeight, screenWidth, 0, 1,
XPPopupDrawWindowCB, XPPopupHandleKeyCB, XPPopupHandleMouseClickCB, info);
if (inCurrentItem < 0) inCurrentItem = 0;
/************ PARSE THE MENU STRING INTO MENU ITEMS **********/
// Parse the itemes into arrays. Remember how tall they are so
// we can calculate the geometry.
std::vector<int> heights;
std::string items(inItems);
while (!items.empty())
{
std::string::size_type split = items.find(';');
if (split == items.npos)
{
split = items.size();
}
std::string item = items.substr(0, split);
if (item == "-")
{
info->items.push_back("-");
info->enabled.push_back(false);
heights.push_back(2);
} else {
if (!item.empty() && item[0] == '(')
{
info->enabled.push_back(false);
info->items.push_back(item.substr(1));
heights.push_back(12);
} else {
info->enabled.push_back(true);
info->items.push_back(item);
heights.push_back(12);
}
}
if (item.size() == items.size())
break;
else
items = items.substr(split+1);
}
/************ PLACE THE ITEMS IN COLUMNS **********/
unsigned int menuWidth = 0;
int leftOff = 0, topOff = 0;
// Calculate the widest menu item anywhere.
for (std::vector<std::string>::iterator iter = info->items.begin(); iter != info->items.end(); ++iter)
if (iter->size() > menuWidth)
menuWidth = iter->size();
menuWidth *= fontWidth;
menuWidth += 35;
int cols = 1;
int itemsInCol = 0;
int maxLen = 0;
int ourItemLeft = 0, ourItemTop = 0;
// Stack up each item, building new columns as necessary.
for( unsigned int i = 0; i < heights.size(); ++i )
{
itemsInCol++;
info->lefts.push_back(leftOff);
info->rights.push_back(leftOff + menuWidth);
info->tops.push_back(topOff);
info->bottoms.push_back(topOff - heights[i]);
if (i == inCurrentItem)
{
ourItemLeft = leftOff;
ourItemTop = topOff;
}
topOff -= heights[i];
if (maxLen > topOff)
maxLen = topOff;
if (topOff < -(screenHeight - 50))
{
itemsInCol = 0;
cols++;
topOff = 0;
leftOff += menuWidth;
info->vstripes.push_back(leftOff);
}
}
// If we built a new column but had no items for it, throw it out.
if (itemsInCol == 0)
{
cols--;
info->vstripes.pop_back();
}
// Now place the window. Make sure to not let it go off screen.
info->window = windID;
info->left = inMouseX - ourItemLeft;
info->top = inMouseY - ourItemTop;
info->right = inMouseX + (menuWidth * cols) - ourItemLeft;
info->bottom = inMouseY + maxLen - ourItemTop;
if (info->right > (screenWidth-10))
{
int deltaLeft = (info->right - (screenWidth-10));
info->right -= deltaLeft;
info->left -= deltaLeft;
}
if (info->left < 10)
{
int deltaRight = 10 - info->left;
info->right += deltaRight;
info->left += deltaRight;
}
if (info->bottom < 10)
{
int deltaUp = 10 - info->bottom;
info->bottom += deltaUp;
info->top += deltaUp;
}
if (info->top > (screenHeight-30))
{
int deltaDown = (info->top - (screenHeight-30));
info->top -= deltaDown;
info->bottom -= deltaDown;
}
info->function = inCallback;
info->ref = inRefcon;
}
#ifndef _WINDOWS
#pragma mark -
#endif
// This routine is called by our popup menu when it is picked; we
// have stored our widget in our refcon, so we save the new choice
// and send a widget message.
static void XPPopupWidgetProc(int inChoice, void * inRefcon)
{
if (inChoice != -1)
{
XPSetWidgetProperty(inRefcon, xpProperty_PopupCurrentItem, inChoice);
XPSendMessageToWidget(inRefcon, xpMessage_PopupNewItemPicked, xpMode_UpChain, (intptr_t) inRefcon, (intptr_t) inChoice);
}
}
// This widget Proc implements the actual button.
static int XPPopupButtonProc(
XPWidgetMessage inMessage,
XPWidgetID inWidget,
intptr_t inParam1,
intptr_t inParam2)
{
// Select if we're in the background.
if (XPUSelectIfNeeded(inMessage, inWidget, inParam1, inParam2, 1/*eat*/)) return 1;
int fh, fv;
int l, t, r, b;
char buf[4096];
XPGetWidgetGeometry(inWidget, &l, &t, &r, &b);
XPLMGetFontDimensions(xplmFont_Basic, &fh, &fv, NULL);
int curItem = XPGetWidgetProperty(inWidget, xpProperty_PopupCurrentItem, NULL);
switch(inMessage) {
case xpMsg_Create:
case xpMsg_DescriptorChanged:
case xpMsg_PropertyChanged:
// If our data changes, reparse our descriptor to change our current item.
if (inMessage != xpMsg_PropertyChanged || inParam1 == xpProperty_PopupCurrentItem)
{
XPGetWidgetDescriptor(inWidget, buf, sizeof(buf));
char * p = buf;
int picksToSkip = curItem;
while (picksToSkip > 0)
{
while (*p && *p != ';') ++p;
if (*p == 0) break;
++p;
--picksToSkip;
}
char * term = p;
while (*term && *term != ';') ++term;
// Store an offset and length of our descriptor that will show as our current text.
XPSetWidgetProperty(inWidget, xpProperty_OffsetToCurrentItem, p - buf);
XPSetWidgetProperty(inWidget, xpProperty_CurrentItemLen, term - p);
XPSetWidgetProperty(inWidget, xpProperty_Enabled, 1);
}
return 1;
case xpMsg_Draw:
{
float white [4];
float gray [4];
int itemOffset = XPGetWidgetProperty(inWidget, xpProperty_OffsetToCurrentItem, NULL);
int itemLen = XPGetWidgetProperty(inWidget, xpProperty_CurrentItemLen, NULL);
// Drawing time. Find the sim version once.
static int sim;
static float firstTime = true;
static int charWidth;
if (firstTime)
{
firstTime = false;
int plugin;
XPLMHostApplicationID id;
XPLMGetVersions(&sim, &plugin, &id);
XPLMGetFontDimensions(xplmFont_Basic, &charWidth, NULL, NULL);
}
// If we are version 7 of the sim, use Sergio's great new popup item.
// Since there is no UI element code for this, we must draw it by hand!
if (sim >= 700)
{
int center = (t + b) / 2;
XPDrawElement( l - 4, center - 13, r + 4, center + 13,
xpElement_PushButton, 0);
} else
// If we are version 6, use a window drag bar as a fake popup button.
XPDrawElement(l+2, b, r-2, t, xpElement_WindowDragBarSmooth, 0);
// Now draw the button label.
int titleLen = XPGetWidgetDescriptor(inWidget, buf, sizeof(buf));
SetupAmbientColor(xpColor_MenuText, white);
SetupAmbientColor(xpColor_MenuTextDisabled, gray);
if (charWidth)
{
int maxCharCapacity = (r - l - 24) / charWidth;
if (itemLen > maxCharCapacity)
itemLen = maxCharCapacity;
}
buf[itemOffset + itemLen] = 0;
if (buf[itemOffset] == '(') ++itemOffset;
titleLen = strlen(buf + itemOffset);
XPLMDrawString(XPGetWidgetProperty(inWidget, xpProperty_Enabled, 0) ? white : gray, l + 4,
(t + b) / 2 - (fv / 2) + 2,
buf + itemOffset, NULL, xplmFont_Basic);
}
return 1;
case xpMsg_MouseDown:
// If the mouse is clicked, do a popup pick.
if (XPGetWidgetProperty(inWidget, xpProperty_Enabled, 0))
{
XPGetWidgetDescriptor(inWidget, buf, sizeof(buf));
XPPickPopup(l, t, buf, XPGetWidgetProperty(inWidget, xpProperty_PopupCurrentItem, NULL),
XPPopupWidgetProc, inWidget);
return 1;
}
default:
return 0;
}
}
// To create a popup, make a new widget with our button proc as the widget proc.
static XPWidgetID XPCreatePopup(
int inLeft,
int inTop,
int inRight,
int inBottom,
int inVisible,
const char * inDescriptor,
XPWidgetID inContainer)
{
return XPCreateCustomWidget(
inLeft,
inTop,
inRight,
inBottom,
inVisible,
inDescriptor,
0,
inContainer,
XPPopupButtonProc);
}
/*------------------------------------------------------------------------*/