1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 ** This file is part of the demonstration applications of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the Technology Preview License Agreement accompanying
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
44 const qreal ROTATE_SPEED_X
= 30.0 / 1000.0;
45 const qreal ROTATE_SPEED_Y
= 20.0 / 1000.0;
46 const qreal ROTATE_SPEED_Z
= 40.0 / 1000.0;
47 const int MAX_ITEM_SIZE
= 512;
48 const int MIN_ITEM_SIZE
= 16;
50 //============================================================================//
52 //============================================================================//
54 ItemBase::ItemBase(int size
, int x
, int y
) : m_size(size
), m_isResizing(false)
56 setFlag(QGraphicsItem::ItemIsMovable
, true);
57 setFlag(QGraphicsItem::ItemIsSelectable
, true);
58 setFlag(QGraphicsItem::ItemIsFocusable
, true);
59 setAcceptHoverEvents(true);
61 m_startTime
= QTime::currentTime();
68 QRectF
ItemBase::boundingRect() const
70 return QRectF(-m_size
/ 2, -m_size
/ 2, m_size
, m_size
);
73 void ItemBase::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
*)
75 if (option
->state
& QStyle::State_Selected
) {
76 painter
->setRenderHint(QPainter::Antialiasing
, true);
77 if (option
->state
& QStyle::State_HasFocus
)
78 painter
->setPen(Qt::yellow
);
80 painter
->setPen(Qt::white
);
81 painter
->drawRect(boundingRect());
83 painter
->drawLine(m_size
/ 2 - 9, m_size
/ 2, m_size
/ 2, m_size
/ 2 - 9);
84 painter
->drawLine(m_size
/ 2 - 6, m_size
/ 2, m_size
/ 2, m_size
/ 2 - 6);
85 painter
->drawLine(m_size
/ 2 - 3, m_size
/ 2, m_size
/ 2, m_size
/ 2 - 3);
87 painter
->setRenderHint(QPainter::Antialiasing
, false);
91 void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent
*event
)
93 if (!isSelected() && scene()) {
94 scene()->clearSelection();
99 QAction
*delAction
= menu
.addAction("Delete");
100 QAction
*newAction
= menu
.addAction("New");
101 QAction
*growAction
= menu
.addAction("Grow");
102 QAction
*shrinkAction
= menu
.addAction("Shrink");
104 QAction
*selectedAction
= menu
.exec(event
->screenPos());
106 if (selectedAction
== delAction
)
107 deleteSelectedItems(scene());
108 else if (selectedAction
== newAction
)
109 duplicateSelectedItems(scene());
110 else if (selectedAction
== growAction
)
111 growSelectedItems(scene());
112 else if (selectedAction
== shrinkAction
)
113 shrinkSelectedItems(scene());
116 void ItemBase::duplicateSelectedItems(QGraphicsScene
*scene
)
121 QList
<QGraphicsItem
*> selected
;
122 selected
= scene
->selectedItems();
124 foreach (QGraphicsItem
*item
, selected
) {
125 ItemBase
*itemBase
= qgraphicsitem_cast
<ItemBase
*>(item
);
127 scene
->addItem(itemBase
->createNew(itemBase
->m_size
, itemBase
->pos().x() + itemBase
->m_size
, itemBase
->pos().y()));
131 void ItemBase::deleteSelectedItems(QGraphicsScene
*scene
)
136 QList
<QGraphicsItem
*> selected
;
137 selected
= scene
->selectedItems();
139 foreach (QGraphicsItem
*item
, selected
) {
140 ItemBase
*itemBase
= qgraphicsitem_cast
<ItemBase
*>(item
);
146 void ItemBase::growSelectedItems(QGraphicsScene
*scene
)
151 QList
<QGraphicsItem
*> selected
;
152 selected
= scene
->selectedItems();
154 foreach (QGraphicsItem
*item
, selected
) {
155 ItemBase
*itemBase
= qgraphicsitem_cast
<ItemBase
*>(item
);
157 itemBase
->prepareGeometryChange();
158 itemBase
->m_size
*= 2;
159 if (itemBase
->m_size
> MAX_ITEM_SIZE
)
160 itemBase
->m_size
= MAX_ITEM_SIZE
;
165 void ItemBase::shrinkSelectedItems(QGraphicsScene
*scene
)
170 QList
<QGraphicsItem
*> selected
;
171 selected
= scene
->selectedItems();
173 foreach (QGraphicsItem
*item
, selected
) {
174 ItemBase
*itemBase
= qgraphicsitem_cast
<ItemBase
*>(item
);
176 itemBase
->prepareGeometryChange();
177 itemBase
->m_size
/= 2;
178 if (itemBase
->m_size
< MIN_ITEM_SIZE
)
179 itemBase
->m_size
= MIN_ITEM_SIZE
;
184 void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent
*event
)
187 int dx
= int(2.0 * event
->pos().x());
188 int dy
= int(2.0 * event
->pos().y());
189 prepareGeometryChange();
190 m_size
= (dx
> dy
? dx
: dy
);
191 if (m_size
< MIN_ITEM_SIZE
)
192 m_size
= MIN_ITEM_SIZE
;
193 else if (m_size
> MAX_ITEM_SIZE
)
194 m_size
= MAX_ITEM_SIZE
;
196 QGraphicsItem::mouseMoveEvent(event
);
200 void ItemBase::hoverMoveEvent(QGraphicsSceneHoverEvent
*event
)
202 if (m_isResizing
|| (isInResizeArea(event
->pos()) && isSelected()))
203 setCursor(Qt::SizeFDiagCursor
);
205 setCursor(Qt::ArrowCursor
);
206 QGraphicsItem::hoverMoveEvent(event
);
209 void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent
*event
)
211 static qreal z
= 0.0;
213 if (event
->button() == Qt::LeftButton
&& isInResizeArea(event
->pos())) {
216 QGraphicsItem::mousePressEvent(event
);
220 void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent
*event
)
222 if (event
->button() == Qt::LeftButton
&& m_isResizing
) {
223 m_isResizing
= false;
225 QGraphicsItem::mouseReleaseEvent(event
);
229 void ItemBase::keyPressEvent(QKeyEvent
*event
)
231 switch (event
->key()) {
233 deleteSelectedItems(scene());
236 duplicateSelectedItems(scene());
239 growSelectedItems(scene());
242 shrinkSelectedItems(scene());
245 QGraphicsItem::keyPressEvent(event
);
250 void ItemBase::wheelEvent(QGraphicsSceneWheelEvent
*event
)
252 prepareGeometryChange();
253 m_size
= int(m_size
* exp(-event
->delta() / 600.0));
254 if (m_size
> MAX_ITEM_SIZE
)
255 m_size
= MAX_ITEM_SIZE
;
256 else if (m_size
< MIN_ITEM_SIZE
)
257 m_size
= MIN_ITEM_SIZE
;
260 int ItemBase::type() const
266 bool ItemBase::isInResizeArea(const QPointF
&pos
)
268 return (-pos
.y() < pos
.x() - m_size
+ 9);
271 //============================================================================//
273 //============================================================================//
275 QtBox::QtBox(int size
, int x
, int y
) : ItemBase(size
, x
, y
), m_texture(0)
277 for (int i
= 0; i
< 8; ++i
) {
278 m_vertices
[i
].setX(i
& 1 ? 0.5f
: -0.5f
);
279 m_vertices
[i
].setY(i
& 2 ? 0.5f
: -0.5f
);
280 m_vertices
[i
].setZ(i
& 4 ? 0.5f
: -0.5f
);
282 for (int i
= 0; i
< 4; ++i
) {
283 m_texCoords
[i
].setX(i
& 1 ? 1.0f
: 0.0f
);
284 m_texCoords
[i
].setY(i
& 2 ? 1.0f
: 0.0f
);
286 m_normals
[0] = QVector3D(-1.0f
, 0.0f
, 0.0f
);
287 m_normals
[1] = QVector3D(1.0f
, 0.0f
, 0.0f
);
288 m_normals
[2] = QVector3D(0.0f
, -1.0f
, 0.0f
);
289 m_normals
[3] = QVector3D(0.0f
, 1.0f
, 0.0f
);
290 m_normals
[4] = QVector3D(0.0f
, 0.0f
, -1.0f
);
291 m_normals
[5] = QVector3D(0.0f
, 0.0f
, 1.0f
);
300 ItemBase
*QtBox::createNew(int size
, int x
, int y
)
302 return new QtBox(size
, x
, y
);
305 void QtBox::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
*widget
)
307 QRectF rect
= boundingRect().translated(pos());
308 float width
= float(painter
->device()->width());
309 float height
= float(painter
->device()->height());
311 float left
= 2.0f
* float(rect
.left()) / width
- 1.0f
;
312 float right
= 2.0f
* float(rect
.right()) / width
- 1.0f
;
313 float top
= 1.0f
- 2.0f
* float(rect
.top()) / height
;
314 float bottom
= 1.0f
- 2.0f
* float(rect
.bottom()) / height
;
315 float moveToRectMatrix
[] = {
316 0.5f
* (right
- left
), 0.0f
, 0.0f
, 0.0f
,
317 0.0f
, 0.5f
* (bottom
- top
), 0.0f
, 0.0f
,
318 0.0f
, 0.0f
, 1.0f
, 0.0f
,
319 0.5f
* (right
+ left
), 0.5f
* (bottom
+ top
), 0.0f
, 1.0f
322 painter
->beginNativePainting();
324 glMatrixMode(GL_PROJECTION
);
326 glLoadMatrixf(moveToRectMatrix
);
327 gluPerspective(60.0, 1.0, 0.01, 10.0);
329 glMatrixMode(GL_MODELVIEW
);
333 //glEnable(GL_DEPTH_TEST);
334 glEnable(GL_CULL_FACE
);
335 glEnable(GL_LIGHTING
);
336 glEnable(GL_COLOR_MATERIAL
);
337 glEnable(GL_NORMALIZE
);
340 m_texture
= new GLTexture2D(":/res/boxes/qt-logo.jpg", 64, 64);
342 glEnable(GL_TEXTURE_2D
);
344 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
);
345 float lightColour
[] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
346 float lightDir
[] = {0.0f
, 0.0f
, 1.0f
, 0.0f
};
347 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, lightColour
);
348 glLightfv(GL_LIGHT0
, GL_POSITION
, lightDir
);
351 glTranslatef(0.0f
, 0.0f
, -1.5f
);
352 glRotatef(ROTATE_SPEED_X
* m_startTime
.msecsTo(QTime::currentTime()), 1.0f
, 0.0f
, 0.0f
);
353 glRotatef(ROTATE_SPEED_Y
* m_startTime
.msecsTo(QTime::currentTime()), 0.0f
, 1.0f
, 0.0f
);
354 glRotatef(ROTATE_SPEED_Z
* m_startTime
.msecsTo(QTime::currentTime()), 0.0f
, 0.0f
, 1.0f
);
355 int dt
= m_startTime
.msecsTo(QTime::currentTime());
357 glScalef(dt
/ 500.0f
, dt
/ 500.0f
, dt
/ 500.0f
);
359 for (int dir
= 0; dir
< 3; ++dir
) {
360 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0);
362 glBegin(GL_TRIANGLE_STRIP
);
363 glNormal3fv(reinterpret_cast<float *>(&m_normals
[2 * dir
+ 0]));
364 for (int i
= 0; i
< 2; ++i
) {
365 for (int j
= 0; j
< 2; ++j
) {
366 glTexCoord2fv(reinterpret_cast<float *>(&m_texCoords
[(j
<< 1) | i
]));
367 glVertex3fv(reinterpret_cast<float *>(&m_vertices
[(i
<< ((dir
+ 2) % 3)) | (j
<< ((dir
+ 1) % 3))]));
372 glBegin(GL_TRIANGLE_STRIP
);
373 glNormal3fv(reinterpret_cast<float *>(&m_normals
[2 * dir
+ 1]));
374 for (int i
= 0; i
< 2; ++i
) {
375 for (int j
= 0; j
< 2; ++j
) {
376 glTexCoord2fv(reinterpret_cast<float *>(&m_texCoords
[(j
<< 1) | i
]));
377 glVertex3fv(reinterpret_cast<float *>(&m_vertices
[(1 << dir
) | (i
<< ((dir
+ 1) % 3)) | (j
<< ((dir
+ 2) % 3))]));
384 //glDisable(GL_DEPTH_TEST);
385 glDisable(GL_CULL_FACE
);
386 glDisable(GL_LIGHTING
);
387 glDisable(GL_COLOR_MATERIAL
);
388 glDisable(GL_TEXTURE_2D
);
389 glDisable(GL_LIGHT0
);
390 glDisable(GL_NORMALIZE
);
394 glMatrixMode(GL_PROJECTION
);
397 painter
->endNativePainting();
399 ItemBase::paint(painter
, option
, widget
);
402 //============================================================================//
404 //============================================================================//
406 CircleItem::CircleItem(int size
, int x
, int y
) : ItemBase(size
, x
, y
)
408 m_color
= QColor::fromHsv(rand() % 360, 255, 255);
411 void CircleItem::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
*widget
)
413 int dt
= m_startTime
.msecsTo(QTime::currentTime());
415 qreal r0
= 0.5 * m_size
* (1.0 - exp(-0.001 * ((dt
+ 3800) % 4000)));
416 qreal r1
= 0.5 * m_size
* (1.0 - exp(-0.001 * ((dt
+ 0) % 4000)));
417 qreal r2
= 0.5 * m_size
* (1.0 - exp(-0.001 * ((dt
+ 1800) % 4000)));
418 qreal r3
= 0.5 * m_size
* (1.0 - exp(-0.001 * ((dt
+ 2000) % 4000)));
426 path
.moveTo(r1
, 0.0);
427 path
.arcTo(-r1
, -r1
, 2 * r1
, 2 * r1
, 0.0, 360.0);
428 path
.lineTo(r0
, 0.0);
429 path
.arcTo(-r0
, -r0
, 2 * r0
, 2 * r0
, 0.0, -360.0);
431 path
.moveTo(r3
, 0.0);
432 path
.arcTo(-r3
, -r3
, 2 * r3
, 2 * r3
, 0.0, 360.0);
433 path
.lineTo(r0
, 0.0);
434 path
.arcTo(-r2
, -r2
, 2 * r2
, 2 * r2
, 0.0, -360.0);
436 painter
->setRenderHint(QPainter::Antialiasing
, true);
437 painter
->setBrush(QBrush(m_color
));
438 painter
->setPen(Qt::NoPen
);
439 painter
->drawPath(path
);
440 painter
->setBrush(Qt::NoBrush
);
441 painter
->setPen(Qt::SolidLine
);
442 painter
->setRenderHint(QPainter::Antialiasing
, false);
444 ItemBase::paint(painter
, option
, widget
);
447 ItemBase
*CircleItem::createNew(int size
, int x
, int y
)
449 return new CircleItem(size
, x
, y
);
452 //============================================================================//
454 //============================================================================//
456 SquareItem::SquareItem(int size
, int x
, int y
) : ItemBase(size
, x
, y
)
458 m_image
= QPixmap(":/res/boxes/square.jpg");
461 void SquareItem::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
*widget
)
463 int dt
= m_startTime
.msecsTo(QTime::currentTime());
464 QTransform oldTransform
= painter
->worldTransform();
465 int dtMod
= dt
% 2000;
466 qreal amp
= 0.002 * (dtMod
< 1000 ? dtMod
: 2000 - dtMod
) - 1.0;
468 qreal scale
= 0.6 + 0.2 * amp
* amp
;
469 painter
->setWorldTransform(QTransform().rotate(15.0 * amp
).scale(scale
, scale
), true);
471 painter
->drawPixmap(-m_size
/ 2, -m_size
/ 2, m_size
, m_size
, m_image
);
473 painter
->setWorldTransform(oldTransform
, false);
474 ItemBase::paint(painter
, option
, widget
);
477 ItemBase
*SquareItem::createNew(int size
, int x
, int y
)
479 return new SquareItem(size
, x
, y
);