def RunOrTest(self, b_run): # outline. # 0. user click calls Activated(). # 1. set up self.waiter, which waits for new object to be created # 2. waiter calls Activated() of this command, and knows what object was created # 3. command removes waiter, and calls morphContainer if self.waiter is not None: if self.waiter.is_done: waiter = self.waiter self.waiter = None assert(b_run) #enforce PoM observer to put feature into appropriate container from PartOMagic.Gui import Observer as pomObserver if pomObserver.isRunning(): pomObserver.observerInstance.poll() #check if not Containers.isContainer(waiter.target_container): raise CommandError(self, u"You created {obj}, which isn't a container. Can't morph {src} into {objt}. Morphing canceled." .format(obj= waiter.target_container, objt= waiter.target_container, src= waiter.source_container)) #make sure active container is not being messed with... ac = Containers.activeContainer() if waiter.source_container in Containers.getContainerChain(ac)+[ac]: pomObserver.activateContainer(Containers.getContainer(waiter.source_container)) if waiter.target_container in Containers.getContainerChain(ac)+[ac]: pomObserver.activateContainer(Containers.getContainer(waiter.target_container)) # do it! with Transaction("Morph container"): morphContainer(waiter.source_container, waiter.target_container) return else: raise CommandError(self, "(waiting for new container to be created...)") sel = Gui.Selection.getSelection() if len(sel)==0 : raise CommandError(self, self.GetResources()['ToolTip']) elif len(sel)==1: sel = sel[0] if not Containers.isContainer(sel): raise CommandError(self, "Selected object is not a container") ac = Containers.activeContainer() if sel in Containers.getContainerChain(ac)+[ac]: raise CommandError(self, "Deactivate the container to be morphed first, please.") if b_run: self.waiter = WaitForNewContainer(self, sel) if b_run: Gui.Selection.clearSelection() else: raise CommandError(self, u"You need to select exactly one object (you selected {num}), ad it must be a container.".format(num= len(sel)))
def RunOrTest(self, b_run): if Gui.ActiveDocument: in_edit = Gui.ActiveDocument.getInEdit() if in_edit is not None: raise CommandError( self, u"{object} is currently being edited. Can't enter anything." .format(object=in_edit.Object.Label)) sel = Gui.Selection.getSelection() if len(sel) == 0: raise CommandError( self, "Enter Object command. Please select an object to enter, first. It can be a container, or a sketch." ) elif len(sel) == 1: sel = screen(sel[0]) ac = Containers.activeContainer() if Containers.isContainer(sel): if sel in Containers.getContainerChain(ac) + [ac]: raise CommandError(self, "Already inside this object") if b_run: Containers.setActiveContainer(sel) if b_run: Gui.Selection.clearSelection() else: cnt = Containers.getContainer(sel) if ac is cnt: if b_run: Gui.ActiveDocument.setEdit(sel) else: if b_run: Containers.setActiveContainer(cnt) else: raise CommandError( self, u"Enter Object command. You need to select exactly one object (you selected {num})." .format(num=len(sel)))
def compoundFromAssembly(root, flatten, exclude, recursive = True, visit_set = None): if visit_set is None: visit_set = set() #recursion guard if root in visit_set: raise ValueError("Circular dependency") visit_set.add(root) if hasattr(root, 'Shape'): return root.Shape else: children = Containers.getDirectChildren(root) shapes = [] for child in children: if child in exclude: continue if child.isDerivedFrom('App::Origin'): continue #otherwise, origins create empty compounds - undesirable. if hasattr(child, 'Shape'): shapes.append(child.Shape) elif Containers.isContainer(child) and recursive: cmp = compoundFromAssembly(child, flatten, exclude, recursive, visit_set) if flatten: shapes.extend(cmp.childShapes()) else: shapes.append(cmp) transform = root.Placement if hasattr(root, 'Placement') else None ret = Part.makeCompound(shapes) if transform is not None: ret.Placement = transform return ret
def slotChangedObject(self, feature, prop_name): if prop_name == 'Group': if not Containers.isContainer(feature): return if 'Restore' in feature.State: return if App.GuiUp: global oneshot if oneshot is None or oneshot.is_done: oneshot = DelayedExecute( (lambda doc=feature.Document: updateAllGhosts(doc)), delay=100) else: updateAllGhosts(feature.Document) elif prop_name == 'Placement': if not Containers.isContainer(feature): return if 'Restore' in feature.State: return onContainerPlacementChanged(feature)
def trackExpands(self): docname = App.ActiveDocument.Name for obj in App.ActiveDocument.Objects: objname = obj.Name key = (docname, objname) curstate = 'Expanded' in obj.State oldstate = self.expandedness.get(key, False) if curstate != oldstate: self.expandedness[key] = curstate if GT.isContainer(obj): gc = GenericContainer(obj) gc.ViewObject.call(gc.ViewObject.expandednessChanged, oldstate, curstate)
def RunOrTest(self, b_run): sel = Gui.Selection.getSelection() if len(sel)==0 : raise CommandError(self,"No object selected. Please select something, first.") else: if b_run: new_sel = [] for obj in sel: if Containers.isContainer(obj): new_sel.extend(Containers.getDirectChildren(obj)) else: new_sel.extend(obj.ViewObject.claimChildren()) select(new_sel)
def RunOrTest(self, b_run): sel = Gui.Selection.getSelection() if len(sel) == 0: raise CommandError( self, "No object selected. Please select something, first.") else: if b_run: new_sel = [] for obj in sel: if Containers.isContainer(obj): new_sel.extend(Containers.getDirectChildren(obj)) else: new_sel.extend(obj.ViewObject.claimChildren()) select(new_sel)
def compoundFromAssembly(root, flatten, exclude, recursive=True, visit_set=None): if visit_set is None: visit_set = set() #recursion guard if root in visit_set: raise ValueError("Circular dependency") visit_set.add(root) if has_property(root, 'Shape'): return root.Shape else: children = Containers.getDirectChildren(root) shapes = [] for child in children: if child in exclude: continue if child.isDerivedFrom('App::Origin'): continue #otherwise, origins create empty compounds - undesirable. if has_property( child, 'Shape' ): #since realthunder, Part has Shape attribute, but not Shape property. We want to process Parts ourselves. if not child.Shape.isNull(): shapes.append(child.Shape) elif Containers.isContainer(child) and recursive: cmp = compoundFromAssembly(child, flatten, exclude, recursive, visit_set) if flatten: shapes.extend(cmp.childShapes()) else: shapes.append(cmp) elif hasattr( obj, 'Shape' ): #App::Link may have attribute but not property, and we totally want to include it. if not child.Shape.isNull(): shapes.append(child.Shape) transform = root.Placement if hasattr(root, 'Placement') else None ret = Part.makeCompound(shapes) if transform is not None: ret.Placement = transform return ret
def compoundFromAssembly(root, flatten, exclude, recursive=True, visit_set=None): if visit_set is None: visit_set = set() #recursion guard if root in visit_set: raise ValueError("Circular dependency") visit_set.add(root) if hasattr(root, 'Shape'): return root.Shape else: children = Containers.getDirectChildren(root) shapes = [] for child in children: if child in exclude: continue if child.isDerivedFrom('App::Origin'): continue #otherwise, origins create empty compounds - undesirable. if hasattr(child, 'Shape'): shapes.append(child.Shape) elif Containers.isContainer(child) and recursive: cmp = compoundFromAssembly(child, flatten, exclude, recursive, visit_set) if flatten: shapes.extend(cmp.childShapes()) else: shapes.append(cmp) transform = root.Placement if hasattr(root, 'Placement') else None ret = Part.makeCompound(shapes) if transform is not None: ret.Placement = transform return ret
def RunOrTest(self, b_run): if Gui.ActiveDocument: in_edit = Gui.ActiveDocument.getInEdit() if in_edit is not None: raise CommandError(self, u"{object} is currently being edited. Can't enter anything.".format(object= in_edit.Object.Label)) sel = Gui.Selection.getSelection() if len(sel)==0 : raise CommandError(self, "Enter Object command. Please select an object to enter, first. It can be a container, or a sketch.") elif len(sel)==1: sel = screen(sel[0]) ac = Containers.activeContainer() if Containers.isContainer(sel): if sel in Containers.getContainerChain(ac) + [ac]: raise CommandError(self, "Already inside this object") if b_run: Containers.setActiveContainer(sel) if b_run: Gui.Selection.clearSelection() else: cnt = Containers.getContainer(sel) if ac is cnt: if b_run: Gui.ActiveDocument.setEdit(sel) else: if b_run: Containers.setActiveContainer(cnt) else: raise CommandError(self, u"Enter Object command. You need to select exactly one object (you selected {num}).".format(num= len(sel)))
def morphContainer(src_container, dst_container): if not Containers.isContainer(src_container): raise TypeError(u"{obj} is not a container".format(obj= src_container.Label)) if not Containers.isContainer(dst_container): raise TypeError(u"{obj} is not a container".format(obj= dst_container.Label)) if src_container in Containers.getContainerChain(dst_container): raise Containers.ContainerTreeError(u"Cannot morph {src} into {dst}, because {src} contains {dst}" .format(src= src_container.Label, dst= dst_container.Label)) doc = dst_container.Document #origin... if hasattr(src_container, "Origin") and hasattr(dst_container, "Origin"): if dst_container.Origin is not None: doc.removeObject(dst_container.Origin.Name) dst_container.Origin = src_container.Origin; src_container.Origin = None #content assert(len(dst_container.Group) == 0) g = src_container.Group src_container.Group = [] #withdraw first, add last - otherwise, error is thrown dst_container.Group = g if hasattr(dst_container, 'Origin'): if hasattr(dst_container, 'Proxy') and dst_container.Origin is not None: #workaround for origin not being claimed as child on Py-powered containers dst_container.Group = [dst_container.Origin] + dst_container.Group elif dst_container.Origin is not None and dst_container.Origin in dst_container.Group: #if converting Py cotainer into c++-one, undo the workaround content = dst_container.Group content.remove(dst_container.Origin) #Tip if hasattr(src_container, "Tip") and hasattr(dst_container, "Tip"): tip_list = src_container.Tip if type(tip_list) is not list: tip_list = [tip_list] if tip_list is not None else [] if type(dst_container.Tip) is list: dst_container.Tip = tip_list else: if len(tip_list) == 0: dst_container.Tip = None elif len(tip_list) == 1: dst_container.Tip = tip_list[0] else: App.Console.PrintWarning(u"Target Tip can only point to one object. Source Tip points to {num}. Last object from source tip was taken.\n" .format(num= len(tip_list))) dst_container.Tip = tip_list[-1] #other properties... properties_to_avoid = set([ # these are avoided because they need manual treatment... 'Group', 'Origin', 'ExpressionEngine', 'Tip', 'Label', #.. and these should never be copied at all 'ExtensionProxy', 'Proxy', ]) properties_to_copy = [] for prop in src_container.PropertiesList: if len(src_container.getEditorMode(prop)) == 0: # screen out read-only and hidden properties if not prop in properties_to_avoid: properties_to_copy.append(prop) print("copying properties") for prop in properties_to_copy: print(" "+prop) copyProperty(src_container, dst_container, prop) #Copy expressions for expr in src_container.ExpressionEngine: dst_container.setExpression(*expr) #redirect links substituteObjectInProperties(src_container, dst_container, doc.Objects) substituteObjectInExpressions(src_container, dst_container, doc.Objects) substituteObjectInSpreadsheets(src_container, dst_container, doc.Objects) label = src_container.Label label = label.replace(src_container.Name, dst_container.Name) Containers.withdrawObject(src_container) doc.removeObject(src_container.Name) #copy Label last, because otherwise it gets "001" at the end... dst_container.Label = label
def morphContainer(src_container, dst_container): if not Containers.isContainer(src_container): raise TypeError( u"{obj} is not a container".format(obj=src_container.Label)) if not Containers.isContainer(dst_container): raise TypeError( u"{obj} is not a container".format(obj=dst_container.Label)) if src_container in Containers.getContainerChain(dst_container): raise Containers.ContainerTreeError( u"Cannot morph {src} into {dst}, because {src} contains {dst}". format(src=src_container.Label, dst=dst_container.Label)) doc = dst_container.Document #origin... if hasattr(src_container, "Origin") and hasattr(dst_container, "Origin"): if dst_container.Origin is not None: doc.removeObject(dst_container.Origin.Name) dst_container.Origin = src_container.Origin src_container.Origin = None #content assert (len(dst_container.Group) == 0) g = src_container.Group src_container.Group = [ ] #withdraw first, add last - otherwise, error is thrown dst_container.Group = g if hasattr(dst_container, 'Origin'): if hasattr(dst_container, 'Proxy') and dst_container.Origin is not None: #workaround for origin not being claimed as child on Py-powered containers dst_container.Group = [dst_container.Origin] + dst_container.Group elif dst_container.Origin is not None and dst_container.Origin in dst_container.Group: #if converting Py cotainer into c++-one, undo the workaround content = dst_container.Group content.remove(dst_container.Origin) #Tip if hasattr(src_container, "Tip") and hasattr(dst_container, "Tip"): tip_list = src_container.Tip if type(tip_list) is not list: tip_list = [tip_list] if tip_list is not None else [] if type(dst_container.Tip) is list: dst_container.Tip = tip_list else: if len(tip_list) == 0: dst_container.Tip = None elif len(tip_list) == 1: dst_container.Tip = tip_list[0] else: App.Console.PrintWarning( u"Target Tip can only point to one object. Source Tip points to {num}. Last object from source tip was taken.\n" .format(num=len(tip_list))) dst_container.Tip = tip_list[-1] #other properties... properties_to_avoid = set([ # these are avoided because they need manual treatment... 'Group', 'Origin', 'ExpressionEngine', 'Tip', 'Label', #.. and these should never be copied at all 'ExtensionProxy', 'Proxy', ]) properties_to_copy = [] for prop in src_container.PropertiesList: if len(src_container.getEditorMode( prop)) == 0: # screen out read-only and hidden properties if not prop in properties_to_avoid: properties_to_copy.append(prop) print("copying properties") for prop in properties_to_copy: print(" " + prop) copyProperty(src_container, dst_container, prop) #Copy expressions for expr in src_container.ExpressionEngine: dst_container.setExpression(*expr) #redirect links substituteObjectInProperties(src_container, dst_container, doc.Objects) substituteObjectInExpressions(src_container, dst_container, doc.Objects) substituteObjectInSpreadsheets(src_container, dst_container, doc.Objects) label = src_container.Label label = label.replace(src_container.Name, dst_container.Name) Containers.withdrawObject(src_container) doc.removeObject(src_container.Name) #copy Label last, because otherwise it gets "001" at the end... dst_container.Label = label
def RunOrTest(self, b_run): # outline. # 0. user click calls Activated(). # 1. set up self.waiter, which waits for new object to be created # 2. waiter calls Activated() of this command, and knows what object was created # 3. command removes waiter, and calls morphContainer if self.waiter is not None: if self.waiter.is_done: waiter = self.waiter self.waiter = None assert (b_run) #enforce PoM observer to put feature into appropriate container from PartOMagic.Gui import Observer as pomObserver if pomObserver.isRunning(): pomObserver.observerInstance.poll() #check if not Containers.isContainer(waiter.target_container): raise CommandError( self, u"You created {obj}, which isn't a container. Can't morph {src} into {objt}. Morphing canceled." .format(obj=waiter.target_container, objt=waiter.target_container, src=waiter.source_container)) #make sure active container is not being messed with... ac = Containers.activeContainer() if waiter.source_container in Containers.getContainerChain( ac) + [ac]: pomObserver.activateContainer( Containers.getContainer(waiter.source_container)) if waiter.target_container in Containers.getContainerChain( ac) + [ac]: pomObserver.activateContainer( Containers.getContainer(waiter.target_container)) # do it! with Transaction("Morph container"): morphContainer(waiter.source_container, waiter.target_container) return else: raise CommandError( self, "(waiting for new container to be created...)") sel = Gui.Selection.getSelection() if len(sel) == 0: raise CommandError(self, self.GetResources()['ToolTip']) elif len(sel) == 1: sel = sel[0] if not Containers.isContainer(sel): raise CommandError(self, "Selected object is not a container") ac = Containers.activeContainer() if sel in Containers.getContainerChain(ac) + [ac]: raise CommandError( self, "Deactivate the container to be morphed first, please.") if b_run: self.waiter = WaitForNewContainer(self, sel) if b_run: Gui.Selection.clearSelection() else: raise CommandError( self, u"You need to select exactly one object (you selected {num}), ad it must be a container." .format(num=len(sel)))