Skip to content

Instantly share code, notes, and snippets.

@JDeeth
Created April 12, 2018 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JDeeth/60e87713583b25c20be7748cdb01cd3b to your computer and use it in GitHub Desktop.
Save JDeeth/60e87713583b25c20be7748cdb01cd3b to your computer and use it in GitHub Desktop.
Wrapper for X-Plane Command interface
#include "command.h"
Command::Command(XPLMCommandRef ref,
std::function<Outcome(Phase)> cb,
bool run_before_sim)
: ref_(ref), before_(run_before_sim ? 1 : 0), callback_(cb) {
XPLMRegisterCommandHandler(
ref_,
[](XPLMCommandRef, XPLMCommandPhase phase, void* vp) {
auto cmd = reinterpret_cast<Command*>(vp);
if (phase == xplm_CommandBegin)
cmd->phase_ = Phase::Begin;
if (phase == xplm_CommandContinue)
cmd->phase_ = Phase::Continue;
if (phase == xplm_CommandEnd)
cmd->phase_ = Phase::End;
auto outcome = cmd->callback_(cmd->phase_);
return outcome == Outcome::Halt ? 0 : 1;
},
before_,
this);
}
Command::Command(std::string cmd_to_replace,
std::function<Outcome(Phase)> callback,
bool run_before)
: Command(XPLMFindCommand(cmd_to_replace.c_str()), callback, run_before) {}
Command::Command(std::string new_cmd,
std::string description,
std::function<Outcome(Phase)> callback,
bool run_before)
: Command(XPLMCreateCommand(new_cmd.c_str(), description.c_str()),
callback,
run_before) {}
Command::~Command() {
XPLMUnregisterCommandHandler(
ref_,
[](XPLMCommandRef, XPLMCommandPhase, void*) { return 0; },
before_,
this);
}
Command::Phase Command::phase() const {
return phase_;
}
void Command::begin() {
XPLMCommandBegin(ref_);
}
void Command::end() {
XPLMCommandEnd(ref_);
}
void Command::once() {
XPLMCommandOnce(ref_);
}
#pragma once
/* This class registers and deregisters a command callback function
in an RAII way (as in, the destructor calls XPLMUnregisterCommandHandler
automatically when the object is destroyed)
Depending on how you call the constructor, it will either create a new
command, if you give it two strings for its name and description:
Command cmd{"YourName/YourProject/show_compile_msg",
"Shows the compilation date and time",
[](Command::Phase phase) {
if (phase == Command::Phase::Begin) {
std::stringstream desc;
desc << "Compiled " << __DATE__ << " " << __TIME__;
XPLMSpeakString(desc.str().c_str());
}
return Command::Outcome::Halt;
}};
Or it will register a new handler for an existing command, if you give it
either the command's name or its XPLMCommandRef.
Command brake_toggle_cmd{
"sim/flight_controls/brakes_toggle_regular",
[&](Command::Phase phase) {
if (phase == Command::Phase::Begin) {
if (handbrake_lever_ratio_ < 0.5f)
handbrake_lever_ratio_ = 0.5f;
else
handbrake_lever_ratio_ = 0.f;
}
return Command::Outcome::Halt;
}};
XPLMCommandPhase is replaced with an enum class:
Command::Phase::Begin
Command::Phase::Continue
Command::Phase::End
and the callback function returns an Outcome enum:
Command::Outcome::Halt (X-Plane stops processing the command)
Command::Outcome::Pass_On (X-Plane continues processing the command)
The default callback function immediately returns Halt, essentially
disabling that command:
Command left_brake_cmd_{"sim/flight_controls/left_brake"};
*/
#include <XPLMUtilities.h>
#include <functional>
#include <string>
class Command {
public:
enum class Outcome { Continue, Halt };
enum class Phase { Begin, Continue, End };
// Finds a command by reference and attaches a new callback to it
Command(XPLMCommandRef ref,
std::function<Outcome(Phase)> callback_ =
[](...) { return Outcome::Halt; },
bool run_before = true);
// Finds a command by name and attaches a new callback to it
Command(std::string cmd_to_replace,
std::function<Outcome(Phase)> callback_ =
[](...) { return Outcome::Halt; },
bool run_before = true);
// Creates a new command and attaches a callback to it
Command(std::string new_cmd,
std::string description,
std::function<Outcome(Phase)> callback_ =
[](...) { return Outcome::Halt; },
bool run_before = true);
~Command();
Phase phase() const;
// Call XPLMCommandBegin/End/Once
void begin();
void end();
void once();
private:
XPLMCommandRef ref_;
int before_;
Phase phase_{Phase::End};
std::function<Outcome(Phase)> callback_;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment