Refactor wall preview for polyline tool.

This commit is contained in:
Bruno Perdigão
2024-10-19 10:25:03 -03:00
parent dcd6acb1f4
commit 217ada0993
5 changed files with 139 additions and 151 deletions
+139 -23
View File
@@ -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 = {
@@ -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"}
@@ -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)
@@ -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
-117
View File
@@ -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):