Commits

Ian Chen committed dffc1ca

Auto snap to wall

  • Participants
  • Parent commits bb1b85c
  • Branches ian-building

Comments (0)

Files changed (14)

gazebo/gui/model_editor/BuildingEditorWidget.cc

   QBrush brush (c, Qt::SolidPattern);
   scene->setBackgroundBrush(brush);
 
-  int boundingWidth = 800;
-  int boundingHeight = 600;
+  int boundingWidth = 1024;
+  int boundingHeight = 800;
   scene->setSceneRect(-boundingWidth/2, -boundingHeight/2,
                       boundingWidth, boundingHeight);
   QHBoxLayout *canvasLayout = new QHBoxLayout(this);
   view->setScene(scene);
   view->centerOn(QPointF(0, 0));
   view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+  view->setDragMode(QGraphicsView::ScrollHandDrag);
 
   // TODO remove this wall and make sure scene updates without any items in it
   WallItem *wallItem = new WallItem(QPointF(0, 0), QPointF(0, 0));

gazebo/gui/model_editor/BuildingMaker.cc

   QObject::connect(_item, SIGNAL(yawChanged(double)),
       manip, SLOT(OnYawChanged(double)));
   QObject::connect(_item, SIGNAL(itemDeleted()), manip, SLOT(OnItemDeleted()));
+}
 
+/////////////////////////////////////////////////
+void BuildingMaker::AttachObject(std::string _child, std::string _parent)
+{
+  ModelManip *child = this->allItems[_child];
+  ModelManip *parent = this->allItems[_parent];
+  parent->AttachObject(child);
 }
 
 /////////////////////////////////////////////////
