Fix #5416. Optimise item decorator and make decoration more subtle to make it easier to see the mesh.

This commit is contained in:
Dion Moult
2024-09-26 23:30:12 +10:00
parent b01471aa55
commit a273c87e41
5 changed files with 61 additions and 60 deletions
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import blf
import gpu
import bmesh
@@ -34,11 +35,51 @@ class ItemDecorator:
def install(cls, context):
if cls.is_installed:
cls.uninstall()
obj_is_selected = {}
objs = {}
for item_obj in context.scene.BIMGeometryProperties.item_objs:
if obj := item_obj.obj:
objs[obj.name] = cls.get_obj_data(obj)
obj_is_selected[obj.name] = obj.select_get()
handler = cls()
handler.objs = objs
handler.obj_is_selected = obj_is_selected
cls.handlers.append(SpaceView3D.draw_handler_add(handler.draw_text, (context,), "WINDOW", "POST_PIXEL"))
cls.handlers.append(SpaceView3D.draw_handler_add(handler.draw, (context,), "WINDOW", "POST_VIEW"))
cls.is_installed = True
@classmethod
def get_obj_data(cls, obj):
verts = []
edges = []
tris = []
if len(obj.data.loop_triangles) > 0:
verts = [tuple(obj.matrix_world @ v.co) for v in obj.data.vertices]
tris = [tuple(t.vertices) for t in obj.data.loop_triangles]
i = len(verts)
matrix_world = obj.matrix_world
bbox_verts = [matrix_world @ Vector(co) for co in obj.bound_box]
bbox_edges = [
(0 + i, 3 + i),
(3 + i, 7 + i),
(7 + i, 4 + i),
(4 + i, 0 + i),
(0 + i, 1 + i),
(3 + i, 2 + i),
(7 + i, 6 + i),
(4 + i, 5 + i),
(1 + i, 2 + i),
(2 + i, 6 + i),
(6 + i, 5 + i),
(5 + i, 1 + i),
]
edges = bbox_edges
verts.extend(bbox_verts)
return {"verts": verts, "edges": edges, "tris": tris}
@classmethod
def uninstall(cls):
for handler in cls.handlers:
@@ -80,7 +121,7 @@ class ItemDecorator:
blf.disable(font_id, blf.SHADOW)
def draw(self, context):
def transparent_color(color, alpha=0.3):
def transparent_color(color, alpha=0.05):
color = [i for i in color]
color[3] = alpha
return color
@@ -89,72 +130,30 @@ class ItemDecorator:
selected_elements_color = self.addon_prefs.decorator_color_selected
unselected_elements_color = self.addon_prefs.decorator_color_unselected
special_elements_color = self.addon_prefs.decorator_color_special
decorator_color_background = self.addon_prefs.decorator_color_background
gpu.state.point_size_set(6)
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))
self.line_shader.uniform_float("lineWidth", 2.0)
self.line_shader.uniform_float("lineWidth", 1.0)
# general shader
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
selected_verts = []
selected_edges = []
selected_tris = []
unselected_verts = []
unselected_edges = []
unselected_tris = []
for item in context.scene.BIMGeometryProperties.item_objs:
if (obj := item.obj) and obj.hide_get() == False:
for obj_name, data in self.objs.items():
if (obj := bpy.data.objects.get(obj_name)) and obj.hide_get() == False:
if self.obj_is_selected[obj_name] != obj.select_get():
self.obj_is_selected[obj_name] = obj.select_get()
data = ItemDecorator.get_obj_data(obj)
self.objs[obj_name] = data
if obj.select_get():
if context.mode != "OBJECT":
continue
edges = selected_edges
verts = selected_verts
tris = selected_tris
self.draw_batch("LINES", data["verts"], selected_elements_color, data["edges"])
self.draw_batch("TRIS", data["verts"], transparent_color(selected_elements_color), data["tris"])
else:
edges = unselected_edges
verts = unselected_verts
tris = unselected_tris
i = len(verts)
matrix_world = obj.matrix_world
bbox_verts = [matrix_world @ Vector(co) for co in obj.bound_box]
bbox_edges = [
(0 + i, 3 + i),
(3 + i, 7 + i),
(7 + i, 4 + i),
(4 + i, 0 + i),
(0 + i, 1 + i),
(3 + i, 2 + i),
(7 + i, 6 + i),
(4 + i, 5 + i),
(1 + i, 2 + i),
(2 + i, 6 + i),
(6 + i, 5 + i),
(5 + i, 1 + i),
]
edges.extend(bbox_edges)
verts.extend(bbox_verts)
if (total_tris := len(obj.data.loop_triangles)) == 0:
continue
if total_tris > 1000: # For performance
continue
offset = len(verts)
verts.extend([tuple(obj.matrix_world @ v.co) for v in obj.data.vertices])
tris.extend([tuple([i + offset for i in t.vertices]) for t in obj.data.loop_triangles])
if unselected_verts:
self.draw_batch("LINES", unselected_verts, transparent_color(unselected_elements_color), unselected_edges)
self.draw_batch("TRIS", unselected_verts, transparent_color(special_elements_color), unselected_tris)
if selected_verts:
self.draw_batch("LINES", selected_verts, selected_elements_color, selected_edges)
self.draw_batch("TRIS", selected_verts, transparent_color(selected_elements_color), selected_tris)
self.draw_batch("LINES", data["verts"], decorator_color_background, data["edges"])
self.draw_batch("TRIS", data["verts"], transparent_color(special_elements_color), data["tris"])
@@ -1745,6 +1745,7 @@ class OverrideModeSetObject(bpy.types.Operator, tool.Ifc.Operator):
return bpy.ops.bim.edit_boundary_geometry()
elif tool.Geometry.is_representation_item(context.active_object):
self.edit_representation_item(context.active_object)
tool.Root.reload_item_decorator()
return {"FINISHED"}
objs = context.selected_objects or [context.active_object]
@@ -2358,6 +2359,8 @@ class ImportRepresentationItems(bpy.types.Operator, tool.Ifc.Operator):
if tool.Geometry.is_meshlike_item(item):
tool.Geometry.lock_object(item_obj)
tool.Root.reload_item_decorator()
class UpdateItemAttributes(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.update_item_attributes"
@@ -131,7 +131,6 @@ class CreateProject(bpy.types.Operator):
)
bonsai.bim.schema.reload(tool.Ifc.get().schema_identifier)
tool.Blender.register_toolbar()
tool.Root.reload_item_decorator()
def rollback(self, data):
IfcStore.file = None
@@ -843,7 +842,6 @@ class LoadProjectElements(bpy.types.Operator):
tool.Project.set_default_context()
tool.Project.set_default_modeling_dimensions()
tool.Root.reload_grid_decorator()
tool.Root.reload_item_decorator()
return {"FINISHED"}
def get_decomposition_elements(self):
+3 -1
View File
@@ -1434,7 +1434,8 @@ class Geometry(bonsai.core.tool.Geometry):
has_changed = False
for item_obj in props.item_objs:
obj = item_obj.obj
if not (obj := item_obj.obj):
continue
item = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id)
if item.is_a("IfcSweptAreaSolid"):
if not tool.Ifc.is_moved(obj):
@@ -1455,6 +1456,7 @@ class Geometry(bonsai.core.tool.Geometry):
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_position)
if has_changed:
cls.reload_representation(rep_obj)
tool.Root.reload_item_decorator()
@classmethod
def import_item_attributes(cls, obj: bpy.types.Object) -> None:
+1 -2
View File
@@ -217,8 +217,7 @@ class Root(bonsai.core.tool.Root):
@classmethod
def reload_item_decorator(cls) -> None:
item_objs = bpy.context.scene.BIMGeometryProperties.item_objs
item_objs.clear()
bpy.context.view_layer.update()
ItemDecorator.install(bpy.context)
@classmethod