diff --git a/src/Mod/Draft/draftguitools/gui_edit.py b/src/Mod/Draft/draftguitools/gui_edit.py index ab1012f46a..c14be0d679 100644 --- a/src/Mod/Draft/draftguitools/gui_edit.py +++ b/src/Mod/Draft/draftguitools/gui_edit.py @@ -181,10 +181,6 @@ class Edit(gui_base_original.Modifier): the user is editing corresponding node, so next click will be processed as an attempt to end editing operation - editpoints: List [FreeCAD::App.Vector] - List of editpoints collected from the edited object, - on whick editTrackers will be placed. - trackers: Dictionary {object.Name : [editTrackers]} It records the list of DraftTrackers.editTracker. {object.Name as String : [editTrackers for the object]} @@ -233,10 +229,7 @@ class Edit(gui_base_original.Modifier): self._mousePressedCB = None # this are used to edit structure objects, it's a bit buggy i think - self.selectstate = None - self.originalDisplayMode = None - self.originalPoints = None - self.originalNodes = None + self.objs_formats = {} # settings param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") @@ -250,7 +243,7 @@ class Edit(gui_base_original.Modifier): #list of supported Draft and Arch objects self.supportedObjs = ["BezCurve","Wire","BSpline","Circle","Rectangle", - "Polygon","Dimension","LinearDimension","Space", + "Polygon","Ellipse","Dimension","LinearDimension","Space", "Structure","PanelCut","PanelSheet","Wall", "Window"] #list of supported Part objects (they don't have a proxy) @@ -299,17 +292,15 @@ class Edit(gui_base_original.Modifier): + "\n") self.register_selection_callback() + def proceed(self): - """this method defines editpoints and set the editTrackers""" + """this method set the editTrackers""" self.unregister_selection_callback() self.edited_objects = self.getObjsFromSelection() if not self.edited_objects: return self.finish() - # Save selectstate and turn selectable false. - # Object can remain selectable commenting following lines: - # self.saveSelectState(self.obj) - # self.setSelectState(self.obj, False) + self.format_objects_for_editing(self.edited_objects) # start object editing Gui.Selection.clearSelection() @@ -318,7 +309,7 @@ class Edit(gui_base_original.Modifier): self.ui.editUi() for obj in self.edited_objects: - self.setEditPoints(obj) + self.setTrackers(obj, self.getEditPoints(obj)) self.register_editing_callbacks() @@ -327,6 +318,18 @@ class Edit(gui_base_original.Modifier): # self.alignWorkingPlane() + def numericInput(self, v, numy=None, numz=None): + """Execute callback by the toolbar to activate the update function. + + This function gets called by the toolbar + or by the mouse click and activate the update function. + """ + if numy: + v = App.Vector(v, numy, numz) + self.endEditing(self.obj, self.editing, v) + App.ActiveDocument.recompute() + + def finish(self, closed=False): """Terminate Edit Tool.""" self.unregister_selection_callback() @@ -340,18 +343,9 @@ class Edit(gui_base_original.Modifier): self.obj.Closed = True if self.ui: self.removeTrackers() - self.restoreSelectState(self.obj) - if utils.get_type(self.obj) == "Structure": - if self.originalDisplayMode is not None: - self.obj.ViewObject.DisplayMode = self.originalDisplayMode - if self.originalPoints is not None: - self.obj.ViewObject.NodeSize = self.originalPoints - if self.originalNodes is not None: - self.obj.ViewObject.ShowNodes = self.originalNodes - self.selectstate = None - self.originalDisplayMode = None - self.originalPoints = None - self.originalNodes = None + + self.deformat_objects_after_editing(self.edited_objects) + super(Edit, self).finish() App.DraftWorkingPlane.restore() if Gui.Snapper.grid: @@ -361,6 +355,7 @@ class Edit(gui_base_original.Modifier): from PySide import QtCore QtCore.QTimer.singleShot(0, Gui.ActiveDocument.resetEdit) + # ------------------------------------------------------------------------- # SCENE EVENTS CALLBACKS # ------------------------------------------------------------------------- @@ -491,7 +486,6 @@ class Edit(gui_base_original.Modifier): self.obj = doc.getObject(str(node.objectName.getValue())) if self.obj is None: return - self.setPlacement(self.obj) App.Console.PrintMessage(self.obj.Name + ": editing node number " @@ -539,127 +533,6 @@ class Edit(gui_base_original.Modifier): self.showTrackers() gui_tool_utils.redraw_3d_view() - # ------------------------------------------------------------------------- - # UTILS - # ------------------------------------------------------------------------- - - def getObjsFromSelection(self): - """Evaluate selection and return a valid object to edit.""" - selection = Gui.Selection.getSelection() - self.edited_objects = [] - if len(selection) > self.maxObjects: - App.Console.PrintMessage(translate("draft", - "Too many objects selected, max number set to: ") - + str(self.maxObjects) + "\n") - return None - for obj in selection: - if utils.get_type(obj) in self.supportedObjs: - self.edited_objects.append(obj) - continue - elif utils.get_type(obj) in self.supportedPartObjs: - if obj.TypeId in self.supportedPartObjs: - self.edited_objects.append(obj) - continue - App.Console.PrintWarning(obj.Name - + translate("draft", - ": this object is not editable") - + "\n") - return self.edited_objects - - def get_selected_obj_at_position(self, pos): - """Return object at given position. - - If object is one of the edited objects (self.edited_objects). - """ - selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1])) - if not selobjs: - return - for info in selobjs: - if not info: - return - for obj in self.edited_objects: - if obj.Name == info["Object"]: - return obj - - def numericInput(self, v, numy=None, numz=None): - """Execute callback by the toolbar to activate the update function. - - This function gets called by the toolbar - or by the mouse click and activate the update function. - """ - if numy: - v = App.Vector(v, numy, numz) - self.endEditing(self.obj, self.editing, v) - App.ActiveDocument.recompute() - - def setSelectState(self, obj, selState=False): - if hasattr(obj.ViewObject, "Selectable"): - obj.ViewObject.Selectable = selState - - def saveSelectState(self, obj): - if hasattr(obj.ViewObject, "Selectable"): - self.selectstate = obj.ViewObject.Selectable - - def restoreSelectState(self,obj): - if obj: - if hasattr(obj.ViewObject,"Selectable") and (self.selectstate is not None): - obj.ViewObject.Selectable = self.selectstate - - def setPlacement(self, obj): - """Set placement of object. - - Set self.pl and self.invpl to self.obj placement - and inverse placement. - """ - if not obj: - return - if "Placement" in obj.PropertiesList: - self.pl = obj.getGlobalPlacement() - self.invpl = self.pl.inverse() - - def alignWorkingPlane(self): - """Align working plane to self.obj.""" - if "Shape" in self.obj.PropertiesList: - pass - #if DraftTools.plane.weak: TODO Use App.DraftWorkingPlane instead of DraftTools.plane - # DraftTools.plane.alignToFace(self.obj.Shape) - if self.planetrack: - self.planetrack.set(self.editpoints[0]) - - def getEditNode(self, pos): - """Get edit node from given screen position.""" - node = self.sendRay(pos) - return node - - def sendRay(self, mouse_pos): - """Send a ray through the scene and return the nearest entity.""" - ray_pick = coin.SoRayPickAction(self.render_manager.getViewportRegion()) - ray_pick.setPoint(coin.SbVec2s(*mouse_pos)) - ray_pick.setRadius(self.pick_radius) - ray_pick.setPickAll(True) - ray_pick.apply(self.render_manager.getSceneGraph()) - picked_point = ray_pick.getPickedPointList() - return self.searchEditNode(picked_point) - - def searchEditNode(self, picked_point): - """Search edit node inside picked point list and return node number.""" - for point in picked_point: - path = point.getPath() - length = path.getLength() - point = path.getNode(length - 2) - #import DraftTrackers - if hasattr(point,"subElementName") and 'EditNode' in str(point.subElementName.getValue()): - return point - return None - - def getEditNodeIndex(self, point): - """Get edit node index from given screen position.""" - if point: - subElement = str(point.subElementName.getValue()) - ep = int(subElement[8:]) - return ep - else: - return None # ------------------------------------------------------------------------- # EDIT TRACKERS functions @@ -755,21 +628,21 @@ class Edit(gui_base_original.Modifier): def updateGhost(self, obj, idx, pt): if utils.get_type(obj) in ["Wire"]: self.ghost.on() - pointList = self.applyPlacement(obj.Points) + pointList = self.globalize_vectors(obj, obj.Points) pointList[idx] = pt if obj.Closed: pointList.append(pointList[0]) self.ghost.updateFromPointlist(pointList) elif utils.get_type(obj) == "BSpline": self.ghost.on() - pointList = self.applyPlacement(obj.Points) + pointList = self.globalize_vectors(obj, obj.Points) pointList[idx] = pt if obj.Closed: pointList.append(pointList[0]) self.ghost.update(pointList) elif utils.get_type(obj) == "BezCurve": self.ghost.on() - plist = self.applyPlacement(obj.Points) + plist = self.globalize_vectors(obj, obj.Points) pointList = edit_draft.recomputePointsBezier(obj,plist,idx,pt,obj.Degree,moveTrackers=True) self.ghost.update(pointList,obj.Degree) elif utils.get_type(obj) == "Circle": @@ -789,14 +662,15 @@ class Edit(gui_base_original.Modifier): # edit by 3 points if self.editing == 0: # center point - p1 = self.invpl.multVec(self.obj.Shape.Vertexes[0].Point) - p2 = self.invpl.multVec(self.obj.Shape.Vertexes[1].Point) - p0 = DraftVecUtils.project(self.invpl.multVec(pt),self.invpl.multVec(edit_draft.getArcMid(obj, global_placement=True))) + p1 = self.relativize_vector(self.obj, self.obj.Shape.Vertexes[0].Point) + p2 = self.relativize_vector(self.obj, self.obj.Shape.Vertexes[1].Point) + p0 = DraftVecUtils.project(self.relativize_vector(self.obj, pt), + self.relativize_vector(self.obj, (edit_draft.getArcMid(obj, global_placement=True)))) self.ghost.autoinvert=False self.ghost.setRadius(p1.sub(p0).Length) self.ghost.setStartPoint(self.obj.Shape.Vertexes[1].Point) self.ghost.setEndPoint(self.obj.Shape.Vertexes[0].Point) - self.ghost.setCenter(self.pl.multVec(p0)) + self.ghost.setCenter(self.globalize_vector(self.obj, p0)) return else: p1 = edit_draft.getArcStart(obj, global_placement=True) @@ -820,19 +694,9 @@ class Edit(gui_base_original.Modifier): elif self.editing == 2: self.ghost.setEndPoint(pt) elif self.editing == 3: - self.ghost.setRadius(self.invpl.multVec(pt).Length) + self.ghost.setRadius(self.relativize_vector(self.obj, pt).Length) gui_tool_utils.redraw_3d_view() - def applyPlacement(self, pointList): - if self.pl: - plist = [] - for p in pointList: - point = self.pl.multVec(p) - plist.append(point) - return plist - else: - return pointList - def finalizeGhost(self): try: self.ghost.finalize() @@ -860,7 +724,6 @@ class Edit(gui_base_original.Modifier): continue self.obj = o break - self.setPlacement(self.obj) if utils.get_type(self.obj) == "Wire" and 'Edge' in info["Component"]: pt = App.Vector(info["x"], info["y"], info["z"]) self.addPointToWire(self.obj, pt, int(info["Component"][4:])) @@ -872,9 +735,7 @@ class Edit(gui_base_original.Modifier): continue self.addPointToCurve(pt, info) self.obj.recompute() - self.removeTrackers(self.obj) - self.setEditPoints(self.obj) - # self.setSelectState(self.obj, False) + self.resetTrackers(self.obj) return def addPointToWire(self, obj, newPoint, edgeIndex): @@ -887,11 +748,11 @@ class Edit(gui_base_original.Modifier): for index, point in enumerate(self.obj.Points): if index == edgeIndex: - newPoints.append(self.invpl.multVec(newPoint)) + newPoints.append(self.relativize_vector(self.obj, newPoint)) newPoints.append(point) if obj.Closed and edgeIndex == len(obj.Points): # last segment when object is closed - newPoints.append(self.invpl.multVec(newPoint)) + newPoints.append(self.relativize_vector(self.obj, newPoint)) obj.Points = newPoints def addPointToCurve(self, point, info=None): @@ -939,11 +800,11 @@ class Edit(gui_base_original.Modifier): uPoints.append(curve.parameter(p)) for i in range(len(uPoints) - 1): if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ): - pts.insert(i + 1, self.invpl.multVec(point)) + pts.insert(i + 1, self.relativize_vector(self.obj, point)) break # DNC: fix: add points to last segment if curve is closed if self.obj.Closed and (uNewPoint > uPoints[-1]): - pts.append(self.invpl.multVec(point)) + pts.append(self.relativize_vector(self.obj, point)) self.obj.Points = pts def delPoint(self, event): @@ -975,112 +836,11 @@ class Edit(gui_base_original.Modifier): self.obj.recompute() # don't do tan/sym on DWire/BSpline! - self.removeTrackers(self.obj) - self.setEditPoints(self.obj) - - # ------------------------------------------------------------------------- - # EDIT OBJECT TOOLS : GENERAL - # ------------------------------------------------------------------------- - - def setEditPoints(self, obj): - """Append given object's editpoints to self.edipoints and set EditTrackers - """ - self.setPlacement(obj) - self.editpoints = self.getEditPoints(obj) - if self.editpoints: # set trackers and align plane - self.setTrackers(obj, self.editpoints) - self.editpoints = [] - - def getEditPoints(self, obj): - """Return a list of App.Vectors according to the given object edit nodes. - """ - objectType = utils.get_type(obj) - - if objectType in ["Wire", "BSpline"]: - self.ui.editUi("Wire") - return edit_draft.getWirePts(obj) - elif objectType == "BezCurve": - self.ui.editUi("BezCurve") - edit_draft.resetTrackersBezier(obj) - self.editpoints = [] - return - elif objectType == "Circle": - return edit_draft.getCirclePts(obj) - elif objectType == "Rectangle": - return edit_draft.getRectanglePts(obj) - elif objectType == "Polygon": - return edit_draft.getPolygonPts(obj) - elif objectType in ("Dimension","LinearDimension"): - return edit_draft.getDimensionPts(obj) - elif objectType == "Wall": - return edit_arch.getWallPts(obj) - elif objectType == "Window": - return edit_arch.getWindowPts(obj) - elif objectType == "Space": - return edit_arch.getSpacePts(obj) - elif objectType == "Structure": - return edit_arch.getStructurePts(obj) - elif objectType == "PanelCut": - return edit_arch.getPanelCutPts(obj) - elif objectType == "PanelSheet": - return edit_arch.getPanelSheetPts(obj) - elif objectType == "Part" and obj.TypeId == "Part::Box": - return edit_part.getPartBoxPts(obj) - elif objectType == "Part::Line" and obj.TypeId == "Part::Line": - return edit_part.getPartLinePts(obj) - elif objectType == "Sketch": - return edit_arch.getSketchPts(obj) - else: - return None - - def update(self, obj, nodeIndex, v): - """Apply the App.Vector to the modified point and update self.obj.""" - - objectType = utils.get_type(obj) - App.ActiveDocument.openTransaction("Edit") - - if objectType in ["Wire", "BSpline"]: - edit_draft.updateWire(obj, nodeIndex, v) - elif objectType == "BezCurve": - edit_draft.updateWire(obj, nodeIndex, v) - elif objectType == "Circle": - edit_draft.updateCircle(obj, nodeIndex, v, self.alt_edit_mode) - elif objectType == "Rectangle": - edit_draft.updateRectangle(obj, nodeIndex, v) - elif objectType == "Polygon": - edit_draft.updatePolygon(obj, nodeIndex, v) - elif objectType in ("Dimension","LinearDimension"): - edit_draft.updateDimension(obj, nodeIndex, v) - elif objectType == "Sketch": - edit_arch.updateSketch(obj, nodeIndex, v) - elif objectType == "Wall": - edit_arch.updateWall(obj, nodeIndex, v) - elif objectType == "Window": - edit_arch.updateWindow(obj, nodeIndex, v) - elif objectType == "Space": - edit_arch.updateSpace(obj, nodeIndex, v) - elif objectType == "Structure": - edit_arch.updateStructure(obj, nodeIndex, v) - elif objectType == "PanelCut": - edit_arch.updatePanelCut(obj, nodeIndex, v) - elif objectType == "PanelSheet": - edit_arch.updatePanelSheet(obj, nodeIndex, v) - elif objectType == "Part::Line" and self.obj.TypeId == "Part::Line": - edit_arch.updatePartLine(obj, nodeIndex, v) - elif objectType == "Part" and self.obj.TypeId == "Part::Box": - edit_arch.updatePartBox(obj, nodeIndex, v) - obj.recompute() - - App.ActiveDocument.commitTransaction() - - try: - gui_tool_utils.redraw_3d_view() - except AttributeError as err: - pass + self.resetTrackers(self.obj) # ------------------------------------------------------------------------ - # Context menu + # DRAFT EDIT Context menu # ------------------------------------------------------------------------ def display_tracker_menu(self, event): @@ -1124,6 +884,7 @@ class Edit(gui_base_original.Modifier): self.tracker_menu.popup(Gui.getMainWindow().cursor().pos()) QtCore.QObject.connect(self.tracker_menu,QtCore.SIGNAL("triggered(QAction *)"),self.evaluate_menu_action) + def evaluate_menu_action(self, labelname): action_label = str(labelname.text()) # Bezier curve menu @@ -1154,4 +915,293 @@ class Edit(gui_base_original.Modifier): del self.event + # ------------------------------------------------------------------------- + # EDIT OBJECT TOOLS + # + # This section contains the code to retrieve the object points and update them + # + # ------------------------------------------------------------------------- + + def getEditPoints(self, obj): + """Return a list of App.Vectors according to the given object edit nodes. + """ + eps = None + objectType = utils.get_type(obj) + + if objectType in ["Wire", "BSpline"]: + eps = edit_draft.getWirePts(obj) + + elif objectType == "BezCurve": + self.ui.editUi("BezCurve") + edit_draft.resetTrackersBezier(obj) + return + + elif objectType == "Circle": + eps = edit_draft.getCirclePts(obj) + + elif objectType == "Rectangle": + eps = edit_draft.getRectanglePts(obj) + + elif objectType == "Polygon": + eps = edit_draft.getPolygonPts(obj) + + elif objectType == "Ellipse": + eps = edit_draft.getEllipsePts(obj) + + elif objectType in ("Dimension","LinearDimension"): + eps = edit_draft.getDimensionPts(obj) + + elif objectType == "Wall": + eps = self.globalize_vectors(obj, edit_arch.getWallPts(obj)) + if obj.Base and utils.get_type(obj.Base) in ["Wire","Circle", + "Rectangle", "Polygon", "Sketch"]: + basepoints = self.getEditPoints(obj.Base) + for point in basepoints: + eps.append(obj.Placement.multVec(point)) #works ok except if App::Part is rotated... why? + return eps + + elif objectType == "Window": + eps = edit_arch.getWindowPts(obj) + + elif objectType == "Space": + eps = edit_arch.getSpacePts(obj) + + elif objectType == "Structure": + eps = edit_arch.getStructurePts(obj) + + elif objectType == "PanelCut": + eps = edit_arch.getPanelCutPts(obj) + + elif objectType == "PanelSheet": + eps = edit_arch.getPanelSheetPts(obj) + + elif objectType == "Part" and obj.TypeId == "Part::Box": + eps = edit_part.getPartBoxPts(obj) + + elif objectType == "Part::Line" and obj.TypeId == "Part::Line": + eps = edit_part.getPartLinePts(obj) + + elif objectType == "Sketch": + eps = edit_arch.getSketchPts(obj) + + if eps: + return self.globalize_vectors(obj, eps) + else: + return None + + + def update(self, obj, nodeIndex, v): + """Apply the App.Vector to the modified point and update self.obj.""" + + v = self.relativize_vector(obj, v) + + App.ActiveDocument.openTransaction("Edit") + self.update_object(obj, nodeIndex, v) + App.ActiveDocument.commitTransaction() + + if not utils.get_type(obj) in ["Wire", "BSpline"]: + self.resetTrackers(obj) + + try: + gui_tool_utils.redraw_3d_view() + except AttributeError as err: + pass + + + def update_object(self, obj, nodeIndex, v): + objectType = utils.get_type(obj) + if objectType in ["Wire", "BSpline"]: + edit_draft.updateWire(obj, nodeIndex, v) + + elif objectType == "BezCurve": + edit_draft.updateWire(obj, nodeIndex, v) + + elif objectType == "Circle": + edit_draft.updateCircle(obj, nodeIndex, v, self.alt_edit_mode) + + elif objectType == "Rectangle": + edit_draft.updateRectangle(obj, nodeIndex, v) + + elif objectType == "Polygon": + edit_draft.updatePolygon(obj, nodeIndex, v) + + elif objectType == "Ellipse": + edit_draft.updateEllipse(obj, nodeIndex, v) + + elif objectType in ("Dimension","LinearDimension"): + edit_draft.updateDimension(obj, nodeIndex, v) + + elif objectType == "Sketch": + edit_arch.updateSketch(obj, nodeIndex, v) + + elif objectType == "Wall": + if nodeIndex == 0: + edit_arch.updateWall(obj, nodeIndex, v) + elif nodeIndex > 0: + if obj.Base: + if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle", + "Polygon", "Sketch"]: + self.update(obj.Base, nodeIndex - 1, v) + + elif objectType == "Window": + edit_arch.updateWindow(obj, nodeIndex, v) + + elif objectType == "Space": + edit_arch.updateSpace(obj, nodeIndex, v) + + elif objectType == "Structure": + edit_arch.updateStructure(obj, nodeIndex, v) + + elif objectType == "PanelCut": + edit_arch.updatePanelCut(obj, nodeIndex, v) + + elif objectType == "PanelSheet": + edit_arch.updatePanelSheet(obj, nodeIndex, v) + + elif objectType == "Part::Line" and self.obj.TypeId == "Part::Line": + edit_part.updatePartLine(obj, nodeIndex, v) + + elif objectType == "Part" and self.obj.TypeId == "Part::Box": + edit_part.updatePartBox(obj, nodeIndex, v) + + obj.recompute() + + + # ------------------------------------------------------------------------- + # UTILS + # ------------------------------------------------------------------------- + + def getObjsFromSelection(self): + """Evaluate selection and return a valid object to edit. + + #to be used for app link support + + for selobj in Gui.Selection.getSelectionEx('', 0): + for sub in selobj.SubElementNames: + obj = selobj.Object + obj_matrix = selobj.Object.getSubObject(sub, retType=4) + """ + + selection = Gui.Selection.getSelection() + self.edited_objects = [] + if len(selection) > self.maxObjects: + App.Console.PrintMessage(translate("draft", + "Too many objects selected, max number set to: ") + + str(self.maxObjects) + "\n") + return None + for obj in selection: + if utils.get_type(obj) in self.supportedObjs: + self.edited_objects.append(obj) + continue + elif utils.get_type(obj) in self.supportedPartObjs: + if obj.TypeId in self.supportedPartObjs: + self.edited_objects.append(obj) + continue + App.Console.PrintWarning(obj.Name + + translate("draft", + ": this object is not editable") + + "\n") + return self.edited_objects + + + def format_objects_for_editing(self, objs): + """Change objects style during editing mode. + """ + for obj in objs: + # TODO: Placeholder for changing the Selectable property of obj ViewProvide + if utils.get_type(obj) == "Structure": + self.objs_formats[obj.Name] = edit_arch.get_structure_format(obj) + edit_arch.set_structure_editing_format(obj) + + + def deformat_objects_after_editing(self, objs): + """Restore objects style during editing mode. + """ + for obj in objs: + # TODO: Placeholder for changing the Selectable property of obj ViewProvide + if utils.get_type(obj) == "Structure": + edit_arch.restore_structure_format(obj, self.objs_formats[obj.Name]) + + + def get_selected_obj_at_position(self, pos): + """Return object at given position. + + If object is one of the edited objects (self.edited_objects). + """ + selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1])) + if not selobjs: + return + for info in selobjs: + if not info: + return + for obj in self.edited_objects: + if obj.Name == info["Object"]: + return obj + + def globalize_vectors(self, obj, pointList): + """Return the given point list in the global coordinate system.""" + plist = [] + for p in pointList: + point = self.globalize_vector(obj, p) + plist.append(point) + return plist + + def globalize_vector(self, obj, point): + """Return the given point in the global coordinate system.""" + if hasattr(obj, "getGlobalPlacement"): + return obj.getGlobalPlacement().multVec(point) + else: + return point + + def relativize_vectors(self, obj, pointList): + """Return the given point list in the given object coordinate system.""" + plist = [] + for p in pointList: + point = self.relativize_vector(obj, p) + plist.append(point) + return plist + + def relativize_vector(self, obj, point): + """Return the given point in the given object coordinate system.""" + if hasattr(obj, "getGlobalPlacement"): + return obj.getGlobalPlacement().inverse().multVec(point) + else: + return point + + def getEditNode(self, pos): + """Get edit node from given screen position.""" + node = self.sendRay(pos) + return node + + def sendRay(self, mouse_pos): + """Send a ray through the scene and return the nearest entity.""" + ray_pick = coin.SoRayPickAction(self.render_manager.getViewportRegion()) + ray_pick.setPoint(coin.SbVec2s(*mouse_pos)) + ray_pick.setRadius(self.pick_radius) + ray_pick.setPickAll(True) + ray_pick.apply(self.render_manager.getSceneGraph()) + picked_point = ray_pick.getPickedPointList() + return self.searchEditNode(picked_point) + + def searchEditNode(self, picked_point): + """Search edit node inside picked point list and return node number.""" + for point in picked_point: + path = point.getPath() + length = path.getLength() + point = path.getNode(length - 2) + #import DraftTrackers + if hasattr(point,"subElementName") and 'EditNode' in str(point.subElementName.getValue()): + return point + return None + + def getEditNodeIndex(self, point): + """Get edit node index from given screen position.""" + if point: + subElement = str(point.subElementName.getValue()) + ep = int(subElement[8:]) + return ep + else: + return None + + Gui.addCommand('Draft_Edit', Edit()) diff --git a/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py b/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py index f8799f65ac..b3269f62b7 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py @@ -23,7 +23,7 @@ """Provide the support functions to Draft_Edit for Arch objects.""" ## @package gui_edit_arch_objects # \ingroup DRAFT -# \brief Provide the support functions to Draft_Edit for Arch objects +# \brief Provide the support functions to Draft_Edit for Arch objects. __title__ = "FreeCAD Draft Edit Tool" __author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " @@ -50,8 +50,8 @@ def getSketchPts(obj): """ editpoints = [] if obj.GeometryCount == 1: - editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,1))) - editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,2))) + editpoints.append(obj.getPoint(0,1)) + editpoints.append(obj.getPoint(0,2)) return editpoints else: _wrn = translate("draft", "Sketch is too complex to edit: " @@ -69,9 +69,9 @@ def updateSketch(obj, nodeIndex, v): 1 : endpoint """ if nodeIndex == 0: - obj.movePoint(0,1,obj.getGlobalPlacement().inverse().multVec(v)) + obj.movePoint(0, 1, v) elif nodeIndex == 1: - obj.movePoint(0,2,obj.getGlobalPlacement().inverse().multVec(v)) + obj.movePoint(0, 2, v) obj.recompute() @@ -85,38 +85,15 @@ def getWallPts(obj): """ editpoints = [] # height of the wall - editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,0,obj.Height))) - # try to add here an editpoint based on wall height (maybe should be good to associate it with a circular tracker) - if obj.Base: - # base points are added to self.trackers under wall-name key - basepoints = [] - if utils.get_type(obj.Base) in ["Wire","Circle","Rectangle", - "Polygon", "Sketch"]: - pass # TODO: make it work again - #basepoints = self.getEditPoints(obj.Base) - #for point in basepoints: - # editpoints.append(obj.Placement.multVec(point)) #works ok except if App::Part is rotated... why? + editpoints.append(App.Vector(0, 0, obj.Height)) return editpoints -def updateWallTrackers(obj): - """Update self.trackers[obj.Name][0] to match with given object.""" - pass - - def updateWall(obj, nodeIndex, v): if nodeIndex == 0: - delta= obj.getGlobalPlacement().inverse().multVec(v) - vz = DraftVecUtils.project(delta, App.Vector(0, 0, 1)) + vz = DraftVecUtils.project(v, App.Vector(0, 0, 1)) if vz.Length > 0: obj.Height = vz.Length - elif nodeIndex > 0: - if obj.Base: - if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle", - "Polygon", "Sketch"]: - pass #TODO: make it work again - #self.update(obj.Base, nodeIndex - 1, - # obj.Placement.inverse().multVec(v)) obj.recompute() @@ -153,29 +130,34 @@ def updateWindow(obj, nodeIndex, v): # STRUCTURE---------------------------------------------------------------- +def get_structure_format(obj): + return (obj.ViewObject.DisplayMode, + obj.ViewObject.NodeSize, + obj.ViewObject.ShowNodes) + +def set_structure_editing_format(obj): + obj.ViewObject.DisplayMode = "Wireframe" + obj.ViewObject.NodeSize = 1 + obj.ViewObject.ShowNodes = True + +def restore_structure_format(obj, modes): + obj.ViewObject.DisplayMode = modes[0] + obj.ViewObject.NodeSize = modes[1] + obj.ViewObject.ShowNodes = modes[2] def getStructurePts(obj): if obj.Nodes: editpoints = [] - # TODO: make it work again - #self.originalDisplayMode = obj.ViewObject.DisplayMode - #self.originalPoints = obj.ViewObject.NodeSize - #self.originalNodes = obj.ViewObject.ShowNodes - #self.obj.ViewObject.DisplayMode = "Wireframe" - #self.obj.ViewObject.NodeSize = 1 - ## self.obj.ViewObject.ShowNodes = True - #for p in obj.Nodes: - # if self.pl: - # p = self.pl.multVec(p) - # editpoints.append(p) - #return editpoints + for p in obj.Nodes: + editpoints.append(p) + return editpoints else: return None def updateStructure(obj, nodeIndex, v): nodes = obj.Nodes - nodes[nodeIndex] = obj.Placement.inverse().multVec(v) + nodes[nodeIndex] = v obj.Nodes = nodes @@ -202,26 +184,26 @@ def getPanelCutPts(obj): if obj.TagPosition.Length == 0: pos = obj.Shape.BoundBox.Center else: - pos = obj.Placement.multVec(obj.TagPosition) + pos = obj.TagPosition editpoints.append(pos) return editpoints def updatePanelCut(obj, nodeIndex, v): if nodeIndex == 0: - obj.TagPosition = obj.Placement.inverse().multVec(v) + obj.TagPosition = v def getPanelSheetPts(obj): editpoints = [] - editpoints.append(obj.Placement.multVec(obj.TagPosition)) + editpoints.append(obj.TagPosition) for o in obj.Group: - editpoints.append(obj.Placement.multVec(o.Placement.Base)) + editpoints.append(o.Placement.Base) return editpoints def updatePanelSheet(obj, nodeIndex, v): if nodeIndex == 0: - obj.TagPosition = obj.Placement.inverse().multVec(v) + obj.TagPosition = v else: - obj.Group[nodeIndex-1].Placement.Base = obj.Placement.inverse().multVec(v) + obj.Group[nodeIndex-1].Placement.Base = v diff --git a/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py b/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py index af5442b138..3808303da2 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py @@ -20,10 +20,22 @@ # * USA * # * * # *************************************************************************** -"""Provide the Draft_Edit command used by the Draft workbench.""" +"""Provide the support functions to Draft_Edit for Draft objects. + +All functions in this module work with Object coordinate space. +No conversion to global coordinate system is needed. + +To support an new Object Draft_Edit needs at least two functions: +getObjectPts(obj): returns a list of points on which Draft_Edit will display + edit trackers +updateObject(obj, nodeIndex, v): update the give object according to the + index of a moved edit tracker and the vector of the displacement +TODO: Abstract the code that handles the preview and move the object specific + code to this module from main Draft_Edit module +""" ## @package gui_edit_draft_objects # \ingroup DRAFT -# \brief Provide the Draft_Edit command used by the Draft workbench +# \brief Provide the support functions to Draft_Edit for Draft objects. __title__ = "FreeCAD Draft Edit Tool" __author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " @@ -46,13 +58,12 @@ import draftutils.utils as utils def getWirePts(obj): editpoints = [] for p in obj.Points: - p = obj.getGlobalPlacement().multVec(p) editpoints.append(p) return editpoints def updateWire(obj, nodeIndex, v): #TODO: Fix it pts = obj.Points - editPnt = obj.getGlobalPlacement().inverse().multVec(v) + editPnt = v # DNC: allows to close the curve by placing ends close to each other tol = 0.001 if ( ( nodeIndex == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or ( @@ -272,34 +283,20 @@ def getRectanglePts(obj): 2 : Height """ editpoints = [] - editpoints.append(obj.getGlobalPlacement().Base) - editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(obj.Length,0,0))) - editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,obj.Height,0))) + editpoints.append(App.Vector(0, 0, 0)) + editpoints.append(App.Vector(obj.Length, 0, 0)) + editpoints.append(App.Vector(0, obj.Height, 0)) return editpoints - def updateRectangle(obj, nodeIndex, v): - delta = obj.getGlobalPlacement().inverse().multVec(v) if nodeIndex == 0: - # p = obj.getGlobalPlacement() - # p.move(delta) - obj.Placement.move(delta) + obj.Placement.Base = obj.Placement.multVec(v) elif nodeIndex == 1: - obj.Length = DraftVecUtils.project(delta,App.Vector(1,0,0)).Length + obj.Length = DraftVecUtils.project(v, App.Vector(1,0,0)).Length elif nodeIndex == 2: - obj.Height = DraftVecUtils.project(delta,App.Vector(0,1,0)).Length + obj.Height = DraftVecUtils.project(v, App.Vector(0,1,0)).Length -# ------------------------------------------------------------------------- -# EDIT OBJECT TOOLS : Ellipse (# TODO: yet to be implemented) -# ------------------------------------------------------------------------- - -def setEllipsePts(obj): - return - -def updateEllipse(obj, nodeIndex, v): - return - # ------------------------------------------------------------------------- # EDIT OBJECT TOOLS : Circle/Arc # ------------------------------------------------------------------------- @@ -430,30 +427,50 @@ def arcInvert(obj): # ------------------------------------------------------------------------- -# EDIT OBJECT TOOLS : Polygon (maybe could also rotate the polygon) +# EDIT OBJECT TOOLS : Ellipse +# ------------------------------------------------------------------------- + +def getEllipsePts(obj): + editpoints = [] + editpoints.append(App.Vector(0, 0, 0)) + editpoints.append(App.Vector(obj.MajorRadius, 0, 0)) + editpoints.append(App.Vector(0, obj.MinorRadius, 0)) + return editpoints + +def updateEllipse(obj, nodeIndex, v): + if nodeIndex == 0: + obj.Placement.Base = obj.Placement.multVec(v) + elif nodeIndex == 1: + obj.MajorRadius = v.Length + elif nodeIndex == 2: + if v.Length <= obj.MajorRadius: + obj.MinorRadius = v.Length + else: + obj.MinorRadius = obj.MajorRadius + obj.recompute() + + +# ------------------------------------------------------------------------- +# EDIT OBJECT TOOLS : Polygon # ------------------------------------------------------------------------- def getPolygonPts(obj): editpoints = [] - editpoints.append(obj.Placement.Base) - editpoints.append(obj.Shape.Vertexes[0].Point) + editpoints.append(App.Vector(0, 0, 0)) + if obj.DrawMode == 'inscribed': + editpoints.append(obj.Placement.inverse().multVec(obj.Shape.Vertexes[0].Point)) + else: + editpoints.append(obj.Placement.inverse().multVec((obj.Shape.Vertexes[0].Point + + obj.Shape.Vertexes[1].Point) / 2 + )) return editpoints - def updatePolygon(obj, nodeIndex, v): - delta = v.sub(obj.Placement.Base) if nodeIndex == 0: - p = obj.Placement - p.move(delta) - obj.Placement = p + obj.Placement.Base = obj.Placement.multVec(v) elif nodeIndex == 1: - if obj.DrawMode == 'inscribed': - obj.Radius = delta.Length - else: - halfangle = ((math.pi*2)/obj.FacesNumber)/2 - rad = math.cos(halfangle)*delta.Length - obj.Radius = rad - obj.recompute() + obj.Radius = v.Length + obj.recompute() # ------------------------------------------------------------------------- diff --git a/src/Mod/Draft/draftguitools/gui_edit_part_objects.py b/src/Mod/Draft/draftguitools/gui_edit_part_objects.py index 49bb049e44..dc07a7eab7 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_part_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_part_objects.py @@ -21,7 +21,7 @@ """Provide the support functions to Draft_Edit for Part objects.""" ## @package gui_edit_part_objects # \ingroup DRAFT -# \brief Provide the support functions to Draft_Edit for Part objects +# \brief Provide the support functions to Draft_Edit for Part objects. __title__ = "FreeCAD Draft Edit Tool" __author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " @@ -37,43 +37,40 @@ import DraftVecUtils def getPartLinePts(obj): editpoints = [] - editpoints.append(obj.Placement.multVec(App.Vector(obj.X1,obj.Y1,obj.Z1))) - editpoints.append(obj.Placement.pl.multVec(App.Vector(obj.X2,obj.Y2,obj.Z2))) + editpoints.append(App.Vector(obj.X1,obj.Y1,obj.Z1)) + editpoints.append(App.Vector(obj.X2,obj.Y2,obj.Z2)) return editpoints - def updatePartLine(obj, nodeIndex, v): - pt=obj.Placement.inverse().multVec(v) if nodeIndex == 0: - obj.X1 = pt.x - obj.Y1 = pt.y - obj.Z1 = pt.z + obj.X1 = v.x + obj.Y1 = v.y + obj.Z1 = v.z elif nodeIndex == 1: - obj.X2 = pt.x - obj.Y2 = pt.y - obj.Z2 = pt.z + obj.X2 = v.x + obj.Y2 = v.y + obj.Z2 = v.z + # PART::BOX--------------------------------------------------------------- -def getPartBoxPts(self, obj): +def getPartBoxPts(obj): editpoints = [] - editpoints.append(obj.Placement.Base) - editpoints.append(obj.Placement.multVec(App.Vector(obj.Length, 0, 0))) - editpoints.append(obj.Placement.multVec(App.Vector(0, obj.Width, 0))) - editpoints.append(obj.Placement.multVec(App.Vector(0, 0, obj.Height))) + editpoints.append(App.Vector(0, 0, 0)) + editpoints.append(App.Vector(obj.Length, 0, 0)) + editpoints.append(App.Vector(0, obj.Width, 0)) + editpoints.append(App.Vector(0, 0, obj.Height)) return editpoints - -def updatePartBox(self, obj, nodeIndex, v): - delta = obj.Placement.inverse().multVec(v) +def updatePartBox(obj, nodeIndex, v): if nodeIndex == 0: - obj.Placement.Base = v + obj.Placement.Base = obj.Placement.Base + v elif nodeIndex == 1: - _vector = DraftVecUtils.project(delta, App.Vector(1, 0, 0)) + _vector = DraftVecUtils.project(v, App.Vector(1, 0, 0)) obj.Length = _vector.Length elif nodeIndex == 2: - _vector = DraftVecUtils.project(delta, App.Vector(0, 1, 0)) + _vector = DraftVecUtils.project(v, App.Vector(0, 1, 0)) obj.Width = _vector.Length elif nodeIndex == 3: - _vector = DraftVecUtils.project(delta, App.Vector(0, 0, 1)) + _vector = DraftVecUtils.project(v, App.Vector(0, 0, 1)) obj.Height = _vector.Length diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index b9ef6c8a58..858260f540 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -147,7 +147,7 @@ def autogroup(obj): obj.X = real_point.x obj.Y = real_point.y obj.Z = real_point.z - elif get_type(obj) in ["Dimension"]: + elif get_type(obj) in ["Dimension", "LinearDimension"]: obj.Start = inverse_placement.multVec(obj.Start) obj.End = inverse_placement.multVec(obj.End) obj.Dimline = inverse_placement.multVec(obj.Dimline)