diff --git a/src/Mod/Arch/ArchCell.py b/src/Mod/Arch/ArchCell.py index 607615055..8783602cc 100644 --- a/src/Mod/Arch/ArchCell.py +++ b/src/Mod/Arch/ArchCell.py @@ -89,30 +89,28 @@ class _Cell(ArchComponent.Component): import Part pl = obj.Placement if obj.Components: + shapes = [] if obj.JoinMode: walls = [] structs = [] - compshapes = [] - for comp in obj.Components: - if Draft.getType(comp) == "Wall": - walls.append(comp.Shape) - elif Draft.getType(comp) == "Structure": - structs.append(comp.Shape) + for c in obj.Components: + if Draft.getType(c) == "Wall": + walls.append(c.Shape) + elif Draft.getType(c) == "Structure": + structs.append(c.Shape) else: - compshapes.append(comp.Shape) - for gr in [walls,structs]: - if gr: - sh = gr.pop(0) - for csh in gr: - sh = sh.oldFuse(csh) - compshapes.append(sh) - baseShape = Part.makeCompound(compshapes) + shapes.append(c.Shape) + for group in [walls,structs]: + if group: + sh = group.pop(0).copy() + for subsh in group: + sh = sh.oldFuse(subsh) + shapes.append(sh) else: - compshapes = [] - for o in obj.Components: - compshapes.append(o.Shape) - baseShape = Part.makeCompound(compshapes) - obj.Shape = baseShape + for c in obj.Components: + shapes.append(c.Shape) + if shapes: + obj.Shape = Part.makeCompound(shapes) obj.Placement = pl class _ViewProviderCell(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 9790fd715..248006f1f 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -59,13 +59,42 @@ class _CommandWall: def Activated(self): sel = FreeCADGui.Selection.getSelection() + done = False if sel: - FreeCAD.ActiveDocument.openTransaction("Wall") - for obj in sel: - makeWall(obj) - FreeCAD.ActiveDocument.commitTransaction() - else: - wall = makeWall() + import Draft + if Draft.getType(sel[0]) != "Wall": + FreeCAD.ActiveDocument.openTransaction("Wall") + for obj in sel: + makeWall(obj) + FreeCAD.ActiveDocument.commitTransaction() + done = True + if not done: + import DraftTrackers + self.points = [] + self.tracker = DraftTrackers.boxTracker() + FreeCADGui.Snapper.getPoint(callback=self.getPoint) + + def getPoint(self,point): + "this function is called by the snapper when it has a 3D point" + if point == None: + self.tracker.finalize() + return + self.points.append(point) + if len(self.points) == 1: + self.tracker.on() + FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update) + elif len(self.points) == 2: + import Draft + l = Draft.makeWire(self.points) + makeWall(l) + self.tracker.finalize() + + def update(self,point): + "this function is called by the Snapper when the mouse is moved" + self.tracker.update([self.points[0],point]) + + + class _Wall(ArchComponent.Component): "The Wall object" diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 83b3814e1..d6e215914 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -154,6 +154,7 @@ class DraftToolBar: def __init__(self): self.tray = None self.sourceCmd = None + self.cancel = None self.taskmode = Draft.getParam("UiMode") self.paramcolor = Draft.getParam("color")>>8 self.color = QtGui.QColor(self.paramcolor) @@ -465,14 +466,14 @@ class DraftToolBar: def taskUi(self,title): if self.taskmode: self.isTaskOn = True - FreeCADGui.Control.closeDialog() + todo.delay(FreeCADGui.Control.closeDialog,None) self.baseWidget = QtGui.QWidget() self.setTitle(title) self.layout = QtGui.QVBoxLayout(self.baseWidget) self.setupToolBar(task=True) self.retranslateUi(self.baseWidget) self.panel = DraftTaskPanel(self.baseWidget) - FreeCADGui.Control.showDialog(self.panel) + todo.delay(FreeCADGui.Control.showDialog,self.panel) else: self.setTitle(title) @@ -509,7 +510,8 @@ class DraftToolBar: self.labelx.setText(translate("draft", "Center X")) self.continueCmd.show() - def pointUi(self,title=translate("draft","Point")): + def pointUi(self,title=translate("draft","Point"),cancel=None): + if cancel: self.cancel = cancel self.taskUi(title) self.xValue.setEnabled(True) self.yValue.setEnabled(True) @@ -832,7 +834,11 @@ class DraftToolBar: def finish(self): "finish button action" - self.sourceCmd.finish(False) + if self.sourceCmd: + self.sourceCmd.finish(False) + if self.cancel: + self.cancel() + self.cancel = None def closeLine(self): "close button action" diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 337c468e4..3469772fd 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -430,13 +430,16 @@ class Snapper: # get the intersection points pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) if pt: - return [pt[0],'ortho',pt[0]] + return [pt[0],'ortho',pt[0]] if eline: - tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() - # get the intersection points - pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) - if pt: + try: + tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() + # get the intersection points + pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) + if pt: return [pt[0],'ortho',pt[0]] + except: + return None return None def snapToElines(self,e1,e2): @@ -613,15 +616,23 @@ class Snapper: if self.constrainLine: self.constrainLine.off() - def getPoint(self,last=None,callback=None): - """getPoint([last],[callback]) : gets a 3D point from the screen. You can provide an existing point, - in that case additional snap options and a tracker are available. You can also passa function as - callback, which will get called with the resulting point as argument, when a point is clicked: + def getPoint(self,last=None,callback=None,movecallback=None): + + """getPoint([last],[callback],[movecallback]) : gets a 3D point from the screen. You + can provide an existing point, in that case additional snap options and a tracker + are available. You can also pass a function as callback, which will get called + with the resulting point as argument, when a point is clicked, and optionally + another callback which gets called when the mouse is moved. + + If the operation gets cancelled (the user pressed Escape), no point is returned. + + Example: def cb(point): - print "got a 3D point: ",point - FreeCADGui.Snapper.getPoint(callback=cb) - """ + if point: + print "got a 3D point: ",point + FreeCADGui.Snapper.getPoint(callback=cb)""" + self.pt = None self.ui = FreeCADGui.draftToolBar self.view = FreeCADGui.ActiveDocument.ActiveView @@ -642,6 +653,8 @@ class Snapper: self.ui.displayPoint(self.pt,last,plane=FreeCAD.DraftWorkingPlane,mask=FreeCADGui.Snapper.affinity) if self.trackLine: self.trackLine.p2(self.pt) + if movecallback: + movecallback(self.pt) def click(event_cb): event = event_cb.getEvent() @@ -656,10 +669,21 @@ class Snapper: callback(self.pt) self.pt = None + def cancel(): + self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick) + self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove) + FreeCADGui.Snapper.off() + self.ui.offUi() + if self.trackLine: + self.trackLine.off() + if callback: + callback(None) + # adding 2 callback functions - self.ui.pointUi() + self.ui.pointUi(cancel=cancel) self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click) self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move) - + + if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index c071f6ef1..0fc5b3986 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -623,3 +623,66 @@ class gridTracker(Tracker): rot = FreeCAD.Rotation() rot.Q = self.trans.rotation.getValue().getValue() return rot.multVec(Vector(pu,pv,0)) + +class boxTracker(Tracker): + "A box tracker, can be based on a line object" + def __init__(self,line=None,width=0.1,height=1): + self.trans = coin.SoTransform() + m = coin.SoMaterial() + m.transparency.setValue(0.8) + m.diffuseColor.setValue([0.4,0.4,0.6]) + self.cube = coin.SoCube() + self.cube.height.setValue(width) + self.cube.depth.setValue(height) + self.baseline = None + if line: + self.baseline = line + self.update() + Tracker.__init__(self,children=[self.trans,m,self.cube]) + + def update(self,line=None,normal=None): + import WorkingPlane + from draftlibs import fcgeo + if not normal: + normal = FreeCAD.DraftWorkingPlane.axis + if line: + if isinstance(line,list): + bp = line[0] + lvec = line[1].sub(line[0]) + else: + lvec = fcgeo.vec(line.Shape.Edges[0]) + bp = line.Shape.Edges[0].Vertexes[0].Point + elif self.baseline: + lvec = fcgeo.vec(self.baseline.Shape.Edges[0]) + bp = self.baseline.Shape.Edges[0].Vertexes[0].Point + else: + return + right = lvec.cross(normal) + self.cube.width.setValue(lvec.Length) + p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)]) + self.trans.rotation.setValue(p.Rotation.Q) + bp = bp.add(fcvec.scale(lvec,0.5)) + bp = bp.add(fcvec.scaleTo(normal,self.cube.depth.getValue()/2)) + self.pos(bp) + + def pos(self,p): + self.trans.translation.setValue(fcvec.tup(p)) + + def width(self,w=None): + if w: + self.cube.height.setValue(w) + else: + return self.cube.height.getValue() + + def length(self,l=None): + if l: + self.cube.width.setValue(l) + else: + return self.cube.width.getValue() + + def heigth(self,h=None): + if h: + self.cube.depth.setValue(h) + self.update() + else: + return self.cube.depth.getValue()