+void BuildingMaker::DetachObject(std::string _child, std::string _parent)
+{
+  ModelManip *child = this->allItems[_child];
+  ModelManip *parent = this->allItems[_parent];
+  parent->DetachObject(child);
+}
+
+
+/////////////////////////////////////////////////
 std::string BuildingMaker::CreateModel(math::Pose _pose)
 {
   this->modelPose = _pose;
     newLinkElem->GetAttribute("name")->Set(modelManip->GetName());
     newLinkElem->GetElement("pose")->Set(visual->GetParent()->GetWorldPose());
 
+//    qDebug() << " visual rotation " << visual->GetRotation().GetAsEuler().x
+//        << visual->GetRotation().GetAsEuler().y
+//        << visual->GetRotation().GetAsEuler().z;
+//    qDebug() << " visual world rot "
+//        << visual->GetWorldPose().rot.GetAsEuler().x
+//        << visual->GetWorldPose().rot.y
+//        << visual->GetWorldPose().rot.z;
+
     if (visual->GetChildCount() == 0)
     {
-
-#if 0
       // subdivide wall surface to create holes for representing
       // window/doors
-      if (name.find("Window") != std::string::npos
+/*      if (name.find("Window") != std::string::npos
           || name.find("Door") != std::string::npos)
       {
         if (modelManip->IsAttached())
           continue;
       }
-      else if (name.find("Wall") != std::string::npos
-          && modelManip->GetAttachedObjectCount() != 0)
+      else if (name.find("Wall") != std::string::npos)
       {
-        std::vector<QRectF> holes;
-        rendering::VisualPtr wallVis = visual;
-        math::Pose wallPose = wallVis->GetWorldPose();
-        for (unsigned int i = 0; i < modelManip->GetAttachedObjectCount(); ++i)
+        if (modelManip->GetAttachedObjectCount() != 0 )
         {
-          ModelManip *attachedObj = modelManip->GetAttachedObject(i);
-          std::string objName = attachedObj->GetName();
-          if (objName.find("Window") != std::string::npos
-              || objName.find("Door") != std::string::npos)
+          std::vector<QRectF> holes;
+          rendering::VisualPtr wallVis = visual;
+          math::Pose wallPose = wallVis->GetWorldPose();
+          for (unsigned int i = 0; i < modelManip->GetAttachedObjectCount(); ++i)
           {
-            rendering::VisualPtr attachedVis = attachedObj->GetVisual();
-            math::Pose offset = attachedVis->GetWorldPose() - wallPose;
-            math::Vector3 size = attachedVis->GetScale();
-            math::Vector3 newOffset = offset.pos - (-wallVis->GetScale()/2.0)
-                - size/2.0;
-            QRectF hole(newOffset.x, newOffset.z, size.x, size.z);
-            holes.push_back(hole);
+            ModelManip *attachedObj = modelManip->GetAttachedObject(i);
+            std::string objName = attachedObj->GetName();
+            if (objName.find("Window") != std::string::npos
+                || objName.find("Door") != std::string::npos)
+            {
+              rendering::VisualPtr attachedVis = attachedObj->GetVisual();
+              math::Pose offset = attachedVis->GetWorldPose() - wallPose;
+              math::Vector3 size = attachedVis->GetScale();
+              math::Vector3 newOffset = offset.pos - (-wallVis->GetScale()/2.0)
+                  - size/2.0;
+              QRectF hole(newOffset.x, newOffset.z, size.x, size.z);
+              holes.push_back(hole);
+            }
+          }
+          std::vector<QRectF> subdivisions;
+          QRectF surface(0, 0, wallVis->GetScale().x, wallVis->GetScale().z);
+
+          //QRectF host(0, 0, 1.0, 1.0);
+          //QRectF hole1(0.2,0.3,0.2,0.2);;
+          //QRectF hole2(0.5,0.2,0.2,0.2);
+          //QRectF hole3(0.4,0.6,0.3,0.4);
+          //std::vector<QRectF> holess;
+          //holess.push_back(hole1);
+          //holess.push_back(hole2);
+          //holess.push_back(hole3);
+          //std::vector<QRectF> subs;
+          //this->SubdivideRectSurface(host, holess, subs);
+
+          this->SubdivideRectSurface(surface, holes, subdivisions);
+
+          newLinkElem->ClearElements();
+          newLinkElem->GetAttribute("name")->Set(modelManip->GetName());
+          newLinkElem->GetElement("pose")->Set(
+              visual->GetParent()->GetWorldPose());
+          for (unsigned int i = 0; i< subdivisions.size(); ++i)
+          {
+            visualNameStream.str("");
+            collisionNameStream.str("");
+            visualElem = templateVisualElem->Clone();
+            collisionElem = templateCollisionElem->Clone();
+            visualNameStream << modelManip->GetName() << "_Visual_" << i;
+            visualElem->GetAttribute("name")->Set(visualNameStream.str());
+            collisionNameStream << modelManip->GetName() << "_Collision_" << i;
+            collisionElem->GetAttribute("name")->Set(collisionNameStream.str());
+
+            math::Vector3 newSubPos = (-wallVis->GetScale()/2.0)
+                + math::Vector3(subdivisions[i].x(), 0, subdivisions[i].y())
+                + math::Vector3(subdivisions[i].width()/2, 0,
+                    subdivisions[i].height()/2);
+            newSubPos.z += wallPose.pos.z;
+            math::Pose newPose(newSubPos,
+                 visual->GetRotation());
+            visualElem->GetElement("pose")->Set(newPose);
+            collisionElem->GetElement("pose")->Set(newPose);
+            math::Vector3 blockSize(subdivisions[i].width(),
+                wallVis->GetScale().y, subdivisions[i].height());
+            visualElem->GetElement("geometry")->GetElement("box")->
+              GetElement("size")->Set(blockSize);
+            collisionElem->GetElement("geometry")->GetElement("box")->
+              GetElement("size")->Set(blockSize);
+            newLinkElem->InsertElement(visualElem);
+            newLinkElem->InsertElement(collisionElem);
           }
         }
-        std::vector<QRectF> subdivisions;
-        QRectF surface(0, 0, wallVis->GetScale().x, wallVis->GetScale().z);
-
-        //QRectF host(0, 0, 1.0, 1.0);
-        //QRectF hole1(0.2,0.3,0.2,0.2);;
-        //QRectF hole2(0.5,0.2,0.2,0.2);
-        //QRectF hole3(0.4,0.6,0.3,0.4);
-        //std::vector<QRectF> holess;
-        //holess.push_back(hole1);
-        //holess.push_back(hole2);
-        //holess.push_back(hole3);
-        //std::vector<QRectF> subs;
-        //this->SubdivideRectSurface(host, holess, subs);
-
-        this->SubdivideRectSurface(surface, holes, subdivisions);
-
-        newLinkElem->ClearElements();
-        for (unsigned int i = 0; i< subdivisions.size(); ++i)
+        else
         {
-          visualNameStream.str("");
-          collisionNameStream.str("");
-          visualElem = templateVisualElem->Clone();
-          collisionElem = templateCollisionElem->Clone();
-          visualNameStream << modelManip->GetName() << "_Visual_" << i;
-          visualElem->GetAttribute("name")->Set(visualNameStream.str());
-          collisionNameStream << modelManip->GetName() << "_Collision_" << i;
-          collisionElem->GetAttribute("name")->Set(collisionNameStream.str());
-
-
-          math::Vector3 newSubPos = wallPose.pos + (-wallVis->GetScale()/2.0)
-              + math::Vector3(subdivisions[i].x(), 0, subdivisions[i].y())
-              + math::Vector3(subdivisions[i].width()/2, 0,
-                  subdivisions[i].height()/2);
-          math::Pose newPose(newSubPos, wallPose.rot);
-        visualElem->GetElement("pose")->Set(newPose);
-        collisionElem->GetElement("pose")->Set(newPose);
-          math::Vector3 blockSize(subdivisions[i].width(),
-              wallVis->GetScale().y, subdivisions[i].height());
+          visualElem->GetAttribute("name")->Set(modelManip->GetName() + "_Visual");
+          collisionElem->GetAttribute("name")->Set(modelManip->GetName()
+              + "_Collision");
+          visualElem->GetElement("pose")->Set(visual->GetPose());
+          collisionElem->GetElement("pose")->Set(visual->GetPose());
           visualElem->GetElement("geometry")->GetElement("box")->
-            GetElement("size")->Set(blockSize);
+              GetElement("size")->Set(visual->GetScale());
           collisionElem->GetElement("geometry")->GetElement("box")->
-            GetElement("size")->Set(blockSize);
-          newLinkElem->InsertElement(visualElem);
-          newLinkElem->InsertElement(collisionElem);
+              GetElement("size")->Set(visual->GetScale());
         }
       }
-#endif
-      visualElem->GetAttribute("name")->Set(modelManip->GetName() + "_Visual");
-      collisionElem->GetAttribute("name")->Set(modelManip->GetName()
-          + "_Collision");
-      visualElem->GetElement("pose")->Set(visual->GetPose());
-      collisionElem->GetElement("pose")->Set(visual->GetPose());
-      visualElem->GetElement("geometry")->GetElement("box")->
-          GetElement("size")->Set(visual->GetScale());
-      collisionElem->GetElement("geometry")->GetElement("box")->
-          GetElement("size")->Set(visual->GetScale());
+
     }
-    else
+    else*/
     {
       // TODO: This handles the special case for stairs where
       // there are nested visuals which SDF doesn't support.

gazebo/gui/model_editor/BuildingMaker.hh

 
       public: void ConnectItem(std::string _partName, EditorItem *_item);
 
+      public: void AttachObject(std::string _child, std::string _parent);
+
+      public: void DetachObject(std::string _child, std::string _parent);
+
       public: static math::Vector3 ConvertSize(QVector3D _size);
 
       public: static math::Vector3 ConvertSize(double _width, double _depth,

gazebo/gui/model_editor/DoorItem.cc

     this->doorWidth = dialog.GetWidth() / this->scale;
     this->doorHeight = dialog.GetHeight() / this->scale;
     this->doorDepth = dialog.GetDepth() / this->scale;
-    itemPos = dialog.GetPosition() / this->scale;
-    itemPos.setY(-itemPos.y());
-    this->doorPos = itemPos;
-    this->setPos(this->doorPos);
+    if ((fabs(dialog.GetPosition().x() - itemPos.x()) >= 0.01)
+        || (fabs(dialog.GetPosition().y() - itemPos.y()) >= 0.01))
+    {
+      itemPos = dialog.GetPosition() / this->scale;
+      itemPos.setY(-itemPos.y());
+      this->doorPos = itemPos;
+      this->setPos(this->doorPos);
+      this->setParentItem(NULL);
+    }
     this->DoorChanged();
   }
   _event->setAccepted(true);

gazebo/gui/model_editor/EditorItem.cc

 {
   emit itemDeleted();
 }
+/*
+/////////////////////////////////////////////////
+void EditorItem::AttachItem(EditorItem *_item)
+{
+  if (!_item->IsAttached())
+  {
+    _item->SetAttachedTo(this);
+    this->attachedItems.push_back(_item);
+  }
+}
+
+/////////////////////////////////////////////////
+void EditorItem::DetachItem(EditorItem *_item)
+{
+  std::remove(this->attachedItems.begin(), this->attachedItems.end(),
+      _item);
+}
+
+/////////////////////////////////////////////////
+bool EditorItem::IsAttached()
+{
+}
+
+/////////////////////////////////////////////////
+void EditorItem::SetAttached(EditorItem *_parent)
+{
+  if (this->IsAttached())
+  {
+    gzerr << this->editorType << " is already attached to a parent \n";
+    return;
+  }
+  this->parent = _parent;
+}
+
+/////////////////////////////////////////////////
+EditorItem *ModelManip::GetAttachedItem(unsigned int _index)
+{
+  if (_index >= this->attachedObjects.size())
+    gzthrow("Index too large");
+
+  return this->attachedObjects[_index];
+}
+
+/////////////////////////////////////////////////
+unsigned int EditorItem::GetAttachedItemCount()
+{
+  return this->attachedItems.size();
+}
+
+/////////////////////////////////////////////////
+bool EditorItem::IsAttached()
+{
+  return (this->parent != NULL);
+}
+*/
 
 /////////////////////////////////////////////////
 QVector3D EditorItem::GetSize()

gazebo/gui/model_editor/EditorItem.hh

 
         public: ~EditorItem();
 
+ /*       public: virtual void AttachItem(EditorItem *_item);
+
+        public: virtual void DetachItem(EditorItem *_item);*/
+
         public: virtual QVector3D GetSize();
 
         public: virtual QVector3D GetScenePosition();
         signals: void itemDeleted();
 
         protected: std::string editorType;
+
+//        protected: std::vector<EditorItem *> attachedItems;
     };
   }
 }

gazebo/gui/model_editor/EditorView.cc

   gui::Events::ConnectChangeLevel(
     boost::bind(&EditorView::OnChangeLevel, this, _1)));
 
