assembly: fix element offset/flip menu action

This commit is contained in:
Zheng, Lei 2020-03-04 16:36:17 +08:00
parent c60a7b7f35
commit ebd9dd8a68
2 changed files with 64 additions and 40 deletions

View File

@ -1259,7 +1259,7 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop):
menu.addAction(action)
action = QtGui.QAction(QtGui.QIcon(),
"Attach" if obj.Detach else "Detach", menu)
"Attach element" if obj.Detach else "Detach element", menu)
if obj.Detach:
action.setToolTip('Attach this element to its linked geometry,\n'
'so that it will auto update on change.')
@ -1271,38 +1271,44 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop):
menu.addAction(action)
if obj.Proxy.isBroken():
action = QtGui.QAction(QtGui.QIcon(), "Fix", menu)
action = QtGui.QAction(QtGui.QIcon(), "Fix element", menu)
action.setToolTip('Auto fix broken element')
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),vobj.Proxy.fix)
menu.addAction(action)
action = QtGui.QAction(QtGui.QIcon(), 'Offset', menu)
action = QtGui.QAction(QtGui.QIcon(), 'Offset element', menu)
action.setToolTip('Activate dragger to offset this element')
menu.addAction(action)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),vobj2.Proxy.offset)
def setupContextMenu(self,vobj,menu):
ViewProviderAsmElement.setupMenu(menu, vobj, vobj)
if vobj2.Object.Offset != FreeCAD.Placement():
action = QtGui.QAction(QtGui.QIcon(), 'Reset offset', menu)
action.setToolTip('Clear offset of this element')
menu.addAction(action)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),vobj2.Proxy.resetOffset)
action = QtGui.QAction(QtGui.QIcon(), 'Flip element', menu)
action.setToolTip('Flip this element\' Z normal by rotating 180 degree\n'
'along the X axis (or Y axis by holding the CTRL key).\n\n'
'Note that this is only effective when for elements\n'
'used in "Attachment" constraint. For others, please\n'
'try "Flip part" instead.')
'Note that depending on the type of constraint and the\n'
'order of the selected element, flipping element may not\n'
'be effective. You can try "Flip part" instead.')
menu.addAction(action)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),self.flip)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),vobj2.Proxy.flip)
action = QtGui.QAction(QtGui.QIcon(), 'Flip part', menu)
action.setToolTip('Flip the owner part using this element Z normal as\n'
'reference, which is done by rotating 180 degree along\n'
action.setToolTip('Flip the owner part using this element Z normal as\n' \
'reference, which is done by rotating 180 degree along\n' \
'the element\'s X axis (or Y axis by holding the CTRL key).\n\n'
'Note that this won\'t work for elements in "Attachment"\n'
'constraint. Please try "Flip element" instead.')
'Note that depending on the type of constraint and the\n'
'order of the selected element, flipping part may not\n'
'be effective. You can try "Flip element" instead.')
menu.addAction(action)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),self.flipPart)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),vobj2.Proxy.flipPart)
def setupContextMenu(self,vobj,menu):
ViewProviderAsmElement.setupMenu(menu, vobj, vobj)
return True
def fix(self):
@ -1331,7 +1337,18 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop):
return mover.movePart(element=self.ViewObject.Object, moveElement=True)
@staticmethod
def doFlip(obj, info, flipElement=False):
def doResetOffset(obj):
FreeCAD.setActiveTransaction('Reset offset')
obj.Offset = FreeCAD.Placement()
obj.recompute(True)
FreeCAD.closeActiveTransaction()
def resetOffset(self):
obj = self.ViewObject.Object
ViewProviderAsmElement.doResetOffset(obj)
@staticmethod
def doFlip(obj, info, flipElement):
if QtGui.QApplication.keyboardModifiers()==QtCore.Qt.ControlModifier:
rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0),180)
else:
@ -1345,8 +1362,9 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop):
obj.Offset = rot.multiply(obj.Offset)
else:
offset = utils.getElementPlacement(obj.getSubObject(''))
offset = offset.inverse().multiply(rot).multiply(offset)
setPlacement(info.Part, info.Placement.multiply(offset))
offset = offset.multiply(rot).multiply(offset.inverse())
setPlacement(info.Part, offset.multiply(info.Placement))
obj.recompute(True)
FreeCAD.closeActiveTransaction()
except Exception:
FreeCAD.closeActiveTransaction(True)
@ -1354,7 +1372,7 @@ class ViewProviderAsmElement(ViewProviderAsmOnTop):
def flip(self):
obj = self.ViewObject.Object
ViewProviderAsmElement.doFlip(obj, obj.Proxy.getInfo())
ViewProviderAsmElement.doFlip(obj, obj.Proxy.getInfo(), True)
def flipPart(self):
obj = self.ViewObject.Object
@ -2052,25 +2070,23 @@ class ViewProviderAsmElementLink(ViewProviderAsmOnTop):
return;
ViewProviderAsmElement.setupMenu(menu, element.ViewObject, vobj)
action = QtGui.QAction(QtGui.QIcon(), 'Flip', menu)
action.setToolTip('For element link inside an "Attachment" constraint,\n'
'flip the element\'s Z normal by rotating 180 degree along\n'
'its X axis (or Y axis by holding the CTRL key). For other\n'
'constraint, flip the owner part instead.')
menu.addAction(action)
QtCore.QObject.connect(action,QtCore.SIGNAL("triggered()"),self.flip)
return True
def offset(self):
from . import mover
return mover.movePart(element=self.ViewObject.Object, moveElement=True)
def resetOffset(self):
obj = self.ViewObject.Object
ViewProviderAsmElement.doResetOffset(obj)
def flip(self):
obj = self.ViewObject.Object
ViewProviderAsmElement.doFlip(obj, obj.Proxy.getInfo(),
Constraint.isAttachment(obj.Proxy.parent.Object))
ViewProviderAsmElement.doFlip(obj, obj.Proxy.getInfo(), True)
def flipPart(self):
obj = self.ViewObject.Object
ViewProviderAsmElement.doFlip(obj, obj.Proxy.getInfo(), False)
class AsmConstraint(AsmGroup):
@ -4295,6 +4311,9 @@ class ViewProviderAssembly(ViewProviderAsmGroup):
def onDragEnd(self):
try:
if getattr(self,'_movingPart',None):
pla = self._movingPart.dragEnd()
if pla:
self.ViewObject.DraggingPlacement = pla
FreeCAD.closeActiveTransaction()
return True
finally:

