Beispiel #1
0
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
Beispiel #2
0
 def RunOrTest(self, b_run):
     sel = Gui.Selection.getSelection()
     if len(sel)==0 :
         ac = Containers.activeContainer()
         if not hasattr(ac, "Tip"):
             raise CommandError(self,u"{cnt} can't have Tip object (it is not a module or a body).".format(cnt= ac.Label))
         if type(ac.Tip) is list:
             if Gui.ActiveDocument.getInEdit() is not None: 
                 raise CommandError(self,"Please leave editing mode.")
             if b_run: Gui.ActiveDocument.setEdit(ac, 0)
             return
         raise CommandError(self, "Set as Tip command. Please select an object to become Tip, first. The object must be geometry. ")
     elif len(sel)==1:
         sel = screen(sel[0])
         ac = Containers.getContainer(sel)
         if not hasattr(ac, "Tip"):
             raise CommandError(self,u"{cnt} can't have Tip object (it is not a module or a body).".format(cnt= ac.Label))
         if type(ac.Tip) is list:
             if Gui.ActiveDocument.getInEdit() is not None: 
                 raise CommandError(self,"Please leave editing mode.")
             if b_run: Gui.ActiveDocument.setEdit(ac, 0)
         else:
             if not sel in Containers.getDirectChildren(ac):
                 raise CommandError(self, u"{feat} is not from active container ({cnt}). Please select an object belonging to active container.".format(feat= sel.Label, cnt= ac.Label))
             if screen(ac.Tip) is sel:
                 raise CommandError(self, u"{feat} is already a Tip of ({cnt}).".format(feat= sel.Label, cnt= ac.Label))
             if b_run: ac.Tip = sel
     else:
         raise CommandError(self, u"Set as Tip command. You need to select exactly one object (you selected {num}).".format(num= len(sel)))
Beispiel #3
0
 def RunOrTest(self, b_run):
     sel = Gui.Selection.getSelection()
     if len(sel)==0 :
         raise CommandError(self,"No object selected. Please select objects to duplicate, first.")
     else:
         if b_run: 
             (full_list, top_list, implicit_list) = Containers.expandList(sel)
             duplicateObjects(full_list, top_list, Containers.activeContainer())
Beispiel #4
0
 def slotDeletedObject(self, feature):
     print (u"deleted {feat}. container chain: {chain}"
             .format(feat= feature.Name, chain= ".".join([cnt.Name for cnt in GT.getContainerChain(feature)])))
     ac = activeContainer()
     if feature in GT.getContainerChain(ac)+[ac]:
         # active container was deleted. Need to leave it ASAP, as long as we can access the chain
         setActiveContainer(GT.getContainer(feature))
         self.poll()
 def RunOrTest(self, b_run):
     if b_run: 
         sel = set(Gui.Selection.getSelection())
         children = Containers.getDirectChildren(Containers.activeContainer())
         for child in children:
             if child in sel:
                 Gui.Selection.removeSelection(child)
             else:
                 Gui.Selection.addSelection(child)
 def RunOrTest(self, b_run):
     sel = Gui.Selection.getSelection()
     if len(sel)==0 :
         raise CommandError(self,"No object selected. Please select an object from another container, first.")
     elif len(sel)==1:
         sel = sel[0]
         cnt = Containers.getContainer(sel)
         if cnt is Containers.activeContainer():
             raise CommandError(self, "This object is already in active container. Please select an object that is not in active container, or activate another container.")
         if b_run: TransferObject([sel], Containers.activeContainer())
     else:
         # multiple selection. Checking is involved. Let's just assume it's correct.
         if b_run: TransferObject(sel, Containers.activeContainer())