+  this->grabberDragRotation = 0;
+
   buildingMaker = new BuildingMaker();
   this->currentLevel = 0;
 
 /////////////////////////////////////////////////
 void EditorView::mousePressEvent(QMouseEvent *_event)
 {
-  QGraphicsView::mousePressEvent(_event);
+  if (!drawInProgress)
+    QGraphicsView::mousePressEvent(_event);
 }
 
 /////////////////////////////////////////////////
     case NONE:
       break;
     case WALL:
-      this->DrawLine(_event->pos());
+      this->DrawWall(_event->pos());
       break;
     case WINDOW:
       if (drawInProgress)
       break;
   }
   if (!drawInProgress)
-  {
     QGraphicsView::mouseReleaseEvent(_event);
-  }
 }
 
 /////////////////////////////////////////////////
       {
         if (wallItem)
         {
+          // snap walls to 0/90/180 degrees
           LineSegmentItem *segment = wallItem->GetSegment(
               wallItem->GetSegmentCount()-1);
           QPointF p1 = segment->mapToScene(segment->line().p1());
     default:
       break;
   }
-  QGraphicsView::mouseMoveEvent(_event);
+
+  if (!drawInProgress)
+  {
+    // auto attach objects
+    QGraphicsItem *grabber = this->scene()->mouseGrabberItem();
+    RectItem *editorItem = dynamic_cast<RectItem *>(grabber);
+    if (grabber && editorItem && (editorItem->GetType() == "Window"
+        || editorItem->GetType() == "Door") )
+    {
+      if (grabber->parentItem())
+      {
+        LineSegmentItem *wallSegment =
+              dynamic_cast<LineSegmentItem *>(grabber->parentItem());
+        if (wallSegment)
+        {
+          QLineF segmentLine(wallSegment->line());
+          segmentLine.setP1(wallSegment->mapToScene(segmentLine.p1()));
+          segmentLine.setP2(wallSegment->mapToScene(segmentLine.p2()));
+          QPointF mousePoint = this->mapToScene(_event->pos());
+          QPointF deltaLine = segmentLine.p2() - segmentLine.p1();
+          QPointF deltaMouse = mousePoint - segmentLine.p1();
+          double deltaLineMouse2 = deltaLine.x()*(-deltaMouse.y())
+              - (-deltaMouse.x())*deltaLine.y();
+          double deltaLine2 = (deltaLine.x()*deltaLine.x())
+              + deltaLine.y()*deltaLine.y();
+          double mouseDotLine = deltaMouse.x()*deltaLine.x()
+                + deltaMouse.y()*deltaLine.y();
+          double t = mouseDotLine / deltaLine2;
+          double distance = fabs(deltaLineMouse2) / sqrt(deltaLine2);
+          if (distance > 30 || t > 1.0 || t < 0.0)
+          {
+            editorItem->setParentItem(NULL);
+            buildingMaker->DetachObject(this->itemToModelMap[editorItem],
+                  this->itemToModelMap[wallSegment]);
+            editorItem->SetRotation(editorItem->GetRotation()
+              - this->grabberDragRotation);
+            editorItem->SetPosition(mousePoint);
+          }
+          else
+          {
+            QPointF closest(segmentLine.p1() + t*deltaLine);
+            grabber->setPos(wallSegment->mapFromScene(closest));
+            grabber->setRotation(wallSegment->rotation());
+          }
+          return;
+        }
+      }
+      else
+      {
+        QList<QGraphicsItem *> overlaps = this->scene()->collidingItems(
+            grabber, Qt::IntersectsItemBoundingRect);
+        for (int i = 0; i < overlaps.size(); ++i)
+        {
+          LineSegmentItem *wallSegment =
+              dynamic_cast<LineSegmentItem *>(overlaps[i]);
+          if (wallSegment)
+          {
+            QPointF scenePos =  grabber->scenePos();
+            if (wallSegment->contains(wallSegment->mapFromScene(scenePos)))
+            {
+              editorItem->setParentItem(wallSegment);
+              buildingMaker->AttachObject(this->itemToModelMap[editorItem],
+                  this->itemToModelMap[wallSegment]);
+              editorItem->SetPosition(wallSegment->mapFromScene(scenePos));
+              this->grabberDragRotation = -wallSegment->line().angle();
+              editorItem->SetRotation(this->grabberDragRotation);
+              return;
+            }
+          }
+        }
+      }
+    }
+
+    QGraphicsView::mouseMoveEvent(_event);
+  }
 }
 
 /////////////////////////////////////////////////
 
     for (int i = 0; i < selectedItems.size(); ++i)
     {
-      QGraphicsItem *item = selectedItems[i];
-      if (dynamic_cast<WallItem *>(item))
+//      QGraphicsItem *item = selectedItems[i];
+      EditorItem *item = dynamic_cast<EditorItem *>(selectedItems[i]);
+/*      if (dynamic_cast<WallItem *>(item))
         wallList.remove(dynamic_cast<WallItem *>(item));
       else if (dynamic_cast<WindowItem *>(item))
           windowList.remove(dynamic_cast<WindowItem *>(item));
       else if (dynamic_cast<DoorItem *>(item))
         doorList.remove(dynamic_cast<DoorItem *>(item));
       else if (dynamic_cast<StairsItem *>(item))
+        stairsList.remove(dynamic_cast<StairsItem *>(item));*/
+      if (item->GetType() == "Wall")
+        wallList.remove(dynamic_cast<WallItem *>(item));
+      else if (item->GetType() == "Window")
+          windowList.remove(dynamic_cast<WindowItem *>(item));
+      else if (item->GetType() == "Door")
+        doorList.remove(dynamic_cast<DoorItem *>(item));
+      else if (item->GetType() == "Stairs")
         stairsList.remove(dynamic_cast<StairsItem *>(item));
+      this->itemToModelMap.erase(item);
       delete selectedItems[i];
+
     }
     drawMode = NONE;
     this->drawInProgress = false;
 }
 
 /////////////////////////////////////////////////
