diff --git a/src/Mod/Show/Containers.py b/src/Mod/Show/Containers.py index 29c3acb3bc..565dd6e06f 100644 --- a/src/Mod/Show/Containers.py +++ b/src/Mod/Show/Containers.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2018 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -20,12 +20,14 @@ # * * # ***************************************************************************/ -#This is a temporary replacement for C++-powered Container class that should be eventually introduced into FreeCAD +# This is a temporary replacement for C++-powered Container class that should be eventually introduced into FreeCAD + class Container(object): """Container class: a unified interface for container objects, such as Group, Part, Body, or Document. This is a temporary implementation.""" - Object = None #DocumentObject or Document, the actual container + + Object = None # DocumentObject or Document, the actual container def __init__(self, obj): self.Object = obj @@ -33,7 +35,7 @@ class Container(object): def self_check(self): if self.Object is None: raise ValueError("Null!") - if not isAContainer(self.Object, links_too= True): + if not isAContainer(self.Object, links_too=True): raise NotAContainerError(self.Object) def getAllChildren(self): @@ -46,18 +48,18 @@ class Container(object): self.self_check() container = self.Object - if container.isDerivedFrom('App::Document'): + if container.isDerivedFrom("App::Document"): return [] - elif container.hasExtension('App::OriginGroupExtension'): + elif container.hasExtension("App::OriginGroupExtension"): if container.Origin is not None: return [container.Origin] else: return [] - elif container.isDerivedFrom('App::Origin'): + elif container.isDerivedFrom("App::Origin"): return container.OriginFeatures - elif container.hasExtension('App::GroupExtension'): + elif container.hasExtension("App::GroupExtension"): return [] - elif container.hasChildElement(): # Link + elif container.hasChildElement(): # Link return [] raise RuntimeError("getStaticChildren: unexpected container type!") @@ -66,7 +68,7 @@ class Container(object): self.self_check() container = self.Object - if container.isDerivedFrom('App::Document'): + if container.isDerivedFrom("App::Document"): # find all objects not contained by any Part or Body result = set(container.Objects) for obj in container.Objects: @@ -74,18 +76,18 @@ class Container(object): children = set(Container(obj).getAllChildren()) result = result - children return list(result) - elif container.hasExtension('App::GroupExtension'): + elif container.hasExtension("App::GroupExtension"): result = container.Group - if container.hasExtension('App::GeoFeatureGroupExtension'): - #geofeaturegroup's group contains all objects within the CS, we don't want that + if container.hasExtension("App::GeoFeatureGroupExtension"): + # geofeaturegroup's group contains all objects within the CS, we don't want that result = [obj for obj in result if obj.getParentGroup() is not container] return result - elif container.isDerivedFrom('App::Origin'): + elif container.isDerivedFrom("App::Origin"): return [] elif container.hasChildElement(): result = [] for sub in container.getSubObjects(1): - sobj = container.getSubObject(sub,retType=1) + sobj = container.getSubObject(sub, retType=1) if sobj: result.append(sobj) return result @@ -97,11 +99,11 @@ class Container(object): self.self_check() container = self.Object - if container.isDerivedFrom('App::Document'): - return True #Document is a special thing... is it a CS or not is a matter of coding convenience. - elif container.hasExtension('App::GeoFeatureGroupExtension'): + if container.isDerivedFrom("App::Document"): + return True # Document is a special thing... is it a CS or not is a matter of coding convenience. + elif container.hasExtension("App::GeoFeatureGroupExtension"): return True - elif container.hasChildElement(): # Link + elif container.hasChildElement(): # Link return True else: return False @@ -111,13 +113,13 @@ class Container(object): self.self_check() container = self.Object - if container.isDerivedFrom('App::Document'): - return True #Document is a special thing... Return value is a matter of coding convenience. - elif container.hasExtension('App::GeoFeatureGroupExtension'): + if container.isDerivedFrom("App::Document"): + return True # Document is a special thing... Return value is a matter of coding convenience. + elif container.hasExtension("App::GeoFeatureGroupExtension"): return True - elif container.isDerivedFrom('App::Origin'): + elif container.isDerivedFrom("App::Origin"): return True - elif container.hasChildElement(): # Link + elif container.hasChildElement(): # Link return True else: return False @@ -134,15 +136,15 @@ class Container(object): container = self.Object return _getMetacontainerChildren(self, Container.isAVisGroup) - def isChildVisible(self,obj): + def isChildVisible(self, obj): container = self.Object - isElementVisible = getattr(container,'isElementVisible',None) + isElementVisible = getattr(container, "isElementVisible", None) if not isElementVisible: return obj.Visibility vis = isElementVisible(obj.Name) if vis < 0: return obj.Visibility - return vis>0 + return vis > 0 def hasObject(self, obj): """Returns True if the container contains specified object directly.""" @@ -151,6 +153,7 @@ class Container(object): def hasObjectRecursive(self, obj): return self.Object in ContainerChain(obj) + def _getMetacontainerChildren(container, isrightcontainer_func): """Gathers up children of metacontainer - a container structure formed by containers of specific type. For example, coordinate systems form a kind of container structure. @@ -159,9 +162,9 @@ def _getMetacontainerChildren(container, isrightcontainer_func): isrightcontainer_func: a function f(cnt)->bool, where cnt is a Container object.""" result = [] - list_traversing_now = [container] #list of Container instances - list_to_be_traversed_next = [] #list of Container instances - visited_containers = set([container.Object]) #set of DocumentObjects + list_traversing_now = [container] # list of Container instances + list_to_be_traversed_next = [] # list of Container instances + visited_containers = set([container.Object]) # set of DocumentObjects while len(list_traversing_now) > 0: list_to_be_traversed_next = [] @@ -178,26 +181,26 @@ def _getMetacontainerChildren(container, isrightcontainer_func): return result - -def isAContainer(obj, links_too = False): - '''isAContainer(obj, links_too): returns True if obj is an object container, such as +def isAContainer(obj, links_too=False): + """isAContainer(obj, links_too): returns True if obj is an object container, such as Group, Part, Body. The important characteristic of an object being a container is that it can be activated to receive new objects. Documents are considered containers, too. If links_too, App::Link objects are considered containers, too. Then, container tree - isn't necessarily a tree.''' + isn't necessarily a tree.""" - if obj.isDerivedFrom('App::Document'): + if obj.isDerivedFrom("App::Document"): return True - if obj.hasExtension('App::GroupExtension'): + if obj.hasExtension("App::GroupExtension"): return True - if obj.isDerivedFrom('App::Origin'): + if obj.isDerivedFrom("App::Origin"): return True if obj.hasChildElement(): return True if links_too else False return False -#from Part-o-magic... + +# from Part-o-magic... def ContainerOf(obj): """ContainerOf(obj): returns the container that immediately has obj.""" cnt = None @@ -211,17 +214,19 @@ def ContainerOf(obj): return obj.Document return cnt + def getVisGroupOf(obj): chain = VisGroupChain(obj) return chain[-1] -#from Part-o-magic... over-engineered, but proven to work -def ContainerChain(feat): - '''ContainerChain(feat): container path to feat (not including feat itself). - Last container directly contains the feature. - Example of output: [,,,]''' - if feat.isDerivedFrom('App::Document'): +# from Part-o-magic... over-engineered, but proven to work +def ContainerChain(feat): + """ContainerChain(feat): container path to feat (not including feat itself). + Last container directly contains the feature. + Example of output: [,,,]""" + + if feat.isDerivedFrom("App::Document"): return [] list_traversing_now = [feat] @@ -243,18 +248,25 @@ def ContainerChain(feat): return [feat.Document] + list_of_deps[::-1] + def CSChain(feat): cnt_chain = ContainerChain(feat) return [cnt for cnt in cnt_chain if Container(cnt).isACS()] + def VisGroupChain(feat): cnt_chain = ContainerChain(feat) return [cnt for cnt in cnt_chain if Container(cnt).isAVisGroup()] + class ContainerError(RuntimeError): pass + + class NotAContainerError(ContainerError): def __init__(self, name="None"): ContainerError.__init__(self, "'{}' is not recognized as container".format(name)) + + class ContainerTreeError(ContainerError): pass diff --git a/src/Mod/Show/DepGraphTools.py b/src/Mod/Show/DepGraphTools.py index 324c556829..0e72ec425a 100644 --- a/src/Mod/Show/DepGraphTools.py +++ b/src/Mod/Show/DepGraphTools.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2016 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -20,10 +20,11 @@ # * * # ***************************************************************************/ + def getAllDependencies(feat): - '''getAllDependencies(feat): gets all features feat depends on, directly or indirectly. + """getAllDependencies(feat): gets all features feat depends on, directly or indirectly. Returns a list, with deepest dependencies last. feat is not included in the list, except - if the feature depends on itself (dependency loop).''' + if the feature depends on itself (dependency loop).""" list_traversing_now = [feat] set_of_deps = set() list_of_deps = [] @@ -41,10 +42,11 @@ def getAllDependencies(feat): return list_of_deps + def getAllDependent(feat): - '''getAllDependent(feat): gets all features that depend on feat, directly or indirectly. + """getAllDependent(feat): gets all features that depend on feat, directly or indirectly. Returns a list, with deepest dependencies last. feat is not included in the list, except - if the feature depends on itself (dependency loop).''' + if the feature depends on itself (dependency loop).""" list_traversing_now = [feat] set_of_deps = set() list_of_deps = [] diff --git a/src/Mod/Show/SceneDetail.py b/src/Mod/Show/SceneDetail.py index 18ccef672f..077fd89a45 100644 --- a/src/Mod/Show/SceneDetail.py +++ b/src/Mod/Show/SceneDetail.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -20,6 +20,7 @@ # * * # ***************************************************************************/ + class SceneDetail(object): """SceneDetail class: abstract class for tempovis scene save/restore plug-in. An implementation must provide: * data storage (as "data" attribute of the object) @@ -32,7 +33,8 @@ class SceneDetail(object): * test for equality, that checks if .data attributes of two SceneDetail instances are equal * info on if the modification affects what is saved to disk, and thus should be undone temporarily for file writing. """ - class_id = '' + + class_id = "" data = None doc = None @@ -45,9 +47,9 @@ class SceneDetail(object): def set_doc(self, doc): self.doc = doc - # - key = None #a string or something alike to use to store/find the entry in TempoVis. For example, a string "{object_name}.{property_name}". - affects_persistence = False #True indicate that the changes will be recorded if the doc is saved, and that this detail should be restored for saving + # + key = None # a string or something alike to use to store/find the entry in TempoVis. For example, a string "{object_name}.{property_name}". + affects_persistence = False # True indicate that the changes will be recorded if the doc is saved, and that this detail should be restored for saving def scene_value(self): """scene_value(): returns the value from the scene""" @@ -62,15 +64,16 @@ class SceneDetail(object): if isinstance(other, self.__class__): return self.data == other.data and self.data is not None else: - raise TypeError('{self} can\'t be compared with {other}' - .format(self= repr(self), other= repr(other))) - # + raise TypeError( + "{self} can't be compared with {other}".format(self=repr(self), other=repr(other)) + ) - # + # + + # @property def full_key(self): return (self.class_id, self.doc.Name if self.doc else None, self.key) - def __ne__(self, other): return not self.__eq__(other) diff --git a/src/Mod/Show/SceneDetails/Camera.py b/src/Mod/Show/SceneDetails/Camera.py index 20efeb689e..78322a7604 100644 --- a/src/Mod/Show/SceneDetails/Camera.py +++ b/src/Mod/Show/SceneDetails/Camera.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -24,19 +24,21 @@ from Show.SceneDetail import SceneDetail import FreeCADGui + class Camera(SceneDetail): """Camera(doc): TempoVis plugin for saving and restoring camera.""" - class_id = 'SDCamera' + + class_id = "SDCamera" def __init__(self, doc): self.doc = doc - self.key = 'the_cam' + self.key = "the_cam" def _viewer(self): gdoc = FreeCADGui.getDocument(self.doc.Name) v = gdoc.activeView() - if not hasattr(v, 'getCamera'): - v = gdoc.mdiViewsOfType('Gui::View3DInventor')[0] + if not hasattr(v, "getCamera"): + v = gdoc.mdiViewsOfType("Gui::View3DInventor")[0] return v def scene_value(self): @@ -44,4 +46,3 @@ class Camera(SceneDetail): def apply_data(self, val): self._viewer().setCamera(val) - diff --git a/src/Mod/Show/SceneDetails/ClipPlane.py b/src/Mod/Show/SceneDetails/ClipPlane.py index e1a7d383a3..221bb97d10 100644 --- a/src/Mod/Show/SceneDetails/ClipPlane.py +++ b/src/Mod/Show/SceneDetails/ClipPlane.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -24,31 +24,35 @@ from Show.SceneDetail import SceneDetail import FreeCAD as App import FreeCADGui as Gui + class ClipPlane(SceneDetail): """ClipPlane(document, enable = None, placement = None, offset = 0.0): TempoVis plugin for applying clipping plane to whole project except edit root. enable can be 0 for disable, 1 for enable, and -1 for toggle (FIXME: toggle value support is a hack for while we can't read out the current state).""" - class_id = 'SDClipPlane' - key = '' + class_id = "SDClipPlane" + key = "" - def __init__(self, document, enable = None, placement = None, offset = 0.0): + def __init__(self, document, enable=None, placement=None, offset=0.0): self.doc = document if enable is not None: if placement is not None and offset != 0.0: placement = placement.copy() - dir = placement.Rotation.multVec(App.Vector(0,0,1)) - placement.Base = placement.Base + dir*offset + dir = placement.Rotation.multVec(App.Vector(0, 0, 1)) + placement.Base = placement.Base + dir * offset self.data = (enable, placement) def scene_value(self): - return (0, None) #hack. For until there is a way to easily query the plane, this should be good enough. + return ( + 0, + None, + ) # hack. For until there is a way to easily query the plane, this should be good enough. def apply_data(self, val): enable, pla = val if enable != 0: - self._viewer().toggleClippingPlane(enable, pla= pla) + self._viewer().toggleClippingPlane(enable, pla=pla) else: self._viewer().toggleClippingPlane(enable) @@ -58,6 +62,6 @@ class ClipPlane(SceneDetail): else: gdoc = Gui.getDocument(self.doc.Name) v = gdoc.activeView() - if not hasattr(v, 'toggleClippingPlane'): - v = gdoc.mdiViewsOfType('Gui::View3DInventor')[0] + if not hasattr(v, "toggleClippingPlane"): + v = gdoc.mdiViewsOfType("Gui::View3DInventor")[0] return v diff --git a/src/Mod/Show/SceneDetails/ObjectClipPlane.py b/src/Mod/Show/SceneDetails/ObjectClipPlane.py index 0220a84d09..f2ede17091 100644 --- a/src/Mod/Show/SceneDetails/ObjectClipPlane.py +++ b/src/Mod/Show/SceneDetails/ObjectClipPlane.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -24,14 +24,16 @@ from Show.SceneDetail import SceneDetail import FreeCAD as App + class ObjectClipPlane(SceneDetail): """ObjectClipPlane(object, enable = None, placement = None, offset = 0.0): Plugin for TempoVis for adding clipping planes to individual objects.""" - class_id = 'SDObjectClipPlane' - propname = '' - objname = '' - def __init__(self, object, enable = None, placement = None, offset = 0.0): + class_id = "SDObjectClipPlane" + propname = "" + objname = "" + + def __init__(self, object, enable=None, placement=None, offset=0.0): self.objname = object.Name self.doc = object.Document self.key = self.objname @@ -40,7 +42,7 @@ class ObjectClipPlane(SceneDetail): def scene_value(self): vp = self.doc.getObject(self.objname).ViewObject - cp = getClipPlaneNode(vp, make_if_missing= False) + cp = getClipPlaneNode(vp, make_if_missing=False) if cp is None: return self.val(False) else: @@ -53,16 +55,17 @@ class ObjectClipPlane(SceneDetail): def apply_data(self, val): enable, pldef = val vp = self.doc.getObject(self.objname).ViewObject - cp = getClipPlaneNode(vp, make_if_missing= True if enable else False) + cp = getClipPlaneNode(vp, make_if_missing=True if enable else False) if cp is None and not enable: return if enable: from pivy import coin + v, d = pldef cp.plane.setValue(coin.SbPlane(coin.SbVec3f(*v), d)) cp.on.setValue(enable) - def val(self, enable, placement = None, offset = 0.0): + def val(self, enable, placement=None, offset=0.0): """val(enable, placement = None, offset = 0.0): constructs a value from convenient parameters. Placement is in global CS. The cutting will be by XY plane of Placement; the stuff in negative Z is visible and the stuff in positive Z is invisible.""" @@ -70,16 +73,20 @@ class ObjectClipPlane(SceneDetail): pldef = None if enable: obj = self.doc.getObject(self.objname) - plm_cs = obj.getGlobalPlacement().multiply(obj.Placement.inverse()) # placement of CS the object is in + plm_cs = obj.getGlobalPlacement().multiply( + obj.Placement.inverse() + ) # placement of CS the object is in plm_plane = plm_cs.inverse().multiply(placement) pldef = placement2plane(plm_plane, offset) return (enable, pldef if enable else None) -def getClipPlaneNode(viewprovider, make_if_missing = True): + +def getClipPlaneNode(viewprovider, make_if_missing=True): from pivy import coin + sa = coin.SoSearchAction() sa.setType(coin.SoClipPlane.getClassTypeId()) - sa.setName('TVClipPlane') + sa.setName("TVClipPlane") sa.traverse(viewprovider.RootNode) if sa.isFound() and sa.getPath().getLength() == 1: return sa.getPath().getTail() @@ -88,19 +95,22 @@ def getClipPlaneNode(viewprovider, make_if_missing = True): return None clipplane = coin.SoClipPlane() viewprovider.RootNode.insertChild(clipplane, 0) - clipplane.setName('TVClipPlane') - clipplane.on.setValue(False) #make sure the plane is not activated by default + clipplane.setName("TVClipPlane") + clipplane.on.setValue(False) # make sure the plane is not activated by default return clipplane + def placement2plane(placement, offset): """returns tuple (normal, D) for making coin plane.""" - normal = placement.Rotation.multVec(App.Vector(0,0,-1)) + normal = placement.Rotation.multVec(App.Vector(0, 0, -1)) D = placement.Base * normal - offset return tuple(normal), D -def clipPlane(obj, enable, placement = None, offset = 0, tv = None): + +def clipPlane(obj, enable, placement=None, offset=0, tv=None): if tv is None: from Show import TempoVis + tv = TempoVis(obj.Document) tv.modify(ClipPlane(obj, enable, placement, offset)) return tv diff --git a/src/Mod/Show/SceneDetails/Pickability.py b/src/Mod/Show/SceneDetails/Pickability.py index 95aed9ea10..171cc8cd05 100644 --- a/src/Mod/Show/SceneDetails/Pickability.py +++ b/src/Mod/Show/SceneDetails/Pickability.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -22,6 +22,7 @@ from Show.SceneDetail import SceneDetail + class Pickability(SceneDetail): """Pickability(object, pickstyle = None):Plugin for TempoVis for altering pick style of objects (i.e., selectability). @@ -29,11 +30,12 @@ class Pickability(SceneDetail): PS_REGULAR = 0 # selectable PS_BOUNDBOX = 1 # selectable, but faster hit testing using bounding box PS_UNPICKABLE = 2 # not selectable and not obstructing.""" - class_id = 'SDPickability' - propname = '' - objname = '' - def __init__(self, object, pickstyle = None): + class_id = "SDPickability" + propname = "" + objname = "" + + def __init__(self, object, pickstyle=None): self.objname = object.Name self.doc = object.Document self.key = self.objname @@ -46,12 +48,15 @@ class Pickability(SceneDetail): def apply_data(self, val): setPickStyle(self.doc.getObject(self.objname).ViewObject, val) + PS_REGULAR = 0 PS_BOUNDBOX = 1 PS_UNPICKABLE = 2 -def getPickStyleNode(viewprovider, make_if_missing = True): + +def getPickStyleNode(viewprovider, make_if_missing=True): from pivy import coin + sa = coin.SoSearchAction() sa.setType(coin.SoPickStyle.getClassTypeId()) sa.traverse(viewprovider.RootNode) @@ -67,14 +72,14 @@ def getPickStyleNode(viewprovider, make_if_missing = True): def getPickStyle(viewprovider): - ps = getPickStyleNode(viewprovider, make_if_missing= False) + ps = getPickStyleNode(viewprovider, make_if_missing=False) if ps is not None: return ps.style.getValue() else: return PS_REGULAR + def setPickStyle(viewprovider, pickstyle): - ps = getPickStyleNode(viewprovider, make_if_missing= pickstyle != 0) #coin.SoPickStyle.SHAPE + ps = getPickStyleNode(viewprovider, make_if_missing=pickstyle != 0) # coin.SoPickStyle.SHAPE if ps is not None: return ps.style.setValue(pickstyle) - diff --git a/src/Mod/Show/SceneDetails/VProperty.py b/src/Mod/Show/SceneDetails/VProperty.py index 35bb26e9d8..bb8d257d99 100644 --- a/src/Mod/Show/SceneDetails/VProperty.py +++ b/src/Mod/Show/SceneDetails/VProperty.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -22,22 +22,23 @@ from Show.SceneDetail import SceneDetail + class VProperty(SceneDetail): """VProperty(object, propname, val = None): plugin for TempoVis to alter ViewProvider properties""" - class_id = 'SDVProperty' + class_id = "SDVProperty" affects_persistence = True - propname = '' - objname = '' + propname = "" + objname = "" mild_restore = True - def __init__(self, object, propname, val = None): + def __init__(self, object, propname, val=None): self.objname = object.Name self.propname = propname self.doc = object.Document - self.key = self.objname + '.' + self.propname + self.key = self.objname + "." + self.propname self.data = val - if propname == 'LinkVisibility': #seems to not be a property + if propname == "LinkVisibility": # seems to not be a property self.affects_persistence = False def scene_value(self): diff --git a/src/Mod/Show/SceneDetails/Workbench.py b/src/Mod/Show/SceneDetails/Workbench.py index 13a5b4e9a7..a014999877 100644 --- a/src/Mod/Show/SceneDetails/Workbench.py +++ b/src/Mod/Show/SceneDetails/Workbench.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -24,14 +24,16 @@ from Show.SceneDetail import SceneDetail import FreeCADGui + class Workbench(SceneDetail): """Workbench(wb = None): Plugin for TempoVis for changing active workbench. wb: string, a name of a workbench (e.g. 'SketcherWorkbench')""" - class_id = 'SDWorkbench' + + class_id = "SDWorkbench" mild_restore = True - def __init__(self, wb = None): - self.key = 'workbench' + def __init__(self, wb=None): + self.key = "workbench" if wb is not None: self.data = wb @@ -40,4 +42,3 @@ class Workbench(SceneDetail): def apply_data(self, val): FreeCADGui.activateWorkbench(val) - diff --git a/src/Mod/Show/ShowUtils.py b/src/Mod/Show/ShowUtils.py index 8592f9cb7d..5ba7e5bf87 100644 --- a/src/Mod/Show/ShowUtils.py +++ b/src/Mod/Show/ShowUtils.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -20,6 +20,7 @@ # * * # ***************************************************************************/ + def is3DObject(obj): """is3DObject(obj): tests if the object has some 3d geometry. TempoVis is made only for objects in 3d view, so all objects that don't pass this check are ignored by TempoVis.""" @@ -29,8 +30,10 @@ def is3DObject(obj): # observation: all viewproviders have transform node, then a switch node. If that switch node contains something, the object has something in 3d view. try: from pivy import coin - return obj.ViewObject.SwitchNode.getNumChildren()>0 + + return obj.ViewObject.SwitchNode.getNumChildren() > 0 except Exception as err: import FreeCAD as App - App.Console.PrintWarning(u"Show.ShowUtils.is3DObject error: {err}\n".format(err= str(err))) - return True #assume. + + App.Console.PrintWarning("Show.ShowUtils.is3DObject error: {err}\n".format(err=str(err))) + return True # assume. diff --git a/src/Mod/Show/TVObserver.py b/src/Mod/Show/TVObserver.py index e0c4b65a8b..a2d190aafd 100644 --- a/src/Mod/Show/TVObserver.py +++ b/src/Mod/Show/TVObserver.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -22,6 +22,7 @@ import FreeCAD + class TVObserver(object): def __init__(self): FreeCAD.addDocumentObserver(self) @@ -31,18 +32,22 @@ class TVObserver(object): def slotStartSaveDocument(self, doc, filepath): from . import TVStack + TVStack._slotStartSaveDocument(doc) def slotFinishSaveDocument(self, doc, filepath): from . import TVStack + TVStack._slotFinishSaveDocument(doc) def slotDeletedDocument(self, doc): from . import TVStack + TVStack._slotDeletedDocument(doc) -#handle module reload -if 'observer_singleton' in vars(): + +# handle module reload +if "observer_singleton" in vars(): observer_singleton.stop() observer_singleton = TVObserver() diff --git a/src/Mod/Show/TVStack.py b/src/Mod/Show/TVStack.py index b803e60acf..62d4f8085f 100644 --- a/src/Mod/Show/TVStack.py +++ b/src/Mod/Show/TVStack.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2019 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -22,11 +22,12 @@ import weakref -global_stacks = {} # dict of TVStacks. key = document name. +global_stacks = {} # dict of TVStacks. key = document name. + class TVStack(object): - index_LUT = None # Key = id(tempovis_instance). Value = index in the stack. - stack = None #list of weakrefs to TV instances. Using weakrefs, so that TempoVis can self-destruct if forgotten. + index_LUT = None # Key = id(tempovis_instance). Value = index in the stack. + stack = None # list of weakrefs to TV instances. Using weakrefs, so that TempoVis can self-destruct if forgotten. document = None _rewind_tv = None @@ -35,13 +36,13 @@ class TVStack(object): self.document = None self.index_LUT = {} self.stack = [] - from . import TVObserver #to start the observer + from . import TVObserver # to start the observer - def insert(self, tv, index = None): + def insert(self, tv, index=None): if index is None: index = len(self.stack) idtv = id(tv) - ref = weakref.ref(tv, (lambda _, idtv=idtv, self=self : self._destruction(idtv))) + ref = weakref.ref(tv, (lambda _, idtv=idtv, self=self: self._destruction(idtv))) self.stack.insert(index, ref) self.rebuild_index(index) @@ -53,7 +54,7 @@ class TVStack(object): try: index = self.index_LUT.get(idtv) except KeyError: - #already withdrawn + # already withdrawn pass else: self.stack.pop(index) @@ -83,20 +84,19 @@ class TVStack(object): from . import mTempoVis index = self.index_LUT[id(tv)] if tv is not None else -1 - for tvref in self.stack[index + 1 : ]: + for tvref in self.stack[index + 1 :]: tv = tvref() if tv.state == mTempoVis.S_ACTIVE: if tv.has(detail): return (tv, tv.data[detail.full_key]) return None - def rebuild_index(self, start = 0): + def rebuild_index(self, start=0): if start == 0: self.index_LUT = {} for i in range(start, len(self.stack)): self.index_LUT[id(self.stack[i]())] = i - def purge_dead(self): """removes dead TV instances from the stack""" n = 0 @@ -117,9 +117,11 @@ class TVStack(object): def unwindForSaving(self): from . import mTempoVis - self.rewindAfterSaving() #just in case there was a failed save before. + self.rewindAfterSaving() # just in case there was a failed save before. - details = {} #dict of detail original values. Key = detail key; value = detail instance with data representing the original value + details = ( + {} + ) # dict of detail original values. Key = detail key; value = detail instance with data representing the original value for ref in self.stack: tv = ref() for key, detail in tv.data.items(): @@ -139,9 +141,11 @@ class TVStack(object): def getSplitSequence(self, tv): """getSplitSequence(tv): returns (list_before, list_after), neither list includes tv.""" index = self.index_LUT[id(tv)] + def deref(lst): return [ref() for ref in lst] - return deref(self.stack[0:index]), deref(self.stack[index+1:]) + + return deref(self.stack[0:index]), deref(self.stack[index + 1 :]) def __getitem__(self, index): return self.stack[index]() @@ -165,7 +169,7 @@ class TVStack(object): return [ref() for ref in self.stack if ref().tag == tag] -def mainStack(document, create_if_missing = True): +def mainStack(document, create_if_missing=True): """mainStack(document, create_if_missing = True):returns the main TVStack instance for provided document""" docname = document.Name @@ -175,18 +179,21 @@ def mainStack(document, create_if_missing = True): return global_stacks.get(docname, None) + def _slotDeletedDocument(document): docname = document.Name stk = global_stacks.pop(docname, None) if stk is not None: stk.dissolve() + def _slotStartSaveDocument(doc): - stk = mainStack(doc, create_if_missing= False) + stk = mainStack(doc, create_if_missing=False) if stk is not None: stk.unwindForSaving() + def _slotFinishSaveDocument(doc): - stk = mainStack(doc, create_if_missing= False) + stk = mainStack(doc, create_if_missing=False) if stk is not None: stk.rewindAfterSaving() diff --git a/src/Mod/Show/__init__.py b/src/Mod/Show/__init__.py index 81be83add6..79f24b93c0 100644 --- a/src/Mod/Show/__init__.py +++ b/src/Mod/Show/__init__.py @@ -1,4 +1,4 @@ __doc__ = "Show module: helper code for visibility automation." from .mTempoVis import TempoVis -from . import DepGraphTools \ No newline at end of file +from . import DepGraphTools diff --git a/src/Mod/Show/mTempoVis.py b/src/Mod/Show/mTempoVis.py index 28de095b4a..f611b15ec1 100644 --- a/src/Mod/Show/mTempoVis.py +++ b/src/Mod/Show/mTempoVis.py @@ -1,4 +1,4 @@ -#/*************************************************************************** +# /*************************************************************************** # * Copyright (c) 2016 Victor Titov (DeepSOIC) * # * * # * This file is part of the FreeCAD CAx development system. * @@ -27,6 +27,7 @@ from . import Containers from . import TVStack import FreeCAD as App + if App.GuiUp: import FreeCADGui as Gui Wrn = lambda msg: App.Console.PrintWarning(msg + "\n") @@ -35,27 +36,36 @@ Log = lambda msg: App.Console.PrintLog(msg + "\n") from copy import copy -S_EMPTY = 0 # TV is initialized, but no changes were done through it -S_ACTIVE = 1 # TV has something to be undone -S_RESTORED = 2 # TV has been restored -S_INTERNAL = 3 # TV instance is being used by another TV instance as a redo data storage +S_EMPTY = 0 # TV is initialized, but no changes were done through it +S_ACTIVE = 1 # TV has something to be undone +S_RESTORED = 2 # TV has been restored +S_INTERNAL = 3 # TV instance is being used by another TV instance as a redo data storage + def _printTraceback(err): import sys + if err is sys.exc_info()[1]: import traceback + tb = traceback.format_exc() Log(tb) + class MAINSTACK(object): - '''it's just a default value definition for TV constructor''' - pass -class JUST_SAVE(object): - '''it's just a default value meaning "save current scene value but don't modify anything"''' + """it's just a default value definition for TV constructor""" + pass + +class JUST_SAVE(object): + '''it's just a default value meaning "save current scene value but don't modify anything"''' + + pass + + class TempoVis(object): - '''TempoVis - helper object to save visibilities of objects before doing + """TempoVis - helper object to save visibilities of objects before doing some GUI editing, hiding or showing relevant stuff during edit, and then restoring all visibilities after editing. @@ -69,25 +79,25 @@ class TempoVis(object): MAINSTACK special value (a global stack for the document will be used), or None (then, the TV is not in any stack, and can be manually instertd into one if desired). - Any additional keyword args are assigned as attributes. You can use it to immediately set a tag, for example.''' + Any additional keyword args are assigned as attributes. You can use it to immediately set a tag, for example.""" document = None - stack = None # reference to stack this TV is in + stack = None # reference to stack this TV is in - data = None # dict. key = ("class_id","key"), value = instance of SceneDetail - data_requested = None #same as data, but stores (wanted) values passed to modify() + data = None # dict. key = ("class_id","key"), value = instance of SceneDetail + data_requested = None # same as data, but stores (wanted) values passed to modify() state = S_EMPTY - tag = '' #stores any user-defined string for identification purposes + tag = "" # stores any user-defined string for identification purposes def _init_attrs(self): - '''initialize member variables to empty values (needed because we can't use mutable initial values when initializing member variables in class definition)''' + """initialize member variables to empty values (needed because we can't use mutable initial values when initializing member variables in class definition)""" self.data = {} self.data_requested = {} - # - def __init__(self, document, stack = MAINSTACK, **kwargs): + # + def __init__(self, document, stack=MAINSTACK, **kwargs): self._init_attrs() self.document = document @@ -99,40 +109,40 @@ class TempoVis(object): else: stack.insert(self) - for key,val in kwargs.items(): + for key, val in kwargs.items(): setattr(self, key, val) def __del__(self): if self.state == S_ACTIVE: - self.restore(ultimate= True) + self.restore(ultimate=True) def has(self, detail): - '''has(self, detail): returns True if this TV has this detail value saved. - example: tv.has(VProperty(obj, "Visibility"))''' + """has(self, detail): returns True if this TV has this detail value saved. + example: tv.has(VProperty(obj, "Visibility"))""" return detail.full_key in self.data def stored_val(self, detail): - '''stored_val(self, detail): returns value of detail remembered by this TV. If not, raises KeyError.''' + """stored_val(self, detail): returns value of detail remembered by this TV. If not, raises KeyError.""" return self.data[detail.full_key].data - def save(self, detail, mild_restore = False): - '''save(detail, mild_restore = False):saves the scene detail to be restored. + def save(self, detail, mild_restore=False): + """save(detail, mild_restore = False):saves the scene detail to be restored. The detail is saved only once; repeated calls are ignored. - mild_restore: internal, do not use.''' + mild_restore: internal, do not use.""" self._change() if not detail.full_key in self.data: - #not saved yet - tv1, curr = self._value_after(detail, query_scene= True) + # not saved yet + tv1, curr = self._value_after(detail, query_scene=True) self.data[detail.full_key] = copy(curr) self.data[detail.full_key].mild_restore = mild_restore else: - #saved already. Change restore policy, if necessary. + # saved already. Change restore policy, if necessary. stored_dt = self.data[detail.full_key] if not mild_restore: stored_dt.mild_restore = False - def modify(self, detail, mild_restore = None): - '''modify(detail, mild_restore = True): modifies scene detail through this TV. + def modify(self, detail, mild_restore=None): + """modify(detail, mild_restore = True): modifies scene detail through this TV. The value is provided as an instance of SceneDetail implementation. The procedure takes care to account for the stack - that is, if in a TV applied later than this one this detail was changed too, the value saved therein is altered, @@ -141,7 +151,7 @@ class TempoVis(object): mild_restore: if True, when restoring later, checks if the value was changed by user after last call to modify(), and doesn't restore if it was changed. - Example: tv.modify(VProperty(obj, "Visibility", True))''' + Example: tv.modify(VProperty(obj, "Visibility", True))""" self._change() @@ -162,36 +172,35 @@ class TempoVis(object): if detail.mild_restore: self.data_requested[detail.full_key] = copy(detail) - def restoreDetail(self, detail, ultimate = False): - '''restoreDetail(detail, ultimate = False): restores a specific scene detail. + def restoreDetail(self, detail, ultimate=False): + """restoreDetail(detail, ultimate = False): restores a specific scene detail. ultimate: if true, the saved value is cleaned out. If the detail is not found, nothing is done. - ''' + """ if not self.has(detail): return self._restore_detail(detail) if ultimate: self.forgetDetail(detail) - def forgetDetail(self, detail): - '''forgetDetail(detail): ditches a saved detail value, making the change done through this TV permanent.''' + """forgetDetail(detail): ditches a saved detail value, making the change done through this TV permanent.""" self.data.pop(detail.full_key, None) self.data_requested.pop(detail.full_key, None) def forget(self): - '''forget(self): clears this TV, making all changes done through it permanent. - Also, withdraws the TV from the stack.''' + """forget(self): clears this TV, making all changes done through it permanent. + Also, withdraws the TV from the stack.""" self.state = S_EMPTY self.data = {} if self.is_in_stack: self.stack.withdraw(self) - def restore(self, ultimate = True): - '''restore(ultimate = True): undoes all changes done through this tempovis / restores saved scene details. + def restore(self, ultimate=True): + """restore(ultimate = True): undoes all changes done through this tempovis / restores saved scene details. ultimate: if true, the saved values are cleaned out, and the TV is withdrawn from the stack. If false, the TV will still remember stuff, and restore can be called again. - ''' + """ if self.state == S_RESTORED: return @@ -202,49 +211,59 @@ class TempoVis(object): try: self._restoreDetail(detail) except Exception as err: - Err("TempoVis.restore: failed to restore detail {key}: {err}".format(key= key, err= str(err))) + Err( + "TempoVis.restore: failed to restore detail {key}: {err}".format( + key=key, err=str(err) + ) + ) _printTraceback(err) if ultimate: self.data = {} if self.is_in_stack: self.stack.withdraw(self) - # + # - # + # def _inserted(self, stack, index): - '''calles when this tv is inserted into a stack''' + """calles when this tv is inserted into a stack""" self.stack = stack + def _withdrawn(self, stack, index): - '''calles when this tv is withdrawn from a stack''' + """calles when this tv is withdrawn from a stack""" self.stack = None + @property def is_in_stack(self): return self.stack is not None - # - # - def modifyVPProperty(self, doc_obj_or_list, prop_names, new_value = JUST_SAVE, mild_restore = None): - '''modifyVPProperty(doc_obj_or_list, prop_names, new_value = JUST_SAVE, mild_restore = None): modifies + # + + # + def modifyVPProperty(self, doc_obj_or_list, prop_names, new_value=JUST_SAVE, mild_restore=None): + """modifyVPProperty(doc_obj_or_list, prop_names, new_value = JUST_SAVE, mild_restore = None): modifies prop_name property of ViewProvider of doc_obj_or_list, and remembers original value of the property. Original values will be restored upon TempoVis deletion, or call to restore(). - mild_restore: test if user changed the value manually when restoring the TV.''' + mild_restore: test if user changed the value manually when restoring the TV.""" if self.state == S_RESTORED: Wrn("Attempting to use a TV that has been restored. There must be a problem with code.") return - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] - if not isinstance(prop_names,(list,tuple)): + if not isinstance(prop_names, (list, tuple)): prop_names = [prop_names] for doc_obj in doc_obj_or_list: for prop_name in prop_names: if not hasattr(doc_obj.ViewObject, prop_name): - Wrn("TempoVis: object {obj} has no attribute {attr}. Skipped." - .format(obj= doc_obj.Name, attr= prop_name)) + Wrn( + "TempoVis: object {obj} has no attribute {attr}. Skipped.".format( + obj=doc_obj.Name, attr=prop_name + ) + ) continue # Because the introduction of external objects, we shall now @@ -253,71 +272,80 @@ class TempoVis(object): # if doc_obj.Document is not self.document: #ignore objects from other documents # raise ValueError("Document object to be modified does not belong to document TempoVis was made for.") from .SceneDetails.VProperty import VProperty + if new_value is JUST_SAVE: if mild_restore: - Wrn("TempoVis: can't just save a value for mild restore. Saving for hard restore.") + Wrn( + "TempoVis: can't just save a value for mild restore. Saving for hard restore." + ) self.save(VProperty(doc_obj, prop_name, new_value)) else: self.modify(VProperty(doc_obj, prop_name, new_value), mild_restore) def restoreVPProperty(self, doc_obj_or_list, prop_names): - '''restoreVPProperty(doc_obj_or_list, prop_name, new_value): restores specific property changes.''' + """restoreVPProperty(doc_obj_or_list, prop_name, new_value): restores specific property changes.""" from .SceneDetails.VProperty import VProperty - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] - if not isinstance(prop_names,(tuple,list)): + if not isinstance(prop_names, (tuple, list)): prop_names = [prop_names] for doc_obj in doc_obj_or_list: for prop_name in prop_names: try: self.restoreDetail(VProperty(doc_obj, prop_name)) except Exception as err: - Err("TempoVis.restore: failed to restore detail {key}: {err}".format(key= key, err= str(err))) + Err( + "TempoVis.restore: failed to restore detail {key}: {err}".format( + key=key, err=str(err) + ) + ) _printTraceback(err) - def saveBodyVisibleFeature(self, doc_obj_or_list): """saveBodyVisibleFeature(self, doc_obj_or_list): saves Visibility of currently visible feature, for every body of PartDesign features in the provided list.""" - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] objs = [] bodies = set() for obj in doc_obj_or_list: - body = getattr(obj,'_Body',None) + body = getattr(obj, "_Body", None) if not body or body in bodies: continue bodies.add(body) - feature = getattr(body,'VisibleFeature',None) + feature = getattr(body, "VisibleFeature", None) if feature: objs.append(feature) - self.modifyVPProperty(objs, 'Visibility', JUST_SAVE) + self.modifyVPProperty(objs, "Visibility", JUST_SAVE) return objs - def show(self, doc_obj_or_list, links_too = True, mild_restore = None): - '''show(doc_obj_or_list, links_too = True): shows objects (sets their Visibility to True). + def show(self, doc_obj_or_list, links_too=True, mild_restore=None): + """show(doc_obj_or_list, links_too = True): shows objects (sets their Visibility to True). doc_obj_or_list can be a document object, or a list of document objects. - If links_too is True, all Links of the objects are also hidden, by setting LinkVisibility attribute of each object.''' + If links_too is True, all Links of the objects are also hidden, by setting LinkVisibility attribute of each object.""" doc_obj_or_list = self._3D_objects(doc_obj_or_list) - self.saveBodyVisibleFeature(doc_obj_or_list) #fix implicit hiding of other features by PartDesign not being recorded to TV - self.modifyVPProperty(doc_obj_or_list, 'Visibility', True, mild_restore) + self.saveBodyVisibleFeature( + doc_obj_or_list + ) # fix implicit hiding of other features by PartDesign not being recorded to TV + self.modifyVPProperty(doc_obj_or_list, "Visibility", True, mild_restore) if links_too: - self.modifyVPProperty(doc_obj_or_list, 'LinkVisibility', True, mild_restore) + self.modifyVPProperty(doc_obj_or_list, "LinkVisibility", True, mild_restore) - def hide(self, doc_obj_or_list, links_too = True, mild_restore = None): - '''hide(doc_obj_or_list): hides objects (sets their Visibility to False). doc_obj_or_list can be a document object, or a list of document objects''' + def hide(self, doc_obj_or_list, links_too=True, mild_restore=None): + """hide(doc_obj_or_list): hides objects (sets their Visibility to False). doc_obj_or_list can be a document object, or a list of document objects""" doc_obj_or_list = self._3D_objects(doc_obj_or_list) # no need to saveBodyVisibleFeature here, as no implicit showing will happen - self.modifyVPProperty(doc_obj_or_list, 'Visibility', False, mild_restore) + self.modifyVPProperty(doc_obj_or_list, "Visibility", False, mild_restore) if links_too: - self.modifyVPProperty(doc_obj_or_list, 'LinkVisibility', False, mild_restore) + self.modifyVPProperty(doc_obj_or_list, "LinkVisibility", False, mild_restore) - def get_all_dependent(self, doc_obj, subname = None): - '''get_all_dependent(doc_obj, subname = None): gets all objects that depend on doc_obj. Containers and Links (if subname) required for visibility of the object are excluded from the list.''' + def get_all_dependent(self, doc_obj, subname=None): + """get_all_dependent(doc_obj, subname = None): gets all objects that depend on doc_obj. Containers and Links (if subname) required for visibility of the object are excluded from the list.""" from . import Containers from .Containers import isAContainer from .DepGraphTools import getAllDependencies, getAllDependent + if subname: # a link-path was provided. doc_obj has nothing to do with the object we want # to collect dependencies from. So, replace it with the one pointed by link-path. @@ -329,48 +357,57 @@ class TempoVis(object): # # I don't know why do we need that isAContainer check here, but I'm leaving it, # realthunder must be knowing his business --DeepSOIC - cnt_chain = [ o for o in cnt_chain - if o==cnt_chain[-1] or isAContainer(o, links_too= True) ] + cnt_chain = [ + o for o in cnt_chain if o == cnt_chain[-1] or isAContainer(o, links_too=True) + ] else: cnt_chain = Containers.ContainerChain(doc_obj) return [o for o in getAllDependent(doc_obj) if not o in cnt_chain] def hide_all_dependent(self, doc_obj): - '''hide_all_dependent(doc_obj): hides all objects that depend on doc_obj. Groups, Parts and Bodies are not hidden by this.''' + """hide_all_dependent(doc_obj): hides all objects that depend on doc_obj. Groups, Parts and Bodies are not hidden by this.""" self.hide(self._3D_objects(self.get_all_dependent(doc_obj))) def show_all_dependent(self, doc_obj): - '''show_all_dependent(doc_obj): shows all objects that depend on doc_obj. This method is probably useless.''' + """show_all_dependent(doc_obj): shows all objects that depend on doc_obj. This method is probably useless.""" from .DepGraphTools import getAllDependencies, getAllDependent + self.show(self._3D_objects(getAllDependent(doc_obj))) def restore_all_dependent(self, doc_obj): - '''show_all_dependent(doc_obj): restores original visibilities of all dependent objects.''' + """show_all_dependent(doc_obj): restores original visibilities of all dependent objects.""" from .DepGraphTools import getAllDependencies, getAllDependent - self.restoreVPProperty( getAllDependent(doc_obj), ('Visibility', 'LinkVisibility') ) + + self.restoreVPProperty(getAllDependent(doc_obj), ("Visibility", "LinkVisibility")) def hide_all_dependencies(self, doc_obj): - '''hide_all_dependencies(doc_obj): hides all objects that doc_obj depends on (directly and indirectly).''' + """hide_all_dependencies(doc_obj): hides all objects that doc_obj depends on (directly and indirectly).""" from .DepGraphTools import getAllDependencies, getAllDependent + self.hide(self._3D_objects(getAllDependencies(doc_obj))) def show_all_dependencies(self, doc_obj): - '''show_all_dependencies(doc_obj): shows all objects that doc_obj depends on (directly and indirectly). This method is probably useless.''' + """show_all_dependencies(doc_obj): shows all objects that doc_obj depends on (directly and indirectly). This method is probably useless.""" from .DepGraphTools import getAllDependencies, getAllDependent + self.show(self._3D_objects(getAllDependencies(doc_obj))) - def saveCamera(self, vw = None): + def saveCamera(self, vw=None): self._change() from .SceneDetails.Camera import Camera + self.save(Camera(self.document)) - def restoreCamera(self, ultimate = False): + def restoreCamera(self, ultimate=False): from .SceneDetails.Camera import Camera + dt = Camera(self.document) self.restoreDetail(dt, ultimate) - def setUnpickable(self, doc_obj_or_list, actual_pick_style = 2): #2 is coin.SoPickStyle.UNPICKABLE - '''setUnpickable(doc_obj_or_list, actual_pick_style = 2): sets object unpickable (transparent to clicks). + def setUnpickable( + self, doc_obj_or_list, actual_pick_style=2 + ): # 2 is coin.SoPickStyle.UNPICKABLE + """setUnpickable(doc_obj_or_list, actual_pick_style = 2): sets object unpickable (transparent to clicks). doc_obj_or_list: object or list of objects to alter (App) actual_pick_style: optional parameter, specifying the actual pick style: 0 = regular, 1 = bounding box, 2 (default) = unpickable. @@ -378,12 +415,12 @@ class TempoVis(object): Implementation detail: uses SoPickStyle node. If viewprovider already has a node of this type as direct child, one is used. Otherwise, new one is created and inserted as the very first node, and remains there even after restore()/deleting - tempovis. ''' + tempovis.""" from .SceneDetails.Pickability import Pickability from .ShowUtils import is3DObject - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] for doc_obj in doc_obj_or_list: if not is3DObject(doc_obj): @@ -391,8 +428,8 @@ class TempoVis(object): dt = Pickability(doc_obj, actual_pick_style) self.modify(dt) - def clipPlane(self, doc_obj_or_list, enable, placement, offset = 0.02): - '''clipPlane(doc_obj_or_list, enable, placement, offset): slices off the object with a clipping plane. + def clipPlane(self, doc_obj_or_list, enable, placement, offset=0.02): + """clipPlane(doc_obj_or_list, enable, placement, offset): slices off the object with a clipping plane. doc_obj_or_list: object or list of objects to alter (App) enable: True if you want clipping, False if you want to remove clipping: placement: XY plane of local coordinates of the placement is the clipping plane. The placement must be in document's global coordinate system. @@ -400,12 +437,12 @@ class TempoVis(object): Implementation detail: uses SoClipPlane node. If viewprovider already has a node of this type as direct child, one is used. Otherwise, new one is created and - inserted as the very first node. The node is left, but disabled when tempovis is restoring.''' + inserted as the very first node. The node is left, but disabled when tempovis is restoring.""" from .SceneDetails.ObjectClipPlane import ObjectClipPlane from .ShowUtils import is3DObject - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] for doc_obj in doc_obj_or_list: if not is3DObject(doc_obj): @@ -415,8 +452,8 @@ class TempoVis(object): @staticmethod def allVisibleObjects(aroundObject): - '''allVisibleObjects(aroundObject): returns list of objects that have to be toggled invisible for only aroundObject to remain. - If a whole container can be made invisible, it is returned, instead of its child objects.''' + """allVisibleObjects(aroundObject): returns list of objects that have to be toggled invisible for only aroundObject to remain. + If a whole container can be made invisible, it is returned, instead of its child objects.""" from .ShowUtils import is3DObject from . import Containers @@ -424,7 +461,7 @@ class TempoVis(object): result = [] for i in range(len(chain)): cnt = chain[i] - cnt_next = chain[i+1] if i+1 < len(chain) else aroundObject + cnt_next = chain[i + 1] if i + 1 < len(chain) else aroundObject container = Containers.Container(cnt) for obj in container.getVisGroupChildren(): if not is3DObject(obj): @@ -434,9 +471,9 @@ class TempoVis(object): result.append(obj) return result - def sketchClipPlane(self, sketch, enable = None, reverted = False): - '''sketchClipPlane(sketch, enable = None): Clips all objects by plane of sketch. - If enable argument is omitted, calling the routine repeatedly will toggle clipping plane.''' + def sketchClipPlane(self, sketch, enable=None, reverted=False): + """sketchClipPlane(sketch, enable = None): Clips all objects by plane of sketch. + If enable argument is omitted, calling the routine repeatedly will toggle clipping plane.""" from .SceneDetails.ClipPlane import ClipPlane @@ -452,32 +489,35 @@ class TempoVis(object): if reverted: pla = pla * App.Rotation(0, 1, 0, 0) - if enable: # clip plane shall be disabled so new placement can be applied + if enable: # clip plane shall be disabled so new placement can be applied self.modify(ClipPlane(doc, 0)) self.modify(ClipPlane(doc, toggle, pla, 0.001)) - sketch.ViewObject.SectionView = enable if enable is not None else not sketch.ViewObject.SectionView + sketch.ViewObject.SectionView = ( + enable if enable is not None else not sketch.ViewObject.SectionView + ) def activateWorkbench(self, wb_name): from .SceneDetails.Workbench import Workbench + self.modify(Workbench(wb_name)) - # + # - # + # def _restoreDetail(self, detail): p = self.data[detail.full_key] - tv1, curr = self._value_after(detail, query_scene= p.mild_restore) + tv1, curr = self._value_after(detail, query_scene=p.mild_restore) if p.mild_restore: if self.data_requested[detail.full_key] != curr: - #the value on the scene doesn't match what was requested through TV. User probably changed it. We don't want to mess it up. + # the value on the scene doesn't match what was requested through TV. User probably changed it. We don't want to mess it up. self._purge_milds(detail) return if tv1 is None: # no other TV has changed this detail later, apply to the scene detail.apply_data(p.data) else: - #modify saved detail of higher TV + # modify saved detail of higher TV tv1.data[detail.full_key].data = p.data def _purge_milds(self, detail): @@ -490,23 +530,24 @@ class TempoVis(object): if tv.data[detail.full_key].mild_restore: tv.forgetDetail(detail) else: - #hard-restoring value encountered, stop + # hard-restoring value encountered, stop break def _change(self): - '''to be called whenever anything is done that is to be restored later.''' + """to be called whenever anything is done that is to be restored later.""" if self.state == S_EMPTY: self.state = S_ACTIVE if self.state == S_RESTORED: Wrn("Attempting to use a TV that has been restored. There must be a problem with code.") self.tv_redo = None - def _value_after(self, detail, query_scene = False): - '''_value_current(detail): returns (tv, detail1). SceneDetail instance holds "current" value of + def _value_after(self, detail, query_scene=False): + """_value_current(detail): returns (tv, detail1). SceneDetail instance holds "current" value of scene detail (current from the context of this TV; i.e. either the current scene status, or the saved state from upper TVs). If no upper TV has saved the detail value, returns either (None, None), or - (None, detail1) if query_scene is True, where detail1 holds value from the scene.''' + (None, detail1) if query_scene is True, where detail1 holds value from the scene.""" + def scene_value(): if query_scene: cpy = copy(detail) @@ -528,7 +569,7 @@ class TempoVis(object): """_3D_objects(doc_obj_or_list): returns list of objects that are in 3d view.""" from .ShowUtils import is3DObject - if not hasattr(doc_obj_or_list, '__iter__'): + if not hasattr(doc_obj_or_list, "__iter__"): doc_obj_or_list = [doc_obj_or_list] return [obj for obj in doc_obj_or_list if is3DObject(obj)]