]> git.tdb.fi Git - libs/gui.git/blob - source/input/control.cpp
Add an activator system to Control
[libs/gui.git] / source / input / control.cpp
1 #include <sigc++/bind_return.h>
2 #include <msp/strings/lexicalcast.h>
3 #include "binarycontrol.h"
4 #include "control.h"
5 #include "device.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace Input {
11
12 ControlSource::ControlSource():
13         dev(0),
14         type(NONE),
15         index(0)
16 { }
17
18 ControlSource::ControlSource(Device &d, ControlSrcType t, unsigned i):
19         dev(&d),
20         type(t),
21         index(i)
22 { }
23
24 std::string ControlSource::str() const
25 {
26         if(type==BUTTON)
27                 return dev->get_button_name(index);
28         else if(type==AXIS_POS)
29                 return dev->get_axis_name(index)+" +";
30         else if(type==AXIS_NEG)
31                 return dev->get_axis_name(index)+" -";
32         else if(type==NONE)
33                 return "None";
34
35         return lexical_cast<string>(index);
36 }
37
38
39 Control::Control():
40         capture_dev(0),
41         activator(0),
42         origin(0)
43 { }
44
45 Control::Control(const ControlSource &s):
46         src(s),
47         capture_dev(0),
48         activator(0),
49         origin(0)
50 { }
51
52 Control::Control(Device &d, ControlSrcType t, unsigned i):
53         src(d, t, i),
54         capture_dev(0),
55         activator(0),
56         origin(0)
57 {
58         connect_signals();
59 }
60
61 Control::~Control()
62 { }
63
64 void Control::capture(Device &d)
65 {
66         notify_callbacks();
67         capture_dev = &d;
68         capture_dev->signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_press), false));
69         capture_dev->signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Control::axis_motion), false));
70 }
71
72 void Control::cancel_capture()
73 {
74         notify_callbacks();
75         capture_dev = 0;
76         connect_signals();
77 }
78
79 void Control::set_source(Device &d, ControlSrcType t, unsigned i)
80 {
81         set_source(ControlSource(d, t, i));
82 }
83
84 void Control::set_source(const ControlSource &s)
85 {
86         notify_callbacks();
87         src = s;
88         connect_signals();
89 }
90
91 void Control::set_activator(BinaryControl *ctrl)
92 {
93         notify_callbacks();
94         activator = ctrl;
95         connect_signals();
96 }
97
98 void Control::connect_signals()
99 {
100         switch(src.type)
101         {
102         case NONE:
103                 break;
104         case BUTTON:
105                 src.dev->signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_press), false));
106                 src.dev->signal_button_release.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_release), false));
107                 break;
108         case AXIS_POS:
109         case AXIS_NEG:
110                 src.dev->signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Control::axis_motion), false));
111                 break;
112         }
113
114         if(activator)
115                 activator->signal_release.connect(sigc::mem_fun(this, &Control::deactivate));
116 }
117
118 void Control::button_press(unsigned i)
119 {
120         if(capture_dev)
121         {
122                 src.dev = capture_dev;
123                 src.type = BUTTON;
124                 src.index = i;
125
126                 notify_callbacks();
127                 capture_dev = 0;
128                 connect_signals();
129                 signal_capture_complete.emit();
130         }
131         else if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
132                 on_press();
133 }
134
135 void Control::button_release(unsigned i)
136 {
137         if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
138                 on_release();
139 }
140
141 void Control::axis_motion(unsigned i, float v, float r)
142 {
143         if(capture_dev)
144         {
145                 ControlSrcType type = NONE;
146                 if(v<-0.9)
147                         type = AXIS_NEG;
148                 else if(v>0.9)
149                         type = AXIS_POS;
150
151                 if(type!=NONE)
152                 {
153                         src.dev = capture_dev;
154                         src.type = type;
155                         src.index = i;
156
157                         notify_callbacks();
158                         capture_dev = 0;
159                         connect_signals();
160                         signal_capture_complete.emit();
161                 }
162         }
163         else if(activator && !activator->get_state() && i==src.index)
164                 origin = v;
165         else if(src.type==AXIS_POS && i==src.index && v>=origin)
166                 on_motion(v-origin, r);
167         else if(src.type==AXIS_NEG && i==src.index && v<=origin)
168                 on_motion(origin-v, -r);
169 }
170
171 void Control::deactivate()
172 {
173         if(src.type==BUTTON)
174                 on_release();
175         else if(src.type==AXIS_POS || src.type==AXIS_NEG)
176         {
177                 float v = src.dev->get_axis_value(src.index);
178                 on_motion(0, (src.type==AXIS_POS ? origin-v : v-origin));
179                 origin = v;
180         }
181 }
182
183 } // namespace Input
184 } // namespace Msp