diff --git a/src/blenderbim/blenderbim/bim/module/cad/__init__.py b/src/blenderbim/blenderbim/bim/module/cad/__init__.py index 4afec2eb96..8285a64ebc 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/cad/__init__.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import bpy -from . import operator, workspace +from . import operator, prop, workspace classes = ( operator.AddIfcArcIndexFillet, @@ -28,6 +28,7 @@ classes = ( operator.CadMitre, operator.CadOffset, operator.CadTrimExtend, + prop.BIMCadProperties, workspace.CadHotkey, ) @@ -35,8 +36,10 @@ classes = ( def register(): if not bpy.app.background: bpy.utils.register_tool(workspace.CadTool, after={"builtin.transform"}, separator=True, group=True) + bpy.types.Scene.BIMCadProperties = bpy.props.PointerProperty(type=prop.BIMCadProperties) def unregister(): if not bpy.app.background: bpy.utils.unregister_tool(workspace.CadTool) + del bpy.types.Scene.BIMCadProperties diff --git a/src/blenderbim/blenderbim/bim/module/cad/operator.py b/src/blenderbim/blenderbim/bim/module/cad/operator.py index 2991cf66c1..2b45084dbb 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/operator.py +++ b/src/blenderbim/blenderbim/bim/module/cad/operator.py @@ -539,8 +539,41 @@ class AddIfcCircle(bpy.types.Operator): return bool(obj) and obj.type == "MESH" def execute(self, context): - obj = context.active_object + if self.has_selected_existing_circle(context): + self.change_radius(context) + else: + self.create_circle(context) + return {"FINISHED"} + def has_selected_existing_circle(self, context): + obj = context.active_object + bm = bmesh.from_edit_mesh(obj.data) + verts = [v for v in bm.verts if v.select and not v.hide] + if len(verts) != 2: + return False + groups = [] + for i, group in enumerate(obj.vertex_groups): + if "IFCCIRCLE" in group.name: + groups.append(i) + bm.verts.layers.deform.verify() + deform_layer = bm.verts.layers.deform.active + for group in groups: + if group in verts[0][deform_layer] and group in verts[1][deform_layer]: + return True + + def change_radius(self, context): + obj = context.active_object + bm = bmesh.from_edit_mesh(obj.data) + verts = [v for v in bm.verts if v.select and not v.hide] + center = verts[0].co.lerp(verts[1].co, 0.5) + verts[0].co = center + ((verts[0].co - center).normalized() * self.radius) + verts[1].co = center + ((verts[1].co - center).normalized() * self.radius) + bm.verts.index_update() + bm.edges.index_update() + bmesh.update_edit_mesh(obj.data) + + def create_circle(self, context): + obj = context.active_object bpy.ops.object.mode_set(mode="OBJECT") # The last group may be the result of a prior run of this operator. # I tried looping through all groups but Blender group indices seem to behave unpredictably. @@ -570,7 +603,6 @@ class AddIfcCircle(bpy.types.Operator): bm.verts.index_update() bm.edges.index_update() bmesh.update_edit_mesh(obj.data) - return {"FINISHED"} class AddIfcArcIndexFillet(bpy.types.Operator): diff --git a/src/blenderbim/blenderbim/bim/module/cad/prop.py b/src/blenderbim/blenderbim/bim/module/cad/prop.py new file mode 100644 index 0000000000..4caab0629f --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/cad/prop.py @@ -0,0 +1,28 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2022 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +from blenderbim.bim.module.model.data import AuthoringData +from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound +from bpy.types import PropertyGroup + + +class BIMCadProperties(PropertyGroup): + resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1) + radius: bpy.props.FloatProperty(name="Radius", default=0.1) + distance: bpy.props.FloatProperty(name="Distance", default=0.1) diff --git a/src/blenderbim/blenderbim/bim/module/cad/workspace.py b/src/blenderbim/blenderbim/bim/module/cad/workspace.py index 18b16be1a8..61d8cc06e6 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/cad/workspace.py @@ -123,36 +123,35 @@ class CadHotkey(bpy.types.Operator): bl_label = "CAD Hotkey" bl_options = {"REGISTER", "UNDO"} hotkey: bpy.props.StringProperty() - resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1) - radius: bpy.props.FloatProperty(name="Radius", default=0.1) - distance: bpy.props.FloatProperty(name="Distance", default=0.1) def execute(self, context): + self.props = context.scene.BIMCadProperties getattr(self, f"hotkey_{self.hotkey}")() return {"FINISHED"} def draw(self, context): + props = context.scene.BIMCadProperties if self.hotkey == "S_C": if self.is_profile(): row = self.layout.row() - row.prop(self, "radius") + row.prop(props, "radius") elif self.hotkey == "S_F": if not self.is_profile(): row = self.layout.row() - row.prop(self, "resolution") + row.prop(props, "resolution") row = self.layout.row() - row.prop(self, "radius") + row.prop(props, "radius") elif self.hotkey == "S_O": row = self.layout.row() - row.prop(self, "distance") + row.prop(props, "distance") elif self.hotkey == "S_V": if not self.is_profile(): row = self.layout.row() - row.prop(self, "resolution") + row.prop(props, "resolution") def hotkey_S_C(self): if self.is_profile(): - bpy.ops.bim.add_ifccircle(radius=self.radius) + bpy.ops.bim.add_ifccircle(radius=self.props.radius) else: bpy.ops.bim.cad_arc_from_2_points() @@ -161,12 +160,12 @@ class CadHotkey(bpy.types.Operator): def hotkey_S_F(self): if self.is_profile(): - bpy.ops.bim.add_ifcarcindex_fillet(radius=self.radius) + bpy.ops.bim.add_ifcarcindex_fillet(radius=self.props.radius) else: - bpy.ops.bim.cad_fillet(resolution=self.resolution, radius=self.radius) + bpy.ops.bim.cad_fillet(resolution=self.props.resolution, radius=self.props.radius) def hotkey_S_O(self): - bpy.ops.bim.cad_offset(distance=self.distance) + bpy.ops.bim.cad_offset(distance=self.props.distance) def hotkey_S_Q(self): bpy.ops.bim.edit_extrusion_profile()