Skip to content

Commit fb9edb7

Browse files
committed
Refactor MeasureDecorator to use model PolylineDecorator code.
1 parent 42b777b commit fb9edb7

File tree

2 files changed

+138
-271
lines changed

2 files changed

+138
-271
lines changed

src/bonsai/bonsai/bim/module/model/decorator.py

Lines changed: 131 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ class PolylineDecorator:
323323
snap_info = None
324324
tool_state = None
325325
relating_type = None
326+
polyline_points = None
326327

327328
@classmethod
328329
def install(cls, context, ui_only=False):
@@ -335,7 +336,10 @@ def install(cls, context, ui_only=False):
335336
SpaceView3D.draw_handler_add(handler.draw_snap_point, (context,), "WINDOW", "POST_PIXEL")
336337
)
337338
cls.handlers.append(
338-
SpaceView3D.draw_handler_add(handler.draw_measurements, (context,), "WINDOW", "POST_PIXEL")
339+
SpaceView3D.draw_handler_add(handler.select_and_draw_measurements_text, (context,), "WINDOW", "POST_PIXEL")
340+
)
341+
cls.handlers.append(
342+
SpaceView3D.draw_handler_add(handler.select_and_draw_measurements_poly, (context,), "WINDOW", "POST_VIEW")
339343
)
340344
cls.handlers.append(SpaceView3D.draw_handler_add(handler, (context,), "WINDOW", "POST_VIEW"))
341345
cls.is_installed = True
@@ -361,28 +365,20 @@ def update(
361365
cls.tool_state = tool_state
362366
cls.input_ui = input_ui
363367

364-
# TODO: unused?
365-
@classmethod
366-
def set_input_ui(cls, input_ui: tool.Polyline.PolylineUI) -> None:
367-
cls.input_ui = input_ui
368-
369368
@classmethod
370369
def set_angle_axis_line(cls, start: Vector, end: Vector) -> None:
371370
cls.axis_start = start
372371
cls.axis_end = end
373372

374373
def calculate_measurement_x_y_and_z(self, context: bpy.types.Context) -> None:
375-
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
376-
polyline_points = polyline_data[0].polyline_points if polyline_data else []
377-
378-
if len(polyline_points) == 0 or len(polyline_points) > 2:
374+
if len(self.polyline_points) == 0 or len(self.polyline_points) > 2:
379375
return None, None
380376

381-
start = polyline_points[0]
382-
if len(polyline_points) == 1:
377+
start = self.polyline_points[0]
378+
if len(self.polyline_points) == 1:
383379
end = context.scene.BIMPolylineProperties.snap_mouse_point[0]
384380
else:
385-
end = polyline_points[1]
381+
end = self.polyline_points[1]
386382

387383
x_axis = (Vector((start.x, start.y, start.z)), Vector((end.x, start.y, start.z)))
388384
y_axis = (Vector((end.x, start.y, start.z)), Vector((end.x, end.y, start.z)))
@@ -423,6 +419,30 @@ def draw_batch(self, shader_type, content_pos, color, indices=None):
423419
shader.uniform_float("color", color)
424420
batch.draw(shader)
425421

422+
def shader_config(self, context):
423+
self.addon_prefs = tool.Blender.get_addon_preferences()
424+
self.decorator_color = self.addon_prefs.decorations_colour
425+
self.decorator_color_special = self.addon_prefs.decorator_color_special
426+
self.decorator_color_selected = self.addon_prefs.decorator_color_selected
427+
self.decorator_color_error = self.addon_prefs.decorator_color_error
428+
self.decorator_color_unselected = self.addon_prefs.decorator_color_unselected
429+
self.decorator_color_background = self.addon_prefs.decorator_color_background
430+
theme = context.preferences.themes.items()[0][1]
431+
self.decorator_color_object_active = (*theme.view_3d.object_active, 1) # unwrap color values and adds alpha=1
432+
self.decorator_color_x_axis = (*theme.user_interface.axis_x, 1)
433+
self.decorator_color_y_axis = (*theme.user_interface.axis_y, 1)
434+
self.decorator_color_z_axis = (*theme.user_interface.axis_z, 1)
435+
436+
gpu.state.blend_set("ALPHA")
437+
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
438+
self.line_shader.bind() # required to be able to change uniforms of the shader
439+
# POLYLINE_UNIFORM_COLOR specific uniforms
440+
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
441+
442+
# general shader
443+
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
444+
gpu.state.point_size_set(6)
445+
426446
def draw_input_ui(self, context: bpy.types.Context) -> None:
427447
texts = {
428448
"D": "Distance: ",
@@ -483,17 +503,9 @@ def draw_text_background(self, context, coords_dim, text_dim):
483503
gpu.state.blend_set("ALPHA")
484504
self.draw_batch("TRIS", verts, color, [(0, 1, 2), (1, 2, 3)])
485505

486-
def draw_measurements(self, context):
487-
region = context.region
506+
def draw_measurements_text(self, context):
507+
region = bpy.context.region
488508
rv3d = region.data
489-
measure_type = context.scene.MeasureToolSettings.measurement_type
490-
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
491-
if not polyline_data:
492-
return
493-
else:
494-
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
495-
polyline_points = polyline_data.polyline_points
496-
497509
self.addon_prefs = tool.Blender.get_addon_preferences()
498510
self.font_id = 1
499511
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
@@ -504,13 +516,15 @@ def draw_measurements(self, context):
504516
color = self.addon_prefs.decorations_colour
505517

506518
blf.color(self.font_id, *color)
507-
for i in range(len(polyline_points)):
519+
for i in range(len(self.polyline_points)):
520+
if i < 1 and self.measure_type == "POLY_AREA":
521+
continue
508522
if i == 0:
509523
continue
510-
dim_text_pos = (Vector(polyline_points[i].position) + Vector(polyline_points[i - 1].position)) / 2
524+
dim_text_pos = (Vector(self.polyline_points[i].position) + Vector(self.polyline_points[i - 1].position)) / 2
511525
dim_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, dim_text_pos)
512526

513-
formatted_value = polyline_points[i].dim
527+
formatted_value = self.polyline_points[i].dim
514528

515529
blf.position(self.font_id, dim_text_coords[0], dim_text_coords[1], 0)
516530
text = "d: " + formatted_value
@@ -520,19 +534,19 @@ def draw_measurements(self, context):
520534

521535
if i == 1:
522536
continue
523-
angle_text_pos = Vector(polyline_points[i - 1].position)
537+
angle_text_pos = Vector(self.polyline_points[i - 1].position)
524538
angle_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, angle_text_pos)
525539
blf.position(self.font_id, angle_text_coords[0], angle_text_coords[1], 0)
526-
text = "a: " + polyline_points[i].angle
540+
text = "a: " + self.polyline_points[i].angle
527541
text_length = blf.dimensions(self.font_id, text)
528542
self.draw_text_background(context, angle_text_coords, text_length)
529543
blf.draw(self.font_id, text)
530544

