diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index eff052bcc9..8e780f941b 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -117,24 +117,15 @@ if bpy is not None: operator.AddSectionsAnnotations, prop.StrProperty, prop.Attribute, - prop.Variable, - prop.Drawing, - prop.Schedule, - prop.DrawingStyle, - prop.Sheet, prop.BIMProperties, - prop.DocProperties, prop.IfcParameter, prop.PsetQto, prop.GlobalId, - prop.RepresentationItem, prop.BIMObjectProperties, prop.BIMMaterialProperties, prop.SweptSolid, prop.ItemSlotMap, prop.BIMMeshProperties, - prop.BIMCameraProperties, - prop.BIMTextProperties, ui.BIM_PT_section_plane, ui.BIM_PT_drawings, ui.BIM_PT_schedules, @@ -176,7 +167,6 @@ if bpy is not None: bpy.types.TOPBAR_MT_file_export.append(menu_func_export) bpy.types.TOPBAR_MT_file_import.append(menu_func_import) bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties) - bpy.types.Scene.DocProperties = bpy.props.PointerProperty(type=prop.DocProperties) bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) # Check if we need this @@ -184,15 +174,12 @@ if bpy is not None: bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties) bpy.types.Curve.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties) bpy.types.Camera.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties) - bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties) - bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties) bpy.types.SCENE_PT_unit.append(ui.ifc_units) for module in modules.values(): module.register() bpy.app.handlers.depsgraph_update_pre.append(operator.depsgraph_update_pre_handler) - bpy.app.handlers.load_post.append(handler.toggleDecorationsOnLoad) def unregister(): for cls in reversed(classes): @@ -203,7 +190,6 @@ if bpy is not None: bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) del bpy.types.Scene.BIMProperties - del bpy.types.Scene.DocProperties del bpy.types.Object.BIMObjectProperties del bpy.types.Material.BIMObjectProperties del bpy.types.Collection.BIMObjectProperties # Check if we need this @@ -211,12 +197,9 @@ if bpy is not None: del bpy.types.Mesh.BIMMeshProperties del bpy.types.Curve.BIMMeshProperties del bpy.types.Camera.BIMMeshProperties - del bpy.types.Camera.BIMCameraProperties - del bpy.types.TextCurve.BIMTextProperties bpy.types.SCENE_PT_unit.remove(ui.ifc_units) for module in reversed(list(modules.values())): module.unregister() bpy.app.handlers.depsgraph_update_pre.remove(operator.depsgraph_update_pre_handler) - bpy.app.handlers.load_post.remove(handler.toggleDecorationsOnLoad) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 508dcc6958..271ad0893e 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -1,7 +1,6 @@ import bpy import json import addon_utils -import blenderbim.bim.decoration as decoration import ifcopenshell.api.owner.settings from bpy.app.handlers import persistent from blenderbim.bim.ifc import IfcStore @@ -252,12 +251,3 @@ def setDefaultProperties(scene): drawing_style.name = "Blender Default" drawing_style.render_type = "DEFAULT" bpy.ops.bim.save_drawing_style(index="2") - - -@persistent -def toggleDecorationsOnLoad(*args): - toggle = bpy.context.scene.DocProperties.should_draw_decorations - if toggle: - decoration.DecorationsHandler.install(bpy.context) - else: - decoration.DecorationsHandler.uninstall() diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index b8337d1c57..4d7666e9eb 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -97,18 +97,6 @@ def get_project_collection(scene): return colls[0] -def get_active_drawing(scene): - """Get active drawing collection and camera""" - props = scene.DocProperties - if props.active_drawing_index is None or len(props.drawings) == 0: - return None, None - try: - drawing = props.drawings[props.active_drawing_index] - return scene.collection.children["Views"].children[f"IfcGroup/{drawing.name}"], drawing.camera - except (KeyError, IndexError): - raise RuntimeError("missing drawing collection") - - def ortho_view_frame(camera, margin=0.015): """Calculates 2d bounding box of camera view area. diff --git a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py index 0a161e652e..c2f248d55c 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py @@ -1,17 +1,31 @@ import bpy -from . import ui, operator +from . import ui, prop, operator, handler classes = ( operator.AddDrawing, operator.CreateDrawing, operator.AddAnnotation, + prop.Variable, + prop.Drawing, + prop.Schedule, + prop.DrawingStyle, + prop.Sheet, + prop.DocProperties, + prop.BIMCameraProperties, + prop.BIMTextProperties, ui.BIM_PT_camera, ) def register(): - pass + bpy.types.Scene.DocProperties = bpy.props.PointerProperty(type=prop.DocProperties) + bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties) + bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties) + bpy.app.handlers.load_post.append(handler.toggleDecorationsOnLoad) def unregister(): - pass + del bpy.types.Scene.DocProperties + del bpy.types.Camera.BIMCameraProperties + del bpy.types.TextCurve.BIMTextProperties + bpy.app.handlers.load_post.remove(handler.toggleDecorationsOnLoad) diff --git a/src/blenderbim/blenderbim/bim/decoration.py b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py similarity index 99% rename from src/blenderbim/blenderbim/bim/decoration.py rename to src/blenderbim/blenderbim/bim/module/drawing/decoration.py index 2cefdb728a..ac36c8506c 100644 --- a/src/blenderbim/blenderbim/bim/decoration.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py @@ -13,7 +13,7 @@ import gpu import bgl from gpu.types import GPUShader, GPUBatch, GPUIndexBuf, GPUVertBuf, GPUVertFormat from gpu_extras.batch import batch_for_shader -from . import helper +import blenderbim.bim.module.drawing.helper as helper class BaseDecorator(): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/handler.py b/src/blenderbim/blenderbim/bim/module/drawing/handler.py new file mode 100644 index 0000000000..961c41c92d --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/drawing/handler.py @@ -0,0 +1,12 @@ +import bpy +import blenderbim.bim.module.drawing.decoration as decoration +from bpy.app.handlers import persistent + + +@persistent +def toggleDecorationsOnLoad(*args): + toggle = bpy.context.scene.DocProperties.should_draw_decorations + if toggle: + decoration.DecorationsHandler.install(bpy.context) + else: + decoration.DecorationsHandler.uninstall() diff --git a/src/blenderbim/blenderbim/bim/module/drawing/helper.py b/src/blenderbim/blenderbim/bim/module/drawing/helper.py index c45ea17820..8f299add09 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/helper.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/helper.py @@ -139,3 +139,15 @@ def format_distance(value, isArea=False, hide_units=True): tx_dist = fmt % value return tx_dist + + +def get_active_drawing(scene): + """Get active drawing collection and camera""" + props = scene.DocProperties + if props.active_drawing_index is None or len(props.drawings) == 0: + return None, None + try: + drawing = props.drawings[props.active_drawing_index] + return scene.collection.children["Views"].children[f"IfcGroup/{drawing.name}"], drawing.camera + except (KeyError, IndexError): + raise RuntimeError("missing drawing collection") diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 030e10778c..ca2cb727e8 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -7,7 +7,6 @@ import ifcopenshell.util.representation 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 from ifcopenshell.api.pset.data import Data as PsetData @@ -15,6 +14,15 @@ from ifcopenshell.api.pset.data import Data as PsetData cwd = os.path.dirname(os.path.realpath(__file__)) +def open_with_user_command(user_command, path): + if user_command: + commands = eval(user_command) + for command in commands: + subprocess.run(command) + else: + webbrowser.open("file://" + path) + + class AddDrawing(bpy.types.Operator): bl_idname = "bim.add_drawing" bl_label = "Add Drawing" @@ -62,6 +70,14 @@ class CreateDrawing(bpy.types.Operator): bl_label = "Create Drawing" def execute(self, context): + self.camera = context.scene.camera + if ( + not (self.camera.type == "CAMERA" and self.camera.data.type == "ORTHO") + or not self.camera.BIMObjectProperties.ifc_definition_id + ): + return + self.props = context.scene.DocProperties + self.drawing_name = IfcStore.get_file().by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name base_svg = self.ifc_to_svg(context) annotation_svg = self.annotation_to_svg(context) svg_path = self.combine_svgs(context, base_svg, annotation_svg) @@ -70,7 +86,7 @@ class CreateDrawing(bpy.types.Operator): def combine_svgs(self, context, base, annotation): # Hacky :) - svg_path = context.scene.BIMProperties.ifc_file[0:-4] + ".svg" + svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg") with open(svg_path, "w") as outfile: with open(base) as infile: for line in infile: @@ -85,7 +101,9 @@ class CreateDrawing(bpy.types.Operator): return svg_path def ifc_to_svg(self, context): - svg_path = context.scene.BIMProperties.ifc_file[0:-4] + "-base.svg" + svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-base.svg") + if os.path.isfile(svg_path) and not self.props.should_regenerate_base_layer: + return svg_path ifcconvert_path = os.path.join(cwd, "..", "..", "..", "libs", "IfcConvert") subprocess.run( [ @@ -109,11 +127,11 @@ class CreateDrawing(bpy.types.Operator): 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_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-annotation.svg") + if os.path.isfile(svg_path) and not self.props.should_regenerate_annotation_layer: + return svg_path + camera = self.camera svg_writer = svgwriter.SvgWriter() if camera.data.BIMCameraProperties.diagram_scale == "CUSTOM": @@ -141,7 +159,7 @@ class CreateDrawing(bpy.types.Operator): 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.output = svg_path svg_writer.data_dir = bpy.context.scene.BIMProperties.data_dir svg_writer.vector_style = drawing_style.vector_style svg_writer.camera = camera diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py new file mode 100644 index 0000000000..35952dfc37 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -0,0 +1,278 @@ +import os +import bpy +import blenderbim.bim.module.drawing.annotation as annotation +import blenderbim.bim.module.drawing.decoration as decoration +from pathlib import Path +from blenderbim.bim.prop import Attribute, StrProperty +from bpy.types import PropertyGroup +from bpy.props import ( + PointerProperty, + StringProperty, + EnumProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + CollectionProperty, +) + + +diagram_scales_enum = [] +titleblocks_enum = [] +sheets_enum = [] +vector_styles_enum = [] + + +def purge(): + global diagram_scales_enum + global titleblocks_enum + global sheets_enum + global vector_styles_enum + diagram_scales_enum = [] + titleblocks_enum = [] + sheets_enum = [] + vector_styles_enum = [] + + +def getDiagramScales(self, context): + global diagram_scales_enum + if ( + len(diagram_scales_enum) < 1 + or (context.scene.unit_settings.system == "IMPERIAL" and len(diagram_scales_enum) == 13) + or (context.scene.unit_settings.system == "METRIC" and len(diagram_scales_enum) == 31) + ): + if context.scene.unit_settings.system == "IMPERIAL": + diagram_scales_enum = [ + ("CUSTOM", "Custom", ""), + ("1'=1'-0\"|1/1", "1'=1'-0\"", ""), + ('6"=1\'-0"|1/6', '6"=1\'-0"', ""), + ('1-1/2"=1\'-0"|1/8', '1-1/2"=1\'-0"', ""), + ('1"=1\'-0"|1/12', '1"=1\'-0"', ""), + ('3/4"=1\'-0"|1/16', '3/4"=1\'-0"', ""), + ('1/2"=1\'-0"|1/24', '1/2"=1\'-0"', ""), + ('3/8"=1\'-0"|1/32', '3/8"=1\'-0"', ""), + ('1/4"=1\'-0"|1/48', '1/4"=1\'-0"', ""), + ('3/16"=1\'-0"|1/64', '3/16"=1\'-0"', ""), + ('1/8"=1\'-0"|1/96', '1/8"=1\'-0"', ""), + ('3/32"=1\'-0"|1/128', '3/32"=1\'-0"', ""), + ('1/16"=1\'-0"|1/192', '1/16"=1\'-0"', ""), + ('1/32"=1\'-0"|1/384', '1/32"=1\'-0"', ""), + ('1/64"=1\'-0"|1/768', '1/64"=1\'-0"', ""), + ('1/128"=1\'-0"|1/1536', '1/128"=1\'-0"', ""), + ("1\"=10'|1/120", "1\"=10'", ""), + ("1\"=20'|1/240", "1\"=20'", ""), + ("1\"=30'|1/360", "1\"=30'", ""), + ("1\"=40'|1/480", "1\"=40'", ""), + ("1\"=50'|1/600", "1\"=50'", ""), + ("1\"=60'|1/720", "1\"=60'", ""), + ("1\"=70'|1/840", "1\"=70'", ""), + ("1\"=80'|1/960", "1\"=80'", ""), + ("1\"=90'|1/1080", "1\"=90'", ""), + ("1\"=100'|1/1200", "1\"=100'", ""), + ("1\"=150'|1/1800", "1\"=150'", ""), + ("1\"=200'|1/2400", "1\"=200'", ""), + ("1\"=300'|1/3600", "1\"=300'", ""), + ("1\"=400'|1/4800", "1\"=400'", ""), + ("1\"=500'|1/6000", "1\"=500'", ""), + ] + else: + diagram_scales_enum = [ + ("CUSTOM", "Custom", ""), + ("1:5000|1/5000", "1:5000", ""), + ("1:2000|1/2000", "1:2000", ""), + ("1:1000|1/1000", "1:1000", ""), + ("1:500|1/500", "1:500", ""), + ("1:200|1/200", "1:200", ""), + ("1:100|1/100", "1:100", ""), + ("1:50|1/50", "1:50", ""), + ("1:20|1/20", "1:20", ""), + ("1:10|1/10", "1:10", ""), + ("1:5|1/5", "1:5", ""), + ("1:2|1/2", "1:2", ""), + ("1:1|1/1", "1:1", ""), + ] + return diagram_scales_enum + + +def updateDrawingName(self, context): + if not self.camera: + return + if self.camera.name == self.name: + return + self.camera.name = "IfcGroup/{}".format(self.name) + self.camera.users_collection[0].name = self.camera.name + self.name = self.camera.name.split("/")[1] + + +def refreshActiveDrawingIndex(self, context): + bpy.ops.bim.activate_view(drawing_index=context.scene.DocProperties.active_drawing_index) + + +def getTitleblocks(self, context): + global titleblocks_enum + if len(titleblocks_enum) < 1: + titleblocks_enum.clear() + for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, "templates", "titleblocks")).glob( + "*.svg" + ): + f = str(filename.stem) + titleblocks_enum.append((f, f, "")) + return titleblocks_enum + + +def refreshTitleblocks(self, context): + global titleblocks_enum + titleblocks_enum.clear() + getTitleblocks(self, context) + + +def toggleDecorations(self, context): + toggle = self.should_draw_decorations + if toggle: + decoration.DecorationsHandler.install(context) + else: + decoration.DecorationsHandler.uninstall() + + +def getVectorStyles(self, context): + global vector_styles_enum + if len(vector_styles_enum) < 1: + sheets_enum.clear() + for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, "styles")).glob("*.css"): + f = str(filename.stem) + vector_styles_enum.append((f, f, "")) + return vector_styles_enum + + +def refreshFontSize(self, context): + annotation.Annotator.resize_text(context.active_object) + + +class Variable(PropertyGroup): + name: StringProperty(name="Name") + prop_key: StringProperty(name="Property Key") + + +class Drawing(PropertyGroup): + name: StringProperty(name="Name", update=updateDrawingName) + camera: PointerProperty(name="Camera", type=bpy.types.Object) + + +class Schedule(PropertyGroup): + name: StringProperty(name="Name") + file: StringProperty(name="File") + + +class Sheet(PropertyGroup): + def set_name(self, new): + old = self.get("name") + path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets") + if old and os.path.isfile(os.path.join(path, old + ".svg")): + os.rename(os.path.join(path, old + ".svg"), os.path.join(path, new + ".svg")) + self["name"] = new + + def get_name(self): + return self.get("name") + + name: StringProperty(name="Name", get=get_name, set=set_name) + drawings: CollectionProperty(name="Drawings", type=Drawing) + active_drawing_index: IntProperty(name="Active Drawing Index") + + +class DrawingStyle(PropertyGroup): + name: StringProperty(name="Name") + raster_style: StringProperty(name="Raster Style") + render_type: EnumProperty( + items=[ + ("NONE", "None", ""), + ("DEFAULT", "Default", ""), + ("VIEWPORT", "Viewport", ""), + ], + name="Render Type", + default="VIEWPORT", + ) + vector_style: EnumProperty(items=getVectorStyles, name="Vector Style") + include_query: StringProperty(name="Include Query") + exclude_query: StringProperty(name="Exclude Query") + attributes: CollectionProperty(name="Attributes", type=StrProperty) + + +class DocProperties(PropertyGroup): + should_regenerate_base_layer: BoolProperty(name="Regenerate Base Layer", default=True) + should_regenerate_annotation_layer: BoolProperty(name="Regenerate Annotation Layer", default=True) + should_recut: BoolProperty(name="Should Recut", default=True) + should_recut_selected: BoolProperty(name="Should Recut Selected Only", default=False) + should_extract: BoolProperty(name="Should Extract", default=True) + drawings: CollectionProperty(name="Drawings", type=Drawing) + active_drawing_index: IntProperty(name="Active Drawing Index", update=refreshActiveDrawingIndex) + current_drawing_index: IntProperty(name="Current Drawing Index") + schedules: CollectionProperty(name="Schedules", type=Schedule) + active_schedule_index: IntProperty(name="Active Schedule Index") + titleblock: EnumProperty(items=getTitleblocks, name="Titleblock", update=refreshTitleblocks) + sheets: CollectionProperty(name="Sheets", type=Sheet) + active_sheet_index: IntProperty(name="Active Sheet Index") + ifc_files: CollectionProperty(name="IFCs", type=StrProperty) + drawing_styles: CollectionProperty(name="Drawing Styles", type=DrawingStyle) + should_draw_decorations: BoolProperty(name="Should Draw Decorations", update=toggleDecorations) + decorations_colour: FloatVectorProperty( + name="Decorations Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4 + ) + + +class BIMCameraProperties(PropertyGroup): + view_name: StringProperty(name="View Name") + target_view: EnumProperty( + items=[ + ("PLAN_VIEW", "PLAN_VIEW", ""), + ("ELEVATION_VIEW", "ELEVATION_VIEW", ""), + ("SECTION_VIEW", "SECTION_VIEW", ""), + ("REFLECTED_PLAN_VIEW", "REFLECTED_PLAN_VIEW", ""), + ("MODEL_VIEW", "MODEL_VIEW", ""), + ], + name="Target View", + default="PLAN_VIEW", + ) + diagram_scale: EnumProperty(items=getDiagramScales, name="Drawing Scale") + custom_diagram_scale: StringProperty(name="Custom Scale") + raster_x: IntProperty(name="Raster X", default=1000) + raster_y: IntProperty(name="Raster Y", default=1000) + is_nts: BoolProperty(name="Is NTS") + cut_objects: EnumProperty( + items=[ + ( + ".IfcWall|.IfcSlab|.IfcCurtainWall|.IfcStair|.IfcStairFlight|.IfcColumn|.IfcBeam|.IfcMember|.IfcCovering|.IfcSpace", + "Overall Plan / Section", + "", + ), + (".IfcElement", "Detail Drawing", ""), + ("CUSTOM", "Custom", ""), + ], + name="Cut Objects", + ) + cut_objects_custom: StringProperty(name="Custom Cut") + active_drawing_style_index: IntProperty(name="Active Drawing Style Index") + + +class BIMTextProperties(PropertyGroup): + font_size: EnumProperty( + items=[ + ("1.8", "1.8 - Small", ""), + ("2.5", "2.5 - Regular", ""), + ("3.5", "3.5 - Large", ""), + ("5.0", "5.0 - Header", ""), + ("7.0", "7.0 - Title", ""), + ], + update=refreshFontSize, + name="Font Size", + ) + symbol: EnumProperty( + items=[ + ("None", "None", ""), + ("rectangle-tag", "Rectangle Tag", ""), + ("door-tag", "Door Tag", ""), + ], + update=refreshFontSize, + name="Symbol", + ) + related_element: PointerProperty(name="Related Element", type=bpy.types.Object) + variables: CollectionProperty(name="Variables", type=Variable) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index fd7400b1f9..655bd3c019 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -29,6 +29,10 @@ class BIM_PT_camera(Panel): layout.label(text="Generation Options:") + row = layout.row() + row.prop(dprops, "should_regenerate_base_layer") + row = layout.row() + row.prop(dprops, "should_regenerate_annotation_layer") row = layout.row() row.prop(dprops, "should_recut") row = layout.row() diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index aeff072a13..d6783310c2 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -13,6 +13,8 @@ import ifcopenshell.util.geolocation import ifcopenshell.util.element import ifcopenshell.util.representation import ifcopenshell.util.schema +# Deleting the below drawing import breaks svgwrite's ElementTree appending because ... magic? +import blenderbim.bim.module.drawing import numpy as np from . import export_ifc from . import import_ifc diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index cf7dce508a..58f5e56fae 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -1,14 +1,9 @@ -import json import os -from pathlib import Path +import bpy +import json import importlib import ifcopenshell -from . import export_ifc -from . import schema -from . import ifc -import blenderbim.bim.module.drawing.annotation as annotation -from . import decoration -import bpy +import ifcopenshell.util.pset from blenderbim.bim.handler import purge_module_data from blenderbim.bim.ifc import IfcStore from bpy.types import PropertyGroup @@ -25,14 +20,14 @@ from bpy.props import ( cwd = os.path.dirname(os.path.realpath(__file__)) -diagram_scales_enum = [] -titleblocks_enum = [] materialpsetnames_enum = [] contexts_enum = [] subcontexts_enum = [] target_views_enum = [] -sheets_enum = [] -vector_styles_enum = [] + + +def getAttributeEnumValues(self, context): + return [(e, e, "") for e in json.loads(self.enum_items)] def updateIfcFile(self, context): @@ -42,114 +37,11 @@ def updateIfcFile(self, context): purge_module_data() -def getDiagramScales(self, context): - global diagram_scales_enum - if ( - len(diagram_scales_enum) < 1 - or (bpy.context.scene.unit_settings.system == "IMPERIAL" and len(diagram_scales_enum) == 13) - or (bpy.context.scene.unit_settings.system == "METRIC" and len(diagram_scales_enum) == 31) - ): - if bpy.context.scene.unit_settings.system == "IMPERIAL": - diagram_scales_enum = [ - ("CUSTOM", "Custom", ""), - ("1'=1'-0\"|1/1", "1'=1'-0\"", ""), - ('6"=1\'-0"|1/6', '6"=1\'-0"', ""), - ('1-1/2"=1\'-0"|1/8', '1-1/2"=1\'-0"', ""), - ('1"=1\'-0"|1/12', '1"=1\'-0"', ""), - ('3/4"=1\'-0"|1/16', '3/4"=1\'-0"', ""), - ('1/2"=1\'-0"|1/24', '1/2"=1\'-0"', ""), - ('3/8"=1\'-0"|1/32', '3/8"=1\'-0"', ""), - ('1/4"=1\'-0"|1/48', '1/4"=1\'-0"', ""), - ('3/16"=1\'-0"|1/64', '3/16"=1\'-0"', ""), - ('1/8"=1\'-0"|1/96', '1/8"=1\'-0"', ""), - ('3/32"=1\'-0"|1/128', '3/32"=1\'-0"', ""), - ('1/16"=1\'-0"|1/192', '1/16"=1\'-0"', ""), - ('1/32"=1\'-0"|1/384', '1/32"=1\'-0"', ""), - ('1/64"=1\'-0"|1/768', '1/64"=1\'-0"', ""), - ('1/128"=1\'-0"|1/1536', '1/128"=1\'-0"', ""), - ("1\"=10'|1/120", "1\"=10'", ""), - ("1\"=20'|1/240", "1\"=20'", ""), - ("1\"=30'|1/360", "1\"=30'", ""), - ("1\"=40'|1/480", "1\"=40'", ""), - ("1\"=50'|1/600", "1\"=50'", ""), - ("1\"=60'|1/720", "1\"=60'", ""), - ("1\"=70'|1/840", "1\"=70'", ""), - ("1\"=80'|1/960", "1\"=80'", ""), - ("1\"=90'|1/1080", "1\"=90'", ""), - ("1\"=100'|1/1200", "1\"=100'", ""), - ("1\"=150'|1/1800", "1\"=150'", ""), - ("1\"=200'|1/2400", "1\"=200'", ""), - ("1\"=300'|1/3600", "1\"=300'", ""), - ("1\"=400'|1/4800", "1\"=400'", ""), - ("1\"=500'|1/6000", "1\"=500'", ""), - ] - else: - diagram_scales_enum = [ - ("CUSTOM", "Custom", ""), - ("1:5000|1/5000", "1:5000", ""), - ("1:2000|1/2000", "1:2000", ""), - ("1:1000|1/1000", "1:1000", ""), - ("1:500|1/500", "1:500", ""), - ("1:200|1/200", "1:200", ""), - ("1:100|1/100", "1:100", ""), - ("1:50|1/50", "1:50", ""), - ("1:20|1/20", "1:20", ""), - ("1:10|1/10", "1:10", ""), - ("1:5|1/5", "1:5", ""), - ("1:2|1/2", "1:2", ""), - ("1:1|1/1", "1:1", ""), - ] - return diagram_scales_enum - - -def updateDrawingName(self, context): - if not self.camera: - return - if self.camera.name == self.name: - return - self.camera.name = "IfcGroup/{}".format(self.name) - self.camera.users_collection[0].name = self.camera.name - self.name = self.camera.name.split("/")[1] - - -def refreshActiveDrawingIndex(self, context): - bpy.ops.bim.activate_view(drawing_index=context.scene.DocProperties.active_drawing_index) - - -def getAttributeEnumValues(self, context): - return [(e, e, "") for e in json.loads(self.enum_items)] - - -def getTitleblocks(self, context): - global titleblocks_enum - if len(titleblocks_enum) < 1: - titleblocks_enum.clear() - for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, "templates", "titleblocks")).glob( - "*.svg" - ): - f = str(filename.stem) - titleblocks_enum.append((f, f, "")) - return titleblocks_enum - - -def refreshTitleblocks(self, context): - global titleblocks_enum - titleblocks_enum.clear() - getTitleblocks(self, context) - - -def toggleDecorations(self, context): - toggle = self.should_draw_decorations - if toggle: - decoration.DecorationsHandler.install(context) - else: - decoration.DecorationsHandler.uninstall() - - def getMaterialPsetNames(self, context): global materialpsetnames_enum materialpsetnames_enum.clear() - pset_names = schema.ifc.psetqto.get_applicable_names("IfcMaterial", pset_only=True) + psetqto = ifcopenshell.util.pset.get_template("IFC4") + pset_names = psetqto.get_applicable_names("IfcMaterial", pset_only=True) materialpsetnames_enum.extend([(p, p, "") for p in pset_names]) return materialpsetnames_enum @@ -215,29 +107,10 @@ def getTargetViews(self, context): return target_views_enum -def getVectorStyles(self, context): - global vector_styles_enum - if len(vector_styles_enum) < 1: - sheets_enum.clear() - for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, "styles")).glob("*.css"): - f = str(filename.stem) - vector_styles_enum.append((f, f, "")) - return vector_styles_enum - - -def refreshFontSize(self, context): - annotation.Annotator.resize_text(context.active_object) - - class StrProperty(PropertyGroup): pass -class Variable(PropertyGroup): - name: StringProperty(name="Name") - prop_key: StringProperty(name="Property Key") - - def updateAttributeStringValue(self, context): updateAttributeValue(self, self.string_value) @@ -276,129 +149,6 @@ class Attribute(PropertyGroup): enum_value: EnumProperty(items=getAttributeEnumValues, name="Value", update=updateAttributeEnumValue) -class Drawing(PropertyGroup): - name: StringProperty(name="Name", update=updateDrawingName) - camera: PointerProperty(name="Camera", type=bpy.types.Object) - - -class Schedule(PropertyGroup): - name: StringProperty(name="Name") - file: StringProperty(name="File") - - -class Sheet(PropertyGroup): - def set_name(self, new): - old = self.get("name") - path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets") - if old and os.path.isfile(os.path.join(path, old + ".svg")): - os.rename(os.path.join(path, old + ".svg"), os.path.join(path, new + ".svg")) - self["name"] = new - - def get_name(self): - return self.get("name") - - name: StringProperty(name="Name", get=get_name, set=set_name) - drawings: CollectionProperty(name="Drawings", type=Drawing) - active_drawing_index: IntProperty(name="Active Drawing Index") - - -class DrawingStyle(PropertyGroup): - name: StringProperty(name="Name") - raster_style: StringProperty(name="Raster Style") - render_type: EnumProperty( - items=[ - ("NONE", "None", ""), - ("DEFAULT", "Default", ""), - ("VIEWPORT", "Viewport", ""), - ], - name="Render Type", - default="VIEWPORT", - ) - vector_style: EnumProperty(items=getVectorStyles, name="Vector Style") - include_query: StringProperty(name="Include Query") - exclude_query: StringProperty(name="Exclude Query") - attributes: CollectionProperty(name="Attributes", type=StrProperty) - - -class DocProperties(PropertyGroup): - should_recut: BoolProperty(name="Should Recut", default=True) - should_recut_selected: BoolProperty(name="Should Recut Selected Only", default=False) - should_extract: BoolProperty(name="Should Extract", default=True) - drawings: CollectionProperty(name="Drawings", type=Drawing) - active_drawing_index: IntProperty(name="Active Drawing Index", update=refreshActiveDrawingIndex) - current_drawing_index: IntProperty(name="Current Drawing Index") - schedules: CollectionProperty(name="Schedules", type=Schedule) - active_schedule_index: IntProperty(name="Active Schedule Index") - titleblock: EnumProperty(items=getTitleblocks, name="Titleblock", update=refreshTitleblocks) - sheets: CollectionProperty(name="Sheets", type=Sheet) - active_sheet_index: IntProperty(name="Active Sheet Index") - ifc_files: CollectionProperty(name="IFCs", type=StrProperty) - drawing_styles: CollectionProperty(name="Drawing Styles", type=DrawingStyle) - should_draw_decorations: BoolProperty(name="Should Draw Decorations", update=toggleDecorations) - decorations_colour: FloatVectorProperty( - name="Decorations Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4 - ) - - -class BIMCameraProperties(PropertyGroup): - view_name: StringProperty(name="View Name") - target_view: EnumProperty( - items=[ - ("PLAN_VIEW", "PLAN_VIEW", ""), - ("ELEVATION_VIEW", "ELEVATION_VIEW", ""), - ("SECTION_VIEW", "SECTION_VIEW", ""), - ("REFLECTED_PLAN_VIEW", "REFLECTED_PLAN_VIEW", ""), - ("MODEL_VIEW", "MODEL_VIEW", ""), - ], - name="Target View", - default="PLAN_VIEW", - ) - diagram_scale: EnumProperty(items=getDiagramScales, name="Drawing Scale") - custom_diagram_scale: StringProperty(name="Custom Scale") - raster_x: IntProperty(name="Raster X", default=1000) - raster_y: IntProperty(name="Raster Y", default=1000) - is_nts: BoolProperty(name="Is NTS") - cut_objects: EnumProperty( - items=[ - ( - ".IfcWall|.IfcSlab|.IfcCurtainWall|.IfcStair|.IfcStairFlight|.IfcColumn|.IfcBeam|.IfcMember|.IfcCovering|.IfcSpace", - "Overall Plan / Section", - "", - ), - (".IfcElement", "Detail Drawing", ""), - ("CUSTOM", "Custom", ""), - ], - name="Cut Objects", - ) - cut_objects_custom: StringProperty(name="Custom Cut") - active_drawing_style_index: IntProperty(name="Active Drawing Style Index") - - -class BIMTextProperties(PropertyGroup): - font_size: EnumProperty( - items=[ - ("1.8", "1.8 - Small", ""), - ("2.5", "2.5 - Regular", ""), - ("3.5", "3.5 - Large", ""), - ("5.0", "5.0 - Header", ""), - ("7.0", "7.0 - Title", ""), - ], - update=refreshFontSize, - name="Font Size", - ) - symbol: EnumProperty( - items=[ - ("None", "None", ""), - ("rectangle-tag", "Rectangle Tag", ""), - ("door-tag", "Door Tag", ""), - ], - update=refreshFontSize, - name="Symbol", - ) - related_element: PointerProperty(name="Related Element", type=bpy.types.Object) - variables: CollectionProperty(name="Variables", type=Variable) - - class BIMProperties(PropertyGroup): schema_dir: StringProperty(default=os.path.join(cwd, "schema") + os.path.sep, name="Schema Directory") data_dir: StringProperty(default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory") @@ -516,11 +266,6 @@ class SweptSolid(PropertyGroup): extrusion: StringProperty(name="Extrusion") -class RepresentationItem(PropertyGroup): - name: StringProperty(name="Name") - vgroup: StringProperty(name="Vertex Group") - - class ItemSlotMap(PropertyGroup): name: StringProperty(name="Item Element ID") slot_index: IntProperty(name="Material Slot Index")