<commit_before>// Copyright 2015, <NAME> and the other displaz contributors.
// Use of this code is governed by the BSD-style license found in LICENSE.txt

// DEBUG enable OpenGL error checking
// #define GL_CHECK 1

#include "glutil.h"
#include "View3D.h"

#include <QTimer>
#include <QTime>
#include <QKeyEvent>
#include <QLayout>
#include <QItemSelectionModel>
#include <QMessageBox>
#include <QGLFormat>

#include "config.h"
#include "fileloader.h"
#include "QtLogger.h"
#include "PointViewerMainWindow.h"
#include "TriMesh.h"
#include "Shader.h"
#include "tinyformat.h"
#include "util.h"

//------------------------------------------------------------------------------
View3D::View3D(GeometryCollection* geometries, const QGLFormat& format, QWidget *parent)
    : QGLWidget(format, parent),
    m_camera(false, false),
    m_mouseButton(Qt::NoButton),
    m_explicitCursorPos(false),
    m_cursorPos(0),
    m_prevCursorSnap(0),
    m_backgroundColor(60, 50, 50),
    m_drawBoundingBoxes(true),
    m_drawCursor(true),
    m_drawAxes(true),
    m_drawGrid(false),
    m_drawAnnotations(true),
    m_badOpenGL(false),
    m_shaderProgram(),
    m_geometries(geometries),
    m_selectionModel(0),
    m_shaderParamsUI(0),
    m_incrementalFrameTimer(0),
    m_incrementalFramebuffer(),
    m_incrementalDraw(false),
    m_drawAxesBackground(QImage(":/resource/axes.png")),
    m_drawAxesLabelX(QImage(":/resource/x.png")),
    m_drawAxesLabelY(QImage(":/resource/y.png")),
    m_drawAxesLabelZ(QImage(":/resource/z.png")),
    m_cursorVertexArray(0),
    m_axesVertexArray(0),
    m_gridVertexArray(0),
    m_quadVertexArray(0),
    m_quadLabelVertexArray(0),
    m_devicePixelRatio(1.0)
{
    connect(m_geometries, SIGNAL(layoutChanged()),                      this, SLOT(geometryChanged()));
    //connect(m_geometries, SIGNAL(destroyed()),                          this, SLOT(modelDestroyed()));
    connect(m_geometries, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(geometryChanged()));
    connect(m_geometries, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex)));
    connect(m_geometries, SIGNAL(rowsInserted(QModelIndex,int,int)),    this, SLOT(geometryInserted(const QModelIndex&, int,int)));
    connect(m_geometries, SIGNAL(rowsRemoved(QModelIndex,int,int)),     this, SLOT(geometryChanged()));

    setSelectionModel(new QItemSelectionModel(m_geometries, this));

    setFocusPolicy(Qt::StrongFocus);
    setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    setFocus();

    connect(&m_camera, SIGNAL(projectionChanged()), this, SLOT(restartRender()));
    connect(&m_camera, SIGNAL(viewChanged()), this, SLOT(restartRender()));

    makeCurrent();
    m_shaderProgram.reset(new ShaderProgram());
    connect(m_shaderProgram.get(), SIGNAL(uniformValuesChanged()),
            this, SLOT(restartRender()));
    connect(m_shaderProgram.get(), SIGNAL(shaderChanged()),
            this, SLOT(restartRender()));
    connect(m_shaderProgram.get(), SIGNAL(paramsChanged()),
            this, SLOT(setupShaderParamUI()));

    m_incrementalFrameTimer = new QTimer(this);
    m_incrementalFrameTimer->setSingleShot(false);
    connect(m_incrementalFrameTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
}


View3D::~View3D() { }


void View3D::restartRender()
{
    m_incrementalDraw = false;
    update();
}

void View3D::geometryChanged()
{
    restartRender();
}

/// Initialize all geometry in m_geometries for indices i in [begin,end)
void View3D::initializeGLGeometry(int begin, int end)
{
    const GeometryCollection::GeometryVec& geoms = m_geometries->get();
    for (int i = begin; i < end; ++i)
    {
        if (m_boundingBoxShader->isValid())
        {
            // TODO: build a shader manager for this
            geoms[i]->setShaderId("boundingbox", m_boundingBoxShader->shaderProgram().programId());
            geoms[i]->setShaderId("meshface", m_meshFaceShader->shaderProgram().programId());
            geoms[i]->setShaderId("meshedge", m_meshEdgeShader->shaderProgram().programId());
            geoms[i]->setShaderId("annotation", m_annotationShader->shaderProgram().programId());
            geoms[i]->initializeGL();
        }
    }
}

void View3D::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    initializeGLGeometry(topLeft.row(), bottomRight.row()+1);
    geometryChanged();
}