531-
if measure_type == "SINGLE":
545+
if self.measure_type == "SINGLE":
532546
axis_line, axis_line_center = self.calculate_measurement_x_y_and_z(context)
533547
for i, dim_text_pos in enumerate(axis_line_center):
534548
dim_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, dim_text_pos)
535-
blf.position(self.font_id, dim_text_coords[0], dim_text_coords[1], 0)
549+
pos = blf.position(self.font_id, dim_text_coords[0], dim_text_coords[1], 0)
536550
value = round((axis_line[i][1] - axis_line[i][0]).length, 4)
537551
direction = axis_line[i][1] - axis_line[i][0]
538552
if (i == 0 and direction.x < 0) or (i == 1 and direction.y < 0) or (i == 2 and direction.z < 0):
@@ -545,10 +559,10 @@ def draw_measurements(self, context):
545559
blf.draw(self.font_id, text)
546560

547561
# Area and Length text
548-
polyline_verts = [Vector((p.x, p.y, p.z)) for p in polyline_points]
562+
polyline_verts = [Vector((p.x, p.y, p.z)) for p in self.polyline_points]
549563

550564
# Area
551-
if measure_type == "POLY_AREA" and polyline_data.area:
565+
if self.measure_type == "POLY_AREA" and self.polyline_data.area:
552566
if len(polyline_verts) < 3:
553567
return
554568
center = sum(polyline_verts, Vector()) / len(polyline_verts) # Center between all polyline points
@@ -557,7 +571,7 @@ def draw_measurements(self, context):
557571
polyline_verts[:-1]
558572
) # Doesn't use the last point if is a closed polyline
559573
area_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, center)
560-
value = polyline_data.area
574+
value = self.polyline_data.area
561575
text = f"area: {value}"
562576
text_length = blf.dimensions(self.font_id, text)
563577
area_text_coords[0] -= text_length[0] / 2 # Center text horizontally
@@ -566,19 +580,85 @@ def draw_measurements(self, context):
566580
blf.draw(self.font_id, text)
567581