View File

@ -49,11 +49,6 @@ class AsmMovingPart(object):
# Place the dragger at element's current (maybe offseted) shape
# center point in assembly coordinate
self.draggerPlacement = utils.getElementPlacement(shape)
# calculate the placement of an unoffseted element in assembly coordinate
self.offset = utils.getElementPlacement(element.getSubObject('',transform=False))
# Calculate the placement to transform the unoffseted element
# shape to the origin of its own coordinate space
self.offsetInv = self.offset.inverse()
return
# if we are not moving the element, but its owner part, transform
@ -135,9 +130,7 @@ class AsmMovingPart(object):
shape = self.element.getSubObject('')
pla = utils.getElementPlacement(shape)
elif utils.isDraftObject(info.Part):
pos = utils.getElementPos(info.Shape)
rot = utils.getElementRotation(info.Shape)
pla = info.Placement.multiply(FreeCAD.Placement(pos,rot))
pla = utils.getElementPlacement(info.Shape)
else:
pla = info.Placement.multiply(self.offset)
logger.trace('part move update {}: {}',objName(info.Parent),pla)
@ -158,6 +151,15 @@ class AsmMovingPart(object):
mat = FreeCADGui.editDocument().EditingTransform
return mat.multiply(self.draggerPlacement.Base)
def dragEnd(self):
if self.moveElement and gui.AsmCmdManager.AutoRecompute:
from . import solver
if not logger.catch('solver exception when moving element',
solver.solve, self.objs):
self.assembly.Object.recompute(True)
else:
return self.update()
def move(self):
info = self.info
part = info.Part
@ -168,8 +170,11 @@ class AsmMovingPart(object):
rollback = []
if self.moveElement:
updatePla = False
offset = utils.roundPlacement(self.offsetInv.multiply(pla))
self.element.Offset = offset
# obtain the placement of an unoffseted element in assembly coordinate
offset = utils.getElementPlacement(self.element.getSubObject('',transform=False))
self.element.Offset = utils.roundPlacement(offset.inverse().multiply(pla))
self.element.recompute(True)
return
elif not info.Subname.startswith('Face') and utils.isDraftWire(part):
updatePla = False
if info.Subname.startswith('Vertex'):