diff --git a/src/blenderbim/blenderbim/bim/module/cad/__init__.py b/src/blenderbim/blenderbim/bim/module/cad/__init__.py index 44d7cf1ce5..2512db37fa 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/cad/__init__.py @@ -21,6 +21,7 @@ from . import operator, workspace classes = ( operator.CadTrimExtend, + operator.CadMitre, workspace.CadHotkey, ) diff --git a/src/blenderbim/blenderbim/bim/module/cad/operator.py b/src/blenderbim/blenderbim/bim/module/cad/operator.py index d4ff417384..60622a74d4 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/operator.py +++ b/src/blenderbim/blenderbim/bim/module/cad/operator.py @@ -28,11 +28,8 @@ messages = { class CadTrimExtend(bpy.types.Operator): - """Weld intersecting edges, project converging edges towards their intersection""" - bl_idname = "bim.cad_trim_extend" bl_label = "CAD Trim / Extend" - join_type: bpy.props.StringProperty() @classmethod def poll(cls, context): @@ -61,7 +58,53 @@ class CadTrimExtend(bpy.types.Operator): edges = [e for e in bm.edges if e.select and not e.hide] if len(edges) == 2: - message = tool.Cad.do_vtx_if_appropriate(bm, edges) + message = tool.Cad.do_vtx_if_appropriate(bm, edges, mode="T") + if isinstance(message, set): + msg = messages.get(message.pop()) + return self.cancel_message(msg) + bm = message + else: + return self.cancel_message("select two edges!") + + bm.verts.index_update() + bm.edges.index_update() + bmesh.update_edit_mesh(me, loop_triangles=True) + + return {"FINISHED"} + + +class CadMitre(bpy.types.Operator): + bl_idname = "bim.cad_mitre" + bl_label = "CAD Trim / Extend" + + @classmethod + def poll(cls, context): + obj = context.active_object + return bool(obj) and obj.type == "MESH" + + def cancel_message(self, msg): + print(msg) + self.report({"WARNING"}, msg) + return {"CANCELLED"} + + def execute(self, context): + # final attempt to enter unfragmented bm/mesh + # ghastly, but what can I do? it works with these + # fails without. + bpy.ops.object.mode_set(mode="OBJECT") + bpy.ops.object.mode_set(mode="EDIT") + + obj = context.active_object + me = obj.data + + bm = bmesh.from_edit_mesh(me) + bm.verts.ensure_lookup_table() + bm.edges.ensure_lookup_table() + + edges = [e for e in bm.edges if e.select and not e.hide] + + if len(edges) == 2: + message = tool.Cad.do_vtx_if_appropriate(bm, edges, mode="V") if isinstance(message, set): msg = messages.get(message.pop()) return self.cancel_message(msg) diff --git a/src/blenderbim/blenderbim/bim/module/cad/workspace.py b/src/blenderbim/blenderbim/bim/module/cad/workspace.py index 33908b3e60..17b6dd36d5 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/cad/workspace.py @@ -36,6 +36,7 @@ class CadTool(WorkSpaceTool): # https://docs.blender.org/api/current/bpy.types.KeyMapItems.html bl_keymap = ( ("bim.cad_hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}), + ("bim.cad_hotkey", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_T")]}), ) def draw_settings(context, layout, tool): @@ -61,4 +62,7 @@ class CadHotkey(bpy.types.Operator): return {"FINISHED"} def hotkey_S_E(self): - bpy.ops.bim.cad_trim_extend(join_type="T") + bpy.ops.bim.cad_trim_extend() + + def hotkey_S_T(self): + bpy.ops.bim.cad_mitre() diff --git a/src/blenderbim/blenderbim/tool/cad.py b/src/blenderbim/blenderbim/tool/cad.py index 008cc803a4..75d8c445dd 100644 --- a/src/blenderbim/blenderbim/tool/cad.py +++ b/src/blenderbim/blenderbim/tool/cad.py @@ -24,6 +24,7 @@ # Changes include: # # - Instead of AutoVTX, user explicitly chooses V, T, or X mode +# - Instead of adding edges, existing edges are extended import sys @@ -261,12 +262,18 @@ class Cad: bm.edges.index_update() return bm + @classmethod + def perform_v(cls, bm, pt, target, edge, pts, vertex_indices): + bm = cls.perform_t(bm, pt, target, edge, pts, vertex_indices) + bm = cls.perform_t(bm, pt, edge, target, pts, vertex_indices) + return bm + @classmethod def prioritise_active_edge(cls, bm, edges): return [edges[0], edges[1]] if bm.select_history.active == edges[0] else [edges[1], edges[0]] @classmethod - def do_vtx_if_appropriate(cls, bm, edges): + def do_vtx_if_appropriate(cls, bm, edges, mode): vertex_indices = cls.get_vert_indices_from_bmedges(edges) # test 1, are there shared vers? if so return non-viable @@ -285,6 +292,9 @@ class Cad: return {"NON_PLANAR_EDGES"} edges = cls.prioritise_active_edge(bm, edges) - # point must lie on an edge or the virtual extention of an edge - bm = cls.perform_t(bm, point, edges[0], edges[1], (p1, p2, p3, p4), vertex_indices) + # point must lie on an edge or the virtual extension of an edge + if mode == "T": + bm = cls.perform_t(bm, point, edges[0], edges[1], (p1, p2, p3, p4), vertex_indices) + elif mode == "V": + bm = cls.perform_v(bm, point, edges[0], edges[1], (p1, p2, p3, p4), vertex_indices) return bm