Add a way to ignore dataChanged() calls of the Scene to optimize big selection manipulation.

Use it to make the visibility change of a selection of items instant instead of possibly very long.
This commit is contained in:
Maxime Gimeno 2018-11-14 11:48:03 +01:00
parent 66e6a5575c
commit 66961f56f6
5 changed files with 89 additions and 44 deletions

View File

@ -134,6 +134,7 @@ MainWindow::~MainWindow()
MainWindow::MainWindow(bool verbose, QWidget* parent) MainWindow::MainWindow(bool verbose, QWidget* parent)
: CGAL::Qt::DemosMainWindow(parent) : CGAL::Qt::DemosMainWindow(parent)
{ {
bbox_need_update = true;
ui = new Ui::MainWindow; ui = new Ui::MainWindow;
ui->setupUi(this); ui->setupUi(this);
menuBar()->setNativeMenuBar(false); menuBar()->setNativeMenuBar(false);
@ -207,7 +208,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent)
this, SLOT(removeManipulatedFrame(CGAL::Three::Scene_item*))); this, SLOT(removeManipulatedFrame(CGAL::Three::Scene_item*)));
connect(scene, SIGNAL(updated_bbox(bool)), connect(scene, SIGNAL(updated_bbox(bool)),
this, SLOT(updateViewerBBox(bool))); this, SLOT(invalidate_bbox()));
connect(scene, SIGNAL(selectionChanged(int)), connect(scene, SIGNAL(selectionChanged(int)),
this, SLOT(selectSceneItem(int))); this, SLOT(selectSceneItem(int)));
@ -863,50 +864,54 @@ void MainWindow::error(QString text) {
void MainWindow::updateViewerBBox(bool recenter = true) void MainWindow::updateViewerBBox(bool recenter = true)
{ {
const Scene::Bbox bbox = scene->bbox(); if(bbox_need_update)
{
const Scene::Bbox bbox = scene->bbox();
CGAL::qglviewer::Vec center = viewer->camera()->pivotPoint(); CGAL::qglviewer::Vec center = viewer->camera()->pivotPoint();
const double xmin = bbox.xmin(); const double xmin = bbox.xmin();
const double ymin = bbox.ymin(); const double ymin = bbox.ymin();
const double zmin = bbox.zmin(); const double zmin = bbox.zmin();
const double xmax = bbox.xmax(); const double xmax = bbox.xmax();
const double ymax = bbox.ymax(); const double ymax = bbox.ymax();
const double zmax = bbox.zmax(); const double zmax = bbox.zmax();
CGAL::qglviewer::Vec CGAL::qglviewer::Vec
vec_min(xmin, ymin, zmin), vec_min(xmin, ymin, zmin),
vec_max(xmax, ymax, zmax), vec_max(xmax, ymax, zmax),
bbox_center((xmin+xmax)/2, (ymin+ymax)/2, (zmin+zmax)/2); bbox_center((xmin+xmax)/2, (ymin+ymax)/2, (zmin+zmax)/2);
CGAL::qglviewer::Vec offset(0,0,0); CGAL::qglviewer::Vec offset(0,0,0);
double l_dist = (std::max)((std::abs)(bbox_center.x - viewer->offset().x), double l_dist = (std::max)((std::abs)(bbox_center.x - viewer->offset().x),
(std::max)((std::abs)(bbox_center.y - viewer->offset().y), (std::max)((std::abs)(bbox_center.y - viewer->offset().y),
(std::abs)(bbox_center.z - viewer->offset().z))); (std::abs)(bbox_center.z - viewer->offset().z)));
if((std::log2)(l_dist) > 13.0 ) if((std::log2)(l_dist) > 13.0 )
for(int i=0; i<3; ++i) for(int i=0; i<3; ++i)
{
offset[i] = -bbox_center[i];
}
if(offset != viewer->offset())
{ {
offset[i] = -bbox_center[i]; viewer->setOffset(offset);
for(int i=0; i<scene->numberOfEntries(); ++i)
{
scene->item(i)->invalidateOpenGLBuffers();
scene->item(i)->itemChanged();
}
} }
if(offset != viewer->offset())
{
viewer->setOffset(offset); viewer->setSceneBoundingBox(vec_min,
for(int i=0; i<scene->numberOfEntries(); ++i) vec_max);
if(recenter)
{ {
scene->item(i)->invalidateOpenGLBuffers(); viewer->camera()->showEntireScene();
scene->item(i)->itemChanged();
} }
} else
{
viewer->camera()->setPivotPoint(center);
viewer->setSceneBoundingBox(vec_min, }
vec_max); bbox_need_update = false;
if(recenter)
{
viewer->camera()->showEntireScene();
}
else
{
viewer->camera()->setPivotPoint(center);
} }
} }
@ -1644,6 +1649,7 @@ void MainWindow::on_actionLoad_triggered()
scene->item(scene->numberOfEntries()-1)->setColor(colors_[++nb_item]); scene->item(scene->numberOfEntries()-1)->setColor(colors_[++nb_item]);
} }
} }
updateViewerBBox(true);
} }
void MainWindow::on_actionSaveAs_triggered() void MainWindow::on_actionSaveAs_triggered()
@ -1817,13 +1823,17 @@ void MainWindow::on_actionDuplicate_triggered()
void MainWindow::on_actionShowHide_triggered() void MainWindow::on_actionShowHide_triggered()
{ {
scene->cutDataUpdate(true);
Q_FOREACH(QModelIndex index, sceneView->selectionModel()->selectedRows()) Q_FOREACH(QModelIndex index, sceneView->selectionModel()->selectedRows())
{ {
int i = scene->getIdFromModelIndex(proxyModel->mapToSource(index)); int i = scene->getIdFromModelIndex(proxyModel->mapToSource(index));
CGAL::Three::Scene_item* item = scene->item(i); CGAL::Three::Scene_item* item = scene->item(i);
item->setVisible(!item->visible()); item->setVisible(!item->visible());
scene->itemChanged(i); item->redraw();
} }
scene->cutDataUpdate(false);
scene->allItemsChanged();
updateViewerBBox(false);
} }
void MainWindow::on_actionSetPolyhedronA_triggered() void MainWindow::on_actionSetPolyhedronA_triggered()
@ -2407,3 +2417,8 @@ void MainWindow::setDefaultSaveDir()
QSettings settings; QSettings settings;
settings.setValue("default_saveas_dir", def_save_dir); settings.setValue("default_saveas_dir", def_save_dir);
} }
void MainWindow::invalidate_bbox()
{
bbox_need_update = true;
}

