diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index e9046a8fa2..afd5c98aa5 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -309,6 +309,7 @@ class PolylineDecorator: instructions = None snap_info = None tool_state = None + relating_type = None @classmethod def install(cls, context): @@ -395,30 +396,116 @@ class PolylineDecorator: shader.uniform_float("color", color) batch.draw(shader) - def draw_product_preview(self, context): - def transparent_color(color, alpha=0.1): - color = [i for i in color] - color[3] = alpha - return color + def get_wall_preview_data(cls, context, relating_type): + def create_bmesh_from_vertices(vertices): + bm = bmesh.new() - self.addon_prefs = tool.Blender.get_addon_preferences() - self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR") - self.line_shader.bind() # required to be able to change uniforms of the shader - self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height)) - self.shader = gpu.shader.from_builtin("UNIFORM_COLOR") - self.line_shader.uniform_float("lineWidth", 2.0) - decorator_color = self.addon_prefs.decorator_color_special + new_verts = [bm.verts.new(v) for v in polyline_vertices] + if is_closed: + new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)] + new_edges.append( + bm.edges.new((new_verts[-1], new_verts[0])) + ) # Add an edge between the last an first point to make it closed. + else: + new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)] + + bm.verts.index_update() + bm.edges.index_update() + return bm + + # Get properties from object type + layers = tool.Model.get_material_layer_parameters(relating_type) + if not layers["thickness"]: + return + thickness = layers["thickness"] + model_props = context.scene.BIMModelProperties + direction_sense = model_props.direction_sense + direction = 1 + if direction_sense == "NEGATIVE": + direction = -1 + offset_type = model_props.offset_type + offset = 0 + if offset_type == "CENTER": + offset = -thickness / 2 + elif offset_type == "INTERIOR": + offset = -thickness + + unit_system = tool.Drawing.get_unit_system() + factor = 1 + if unit_system == "IMPERIAL": + factor = 3.048 + if unit_system == "METRIC": + unit_length = context.scene.unit_settings.length_unit + if unit_length == "MILLIMETERS": + factor = 1000 + + # For the model properties, the offset value should just be converted + # However, for the wall preview logic that follows, offset and thickness must change direction + model_props.offset = offset * factor + thickness *= direction + offset *= direction + + height = float(model_props.extrusion_depth) + rl = float(model_props.rl1) + x_angle = float(model_props.x_angle) + angle_distortion = height * math.tan(x_angle) + + wall_preview_data = {} + wall_preview_data["verts"] = [] + + # Verts + polyline_vertices = [] polyline_data = context.scene.BIMPolylineProperties.insertion_polyline polyline_points = polyline_data[0].polyline_points if polyline_data else [] - prop = context.scene.BIMPolylineProperties.product_preview + if len(polyline_points) < 2: + wall_preview_data = [] + return + for point in polyline_points: + polyline_vertices.append(Vector((point.x, point.y, point.z))) + is_closed = False + if ( + polyline_vertices[0].x == polyline_vertices[-1].x + and polyline_vertices[0].y == polyline_vertices[-1].y + and polyline_vertices[0].z == polyline_vertices[-1].z + ): + is_closed = True + polyline_vertices.pop(-1) # Remove the last point. The edges are going to inform that the shape is closed. + + bm_base = create_bmesh_from_vertices(polyline_vertices) + base_vertices = tool.Cad.offset_edges(bm_base, offset) + offset_base_verts = tool.Cad.offset_edges(bm_base, thickness + offset) + top_vertices = tool.Cad.offset_edges(bm_base, angle_distortion + offset) + offset_top_verts = tool.Cad.offset_edges(bm_base, angle_distortion + thickness + offset) + if is_closed: + base_vertices.append(base_vertices[0]) + offset_base_verts.append(offset_base_verts[0]) + top_vertices.append(top_vertices[0]) + offset_top_verts.append(offset_top_verts[0]) + + if offset_base_verts is not None: + for v in base_vertices: + wall_preview_data["verts"].append((v.co.x, v.co.y, v.co.z + rl)) + + for v in offset_base_verts[::-1]: + wall_preview_data["verts"].append((v.co.x, v.co.y, v.co.z + rl)) + + for v in top_vertices: + wall_preview_data["verts"].append((v.co.x, v.co.y, v.co.z + rl + height)) + + for v in offset_top_verts[::-1]: + wall_preview_data["verts"].append((v.co.x, v.co.y, v.co.z + rl + height)) + + bm_base.free() + + # Edges and Tris points = [] side_edges_1 = [] side_edges_2 = [] base_edges = [] - for i in range(len(prop)): - points.append(Vector((prop[i].x, prop[i].y, prop[i].z))) + for i in range(len(wall_preview_data["verts"])): + points.append(Vector(wall_preview_data["verts"][i])) n = len(points) // 2 bottom_side_1 = [[i, (i + 1) % (n)] for i in range((n - 1) // 2)] @@ -438,8 +525,8 @@ class PolylineDecorator: loops = [side_edges_1, side_edges_2, base_edges] - all_edges = [] - all_tris = [] + wall_preview_data["edges"] = [] + wall_preview_data["tris"] = [] for i, group in enumerate(loops): bm = bmesh.new() @@ -457,13 +544,42 @@ class PolylineDecorator: bm.edges.index_update() edges = [[v.index for v in e.verts] for e in bm.edges] tris = [[l.vert.index for l in loop] for loop in bm.calc_loop_triangles()] - all_edges.extend(edges) - all_tris.extend(tris) + wall_preview_data["edges"].extend(edges) + wall_preview_data["tris"].extend(tris) - all_edges = list(set(tuple(e) for e in all_edges)) - all_tris = list(set(tuple(t) for t in all_tris)) - self.draw_batch("LINES", points, decorator_color, all_edges) - self.draw_batch("TRIS", points, transparent_color(decorator_color), all_tris) + wall_preview_data["edges"] = list(set(tuple(e) for e in wall_preview_data["edges"])) + wall_preview_data["tris"] = list(set(tuple(t) for t in wall_preview_data["tris"])) + + return wall_preview_data + + def draw_product_preview(self, context): + def transparent_color(color, alpha=0.1): + color = [i for i in color] + color[3] = alpha + return color + + self.addon_prefs = tool.Blender.get_addon_preferences() + self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR") + self.line_shader.bind() # required to be able to change uniforms of the shader + self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height)) + self.shader = gpu.shader.from_builtin("UNIFORM_COLOR") + self.line_shader.uniform_float("lineWidth", 2.0) + decorator_color = self.addon_prefs.decorator_color_special + polyline_data = context.scene.BIMPolylineProperties.insertion_polyline + polyline_points = polyline_data[0].polyline_points if polyline_data else [] + + snap_prop = context.scene.BIMPolylineProperties.snap_mouse_point[0] + mouse_point = Vector((snap_prop.x, snap_prop.y, snap_prop.z)) + self.relating_type = None + props = context.scene.BIMModelProperties + relating_type_id = props.relating_type_id + if relating_type_id: + self.relating_type = tool.Ifc.get().by_id(int(relating_type_id)) + + wall_preview_data = self.get_wall_preview_data(context, self.relating_type) + if wall_preview_data: + self.draw_batch("LINES", wall_preview_data["verts"], decorator_color, wall_preview_data["edges"]) + self.draw_batch("TRIS", wall_preview_data["verts"], transparent_color(decorator_color), wall_preview_data["tris"]) def draw_input_ui(self, context): texts = { diff --git a/src/bonsai/bonsai/bim/module/model/product.py b/src/bonsai/bonsai/bim/module/model/product.py index 17a6b9a753..24cf8bad80 100644 --- a/src/bonsai/bonsai/bim/module/model/product.py +++ b/src/bonsai/bonsai/bim/module/model/product.py @@ -180,7 +180,6 @@ class AddOccurrence(bpy.types.Operator, PolylineOperator): if not self.tool_state.is_input_on and event.value == "RELEASE" and event.type in {"RIGHTMOUSE"}: context.workspace.status_text_set(text=None) PolylineDecorator.uninstall() - context.scene.BIMPolylineProperties.product_preview.clear() tool.Polyline.clear_polyline() tool.Blender.update_viewport() return {"FINISHED"} @@ -190,7 +189,6 @@ class AddOccurrence(bpy.types.Operator, PolylineOperator): cancel = self.handle_cancelation(context, event) if cancel is not None: - context.scene.BIMPolylineProperties.product_preview.clear() return cancel return {"RUNNING_MODAL"} diff --git a/src/bonsai/bonsai/bim/module/model/prop.py b/src/bonsai/bonsai/bim/module/model/prop.py index 37fb17cc06..7800638769 100644 --- a/src/bonsai/bonsai/bim/module/model/prop.py +++ b/src/bonsai/bonsai/bim/module/model/prop.py @@ -773,5 +773,4 @@ class BIMPolylineProperties(PropertyGroup): snap_mouse_point: bpy.props.CollectionProperty(type=SnapMousePoint) snap_mouse_ref: bpy.props.CollectionProperty(type=SnapMousePoint) insertion_polyline: bpy.props.CollectionProperty(type=Polyline) - product_preview: bpy.props.CollectionProperty(type=PolylinePoint) measurement_polyline: bpy.props.CollectionProperty(type=Polyline) diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 8df0c66f80..8663249fd0 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -355,7 +355,6 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): context.scene.BIMModelProperties.direction_sense = ( "NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE" ) - tool.Polyline.create_wall_preview_vertices(context, self.relating_type) if event.value == "RELEASE" and event.type == "O": offset_type = context.scene.BIMModelProperties.offset_type @@ -363,7 +362,6 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): index = items.index(offset_type) size = len(items) context.scene.BIMModelProperties.offset_type = items[((index + 1) % size)] - tool.Polyline.create_wall_preview_vertices(context, self.relating_type) props = bpy.context.scene.BIMModelProperties wall_config = f"""Direction: {props.direction_sense} @@ -386,7 +384,6 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): self.create_walls_from_polyline(context) context.workspace.status_text_set(text=None) PolylineDecorator.uninstall() - context.scene.BIMPolylineProperties.product_preview.clear() tool.Polyline.clear_polyline() tool.Blender.update_viewport() return {"FINISHED"} @@ -395,12 +392,8 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): self.handle_inserting_polyline(context, event) - if event.type in {"C", "LEFTMOUSE", "RIGHTMOUSE", "RET", "NUMPAD_ENTER", "BACK_SPACE"}: - tool.Polyline.create_wall_preview_vertices(context, self.relating_type) - cancel = self.handle_cancelation(context, event) if cancel is not None: - context.scene.BIMPolylineProperties.product_preview.clear() return cancel return {"RUNNING_MODAL"} @@ -1478,7 +1471,6 @@ class DumbWallJoiner: x_axis = bbn - bsf y_axis = tsf - bsf else: - print(">>>>B") if layers1["direction_sense"] == "POSITIVE": pt = bbn.to_2d().to_3d() x_axis = bsf - bbn diff --git a/src/bonsai/bonsai/tool/polyline.py b/src/bonsai/bonsai/tool/polyline.py index 24fffa3017..4c1f182564 100644 --- a/src/bonsai/bonsai/tool/polyline.py +++ b/src/bonsai/bonsai/tool/polyline.py @@ -303,123 +303,6 @@ class Polyline(bonsai.core.tool.Polyline): return - @classmethod - def create_wall_preview_vertices(cls, context, relating_type): - def create_bmesh_from_vertices(vertices): - bm = bmesh.new() - - new_verts = [bm.verts.new(v) for v in polyline_vertices] - if is_closed: - new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)] - new_edges.append( - bm.edges.new((new_verts[-1], new_verts[0])) - ) # Add an edge between the last an first point to make it closed. - else: - new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)] - - bm.verts.index_update() - bm.edges.index_update() - return bm - - # Get properties from object type - layers = tool.Model.get_material_layer_parameters(relating_type) - if not layers["thickness"]: - return - thickness = layers["thickness"] - model_props = context.scene.BIMModelProperties - direction_sense = model_props.direction_sense - direction = 1 - if direction_sense == "NEGATIVE": - direction = -1 - offset_type = model_props.offset_type - offset = 0 - if offset_type == "CENTER": - offset = -thickness / 2 - elif offset_type == "INTERIOR": - offset = -thickness - - unit_system = tool.Drawing.get_unit_system() - factor = 1 - if unit_system == "IMPERIAL": - factor = 3.048 - if unit_system == "METRIC": - unit_length = bpy.context.scene.unit_settings.length_unit - if unit_length == "MILLIMETERS": - factor = 1000 - - # For the model properties, the offset value should just be converted - # However, for the wall preview logic that follows, offset and thickness must change direction - model_props.offset = offset * factor - thickness *= direction - offset *= direction - - height = float(model_props.extrusion_depth) - rl = float(model_props.rl1) - x_angle = float(model_props.x_angle) - angle_distortion = height * tan(x_angle) - - polyline_vertices = [] - polyline_data = context.scene.BIMPolylineProperties.insertion_polyline - polyline_points = polyline_data[0].polyline_points if polyline_data else [] - if len(polyline_points) < 2: - context.scene.BIMPolylineProperties.product_preview.clear() - return - for point in polyline_points: - polyline_vertices.append(Vector((point.x, point.y, point.z))) - - is_closed = False - if ( - polyline_vertices[0].x == polyline_vertices[-1].x - and polyline_vertices[0].y == polyline_vertices[-1].y - and polyline_vertices[0].z == polyline_vertices[-1].z - ): - is_closed = True - polyline_vertices.pop(-1) # Remove the last point. The edges are going to inform that the shape is closed. - - bm_base = create_bmesh_from_vertices(polyline_vertices) - base_vertices = tool.Cad.offset_edges(bm_base, offset) - offset_base_verts = tool.Cad.offset_edges(bm_base, thickness + offset) - top_vertices = tool.Cad.offset_edges(bm_base, angle_distortion + offset) - offset_top_verts = tool.Cad.offset_edges(bm_base, angle_distortion + thickness + offset) - - if is_closed: - base_vertices.append(base_vertices[0]) - offset_base_verts.append(offset_base_verts[0]) - top_vertices.append(top_vertices[0]) - offset_top_verts.append(offset_top_verts[0]) - - if offset_base_verts is not None: - context.scene.BIMPolylineProperties.product_preview.clear() - for v in base_vertices: - new_v = Vector((v.co.x, v.co.y, v.co.z)) - prop = context.scene.BIMPolylineProperties.product_preview.add() - prop.x = new_v.x - prop.y = new_v.y - prop.z = new_v.z + rl - - for v in offset_base_verts[::-1]: - new_v = Vector((v.co.x, v.co.y, v.co.z)) - prop = context.scene.BIMPolylineProperties.product_preview.add() - prop.x = new_v.x - prop.y = new_v.y - prop.z = new_v.z + rl - - for v in top_vertices: - # new_v = v #+ scaled_direction - new_v = Vector((v.co.x, v.co.y, v.co.z)) - prop = context.scene.BIMPolylineProperties.product_preview.add() - prop.x = new_v.x - prop.y = new_v.y - prop.z = new_v.z + rl + height - - for v in offset_top_verts[::-1]: - new_v = Vector((v.co.x, v.co.y, v.co.z)) # + scaled_direction - prop = context.scene.BIMPolylineProperties.product_preview.add() - prop.x = new_v.x - prop.y = new_v.y - prop.z = new_v.z + rl + height - - bm_base.free() @classmethod def validate_input(cls, input_number, input_type):