diff options
| author | Sergiusz Bazanski <q3k@q3k.org> | 2018-07-26 16:20:58 +0100 | 
|---|---|---|
| committer | Sergiusz Bazanski <q3k@q3k.org> | 2018-07-26 16:20:58 +0100 | 
| commit | c897c0ca9afab1d758f5c1b77312e77057a4c814 (patch) | |
| tree | 97aa0945f08ce5b26117242b017f39a73a214a7a | |
| parent | 30d481e3215f33eff80e73c1ee0ed9cc3a8834f0 (diff) | |
| download | nextpnr-c897c0ca9afab1d758f5c1b77312e77057a4c814.tar.gz nextpnr-c897c0ca9afab1d758f5c1b77312e77057a4c814.tar.bz2 nextpnr-c897c0ca9afab1d758f5c1b77312e77057a4c814.zip | |
gui: clickable bels, WIP
| -rw-r--r-- | gui/basewindow.cc | 1 | ||||
| -rw-r--r-- | gui/designwidget.cc | 7 | ||||
| -rw-r--r-- | gui/designwidget.h | 1 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.cc | 74 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.h | 20 | 
5 files changed, 88 insertions, 15 deletions
| diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 78c2fe3a..3cb2cc96 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -83,6 +83,7 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, QWidget *parent      connect(this, SIGNAL(contextChanged(Context *)), fpgaView, SLOT(newContext(Context *)));
      connect(designview, SIGNAL(selected(std::vector<DecalXY>)), fpgaView,
              SLOT(onSelectedArchItem(std::vector<DecalXY>)));
 +    connect(fpgaView, SIGNAL(clickedBel(BelId)), designview, SLOT(onClickedBel(BelId)));
      connect(designview, SIGNAL(highlight(std::vector<DecalXY>, int)), fpgaView,
              SLOT(onHighlightGroupChanged(std::vector<DecalXY>, int)));
 diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 7e8e2840..6d2a6d3d 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -495,6 +495,13 @@ QtProperty *DesignWidget::addSubGroup(QtProperty *topItem, const QString &name)      return item;
  }
 +void DesignWidget::onClickedBel(BelId bel)
 +{
 +    QTreeWidgetItem *item = nameToItem[getElementIndex(ElementType::BEL)].value(ctx->getBelName(bel).c_str(ctx));
 +    treeWidget->setCurrentItem(item);
 +    Q_EMIT selected(getDecals(ElementType::BEL, ctx->getBelName(bel)));
 +}
 +
  void DesignWidget::onItemSelectionChanged()
  {
      if (treeWidget->selectedItems().size() == 0)
 diff --git a/gui/designwidget.h b/gui/designwidget.h index b5877f60..61681541 100644 --- a/gui/designwidget.h +++ b/gui/designwidget.h @@ -74,6 +74,7 @@ class DesignWidget : public QWidget    public Q_SLOTS:
      void newContext(Context *ctx);
      void updateTree();
 +    void onClickedBel(BelId bel);
    private:
      Context *ctx;
 diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 15f37ce0..b9e05a04 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -314,11 +314,10 @@ void FPGAViewWidget::initializeGL()  void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)  {      const float scale = 1.0; -    float offsetX = 0.0, offsetY = 0.0; +    float offsetX = decal.x; +    float offsetY = decal.y;      for (auto &el : ctx_->getDecalGraphics(decal.decal)) { -        offsetX = decal.x; -        offsetY = decal.y;          if (el.type == GraphicElement::G_BOX) {              auto line = PolyLine(true); @@ -400,8 +399,8 @@ void FPGAViewWidget::paintGL()      matrix *= viewMove_;      // Calculate world thickness to achieve a screen 1px/1.1px line. -    float thick1Px = mouseToWorldCoordinates(1, 0).x(); -    float thick11Px = mouseToWorldCoordinates(1.1, 0).x(); +    float thick1Px = mouseToWorldDimensions(1, 0).x(); +    float thick11Px = mouseToWorldDimensions(1.1, 0).x();      // Draw grid.      auto grid = LineShaderData(); @@ -462,13 +461,14 @@ void FPGAViewWidget::renderLines(void)      }      // Local copy of decals, taken as fast as possible to not block the P&R. -    std::vector<DecalXY> belDecals; +    std::vector<std::pair<BelId, DecalXY>> belDecals;      std::vector<DecalXY> wireDecals;      std::vector<DecalXY> pipDecals;      std::vector<DecalXY> groupDecals; +      if (decalsChanged) {          for (auto bel : ctx_->getBels()) { -            belDecals.push_back(ctx_->getBelDecal(bel)); +            belDecals.push_back(std::pair<BelId, DecalXY>(bel, ctx_->getBelDecal(bel)));          }          for (auto wire : ctx_->getWires()) {              wireDecals.push_back(ctx_->getWireDecal(wire)); @@ -489,11 +489,15 @@ void FPGAViewWidget::renderLines(void)      rendererArgs_->highlightedOrSelectedChanged = false;      rendererArgsLock_.unlock(); +    QuadTreeBels::BoundingBox globalBB = QuadTreeBels::BoundingBox(-1000, -1000, 1000, 1000); +      if (decalsChanged) {          auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData);          // Draw Bels. +        data->qtBels = std::unique_ptr<QuadTreeBels>(new QuadTreeBels(globalBB));          for (auto const &decal : belDecals) { -            drawDecal(data->decals, decal); +            drawDecal(data->decals, decal.second); +            commitToQuadtree(data->qtBels.get(), decal.second, decal.first);          }          // Draw Wires.          for (auto const &decal : wireDecals) { @@ -550,12 +554,50 @@ void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int gr  void FPGAViewWidget::resizeGL(int width, int height) {} -void FPGAViewWidget::mousePressEvent(QMouseEvent *event) { lastPos_ = event->pos(); } +void FPGAViewWidget::mousePressEvent(QMouseEvent *event) +{ +    if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) { +        lastPos_ = event->pos(); +    } +    if (event->buttons() & Qt::LeftButton) { +        int x = event->x(); +        int y = event->y(); +        auto world = mouseToWorldCoordinates(x, y); +        rendererDataLock_.lock(); +        if (rendererData_->qtBels != nullptr) { +            auto elems = rendererData_->qtBels->get(world.x(), world.y()); +            if (elems.size() > 0) { +                clickedBel(elems[0]); +            } +        } +        rendererDataLock_.unlock(); +    } +}  // Invert the projection matrix to calculate screen/mouse to world/grid  // coordinates.  QVector4D FPGAViewWidget::mouseToWorldCoordinates(int x, int y)  { +    const qreal retinaScale = devicePixelRatio(); + +    auto projection = getProjection(); + +    QMatrix4x4 vp; +    vp.viewport(0, 0, width() * retinaScale, height() * retinaScale); + +    QVector4D vec(x, y, 0, 1); +    vec = vp.inverted() * vec; +    vec = projection.inverted() * vec; + +    auto ray = vec.toVector3DAffine(); +    auto world = QVector4D(ray.x()*ray.z(), -ray.y()*ray.z(), 0, 1); +    world = viewMove_.inverted() * world; + +    return world; +} + +QVector4D FPGAViewWidget::mouseToWorldDimensions(int x, int y) +{      QMatrix4x4 p = getProjection();      QVector2D unit = p.map(QVector4D(1, 1, 0, 1)).toVector2DAffine(); @@ -566,14 +608,16 @@ QVector4D FPGAViewWidget::mouseToWorldCoordinates(int x, int y)  void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event)  { -    const int dx = event->x() - lastPos_.x(); -    const int dy = event->y() - lastPos_.y(); -    lastPos_ = event->pos(); +    if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) { +        const int dx = event->x() - lastPos_.x(); +        const int dy = event->y() - lastPos_.y(); +        lastPos_ = event->pos(); -    auto world = mouseToWorldCoordinates(dx, dy); -    viewMove_.translate(world.x(), -world.y()); +        auto world = mouseToWorldDimensions(dx, dy); +        viewMove_.translate(world.x(), -world.y()); -    update(); +        update(); +    }  }  void FPGAViewWidget::wheelEvent(QWheelEvent *event) diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index b87c5d0a..f69fa786 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -33,6 +33,7 @@  #include <QWaitCondition>  #include "nextpnr.h" +#include "quadtree.h"  NEXTPNR_NAMESPACE_BEGIN @@ -292,6 +293,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions      void onSelectedArchItem(std::vector<DecalXY> decals);      void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);      void pokeRenderer(void); +  Q_SIGNALS: +    void clickedBel(BelId bel);    private:      void renderLines(void); @@ -302,6 +305,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions      float zoom_;      QMatrix4x4 getProjection(void);      QVector4D mouseToWorldCoordinates(int x, int y); +    QVector4D mouseToWorldDimensions(int x, int y);      const float zoomNear_ = 1.0f;    // do not zoom closer than this      const float zoomFar_ = 10000.0f; // do not zoom further than this @@ -314,6 +318,21 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions      std::unique_ptr<PeriodicRunner> renderRunner_; +    using QuadTreeBels = QuadTree<float, BelId>; + +    template <typename T> +    void commitToQuadtree(T *tree, const DecalXY &decal, BelId bel) +    { +        float offsetX = decal.x; +        float offsetY = decal.y; + +        for (auto &el : ctx_->getDecalGraphics(decal.decal)) { +            if (el.type == GraphicElement::G_BOX) { +                tree->insert(typename T::BoundingBox(offsetX + el.x1, offsetY + el.y1, offsetX + el.x2, offsetY + el.y2), bel); +            } +        } +    } +      struct      {          QColor background; @@ -331,6 +350,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions          LineShaderData decals[4];          LineShaderData selected;          LineShaderData highlighted[8]; +        std::unique_ptr<QuadTreeBels> qtBels;      };      struct RendererArgs | 
