Files
simgear/simgear/structure/SGBinding.hxx
T
James Turner 6ab7f68f4b Bindings: don’t cache the command pointer
Caching it complicates add/remove command logic, so making a simple
fix for now, which can be back-ported to 2020.2; ideally we would
cache the pointer but have an invalidation scheme, but that’s
considerably more work and risk.

Relates to Sentry crash:
https://sentry.io/organizations/flightgear/issues/1858764364
2020-09-06 15:23:52 +01:00

172 lines
3.9 KiB
C++

/**
* \file commands.hxx
* Interface definition for encapsulated commands.
* Started Spring 2001 by David Megginson, david@megginson.com
* This code is released into the Public Domain.
*
* $Id$
*/
#ifndef __SGBINDING_HXX
#define __SGBINDING_HXX
#include <simgear/compiler.h>
#include <string>
#include <map>
#include <vector>
#include <simgear/props/props.hxx>
#include <simgear/props/condition.hxx>
#include "commands.hxx"
/**
* An input binding of some sort.
*
* <p>This class represents a binding that can be assigned to a
* keyboard key, a joystick button or axis, or even a panel
* instrument.</p>
*/
class SGBinding : public SGConditional
{
public:
/**
* Default constructor.
*/
SGBinding ();
/**
* Convenience constructor.
*
* @param commandName TODO
*/
SGBinding(const std::string& commandName);
/**
* Convenience constructor.
*
* @param node The binding will be built from this node.
* @param root Property root used while building binding.
*/
SGBinding( const SGPropertyNode *node,
SGPropertyNode *root );
/**
* Destructor.
*/
virtual ~SGBinding () = default;
/**
* Clear internal state of the binding back to empty.
*
* This was particularly useful when SGBinding's destructor had its 'remove
* on delete' behaviour, however this is not the case anymore.
*/
void clear();
/**
* Get the command name.
*
* @return The string name of the command for this binding.
*/
const std::string &getCommandName () const { return _command_name; }
/**
* Get the argument that will be passed to the command.
*
* @return A property node that will be passed to the command as its
* argument, or 0 if none was supplied.
*/
const SGPropertyNode * getArg () { return _arg; }
/**
* Read a binding from a property node.
*
* @param node The property node containing the binding.
* @param root The property root node used while building the binding from
* \a node.
*/
void read (const SGPropertyNode * node, SGPropertyNode* root);
/**
* Fire a binding.
*/
void fire () const;
/**
* Fire a binding with a scaled movement (rather than absolute position).
*/
void fire (double offset, double max) const;
/**
* Fire a binding with a setting (i.e. joystick axis).
*
* A double 'setting' property will be added to the arguments.
*
* @param setting The input setting, usually between -1.0 and 1.0.
*/
void fire (double setting) const;
/**
* Fire a binding with a number of additional parameters
*
* The children of params will be merged with the fixed arguments.
*/
void fire (SGPropertyNode* params) const;
private:
void innerFire() const;
// just to be safe.
SGBinding (const SGBinding &binding);
std::string _command_name;
mutable SGPropertyNode_ptr _arg;
mutable SGPropertyNode_ptr _setting;
mutable SGPropertyNode_ptr _root;
};
typedef SGSharedPtr<SGBinding> SGBinding_ptr;
typedef std::vector<SGBinding_ptr > SGBindingList;
typedef std::map<unsigned,SGBindingList> SGBindingMap;
/**
* fire every binding in a list, in sequence
*/
void fireBindingList(const SGBindingList& aBindings, SGPropertyNode* params = NULL);
/**
* fire every binding in a list with a setting value
*/
void fireBindingListWithOffset(const SGBindingList& aBindings, double offset, double max);
/**
* read multiple bindings from property-list format
*/
SGBindingList readBindingList(const simgear::PropertyList& aNodes, SGPropertyNode* aRoot);
/**
* call clear() on every binding in a list
*/
void clearBindingList(const SGBindingList& aBindings);
/**
* check if at least one binding in the list is enabled. Returns false if bindings
* list is empty, or all bindings are conditinally disabled.
*/
bool anyBindingEnabled(const SGBindingList& bindings);
#endif