568582
# Length
569-
if measure_type in {"POLYLINE", "POLY_AREA"}:
583+
if self.measure_type in {"POLYLINE", "POLY_AREA"}:
570584
if len(polyline_verts) < 3:
571585
return
572586
total_length_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, polyline_verts[-1])
573587
blf.position(self.font_id, total_length_text_coords[0], total_length_text_coords[1], 0)
574-
value = polyline_data.total_length
588+
value = self.polyline_data.total_length
575589
text = f"length: {value}"
576590
text_length = blf.dimensions(self.font_id, text)
577591
self.draw_text_background(context, total_length_text_coords, text_length)
578592
blf.draw(self.font_id, text)
579593

580594
blf.disable(self.font_id, blf.SHADOW)
581595

596+
def draw_measurements_poly(self, context):
597+
self.shader_config(context)
598+
polyline_verts: list[Vector] = []
599+
polyline_edges: list[list[int]] = []
600+
for point_prop in self.polyline_points:
601+
point = Vector((point_prop.x, point_prop.y, point_prop.z))
602+
polyline_verts.append(point)
603+
604+
for i in range(len(polyline_verts) - 1):
605+
polyline_edges.append([i, i + 1])
606+
607+
# Lines for X, Y, Z of single measure
608+
if self.polyline_data and self.polyline_data.measurement_type == "SINGLE":
609+
axis, _ = self.calculate_measurement_x_y_and_z(context)
610+
x_axis, y_axis, z_axis = axis
611+
self.draw_batch("LINES", [*x_axis], self.decorator_color_x_axis, [(0, 1)])
612+
self.draw_batch("LINES", [*y_axis], self.decorator_color_y_axis, [(0, 1)])
613+
self.draw_batch("LINES", [*z_axis], self.decorator_color_z_axis, [(0, 1)])
614+
615+
# Area highlight
616+
if self.polyline_data:
617+
area = self.polyline_data.area.split(" ")[0]
618+
if self.polyline_data.measurement_type == "POLY_AREA" and area:
619+
if float(area) > 0:
620+
tris = self.calculate_polygon(polyline_verts)["tris"]
621+
self.draw_batch("TRIS", polyline_verts, transparent_color(self.decorator_color_special), tris)
622+
623+
# Draw polyline with selected points
624+
self.line_shader.uniform_float("lineWidth", 2.0)
625+
self.draw_batch("POINTS", polyline_verts, self.decorator_color_special)
626+
if len(polyline_verts) > 1:
627+
self.draw_batch("LINES", polyline_verts, self.decorator_color_special, polyline_edges)
628+
629+
def get_polylines_data(self, context):
630+
self.measure_type = context.scene.MeasureToolSettings.measurement_type
631+
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
632+
self.measure_data = context.scene.BIMPolylineProperties.measurement_polyline
633+
634+
def select_and_draw_measurements_text(self, context):
635+
self.get_polylines_data(context)
636+
if self.polyline_data:
637+
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
638+
self.polyline_points = self.polyline_data.polyline_points
639+
self.draw_measurements_text(context)
640+
641+
if self.measure_data:
642+
for polyline_data in self.measure_data:
643+
self.polyline_data = polyline_data
644+
self.measure_type = polyline_data.measurement_type
645+
self.polyline_points = self.polyline_data.polyline_points
646+
self.draw_measurements_text(context)
647+
648+
def select_and_draw_measurements_poly(self, context):
649+
self.get_polylines_data(context)
650+
if self.polyline_data:
651+
self.polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
652+
self.polyline_points = self.polyline_data.polyline_points
653+
self.draw_measurements_poly(context)
654+
655+
if self.measure_data:
656+
for polyline_data in self.measure_data:
657+
self.polyline_data = polyline_data
658+
self.measure_type = polyline_data.measurement_type
659+
self.polyline_points = self.polyline_data.polyline_points
660+
self.draw_measurements_poly(context)
661+
582662
def draw_snap_point(self, context):
583663
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
584664
self.line_shader.bind() # required to be able to change uniforms of the shader
@@ -736,6 +816,7 @@ def __call__(self, context):
736816
polyline_points = polyline_data.polyline_points
737817
else:
738818
polyline_points = []
819+
self.polyline_points = polyline_points
739820
polyline_verts: list[Vector] = []
740821
polyline_edges: list[list[int]] = []
741822
for point_prop in polyline_points:
@@ -764,21 +845,21 @@ def __call__(self, context):
764845
self.line_shader.uniform_float("lineWidth", 0.75)
765846
self.draw_batch("LINES", [self.axis_start, self.axis_end], axis_color, [(0, 1)])
766847

