* Minor improvements to the handling of landing gear by the SetGear and HandlePOSI functions * sendPOSI command change (double for lat/lon/h) (#111) * Updated POSI to use doubles for lat/lon/alt, as step size for floats was unacceptably large at high longitudes. * Updated Java library for MATLAB, updated Java project, and updated Windows plugin binaries * Rolled back Java version to 1.7 for MATLAB compatibility * Update MessageHandlers.cpp * Update DataManager.cpp * Added pause functionality for individual a/c Adds new cases such that: 0: Unpauses all a/c 1: Pauses all a/c 2: Switches case for all a/c 100:119: Pauses a/c 0:19 200:219: Unpauses a/c 0:19 Updates log messages. Keeps the 0,1,2 arguments as they previously were. * Finished individual pause functionality * Update DataManager.cpp * Updated flags to allow for individual pause commands * Individual pause command documentation * Updated flags to allow for individual pause commands * Adding individual pause to documentation * Updated flags to allow for individual pause commands * Requested changes, cleaning * Update CMakeLists.txt Include "-fno-stack-protector" for linking and compiling for systems that do not have this have this flag as a default. * Enabling AI after setting position (#118) Previously, the code enabled the AI before setting the position of a/c, which negated its purpose. * Updated XPlane SDK to version 2.1.3 * Resolve function ambiguity for std::abs on mac Fixes #126 * Update copyright notice * Update Windows binaries * Update Linux binaries * Update version numbers * fix osx abs ambiguity (#142) * fix indexing error (#143) * Runway camera location control (#144) * update ignore * basics working * set cam pos remotely * log cam position * keep default behaviour, if short view message is received Compatibility with existing software * all to tabs * rename variable * option to use camera direction fields * Added UDP multicast for plugin discovery (#153) * Added Timer * Added UDPSocket::GetAddr * Added MessageHandlers::SendBeacon() * PoC of starting a timer on PluginEnable * C++11 * Added Timer to xcode project * C++11 in cmake * added Timer to cmake * use function pointer in Timer * moved Timer to namespace + wait for thread to join when stopping the timer * Windows: changed uint to unisgned short * Windows: Added Timer.h/cpp to project * GetAddr static * Send xplane and plugin version with BECN * SendBeacon with params * fixed file copyrights * Include functional to fix Linux compile error * review fixes * Send plugin receive port in BECN * review fixes * Fixed tabs vs spaces indentations (#157) * Java client BECN implementation (#155) * Added MS Azure Dev Ops CI integration (#162) * Do not build for i386 on macOS Use ARCHS_STANDARD to avoid the error “The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture.” * Fixed missing include The Visual Studio solution was not compiling * Fixed isnan ambigious refernce Ambigious reference when compiling on travis https://stackoverflow.com/questions/33770374/why-is-isnan-ambiguous-and-how-to-avoid-it * Set MSVC warning level to 3 Too many warnings were generated when building a Release build making Travis job to fail because of too much output * Use default toolset for Visual Studio AppVeyor recommends to set the default toolset * #include <cstdint> * Use MSVC ToolsVersion="14.0" # Conflicts: # xpcPlugin/xpcPlugin/xpcPlugin.vcxproj * Removed binaries from repository # Conflicts: # xpcPlugin/XPlaneConnect/64/win.xpl # xpcPlugin/XPlaneConnect/win.xpl * Added ms azure ci xcode linux linux + macos linux + macos removed branch filter win tests win tests Test all platfroms artifacts tests * output all binaries to ‘XPlaneConnect’ All platforms produce a binary in xpcPlugin/XPlaneConnect/ xpcPlugin/XPlaneConnect/64/ * Added ms azure GH deploy deploy stage GH release test trigger tags * Clean up yml file - Added variables - Added job decriptions * Ignore script to ignore .exp files + fixed output path * Renamed ms azure GH connection * Update service connection for azure pipeline * Added Python3 compatible xpc client. (#156) * Update Azure Pipelines service connection
312 lines
8.0 KiB
C++
312 lines
8.0 KiB
C++
// Copyright (c) 2013-2018 United States Government as represented by the Administrator of the
|
|
// National Aeronautics and Space Administration. All Rights Reserved.
|
|
//
|
|
// X-Plane API
|
|
// Copyright(c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
// associated documentation files(the "Software"), to deal in the Software without restriction,
|
|
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
// sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions :
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Neither the names of the authors nor that of X - Plane or Laminar Research
|
|
// may be used to endorse or promote products derived from this software
|
|
// without specific prior written permission from the authors or
|
|
// Laminar Research, respectively.
|
|
#include "Drawing.h"
|
|
|
|
#include "XPLMDisplay.h"
|
|
#include "XPLMGraphics.h"
|
|
#include "XPLMDataAccess.h"
|
|
|
|
#include <cmath>
|
|
#include <string>
|
|
#include <cstring>
|
|
// OpenGL includes
|
|
#if IBM
|
|
#include <windows.h>
|
|
#endif
|
|
#ifdef __APPLE__
|
|
# include <OpenGL/gl.h>
|
|
#else
|
|
# include <GL/gl.h>
|
|
#endif
|
|
|
|
namespace XPC
|
|
{
|
|
// Internal Structures
|
|
typedef struct
|
|
{
|
|
double x;
|
|
double y;
|
|
double z;
|
|
} LocalPoint;
|
|
|
|
// Internal Memory
|
|
static const size_t MSG_MAX = 1024;
|
|
static const size_t MSG_LINE_MAX = MSG_MAX / 16;
|
|
static bool msgEnabled = false;
|
|
static int msgX = -1;
|
|
static int msgY = -1;
|
|
static char msgVal[MSG_MAX] = { 0 };
|
|
static size_t newLineCount = 0;
|
|
static size_t newLines[MSG_LINE_MAX] = { 0 };
|
|
static float rgb[3] = { 0.25F, 1.0F, 0.25F };
|
|
|
|
static const size_t WAYPOINT_MAX = 128;
|
|
static bool routeEnabled = false;
|
|
static size_t numWaypoints = 0;
|
|
static Waypoint waypoints[WAYPOINT_MAX];
|
|
static LocalPoint localPoints[WAYPOINT_MAX];
|
|
|
|
XPLMDataRef planeXref;
|
|
XPLMDataRef planeYref;
|
|
XPLMDataRef planeZref;
|
|
|
|
// Internal Functions
|
|
|
|
/// Comparse two size_t integers. Used by qsort in RemoveWaypoints.
|
|
static int cmp(const void * a, const void * b)
|
|
{
|
|
std::size_t sa = *(size_t*)a;
|
|
std::size_t sb = *(size_t*)b;
|
|
if (sa > sb)
|
|
{
|
|
return 1;
|
|
}
|
|
if (sb > sa)
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// Draws a cube centered at the specified OpenGL world coordinates.
|
|
///
|
|
/// \param x The X coordinate.
|
|
/// \param y The Y coordinate.
|
|
/// \param z The Z coordinate.
|
|
/// \param d The distance from the player airplane to the center of the cube.
|
|
static void gl_drawCube(float x, float y, float z, float d)
|
|
{
|
|
// tan(0.25) degrees. Should scale all markers to appear about the same size
|
|
const float TAN = 0.00436335F;
|
|
float h = d * TAN;
|
|
|
|
glBegin(GL_QUAD_STRIP);
|
|
// Top
|
|
glVertex3f(x - h, y + h, z - h);
|
|
glVertex3f(x + h, y + h, z - h);
|
|
glVertex3f(x - h, y + h, z + h);
|
|
glVertex3f(x + h, y + h, z + h);
|
|
// Front
|
|
glVertex3f(x - h, y - h, z + h);
|
|
glVertex3f(x + h, y - h, z + h);
|
|
// Bottom
|
|
glVertex3f(x - h, y - h, z - h);
|
|
glVertex3f(x + h, y - h, z - h);
|
|
// Back
|
|
glVertex3f(x - h, y + h, z - h);
|
|
glVertex3f(x + h, y + h, z - h);
|
|
|
|
glEnd();
|
|
glBegin(GL_QUADS);
|
|
// Left
|
|
glVertex3f(x - h, y + h, z - h);
|
|
glVertex3f(x - h, y + h, z + h);
|
|
glVertex3f(x - h, y - h, z + h);
|
|
glVertex3f(x - h, y - h, z - h);
|
|
// Right
|
|
glVertex3f(x + h, y + h, z + h);
|
|
glVertex3f(x + h, y + h, z - h);
|
|
glVertex3f(x + h, y - h, z - h);
|
|
glVertex3f(x + h, y - h, z + h);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
/// Draws the string set by the TEXT command.
|
|
static int MessageDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
|
{
|
|
const int LINE_HEIGHT = 16;
|
|
XPLMDrawString(rgb, msgX, msgY, msgVal, NULL, xplmFont_Basic);
|
|
int y = msgY - LINE_HEIGHT;
|
|
for (size_t i = 0; i < newLineCount; ++i)
|
|
{
|
|
XPLMDrawString(rgb, msgX, y, msgVal + newLines[i], NULL, xplmFont_Basic);
|
|
y -= LINE_HEIGHT;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/// Draws waypoints.
|
|
static int RouteDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
|
{
|
|
float px = XPLMGetDataf(planeXref);
|
|
float py = XPLMGetDataf(planeYref);
|
|
float pz = XPLMGetDataf(planeZref);
|
|
|
|
// Convert to local
|
|
for (size_t i = 0; i < numWaypoints; ++i)
|
|
{
|
|
Waypoint* g = &waypoints[i];
|
|
LocalPoint* l = &localPoints[i];
|
|
XPLMWorldToLocal(g->latitude, g->longitude, g->altitude,
|
|
&l->x, &l->y, &l->z);
|
|
}
|
|
|
|
|
|
// Draw posts
|
|
glColor3f(1.0F, 1.0F, 1.0F);
|
|
glBegin(GL_LINES);
|
|
for (size_t i = 0; i < numWaypoints; ++i)
|
|
{
|
|
LocalPoint* l = &localPoints[i];
|
|
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
|
glVertex3f((float)l->x, -1000.0F, (float)l->z);
|
|
}
|
|
glEnd();
|
|
|
|
// Draw route
|
|
glColor3f(1.0F, 0.0F, 0.0F);
|
|
glBegin(GL_LINE_STRIP);
|
|
for (size_t i = 0; i < numWaypoints; ++i)
|
|
{
|
|
LocalPoint* l = &localPoints[i];
|
|
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
|
}
|
|
glEnd();
|
|
|
|
// Draw markers
|
|
glColor3f(1.0F, 1.0F, 1.0F);
|
|
for (size_t i = 0; i < numWaypoints; ++i)
|
|
{
|
|
LocalPoint* l = &localPoints[i];
|
|
float xoff = (float)l->x - px;
|
|
float yoff = (float)l->y - py;
|
|
float zoff = (float)l->z - pz;
|
|
float d = sqrtf(xoff*xoff + yoff*yoff + zoff*zoff);
|
|
gl_drawCube((float)l->x, (float)l->y, (float)l->z, d);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// Public Functions
|
|
void Drawing::ClearMessage()
|
|
{
|
|
XPLMUnregisterDrawCallback(MessageDrawCallback, xplm_Phase_Window, 0, NULL);
|
|
msgEnabled = false;
|
|
}
|
|
|
|
void Drawing::SetMessage(int x, int y, char* msg)
|
|
{
|
|
// Determine the size of the message and clear it if it is empty.
|
|
size_t len = strnlen(msg, MSG_MAX - 1);
|
|
if (len == 0)
|
|
{
|
|
ClearMessage();
|
|
return;
|
|
}
|
|
|
|
// Set the message, location, and mark new lines.
|
|
strncpy(msgVal, msg, len + 1);
|
|
newLineCount = 0;
|
|
for (size_t i = 0; i < len && newLineCount < MSG_LINE_MAX; ++i)
|
|
{
|
|
if (msgVal[i] == '\n' || msgVal[i] == '\r')
|
|
{
|
|
msgVal[i] = 0;
|
|
newLines[newLineCount++] = i + 1;
|
|
}
|
|
}
|
|
msgX = x < 0 ? 10 : x;
|
|
msgY = y < 0 ? 600 : y;
|
|
|
|
// Enable drawing if necessary
|
|
if (!msgEnabled)
|
|
{
|
|
XPLMRegisterDrawCallback(MessageDrawCallback, xplm_Phase_Window, 0, NULL);
|
|
msgEnabled = true;
|
|
}
|
|
}
|
|
|
|
void Drawing::ClearWaypoints()
|
|
{
|
|
numWaypoints = 0;
|
|
if (routeEnabled)
|
|
{
|
|
XPLMUnregisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Drawing::AddWaypoints(Waypoint points[], size_t numPoints)
|
|
{
|
|
if (numWaypoints + numPoints > WAYPOINT_MAX)
|
|
{
|
|
numPoints = WAYPOINT_MAX - numWaypoints;
|
|
}
|
|
size_t finalNumWaypoints = numPoints + numWaypoints;
|
|
for (size_t i = 0; i < numPoints; ++i)
|
|
{
|
|
waypoints[numWaypoints + i] = points[i];
|
|
}
|
|
numWaypoints = finalNumWaypoints;
|
|
|
|
if (!routeEnabled)
|
|
{
|
|
XPLMRegisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
|
}
|
|
if (!planeXref)
|
|
{
|
|
planeXref = XPLMFindDataRef("sim/flightmodel/position/local_x");
|
|
planeYref = XPLMFindDataRef("sim/flightmodel/position/local_y");
|
|
planeZref = XPLMFindDataRef("sim/flightmodel/position/local_z");
|
|
}
|
|
}
|
|
|
|
void Drawing::RemoveWaypoints(Waypoint points[], size_t numPoints)
|
|
{
|
|
// Build a list of indices of waypoints we should delete.
|
|
size_t delPoints[WAYPOINT_MAX];
|
|
size_t delPointsCur = 0;
|
|
for (size_t i = 0; i < numPoints; ++i)
|
|
{
|
|
Waypoint p = points[i];
|
|
for (size_t j = 0; j < numWaypoints; ++j)
|
|
{
|
|
Waypoint q = waypoints[j];
|
|
if (p.latitude == q.latitude &&
|
|
p.longitude == q.longitude &&
|
|
p.altitude == q.altitude)
|
|
{
|
|
delPoints[delPointsCur++] = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Sort the indices so that we only have to iterate them once
|
|
qsort(delPoints, delPointsCur, sizeof(size_t), cmp);
|
|
|
|
// Copy the new array on top of the old array
|
|
size_t copyCur = 0;
|
|
size_t count = delPointsCur;
|
|
delPointsCur = 0;
|
|
for (size_t i = 0; i < numWaypoints; ++i)
|
|
{
|
|
if (i == delPoints[delPointsCur])
|
|
{
|
|
++delPointsCur;
|
|
continue;
|
|
}
|
|
waypoints[copyCur++] = waypoints[i];
|
|
}
|
|
numWaypoints -= count;
|
|
if (numWaypoints == 0)
|
|
{
|
|
ClearWaypoints();
|
|
}
|
|
}
|
|
}
|