diff --git a/.gitignore b/.gitignore index 2575f4c..d77d831 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ # OS generated files # ###################### .DS_Store? +.DS_Store ehthumbs.db Icon? Thumbs.db @@ -69,6 +70,7 @@ build/ xcuserdata *.moved-aside *.xccheckout +xcshareddata # IntelliJ Files # ################## diff --git a/xpcPlugin/MessageHandlers.cpp b/xpcPlugin/MessageHandlers.cpp index 0a97c40..4808c7a 100644 --- a/xpcPlugin/MessageHandlers.cpp +++ b/xpcPlugin/MessageHandlers.cpp @@ -20,10 +20,13 @@ #include "Log.h" #include "XPLMUtilities.h" +#include "XPLMGraphics.h" + #include #include + namespace XPC { std::map MessageHandlers::connections; @@ -597,7 +600,7 @@ namespace XPC // Update log Log::FormatLine(LOG_TRACE, "SIMU", "Message Received (Conn %i)", connection.id); - char v = msg.GetBuffer()[5]; + unsigned char v = msg.GetBuffer()[5]; if (v < 0 || (v > 2 && v < 100) || (v > 119 && v < 200) || v > 219) { Log::FormatLine(LOG_ERROR, "SIMU", "ERROR: Invalid argument: %i", v); @@ -686,21 +689,111 @@ namespace XPC Log::WriteLine(LOG_INFO, "TEXT", "[TEXT] Text set"); } } - + void MessageHandlers::HandleView(const Message& msg) { // Update Log Log::FormatLine(LOG_TRACE, "VIEW", "Message Received(Conn %i)", connection.id); + int enable_camera_location = 0; + const std::size_t size = msg.GetSize(); - if (size != 9) + if (size == 9) { - Log::FormatLine(LOG_ERROR, "VIEW", "Error: Unexpected length. Message was %d bytes, expected 9.", size); + // default view switcher as before + } + else if (size == 37) + { + // Allow camera location control + enable_camera_location = 1; + } + else + { + Log::FormatLine(LOG_ERROR, "VIEW", "Error: Unexpected length. Message was %d bytes, expected 9 or 37.", size); return; } const unsigned char* buffer = msg.GetBuffer(); int type = *((int*)(buffer + 5)); XPLMCommandKeyStroke(type); + + if(type == 79 && enable_camera_location == 1) // runway camera view + { + static struct CameraProperties campos; + + campos.loc[0] = *(double*)(buffer+9); + campos.loc[1] = *(double*)(buffer+17); + campos.loc[2] = *(double*)(buffer+25); + campos.direction[0] = -998; + campos.direction[1] = -998; + campos.direction[2] = -998; + campos.zoom = *(float*)(buffer+33); + + Log::FormatLine(LOG_TRACE, "VIEW", "Cam pos %f %f %f zoom %f", campos.loc[0], campos.loc[1], campos.loc[2],campos.zoom); + + XPLMControlCamera(xplm_ControlCameraUntilViewChanges, CamFunc, &campos); + } + } + + int MessageHandlers::CamFunc( XPLMCameraPosition_t * outCameraPosition, int inIsLosingControl, void *inRefcon) + { + if (outCameraPosition && !inIsLosingControl) + { + struct CameraProperties* campos = (struct CameraProperties*)inRefcon; + + // camera position + double clat = campos->loc[0]; + double clon = campos->loc[1]; + double calt = campos->loc[2]; + + double cX, cY, cZ; + XPLMWorldToLocal(clat, clon, calt, &cX, &cY, &cZ); + + outCameraPosition->x = cX; + outCameraPosition->y = cY; + outCameraPosition->z = cZ; + +// Log::FormatLine(LOG_TRACE, "CAM", "Cam pos %f %f %f", clat, clon, calt); + + if(campos->direction[0] == -998) // calculate camera direction + { + // aircraft position + double x = XPC::DataManager::GetDouble(XPC::DREF_LocalX, 0); + double y = XPC::DataManager::GetDouble(XPC::DREF_LocalY, 0); + double z = XPC::DataManager::GetDouble(XPC::DREF_LocalZ, 0); + + // relative position vector cam to plane + double dx = x - cX; + double dy = y - cY; + double dz = z - cZ; + +// Log::FormatLine(LOG_TRACE, "CAM", "Cam vect %f %f %f", dx, dy, dz); + + double pi = 3.141592653589793; + + // horizontal distance + double dist = sqrt(dx*dx + dz*dz); + + outCameraPosition->pitch = atan2(dy, dist) * 180.0/pi; + + double angle = atan2(dz, dx) * 180.0/pi; // rel to pos right (pos X) + + outCameraPosition->heading = 90 + angle; // rel to north + +// Log::FormatLine(LOG_TRACE, "CAM", "Cam p %f hdg %f ", outCameraPosition->pitch, outCameraPosition->heading); + + outCameraPosition->roll = 0; + } + else + { + outCameraPosition->roll = campos->direction[0]; + outCameraPosition->pitch = campos->direction[1]; + outCameraPosition->heading = campos->direction[2]; + } + + outCameraPosition->zoom = campos->zoom; + } + + return 1; } void MessageHandlers::HandleWypt(const Message& msg) diff --git a/xpcPlugin/MessageHandlers.h b/xpcPlugin/MessageHandlers.h index 983a904..52b652e 100644 --- a/xpcPlugin/MessageHandlers.h +++ b/xpcPlugin/MessageHandlers.h @@ -7,6 +7,9 @@ #include #include +#include "XPLMCamera.h" + + namespace XPC { /// A function that handles a message. @@ -26,10 +29,10 @@ namespace XPC /// socket. /// /// \details After a message is read, HandleMessage analyzes the sender's network address - /// to determine whether the sender is a new client. It then either loads - /// connection details for an existing client, or creates a new connection record - /// for new clients. Finally, the message handler checks the message type and - /// dispatches the message to the appropriate handler. + /// to determine whether the sender is a new client. It then either loads + /// connection details for an existing client, or creates a new connection record + /// for new clients. Finally, the message handler checks the message type and + /// dispatches the message to the appropriate handler. /// \param msg The message to be processed. static void HandleMessage(Message& msg); @@ -54,6 +57,14 @@ namespace XPC static void HandleXPlaneData(const Message& msg); static void HandleUnknown(const Message& msg); + + static int CamFunc( XPLMCameraPosition_t * outCameraPosition, int inIsLosingControl, void *inRefcon); + + struct CameraProperties{ + double loc[3]; + float direction[3]; + float zoom; + }; typedef struct {