diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 67e4fc014e..8c9330465b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -117,6 +117,7 @@ classes = ( space.ToggleHideSpaces, mep.FitFlowSegments, mep.RegenerateDistributionElement, + prop.SnapVertex, prop.BIMModelProperties, prop.BIMArrayProperties, prop.BIMStairProperties, diff --git a/src/blenderbim/blenderbim/bim/module/model/decorator.py b/src/blenderbim/blenderbim/bim/module/model/decorator.py index 2bc9ceb608..f30935c478 100644 --- a/src/blenderbim/blenderbim/bim/module/model/decorator.py +++ b/src/blenderbim/blenderbim/bim/module/model/decorator.py @@ -291,3 +291,55 @@ class ProfileDecorator: listEdg.append((Vertices - 1, 0)) return points, listEdg + + +class WallPolylineDecorator: + installed = False + + + @classmethod + def install(cls, context): + if cls.installed: + cls.uninstall() + handler = cls() + cls.installed = SpaceView3D.draw_handler_add(handler, (context,), "WINDOW", "POST_VIEW") + + @classmethod + def uninstall(cls): + try: + SpaceView3D.draw_handler_remove(cls.installed, "WINDOW") + except ValueError: + pass + cls.installed = None + + def draw_batch(self, shader_type, content_pos, color, indices=None): + shader = self.line_shader if shader_type == "LINES" else self.shader + batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices) + shader.uniform_float("color", color) + batch.draw(shader) + + def __call__(self, context): + + self.addon_prefs = tool.Blender.get_addon_preferences() + decorator_color = self.addon_prefs.decorations_colour + decorator_color_special = self.addon_prefs.decorator_color_special + decorator_color_selected = self.addon_prefs.decorator_color_selected + decorator_color_error = self.addon_prefs.decorator_color_error + + + gpu.state.blend_set("ALPHA") + self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR") + self.line_shader.bind() # required to be able to change uniforms of the shader + # POLYLINE_UNIFORM_COLOR specific uniforms + self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height)) + + # general shader + self.shader = gpu.shader.from_builtin("UNIFORM_COLOR") + gpu.state.point_size_set(10) + + snap_prop = context.scene.BIMModelProperties.snap_vertex[0] + points = [Vector((snap_prop.x, snap_prop.y, snap_prop.z))] + if snap_prop.snap_type != "Face": + self.draw_batch("POINTS", points, decorator_color_selected) + else: + self.draw_batch("POINTS", points, decorator_color_special) diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index c1f011bb18..2318c529c5 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -99,6 +99,13 @@ def is_object_array_applicable(self, obj): return ifcopenshell.util.element.get_pset(element, "BBIM_Array") +class SnapVertex(PropertyGroup): + x: bpy.props.FloatProperty(name="X") + y: bpy.props.FloatProperty(name="Y") + z: bpy.props.FloatProperty(name="Z") + snap_type: bpy.props.StringProperty(name="Snap Type") + + class BIMModelProperties(PropertyGroup): ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class) relating_type_id: bpy.props.EnumProperty( @@ -190,6 +197,7 @@ class BIMModelProperties(PropertyGroup): type_predefined_type: bpy.props.EnumProperty(items=get_type_predefined_type, name="Predefined Type", default=None) type_name: bpy.props.StringProperty(name="Name", default="TYPEX") boundary_class: bpy.props.EnumProperty(items=get_boundary_class, name="Boundary Class") + snap_vertex: bpy.props.CollectionProperty(type=SnapVertex) class BIMArrayProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index c1e3a03d0e..bd37eeb63e 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -41,6 +41,7 @@ from mathutils import Vector, Matrix from mathutils.bvhtree import BVHTree from bpy_extras import view3d_utils from blenderbim.bim.module.model.opening import FilledOpeningGenerator +from blenderbim.bim.module.model.decorator import WallPolylineDecorator from typing import Optional @@ -321,6 +322,8 @@ class DrawPolylineWall(bpy.types.Operator): return ray_origin, ray_target, ray_direction + + def get_object_ray_data(obj_matrix): ray_origin, ray_target, ray_direction = get_viewport_ray_data() matrix_inv = obj_matrix.inverted() @@ -424,7 +427,8 @@ class DrawPolylineWall(bpy.types.Operator): edges_center = [] for v1, v2 in zip(vertices, vertices[1:] + [vertices[0]]): - edges_center.append((v1-v2) / 2) + middle_dist = (v2-v1) / 2 + edges_center.append(v1 + middle_dist) snap_points.update({tuple(vertex): "Vertices" for vertex in vertices}) snap_points.update({tuple(edge_center): "Edge Center" for edge_center in edges_center}) @@ -466,12 +470,26 @@ class DrawPolylineWall(bpy.types.Operator): snap_points = get_snap_points(obj, face_index) snap_point = select_snap_point(snap_points, hit, snap_threshold) + try: + snap_vextex = context.scene.BIMModelProperties.snap_vertex[0] + except: + snap_vextex = context.scene.BIMModelProperties.snap_vertex.add() + if snap_point: + snap_vextex.x = snap_point[0][0] + snap_vextex.y = snap_point[0][1] + snap_vextex.z = snap_point[0][2] + snap_vextex.snap_type = snap_point[1] scene.cursor.location = snap_point[0] else: + snap_vextex.x = hit[0] + snap_vextex.y = hit[1] + snap_vextex.z = hit[2] + snap_vextex.snap_type = "Face" scene.cursor.location = hit else: + WallPolylineDecorator.uninstall() bpy.ops.object.select_all(action="DESELECT") scene.cursor.location = intersection @@ -481,6 +499,7 @@ class DrawPolylineWall(bpy.types.Operator): return {'PASS_THROUGH'} elif event.type == 'MOUSEMOVE': start_time = time() + WallPolylineDecorator.install(context) self.main(context, event) operator_time = time() - start_time print(f"main function was finished in {operator_time:.2f} seconds") @@ -492,6 +511,7 @@ class DrawPolylineWall(bpy.types.Operator): self.ray_cast_type = 'BVH' print("BVH selected.") elif event.type in {'RIGHTMOUSE', 'ESC'}: + WallPolylineDecorator.uninstall() print("CANCELLLL") return {'CANCELLED'}