Beispiel #7
0
 def RunOrTest(self, b_run):
     sel = Gui.Selection.getSelection()
     if len(sel)==0 :
         raise CommandError(self, "MUX Assembly command. Please select a Part container, then invoke the tool. A mux object will be created, a compound of all features of Part.")
     elif len(sel)==1:
         sel = sel[0]
         ac = Containers.activeContainer()
         if b_run: 
             if sel in (Containers.getAllDependent(ac)+ [ac]):
                 raise CommandError(self, "Can't create MUX here, because a circular dependency will result.")
             Create(sel)
     else:
         raise CommandError(self, u"MUX Assembly command. You need to select exactly one object (you selected {num}).".format(num= len(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)
Beispiel #9
0
 def RunOrTest(self, b_run):
     sel = Gui.Selection.getSelection()
     if len(sel)==0 :
         raise CommandError(self, "Shapebinder command. Please select an object to import to active container, first. The object must be geometry.")
     elif len(sel)==1:
         sel = screen(sel[0])
         ac = Containers.activeContainer()
         if sel in Containers.getDirectChildren(ac):
             raise CommandError(self, u"{feat} is from active container ({cnt}). Please select an object belonging to another container.".format(feat= sel.Label, cnt= ac.Label))
         if sel in (Containers.getAllDependent(ac)+ [ac]):
             raise CommandError(self, "Can't create a shapebinder, because a circular dependency will result.")
         if b_run: CreateShapeBinder(sel)
     else:
         raise CommandError(self, u"Shapebinder command. You need to select exactly one object (you selected {num}).".format(num= len(sel)))
Beispiel #10
0
def duplicateObjects(objects, top_objects, target_cnt):
    with Transaction("PoM Duplicate"):
        keeper = Observer.suspend()
        
        objset = set(objects)
        doc = objects[0].Document
        namelist = [obj.Name for obj in doc.TopologicalSortedObjects if obj in objset][::-1]
        
        tmp_prj = FCProject.fromFC(doc, namelist)
        map = tmp_prj.mergeToFC(doc)
        for obj in top_objects:
            new_top_obj = doc.getObject(map[obj.Name])
            Containers.addObjectTo(target_cnt, new_top_obj, b_advance_tip= True)
        keeper.release()
Beispiel #11
0
 def enterContainer(self, cnt):
     '''enterContainer(self, cnt): when cnt either directly is being activated, or one of its child containers is being activated. Assumes container of cnt is already entered.'''
     print ("entering "+cnt.Name)
     if cnt.isDerivedFrom("App::Document"): # may happen when creating new document. Ignoring.
         return
     key = cnt.Document.Name+"."+cnt.Name
     if key in self.TVs:
         # just in case old tempovis associated with the container wasn't removed for some reason.
         self.TVs[key].forget()
     tv = TempoVis(cnt.Document)
     self.TVs[key] = tv
     list_hiding = [o for o in GT.getDirectChildren(GT.getContainer(cnt)) if not o is cnt]
     list_hiding = [o for o in list_hiding if not o.isDerivedFrom('App::DocumentObjectGroup')] # don't touch visibility of groups just yet...
     tv.hide(list_hiding)
     tv.show(cnt)
Beispiel #12
0
 def activeContainerChanged(self, oldContainer, newContainer):
     n1 = "None"
     n2 = "None"
     if oldContainer:
         n1 = oldContainer.Name
     if newContainer:
         n2 = newContainer.Name
     print(u"container changed from {c1} to {c2}".format(c1= n1, c2= n2))
     
     if oldContainer is None: #happens when creating new document
         return
         
     chain_from, chain_to = GT.getContainerRelativePath(oldContainer, newContainer)
     for cnt in chain_from[::-1]:
         try:
             gc = GenericContainer(cnt)
             gc.ViewObject.call(gc.ViewObject.activationChanged, oldContainer, newContainer, event= -1)
         except Exception as err:
             App.Console.PrintError(u"Error deactivating container '{cnt}': {err}".format(cnt= cnt.Label, err= err.message))
         self.leaveContainer(cnt)
     for cnt in chain_to:
         try:
             gc = GenericContainer(cnt)
             gc.ViewObject.call(gc.ViewObject.activationChanged, oldContainer, newContainer, event= +1)
         except Exception as err:
             App.Console.PrintError(u"Error activating container '{cnt}': {err}".format(cnt= cnt.Label, err= err.message))
         self.enterContainer(cnt)
     
     self.updateVPs()
Beispiel #13
0
 def fillList(self):
     lw = self.form.treeR
     lw.clear()
     lw.setColumnCount(len(self.columns))
     lw.setHeaderLabels(self.column_titles)
     for repl in self.replacements:
         item = QtGui.QTreeWidgetItem(lw)
         
         item.setText(self.column['Kind'], repl.relation.kind)
         item.setText(self.column['Object'], repl.relation.linking_object.Label)
         item.setText(self.column['Property'], repl.relation.linking_property)
         try:
             chain = Containers.getContainerChain(repl.relation.linking_object)[1:] + [repl.relation.linking_object] #[1:] strips off project name, to unclutter the column.
             path = '.'.join([cnt.Name for cnt in chain])
         except Exception as err:
             import traceback
             tb = traceback.format_exc()
             App.Console.PrintError(tb+'\n\n')
             path = "!" + str(err)
         item.setText(self.column['Path'], path)
         item.setText(self.column['Value'], str(repl.relation.value_repr))
         
         repl.gui_item = item
         item.setData(0,256,repl)
         flags = Qt.ItemIsUserCheckable | Qt.ItemIsSelectable
         if not repl.disabled:
             flags = flags | Qt.ItemIsEnabled
         item.setFlags(flags)
         item.setCheckState(0, Qt.Checked if repl.checked else Qt.Unchecked)
         if repl.disabled:
             item.setText(self.column['State'], repl.disabled_reason)
Beispiel #14
0
 def updateVPs(self):
     '''updates many viewprovider properties (except visibility, which is handled by TempoVis objets)'''
     ac = activeContainer()
     
     if ac.isDerivedFrom("App::Document"):
         objects_in = set(App.ActiveDocument.Objects)
     else:
         objects_in = set(  GT.getDirectChildren(ac)  )
     objects_out = set(App.ActiveDocument.Objects) - objects_in
     
     # make all object in context selectable. This is mainly to undo consequences of old behavior of making everything out-of-context non-selectable
     for o in objects_in:
         if hasattr(o.ViewObject, "Selectable"):
             o.ViewObject.Selectable = True
     
     for o in App.ActiveDocument.findObjects("App::Origin"):
         o.ViewObject.Visibility = GT.getContainer(o) is ac
Beispiel #15
0
 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: 
             (full_list, top_list, implicit_list) = Containers.expandList(sel)
             select(implicit_list)
Beispiel #16
0
 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)))
