1 /*
2 * OpenSCAD (www.openscad.org)
3 * Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
4 * Marius Kintel <marius@kintel.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * As a special exception, you have permission to link this program
12 * with the CGAL library and distribute executables, as long as you
13 * follow the requirements of the GNU GPL in regard to all of the
14 * software in the executable aside from CGAL.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27 /*
28 * Initial implementation by Jochen Kunz and Gert Menke provided as
29 * Public Domain.
30 */
31
32 #include "input/SpaceNavInputDriver.h"
33 #include "input/InputDriverManager.h"
34
35 #include <spnav.h>
36 #include <unistd.h>
37
SpaceNavInputDriver()38 SpaceNavInputDriver::SpaceNavInputDriver()
39 {
40
41 }
42
~SpaceNavInputDriver()43 SpaceNavInputDriver::~SpaceNavInputDriver()
44 {
45
46 }
47
run()48 void SpaceNavInputDriver::run()
49 {
50 while (spnav_input()) {
51 QThread::msleep(20);
52 spnav_remove_events(SPNAV_EVENT_MOTION);
53 }
54 }
55
56 /*
57 * Handle events from the spacenavd daemon. The method blocks until at least
58 * one event is available and then processes all events until the queue is
59 * empty.
60 */
spnav_input(void)61 bool SpaceNavInputDriver::spnav_input(void)
62 {
63 spnav_event ev;
64
65 // The low level driver seems to inhibit events in the dead zone, so if we
66 // enter that case, make sure to zero out our axis values.
67 bool have_event = false;
68 for (int a = 0; a < 3; ++a) {
69 if (spnav_poll_event(&ev) != 0) {
70 have_event = true;
71 break;
72 }
73 QThread::msleep(20);
74 }
75
76 if (!have_event) {
77 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(0, 0));
78 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(1, 0));
79 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(2, 0));
80 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(3, 0));
81 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(4, 0));
82 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(5, 0));
83
84 if (spnav_wait_event(&ev) == 0) {
85 return false;
86 }
87 }
88
89 do {
90 if (ev.type == SPNAV_EVENT_MOTION) {
91 #ifdef DEBUG
92 if ((ev.motion.x != 0) || (ev.motion.y != 0) || (ev.motion.z != 0)) {
93 PRINTDB("Translate Event: x = %d, y = %d, z = %d", ev.motion.x % ev.motion.y % ev.motion.z);
94 }
95 if ((ev.motion.rx != 0) || (ev.motion.ry != 0) || (ev.motion.rz != 0)) {
96 PRINTDB("Rotate Event: rx = %d, ry = %d, rz = %d", ev.motion.rx % ev.motion.ry % ev.motion.rz);
97 }
98 #endif
99
100 if (this->dominantAxisOnly) {
101 // dominant axis only
102 int m=ev.motion.x;
103 if (abs(m) < abs(ev.motion.y)) m=ev.motion.y;
104 if (abs(m) < abs(ev.motion.z)) m=ev.motion.z;
105 if (abs(m) < abs(ev.motion.rx)) m=ev.motion.rx;
106 if (abs(m) < abs(ev.motion.ry)) m=ev.motion.ry;
107 if (abs(m) < abs(ev.motion.rz)) m=ev.motion.rz;
108
109 if (ev.motion.x == m) { ev.motion.y=0; ev.motion.z=0; ev.motion.rx=0; ev.motion.ry=0; ev.motion.rz=0; }
110 if (ev.motion.y == m) { ev.motion.x=0; ev.motion.z=0; ev.motion.rx=0; ev.motion.ry=0; ev.motion.rz=0; }
111 if (ev.motion.z == m) { ev.motion.x=0; ev.motion.y=0; ev.motion.rx=0; ev.motion.ry=0; ev.motion.rz=0; }
112 if (ev.motion.rx== m) { ev.motion.x=0; ev.motion.y=0; ev.motion.z=0; ev.motion.ry=0; ev.motion.rz=0; }
113 if (ev.motion.ry== m) { ev.motion.x=0; ev.motion.y=0; ev.motion.z=0; ev.motion.rx=0; ev.motion.rz=0; }
114 if (ev.motion.rz== m) { ev.motion.x=0; ev.motion.y=0; ev.motion.z=0; ev.motion.rx=0; ev.motion.ry=0; }
115 }
116
117 if (ev.motion.x != 0) {
118 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(0, ev.motion.x / 500.0));
119 }
120 if (ev.motion.y != 0) {
121 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(1, ev.motion.y / 500.0));
122 }
123 if (ev.motion.z != 0) {
124 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(2, ev.motion.z / 500.0));
125 }
126 if (ev.motion.rx != 0) {
127 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(3, ev.motion.rx / 500.0));
128 }
129 if (ev.motion.ry != 0) {
130 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(4, ev.motion.ry / 500.0));
131 }
132 if (ev.motion.rz != 0) {
133 InputDriverManager::instance()->sendEvent(new InputEventAxisChanged(5, ev.motion.rz / 500.0));
134 }
135 } else if (ev.type == SPNAV_EVENT_BUTTON) {
136 PRINTDB("Button Event: num = %d, %s", ev.button.bnum % (ev.button.press ? "pressed" : "released"));
137 InputEvent *event = new InputEventButtonChanged(ev.button.bnum, ev.button.press);
138 InputDriverManager::instance()->sendEvent(event);
139 }
140 } while (spnav_poll_event(&ev));
141
142 return true;
143 }
144
open()145 bool SpaceNavInputDriver::open()
146 {
147 if (spnav_open() < 0) {
148 return false;
149 }
150 start();
151 return true;
152 }
153
close()154 void SpaceNavInputDriver::close()
155 {
156
157 }
158
setDominantAxisOnly(bool var)159 void SpaceNavInputDriver::setDominantAxisOnly(bool var){
160 this->dominantAxisOnly = var;
161 }
162
get_name() const163 const std::string & SpaceNavInputDriver::get_name() const
164 {
165 static std::string name = "SpaceNavInputDriver";
166 return name;
167 }
168
get_info() const169 std::string SpaceNavInputDriver::get_info() const
170 {
171 return STR(get_name() << " " << (isOpen() ? "open" : "not open") << " ");
172 }
173