/*************************************************************************** * Copyright (c) 2004 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #ifndef GUI_VIEW3DINVENTORVIEWER_H #define GUI_VIEW3DINVENTORVIEWER_H #include #include #include #include #include #include #include #include #include #include #include #include "Namespace.h" #include "Selection.h" #include "View3DInventorSelection.h" #include "Quarter/SoQTQuarterAdaptor.h" class SoTranslation; class SoTransform; class SoText2; class SoSeparator; class SoShapeHints; class SoMaterial; class SoRotationXYZ; class SbSphereSheetProjector; class SoEventCallback; class SbBox2s; class SoVectorizeAction; class QImage; class SoGroup; class SoPickStyle; class NaviCube; class SoClipPlane; namespace Quarter = SIM::Coin3D::Quarter; namespace Gui { class ViewProvider; class SoFCBackgroundGradient; class NavigationStyle; class SoFCUnifiedSelection; class Document; class GLGraphicsItem; class SoShapeScale; class ViewerEventFilter; /** GUI view into a 3D scene provided by View3DInventor * */ class GuiExport View3DInventorViewer : public Quarter::SoQTQuarterAdaptor, public SelectionObserver { using inherited = Quarter::SoQTQuarterAdaptor; Q_OBJECT public: /// Pick modes for picking points in the scene enum SelectionMode { Lasso = 0, /**< Select objects using a lasso. */ Rectangle = 1, /**< Select objects using a rectangle. */ Rubberband = 2, /**< Select objects using a rubberband. */ BoxZoom = 3, /**< Perform a box zoom. */ Clip = 4, /**< Clip objects using a lasso. */ }; /** @name Modus handling of the viewer * Here you can switch several features on/off * and modes of the Viewer */ //@{ enum ViewerMod { ShowCoord=1, /**< Enables the Coordinate system in the corner. */ ShowFPS =2, /**< Enables the Frames Per Second counter. */ SimpleBackground=4,/**< switch to a simple background. */ DisallowRotation=8,/**< switch off the rotation. */ DisallowPanning=16,/**< switch off the panning. */ DisallowZooming=32,/**< switch off the zooming. */ }; //@} /** @name Anti-Aliasing modes of the rendered 3D scene * Specifies Anti-Aliasing (AA) method * - Smoothing enables OpenGL line and vertex smoothing (basically deprecated) * - MSAA is hardware multi sampling (with 2, 4 or 8 passes), a quite common and efficient AA technique */ //@{ enum AntiAliasing { None, Smoothing, MSAA2x, MSAA4x, MSAA8x }; //@} /** @name Render mode */ //@{ enum RenderType { Native, Framebuffer, Image }; //@} /** @name Background */ //@{ enum Background { NoGradient, LinearGradient, RadialGradient }; //@} explicit View3DInventorViewer (QWidget *parent, const QtGLWidget* sharewidget = nullptr); View3DInventorViewer (const QtGLFormat& format, QWidget *parent, const QtGLWidget* sharewidget = nullptr); ~View3DInventorViewer() override; void init(); /// Observer message from the Selection void onSelectionChanged(const SelectionChanges &Reason) override; SoDirectionalLight* getBacklight() const; void setBacklightEnabled(bool on); bool isBacklightEnabled() const; void setSceneGraph (SoNode *root) override; SbBool searchNode(SoNode*) const; void setAnimationEnabled(const SbBool enable); SbBool isAnimationEnabled() const; void setPopupMenuEnabled(const SbBool on); SbBool isPopupMenuEnabled() const; void startAnimating(const SbVec3f& axis, float velocity); void stopAnimating(); SbBool isAnimating() const; void setFeedbackVisibility(const SbBool enable); SbBool isFeedbackVisible() const; void setFeedbackSize(const int size); int getFeedbackSize() const; /// Get the preferred samples from the user settings static int getNumSamples(); void setRenderType(const RenderType type); RenderType getRenderType() const; void renderToFramebuffer(QtGLFramebufferObject*); QImage grabFramebuffer(); void imageFromFramebuffer(int width, int height, int samples, const QColor& bgcolor, QImage& img); void setViewing(SbBool enable) override; virtual void setCursorEnabled(SbBool enable); void addGraphicsItem(GLGraphicsItem*); void removeGraphicsItem(GLGraphicsItem*); std::list getGraphicsItems() const; std::list getGraphicsItemsOfType(const Base::Type&) const; void clearGraphicsItems(); /** @name Handling of view providers */ //@{ /// Checks if the view provider is a top-level object of the scene SbBool hasViewProvider(ViewProvider*) const; /// Checks if the view provider is part of the scene. /// In contrast to hasViewProvider() this method also checks if the view /// provider is a child of another view provider SbBool containsViewProvider(const ViewProvider*) const; /// adds an ViewProvider to the view, e.g. from a feature void addViewProvider(ViewProvider*); /// remove a ViewProvider void removeViewProvider(ViewProvider*); /// get view provider by path ViewProvider* getViewProviderByPath(SoPath*) const; ViewProvider* getViewProviderByPathFromTail(SoPath*) const; /// get all view providers of given type std::vector getViewProvidersOfType(const Base::Type& typeId) const; /// set the ViewProvider in special edit mode void setEditingViewProvider(Gui::ViewProvider* p, int ModNum); /// return whether a view provider is edited SbBool isEditingViewProvider() const; /// reset from edit mode void resetEditingViewProvider(); void setupEditingRoot(SoNode *node=nullptr, const Base::Matrix4D *mat=nullptr); void resetEditingRoot(bool updateLinks=true); void setEditingTransform(const Base::Matrix4D &mat); /** Helper method to get picked entities while editing. * It's in the responsibility of the caller to delete the returned instance. */ SoPickedPoint* getPointOnRay(const SbVec2s& pos, const ViewProvider* vp) const; /** Helper method to get picked entities while editing. * It's in the responsibility of the caller to delete the returned instance. */ SoPickedPoint* getPointOnRay(const SbVec3f& pos, const SbVec3f& dir, const ViewProvider* vp) const; /// display override mode void setOverrideMode(const std::string &mode); void updateOverrideMode(const std::string &mode); std::string getOverrideMode() const {return overrideMode;} //@} /** @name Making pictures */ //@{ /** * Creates an image with width \a w and height \a h of the current scene graph * using a multi-sampling of \a s and exports the rendered scenegraph to an image. */ void savePicture(int w, int h, int s, const QColor&, QImage&) const; void saveGraphic(int pagesize, const QColor&, SoVectorizeAction* va) const; //@} /** * Writes the current scenegraph to an Inventor file, either in ascii or binary. */ bool dumpToFile(SoNode* node, const char* filename, bool binary) const; /** @name Selection methods */ //@{ void startSelection(SelectionMode = Lasso); void abortSelection(); void stopSelection(); bool isSelecting() const; std::vector getGLPolygon(SelectionRole* role=nullptr) const; std::vector getGLPolygon(const std::vector&) const; const std::vector& getPolygon(SelectionRole* role=nullptr) const; void setSelectionEnabled(const SbBool enable); SbBool isSelectionEnabled() const; //@} /// Returns the screen coordinates of the origin of the path's tail object /*! Return value is in floating-point pixels, origin at bottom-left. */ SbVec2f screenCoordsOfPath(SoPath *path) const; /** @name Edit methods */ //@{ void setEditing(SbBool edit); SbBool isEditing() const { return this->editing; } void setEditingCursor (const QCursor& cursor); void setComponentCursor(const QCursor& cursor); void setRedirectToSceneGraph(SbBool redirect) { this->redirected = redirect; } SbBool isRedirectedToSceneGraph() const { return this->redirected; } void setRedirectToSceneGraphEnabled(SbBool enable) { this->allowredir = enable; } SbBool isRedirectToSceneGraphEnabled() const { return this->allowredir; } //@} /** @name Pick actions */ //@{ // calls a PickAction on the scene graph bool pickPoint(const SbVec2s& pos,SbVec3f &point,SbVec3f &norm) const; SoPickedPoint* pickPoint(const SbVec2s& pos) const; const SoPickedPoint* getPickedPoint(SoEventCallback * n) const; SbBool pubSeekToPoint(const SbVec2s& pos); void pubSeekToPoint(const SbVec3f& pos); //@} /** * Set up a callback function \a cb which will be invoked for the given eventtype. * \a userdata will be given as the first argument to the callback function. */ void addEventCallback(SoType eventtype, SoEventCallbackCB * cb, void* userdata = nullptr); /** * Unregister the given callback function \a cb. */ void removeEventCallback(SoType eventtype, SoEventCallbackCB * cb, void* userdata = nullptr); /** @name Clipping plane, near and far plane */ //@{ /** Returns the view direction from the user's eye point in direction to the * viewport which is actually the negative normal of the near plane. * The vector is normalized to length of 1. */ SbVec3f getViewDirection() const; void setViewDirection(SbVec3f); /** Returns the up direction */ SbVec3f getUpDirection() const; /** Returns the orientation of the camera. */ SbRotation getCameraOrientation() const; /** Returns the 3d point on the focal plane to the given 2d point. */ SbVec3f getPointOnFocalPlane(const SbVec2s&) const; /** Returns the 2d coordinates on the viewport to the given 3d point. */ SbVec2s getPointOnViewport(const SbVec3f&) const; /** Converts Inventor coordinates into Qt coordinates. * The conversion takes the device pixel ratio into account. */ QPoint toQPoint(const SbVec2s&) const; /** Converts Qt coordinates into Inventor coordinates. * The conversion takes the device pixel ratio into account. */ SbVec2s fromQPoint(const QPoint&) const; /** Returns the near plane represented by its normal and base point. */ void getNearPlane(SbVec3f& rcPt, SbVec3f& rcNormal) const; /** Returns the far plane represented by its normal and base point. */ void getFarPlane(SbVec3f& rcPt, SbVec3f& rcNormal) const; /** Adds or remove a manipulator to/from the scenegraph. */ void toggleClippingPlane(int toggle=-1, bool beforeEditing=false, bool noManip=false, const Base::Placement &pla = Base::Placement()); /** Checks whether a clipping plane is set or not. */ bool hasClippingPlane() const; /** Project the given normalized 2d point onto the near plane */ SbVec3f projectOnNearPlane(const SbVec2f&) const; /** Project the given normalized 2d point onto the far plane */ SbVec3f projectOnFarPlane(const SbVec2f&) const; /** Project the given 2d point to a line */ void projectPointToLine(const SbVec2s&, SbVec3f& pt1, SbVec3f& pt2) const; /** Get the normalized position of the 2d point. */ SbVec2f getNormalizedPosition(const SbVec2s&) const; //@} /** @name Dimension controls * the "turn*" functions are wired up to parameter groups through view3dinventor. * don't call them directly. instead set the parameter groups. * @see TaskDimension */ //@{ void turnAllDimensionsOn(); void turnAllDimensionsOff(); void turn3dDimensionsOn(); void turn3dDimensionsOff(); void turnDeltaDimensionsOn(); void turnDeltaDimensionsOff(); void eraseAllDimensions(); void addDimension3d(SoNode *node); void addDimensionDelta(SoNode *node); //@} /** * Set the camera's orientation. If isAnimationEnabled() returns * \a true the reorientation is animated, otherwise its directly * set. */ void setCameraOrientation(const SbRotation& rot, SbBool moveTocenter=false); void setCameraType(SoType t) override; void moveCameraTo(const SbRotation& rot, const SbVec3f& pos, int steps, int ms); /** * Zooms the viewport to the size of the bounding box. */ void boxZoom(const SbBox2s&); /** * Reposition the current camera so we can see the complete scene. */ void viewAll() override; void viewAll(float factor); /// Breaks out a VR window for a Rift void viewVR(); /** * Returns the bounding box of the scene graph. */ SbBox3f getBoundingBox() const; /** * Reposition the current camera so we can see all selected objects * of the scene. Therefore we search for all SOFCSelection nodes, if * none of them is selected nothing happens. */ void viewSelection(); void setGradientBackground(Background); Background getGradientBackground() const; void setGradientBackgroundColor(const SbColor& fromColor, const SbColor& toColor); void setGradientBackgroundColor(const SbColor& fromColor, const SbColor& toColor, const SbColor& midColor); void setNavigationType(Base::Type); void setAxisCross(bool b); bool hasAxisCross(); void showRotationCenter(bool show); void setEnabledFPSCounter(bool b); void setEnabledNaviCube(bool b); bool isEnabledNaviCube() const; void setNaviCubeCorner(int); NaviCube* getNaviCube() const; void setEnabledVBO(bool b); bool isEnabledVBO() const; void setRenderCache(int); void getDimensions(float& fHeight, float& fWidth) const; float getMaxDimension() const; SbVec3f getCenterPointOnFocalPlane() const; NavigationStyle* navigationStyle() const; void setDocument(Gui::Document *pcDocument); Gui::Document* getDocument(); virtual PyObject *getPyObject(); protected: GLenum getInternalTextureFormat() const; void renderScene(); void renderFramebuffer(); void renderGLImage(); void animatedViewAll(int steps, int ms); void actualRedraw() override; void setSeekMode(SbBool enable) override; void afterRealizeHook() override; bool processSoEvent(const SoEvent * ev) override; void dropEvent (QDropEvent * e) override; void dragEnterEvent (QDragEnterEvent * e) override; void dragMoveEvent(QDragMoveEvent *e) override; void dragLeaveEvent(QDragLeaveEvent *e) override; SbBool processSoEventBase(const SoEvent * const ev); void printDimension(); void selectAll(); private: static void setViewportCB(void * userdata, SoAction * action); static void clearBufferCB(void * userdata, SoAction * action); static void setGLWidgetCB(void * userdata, SoAction * action); static void handleEventCB(void * userdata, SoEventCallback * n); static void interactionStartCB(void * data, Quarter::SoQTQuarterAdaptor * viewer); static void interactionFinishCB(void * data, Quarter::SoQTQuarterAdaptor * viewer); static void interactionLoggerCB(void * ud, SoAction* action); private: static void selectCB(void * closure, SoPath * p); static void deselectCB(void * closure, SoPath * p); static SoPath * pickFilterCB(void * data, const SoPickedPoint * pick); void initialize(); void drawAxisCross(); static void drawArrow(); void drawSingleBackground(const QColor&); void setCursorRepresentation(int mode); void aboutToDestroyGLContext() override; void createStandardCursors(double); private: NaviCube* naviCube; std::set _ViewProviderSet; std::map _ViewProviderMap; std::list graphicsItems; ViewProvider* editViewProvider; SoFCBackgroundGradient *pcBackGround; SoSeparator * backgroundroot; SoSeparator * foregroundroot; SoDirectionalLight* backlight; // Scene graph root SoSeparator * pcViewProviderRoot; // Child group in the scene graph that contains view providers related to the physical object SoGroup* objectGroup; std::unique_ptr inventorSelection; SoSeparator * pcEditingRoot; SoTransform * pcEditingTransform; bool restoreEditingRoot; SoEventCallback* pEventCallback; NavigationStyle* navigation; SoFCUnifiedSelection* selectionRoot; SoClipPlane *pcClipPlane; RenderType renderType; QtGLFramebufferObject* framebuffer; QImage glImage; SbBool shading; SoSwitch *dimensionRoot; // small axis cross in the corner SbBool axiscrossEnabled; int axiscrossSize; // big one in the middle SoShapeScale* axisCross; SoGroup* axisGroup; SoGroup* rotationCenterGroup; //stuff needed to draw the fps counter bool fpsEnabled; bool vboEnabled; SbBool naviCubeEnabled; SbBool editing; QCursor editCursor, zoomCursor, panCursor, spinCursor; SbBool redirected; SbBool allowredir; std::string overrideMode; Gui::Document* guiDocument = nullptr; ViewerEventFilter* viewerEventFilter; PyObject *_viewerPy; // friends friend class NavigationStyle; friend class GLPainter; friend class ViewerEventFilter; }; } // namespace Gui #endif // GUI_VIEW3DINVENTORVIEWER_H