Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
CursorPainter.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50
51
52
53 //=============================================================================
54 //
55 // CLASS CursorPainter - IMPLEMENTATION
56 //
57 //=============================================================================
58
59 //== INCLUDES =================================================================
60
61 #include <QPixmap>
62 #include <QBitmap>
63
64 #include <OpenFlipper/common/GlobalOptions.hh>
65
66 #include "CursorPainter.hh"
67 #include "QtBaseViewer.hh"
68
69 //== NAMESPACES ===============================================================
70
71 CursorPainter::CursorPainter (QObject *_parent) :
72 QObject(_parent),
73 cursor_(),
74 initialized_(false),
75 enabled_(false),
76 mouseIn_(false),
77 forceNative_(false),
78 xOff_(0),
79 yOff_(0),
80 texture_(0),
81 hasCursor_(false)
82 {
83 }
84
85 //-----------------------------------------------------------------------------
86
87 CursorPainter::~CursorPainter ()
88 {
89 if (initialized_)
90 {
91 glDeleteTextures (1, &texture_);
92 }
93 }
94
95 //-----------------------------------------------------------------------------
96
97 void CursorPainter::setCursor (const QCursor &_cursor)
98 {
99 nativeCursor_ = _cursor;
100 cursorToCursor ();
101 cursorToTexture ();
102 if (!(initialized_ && enabled_ && hasCursor_) || forceNative_) {
103 foreach (glViewer *v, views_)
104 v->setCursor ((forceNative_)? nativeCursor_ : cursor_);
105 }
106 }
107
108 //-----------------------------------------------------------------------------
109
110 void CursorPainter::initializeGL()
111 {
112 if (initialized_)
113 return;
114 initialized_ = true;
115
116 // setup cursor texture
117 glGenTextures (1, &texture_);
118
119 ACG::GLState::bindTexture (GL_TEXTURE_2D, texture_);
120 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
121 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
122 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
123 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
124 ACG::GLState::bindTexture (GL_TEXTURE_2D, 0);
125
126 cursorToTexture ();
127
128 if (enabled_ && hasCursor_ && !forceNative_)
129 {
130 foreach (glViewer *v, views_)
131 v->setCursor (Qt::BlankCursor);
132
133 }
134 else
135 {
136 foreach (glViewer *v, views_)
137 v->setCursor ((forceNative_)? nativeCursor_ : cursor_);
138
139 }
140 }
141
142 //-----------------------------------------------------------------------------
143
144 void CursorPainter::registerViewer(glViewer * _viewer)
145 {
146 views_.append (_viewer);
147 _viewer->setCursorPainter (this);
148 }
149
150 //-----------------------------------------------------------------------------
151
152 void CursorPainter::paintCursor (ACG::GLState *_state)
153 {
154 if (!initialized_)
155 return;
156
157 if (!enabled())
158 return;
159
160 // project (0, 0, 0) to get its position on the screen
161 ACG::Vec3d zPos = _state->project (ACG::Vec3d (0.0, 0.0, 0.0));
162 // unproject the result translated by 1px in x and y
163 zPos = _state->unproject (ACG::Vec3d (zPos[0] + 1, zPos[1] + 1, zPos[2]));
164
165 // this gives us the size of one pixel in the current scene transformation
166 // now we can paint the cursor always with the same width/height
167 float xscale = zPos[0];
168 float yscale = -zPos[1];
169
170 glPushAttrib (GL_ALL_ATTRIB_BITS);
171
172 ACG::GLState::disable (GL_DEPTH_TEST);
173 ACG::GLState::disable(GL_LIGHTING);
174 ACG::GLState::enable(GL_BLEND);
175
176 ACG::GLState::blendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
177
178 // bind texture
179 ACG::GLState::enable (GL_TEXTURE_2D);
180 ACG::GLState::bindTexture (GL_TEXTURE_2D, texture_);
181
182 glColor4f (1.0, 1.0, 1.0, 1.0);
183
184 float x1 = -xOff_ * xscale;
185 float x2 = (32 - xOff_) * xscale;
186 float y1 = -yOff_ * yscale;
187 float y2 = (32 - yOff_) * yscale;
188
189 // draw cursor quad
190 glBegin (GL_QUADS);
191 glTexCoord2f (0, 0);
192 glVertex3f (x1, y1, 0);
193 glTexCoord2f (0, 1);
194 glVertex3f (x1, y2, 0);
195 glTexCoord2f (1, 1);
196 glVertex3f (x2, y2, 0);
197 glTexCoord2f (1, 0);
198 glVertex3f (x2, y1, 0);
199 glEnd ();
200
201
202 glPopAttrib ();
203 }
204
205 //-----------------------------------------------------------------------------
206
207 void CursorPainter::updateCursorPosition (QPointF _scenePos)
208 {
209 cursorPos_ = _scenePos;
210 setMouseIn (true);
211 }
212
213 //-----------------------------------------------------------------------------
214
215 QPointF CursorPainter::cursorPosition()
216 {
217 return cursorPos_;
218 }
219
220 //-----------------------------------------------------------------------------
221
222 void CursorPainter::setEnabled(bool _enabled)
223 {
224 enabled_ = _enabled;
225
226 if (initialized_)
227 {
228 if (_enabled && hasCursor_)
229 {
230 foreach (glViewer *v, views_)
231 v->setCursor (Qt::BlankCursor);
232 }
233 else
234 {
235 foreach (glViewer *v, views_)
236 v->setCursor ((forceNative_)? nativeCursor_ : cursor_);
237 }
238 }
239 }
240
241 //-----------------------------------------------------------------------------
242
243 bool CursorPainter::enabled()
244 {
245 return initialized_ && enabled_ && hasCursor_ && mouseIn_ && !forceNative_;
246 }
247
248 //-----------------------------------------------------------------------------
249
250 void CursorPainter::cursorToTexture()
251 {
252
253 if (!initialized_) {
254 return;
255 }
256
257 unsigned char buf[4096];
258 QImage cImg;
259
260 hasCursor_ = false;
261
262 // Initialize hotspot with default position in the upper left corner of the cursor
263 xOff_ = 0;
264 yOff_ = 0;
265
267 switch (nativeCursor_.shape())
268 {
269 case Qt::ArrowCursor:
270 cImg.load (OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cursor_arrow.png");
271 break;
272 case Qt::PointingHandCursor:
273 cImg.load (OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cursor_move.png");
274 break;
275 case Qt::WhatsThisCursor:
276 cImg.load (OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cursor_whatsthis.png");
277 break;
278 case Qt::BitmapCursor:
279 // Get the image of the cursor
280 cImg = QImage(( nativeCursor_.pixmap().toImage() ) );
281
282
283 // get the hotspot from the cursor
284 xOff_ = nativeCursor_.hotSpot().x();
285 yOff_ = nativeCursor_.hotSpot().y();
286 break;
287 default:
288 std::cerr << "cursorToTexture: Unknown cursor shape!" << nativeCursor_.shape() << std::endl;
289 return;
290 }
291
292 // Check if the cursor dimension is matching our requirements
293 if (cImg.width () != 32 || cImg.height () != 32) {
294 std::cerr << "cursorToTexture: Dimension error" << nativeCursor_.shape() << std::endl;
295 return;
296 }
297
298 // convert ARGB QImage to RGBA for gl
299 int index = 0;
300 for (int y = 0; y < cImg.height (); y++)
301 for (int x = 0; x < cImg.width (); x++)
302 {
303 QRgb pix = cImg.pixel (x, y);
304 buf[index] = qRed (pix);
305 buf[index+1] = qGreen (pix);
306 buf[index+2] = qBlue (pix);
307 buf[index+3] = qAlpha (pix);
308 index += 4;
309 }
310
311 ACG::GLState::enable (GL_TEXTURE_2D);
312 ACG::GLState::bindTexture (GL_TEXTURE_2D, texture_);
313 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0,
314 GL_RGBA, GL_UNSIGNED_BYTE, buf);
315 ACG::GLState::bindTexture (GL_TEXTURE_2D, 0);
316 ACG::GLState::disable (GL_TEXTURE_2D);
317
318 hasCursor_ = true;
319 }
320
321 //-----------------------------------------------------------------------------
322
323 void CursorPainter::setMouseIn(bool _in)
324 {
325 mouseIn_ = _in;
326 }
327
328 //-----------------------------------------------------------------------------
329
330 QRectF CursorPainter::cursorBoundingBox()
331 {
332 return QRectF (-xOff_, -yOff_, 32, 32);
333 }
334
335 //=============================================================================
336 //=============================================================================
337
338 void CursorPainter::setForceNative(bool _enabled)
339 {
340 forceNative_ = _enabled;
341
342 if (!(initialized_ && enabled_ && hasCursor_) || forceNative_)
343 {
344 foreach (glViewer *v, views_)
345 v->setCursor ((forceNative_)? nativeCursor_ : cursor_);
346
347 }
348 else
349 {
350 foreach (glViewer *v, views_)
351 v->setCursor (Qt::BlankCursor);
352 }
353 }
354
355 void CursorPainter::cursorToCursor()
356 {
357 QPixmap pix;
358
359 switch (nativeCursor_.shape())
360 {
361 case Qt::ArrowCursor:
362 pix.load (OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cursor_arrow.png");
363 if (!pix.isNull() && pix.width() == 32 && pix.height() == 32)
364 {
365 cursor_ = QCursor (pix, 0, 0);
366 }
367 else
368 cursor_ = nativeCursor_;
369 break;
370 case Qt::PointingHandCursor:
371 pix.load (OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cursor_move.png");
372 if (!pix.isNull() && pix.width() == 32 && pix.height() == 32)
373 {
374 cursor_ = QCursor (pix, 0, 0);
375 }
376 else
377 cursor_ = nativeCursor_;
378 break;
379 default:
380 cursor_ = nativeCursor_;
381 return;
382 }
383 }
384
385
386
CursorPainter::setForceNative
void setForceNative(bool _enabled)
Enabled/Disables native cursors.
Definition: CursorPainter.cc:338
ACG::GLState::enable
static void enable(GLenum _cap)
replaces glEnable, but supports locking
Definition: GLState.cc:1490
glViewer::setCursorPainter
void setCursorPainter(CursorPainter *_cursorPainter)
sets the current cursor painter
Definition: QtBaseViewer.cc:2420
CursorPainter::setMouseIn
void setMouseIn(bool _in)
Inform the cursor painter about mouse enter / leave.
Definition: CursorPainter.cc:323
CursorPainter::registerViewer
void registerViewer(glViewer *_viewer)
Add a glViewer that will use this CursorPainter.
Definition: CursorPainter.cc:144
ACG::GLState::unproject
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:649
ACG::GLState::bindTexture
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1812
CursorPainter::cursorBoundingBox
QRectF cursorBoundingBox()
Bounding box of the cursor.
Definition: CursorPainter.cc:330
CursorPainter::enabled
bool enabled()
Returns true if cursor painting is enabled and compatible cursor is set.
Definition: CursorPainter.cc:243
ACG::GLState
Definition: GLState.hh:220
ACG::GLState::blendFunc
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:314
CursorPainter::cursorToTexture
void cursorToTexture()
Definition: CursorPainter.cc:250
CursorPainter::paintCursor
void paintCursor(ACG::GLState *_state)
Cursor painting function. The _state has to be setup that 0,0,0 is at the cursor position.
Definition: CursorPainter.cc:152
OpenMesh::VectorT
Definition: Vector11T.hh:83
CursorPainter::cursorPosition
QPointF cursorPosition()
Return the current cursor position.
Definition: CursorPainter.cc:215
CursorPainter::~CursorPainter
~CursorPainter()
Destructor.
Definition: CursorPainter.cc:87
GlobalOptions.hh
glViewer
Definition: QtBaseViewer.hh:130
CursorPainter::initializeGL
void initializeGL()
Needs to be called after the gl context has been set up to initialize internal values.
Definition: CursorPainter.cc:110
ACG::GLState::disable
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Definition: GLState.cc:1504
CursorPainter::setEnabled
void setEnabled(bool _enabled)
Enabled/Disables gl cursor painting.
Definition: CursorPainter.cc:222
CursorPainter::CursorPainter
CursorPainter(QObject *_parent=0)
Constructor.
Definition: CursorPainter.cc:71
CursorPainter::updateCursorPosition
void updateCursorPosition(QPointF _scenePos)
Sets the current cursor position.
Definition: CursorPainter.cc:207
CursorPainter::setCursor
void setCursor(const QCursor &_cursor)
Sets the current used cursor.
Definition: CursorPainter.cc:97
ACG::GLState::project
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:638