-void EditorView::DrawLine(QPoint _pos)
+void EditorView::DrawWall(QPoint _pos)
 {
   WallItem *wallItem = NULL;
   if (!drawInProgress)
     this->lastWallSegmentName = wallSegmentName;
     this->buildingMaker->ConnectItem(wallSegmentName, segment);
     this->buildingMaker->ConnectItem(wallSegmentName, wallItem);
+    this->itemToModelMap[segment] = wallSegmentName;
+//    this->itemToModelMap[wallItem] = wallSegmentName;
   }
 }
 
     std::string windowName = this->buildingMaker->AddWindow(
         windowItem->GetSize(), windowPosition, windowItem->GetSceneRotation());
     this->buildingMaker->ConnectItem(windowName, windowItem);
+    this->itemToModelMap[windowItem] = windowName;
 
     this->drawInProgress = true;
   }
     std::string doorName = this->buildingMaker->AddDoor(
         doorItem->GetSize(), doorPosition, doorItem->GetSceneRotation());
     this->buildingMaker->ConnectItem(doorName, doorItem);
+    this->itemToModelMap[doorItem] = doorName;
 
     this->drawInProgress = true;
   }
         stairsItem->GetSteps());
 
     this->buildingMaker->ConnectItem(stairsName, stairsItem);