767-
# Lines for X, Y, Z of single measure
768-
if polyline_data and polyline_data.measurement_type == "SINGLE":
769-
axis, _ = self.calculate_measurement_x_y_and_z(context)
770-
x_axis, y_axis, z_axis = axis
771-
self.draw_batch("LINES", [*x_axis], decorator_color_x_axis, [(0, 1)])
772-
self.draw_batch("LINES", [*y_axis], decorator_color_y_axis, [(0, 1)])
773-
self.draw_batch("LINES", [*z_axis], decorator_color_z_axis, [(0, 1)])
774-
775-
# Area highlight
776-
if polyline_data:
777-
area = polyline_data.area.split(" ")[0]
778-
if polyline_data.measurement_type == "POLY_AREA" and area:
779-
if float(area) > 0:
780-
tris = self.calculate_polygon(polyline_verts)["tris"]
781-
self.draw_batch("TRIS", polyline_verts, transparent_color(decorator_color_special), tris)
848+
# # Lines for X, Y, Z of single measure
849+
# if polyline_data and polyline_data.measurement_type == "SINGLE":
850+
# axis, _ = self.calculate_measurement_x_y_and_z(context)
851+
# x_axis, y_axis, z_axis = axis
852+
# self.draw_batch("LINES", [*x_axis], decorator_color_x_axis, [(0, 1)])
853+
# self.draw_batch("LINES", [*y_axis], decorator_color_y_axis, [(0, 1)])
854+
# self.draw_batch("LINES", [*z_axis], decorator_color_z_axis, [(0, 1)])
855+
856+
# # Area highlight
857+
# if polyline_data:
858+
# area = polyline_data.area.split(" ")[0]
859+
# if polyline_data.measurement_type == "POLY_AREA" and area:
860+
# if float(area) > 0:
861+
# tris = self.calculate_polygon(polyline_verts)["tris"]
862+
# self.draw_batch("TRIS", polyline_verts, transparent_color(decorator_color_special), tris)
782863

783864
# Mouse points
784865
if snap_prop.snap_type in ["Plane", "Axis", "Mix"]:

0 commit comments

Comments
 (0)