def clicked(self, button): if button == QtGui.QDialogButtonBox.Ignore: # ask for confirmation before resetting everything msgName = Asm4.nameLabel(self.selectedLink) # see whether the ExpressionEngine field is filled if self.selectedLink.ExpressionEngine: # if yes, then ask for confirmation confirmed = Asm4.confirmBox( 'This command will release all attachments on ' + msgName + ' and set it to manual positioning in its current location.' ) # if not, then it's useless to bother the user else: confirmed = True if confirmed: # unset the ExpressionEngine for the Placement self.selectedLink.setExpression('Placement', None) # reset the assembly properties Asm4.makeAsmProperties(self.selectedLink, reset=True) # finish FCC.PrintWarning("Part is now manually placed\n") self.finish() else: FCC.PrintWarning("Part untouched\n") self.finish()
def Apply( self ): # get the instance to attach to: # it's either the top level assembly or a sister App::Link if self.parentList.currentText() == 'Parent Assembly': a_Link = 'Parent Assembly' a_Part = None elif self.parentList.currentIndex() > 1: parent = self.parentTable[ self.parentList.currentIndex() ] a_Link = parent.Name a_Part = parent.LinkedObject.Document.Name else: a_Link = None a_Part = None # the attachment LCS's name in the parent # check that something is selected in the QlistWidget if self.attLCSlist.selectedItems(): a_LCS = self.attLCStable[ self.attLCSlist.currentRow() ].Name else: a_LCS = None # the linked App::Part's name l_Part = self.selectedLink.LinkedObject.Document.Name # the LCS's name in the linked part to be used for its attachment # check that something is selected in the QlistWidget if self.partLCSlist.selectedItems(): #l_LCS = self.partLCSlist.selectedItems()[0].text() l_LCS = self.partLCStable[ self.partLCSlist.currentRow() ].Name else: l_LCS = None # check that all of them have something in # constrName has been checked at the beginning if a_Link and a_LCS and l_Part and l_LCS : # this is where all the magic is, see: # # https://forum.freecadweb.org/viewtopic.php?p=278124#p278124 # # as of FreeCAD v0.19 the syntax is different: # https://forum.freecadweb.org/viewtopic.php?f=17&t=38974&p=337784#p337784 # # expr = ParentLink.Placement * ParentPart#LCS.Placement * constr_LinkName.AttachmentOffset * LinkedPart#LCS.Placement ^ -1' # expr = LCS_in_the_assembly.Placement * constr_LinkName.AttachmentOffset * LinkedPart#LCS.Placement ^ -1' expr = Asm4.makeExpressionPart( a_Link, a_Part, a_LCS, l_Part, l_LCS ) # add the Asm4 properties if it's a pure App::Link Asm4.makeAsmProperties(self.selectedLink) # store the part where we're attached to in the constraints object self.selectedLink.AssemblyType = 'Asm4EE' self.selectedLink.AttachedBy = '#'+l_LCS self.selectedLink.AttachedTo = a_Link+'#'+a_LCS # load the expression into the link's Expression Engine self.selectedLink.setExpression('Placement', expr ) # recompute the object to apply the placement: self.selectedLink.recompute() self.parentAssembly.recompute(True) return True else: #FCC.PrintWarning("Problem in selections\n") return False
def freeInsert(self): # ask for confirmation before resetting everything fName = self.selectedFastener.Name fLabel = self.selectedFastener.Label if fName==fName: fText = fName else: fText = fName+' ('+fName+')' # see whether the ExpressionEngine field is filled if self.old_EE : # if yes, then ask for confirmation confirmed = Asm4.confirmBox('This command will release all attachments on '+fText+' and set it to manual positioning in its current location.') # if not, then it's useless to bother the user else: confirmed = True if confirmed: # unset the ExpressionEngine for the Placement # self.selectedFastener.setExpression( 'Placement', expr ) self.selectedFastener.setExpression('Placement', None) # reset the assembly properties Asm4.makeAsmProperties(self.selectedFastener) # finish self.close() else: return
def onApply(self): # get the name of the part to attach to: # it's either the top level part name ('Model') # or the provided link's name. if self.parentList.currentText() == 'Parent Assembly': a_Link = 'Parent Assembly' a_Part = None elif self.parentList.currentIndex() > 1: parent = self.asmParts[ self.parentList.currentIndex() ] a_Link = parent.Name a_Part = parent.LinkedObject.Document.Name else: a_Link = None a_Part = None # the attachment LCS's name in the parent # check that something is selected in the QlistWidget if self.attLCSlist.selectedItems(): a_LCS = self.attLCStable[ self.attLCSlist.currentRow() ].Name else: a_LCS = None # check that all of them have something in if a_Link and a_LCS : # <<LinkName>>.Placement.multiply( <<LinkName>>.<<LCS.>>.Placement ) # expr = '<<'+ a_Part +'>>.Placement.multiply( <<'+ a_Part +'>>.<<'+ a_LCS +'.>>.Placement )' expr = self.makeExpressionFastener( a_Link, a_Part, a_LCS ) # this can be skipped when this method becomes stable self.expression.setText( expr ) # indicate the this fastener has been placed with the Assembly4 workbench if not hasattr(self.selectedFastener,'AssemblyType'): Asm4.makeAsmProperties(self.selectedFastener) self.selectedFastener.AssemblyType = 'Asm4EE' # the fastener is attached by its Origin, no extra LCS self.selectedFastener.AttachedBy = 'Origin' # store the part where we're attached to in the constraints object self.selectedFastener.AttachedTo = a_Link+'#'+a_LCS # load the built expression into the Expression field of the constraint self.selectedFastener.setExpression( 'Placement', expr ) # check the Invert and Offset values self.selectedFastener.invert = self.Invert.isChecked() self.selectedFastener.offset = self.Offset.value() # recompute the object to apply the placement: self.selectedFastener.recompute() self.parentAssembly.recompute() self.activeDoc.recompute() # highlight the selected fastener in its new position Gui.Selection.clearSelection() Gui.Selection.addSelection( self.activeDoc.Name, 'Model', self.selectedFastener.Name +'.') else: self.expression.setText( 'Problem in selections' ) return
def freeInsert(self): # ask for confirmation before resetting everything linkName = self.selectedLink.Name linkLabel = self.selectedLink.Label if linkName == linkName: linkText = linkName else: linkText = linkName + ' (' + linkName + ')' # see whether the ExpressionEngine field is filled if self.selectedLink.ExpressionEngine: # if yes, then ask for confirmation confirmed = Asm4.confirmBox( 'This command will release all attachments on ' + linkText + ' and set it to manual positioning in its current location.') # if not, then it's useless to bother the user else: confirmed = True if confirmed: # unset the ExpressionEngine for the Placement self.selectedLink.setExpression('Placement', None) # reset the assembly properties Asm4.makeAsmProperties(self.selectedLink, reset=True) """ # property AssemblyType if hasattr(self.selectedLink,'AssemblyType'): self.selectedLink.AssemblyType = '' else: self.selectedLink.addProperty( 'App::PropertyString', 'AssemblyType', 'Attachment' ).AssemblyType = '' # property AttachedBy if hasattr(self.selectedLink,'AttachedBy'): self.selectedLink.AttachedBy = '' else: self.selectedLink.addProperty( 'App::PropertyString', 'AttachedBy', 'Attachment' ).AttachedBy = '' # property AttachedTo if hasattr(self.selectedLink,'AttachedTo'): self.selectedLink.AttachedTo = '' else: self.selectedLink.addProperty( 'App::PropertyString', 'AttachedTo', 'Attachment' ).AttachedTo = '' # property AttachmentOffset if hasattr(self.selectedLink,'AttachmentOffset'): self.selectedLink.AttachmentOffset = App.Placement() else: self.selectedLink.addProperty( 'App::PropertyPlacement', 'AttachmentOffset', 'Attachment' ).AttachmentOffset = App.Placement() """ Gui.Selection.clearSelection() Gui.Selection.addSelection(self.activeDoc.Name, 'Model', self.selectedLink.Name + '.') # finish self.close() else: return
def clicked(self, bt): if bt == QtGui.QDialogButtonBox.Ignore: # ask for confirmation before resetting everything msgName = Asm4.nameLabel(self.selectedFastener) # see whether the ExpressionEngine field is filled if self.old_EE : # if yes, then ask for confirmation confirmed = Asm4.confirmBox('This command will release all attachments on '+msgName+' and set it to manual positioning in its current location.') else: # if not, then it's useless to bother the user confirmed = True if confirmed: # unset the ExpressionEngine in the Placement self.selectedFastener.setExpression('Placement', None) # reset Asm4 properties Asm4.makeAsmProperties( self.selectedFastener, reset=True ) self.finish()
def placeFastenerToLCS(attFstnr, attLink, attPart, attLCS): expr = makeExpressionFastener(attLink, attPart, attLCS) # indicate the this fastener has been placed with the Assembly4 workbench if not hasattr(attFstnr, 'AssemblyType'): Asm4.makeAsmProperties(attFstnr) attFstnr.AssemblyType = 'Asm4EE' # the fastener is attached by its Origin, no extra LCS attFstnr.AttachedBy = 'Origin' # store the part where we're attached to in the constraints object attFstnr.AttachedTo = attLink + '#' + attLCS # load the built expression into the Expression field of the constraint attFstnr.setExpression('Placement', expr) # recompute the object to apply the placement: attFstnr.recompute() container = attFstnr.getParentGeoFeatureGroup() if container: container.recompute() if attFstnr.Document: attFstnr.Document.recompute()
def Activated(self): # check that we have selected a Fastener from the Fastener WB selection = getSelectionFS() if selection == None: return # check that the fastener is an Asm4 fastener if not hasattr(selection,'AssemblyType'): Asm4.makeAsmProperties(selection) # we only deal with Asm4 or empty types asmType = selection.AssemblyType if asmType=='Asm4EE' or asmType=='': # now we should be safe, call the UI Gui.Control.showDialog( placeFastenerUI() ) else: convert = Asm4.confirmBox("This doesn't seem to be an Assembly4 Fastener") if convert: Asm4.makeAsmProperties( selection, reset=True ) selection.AssemblyType = 'Asm4EE' Gui.Control.showDialog( placeFastenerUI() ) return
def Activated(self): # check that the Fasteners WB has been loaded before: if not 'FSChangeParams' in Gui.listCommands(): Gui.activateWorkbench('FastenersWorkbench') Gui.activateWorkbench('Assembly4Workbench') # check that we have somewhere to put our stuff self.asmDoc = App.ActiveDocument part = self.getPart() if part: newFastener = App.ActiveDocument.addObject("Part::FeaturePython", self.FStype) newFastener.ViewObject.ShapeColor = self.FScolor if self.FStype == 'Screw': FS.FSScrewObject(newFastener, 'ISO4762', None) elif self.FStype == 'Nut': FS.FSScrewObject(newFastener, 'ISO4032', None) elif self.FStype == 'Washer': FS.FSScrewObject(newFastener, 'ISO7089', None) elif self.FStype == 'ThreadedRod': FS.FSThreadedRodObject(newFastener, None) # make the Proxy and stuff newFastener.Label = newFastener.Proxy.itemText FS.FSViewProviderTree(newFastener.ViewObject) # add Asm4 properties if necessary Asm4.makeAsmProperties(newFastener, reset=True) # add it to the Part part.addObject(newFastener) # hide "offset" and "invert" properties to avoid confusion as they are not used in Asm4 if hasattr(newFastener, 'offset'): newFastener.setPropertyStatus('offset', 'Hidden') if hasattr(newFastener, 'invert'): newFastener.setPropertyStatus('invert', 'Hidden') newFastener.recompute() # ... and select it Gui.Selection.clearSelection() Gui.Selection.addSelection(newFastener) Gui.runCommand('FSChangeParams')
def __init__(self): self.base = QtGui.QWidget() self.form = self.base iconFile = os.path.join(Asm4.iconPath, 'Place_Link.svg') self.form.setWindowIcon(QtGui.QIcon(iconFile)) self.form.setWindowTitle('Place linked Part') # check that we have selected two LCS or an App::Link object self.selectedLink = [] self.selectedLCSA = None self.selectedLinkB = None self.selectedLCSB = None selection = Asm4.getSelectedLink() #selectedLCSPair = Asm4.getLinkAndDatum2() self.Xtranslation = 0.00 self.Ytranslation = 0.00 self.Ztranslation = 0.00 self.XrotationAngle = 0.00 self.YrotationAngle = 0.00 self.ZrotationAngle = 0.00 # draw the GUI, objects are defined later down self.drawUI() global taskUI taskUI = self #Handle single selected App::Link if not selection: # This shouldn't happen FCC.PrintWarning( "This is not an error message you are supposed to see, something went wrong\n" ) Gui.Control.closeDialog() else: self.selectedLink = selection Asm4.makeAsmProperties(self.selectedLink) #save original AttachmentOffset of linked part self.old_LinkAttachmentOffset = self.selectedLink.AttachmentOffset self.old_LinkRotation = self.selectedLink.AttachmentOffset.Rotation self.old_LinkPosition = self.selectedLink.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.selectedLink.ViewObject.OverrideMaterial self.old_DrawStyle = self.selectedLink.ViewObject.DrawStyle self.old_LineWidth = self.selectedLink.ViewObject.LineWidth self.old_DiffuseColor = self.selectedLink.ViewObject.ShapeMaterial.DiffuseColor self.old_Transparency = self.selectedLink.ViewObject.ShapeMaterial.Transparency # set new view properties self.selectedLink.ViewObject.OverrideMaterial = True self.selectedLink.ViewObject.DrawStyle = DrawStyle self.selectedLink.ViewObject.LineWidth = LineWidth self.selectedLink.ViewObject.ShapeMaterial.DiffuseColor = DiffuseColor self.selectedLink.ViewObject.ShapeMaterial.Transparency = Transparency # get the current active document to avoid errors if user changes tab self.activeDoc = App.activeDocument() # the parent (top-level) assembly is the App::Part called Model (hard-coded) self.parentAssembly = self.activeDoc.Model # check that the link is an Asm4 link: self.isAsm4EE = False if hasattr(self.selectedLink, 'AssemblyType'): if self.selectedLink.AssemblyType == 'Asm4EE' or self.selectedLink.AssemblyType == '': self.isAsm4EE = True else: Asm4.warningBox( "This Link's assembly type doesn't correspond to this WorkBench" ) return # 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 objName in self.parentAssembly.getSubObjects(): # remove the trailing . obj = self.activeDoc.getObject(objName[0:-1]) if obj.TypeId == 'App::Link' and hasattr(obj.LinkedObject, 'isDerivedFrom'): if obj.LinkedObject.isDerivedFrom( 'App::Part') or obj.LinkedObject.isDerivedFrom( 'PartDesign::Body'): # ... except if it's the selected link itself if obj != self.selectedLink: self.parentTable.append(obj) # add to the drop-down combo box with the assembly tree's parts objIcon = obj.LinkedObject.ViewObject.Icon objText = Asm4.nameLabel(obj) self.parentList.addItem(objIcon, objText, obj) # find all the LCS in the selected link self.partLCStable = Asm4.getPartLCS(self.selectedLink.LinkedObject) # build the list self.partLCSlist.clear() for lcs in self.partLCStable: newItem = QtGui.QListWidgetItem() newItem.setText(Asm4.nameLabel(lcs)) newItem.setIcon(lcs.ViewObject.Icon) self.partLCSlist.addItem(newItem) # get the old values if self.isAsm4EE: self.old_AO = self.selectedLink.AttachmentOffset self.old_linkLCS = self.selectedLink.AttachedBy[1:] (self.old_Parent, separator, self.old_parentLCS) = self.selectedLink.AttachedTo.partition('#') else: self.old_AO = [] self.old_Parent = '' self.old_EE = '' # get and store the current expression engine: self.old_EE = Asm4.placementEE(self.selectedLink.ExpressionEngine) # decode the old ExpressionEngine old_Parent = '' old_ParentPart = '' old_attLCS = '' constrName = '' linkedDoc = '' old_linkLCS = '' # if the decode is unsuccessful, old_Expression is set to False and the other things are set to 'None' (old_Parent, old_attLCS, old_linkLCS) = Asm4.splitExpressionLink(self.old_EE, self.old_Parent) # find the old LCS in the list of LCS of the linked part... # MatchExactly, MatchContains, MatchEndsWith ... lcs_found = self.partLCSlist.findItems(old_linkLCS, QtCore.Qt.MatchExactly) if not lcs_found: lcs_found = self.partLCSlist.findItems(old_linkLCS + ' (', QtCore.Qt.MatchStartsWith) 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.MatchStartsWith) if lcs_found: # ... and select it self.attLCSlist.setCurrentItem(lcs_found[0])
def Activated(self): # get the current active document to avoid errors if user changes tab self.activeDoc = App.activeDocument() # the parent (top-level) assembly is the App::Part called Model (hard-coded) self.parentAssembly = self.activeDoc.Model # check that we have selected a PartDesign::CoordinateSystem self.selectedFastener = [] selection = self.GetSelection() if selection == None: self.close() else: self.selectedFastener = selection # check that the fastener is an Asm4 fastener if not hasattr(self.selectedFastener,'AssemblyType'): Asm4.makeAsmProperties(self.selectedFastener) asmType = self.selectedFastener.AssemblyType # we only deal with Asm4 or empty types if asmType!='Asm4EE' and asmType!='': Asm4.warningBox("This doesn't seem to be an Assembly4 Fastener") return(False) # check where the fastener was attached to (self.old_Parent, separator, self.old_parentLCS) = self.selectedFastener.AttachedTo.partition('#') # get and store the current expression engine: self.old_EE = '' old_EE = self.selectedFastener.ExpressionEngine if old_EE: for ( key, expr ) in old_EE: #( key, expr ) = ee if key=='Placement': self.old_EE = expr # Now we can draw the UI self.initUI() self.show() # decode the old ExpressionEngine # if the decode is unsuccessful, old_Expression is set to False # and old_attPart and old_attLCS are set to 'None' old_Parent = '' old_parentPart = '' old_parentLCS = '' if self.old_EE and self.old_Parent: ( old_Parent, old_parentPart, old_parentLCS ) = self.splitExpressionFastener( self.old_EE, self.old_Parent ) #self.expression.setText( 'old_Parent = '+ old_Parent ) # We get all the App::Link parts in the assembly self.asmParts = [] # the first item is "Select linked Part" therefore we add an empty object self.asmParts.append( [] ) # We also add the parent assembly self.asmParts.append( self.parentAssembly ) # Add it as first element to the drop-down combo-box parentIcon = self.parentAssembly.ViewObject.Icon self.parentList.addItem( parentIcon, 'Parent Assembly', self.parentAssembly ) # find all the linked parts in the assembly for obj in self.activeDoc.findObjects("App::Link"): if obj.LinkedObject.isDerivedFrom('App::Part'): # add it to our tree table if it's a link to an App::Part ... self.asmParts.append( obj ) # ... and add to the drop-down combo box with the assembly tree's parts objIcon = obj.LinkedObject.ViewObject.Icon self.parentList.addItem( objIcon, obj.Name, obj) # find the oldPart in the part list... parent_index = 1 if old_Parent == 'Parent Assembly': parent_found = True else: parent_found = False for item in self.asmParts[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 oldLCS in the list of LCS of the linked part... lcs_found = [] lcs_found = self.attLCSlist.findItems( old_parentLCS, QtCore.Qt.MatchExactly ) if lcs_found: # ... and select it self.attLCSlist.setCurrentItem( lcs_found[0] ) else: # may-be it was renamed, see if we can find it as (name) lcs_found = self.attLCSlist.findItems( '('+old_parentLCS+')', QtCore.Qt.MatchContains ) if lcs_found: self.attLCSlist.setCurrentItem( lcs_found[0] )