diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index f6083bc94..a0c340b79 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -319,17 +319,27 @@ def getCutVolume(cutplane,shapes): import Part if not isinstance(shapes,list): shapes = [shapes] - placement = FreeCAD.Placement(cutplane.Placement) # building boundbox bb = shapes[0].BoundBox for sh in shapes[1:]: bb.add(sh.BoundBox) bb.enlarge(1) + # building cutplane space + placement = None um = vm = wm = 0 - ax = placement.Rotation.multVec(FreeCAD.Vector(0,0,1)) - u = placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) - v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0)) - if not bb.isCutPlane(placement.Base,ax): + try: + if hasattr(cutplane,"Shape"): + p = cutplane.Shape.copy().Faces[0] + else: + p = cutplane.copy().Faces[0] + except: + FreeCAD.Console.PrintMessage(str(translate("Arch","Invalid cutplane"))) + return None,None,None + ce = p.CenterOfMass + ax = p.normalAt(0,0) + u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize() + v = u.cross(ax) + if not bb.isCutPlane(ce,ax): FreeCAD.Console.PrintMessage(str(translate("Arch","No objects are cut by the plane"))) return None,None,None else: @@ -342,20 +352,23 @@ def getCutVolume(cutplane,shapes): FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax), FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)] for c in corners: - dv = c.sub(placement.Base) + dv = c.sub(ce) um1 = DraftVecUtils.project(dv,u).Length um = max(um,um1) vm1 = DraftVecUtils.project(dv,v).Length vm = max(vm,vm1) wm1 = DraftVecUtils.project(dv,ax).Length wm = max(wm,wm1) - p1 = FreeCAD.Vector(-um,vm,0) - p2 = FreeCAD.Vector(um,vm,0) - p3 = FreeCAD.Vector(um,-vm,0) - p4 = FreeCAD.Vector(-um,-vm,0) + vu = DraftVecUtils.scaleTo(u,um) + vui = DraftVecUtils.neg(vu) + vv = DraftVecUtils.scaleTo(v,vm) + vvi = DraftVecUtils.neg(vv) + p1 = ce.add(vu.add(vvi)) + p2 = ce.add(vu.add(vv)) + p3 = ce.add(vui.add(vv)) + p4 = ce.add(vui.add(vvi)) cutface = Part.makePolygon([p1,p2,p3,p4,p1]) cutface = Part.Face(cutface) - cutface.Placement = placement cutnormal = DraftVecUtils.scaleTo(ax,wm) cutvolume = cutface.extrude(cutnormal) cutnormal = DraftVecUtils.neg(cutnormal) @@ -558,17 +571,22 @@ class _CommandAdd: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Grouping"))) - if not mergeCells(sel): - host = sel.pop() - ss = "[" - for o in sel: - if len(ss) > 1: - ss += "," - ss += "FreeCAD.ActiveDocument."+o.Name - ss += "]" + if Draft.getType(sel[-1]) == "Space": + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Add space boundary"))) FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.addComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") + FreeCADGui.doCommand("Arch.addSpaceBoundaries( FreeCAD.ActiveDocument."+sel[-1].Name+", FreeCADGui.Selection.getSelectionEx() )") + else: + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Grouping"))) + if not mergeCells(sel): + host = sel.pop() + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.addComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() @@ -588,20 +606,25 @@ class _CommandRemove: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping"))) - if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1): - host = sel.pop() - ss = "[" - for o in sel: - if len(ss) > 1: - ss += "," - ss += "FreeCAD.ActiveDocument."+o.Name - ss += "]" + if Draft.getType(sel[-1]) == "Space": + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Remove space boundary"))) FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") + FreeCADGui.doCommand("Arch.removeSpaceBoundaries( FreeCAD.ActiveDocument."+sel[-1].Name+", FreeCADGui.Selection.getSelection() )") else: - FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping"))) + if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1): + host = sel.pop() + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") + else: + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 73fc1d574..23dac1ffd 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -409,7 +409,7 @@ class ViewProviderComponent: vobj.Proxy = self self.Object = vobj.Object - def updateData(self,vobj,prop): + def updateData(self,obj,prop): return def onChanged(self,vobj,prop): diff --git a/src/Mod/Arch/ArchSpace.py b/src/Mod/Arch/ArchSpace.py index 9a7669e46..c7468bdeb 100644 --- a/src/Mod/Arch/ArchSpace.py +++ b/src/Mod/Arch/ArchSpace.py @@ -21,12 +21,14 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,ArchCommands,math +import FreeCAD,FreeCADGui,ArchComponent,ArchCommands,math,Draft from DraftTools import translate from PyQt4 import QtCore def makeSpace(objects): - """makeSpace(objects): Creates a space objects from the given boundary objects""" + """makeSpace(objects): Creates a space object from the given objects. Objects can be one + document object, in which case it becomes the base shape of the space object, or a list of + selection objects as got from getSelectionEx(), or a list of tuples (object, subobjectname)""" if not objects: return if not isinstance(objects,list): @@ -38,8 +40,25 @@ def makeSpace(objects): obj.Base = objects[0] objects[0].ViewObject.hide() else: - obj.Objects = objects - + obj.Proxy.addSubobjects(obj,objects) + +def addSpaceBoundaries(space,subobjects): + """addSpaceBoundaries(space,subobjects): adds the given subobjects to the given space""" + import Draft + if Draft.getType(space) == "Space": + space.Proxy.addSubobjects(space,subobjects) + +def removeSpaceBoundaries(space,objects): + """removeSpaceBoundaries(space,objects): removes the given objects from the given spaces boundaries""" + import Draft + if Draft.getType(space) == "Space": + bounds = space.Boundaries + for o in objects: + for b in bounds: + if o.Name == b[0].Name: + bounds.remove(b) + break + space.Boundaries = bounds class _CommandSpace: "the Arch Space command definition" @@ -58,7 +77,10 @@ class _CommandSpace: def Activated(self): FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Space"))) FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.makeSpace(FreeCADGui.Selection.getSelection())") + if len(FreeCADGui.Selection.getSelection()) == 1: + FreeCADGui.doCommand("Arch.makeSpace(FreeCADGui.Selection.getSelection())") + else: + FreeCADGui.doCommand("Arch.makeSpace(FreeCADGui.Selection.getSelectionEx())") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() @@ -69,7 +91,7 @@ class _Space(ArchComponent.Component): obj.Proxy = self obj.addProperty("App::PropertyLink","Base","Base", str(translate("Arch","A base shape defining this space"))) - obj.addProperty("App::PropertyLinkList","Objects","Base", + obj.addProperty("App::PropertyLinkSubList","Boundaries","Base", str(translate("Arch","The objects that make the boundaries of this space object"))) self.Type = "Space" @@ -77,64 +99,103 @@ class _Space(ArchComponent.Component): self.getShape(obj) def onChanged(self,obj,prop): - if prop in ["Objects","Base"]: + if prop in ["Boundaries","Base"]: self.getShape(obj) + + def addSubobjects(self,obj,subobjects): + "adds subobjects to this space" + objs = obj.Boundaries + for o in subobjects: + if isinstance(o,tuple) or isinstance(o,list): + if o[0].Name != obj.Name: + objs.append(tuple(o)) + else: + for el in o.SubElementNames: + if "Face" in el: + if o.Object.Name != obj.Name: + objs.append((o.Object,el)) + obj.Boundaries = objs def getShape(self,obj): - "computes a shape" + "computes a shape from a base shape and/or bounday faces" import Part shape = None faces = [] + #print "starting compute" # 1: if we have a base shape, we use it if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: - shape = obj.Base.Shape.Solids[0] + shape = obj.Base.Shape.Solids[0].copy() # 2: if not, add all bounding boxes of considered objects and build a first shape if shape: + #print "got shape from base object" bb = shape.BoundBox else: bb = None - for obj in obj.Objects: - if obj.isDerivedFrom("Part::Feature"): + for b in obj.Boundaries: + if b[0].isDerivedFrom("Part::Feature"): if not bb: - bb = obj.Shape.BoundBox + bb = b[0].Shape.BoundBox else: - bb.add(obj.Shape.BoundBox) + bb.add(b[0].Shape.BoundBox) if not bb: return shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin)) + #print "created shape from boundbox" - # 3: identify all faces pointing towards the center of our shape + # 3: identifing boundary faces goodfaces = [] - for obj in obj.Objects: - if obj.isDerivedFrom("Part::Feature"): - faces.extend(obj.Shape.Faces) - for face in faces: - pt = face.CenterOfMass - norm = face.normalAt(1,1) #TODO calculate for curved faces - v1 = bb.Center.sub(pt) - if v1.getAngle(norm) < math.pi/2: - goodfaces.append(face) - faces = goodfaces + for b in obj.Boundaries: + if b[0].isDerivedFrom("Part::Feature"): + if "Face" in b[1]: + fn = int(b[1][4:])-1 + faces.append(b[0].Shape.Faces[fn]) + #print "adding face ",fn," of object ",b[0].Name + + #print "total: ", len(faces), " faces" # 4: get cutvolumes from faces cutvolumes = [] for f in faces: + f = f.copy() + f.reverse() cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape) if cutvolume: - cutvolumes.append(cutvolume) + #print "generated 1 cutvolume" + cutvolumes.append(cutvolume.copy()) + #Part.show(cutvolume) for v in cutvolumes: + #print "cutting" shape = shape.cut(v) # 5: get the final shape if shape: if shape.Solids: + #print "setting objects shape" shape = shape.Solids[0] obj.Shape = shape + return + + print "Arch: error computing space boundary" + + def getArea(self,obj): + "returns the horizontal area at the center of the space" + import Part,DraftGeomUtils + try: + pl = Part.makePlane(1,1) + sh = obj.Shape.copy() + cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh) + e = sh.section(cutplane) + e = DraftGeomUtils.sortEdges(e.Edges) + w = Part.Wire(e) + f = Part.Face(w) + return round(f.Area,Draft.getParam("dimPrecision")) + except: + return 0 class _ViewProviderSpace(ArchComponent.ViewProviderComponent): @@ -144,6 +205,12 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent): vobj.LineWidth = 1 vobj.LineColor = (1.0,0.0,0.0,1.0) vobj.DrawStyle = "Dotted" + vobj.addProperty("App::PropertyString","Override","Base", + "Text override. Use $area to insert the area") + vobj.addProperty("App::PropertyColor","TextColor","Base", + "The color of the area text") + vobj.TextColor = (1.0,0.0,0.0,1.0) + vobj.Override = "$area m2" ArchComponent.ViewProviderComponent.__init__(self,vobj) def getIcon(self): @@ -156,5 +223,65 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent): else: return [] + def setDisplayMode(self,mode): + if mode == "Detailed": + self.setAnnotation(True) + return "Flat Lines" + else: + self.setAnnotation(False) + return mode + + def getArea(self,obj): + "returns a formatted area text" + area = str(obj.Proxy.getArea(obj)) + if obj.ViewObject.Override: + text = obj.ViewObject.Override + area = text.replace("$area",str(area)) + return str(area) + + def setAnnotation(self,recreate=True): + if hasattr(self,"Object"): + if hasattr(self,"area"): + if self.area: + self.Object.ViewObject.Annotation.removeChild(self.area) + self.area = None + self.coords = None + self.anno = None + if recreate: + area = self.getArea(self.Object) + if area: + from pivy import coin + import SketcherGui + self.area = coin.SoSeparator() + self.coords = coin.SoTransform() + if self.Object.Shape: + if not self.Object.Shape.isNull(): + c = self.Object.Shape.CenterOfMass + self.coords.translation.setValue([c.x,c.y,c.z]) + self.anno = coin.SoType.fromName("SoDatumLabel").createInstance() + self.anno.string.setValue(area) + self.anno.datumtype.setValue(6) + color = coin.SbVec3f(self.Object.ViewObject.TextColor[:3]) + self.anno.textColor.setValue(color) + self.area.addChild(self.coords) + self.area.addChild(self.anno) + self.Object.ViewObject.Annotation.addChild(self.area) + + def updateData(self,obj,prop): + if prop == "Shape": + if hasattr(self,"area"): + if self.area: + area = self.getArea(obj) + self.anno.string.setValue(area) + if not obj.Shape.isNull(): + c = obj.Shape.CenterOfMass + self.coords.translation.setValue([c.x,c.y,c.z]) + + def onChanged(self,vobj,prop): + if prop in ["Override","TextColor"]: + if vobj.DisplayMode == "Detailed": + self.setAnnotation(True) + return + FreeCADGui.addCommand('Arch_Space',_CommandSpace()) diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 379730903..73b70ef18 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -94,6 +94,8 @@ class _CommandStructure: FreeCAD.ActiveDocument.recompute() else: # interactive mode + if hasattr(FreeCAD,"DraftWorkingPlane"): + FreeCAD.DraftWorkingPlane.setup() import DraftTrackers self.points = [] self.tracker = DraftTrackers.boxTracker() diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 5f0ca5cb0..6b60020bf 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -157,6 +157,8 @@ class _CommandWall: import DraftTrackers self.points = [] self.tracker = DraftTrackers.boxTracker() + if hasattr(FreeCAD,"DraftWorkingPlane"): + FreeCAD.DraftWorkingPlane.setup() FreeCADGui.Snapper.getPoint(callback=self.getPoint,extradlg=self.taskbox()) def getPoint(self,point=None,obj=None): diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 4cf4ece7a..b0b18e9ba 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -87,11 +87,12 @@ class ArchWorkbench(Workbench): "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array", - "Draft_Clone","Draft_Heal"] + "Draft_Clone"] self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", - "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap", + "Draft_SelectGroup","Draft_SelectPlane", "Draft_ShowSnapBar","Draft_ToggleGrid","Draft_UndoLine", "Draft_FinishLine","Draft_CloseLine"] + self.draftutils = ["Draft_Heal"] self.snapList = ['Draft_Snap_Lock','Draft_Snap_Midpoint','Draft_Snap_Perpendicular', 'Draft_Snap_Grid','Draft_Snap_Intersection','Draft_Snap_Parallel', 'Draft_Snap_Endpoint','Draft_Snap_Angle','Draft_Snap_Center', @@ -105,6 +106,7 @@ class ArchWorkbench(Workbench): self.appendMenu(str(translate("arch","&Architecture")),self.archtools) self.appendMenu(str(translate("arch","&Draft")),self.drafttools+self.draftmodtools) self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Context Tools"))],self.draftcontexttools) + self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Utilities"))],self.draftutils) self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Snapping"))],self.snapList) FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index e7db49a3d..0914c7cd1 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -2574,7 +2574,7 @@ class _ViewProviderDimension(_ViewProviderDraft): obj.addProperty("App::PropertyColor","LineColor","Base","Line color") obj.addProperty("App::PropertyLength","ExtLines","Base","Ext lines") obj.addProperty("App::PropertyVector","TextPosition","Base","The position of the text. Leave (0,0,0) for automatic position") - obj.addProperty("App::PropertyString","Override","Base","Text override. Use 'dim' to insert the dimension length") + obj.addProperty("App::PropertyString","Override","Base","Text override. Use $dim to insert the dimension length") obj.FontSize=getParam("textheight") obj.FontName=getParam("textfont") obj.ExtLines=0.3 @@ -2735,7 +2735,7 @@ class _ViewProviderDimension(_ViewProviderDraft): dtext = "%."+str(dtext)+"f" dtext = (dtext % p3.sub(p2).Length) if text: - text = text.replace("dim",dtext) + text = text.replace("$dim",dtext) else: text = dtext if hasattr(self,"text"): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index fe67b50f9..18854b4f0 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -232,12 +232,7 @@ class DraftTool: self.ui.sourceCmd = self self.ui.setTitle(name) self.ui.show() - try: - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - except: - pass + plane.setup() self.node = [] self.pos = [] self.constrain = None @@ -2718,7 +2713,7 @@ class Trimex(Modifier): "trims the actual object" if self.extrudeMode: delta = self.extrude(self.shift,real=True) - print "delta",delta + #print "delta",delta self.doc.openTransaction("Extrude") obj = Draft.extrude(self.obj,delta) self.doc.commitTransaction() @@ -3630,19 +3625,6 @@ class Point: todo.delayCommit(commitlist) FreeCADGui.Snapper.off() -class ToggleSnap(): - "The ToggleSnap FreeCAD command definition" - - def GetResources(self): - return {'Pixmap' : 'Snap_Lock', - 'Accel' : "Shift+S", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggle snap"), - 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggles Draft snap on or off")} - - def Activated(self): - if hasattr(FreeCADGui,"Snapper"): - FreeCADGui.Snapper.toggle() - class ShowSnapBar(): "The ShowSnapBar FreeCAD command definition" @@ -3723,12 +3705,12 @@ class Heal(): class Draft_Snap_Lock(): def GetResources(self): return {'Pixmap' : 'Snap_Lock', + 'Accel' : "Shift+S", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Toggle On/Off"), 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Activates/deactivates all snap tools at once")} def Activated(self): if hasattr(FreeCADGui,"Snapper"): if hasattr(FreeCADGui.Snapper,"masterbutton"): - print FreeCADGui.Snapper.masterbutton FreeCADGui.Snapper.masterbutton.toggle() class Draft_Snap_Midpoint(): @@ -3911,7 +3893,6 @@ FreeCADGui.addCommand('Draft_ToggleDisplayMode',ToggleDisplayMode()) FreeCADGui.addCommand('Draft_AddToGroup',AddToGroup()) FreeCADGui.addCommand('Draft_SelectGroup',SelectGroup()) FreeCADGui.addCommand('Draft_Shape2DView',Shape2DView()) -FreeCADGui.addCommand('Draft_ToggleSnap',ToggleSnap()) FreeCADGui.addCommand('Draft_ShowSnapBar',ShowSnapBar()) FreeCADGui.addCommand('Draft_ToggleGrid',ToggleGrid()) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index a54152db1..544b93f25 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -112,11 +112,12 @@ class DraftWorkbench (Workbench): "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array", - "Draft_Clone","Draft_Heal"] + "Draft_Clone"] self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", - "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap", + "Draft_SelectGroup","Draft_SelectPlane", "Draft_ShowSnapBar","Draft_ToggleGrid"] self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] + self.utils = ["Draft_Heal"] self.snapList = ['Draft_Snap_Lock','Draft_Snap_Midpoint','Draft_Snap_Perpendicular', 'Draft_Snap_Grid','Draft_Snap_Intersection','Draft_Snap_Parallel', 'Draft_Snap_Endpoint','Draft_Snap_Angle','Draft_Snap_Center', @@ -125,6 +126,7 @@ class DraftWorkbench (Workbench): self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Draft modification tools"),self.modList) self.appendMenu(str(translate("draft","&Draft")),self.cmdList+self.modList) self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Context tools"))],self.treecmdList) + self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Utilities"))],self.utils) self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Wire tools"))],self.lineList) self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Snapping"))],self.snapList) if hasattr(FreeCADGui,"draftToolBar"): diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index a0057df5e..8ef841457 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -187,10 +187,20 @@ class plane: # len(sex) > 2, look for point and line, three points, etc. return False - def setup(self, direction, point, upvec=None): + def setup(self, direction=None, point=None, upvec=None): '''If working plane is undefined, define it!''' if self.weak: - self.alignToPointAndAxis(point, direction, 0, upvec) + if direction and point: + self.alignToPointAndAxis(point, direction, 0, upvec) + else: + try: + from pivy import coin + rot = FreeCADGui.ActiveDocument.ActiveView.getCameraNode().getField("orientation").getValue() + upvec = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) + vdir = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + self.alignToPointAndAxis(Vector(0,0,0), DraftVecUtils.neg(vdir), upvec) + except: + print "Draft: Unable to align the working plane to the current view" self.weak = True def reset(self):