/*************************************************************************** * Copyright (c) 2005 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_SOFCUNIFIEDSELECTION_H #define GUI_SOFCUNIFIEDSELECTION_H #include #include #include #include #include #include #include #include "View3DInventorViewer.h" #include "SoFCSelectionContext.h" #include #include #include class SoFullPath; class SoPickedPoint; class SoDetail; namespace Gui { class Document; class ViewProviderDocumentObject; /** Unified Selection node * This is the new selection node for the 3D Viewer which will * gradually remove all the low level selection nodes in the view * provider. The handling of the highlighting and the selection will * be unified here. * \author Jürgen Riegel */ class GuiExport SoFCUnifiedSelection : public SoSeparator { typedef SoSeparator inherited; SO_NODE_HEADER(Gui::SoFCUnifiedSelection); public: static void initClass(void); static void finish(void); SoFCUnifiedSelection(void); void applySettings(); enum HighlightModes { AUTO, ON, OFF }; const char* getFileFormatName(void) const; void write(SoWriteAction * action); SoSFColor colorHighlight; SoSFColor colorSelection; SoSFEnum highlightMode; SoSFEnum selectionMode; SoSFBool selectionRole; SoSFBool useNewSelection; virtual void doAction(SoAction *action); //virtual void GLRender(SoGLRenderAction * action); virtual void handleEvent(SoHandleEventAction * action); virtual void GLRenderBelowPath(SoGLRenderAction * action); //virtual void GLRenderInPath(SoGLRenderAction * action); //static void turnOffCurrentHighlight(SoGLRenderAction * action); static bool hasHighlight(); friend class View3DInventorViewer; protected: virtual ~SoFCUnifiedSelection(); //virtual void redrawHighlighted(SoAction * act, SbBool flag); //virtual SbBool readInstance(SoInput * in, unsigned short flags); private: //static void turnoffcurrent(SoAction * action); //void setOverride(SoGLRenderAction * action); //SbBool isHighlighted(SoAction *action); //SbBool preRender(SoGLRenderAction *act, GLint &oldDepthFunc); static int getPriority(const SoPickedPoint* p); struct PickedInfo { const SoPickedPoint *pp; ViewProviderDocumentObject *vpd; std::string element; PickedInfo():pp(0),vpd(0) {} }; bool setHighlight(const PickedInfo &); bool setHighlight(SoFullPath *path, const SoDetail *det, ViewProviderDocumentObject *vpd, const char *element, float x, float y, float z); bool setSelection(const std::vector &, bool ctrlDown=false); std::vector getPickedList(SoHandleEventAction* action, bool singlePick) const; Gui::Document *pcDocument; static SoFullPath * currenthighlight; SoFullPath * detailPath; SbBool setPreSelection; // -1 = not handled, 0 = not selected, 1 = selected int32_t preSelection; SoColorPacker colorpacker; }; class GuiExport SoFCPathAnnotation : public SoSeparator { typedef SoSeparator inherited; SO_NODE_HEADER(Gui::SoFCPathAnnotation); public: static void initClass(void); static void finish(void); SoFCPathAnnotation(); void setPath(SoPath *); SoPath *getPath() {return path;} void setDetail(SoDetail *d); SoDetail *getDetail() {return det;} virtual void GLRenderBelowPath(SoGLRenderAction * action); virtual void GLRender(SoGLRenderAction * action); virtual void GLRenderInPath(SoGLRenderAction * action); virtual void getBoundingBox(SoGetBoundingBoxAction * action); protected: virtual ~SoFCPathAnnotation(); protected: SoPath *path; SoTempPath *tmpPath; SoDetail *det; }; class GuiExport SoFCSeparator : public SoSeparator { typedef SoSeparator inherited; SO_NODE_HEADER(Gui::SoFCSeparator); public: static void initClass(void); static void finish(void); SoFCSeparator(bool trackCacheMode=true); virtual void GLRenderBelowPath(SoGLRenderAction * action); static void setCacheMode(CacheEnabled mode) { CacheMode = mode; } static CacheEnabled getCacheMode() { return CacheMode; } private: bool trackCacheMode; static CacheEnabled CacheMode; }; class GuiExport SoFCSelectionRoot : public SoFCSeparator { typedef SoFCSeparator inherited; SO_NODE_HEADER(Gui::SoFCSelectionRoot); public: static void initClass(void); static void finish(void); SoFCSelectionRoot(bool trackCacheMode=false); virtual void GLRenderBelowPath(SoGLRenderAction * action); virtual void GLRenderInPath(SoGLRenderAction * action); virtual void doAction(SoAction *action); virtual void pick(SoPickAction * action); virtual void rayPick(SoRayPickAction * action); virtual void handleEvent(SoHandleEventAction * action); virtual void search(SoSearchAction * action); virtual void getPrimitiveCount(SoGetPrimitiveCountAction * action); virtual void getBoundingBox(SoGetBoundingBoxAction * action); virtual void getMatrix(SoGetMatrixAction * action); virtual void callback(SoCallbackAction *action); template static std::shared_ptr getRenderContext(SoNode *node, std::shared_ptr def = std::shared_ptr()) { return std::dynamic_pointer_cast(getNodeContext(SelStack,node,def)); } /** Returns selection context for rendering. * * @param node: the querying node * @param def: default context if none is found * @param ctx2: secondary context output * * @return Returned the primary context for selection, and the context is * always stored in the first encountered SoFCSelectionRoot in the path. It * is keyed using the entire sequence of SoFCSelectionRoot along the path * to \c node, replacing the first SoFCSelectionRoot with the given node. * * @return Secondary context returned in \c ctx2 is for customized * highlighting, and is not affected by mouse event. The highlight is * applied manually using SoSelectionElementAction. It is stored in the * last encountered SoFCSelectionRoot, and is keyed using the querying * \c node and (if there are more than one SoFCSelectionRoot along the * path) the first SoFCSelectionRoot. The reason is so that any link to a * node (new links means additional SoFCSelectionRoot added in front) with * customized subelement highlight will also show the highlight. Secondary * context can be chained, which why the secondary context type must provide * an function called merge() for getRenderContext() to merge the context. * See SoFCSelectionContext::merge() for an implementation of merging multiple * context. * * @note For simplicity reason, currently secondary context is only freed * when the storage SoFCSSelectionRoot node is freed. */ template static std::shared_ptr getRenderContext(SoNode *node, std::shared_ptr def, std::shared_ptr &ctx2) { ctx2 = std::dynamic_pointer_cast(getNodeContext2(SelStack,node,T::merge)); return std::dynamic_pointer_cast(getNodeContext(SelStack,node,def)); } /** Get the selection context for an action. * * @param action: the action. SoSelectionElementAction has any option to * query for secondary context. \sa getRenderContext for detail about * secondary context * @param node: the querying node * @param def: default context if none is found, only used if querying * non-secondary context * @param create: create a new context if none is found * * @return If no SoFCSelectionRoot is found in the current path of action, * \c def is returned. Otherwise a selection context returned. A new one * will be created if none is found. */ template static std::shared_ptr getActionContext( SoAction *action, SoNode *node, std::shared_ptr def=std::shared_ptr(), bool create=true) { auto res = findActionContext(action,node,create,false); if(!res.second) { if(res.first) return std::shared_ptr(); // default context is only applicable for non-secondary context query return def; } // make a new context if there is none auto &ctx = *res.second; if(ctx) { auto ret = std::dynamic_pointer_cast(ctx); if(!ret) ctx.reset(); } if(!ctx && create) ctx = std::make_shared(); return std::static_pointer_cast(ctx); } static bool removeActionContext(SoAction *action, SoNode *node) { return findActionContext(action,node,false,true).second!=0; } template static std::shared_ptr getSecondaryActionContext(SoAction *action, SoNode *node) { auto it = ActionStacks.find(action); if(it == ActionStacks.end()) return std::shared_ptr(); return std::dynamic_pointer_cast(getNodeContext2(it->second,node,T::merge)); } static void checkSelection(bool &sel, SbColor &selColor, bool &hl, SbColor &hlColor); static void moveActionStack(SoAction *from, SoAction *to, bool erase); static SoNode *getCurrentRoot(bool front, SoNode *def); void resetContext(); static bool checkColorOverride(SoState *state); bool hasColorOverride() const { return overrideColor; } void setColorOverride(App::Color c) { overrideColor = true; colorOverride = SbColor(c.r,c.g,c.b); transOverride = c.a; } void removeColorOverride() { overrideColor = false; } enum SelectStyles { Full, Box, PassThrough }; SoSFEnum selectionStyle; static bool renderBBox(SoGLRenderAction *action, SoNode *node, SbColor color); protected: virtual ~SoFCSelectionRoot(); void renderPrivate(SoGLRenderAction *, bool inPath); bool _renderPrivate(SoGLRenderAction *, bool inPath); class Stack : public std::vector { public: std::unordered_set nodeSet; size_t offset = 0; }; static SoFCSelectionContextBasePtr getNodeContext( Stack &stack, SoNode *node, SoFCSelectionContextBasePtr def); static SoFCSelectionContextBasePtr getNodeContext2( Stack &stack, SoNode *node, SoFCSelectionContextBase::MergeFunc *merge); static std::pair findActionContext( SoAction *action, SoNode *node, bool create, bool erase); static Stack SelStack; static std::unordered_map ActionStacks; struct StackComp { bool operator()(const Stack &a, const Stack &b) const; }; typedef std::map ContextMap; ContextMap contextMap; ContextMap contextMap2;//holding secondary context struct SelContext: SoFCSelectionContextBase { public: SbColor selColor; SbColor hlColor; bool selAll = false; bool hlAll = false; bool hideAll = false; static MergeFunc merge; }; typedef std::shared_ptr SelContextPtr; typedef std::vector ColorStack; static ColorStack SelColorStack; static ColorStack HlColorStack; static SoFCSelectionRoot *ShapeColorNode; bool overrideColor = false; SbColor colorOverride; float transOverride = 0.0f; SoColorPacker shapeColorPacker; bool doActionPrivate(Stack &stack, SoAction *); }; /** * @author Werner Mayer */ class GuiExport SoHighlightElementAction : public SoAction { SO_ACTION_HEADER(SoHighlightElementAction); public: SoHighlightElementAction (); ~SoHighlightElementAction(); void setHighlighted(SbBool); SbBool isHighlighted() const; void setColor(const SbColor&); const SbColor& getColor() const; void setElement(const SoDetail*); const SoDetail* getElement() const; static void initClass(); protected: virtual void beginTraversal(SoNode *node); private: static void callDoAction(SoAction *action,SoNode *node); private: SbBool _highlight; SbColor _color; const SoDetail* _det; }; /** * @author Werner Mayer */ class GuiExport SoSelectionElementAction : public SoAction { SO_ACTION_HEADER(SoSelectionElementAction); public: enum Type {None, Append, Remove, All, Color, Hide, Show}; SoSelectionElementAction (Type=None, bool secondary = false); ~SoSelectionElementAction(); Type getType() const; void setType(Type type) { _type = type; } void setColor(const SbColor&); const SbColor& getColor() const; void setElement(const SoDetail*); const SoDetail* getElement() const; bool isSecondary() const {return _secondary;} void setSecondary(bool enable) { _secondary = enable; } const std::map &getColors() const { return _colors; } void setColors(const std::map &colors) { _colors = colors; } void swapColors(std::map &colors) { _colors.swap(colors); } static void initClass(); protected: virtual void beginTraversal(SoNode *node); private: static void callDoAction(SoAction *action,SoNode *node); private: Type _type; SbColor _color; const SoDetail* _det; std::map _colors; bool _secondary; }; /** * @author Werner Mayer */ class GuiExport SoVRMLAction : public SoAction { SO_ACTION_HEADER(SoVRMLAction); public: SoVRMLAction(); ~SoVRMLAction(); void setOverrideMode(SbBool); SbBool isOverrideMode() const; static void initClass(); private: SbBool overrideMode; std::list bindList; static void callDoAction(SoAction *action,SoNode *node); }; } // namespace Gui #endif // !GUI_SOFCUNIFIEDSELECTION_H