File indexing completed on 2024-04-28 07:39:37
0001 /*. 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "motorgraphics.h" 0008 0009 #include "worldmodel.h" 0010 #include "worldscene.h" 0011 0012 #include <stepcore/motor.h> 0013 #include <stepcore/particle.h> 0014 #include <stepcore/rigidbody.h> 0015 0016 #include <QEvent> 0017 #include <QGraphicsSceneMouseEvent> 0018 #include <QItemSelectionModel> 0019 0020 #include <KLocalizedString> 0021 0022 bool LinearMotorCreator::sceneEvent(QEvent* event) 0023 { 0024 QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event); 0025 if(event->type() == QEvent::GraphicsSceneMousePress && mouseEvent->button() == Qt::LeftButton) { 0026 QPointF pos = mouseEvent->scenePos(); 0027 QVariant vpos = QVariant::fromValue(StepGraphicsItem::pointToVector(pos)); 0028 0029 _worldModel->simulationPause(); 0030 _worldModel->beginMacro(i18n("Create %1", _worldModel->newItemName(_className))); 0031 _item = _worldModel->createItem(className()); Q_ASSERT(_item != nullptr); 0032 0033 _worldModel->setProperty(_item, QStringLiteral("localPosition"), vpos); 0034 _worldModel->addItem(_item); 0035 tryAttach(pos); 0036 0037 _worldModel->selectionModel()->setCurrentIndex(_worldModel->objectIndex(_item), 0038 QItemSelectionModel::ClearAndSelect); 0039 _worldModel->endMacro(); 0040 0041 setFinished(); 0042 return true; 0043 } 0044 return false; 0045 } 0046 0047 void LinearMotorCreator::tryAttach(const QPointF& pos) 0048 { 0049 foreach(QGraphicsItem* it, _worldScene->items(pos)) { 0050 StepCore::Item* item = _worldScene->itemFromGraphics(it); 0051 if(dynamic_cast<StepCore::Particle*>(item) || dynamic_cast<StepCore::RigidBody*>(item)) { 0052 _worldModel->setProperty(_item, QStringLiteral("body"), 0053 QVariant::fromValue<StepCore::Object*>(item), WorldModel::UndoNoMerge); 0054 0055 StepCore::Vector2d lPos(0, 0); 0056 if(dynamic_cast<StepCore::RigidBody*>(item)) 0057 lPos = dynamic_cast<StepCore::RigidBody*>(item)->pointWorldToLocal(StepGraphicsItem::pointToVector(pos)); 0058 0059 _worldModel->setProperty(_item, QStringLiteral("localPosition"), QVariant::fromValue(lPos)); 0060 break; 0061 } 0062 } 0063 } 0064 0065 LinearMotorGraphicsItem::LinearMotorGraphicsItem(StepCore::Item* item, WorldModel* worldModel) 0066 : StepGraphicsItem(item, worldModel), _moving(false) 0067 { 0068 Q_ASSERT(dynamic_cast<StepCore::LinearMotor*>(_item) != nullptr); 0069 setFlag(QGraphicsItem::ItemIsSelectable); 0070 setFlag(QGraphicsItem::ItemIsMovable); 0071 setZValue(HANDLER_ZVALUE); 0072 0073 _forceHandler = new ArrowHandlerGraphicsItem(item, worldModel, this, 0074 _item->metaObject()->property(QStringLiteral("forceValue"))); 0075 _forceHandler->setVisible(false); 0076 } 0077 0078 inline StepCore::LinearMotor* LinearMotorGraphicsItem::motor() const 0079 { 0080 return static_cast<StepCore::LinearMotor*>(_item); 0081 } 0082 0083 QPainterPath LinearMotorGraphicsItem::shape() const 0084 { 0085 QPainterPath path; 0086 double radius = (RADIUS+1)/currentViewScale(); 0087 path.addEllipse(QRectF(-radius,-radius,radius*2,radius*2)); 0088 return path; 0089 } 0090 0091 void LinearMotorGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 0092 { 0093 if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) { 0094 QPointF newPos(mapToParent(event->pos()) - transform().map(event->buttonDownPos(Qt::LeftButton))); 0095 QVariant vpos = QVariant::fromValue(pointToVector(newPos)); 0096 0097 _worldModel->simulationPause(); 0098 if(!_moving) { 0099 _moving = true; 0100 _worldModel->beginMacro(i18n("Move %1", _item->name())); 0101 _worldModel->setProperty(_item, QStringLiteral("body"), 0102 QVariant::fromValue<StepCore::Object*>(NULL), WorldModel::UndoNoMerge); 0103 } 0104 0105 _worldModel->setProperty(_item, QStringLiteral("localPosition"), vpos); 0106 } else { 0107 event->ignore(); 0108 } 0109 } 0110 0111 void LinearMotorGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 0112 { 0113 if(_moving) { 0114 QPointF pos = event->scenePos(); 0115 foreach(QGraphicsItem* it, scene()->items(pos)) { 0116 StepCore::Item* item = static_cast<WorldScene*>(scene())->itemFromGraphics(it); 0117 if(dynamic_cast<StepCore::Particle*>(item) || dynamic_cast<StepCore::RigidBody*>(item)) { 0118 _worldModel->simulationPause(); 0119 _worldModel->setProperty(_item, QStringLiteral("body"), 0120 QVariant::fromValue<StepCore::Object*>(item), WorldModel::UndoNoMerge); 0121 0122 StepCore::Vector2d lPos(0, 0); 0123 if(dynamic_cast<StepCore::RigidBody*>(item)) 0124 lPos = dynamic_cast<StepCore::RigidBody*>(item)->pointWorldToLocal(StepGraphicsItem::pointToVector(pos)); 0125 0126 _worldModel->setProperty(_item, QStringLiteral("localPosition"), QVariant::fromValue(lPos)); 0127 0128 break; 0129 } 0130 } 0131 0132 _moving = false; 0133 _worldModel->endMacro(); 0134 } else StepGraphicsItem::mouseReleaseEvent(event); 0135 } 0136 0137 0138 void LinearMotorGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) 0139 { 0140 double s = currentViewScale(); 0141 double radius = RADIUS/s; 0142 0143 painter->setRenderHint(QPainter::Antialiasing, true); 0144 painter->setPen(Qt::NoPen); 0145 painter->setBrush(QBrush(QColor::fromRgba(motor()->color()))); 0146 painter->drawEllipse(QRectF(-radius,-radius,radius*2,radius*2)); 0147 painter->setPen(QPen(QColor::fromRgba(motor()->color()), radius, Qt::SolidLine, Qt::RoundCap)); 0148 drawArrow(painter, motor()->forceValue()); 0149 0150 //painter->setPen(QPen(QColor::fromRgba(particle()->color()), 2*radius, Qt::SolidLine, Qt::RoundCap)); 0151 //painter->drawPoint(0,0); 0152 0153 if(_isSelected) { 0154 painter->setPen(QPen(SELECTION_COLOR, 0, Qt::DashLine)); 0155 painter->setBrush(Qt::NoBrush); 0156 //painter->setBrush(QBrush(QColor(0, 0x99, 0xff))); 0157 radius = (RADIUS+SELECTION_MARGIN)/s; 0158 painter->drawEllipse(QRectF(-radius, -radius, radius*2, radius*2)); 0159 } 0160 0161 // painter->setRenderHint(QPainter::Antialiasing, true); 0162 // painter->setPen(QPen(QColor::fromRgba(motor()->color()), 0)); 0163 // //painter->setBrush(QBrush(Qt::black)); 0164 // 0165 // if(_isSelected) { 0166 // painter->setPen(QPen(SELECTION_COLOR, 0, Qt::DashLine)); 0167 // } 0168 0169 } 0170 0171 void LinearMotorGraphicsItem::viewScaleChanged() 0172 { 0173 prepareGeometryChange(); 0174 0175 double s = currentViewScale(); 0176 const StepCore::Vector2d& f = motor()->forceValue(); 0177 _boundingRect = QRectF(0,0,f[0],f[1]).normalized(); 0178 _boundingRect.adjust(-(RADIUS+ARROW_STROKE)/s, -(RADIUS+ARROW_STROKE)/s, 0179 (RADIUS+ARROW_STROKE)/s, (RADIUS+ARROW_STROKE)/s); 0180 _boundingRect |= QRectF((-RADIUS-SELECTION_MARGIN)/s, (-RADIUS-SELECTION_MARGIN)/s, 0181 (RADIUS+SELECTION_MARGIN)*2/s,( RADIUS+SELECTION_MARGIN)*2/s); 0182 // worldDataChanged(false); 0183 } 0184 0185 void LinearMotorGraphicsItem::worldDataChanged(bool dynamicOnly) 0186 { 0187 if(!dynamicOnly) { 0188 viewScaleChanged(); 0189 update(); 0190 } 0191 setPos(vectorToPoint(motor()->position())); 0192 } 0193 0194 void LinearMotorGraphicsItem::stateChanged() 0195 { 0196 if(_isSelected) _forceHandler->setVisible(true); 0197 else _forceHandler->setVisible(false); 0198 } 0199 0200 0201 //////////////////////////////////////////////////////////////////////////////////////////////// 0202 0203 bool CircularMotorCreator::sceneEvent(QEvent* event) 0204 { 0205 QGraphicsSceneMouseEvent* mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event); 0206 if(event->type() == QEvent::GraphicsSceneMousePress && mouseEvent->button() == Qt::LeftButton) { 0207 QPointF pos = mouseEvent->scenePos(); 0208 QVariant vpos = QVariant::fromValue(StepGraphicsItem::pointToVector(pos)); 0209 0210 _worldModel->simulationPause(); 0211 _worldModel->beginMacro(i18n("Create %1", _worldModel->newItemName(_className))); 0212 _item = _worldModel->createItem(className()); Q_ASSERT(_item != nullptr); 0213 0214 _worldModel->setProperty(_item, QStringLiteral("localPosition"), vpos); 0215 _worldModel->addItem(_item); 0216 tryAttach(pos); 0217 0218 _worldModel->selectionModel()->setCurrentIndex(_worldModel->objectIndex(_item), 0219 QItemSelectionModel::ClearAndSelect); 0220 _worldModel->endMacro(); 0221 0222 setFinished(); 0223 return true; 0224 } 0225 return false; 0226 } 0227 0228 void CircularMotorCreator::tryAttach(const QPointF& pos) 0229 { 0230 foreach(QGraphicsItem* it, _worldScene->items(pos)) { 0231 StepCore::Item* item = _worldScene->itemFromGraphics(it); 0232 if(dynamic_cast<StepCore::RigidBody*>(item)) { 0233 _worldModel->setProperty(_item, QStringLiteral("body"), 0234 QVariant::fromValue<StepCore::Object*>(item), WorldModel::UndoNoMerge); 0235 0236 StepCore::Vector2d lPos(0, 0); 0237 lPos = dynamic_cast<StepCore::RigidBody*>(item)->pointWorldToLocal(StepGraphicsItem::pointToVector(pos)); 0238 _worldModel->setProperty(_item, QStringLiteral("localPosition"), QVariant::fromValue(lPos)); 0239 break; 0240 } 0241 } 0242 } 0243 0244 CircularMotorGraphicsItem::CircularMotorGraphicsItem(StepCore::Item* item, WorldModel* worldModel) 0245 : StepGraphicsItem(item, worldModel), _moving(false) 0246 { 0247 Q_ASSERT(dynamic_cast<StepCore::CircularMotor*>(_item) != nullptr); 0248 setFlag(QGraphicsItem::ItemIsSelectable); 0249 setFlag(QGraphicsItem::ItemIsMovable); 0250 _torqueHandler = new CircularArrowHandlerGraphicsItem(item, worldModel, this, ARROW_RADIUS, 0251 _item->metaObject()->property(QStringLiteral("torqueValue"))); 0252 _torqueHandler->setVisible(false); 0253 setZValue(HANDLER_ZVALUE); 0254 } 0255 0256 inline StepCore::CircularMotor* CircularMotorGraphicsItem::motor() const 0257 { 0258 return static_cast<StepCore::CircularMotor*>(_item); 0259 } 0260 0261 QPainterPath CircularMotorGraphicsItem::shape() const 0262 { 0263 QPainterPath path; 0264 double radius = (RADIUS+1)/currentViewScale(); 0265 path.addEllipse(QRectF(-radius,-radius,radius*2,radius*2)); 0266 return path; 0267 } 0268 0269 void CircularMotorGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 0270 { 0271 if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) { 0272 QPointF newPos(mapToParent(event->pos()) - transform().map(event->buttonDownPos(Qt::LeftButton))); 0273 QVariant vpos = QVariant::fromValue(pointToVector(newPos)); 0274 0275 _worldModel->simulationPause(); 0276 if(!_moving) { 0277 _moving = true; 0278 _worldModel->beginMacro(i18n("Move %1", _item->name())); 0279 _worldModel->setProperty(_item, QStringLiteral("body"), 0280 QVariant::fromValue<StepCore::Object*>(NULL), WorldModel::UndoNoMerge); 0281 } 0282 0283 _worldModel->setProperty(_item, QStringLiteral("localPosition"), vpos); 0284 } else { 0285 event->ignore(); 0286 } 0287 } 0288 0289 void CircularMotorGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 0290 { 0291 if(_moving) { 0292 QPointF pos = event->scenePos(); 0293 foreach(QGraphicsItem* it, scene()->items(pos)) { 0294 StepCore::Item* item = static_cast<WorldScene*>(scene())->itemFromGraphics(it); 0295 if(dynamic_cast<StepCore::RigidBody*>(item)) { 0296 _worldModel->simulationPause(); 0297 _worldModel->setProperty(_item, QStringLiteral("body"), 0298 QVariant::fromValue<StepCore::Object*>(item), WorldModel::UndoNoMerge); 0299 0300 StepCore::Vector2d lPos(0, 0); 0301 if(dynamic_cast<StepCore::RigidBody*>(item)) 0302 lPos = dynamic_cast<StepCore::RigidBody*>(item)->pointWorldToLocal(StepGraphicsItem::pointToVector(pos)); 0303 0304 _worldModel->setProperty(_item, QStringLiteral("localPosition"), QVariant::fromValue(lPos)); 0305 0306 break; 0307 } 0308 } 0309 0310 _moving = false; 0311 _worldModel->endMacro(); 0312 } else StepGraphicsItem::mouseReleaseEvent(event); 0313 } 0314 0315 0316 void CircularMotorGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) 0317 { 0318 double s = currentViewScale(); 0319 double radius = RADIUS/s; 0320 0321 painter->setRenderHint(QPainter::Antialiasing, true); 0322 painter->setPen(Qt::NoPen); 0323 painter->setBrush(QBrush(QColor::fromRgba(motor()->color()))); 0324 painter->drawEllipse(QRectF(-radius,-radius,radius*2,radius*2)); 0325 painter->setPen(QPen(QColor::fromRgba(motor()->color()), radius, Qt::SolidLine, Qt::RoundCap)); 0326 drawCircularArrow(painter, motor()->torqueValue(), ARROW_RADIUS); 0327 0328 //painter->setPen(QPen(QColor::fromRgba(particle()->color()), 2*radius, Qt::SolidLine, Qt::RoundCap)); 0329 //painter->drawPoint(0,0); 0330 0331 if(_isSelected) { 0332 painter->setPen(QPen(SELECTION_COLOR, 0, Qt::DashLine)); 0333 painter->setBrush(Qt::NoBrush); 0334 //painter->setBrush(QBrush(QColor(0, 0x99, 0xff))); 0335 radius = (RADIUS+SELECTION_MARGIN)/s; 0336 painter->drawEllipse(QRectF(-radius, -radius, radius*2, radius*2)); 0337 } 0338 0339 // painter->setRenderHint(QPainter::Antialiasing, true); 0340 // painter->setPen(QPen(QColor::fromRgba(motor()->color()), 0)); 0341 // //painter->setBrush(QBrush(Qt::black)); 0342 // 0343 // if(_isSelected) { 0344 // painter->setPen(QPen(SELECTION_COLOR, 0, Qt::DashLine)); 0345 // } 0346 0347 } 0348 0349 void CircularMotorGraphicsItem::viewScaleChanged() 0350 { 0351 prepareGeometryChange(); 0352 0353 double s = currentViewScale(); 0354 double r = (ARROW_RADIUS + CIRCULAR_ARROW_STROKE + SELECTION_MARGIN)/s; 0355 _boundingRect = QRectF(-r, -r, 2*r, 2*r); 0356 } 0357 0358 void CircularMotorGraphicsItem::worldDataChanged(bool dynamicOnly) 0359 { 0360 if(!dynamicOnly) { 0361 viewScaleChanged(); 0362 update(); 0363 } 0364 setPos(vectorToPoint(motor()->position())); 0365 } 0366 0367 void CircularMotorGraphicsItem::stateChanged() 0368 { 0369 if(_isSelected) _torqueHandler->setVisible(true); 0370 else _torqueHandler->setVisible(false); 0371 } 0372