Beispiel #17
0
 def RunOrTest(self, b_run):
     if Gui.ActiveDocument.getInEdit() is not None:
         if b_run: 
             Gui.ActiveDocument.resetEdit()
             App.ActiveDocument.recompute()
             App.ActiveDocument.commitTransaction()
     elif Gui.Control.activeDialog():
         if b_run:
             Gui.Control.closeDialog()
             App.ActiveDocument.recompute()
             App.ActiveDocument.commitTransaction()
     else:
         ac = Containers.activeContainer()
         if ac.isDerivedFrom("App::Document"):
             raise CommandError(self, "Nothing to leave.")
         if b_run: Containers.setActiveContainer(Containers.getContainer(ac))
         if b_run: Gui.Selection.clearSelection()
         if b_run: Gui.Selection.addSelection(ac)    
         if b_run: App.ActiveDocument.recompute() #fixme: scoped recompute, maybe?
Beispiel #18
0
 def check_dag(self):
     """check_dag(): returns True if DAG-compatible, and False otherwise. Note that it may be wrong for mass-replacements"""
     if replaced:
         raise AlreadyReplacedError("Replacement already done, can't check.")
     if self.new_object is None: 
         return True
     import Containers
     deps = Containers.getAllDependent(self.relation.linking_object)
     if self.new_object in deps: 
         return False
     return True
Beispiel #19
0
 def containerAdded(self):
     App.removeDocumentObserver(self)
     for obj in self.new_objects:
         if Containers.canBeActive(obj):
             if self.target_container is not None:
                 raise CommandError(self.command, "More than one container was created. I have no idea what to do! --Part-o-Magic")
             self.target_container = obj #if multiple objects had been created, pick one that is a container
     if self.target_container is None:
         self.target_container = self.new_objects[0] #return something... so that an error message is displayed.
     self.is_done = True
     self.command.Activated()
Beispiel #20
0
 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)
Beispiel #21
0
def addObjectTo(container, feature):
    if hasattr(App, 'ActiveContainer'):
        # New FreeCAD. Feature is added to the container automatically. All that's left to do is call advanceTip().
        return container

    if container.isDerivedFrom("App::Document"):
        return container
    
    # close editing before addition.
    #  Adding to container while editing causes editing to close anyway. But we want do do 
    #  that ourself, so that we know that we need to re-open it.
    bool_editingclosed = False
    if hasattr(Gui.ActiveDocument,"getInEdit"):
        if Gui.ActiveDocument.getInEdit():
            if Gui.ActiveDocument.getInEdit().Object is feature:
                Gui.ActiveDocument.resetEdit()
                bool_editingclosed = True
    
    #actual addition
    added = False
    actual_container = container
    while not added:
        try:
            GT.addObjectTo(actual_container, feature, b_advance_tip = False)
            added = True
        except App.Base.FreeCADError as err:
            #assuming it's a "not allowed" error
            #try adding to upper level container. Until Document is reached, which should never fail with FreeCADError
            actual_container = GT.getContainer(actual_container)
    if actual_container is not container:
        msgbox("Part-o-magic",u"Cannot add the new object of type {typ} to '{container}'. Feature added to '{actual_container}' instead."
                              .format(container= container.Label, actual_container= actual_container.Label, typ= feature.TypeId))
        
    # re-open editing that we had closed...
    if bool_editingclosed:
        Gui.ActiveDocument.setEdit(feature)
    
    return actual_container
Beispiel #22
0
def addObjectTo(container, feature):
    if hasattr(App, 'ActiveContainer'):
        # New FreeCAD. Feature is added to the container automatically. All that's left to do is call advanceTip().
        return container

    if container.isDerivedFrom("App::Document"):
        return container
    
    # close editing before addition.
    #  Adding to container while editing causes editing to close anyway. But we want do do 
    #  that ourself, so that we know that we need to re-open it.
    bool_editingclosed = False
    if hasattr(Gui.ActiveDocument,"getInEdit"):
        if Gui.ActiveDocument.getInEdit():
            if Gui.ActiveDocument.getInEdit().Object is feature:
                Gui.ActiveDocument.resetEdit()
                bool_editingclosed = True
    
    #actual addition
    added = False
    actual_container = container
    while not added:
        try:
            GT.addObjectTo(actual_container, feature, b_advance_tip = False)
            added = True
        except App.Base.FreeCADError as err:
            #assuming it's a "not allowed" error
            #try adding to upper level container. Until Document is reached, which should never fail with FreeCADError
            actual_container = GT.getContainer(actual_container)
    if actual_container is not container:
        msgbox("Part-o-magic",u"Cannot add the new object of type {typ} to '{container}'. Feature added to '{actual_container}' instead."
                              .format(container= container.Label, actual_container= actual_container.Label, typ= feature.TypeId))
        
    # re-open editing that we had closed...
    if bool_editingclosed:
        Gui.ActiveDocument.setEdit(feature)
    
    return actual_container
Beispiel #23
0
 def enterContainer(self, cnt):
     '''enterContainer(self, cnt): when cnt either directly is being activated, or one of its child containers is being activated. Assumes container of cnt is already entered.'''
     print("entering " + cnt.Name)
     if cnt.isDerivedFrom(
             "App::Document"
     ):  # may happen when creating new document. Ignoring.
         return
     key = cnt.Document.Name + "." + cnt.Name
     if key in self.TVs:
         # just in case old tempovis associated with the container wasn't removed for some reason.
         self.TVs[key].forget()
     tv = TempoVis(cnt.Document)
     self.TVs[key] = tv
     list_hiding = [
         o for o in GT.getDirectChildren(GT.getContainer(cnt))
         if not o is cnt
     ]
     list_hiding = [
         o for o in list_hiding
         if not o.isDerivedFrom('App::DocumentObjectGroup')
     ]  # don't touch visibility of groups just yet...
     tv.hide(list_hiding)
     tv.show(cnt)
