GCManipulator.cc 7.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Definition of the class GCManipulator.
 *
28
 *   @author Lionel Heng <hengli@inf.ethz.ch>
29 30 31 32
 *
 */

#include "GCManipulator.h"
lm's avatar
lm committed
33
#include <osg/Version>
34 35 36

GCManipulator::GCManipulator()
{
37 38 39
    _moveSensitivity = 0.05;
    _zoomSensitivity = 1.0;
    _minZoomRange = 2.0;
40 41 42
}

void
43
GCManipulator::setMinZoomRange(double minZoomRange)
44 45 46 47
{
    _minZoomRange = minZoomRange;
}

48
void
49
GCManipulator::move(double dx, double dy, double dz)
50
{
51
    _center += osg::Vec3d(dx, dy, dz);
52 53
}

54 55 56 57 58 59
bool
GCManipulator::handle(const osgGA::GUIEventAdapter& ea,
                      osgGA::GUIActionAdapter& us)
{
    using namespace osgGA;

60 61 62 63 64 65
    switch (ea.getEventType()) {
    case GUIEventAdapter::PUSH: {
        flushMouseEventStack();
        addMouseEvent(ea);
        if (calcMovement()) {
            us.requestRedraw();
66
        }
67 68 69 70
        us.requestContinuousUpdate(false);
        _thrown = false;
        return true;
    }
71

72 73 74 75 76
    case GUIEventAdapter::RELEASE: {
        if (ea.getButtonMask() == 0) {
            if (isMouseMoving()) {
                if (calcMovement()) {
                    us.requestRedraw();
77 78
                    us.requestContinuousUpdate(false);
                    _thrown = false;
79
                }
80
            } else {
81 82
                flushMouseEventStack();
                addMouseEvent(ea);
83
                if (calcMovement()) {
84 85 86 87 88 89
                    us.requestRedraw();
                }
                us.requestContinuousUpdate(false);
                _thrown = false;
            }

90 91
        } else {
            flushMouseEventStack();
92
            addMouseEvent(ea);
93
            if (calcMovement()) {
94 95 96 97 98
                us.requestRedraw();
            }
            us.requestContinuousUpdate(false);
            _thrown = false;
        }
99 100
        return true;
    }
101

102 103 104 105 106 107 108 109 110
    case GUIEventAdapter::DRAG: {
        addMouseEvent(ea);
        if (calcMovement()) {
            us.requestRedraw();
        }
        us.requestContinuousUpdate(false);
        _thrown = false;
        return true;
    }
111

112 113 114
    case GUIEventAdapter::SCROLL: {
        // zoom model
        double scale = 1.0;
115

116 117 118 119 120 121
        if (ea.getScrollingMotion() == GUIEventAdapter::SCROLL_UP) {
            scale -= _zoomSensitivity * 0.1;
        } else {
            scale += _zoomSensitivity * 0.1;
        }
        if (_distance * scale > _minZoomRange) {
122

123
            _distance *= scale;
124 125 126

        }

127 128 129
        return true;
    }

130 131
    case GUIEventAdapter::KEYDOWN:
        // pan model
132 133 134 135 136 137 138 139 140 141 142
        switch (ea.getKey()) {
        case GUIEventAdapter::KEY_Space: {
            flushMouseEventStack();
            _thrown = false;
            home(ea,us);
            us.requestRedraw();
            us.requestContinuousUpdate(false);
            return true;
        }
        case GUIEventAdapter::KEY_Left: {
            double scale = -_moveSensitivity * _distance;
143

144 145
            osg::Matrix rotation_matrix;
            rotation_matrix.makeRotate(_rotation);
146

147
            osg::Vec3d dv(scale, 0.0, 0.0);
148

149
            _center += dv * rotation_matrix;
150

151 152 153 154
            return true;
        }
        case GUIEventAdapter::KEY_Right: {
            double scale = _moveSensitivity * _distance;
155

156 157
            osg::Matrix rotation_matrix;
            rotation_matrix.makeRotate(_rotation);
158

159
            osg::Vec3d dv(scale, 0.0, 0.0);
160

161
            _center += dv * rotation_matrix;
162

163 164 165 166
            return true;
        }
        case GUIEventAdapter::KEY_Up: {
            double scale = _moveSensitivity * _distance;
167

168 169
            osg::Matrix rotation_matrix;
            rotation_matrix.makeRotate(_rotation);
170

171
            osg::Vec3d dv(0.0, scale, 0.0);
172

173
            _center += dv * rotation_matrix;
174

175 176 177 178
            return true;
        }
        case GUIEventAdapter::KEY_Down: {
            double scale = -_moveSensitivity * _distance;
179

180 181
            osg::Matrix rotation_matrix;
            rotation_matrix.makeRotate(_rotation);
182

183
            osg::Vec3d dv(0.0, scale, 0.0);
184

185
            _center += dv * rotation_matrix;
186

187 188 189
            return true;
        }
        return false;
190 191 192
        }

    case GUIEventAdapter::FRAME:
193 194
        if (_thrown) {
            if (calcMovement()) {
195 196 197 198 199 200 201 202 203 204 205 206
                us.requestRedraw();
            }
        }
        return false;

    default:
        return false;
    }
}


