Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ppl.pro
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ HEADERS += \
src/action.h \
src/smoothed.h \
src/processor.h \
src/vertexbuffer.hpp
src/vertexbuffer.hpp \
src/command.h

SOURCES += \
src/pluginpath.cpp \
Expand All @@ -96,7 +97,8 @@ SOURCES += \
src/logwriter.cpp \
src/menuitem.cpp \
src/processor.cpp \
src/vertexbuffer.cpp
src/vertexbuffer.cpp \
src/command.cpp

withsound {
win32 {
Expand Down
78 changes: 78 additions & 0 deletions src/command.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "command.h"

/* Copyright (c) 2018, Jack Deeth github@jackdeeth.org.uk
// All rights reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are
those
// of the authors and should not be interpreted as representing official
policies,
// either expressed or implied, of the FreeBSD Project.
*/

PPL::Command::Command(XPLMCommandRef ref,
std::function<Outcome(XPLMCommandRef, Phase)> cb,
bool run_before_sim)
: callback(cb), ref_(ref), before_(run_before_sim ? 1 : 0) {
XPLMRegisterCommandHandler(ref_, scb, before_, this);
}

PPL::Command::Command(std::string cmd_to_replace,
std::function<Outcome(XPLMCommandRef, Phase)> callback,
bool run_before)
: Command(XPLMFindCommand(cmd_to_replace.c_str()), callback, run_before) {}

PPL::Command::Command(std::string new_cmd,
std::string description,
std::function<Outcome(XPLMCommandRef, Phase)> callback,
bool run_before)
: Command(XPLMCreateCommand(new_cmd.c_str(), description.c_str()),
callback,
run_before) {}

PPL::Command::~Command() {
XPLMUnregisterCommandHandler(ref_, scb, before_, this);
}

PPL::Command::Phase PPL::Command::phase() const { return phase_; }

void PPL::Command::begin() { XPLMCommandBegin(ref_); }

void PPL::Command::end() { XPLMCommandEnd(ref_); }

void PPL::Command::once() { XPLMCommandOnce(ref_); }

int PPL::Command::scb(XPLMCommandRef ref, XPLMCommandPhase phase, void *vp) {
// scb = shared/static call-back
// converts C conventions with (post?)modern C++
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(ref, cmd->phase_);
return outcome == Outcome::Halt ? 0 : 1;
}
132 changes: 132 additions & 0 deletions src/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#pragma once

/* Copyright (c) 2018, Jack Deeth github@jackdeeth.org.uk
// All rights reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are
those
// of the authors and should not be interpreted as representing official
policies,
// either expressed or implied, of the FreeBSD Project.
*/

/* Example usage:

// disable an existing command
PPL::Command left_brake_cmd_{"sim/flight_controls/left_brake"};

// hijack an existing command
const auto End{PPL::Command::Phase::End};
const auto Halt{PPL::Command::Outcome::Halt};
PPL::Command brake_toggle_cmd_{
"sim/flight_controls/brakes_toggle_regular",
[&](XPLMCommandRef, PPL::Command::Phase phase) {
if (phase == End) {
if (handbrake_lever_ratio_ < 0.5f)
handbrake_lever_ratio_ = 0.5f;
else
handbrake_lever_ratio_ = 0.f;
}
return Halt;
}};

// create a new command
class CompileMessage {
public:
CompileMessage(std::string command_name =
"YourName/YourProject/show_compile_msg",
std::string desc = "Announces compilation date/time of plugin"
: cmd_{command_name, desc, [](XPLMCommandRef, PPL::Command::Phase phase) {
if (phase == PPL::Command::Phase::Begin)
XPLMSpeakString(compile_message().c_str());
return PPL::Command::Outcome::Halt;
}} {}

static std::string compile_message() {
std::stringstream msg;
msg << "Compiled " << __DATE__ << " at " << __TIME__;
return msg.str();
}
private:
PPL::Command cmd_;
};

*/

#include <XPLMUtilities.h>

#include <functional>
#include <string>

// RAII wrapper for X-Plane Commands API

namespace PPL {

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(XPLMCommandRef, Phase)> callback =
[](...) { return Outcome::Halt; },
bool run_before = true);

// Finds a command by name and attaches a new callback to it
// (useful for hijacking and/or blocking existing commands)
Command(std::string cmd_to_replace,
std::function<Outcome(XPLMCommandRef, 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(XPLMCommandRef, Phase)> callback =
[](...) { return Outcome::Halt; },
bool run_before = true);

~Command();

Phase phase() const;

void begin();
void end();
void once();

std::function<Outcome(XPLMCommandRef, Phase)> callback;

static int scb(XPLMCommandRef ref, XPLMCommandPhase phase, void *vp);

private:
XPLMCommandRef ref_;
int before_;
Phase phase_{Phase::End};
};

} // namespace