Beispiel #24
0
    def setEdit(self, selfvp, mode):
        print("ShapeGroup enter edit mode {num}".format(num= mode))
        if mode == 0:
            try:
                selfobj = selfvp.Object
                #ensure right container is active
                from PartOMagic.Base import Containers
                container = Containers.getContainer(selfobj)
                if Containers.activeContainer() is not Containers.getContainer(selfobj):
                    from PartOMagic.Gui import Observer
                    Observer.activateContainer(container)

                selfobj.Document.openTransaction(u'Edit Tip of {sg}'.format(sg= selfobj.Label))
                
                #prepare scene
                from PartOMagic.Gui.TempoVis import TempoVis
                self.tv = TempoVis(selfobj.Document)
                tv = self.tv
                #update visibilities of children to match what's in tip
                children = selfobj.Group
                tip = selfobj.Tip
                for child in children:
                    tv.modifyVPProperty(child, 'Visibility', child in tip)
                #ensure children are visible, and nothing else...
                tv.modifyVPProperty(selfobj, 'DisplayMode','Group')
                tv.show(selfobj)
                for child in Containers.getDirectChildren(container):
                    if child is not selfobj:
                        tv.hide(child)
                
                #start editing
                self.observer = VisibilityObserver(selfobj.Group, self.editCallback)
            except Exception as err:
                App.Console.PrintError(u"Error in ShapeGroup setEdit: {err}\n".format(err= err.message))
                return False
            return True
        raise NotImplementedError()
Beispiel #25
0
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
Beispiel #26
0
    def setEdit(self, selfvp, mode):
        print("ShapeGroup enter edit mode {num}".format(num= mode))
        if mode == 0:
            try:
                selfobj = selfvp.Object
                #ensure right container is active
                from PartOMagic.Base import Containers
                container = Containers.getContainer(selfobj)
                if Containers.activeContainer() is not Containers.getContainer(selfobj):
                    from PartOMagic.Gui import Observer
                    Observer.activateContainer(container)

                selfobj.Document.openTransaction(u'Edit Tip of {sg}'.format(sg= selfobj.Label))
                
                #prepare scene
                from PartOMagic.Gui.TempoVis import TempoVis
                self.tv = TempoVis(selfobj.Document)
                tv = self.tv
                #update visibilities of children to match what's in tip
                children = selfobj.Group
                tip = selfobj.Tip
                for child in children:
                    tv.modifyVPProperty(child, 'Visibility', child in tip)
                #ensure children are visible, and nothing else...
                tv.modifyVPProperty(selfobj, 'DisplayMode','Group')
                tv.show(selfobj)
                for child in Containers.getDirectChildren(container):
                    if child is not selfobj:
                        tv.hide(child)
                
                #start editing
                self.observer = VisibilityObserver(selfobj.Group, self.editCallback)
            except Exception as err:
                App.Console.PrintError(u"Error in ShapeGroup setEdit: {err}\n".format(err= err.message))
                return False
            return True
        raise NotImplementedError()
Beispiel #27
0
 def slotStartEditing(self, feature):
     print(u"Start Editing {f}".format(f=feature.Name))
     cnt = GT.getContainer(feature)
     # if GT.activeContainer() is not cnt:
     #     print(u"Feature being edited is not in active container. Activating {cnt}...".format(cnt= cnt.Name))
     #     Gui.ActiveDocument.resetEdit()
     #     GT.setActiveContainer(cnt)
     #     return
     if feature.isDerivedFrom("PartDesign::Boolean"):
         # show all bodies nearby...
         part = GT.getContainer(cnt)
         children = GT.getDirectChildren(part)
         children = [
             child for child in children
             if child.isDerivedFrom("Part::BodyBase")
         ]
         children = set(children)
         children.remove(cnt)
         for obj in GT.getAllDependent(cnt):
             if obj in children:
                 children.remove(obj)
         tv = TempoVis(feature.Document)
         tv.show(children)
         self.edit_TVs[feature.Document.Name] = tv
Beispiel #28
0
 def onDelete(self, viewprovider, subelements): # subelements is a tuple of strings
     try:
         selfobj = self.Object
         import PartOMagic.Base.Containers as Containers
         body = Containers.getContainer(selfobj)
         if not body.isDerivedFrom('PartDesign::Body'): return
         
         if self.ViewObject.Visibility and selfobj.BaseFeature:
             selfobj.BaseFeature.ViewObject.show()
             
         body.removeObject(selfobj)
         
     except Exception as err:
         App.Console.PrintError("Error in onDelete: " + err.message)
     return True
Beispiel #29
0
 def containerAdded(self):
     App.removeDocumentObserver(self)
     for obj in self.new_objects:
         if Containers.canBeActive(obj):
             if self.target_container is not None:
                 raise CommandError(
                     self.command,
                     "More than one container was created. I have no idea what to do! --Part-o-Magic"
                 )
             self.target_container = obj  #if multiple objects had been created, pick one that is a container
     if self.target_container is None:
         self.target_container = self.new_objects[
             0]  #return something... so that an error message is displayed.
     self.is_done = True
     self.command.Activated()
