/* * Copyright (C) 2012 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "gazebo/common/Color.hh" #include "gazebo/gui/Conversions.hh" #include "gazebo/gui/building/BuildingEditorWidget.hh" #include "gazebo/gui/building/BuildingMaker.hh" #include "gazebo/gui/building/EditorView.hh" #include "gazebo/gui/building/RotateHandle.hh" #include "gazebo/gui/building/StairsInspectorDialog.hh" #include "gazebo/gui/building/StairsItem.hh" #include "gazebo/gui/building/StairsItemPrivate.hh" using namespace gazebo; using namespace gui; ///////////////////////////////////////////////// StairsItem::StairsItem() : RectItem(), dataPtr(new StairsItemPrivate()) { this->editorType = "Stairs"; this->itemScale = BuildingMaker::conversionScale; this->level = 0; this->dataPtr->stairsSteps = 15; this->dataPtr->stairsDepth = 350; this->dataPtr->stairsWidth = 100; this->dataPtr->stairsHeight = 250; // this->dataPtr->stairsUnitRise = 10; // this->dataPtr->stairsUnitRun = 10; // this->dataPtr->stairsDepth = // this->dataPtr->stairsSteps * this->dataPtr->stairsUnitRun; // this->dataPtr->stairsHeight = // this->dataPtr->stairsSteps * this->dataPtr->stairsUnitRise; this->dataPtr->stairsPos = Conversions::Convert(this->scenePos()); this->dataPtr->stairsElevation = 0; this->width = this->dataPtr->stairsWidth; this->height = this->dataPtr->stairsDepth; this->drawingWidth = this->width; this->drawingHeight = this->height; this->UpdateCornerPositions(); this->zValueIdle = 3; this->setZValue(this->zValueIdle); this->dataPtr->inspector = new StairsInspectorDialog(); this->dataPtr->inspector->setModal(false); connect(this->dataPtr->inspector, SIGNAL(Applied()), this, SLOT(OnApply())); this->openInspectorAct = new QAction(tr("&Open Stairs Inspector"), this); this->openInspectorAct->setStatusTip(tr("Open Stairs Inspector")); connect(this->openInspectorAct, SIGNAL(triggered()), this, SLOT(OnOpenInspector())); this->deleteItemAct = new QAction(tr("&Delete"), this); this->deleteItemAct->setStatusTip(tr("Delete")); connect(this->deleteItemAct, SIGNAL(triggered()), this, SLOT(OnDeleteItem())); } ///////////////////////////////////////////////// StairsItem::~StairsItem() { delete this->dataPtr->inspector; } ///////////////////////////////////////////////// ignition::math::Vector3d StairsItem::Size() const { return ignition::math::Vector3d(this->dataPtr->stairsWidth, this->dataPtr->stairsDepth, this->dataPtr->stairsHeight); } ///////////////////////////////////////////////// ignition::math::Vector3d StairsItem::ScenePosition() const { return ignition::math::Vector3d(this->scenePos().x(), this->scenePos().y(), this->dataPtr->stairsElevation); } ///////////////////////////////////////////////// double StairsItem::SceneRotation() const { return this->rotationAngle; } ///////////////////////////////////////////////// int StairsItem::Steps() const { return this->dataPtr->stairsSteps; } ///////////////////////////////////////////////// bool StairsItem::RotateEventFilter(RotateHandle *_rotate, QEvent *_event) { QGraphicsSceneMouseEvent *mouseEvent = dynamic_cast(_event); switch (_event->type()) { case QEvent::GraphicsSceneMousePress: { _rotate->SetMouseState(QEvent::GraphicsSceneMousePress); _rotate->SetMouseDownX(mouseEvent->pos().x()); _rotate->SetMouseDownY(mouseEvent->pos().y()); break; } case QEvent::GraphicsSceneMouseRelease: { _rotate->SetMouseState(QEvent::GraphicsSceneMouseRelease); break; } case QEvent::GraphicsSceneMouseMove: { _rotate->SetMouseState(QEvent::GraphicsSceneMouseMove); break; } case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverMove: { // QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); QApplication::setOverrideCursor(BuildingEditorWidget::rotateCursor); return true; } case QEvent::GraphicsSceneHoverLeave: { QApplication::restoreOverrideCursor(); return true; } default: return false; break; } if (mouseEvent == NULL) return false; if (_rotate->MouseState() == QEvent::GraphicsSceneMouseMove) { QPoint localCenter(this->drawingOriginX, this->drawingOriginY); QPointF center = this->mapToScene(localCenter); QPointF newPoint = mouseEvent->scenePos(); QLineF line(center.x(), center.y(), newPoint.x(), newPoint.y()); // limit stairs to right angles until there is proper csg support double angle = line.angle(); double range = 45; double angleToRotate = this->rotationAngle; if (angle > (90 - range) && (angle < 90 + range)) angleToRotate = 0; else if (angle > (180 - range) && (angle < 180 + range)) angleToRotate = -90; else if (angle > (270 - range) && (angle < 270 + range)) angleToRotate = 180; else if (angle > (360 - range) || (angle < 0 + range)) angleToRotate = 90; if (fabs(angleToRotate - this->rotationAngle) > 0) this->SetRotation(angleToRotate); } return true; } ///////////////////////////////////////////////// void StairsItem::paint(QPainter *_painter, const QStyleOptionGraphicsItem * /*_option*/, QWidget * /*_widget*/) { QPointF topLeft(this->drawingOriginX - this->drawingWidth/2, this->drawingOriginY - this->drawingHeight/2); QPointF topRight( this->drawingOriginX + this->drawingWidth/2, this->drawingOriginY - this->drawingHeight/2); QPointF bottomLeft( this->drawingOriginX - this->drawingWidth/2, this->drawingOriginY + this->drawingHeight/2); QPointF bottomRight( this->drawingOriginX + this->drawingWidth/2, this->drawingOriginY + this->drawingHeight/2); this->dataPtr->stairsPos = Conversions::Convert(this->scenePos()); this->dataPtr->stairsWidth = this->drawingWidth; this->dataPtr->stairsDepth = this->drawingHeight; _painter->save(); if (this->isSelected()) this->DrawBoundingBox(_painter); this->ShowHandles(this->isSelected()); QPen stairsPen; stairsPen.setStyle(Qt::SolidLine); stairsPen.setColor(Conversions::Convert(this->borderColor)); _painter->setPen(stairsPen); QPointF drawStepLeft = topLeft; QPointF drawStepRight = topRight; double stairsUnitRun = this->dataPtr->stairsDepth / static_cast(this->dataPtr->stairsSteps); for (int i = 0; i <= this->dataPtr->stairsSteps; ++i) { double stepIncr = topLeft.y() + i*stairsUnitRun; drawStepLeft.setY(stepIncr); drawStepRight.setY(stepIncr); _painter->drawLine(drawStepLeft, drawStepRight); } _painter->drawLine(topLeft, bottomLeft); _painter->drawLine(topRight, bottomRight); _painter->restore(); } ///////////////////////////////////////////////// void StairsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *_event) { this->OnOpenInspector(); _event->setAccepted(true); } ///////////////////////////////////////////////// void StairsItem::OnApply() { StairsInspectorDialog *dialog = qobject_cast(QObject::sender()); QPointF startPos = Conversions::Convert(this->dataPtr->stairsPos) * this->itemScale; startPos.setY(-startPos.y()); this->SetSize(ignition::math::Vector2i(dialog->Width() / this->itemScale, dialog->Depth() / this->itemScale)); this->dataPtr->stairsWidth = dialog->Width() / this->itemScale; this->dataPtr->stairsHeight = dialog->Height() / this->itemScale; this->dataPtr->stairsDepth = dialog->Depth() / this->itemScale; if ((fabs(dialog->StartPosition().X() - startPos.x()) >= 0.01) || (fabs(dialog->StartPosition().Y() - startPos.y()) >= 0.01)) { this->dataPtr->stairsPos = dialog->StartPosition() / this->itemScale; this->dataPtr->stairsPos.Y(-this->dataPtr->stairsPos.Y()); this->setPos(Conversions::Convert(this->dataPtr->stairsPos)); this->setParentItem(NULL); } if (this->dataPtr->stairsSteps != dialog->Steps()) { this->dataPtr->stairsSteps = dialog->Steps(); this->StepsChanged(); } // this->dataPtr->stairsElevation = dialog->GetElevation(); this->SetTexture3d(dialog->Texture()); this->SetColor3d(dialog->Color()); this->StairsChanged(); } ///////////////////////////////////////////////// void StairsItem::OnOpenInspector() { this->dataPtr->inspector->SetName(this->Name()); this->dataPtr->inspector->SetWidth( this->dataPtr->stairsWidth * this->itemScale); this->dataPtr->inspector->SetDepth( this->dataPtr->stairsDepth * this->itemScale); this->dataPtr->inspector->SetHeight( this->dataPtr->stairsHeight * this->itemScale); this->dataPtr->inspector->SetSteps(this->dataPtr->stairsSteps); // dialog.SetElevation(this->dataPtr->stairsElevation); auto startPos = this->dataPtr->stairsPos * this->itemScale; startPos.Y(-startPos.Y()); this->dataPtr->inspector->SetStartPosition(startPos); this->dataPtr->inspector->SetColor(this->visual3dColor); this->dataPtr->inspector->SetTexture(this->visual3dTexture); this->dataPtr->inspector->move(QCursor::pos()); this->dataPtr->inspector->show(); } ///////////////////////////////////////////////// void StairsItem::OnDeleteItem() { dynamic_cast(this->scene()->views()[0])->DeleteItem(this); } ///////////////////////////////////////////////// void StairsItem::StairsChanged() { emit WidthChanged(this->dataPtr->stairsWidth); emit DepthChanged(this->dataPtr->stairsDepth); emit HeightChanged(this->dataPtr->stairsHeight); emit PositionChanged(this->dataPtr->stairsPos.X(), this->dataPtr->stairsPos.Y(), this->levelBaseHeight + this->dataPtr->stairsElevation); } ///////////////////////////////////////////////// void StairsItem::StepsChanged() { // emit a signal to delete 3d and make a new one // TODO there should be a more efficient way to do this. emit ItemDeleted(); dynamic_cast((this->scene()->views())[0])->Create3DVisual(this); this->StairsChanged(); }