arenacontroller.cpp
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     //if (minDist == distLeft)
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     //if (minDist == distLeft)
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     // Only freely movable items require snap to grid to be turned off
00097     setSnapToGrid(!(sceneElements.count() == 1 &&
00098                     sceneElements.first()->element()->isItem()));
00099     // Only auto-rotate walls if we are moving only one wall
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     // ArenaSceneElement is automatically created when ArenaElement is added to arena
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         // activeElement is deleted automatically by the scene
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/* + QPointF(0, 1)*/);
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         if (m_activeElement->element()->isWall())
00204         {
00205             QPointF snapPos = getRotationSnapPoint(m_mousePos);
00206             QPointF lineDir = (snapPos - center);
00207             lineDir /= sqrt(lineDir.x()*lineDir.x() + lineDir.y()*lineDir.y());
00208 
00209             painter->drawLine(center + lineDir * r, snapPos);
00210         }
00211         */
00212     }
00213 }


hector_nist_arena_designer
Author(s): Johannes Simon, Stefan Kohlbrecher
autogenerated on Thu Aug 27 2015 13:12:37