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.utils as utils
from asm3.utils import logger, objName
from asm3.constraint import Constraint
from asm3.constraint import Constraint, cstrName
from asm3.system import System
def setupUndo(doc,undoDocs,name):
@ -35,6 +35,26 @@ def getProxy(obj,tp):
checkType(obj,tp)
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()
Selection = namedtuple('AsmSelection',('Object','SubElementNames'))
@ -170,7 +190,7 @@ class ViewProviderAsmPartGroup(ViewProviderAsmGroup):
return False
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):
return True
@ -413,7 +433,7 @@ class AsmElement(AsmBase):
# Pop the immediate child name, and replace it with child
# assembly's element group name
prefix = prefix[:prefix.rfind('.')+1] + \
ret.Assembly.Proxy.getElementGroup().Name
resolveAssembly(ret.Assembly).getElementGroup().Name
subname = '{}.${}.'.format(prefix,element.Label)
@ -505,7 +525,7 @@ def getPartInfo(parent, subname):
subnameRef = subname
names = subname.split('.')
if isTypeOf(parent,Assembly):
if isTypeOf(parent,Assembly,True):
child = parent.getSubObject(names[0]+'.',1)
if not child:
raise RuntimeError('Invalid sub object {}, {}'.format(
@ -663,10 +683,14 @@ class AsmElementLink(AsmBase):
# The reference stored inside this ElementLink. We need the sub assembly
# 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
# 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]
return '{}.{}.{}'.format(ref[0:ref.find('.')],
assembly.getPartGroup().Name, element.getElementSubname())
prefix = ref[0:ref.rfind('.',0,ref.rfind('.',0,-1))]
return '{}.{}.{}'.format(prefix, assembly.getPartGroup().Name,
element.getElementSubname())
def setLink(self,owner,subname):
# 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
# assembly's element group name
prefix = prefix[:prefix.rfind('.')+1] + \
ret.Assembly.Proxy.getElementGroup().Name
resolveAssembly(ret.Assembly).getElementGroup().Name
subname = '{}.${}.'.format(prefix, element.Label)
@ -869,7 +893,8 @@ class AsmConstraint(AsmGroup):
raise RuntimeError('too many selection')
if len(subs)==2:
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])
sel = sels[0]
@ -889,7 +914,8 @@ class AsmConstraint(AsmGroup):
'assembly'.format(sel.Object.Name,sub))
# 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:
raise RuntimeError('no element selection')
assembly = ret[-1].Assembly
@ -917,8 +943,10 @@ class AsmConstraint(AsmGroup):
# we shall adjust the element subname by popping the first '.'
sub = found.Subname
sub = sub[sub.index('.')+1:]
if sub[-1] == '.' and not isTypeOf(sobj,(Assembly,AsmConstraint,
AsmConstraintGroup,AsmElement,AsmElementLink)):
if sub[-1] == '.' and \
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
subElement = utils.deduceSelectedElement(found.Object,sub)
if not subElement:
@ -1070,7 +1098,7 @@ class AsmConstraintGroup(AsmGroup):
return obj
class ViewProviderAsmConstraintGroup(ViewProviderAsmGroupOnTop):
class ViewProviderAsmConstraintGroup(ViewProviderAsmGroup):
_iconName = 'Assembly_Assembly_Constraints_Tree.svg'
def canDropObjects(self):
@ -1119,7 +1147,7 @@ class AsmElementGroup(AsmGroup):
return obj
class ViewProviderAsmElementGroup(ViewProviderAsmGroupOnTop):
class ViewProviderAsmElementGroup(ViewProviderAsmGroup):
_iconName = 'Assembly_Assembly_Element_Tree.svg'
def onDelete(self,_obj,_subs):
@ -1263,13 +1291,12 @@ class Assembly(AsmGroup):
for o in cstrGroup.Group:
checkType(o,AsmConstraint)
if Constraint.isDisabled(o):
logger.debug('skip constraint "{}" type '
'{}'.format(objName(o),o.Type))
logger.debug('skip constraint {}'.format(cstrName(o)))
continue
if not System.isConstraintSupported(self.Object,
Constraint.getTypeName(o)):
logger.debug('skip unsupported constraint "{}" type '
'{}'.format(objName(o),o.Type))
logger.debug('skip unsupported constraint '
'{}'.format(cstrName(o)))
continue
ret.append(o)
self.constraints = ret
@ -1351,7 +1378,7 @@ class Assembly(AsmGroup):
sels = FreeCADGui.Selection.getSelectionEx('',False)
for sel in sels:
if not sel.SubElementNames:
if isTypeOf(sel.Object,Assembly):
if isTypeOf(sel.Object,Assembly,True):
objs.add(sel.Object)
continue
for subname in sel.SubElementNames:
@ -1441,14 +1468,7 @@ class Assembly(AsmGroup):
class AsmMovingPart(object):
def __init__(self,hierarchy,info):
self.objs = [h.Assembly for h in reversed(hierarchy)]
if isTypeOf(info.Parent,Assembly):
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.assembly = resolveAssembly(info.Parent)
self.parent = info.Parent
self.subname = info.SubnameRef
self.undos = None
@ -1573,7 +1593,7 @@ def getMovingPartInfo():
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
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
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]))
if len(sels[0].SubElementNames)==1:
info = getPartInfo(ret[-1].Assembly,ret[-1].Subname)
if not info and len(ret)>1:
info = getPartInfo(ret[-2].Assembly,ret[-2].Subname)
info = getPartInfo(ret[0].Assembly,ret[0].Subname)
if not info:
return
return (ret, info)
@ -1633,14 +1651,12 @@ def movePart(useCenterballDragger=None):
doc = FreeCADGui.editDocument()
if doc:
doc.resetEdit()
if isTypeOf(info.Parent,AsmPartGroup):
vobj = info.Parent.Proxy.parent.Object.ViewObject
else:
vobj = info.Parent.ViewObject
vobj = resolveAssembly(info.Parent).Object.ViewObject
doc = info.Parent.ViewObject.Document
if useCenterballDragger is not None:
vobj.UseCenterballDragger = useCenterballDragger
vobj.Proxy._movingPart = AsmMovingPart(*ret)
return vobj.Document.setEdit(vobj,1)
return doc.setEdit(vobj,1)
class ViewProviderAssembly(ViewProviderAsmGroup):