gui: add GotoRelation command

Can either go from part or constraint to their corresponding relation
item.
This commit is contained in:
Zheng, Lei 2018-07-13 11:23:10 +08:00
parent 8cf599ec15
commit c359f07870
3 changed files with 155 additions and 32 deletions

View File

@ -1553,6 +1553,77 @@ class AsmRelationGroup(AsmBase):
obj.purgeTouched()
return obj
@staticmethod
def gotoRelationOfConstraint(obj,subname):
sub = Part.splitSubname(subname)[0].split('.')
sobj = obj.getSubObject(subname,retType=1)
if isTypeOf(sobj,AsmElementLink):
sobj = sobj.parent.Object
sub = sub[:-2]
else:
sub = sub[:-1]
if not isTypeOf(sobj,AsmConstraint):
return
sub[-2] = '3'
sub[-1] = ''
sub = '.'.join(sub)
subs = []
relationGroup = sobj.Proxy.getAssembly().getRelationGroup(True)
for relation in relationGroup.Proxy.getRelations().values():
for o in relation.Group:
if isTypeOf(o,AsmRelation):
found = False
for child in o.Group:
if child == sobj:
subs.append('{}{}.{}.{}.'.format(
sub,relation.Name,o.Name,child.Name))
found = True
break
if found:
continue
elif o == sobj:
subs.append('{}{}.{}.'.format(sub,relation.Name,o.Name))
if subs:
FreeCADGui.Selection.pushSelStack()
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(obj,subs)
FreeCADGui.Selection.pushSelStack()
FreeCADGui.runCommand('Std_TreeSelection')
@staticmethod
def gotoRelation(moveInfo):
if not moveInfo:
return
info = moveInfo.ElementInfo
if info.Subname:
subs = moveInfo.SelSubname[:-len(info.Subname)]
else:
subs = moveInfo.SelSubname
subs = subs.split('.')
relationGroup = resolveAssembly(info.Parent).getRelationGroup()
if isinstance(info.Part,tuple):
part = info.Part[0]
else:
part = info.Part
relation = relationGroup.Proxy.findRelation(part)
if not relation:
return
if isinstance(info.Part,tuple):
if len(subs)<4:
subs.append('')
subs[-4] = '3'
subs[-3] = relation.Name
subs[-2] = relation.Group[info.Part[1]].Name
else:
subs[-3] = '3'
subs[-2] = relation.Name
FreeCADGui.Selection.pushSelStack()
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(moveInfo.SelObj,'.'.join(subs))
FreeCADGui.Selection.pushSelStack()
FreeCADGui.runCommand('Std_TreeSelection')
class ViewProviderAsmRelationGroup(ViewProviderAsmBase):
_iconName = 'Assembly_Assembly_Relation_Tree.svg'
@ -1587,6 +1658,18 @@ class AsmRelation(AsmBase):
obj.setPropertyStatus('Group','Hidden')
super(AsmRelation,self).attach(obj)
def getSubObject(self,obj,subname,retType,mat,transform,depth):
if not subname or subname[0]==';':
return False
idx = subname.find('.')
if idx<0:
return False
name = subname[:idx]
for o in obj.Group:
if o.Name == name:
return o.getSubObject(subname[idx+1:],
retType,mat,transform,depth+1)
def getAssembly(self):
return self.parent.getAssembly()

77
gui.py
View File

