From dd7b65a585fe0fe2a8ceb37be55e1f721de24190 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 25 Feb 2017 20:34:43 -0300 Subject: [PATCH] Draft: Added utilities -> create Working Plane Proxy command --- src/Mod/Arch/InitGui.py | 2 +- src/Mod/Draft/Draft.py | 180 ++++++++++++++++++++++++++++++++++ src/Mod/Draft/DraftGui.py | 10 -- src/Mod/Draft/DraftTools.py | 30 +++++- src/Mod/Draft/InitGui.py | 2 +- src/Mod/Draft/WorkingPlane.py | 6 +- 6 files changed, 215 insertions(+), 15 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 7e4937d2b..aabbf6862 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -63,7 +63,7 @@ class ArchWorkbench(Workbench): "Draft_FinishLine","Draft_CloseLine"] self.draftutils = ["Draft_VisGroup","Draft_Heal","Draft_FlipDimension", "Draft_ToggleConstructionMode","Draft_ToggleContinueMode","Draft_Edit", - "Draft_Slope"] + "Draft_Slope","Draft_SetWorkingPlaneProxy"] 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', diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 536d2ca33..b9d3a0471 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -3561,6 +3561,16 @@ def downgrade(objects,delete=False,force=None): return [addList,deleteList] +def makeWorkingPlaneProxy(placement): + "creates a Working Plane proxy object in the current document" + if FreeCAD.ActiveDocument: + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","WPProxy") + WorkingPlaneProxy(obj) + if FreeCAD.GuiUp: + ViewProviderWorkingPlaneProxy(obj.ViewObject) + obj.Placement = placement + + #--------------------------------------------------------------------------- # Python Features definitions #--------------------------------------------------------------------------- @@ -6047,4 +6057,174 @@ class _ViewProviderVisGroup: if vobj.Object.InList[0].isDerivedFrom("Drawing::FeaturePage"): vobj.Object.InList[0].touch() + +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")) + obj.addProperty("Part::PropertyPartShape","Shape","Base","") + self.Type = "WorkingPlaneProxy" + + def execute(self,obj): + import Part + l = 1 + if obj.ViewObject: + if hasattr(obj.ViewObject,"DisplaySize"): + l = obj.ViewObject.DisplaySize.Value + p = Part.makePlane(l,l,Vector(l/2,-l/2,0),Vector(0,0,-1)) + # make sure the normal direction is pointing outwards, you never know what OCC will decide... + if p.normalAt(0,0).getAngle(obj.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))) > 1: + p.reverse() + p.Placement = obj.Placement + obj.Shape = p + + def onChanged(self,obj,prop): + pass + + def getNormal(self,obj): + return obj.Shape.Faces[0].normalAt(0,0) + + def __getstate__(self): + return self.Type + + def __setstate__(self,state): + if state: + self.Type = state + + +class ViewProviderWorkingPlaneProxy: + + "A View Provider for working plane proxies" + + def __init__(self,vobj): + vobj.addProperty("App::PropertyLength","DisplaySize","Arch",QT_TRANSLATE_NOOP("App::Property","The display length of this section plane")) + vobj.addProperty("App::PropertyLength","ArrowSize","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the arrows of this section plane")) + vobj.addProperty("App::PropertyPercent","Transparency","Base","") + vobj.addProperty("App::PropertyFloat","LineWidth","Base","") + vobj.addProperty("App::PropertyColor","LineColor","Base","") + vobj.DisplaySize = 100 + vobj.ArrowSize = 5 + vobj.Transparency = 70 + vobj.LineWidth = 1 + vobj.LineColor = (0.0,0.25,0.25,1.0) + vobj.Proxy = self + self.Object = vobj.Object + + def getIcon(self): + import Draft_rc + return ":/icons/Draft_SelectPlane.svg" + + def claimChildren(self): + return [] + + def attach(self,vobj): + from pivy import coin + self.clip = None + self.mat1 = coin.SoMaterial() + self.mat2 = coin.SoMaterial() + self.fcoords = coin.SoCoordinate3() + fs = coin.SoIndexedFaceSet() + fs.coordIndex.setValues(0,7,[0,1,2,-1,0,2,3]) + self.drawstyle = coin.SoDrawStyle() + self.drawstyle.style = coin.SoDrawStyle.LINES + self.lcoords = coin.SoCoordinate3() + ls = coin.SoType.fromName("SoBrepEdgeSet").createInstance() + ls.coordIndex.setValues(0,28,[0,1,-1,2,3,4,5,-1,6,7,-1,8,9,10,11,-1,12,13,-1,14,15,16,17,-1,18,19,20,21]) + sep = coin.SoSeparator() + psep = coin.SoSeparator() + fsep = coin.SoSeparator() + fsep.addChild(self.mat2) + fsep.addChild(self.fcoords) + fsep.addChild(fs) + psep.addChild(self.mat1) + psep.addChild(self.drawstyle) + psep.addChild(self.lcoords) + psep.addChild(ls) + sep.addChild(fsep) + sep.addChild(psep) + vobj.addDisplayMode(sep,"Default") + self.onChanged(vobj,"DisplaySize") + self.onChanged(vobj,"LineColor") + self.onChanged(vobj,"Transparency") + + def getDisplayModes(self,vobj): + return ["Default"] + + def getDefaultDisplayMode(self): + return "Default" + + def setDisplayMode(self,mode): + return mode + + def updateData(self,obj,prop): + if prop in ["Placement"]: + self.onChanged(obj.ViewObject,"DisplaySize") + return + + def onChanged(self,vobj,prop): + if prop == "LineColor": + l = vobj.LineColor + self.mat1.diffuseColor.setValue([l[0],l[1],l[2]]) + self.mat2.diffuseColor.setValue([l[0],l[1],l[2]]) + elif prop == "Transparency": + if hasattr(vobj,"Transparency"): + self.mat2.transparency.setValue(vobj.Transparency/100.0) + elif prop in ["DisplaySize","ArrowSize"]: + if hasattr(vobj,"DisplaySize"): + l = vobj.DisplaySize.Value/2 + else: + l = 1 + verts = [] + fverts = [] + l1 = 0.1 + if hasattr(vobj,"ArrowSize"): + l1 = vobj.ArrowSize.Value if vobj.ArrowSize.Value > 0 else 0.1 + l2 = l1/3 + pl = FreeCAD.Placement(vobj.Object.Placement) + fverts.append(pl.multVec(Vector(-l,-l,0))) + fverts.append(pl.multVec(Vector(l,-l,0))) + fverts.append(pl.multVec(Vector(l,l,0))) + fverts.append(pl.multVec(Vector(-l,l,0))) + + verts.append(pl.multVec(Vector(0,0,0))) + verts.append(pl.multVec(Vector(l-l1,0,0))) + verts.append(pl.multVec(Vector(l-l1,l2,0))) + verts.append(pl.multVec(Vector(l,0,0))) + verts.append(pl.multVec(Vector(l-l1,-l2,0))) + verts.append(pl.multVec(Vector(l-l1,l2,0))) + + verts.append(pl.multVec(Vector(0,0,0))) + verts.append(pl.multVec(Vector(0,l-l1,0))) + verts.append(pl.multVec(Vector(-l2,l-l1,0))) + verts.append(pl.multVec(Vector(0,l,0))) + verts.append(pl.multVec(Vector(l2,l-l1,0))) + verts.append(pl.multVec(Vector(-l2,l-l1,0))) + + verts.append(pl.multVec(Vector(0,0,0))) + verts.append(pl.multVec(Vector(0,0,l-l1))) + verts.append(pl.multVec(Vector(-l2,0,l-l1))) + verts.append(pl.multVec(Vector(0,0,l))) + verts.append(pl.multVec(Vector(l2,0,l-l1))) + verts.append(pl.multVec(Vector(-l2,0,l-l1))) + verts.append(pl.multVec(Vector(0,-l2,l-l1))) + verts.append(pl.multVec(Vector(0,0,l))) + verts.append(pl.multVec(Vector(0,l2,l-l1))) + verts.append(pl.multVec(Vector(0,-l2,l-l1))) + + self.lcoords.point.setValues(verts) + self.fcoords.point.setValues(fverts) + elif prop == "LineWidth": + self.drawstyle.lineWidth = vobj.LineWidth + return + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + # @} diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 92a37bd12..fa2ecec94 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -733,16 +733,6 @@ class DraftToolBar: maxwidth = maxwidth + 16 +10 # add icon width and a margin for i in pb: i.setMaximumWidth(maxwidth) - - if (not self.taskmode) or self.tray: - self.wplabel.setToolTip(translate("draft", "Set/unset a working plane")) - self.colorButton.setToolTip(translate("draft", "Line Color")) - self.facecolorButton.setToolTip(translate("draft", "Face Color")) - self.widthButton.setToolTip(translate("draft", "Line Width")) - self.fontsizeButton.setToolTip(translate("draft", "Font Size")) - self.applyButton.setToolTip(translate("draft", "Apply to selected objects")) - self.constrButton.setToolTip(translate("draft", "Toggles Construction Mode")) - self.autoGroupButton.setToolTip(translate("draft", "Sets/unsets auto-grouping")) #--------------------------------------------------------------------------- # Interface modes diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 62d1f9f52..8b84dfd99 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -344,6 +344,11 @@ class SelectPlane(DraftTool): self.display(plane.axis) self.finish() return + elif Draft.getType(sel.Object) == "WorkingPlaneProxy": + plane.setFromPlacement(sel.Object.Placement,rebase=True) + self.display(plane.axis) + self.finish() + return elif sel.HasSubObjects: if len(sel.SubElementNames) == 1: if "Face" in sel.SubElementNames[0]: @@ -432,10 +437,10 @@ class SelectPlane(DraftTool): else: suffix = '' if type(arg).__name__ == 'str': self.ui.wplabel.setText(arg+suffix) - self.ui.wplabel.setToolTip(translate("draft", "Current working plane:")+arg+suffix) elif type(arg).__name__ == 'Vector': plv = 'd('+str(arg.x)+','+str(arg.y)+','+str(arg.z)+')' self.ui.wplabel.setText(plv+suffix) + self.ui.wplabel.setToolTip(translate("draft", "Current working plane:")+self.ui.wplabel.text()) FreeCADGui.doCommandGui("FreeCADGui.Snapper.setGrid()") #--------------------------------------------------------------------------- @@ -5056,6 +5061,28 @@ class SetAutoGroup(): self.ui.setAutoGroup(self.groups[i]) +class SetWorkingPlaneProxy(): + "The SetWorkingPlaneProxy FreeCAD command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_SelectPlane', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy", "Create WP Proxy"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy", "Creates a proxy object from the current working plane")} + + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False + + def Activated(self): + if hasattr(FreeCAD,"DraftWorkingPlane"): + FreeCAD.ActiveDocument.openTransaction("Create WP proxy") + FreeCADGui.addModule("Draft") + FreeCADGui.doCommand("Draft.makeWorkingPlaneProxy(FreeCAD.DraftWorkingPlane.getPlacement())") + FreeCAD.ActiveDocument.recompute() + FreeCAD.ActiveDocument.commitTransaction() + #--------------------------------------------------------------------------- # Snap tools #--------------------------------------------------------------------------- @@ -5298,6 +5325,7 @@ FreeCADGui.addCommand('Draft_ShowSnapBar',ShowSnapBar()) FreeCADGui.addCommand('Draft_ToggleGrid',ToggleGrid()) FreeCADGui.addCommand('Draft_FlipDimension',Draft_FlipDimension()) FreeCADGui.addCommand('Draft_AutoGroup',SetAutoGroup()) +FreeCADGui.addCommand('Draft_SetWorkingPlaneProxy',SetWorkingPlaneProxy()) # snap commands FreeCADGui.addCommand('Draft_Snap_Lock',Draft_Snap_Lock()) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 9052b25a5..9bc6f8163 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -83,7 +83,7 @@ class DraftWorkbench (Workbench): self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] self.utils = ["Draft_VisGroup","Draft_Heal","Draft_FlipDimension", "Draft_ToggleConstructionMode","Draft_ToggleContinueMode","Draft_Edit", - "Draft_Slope"] + "Draft_Slope","Draft_SetWorkingPlaneProxy"] 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', diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 990b582fa..8bf32a5a8 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -311,12 +311,14 @@ class plane: 0.0,0.0,0.0,1.0) return FreeCAD.Placement(m) - def setFromPlacement(self,pl): - "sets the working plane from a placement (rotaton ONLY)" + def setFromPlacement(self,pl,rebase=False): + "sets the working plane from a placement (rotaton ONLY, unless rebaee=True)" rot = FreeCAD.Placement(pl).Rotation self.u = rot.multVec(FreeCAD.Vector(1,0,0)) self.v = rot.multVec(FreeCAD.Vector(0,1,0)) self.axis = rot.multVec(FreeCAD.Vector(0,0,1)) + if rebase: + self.position = pl.Base def inverse(self): "inverts the direction of the working plane"