Draft/Arch related changes
* Add Draft_LinkArray and Draft_PathLinkArray that uses link for both data and visualization, which supports linking external objects * Add link group support for draft snap * Fix ArchWindows expression ambiguity
This commit is contained in:
@@ -358,7 +358,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
|
||||
s.renameConstraint(58,'Frame8')
|
||||
s.renameConstraint(59,'Frame9')
|
||||
s.renameConstraint(60,'F10')
|
||||
s.setExpression('Constraints.F10','-Constraints.Frame5')
|
||||
s.setExpression('.Constraints.F10','-.Constraints.Frame5')
|
||||
fw = str(w2)
|
||||
if w2 == w1:
|
||||
fw = "0.00+V"
|
||||
|
||||
@@ -547,7 +547,10 @@ def formatObject(target,origin=None):
|
||||
val = getattr(matchrep,p).Value
|
||||
else:
|
||||
val = getattr(matchrep,p)
|
||||
setattr(obrep,p,val)
|
||||
try:
|
||||
setattr(obrep,p,val)
|
||||
except Exception:
|
||||
pass
|
||||
if matchrep.DisplayMode in obrep.listDisplayModes():
|
||||
obrep.DisplayMode = matchrep.DisplayMode
|
||||
if hasattr(matchrep,"DiffuseColor") and hasattr(obrep,"DiffuseColor"):
|
||||
@@ -1237,7 +1240,7 @@ def makeBlock(objectslist):
|
||||
select(obj)
|
||||
return obj
|
||||
|
||||
def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Array"):
|
||||
def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Array",useLink=False):
|
||||
"""makeArray(object,xvector,yvector,xnum,ynum,[name]) for rectangular array, or
|
||||
makeArray(object,xvector,yvector,zvector,xnum,ynum,znum,[name]) for rectangular array, or
|
||||
makeArray(object,center,totalangle,totalnum,[name]) for polar array: Creates an array
|
||||
@@ -1247,11 +1250,15 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
|
||||
same for z direction with zvector and znum. In case of polar array, center is a vector,
|
||||
totalangle is the angle to cover (in degrees) and totalnum is the number of objects,
|
||||
including the original. The result is a parametric Draft Array."""
|
||||
|
||||
if not FreeCAD.ActiveDocument:
|
||||
FreeCAD.Console.PrintError("No active document. Aborting\n")
|
||||
return
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
|
||||
_Array(obj)
|
||||
if useLink:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name,_Array(None),None,True)
|
||||
else:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
|
||||
_Array(obj)
|
||||
obj.Base = baseobject
|
||||
if arg6:
|
||||
obj.ArrayType = "ortho"
|
||||
@@ -1273,7 +1280,13 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
|
||||
obj.Angle = arg2
|
||||
obj.NumberPolar = arg3
|
||||
if gui:
|
||||
_ViewProviderDraftArray(obj.ViewObject)
|
||||
if useLink:
|
||||
_ViewProviderDraftLink(obj.ViewObject)
|
||||
else:
|
||||
_ViewProviderDraftArray(obj.ViewObject)
|
||||
formatObject(obj,obj.Base)
|
||||
if len(obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
obj.ViewObject.Proxy.resetColors(obj.ViewObject)
|
||||
baseobject.ViewObject.hide()
|
||||
formatObject(obj,obj.Base)
|
||||
if len(obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
@@ -1281,8 +1294,8 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
|
||||
select(obj)
|
||||
return obj
|
||||
|
||||
def makePathArray(baseobject,pathobject,count,xlate=None,align=False,pathobjsubs=[]):
|
||||
"""makePathArray(docobj,path,count,xlate,align,pathobjsubs): distribute
|
||||
def makePathArray(baseobject,pathobject,count,xlate=None,align=False,pathobjsubs=[],useLink=False):
|
||||
"""makePathArray(docobj,path,count,xlate,align,pathobjsubs,useLink): distribute
|
||||
count copies of a document baseobject along a pathobject or subobjects of a
|
||||
pathobject. Optionally translates each copy by FreeCAD.Vector xlate direction
|
||||
and distance to adjust for difference in shape centre vs shape reference point.
|
||||
@@ -1290,8 +1303,11 @@ def makePathArray(baseobject,pathobject,count,xlate=None,align=False,pathobjsubs
|
||||
if not FreeCAD.ActiveDocument:
|
||||
FreeCAD.Console.PrintError("No active document. Aborting\n")
|
||||
return
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","PathArray")
|
||||
_PathArray(obj)
|
||||
if useLink:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","PathArray",_PathArray(None),None,True)
|
||||
else:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","PathArray")
|
||||
_PathArray(obj)
|
||||
obj.Base = baseobject
|
||||
obj.PathObj = pathobject
|
||||
if pathobjsubs:
|
||||
@@ -1305,7 +1321,13 @@ def makePathArray(baseobject,pathobject,count,xlate=None,align=False,pathobjsubs
|
||||
obj.Xlate = xlate
|
||||
obj.Align = align
|
||||
if gui:
|
||||
_ViewProviderDraftArray(obj.ViewObject)
|
||||
if useLink:
|
||||
_ViewProviderDraftLink(obj.ViewObject)
|
||||
else:
|
||||
_ViewProviderDraftArray(obj.ViewObject)
|
||||
formatObject(obj,obj.Base)
|
||||
if len(obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
obj.ViewObject.Proxy.resetColors(obj.ViewObject)
|
||||
baseobject.ViewObject.hide()
|
||||
formatObject(obj,obj.Base)
|
||||
if len(obj.Base.ViewObject.DiffuseColor) > 1:
|
||||
@@ -3643,7 +3665,8 @@ def calculatePlacementsOnPath(shapeRotation, pathwire, count, xlate, align):
|
||||
class _DraftObject:
|
||||
"""The base class for Draft objects"""
|
||||
def __init__(self,obj,tp="Unknown"):
|
||||
obj.Proxy = self
|
||||
if obj:
|
||||
obj.Proxy = self
|
||||
self.Type = tp
|
||||
|
||||
def __getstate__(self):
|
||||
@@ -3804,6 +3827,39 @@ class _ViewProviderDraftPart(_ViewProviderDraftAlt):
|
||||
def getIcon(self):
|
||||
return ":/icons/Tree_Part.svg"
|
||||
|
||||
class _ViewProviderDraftLink:
|
||||
"a view provider for link type object"
|
||||
|
||||
def __init__(self,vobj):
|
||||
self.Object = vobj.Object
|
||||
vobj.Proxy = self
|
||||
|
||||
def attach(self,vobj):
|
||||
self.Object = vobj.Object
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
def getIcon(self):
|
||||
tp = self.Object.Proxy.Type
|
||||
if tp == 'Array':
|
||||
return ":/icons/Draft_LinkArray.svg"
|
||||
elif tp == 'PathArray':
|
||||
return ":/icons/Draft_PathLinkArray.svg"
|
||||
|
||||
def claimChildren(self):
|
||||
obj = self.Object
|
||||
if hasattr(obj,'ExpandArray'):
|
||||
expand = obj.ExpandArray
|
||||
else:
|
||||
expand = obj.ShowElement
|
||||
if not expand:
|
||||
return [obj.Base]
|
||||
else:
|
||||
return obj.ElementList
|
||||
|
||||
class _Dimension(_DraftObject):
|
||||
"""The Draft Dimension object"""
|
||||
@@ -5632,11 +5688,117 @@ class _Shape2DView(_DraftObject):
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
|
||||
class _Array(_DraftObject):
|
||||
"""The Draft Array object"""
|
||||
class _DraftLink(_DraftObject):
|
||||
|
||||
def __init__(self,obj,tp):
|
||||
self.useLink = False if obj else True
|
||||
_DraftObject.__init__(self,obj,tp)
|
||||
if obj:
|
||||
self.attach(obj)
|
||||
|
||||
def __getstate__(self):
|
||||
return self.__dict__
|
||||
|
||||
def __setstate__(self,state):
|
||||
if isinstance(state,dict):
|
||||
self.__dict__ = state
|
||||
else:
|
||||
self.useLink = False
|
||||
_DraftObject.__setstate__(self,state)
|
||||
|
||||
def attach(self,obj):
|
||||
if self.useLink:
|
||||
obj.addExtension('App::LinkExtensionPython', None)
|
||||
self.linkSetup(obj)
|
||||
|
||||
def linkSetup(self,obj):
|
||||
obj.configLinkProperty('Placement',LinkedObject='Base')
|
||||
if hasattr(obj,'ShowElement'):
|
||||
# rename 'ShowElement' property to 'ExpandArray' to avoid conflict
|
||||
# with native App::Link
|
||||
obj.configLinkProperty('ShowElement')
|
||||
showElement = obj.ShowElement
|
||||
obj.addProperty("App::PropertyBool","ExpandArray","Draft",
|
||||
QT_TRANSLATE_NOOP("App::Property","Show array element as children object"))
|
||||
obj.ExpandArray = showElement
|
||||
obj.configLinkProperty(ShowElement='ExpandArray')
|
||||
obj.removeProperty('ShowElement')
|
||||
else:
|
||||
obj.configLinkProperty(ShowElement='ExpandArray')
|
||||
if getattr(obj,'ExpandArray',False):
|
||||
obj.setPropertyStatus('PlacementList','Immutable')
|
||||
else:
|
||||
obj.setPropertyStatus('PlacementList','-Immutable')
|
||||
|
||||
def getViewProviderName(self,_obj):
|
||||
if self.useLink:
|
||||
return 'Gui::ViewProviderLinkPython'
|
||||
return ''
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
if self.useLink:
|
||||
self.linkSetup(obj)
|
||||
if obj.Shape.isNull():
|
||||
self.buildShape(obj,obj.Placement,obj.PlacementList)
|
||||
|
||||
def buildShape(self,obj,pl,pls):
|
||||
import Part
|
||||
import DraftGeomUtils
|
||||
|
||||
if self.useLink:
|
||||
if not getattr(obj,'ExpandArray',True) or obj.Count != len(pls):
|
||||
obj.setPropertyStatus('PlacementList','-Immutable')
|
||||
obj.PlacementList = pls
|
||||
obj.setPropertyStatus('PlacementList','Immutable')
|
||||
obj.Count = len(pls)
|
||||
|
||||
if obj.Base:
|
||||
shape = Part.getShape(obj.Base)
|
||||
if shape.isNull():
|
||||
raise RuntimeError("'{}' cannot build shape of '{}'\n".format(
|
||||
obj.Name,obj.Base.Name))
|
||||
else:
|
||||
shape = shape.copy()
|
||||
shape.Placement = FreeCAD.Placement()
|
||||
base = []
|
||||
for i,pla in enumerate(pls):
|
||||
vis = getattr(obj,'VisibilityList',[])
|
||||
if len(vis)>i and not vis[i]:
|
||||
continue;
|
||||
# 'I' is a prefix for disambiguation when mapping element names
|
||||
base.append(shape.transformed(pla.toMatrix(),op='I{}'.format(i)))
|
||||
if getattr(obj,'Fuse',False) and len(base) > 1:
|
||||
obj.Shape = base[0].multiFuse(base[1:]).removeSplitter()
|
||||
else:
|
||||
obj.Shape = Part.makeCompound(base)
|
||||
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
|
||||
if self.useLink:
|
||||
return False # return False to call LinkExtension::execute()
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if getattr(obj,'useLink',False):
|
||||
return
|
||||
elif prop == 'Fuse':
|
||||
if obj.Fuse:
|
||||
obj.setPropertyStatus('Shape','-Transient')
|
||||
else:
|
||||
obj.setPropertyStatus('Shape','Transient')
|
||||
elif prop == 'ExpandArray':
|
||||
if hasattr(obj,'PlacementList'):
|
||||
obj.setPropertyStatus('PlacementList',
|
||||
'-Immutable' if obj.ExpandArray else 'Immutable')
|
||||
|
||||
|
||||
class _Array(_DraftLink):
|
||||
"The Draft Array object"
|
||||
|
||||
def __init__(self,obj):
|
||||
_DraftObject.__init__(self,obj,"Array")
|
||||
_DraftLink.__init__(self,obj,"Array")
|
||||
|
||||
def attach(self, obj):
|
||||
obj.addProperty("App::PropertyLink","Base","Draft",QT_TRANSLATE_NOOP("App::Property","The base object that must be duplicated"))
|
||||
obj.addProperty("App::PropertyEnumeration","ArrayType","Draft",QT_TRANSLATE_NOOP("App::Property","The type of array to create"))
|
||||
obj.addProperty("App::PropertyVector","Axis","Draft",QT_TRANSLATE_NOOP("App::Property","The axis direction"))
|
||||
@@ -5651,6 +5813,13 @@ class _Array(_DraftObject):
|
||||
obj.addProperty("App::PropertyVectorDistance","Center","Draft",QT_TRANSLATE_NOOP("App::Property","Center point"))
|
||||
obj.addProperty("App::PropertyAngle","Angle","Draft",QT_TRANSLATE_NOOP("App::Property","Angle to cover with copies"))
|
||||
obj.addProperty("App::PropertyBool","Fuse","Draft",QT_TRANSLATE_NOOP("App::Property","Specifies if copies must be fused (slower)"))
|
||||
obj.Fuse = False
|
||||
if self.useLink:
|
||||
obj.addProperty("App::PropertyInteger","Count","Draft",'')
|
||||
obj.addProperty("App::PropertyBool","ExpandArray","Draft",
|
||||
QT_TRANSLATE_NOOP("App::Property","Show array element as children object"))
|
||||
obj.ExpandArray = False
|
||||
|
||||
obj.ArrayType = ['ortho','polar']
|
||||
obj.NumberX = 1
|
||||
obj.NumberY = 1
|
||||
@@ -5661,83 +5830,78 @@ class _Array(_DraftObject):
|
||||
obj.IntervalZ = Vector(0,0,1)
|
||||
obj.Angle = 360
|
||||
obj.Axis = Vector(0,0,1)
|
||||
obj.Fuse = False
|
||||
|
||||
_DraftLink.attach(self,obj)
|
||||
|
||||
def linkSetup(self,obj):
|
||||
_DraftLink.linkSetup(self,obj)
|
||||
obj.configLinkProperty(ElementCount='Count')
|
||||
obj.setPropertyStatus('Count','Hidden')
|
||||
|
||||
def execute(self,obj):
|
||||
import DraftGeomUtils
|
||||
if hasattr(obj,"Fuse"):
|
||||
fuse = obj.Fuse
|
||||
else:
|
||||
fuse = False
|
||||
if obj.Base:
|
||||
pl = obj.Placement
|
||||
if obj.ArrayType == "ortho":
|
||||
sh = self.rectArray(obj.Base.Shape,obj.IntervalX,obj.IntervalY,
|
||||
obj.IntervalZ,obj.NumberX,obj.NumberY,obj.NumberZ,fuse)
|
||||
pls = self.rectArray(obj.Base.Placement,obj.IntervalX,obj.IntervalY,
|
||||
obj.IntervalZ,obj.NumberX,obj.NumberY,obj.NumberZ)
|
||||
else:
|
||||
av = obj.IntervalAxis if hasattr(obj,"IntervalAxis") else None
|
||||
sh = self.polarArray(obj.Base.Shape,obj.Center,obj.Angle.Value,obj.NumberPolar,obj.Axis,av,fuse)
|
||||
obj.Shape = sh
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
pls = self.polarArray(obj.Base.Placement,obj.Center,obj.Angle.Value,obj.NumberPolar,obj.Axis,av)
|
||||
|
||||
def rectArray(self,shape,xvector,yvector,zvector,xnum,ynum,znum,fuse=False):
|
||||
return _DraftLink.buildShape(self,obj,pl,pls)
|
||||
|
||||
def rectArray(self,pl,xvector,yvector,zvector,xnum,ynum,znum):
|
||||
import Part
|
||||
base = [shape.copy()]
|
||||
base = [pl.copy()]
|
||||
for xcount in range(xnum):
|
||||
currentxvector=Vector(xvector).multiply(xcount)
|
||||
if not xcount==0:
|
||||
nshape = shape.copy()
|
||||
nshape.translate(currentxvector)
|
||||
base.append(nshape)
|
||||
npl = pl.copy()
|
||||
npl.translate(currentxvector)
|
||||
base.append(npl)
|
||||
for ycount in range(ynum):
|
||||
currentyvector=FreeCAD.Vector(currentxvector)
|
||||
currentyvector=currentyvector.add(Vector(yvector).multiply(ycount))
|
||||
if not ycount==0:
|
||||
nshape = shape.copy()
|
||||
nshape.translate(currentyvector)
|
||||
base.append(nshape)
|
||||
npl = pl.copy()
|
||||
npl.translate(currentyvector)
|
||||
base.append(npl)
|
||||
for zcount in range(znum):
|
||||
currentzvector=FreeCAD.Vector(currentyvector)
|
||||
currentzvector=currentzvector.add(Vector(zvector).multiply(zcount))
|
||||
if not zcount==0:
|
||||
nshape = shape.copy()
|
||||
nshape.translate(currentzvector)
|
||||
base.append(nshape)
|
||||
if fuse and len(base) > 1:
|
||||
return base[0].multiFuse(base[1:]).removeSplitter()
|
||||
else:
|
||||
return Part.makeCompound(base)
|
||||
npl = pl.copy()
|
||||
npl.translate(currentzvector)
|
||||
base.append(npl)
|
||||
return base
|
||||
|
||||
def polarArray(self,shape,center,angle,num,axis,axisvector,fuse=False):
|
||||
def polarArray(self,pl,center,angle,num,axis,axisvector):
|
||||
#print("angle ",angle," num ",num)
|
||||
import Part
|
||||
base = [pl.copy()]
|
||||
if angle == 360:
|
||||
fraction = float(angle)/num
|
||||
else:
|
||||
if num == 0:
|
||||
return shape
|
||||
return base
|
||||
fraction = float(angle)/(num-1)
|
||||
base = [shape.copy()]
|
||||
for i in range(num-1):
|
||||
currangle = fraction + (i*fraction)
|
||||
nshape = shape.copy()
|
||||
nshape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), currangle)
|
||||
npl = pl.copy()
|
||||
npl.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), currangle)
|
||||
if axisvector:
|
||||
if not DraftVecUtils.isNull(axisvector):
|
||||
nshape.translate(FreeCAD.Vector(axisvector).multiply(i+1))
|
||||
base.append(nshape)
|
||||
if fuse and len(base) > 1:
|
||||
return base[0].multiFuse(base[1:]).removeSplitter()
|
||||
else:
|
||||
return Part.makeCompound(base)
|
||||
npl.translate(FreeCAD.Vector(axisvector).multiply(i+1))
|
||||
base.append(npl)
|
||||
return base
|
||||
|
||||
|
||||
class _PathArray(_DraftObject):
|
||||
class _PathArray(_DraftLink):
|
||||
"""The Draft Path Array object"""
|
||||
|
||||
def __init__(self,obj):
|
||||
_DraftObject.__init__(self,obj,"PathArray")
|
||||
_DraftLink.__init__(self,obj,"PathArray")
|
||||
|
||||
def attach(self,obj):
|
||||
obj.addProperty("App::PropertyLinkGlobal","Base","Draft",QT_TRANSLATE_NOOP("App::Property","The base object that must be duplicated"))
|
||||
obj.addProperty("App::PropertyLinkGlobal","PathObj","Draft",QT_TRANSLATE_NOOP("App::Property","The path object along which to distribute objects"))
|
||||
obj.addProperty("App::PropertyLinkSubListGlobal","PathSubs",QT_TRANSLATE_NOOP("App::Property","Selected subobjects (edges) of PathObj"))
|
||||
@@ -5749,6 +5913,17 @@ class _PathArray(_DraftObject):
|
||||
obj.Xlate = FreeCAD.Vector(0,0,0)
|
||||
obj.Align = False
|
||||
|
||||
if self.useLink:
|
||||
obj.addProperty("App::PropertyBool","ExpandArray","Draft",
|
||||
QT_TRANSLATE_NOOP("App::Property","Show array element as children object"))
|
||||
obj.ExpandArray = False
|
||||
|
||||
_DraftLink.attach(self,obj)
|
||||
|
||||
def linkSetup(self,obj):
|
||||
_DraftLink.linkSetup(self,obj)
|
||||
obj.configLinkProperty(ElementCount='Count')
|
||||
|
||||
def execute(self,obj):
|
||||
import FreeCAD
|
||||
import Part
|
||||
@@ -5764,9 +5939,8 @@ class _PathArray(_DraftObject):
|
||||
else:
|
||||
FreeCAD.Console.PrintLog ("_PathArray.createGeometry: path " + obj.PathObj.Name + " has no edges\n")
|
||||
return
|
||||
obj.Shape = self.pathArray(obj.Base.Shape,w,obj.Count,obj.Xlate,obj.Align)
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
base = self.pathArray(obj.Base.Placement,w,obj.Count,obj.Xlate,obj.Align)
|
||||
return _DraftLink.buildShape(self,obj,pl,base)
|
||||
|
||||
def getWireFromSubs(self,obj):
|
||||
'''Make a wire from PathObj subelements'''
|
||||
@@ -5895,18 +6069,29 @@ class _Clone(_DraftObject):
|
||||
obj.Scale = Vector(1,1,1)
|
||||
|
||||
def join(self,obj,shapes):
|
||||
if len(shapes) < 2:
|
||||
fuse = getattr(obj,'Fuse',False)
|
||||
if fuse:
|
||||
tmps = []
|
||||
for s in shapes:
|
||||
tmps += s.Solids
|
||||
if not tmps:
|
||||
for s in shapes:
|
||||
tmps += s.Faces
|
||||
if not tmps:
|
||||
for s in shapes:
|
||||
tmps += s.Edges
|
||||
shapes = tmps
|
||||
if len(shapes) == 1:
|
||||
return shapes[0]
|
||||
import Part
|
||||
if hasattr(obj,"Fuse"):
|
||||
if obj.Fuse:
|
||||
try:
|
||||
sh = shapes[0].multiFuse(shapes[1:])
|
||||
sh = sh.removeSplitter()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
return sh
|
||||
if fuse:
|
||||
try:
|
||||
sh = shapes[0].multiFuse(shapes[1:])
|
||||
sh = sh.removeSplitter()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
return sh
|
||||
return Part.makeCompound(shapes)
|
||||
|
||||
def execute(self,obj):
|
||||
@@ -5916,44 +6101,29 @@ class _Clone(_DraftObject):
|
||||
if obj.isDerivedFrom("Part::Part2DObject"):
|
||||
# if our clone is 2D, make sure all its linked geometry is 2D too
|
||||
for o in obj.Objects:
|
||||
if not o.isDerivedFrom("Part::Part2DObject"):
|
||||
if not o.getLinkedObject(True).isDerivedFrom("Part::Part2DObject"):
|
||||
FreeCAD.Console.PrintWarning("Warning 2D Clone "+obj.Name+" contains 3D geometry")
|
||||
return
|
||||
objs = getGroupContents(obj.Objects)
|
||||
for o in objs:
|
||||
sh = None
|
||||
if o.isDerivedFrom("Part::Feature"):
|
||||
if not o.Shape.isNull():
|
||||
sh = o.Shape.copy()
|
||||
elif o.hasExtension("App::GeoFeatureGroupExtension"):
|
||||
shps = []
|
||||
for so in o.Group:
|
||||
if so.isDerivedFrom("Part::Feature"):
|
||||
if not so.Shape.isNull():
|
||||
shps.append(so.Shape)
|
||||
if shps:
|
||||
sh = self.join(obj,shps)
|
||||
if sh:
|
||||
m = FreeCAD.Matrix()
|
||||
if hasattr(obj,"Scale") and not sh.isNull():
|
||||
sx,sy,sz = obj.Scale
|
||||
if not DraftVecUtils.equals(obj.Scale,Vector(1,1,1)):
|
||||
op = sh.Placement
|
||||
sh.Placement = FreeCAD.Placement()
|
||||
m.scale(obj.Scale)
|
||||
if sx == sy == sz:
|
||||
sh.transformShape(m)
|
||||
else:
|
||||
sh = sh.transformGeometry(m)
|
||||
sh.Placement = op
|
||||
if not sh.isNull():
|
||||
shapes.append(sh)
|
||||
for o in obj.Objects:
|
||||
sh = Part.getShape(o)
|
||||
if not sh.isNull():
|
||||
shapes.append(sh)
|
||||
if shapes:
|
||||
if len(shapes) == 1:
|
||||
obj.Shape = shapes[0]
|
||||
obj.Placement = shapes[0].Placement
|
||||
else:
|
||||
obj.Shape = self.join(obj,shapes)
|
||||
sh = self.join(obj,shapes)
|
||||
m = FreeCAD.Matrix()
|
||||
if hasattr(obj,"Scale") and not sh.isNull():
|
||||
sx,sy,sz = obj.Scale
|
||||
if not DraftVecUtils.equals(obj.Scale,Vector(1,1,1)):
|
||||
op = sh.Placement
|
||||
sh.Placement = FreeCAD.Placement()
|
||||
m.scale(obj.Scale)
|
||||
if sx == sy == sz:
|
||||
sh.transformShape(m)
|
||||
else:
|
||||
sh = sh.transformGeometry(m)
|
||||
sh.Placement = op
|
||||
obj.Shape = sh
|
||||
|
||||
obj.Placement = pl
|
||||
if hasattr(obj,"positionBySupport"):
|
||||
obj.positionBySupport()
|
||||
|
||||
@@ -234,8 +234,8 @@ class Snapper:
|
||||
self.trackLine.p1(lastpoint)
|
||||
|
||||
# checking if parallel to one of the edges of the last objects or to a polar direction
|
||||
eline = None
|
||||
if active:
|
||||
eline = None
|
||||
point,eline = self.snapToPolar(point,lastpoint)
|
||||
point,eline = self.snapToExtensions(point,lastpoint,constrain,eline)
|
||||
|
||||
@@ -273,14 +273,21 @@ class Snapper:
|
||||
|
||||
def snapToObject(self, lastpoint, active, constrain, eline, point, oldActive):
|
||||
# we have an object to snap to
|
||||
snaps = []
|
||||
|
||||
obj = FreeCAD.ActiveDocument.getObject(self.snapInfo['Object'])
|
||||
parent = self.snapInfo.get('ParentObject',None)
|
||||
if parent:
|
||||
subname = self.snapInfo['SubName']
|
||||
obj = parent.getSubObject(subname,retType=1)
|
||||
else:
|
||||
obj = FreeCAD.ActiveDocument.getObject(self.snapInfo['Object'])
|
||||
parent = obj
|
||||
subname = self.snapInfo['Component']
|
||||
if not obj:
|
||||
self.spoint = self.cstr(lastpoint, constrain, point)
|
||||
self.spoint = cstr(point)
|
||||
self.running = False
|
||||
return self.spoint
|
||||
|
||||
snaps = []
|
||||
self.lastSnappedObject = obj
|
||||
|
||||
if hasattr(obj.ViewObject,"Selectable"):
|
||||
@@ -303,11 +310,10 @@ class Snapper:
|
||||
# active snapping
|
||||
comp = self.snapInfo['Component']
|
||||
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
shape = Part.getShape(parent,subname,
|
||||
needSubElement=True,noElementMap=True)
|
||||
|
||||
# applying global placements
|
||||
shape = obj.Shape.copy()
|
||||
shape.Placement = obj.getGlobalPlacement()
|
||||
if not shape.isNull():
|
||||
|
||||
snaps.extend(self.snapToSpecials(obj,lastpoint,eline))
|
||||
|
||||
|
||||
@@ -4805,6 +4805,10 @@ class Draft2Sketch(Modifier):
|
||||
class Array(Modifier):
|
||||
"""The Shape2DView FreeCAD command definition"""
|
||||
|
||||
def __init__(self,useLink=False):
|
||||
Modifier.__init__(self)
|
||||
self.useLink = useLink
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_Array',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Array", "Array"),
|
||||
@@ -4827,14 +4831,29 @@ class Array(Modifier):
|
||||
obj = FreeCADGui.Selection.getSelection()[0]
|
||||
FreeCADGui.addModule("Draft")
|
||||
self.commit(translate("draft","Array"),
|
||||
['obj = Draft.makeArray(FreeCAD.ActiveDocument.'+obj.Name+',FreeCAD.Vector(1,0,0),FreeCAD.Vector(0,1,0),2,2)',
|
||||
['obj = Draft.makeArray(FreeCAD.ActiveDocument.{},FreeCAD.Vector(1,0,0),FreeCAD.Vector(0,1,0),2,2,useLink={})'.format(obj.Name,self.useLink),
|
||||
'Draft.autogroup(obj)',
|
||||
'FreeCAD.ActiveDocument.recompute()'])
|
||||
self.finish()
|
||||
|
||||
class LinkArray(Array):
|
||||
"The Shape2DView FreeCAD command definition"
|
||||
|
||||
def __init__(self):
|
||||
Array.__init__(self,True)
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_LinkArray',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_LinkArray", "LinkArray"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_LinkArray", "Creates a polar or rectangular link array from a selected object")}
|
||||
|
||||
class PathArray(Modifier):
|
||||
"""The PathArray FreeCAD command definition"""
|
||||
|
||||
def __init__(self,useLink=False):
|
||||
Modifier.__init__(self)
|
||||
self.useLink = useLink
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_PathArray',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_PathArray", "PathArray"),
|
||||
@@ -4863,11 +4882,22 @@ class PathArray(Modifier):
|
||||
defCount = 4
|
||||
defAlign = False
|
||||
FreeCAD.ActiveDocument.openTransaction("PathArray")
|
||||
Draft.makePathArray(base,path,defCount,defXlate,defAlign,pathsubs)
|
||||
Draft.makePathArray(base,path,defCount,defXlate,defAlign,pathsubs,useLink=self.useLink)
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute() # feature won't appear until recompute.
|
||||
self.finish()
|
||||
|
||||
class PathLinkArray(PathArray):
|
||||
"The PathLinkArray FreeCAD command definition"
|
||||
|
||||
def __init__(self):
|
||||
PathArray.__init__(self,True)
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_PathLinkArray',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_PathLinkArray", "PathLinkArray"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_PathLinkArray", "Creates links of a selected object along a selected path.")}
|
||||
|
||||
class PointArray(Modifier):
|
||||
"""The PointArray FreeCAD command definition"""
|
||||
|
||||
@@ -5851,8 +5881,10 @@ FreeCADGui.addCommand('Draft_DelPoint',DelPoint())
|
||||
FreeCADGui.addCommand('Draft_WireToBSpline',WireToBSpline())
|
||||
FreeCADGui.addCommand('Draft_Draft2Sketch',Draft2Sketch())
|
||||
FreeCADGui.addCommand('Draft_Array',Array())
|
||||
FreeCADGui.addCommand('Draft_LinkArray',LinkArray())
|
||||
FreeCADGui.addCommand('Draft_Clone',Draft_Clone())
|
||||
FreeCADGui.addCommand('Draft_PathArray',PathArray())
|
||||
FreeCADGui.addCommand('Draft_PathLinkArray',PathLinkArray())
|
||||
FreeCADGui.addCommand('Draft_PointArray',PointArray())
|
||||
FreeCADGui.addCommand('Draft_Heal',Heal())
|
||||
FreeCADGui.addCommand('Draft_Mirror',Mirror())
|
||||
|
||||
@@ -723,6 +723,7 @@ class editTracker(Tracker):
|
||||
else:
|
||||
selnode = coin.SoType.fromName("SoFCSelection").createInstance()
|
||||
if name:
|
||||
selnode.useNewSelection = False
|
||||
selnode.documentName.setValue(FreeCAD.ActiveDocument.Name)
|
||||
selnode.objectName.setValue(name)
|
||||
selnode.subElementName.setValue("EditNode"+str(idx))
|
||||
|
||||
@@ -85,8 +85,8 @@ class DraftWorkbench(Workbench):
|
||||
"Draft_Edit", "Draft_Edit_Improved",
|
||||
"Draft_WireToBSpline", "Draft_AddPoint",
|
||||
"Draft_DelPoint", "Draft_Shape2DView",
|
||||
"Draft_Draft2Sketch", "Draft_Array",
|
||||
"Draft_PathArray", "Draft_PointArray", "Draft_Clone",
|
||||
"Draft_Draft2Sketch", "Draft_Array", "Draft_LinkArray",
|
||||
"Draft_PathArray", "Draft_PathLinkArray", "Draft_PointArray", "Draft_Clone",
|
||||
"Draft_Drawing", "Draft_Mirror", "Draft_Stretch"]
|
||||
self.treecmdList = ["Draft_ApplyStyle", "Draft_ToggleDisplayMode",
|
||||
"Draft_AddToGroup", "Draft_SelectGroup",
|
||||
|
||||
@@ -44,11 +44,13 @@
|
||||
<file>icons/Draft_Wipe.svg</file>
|
||||
<file>icons/Draft_Draft2Sketch.svg</file>
|
||||
<file>icons/Draft_Array.svg</file>
|
||||
<file>icons/Draft_LinkArray.svg</file>
|
||||
<file>icons/Draft_Cursor.svg</file>
|
||||
<file>icons/Draft_Dot.svg</file>
|
||||
<file>icons/Draft_Point.svg</file>
|
||||
<file>icons/Draft_Snap.svg</file>
|
||||
<file>icons/Draft_PathArray.svg</file>
|
||||
<file>icons/Draft_PathLinkArray.svg</file>
|
||||
<file>icons/Draft_PointArray.svg</file>
|
||||
<file>icons/Draft_VisGroup.svg</file>
|
||||
<file>icons/Snap_Lock.svg</file>
|
||||
|
||||
584
src/Mod/Draft/Resources/icons/Draft_LinkArray.svg
Normal file
584
src/Mod/Draft/Resources/icons/Draft_LinkArray.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 22 KiB |
1137
src/Mod/Draft/Resources/icons/Draft_PathLinkArray.svg
Normal file
1137
src/Mod/Draft/Resources/icons/Draft_PathLinkArray.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 37 KiB |
Reference in New Issue
Block a user