Go to the documentation of this file.00001 #include "arenacontroller.h"
00002
00003 #include "arenascene.h"
00004 #include "arenasceneelement.h"
00005 #include "../model/arena.h"
00006 #include "../model/arenaelement.h"
00007 #include "../model/arenaelementtype.h"
00008
00009 #include <QPainter>
00010 #include <QDebug>
00011
00012 #include <math.h>
00013
00014 ArenaController::ArenaController(Arena *arena, ArenaScene *scene)
00015 : m_arena(arena)
00016 , m_scene(scene)
00017 , m_lastDragFinished(true)
00018 , m_autoRotateWalls(false)
00019 , m_snapToGrid(true)
00020 {
00021 }
00022
00023 qreal squaredDistance(const QPointF &a, const QPointF &b)
00024 {
00025 qreal diffX = b.x() - a.x();
00026 qreal diffY = b.y() - a.y();
00027 return diffX*diffX + diffY*diffY;
00028 }
00029
00030 int getSnapRotation(const QPointF &scenePos)
00031 {
00032 qreal halfItemSize = ITEM_SIZE / 2.0;
00033 QPointF gridPos = ArenaScene::nearestGridPoint(scenePos);
00034 QPointF top = gridPos - QPointF(0, halfItemSize);
00035 QPointF bottom = gridPos + QPointF(0, halfItemSize);
00036 QPointF left = gridPos - QPointF(halfItemSize, 0);
00037 QPointF right = gridPos + QPointF(halfItemSize, 0);
00038
00039 qreal distTop = squaredDistance(scenePos, top);
00040 qreal distBottom = squaredDistance(scenePos, bottom);
00041 qreal distLeft = squaredDistance(scenePos, left);
00042 qreal distRight = squaredDistance(scenePos, right);
00043
00044 qreal minDist = qMin(distTop, qMin(distBottom, qMin(distLeft, distRight)));
00045
00046 if (minDist == distTop)
00047 return 0;
00048 if (minDist == distRight)
00049 return 90;
00050 if (minDist == distBottom)
00051 return 180;
00052
00053 return 270;
00054 }
00055
00056 QPointF getRotationSnapPoint(const QPointF &scenePos)
00057 {
00058 QPointF gridPos = ArenaScene::nearestGridPoint(scenePos);
00059 QPointF top = gridPos + QPointF(ITEM_SIZE / 2.0, 0.0);
00060 QPointF bottom = gridPos + QPointF(ITEM_SIZE / 2.0, ITEM_SIZE);
00061 QPointF left = gridPos + QPointF(0.0, ITEM_SIZE / 2.0);
00062 QPointF right = gridPos + QPointF(ITEM_SIZE, ITEM_SIZE / 2.0);
00063
00064 qreal distTop = squaredDistance(scenePos, top);
00065 qreal distBottom = squaredDistance(scenePos, bottom);
00066 qreal distLeft = squaredDistance(scenePos, left);
00067 qreal distRight = squaredDistance(scenePos, right);
00068
00069 qreal minDist = qMin(distTop, qMin(distBottom, qMin(distLeft, distRight)));
00070
00071 if (minDist == distTop)
00072 return top;
00073 if (minDist == distRight)
00074 return right;
00075 if (minDist == distBottom)
00076 return bottom;
00077
00078 return left;
00079 }
00080
00081 void ArenaController::startDrag(ArenaSceneElement *sceneElement)
00082 {
00083 startDrag(QList<ArenaSceneElement*>() << sceneElement);
00084 }
00085
00086 void ArenaController::startDrag(QList<ArenaSceneElement*> sceneElements)
00087 {
00088 m_activeElements = sceneElements;
00089 m_lastDragFinished = false;
00090 m_totalMouseOffset = QPointF(0, 0);
00091
00092 m_origPositions.clear();
00093 foreach (ArenaSceneElement *sceneElement, sceneElements)
00094 m_origPositions[sceneElement] = sceneElement->pos();
00095
00096
00097 setSnapToGrid(!(sceneElements.count() == 1 &&
00098 sceneElements.first()->element()->isItem()));
00099
00100 setAutoRotateWalls(sceneElements.count() == 1);
00101 }
00102
00103 void ArenaController::startInsertion(const QString &elementType, const QPointF &pos)
00104 {
00105 foreach (QGraphicsItem *item, m_scene->selectedItems())
00106 item->setSelected(false);
00107
00108 ArenaElement *element = m_arena->addElement(elementType);
00109 Q_ASSERT(element);
00110
00111
00112 ArenaSceneElement *sceneElement = m_scene->sceneElementFor(element);
00113 Q_ASSERT(sceneElement);
00114
00115 sceneElement->setSelected(true);
00116
00117 startDrag(sceneElement);
00118
00119 dragTo(pos);
00120 }
00121
00122 void ArenaController::cancelInsertion()
00123 {
00124 foreach (ArenaSceneElement *activeElement, m_activeElements)
00125 {
00126 ArenaElement *element = activeElement->element();
00127 m_arena->removeElement(element);
00128 delete element;
00129
00130 }
00131
00132 endOperation();
00133 }
00134
00135 void ArenaController::endOperation()
00136 {
00137 m_activeElements.clear();
00138 m_lastDragFinished = true;
00139 }
00140
00141 bool ArenaController::operationInProgress() const
00142 {
00143 return !m_lastDragFinished;
00144 }
00145
00146 void ArenaController::dragBy(const QPointF &by)
00147 {
00148 m_totalMouseOffset += by;
00149 QPointF gridMouseOffset = m_snapToGrid ?
00150 ArenaScene::nearestGridPoint(m_totalMouseOffset) : m_totalMouseOffset;
00151 foreach (ArenaSceneElement *activeElement, m_activeElements)
00152 {
00153 QPointF origPos = m_origPositions[activeElement];
00154 QPointF newPos = origPos + gridMouseOffset;
00155 qDebug() << "origPos:" << origPos;
00156 dragTo(activeElement, newPos);
00157 }
00158 }
00159
00160 void ArenaController::dragTo(const QPointF &to)
00161 {
00162 foreach (ArenaSceneElement *activeElement, m_activeElements)
00163 {
00164 dragTo(activeElement, to);
00165 }
00166 }
00167
00168 void ArenaController::dragTo(ArenaSceneElement *sceneElement, const QPointF &to)
00169 {
00170 ArenaElement *element = sceneElement->element();
00171
00172 element->setPos(ArenaScene::sceneToGrid(to));
00173
00174 QPointF gridPointScene = ArenaScene::nearestGridPoint(to);
00175 if (element->isItem())
00176 {
00177 QPointF gridOffset = ArenaScene::sceneToGridF(to) -
00178 ArenaScene::sceneToGridF(gridPointScene);
00179 element->setItemOffset(gridOffset);
00180 }
00181
00182 if (m_autoRotateWalls && element->isWall())
00183 {
00184 element->setRotation(getSnapRotation(to));
00185 }
00186 }
00187
00188 void ArenaController::draw(QPainter *painter, const QRectF &rect)
00189 {
00190 if (m_activeElements.count() != 1)
00191 return;
00192
00193 ArenaSceneElement *activeElement = m_activeElements.first();
00194 if (activeElement->element()->isWall() || activeElement->element()->isItem())
00195 {
00196 QPointF gridPos = ArenaScene::nearestGridPoint(activeElement->pos());
00197 int r = 10;
00198 painter->setBrush(QBrush(0xE0E0E0));
00199 painter->setPen(0xE0E0E0);
00200 painter->drawEllipse(gridPos, r, r);
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 }
00213 }