assembly: fixed linked part moving

This commit is contained in:
Zheng, Lei 2017-12-03 18:20:25 +08:00
parent bd6635207b
commit c738d24b7d

View File

@ -4,7 +4,7 @@ import FreeCAD, FreeCADGui
import asm3 import asm3
import asm3.utils as utils import asm3.utils as utils
from asm3.utils import logger, objName from asm3.utils import logger, objName
from asm3.constraint import Constraint from asm3.constraint import Constraint, cstrName
from asm3.system import System from asm3.system import System
def setupUndo(doc,undoDocs,name): def setupUndo(doc,undoDocs,name):
@ -35,6 +35,26 @@ def getProxy(obj,tp):
checkType(obj,tp) checkType(obj,tp)
return obj.Proxy return obj.Proxy
def resolveAssembly(obj):
'''Try various ways to obtain an assembly from the input object
obj can be a link, a proxy, a child group of an assembly, or simply an
assembly
'''
func = getattr(obj,'getLinkedObject',None)
if func:
obj = func(True)
proxy = getattr(obj,'Proxy',None)
if proxy:
obj = proxy
if isinstance(obj,Assembly):
return obj
func = getattr(obj,'getAssembly',None)
if func:
return func()
raise TypeError('cannot resolve assembly from {}'.format(obj))
# For faking selection obtained from Gui.getSelectionEx() # For faking selection obtained from Gui.getSelectionEx()
Selection = namedtuple('AsmSelection',('Object','SubElementNames')) Selection = namedtuple('AsmSelection',('Object','SubElementNames'))
@ -170,7 +190,7 @@ class ViewProviderAsmPartGroup(ViewProviderAsmGroup):
return False return False
def canDropObjectEx(self,obj,_owner,_subname): def canDropObjectEx(self,obj,_owner,_subname):
return isTypeOf(obj,Assembly) or not isTypeOf(obj,AsmBase) return isTypeOf(obj,Assembly, True) or not isTypeOf(obj,AsmBase)
def canDragObject(self,_obj): def canDragObject(self,_obj):
return True return True
@ -413,7 +433,7 @@ class AsmElement(AsmBase):
# Pop the immediate child name, and replace it with child # Pop the immediate child name, and replace it with child
# assembly's element group name # assembly's element group name
prefix = prefix[:prefix.rfind('.')+1] + \ prefix = prefix[:prefix.rfind('.')+1] + \
ret.Assembly.Proxy.getElementGroup().Name resolveAssembly(ret.Assembly).getElementGroup().Name
subname = '{}.${}.'.format(prefix,element.Label) subname = '{}.${}.'.format(prefix,element.Label)
@ -505,7 +525,7 @@ def getPartInfo(parent, subname):
subnameRef = subname subnameRef = subname
names = subname.split('.') names = subname.split('.')
if isTypeOf(parent,Assembly): if isTypeOf(parent,Assembly,True):
child = parent.getSubObject(names[0]+'.',1) child = parent.getSubObject(names[0]+'.',1)
if not child: if not child:
raise RuntimeError('Invalid sub object {}, {}'.format( raise RuntimeError('Invalid sub object {}, {}'.format(
@ -663,10 +683,14 @@ class AsmElementLink(AsmBase):
# The reference stored inside this ElementLink. We need the sub assembly # The reference stored inside this ElementLink. We need the sub assembly
# name, which is the name before the first dot. This name may be # name, which is the name before the first dot. This name may be
# different from the actual assembly object's name, in case where the # different from the actual assembly object's name, in case where the
# assembly is accessed through a link # assembly is accessed through a link. And the sub assembly may be
# inside a link array, which we don't know for sure. But we do know that
# the last two names are element group and element label. So just pop
# two names.
ref = self.Object.LinkedObject[1] ref = self.Object.LinkedObject[1]
return '{}.{}.{}'.format(ref[0:ref.find('.')], prefix = ref[0:ref.rfind('.',0,ref.rfind('.',0,-1))]
assembly.getPartGroup().Name, element.getElementSubname()) return '{}.{}.{}'.format(prefix, assembly.getPartGroup().Name,
element.getElementSubname())
def setLink(self,owner,subname): def setLink(self,owner,subname):
# check if there is any sub assembly in the reference # check if there is any sub assembly in the reference
@ -692,7 +716,7 @@ class AsmElementLink(AsmBase):
# Pop the immediate child name, and replace it with child # Pop the immediate child name, and replace it with child
# assembly's element group name # assembly's element group name
prefix = prefix[:prefix.rfind('.')+1] + \ prefix = prefix[:prefix.rfind('.')+1] + \
ret.Assembly.Proxy.getElementGroup().Name resolveAssembly(ret.Assembly).getElementGroup().Name
subname = '{}.${}.'.format(prefix, element.Label) subname = '{}.${}.'.format(prefix, element.Label)
@ -869,7 +893,8 @@ class AsmConstraint(AsmGroup):
raise RuntimeError('too many selection') raise RuntimeError('too many selection')
if len(subs)==2: if len(subs)==2:
sobj = sels[0].Object.getSubObject(subs[1],1) sobj = sels[0].Object.getSubObject(subs[1],1)
if isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)): if isTypeOf(sobj,Assembly,True) or \
isTypeOf(sobj,(AsmConstraintGroup,AsmConstraint)):
subs = (subs[1],subs[0]) subs = (subs[1],subs[0])
sel = sels[0] sel = sels[0]
@ -889,7 +914,8 @@ class AsmConstraint(AsmGroup):
'assembly'.format(sel.Object.Name,sub)) 'assembly'.format(sel.Object.Name,sub))
# check if the selection is a constraint group or a constraint # check if the selection is a constraint group or a constraint
if isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)): if isTypeOf(sobj,Assembly,True) or \
isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)):
if assembly: if assembly:
raise RuntimeError('no element selection') raise RuntimeError('no element selection')
assembly = ret[-1].Assembly assembly = ret[-1].Assembly
@ -917,8 +943,10 @@ class AsmConstraint(AsmGroup):
# we shall adjust the element subname by popping the first '.' # we shall adjust the element subname by popping the first '.'
sub = found.Subname sub = found.Subname
sub = sub[sub.index('.')+1:] sub = sub[sub.index('.')+1:]
if sub[-1] == '.' and not isTypeOf(sobj,(Assembly,AsmConstraint, if sub[-1] == '.' and \
AsmConstraintGroup,AsmElement,AsmElementLink)): not isTypeOf(sobj,Assembly,True) and \
not isTypeOf(sobj,(AsmConstraint,AsmConstraintGroup,
AsmElement,AsmElementLink)):
# Too bad, its a full selection, let's guess the sub element # Too bad, its a full selection, let's guess the sub element
subElement = utils.deduceSelectedElement(found.Object,sub) subElement = utils.deduceSelectedElement(found.Object,sub)
if not subElement: if not subElement:
@ -1070,7 +1098,7 @@ class AsmConstraintGroup(AsmGroup):
return obj return obj
class ViewProviderAsmConstraintGroup(ViewProviderAsmGroupOnTop): class ViewProviderAsmConstraintGroup(ViewProviderAsmGroup):
_iconName = 'Assembly_Assembly_Constraints_Tree.svg' _iconName = 'Assembly_Assembly_Constraints_Tree.svg'
def canDropObjects(self): def canDropObjects(self):
@ -1119,7 +1147,7 @@ class AsmElementGroup(AsmGroup):
return obj return obj
class ViewProviderAsmElementGroup(ViewProviderAsmGroupOnTop): class ViewProviderAsmElementGroup(ViewProviderAsmGroup):
_iconName = 'Assembly_Assembly_Element_Tree.svg' _iconName = 'Assembly_Assembly_Element_Tree.svg'
def onDelete(self,_obj,_subs): def onDelete(self,_obj,_subs):
@ -1263,13 +1291,12 @@ class Assembly(AsmGroup):
for o in cstrGroup.Group: for o in cstrGroup.Group:
checkType(o,AsmConstraint) checkType(o,AsmConstraint)
if Constraint.isDisabled(o): if Constraint.isDisabled(o):
logger.debug('skip constraint "{}" type ' logger.debug('skip constraint {}'.format(cstrName(o)))
'{}'.format(objName(o),o.Type))
continue continue
if not System.isConstraintSupported(self.Object, if not System.isConstraintSupported(self.Object,
Constraint.getTypeName(o)): Constraint.getTypeName(o)):
logger.debug('skip unsupported constraint "{}" type ' logger.debug('skip unsupported constraint '
'{}'.format(objName(o),o.Type)) '{}'.format(cstrName(o)))
continue continue
ret.append(o) ret.append(o)
self.constraints = ret self.constraints = ret
@ -1351,7 +1378,7 @@ class Assembly(AsmGroup):
sels = FreeCADGui.Selection.getSelectionEx('',False) sels = FreeCADGui.Selection.getSelectionEx('',False)
for sel in sels: for sel in sels:
if not sel.SubElementNames: if not sel.SubElementNames:
if isTypeOf(sel.Object,Assembly): if isTypeOf(sel.Object,Assembly,True):
objs.add(sel.Object) objs.add(sel.Object)
continue continue
for subname in sel.SubElementNames: for subname in sel.SubElementNames:
@ -1441,14 +1468,7 @@ class Assembly(AsmGroup):
class AsmMovingPart(object): class AsmMovingPart(object):
def __init__(self,hierarchy,info): def __init__(self,hierarchy,info):
self.objs = [h.Assembly for h in reversed(hierarchy)] self.objs = [h.Assembly for h in reversed(hierarchy)]
if isTypeOf(info.Parent,Assembly): self.assembly = resolveAssembly(info.Parent)
self.assembly = info.Parent.Proxy
elif isTypeOf(info.Parent,AsmPartGroup):
self.assembly = info.Parent.Proxy.parent
else:
raise RuntimeError('invalid moving part parent object {}'.format(
objName(info.Parent)))
self.parent = info.Parent self.parent = info.Parent
self.subname = info.SubnameRef self.subname = info.SubnameRef
self.undos = None self.undos = None
@ -1573,7 +1593,7 @@ def getMovingPartInfo():
Assembly.findChildren()), and AsmPartInfo of the selected child part object. Assembly.findChildren()), and AsmPartInfo of the selected child part object.
If there is only one selection, then the moving part will be one belong to If there is only one selection, then the moving part will be one belong to
the deepest nested assembly object is selected hierarchy. the highest level assembly in selected hierarchy.
If there are two selections, then one selection must be a parent assembly If there are two selections, then one selection must be a parent assembly
containing the other child object. The moving object will then be the containing the other child object. The moving object will then be the
@ -1597,9 +1617,7 @@ def getMovingPartInfo():
objName(sels[0].Object),sels[0].SubElementNames[0])) objName(sels[0].Object),sels[0].SubElementNames[0]))
if len(sels[0].SubElementNames)==1: if len(sels[0].SubElementNames)==1:
info = getPartInfo(ret[-1].Assembly,ret[-1].Subname) info = getPartInfo(ret[0].Assembly,ret[0].Subname)
if not info and len(ret)>1:
info = getPartInfo(ret[-2].Assembly,ret[-2].Subname)
if not info: if not info:
return return
return (ret, info) return (ret, info)
@ -1633,14 +1651,12 @@ def movePart(useCenterballDragger=None):
doc = FreeCADGui.editDocument() doc = FreeCADGui.editDocument()
if doc: if doc:
doc.resetEdit() doc.resetEdit()
if isTypeOf(info.Parent,AsmPartGroup): vobj = resolveAssembly(info.Parent).Object.ViewObject
vobj = info.Parent.Proxy.parent.Object.ViewObject doc = info.Parent.ViewObject.Document
else:
vobj = info.Parent.ViewObject
if useCenterballDragger is not None: if useCenterballDragger is not None:
vobj.UseCenterballDragger = useCenterballDragger vobj.UseCenterballDragger = useCenterballDragger
vobj.Proxy._movingPart = AsmMovingPart(*ret) vobj.Proxy._movingPart = AsmMovingPart(*ret)
return vobj.Document.setEdit(vobj,1) return doc.setEdit(vobj,1)
class ViewProviderAssembly(ViewProviderAsmGroup): class ViewProviderAssembly(ViewProviderAsmGroup):