void View3D::geometryInserted(const QModelIndex& /*unused*/, int firstRow, int lastRow)
{
    // NB: Geometry inserted at indices i in [firstRow,lastRow]  (end inclusive)
    initializeGLGeometry(firstRow, lastRow+1);
    if (m_geometries->rowCount() == (lastRow+1-firstRow) && !m_explicitCursorPos)
    {
        // When loading first geometry (or geometries), centre on it.
        centerOnGeometry(m_geometries->index(0));
    }
    geometryChanged();
}


void View3D::setShaderParamsUIWidget(QWidget* widget)
{
    m_shaderParamsUI = widget;
}


void View3D::setupShaderParamUI()
{
    if (!m_shaderProgram || !m_shaderParamsUI)
        return;
    while (QWidget* child = m_shaderParamsUI->findChild<QWidget*>())
        delete child;
    delete m_shaderParamsUI->layout();
    m_shaderProgram->setupParameterUI(m_shaderParamsUI);
}


void View3D::setSelectionModel(QItemSelectionModel* selectionModel)
{
    assert(selectionModel);
    if (selectionModel->model() != m_geometries)
    {
        assert(0 && "Attempt to set incompatible selection model");
        return;
    }
    if (m_selectionModel)
    {
        disconnect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                   this, SLOT(restartRender()));
    }
    m_selectionModel = selectionModel;
    connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(restartRender()));
}


void View3D::addAnnotation(const QString& label, const QString& text,
                           const Imath::V3d& pos)
{
    GLuint programId = m_annotationShader->shaderProgram().programId();
    auto annotation = std::make_shared<Annotation>(label, programId, text, pos);
    m_annotations.append(annotation);
    restartRender();
}


void View3D::removeAnnotations(const QRegExp& labelRegex)
{
    QVector<std::shared_ptr<Annotation>> annotations;
    foreach (auto annotation, m_annotations)
    {
        if (!labelRegex.exactMatch(annotation->label()))
            annotations.append(annotation);
    }
    m_annotations = annotations;
}


void View3D::setBackground(QColor col)
{
    m_backgroundColor = col;
    restartRender();
}


void View3D::toggleDrawBoundingBoxes()
{
    m_drawBoundingBoxes = !m_drawBoundingBoxes;
    restartRender();
}

void View3D::toggleDrawCursor()
{
    m_drawCursor = !m_drawCursor;
    restartRender();
}
<commit_msg>Bugfix: restart render when annotations are unloaded<commit_after>// Copyright 2015, <NAME> and the other displaz contributors.
// Use of this code is governed by the BSD-style license found in LICENSE.txt

// DEBUG enable OpenGL error checking
// #define GL_CHECK 1

#include "glutil.h"
#include "View3D.h"

#include <QTimer>
#include <QTime>
#include <QKeyEvent>
#include <QLayout>
#include <QItemSelectionModel>
#include <QMessageBox>
#include <QGLFormat>

#include "config.h"
#include "fileloader.h"
#include "QtLogger.h"
#include "PointViewerMainWindow.h"
#include "TriMesh.h"
#include "Shader.h"
#include "tinyformat.h"
#include "util.h"

//------------------------------------------------------------------------------
View3D::View3D(GeometryCollection* geometries, const QGLFormat& format, QWidget *parent)
    : QGLWidget(format, parent),
    m_camera(false, false),
    m_mouseButton(Qt::NoButton),
    m_explicitCursorPos(false),
    m_cursorPos(0),
    m_prevCursorSnap(0),
    m_backgroundColor(60, 50, 50),
    m_drawBoundingBoxes(true),
    m_drawCursor(true),
    m_drawAxes(true),
    m_drawGrid(false),
    m_drawAnnotations(true),
    m_badOpenGL(false),
    m_shaderProgram(),
    m_geometries(geometries),
    m_selectionModel(0),
    m_shaderParamsUI(0),
    m_incrementalFrameTimer(0),
    m_incrementalFramebuffer(),
    m_incrementalDraw(false),
    m_drawAxesBackground(QImage(":/resource/axes.png")),
    m_drawAxesLabelX(QImage(":/resource/x.png")),
    m_drawAxesLabelY(QImage(":/resource/y.png")),
    m_drawAxesLabelZ(QImage(":/resource/z.png")),
    m_cursorVertexArray(0),
    m_axesVertexArray(0),
    m_gridVertexArray(0),
    m_quadVertexArray(0),
    m_quadLabelVertexArray(0),
    m_devicePixelRatio(1.0)
{
    connect(m_geometries, SIGNAL(layoutChanged()),                      this, SLOT(geometryChanged()));
    //connect(m_geometries, SIGNAL(destroyed()),                          this, SLOT(modelDestroyed()));
    connect(m_geometries, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(geometryChanged()));
    connect(m_geometries, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex)));
    connect(m_geometries, SIGNAL(rowsInserted(QModelIndex,int,int)),    this, SLOT(geometryInserted(const QModelIndex&, int,int)));
    connect(m_geometries, SIGNAL(rowsRemoved(QModelIndex,int,int)),     this, SLOT(geometryChanged()));

    setSelectionModel(new QItemSelectionModel(m_geometries, this));

    setFocusPolicy(Qt::StrongFocus);
    setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    setFocus();

    connect(&m_camera, SIGNAL(projectionChanged()), this, SLOT(restartRender()));
    connect(&m_camera, SIGNAL(viewChanged()), this, SLOT(restartRender()));

    makeCurrent();
    m_shaderProgram.reset(new ShaderProgram());
    connect(m_shaderProgram.get(), SIGNAL(uniformValuesChanged()),
            this, SLOT(restartRender()));
    connect(m_shaderProgram.get(), SIGNAL(shaderChanged()),
            this, SLOT(restartRender()));
    connect(m_shaderProgram.get(), SIGNAL(paramsChanged()),
            this, SLOT(setupShaderParamUI()));

    m_incrementalFrameTimer = new QTimer(this);
    m_incrementalFrameTimer->setSingleShot(false);
    connect(m_incrementalFrameTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
}