Beispiel #30
0
 def onDelete(self, viewprovider, subelements): # subelements is a tuple of strings
     try:
         selfobj = self.Object
         import PartOMagic.Base.Containers as Containers
         body = Containers.getContainer(selfobj)
         if not body.isDerivedFrom('PartDesign::Body'): return
         
         if self.ViewObject.Visibility and selfobj.BaseFeature:
             selfobj.BaseFeature.ViewObject.show()
             
         body.removeObject(selfobj)
         
     except Exception as err:
         App.Console.PrintError("Error in onDelete: " + err.message)
     return True
Beispiel #31
0
    def activeContainerChanged(self, oldContainer, newContainer):
        n1 = "None"
        n2 = "None"
        if oldContainer:
            n1 = oldContainer.Name
        if newContainer:
            n2 = newContainer.Name
        print(u"container changed from {c1} to {c2}".format(c1=n1, c2=n2))

        if oldContainer is None:  #happens when creating new document
            return

        chain_from, chain_to = GT.getContainerRelativePath(
            oldContainer, newContainer)
        for cnt in chain_from[::-1]:
            try:
                gc = GenericContainer(cnt)
                gc.ViewObject.call(gc.ViewObject.activationChanged,
                                   oldContainer,
                                   newContainer,
                                   event=-1)
            except Exception as err:
                App.Console.PrintError(
                    u"Error deactivating container '{cnt}': {err}".format(
                        cnt=cnt.Label, err=err.message))
            self.leaveContainer(cnt)
        for cnt in chain_to:
            try:
                gc = GenericContainer(cnt)
                gc.ViewObject.call(gc.ViewObject.activationChanged,
                                   oldContainer,
                                   newContainer,
                                   event=+1)
            except Exception as err:
                App.Console.PrintError(
                    u"Error activating container '{cnt}': {err}".format(
                        cnt=cnt.Label, err=err.message))
            self.enterContainer(cnt)

        self.updateVPs()
Beispiel #32
0
 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)))            
Beispiel #33
0
 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)))            
Beispiel #34
0
 def slotStartEditing(self, feature):
     print(u"Start Editing {f}".format(f= feature.Name))
     cnt = GT.getContainer(feature)
     if GT.activeContainer() is not cnt:
         print(u"Feature being edited is not in active container. Activating {cnt}...".format(cnt= cnt.Name))
         Gui.ActiveDocument.resetEdit()
         GT.setActiveContainer(cnt)
         return
     if feature.isDerivedFrom("PartDesign::Boolean"):
         # show all bodies nearby...
         part = GT.getContainer(cnt)
         children = GT.getDirectChildren(part)
         children = [child for child in children if child.isDerivedFrom("Part::BodyBase")]
         children = set(children)
         children.remove(cnt)
         for obj in GT.getAllDependent(cnt):
             if obj in children:
                 children.remove(obj)
         tv = TempoVis(feature.Document)
         tv.show(children)
         self.edit_TVs[feature.Document.Name] = tv
Beispiel #35
0
    def fillList(self):
        lw = self.form.treeR
        lw.clear()
        lw.setColumnCount(len(self.columns))
        lw.setHeaderLabels(self.column_titles)
        for repl in self.replacements:
            item = QtGui.QTreeWidgetItem(lw)

            item.setText(self.column['Kind'], repl.relation.kind)
            item.setText(self.column['Object'],
                         repl.relation.linking_object.Label)
            item.setText(self.column['Property'],
                         repl.relation.linking_property)
            try:
                chain = Containers.getContainerChain(
                    repl.relation.linking_object)[1:] + [
                        repl.relation.linking_object
                    ]  #[1:] strips off project name, to unclutter the column.
                path = '.'.join([cnt.Name for cnt in chain])
            except Exception as err:
                import traceback
                tb = traceback.format_exc()
                App.Console.PrintError(tb + '\n\n')
                path = "!" + str(err)
            item.setText(self.column['Path'], path)
            item.setText(self.column['Value'], str(repl.relation.value_repr))

            repl.gui_item = item
            item.setData(0, 256, repl)
            flags = Qt.ItemIsUserCheckable | Qt.ItemIsSelectable
            if not repl.disabled:
                flags = flags | Qt.ItemIsEnabled
            item.setFlags(flags)
            item.setCheckState(0, Qt.Checked if repl.checked else Qt.Unchecked)
            if repl.disabled:
                item.setText(self.column['State'], repl.disabled_reason)
Beispiel #36
0
 def expandednessChanged(self, old_state, new_state):
     ac = Containers.activeContainer()
     activeChain = Containers.getContainerChain(ac) + [ac]
     self.call(
         self.doDisplayModeAutomation, ac, ac, +1 if new_state == True else
         (0 if self.selfobj in activeChain else -1))
Beispiel #37
0
def getPartOf(feature):
    chain = GT.getContainerChain(feature)
    for cnt in chain[::-1]:
        if not cnt.isDerivedFrom("PartDesign::Body"):
            return cnt
    assert(False)
Beispiel #38
0
def getPartOf(feature):
    chain = GT.getContainerChain(feature)
    for cnt in chain[::-1]:
        if not cnt.isDerivedFrom("PartDesign::Body"):
            return cnt
    assert(False)
Beispiel #39
0
 def slotDeletedObject(self, feature):
     ac = activeContainer()
     if feature in GT.getContainerChain(ac)+[ac]:
         # active container was deleted. Need to leave it ASAP, as long as we can access the chain
         setActiveContainer(GT.getContainer(feature))
         self.poll()
