Complete support for drag and drop
This commit is contained in:
parent
6b91e11daf
commit
2274fec363
306
assembly.py
306
assembly.py
|
@ -28,13 +28,16 @@ def isTypeOf(obj,tp,resolve=False):
|
|||
|
||||
def checkType(obj,tp,resolve=False):
|
||||
if not isTypeOf(obj,tp,resolve):
|
||||
raise TypeError('Expect object "{}" to be of type "{}"'.format(
|
||||
raise TypeError('Expect object {} to be of type "{}"'.format(
|
||||
objName(obj),tp.__name__))
|
||||
|
||||
def getProxy(obj,tp):
|
||||
checkType(obj,tp)
|
||||
return obj.Proxy
|
||||
|
||||
# For faking selection obtained from Gui.getSelectionEx()
|
||||
Selection = namedtuple('AsmSelection',('Object','SubElementNames'))
|
||||
|
||||
class AsmBase(object):
|
||||
def __init__(self):
|
||||
self.Object = None
|
||||
|
@ -86,6 +89,15 @@ class ViewProviderAsmBase(object):
|
|||
if cls._iconName:
|
||||
return utils.getIcon(cls)
|
||||
|
||||
def canDropObjects(self):
|
||||
return True
|
||||
|
||||
def canDragObjects(self):
|
||||
return False
|
||||
|
||||
def canDragAndDropObject(self,_obj):
|
||||
return False
|
||||
|
||||
|
||||
class AsmGroup(AsmBase):
|
||||
def linkSetup(self,obj):
|
||||
|
@ -115,6 +127,9 @@ class ViewProviderAsmGroup(ViewProviderAsmBase):
|
|||
def doubleClicked(self, _vobj):
|
||||
return False
|
||||
|
||||
def canDropObject(self,_child):
|
||||
return False
|
||||
|
||||
|
||||
class AsmPartGroup(AsmGroup):
|
||||
def __init__(self,parent):
|
||||
|
@ -139,12 +154,19 @@ class ViewProviderAsmPartGroup(ViewProviderAsmBase):
|
|||
def onDelete(self,_obj,_subs):
|
||||
return False
|
||||
|
||||
def canDropObject(self,obj):
|
||||
def canDropObjectEx(self,obj,_owner,_subname):
|
||||
return isTypeOf(obj,Assembly) or not isTypeOf(obj,AsmBase)
|
||||
|
||||
def canDropObjects(self):
|
||||
def canDragObject(self,_obj):
|
||||
return True
|
||||
|
||||
def canDragObjects(self):
|
||||
return True
|
||||
|
||||
def canDragAndDropObject(self,_obj):
|
||||
return True
|
||||
|
||||
|
||||
class AsmElement(AsmBase):
|
||||
def __init__(self,parent):
|
||||
self.shape = None
|
||||
|
@ -237,17 +259,24 @@ class AsmElement(AsmBase):
|
|||
'The selections must have a common (grand)parent assembly')
|
||||
|
||||
sel = sels[0]
|
||||
subs = sel.SubElementNames
|
||||
subs = list(sel.SubElementNames)
|
||||
if not subs:
|
||||
raise RuntimeError('no sub object in selection')
|
||||
if len(subs)>2:
|
||||
raise RuntimeError('At most two selection is allowed.\n'
|
||||
'The first selection must be a sub element belonging to some '
|
||||
'assembly. The optional second selection must be an element '
|
||||
'belonging to the same assembly of the first selection')
|
||||
if len(subs)==2:
|
||||
if len(subs[0])<len(subs[1]):
|
||||
subs = [subs[1],subs[2]]
|
||||
|
||||
subElement = subs[0].split('.')[-1]
|
||||
if not subElement:
|
||||
raise RuntimeError(
|
||||
'Please select a sub element belonging to some assembly')
|
||||
if subs[0][-1] == '.':
|
||||
subElement = utils.deduceSelectedElement(sel.Object,subs[0])
|
||||
if not subElement:
|
||||
raise RuntimeError('no sub element (face, edge, vertex) in '
|
||||
'{}.{}'.format(sel.Object.Name,subs[0]))
|
||||
subs[0] += subElement
|
||||
|
||||
link = Assembly.findPartGroup(sel.Object,subs[0])
|
||||
if not link:
|
||||
|
@ -276,14 +305,17 @@ class AsmElement(AsmBase):
|
|||
def make(selection=None,name='Element'):
|
||||
if not selection:
|
||||
selection = AsmElement.getSelection()
|
||||
if not selection.Subname or selection.Subname[-1]=='.':
|
||||
raise RuntimeError('Subname must refer to a sub-element')
|
||||
assembly = getProxy(selection.Assembly,Assembly)
|
||||
element = selection.Element
|
||||
if not element:
|
||||
elements = assembly.getElementGroup()
|
||||
# try to search the element group for an existing element
|
||||
for e in elements.Group:
|
||||
if getProxy(e,AsmElement).getSubName() == selection.Subname:
|
||||
return element
|
||||
sub = logger.catch('',e.Proxy.getSubName)
|
||||
if sub == selection.Subname:
|
||||
return e
|
||||
element = elements.Document.addObject("App::FeaturePython",
|
||||
name,AsmElement(elements),None,True)
|
||||
ViewProviderAsmElement(element.ViewObject)
|
||||
|
@ -307,6 +339,20 @@ class ViewProviderAsmElement(ViewProviderAsmBase):
|
|||
def getDefaultColor(self):
|
||||
return (60.0/255.0,1.0,1.0)
|
||||
|
||||
def canDropObjectEx(self,_obj,owner,subname):
|
||||
# check if is dropping a sub-element
|
||||
if not subname or subname[-1]=='.':
|
||||
return False
|
||||
proxy = self.ViewObject.Object.Proxy
|
||||
return proxy.getAssembly().getPartGroup()==owner
|
||||
|
||||
def dropObjectEx(self,vobj,_obj,_owner,subname):
|
||||
obj = vobj.Object
|
||||
AsmElement.make(AsmElement.Selection(
|
||||
Assembly=obj.Proxy.getAssembly().Object,
|
||||
Element=obj, Subname=subname))
|
||||
|
||||
|
||||
PartInfo = namedtuple('AsmPartInfo', ('Parent','SubnameRef','Part',
|
||||
'PartName','Placement','Object','Subname','Shape'))
|
||||
|
||||
|
@ -517,7 +563,9 @@ class AsmElementLink(AsmBase):
|
|||
logger.debug('shape subname {} -> {}'.format(subname,sub))
|
||||
return sub
|
||||
|
||||
def prepareLink(self,owner,subname):
|
||||
def prepareLink(self,owner,subname,checkOnly=False):
|
||||
if not owner or not subname:
|
||||
raise RuntimeError('no owner or subname')
|
||||
assembly = self.getAssembly()
|
||||
sobj = owner.getSubObject(subname,1)
|
||||
if not sobj:
|
||||
|
@ -550,6 +598,11 @@ class AsmElementLink(AsmBase):
|
|||
if not isTypeOf(ret[-1].Object,AsmPartGroup):
|
||||
raise RuntimeError('Invalid element link ' + subname)
|
||||
|
||||
if checkOnly:
|
||||
if not ret[-1].Subname or ret[-1].Subname[-1]=='.':
|
||||
raise RuntimeError('Subname must refer to a sub-element')
|
||||
return True
|
||||
|
||||
# call AsmElement.make to either create a new element, or an existing
|
||||
# element if there is one
|
||||
element = AsmElement.make(AsmElement.Selection(
|
||||
|
@ -566,7 +619,16 @@ class AsmElementLink(AsmBase):
|
|||
|
||||
def setLink(self,owner,subname):
|
||||
obj = self.Object
|
||||
obj.setLink(*self.prepareLink(owner,subname))
|
||||
owner,subname = self.prepareLink(owner,subname)
|
||||
for sibling in self.parent.Object.Group:
|
||||
if sibling == self.Object:
|
||||
continue
|
||||
linked = sibling.LinkedObject
|
||||
if isinstance(linked,tuple) and \
|
||||
linked[0]==owner and linked[1]==subname:
|
||||
raise RuntimeError('duplicate element link {} in constraint '
|
||||
'{}'.format(objName(sibling),objName(self.parent.Object)))
|
||||
obj.setLink(owner,subname)
|
||||
linked = obj.getLinkedObject(False)
|
||||
if linked and linked!=obj:
|
||||
label = linked.Label.split('_')
|
||||
|
@ -607,7 +669,7 @@ class AsmElementLink(AsmBase):
|
|||
setupUndo(part.Document,undoDocs,undoName)
|
||||
part.Placement = pla
|
||||
|
||||
MakeInfo = namedtuple('AsmElementLinkSelection',
|
||||
MakeInfo = namedtuple('AsmElementLinkMakeInfo',
|
||||
('Constraint','Owner','Subname'))
|
||||
|
||||
@staticmethod
|
||||
|
@ -627,6 +689,17 @@ class ViewProviderAsmElementLink(ViewProviderAsmBase):
|
|||
def doubleClicked(self,_vobj):
|
||||
return movePart()
|
||||
|
||||
def canDropObjectEx(self,_obj,owner,subname):
|
||||
if logger.catchTrace('Cannot drop to AsmLink {}'.format(
|
||||
objName(self.ViewObject.Object)),
|
||||
self.ViewObject.Object.Proxy.prepareLink,
|
||||
owner, subname, True):
|
||||
return True
|
||||
return False
|
||||
|
||||
def dropObjectEx(self,vobj,_obj,owner,subname):
|
||||
vobj.Object.Proxy.setLink(owner,subname)
|
||||
|
||||
|
||||
class AsmConstraint(AsmGroup):
|
||||
|
||||
|
@ -700,77 +773,100 @@ class AsmConstraint(AsmGroup):
|
|||
return
|
||||
shapes.append(info.Shape)
|
||||
elements.append(o)
|
||||
Constraint.check(obj,shapes)
|
||||
Constraint.check(obj,shapes,True)
|
||||
self.elements = elements
|
||||
return self.elements
|
||||
|
||||
Selection = namedtuple('ConstraintSelection',
|
||||
Selection = namedtuple('AsmConstraintSelection',
|
||||
('SelObject','SelSubname','Assembly','Constraint','Elements'))
|
||||
|
||||
@staticmethod
|
||||
def getSelection(typeid=0):
|
||||
def getSelection(typeid=0,sels=None):
|
||||
'''
|
||||
Parse Gui.Selection for making a constraint
|
||||
|
||||
The selected elements must all belong to the same immediate parent
|
||||
assembly.
|
||||
'''
|
||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||
if not sels:
|
||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||
if not sels:
|
||||
raise RuntimeError('no selection')
|
||||
if len(sels)>1:
|
||||
raise RuntimeError(
|
||||
'The selections must have a common (grand)parent assembly')
|
||||
subs = sels[0].SubElementNames
|
||||
if not subs:
|
||||
raise RuntimeError('no sub-object in selection')
|
||||
if len(subs)>2:
|
||||
raise RuntimeError('too many selection')
|
||||
if len(subs)==2:
|
||||
sobj = sels[0].Object.getSubObject(subs[1],1)
|
||||
if isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)):
|
||||
subs = (subs[1],subs[0])
|
||||
|
||||
sel = sels[0]
|
||||
cstr = None
|
||||
elements = []
|
||||
assembly = None
|
||||
selSubname = None
|
||||
for sub in sel.SubElementNames:
|
||||
for sub in subs:
|
||||
sobj = sel.Object.getSubObject(sub,1)
|
||||
if not sobj:
|
||||
raise RuntimeError('Cannot find sub-object "{}" of {}'.format(
|
||||
sub,sel.Object))
|
||||
raise RuntimeError('Cannot find sub-object {}.{}'.format(
|
||||
sel.Object.Name,sub))
|
||||
ret = Assembly.find(sel.Object,sub,
|
||||
recursive=True,relativeToChild=False)
|
||||
if not ret:
|
||||
raise RuntimeError('Selection {}.{} is not from an '
|
||||
'assembly'.format(sel.Object.Name,sub))
|
||||
|
||||
# check if the selection is a constraint group or a constraint
|
||||
if isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)):
|
||||
if assembly:
|
||||
raise RuntimeError('no element selection')
|
||||
assembly = ret[-1].Assembly
|
||||
selSubname = sub[:-len(ret[-1].Subname)]
|
||||
if isTypeOf(sobj,AsmConstraint):
|
||||
cstr = sobj
|
||||
continue
|
||||
|
||||
if not assembly:
|
||||
# check if the selection is a constraint group or a constraint
|
||||
if isTypeOf(sobj,(AsmConstraintGroup,Assembly,AsmConstraint)):
|
||||
assembly = ret[-1].Assembly
|
||||
selSubname = sub[:-len(ret[-1].Subname)]
|
||||
if isTypeOf(sobj,AsmConstraint):
|
||||
cstr = sobj
|
||||
continue
|
||||
assembly = ret[0].Assembly
|
||||
selSubname = sub[:-len(ret[0].Subname)]
|
||||
|
||||
found = None
|
||||
for r in ret:
|
||||
if r.Assembly == assembly:
|
||||
found = r
|
||||
break
|
||||
if not found:
|
||||
raise RuntimeError('Selection {}.{} is not from the target '
|
||||
'assembly {}'.format(sel.Object.Name,sub,objName(assembly)))
|
||||
found = ret[0]
|
||||
else:
|
||||
found = None
|
||||
for r in ret:
|
||||
if r.Assembly == assembly:
|
||||
found = r
|
||||
break
|
||||
if not found:
|
||||
raise RuntimeError('Selection {}.{} is not from the target '
|
||||
'assembly {}'.format(
|
||||
sel.Object.Name,sub,objName(assembly)))
|
||||
|
||||
# because we call Assembly.find() above with relativeToChild=False,
|
||||
# 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)):
|
||||
# Too bad, its a full selection, let's guess the sub element
|
||||
subElement = utils.deduceSelectedElement(found.Object,sub)
|
||||
if not subElement:
|
||||
raise RuntimeError('no sub element (face, edge, vertex) in '
|
||||
'{}.{}'.format(found.Object.Name,sub))
|
||||
sub += subElement
|
||||
|
||||
elements.append((found.Object,sub))
|
||||
|
||||
check = None
|
||||
if cstr and not Constraint.isDisabled(cstr):
|
||||
typeid = Constraint.getTypeID(cstr)
|
||||
info = cstr.Proxy.getInfo()
|
||||
check = [o.getShape() for o in info.Elements] + elements
|
||||
else:
|
||||
check = elements
|
||||
if check:
|
||||
if not Constraint.isDisabled(cstr):
|
||||
if cstr:
|
||||
typeid = Constraint.getTypeID(cstr)
|
||||
check = [o.Proxy.getInfo().Shape for o in cstr.Group] + elements
|
||||
else:
|
||||
check = elements
|
||||
Constraint.check(typeid,check)
|
||||
|
||||
return AsmConstraint.Selection(SelObject=sel.Object,
|
||||
|
@ -780,7 +876,7 @@ class AsmConstraint(AsmGroup):
|
|||
Elements = elements)
|
||||
|
||||
@staticmethod
|
||||
def make(typeid, sel=None, name='Constraint', undo=True):
|
||||
def make(typeid,sel=None,name='Constraint',undo=True):
|
||||
if not sel:
|
||||
sel = AsmConstraint.getSelection(typeid)
|
||||
if sel.Constraint:
|
||||
|
@ -795,7 +891,10 @@ class AsmConstraint(AsmGroup):
|
|||
doc.openTransaction('Assembly make constraint')
|
||||
cstr = constraints.Document.addObject("App::FeaturePython",
|
||||
name,AsmConstraint(constraints),None,True)
|
||||
ViewProviderAsmConstraint(cstr.ViewObject)
|
||||
proxy = ViewProviderAsmConstraint(cstr.ViewObject)
|
||||
logger.debug('cstr viewobject {},{},{},{}'.format(
|
||||
id(proxy),id(cstr.ViewObject.Proxy),
|
||||
id(proxy.ViewObject),id(cstr.ViewObject)))
|
||||
constraints.setLink({-1:cstr})
|
||||
Constraint.setTypeID(cstr,typeid)
|
||||
|
||||
|
@ -809,13 +908,15 @@ class AsmConstraint(AsmGroup):
|
|||
if undo:
|
||||
doc.commitTransaction()
|
||||
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
subname = sel.SelSubname
|
||||
if subname:
|
||||
subname += '.'
|
||||
subname += sel.Assembly.Proxy.getConstraintGroup().Name + '.' + \
|
||||
cstr.Name + '.'
|
||||
FreeCADGui.Selection.addSelection(sel.SelObject,subname)
|
||||
if sel.SelObject:
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
subname = sel.SelSubname
|
||||
if subname:
|
||||
subname += '.'
|
||||
subname += sel.Assembly.Proxy.getConstraintGroup().Name + \
|
||||
'.' + cstr.Name + '.'
|
||||
FreeCADGui.Selection.addSelection(sel.SelObject,subname)
|
||||
FreeCADGui.runCommand('Std_TreeSelection')
|
||||
return cstr
|
||||
|
||||
except Exception:
|
||||
|
@ -837,6 +938,44 @@ class ViewProviderAsmConstraint(ViewProviderAsmGroup):
|
|||
def getIcon(self):
|
||||
return Constraint.getIcon(self.ViewObject.Object)
|
||||
|
||||
def _getSelection(self,owner,subname):
|
||||
if not owner:
|
||||
raise RuntimeError('no owner')
|
||||
parent = getattr(owner.Proxy,'parent',None)
|
||||
if isinstance(parent,AsmConstraintGroup):
|
||||
# This can happen when we are dropping another element link from the
|
||||
# same constraint group, in which case, 'owner' here will be the
|
||||
# parent constraint of the dropping element link
|
||||
subname = owner.Name + '.' + subname
|
||||
owner = parent.Object
|
||||
parent = parent.parent # ascend to the parent assembly
|
||||
if not isinstance(parent,Assembly):
|
||||
raise RuntimeError('not from the same assembly')
|
||||
subname = owner.Name + '.' + subname
|
||||
obj = self.ViewObject.Object
|
||||
mysub = parent.getConstraintGroup().Name + '.' + obj.Name + '.'
|
||||
sel = [Selection(Object=parent.Object,SubElementNames=[subname,mysub])]
|
||||
typeid = Constraint.getTypeID(obj)
|
||||
return AsmConstraint.getSelection(typeid,sel)
|
||||
|
||||
def canDropObjectEx(self,_obj,owner,subname):
|
||||
cstr = self.ViewObject.Object
|
||||
if logger.catchTrace('Cannot drop to AsmConstraint {}'.format(cstr),
|
||||
self._getSelection,owner,subname):
|
||||
return True
|
||||
return False
|
||||
|
||||
def dropObjectEx(self,_vobj,_obj,owner,subname):
|
||||
sel = self._getSelection(owner,subname)
|
||||
cstr = self.ViewObject.Object
|
||||
typeid = Constraint.getTypeID(cstr)
|
||||
sel = AsmConstraint.Selection(SelObject=None,
|
||||
SelSubname=None,
|
||||
Assembly=sel.Assembly,
|
||||
Constraint=cstr,
|
||||
Elements=sel.Elements)
|
||||
AsmConstraint.make(typeid,sel,undo=False)
|
||||
|
||||
|
||||
class AsmConstraintGroup(AsmGroup):
|
||||
def __init__(self,parent):
|
||||
|
@ -864,6 +1003,9 @@ class AsmConstraintGroup(AsmGroup):
|
|||
class ViewProviderAsmConstraintGroup(ViewProviderAsmBase):
|
||||
_iconName = 'Assembly_Assembly_Constraints_Tree.svg'
|
||||
|
||||
def canDropObjects(self):
|
||||
return False
|
||||
|
||||
|
||||
class AsmElementGroup(AsmGroup):
|
||||
def __init__(self,parent):
|
||||
|
@ -876,6 +1018,9 @@ class AsmElementGroup(AsmGroup):
|
|||
for o in obj.Group:
|
||||
getProxy(o,AsmElement).parent = self
|
||||
|
||||
def getAssembly(self):
|
||||
return self.parent
|
||||
|
||||
@staticmethod
|
||||
def make(parent,name='Elements'):
|
||||
obj = parent.Document.addObject("App::FeaturePython",name,
|
||||
|
@ -891,24 +1036,17 @@ class ViewProviderAsmElementGroup(ViewProviderAsmBase):
|
|||
def onDelete(self,_obj,_subs):
|
||||
return False
|
||||
|
||||
def canDragObject(self,_obj):
|
||||
return False
|
||||
|
||||
def canDragObjects(self):
|
||||
return False
|
||||
|
||||
def canDragAndDropObject(self,_obj):
|
||||
return False
|
||||
|
||||
def canDropObjectEx(self,_obj,owner,subname):
|
||||
# check if is dropping a sub-element
|
||||
if subname.rfind('.')+1 == len(subname):
|
||||
if not subname or subname[-1]=='.':
|
||||
return False
|
||||
return self.ViewObject.Object.Proxy.parent.getPartGroup()==owner
|
||||
proxy = self.ViewObject.Object.Proxy
|
||||
return proxy.getAssembly().getPartGroup()==owner
|
||||
|
||||
def dropObjectEx(self,vobj,_obj,_owner,subname):
|
||||
AsmElement.make(AsmElement.Selection(
|
||||
vobj.Object.Proxy.parent.Object,None,subname))
|
||||
Assembly=vobj.Object.Proxy.getAssembly().Object,
|
||||
Element=None, Subname=subname))
|
||||
|
||||
|
||||
BuildShapeNone = 'None'
|
||||
|
@ -1341,6 +1479,9 @@ def getMovingPartInfo():
|
|||
if not sels:
|
||||
raise RuntimeError('no selection')
|
||||
|
||||
if not sels[0].SubElementNames:
|
||||
raise RuntimeError('no sub object in selection')
|
||||
|
||||
if len(sels)>1 or len(sels[0].SubElementNames)>2:
|
||||
raise RuntimeError('too many selection')
|
||||
|
||||
|
@ -1401,24 +1542,29 @@ class ViewProviderAssembly(ViewProviderAsmGroup):
|
|||
self._movingPart = None
|
||||
super(ViewProviderAssembly,self).__init__(vobj)
|
||||
|
||||
def canDragObject(self,_child):
|
||||
return False
|
||||
def _convertSubname(self,owner,subname):
|
||||
sub = subname.split('.')
|
||||
if not sub:
|
||||
return
|
||||
me = self.ViewObject.Object
|
||||
partGroup = me.Proxy.getPartGroup().ViewObject
|
||||
if sub == me.Name:
|
||||
return partGroup,partGroup,subname[len[sub]+1:]
|
||||
return partGroup,owner,subname
|
||||
|
||||
def canDragObjects(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def PartGroup(self):
|
||||
return self.ViewObject.Object.Proxy.getPartGroup()
|
||||
|
||||
def canDropObject(self,obj):
|
||||
self.PartGroup.ViewObject.canDropObject(obj)
|
||||
|
||||
def canDropObjects(self):
|
||||
return True
|
||||
def canDropObjectEx(self,obj,owner,subname):
|
||||
info = self._convertSubname(owner,subname)
|
||||
if not info:
|
||||
return False
|
||||
partGroup,owner,subname = info
|
||||
return partGroup.canDropObject(obj,owner,subname)
|
||||
|
||||
def dropObjectEx(self,_vobj,obj,owner,subname):
|
||||
self.PartGroup.ViewObject.dropObject(obj,owner,subname)
|
||||
info = self._convertSubname(owner,subname)
|
||||
if not info:
|
||||
return False
|
||||
partGroup,owner,subname = info
|
||||
partGroup.dropObject(obj,owner,subname)
|
||||
|
||||
def getIcon(self):
|
||||
return System.getIcon(self.ViewObject.Object)
|
||||
|
|
|
@ -218,8 +218,8 @@ class Constraint(ProxyType):
|
|||
return getattr(obj,mcs._disabled,False)
|
||||
|
||||
@classmethod
|
||||
def check(mcs,tp,group):
|
||||
mcs.getType(tp).check(group)
|
||||
def check(mcs,tp,group,checkCount=False):
|
||||
mcs.getType(tp).check(group,checkCount)
|
||||
|
||||
@classmethod
|
||||
def prepare(mcs,obj,solver):
|
||||
|
@ -260,9 +260,10 @@ class Constraint(ProxyType):
|
|||
ret = {}
|
||||
for obj in cstrs:
|
||||
cstr = mcs.getProxy(obj)
|
||||
for info in cstr.getFixedTransform(obj):
|
||||
found = True
|
||||
ret[info.Part] = info
|
||||
if cstr.hasFixedPart(obj):
|
||||
for info in cstr.getFixedTransform(obj):
|
||||
found = True
|
||||
ret[info.Part] = info
|
||||
|
||||
if not found and not firstPart:
|
||||
elements = obj.Proxy.getElements()
|
||||
|
@ -331,32 +332,33 @@ class Base(with_metaclass(Constraint,object)):
|
|||
@classmethod
|
||||
def getEntityDef(cls,group,checkCount,obj=None):
|
||||
entities = cls._entityDef
|
||||
if len(group) != len(entities):
|
||||
if not checkCount and len(group)<len(entities):
|
||||
return entities[:len(group)]
|
||||
if cls._workplane and len(group)==len(entities)+1:
|
||||
entities = list(entities)
|
||||
entities.append(_w)
|
||||
else:
|
||||
if not obj:
|
||||
name = cls.getName()
|
||||
else:
|
||||
name += cstrName(obj)
|
||||
raise RuntimeError('Constraint {} has wrong number of '
|
||||
'elements {}, expecting {}'.format(
|
||||
name,len(group),len(entities)))
|
||||
return entities
|
||||
if len(group) == len(entities):
|
||||
return entities
|
||||
if cls._workplane and len(group)==len(entities)+1:
|
||||
return list(entities) + [_w]
|
||||
if not checkCount and len(group)<len(entities):
|
||||
return entities[:len(group)]
|
||||
if not obj:
|
||||
name = cls.getName()
|
||||
else:
|
||||
name += cstrName(obj)
|
||||
if len(group)<len(entities):
|
||||
msg = entities[len(group)](None,None,None,None)
|
||||
raise RuntimeError('Constraint {} expects a {} element of '
|
||||
'{}'.format(name,_ordinal[len(group)],msg))
|
||||
raise RuntimeError('Constraint {} has too many elements, expecting '
|
||||
'only {}'.format(name,len(entities)))
|
||||
|
||||
@classmethod
|
||||
def check(cls,group):
|
||||
entities = cls.getEntityDef(group,False)
|
||||
def check(cls,group,checkCount=False):
|
||||
entities = cls.getEntityDef(group,checkCount)
|
||||
for i,e in enumerate(entities):
|
||||
o = group[i]
|
||||
msg = e(None,None,None,o)
|
||||
if not msg:
|
||||
continue
|
||||
if i == len(cls._entityDef):
|
||||
raise RuntimeError('Constraint "{}" requires the optional {} '
|
||||
raise RuntimeError('Constraint "{}" requires an optional {} '
|
||||
'element to be a planar face for defining a '
|
||||
'workplane'.format(cls.getName(), _ordinal[i], msg))
|
||||
raise RuntimeError('Constraint "{}" requires the {} element to be'
|
||||
|
@ -475,7 +477,7 @@ class Locked(Base):
|
|||
return ret
|
||||
|
||||
@classmethod
|
||||
def check(cls,group):
|
||||
def check(cls,group,_checkCount=False):
|
||||
if not all([utils.isElement(o) for o in group]):
|
||||
raise RuntimeError('Constraint "{}" requires all children to be '
|
||||
'of element (Vertex, Edge or Face)'.format(cls.getName()))
|
||||
|
@ -486,7 +488,7 @@ class BaseMulti(Base):
|
|||
_entityDef = (_wa,)
|
||||
|
||||
@classmethod
|
||||
def check(cls,group):
|
||||
def check(cls,group,_checkCount=False):
|
||||
if len(group)<2:
|
||||
raise RuntimeError('Constraint "{}" requires at least two '
|
||||
'elements'.format(cls.getName()))
|
||||
|
|
16
utils.py
16
utils.py
|
@ -61,6 +61,22 @@ def isLine(param):
|
|||
else:
|
||||
return isinstance(param,Part.Line)
|
||||
|
||||
def deduceSelectedElement(obj,subname):
|
||||
shape = obj.getSubObject(subname)
|
||||
if not shape:
|
||||
return
|
||||
count = len(shape.Faces)
|
||||
if count==1:
|
||||
return 'Face1'
|
||||
elif not count:
|
||||
count = len(shape.Edges)
|
||||
if count==1:
|
||||
return 'Edge1'
|
||||
elif not count:
|
||||
count = len(shape.Vertexes)
|
||||
if count==1:
|
||||
return 'Vertex1'
|
||||
|
||||
def getElement(obj,tp):
|
||||
if isinstance(obj,tuple):
|
||||
obj = obj[0].getSubObject(obj[1])
|
||||
|
|
Loading…
Reference in New Issue
Block a user