+    this->itemToModelMap[stairsItem] = stairsName;
 
     this->drawInProgress = true;
   }
 }
 
 /////////////////////////////////////////////////
-void EditorView::CloneItem3D(EditorItem* _item)
+void EditorView::CreateItem3D(EditorItem* _item)
 {
   if (_item->GetType() == "Stairs")
   {
         stairsItem->GetSize(), stairsPosition, stairsItem->GetSceneRotation(),
         stairsItem->GetSteps());
     this->buildingMaker->ConnectItem(stairsName, stairsItem);
+    this->itemToModelMap[stairsItem] = stairsName;
   }
+  //TODO add implementation for other times
 }
 
 /////////////////////////////////////////////////
 void EditorView::OnCreateEditorItem(const std::string &_type)
 {
-
-//qDebug() << " create editor itme " << _type.c_str();
-
   if (_type == "Wall")
     this->drawMode = WALL;
   else if (_type == "Window")
 
       this->buildingMaker->ConnectItem(wallSegmentName, segment);
       this->buildingMaker->ConnectItem(wallSegmentName, wallItem);
+      this->itemToModelMap[segment] = wallSegmentName;
+//      this->itemToModelMap[wallItem] = wallSegmentName;
     }
   }
   this->wallList.insert(this->wallList.end(), newWalls.begin(),

gazebo/gui/model_editor/EditorView.hh

 
       public: enum mouseActions{Select, Translate, Rotate};
 
-      public: void CloneItem3D(EditorItem *item);
+      public: void CreateItem3D(EditorItem *item);
 
       private: void contextMenuEvent(QContextMenuEvent *event);
 
 
       private: void keyPressEvent(QKeyEvent *_event);
 
-      private: void DrawLine(QPoint _pos);
+      private: void DrawWall(QPoint _pos);
 
       private: void DrawWindow(QPoint _pos);
 
 
       private: std::list<StairsItem*> stairsList;
 
+      private: std::map<EditorItem *, std::string> itemToModelMap;
+
       private: QPoint lastLineCornerPos;
 
       private: std::vector<event::ConnectionPtr> connections;
 
       private: QAction *openLevelInspectorAct;
 
+      private: double grabberDragRotation;
+
 
     };
   }