Beispiel #40
0
 def doubleClicked(self, vobj):
     Containers.setActiveContainer(Containers.getContainer(
         vobj.Object.Base))
     return True
Beispiel #41
0
 def addObjectVars(obj):
     vardict['object_name'             ] = obj.Name
     vardict['object_label'            ] = obj.Label
     vardict['object_container_label'  ] = Containers.getContainer(obj).Label
     vardict['object_container_name'   ] = Containers.getContainer(obj).Name
Beispiel #42
0
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
Beispiel #43
0
 def RunOrTest(self, b_run):
     if b_run:
         children = Containers.getDirectChildren(
             Containers.activeContainer())
         select(children)
Beispiel #44
0
def TransferObject(objects, target_cnt):
    with Transaction("Transfer object"):
        for obj in objects:
            Containers.moveObjectTo(obj, target_cnt)
Beispiel #45
0
    def _replace(self, check_dag):
        # does the business of replacing. But does not set self.replaced flag, so that I can use return statement without caution.
        prop = self.relation.linking_property
        new = self.new_object
        obj = self.relation.linking_object
        kind = self.relation.kind

        printLog(u"  replacing: {self}\n".format(self=self))
        if check_dag:
            if self.check_dag() == False:
                raise DAGError(
                    u"Replacement will cause a cycle: {repl}".format(
                        repl=repr(self)))

        try:
            self.relation.self_check()
        except ExpressionGoneError:
            if new is None:
                return  #during mass-replacements with no new object, expression may have been gone already as a result of previous replacement. Skip this.
            raise

        if kind == 'CellExpression':
            if self.relation.linked_object is self.new_object:
                printWarn(
                    u"Replacement invoked, but nothing to do. {self}".format(
                        self=repr(self)))
                return  #nothing to do
            range = self.relation.expression_charrange
            oldexpr = obj.getContents(prop)  #raises ValueError if not a cell
            if len(oldexpr) == 0 and new is None:
                return  #during mass-replacements with no new object, expression may have been gone already as a result of previous replacement. Skip this.
            if not oldexpr.startswith('='):
                raise ReplacementError("No expression found for replacement")
            if new is not None:
                newexpr = oldexpr[0:range[0]] + new.Name + oldexpr[range[1]:]
            else:
                newexpr = ''

            if newexpr is not None:
                printLog(u"    '{oldexpr}' -> '{newexpr}'\n".format(
                    oldexpr=oldexpr, newexpr=newexpr))
                obj.set(prop, newexpr)
        elif kind == 'Expression':
            if self.relation.linked_object is self.new_object:
                printWarn(
                    u"Replacement invoked, but nothing to do. {self}".format(
                        self=repr(self)))
                return  #nothing to do
            ee = dict(obj.ExpressionEngine)
            if not prop in ee and new is None:
                return  #during mass-replacements with no new object, expression may have been gone already as a result of previous replacement. Skip this.
            if not prop in ee:
                raise ReplacementError("No expression found for replacement")
            oldexpr = ee[prop]
            range = self.relation.expression_charrange
            if new is not None:
                newexpr = oldexpr[0:range[0]] + new.Name + oldexpr[range[1]:]
            else:
                newexpr = ''
            if newexpr is not None:
                printLog(u"    '{oldexpr}' -> '{newexpr}'\n".format(
                    oldexpr=oldexpr, newexpr=newexpr))
                obj.setExpression(prop, newexpr)
        elif kind == 'Child' or kind == 'Link':
            if self.relation.linked_object is self.new_object:
                printWarn(
                    u"Replacement invoked, but nothing to do. {self}".format(
                        self=repr(self)))
                return  #nothing to do
            if kind == 'Child':
                #when replacing child links, make sure the new object is not in a container. Otherwise FreeCAD throws an error.
                from PartOMagic.Base import Containers
                Containers.withdrawObject(new)
            typ = obj.getTypeIdOfProperty(prop)
            val = getattr(obj, prop)
            if typ.startswith('App::PropertyLinkList'):
                val = val[0:self.relation.list_index] + (
                    [] if new is None else
                    [new]) + val[self.relation.list_index + 1:]
            elif typ.startswith('App::PropertyLink'):
                val = new
            else:
                raise TypeError(
                    u"Unexpected type of property: {typ}".format(typ=typ))
            setattr(obj, prop, val)
        elif kind == 'Sublink':
            typ = obj.getTypeIdOfProperty(prop)
            val = getattr(obj, prop)
            if self.relation.linked_object is self.new_object and (
                    self.new_sublist is None
                    or self.relation.sublist == self.new_sublist):
                printWarn(
                    u'Replacement invoked, but nothing to do. {self}'.format(
                        self=repr(self)))
                return  #nothing to do

            sublist = self.new_sublist if self.new_sublist is not None else self.relation.sublist
            if typ.startswith('App::PropertyLinkSubList'):
                val = val[0:self.relation.list_index] + [
                    (new, sublist)
                ] + val[self.relation.list_index + 1:]
            elif typ.startswith('App::PropertyLinkSub'):
                val = (new, sublist)
            else:
                raise TypeError(
                    u"Unexpected type of property: {typ}".format(typ=typ))
            setattr(obj, prop, val)
        else:
            raise TypeError(
                u"Unexpected kind of dependency: {kind}".format(kind=kind))
