#include <sigc++/bind_return.h>
#include <msp/strings/lexicalcast.h>
+#include "binarycontrol.h"
#include "control.h"
#include "device.h"
Control::Control():
- capture_dev(0)
+ capture_dev(0),
+ activator(0),
+ origin(0)
{ }
Control::Control(const ControlSource &s):
src(s),
- capture_dev(0)
+ capture_dev(0),
+ activator(0),
+ origin(0)
{ }
Control::Control(Device &d, ControlSrcType t, unsigned i):
src(d, t, i),
- capture_dev(0)
+ capture_dev(0),
+ activator(0),
+ origin(0)
{
connect_signals();
}
connect_signals();
}
+void Control::set_activator(BinaryControl *ctrl)
+{
+ notify_callbacks();
+ activator = ctrl;
+ connect_signals();
+}
+
void Control::connect_signals()
{
switch(src.type)
src.dev->signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Control::axis_motion), false));
break;
}
+
+ if(activator)
+ activator->signal_release.connect(sigc::mem_fun(this, &Control::deactivate));
}
void Control::button_press(unsigned i)
connect_signals();
signal_capture_complete.emit();
}
- else if(src.type==BUTTON && i==src.index)
+ else if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
on_press();
}
void Control::button_release(unsigned i)
{
- if(src.type==BUTTON && i==src.index)
+ if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
on_release();
}
signal_capture_complete.emit();
}
}
- else if(src.type==AXIS_POS && i==src.index && v>=0)
- on_motion(v, r);
- else if(src.type==AXIS_NEG && i==src.index && v<=0)
- on_motion(-v, -r);
+ else if(activator && !activator->get_state() && i==src.index)
+ origin = v;
+ else if(src.type==AXIS_POS && i==src.index && v>=origin)
+ on_motion(v-origin, r);
+ else if(src.type==AXIS_NEG && i==src.index && v<=origin)
+ on_motion(origin-v, -r);
+}
+
+void Control::deactivate()
+{
+ if(src.type==BUTTON)
+ on_release();
+ else if(src.type==AXIS_POS || src.type==AXIS_NEG)
+ {
+ float v = src.dev->get_axis_value(src.index);
+ on_motion(0, (src.type==AXIS_POS ? origin-v : v-origin));
+ origin = v;
+ }
}
} // namespace Input
namespace Msp {
namespace Input {
+class BinaryControl;
class Device;
enum ControlSrcType
source. How the source values are interpreted depends on the exact type of the
control. Controls also support interactive binding by capturing a button press
or axis motion.
+
+A BinaryControl can be used as an activator, requiring that control to be
+active for any events to be processed. This can be used to implement shifted
+controls (when used on a BinaryControl) or click-and-drag functionality (when
+used on a SmoothControl).
*/
class Control: public sigc::trackable
{
protected:
ControlSource src;
Device *capture_dev;
+ BinaryControl *activator;
+ float origin;
Control();
Control(const ControlSource &);
void set_source(Device &, ControlSrcType, unsigned);
void set_source(const ControlSource &);
const ControlSource &get_source() const { return src; }
+ void set_activator(BinaryControl *);
+ BinaryControl *get_activator() const { return activator; }
protected:
virtual void on_press() = 0;
virtual void on_release() = 0;
void button_press(unsigned);
void button_release(unsigned);
void axis_motion(unsigned, float, float);
+ void deactivate();
Control(const Control &);
Control &operator=(const Control &);