Skip to content

Commit

Permalink
before reveiw pull request
Browse files Browse the repository at this point in the history
  • Loading branch information
alireza787b committed Apr 1, 2024
1 parent 5c96d89 commit 3bff6bb
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 15 deletions.
4 changes: 4 additions & 0 deletions include/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ class ConfigManager {
static bool hasPropBrake(int motorIndex);
static const int MAX_MOTORS = 8; // Maximum possible motors in X-Plane
static void configureMotorBrakes(const CSimpleIniA& ini);
static std::vector<std::string> getAirframeLists();
static std::string getActiveAirframeName();
static void setActiveAirframeName(const std::string& airframeName);
static std::string getAirframeByIndex(int index);



Expand Down
103 changes: 102 additions & 1 deletion src/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,105 @@ std::vector<int> ConfigManager::parseMotorIndices(const std::string& indicesStr)
}
}
return indices;
}
}


/**
* @brief Retrieves a list of airframe configuration names from the config.ini file.
*
* This function reads the config.ini file and extracts the names of all sections,
* which represent different airframe configurations. It uses the SimpleIni library
* to parse the INI file and collect the section names. Each section name is assumed
* to correspond to a unique airframe configuration.
*
* The function is static and can be called without an instance of ConfigManager.
* It utilizes the getConfigFilePath method to resolve the path to the config.ini file.
*
* Usage example:
* std::vector<std::string> airframes = ConfigManager::getAirframeLists();
* for (const auto& airframe : airframes) {
* // Process each airframe name
* }
*
* @return A vector of strings, each representing the name of an airframe configuration.
* Returns an empty vector if the config.ini file cannot be read or if there are no sections.
*/
std::vector<std::string> ConfigManager::getAirframeLists() {
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(getConfigFilePath().c_str());

CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);

std::vector<std::string> airframeNames;
for (const auto& section : sections) {
// Check and ignore the default section which does not represent an airframe.
if (std::string(section.pItem) != "") {
airframeNames.push_back(section.pItem);
}
}

return airframeNames;
}



/**
* @brief Retrieves the name of the currently active airframe configuration.
*
* This function reads the 'config.ini' file to obtain the name of the active airframe configuration.
* It returns the value of the 'config_name' parameter, which indicates the currently selected airframe.
*
* @return The name of the active airframe configuration. Returns an empty string if not specified.
*/
std::string ConfigManager::getActiveAirframeName() {
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(getConfigFilePath().c_str());
return ini.GetValue("", "config_name", "");
}

/**
* @brief Sets the active airframe configuration to the specified name.
*
* This function updates the 'config.ini' file to set the active airframe configuration.
* It first checks if the specified airframe name exists in the config file. If it does,
* the 'config_name' parameter is updated with the new airframe name. The updated configuration
* is then saved back to the 'config.ini' file.
*
* @param airframeName The name of the airframe configuration to be set as active.
*/
void ConfigManager::setActiveAirframeName(const std::string& airframeName) {
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(getConfigFilePath().c_str());

// Check if the airframe name exists in the config
CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);
bool exists = std::any_of(sections.begin(), sections.end(), [&](const CSimpleIniA::Entry& entry) {
return entry.pItem == airframeName;
});

if (exists) {
ini.SetValue("", "config_name", airframeName.c_str());
ini.SaveFile(getConfigFilePath().c_str());
XPLMDebugString("px4xplane: Config File Updated.");

}
else {
XPLMDebugString(("px4xplane: Airframe name not found in config: " + airframeName + "\n").c_str());
}
}


std::string ConfigManager::getAirframeByIndex(int index) {
// Retrieve the list of airframes and return the one at the given index
std::vector<std::string> airframes = getAirframeLists();
if (index >= 0 && index < airframes.size()) {
return airframes[index];
}
return ""; // Return an empty string if the index is out of range
}

132 changes: 118 additions & 14 deletions src/px4xplane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@

static XPLMWindowID g_window;
static XPLMMenuID g_menu_id;
static XPLMMenuID airframesMenu; // Global variable for the airframes submenu
static int g_airframesMenuItemIndex; // Global variable to store the index of the airframes submenu


