cgal/Lab/demo/Lab/Scene.h

376 lines
13 KiB
C++

//! \file Scene.h
#ifndef SCENE_H
#define SCENE_H
#include "config.h"
#include "Scene_config.h"
#include <CGAL/Three/Scene_interface.h>
#include <CGAL/Three/Scene_draw_interface.h>
#include <CGAL/Three/Viewer_config.h>
#include <QtOpenGLWidgets>
#include <QStandardItemModel>
#include <QString>
#include <QColor>
#include <QList>
#include <QVector>
#include <QMap>
#include <QItemDelegate>
#include <QPixmap>
#include <QItemSelection>
#include <CGAL/Qt/qglviewer.h>
#include <QDebug>
#include <iostream>
#include <cmath>
#include <variant>
#include <CGAL/Three/Scene_group_item.h>
class QEvent;
class QMouseEvent;
class QOpenGLFramebufferObject;
namespace CGAL { namespace Three{ class Viewer_interface;}}
//! This class is not supposed to be used by Plugins, but sometimes you may need access to
//! peculiar signals or slots.
class SCENE_EXPORT Scene :
public QStandardItemModel, public CGAL::Three::Scene_interface, public CGAL::Three::Scene_draw_interface
{
Q_OBJECT
Q_PROPERTY(int numberOfEntries READ numberOfEntries)
friend class SceneDelegate;
public:
QList<QModelIndex> getModelIndexFromId(int id) const;
int getIdFromModelIndex(QModelIndex modelId) const;
enum Columns { NameColumn = 0,
ColorColumn,
RenderingModeColumn,
VisibleColumn,
ABColumn,
LastColumn = ABColumn,
NumberOfColumns = LastColumn + 1};
Scene(QObject* parent);
~Scene();
int addItem(CGAL::Three::Scene_item* item) override;
void addChild(Scene_item* item) override;
Q_INVOKABLE void changeGroup(CGAL::Three::Scene_item* item, CGAL::Three::Scene_group_item* target_group) override;
CGAL::Three::Scene_item* replaceItem(int index, CGAL::Three::Scene_item* item, bool emit_item_about_to_be_destroyed = false) override;
Q_INVOKABLE int erase(int) override;
int erase(QList<int>) override;
int duplicate(int index) override;
// Accessors (getters)
int numberOfEntries() const override;
// returns the list of items.
const QList<CGAL::Three::Scene_item*>& entries() const { return m_entries; }
Q_INVOKABLE CGAL::Three::Scene_item* item(int) const override;
int item_id(CGAL::Three::Scene_item*) const override;
//! \todo Replace Index based selection functionality with those
//! functions.
///@{
CGAL::Three::Scene_item* selectedItem() const;
QList<CGAL::Three::Scene_item*> selectedItems() const;
QList<CGAL::Three::Scene_item*> selectionA() const;
QList<CGAL::Three::Scene_item*> selectionB() const;
///@}
int mainSelectionIndex() const override;
QList<int> selectionIndices() const override;
int selectionAindex() const override;
int selectionBindex() const override;
void initializeGL(CGAL::Three::Viewer_interface*) override;
void initGL(CGAL::Three::Viewer_interface* viewer);
void setPickedPixel(const QPoint &p) override {picked_pixel = p;}
void draw(CGAL::Three::Viewer_interface*) override;
void drawWithNames(CGAL::Three::Viewer_interface*) override;
bool keyPressEvent(QKeyEvent* e) override;
void printPrimitiveId(QPoint point,
CGAL::Three::Viewer_interface*) override;
void printVertexIds() override;
void printEdgeIds() override;
void printFaceIds() override;
void printAllIds() override;
//!Re-computes the primitiveIds for `item`
void updatePrimitiveIds(Scene_item *item) override;
bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) override;
Bbox bbox() const override;
void computeBbox();
double len_diagonal() const override
{
Bbox box = bbox();
double dx = box.xmax() - box.xmin();
double dy = box.ymax() - box.ymin();
double dz = box.zmax() - box.zmin();
return std::sqrt(dx*dx + dy*dy + dz*dz);
}
//Moves a name up in the Geometric Objects view
void moveRowUp();
//Moves a name down in the Geometric Objects view
void moveRowDown();
// QStandardItemModel functions
//Defines the behavior when a name is drag-and-dropped in the Geometric Objects view
bool dropMimeData(const QMimeData *, Qt::DropAction, int, int,
const QModelIndex &parent) override;
//Contains the text and icons of an item in the Geometric Objects view
QVariant data ( const QModelIndex & index,
int role = ::Qt::DisplayRole ) const override;
//@returns the type of data corresponding to the role.
QVariant headerData ( int section, ::Qt::Orientation orientation,
int role = ::Qt::DisplayRole ) const override;
//@returns the flags for the item at the target index.
::Qt::ItemFlags flags ( const QModelIndex & index ) const override;
// Sets the column data for the target index. Returns false if index is not valid and
// if role is not EditRole.
bool setData(const QModelIndex &index, const QVariant &value,
int role) override;
//Returns a list of all the items.
QList<CGAL::Three::Scene_item*> item_entries() const ;
// auxiliary public function for QMainWindow
//Selects the row at index i in the sceneView.
QItemSelection createSelection(int i);
//same for lists
QItemSelection createSelection(QList<int> is);
//Selects all the rows in the sceneView.
QItemSelection createSelectionAll();
//Connects specific signals to a group when it is added and
// gives a reference to the scene to it.
void addGroup(Scene_group_item* group);
void zoomToPosition(QPoint point,
CGAL::Three::Viewer_interface*) override;
void setUpdatesEnabled(bool b) override
{
dont_emit_changes = !b;
if(!b)
allItemsChanged();
}
public Q_SLOTS:
//!Specifies a group as Expanded for the Geometric Objects view
void setExpanded(QModelIndex);
//!Specifies a group as Collapsed for the Geometric Objects view
void setCollapsed(QModelIndex);
//!Transmits a CGAL::Three::Scene_item::itemChanged() signal to the scene.
void itemChanged();
void itemChanged(int i) override;
void itemChanged(CGAL::Three::Scene_item*) override;
void allItemsChanged() override;
//!Transmits a CGAL::Three::Scene_item::itemVisibilityChanged() signal to the scene.
void itemVisibilityChanged();
void itemVisibilityChanged(CGAL::Three::Scene_item*) override;
//!Removes `item` from all the groups of the scene.
void remove_item_from_groups(CGAL::Three::Scene_item* item);
//!Re-organizes the sceneView.
void redraw_model();
//! Sets the selected item to the target index. Emits a signal to notify
//! that a new item is now selected, but does not update the Geometric Objects view.
//! Used in intern and by the mainwindow
void setSelectedItemIndex(int i)
{
selected_item = i;
Q_EMIT itemIndexSelected(i);
}
void setSelectedItem(int i ) override
{
selected_item = i;
Q_EMIT selectionChanged(i);
}
//! Does the same as setSelectedItem(int)
void setSelectedItem(CGAL::Three::Scene_item* item_to_select)
{
int i=0;
for(CGAL::Three::Scene_item* item : m_entries)
{
if (item==item_to_select)
{
setSelectedItem(i);
break;
}
++i;
}
}
//! Sets the target list of indices as the selected indices.
const QList<int>& setSelectedItemIndices(QList<int> l,
const bool do_emit = true)
{
for(int i :l)
{
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item(i));
if(group)
{
QList<int> list;
for(Item_id id : group->getChildrenForSelection())
list << id;
l << setSelectedItemIndices(list, false /*do not emit*/);
}
}
selected_items_list = l;
if(do_emit)
Q_EMIT itemIndicesSelected(selected_items_list);
return selected_items_list;
}
//! Sets the target list of indices as the selected indices.
const QList<int>& setSelectedItemList(QList<int> l,
const bool do_emit = true)
{
for(int i :l)
{
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item(i));
if(group)
{
QList<int> list;
for(Item_id id : group->getChildrenForSelection())
list << id;
l << setSelectedItemList(list, false /*do not emit*/);
}
}
selected_items_list = l;
if(do_emit)
Q_EMIT selectionChanged(selected_items_list);
return selected_items_list;
}
// Accessors (setters)
//!Sets the item at index i to visible or not visible.
void setItemVisible(int, bool b);
//!Sets the item_A as the item at index i .
void setItemA(int i);
//!Sets the item_B as the item at index i .
void setItemB(int i);
void newViewer(CGAL::Three::Viewer_interface*);
void removeViewer(CGAL::Three::Viewer_interface*);
void enableVisibilityRecentering(bool);
Q_SIGNALS:
//generated automatically by moc
//!Is emitted when the ids of the items are changed.
void indexErased(Scene_interface::Item_id id);
//! Emit this to mark `modelindex` as selected in the Geometric Objects view.
void itemPicked(const QModelIndex& modelindex);
//! Is emitted when a new item is added to the scene.
void newItem(int);
//! Emit this to re-compute the viewer's Bbox;
//! If `b` is true, the scene will be recentered
void updated_bbox(bool b);
//! Emit this to redraw the scene.
void updated();
//! Is emitted when `item` is erased.
void itemAboutToBeDestroyed(CGAL::Three::Scene_item* item);
//! Is emitted when the selection ray is changed.
void selectionRay(double, double, double, double, double, double);
//! Used to update the selected item in the Geometric Objects view.
void selectionChanged(int i);
//! Used to update the selected items in the Geometric Objects view.
void selectionChanged(QList<int> is);
//! Used when you don't want to update the selectedItem in the Geometric Objects view.
void itemIndexSelected(int i);
//! Used when you don't want to update the selectedItem in the Geometric Objects view.
void itemIndicesSelected(QList<int> is);
//! Emit this to reset the collapsed state of all groups after the Geometric Objects view has been redrawn.
void restoreCollapsedState();
//! Is emitted when draw() is finished.
void drawFinished();
private Q_SLOTS:
// Casts a selection ray and calls the item function select.
void adjustIds(Scene_interface::Item_id removed_id);
void setSelectionRay(double, double, double, double, double, double);
void callDraw();
void s_itemAboutToBeDestroyed(CGAL::Three::Scene_item *);
private:
/*! Calls the drawing functions of each visible item according
* to its current renderingMode. If with_names is true, uses
* the OpenGL mode GL_WITH_NAMES, essentially used for the picking.*/
void draw_aux(bool with_names, CGAL::Three::Viewer_interface*);
bool has_alpha();
void renderScene(const QList<Scene_interface::Item_id > &items,
CGAL::Three::Viewer_interface* viewer, QMap<float, int> &picked_item_IDs, bool with_names,
int pass, bool writing_depth,
QOpenGLFramebufferObject* fbo);
void renderWireScene(const QList<Scene_interface::Item_id> &items,
Viewer_interface *viewer, QMap<float, int> &picked_item_IDs, bool with_names);
void renderPointScene(const QList<Scene_interface::Item_id> &items,
Viewer_interface *viewer,
QMap<float, int>& picked_item_IDs,
bool with_names);
// Re-draw the hierarchy of the view.
void organize_items(CGAL::Three::Scene_item* item, QStandardItem *root, int loop);
// List of Scene_items.
typedef QList<CGAL::Three::Scene_item*> Entries;
//List containing all the scene_items.
Entries m_entries;
QList<Item_id> m_groups; //used to optimize createSelectionAll()
QList<Item_id> children;
// Index of the currently selected item.
int selected_item;
//List of indices of the currently selected items.
QList<int> selected_items_list;
//Index of the item_A.
int item_A;
//Index of the item_B.
int item_B;
bool picked;
QPoint picked_pixel;
bool gl_init;
QMap<QModelIndex, int> index_map;
float points[18];
float uvs[12];
QOpenGLShaderProgram program;
QMap<CGAL::Three::Viewer_interface*, QOpenGLVertexArrayObject*> vaos;
mutable QOpenGLBuffer vbo[2];
Bbox last_bbox;
//the scene will ignore the itemChanged() signals while this is true.
bool dont_emit_changes;
bool visibility_recentering_enabled;
bool sort_lists(QVector<QList<int> >&sorted_lists, bool up);
}; // end class Scene
class QAbstractProxyModel;
//\brief The SceneDelegate class
//Handles the columns of the sceneView
class SCENE_EXPORT SceneDelegate : public QItemDelegate
{
public:
SceneDelegate(QObject * parent = nullptr)
: QItemDelegate(parent),
checkOnPixmap(":/cgal/icons/check-on.png"),
checkOffPixmap(":/cgal/icons/check-off.png")
{
}
// Handles the clicks on the sceneView
bool editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index);
// Draws the content of the sceneView
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setProxy(QAbstractProxyModel* p_proxy){
proxy = p_proxy;
}
void setScene(Scene* p_scene){
scene = p_scene;
}
private:
QPixmap checkOnPixmap;
QPixmap checkOffPixmap;
QAbstractProxyModel *proxy;
Scene *scene;
mutable int size;
}; // end class SceneDelegate
#endif // SCENE_H