Draft: Support new-style Draft texts in TechDraw
This commit is contained in:
@@ -253,7 +253,7 @@ def ungroup(obj):
|
||||
g = grp.Group
|
||||
g.remove(obj)
|
||||
grp.Group = g
|
||||
|
||||
|
||||
def autogroup(obj):
|
||||
"adds a given object to the autogroup, if applicable"
|
||||
if FreeCAD.GuiUp:
|
||||
@@ -357,7 +357,7 @@ def shapify(obj):
|
||||
def getGroupContents(objectslist,walls=False,addgroups=False,spaces=False):
|
||||
'''getGroupContents(objectlist,[walls,addgroups]): if any object of the given list
|
||||
is a group, its content is appened to the list, which is returned. If walls is True,
|
||||
walls and structures are also scanned for included windows or rebars. If addgroups
|
||||
walls and structures are also scanned for included windows or rebars. If addgroups
|
||||
is true, the group itself is also included in the list.'''
|
||||
def getWindows(obj):
|
||||
l = []
|
||||
@@ -1159,9 +1159,9 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
|
||||
makeArray(object,center,totalangle,totalnum,[name]) for polar array: Creates an array
|
||||
of the given object
|
||||
with, in case of rectangular array, xnum of iterations in the x direction
|
||||
at xvector distance between iterations, same for y direction with yvector and ynum,
|
||||
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,
|
||||
at xvector distance between iterations, same for y direction with yvector and ynum,
|
||||
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")
|
||||
@@ -1400,7 +1400,7 @@ def move(objectslist,vector,copy=False):
|
||||
newobj.End = obj.End.add(vector)
|
||||
newobj.Dimline = obj.Dimline.add(vector)
|
||||
else:
|
||||
if copy and obj.isDerivedFrom("Mesh::Feature"):
|
||||
if copy and obj.isDerivedFrom("Mesh::Feature"):
|
||||
print("Mesh copy not supported at the moment") # TODO
|
||||
newobj = obj
|
||||
if "Placement" in obj.PropertiesList:
|
||||
@@ -1416,19 +1416,19 @@ def move(objectslist,vector,copy=False):
|
||||
if copy and getParam("selectBaseObjects",False):
|
||||
select(objectslist)
|
||||
else:
|
||||
select(newobjlist)
|
||||
select(newobjlist)
|
||||
if len(newobjlist) == 1: return newobjlist[0]
|
||||
return newobjlist
|
||||
|
||||
def array(objectslist,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None):
|
||||
'''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array,
|
||||
'''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array,
|
||||
array(objectslist,xvector,yvector,zvector,xnum,ynum,znum) for rectangular array,
|
||||
or array(objectslist,center,totalangle,totalnum) for polar array: Creates an array
|
||||
of the objects contained in list (that can be an object or a list of objects)
|
||||
with, in case of rectangular array, xnum of iterations in the x direction
|
||||
at xvector distance between iterations, and same for y and z directions with yvector
|
||||
and ynum and 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
|
||||
and ynum and 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.
|
||||
|
||||
This function creates an array of independent objects. Use makeArray() to create a
|
||||
@@ -1609,7 +1609,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy
|
||||
newobj.ViewObject.FontSize = factor
|
||||
d = obj.Position.sub(center)
|
||||
newobj.Position = center.add(Vector(d.x*delta.x,d.y*delta.y,d.z*delta.z))
|
||||
if copy:
|
||||
if copy:
|
||||
formatObject(newobj,obj)
|
||||
newobjlist.append(newobj)
|
||||
if copy and getParam("selectBaseObjects",False):
|
||||
@@ -2274,6 +2274,16 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
||||
return svg
|
||||
|
||||
def getText(color,fontsize,fontname,angle,base,text,linespacing=0.5,align="center",flip=True):
|
||||
if isinstance(angle,FreeCAD.Rotation):
|
||||
if not plane:
|
||||
angle = angle.Angle
|
||||
else:
|
||||
if plane.axis.getAngle(angle.Axis) < 0.001:
|
||||
angle = angle.Angle
|
||||
elif abs(plane.axis.getAngle(angle.Axis)-math.pi) < 0.001:
|
||||
return "" # text is perpendicular to view, so it shouldn't appear
|
||||
else:
|
||||
angle = 0 #TODO maybe there is something better to do here?
|
||||
if not isinstance(text,list):
|
||||
text = text.split("\n")
|
||||
if align.lower() == "center":
|
||||
@@ -2487,16 +2497,22 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
||||
tbase = getProj(prx.tbase)
|
||||
svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)
|
||||
|
||||
elif getType(obj) == "Annotation":
|
||||
elif getType(obj) in ["Annotation","DraftText"]:
|
||||
"returns an svg representation of a document annotation"
|
||||
if not obj.ViewObject:
|
||||
print ("export of texts to SVG is only available in GUI mode")
|
||||
else:
|
||||
n = obj.ViewObject.FontName
|
||||
a = obj.ViewObject.Rotation.getValueAs("rad")
|
||||
t = obj.LabelText
|
||||
if getType(obj) == "Annotation":
|
||||
p = getProj(obj.Position)
|
||||
r = obj.ViewObject.Rotation.getValueAs("rad")
|
||||
t = obj.LabelText
|
||||
else: # DraftText
|
||||
p = getProj(obj.Placement.Base)
|
||||
r = obj.Placement.Rotation
|
||||
t = obj.Text
|
||||
j = obj.ViewObject.Justification
|
||||
svg += getText(stroke,fontsize,n,a,getProj(obj.Position),t,linespacing,j)
|
||||
svg += getText(stroke,fontsize,n,r,p,t,linespacing,j)
|
||||
|
||||
elif getType(obj) == "Axis":
|
||||
"returns the SVG representation of an Arch Axis system"
|
||||
@@ -2551,7 +2567,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
||||
if len(f.Edges) == 1:
|
||||
if isinstance(f.Edges[0].Curve,Part.Circle):
|
||||
svg += getCircle(f.Edges[0])
|
||||
|
||||
|
||||
elif getType(obj) == "Rebar":
|
||||
fill = "none"
|
||||
lstyle = getLineStyle()
|
||||
@@ -2645,7 +2661,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
||||
angle = -DraftVecUtils.angle(p2.sub(p1))
|
||||
arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
|
||||
svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)
|
||||
|
||||
|
||||
# techdraw expects bottom-to-top coordinates
|
||||
if techdraw:
|
||||
svg = '<g transform ="scale(1,-1)">'+svg+'</g>'
|
||||
@@ -2744,23 +2760,23 @@ def makeShape2DView(baseobj,projectionVector=None,facenumbers=[]):
|
||||
|
||||
def makeSketch(objectslist,autoconstraints=False,addTo=None,
|
||||
delete=False,name="Sketch",radiusPrecision=-1):
|
||||
'''makeSketch(objectslist,[autoconstraints],[addTo],[delete],[name],[radiusPrecision]):
|
||||
'''makeSketch(objectslist,[autoconstraints],[addTo],[delete],[name],[radiusPrecision]):
|
||||
|
||||
Makes a Sketch objectslist with the given Draft objects.
|
||||
Makes a Sketch objectslist with the given Draft objects.
|
||||
|
||||
* objectlist: can be single or list of objects of Draft type objects,
|
||||
Part::Feature, Part.Shape, or mix of them.
|
||||
|
||||
* autoconstraints(False): if True, constraints will be automatically added to
|
||||
wire nodes, rectangles and circles.
|
||||
|
||||
wire nodes, rectangles and circles.
|
||||
|
||||
* addTo(None) : if set to an existing sketch, geometry will be added to it
|
||||
instead of creating a new one.
|
||||
|
||||
* delete(False): if True, the original object will be deleted.
|
||||
|
||||
* delete(False): if True, the original object will be deleted.
|
||||
If set to a string 'all' the object and all its linked object will be
|
||||
deleted
|
||||
|
||||
|
||||
* name('Sketch'): the name for the new sketch object
|
||||
|
||||
* radiusPrecision(-1): If <0, disable radius constraint. If =0, add indiviaul
|
||||
@@ -6084,7 +6100,7 @@ class _Clone(_DraftObject):
|
||||
obj.addProperty("App::PropertyVector","Scale","Draft",QT_TRANSLATE_NOOP("App::Property","The scale factor of this clone"))
|
||||
obj.addProperty("App::PropertyBool","Fuse","Draft",QT_TRANSLATE_NOOP("App::Property","If this clones several objects, this specifies if the result is a fusion or a compound"))
|
||||
obj.Scale = Vector(1,1,1)
|
||||
|
||||
|
||||
def join(self,obj,shapes):
|
||||
if len(shapes) < 2:
|
||||
return shapes[0]
|
||||
@@ -6214,7 +6230,7 @@ class _ViewProviderDraftArray(_ViewProviderDraft):
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/Draft_Array.svg"
|
||||
|
||||
|
||||
def resetColors(self, vobj):
|
||||
colors = []
|
||||
if vobj.Object.Base:
|
||||
@@ -6550,9 +6566,9 @@ class _ViewProviderVisGroup:
|
||||
|
||||
|
||||
class WorkingPlaneProxy:
|
||||
|
||||
|
||||
"The Draft working plane proxy object"
|
||||
|
||||
|
||||
def __init__(self,obj):
|
||||
obj.Proxy = self
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
|
||||
@@ -6615,11 +6631,11 @@ class ViewProviderWorkingPlaneProxy:
|
||||
|
||||
def claimChildren(self):
|
||||
return []
|
||||
|
||||
|
||||
def doubleClicked(self,vobj):
|
||||
FreeCADGui.runCommand("Draft_SelectPlane")
|
||||
return True
|
||||
|
||||
|
||||
def setupContextMenu(self,vobj,menu):
|
||||
from PySide import QtCore,QtGui
|
||||
action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Write camera position",menu)
|
||||
@@ -6628,7 +6644,7 @@ class ViewProviderWorkingPlaneProxy:
|
||||
action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Write objects state",menu)
|
||||
QtCore.QObject.connect(action2,QtCore.SIGNAL("triggered()"),self.writeState)
|
||||
menu.addAction(action2)
|
||||
|
||||
|
||||
def writeCamera(self):
|
||||
if hasattr(self,"Object"):
|
||||
from pivy import coin
|
||||
@@ -6647,7 +6663,7 @@ class ViewProviderWorkingPlaneProxy:
|
||||
cdata.append(n.heightAngle.getValue())
|
||||
cdata.append(1.0) # perspective camera
|
||||
self.Object.ViewObject.ViewData = cdata
|
||||
|
||||
|
||||
def writeState(self):
|
||||
if hasattr(self,"Object"):
|
||||
FreeCAD.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft","Writing objects shown/hidden state")+"\n")
|
||||
@@ -6787,9 +6803,9 @@ def makeLabel(targetpoint=None,target=None,direction=None,distance=None,labeltyp
|
||||
|
||||
|
||||
class DraftLabel:
|
||||
|
||||
|
||||
"The Draft Label object"
|
||||
|
||||
|
||||
def __init__(self,obj):
|
||||
obj.Proxy = self
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
|
||||
@@ -6988,7 +7004,7 @@ class ViewProviderDraftLabel:
|
||||
self.text2d.string.setValues([l.encode("utf8") for l in obj.Text if l])
|
||||
self.text3d.string.setValues([l.encode("utf8") for l in obj.Text if l])
|
||||
self.onChanged(obj.ViewObject,"TextAlignment")
|
||||
|
||||
|
||||
def getTextSize(self,vobj):
|
||||
from pivy import coin
|
||||
if vobj.DisplayMode == "3D text":
|
||||
@@ -7081,9 +7097,9 @@ class ViewProviderDraftLabel:
|
||||
|
||||
|
||||
class DraftText:
|
||||
|
||||
|
||||
"The Draft Text object"
|
||||
|
||||
|
||||
def __init__(self,obj):
|
||||
obj.Proxy = self
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
|
||||
|
||||
@@ -436,7 +436,7 @@ class SelectPlane(DraftTool):
|
||||
self.finish()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def getCenterPoint(self,x,y,z):
|
||||
if not self.ui.isCenterPlane:
|
||||
return "0,0,0"
|
||||
@@ -503,7 +503,7 @@ class SelectPlane(DraftTool):
|
||||
def redraw3DView():
|
||||
"""redraw3DView(): forces a redraw of 3d view."""
|
||||
try:
|
||||
FreeCADGui.ActiveDocument.ActiveView.redraw()
|
||||
FreeCADGui.ActiveDocument.ActiveView.redraw()
|
||||
except AttributeError as err:
|
||||
pass
|
||||
|
||||
@@ -1811,6 +1811,7 @@ class Text(Creator):
|
||||
self.commit(translate("draft","Create Text"),
|
||||
['text = Draft.makeText('+tx+',point='+DraftVecUtils.toString(self.node[0])+')',
|
||||
'Draft.autogroup(text)'])
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
self.finish(cont=True)
|
||||
|
||||
@@ -1889,7 +1890,7 @@ class Dimension(Creator):
|
||||
self.setFromSelection()
|
||||
msg(translate("draft", "Pick first point:")+"\n")
|
||||
FreeCADGui.draftToolBar.show()
|
||||
|
||||
|
||||
def setFromSelection(self):
|
||||
"If we already have selected geometry, fill the nodes accordingly"
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
@@ -2158,7 +2159,7 @@ class Dimension(Creator):
|
||||
elif (len(self.node) == 2) and self.cont:
|
||||
self.node.append(self.cont)
|
||||
self.createObject()
|
||||
if not self.cont:
|
||||
if not self.cont:
|
||||
self.finish()
|
||||
elif (len(self.node) == 3):
|
||||
# for unlinked arc mode:
|
||||
@@ -2168,7 +2169,7 @@ class Dimension(Creator):
|
||||
# cen = self.node[0].add(v)
|
||||
# self.node = [self.node[0],self.node[1],cen]
|
||||
self.createObject()
|
||||
if not self.cont:
|
||||
if not self.cont:
|
||||
self.finish()
|
||||
elif self.angledata:
|
||||
self.node.append(self.point)
|
||||
@@ -2184,7 +2185,7 @@ class Dimension(Creator):
|
||||
self.dimtrack.on()
|
||||
elif (len(self.node) == 3):
|
||||
self.createObject()
|
||||
if not self.cont:
|
||||
if not self.cont:
|
||||
self.finish()
|
||||
|
||||
class ShapeString(Creator):
|
||||
@@ -2837,7 +2838,7 @@ class Offset(Modifier):
|
||||
d = DraftVecUtils.toString(self.dvec)
|
||||
copymode = False
|
||||
occmode = self.ui.occOffset.isChecked()
|
||||
if self.ui.isCopy.isChecked():
|
||||
if self.ui.isCopy.isChecked():
|
||||
copymode = True
|
||||
FreeCADGui.addModule("Draft")
|
||||
self.commit(translate("draft","Offset"),
|
||||
@@ -2864,9 +2865,9 @@ class Stretch(Modifier):
|
||||
self.call = self.view.addEventCallback("SoEvent",selectObject)
|
||||
else:
|
||||
self.proceed()
|
||||
|
||||
|
||||
def proceed(self):
|
||||
if self.call:
|
||||
if self.call:
|
||||
self.view.removeEventCallback("SoEvent",self.call)
|
||||
self.sel = FreeCADGui.Selection.getSelection()
|
||||
if self.ui and self.sel:
|
||||
@@ -3497,7 +3498,7 @@ class Trimex(Modifier):
|
||||
self.doc.commitTransaction()
|
||||
self.doc.recompute()
|
||||
for g in self.ghost: g.off()
|
||||
|
||||
|
||||
def trimObjects(self,objectslist):
|
||||
"attempts to trim two objects together"
|
||||
import Part
|
||||
@@ -3563,7 +3564,7 @@ class Trimex(Modifier):
|
||||
else:
|
||||
obj.FirstAngle = ang
|
||||
self.doc.recompute()
|
||||
|
||||
|
||||
|
||||
def finish(self,closed=False):
|
||||
Modifier.finish(self)
|
||||
@@ -3984,7 +3985,7 @@ class Edit(Modifier):
|
||||
self.obj.ViewObject.NodeSize = 1
|
||||
self.obj.ViewObject.ShowNodes = True
|
||||
for p in self.obj.Nodes:
|
||||
if self.pl:
|
||||
if self.pl:
|
||||
p = self.pl.multVec(p)
|
||||
self.editpoints.append(p)
|
||||
elif Draft.getType(self.obj) == "PanelCut":
|
||||
@@ -4066,7 +4067,7 @@ class Edit(Modifier):
|
||||
# commented out the following line to disable updating
|
||||
# the object during edit, otherwise it confuses the snapper
|
||||
#self.update(self.trackers[self.editing].get())
|
||||
redraw3DView()
|
||||
redraw3DView()
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
self.ui.redraw()
|
||||
@@ -4237,7 +4238,7 @@ class Edit(Modifier):
|
||||
else:
|
||||
self.obj.Group[self.editing-1].Placement.Base = self.invpl.multVec(v)
|
||||
try:
|
||||
FreeCADGui.ActiveDocument.ActiveView.redraw()
|
||||
FreeCADGui.ActiveDocument.ActiveView.redraw()
|
||||
except AttributeError as err:
|
||||
pass
|
||||
|
||||
@@ -5231,7 +5232,7 @@ class SetAutoGroup():
|
||||
self.labels = ["None"]
|
||||
for g in gn:
|
||||
o = FreeCAD.ActiveDocument.getObject(g)
|
||||
if o:
|
||||
if o:
|
||||
self.labels.append(o.Label)
|
||||
self.ui.sourceCmd = self
|
||||
self.ui.popupMenu(self.labels)
|
||||
@@ -5293,7 +5294,7 @@ class Draft_Label(Creator):
|
||||
self.call = self.view.addEventCallback("SoEvent",self.action)
|
||||
msg(translate("draft", "Pick target point:")+"\n")
|
||||
self.ui.isCopy.hide()
|
||||
|
||||
|
||||
def setmode(self,i):
|
||||
self.labeltype = ["Custom","Name","Label","Position","Length","Area","Volume","Tag","Material"][i]
|
||||
Draft.setParam("labeltype",self.labeltype)
|
||||
@@ -5302,7 +5303,7 @@ class Draft_Label(Creator):
|
||||
if self.ghost:
|
||||
self.ghost.finalize()
|
||||
Creator.finish(self)
|
||||
|
||||
|
||||
def create(self):
|
||||
if len(self.node) == 3:
|
||||
targetpoint = self.node[0]
|
||||
@@ -5350,7 +5351,7 @@ class Draft_Label(Creator):
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event":
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
FreeCADGui.Snapper.affinity = None # don't keep affinity
|
||||
FreeCADGui.Snapper.affinity = None # don't keep affinity
|
||||
if len(self.node) == 2:
|
||||
setMod(arg,MODCONSTRAIN,True)
|
||||
self.point,ctrlPoint,info = getPoint(self,arg)
|
||||
@@ -5422,13 +5423,13 @@ class Draft_AddConstruction():
|
||||
for obj in FreeCADGui.Selection.getSelection():
|
||||
grp.addObject(obj)
|
||||
obrep = obj.ViewObject
|
||||
if "TextColor" in obrep.PropertiesList:
|
||||
if "TextColor" in obrep.PropertiesList:
|
||||
obrep.TextColor = col
|
||||
if "PointColor" in obrep.PropertiesList:
|
||||
if "PointColor" in obrep.PropertiesList:
|
||||
obrep.PointColor = col
|
||||
if "LineColor" in obrep.PropertiesList:
|
||||
if "LineColor" in obrep.PropertiesList:
|
||||
obrep.LineColor = col
|
||||
if "ShapeColor" in obrep.PropertiesList:
|
||||
if "ShapeColor" in obrep.PropertiesList:
|
||||
obrep.ShapeColor = col
|
||||
if hasattr(obrep,"Transparency"):
|
||||
obrep.Transparency = 80
|
||||
|
||||
Reference in New Issue
Block a user