Show: Apply clang format

This commit is contained in:
wmayer
2023-09-10 12:19:29 +02:00
committed by wwmayer
parent 546e84d23d
commit 2c3230a986
14 changed files with 346 additions and 251 deletions

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2018 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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: [<document>,<SuperPart>,<Part>,<Body>]'''
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: [<document>,<SuperPart>,<Part>,<Body>]"""
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

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2016 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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 = []

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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
# <interface>
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
# <interface>
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)))
# </interface>
raise TypeError(
"{self} can't be compared with {other}".format(self=repr(self), other=repr(other))
)
# <utility>
# </interface>
# <utility>
@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)

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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)

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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)

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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):

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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)

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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.

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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()

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2019 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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()

View File

@@ -1,4 +1,4 @@
__doc__ = "Show module: helper code for visibility automation."
from .mTempoVis import TempoVis
from . import DepGraphTools
from . import DepGraphTools

View File

@@ -1,4 +1,4 @@
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2016 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
# * *
# * 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 = {}
#<core interface>
def __init__(self, document, stack = MAINSTACK, **kwargs):
# <core interface>
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)
#</core interface>
# </core interface>
#<stack interface>
# <stack interface>
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
#</stack interface>
#<convenience functions>
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
# </stack interface>
# <convenience functions>
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))
#</convenience functions>
# </convenience functions>
#<internals>
# <internals>
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)]