mirror of https://github.com/CGAL/cgal
376 lines
13 KiB
C++
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
|