arenacontroller.cpp
Go to the documentation of this file.
1 #include "arenacontroller.h"
2 
3 #include "arenascene.h"
4 #include "arenasceneelement.h"
5 #include "../model/arena.h"
6 #include "../model/arenaelement.h"
7 #include "../model/arenaelementtype.h"
8 
9 #include <QPainter>
10 #include <QDebug>
11 
12 #include <math.h>
13 
15  : m_arena(arena)
16  , m_scene(scene)
17  , m_lastDragFinished(true)
18  , m_autoRotateWalls(false)
19  , m_snapToGrid(true)
20 {
21 }
22 
23 qreal squaredDistance(const QPointF &a, const QPointF &b)
24 {
25  qreal diffX = b.x() - a.x();
26  qreal diffY = b.y() - a.y();
27  return diffX*diffX + diffY*diffY;
28 }
29 
30 int getSnapRotation(const QPointF &scenePos)
31 {
32  qreal halfItemSize = ITEM_SIZE / 2.0;
33  QPointF gridPos = ArenaScene::nearestGridPoint(scenePos);
34  QPointF top = gridPos - QPointF(0, halfItemSize);
35  QPointF bottom = gridPos + QPointF(0, halfItemSize);
36  QPointF left = gridPos - QPointF(halfItemSize, 0);
37  QPointF right = gridPos + QPointF(halfItemSize, 0);
38 
39  qreal distTop = squaredDistance(scenePos, top);
40  qreal distBottom = squaredDistance(scenePos, bottom);
41  qreal distLeft = squaredDistance(scenePos, left);
42  qreal distRight = squaredDistance(scenePos, right);
43 
44  qreal minDist = qMin(distTop, qMin(distBottom, qMin(distLeft, distRight)));
45 
46  if (minDist == distTop)
47  return 0;
48  if (minDist == distRight)
49  return 90;
50  if (minDist == distBottom)
51  return 180;
52  //if (minDist == distLeft)
53  return 270;
54 }
55 
56 QPointF getRotationSnapPoint(const QPointF &scenePos)
57 {
58  QPointF gridPos = ArenaScene::nearestGridPoint(scenePos);
59  QPointF top = gridPos + QPointF(ITEM_SIZE / 2.0, 0.0);
60  QPointF bottom = gridPos + QPointF(ITEM_SIZE / 2.0, ITEM_SIZE);
61  QPointF left = gridPos + QPointF(0.0, ITEM_SIZE / 2.0);
62  QPointF right = gridPos + QPointF(ITEM_SIZE, ITEM_SIZE / 2.0);
63 
64  qreal distTop = squaredDistance(scenePos, top);
65  qreal distBottom = squaredDistance(scenePos, bottom);
66  qreal distLeft = squaredDistance(scenePos, left);
67  qreal distRight = squaredDistance(scenePos, right);
68 
69  qreal minDist = qMin(distTop, qMin(distBottom, qMin(distLeft, distRight)));
70 
71  if (minDist == distTop)
72  return top;
73  if (minDist == distRight)
74  return right;
75  if (minDist == distBottom)
76  return bottom;
77  //if (minDist == distLeft)
78  return left;
79 }
80 
82 {
83  startDrag(QList<ArenaSceneElement*>() << sceneElement);
84 }
85 
86 void ArenaController::startDrag(QList<ArenaSceneElement*> sceneElements)
87 {
88  m_activeElements = sceneElements;
89  m_lastDragFinished = false;
90  m_totalMouseOffset = QPointF(0, 0);
91 
92  m_origPositions.clear();
93  foreach (ArenaSceneElement *sceneElement, sceneElements)
94  m_origPositions[sceneElement] = sceneElement->pos();
95 
96  // Only freely movable items require snap to grid to be turned off
97  setSnapToGrid(!(sceneElements.count() == 1 &&
98  sceneElements.first()->element()->isItem()));
99  // Only auto-rotate walls if we are moving only one wall
100  setAutoRotateWalls(sceneElements.count() == 1);
101 }
102 
103 void ArenaController::startInsertion(const QString &elementType, const QPointF &pos)
104 {
105  foreach (QGraphicsItem *item, m_scene->selectedItems())
106  item->setSelected(false);
107 
108  ArenaElement *element = m_arena->addElement(elementType);
109  Q_ASSERT(element);
110 
111  // ArenaSceneElement is automatically created when ArenaElement is added to arena
112  ArenaSceneElement *sceneElement = m_scene->sceneElementFor(element);
113  Q_ASSERT(sceneElement);
114 
115  sceneElement->setSelected(true);
116 
117  startDrag(sceneElement);
118 
119  dragTo(pos);
120 }
121 
123 {
124  foreach (ArenaSceneElement *activeElement, m_activeElements)
125  {
126  ArenaElement *element = activeElement->element();
127  m_arena->removeElement(element);
128  delete element;
129  // activeElement is deleted automatically by the scene
130  }
131 
132  endOperation();
133 }
134 
136 {
137  m_activeElements.clear();
138  m_lastDragFinished = true;
139 }
140 
142 {
143  return !m_lastDragFinished;
144 }
145 
146 void ArenaController::dragBy(const QPointF &by)
147 {
148  m_totalMouseOffset += by;
149  QPointF gridMouseOffset = m_snapToGrid ?
151  foreach (ArenaSceneElement *activeElement, m_activeElements)
152  {
153  QPointF origPos = m_origPositions[activeElement];
154  QPointF newPos = origPos + gridMouseOffset;
155  qDebug() << "origPos:" << origPos;
156  dragTo(activeElement, newPos);
157  }
158 }
159 
160 void ArenaController::dragTo(const QPointF &to)
161 {
162  foreach (ArenaSceneElement *activeElement, m_activeElements)
163  {
164  dragTo(activeElement, to);
165  }
166 }
167 
168 void ArenaController::dragTo(ArenaSceneElement *sceneElement, const QPointF &to)
169 {
170  ArenaElement *element = sceneElement->element();
171 
172  element->setPos(ArenaScene::sceneToGrid(to));
173 
174  QPointF gridPointScene = ArenaScene::nearestGridPoint(to);
175  if (element->isItem())
176  {
177  QPointF gridOffset = ArenaScene::sceneToGridF(to) -
178  ArenaScene::sceneToGridF(gridPointScene);
179  element->setItemOffset(gridOffset/* + QPointF(0, 1)*/);
180  }
181 
182  if (m_autoRotateWalls && element->isWall())
183  {
184  element->setRotation(getSnapRotation(to));
185  }
186 }
187 
188 void ArenaController::draw(QPainter *painter, const QRectF &rect)
189 {
190  if (m_activeElements.count() != 1)
191  return;
192 
193  ArenaSceneElement *activeElement = m_activeElements.first();
194  if (activeElement->element()->isWall() || activeElement->element()->isItem())
195  {
196  QPointF gridPos = ArenaScene::nearestGridPoint(activeElement->pos());
197  int r = 10;
198  painter->setBrush(QBrush(0xE0E0E0));
199  painter->setPen(0xE0E0E0);
200  painter->drawEllipse(gridPos, r, r);
201 
202  /*
203  if (m_activeElement->element()->isWall())
204  {
205  QPointF snapPos = getRotationSnapPoint(m_mousePos);
206  QPointF lineDir = (snapPos - center);
207  lineDir /= sqrt(lineDir.x()*lineDir.x() + lineDir.y()*lineDir.y());
208 
209  painter->drawLine(center + lineDir * r, snapPos);
210  }
211  */
212  }
213 }
QMap< ArenaSceneElement *, QPointF > m_origPositions
qreal squaredDistance(const QPointF &a, const QPointF &b)
void removeElement(ArenaElement *element)
Definition: arena.cpp:461
bool operationInProgress() const
void setItemOffset(const QPointF &offset)
See itemOffset()
void draw(QPainter *painter, const QRectF &rect)
const int ITEM_SIZE
Definition: arenascene.h:13
static QPoint sceneToGrid(QPointF scenePos)
Definition: arenascene.cpp:33
bool isItem() const
Convenience method returning true iff. this is an item element (freely movable)
void dragTo(const QPointF &to)
void setSnapToGrid(bool snap)
ArenaElement * element() const
void dragBy(const QPointF &by)
Definition: arena.h:10
QPointF getRotationSnapPoint(const QPointF &scenePos)
void setRotation(int rotation)
Sets the rotation in degrees.
ArenaScene * m_scene
ArenaElement * addElement(const QString &elementType)
Creates and adds an element of type elementType.
Definition: arena.cpp:481
void setPos(QPoint pos)
Sets the position in arena coordinates.
int getSnapRotation(const QPointF &scenePos)
static QPointF sceneToGridF(QPointF scenePos)
Definition: arenascene.cpp:39
static QPointF nearestGridPoint(QPointF scenePos)
Definition: arenascene.cpp:56
ArenaController(Arena *arena, ArenaScene *scene)
void startInsertion(const QString &elementType, const QPointF &pos)
QPointF m_totalMouseOffset
QList< ArenaSceneElement * > m_activeElements
SceneElement currently being manipulated through this controller.
ArenaSceneElement * sceneElementFor(ArenaElement *element)
Definition: arenascene.cpp:74
bool isWall() const
Convenience method returning true iff. this is a wall element.
bool m_lastDragFinished
True iff. endDrag() has been called after last startDrag()
void startDrag(ArenaSceneElement *sceneElement)
void setAutoRotateWalls(bool autoRotate)


hector_nist_arena_designer
Author(s): Stefan Kohlbrecher , Johannes Simon
autogenerated on Fri Aug 21 2020 10:45:27