bool
207
GCManipulator::calcMovement(void)
208 209 210 211
{
    using namespace osgGA;

    // return if less then two events have been added.
212
    if (_ga_t0.get() == NULL || _ga_t1.get() == NULL) {
213 214 215
        return false;
    }

216 217
    double dx = _ga_t0->getXnormalized() - _ga_t1->getXnormalized();
    double dy = _ga_t0->getYnormalized() - _ga_t1->getYnormalized();
218 219

    // return if there is no movement.
220
    if (dx == 0.0 && dy == 0.0) {
221 222 223 224
        return false;
    }

    unsigned int buttonMask = _ga_t1->getButtonMask();
225
    if (buttonMask == GUIEventAdapter::LEFT_MOUSE_BUTTON) {
226
        // rotate camera
lm's avatar
lm committed
227
#if ((OPENSCENEGRAPH_MAJOR_VERSION == 2) & (OPENSCENEGRAPH_MINOR_VERSION > 8)) | (OPENSCENEGRAPH_MAJOR_VERSION > 2)
James Goppert's avatar
James Goppert committed
228
        osg::Vec3d axis;
lm's avatar
lm committed
229 230
#else
        osg::Vec3 axis;
231
#endif
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
        float angle;

        float px0 = _ga_t0->getXnormalized();
        float py0 = _ga_t0->getYnormalized();

        float px1 = _ga_t1->getXnormalized();
        float py1 = _ga_t1->getYnormalized();

        trackball(axis, angle, px1, py1, px0, py0);

        osg::Quat new_rotate;
        new_rotate.makeRotate(angle, axis);

        _rotation = _rotation * new_rotate;

        return true;

249 250 251
    } else if (buttonMask == GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
               buttonMask == (GUIEventAdapter::LEFT_MOUSE_BUTTON |
                              GUIEventAdapter::RIGHT_MOUSE_BUTTON)) {
252
        // pan model
253
        double scale = -_moveSensitivity * _distance;
254 255 256 257

        osg::Matrix rotation_matrix;
        rotation_matrix.makeRotate(_rotation);

258
        osg::Vec3d dv(dx * scale, dy * scale, 0.0);
259 260 261 262 263

        _center += dv * rotation_matrix;

        return true;

264
    } else if (buttonMask == GUIEventAdapter::RIGHT_MOUSE_BUTTON) {
265
        // zoom model
266
        double scale = 1.0 + dy * _zoomSensitivity;
267
        if (_distance * scale > _minZoomRange) {
268 269 270 271 272 273 274 275 276

            _distance *= scale;

        }
        return true;
    }

    return false;
}