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
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
def updateDeps(self, selfobj, check_only=False): """update PlacementLinks to match with container path""" toleave, toenter = Containers.getContainerRelativePath( Containers.getContainer(selfobj.Base), Containers.getContainer(selfobj)) leave_deps = [] if selfobj.UseForwardPlacements: for cnt in toleave[::-1]: if hasattr(cnt, 'Placement'): leave_deps.append(cnt) enter_deps = [] if selfobj.UseInversePlacements: for cnt in toenter: if hasattr(cnt, 'Placement'): enter_deps.append(cnt) if selfobj.PlacementLinks != leave_deps or not hasattr( self, '_implicit_deps') or self._implicit_deps != enter_deps: if check_only: App.Console.PrintError( u"Placement dependencies of {feat} are out of sync!\n". format(feat=selfobj.Name)) else: selfobj.PlacementLinks = leave_deps self._implicit_deps = enter_deps selfobj.touch() for dep in enter_deps: for (prop, expr) in dep.ExpressionEngine: if prop.startswith('Placement'): raise GhostError( u'{dep} has expression bound to its placement. {ghost} uses it, but is inside of the container, so it can\'t be properly recomputed.' .format(dep=dep.Label, ghost=selfobj.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)))
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 getTransform(self, selfobj): self.updateDeps(selfobj, check_only=True) toleave, toenter = Containers.getContainerRelativePath( Containers.getContainer(selfobj.Base), Containers.getContainer(selfobj)) self.path = (toleave, toenter) #save for future reference... transform = App.Placement() if selfobj.UseForwardPlacements: for cnt in toleave[::-1]: if hasattr(cnt, 'Placement'): transform = cnt.Placement.multiply(transform) if selfobj.UseInversePlacements: for cnt in toenter: if hasattr(cnt, 'Placement'): transform = cnt.Placement.inverse().multiply(transform) return transform
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)))
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 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 setEdit(self, selfvp, 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()
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
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())
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.''' 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)
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()
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
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
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)
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
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)))
def updateVPs(self): '''updates many viewprovider properties (except visibility, which is handled by TempoVis objects)''' 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
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())
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?
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?
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
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
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 doubleClicked(self, vobj): Containers.setActiveContainer(Containers.getContainer( vobj.Object.Base)) return True
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)
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()
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
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)
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)))