// Global variable to hold our command reference
static XPLMCommandRef toggleEnableCmd;

Expand All @@ -53,6 +57,14 @@ void updateMenuItems();
float MyFlightLoopCallback(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop, int inCounter, void* inRefcon);


// Debugging function - Logs a message to the X-Plane log
void debugLog(const char* message) {
XPLMDebugString("px4xplane: ");
XPLMDebugString(message);
XPLMDebugString("\n");
}



int drawHeader(int l, int t, float col_white[]) {
char header[512];
Expand Down Expand Up @@ -164,6 +176,7 @@ PLUGIN_API int XPluginStart(
XPLMRegisterFlightLoopCallback(MyFlightLoopCallback, -1.0f, NULL);


debugLog("Plugin started successfully");


return 1;
Expand Down Expand Up @@ -206,18 +219,61 @@ void draw_px4xplane(XPLMWindowID in_window_id, void* in_refcon) {
drawFooter(l, b, col_white);
}

// Function to refresh the airframes submenu to indicate the active airframe.
void refreshAirframesMenu() {
// Clear the current submenu items.
XPLMClearAllMenuItems(airframesMenu);

// Repopulate the submenu with updated airframe names and active status.
std::vector<std::string> airframeNames = ConfigManager::getAirframeLists();
for (const std::string& name : airframeNames) {
// Append each airframe to the submenu and mark the active one.
XPLMAppendMenuItem(airframesMenu, (name + (name == ConfigManager::getActiveAirframeName() ? " *" : "")).c_str(), (void*)new std::string(name), 1);
}
}


void menu_handler(void* in_menu_ref, void* in_item_ref) {
//TODO: Remember here there is a problem. handler cant find when we click on airframes. now I did a hack and put that in else when it is not part of main list menu. we should fix this later.
debugLog("Menu handler called");

if (in_menu_ref == (void*)g_menu_id) {
if ((int)(intptr_t)in_item_ref == g_airframesMenuItemIndex) {
debugLog("Airframes submenu selected");
// The submenu itself was clicked; specific handling if needed
}
else {
// Handling other main menu items
if (in_item_ref == (void*)0) {
XPLMSetWindowIsVisible(g_window, 1);
debugLog("Show Data menu item selected");
}
else if (in_item_ref == (void*)1) {
toggleEnable();
debugLog("Toggle enable menu item selected");
}
}
}
else {
// Handling airframes submenu interactions
debugLog("Entered airframe submenu handler");

int index = (int)(intptr_t)in_item_ref;
std::vector<std::string> airframeNames = ConfigManager::getAirframeLists();

if (index >= 0 && index < airframeNames.size()) {
const std::string& selectedAirframe = airframeNames[index];
debugLog(("Airframe selected: " + selectedAirframe).c_str());

void menu_handler(XPLMMenuID in_menu, void* in_item_ref) {
if (in_item_ref == (void*)0) { // Show Window item
XPLMSetWindowIsVisible(g_window, 1);
}
else if (in_item_ref == (void*)1) { // Toggle enable
toggleEnable();
}
ConfigManager::setActiveAirframeName(selectedAirframe);
refreshAirframesMenu();
}
}

}



void toggleEnable() {
XPLMDebugString("px4xplane: toggleEnable() called.\n");
if (ConnectionManager::isConnected()) {
Expand Down Expand Up @@ -267,26 +323,64 @@ std::vector<float> getDataRefFloatArray(const char* dataRefName) {




void create_menu() {
debugLog("Creating plugin menu");

int menu_container_idx = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "PX4 X-Plane", NULL, 1);
g_menu_id = XPLMCreateMenu("px4xplane", XPLMFindPluginsMenu(), menu_container_idx, menu_handler, NULL);

XPLMAppendMenuItem(g_menu_id, "Show Data", (void*)0, 1);
// Save the index of the airframes submenu in the main menu
g_airframesMenuItemIndex = XPLMAppendMenuItem(g_menu_id, "Airframes", NULL, 1);
airframesMenu = XPLMCreateMenu("Airframes", g_menu_id, g_airframesMenuItemIndex, menu_handler, NULL);


debugLog("Airframes submenu created");

std::vector<std::string> airframeNames = ConfigManager::getAirframeLists();
std::string activeAirframe = ConfigManager::getActiveAirframeName();
for (size_t i = 0; i < airframeNames.size(); ++i) {
const std::string& name = airframeNames[i];
std::string menuItemName = name;
if (name == activeAirframe) {
menuItemName += " *";
}
XPLMAppendMenuItem(airframesMenu, menuItemName.c_str(), (void*)(intptr_t)i, 1);
}

XPLMAppendMenuItem(g_menu_id, "Show Data", (void*)0, 1);
toggleEnableCmd = XPLMCreateCommand("px4xplane/toggleEnable", "Toggle enable/disable state");
XPLMRegisterCommandHandler(toggleEnableCmd, toggleEnableHandler, 1, (void*)0);
XPLMAppendMenuSeparator(g_menu_id);
XPLMAppendMenuItemWithCommand(g_menu_id, "Connect to SITL", toggleEnableCmd);
XPLMAppendMenuItemWithCommand(g_menu_id, "Disconnect from SITL", toggleEnableCmd);

XPLMAppendMenuItemWithCommand(g_menu_id, "Connect to SITL", toggleEnableCmd); // Update this dynamically based on connection state
XPLMAppendMenuItemWithCommand(g_menu_id, "Disconnect from SITL", toggleEnableCmd); // Update this dynamically based on connection state
updateMenuItems(); // Update menu items after toggling connection
updateMenuItems();

debugLog("Menu created successfully");
}


void updateMenuItems() {
XPLMClearAllMenuItems(g_menu_id); // Clear all existing items
XPLMAppendMenuItem(g_menu_id, "Show Settings", (void*)0, 1);
XPLMClearAllMenuItems(g_menu_id);

// Recreate the main menu items
// Important: Update the airframesMenuItemIndex to reflect the new index after clearing
g_airframesMenuItemIndex = XPLMAppendMenuItem(g_menu_id, "Airframes", NULL, 1);
airframesMenu = XPLMCreateMenu("Airframes", g_menu_id, g_airframesMenuItemIndex, menu_handler, NULL);

std::vector<std::string> airframeNames = ConfigManager::getAirframeLists();
std::string activeAirframe = ConfigManager::getActiveAirframeName();
for (size_t i = 0; i < airframeNames.size(); ++i) {
const std::string& name = airframeNames[i];
std::string menuItemName = name;
if (name == activeAirframe) {
menuItemName += " *";
}
XPLMAppendMenuItem(airframesMenu, menuItemName.c_str(), (void*)(intptr_t)i, 1);
}

// Recreate the remaining main menu items
XPLMAppendMenuItem(g_menu_id, "Show Data", (void*)0, 1);
XPLMAppendMenuSeparator(g_menu_id);
if (ConnectionManager::isConnected()) {
XPLMAppendMenuItemWithCommand(g_menu_id, "Disconnect from SITL", toggleEnableCmd);
Expand All @@ -297,6 +391,15 @@ void updateMenuItems() {
}


// Placeholder function for handling airframe selection commands.
void handleAirframeSelection(const std::string& airframeName) {
// TODO: Implement the logic for when a user selects an airframe from the "Airframes" submenu.
debugLog(("Airframe selected: " + airframeName).c_str());
// Perform necessary actions to activate the selected airframe.
}



// Constants for update frequencies (in seconds)
constexpr float SENSOR_UPDATE_PERIOD = 1.0f / 100.0f; // 100 Hz for sensor data
constexpr float GPS_UPDATE_PERIOD = 1.0f / 10.0f; // 10 Hz for GPS data
Expand Down Expand Up @@ -393,6 +496,7 @@ PLUGIN_API void XPluginStop(void) {
if (ConnectionManager::isConnected()) {
toggleEnable();
}

XPLMUnregisterFlightLoopCallback(MyFlightLoopCallback, NULL);
#if IBM
ConnectionManager::cleanupWinSock();
Expand Down

0 comments on commit 3bff6bb

Please sign in to comment.