Merge pull request #4811 from carlopav/DraftEdit_Improvements
Draft: Edit improvements to context menu and code organization
This commit is contained in:
@@ -457,7 +457,16 @@ class Edit(gui_base_original.Modifier):
|
||||
):#left click
|
||||
if not event.wasAltDown():
|
||||
if self.editing is None:
|
||||
self.startEditing(event)
|
||||
|
||||
pos = event.getPosition()
|
||||
node = self.getEditNode(pos)
|
||||
node_idx = self.getEditNodeIndex(node)
|
||||
if node_idx is None:
|
||||
return
|
||||
doc = App.getDocument(str(node.documentName.getValue()))
|
||||
obj = doc.getObject(str(node.objectName.getValue()))
|
||||
|
||||
self.startEditing(obj, node_idx)
|
||||
else:
|
||||
self.endEditing(self.obj, self.editing)
|
||||
elif event.wasAltDown(): # left click with ctrl down
|
||||
@@ -486,32 +495,25 @@ class Edit(gui_base_original.Modifier):
|
||||
self.overNode.setColor(COLORS["default"])
|
||||
self.overNode = None
|
||||
|
||||
def startEditing(self, event):
|
||||
def startEditing(self, obj, node_idx):
|
||||
"""Start editing selected EditNode."""
|
||||
pos = event.getPosition()
|
||||
node = self.getEditNode(pos)
|
||||
ep = self.getEditNodeIndex(node)
|
||||
if ep is None:
|
||||
self.obj = obj # this is still needed to handle preview
|
||||
if obj is None:
|
||||
return
|
||||
|
||||
doc = App.getDocument(str(node.documentName.getValue()))
|
||||
self.obj = doc.getObject(str(node.objectName.getValue()))
|
||||
if self.obj is None:
|
||||
return
|
||||
|
||||
App.Console.PrintMessage(self.obj.Name
|
||||
App.Console.PrintMessage(obj.Name
|
||||
+ ": editing node number "
|
||||
+ str(ep) + "\n")
|
||||
+ str(node_idx) + "\n")
|
||||
|
||||
self.ui.lineUi()
|
||||
self.ui.isRelative.show()
|
||||
self.editing = ep
|
||||
self.trackers[self.obj.Name][self.editing].off()
|
||||
self.editing = node_idx
|
||||
self.trackers[obj.Name][node_idx].off()
|
||||
|
||||
self.finalizeGhost()
|
||||
self.initGhost(self.obj)
|
||||
self.initGhost(obj)
|
||||
|
||||
self.node.append(self.trackers[self.obj.Name][self.editing].get())
|
||||
self.node.append(self.trackers[obj.Name][node_idx].get())
|
||||
Gui.Snapper.setSelectMode(False)
|
||||
self.hideTrackers()
|
||||
|
||||
@@ -670,116 +672,12 @@ class Edit(gui_base_original.Modifier):
|
||||
except Exception:
|
||||
return
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Add/Delete Vertexes
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def addPoint(self, event):
|
||||
"""Add point to obj and reset trackers.
|
||||
"""
|
||||
pos = event.getPosition()
|
||||
# self.setSelectState(obj, True)
|
||||
selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1]))
|
||||
if not selobjs:
|
||||
return
|
||||
for info in selobjs:
|
||||
if not info:
|
||||
return
|
||||
for o in self.edited_objects:
|
||||
if o.Name != info["Object"]:
|
||||
continue
|
||||
obj = o
|
||||
break
|
||||
if utils.get_type(obj) == "Wire" and 'Edge' in info["Component"]:
|
||||
pt = App.Vector(info["x"], info["y"], info["z"])
|
||||
self.addPointToWire(obj, pt, int(info["Component"][4:]))
|
||||
elif utils.get_type(obj) in ["BSpline", "BezCurve"]: #to fix double vertex created
|
||||
# pt = self.point
|
||||
if "x" in info:# prefer "real" 3D location over working-plane-driven one if possible
|
||||
pt = App.Vector(info["x"], info["y"], info["z"])
|
||||
else:
|
||||
continue
|
||||
self.addPointToCurve(pt, obj, info)
|
||||
obj.recompute()
|
||||
self.resetTrackers(obj)
|
||||
return
|
||||
|
||||
def addPointToWire(self, obj, newPoint, edgeIndex):
|
||||
newPoints = []
|
||||
if hasattr(obj, "ChamferSize") and hasattr(obj, "FilletRadius"):
|
||||
if obj.ChamferSize > 0 and obj.FilletRadius > 0:
|
||||
edgeIndex = (edgeIndex + 3) / 4
|
||||
elif obj.ChamferSize > 0 or obj.FilletRadius > 0:
|
||||
edgeIndex = (edgeIndex + 1) / 2
|
||||
|
||||
for index, point in enumerate(obj.Points):
|
||||
if index == edgeIndex:
|
||||
newPoints.append(self.localize_vector(obj, newPoint))
|
||||
newPoints.append(point)
|
||||
if obj.Closed and edgeIndex == len(obj.Points):
|
||||
# last segment when object is closed
|
||||
newPoints.append(self.localize_vector(obj, newPoint))
|
||||
obj.Points = newPoints
|
||||
|
||||
def addPointToCurve(self, point, obj, info=None):
|
||||
import Part
|
||||
if utils.get_type(obj) not in ["BSpline", "BezCurve"]:
|
||||
return
|
||||
pts = obj.Points
|
||||
if utils.get_type(obj) == "BezCurve":
|
||||
if not info['Component'].startswith('Edge'):
|
||||
return # clicked control point
|
||||
edgeindex = int(info['Component'].lstrip('Edge')) - 1
|
||||
wire = obj.Shape.Wires[0]
|
||||
bz = wire.Edges[edgeindex].Curve
|
||||
param = bz.parameter(point)
|
||||
seg1 = wire.Edges[edgeindex].copy().Curve
|
||||
seg2 = wire.Edges[edgeindex].copy().Curve
|
||||
seg1.segment(seg1.FirstParameter, param)
|
||||
seg2.segment(param, seg2.LastParameter)
|
||||
if edgeindex == len(wire.Edges):
|
||||
# we hit the last segment, we need to fix the degree
|
||||
degree=wire.Edges[0].Curve.Degree
|
||||
seg1.increase(degree)
|
||||
seg2.increase(degree)
|
||||
edges = wire.Edges[0:edgeindex] + [Part.Edge(seg1),Part.Edge(seg2)] \
|
||||
+ wire.Edges[edgeindex + 1:]
|
||||
pts = edges[0].Curve.getPoles()[0:1]
|
||||
for edge in edges:
|
||||
pts.extend(edge.Curve.getPoles()[1:])
|
||||
if obj.Closed:
|
||||
pts.pop()
|
||||
c = obj.Continuity
|
||||
# assume we have a tangent continuity for an arbitrarily split
|
||||
# segment, unless it's linear
|
||||
cont = 1 if (obj.Degree >= 2) else 0
|
||||
obj.Continuity = c[0:edgeindex] + [cont] + c[edgeindex:]
|
||||
else:
|
||||
if (utils.get_type(obj) in ["BSpline"]):
|
||||
if (obj.Closed == True):
|
||||
curve = obj.Shape.Edges[0].Curve
|
||||
else:
|
||||
curve = obj.Shape.Curve
|
||||
uNewPoint = curve.parameter(point)
|
||||
uPoints = []
|
||||
for p in obj.Points:
|
||||
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.localize_vector(obj, point))
|
||||
break
|
||||
# DNC: fix: add points to last segment if curve is closed
|
||||
if obj.Closed and (uNewPoint > uPoints[-1]):
|
||||
pts.append(self.localize_vector(obj, point))
|
||||
obj.Points = pts
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# DRAFT EDIT Context menu
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
def display_tracker_menu(self, event):
|
||||
self.tracker_menu = QtGui.QMenu()
|
||||
self.event = event
|
||||
actions = None
|
||||
|
||||
if self.overNode:
|
||||
@@ -790,22 +688,27 @@ class Edit(gui_base_original.Modifier):
|
||||
|
||||
obj_gui_tools = self.get_obj_gui_tools(obj)
|
||||
if obj_gui_tools:
|
||||
actions = obj_gui_tools.get_edit_point_context_menu(obj, ep)
|
||||
actions = obj_gui_tools.get_edit_point_context_menu(self, obj, ep)
|
||||
|
||||
else:
|
||||
# try if user is over an edited object
|
||||
pos = self.event.getPosition()
|
||||
pos = event.getPosition()
|
||||
obj = self.get_selected_obj_at_position(pos)
|
||||
if utils.get_type(obj) in ["Line", "Wire", "BSpline", "BezCurve"]:
|
||||
actions = ["add point"]
|
||||
elif utils.get_type(obj) in ["Circle"] and obj.FirstAngle != obj.LastAngle:
|
||||
actions = ["invert arc"]
|
||||
|
||||
obj_gui_tools = self.get_obj_gui_tools(obj)
|
||||
if obj_gui_tools:
|
||||
actions = obj_gui_tools.get_edit_obj_context_menu(self, obj, pos)
|
||||
|
||||
if actions is None:
|
||||
return
|
||||
|
||||
for a in actions:
|
||||
self.tracker_menu.addAction(a)
|
||||
for (label, callback) in actions:
|
||||
def wrapper(callback=callback):
|
||||
callback()
|
||||
self.resetTrackers(obj)
|
||||
|
||||
action = self.tracker_menu.addAction(label)
|
||||
action.setData(wrapper)
|
||||
|
||||
self.tracker_menu.popup(Gui.getMainWindow().cursor().pos())
|
||||
|
||||
@@ -814,31 +717,9 @@ class Edit(gui_base_original.Modifier):
|
||||
self.evaluate_menu_action)
|
||||
|
||||
|
||||
def evaluate_menu_action(self, labelname):
|
||||
action_label = str(labelname.text())
|
||||
|
||||
doc = None
|
||||
obj = None
|
||||
idx = None
|
||||
|
||||
if self.overNode:
|
||||
doc = self.overNode.get_doc_name()
|
||||
obj = App.getDocument(doc).getObject(self.overNode.get_obj_name())
|
||||
idx = self.overNode.get_subelement_index()
|
||||
|
||||
obj_gui_tools = self.get_obj_gui_tools(obj)
|
||||
if obj and obj_gui_tools:
|
||||
actions = obj_gui_tools.evaluate_context_menu_action(self, obj, idx, action_label)
|
||||
|
||||
elif action_label == "add point":
|
||||
self.addPoint(self.event)
|
||||
|
||||
elif action_label == "invert arc":
|
||||
pos = self.event.getPosition()
|
||||
obj = self.get_selected_obj_at_position(pos)
|
||||
obj_gui_tools.arcInvert(obj)
|
||||
|
||||
del self.event
|
||||
def evaluate_menu_action(self, action):
|
||||
callback = action.data()
|
||||
callback()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -962,6 +843,20 @@ class Edit(gui_base_original.Modifier):
|
||||
obj_gui_tools.restore_object_style(obj, self.objs_formats[obj.Name])
|
||||
|
||||
|
||||
def get_specific_object_info(self, obj, pos):
|
||||
"""Return info of a specific object at a given position.
|
||||
"""
|
||||
selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1]))
|
||||
if not selobjs:
|
||||
return
|
||||
for info in selobjs:
|
||||
if not info:
|
||||
continue
|
||||
if obj.Name == info["Object"] and "x" in info:
|
||||
# prefer "real" 3D location over working-plane-driven one if possible
|
||||
pt = App.Vector(info["x"], info["y"], info["z"])
|
||||
return info, pt
|
||||
|
||||
def get_selected_obj_at_position(self, pos):
|
||||
"""Return object at given position.
|
||||
|
||||
|
||||
@@ -73,12 +73,6 @@ class ArchWallGuiTools(GuiTools):
|
||||
if vz.Length > 0:
|
||||
obj.Height = vz.Length
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class ArchWindowGuiTools(GuiTools):
|
||||
|
||||
@@ -112,12 +106,6 @@ class ArchWindowGuiTools(GuiTools):
|
||||
for obj in obj.Hosts:
|
||||
obj.recompute()
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class ArchStructureGuiTools(GuiTools):
|
||||
|
||||
@@ -138,12 +126,6 @@ class ArchStructureGuiTools(GuiTools):
|
||||
nodes[node_idx] = v
|
||||
obj.Nodes = nodes
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
def get_object_style(self, obj):
|
||||
return (obj.ViewObject.DisplayMode,
|
||||
obj.ViewObject.NodeSize,
|
||||
@@ -177,12 +159,6 @@ class ArchSpaceGuiTools(GuiTools):
|
||||
if node_idx == 0:
|
||||
obj.ViewObject.TextPosition = v
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class ArchPanelCutGuiTools(GuiTools):
|
||||
|
||||
@@ -202,12 +178,6 @@ class ArchPanelCutGuiTools(GuiTools):
|
||||
if node_idx == 0:
|
||||
obj.TagPosition = v
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class ArchPanelSheetGuiTools(GuiTools):
|
||||
|
||||
@@ -227,11 +197,4 @@ class ArchPanelSheetGuiTools(GuiTools):
|
||||
else:
|
||||
obj.Group[node_idx-1].Placement.Base = v
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -61,14 +61,33 @@ class GuiTools:
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
""" Return a list of Draft_Edit context menu actions.
|
||||
def get_edit_point_context_menu(self, edit_command, obj, node_idx):
|
||||
""" Get the context menu associated to edit points (user is over an editpoint)
|
||||
|
||||
Return a list of tuples containig menu labels and associated functions:
|
||||
return [
|
||||
("action label", lambda: self.handle_action_label(edit_command, obj, node_idx)),
|
||||
]
|
||||
|
||||
Parameters:
|
||||
edit_command: running Draft_Edit command
|
||||
obj: the edited object
|
||||
node_idx: number of the edited node
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
""" Do something when a Draft_Edit context menu action is triggered over a node.
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
""" Get the context menu associated to edited object (user is over the object)
|
||||
|
||||
Return a list of tuples containig menu labels and associated functions:
|
||||
return [
|
||||
("action label", lambda: self.handle_action_label(edit_command, obj, position)),
|
||||
]
|
||||
|
||||
Parameters:
|
||||
edit_command: running Draft_Edit command
|
||||
obj: the edited object
|
||||
position: position of the cursor on the screen (x, y)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ __url__ = "https://www.freecadweb.org"
|
||||
# @{
|
||||
import math
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
import DraftVecUtils
|
||||
|
||||
from draftutils.translate import translate
|
||||
@@ -103,15 +104,16 @@ class DraftWireGuiTools(GuiTools):
|
||||
pts[node_idx] = v
|
||||
obj.Points = pts
|
||||
|
||||
def get_edit_point_context_menu(self, edit_command, obj, node_idx):
|
||||
return [
|
||||
("delete point", lambda: self.delete_point(obj, node_idx)),
|
||||
]
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
actions = ["delete point"]
|
||||
return actions
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
if action == "delete point":
|
||||
self.delete_point(obj, node_idx)
|
||||
edit_command.resetTrackers(obj)
|
||||
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)),
|
||||
]
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.wireTracker(obj.Shape)
|
||||
@@ -123,7 +125,39 @@ class DraftWireGuiTools(GuiTools):
|
||||
if obj.Closed:
|
||||
pointList.append(pointList[0])
|
||||
edit_command.ghost.updateFromPointlist(pointList)
|
||||
|
||||
|
||||
def add_point(self, edit_command, obj, pos):
|
||||
"""Add point to obj.
|
||||
"""
|
||||
info, newPoint = edit_command.get_specific_object_info(obj,pos)
|
||||
|
||||
if not info:
|
||||
return
|
||||
if not 'Edge' in info["Component"]:
|
||||
return
|
||||
edgeIndex = int(info["Component"][4:])
|
||||
|
||||
newPoints = []
|
||||
if hasattr(obj, "ChamferSize") and hasattr(obj, "FilletRadius"):
|
||||
# TODO: If Draft_Wire fails to calculate one of the fillets or chamfers
|
||||
# this algo fails to identify the correct edge
|
||||
if obj.ChamferSize > 0 and obj.FilletRadius > 0:
|
||||
edgeIndex = (edgeIndex + 3) / 4
|
||||
elif obj.ChamferSize > 0 or obj.FilletRadius > 0:
|
||||
edgeIndex = (edgeIndex + 1) / 2
|
||||
|
||||
for index, point in enumerate(obj.Points):
|
||||
if index == edgeIndex:
|
||||
newPoints.append(edit_command.localize_vector(obj, newPoint))
|
||||
newPoints.append(point)
|
||||
if obj.Closed and edgeIndex == len(obj.Points):
|
||||
# last segment when object is closed
|
||||
newPoints.append(edit_command.localize_vector(obj, newPoint))
|
||||
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")
|
||||
@@ -136,6 +170,9 @@ class DraftWireGuiTools(GuiTools):
|
||||
|
||||
obj.recompute()
|
||||
|
||||
def reverse_wire(self, obj):
|
||||
obj.Points = reversed(obj.Points)
|
||||
obj.recompute()
|
||||
|
||||
class DraftBSplineGuiTools(DraftWireGuiTools):
|
||||
|
||||
@@ -149,6 +186,33 @@ class DraftBSplineGuiTools(DraftWireGuiTools):
|
||||
pointList.append(pointList[0])
|
||||
edit_command.ghost.update(pointList)
|
||||
|
||||
def add_point(self, edit_command, obj, pos):
|
||||
"""Add point to obj.
|
||||
"""
|
||||
info, pt = edit_command.get_specific_object_info(obj,pos)
|
||||
if not info or (pt is None):
|
||||
return
|
||||
|
||||
pts = obj.Points
|
||||
if (obj.Closed == True):
|
||||
curve = obj.Shape.Edges[0].Curve
|
||||
else:
|
||||
curve = obj.Shape.Curve
|
||||
uNewPoint = curve.parameter(pt)
|
||||
uPoints = []
|
||||
for p in obj.Points:
|
||||
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, edit_command.localize_vector(obj, pt))
|
||||
break
|
||||
# DNC: fix: add points to last segment if curve is closed
|
||||
if obj.Closed and (uNewPoint > uPoints[-1]):
|
||||
pts.append(edit_command.localize_vector(obj, pt))
|
||||
obj.Points = pts
|
||||
|
||||
obj.recompute()
|
||||
|
||||
|
||||
class DraftRectangleGuiTools(GuiTools):
|
||||
|
||||
@@ -176,12 +240,6 @@ class DraftRectangleGuiTools(GuiTools):
|
||||
elif node_idx == 2:
|
||||
obj.Height = DraftVecUtils.project(v, App.Vector(0,1,0)).Length
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class DraftCircleGuiTools(GuiTools):
|
||||
|
||||
@@ -277,26 +335,46 @@ class DraftCircleGuiTools(GuiTools):
|
||||
obj.Radius = v.Length
|
||||
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
def get_edit_point_context_menu(self, edit_command, obj, node_idx):
|
||||
actions = None
|
||||
if obj.FirstAngle != obj.LastAngle:
|
||||
if node_idx == 0: # user is over arc start point
|
||||
actions = ["move arc"]
|
||||
return [
|
||||
("move arc", lambda: self.handle_move_arc(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 1: # user is over arc start point
|
||||
actions = ["set first angle"]
|
||||
return [
|
||||
("mset first angle", lambda: self.handle_set_first_angle(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 2: # user is over arc end point
|
||||
actions = ["set last angle"]
|
||||
return [
|
||||
("set last angle", lambda: self.handle_set_last_angle(edit_command, obj, node_idx)),
|
||||
]
|
||||
elif node_idx == 3: # user is over arc mid point
|
||||
actions = ["set radius"]
|
||||
if actions:
|
||||
return actions
|
||||
return [
|
||||
("set radius", lambda: self.handle_set_radius(edit_command, obj, node_idx)),
|
||||
]
|
||||
|
||||
def handle_move_arc(self, edit_command, obj, node_idx):
|
||||
edit_command.alt_edit_mode = 1
|
||||
edit_command.startEditing(obj, node_idx)
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
if action in ("move arc", "set radius",
|
||||
"set first angle", "set last angle"):
|
||||
edit_command.alt_edit_mode = 1
|
||||
edit_command.startEditing(edit_command.event)
|
||||
def handle_set_first_angle(self, edit_command, obj, node_idx):
|
||||
edit_command.alt_edit_mode = 1
|
||||
edit_command.startEditing(obj, node_idx)
|
||||
|
||||
def handle_set_last_angle(self, edit_command, obj, node_idx):
|
||||
edit_command.alt_edit_mode = 1
|
||||
edit_command.startEditing(obj, node_idx)
|
||||
|
||||
def handle_set_radius(self, edit_command, obj, node_idx):
|
||||
edit_command.alt_edit_mode = 1
|
||||
edit_command.startEditing(obj, node_idx)
|
||||
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
return [
|
||||
("invert arc", lambda: self.arcInvert(obj)),
|
||||
]
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.arcTracker()
|
||||
@@ -414,12 +492,6 @@ class DraftEllipseGuiTools(GuiTools):
|
||||
else:
|
||||
obj.MinorRadius = obj.MajorRadius
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class DraftPolygonGuiTools(GuiTools):
|
||||
|
||||
@@ -444,12 +516,6 @@ class DraftPolygonGuiTools(GuiTools):
|
||||
obj.Radius = v.Length
|
||||
obj.recompute()
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class DraftDimensionGuiTools(GuiTools):
|
||||
|
||||
@@ -475,12 +541,6 @@ class DraftDimensionGuiTools(GuiTools):
|
||||
elif node_idx == 3:
|
||||
obj.ViewObject.TextPosition = v
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class DraftBezCurveGuiTools(GuiTools):
|
||||
|
||||
@@ -521,29 +581,18 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
obj.Points = pts
|
||||
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
if utils.get_type(obj) in ["Line", "Wire", "BSpline"]:
|
||||
actions = ["delete point"]
|
||||
elif utils.get_type(obj) in ["BezCurve"]:
|
||||
actions = ["make sharp", "make tangent",
|
||||
"make symmetric", "delete point"]
|
||||
return actions
|
||||
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)),
|
||||
]
|
||||
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
if action == "delete point":
|
||||
self.delete_point(obj, node_idx)
|
||||
edit_command.resetTrackers(obj)
|
||||
# Bezier curve menu
|
||||
elif action in ["make sharp", "make tangent", "make symmetric"]:
|
||||
if action == "make sharp":
|
||||
self.smoothBezPoint(obj, node_idx, 'Sharp')
|
||||
elif action == "make tangent":
|
||||
self.smoothBezPoint(obj, node_idx, 'Tangent')
|
||||
elif action == "make symmetric":
|
||||
self.smoothBezPoint(obj, node_idx, 'Symmetric')
|
||||
edit_command.resetTrackers(obj)
|
||||
|
||||
def get_edit_obj_context_menu(self, edit_command, obj, position):
|
||||
return [
|
||||
("add point", lambda: self.add_point(edit_command, obj, position)),
|
||||
]
|
||||
|
||||
def init_preview_object(self, obj):
|
||||
return trackers.bezcurveTracker()
|
||||
@@ -714,4 +763,46 @@ class DraftBezCurveGuiTools(GuiTools):
|
||||
obj.Points = pts
|
||||
obj.Continuity = newcont
|
||||
|
||||
def add_point(self, edit_command, obj, pos):
|
||||
"""Add point to obj and reset trackers.
|
||||
"""
|
||||
info, pt = edit_command.get_specific_object_info(obj,pos)
|
||||
if not info or (pt is None):
|
||||
return
|
||||
|
||||
import Part
|
||||
|
||||
pts = obj.Points
|
||||
if not info['Component'].startswith('Edge'):
|
||||
return # clicked control point
|
||||
edgeindex = int(info['Component'].lstrip('Edge')) - 1
|
||||
wire = obj.Shape.Wires[0]
|
||||
bz = wire.Edges[edgeindex].Curve
|
||||
param = bz.parameter(pt)
|
||||
seg1 = wire.Edges[edgeindex].copy().Curve
|
||||
seg2 = wire.Edges[edgeindex].copy().Curve
|
||||
seg1.segment(seg1.FirstParameter, param)
|
||||
seg2.segment(param, seg2.LastParameter)
|
||||
if edgeindex == len(wire.Edges):
|
||||
# we hit the last segment, we need to fix the degree
|
||||
degree=wire.Edges[0].Curve.Degree
|
||||
seg1.increase(degree)
|
||||
seg2.increase(degree)
|
||||
edges = wire.Edges[0:edgeindex] + [Part.Edge(seg1),Part.Edge(seg2)] \
|
||||
+ wire.Edges[edgeindex + 1:]
|
||||
pts = edges[0].Curve.getPoles()[0:1]
|
||||
for edge in edges:
|
||||
pts.extend(edge.Curve.getPoles()[1:])
|
||||
if obj.Closed:
|
||||
pts.pop()
|
||||
c = obj.Continuity
|
||||
# assume we have a tangent continuity for an arbitrarily split
|
||||
# segment, unless it's linear
|
||||
cont = 1 if (obj.Degree >= 2) else 0
|
||||
obj.Continuity = c[0:edgeindex] + [cont] + c[edgeindex:]
|
||||
|
||||
obj.Points = pts
|
||||
|
||||
obj.recompute()
|
||||
|
||||
## @}
|
||||
|
||||
@@ -57,12 +57,6 @@ class PartLineGuiTools(GuiTools):
|
||||
obj.Y2 = v.y
|
||||
obj.Z2 = v.z
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class PartBoxGuiTools(GuiTools):
|
||||
|
||||
@@ -90,12 +84,6 @@ class PartBoxGuiTools(GuiTools):
|
||||
_vector = DraftVecUtils.project(v, App.Vector(0, 0, 1))
|
||||
obj.Height = _vector.Length
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class PartCylinderGuiTools(GuiTools):
|
||||
|
||||
@@ -119,12 +107,6 @@ class PartCylinderGuiTools(GuiTools):
|
||||
_vector = DraftVecUtils.project(v, App.Vector(0, 0, 1))
|
||||
obj.Height = _vector.Length
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class PartConeGuiTools(GuiTools):
|
||||
|
||||
@@ -151,12 +133,6 @@ class PartConeGuiTools(GuiTools):
|
||||
_vector = DraftVecUtils.project(v, App.Vector(0, 0, 1))
|
||||
obj.Height = _vector.Length
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
class PartSphereGuiTools(GuiTools):
|
||||
|
||||
@@ -176,10 +152,4 @@ class PartSphereGuiTools(GuiTools):
|
||||
if v.Length > 0.0:
|
||||
obj.Radius = v.Length # TODO: Perhaps better to project on the face?
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
## @}
|
||||
|
||||
@@ -75,11 +75,4 @@ class SketcherSketchObjectGuiTools(GuiTools):
|
||||
obj.movePoint(0, 2, v)
|
||||
obj.recompute()
|
||||
|
||||
def get_edit_point_context_menu(self, obj, node_idx):
|
||||
pass
|
||||
|
||||
def evaluate_context_menu_action(self, edit_command, obj, node_idx, action):
|
||||
pass
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
Reference in New Issue
Block a user