View File

@ -436,11 +436,13 @@ public:
public Q_SLOTS: public Q_SLOTS:
void toggleFullScreen(); void toggleFullScreen();
void setDefaultSaveDir(); void setDefaultSaveDir();
void invalidate_bbox();
private: private:
QList<QDockWidget *> visibleDockWidgets; QList<QDockWidget *> visibleDockWidgets;
QLineEdit operationSearchBar; QLineEdit operationSearchBar;
QWidgetAction* searchAction; QWidgetAction* searchAction;
QString def_save_dir; QString def_save_dir;
bool bbox_need_update;
}; };
#endif // ifndef MAINWINDOW_H #endif // ifndef MAINWINDOW_H

View File

@ -42,6 +42,7 @@ Scene::Scene(QObject* parent)
this, SLOT(adjustIds(Scene_interface::Item_id))); this, SLOT(adjustIds(Scene_interface::Item_id)));
picked = false; picked = false;
gl_init = false; gl_init = false;
dont_emit_changes = false;
} }
Scene::Item_id Scene::Item_id
@ -1175,6 +1176,8 @@ void Scene::itemChanged()
void Scene::itemChanged(Item_id i) void Scene::itemChanged(Item_id i)
{ {
if(dont_emit_changes)
return;
if(i < 0 || i >= m_entries.size()) if(i < 0 || i >= m_entries.size())
return; return;
@ -1182,7 +1185,14 @@ void Scene::itemChanged(Item_id i)
this->createIndex(i, LastColumn)); this->createIndex(i, LastColumn));
} }
void Scene::itemChanged(CGAL::Three::Scene_item*) void Scene::itemChanged(CGAL::Three::Scene_item*item )
{
if(dont_emit_changes)
return;
itemChanged(item_id(item));
}
void Scene::allItemsChanged()
{ {
Q_EMIT dataChanged(this->createIndex(0, 0), Q_EMIT dataChanged(this->createIndex(0, 0),
this->createIndex(m_entries.size() - 1, LastColumn)); this->createIndex(m_entries.size() - 1, LastColumn));

View File

@ -136,7 +136,11 @@ public:
void zoomToPosition(QPoint point, void zoomToPosition(QPoint point,
CGAL::Three::Viewer_interface*) Q_DECL_OVERRIDE; CGAL::Three::Viewer_interface*) Q_DECL_OVERRIDE;
void cutDataUpdate(bool b) Q_DECL_OVERRIDE
{
dont_emit_changes = b;
}
public Q_SLOTS: public Q_SLOTS:
//!Specifies a group as Expanded for the Geometric Objects view //!Specifies a group as Expanded for the Geometric Objects view
void setExpanded(QModelIndex); void setExpanded(QModelIndex);
@ -146,6 +150,7 @@ public Q_SLOTS:
void itemChanged(); void itemChanged();
void itemChanged(int i) Q_DECL_OVERRIDE; void itemChanged(int i) Q_DECL_OVERRIDE;
void itemChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE; void itemChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE;
void allItemsChanged() Q_DECL_OVERRIDE;
//!Transmits a CGAL::Three::Scene_item::itemVisibilityChanged() signal to the scene. //!Transmits a CGAL::Three::Scene_item::itemVisibilityChanged() signal to the scene.
void itemVisibilityChanged(); void itemVisibilityChanged();
void itemVisibilityChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE; void itemVisibilityChanged(CGAL::Three::Scene_item*) Q_DECL_OVERRIDE;
@ -280,6 +285,8 @@ private:
QOpenGLShaderProgram program; QOpenGLShaderProgram program;
QOpenGLVertexArrayObject* vao; QOpenGLVertexArrayObject* vao;
mutable QOpenGLBuffer vbo[2]; mutable QOpenGLBuffer vbo[2];
//the scene will ignore the itemChanged() signals while this is true.
bool dont_emit_changes;
}; // end class Scene }; // end class Scene

View File

@ -144,11 +144,22 @@ public:
//! Updates the information about `item` in the //! Updates the information about `item` in the
//! Geometric Objects list and redraws the scene. //! Geometric Objects list and redraws the scene.
virtual void itemChanged(CGAL::Three::Scene_item* item) = 0; virtual void itemChanged(CGAL::Three::Scene_item* item) = 0;
//!
//! \brief Updates all the items in the SceneView.
//!
virtual void allItemsChanged() = 0;
//! Re computes the scene Bbox without recentering it. //! Re computes the scene Bbox without recentering it.
virtual void itemVisibilityChanged(CGAL::Three::Scene_item*) = 0; virtual void itemVisibilityChanged(CGAL::Three::Scene_item*) = 0;
//! Clears the current selection then sets the selected item to the target index. //! Clears the current selection then sets the selected item to the target index.
//! Used to update the selection in the Geometric Objects view. //! Used to update the selection in the Geometric Objects view.
virtual void setSelectedItem(Item_id) = 0; virtual void setSelectedItem(Item_id) = 0;
//! \brief ignore data updating.
//!
//! This will ignore all the individual calls to `itemChanged()` until
//! `cutDataUpdate()` is called whith `b` being `false`.
//! Activate this when you know you will call allItemsChanged() after a loop.
//!
virtual void cutDataUpdate(bool b) =0;
}; // end interface Scene_interface }; // end interface Scene_interface
} }
} }