def IsActive(self): # we only insert variant links into assemblies and root parts if Asm4.getAssembly() or Asm4.getSelectedRootPart(): return True # if an existing variant link is selected, we duplicate it if Asm4.getSelectedVarLink(): return True return False
def __init__(self): # remove selectionFilter self.selectionFilterStatus = selectionFilter.observerStatus() selectionFilter.observerDisable() # get the current active document to avoid errors if user changes tab self.activeDoc = App.ActiveDocument # we have checked before that all this is correct selection = Asm4.getSelectedLink() if selection is None: selection = Asm4.getSelectedVarLink() self.selectedObj = selection #self.rootAssembly = self.selectedObj.getParentGeoFeatureGroup() self.rootAssembly = Asm4.getAssembly() # has been checked before, this is for security only if Asm4.isAsm4EE(self.selectedObj): # get the old values self.old_AO = self.selectedObj.AttachmentOffset self.old_linkLCS = self.selectedObj.AttachedBy[1:] else: # this shouldn't happen FCC.PrintWarning("WARNING : unsupported Assembly/Solver/Part combination, you shouldn't be seeing this\n") Asm4.makeAsmProperties(self.selectedObj) self.old_AO = [] self.old_linkLCS = '' # define the GUI # draw the GUI, objects are defined later down # self.UI = QtGui.QWidget() # self.form = self.UI self.form = QtGui.QWidget() iconFile = os.path.join( Asm4.iconPath , 'Place_Link.svg') self.form.setWindowIcon(QtGui.QIcon( iconFile )) self.form.setWindowTitle('Place linked Part') self.drawUI(self.form) #save original AttachmentOffset of linked part self.old_LinkAttachmentOffset = self.selectedObj.AttachmentOffset self.old_LinkRotation = self.selectedObj.AttachmentOffset.Rotation self.old_LinkPosition = self.selectedObj.AttachmentOffset.Base # default values correspond to original AttachmentOffset of linked part self.Xtranslation = self.old_LinkPosition[0] self.Ytranslation = self.old_LinkPosition[1] self.Ztranslation = self.old_LinkPosition[2] self.XrotationAngle = self.old_LinkRotation.toEuler()[0] self.YrotationAngle = self.old_LinkRotation.toEuler()[1] self.ZrotationAngle = self.old_LinkRotation.toEuler()[2] # save previous view properties self.old_OverrideMaterial = self.selectedObj.ViewObject.OverrideMaterial self.old_DrawStyle = self.selectedObj.ViewObject.DrawStyle self.old_LineWidth = self.selectedObj.ViewObject.LineWidth self.old_DiffuseColor = self.selectedObj.ViewObject.ShapeMaterial.DiffuseColor self.old_Transparency = self.selectedObj.ViewObject.ShapeMaterial.Transparency # set new view properties self.selectedObj.ViewObject.OverrideMaterial = True self.selectedObj.ViewObject.DrawStyle = DrawStyle self.selectedObj.ViewObject.LineWidth = LineWidth self.selectedObj.ViewObject.ShapeMaterial.DiffuseColor = DiffuseColor self.selectedObj.ViewObject.ShapeMaterial.Transparency = Transparency # get the old values self.old_EE = '' old_Parent = '' old_ParentPart = '' old_attLCS = '' constrName = '' linkedDoc = '' old_linkLCS = '' # get and store the current expression engine: self.old_EE = Asm4.placementEE(self.selectedObj.ExpressionEngine) # decode the old ExpressionEngine # if the decode is unsuccessful, old_Expression is set to False and the other things are set to 'None' (self.old_Parent, separator, self.old_parentLCS) = self.selectedObj.AttachedTo.partition('#') ( old_Parent, old_attLCS, old_linkLCS ) = self.splitExpressionLink( self.old_EE, self.old_Parent ) # sometimes, the object is in << >> which is an error by FreeCAD, # because that's reserved for labels, but we still look for it if len(old_attLCS)>4 and old_attLCS[:2]=='<<' and old_attLCS[-2:]=='>>': old_attLCS = old_attLCS[2:-2] if len(old_linkLCS)>4 and old_linkLCS[:2]=='<<' and old_linkLCS[-2:]=='>>': old_linkLCS = old_linkLCS[2:-2] # initialize the UI with the current data self.attLCStable = [] self.initUI() # now self.parentList and self.parentTable are available # find all the linked parts in the assembly for obj in self.activeDoc.findObjects("App::Link"): if self.rootAssembly.getObject(obj.Name) is not None and hasattr(obj.LinkedObject,'isDerivedFrom'): linkedObj = obj.LinkedObject if linkedObj.isDerivedFrom('App::Part') or linkedObj.isDerivedFrom('PartDesign::Body'): # ... except if it's the selected link itself if obj != self.selectedObj: self.parentTable.append( obj ) # add to the drop-down combo box with the assembly tree's parts objIcon = linkedObj.ViewObject.Icon objText = Asm4.labelName(obj) self.parentList.addItem( objIcon, objText, obj) # find all the LCS in the selected link self.partLCStable = Asm4.getPartLCS( self.selectedObj.LinkedObject ) # build the list self.partLCSlist.clear() for lcs in self.partLCStable: newItem = QtGui.QListWidgetItem() newItem.setText(Asm4.labelName(lcs)) newItem.setIcon( lcs.ViewObject.Icon ) self.partLCSlist.addItem(newItem) # find the old LCS in the list of LCS of the linked part... # MatchExactly, MatchContains, MatchEndsWith ... # find with Name ... lcs_found = self.partLCSlist.findItems( old_linkLCS, QtCore.Qt.MatchExactly ) # ... or with (Name) if not lcs_found: lcs_found = self.partLCSlist.findItems( '('+old_linkLCS+')', QtCore.Qt.MatchEndsWith ) if lcs_found: # ... and select it self.partLCSlist.setCurrentItem( lcs_found[0] ) # find the oldPart in the part list... if old_Parent == 'Parent Assembly': parent_found = True parent_index = 1 else: parent_found = False parent_index = 1 for item in self.parentTable[1:]: if item.Name == old_Parent: parent_found = True break else: parent_index = parent_index +1 if not parent_found: parent_index = 0 self.parentList.setCurrentIndex( parent_index ) # this should have triggered self.getPartLCS() to fill the LCS list # find the old attachment Datum in the list of the Datums in the linked part... lcs_found = self.attLCSlist.findItems( old_attLCS, QtCore.Qt.MatchExactly ) if not lcs_found: lcs_found = self.attLCSlist.findItems( '('+old_attLCS+')', QtCore.Qt.MatchEndsWith ) if lcs_found: # ... and select it self.attLCSlist.setCurrentItem( lcs_found[0] ) # selection observer to detect selection of LCS in the 3D window and tree Gui.Selection.addObserver(self, 0)
def Activated(self): # This function is executed when the command is activated self.UI = QtGui.QDialog() self.drawUI() # initialise stuff self.activeDoc = App.ActiveDocument self.rootAssembly = None self.origLink = None self.brokenLink = False self.allParts = [] self.partsDoc = [] self.filterPartList.clear() self.partList.clear() self.linkNameInput.clear() # if an Asm4 Assembly is present, that's where we put the variant link if Asm4.getAssembly(): self.rootAssembly = Asm4.getAssembly() # an App::Part at the root of the document is selected, we insert the link there elif Asm4.getSelectedRootPart(): self.rootAssembly = Asm4.getSelectedRootPart() # if a variant link is selected, we see if we can duplicate it if Asm4.getSelectedVarLink(): selObj = Asm4.getSelectedVarLink() parent = selObj.getParentGeoFeatureGroup() # if the selected link is in a root App::Part if parent.TypeId == 'App::Part' and parent.getParentGeoFeatureGroup() is None: self.rootAssembly = parent self.origLink = selObj self.origPart = selObj.SourceObject ''' # if a broken link is selected elif len(Gui.Selection.getSelection())==1 : selObj = Gui.Selection.getSelection()[0] if selObj.isDerivedFrom('App::Link') and selObj.LinkedObject is None: parent = selObj.getParentGeoFeatureGroup() # if the selected (broken) link is in a root App::Part if parent.TypeId == 'App::Part' and parent.getParentGeoFeatureGroup() is None: self.brokenLink = True self.rootAssembly = parent self.origLink = selObj self.UI.setWindowTitle('Re-link broken link') self.insertButton.setText('Replace') self.linkNameInput.setText(Asm4.labelName(selObj)) self.linkNameInput.setEnabled(False) ''' if self.rootAssembly is None: Asm4.warningBox( 'Please create an Assembly' ) return # Search for all App::Parts having a "Variables" property container in all open documents # Also store the document of the part for doc in App.listDocuments().values(): # don't consider temporary documents if not doc.Temporary: for obj in doc.findObjects("App::Part"): # we don't want to link to itself to the 'Model' object # other App::Part in the same document are OK # but only those at top level (not nested inside other containers) if obj != self.rootAssembly and obj.getParentGeoFeatureGroup() is None: # and only those that have a Variables property container variables = obj.getObject('Variables') if hasattr(variables,'Type') and variables.Type=='App::PropertyContainer': self.allParts.append( obj ) self.partsDoc.append( doc ) # build the list for part in self.allParts: newItem = QtGui.QListWidgetItem() newItem.setText( part.Document.Name +"#"+ Asm4.labelName(part) ) newItem.setIcon(part.ViewObject.Icon) self.partList.addItem(newItem) # if an existing valid App::Link was selected if self.origLink and not self.brokenLink: origPart = self.origLink.SourceObject # try to find the original part of the selected link origPartText = origPart.Document.Name +"#"+ Asm4.labelName(origPart) # MatchExactly, MatchContains, MatchEndsWith, MatchStartsWith ... partFound = self.partList.findItems( origPartText, QtCore.Qt.MatchExactly ) if partFound: self.partList.setCurrentItem(partFound[0]) # self.onItemClicked(partFound[0]) # if the last character is a number, we increment this number origName = self.origLink.Label lastChar = origName[-1] if lastChar.isnumeric(): (rootName,sep,num) = origName.rpartition('_') proposedLinkName = Asm4.nextInstance(rootName,startAtOne=True) # else we take the next instance else: proposedLinkName = Asm4.nextInstance(origName) # set the proposed name in the entry field if not self.brokenLink: self.linkNameInput.setText( proposedLinkName ) # show the UI self.UI.show()
def Activated(self): # try with a regular App::Link selection = Asm4.getSelectedLink() # may-be an Asm4::VariantLink ? if selection is None: selection = Asm4.getSelectedVarLink() # if we found a valid link if selection is not None: # check that it's in the root assembly parent = selection.getParentGeoFeatureGroup() if parent and parent == Asm4.getAssembly(): # if it's a valid assembly and part if Asm4.isAsm4EE(selection): # BUGFIX: if the part was corrupted by Assembly4 v0.11.5: if hasattr(selection, 'MapMode'): Asm4.warningBox( "This Part has the Attachment extension, it can only be placed manually" ) else: # launch the UI in the task panel ui = placeLinkUI() Gui.Control.showDialog(ui) # else try to convert it else: convert = Asm4.confirmBox( "This Part wasn't assembled with this Assembly4 WorkBench, but I can convert it." ) if convert: Asm4.makeAsmProperties(selection, reset=True) # launch the UI in the task panel ui = placeLinkUI() Gui.Control.showDialog(ui) else: Asm4.warningBox('Please select a link in the assembly Model.') else: # or any part that has a Placement ? if len(Gui.Selection.getSelection()) == 1: selection = Gui.Selection.getSelection()[0] # object has a Placement property if hasattr(selection, 'Placement') and selection.getTypeIdOfProperty( 'Placement') == 'App::PropertyPlacement': # we don't want to mess with obects that are attached with the Attacher (MapMode) if hasattr(selection, 'MapMode'): FCC.PrintMessage( 'Object has MapMode property, you should use that\n' ) else: # check that it's in the root assembly parent = selection.getParentGeoFeatureGroup() if parent and parent == Asm4.getAssembly(): # is it's a virgin object, give it Asm4 properties if not hasattr(selection, 'SolverId'): Asm4.makeAsmProperties(selection) # if it's a valid assembly and part if Asm4.isAsm4EE(selection): # launch the UI in the task panel ui = placePartUI() Gui.Control.showDialog(ui) # else try to convert it else: convert = Asm4.confirmBox( "This Part wasn't assembled with this Assembly4 WorkBench, but I can convert it." ) if convert: Asm4.makeAsmProperties(selection, reset=True) # launch the UI in the task panel ui = placePartUI() Gui.Control.showDialog(ui) # the selected object doesn't belong to the root assembly else: Asm4.warningBox( 'Please select an object in the assembly Model.' ) return