Beispiel #46
0
def TransferObject(objects, target_cnt):
    with Transaction("Transfer object"):
        for obj in objects:
            Containers.moveObjectTo(obj, target_cnt)
Beispiel #47
0
 def addObjectVars(obj):
     vardict['object_name'             ] = obj.Name
     vardict['object_label'            ] = obj.Label
     vardict['object_container_label'  ] = Containers.getContainer(obj).Label
     vardict['object_container_name'   ] = Containers.getContainer(obj).Name
Beispiel #48
0
 def export(self, selfobj):
     #check the model
     from PartOMagic.Base import Containers
     for obj in Containers.getAllDependencies(selfobj):
         if 'Invalid' in obj.State:
             raise RuntimeError(u"File not exported, because {feat} is in error state.".format(feat= obj.Label))
 
     #form absolute path
     filepath = selfobj.FilePath
     
     from os import path
     extension = path.splitext(filepath)[1][1:]
     if len(extension)<1:
         raise ValueError("File has no extension, can't determine export type.")
     
     self.fetchModule(selfobj)
     import importlib
     mod = importlib.import_module(selfobj.UsingModule)
     
     
     if not path.isabs(filepath):
         if len(selfobj.Document.FileName)==0:
             raise ValueError("Can't save to a relative path, because the project is not saved to a file.")
         context = path.dirname(selfobj.Document.FileName)
         filepath = path.join(context, filepath)
     
     #collect what to export
     objects_to_export = []
     containermode = selfobj.ContainerMode
     if hasattr(selfobj.ObjectToExport, "Group"):
         if containermode == '(Auto)':
             if hasattr(selfobj.ObjectToExport, 'Shape'):
                 containermode = 'Feed straight to exporter' 
             elif hasattr(selfobj.ObjectToExport, 'Tip'):
                 containermode = 'Feed tip features to exporter'
             else:
                 containermode = 'Feed all children'
             selfobj.ContainerMode = containermode
         if containermode == 'Feed straight to exporter':
             objects_to_export.append(selfobj.ObjectToExport)
         elif containermode == 'Feed tip features to exporter':
             objects_to_export += selfobj.ObjectToExport.Tip if type(selfobj.ObjectToExport.Tip) is list else [selfobj.ObjectToExport.Tip]
         elif containermode == 'Feed all children':
             objects_to_export += selfobj.ObjectToExport.Group
         else: 
             raise NotImplementedError(u"Unexpected contaner mode {mode}".format(mode= repr(containermode)))
     else:
         objects_to_export.append(selfobj.ObjectToExport)
     
     if selfobj.MeshAccuracy > 1e-7:
         for obj in objects_to_export:
             if hasattr(obj, 'Shape'):
                 obj.Shape.tessellate(selfobj.MeshAccuracy)
             else:
                 App.Console.PrintWarning(u"Exporter {exporter}: object to export ({object}) has no b-rep shape. Can't re-tessellate."
                                           .format(exporter= selfobj.Name, object= obj.Label))
     
     vardict = {
         'project_name'               : selfobj.Document.Name,
         'project_filetitle'          : path.splitext(path.basename(selfobj.Document.FileName))[0],
         'project_filename'           : path.basename(selfobj.Document.FileName),
         'project_folder'             : path.split(path.split(selfobj.Document.FileName)[0])[1],
         'project_label'              : selfobj.Document.Label,
         'exporter_label'             : selfobj.Label,
         'exporter_name'              : selfobj.Name,
         'exporter_container_label'   : Containers.getContainer(selfobj).Label,
         'exporter_container_name'    : Containers.getContainer(selfobj).Name,
     }
     
     def addObjectVars(obj):
         vardict['object_name'             ] = obj.Name
         vardict['object_label'            ] = obj.Label
         vardict['object_container_label'  ] = Containers.getContainer(obj).Label
         vardict['object_container_name'   ] = Containers.getContainer(obj).Name
     
     try:
         if selfobj.MultiMode == 'Write one file':
             addObjectVars(selfobj.ObjectToExport)
             filepath = filepath.replace('%Label%', selfobj.ObjectToExport.Label).format(**vardict)
             mod.export(objects_to_export, filepath)
             print(u"Exported {file}".format(file= filepath))
             if selfobj.FullActualPath != filepath: #check, to avoid touching all exporters upon every file save
                 selfobj.FullActualPath = filepath
         elif selfobj.MultiMode == 'Write many files':
             files_written = set()
             for obj in objects_to_export:
                 addObjectVars(obj)
                 thisfilepath = filepath.replace('%Label%', obj.Label).format(**vardict)
                 if thisfilepath in files_written:
                     raise ValueError(u'Exporter {exporter} is supposed to write multiple files, but the filenames repeat: {fn}. Please make sure a variable is used in the file name, such as {{object_name}}, or {{object_label}}.'
                         .format(exporter= selfobj.Label, fn= thisfilepath))
                 mod.export([obj], thisfilepath)
                 print(u"Exported {file}".format(file= thisfilepath))
             if selfobj.FullActualPath != thisfilepath: #check, to avoid touching all exporters upon every file save
                 selfobj.FullActualPath = thisfilepath
         else:
             raise NotImplementedError(u"Unexpected MultiMode: {mode}".format(mode= repr(selfobj.MultiMode)))
     except KeyError as ke:
         key = ke.args[0]
         message = (u'Variable name not recognized: {key}.\n\nVariables available:\n{varlist}'
             .format(
                 key= key,
                 varlist = '\n'.join(['{' + var + '}' + ': ' + vardict[var] for var in vardict])
             )
         )
         raise KeyError(message)
