mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 13:23:40 +00:00
Bonsai: fix BCF viewpoint line markup crash on modern Grease Pencil API
draw_lines() used the pre-4.3 Annotation Grease Pencil scripting API (frame.strokes.new()), which Blender removed the stroke-mutation methods from in 4.3 and dropped scene.grease_pencil/the legacy datablock entirely in 5.1. Activating a BCF viewpoint whose markup includes lines then crashed with AttributeError: bpy_prop_collection: attribute "new" not found. Detect the available API by capability (frame.drawing presence) rather than a hardcoded version check, since Blender exposes the rewritten, object-based Grease Pencil through grease_pencils_v3 on 4.3-5.0 and through the unified grease_pencils on 5.1+, while 4.2 still has the original Annotation API. Reproduced live against the reporter's actual BCF/IFC files on Blender 4.5.8 and 5.1.2: the crash occurs on unpatched code, and no crash occurs after the fix, with the viewpoint markup lines correctly drawn on both. Fixes #7318. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -1259,9 +1259,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
|||||||
if self.file:
|
if self.file:
|
||||||
self.set_viewpoint_components(viewpoint, context)
|
self.set_viewpoint_components(viewpoint, context)
|
||||||
|
|
||||||
gp = bpy.data.grease_pencils.get("BCF")
|
self.delete_lines()
|
||||||
if gp:
|
|
||||||
bpy.data.grease_pencils.remove(gp)
|
|
||||||
if viewpoint.visualization_info.lines:
|
if viewpoint.visualization_info.lines:
|
||||||
self.draw_lines(viewpoint, context)
|
self.draw_lines(viewpoint, context)
|
||||||
|
|
||||||
@@ -1434,24 +1432,58 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
|||||||
if obj:
|
if obj:
|
||||||
obj.color = self.hex_to_rgb(color)
|
obj.color = self.hex_to_rgb(color)
|
||||||
|
|
||||||
|
def delete_lines(self) -> None:
|
||||||
|
if obj := bpy.data.objects.get("BCF"):
|
||||||
|
bpy.data.objects.remove(obj)
|
||||||
|
for grease_pencils in (bpy.data.grease_pencils, getattr(bpy.data, "grease_pencils_v3", None)):
|
||||||
|
if grease_pencils is not None and (gp := grease_pencils.get("BCF")):
|
||||||
|
grease_pencils.remove(gp)
|
||||||
|
|
||||||
def draw_lines(self, viewpoint: bcf.agnostic.visinfo.VisualizationInfoHandler, context: bpy.types.Context) -> None:
|
def draw_lines(self, viewpoint: bcf.agnostic.visinfo.VisualizationInfoHandler, context: bpy.types.Context) -> None:
|
||||||
gp = bpy.data.grease_pencils.new("BCF")
|
# Blender 4.3+ moved the object-based Grease Pencil to its own
|
||||||
scene = context.scene
|
# `grease_pencils_v3` collection (merged back into `grease_pencils`
|
||||||
scene.grease_pencil = gp
|
# in 5.1+, which also dropped the legacy Annotation API used below).
|
||||||
scene.frame_set(1)
|
grease_pencils = getattr(bpy.data, "grease_pencils_v3", None)
|
||||||
|
if grease_pencils is None:
|
||||||
|
grease_pencils = bpy.data.grease_pencils
|
||||||
|
gp = grease_pencils.new("BCF")
|
||||||
layer = gp.layers.new("BCF Annotation", set_active=True)
|
layer = gp.layers.new("BCF Annotation", set_active=True)
|
||||||
layer.thickness = 3
|
|
||||||
layer.color = (1, 0, 0)
|
|
||||||
frame = layer.frames.new(1)
|
frame = layer.frames.new(1)
|
||||||
stroke = frame.strokes.new()
|
lines = viewpoint.visualization_info.lines.line
|
||||||
stroke.display_mode = "3DSPACE"
|
if (drawing := getattr(frame, "drawing", None)) is not None:
|
||||||
stroke.points.add(len(viewpoint.visualization_info.lines.line) * 2)
|
obj = bpy.data.objects.new("BCF", gp)
|
||||||
coords = []
|
context.scene.collection.objects.link(obj)
|
||||||
for l in viewpoint.visualization_info.lines.line:
|
drawing.add_strokes(sizes=[2] * len(lines))
|
||||||
coords.extend(
|
coords = []
|
||||||
[l.start_point.x, l.start_point.y, l.start_point.z, l.end_point.x, l.end_point.y, l.end_point.z]
|
for l in lines:
|
||||||
)
|
coords.extend(
|
||||||
stroke.points.foreach_set("co", coords)
|
[l.start_point.x, l.start_point.y, l.start_point.z, l.end_point.x, l.end_point.y, l.end_point.z]
|
||||||
|
)
|
||||||
|
drawing.attributes["position"].data.foreach_set("vector", coords)
|
||||||
|
radius = drawing.attributes.new("radius", "FLOAT", "POINT")
|
||||||
|
radius.data.foreach_set("value", [0.01] * (len(lines) * 2))
|
||||||
|
drawing.tag_positions_changed()
|
||||||
|
mat = bpy.data.materials.get("BCF Annotation")
|
||||||
|
if mat is None:
|
||||||
|
mat = bpy.data.materials.new("BCF Annotation")
|
||||||
|
bpy.data.materials.create_gpencil_data(mat)
|
||||||
|
mat.grease_pencil.color = (1, 0, 0, 1)
|
||||||
|
gp.materials.append(mat)
|
||||||
|
else:
|
||||||
|
scene = context.scene
|
||||||
|
scene.grease_pencil = gp
|
||||||
|
scene.frame_set(1)
|
||||||
|
layer.thickness = 3
|
||||||
|
layer.color = (1, 0, 0)
|
||||||
|
stroke = frame.strokes.new()
|
||||||
|
stroke.display_mode = "3DSPACE"
|
||||||
|
stroke.points.add(len(lines) * 2)
|
||||||
|
coords = []
|
||||||
|
for l in lines:
|
||||||
|
coords.extend(
|
||||||
|
[l.start_point.x, l.start_point.y, l.start_point.z, l.end_point.x, l.end_point.y, l.end_point.z]
|
||||||
|
)
|
||||||
|
stroke.points.foreach_set("co", coords)
|
||||||
|
|
||||||
def create_clipping_planes(self, viewpoint: bcf.agnostic.visinfo.VisualizationInfoHandler) -> None:
|
def create_clipping_planes(self, viewpoint: bcf.agnostic.visinfo.VisualizationInfoHandler) -> None:
|
||||||
n = 0
|
n = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user