gazebo/gui/model_editor/LineSegmentItem.cc

     : EditorItem(), QGraphicsLineItem(_parent), index(_index), start(0, 0),
       end(0, 0)
 {
+  this->editorType = "Line";
+
   if (_parent)
     this->setParentItem(_parent);
   this->setAcceptHoverEvents(true);

gazebo/gui/model_editor/RectItem.cc

 
   this->setSelected(false);
   this->setFlags(this->flags() | QGraphicsItem::ItemIsSelectable);
+  this->setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
 
   this->UpdateCornerPositions();
   this->setAcceptHoverEvents(true);
 QVariant RectItem::itemChange(GraphicsItemChange _change,
   const QVariant &_value)
 {
-  if (_change == QGraphicsItem::ItemSelectedChange && this->scene()) {
+  if (_change == QGraphicsItem::ItemSelectedChange && this->scene())
+  {
 
     if (_value.toBool())
     {
       this->rotateHandle->removeSceneEventFilter(this);
     }
   }
+  else if (_change == QGraphicsItem::ItemScenePositionHasChanged
+      && this->scene())
+  {
+    emit posXChanged(this->scenePos().x());
+    emit posYChanged(this->scenePos().y());
+  }
+  if (_change == QGraphicsItem::ItemParentChange && this->scene())
+  {
+
+  }
   return QGraphicsItem::itemChange(_change, _value);
 }
 
     this->translate(-localCenter.x(), 0);*/
 
     this->SetRotation(this->GetRotation() + angle);
+
 //    this->setTransformOriginPoint(localCenter);
 //    this->setRotation(this->rotation() -prevLine.angleTo(line));
   }
     double angle = rotationAngle / 360.0 * (2 * M_PI);
     double dx = 0;
     double dy = 0;
-    double deltaLength = sqrt((deltaHeight * deltaHeight)
-        + (deltaWidth * deltaWidth));
     switch(_corner->GetIndex())
     {
       // corners
   this->location.setY( (static_cast<int>(this->location.y())
       / this->gridSpace) * this->gridSpace);*/
 
-  this->SetPosition(this->location);
+//  this->SetPosition(this->location);
 }
 
 /////////////////////////////////////////////////
 
   this->setSelected(true);
   QApplication::setOverrideCursor(QCursor(Qt::SizeAllCursor));
-  this->location = this->pos();
+//  this->location = this->pos();
   _event->setAccepted(true);
 }
 
     return;
 
   QPointF delta = _event->scenePos() - _event->lastScenePos();
