From d93259e2383e9fb7b133aebe6edb56abfa0fd981 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 13 Jul 2019 21:34:43 +0800 Subject: [PATCH] Path changes * Relaxed valid base shape requirement, as long as it can return a shape using part.getShape() * Improve ViewProviderPath performance by sharing the same selection observer * Relocate libarea binary installation --- src/Mod/Path/App/AppPathPy.cpp | 5 +- src/Mod/Path/App/Area.h | 5 +- src/Mod/Path/Gui/ViewProviderPath.cpp | 98 ++++++++++++++++++++------- src/Mod/Path/Gui/ViewProviderPath.h | 7 +- src/Mod/Path/PathCommands.py | 15 ++-- src/Mod/Path/PathScripts/PathUtil.py | 21 ++---- src/Mod/Path/libarea/CMakeLists.txt | 11 ++- 7 files changed, 97 insertions(+), 65 deletions(-) diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index fcdf1411ca..381ef87ef6 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -94,10 +95,6 @@ PyErr_SetString(Base::BaseExceptionFreeCADError,e); \ } throw Py::Exception(); -namespace Part { -extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape); -} - namespace Path { class Module : public Py::ExtensionModule { diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 08a671663d..251ea9e915 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -35,13 +35,10 @@ #include #include +#include #include "Path.h" #include "AreaParams.h" -namespace Part { -extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape); -} - class CArea; class CCurve; class Bnd_Box; diff --git a/src/Mod/Path/Gui/ViewProviderPath.cpp b/src/Mod/Path/Gui/ViewProviderPath.cpp index 8ea83d7c8b..e7b14e9a10 100644 --- a/src/Mod/Path/Gui/ViewProviderPath.cpp +++ b/src/Mod/Path/Gui/ViewProviderPath.cpp @@ -43,6 +43,8 @@ # include #endif +#include + #include "ViewProviderPath.h" #include @@ -53,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +78,72 @@ using namespace PathGui; using namespace Path; using namespace PartGui; +namespace PathGui { + +class PathSelectionObserver: public Gui::SelectionObserver { +public: + static void init() { + static PathSelectionObserver *instance; + if(!instance) + instance = new PathSelectionObserver(); + } + + void setArrow(SoSwitch *pcSwitch=0) { + if(pcSwitch==pcLastArrowSwitch) + return; + if(pcLastArrowSwitch) { + pcLastArrowSwitch->whichChild = -1; + pcLastArrowSwitch->unref(); + pcLastArrowSwitch = 0; + } + if(pcSwitch) { + pcSwitch->ref(); + pcSwitch->whichChild = 0; + pcLastArrowSwitch = pcSwitch; + } + } + + void onSelectionChanged(const Gui::SelectionChanges& msg) { + if(msg.Type == Gui::SelectionChanges::RmvPreselect) { + setArrow(); + return; + } + if((msg.Type!=Gui::SelectionChanges::SetPreselect + && msg.Type!=Gui::SelectionChanges::MovePreselect) + || !msg.pOriginalMsg || !msg.pSubObject || !msg.pParentObject) + return; + Base::Matrix4D linkMat; + auto sobj = msg.pSubObject->getLinkedObject(true,&linkMat,false); + auto vp = Base::freecad_dynamic_cast( + Application::Instance->getViewProvider(sobj)); + if(!vp) { + setArrow(); + return; + } + + if(vp->pt0Index >= 0) { + Base::Matrix4D mat; + msg.pParentObject->getSubObject(msg.pSubName,0,&mat); + mat *= linkMat; + mat.inverse(); + Base::Vector3d pt = mat*Base::Vector3d(msg.x,msg.y,msg.z); + const SbVec3f &ptTo = *vp->pcLineCoords->point.getValues(vp->pt0Index); + SbVec3f ptFrom(pt.x,pt.y,pt.z); + if(ptFrom != ptTo) { + vp->pcArrowTransform->pointAt(ptFrom,ptTo); + setArrow(vp->pcArrowSwitch); + return; + } + } + setArrow(); + } + + SoSwitch *pcLastArrowSwitch = 0; +}; +} + +////////////////////////////////////////////////////////////////////////////// + PROPERTY_SOURCE(PathGui::ViewProviderPath, Gui::ViewProviderGeometryObject) ViewProviderPath::ViewProviderPath() @@ -171,6 +240,8 @@ ViewProviderPath::ViewProviderPath() SelectionStyle.setEnums(SelectionStyleEnum); unsigned long sstyle = hGrp->GetInt("DefaultSelectionStyle",0); SelectionStyle.setValue(sstyle); + + PathSelectionObserver::init(); } ViewProviderPath::~ViewProviderPath() @@ -249,7 +320,7 @@ std::string ViewProviderPath::getElement(const SoDetail* detail) const pt0Index = line_detail->getPoint0()->getCoordinateIndex(); if(pt0Index<0 || pt0Index>=pcLineCoords->point.getNum()) pt0Index = -1; - return str.str(); + return boost::replace_all_copy(str.str(),".",","); } } } @@ -272,31 +343,6 @@ SoDetail* ViewProviderPath::getDetail(const char* subelement) const return detail; } -void ViewProviderPath::onSelectionChanged(const Gui::SelectionChanges& msg) { - if(msg.Type == Gui::SelectionChanges::SetPreselect && msg.pSubName && - pt0Index >= 0 && getObject() && getObject()->getDocument()) - { - const char *docName = getObject()->getDocument()->getName(); - const char *objName = getObject()->getNameInDocument(); - if(docName && objName && - strcmp(msg.pDocName,docName)==0 && - strcmp(msg.pObjectName,objName)==0) - { - Path::Feature* pcPathObj = static_cast(pcObject); - Base::Vector3d pt = pcPathObj->Placement.getValue().inverse().toMatrix()* - Base::Vector3d(msg.x,msg.y,msg.z); - const SbVec3f &ptTo = *pcLineCoords->point.getValues(pt0Index); - SbVec3f ptFrom(pt.x,pt.y,pt.z); - if(ptFrom != ptTo) { - pcArrowTransform->pointAt(ptFrom,ptTo); - pcArrowSwitch->whichChild = 0; - return; - } - } - } - pcArrowSwitch->whichChild = -1; -} - void ViewProviderPath::onChanged(const App::Property* prop) { if(blockPropertyChange) return; diff --git a/src/Mod/Path/Gui/ViewProviderPath.h b/src/Mod/Path/Gui/ViewProviderPath.h index 18666c91da..5beb36b755 100644 --- a/src/Mod/Path/Gui/ViewProviderPath.h +++ b/src/Mod/Path/Gui/ViewProviderPath.h @@ -42,8 +42,9 @@ class SoSwitch; namespace PathGui { +class PathSelectionObserver; + class PathGuiExport ViewProviderPath : public Gui::ViewProviderGeometryObject - , public Gui::SelectionObserver { PROPERTY_HEADER(PathGui::ViewProviderPath); typedef ViewProviderGeometryObject inherited; @@ -78,14 +79,14 @@ public: virtual std::string getElement(const SoDetail *) const; SoDetail* getDetail(const char* subelement) const; - virtual void onSelectionChanged(const Gui::SelectionChanges& msg); - void updateShowConstraints(); void updateVisual(bool rebuild = false); void hideSelection(); virtual void showBoundingBox(bool show); + friend class PathSelectionObserver; + protected: virtual void onChanged(const App::Property* prop); diff --git a/src/Mod/Path/PathCommands.py b/src/Mod/Path/PathCommands.py index 432ac4e1fc..2f85f24572 100644 --- a/src/Mod/Path/PathCommands.py +++ b/src/Mod/Path/PathCommands.py @@ -104,15 +104,18 @@ class _CommandSelectLoop: FreeCADGui.Selection.addSelection(obj, "Edge" + str(elist.index(e) + 1)) def formsPartOfALoop(self, obj, sub, names): - if names[0][0:4] != 'Edge': - if names[0][0:4] == 'Face' and horizontalFaceLoop(obj, sub, names): + try: + if names[0][0:4] != 'Edge': + if names[0][0:4] == 'Face' and horizontalFaceLoop(obj, sub, names): + return True + return False + if len(names) == 1 and horizontalEdgeLoop(obj, sub): return True - return False - if len(names) == 1 and horizontalEdgeLoop(obj, sub): + if len(names) == 1 or names[1][0:4] != 'Edge': + return False return True - if len(names) == 1 or names[1][0:4] != 'Edge': + except Exception: return False - return True if FreeCAD.GuiUp: diff --git a/src/Mod/Path/PathScripts/PathUtil.py b/src/Mod/Path/PathScripts/PathUtil.py index 67fd01b4d9..d040ce2295 100644 --- a/src/Mod/Path/PathScripts/PathUtil.py +++ b/src/Mod/Path/PathScripts/PathUtil.py @@ -53,31 +53,20 @@ def isValidBaseObject(obj): # Can't link to anything inside a geo feature group anymore PathLog.debug("%s is inside a geo feature group" % obj.Label) return False - if hasattr(obj, 'TypeId') and 'App::Part' == obj.TypeId: - return obj.Group and any(hasattr(o, 'Shape') for o in obj.Group) - if not hasattr(obj, 'Shape'): - PathLog.debug("%s has no shape" % obj.Label) - return False if obj.TypeId in NotValidBaseTypeIds: PathLog.debug("%s is blacklisted (%s)" % (obj.Label, obj.TypeId)) return False if hasattr(obj, 'Sheets') or hasattr(obj, 'TagText'): # Arch.Panels and Arch.PanelCut PathLog.debug("%s is not an Arch.Panel" % (obj.Label)) return False - return True + import Part + return not Part.getShape(obj).isNull() def isSolid(obj): '''isSolid(obj) ... return True if the object is a valid solid.''' - if hasattr(obj, 'Tip'): - return isSolid(obj.Tip) - if hasattr(obj, 'Shape'): - if obj.Shape.Volume > 0.0 and obj.Shape.isClosed(): - return True - if hasattr(obj, 'TypeId') and 'App::Part' == obj.TypeId: - if not obj.Group or any(hasattr(o, 'Shape') and not isSolid(o) for o in obj.Group): - return False - return True - return False + import Part + shape = Part.getShape(obj) + return not shape.isNull() and shape.Volume and shape.isClosed() def toolControllerForOp(op): '''toolControllerForOp(op) ... return the tool controller used by the op. diff --git a/src/Mod/Path/libarea/CMakeLists.txt b/src/Mod/Path/libarea/CMakeLists.txt index f01b6ec74c..c3a73e48be 100644 --- a/src/Mod/Path/libarea/CMakeLists.txt +++ b/src/Mod/Path/libarea/CMakeLists.txt @@ -98,7 +98,7 @@ add_library( add_library( area - MODULE + SHARED ${PYAREA_SRC} ) @@ -151,7 +151,7 @@ else(MSVC) endif(MSVC) target_link_libraries(area-native ${area_native_LIBS}) -SET_BIN_DIR(area-native area-native) +SET_BIN_DIR(area-native area-native /Mod/Path) target_link_libraries(area area-native ${area_LIBS} ${area_native_LIBS}) @@ -161,7 +161,7 @@ if(NOT BUILD_DYNAMIC_LINK_PYTHON AND CMAKE_COMPILER_IS_CLANGXX) target_link_libraries(area "-Wl,-undefined,dynamic_lookup") endif() -SET_BIN_DIR(area area) +SET_BIN_DIR(area area /Mod/Path) SET_PYTHON_PREFIX_SUFFIX(area) # this figures out where to install the Python modules @@ -176,12 +176,11 @@ message(STATUS "area module (for Path Workbench) will be installed to: " ${CMAKE if(WIN32) set_target_properties(area-native PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) INSTALL(TARGETS area-native - RUNTIME DESTINATION bin - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + DESTINATION ${CMAKE_INSTALL_LIBDIR} ) else(WIN32) INSTALL(TARGETS area-native - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif(WIN32)