@ -231,31 +231,48 @@ class AsmCmdMove(AsmCmdBase):
_id = 2
_menuText = 'Move part'
_iconName = 'Assembly_Move.svg'
_useCenterballDragger = True
_accel = 'A, M'
_moveInfo = None
@classmethod
def Activated(cls):
from . import mover
mover.movePart(cls._useCenterballDragger)
mover.movePart(True,cls._moveInfo)
@classmethod
def canMove(cls):
from . import mover
cls._moveInfo = None
cls._moveInfo = mover.getMovingElementInfo()
mover.checkFixedPart(cls._moveInfo.ElementInfo)
return True
@classmethod
def checkActive(cls):
from . import mover
cls._active = mover.canMovePart()
cls._active = logger.catchTrace('',cls.canMove)
@classmethod
def onClearSelection(cls):
cls._active = False
cls._moveInfo = None
class AsmCmdAxialMove(AsmCmdMove):
class AsmCmdAxialMove(AsmCmdBase):
_id = 3
_menuText = 'Axial move part'
_iconName = 'Assembly_AxialMove.svg'
_useCenterballDragger = False
_accel = 'A, A'
class AsmCmdQuickMove(AsmCmdBase):
@classmethod
def IsActive(cls):
return AsmCmdMove.IsActive()
@classmethod
def Activated(cls):
from . import mover
mover.movePart(False,AsmCmdMove._moveInfo)
class AsmCmdQuickMove(AsmCmdAxialMove):
_id = 13
_menuText = 'Quick move'
_tooltip = 'Bring an object contained in an assembly to where the mouse\n'\
@ -269,15 +286,6 @@ class AsmCmdQuickMove(AsmCmdBase):
from . import mover
mover.quickMove()
@classmethod
def checkActive(cls):
from . import mover
cls._active = mover.canMovePart()
@classmethod
def onClearSelection(cls):
cls._active = False
class AsmCmdCheckable(AsmCmdBase):
_id = -2
_saveParam = False
@ -465,6 +473,45 @@ class AsmCmdAddWorkplaneGroup(AsmCmdAddWorkplane):
def Activated(cls,idx=0):
FreeCADGui.runCommand(cls._cmds[idx])
class AsmCmdGotoRelation(AsmCmdBase):
_id = 16
_menuText = 'Go to relation'
_tooltip = 'Select the corresponding part object in the relation group'
_iconName = 'Assembly_GotoRelation.svg'
_accel = 'A, R'
@classmethod
def Activated(cls):
from .assembly import AsmRelationGroup
if AsmCmdMove._moveInfo:
AsmRelationGroup.gotoRelation(AsmCmdMove._moveInfo)
return
sels = FreeCADGui.Selection.getSelectionEx('',0,True)
if sels and len(sels[0].SubElementNames)==1:
AsmRelationGroup.gotoRelationOfConstraint(
sels[0].Object,sels[0].SubElementNames[0])
@classmethod
def IsActive(cls):
if AsmCmdMove._moveInfo:
return True
if cls._active is None:
cls.checkActive()
return cls._active
@classmethod
def checkActive(cls):
from .assembly import isTypeOf, AsmConstraint, AsmElementLink
sels = FreeCADGui.Selection.getSelection('',1,True)
if sels and isTypeOf(sels[0],(AsmConstraint,AsmElementLink)):
cls._active = True
else:
cls._active = False
@classmethod
def onSelectionChange(cls,hasSelection):
cls._active = None if hasSelection else False
class AsmCmdUp(AsmCmdBase):
_id = 6

View File

@ -210,13 +210,10 @@ class AsmMovingPart(object):
# AsmMovingPart.update()
return self.draggerPlacement
def _checkFixedPart(info):
def checkFixedPart(info):
if not gui.AsmCmdManager.LockMover:
return
if isTypeOf(info.Parent,Assembly,True):
assembly = info.Parent.getLinkedObject(True).Proxy
else:
assembly = info.Parent.getAssembly()
assembly = resolveAssembly(info.Parent)
cstrs = assembly.getConstraints()
parts = assembly.getPartGroup().Group
if info.Part in Constraint.getFixedParts(None,cstrs,parts):
@ -258,7 +255,6 @@ def getMovingElementInfo():
if len(sels[0].SubElementNames)==1:
info = getElementInfo(ret[0].Assembly,
ret[0].Subname, checkPlacement=True)
_checkFixedPart(info)
return MovingPartInfo(SelObj=selObj,
SelSubname=selSub,
Hierarchy=ret,
@ -283,22 +279,19 @@ def getMovingElementInfo():
for r in ret2:
if assembly == r.Assembly:
info = getElementInfo(r.Assembly,r.Subname,checkPlacement=True)
_checkFixedPart(info)
return MovingPartInfo(SelObj=selObj,
SelSubname=selSub,
Hierarchy=ret2,
ElementInfo=info)
raise RuntimeError('not child parent selection')
def canMovePart():
return logger.catchTrace('',getMovingElementInfo) is not None
def movePart(useCenterballDragger=None):
ret = logger.catch('exception when moving part', getMovingElementInfo)
if not ret:
return False
info = ret.ElementInfo
def movePart(useCenterballDragger=None,moveInfo=None):
if not moveInfo:
moveInfo = logger.catch(
'exception when moving part', getMovingElementInfo)
if not moveInfo:
return False
info = moveInfo.ElementInfo
doc = FreeCADGui.editDocument()
if doc:
doc.resetEdit()
@ -306,7 +299,7 @@ def movePart(useCenterballDragger=None):
doc = info.Parent.ViewObject.Document
if useCenterballDragger is not None:
vobj.UseCenterballDragger = useCenterballDragger
vobj.Proxy._movingPart = AsmMovingPart(ret.Hierarchy,info)
vobj.Proxy._movingPart = AsmMovingPart(moveInfo.Hierarchy,info)
FreeCADGui.Selection.clearSelection()
return doc.setEdit(vobj,1)