-  this->location += delta;
-  this->SetPosition(this->location);
+  this->SetPosition(this->scenePos() + delta);
+//  this->location += delta;
+//  this->SetPosition(this->location);
 }
 
 /////////////////////////////////////////////////
 void RectItem::SetPosition(double _x, double _y)
 {
   this->setPos(_x, _y);
-  emit posXChanged(_x);
-  emit posYChanged(_y);
+//  emit posXChanged(_x);
+//  emit posYChanged(_y);
 }
 
 /////////////////////////////////////////////////

gazebo/gui/model_editor/StairsItem.cc

     this->stairsWidth = dialog.GetWidth() / this->scale;
     this->stairsHeight = dialog.GetHeight() / this->scale;
     this->stairsDepth = dialog.GetDepth() / this->scale;
-    this->stairsPos = dialog.GetStartPosition()  / this->scale;
-    this->stairsPos.setY(-this->stairsPos.y());
-    this->setPos(stairsPos);
+    if ((fabs(dialog.GetStartPosition().x() - startPos.x()) >= 0.01)
+        || (fabs(dialog.GetStartPosition().y() - startPos.y()) >= 0.01))
+    {
+      this->stairsPos = dialog.GetStartPosition() / this->scale;
+      this->stairsPos.setY(-this->stairsPos.y());
+      this->setPos(stairsPos);
+      this->setParentItem(NULL);
+    }
     if (this->stairsSteps != dialog.GetSteps())
     {
       this->stairsSteps = dialog.GetSteps();
     // 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<EditorView *>((this->scene()->views())[0])->CloneItem3D(this);
+    dynamic_cast<EditorView *>((this->scene()->views())[0])->CreateItem3D(this);
     this->StairsChanged();
 }

gazebo/gui/model_editor/WallItem.cc

  *
 */
 
+#include "gui/model_editor/RectItem.hh"
 #include "gui/model_editor/BuildingItem.hh"
 #include "gui/model_editor/PolylineItem.hh"
-#include "gui/model_editor/WallItem.hh"
 #include "gui/model_editor/LineSegmentItem.hh"
 #include "gui/model_editor/WallInspectorDialog.hh"
 #include "gui/model_editor/BuildingMaker.hh"
+#include "gui/model_editor/CornerGrabber.hh"
+#include "gui/model_editor/WallItem.hh"
 
 using namespace gazebo;
 using namespace gui;
   return wallItem;
 }
 
