SDK200Tests

From X-Plane SDK
Jump to: navigation, search



/*
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;
}						

//---------------------------------------------------------------------------