View3D::~View3D() { }


void View3D::restartRender()
{
    m_incrementalDraw = false;
    update();
}

void View3D::geometryChanged()
{
    restartRender();
}

/// Initialize all geometry in m_geometries for indices i in [begin,end)
void View3D::initializeGLGeometry(int begin, int end)
{
    const GeometryCollection::GeometryVec& geoms = m_geometries->get();
    for (int i = begin; i < end; ++i)
    {
        if (m_boundingBoxShader->isValid())
        {
            // TODO: build a shader manager for this
            geoms[i]->setShaderId("boundingbox", m_boundingBoxShader->shaderProgram().programId());
            geoms[i]->setShaderId("meshface", m_meshFaceShader->shaderProgram().programId());
            geoms[i]->setShaderId("meshedge", m_meshEdgeShader->shaderProgram().programId());
            geoms[i]->setShaderId("annotation", m_annotationShader->shaderProgram().programId());
            geoms[i]->initializeGL();
        }
    }
}

void View3D::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    initializeGLGeometry(topLeft.row(), bottomRight.row()+1);
    geometryChanged();
}

void View3D::geometryInserted(const QModelIndex& /*unused*/, int firstRow, int lastRow)
{
    // NB: Geometry inserted at indices i in [firstRow,lastRow]  (end inclusive)
    initializeGLGeometry(firstRow, lastRow+1);
    if (m_geometries->rowCount() == (lastRow+1-firstRow) && !m_explicitCursorPos)
    {
        // When loading first geometry (or geometries), centre on it.
        centerOnGeometry(m_geometries->index(0));
    }
    geometryChanged();
}


void View3D::setShaderParamsUIWidget(QWidget* widget)
{
    m_shaderParamsUI = widget;
}


void View3D::setupShaderParamUI()
{
    if (!m_shaderProgram || !m_shaderParamsUI)
        return;
    while (QWidget* child = m_shaderParamsUI->findChild<QWidget*>())
        delete child;
    delete m_shaderParamsUI->layout();
    m_shaderProgram->setupParameterUI(m_shaderParamsUI);
}


void View3D::setSelectionModel(QItemSelectionModel* selectionModel)
{
    assert(selectionModel);
    if (selectionModel->model() != m_geometries)
    {
        assert(0 && "Attempt to set incompatible selection model");
        return;
    }
    if (m_selectionModel)
    {
        disconnect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                   this, SLOT(restartRender()));
    }
    m_selectionModel = selectionModel;
    connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(restartRender()));
}


void View3D::addAnnotation(const QString& label, const QString& text,
                           const Imath::V3d& pos)
{
    GLuint programId = m_annotationShader->shaderProgram().programId();
    auto annotation = std::make_shared<Annotation>(label, programId, text, pos);
    m_annotations.append(annotation);
    restartRender();
}


void View3D::removeAnnotations(const QRegExp& labelRegex)
{
    QVector<std::shared_ptr<Annotation>> annotations;
    foreach (auto annotation, m_annotations)
    {
        if (!labelRegex.exactMatch(annotation->label()))
            annotations.append(annotation);
    }
    m_annotations = annotations;
    restartRender();
}


void View3D::setBackground(QColor col)
{
    m_backgroundColor = col;
    restartRender();
}


void View3D::toggleDrawBoundingBoxes()
{
    m_drawBoundingBoxes = !m_drawBoundingBoxes;
    restartRender();
}

void View3D::toggleDrawCursor()
{
    m_drawCursor = !m_drawCursor;
    restartRender();
}

{'fraction_non_alphanumeric': 0.14291983616149795, 'fraction_numerical': 0.006875365710942071, 'mean_word_length': 4.124812593703148, 'pattern_counts': {'":': 8, '<': 29, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '621561', 'n_tokens_mistral': 4397, 'n_tokens_neox': 4307, 'n_words': 739}