Draft: Improve Draft_Edit context menus
This commit is contained in:
@@ -285,7 +285,6 @@ class DraftToolBar:
|
||||
self.uiloader = FreeCADGui.UiLoader()
|
||||
self.autogroup = None
|
||||
self.isCenterPlane = False
|
||||
self.lastMode = None
|
||||
self.input_fields = {
|
||||
"xValue":{"value":"x","unit":"Length"},
|
||||
"yValue":{"value":"y","unit":"Length"},
|
||||
@@ -1198,34 +1197,8 @@ class DraftToolBar:
|
||||
self.labelx.show()
|
||||
self.makeDumbTask(extra, on_close_call)
|
||||
|
||||
def editUi(self, mode=None):
|
||||
self.lastMode=mode
|
||||
self.taskUi(translate("draft", "Edit"))
|
||||
self.hideXYZ()
|
||||
self.numFaces.hide()
|
||||
self.hasFill.hide()
|
||||
# self.addButton.show()
|
||||
# self.delButton.show()
|
||||
# if mode == 'Wire':
|
||||
# self.setEditButtons(True)
|
||||
# self.setBezEditButtons(False)
|
||||
# elif mode == 'Arc':
|
||||
# self.addButton.hide()
|
||||
# self.delButton.hide()
|
||||
# self.arc3PtButton.show()
|
||||
# elif mode == 'BezCurve':
|
||||
# self.sharpButton.show()
|
||||
# self.tangentButton.show()
|
||||
# self.symmetricButton.show()
|
||||
self.closeButton.show()
|
||||
# self.finishButton.show()
|
||||
# always start Edit with buttons unchecked
|
||||
# self.addButton.setChecked(False)
|
||||
# self.delButton.setChecked(False)
|
||||
# self.sharpButton.setChecked(False)
|
||||
# self.tangentButton.setChecked(False)
|
||||
# self.symmetricButton.setChecked(False)
|
||||
# self.arc3PtButton.setChecked(False)
|
||||
def editUi(self):
|
||||
self.makeDumbTask(on_close_call=self.finish)
|
||||
|
||||
def extUi(self):
|
||||
if Draft.getParam("UsePartPrimitives",False):
|
||||
|
||||
@@ -91,29 +91,13 @@ class Edit(gui_base_original.Modifier):
|
||||
Task panel (Draft Toolbar)
|
||||
----------
|
||||
self.ui = Gui.draftToolBar
|
||||
TODO: since we introduced context menu for interacting
|
||||
with editTrackers, point 2 should become obsolete,
|
||||
because not consistent with multi-object editing.
|
||||
|
||||
Draft_Edit uses taskpanel in 3 ways:
|
||||
Draft_Edit uses the taskpanel in 2 ways:
|
||||
|
||||
1 - when waiting for user to select an object
|
||||
calling self.ui.selectUi()
|
||||
1 - the user can select select an object and close the operation
|
||||
self.ui.editUi()
|
||||
|
||||
2 - when Trackers are displayed and user must click one, a
|
||||
custom task panel is displayed depending on edited
|
||||
object:
|
||||
self.ui.editUi() -> the default one
|
||||
self.ui.editUi("Wire") -> line and wire editing
|
||||
self.ui.editUi("BezCurve") -> BezCurve editing
|
||||
self.ui.editUi("Circle") -> circle editing
|
||||
self.ui.editUi("Arc") -> arc editing
|
||||
When Draft_Edit evaluate mouse click, depending if some
|
||||
ui button have been pressed (.isChecked()), decide if
|
||||
the action is a startEditing or AddPoint or DelPoint or
|
||||
change BezCurve Continuity, ecc.
|
||||
|
||||
3 - when in editing, lineUi support clicking destination point
|
||||
2 - when editing, lineUi support clicking destination point
|
||||
by self.startEditing
|
||||
self.ui.lineUi()
|
||||
|
||||
@@ -123,7 +107,6 @@ class Edit(gui_base_original.Modifier):
|
||||
using soRayPickAction, it identifies the selected editTracker and
|
||||
start editing it. Here is where "looo" code was very useful.
|
||||
|
||||
|
||||
Editing preview
|
||||
---------------
|
||||
When object editing begins, self.ghost is initiated with the
|
||||
@@ -234,7 +217,7 @@ class Edit(gui_base_original.Modifier):
|
||||
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
|
||||
self.maxObjects = param.GetInt("DraftEditMaxObjects", 5)
|
||||
self.pick_radius = param.GetInt("DraftEditPickRadius", 20)
|
||||
|
||||
|
||||
self.alt_edit_mode = 0 # default edit mode for objects
|
||||
|
||||
# preview
|
||||
@@ -300,7 +283,7 @@ class Edit(gui_base_original.Modifier):
|
||||
self.proceed()
|
||||
else:
|
||||
self.ui.selectUi(on_close_call=self.finish)
|
||||
App.Console.PrintMessage(translate("draft",
|
||||
App.Console.PrintMessage(translate("draft",
|
||||
"Select a Draft object to edit")
|
||||
+ "\n")
|
||||
self.register_selection_callback()
|
||||
@@ -357,7 +340,7 @@ class Edit(gui_base_original.Modifier):
|
||||
|
||||
if self.edited_objects:
|
||||
self.deformat_objects_after_editing(self.edited_objects)
|
||||
|
||||
|
||||
super(Edit, self).finish()
|
||||
if Gui.Snapper.grid:
|
||||
Gui.Snapper.grid.set()
|
||||
@@ -448,7 +431,7 @@ class Edit(gui_base_original.Modifier):
|
||||
mouse button event handler, calls: startEditing, endEditing, addPoint, delPoint
|
||||
"""
|
||||
event = event_callback.getEvent()
|
||||
if (event.getState() == coin.SoMouseButtonEvent.DOWN and
|
||||
if (event.getState() == coin.SoMouseButtonEvent.DOWN and
|
||||
event.getButton() == event.BUTTON1
|
||||
):#left click
|
||||
if not event.wasAltDown():
|
||||
@@ -501,7 +484,7 @@ class Edit(gui_base_original.Modifier):
|
||||
+ ": editing node number "
|
||||
+ str(node_idx) + "\n")
|
||||
|
||||
self.ui.lineUi()
|
||||
self.ui.lineUi(title=translate("draft", "Edit node"), icon="Draft_Edit")
|
||||
self.editing = node_idx
|
||||
self.trackers[obj.Name][node_idx].off()
|
||||
|
||||
@@ -538,7 +521,7 @@ class Edit(gui_base_original.Modifier):
|
||||
self.trackers[obj.Name][nodeIndex].set(v)
|
||||
self.update(obj, nodeIndex, v)
|
||||
self.alt_edit_mode = 0
|
||||
self.ui.editUi(self.ui.lastMode)
|
||||
self.ui.editUi()
|
||||
self.node = []
|
||||
self.editing = None
|
||||
self.showTrackers()
|
||||
@@ -651,7 +634,7 @@ class Edit(gui_base_original.Modifier):
|
||||
self.current_editing_object_gui_tools = self.get_obj_gui_tools(obj)
|
||||
if self.current_editing_object_gui_tools:
|
||||
self.ghost = self.current_editing_object_gui_tools.init_preview_object(obj)
|
||||
|
||||
|
||||
def updateGhost(self, obj, node_idx, v):
|
||||
self.ghost.on()
|
||||
|
||||
@@ -719,7 +702,7 @@ class Edit(gui_base_original.Modifier):
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS
|
||||
# EDIT OBJECT TOOLS
|
||||
#
|
||||
# This section contains the code to retrieve the object points and update them
|
||||
#
|
||||
@@ -799,7 +782,7 @@ class Edit(gui_base_original.Modifier):
|
||||
|
||||
#to be used for app link support
|
||||
|
||||
for selobj in Gui.Selection.getSelectionEx('', 0):
|
||||
for selobj in Gui.Selection.getSelectionEx('', 0):
|
||||
for sub in selobj.SubElementNames:
|
||||
obj = selobj.Object
|
||||
obj_matrix = selobj.Object.getSubObject(sub, retType=4)
|
||||
@@ -828,7 +811,7 @@ class Edit(gui_base_original.Modifier):
|
||||
if obj_gui_tools:
|
||||
self.objs_formats[obj.Name] = obj_gui_tools.get_object_style(obj)
|
||||
obj_gui_tools.set_object_editing_style(obj)
|
||||
|
||||
|
||||
|
||||
def deformat_objects_after_editing(self, objs):
|
||||
"""Restore objects style during editing mode.
|
||||
@@ -902,7 +885,7 @@ class Edit(gui_base_original.Modifier):
|
||||
"""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())
|
||||
@@ -936,7 +919,7 @@ class Edit(gui_base_original.Modifier):
|
||||
|
||||
|
||||
class GuiToolsRepository():
|
||||
""" This object provide a repository to collect all the specific objects
|
||||
""" This object provide a repository to collect all the specific objects
|
||||
editing tools.
|
||||
"""
|
||||
def __init__(self):
|
||||
|
||||
@@ -106,15 +106,29 @@ class DraftWireGuiTools(GuiTools):
|
||||
|
||||
def get_edit_point_context_menu(self, edit_command, obj, node_idx):
|
||||
return [
|
||||
("delete point", lambda: self.delete_point(obj, node_idx)),
|
||||
(translate("draft", "Delete point"), lambda: self.delete_point(obj, node_idx)),
|
||||
]
|
||||
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
return [
|
||||
("add point", lambda: self.add_point(edit_command, obj, position)),
|
||||
("reverse wire", lambda: self.reverse_wire(obj)),
|
||||
(translate("draft", "Add point"), lambda: self.add_point(edit_command, obj, position)),
|
||||
(self.get_open_close_menu_text(obj), lambda: self.open_close_wire(obj)),
|
||||
(self.get_reverse_menu_text(obj), lambda: self.reverse_wire(obj)),
|
||||
]
|
||||
|
||||
def get_open_close_menu_text(self, obj):
|
||||
"""This function is overridden in the DraftBSplineGuiTools class.
|
||||
"""
|
||||
if obj.Closed:
|
||||
return translate("draft", "Open wire")
|
||||
else:
|
||||
return translate("draft", "Close wire")
|
||||
|
||||
def get_reverse_menu_text(self, obj):
|
||||
"""This function is overridden in the DraftBSplineGuiTools class.
|
||||
"""
|
||||
return translate("draft", "Reverse wire")
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.wireTracker(obj.Shape)
|
||||
|
||||
@@ -133,7 +147,7 @@ class DraftWireGuiTools(GuiTools):
|
||||
|
||||
if not info:
|
||||
return
|
||||
if not 'Edge' in info["Component"]:
|
||||
if not 'Edge' in info["Component"]:
|
||||
return
|
||||
edgeIndex = int(info["Component"][4:])
|
||||
|
||||
@@ -156,11 +170,10 @@ class DraftWireGuiTools(GuiTools):
|
||||
obj.Points = newPoints
|
||||
|
||||
obj.recompute()
|
||||
return
|
||||
|
||||
def delete_point(self, obj, node_idx):
|
||||
if len(obj.Points) <= 2:
|
||||
_msg = translate("draft", "Active object must have more than two points/nodes")
|
||||
_msg = translate("draft", "Active object must have more than two points/nodes")
|
||||
App.Console.PrintWarning(_msg + "\n")
|
||||
return
|
||||
|
||||
@@ -170,12 +183,26 @@ class DraftWireGuiTools(GuiTools):
|
||||
|
||||
obj.recompute()
|
||||
|
||||
def open_close_wire(self, obj):
|
||||
obj.Closed = not obj.Closed
|
||||
obj.recompute()
|
||||
|
||||
def reverse_wire(self, obj):
|
||||
obj.Points = reversed(obj.Points)
|
||||
obj.recompute()
|
||||
|
||||
|
||||
class DraftBSplineGuiTools(DraftWireGuiTools):
|
||||
|
||||
def get_open_close_menu_text(self, obj):
|
||||
if obj.Closed:
|
||||
return translate("draft", "Open spline")
|
||||
else:
|
||||
return translate("draft", "Close spline")
|
||||
|
||||
def get_reverse_menu_text(self, obj):
|
||||
return translate("draft", "Reverse spline")
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.bsplineTracker()
|
||||
|
||||
@@ -301,7 +328,7 @@ class DraftCircleGuiTools(GuiTools):
|
||||
p1 = obj.Placement.multVec(self.getArcStart(obj))
|
||||
p2 = obj.Placement.multVec(self.getArcMid(obj))
|
||||
p3 = obj.Placement.multVec(self.getArcEnd(obj))
|
||||
|
||||
|
||||
if node_idx == 1: # first point
|
||||
p1 = v
|
||||
elif node_idx == 3: # midpoint
|
||||
@@ -316,7 +343,7 @@ class DraftCircleGuiTools(GuiTools):
|
||||
p0 = arc.Location
|
||||
obj.Placement.Base = p0
|
||||
obj.Radius = arc.Radius
|
||||
|
||||
|
||||
delta = s.Vertexes[0].Point
|
||||
obj.FirstAngle = -math.degrees(DraftVecUtils.angle(p1.sub(p0)))
|
||||
delta = s.Vertexes[1].Point
|
||||
@@ -341,19 +368,19 @@ class DraftCircleGuiTools(GuiTools):
|
||||
if obj.FirstAngle != obj.LastAngle:
|
||||
if node_idx == 0: # user is over arc start point
|
||||
return [
|
||||
("move arc", lambda: self.handle_move_arc(edit_command, obj, node_idx)),
|
||||
(translate("draft", "Move arc"), lambda: self.handle_move_arc(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 1: # user is over arc start point
|
||||
return [
|
||||
("set first angle", lambda: self.handle_set_first_angle(edit_command, obj, node_idx)),
|
||||
(translate("draft", "Set first angle"), lambda: self.handle_set_first_angle(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 2: # user is over arc end point
|
||||
return [
|
||||
("set last angle", lambda: self.handle_set_last_angle(edit_command, obj, node_idx)),
|
||||
(translate("draft", "Set last angle"), lambda: self.handle_set_last_angle(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 3: # user is over arc mid point
|
||||
return [
|
||||
("set radius", lambda: self.handle_set_radius(edit_command, obj, node_idx)),
|
||||
(translate("draft", "Set radius"), lambda: self.handle_set_radius(edit_command, obj, node_idx)),
|
||||
]
|
||||
|
||||
def handle_move_arc(self, edit_command, obj, node_idx):
|
||||
@@ -373,8 +400,12 @@ class DraftCircleGuiTools(GuiTools):
|
||||
edit_command.startEditing(obj, node_idx)
|
||||
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
# Do not show the `Invert arc` option for circles:
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
return
|
||||
|
||||
return [
|
||||
("invert arc", lambda: self.arcInvert(obj)),
|
||||
(translate("draft", "Invert arc"), lambda: self.arcInvert(obj)),
|
||||
]
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
@@ -505,7 +536,7 @@ class DraftPolygonGuiTools(GuiTools):
|
||||
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 +
|
||||
editpoints.append(obj.Placement.inverse().multVec((obj.Shape.Vertexes[0].Point +
|
||||
obj.Shape.Vertexes[1].Point) / 2
|
||||
))
|
||||
return editpoints
|
||||
@@ -560,7 +591,7 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
pts = obj.Points
|
||||
# DNC: check for coincident startpoint/endpoint to auto close the curve
|
||||
tol = 0.001
|
||||
if ( ( node_idx == 0 ) and ( (v - pts[-1]).Length < tol) ) or (
|
||||
if ( ( node_idx == 0 ) and ( (v - pts[-1]).Length < tol) ) or (
|
||||
node_idx == len(pts) - 1 ) and ( (v - pts[0]).Length < tol):
|
||||
obj.Closed = True
|
||||
# DNC: checks if point enter is equal to other, this could cause a OCC problem
|
||||
@@ -569,7 +600,7 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
"coincident points, please try again.")
|
||||
App.Console.PrintMessage(_err + "\n")
|
||||
return
|
||||
|
||||
|
||||
pts = self.recomputePointsBezier(obj, pts, node_idx, v, obj.Degree, moveTrackers=False)
|
||||
|
||||
if obj.Closed:
|
||||
@@ -584,17 +615,25 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
|
||||
def get_edit_point_context_menu(self, edit_command, obj, node_idx):
|
||||
return [
|
||||
("make sharp", lambda: self.smoothBezPoint(obj, node_idx, 'Sharp')),
|
||||
("make tangent", lambda: self.smoothBezPoint(obj, node_idx, 'Tangent')),
|
||||
("make symmetric", lambda: self.smoothBezPoint(obj, node_idx, 'Symmetric')),
|
||||
("delete point", lambda: self.delete_point(obj, node_idx)),
|
||||
(translate("draft", "Delete point"), lambda: self.delete_point(obj, node_idx)),
|
||||
(translate("draft", "Make sharp"), lambda: self.smoothBezPoint(obj, node_idx, "Sharp")),
|
||||
(translate("draft", "Make tangent"), lambda: self.smoothBezPoint(obj, node_idx, "Tangent")),
|
||||
(translate("draft", "Make symmetric"), lambda: self.smoothBezPoint(obj, node_idx, "Symmetric")),
|
||||
]
|
||||
|
||||
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
return [
|
||||
("add point", lambda: self.add_point(edit_command, obj, position)),
|
||||
(translate("draft", "Add point"), lambda: self.add_point(edit_command, obj, position)),
|
||||
(self.get_open_close_menu_text(obj), lambda: self.open_close_wire(obj)),
|
||||
(translate("draft", "Reverse curve"), lambda: self.reverse_wire(obj)),
|
||||
]
|
||||
|
||||
def get_open_close_menu_text(self, obj):
|
||||
if obj.Closed:
|
||||
return translate("draft", "Open curve")
|
||||
else:
|
||||
return translate("draft", "Close curve")
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.bezcurveTracker()
|
||||
|
||||
@@ -602,18 +641,6 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
plist = edit_command.globalize_vectors(obj, obj.Points)
|
||||
pointList = self.recomputePointsBezier(obj,plist,node_idx,v,obj.Degree,moveTrackers=False)
|
||||
edit_command.ghost.update(pointList, obj.Degree)
|
||||
|
||||
def delete_point(self, obj, node_idx):
|
||||
if len(obj.Points) <= 2:
|
||||
_msg = translate("draft", "Active object must have more than two points/nodes")
|
||||
App.Console.PrintWarning(_msg + "\n")
|
||||
return
|
||||
|
||||
pts = obj.Points
|
||||
pts.pop(node_idx)
|
||||
obj.Points = pts
|
||||
obj.Proxy.resetcontinuity(obj)
|
||||
obj.recompute()
|
||||
|
||||
def recomputePointsBezier(self, obj, pts, idx, v,
|
||||
degree, moveTrackers=False):
|
||||
@@ -677,7 +704,8 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
|
||||
|
||||
def smoothBezPoint(self, obj, point, style='Symmetric'):
|
||||
"called when changing the continuity of a knot"
|
||||
"""called when changing the continuity of a knot
|
||||
"""
|
||||
style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2}
|
||||
if point is None:
|
||||
return
|
||||
@@ -770,7 +798,7 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
info, pt = edit_command.get_specific_object_info(obj,pos)
|
||||
if not info or (pt is None):
|
||||
return
|
||||
|
||||
|
||||
import Part
|
||||
|
||||
pts = obj.Points
|
||||
@@ -806,4 +834,24 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
|
||||
obj.recompute()
|
||||
|
||||
def delete_point(self, obj, node_idx):
|
||||
if len(obj.Points) <= 2:
|
||||
_msg = translate("draft", "Active object must have more than two points/nodes")
|
||||
App.Console.PrintWarning(_msg + "\n")
|
||||
return
|
||||
|
||||
pts = obj.Points
|
||||
pts.pop(node_idx)
|
||||
obj.Points = pts
|
||||
obj.Proxy.resetcontinuity(obj)
|
||||
obj.recompute()
|
||||
|
||||
def open_close_wire(self, obj):
|
||||
obj.Closed = not obj.Closed
|
||||
obj.recompute()
|
||||
|
||||
def reverse_wire(self, obj):
|
||||
obj.Points = reversed(obj.Points)
|
||||
obj.recompute()
|
||||
|
||||
## @}
|
||||
|
||||
Reference in New Issue
Block a user