assembly: fixed linked part moving
This commit is contained in:
parent
bd6635207b
commit
c738d24b7d
88
assembly.py
88
assembly.py
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user