A little progress on refactoring the old drawing module into an IfcConvert based system. See #1153.

This commit is contained in:
Dion Moult
2021-05-14 17:48:53 +10:00
parent c40f07f9b5
commit 13c642c6ab
9 changed files with 328 additions and 224 deletions
@@ -86,7 +86,6 @@ if bpy is not None:
operator.AddIfcFile,
operator.RemoveIfcFile,
operator.SelectDocIfcFile,
operator.AddAnnotation,
operator.GenerateReferences,
operator.ResizeText,
operator.AddVariable,
-139
View File
@@ -78,145 +78,6 @@ def export_attributes(props, callback=None):
# TODO: migrate the below helper functions into the drawing module, since it is specific to that module
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
# MeasureIt-ARCH is GPL-v3
# In the future I will need to rewrite this to allow the user to have custom
# settings for each annotation object, not read from Blender.
def format_distance(value, isArea=False, hide_units=True):
s_code = "\u00b2" # Superscript two THIS IS LEGACY (but being kept for when Area Measurements are re-implimented)
# Get Scene Unit Settings
scaleFactor = bpy.context.scene.unit_settings.scale_length
unit_system = bpy.context.scene.unit_settings.system
unit_length = bpy.context.scene.unit_settings.length_unit
toInches = 39.3700787401574887
inPerFoot = 11.999
if isArea:
toInches = 1550
inPerFoot = 143.999
value *= scaleFactor
# Imperial Formating
if unit_system == "IMPERIAL":
precision = bpy.context.scene.BIMProperties.imperial_precision
if precision == "NONE":
precision = 256
elif precision == "1":
precision = 1
elif "/" in precision:
precision = int(precision.split("/")[1])
base = int(precision)
decInches = value * toInches
# Seperate ft and inches
# Unless Inches are the specified Length Unit
if unit_length != "INCHES":
feet = math.floor(decInches / inPerFoot)
decInches -= feet * inPerFoot
else:
feet = 0
# Seperate Fractional Inches
inches = math.floor(decInches)
if inches != 0:
frac = round(base * (decInches - inches))
else:
frac = round(base * (decInches))
# Set proper numerator and denominator
if frac != base:
numcycles = int(math.log2(base))
for i in range(numcycles):
if frac % 2 == 0:
frac = int(frac / 2)
base = int(base / 2)
else:
break
else:
frac = 0
inches += 1
# Check values and compose string
if inches == 12:
feet += 1
inches = 0
if not isArea:
tx_dist = ""
if feet:
tx_dist += str(feet) + "'"
if feet and inches:
tx_dist += " - "
if inches:
tx_dist += str(inches)
if inches and frac:
tx_dist += " "
if frac:
tx_dist += str(frac) + "/" + str(base)
if inches or frac:
tx_dist += '"'
else:
tx_dist = str("%1.3f" % (value * toInches / inPerFoot)) + " sq. ft."
# METRIC FORMATING
elif unit_system == "METRIC":
precision = bpy.context.scene.BIMProperties.metric_precision
if precision != 0:
value = precision * round(float(value) / precision)
# Meters
if unit_length == "METERS":
fmt = "%1.3f"
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
# Centimeters
elif unit_length == "CENTIMETERS":
fmt = "%1.1f"
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
# Millimeters
elif unit_length == "MILLIMETERS":
fmt = "%1.0f"
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
# Otherwise Use Adaptive Units
else:
if round(value, 2) >= 1.0:
fmt = "%1.3f"
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
else:
if round(value, 2) >= 0.01:
fmt = "%1.1f"
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
else:
fmt = "%1.0f"
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
if isArea:
tx_dist += s_code
else:
tx_dist = fmt % value
return tx_dist
def parse_diagram_scale(camera):
"""Returns numeric value of scale"""
if camera.BIMCameraProperties.diagram_scale == "CUSTOM":
@@ -4,6 +4,7 @@ from . import ui, operator
classes = (
operator.AddDrawing,
operator.CreateDrawing,
operator.AddAnnotation,
ui.BIM_PT_camera,
)
@@ -0,0 +1,141 @@
import bpy
import math
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
# MeasureIt-ARCH is GPL-v3
# In the future I will need to rewrite this to allow the user to have custom
# settings for each annotation object, not read from Blender.
def format_distance(value, isArea=False, hide_units=True):
s_code = "\u00b2" # Superscript two THIS IS LEGACY (but being kept for when Area Measurements are re-implimented)
# Get Scene Unit Settings
scaleFactor = bpy.context.scene.unit_settings.scale_length
unit_system = bpy.context.scene.unit_settings.system
unit_length = bpy.context.scene.unit_settings.length_unit
toInches = 39.3700787401574887
inPerFoot = 11.999
if isArea:
toInches = 1550
inPerFoot = 143.999
value *= scaleFactor
# Imperial Formating
if unit_system == "IMPERIAL":
precision = bpy.context.scene.BIMProperties.imperial_precision
if precision == "NONE":
precision = 256
elif precision == "1":
precision = 1
elif "/" in precision:
precision = int(precision.split("/")[1])
base = int(precision)
decInches = value * toInches
# Seperate ft and inches
# Unless Inches are the specified Length Unit
if unit_length != "INCHES":
feet = math.floor(decInches / inPerFoot)
decInches -= feet * inPerFoot
else:
feet = 0
# Seperate Fractional Inches
inches = math.floor(decInches)
if inches != 0:
frac = round(base * (decInches - inches))
else:
frac = round(base * (decInches))
# Set proper numerator and denominator
if frac != base:
numcycles = int(math.log2(base))
for i in range(numcycles):
if frac % 2 == 0:
frac = int(frac / 2)
base = int(base / 2)
else:
break
else:
frac = 0
inches += 1
# Check values and compose string
if inches == 12:
feet += 1
inches = 0
if not isArea:
tx_dist = ""
if feet:
tx_dist += str(feet) + "'"
if feet and inches:
tx_dist += " - "
if inches:
tx_dist += str(inches)
if inches and frac:
tx_dist += " "
if frac:
tx_dist += str(frac) + "/" + str(base)
if inches or frac:
tx_dist += '"'
else:
tx_dist = str("%1.3f" % (value * toInches / inPerFoot)) + " sq. ft."
# METRIC FORMATING
elif unit_system == "METRIC":
precision = bpy.context.scene.BIMProperties.metric_precision
if precision != 0:
value = precision * round(float(value) / precision)
# Meters
if unit_length == "METERS":
fmt = "%1.3f"
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
# Centimeters
elif unit_length == "CENTIMETERS":
fmt = "%1.1f"
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
# Millimeters
elif unit_length == "MILLIMETERS":
fmt = "%1.0f"
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
# Otherwise Use Adaptive Units
else:
if round(value, 2) >= 1.0:
fmt = "%1.3f"
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
else:
if round(value, 2) >= 0.01:
fmt = "%1.1f"
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
else:
fmt = "%1.0f"
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
if isArea:
tx_dist += s_code
else:
tx_dist = fmt % value
return tx_dist
@@ -3,6 +3,9 @@ import bpy
import json
import subprocess
import webbrowser
import blenderbim.bim.module.drawing.svgwriter as svgwriter
import blenderbim.bim.module.drawing.annotation as annotation
from mathutils import Vector, Matrix, Euler, geometry
from blenderbim.bim.operator import open_with_user_command
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.group.data import Data as GroupData
@@ -57,33 +60,156 @@ class CreateDrawing(bpy.types.Operator):
bl_label = "Create Drawing"
def execute(self, context):
base_svg = self.ifc_to_svg(context)
annotation_svg = self.annotation_to_svg(context)
svg_path = self.combine_svgs(context, base_svg, annotation_svg)
open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
return {"FINISHED"}
def combine_svgs(self, context, base, annotation):
# Hacky :)
svg_path = context.scene.BIMProperties.ifc_file[0:-4] + ".svg"
with open(svg_path, 'w') as outfile:
with open(base) as infile:
for line in infile:
if "</svg>" in line:
continue
outfile.write(line)
with open(annotation) as infile:
for i, line in enumerate(infile):
if i == 0 or i == 1:
continue
outfile.write(line)
return svg_path
def ifc_to_svg(self, context):
svg_path = context.scene.BIMProperties.ifc_file[0:-4] + "-base.svg"
ifcconvert_path = os.path.join(cwd, "..", "..", "..", "libs", "IfcConvert")
subprocess.run(
[
ifcconvert_path,
context.scene.BIMProperties.ifc_file,
"-yv",
context.scene.BIMProperties.ifc_file[0:-4] + ".svg",
svg_path,
"--plan",
"--model",
"--section-height-from-storeys",
"--section-height=1.2",
"--door-arcs",
"--print-space-names",
"--print-space-areas",
"--bounds=1024x1024",
"--elevation-ref=DRAWING",
"--svg-xmlns",
"--svg-project",
"--svg-poly",
"--svg-without-storeys",
"--exclude",
"entities",
"IfcSpace",
"IfcOpeningElement",
]
)
open_with_user_command(
bpy.context.preferences.addons["blenderbim"].preferences.svg_command,
context.scene.BIMProperties.ifc_file[0:-4] + ".svg",
)
return svg_path
def annotation_to_svg(self, context):
camera = context.scene.camera
if not (camera.type == "CAMERA" and camera.data.type == "ORTHO"):
return
svg_writer = svgwriter.SvgWriter()
if camera.data.BIMCameraProperties.diagram_scale == "CUSTOM":
human_scale, fraction = camera.data.BIMCameraProperties.custom_diagram_scale.split("|")
else:
human_scale, fraction = camera.data.BIMCameraProperties.diagram_scale.split("|")
numerator, denominator = fraction.split("/")
if camera.data.BIMCameraProperties.is_nts:
svg_writer.human_scale = "NTS"
else:
svg_writer.human_scale = human_scale
drawing_style = bpy.context.scene.DocProperties.drawing_styles[
camera.data.BIMCameraProperties.active_drawing_style_index
]
render = bpy.context.scene.render
if self.is_landscape():
width = camera.data.ortho_scale
height = width / render.resolution_x * render.resolution_y
else:
height = camera.data.ortho_scale
width = height / render.resolution_y * render.resolution_x
svg_writer.scale = float(numerator) / float(denominator)
svg_writer.output = context.scene.BIMProperties.ifc_file[0:-4] + "-annotation.svg"
svg_writer.data_dir = bpy.context.scene.BIMProperties.data_dir
svg_writer.vector_style = drawing_style.vector_style
svg_writer.camera = camera
svg_writer.camera_width = width
svg_writer.camera_height = height
svg_writer.camera_projection = tuple(camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)))
for obj in camera.users_collection[0].objects:
if "IfcGrid" in obj.name:
svg_writer.annotations.setdefault("grid_objs", []).append(obj)
elif obj.type == "CAMERA":
continue
if "IfcAnnotation/" not in obj.name:
continue
if "Leader" in obj.name:
svg_writer.annotations["leader_obj"] = (obj, obj.data)
elif "Stair" in obj.name:
svg_writer.annotations["stair_obj"] = obj
elif "Equal" in obj.name:
svg_writer.annotations.setdefault("equal_objs", []).append(obj)
elif "Dimension" in obj.name:
svg_writer.annotations.setdefault("dimension_objs", []).append(obj)
elif "Break" in obj.name:
svg_writer.annotations["break_obj"] = obj
elif "Hidden" in obj.name:
svg_writer.annotations.setdefault("hidden_objs", []).append((obj, obj.data))
elif "Solid" in obj.name:
svg_writer.annotations.setdefault("solid_objs", []).append((obj, obj.data))
elif "Plan Level" in obj.name:
svg_writer.annotations["plan_level_obj"] = obj
elif "Section Level" in obj.name:
svg_writer.annotations["section_level_obj"] = obj
elif obj.type == "FONT":
svg_writer.annotations.setdefault("text_objs", []).append(obj)
else:
svg_writer.annotations.setdefault("misc_objs", []).append(obj)
svg_writer.annotations["attributes"] = [a.name for a in drawing_style.attributes]
svg_writer.write()
return svg_writer.output
def is_landscape(self):
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
class AddAnnotation(bpy.types.Operator):
bl_idname = "bim.add_annotation"
bl_label = "Add Annotation"
obj_name: bpy.props.StringProperty()
data_type: bpy.props.StringProperty()
def execute(self, context):
if not bpy.context.scene.camera:
return {"FINISHED"}
if self.data_type == "text":
if bpy.context.selected_objects:
for selected_object in bpy.context.selected_objects:
obj = annotation.Annotator.add_text(related_element=selected_object)
else:
obj = annotation.Annotator.add_text()
else:
obj = annotation.Annotator.get_annotation_obj(self.obj_name, self.data_type)
if self.obj_name == "Break":
obj = annotation.Annotator.add_plane_to_annotation(obj)
else:
obj = annotation.Annotator.add_line_to_annotation(obj)
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode="EDIT")
return {"FINISHED"}
@@ -6,8 +6,8 @@ import pystache
import xml.etree.ElementTree as ET
import svgwrite
import ifcopenshell
from . import annotation
from . import helper
import blenderbim.bim.module.drawing.helper as helper
import blenderbim.bim.module.drawing.annotation as annotation
from mathutils import Vector
from mathutils import geometry
from blenderbim.bim.ifc import IfcStore
@@ -39,14 +39,16 @@ class External(svgwrite.container.Group):
class SvgWriter:
def __init__(self, ifc_cutter):
self.ifc_cutter = ifc_cutter
def __init__(self):
self.output = "out.svg"
self.data_dir = None
self.vector_style = None
self.human_scale = "NTS"
self.annotations = {}
self.scale = 1 / 100 # 1:100
def write(self):
self.calculate_scale()
self.output = os.path.join(self.ifc_cutter.data_dir, "diagrams", self.ifc_cutter.diagram_name + ".svg")
self.svg = svgwrite.Drawing(
self.output,
debug=False,
@@ -60,42 +62,43 @@ class SvgWriter:
self.add_markers()
self.add_symbols()
self.add_patterns()
self.draw_background_image()
self.draw_background_elements()
self.draw_cut_polygons()
# self.draw_background_image()
# self.draw_background_elements()
# self.draw_cut_polygons()
self.draw_annotations()
self.svg.save(pretty=True)
def calculate_scale(self):
self.scale *= 1000 # IFC is in meters, SVG is in mm
self.raw_width = self.ifc_cutter.section_box["x"]
self.raw_height = self.ifc_cutter.section_box["y"]
self.raw_width = self.camera_width
self.raw_height = self.camera_height
self.width = self.raw_width * self.scale
self.height = self.raw_height * self.scale
def add_stylesheet(self):
with open("{}styles/{}.css".format(self.ifc_cutter.data_dir, self.ifc_cutter.vector_style), "r") as stylesheet:
with open("{}styles/{}.css".format(self.data_dir, self.vector_style), "r") as stylesheet:
self.svg.defs.add(self.svg.style(stylesheet.read()))
def add_markers(self):
tree = ET.parse("{}templates/markers.svg".format(self.ifc_cutter.data_dir))
tree = ET.parse("{}templates/markers.svg".format(self.data_dir))
root = tree.getroot()
for child in root.getchildren():
self.svg.defs.add(External(child))
def add_symbols(self):
tree = ET.parse("{}templates/symbols.svg".format(self.ifc_cutter.data_dir))
tree = ET.parse("{}templates/symbols.svg".format(self.data_dir))
root = tree.getroot()
for child in root.getchildren():
self.svg.defs.add(External(child))
def add_patterns(self):
tree = ET.parse("{}templates/patterns.svg".format(self.ifc_cutter.data_dir))
tree = ET.parse("{}templates/patterns.svg".format(self.data_dir))
root = tree.getroot()
for child in root.getchildren():
self.svg.defs.add(External(child))
def draw_background_image(self):
return # TODO reimplement for artistic drawing options
self.svg.add(
self.svg.image(
os.path.join("..", "diagrams", os.path.basename(self.ifc_cutter.background_image)),
@@ -104,6 +107,7 @@ class SvgWriter:
)
def draw_background_elements(self):
return # TODO purge?
for element in self.ifc_cutter.background_elements:
if element["type"] == "polygon":
self.draw_polygon(element, "background")
@@ -116,16 +120,16 @@ class SvgWriter:
x_offset = self.raw_width / 2
y_offset = self.raw_height / 2
for obj in self.ifc_cutter.equal_objs:
for obj in self.annotations.get("equal_objs", []):
self.draw_dimension_annotations(obj, text_override="EQ")
for obj in self.ifc_cutter.dimension_objs:
for obj in self.annotations.get("dimension_objs", []):
self.draw_dimension_annotations(obj)
self.draw_measureit_arch_dimension_annotations()
if self.ifc_cutter.break_obj:
self.draw_break_annotations(self.ifc_cutter.break_obj)
if self.annotations.get("break_obj"):
self.draw_break_annotations(self.annotations["break_obj"])
for grid_obj in self.ifc_cutter.grid_objs:
for grid_obj in self.annotations.get("grid_objs", []):
matrix_world = grid_obj.matrix_world
for edge in grid_obj.data.edges:
classes = ["annotation", "grid"]
@@ -174,21 +178,21 @@ class SvgWriter:
self.draw_ifc_annotation()
for obj in self.ifc_cutter.misc_objs:
for obj in self.annotations.get("misc_objs", []):
self.draw_misc_annotation(obj, ["IfcAnnotation"])
for obj_data in self.ifc_cutter.hidden_objs:
for obj_data in self.annotations.get("hidden_objs", []):
self.draw_line_annotation(obj_data, ["hidden"])
for obj_data in self.ifc_cutter.solid_objs:
for obj_data in self.annotations.get("solid_objs", []):
self.draw_line_annotation(obj_data, ["solid"])
if self.ifc_cutter.leader_obj:
self.draw_line_annotation(self.ifc_cutter.leader_obj, ["leader"])
if self.annotations.get("leader_obj"):
self.draw_line_annotation(self.annotations["leader_obj"], ["leader"])
if self.ifc_cutter.plan_level_obj:
matrix_world = self.ifc_cutter.plan_level_obj.matrix_world
for spline in self.ifc_cutter.plan_level_obj.data.splines:
if self.annotations.get("plan_level_obj"):
matrix_world = self.annotations["plan_level_obj"].matrix_world
for spline in self.annotations["plan_level_obj"].data.splines:
classes = ["annotation", "plan-level"]
points = self.get_spline_points(spline)
projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points]
@@ -208,7 +212,7 @@ class SvgWriter:
)
)
# TODO: allow metric to be configurable
rl = ((matrix_world @ points[0].co).xyz + self.ifc_cutter.plan_level_obj.location).z
rl = ((matrix_world @ points[0].co).xyz + self.annotations["plan_level_obj"].location).z
if bpy.context.scene.unit_settings.system == "IMPERIAL":
rl = helper.format_distance(rl)
else:
@@ -231,9 +235,9 @@ class SvgWriter:
)
)
if self.ifc_cutter.section_level_obj:
matrix_world = self.ifc_cutter.section_level_obj.matrix_world
for spline in self.ifc_cutter.section_level_obj.data.splines:
if self.annotations.get("section_level_obj"):
matrix_world = self.annotations["section_level_obj"].matrix_world
for spline in self.annotations["section_level_obj"].data.splines:
classes = ["annotation", "section-level"]
points = self.get_spline_points(spline)
projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points]
@@ -273,9 +277,9 @@ class SvgWriter:
)
)
if self.ifc_cutter.stair_obj:
matrix_world = self.ifc_cutter.stair_obj.matrix_world
for spline in self.ifc_cutter.stair_obj.data.splines:
if self.annotations.get("stair_obj"):
matrix_world = self.annotations["stair_obj"].matrix_world
for spline in self.annotations["stair_obj"].data.splines:
classes = ["annotation", "stair"]
points = self.get_spline_points(spline)
projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points]
@@ -308,7 +312,7 @@ class SvgWriter:
def draw_ifc_annotation(self):
x_offset = self.raw_width / 2
y_offset = self.raw_height / 2
for annotation in self.ifc_cutter.annotation_objs:
for annotation in self.annotations.get("annotation_objs", []):
for edge in annotation["edges"]:
v0_global = annotation["vertices"][edge[0]]
v1_global = annotation["vertices"][edge[1]]
@@ -357,7 +361,7 @@ class SvgWriter:
classes.append("material-{}".format(re.sub("[^0-9a-zA-Z]+", "", slot.material.name)))
global_id = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId
classes.append("globalid-{}".format(global_id))
for attribute in self.ifc_cutter.attributes:
for attribute in self.annotations.get("attributes", []):
result = self.get_obj_value(obj, attribute)
if result:
classes.append(
@@ -435,7 +439,7 @@ class SvgWriter:
x_offset = self.raw_width / 2
y_offset = self.raw_height / 2
for text_obj in self.ifc_cutter.text_objs:
for text_obj in self.annotations.get("text_objs", []):
text_position = self.project_point_onto_camera(text_obj.location)
text_position = Vector(((x_offset + text_position.x), (y_offset - text_position.y)))
@@ -473,8 +477,8 @@ class SvgWriter:
alignment_baseline = "baseline"
text_body = text_obj.data.body
if text_obj.name in self.ifc_cutter.template_variables:
text_body = pystache.render(text_body, self.ifc_cutter.template_variables[text_obj.name])
if text_obj.name in self.annotations.get("template_variables", {}):
text_body = pystache.render(text_body, self.annotations["template_variables"][text_obj.name])
for line_number, text_line in enumerate(text_body.split("\n")):
self.svg.add(
@@ -587,17 +591,18 @@ class SvgWriter:
)
def project_point_onto_camera(self, point):
return self.ifc_cutter.camera_obj.matrix_world.inverted() @ geometry.intersect_line_plane(
return self.camera.matrix_world.inverted() @ geometry.intersect_line_plane(
point.xyz,
point.xyz - Vector(self.ifc_cutter.section_box["projection"]),
self.ifc_cutter.camera_obj.location,
Vector(self.ifc_cutter.section_box["projection"]),
point.xyz - Vector(self.camera_projection),
self.camera.location,
Vector(self.camera_projection),
)
def get_spline_points(self, spline):
return spline.bezier_points if spline.bezier_points else spline.points
def draw_cut_polygons(self):
return # deprecate?
for polygon in self.ifc_cutter.cut_polygons:
self.draw_polygon(polygon, "cut")
-29
View File
@@ -16,12 +16,10 @@ import numpy as np
from . import export_ifc
from . import import_ifc
from . import cut_ifc
from . import svgwriter
from . import sheeter
from . import scheduler
from . import schema
from . import ifc
from . import annotation
from . import helper
from bpy_extras.io_utils import ImportHelper
from mathutils import Vector, Matrix, Euler, geometry
@@ -1102,33 +1100,6 @@ class SelectDocIfcFile(bpy.types.Operator):
return {"RUNNING_MODAL"}
class AddAnnotation(bpy.types.Operator):
bl_idname = "bim.add_annotation"
bl_label = "Add Annotation"
obj_name: bpy.props.StringProperty()
data_type: bpy.props.StringProperty()
def execute(self, context):
if not bpy.context.scene.camera:
return {"FINISHED"}
if self.data_type == "text":
if bpy.context.selected_objects:
for selected_object in bpy.context.selected_objects:
obj = annotation.Annotator.add_text(related_element=selected_object)
else:
obj = annotation.Annotator.add_text()
else:
obj = annotation.Annotator.get_annotation_obj(self.obj_name, self.data_type)
if self.obj_name == "Break":
obj = annotation.Annotator.add_plane_to_annotation(obj)
else:
obj = annotation.Annotator.add_line_to_annotation(obj)
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode="EDIT")
return {"FINISHED"}
class GenerateReferences(bpy.types.Operator):
bl_idname = "bim.generate_references"
bl_label = "Generate References"
+1 -1
View File
@@ -6,7 +6,7 @@ import ifcopenshell
from . import export_ifc
from . import schema
from . import ifc
from . import annotation
import blenderbim.bim.module.drawing.annotation as annotation
from . import decoration
import bpy
from blenderbim.bim.handler import purge_module_data