From 775cf739c630e32240b1b6db09eb5c011ea7e562 Mon Sep 17 00:00:00 2001 From: Tats Date: Tue, 14 Jul 2015 13:24:36 -0600 Subject: [PATCH] - Moved the control of shapes outside of the scene items - Introduced a specialized range of classes to deal with the drawing of controls --- DestinationGLCanvas.cpp | 10 ++ DestinationGLCanvas.h | 1 + Mapper.cpp | 339 ++++++++++++++++++-------------------- Mapper.h | 129 +++++++++------ MapperGLCanvas.cpp | 355 +++++++++++++++++++++++----------------- MapperGLCanvas.h | 20 ++- OutputGLCanvas.cpp | 30 ++-- SourceGLCanvas.cpp | 12 ++ SourceGLCanvas.h | 1 + 9 files changed, 511 insertions(+), 386 deletions(-) diff --git a/DestinationGLCanvas.cpp b/DestinationGLCanvas.cpp index 9009640..84204c3 100644 --- a/DestinationGLCanvas.cpp +++ b/DestinationGLCanvas.cpp @@ -34,3 +34,13 @@ MShape* DestinationGLCanvas::getShapeFromMappingId(uid mappingId) return getMainWindow()->getMappingManager().getMappingById(mappingId)->getShape().get(); } +ShapeGraphicsItem* DestinationGLCanvas::getShapeGraphicsItemFromMappingId(uid mappingId) +{ + if (mappingId == NULL_UID) + return NULL; + + else + { + return MainWindow::instance()->getMapperByMappingId(mappingId)->getGraphicsItem(); + } +} diff --git a/DestinationGLCanvas.h b/DestinationGLCanvas.h index 1cf0007..7cee0c4 100644 --- a/DestinationGLCanvas.h +++ b/DestinationGLCanvas.h @@ -35,6 +35,7 @@ public: virtual ~DestinationGLCanvas() {} virtual MShape* getShapeFromMappingId(uid mappingId); + virtual ShapeGraphicsItem* getShapeGraphicsItemFromMappingId(uid mappingId); }; #endif /* DESTINATIONGLCANVAS_H_ */ diff --git a/Mapper.cpp b/Mapper.cpp index 965c5ce..9596853 100644 --- a/Mapper.cpp +++ b/Mapper.cpp @@ -21,18 +21,83 @@ #include "Mapper.h" #include "MainWindow.h" +ShapeControlPainter::ShapeControlPainter(ShapeGraphicsItem* shapeItem) + : _shapeItem(shapeItem) +{} + +MShape::ptr ShapeControlPainter::getShape() const { return _shapeItem->getShape(); } + +void ShapeControlPainter::paint(QPainter *painter, const QList& selectedVertices) +{ + _paintShape(painter); + _paintVertices(painter); +} + +void ShapeControlPainter::_paintVertices(QPainter *painter, const QList& selectedVertices) +{ + qreal zoomFactor = _shapeItem->getCanvas()->getZoomFactor(); + qreal selectRadius = MM::VERTEX_SELECT_RADIUS / zoomFactor; + qreal strokeWidth = MM::VERTEX_SELECT_STROKE_WIDTH / zoomFactor; + + for (int i=0; inVertices(); i++) + Util::drawControlsVertex(painter, getShape()->getVertex(i), selectedVertices.contains(i), selectRadius, strokeWidth); +} + +void PolygonControlPainter::_paintShape(QPainter *painter) +{ + Polygon* poly = static_cast(getShape().get()); + Q_ASSERT(poly); + + // Init colors and stroke. + painter->setPen(_shapeItem->_getRescaledShapeStroke()); + + // Draw inner quads. + painter->drawPolygon(poly->toPolygon()); +} + + +void EllipseControlPainter::_paintShape(QPainter *painter) +{ + Ellipse* ellipse = static_cast(getShape().get()); + Q_ASSERT(ellipse); + + // Init colors and stroke. + painter->setPen(_shapeItem->_getRescaledShapeStroke()); + painter->setBrush(Qt::NoBrush); + + // Draw ellipse contour. + QPainterPath path; + QTransform transform; + transform.translate(ellipse->getCenter().x(), ellipse->getCenter().y()); + transform.rotate(ellipse->getRotation()); + path.addEllipse(QPoint(0,0), ellipse->getHorizontalRadius(), ellipse->getVerticalRadius()); + painter->drawPath(transform.map(path)); +} + +void MeshControlPainter::_paintShape(QPainter *painter) +{ + Mesh* mesh = static_cast(getShape().get()); + Q_ASSERT(mesh); + + // Init colors and stroke. + painter->setPen(_shapeItem->_getRescaledShapeStroke(true)); + + // Draw inner quads. + QVector quads = mesh->getQuads(); + for (QVector::const_iterator it = quads.begin(); it != quads.end(); ++it) + { + painter->drawPolygon(it->toPolygon()); + } + + // Draw outer quad. + painter->setPen(_shapeItem->_getRescaledShapeStroke()); + painter->drawPolygon(_shapeItem->mapFromScene(mesh->toPolygon())); +} + ShapeGraphicsItem::ShapeGraphicsItem(Mapping::ptr mapping, bool output) : _mapping(mapping), _output(output) { _shape = output ? _mapping->getShape() : _mapping->getInputShape(); - - setFlags(ItemIsMovable | ItemIsSelectable); - - // Shape filters child (control point) events. - setFiltersChildEvents(true); - - // Create control point graphics items. - _createVertices(); } MapperGLCanvas* ShapeGraphicsItem::getCanvas() const @@ -45,40 +110,39 @@ bool ShapeGraphicsItem::isMappingCurrent() const { return MainWindow::instance() bool ShapeGraphicsItem::sceneEventFilter(QGraphicsItem * watched, QEvent * event) { - // Change vertex in model according to moved item. - if (event->type() == QEvent::GraphicsSceneMouseMove) - { - QGraphicsSceneMoveEvent* moveEvent = static_cast(event); - QGraphicsSceneMouseEvent* mouseEvent = static_cast(event); - // Q_ASSERT(moveEvent); - Q_ASSERT(mouseEvent); - - int idx = childItems().indexOf(watched); - Q_ASSERT(idx != -1); - -// QPointF pos = moveEvent->newPos();// + this->pos(); - QPointF pos = mouseEvent->scenePos(); - - // Sticky vertex. - if (MainWindow::instance()->stickyVertices()) - _glueVertex(&pos); - - // qDebug() << moveEvent->oldPos() << " " << pos << " " << childItems().at(idx)->pos() << endl; - _shape->setVertex(idx, pos); - - _syncVertices(); - - // Refresh this shape. - // update(); - - // override default - return true; - } - else - { - // Returns false to allow the child item to process its event. - return false; - } + return true; +// // Change vertex in model according to moved item. +// if (event->type() == QEvent::GraphicsSceneMouseMove) +// { +// QGraphicsSceneMoveEvent* moveEvent = static_cast(event); +// QGraphicsSceneMouseEvent* mouseEvent = static_cast(event); +// // Q_ASSERT(moveEvent); +// Q_ASSERT(mouseEvent); +// +// int idx = childItems().indexOf(watched); +// Q_ASSERT(idx != -1); +// +//// QPointF pos = moveEvent->newPos();// + this->pos(); +// QPointF pos = mouseEvent->scenePos(); +// +// // Sticky vertex. +// if (MainWindow::instance()->stickyVertices()) +// _glueVertex(&pos); +// +// // qDebug() << moveEvent->oldPos() << " " << pos << " " << childItems().at(idx)->pos() << endl; +// _shape->setVertex(idx, pos); +// +// // Refresh this shape. +// // update(); +// +// // override default +// return true; +// } +// else +// { +// // Returns false to allow the child item to process its event. +// return false; +// } } void ShapeGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event) @@ -109,9 +173,6 @@ void ShapeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) return; QGraphicsItem::mouseMoveEvent(event); - - // Sync shape. - _syncShape(); } void ShapeGraphicsItem::paint(QPainter *painter, @@ -130,20 +191,19 @@ void ShapeGraphicsItem::paint(QPainter *painter, _prePaint(painter, option); _doPaint(painter, option); _postPaint(painter, option); - - if (MainWindow::instance()->displayControls() && isMappingCurrent()) - { - _doPaintControls(painter, option); - } } } void ShapeGraphicsItem::_doPaintControls(QPainter *painter, const QStyleOptionGraphicsItem *option) { - Q_UNUSED(option); - painter->setPen(_getRescaledShapeStroke()); - painter->setBrush(Qt::NoBrush); - painter->drawPath(shape()); +// Q_UNUSED(option); +// _controlPainter->paint(painter, ) +// Util::drawControls +// painter->setPen(_getRescaledShapeStroke()); +// painter->setBrush(Qt::NoBrush); +// painter->drawPath(shape()); +// Util::drawControlsVertex(painter, QPointF(0,0), (option->state & QStyle::State_Selected), MM::VERTEX_SELECT_RADIUS); +// } } @@ -158,133 +218,58 @@ void ShapeGraphicsItem::_doPaintControls(QPainter *painter, const QStyleOptionGr // return QGraphicsItem::itemChange(change, value); //} -void ShapeGraphicsItem::resetVertices() { - // Clear vertices. - QList allChildren = children(); - for (QList::iterator it = allChildren.begin(); it!=allChildren.end(); ++it) - { - (*it)->setParentItem(0); - scene()->removeItem(*it); - delete (*it); - } - - // Re-create them. - _createVertices(); -} - -void ShapeGraphicsItem::_createVertices() -{ - // rect offset - for (int i=0; i<_shape->nVertices(); i++) - { - // XXX is this freed by parent? - QPointF pos = mapFromScene(_shape->getVertex(i));// - this->pos(); - VertexGraphicsItem* child = new VertexGraphicsItem(i); -// child->setPos( pos ); - child->setParentItem(this); - child->setPos( pos ); - child->setRect( -MM::VERTEX_SELECT_RADIUS, -MM::VERTEX_SELECT_RADIUS, MM::VERTEX_SELECT_RADIUS*2, MM::VERTEX_SELECT_RADIUS*2); -// child->setRect(pos.x()-offset, pos.y()-offset, MM::VERTEX_SELECT_RADIUS, MM::VERTEX_SELECT_RADIUS); -// qDebug() << "Adding child at " << pos << " " << child->pos(); -// qDebug() << ", after add " << child->pos() << endl; - } -} - -void ShapeGraphicsItem::_syncShape() -{ - QList children = childItems(); - for (int i=0; i<_shape->nVertices(); i++) - { - _shape->setVertex(i, children.at(i)->scenePos()); - } - - // The shape object is the model: it contains the logic to make sure the vertices are ok. - // So here we need to re-sync the vertices (view side) according to the model. - _syncVertices(); -} - -void ShapeGraphicsItem::_syncVertices() -{ - for (int i=0; i<_shape->nVertices(); i++) - { - QPointF pos = _shape->getVertex(i) ;//- this->pos(); // this is in scene coordinates - childItems().at(i)->setPos(this->mapFromScene(pos)); - childItems().at(i)->update(); - } -} - -void ShapeGraphicsItem::_glueVertex(QPointF* p) -{ - MappingManager manager = MainWindow::instance()->getMappingManager(); - for (int i = 0; i < manager.nMappings(); i++) - { - MShape *shape = manager.getMapping(i)->getShape().get(); - if (shape && shape != _shape.get()) - { - for (int vertex = 0; vertex < shape->nVertices(); vertex++) - { - const QPointF& v = shape->getVertex(vertex); - if (distIsInside(v, *p, MM::VERTEX_STICK_RADIUS)) - { - p->setX(v.x()); - p->setY(v.y()); - } - } - } - } -} QPen ShapeGraphicsItem::_getRescaledShapeStroke(bool innerStroke) { return QPen(QBrush(MM::CONTROL_COLOR), (innerStroke ? MM::SHAPE_INNER_STROKE_WIDTH : MM::SHAPE_STROKE_WIDTH) / getCanvas()->getZoomFactor()); } -void VertexGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event) -{ - ShapeGraphicsItem* shapeParent = static_cast(parentItem()); - if (!shapeParent->isMappingVisible()) - { - // Prevent mouse grabbing. - event->ignore(); - } - else - { - if (shapeParent->isOutput()) - { - QGraphicsItem::mousePressEvent(event); - if (event->button() == Qt::LeftButton) - { - MainWindow::instance()->setCurrentMapping(shapeParent->getMapping()->getId()); - } - } - else - { - if (shapeParent->isMappingCurrent()) - QGraphicsItem::mousePressEvent(event); - else - event->ignore(); // prevent mousegrabbing on non-current mapping - } - } -} - -void VertexGraphicsItem::paint(QPainter *painter, - const QStyleOptionGraphicsItem *option, - QWidget* widget) -{ - Q_UNUSED(widget); - if (MainWindow::instance()->displayControls()) - { - ShapeGraphicsItem* shapeParent = static_cast(parentItem()); - if (shapeParent->isMappingVisible() && - shapeParent->isMappingCurrent()) - { - qreal zoomFactor = 1.0 / shapeParent->getCanvas()->getZoomFactor(); - resetMatrix(); - scale(zoomFactor, zoomFactor); - Util::drawControlsVertex(painter, QPointF(0,0), (option->state & QStyle::State_Selected), MM::VERTEX_SELECT_RADIUS); - } - } -} +//void VertexGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event) +//{ +// ShapeGraphicsItem* shapeParent = static_cast(parentItem()); +// if (!shapeParent->isMappingVisible()) +// { +// // Prevent mouse grabbing. +// event->ignore(); +// } +// else +// { +// if (shapeParent->isOutput()) +// { +// QGraphicsItem::mousePressEvent(event); +// if (event->button() == Qt::LeftButton) +// { +// MainWindow::instance()->setCurrentMapping(shapeParent->getMapping()->getId()); +// } +// } +// else +// { +// if (shapeParent->isMappingCurrent()) +// QGraphicsItem::mousePressEvent(event); +// else +// event->ignore(); // prevent mousegrabbing on non-current mapping +// } +// } +//} +// +//void VertexGraphicsItem::paint(QPainter *painter, +// const QStyleOptionGraphicsItem *option, +// QWidget* widget) +//{ +// Q_UNUSED(widget); +//// if (MainWindow::instance()->displayControls()) +//// { +//// ShapeGraphicsItem* shapeParent = static_cast(parentItem()); +//// if (shapeParent->isMappingVisible() && +//// shapeParent->isMappingCurrent()) +//// { +//// qreal zoomFactor = 1.0 / shapeParent->getCanvas()->getZoomFactor(); +//// resetMatrix(); +//// scale(zoomFactor, zoomFactor); +//// Util::drawControlsVertex(painter, QPointF(0,0), (option->state & QStyle::State_Selected), MM::VERTEX_SELECT_RADIUS); +//// } +//// } +//} void ColorGraphicsItem::_prePaint(QPainter *painter, const QStyleOptionGraphicsItem *option) @@ -1052,8 +1037,8 @@ void MeshTextureMapper::setValue(QtProperty* property, const QVariant& value) outputMesh->resize(size.width(), size.height()); inputMesh->resize(size.width(), size.height()); - _graphicsItem->resetVertices(); - _inputGraphicsItem->resetVertices(); +// _graphicsItem->resetVertices(); +// _inputGraphicsItem->resetVertices(); // TODO: here we need to create the graphicsitems diff --git a/Mapper.h b/Mapper.h index afcfb55..634d337 100644 --- a/Mapper.h +++ b/Mapper.h @@ -51,21 +51,77 @@ #include "variantmanager.h" #include "variantfactory.h" -class VertexGraphicsItem; +class MapperGLCanvas; + +class ShapeGraphicsItem; + +class ShapeControlPainter +{ +public: + typedef std::tr1::shared_ptr ptr; + + ShapeControlPainter(ShapeGraphicsItem* shapeItem); + virtual ~ShapeControlPainter() {} + + MShape::ptr getShape() const; + + virtual void paint(QPainter *painter, const QList& selectedVertices = QList()); + +protected: + virtual void _paintShape(QPainter *painter) = 0; + virtual void _paintVertices(QPainter *painter, const QList& selectedVertices = QList()); + + ShapeGraphicsItem* _shapeItem; +}; + +class PolygonControlPainter : public ShapeControlPainter +{ +public: + PolygonControlPainter(ShapeGraphicsItem* shapeItem) : ShapeControlPainter(shapeItem) {} + virtual ~PolygonControlPainter() {} + +protected: + virtual void _paintShape(QPainter *painter); +}; + +class EllipseControlPainter : public ShapeControlPainter +{ +public: + EllipseControlPainter(ShapeGraphicsItem* shapeItem) : ShapeControlPainter(shapeItem) {} + virtual ~EllipseControlPainter() {} + +protected: + virtual void _paintShape(QPainter *painter); +}; + +class MeshControlPainter : public ShapeControlPainter +{ +public: + MeshControlPainter(ShapeGraphicsItem* shapeItem) : ShapeControlPainter(shapeItem) {} + virtual ~MeshControlPainter() {} + +protected: + virtual void _paintShape(QPainter *painter); +}; class ShapeGraphicsItem : public QGraphicsItem { Q_DECLARE_TR_FUNCTIONS(ShapeGraphicsItem) -public: +protected: ShapeGraphicsItem(Mapping::ptr mapping, bool output=true); +public: virtual ~ShapeGraphicsItem() {} +public: + // TODO: dangereux: confusion possible entre shape() et getShape()... MShape::ptr getShape() const { return _shape; } Mapping::ptr getMapping() const { return _mapping; } + ShapeControlPainter::ptr getControlPainter() { return _controlPainter; } + bool isOutput() const { return _output; } MapperGLCanvas* getCanvas() const; @@ -86,65 +142,32 @@ public: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); -public: - void resetVertices(); - protected: - // Generates the VertexGraphicsItems that are defining the vertices of that shape. - virtual void _createVertices(); - - // Sync MShape from current VertexGraphicsItems. - virtual void _syncShape(); - - // Sync VertexGraphicsItems from MShape. - virtual void _syncVertices(); - virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option) = 0; virtual void _prePaint(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(painter); Q_UNUSED(option); } virtual void _postPaint(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(painter); Q_UNUSED(option); } +public: virtual void _doPaintControls(QPainter *painter, const QStyleOptionGraphicsItem *option); - // TODO: Perhaps the sticky-sensitivity should be configurable through GUI - void _glueVertex(QPointF* p); - // Utility function: returns a stroke with rescaled width such that the stroke appears // invariant to the zoom level (to be used in _doPaintControls() method). QPen _getRescaledShapeStroke(bool innerStroke=false); - +protected: Mapping::ptr _mapping; MShape::ptr _shape; + ShapeControlPainter::ptr _controlPainter; bool _output; }; -/// Graphics item for vertices / control points. -class VertexGraphicsItem : public QGraphicsEllipseItem -{ - Q_DECLARE_TR_FUNCTIONS(VertexGraphicsItem) - -public: - VertexGraphicsItem(int index) : _index(index) { - setFlags(ItemIsMovable | ItemIsSelectable); - } - virtual ~VertexGraphicsItem() {} - - // Prevent mousegrabbing if mapping is invisible. - void mousePressEvent(QGraphicsSceneMouseEvent *event); - - virtual void paint(QPainter *painter, - const QStyleOptionGraphicsItem *option, - QWidget* widget); - -protected: - int _index; -}; - class ColorGraphicsItem : public ShapeGraphicsItem { +protected: + ColorGraphicsItem(Mapping::ptr mapping, bool output=true) + : ShapeGraphicsItem(mapping, output) {} public: - ColorGraphicsItem(Mapping::ptr mapping, bool output=true) : ShapeGraphicsItem(mapping, output) {} virtual ~ColorGraphicsItem() {} protected: @@ -156,7 +179,10 @@ protected: class PolygonColorGraphicsItem : public ColorGraphicsItem { public: - PolygonColorGraphicsItem(Mapping::ptr mapping, bool output=true) : ColorGraphicsItem(mapping, output) {} + PolygonColorGraphicsItem(Mapping::ptr mapping, bool output=true) + : ColorGraphicsItem(mapping, output) { + _controlPainter.reset(new PolygonControlPainter(this)); + } virtual ~PolygonColorGraphicsItem() {} virtual QPainterPath shape() const; @@ -164,6 +190,7 @@ public: protected: virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option); +public: void _doPaintControls(QPainter* painter, const QStyleOptionGraphicsItem *option); }; @@ -171,7 +198,10 @@ protected: class EllipseColorGraphicsItem : public ColorGraphicsItem { public: - EllipseColorGraphicsItem(Mapping::ptr mapping, bool output=true) : ColorGraphicsItem(mapping, output) {} + EllipseColorGraphicsItem(Mapping::ptr mapping, bool output=true) + : ColorGraphicsItem(mapping, output) { + _controlPainter.reset(new EllipseControlPainter(this)); + } virtual ~EllipseColorGraphicsItem() {} virtual QPainterPath shape() const; @@ -207,9 +237,12 @@ protected: class PolygonTextureGraphicsItem : public TextureGraphicsItem { public: - PolygonTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : TextureGraphicsItem(mapping, output) {} + PolygonTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : TextureGraphicsItem(mapping, output) { + _controlPainter.reset(new PolygonControlPainter(this)); + } virtual ~PolygonTextureGraphicsItem(){} +public: virtual void _doPaintControls(QPainter* painter, const QStyleOptionGraphicsItem *option); virtual QPainterPath shape() const; @@ -231,7 +264,9 @@ public: class MeshTextureGraphicsItem : public PolygonTextureGraphicsItem { public: - MeshTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : PolygonTextureGraphicsItem(mapping, output) {} + MeshTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : PolygonTextureGraphicsItem(mapping, output) { + _controlPainter.reset(new MeshControlPainter(this)); + } virtual ~MeshTextureGraphicsItem(){} virtual void _doPaintControls(QPainter* painter, const QStyleOptionGraphicsItem *option); @@ -247,7 +282,9 @@ private: class EllipseTextureGraphicsItem : public TextureGraphicsItem { public: - EllipseTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : TextureGraphicsItem(mapping, output) {} + EllipseTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : TextureGraphicsItem(mapping, output) { + _controlPainter.reset(new EllipseControlPainter(this)); + } virtual ~EllipseTextureGraphicsItem(){} virtual QPainterPath shape() const; diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index 5b6fdd3..ef58167 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -58,145 +58,199 @@ MapperGLCanvas::MapperGLCanvas(MainWindow* mainWindow, QWidget* parent, const QG this->scene()->setBackgroundBrush(Qt::black); } -MShape* MapperGLCanvas::getCurrentShape() { +MShape* MapperGLCanvas::getCurrentShape() +{ return getShapeFromMappingId(MainWindow::instance()->getCurrentMappingId()); } +ShapeGraphicsItem* MapperGLCanvas::getCurrentShapeGraphicsItem() +{ + return getShapeGraphicsItemFromMappingId(MainWindow::instance()->getCurrentMappingId()); +} + +// Draws foreground (displays crosshair if needed). +void MapperGLCanvas::drawForeground(QPainter *painter , const QRectF &rect) +{ + if (_mainWindow->displayControls()) + { + uid mid = _mainWindow->getCurrentMappingId(); + if (mid != NULL_UID) + { + ShapeGraphicsItem* item = getCurrentShapeGraphicsItem(); + if (item) + item->getControlPainter()->paint(painter); + } + } +} + // -//void MapperGLCanvas::mousePressEvent(QMouseEvent* event) -//{ -// int i; -// int dist; -// int minDistance; -// -// bool mousePressedOnSomething = false; -// -// _mousePressedPosition = event->pos(); -// -// // Note: we compare with the square value for fastest computation of the distance -// minDistance = MM::VERTEX_SELECT_RADIUS * MM::VERTEX_SELECT_RADIUS; -// -// // Drag the closest vertex -// if (event->buttons() & Qt::LeftButton) +void MapperGLCanvas::mousePressEvent(QMouseEvent* event) +{ + int i; + int dist; + int minDistance; + + bool mousePressedOnSomething = false; + + _mousePressedPosition = event->pos(); + QPointF pos = mapToScene(event->pos()); + + // Note: we compare with the square value for fastest computation of the distance + minDistance = MM::VERTEX_SELECT_RADIUS * MM::VERTEX_SELECT_RADIUS; + + // Drag the closest vertex. + if (event->buttons() & Qt::LeftButton) + { + MShape* shape = getCurrentShape(); + if (shape) + { + // find the ID of the nearest vertex: (from the selected shape) + for (i = 0; i < shape->nVertices(); i++) + { + dist = distSq(pos, shape->getVertex(i)); // squared distance + if (dist < minDistance) + { + _activeVertex = i; + minDistance = dist; + + _mousePressedOnVertex = true; + mousePressedOnSomething = true; + + _grabbedObjectStartPosition = shape->getVertex(i); + } + } + } + } + + if (mousePressedOnSomething) + return; + + // Select a shape with a click. + if (event->buttons() & Qt::LeftButton || Qt::RightButton) // Add Right click for context menu + { + MShape* selectedShape = getCurrentShape(); + MappingManager manager = getMainWindow()->getMappingManager(); + QVector mappings = manager.getVisibleMappings(); + for (QVector::const_iterator it = mappings.end() - 1; it >= mappings.begin(); --it) + { + MShape *shape = getShapeFromMappingId((*it)->getId()); + // Mouse pressed on a shape. + if (shape && shape->includesPoint(pos)) + { + mousePressedOnSomething = true; + // Deselect vertices. + deselectVertices(); + // Change mapping. + if (shape != selectedShape) + { + getMainWindow()->setCurrentMapping((*it)->getId()); + + // Reset orig. + selectedShape = getCurrentShape(); + } + break; + } + } + + // Grab the shape. + if (event->buttons() & Qt::LeftButton) // This preserve me from duplicate code above + { + if (selectedShape && selectedShape->includesPoint(pos)) + { + _shapeGrabbed = true; + _shapeFirstGrab = true; + + _grabbedObjectStartPosition = pos; + } + } + } + + if (mousePressedOnSomething) + return; + + // Deactivate. + deselectAll(); +} + +void MapperGLCanvas::mouseReleaseEvent(QMouseEvent* event) +{ + Q_UNUSED(event); +// // Click on vertex ==> select the vertex. +// if ((event->buttons() & Qt::LeftButton) && _mousePressedOnVertex) // { -// Shape* shape = getCurrentShape(); -// if (shape) -// { -// // find the ID of the nearest vertex: (from the selected shape) -// for (i = 0; i < shape->nVertices(); i++) -// { -// dist = distSq(_mousePressedPosition, shape->getVertex(i)); // squared distance -// if (dist < minDistance) -// { -// _activeVertex = i; -// minDistance = dist; -// -// _mousePressedOnVertex = true; -// mousePressedOnSomething = true; -// } -// } -// } // } -// -// if (mousePressedOnSomething) -// return; -// -// // Select a shape with a click. -// if (event->buttons() & Qt::LeftButton || Qt::RightButton) // Add Right click for context menu -// { -// Shape* orig = getCurrentShape(); -// MappingManager manager = getMainWindow()->getMappingManager(); -// QVector mappings = manager.getVisibleMappings(); -// for (QVector::const_iterator it = mappings.end() - 1; it >= mappings.begin(); --it) -// { -// Shape *shape = getShapeFromMappingId((*it)->getId()); -// // Mouse pressed on a shape. -// if (shape && shape->includesPoint(_mousePressedPosition)) -// { -// mousePressedOnSomething = true; -// // Deselect vertices. -// deselectVertices(); -// // Change mapping. -// if (shape != orig) -// { -// getMainWindow()->setCurrentMapping((*it)->getId()); -// } -// break; -// } -// } -// -// // Grab the shape. -// if (event->buttons() & Qt::LeftButton) // This preserve me from duplicate code above -// { -// if (orig && orig->includesPoint(_mousePressedPosition)) -// { -// _shapeGrabbed = true; -// _shapeFirstGrab = true; -// } -// } -// } -// -// if (mousePressedOnSomething) -// return; -// -// // Deactivate. -// deselectAll(); -//} -// -//void MapperGLCanvas::mouseReleaseEvent(QMouseEvent* event) -//{ -// Q_UNUSED(event); -//// // Click on vertex ==> select the vertex. -//// if ((event->buttons() & Qt::LeftButton) && _mousePressedOnVertex) -//// { -//// } -// _mousePressedOnVertex = false; -// _shapeGrabbed = false; -//} -// -//void MapperGLCanvas::mouseMoveEvent(QMouseEvent* event) -//{ -// // Prepare to store commands -// undoStack = getMainWindow()->getUndoStack(); -// -// if (_mousePressedOnVertex) -// { -// // std::cout << "Move event " << std::endl; -// Shape* shape = getCurrentShape(); -// if (shape && _activeVertex != NO_VERTEX) -// { + if (_mousePressedOnVertex) + { + } + else if (_shapeGrabbed) + { + + } + _mousePressedOnVertex = false; + _shapeGrabbed = false; +} + +void MapperGLCanvas::mouseMoveEvent(QMouseEvent* event) +{ + static QPoint lastMousePos; + + QPointF pos = mapToScene(event->pos()); + + // Prepare to store commands + undoStack = getMainWindow()->getUndoStack(); + + // Vertex grab. + if (_mousePressedOnVertex) + { + // std::cout << "Move event " << std::endl; + MShape* shape = getCurrentShape(); + if (shape && _activeVertex != NO_VERTEX) + { // QPointF p = shape->getVertex(_activeVertex); // // Set point to mouse coordinates. -// p.setX(event->x()); -// p.setY(event->y()); -// -// // Stick to vertices. -// if (stickyVertices()) -// glueVertex(shape, &p); -// -// // Enable to Undo and Redo when mouse move the position of vertices -// undoStack->push(new MoveVertexCommand(this, _activeVertex, p)); -// } -// } -// else if (_shapeGrabbed) -// { -// // std::cout << "Move event " << std::endl; -// Shape* shape = getCurrentShape(); -// static QPointF prevMousePosition(0,0); // point that keeps track of last position of the mouse -// if (shape) -// { -// if (!_shapeFirstGrab) -// { -// undoStack->push(new MoveShapesCommand(this, event, prevMousePosition)); -// } -// else -// _shapeFirstGrab = false; -// } -// // Update previous mouse position. -// prevMousePosition.setX( event->x() ); -// prevMousePosition.setY( event->y() ); -// } -//} +// p.setX(pos.x()); +// p.setY(pos.y()); + + QPointF p = pos; + + // Stick to vertices. + if (_mainWindow->stickyVertices()) + _glueVertex(&p); + + shape->setVertex(_activeVertex, p); + } + } + + // Shape grab. + else if (_shapeGrabbed) + { + // std::cout << "Move event " << std::endl; + MShape* shape = getCurrentShape(); + if (shape) + { + if (_shapeFirstGrab) + { + lastMousePos = _mousePressedPosition; + _shapeFirstGrab = false; + } + } + + QPointF diff = pos - mapToScene(lastMousePos); + shape->translate(diff.x(), diff.y()); + } + + // Window translation action + else if (event->buttons() & Qt::MiddleButton) + { + QPointF diff = pos - mapToScene(lastMousePos); + QGraphicsView* view = scene()->views().first(); + view->translate(diff.x(), diff.y()); + view->update(); + } + + lastMousePos = event->pos(); +} + // //void MapperGLCanvas::keyPressEvent(QKeyEvent* event) //{ @@ -391,24 +445,6 @@ void MapperGLCanvas::wheelEvent(QWheelEvent *event) event->accept(); } -void MapperGLCanvas::mouseMoveEvent(QMouseEvent *event) -{ - static QPoint lastPos; - - // Click-and-drag translate view. - if (event->buttons() & Qt::MiddleButton) - { - QPoint pos = event->pos(); - QPointF diff = mapToScene(pos) - mapToScene(lastPos); - QGraphicsView* view = scene()->views().first(); - view->translate(diff.x(), diff.y()); - view->update(); - lastPos = pos; - } - - QGraphicsView::mouseMoveEvent(event); -} - bool MapperGLCanvas::eventFilter(QObject *target, QEvent *event) { if (event->type() == QEvent::KeyPress) @@ -424,3 +460,24 @@ bool MapperGLCanvas::eventFilter(QObject *target, QEvent *event) } } + +void MapperGLCanvas::_glueVertex(QPointF* p) +{ + MappingManager manager = MainWindow::instance()->getMappingManager(); + for (int i = 0; i < manager.nMappings(); i++) + { + MShape *shape = manager.getMapping(i)->getShape().get(); + if (shape && shape != getCurrentShape()) + { + for (int vertex = 0; vertex < shape->nVertices(); vertex++) + { + const QPointF& v = shape->getVertex(vertex); + if (distIsInside(v, *p, MM::VERTEX_STICK_RADIUS)) + { + p->setX(v.x()); + p->setY(v.y()); + } + } + } + } +} diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index ed6e16e..212cdff 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -35,7 +35,10 @@ #include "UidAllocator.h" #include "Shape.h" +#include "Mapper.h" + class MainWindow; +class ShapeGraphicsItem; /** * Mother class for OpenGL canvases that allow the display and controls of shapes and vertices. @@ -52,11 +55,17 @@ public: /// Returns shape associated with mapping id. virtual MShape* getShapeFromMappingId(uid mappingId) = 0; + virtual ShapeGraphicsItem* getShapeGraphicsItemFromMappingId(uid mappingId) = 0; MShape* getCurrentShape(); + ShapeGraphicsItem* getCurrentShapeGraphicsItem(); + // QSize sizeHint() const; // QSize minimumSizeHint() const; + // Draws foreground (displays crosshair if needed). + void drawForeground(QPainter *painter , const QRectF &rect); + /** * Stick vertex p of Shape orig to another Shape's vertex, if the 2 vertices are * close enough. The distance per coordinate is currently set in dist_stick @@ -111,9 +120,12 @@ private: // Pointer to main window. MainWindow* _mainWindow; - // Last point pressed. + // Last point pressed (in mouse/window coordinates). QPoint _mousePressedPosition; + // Start position of last object grabbed (in scene coordinates). + QPointF _grabbedObjectStartPosition; + // Mouse currently pressed inside a vertex. bool _mousePressedOnVertex; @@ -142,11 +154,17 @@ public slots: void deselectAll(); void wheelEvent(QWheelEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // Event Filter bool eventFilter(QObject *target, QEvent *event); +protected: + // TODO: Perhaps the sticky-sensitivity should be configurable through GUI + void _glueVertex(QPointF* p); + public: static const int NO_VERTEX = -1; }; diff --git a/OutputGLCanvas.cpp b/OutputGLCanvas.cpp index 6f222f2..953c455 100644 --- a/OutputGLCanvas.cpp +++ b/OutputGLCanvas.cpp @@ -41,28 +41,30 @@ void OutputGLCanvas::drawForeground(QPainter *painter , const QRectF &rect) _drawTestSignal(painter); painter->restore(); glPopMatrix(); - return; } - - // Display crosshair cursor. - if (_displayCrosshair) + else { - QPointF cursorPosition = mapToScene(cursor().pos());// - rect.topLeft();//(QCursor::pos());///*this->mapFromGlobal(*/QCursor::pos()/*)*/; - if (rect.contains(cursorPosition)) + MapperGLCanvas::drawForeground(painter, rect); + + // Display crosshair cursor. + if (_displayCrosshair) { - painter->setPen(MM::CONTROL_COLOR); - painter->drawLine(cursorPosition.x(), rect.y(), cursorPosition.x(), rect.height()); - painter->drawLine(rect.x(), cursorPosition.y(), rect.width(), cursorPosition.y()); + QPointF cursorPosition = mapToScene(cursor().pos());// - rect.topLeft();//(QCursor::pos());///*this->mapFromGlobal(*/QCursor::pos()/*)*/; + if (rect.contains(cursorPosition)) + { + painter->setPen(MM::CONTROL_COLOR); + painter->drawLine(cursorPosition.x(), rect.y(), cursorPosition.x(), rect.height()); + painter->drawLine(rect.x(), cursorPosition.y(), rect.width(), cursorPosition.y()); + } } } + } void OutputGLCanvas::_drawTestSignal(QPainter* painter) { const QRect& geo = geometry(); painter->setPen(MM::CONTROL_COLOR); - int height = geo.height(); - int width = geo.width(); int rect_size = 10; QColor color_0(191, 191, 191); QColor color_1(128, 128, 128); @@ -71,9 +73,10 @@ void OutputGLCanvas::_drawTestSignal(QPainter* painter) painter->setPen(Qt::NoPen); - for (int x = 0; x < width; x += rect_size) + // Draw checkerboard pattern. + for (int x = geo.x(); x < geo.width(); x += rect_size) { - for (int y = 0; y < height; y += rect_size) + for (int y = geo.y(); y < geo.height(); y += rect_size) { if (((x + y) % 20) == 0) { @@ -85,6 +88,7 @@ void OutputGLCanvas::_drawTestSignal(QPainter* painter) } } + // Draw the actual brush. painter->fillRect(geo, this->_brush_test_signal); } diff --git a/SourceGLCanvas.cpp b/SourceGLCanvas.cpp index 66ddbdc..3118812 100644 --- a/SourceGLCanvas.cpp +++ b/SourceGLCanvas.cpp @@ -40,6 +40,18 @@ MShape* SourceGLCanvas::getShapeFromMappingId(uid mappingId) return mapping->getInputShape().get(); } } + +ShapeGraphicsItem* SourceGLCanvas::getShapeGraphicsItemFromMappingId(uid mappingId) +{ + if (mappingId == NULL_UID) + return NULL; + + else + { + return MainWindow::instance()->getMapperByMappingId(mappingId)->getInputGraphicsItem(); + } +} + // //void SourceGLCanvas::doDraw(QPainter* painter) diff --git a/SourceGLCanvas.h b/SourceGLCanvas.h index ec92045..4622060 100644 --- a/SourceGLCanvas.h +++ b/SourceGLCanvas.h @@ -36,6 +36,7 @@ public: virtual ~SourceGLCanvas() {} virtual MShape* getShapeFromMappingId(uid mappingId); + virtual ShapeGraphicsItem* getShapeGraphicsItemFromMappingId(uid mappingId); private: // virtual void doDraw(QPainter* painter);