+
+/////////////////////////////////////////////////
+bool WallItem::cornerEventFilter(CornerGrabber* _corner,
+    QEvent *_event)
+{
+  QGraphicsSceneMouseEvent *mouseEvent =
+    dynamic_cast<QGraphicsSceneMouseEvent*>(_event);
+
+  switch (_event->type())
+  {
+    case QEvent::GraphicsSceneMousePress:
+    {
+      _corner->SetMouseState(QEvent::GraphicsSceneMousePress);
+      QPointF scenePosition =  _corner->mapToScene(mouseEvent->pos());
+
+      _corner->SetMouseDownX(scenePosition.x());
+      _corner->SetMouseDownY(scenePosition.y());
+      break;
+    }
+    case QEvent::GraphicsSceneMouseRelease:
+    {
+      _corner->SetMouseState(QEvent::GraphicsSceneMouseRelease);
+      break;
+    }
+    case QEvent::GraphicsSceneMouseMove:
+    {
+      _corner->SetMouseState(QEvent::GraphicsSceneMouseMove);
+      break;
+    }
+    case QEvent::GraphicsSceneHoverEnter:
+    case QEvent::GraphicsSceneHoverMove:
+    {
+      QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+      return true;
+    }
+    case QEvent::GraphicsSceneHoverLeave:
+    {
+      QApplication::restoreOverrideCursor();
+      return true;
+    }
+
+    default:
+    {
+      break;
+    }
+  }
+
+  if (!mouseEvent)
+    return false;
+
+  if (_corner->GetMouseState() == QEvent::GraphicsSceneMouseMove)
+  {
+    QPointF scenePosition = _corner->mapToScene(mouseEvent->pos());
+
+    this->SetVertexPosition(_corner->GetIndex(), scenePosition);
+
+    this->update();
+
+    for (int i = _corner->GetIndex(); i > _corner->GetIndex() - 2; --i)
+    {
+      if ((i - this->GetSegmentCount()) != 0 && i >= 0)
+      {
+        LineSegmentItem *segment = this->GetSegment(i);
+        QList<QGraphicsItem *> children = segment->childItems();
+        for (int j = 0; j < children.size(); ++j)
+        {
+          // TODO find a more generic way than casting child as rect item
+          RectItem *rectItem = dynamic_cast<RectItem *>(children[j]);
+          if (rectItem)
+          {
+            rectItem->SetRotation(-segment->line().angle());
+            QPointF delta = rectItem->pos() - segment->line().p1();
+            QPointF deltaLine = segment->line().p2() - segment->line().p1();
+            double deltaRatio = sqrt(delta.x()*delta.x() + delta.y()*delta.y())
+                / segment->line().length();
+            rectItem->setPos(segment->line().p1() + deltaRatio*deltaLine);
+
+          }
+        }
+      }
+    }
+  }
+  return true;
+}
+
 /////////////////////////////////////////////////
 bool WallItem::segmentEventFilter(LineSegmentItem *_segment,
     QEvent *_event)
     this->segmentMouseMove = scenePosition;
 
     this->update();
+
+    QList<QGraphicsItem *> children = _segment->childItems();
+    for ( int i = 0; i < children.size(); ++i)
+      children[i]->moveBy(trans.x(), trans.y());
   }
   return true;
 }

gazebo/gui/model_editor/WallItem.hh

   {
     class PolylineItem;
 
+    class CornerGrabber;
+
     class LineSegmentItem;
 
     class BuildingItem;
 
         public: void Update();
 
+        private: bool cornerEventFilter(CornerGrabber *_corner,
+            QEvent *_event);
+
         private: bool segmentEventFilter(LineSegmentItem *_segment,
             QEvent *_event);
 

gazebo/gui/model_editor/WindowItem.cc

   this->windowHeight = 80;
   this->windowWidth = 80;
   this->windowSideBar = 10;
-  this->windowPos = this->pos();
+  this->windowPos = this->scenePos();
   this->windowElevation = 50;
 
   this->width = this->windowWidth;
 
   this->windowWidth = this->drawingWidth;
   this->windowDepth = this->drawingHeight;
-  this->windowPos = this->pos();
+  this->windowPos = this->scenePos();
   _painter->restore();
 
 //  QGraphicsPolygonItem::paint(_painter, _option, _widget);
     this->windowHeight = dialog.GetHeight() / this->scale;
     this->windowDepth = dialog.GetDepth() / this->scale;
     this->windowElevation = dialog.GetElevation() / this->scale;
-    itemPos = dialog.GetPosition() / this->scale;
-    itemPos.setY(-itemPos.y());
-    this->windowPos = itemPos;
-    this->setPos(this->windowPos);
+    if ((fabs(dialog.GetPosition().x() - itemPos.x()) >= 0.01)
+        || (fabs(dialog.GetPosition().y() - itemPos.y()) >= 0.01))
+    {
+      itemPos = dialog.GetPosition() / this->scale;
+      itemPos.setY(-itemPos.y());
+      this->windowPos = itemPos;
+      this->setPos(this->windowPos);
+      this->setParentItem(NULL);
+    }
     this->WindowChanged();
   }
   _event->setAccepted(true);