Beispiel #49
0
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
Beispiel #50
0
 def export(self, selfobj):
     #check the model
     from PartOMagic.Base import Containers
     for obj in Containers.getAllDependencies(selfobj):
         if 'Invalid' in obj.State:
             raise RuntimeError(u"File not exported, because {feat} is in error state.".format(feat= obj.Label))
 
     #form absolute path
     filepath = selfobj.FilePath
     
     from os import path
     extension = path.splitext(filepath)[1][1:]
     if len(extension)<1:
         raise ValueError("File has no extension, can't determine export type.")
     
     self.fetchModule(selfobj)
     import importlib
     mod = importlib.import_module(selfobj.UsingModule)
     
     
     if not path.isabs(filepath):
         if len(selfobj.Document.FileName)==0:
             raise ValueError("Can't save to a relative path, because the project is not saved to a file.")
         context = path.dirname(selfobj.Document.FileName)
         filepath = path.join(context, filepath)
     
     #collect what to export
     objects_to_export = []
     containermode = selfobj.ContainerMode
     if hasattr(selfobj.ObjectToExport, "Group"):
         if containermode == '(Auto)':
             if hasattr(selfobj.ObjectToExport, 'Shape'):
                 containermode = 'Feed straight to exporter' 
             elif hasattr(selfobj.ObjectToExport, 'Tip'):
                 containermode = 'Feed tip features to exporter'
             else:
                 containermode = 'Feed all children'
             selfobj.ContainerMode = containermode
         if containermode == 'Feed straight to exporter':
             objects_to_export.append(selfobj.ObjectToExport)
         elif containermode == 'Feed tip features to exporter':
             objects_to_export += selfobj.ObjectToExport.Tip if type(selfobj.ObjectToExport.Tip) is list else [selfobj.ObjectToExport.Tip]
         elif containermode == 'Feed all children':
             objects_to_export += selfobj.ObjectToExport.Group
         else: 
             raise NotImplementedError(u"Unexpected contaner mode {mode}".format(mode= repr(containermode)))
     else:
         objects_to_export.append(selfobj.ObjectToExport)
     
     if selfobj.MeshAccuracy > 1e-7:
         for obj in objects_to_export:
             if hasattr(obj, 'Shape'):
                 obj.Shape.tessellate(selfobj.MeshAccuracy)
             else:
                 App.Console.PrintWarning(u"Exporter {exporter}: object to export ({object}) has no b-rep shape. Can't re-tessellate."
                                           .format(exporter= selfobj.Name, object= obj.Label))
     
     vardict = {
         'project_name'               : selfobj.Document.Name,
         'project_filetitle'          : path.splitext(path.basename(selfobj.Document.FileName))[0],
         'project_filename'           : path.basename(selfobj.Document.FileName),
         'project_folder'             : path.split(path.split(selfobj.Document.FileName)[0])[1],
         'project_label'              : selfobj.Document.Label,
         'exporter_label'             : selfobj.Label,
         'exporter_name'              : selfobj.Name,
         'exporter_container_label'   : Containers.getContainer(selfobj).Label,
         'exporter_container_name'    : Containers.getContainer(selfobj).Name,
     }
     
     def addObjectVars(obj):
         vardict['object_name'             ] = obj.Name
         vardict['object_label'            ] = obj.Label
         vardict['object_container_label'  ] = Containers.getContainer(obj).Label
         vardict['object_container_name'   ] = Containers.getContainer(obj).Name
     
     try:
         if selfobj.MultiMode == 'Write one file':
             addObjectVars(selfobj.ObjectToExport)
             filepath = filepath.replace('%Label%', selfobj.ObjectToExport.Label).format(**vardict)
             mod.export(objects_to_export, filepath)
             print(u"Exported {file}".format(file= filepath))
             if selfobj.FullActualPath != filepath: #check, to avoid touching all exporters upon every file save
                 selfobj.FullActualPath = filepath
         elif selfobj.MultiMode == 'Write many files':
             files_written = set()
             for obj in objects_to_export:
                 addObjectVars(obj)
                 thisfilepath = filepath.replace('%Label%', obj.Label).format(**vardict)
                 if thisfilepath in files_written:
                     raise ValueError(u'Exporter {exporter} is supposed to write multiple files, but the filenames repeat: {fn}. Please make sure a variable is used in the file name, such as {{object_name}}, or {{object_label}}.'
                         .format(exporter= selfobj.Label, fn= thisfilepath))
                 mod.export([obj], thisfilepath)
                 print(u"Exported {file}".format(file= thisfilepath))
             if selfobj.FullActualPath != thisfilepath: #check, to avoid touching all exporters upon every file save
                 selfobj.FullActualPath = thisfilepath
         else:
             raise NotImplementedError(u"Unexpected MultiMode: {mode}".format(mode= repr(selfobj.MultiMode)))
     except KeyError as ke:
         key = ke.args[0]
         message = (u'Variable name not recognized: {key}.\n\nVariables available:\n{varlist}'
             .format(
                 key= key,
                 varlist = '\n'.join(['{' + var + '}' + ': ' + vardict[var] for var in vardict])
             )
         )
         raise KeyError(message)
Beispiel #51
0
    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)))