gui: add GotoRelation command
Can either go from part or constraint to their corresponding relation item.
This commit is contained in:
parent
8cf599ec15
commit
c359f07870
83
assembly.py
83
assembly.py
|
@ -1553,6 +1553,77 @@ class AsmRelationGroup(AsmBase):
|
||||||
obj.purgeTouched()
|
obj.purgeTouched()
|
||||||
return obj
|
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):
|
class ViewProviderAsmRelationGroup(ViewProviderAsmBase):
|
||||||
_iconName = 'Assembly_Assembly_Relation_Tree.svg'
|
_iconName = 'Assembly_Assembly_Relation_Tree.svg'
|
||||||
|
@ -1587,6 +1658,18 @@ class AsmRelation(AsmBase):
|
||||||
obj.setPropertyStatus('Group','Hidden')
|
obj.setPropertyStatus('Group','Hidden')
|
||||||
super(AsmRelation,self).attach(obj)
|
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):
|
def getAssembly(self):
|
||||||
return self.parent.getAssembly()
|
return self.parent.getAssembly()
|
||||||
|
|
||||||
|
|
77
gui.py
77
gui.py
|
@ -231,31 +231,48 @@ class AsmCmdMove(AsmCmdBase):
|
||||||
_id = 2
|
_id = 2
|
||||||
_menuText = 'Move part'
|
_menuText = 'Move part'
|
||||||
_iconName = 'Assembly_Move.svg'
|
_iconName = 'Assembly_Move.svg'
|
||||||
_useCenterballDragger = True
|
|
||||||
_accel = 'A, M'
|
_accel = 'A, M'
|
||||||
|
_moveInfo = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def Activated(cls):
|
def Activated(cls):
|
||||||
from . import mover
|
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
|
@classmethod
|
||||||
def checkActive(cls):
|
def checkActive(cls):
|
||||||
from . import mover
|
cls._active = logger.catchTrace('',cls.canMove)
|
||||||
cls._active = mover.canMovePart()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def onClearSelection(cls):
|
def onClearSelection(cls):
|
||||||
cls._active = False
|
cls._active = False
|
||||||
|
cls._moveInfo = None
|
||||||
|
|
||||||
class AsmCmdAxialMove(AsmCmdMove):
|
class AsmCmdAxialMove(AsmCmdBase):
|
||||||
_id = 3
|
_id = 3
|
||||||
_menuText = 'Axial move part'
|
_menuText = 'Axial move part'
|
||||||
_iconName = 'Assembly_AxialMove.svg'
|
_iconName = 'Assembly_AxialMove.svg'
|
||||||
_useCenterballDragger = False
|
_useCenterballDragger = False
|
||||||
_accel = 'A, A'
|
_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
|
_id = 13
|
||||||
_menuText = 'Quick move'
|
_menuText = 'Quick move'
|
||||||
_tooltip = 'Bring an object contained in an assembly to where the mouse\n'\
|
_tooltip = 'Bring an object contained in an assembly to where the mouse\n'\
|
||||||
|
@ -269,15 +286,6 @@ class AsmCmdQuickMove(AsmCmdBase):
|
||||||
from . import mover
|
from . import mover
|
||||||
mover.quickMove()
|
mover.quickMove()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def checkActive(cls):
|
|
||||||
from . import mover
|
|
||||||
cls._active = mover.canMovePart()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def onClearSelection(cls):
|
|
||||||
cls._active = False
|
|
||||||
|
|
||||||
class AsmCmdCheckable(AsmCmdBase):
|
class AsmCmdCheckable(AsmCmdBase):
|
||||||
_id = -2
|
_id = -2
|
||||||
_saveParam = False
|
_saveParam = False
|
||||||
|
@ -465,6 +473,45 @@ class AsmCmdAddWorkplaneGroup(AsmCmdAddWorkplane):
|
||||||
def Activated(cls,idx=0):
|
def Activated(cls,idx=0):
|
||||||
FreeCADGui.runCommand(cls._cmds[idx])
|
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):
|
class AsmCmdUp(AsmCmdBase):
|
||||||
_id = 6
|
_id = 6
|
||||||
|
|
25
mover.py
25
mover.py
|
@ -210,13 +210,10 @@ class AsmMovingPart(object):
|
||||||
# AsmMovingPart.update()
|
# AsmMovingPart.update()
|
||||||
return self.draggerPlacement
|
return self.draggerPlacement
|
||||||
|
|
||||||
def _checkFixedPart(info):
|
def checkFixedPart(info):
|
||||||
if not gui.AsmCmdManager.LockMover:
|
if not gui.AsmCmdManager.LockMover:
|
||||||
return
|
return
|
||||||
if isTypeOf(info.Parent,Assembly,True):
|
assembly = resolveAssembly(info.Parent)
|
||||||
assembly = info.Parent.getLinkedObject(True).Proxy
|
|
||||||
else:
|
|
||||||
assembly = info.Parent.getAssembly()
|
|
||||||
cstrs = assembly.getConstraints()
|
cstrs = assembly.getConstraints()
|
||||||
parts = assembly.getPartGroup().Group
|
parts = assembly.getPartGroup().Group
|
||||||
if info.Part in Constraint.getFixedParts(None,cstrs,parts):
|
if info.Part in Constraint.getFixedParts(None,cstrs,parts):
|
||||||
|
@ -258,7 +255,6 @@ def getMovingElementInfo():
|
||||||
if len(sels[0].SubElementNames)==1:
|
if len(sels[0].SubElementNames)==1:
|
||||||
info = getElementInfo(ret[0].Assembly,
|
info = getElementInfo(ret[0].Assembly,
|
||||||
ret[0].Subname, checkPlacement=True)
|
ret[0].Subname, checkPlacement=True)
|
||||||
_checkFixedPart(info)
|
|
||||||
return MovingPartInfo(SelObj=selObj,
|
return MovingPartInfo(SelObj=selObj,
|
||||||
SelSubname=selSub,
|
SelSubname=selSub,
|
||||||
Hierarchy=ret,
|
Hierarchy=ret,
|
||||||
|
@ -283,22 +279,19 @@ def getMovingElementInfo():
|
||||||
for r in ret2:
|
for r in ret2:
|
||||||
if assembly == r.Assembly:
|
if assembly == r.Assembly:
|
||||||
info = getElementInfo(r.Assembly,r.Subname,checkPlacement=True)
|
info = getElementInfo(r.Assembly,r.Subname,checkPlacement=True)
|
||||||
_checkFixedPart(info)
|
|
||||||
return MovingPartInfo(SelObj=selObj,
|
return MovingPartInfo(SelObj=selObj,
|
||||||
SelSubname=selSub,
|
SelSubname=selSub,
|
||||||
Hierarchy=ret2,
|
Hierarchy=ret2,
|
||||||
ElementInfo=info)
|
ElementInfo=info)
|
||||||
raise RuntimeError('not child parent selection')
|
raise RuntimeError('not child parent selection')
|
||||||
|
|
||||||
def canMovePart():
|
def movePart(useCenterballDragger=None,moveInfo=None):
|
||||||
return logger.catchTrace('',getMovingElementInfo) is not None
|
if not moveInfo:
|
||||||
|
moveInfo = logger.catch(
|
||||||
def movePart(useCenterballDragger=None):
|
'exception when moving part', getMovingElementInfo)
|
||||||
ret = logger.catch('exception when moving part', getMovingElementInfo)
|
if not moveInfo:
|
||||||
if not ret:
|
|
||||||
return False
|
return False
|
||||||
|
info = moveInfo.ElementInfo
|
||||||
info = ret.ElementInfo
|
|
||||||
doc = FreeCADGui.editDocument()
|
doc = FreeCADGui.editDocument()
|
||||||
if doc:
|
if doc:
|
||||||
doc.resetEdit()
|
doc.resetEdit()
|
||||||
|
@ -306,7 +299,7 @@ def movePart(useCenterballDragger=None):
|
||||||
doc = info.Parent.ViewObject.Document
|
doc = info.Parent.ViewObject.Document
|
||||||
if useCenterballDragger is not None:
|
if useCenterballDragger is not None:
|
||||||
vobj.UseCenterballDragger = useCenterballDragger
|
vobj.UseCenterballDragger = useCenterballDragger
|
||||||
vobj.Proxy._movingPart = AsmMovingPart(ret.Hierarchy,info)
|
vobj.Proxy._movingPart = AsmMovingPart(moveInfo.Hierarchy,info)
|
||||||
FreeCADGui.Selection.clearSelection()
|
FreeCADGui.Selection.clearSelection()
|
||||||
return doc.setEdit(vobj,1)
|
return doc.setEdit(vobj,1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user