$search
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 }