diff --git a/src/blenderbim/blenderbim/bim/data/assets/shading_styles.json b/src/blenderbim/blenderbim/bim/data/assets/shading_styles.json new file mode 100644 index 0000000000..01dd9742b3 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/data/assets/shading_styles.json @@ -0,0 +1,125 @@ +{ + "Technical": { + "raster_style": { + "bpy.data.worlds[0].color": [ + 1, + 1, + 1 + ], + "scene.render.engine": "BLENDER_WORKBENCH", + "scene.render.film_transparent": false, + "scene.display.shading.show_object_outline": true, + "scene.display.shading.show_cavity": false, + "scene.display.shading.cavity_type": "BOTH", + "scene.display.shading.curvature_ridge_factor": 1, + "scene.display.shading.curvature_valley_factor": 1, + "scene.view_settings.view_transform": "Standard", + "scene.display.shading.light": "FLAT", + "scene.display.shading.color_type": "SINGLE", + "scene.display.shading.single_color": [ + 1, + 1, + 1 + ], + "scene.display.shading.show_shadows": false, + "scene.display.shading.shadow_intensity": 0.5, + "scene.display.light_direction": [ + 0.5, + 0.5, + 0.5 + ], + "scene.view_settings.use_curve_mapping": false, + "space.overlay.show_wireframes": true, + "space.overlay.wireframe_threshold": 0, + "space.overlay.show_floor": false, + "space.overlay.show_axis_x": false, + "space.overlay.show_axis_y": false, + "space.overlay.show_axis_z": false, + "space.overlay.show_object_origins": false, + "space.overlay.show_relationship_lines": false + }, + "render_type": "VIEWPORT" + }, + "Shaded": { + "raster_style": { + "bpy.data.worlds[0].color": [ + 1, + 1, + 1 + ], + "scene.render.engine": "BLENDER_WORKBENCH", + "scene.render.film_transparent": false, + "scene.display.shading.show_object_outline": true, + "scene.display.shading.show_cavity": true, + "scene.display.shading.cavity_type": "BOTH", + "scene.display.shading.curvature_ridge_factor": 1, + "scene.display.shading.curvature_valley_factor": 1, + "scene.view_settings.view_transform": "Standard", + "scene.display.shading.light": "STUDIO", + "scene.display.shading.color_type": "MATERIAL", + "scene.display.shading.single_color": [ + 1, + 1, + 1 + ], + "scene.display.shading.show_shadows": true, + "scene.display.shading.shadow_intensity": 0.5, + "scene.display.light_direction": [ + 0.5, + 0.5, + 0.5 + ], + "scene.view_settings.use_curve_mapping": false, + "space.overlay.show_wireframes": false, + "space.overlay.wireframe_threshold": 0, + "space.overlay.show_floor": false, + "space.overlay.show_axis_x": false, + "space.overlay.show_axis_y": false, + "space.overlay.show_axis_z": false, + "space.overlay.show_object_origins": false, + "space.overlay.show_relationship_lines": false + }, + "render_type": "VIEWPORT" + }, + "Blender Default": { + "raster_style": { + "bpy.data.worlds[0].color": [ + 0.05087608844041824, + 0.05087608844041824, + 0.05087608844041824 + ], + "scene.render.engine": "BLENDER_EEVEE", + "scene.render.film_transparent": false, + "scene.view_settings.view_transform": "Filmic", + "scene.display.shading.show_object_outline": false, + "scene.display.shading.show_cavity": false, + "scene.display.shading.cavity_type": "WORLD", + "scene.display.shading.curvature_ridge_factor": 0.0, + "scene.display.shading.curvature_valley_factor": 0.0, + "scene.display.shading.light": "STUDIO", + "scene.display.shading.color_type": "MATERIAL", + "scene.display.shading.single_color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929 + ], + "scene.display.shading.show_shadows": false, + "scene.display.shading.shadow_intensity": 0.5, + "scene.display.light_direction": [ + 0.5773502588272095, + 0.5773502588272095, + 0.5773502588272095 + ], + "scene.view_settings.use_curve_mapping": false, + "space.overlay.show_wireframes": false, + "space.overlay.wireframe_threshold": 1.0, + "space.overlay.show_floor": true, + "space.overlay.show_axis_x": true, + "space.overlay.show_axis_y": true, + "space.overlay.show_axis_z": false, + "space.overlay.show_object_origins": true, + "space.overlay.show_relationship_lines": true + }, + "render_type": "VIEWPORT" + } +} \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc b/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc index cb7d9f399a..f0728a6340 100644 --- a/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc +++ b/src/blenderbim/blenderbim/bim/data/pset/EPset_Drawing.ifc @@ -5,7 +5,7 @@ FILE_NAME('EPset_Drawing.ifc','2020-01-01T00:00:00',(),(),'EPset_Drawing','EPset FILE_SCHEMA(('IFC4')); ENDSEC; DATA; -#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19)); +#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20,#21)); #2=IFCSIMPLEPROPERTYTEMPLATE('23JavTMk98ZxXhrUEnjAcf',$,'TargetView','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #3=IFCSIMPLEPROPERTYTEMPLATE('1yVWUt5H9DAOuu0OaMMLpe',$,'Scale','The scale of this drawing represented as a numerator and denominator, such as 1/100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #4=IFCSIMPLEPROPERTYTEMPLATE('3gsuPBtU93b8f0gg1pjkq6',$,'HumanScale','The scale of this drawing in human readable format, such as 1:100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); @@ -24,5 +24,7 @@ DATA; #17=IFCSIMPLEPROPERTYTEMPLATE('38uAtrp9nD_901NO42zd$7',$,'ImperialPrecision','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #18=IFCSIMPLEPROPERTYTEMPLATE('1MX0uffTL6TOvtvEJpxFmk',$,'DecimalPlaces','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.); #19=IFCSIMPLEPROPERTYTEMPLATE('0joEq0Rd10cxweEh0NeHT6',$,'JoinCriteria','Comma separated selection keys which determine what cut objects are to be joined.',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.); +#20=IFCSIMPLEPROPERTYTEMPLATE('0nYMT3OSj5gArVniCWZRtv',$,'ShadingStyles','',.P_SINGLEVALUE.,'IfcURIReference',$,$,$,$,$,.READWRITE.); +#21=IFCSIMPLEPROPERTYTEMPLATE('3VWG22eZXBdQwdKlzMeVQH',$,'CurrentShadingStyle','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); ENDSEC; END-ISO-10303-21; diff --git a/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc b/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc index 3f0f40c504..cefd92a827 100644 --- a/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc +++ b/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc @@ -18,7 +18,7 @@ DATA; #11=IFCSIMPLEPROPERTYTEMPLATE('1DtsPn5a9FG8$zXHDDMavY',$,'ShowEndArrow','Display end arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); #12=IFCSIMPLEPROPERTYTEMPLATE('2$6U0mLI9AiPRWeBabdY3u',$,'EndArrowSymbol','Custom symbol for the end of the section marker arrow. Need to make sure it''s present in "symbols.svg".',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #13=IFCSIMPLEPROPERTYTEMPLATE('1naFqntIL7igCY7hCaE7kq',$,'HasConnectedSectionLine','Connect or disconnect section markers with line (by default = True).',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); -#14=IFCPROPERTYSETTEMPLATE('3V8oZ8YRD3_O7uR5vcUleS',$,'BBIM_Documentation','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#15,#16,#17,#18,#19,#20,#21,#22)); +#14=IFCPROPERTYSETTEMPLATE('3V8oZ8YRD3_O7uR5vcUleS',$,'BBIM_Documentation','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#15,#16,#17,#18,#19,#20,#21,#22,#23)); #15=IFCSIMPLEPROPERTYTEMPLATE('0ulAhgk3v9qfGlDILauR6J',$,'SheetsDir','Default sheets directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #16=IFCSIMPLEPROPERTYTEMPLATE('2yvlVKiQXASucfH40deCvu',$,'LayoutsDir','Default layouts directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #17=IFCSIMPLEPROPERTYTEMPLATE('2kXZqXicL3jRwsOnLM_0ho',$,'TitleblocksDir','Default titleblocks directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); @@ -27,10 +27,12 @@ DATA; #20=IFCSIMPLEPROPERTYTEMPLATE('23tejOrxj859R_eCRp1AFP',$,'MarkersPath','Default markers SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #21=IFCSIMPLEPROPERTYTEMPLATE('1UDakJ5_f7kBhggNSW4$h5',$,'SymbolsPath','Default symbols SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #22=IFCSIMPLEPROPERTYTEMPLATE('0d53LEtgLDQxnv__NfgH7i',$,'PatternsPath','Default patterns SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); -#23=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#24,#25,#26,#27)); -#24=IFCSIMPLEPROPERTYTEMPLATE('1rL2AbQsXD8RbpoWH5pYOV',$,'ShowDescriptionOnly','Hide the measurement values and show only annotation description',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); -#25=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); -#26=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); -#27=IFCSIMPLEPROPERTYTEMPLATE('0bnzttUb9BPuN597uNTXOE',$,'TextSuffix','Text to add after annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#23=IFCSIMPLEPROPERTYTEMPLATE('26qFNMv7nCHgU6Jd7Anga5',$,'ShadingStylesPath','Default shading styles',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#25,#26,#27,#28)); +#25=IFCSIMPLEPROPERTYTEMPLATE('1rL2AbQsXD8RbpoWH5pYOV',$,'ShowDescriptionOnly','Hide the measurement values and show only annotation description',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#26=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#27=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#28=IFCSIMPLEPROPERTYTEMPLATE('0bnzttUb9BPuN597uNTXOE',$,'TextSuffix','Text to add after annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); + ENDSEC; END-ISO-10303-21; diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 1705b3beba..4456fc34fa 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -282,73 +282,4 @@ def setDefaultProperties(scene): ) ifcopenshell.api.owner.settings.get_user = lambda ifc: core_owner.get_user(tool.Owner) ifcopenshell.api.owner.settings.get_application = get_application - # TODO: Move to drawing module - if len(bpy.context.scene.DocProperties.drawing_styles) == 0: - drawing_style = bpy.context.scene.DocProperties.drawing_styles.add() - drawing_style.name = "Blender Default" - drawing_style.render_type = "DEFAULT" - bpy.ops.bim.save_drawing_style(index="0") - - drawing_style = bpy.context.scene.DocProperties.drawing_styles.add() - drawing_style.name = "Technical" - drawing_style.render_type = "VIEWPORT" - drawing_style.raster_style = json.dumps( - { - RasterStyleProperty.WORLD_COLOR.value: (1, 1, 1), - RasterStyleProperty.RENDER_ENGINE.value: "BLENDER_WORKBENCH", - RasterStyleProperty.RENDER_TRANSPARENT.value: False, - RasterStyleProperty.SHADING_SHOW_OBJECT_OUTLINE.value: True, - RasterStyleProperty.SHADING_SHOW_CAVITY.value: False, - RasterStyleProperty.SHADING_CAVITY_TYPE.value: "BOTH", - RasterStyleProperty.SHADING_CURVATURE_RIDGE_FACTOR.value: 1, - RasterStyleProperty.SHADING_CURVATURE_VALLEY_FACTOR.value: 1, - RasterStyleProperty.VIEW_TRANSFORM.value: "Standard", - RasterStyleProperty.SHADING_LIGHT.value: "FLAT", - RasterStyleProperty.SHADING_COLOR_TYPE.value: "SINGLE", - RasterStyleProperty.SHADING_SINGLE_COLOR.value: (1, 1, 1), - RasterStyleProperty.SHADING_SHOW_SHADOWS.value: False, - RasterStyleProperty.SHADING_SHADOW_INTENSITY.value: 0.5, - RasterStyleProperty.DISPLAY_LIGHT_DIRECTION.value: (0.5, 0.5, 0.5), - RasterStyleProperty.VIEW_USE_CURVE_MAPPING.value: False, - RasterStyleProperty.OVERLAY_SHOW_WIREFRAMES.value: True, - RasterStyleProperty.OVERLAY_WIREFRAME_THRESHOLD.value: 0, - RasterStyleProperty.OVERLAY_SHOW_FLOOR.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_X.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_Y.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_Z.value: False, - RasterStyleProperty.OVERLAY_SHOW_OBJECT_ORIGINS.value: False, - RasterStyleProperty.OVERLAY_SHOW_RELATIONSHIP_LINES.value: False, - } - ) - drawing_style = bpy.context.scene.DocProperties.drawing_styles.add() - drawing_style.name = "Shaded" - drawing_style.render_type = "VIEWPORT" - drawing_style.raster_style = json.dumps( - { - RasterStyleProperty.WORLD_COLOR.value: (1, 1, 1), - RasterStyleProperty.RENDER_ENGINE.value: "BLENDER_WORKBENCH", - RasterStyleProperty.RENDER_TRANSPARENT.value: False, - RasterStyleProperty.SHADING_SHOW_OBJECT_OUTLINE.value: True, - RasterStyleProperty.SHADING_SHOW_CAVITY.value: True, - RasterStyleProperty.SHADING_CAVITY_TYPE.value: "BOTH", - RasterStyleProperty.SHADING_CURVATURE_RIDGE_FACTOR.value: 1, - RasterStyleProperty.SHADING_CURVATURE_VALLEY_FACTOR.value: 1, - RasterStyleProperty.VIEW_TRANSFORM.value: "Standard", - RasterStyleProperty.SHADING_LIGHT.value: "STUDIO", - RasterStyleProperty.SHADING_COLOR_TYPE.value: "MATERIAL", - RasterStyleProperty.SHADING_SINGLE_COLOR.value: (1, 1, 1), - RasterStyleProperty.SHADING_SHOW_SHADOWS.value: True, - RasterStyleProperty.SHADING_SHADOW_INTENSITY.value: 0.5, - RasterStyleProperty.DISPLAY_LIGHT_DIRECTION.value: (0.5, 0.5, 0.5), - RasterStyleProperty.VIEW_USE_CURVE_MAPPING.value: False, - RasterStyleProperty.OVERLAY_SHOW_WIREFRAMES.value: False, - RasterStyleProperty.OVERLAY_WIREFRAME_THRESHOLD.value: 0, - RasterStyleProperty.OVERLAY_SHOW_FLOOR.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_X.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_Y.value: False, - RasterStyleProperty.OVERLAY_SHOW_AXIS_Z.value: False, - RasterStyleProperty.OVERLAY_SHOW_OBJECT_ORIGINS.value: False, - RasterStyleProperty.OVERLAY_SHOW_RELATIONSHIP_LINES.value: False, - } - ) - AuthoringData.type_thumbnails = {} + AuthoringData.type_thumbnails = {} diff --git a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py index b8e95a2e56..2b993e256a 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py @@ -61,11 +61,13 @@ classes = ( operator.RemoveDrawingStyle, operator.RemoveDrawingStyleAttribute, operator.RemoveSchedule, + operator.ReloadDrawingStyles, operator.RemoveSheet, operator.RemoveTextLiteral, operator.SelectAllDrawings, operator.ResizeText, operator.SaveDrawingStyle, + operator.SaveDrawingStylesData, operator.SelectAssignedProduct, operator.SelectDocIfcFile, prop.Variable, diff --git a/src/blenderbim/blenderbim/bim/module/drawing/data.py b/src/blenderbim/blenderbim/bim/module/drawing/data.py index cc9928e17f..e3b9f4fb67 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/data.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/data.py @@ -103,6 +103,7 @@ class DrawingsData: "has_saved_ifc": cls.has_saved_ifc(), "total_drawings": cls.total_drawings(), "location_hint": cls.location_hint(), + "active_drawing_pset_data": cls.active_drawing_pset_data(), } cls.is_loaded = True @@ -124,6 +125,15 @@ class DrawingsData: return results return [(h.upper(), h, "") for h in ["North", "South", "East", "West"]] + @classmethod + def active_drawing_pset_data(cls): + ifc_file = tool.Ifc.get() + drawing_id = bpy.context.scene.DocProperties.active_drawing_id + if drawing_id == 0: + return {} + drawing = ifc_file.by_id(bpy.context.scene.DocProperties.active_drawing_id) + return ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing") + class SchedulesData: data = {} diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index ac7471eb49..68bc466f46 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -41,7 +41,7 @@ import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.helper as helper from blenderbim.bim.module.drawing.decoration import CutDecorator -from blenderbim.bim.module.drawing.data import DecoratorData +from blenderbim.bim.module.drawing.data import DecoratorData, DrawingsData import blenderbim.bim.export_ifc from lxml import etree from mathutils import Vector @@ -628,7 +628,6 @@ class CreateDrawing(bpy.types.Operator): # Loop over the cell paths for pi, p in enumerate(g2.getElementsByTagName("path")): - d = p.getAttribute("d") coords = [co[1:].split(",") for co in d.split() if co[1:]] polygon = shapely.Polygon(coords) @@ -943,11 +942,17 @@ class CreateDrawing(bpy.types.Operator): camera_props = self.camera.data.BIMCameraProperties if camera_props.diagram_scale == "CUSTOM": if context.scene.unit_settings.system == "IMPERIAL": - if camera_props.custom_diagram_scale_input1[-1] == "'" or camera_props.custom_diagram_scale_input1[-1] == "\"": + if ( + camera_props.custom_diagram_scale_input1[-1] == "'" + or camera_props.custom_diagram_scale_input1[-1] == '"' + ): camera_props.custom_diagram_scale_input1 = camera_props.custom_diagram_scale_input1[:-1] if camera_props.custom_diagram_scale_input2[-1] == "'": camera_props.custom_diagram_scale_input2 = camera_props.custom_diagram_scale_input2[:-1] - if camera_props.custom_diagram_scale_input2[1:] == "'-0\"" or camera_props.custom_diagram_scale_input2[1:] == "' 0\"": + if ( + camera_props.custom_diagram_scale_input2[1:] == "'-0\"" + or camera_props.custom_diagram_scale_input2[1:] == "' 0\"" + ): camera_props.custom_diagram_scale_input2 = camera_props.custom_diagram_scale_input2[0] if "/" in camera_props.custom_diagram_scale_input1: if " " in camera_props.custom_diagram_scale_input1: @@ -1333,9 +1338,12 @@ class ActivateDrawing(bpy.types.Operator): def execute(self, context): drawing = tool.Ifc.get().by_id(self.drawing) + dprops = bpy.context.scene.DocProperties core.activate_drawing_view(tool.Ifc, tool.Drawing, drawing=drawing) - bpy.context.scene.DocProperties.active_drawing_id = self.drawing + dprops.active_drawing_id = self.drawing + dprops.drawing_styles.clear() if ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing", "HasUnderlay"): + bpy.ops.bim.reload_drawing_styles() bpy.ops.bim.activate_drawing_style() core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=tool.Ifc.get().by_id(self.drawing)) CutDecorator.install(context) @@ -1405,18 +1413,81 @@ class RemoveDrawing(bpy.types.Operator, Operator): core.remove_drawing(tool.Ifc, tool.Drawing, drawing=drawing) -class AddDrawingStyle(bpy.types.Operator): +class ReloadDrawingStyles(bpy.types.Operator): + bl_idname = "bim.reload_drawing_styles" + bl_label = "Reload Drawing Styles" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + if not DrawingsData.is_loaded: + DrawingsData.load() + drawing_pset_data = DrawingsData.data["active_drawing_pset_data"] + camera_props = context.active_object.data.BIMCameraProperties + + # added this part as a temporary fallback + # TODO: should remove it a bit later when projects get more accommodated + # with saving shadingstyles to ifc and separate json file + if "ShadingStyles" not in drawing_pset_data: + ifc_file = tool.Ifc.get() + pset = ifc_file.by_id(drawing_pset_data["id"]) + edit_properties = { + "ShadingStyles": ( + shading_styles_path := tool.Drawing.get_default_drawing_resource_path("ShadingStyles") + ), + "CurrentShadingStyle": tool.Drawing.get_default_shading_style(), + } + ifcopenshell.api.run("pset.edit_pset", ifc_file, pset=pset, properties=edit_properties) + tool.Drawing.setup_shading_styles_path(shading_styles_path) + + DrawingsData.load() + drawing_pset_data = DrawingsData.data["active_drawing_pset_data"] + + if "ShadingStyles" not in drawing_pset_data: + self.report({"ERROR"}, "Could not find shading styles path in EPset_Drawing.ShadingStyles.") + return {"CANCELLED"} + + rel_path = drawing_pset_data["ShadingStyles"] + current_style = drawing_pset_data.get("CurrentShadingStyle", None) + + json_path = Path(tool.Ifc.resolve_uri(rel_path)) + if not json_path.exists(): + self.report({"ERROR"}, "Shading styles file not found: {}".format(json_path)) + return {"CANCELLED"} + + with open(json_path, "r") as fi: + shading_styles_json = json.load(fi) + + drawing_styles = context.scene.DocProperties.drawing_styles + drawing_styles.clear() + styles = [style for style in shading_styles_json] + for style_name in styles: + style_data = shading_styles_json[style_name] + drawing_style = drawing_styles.add() + drawing_style["name"] = style_name # setting as attribute to avoid triggering setter + drawing_style.render_type = style_data["render_type"] + drawing_style.raster_style = json.dumps(style_data["raster_style"]) + + if current_style is not None: + camera_props.active_drawing_style_index = styles.index(current_style) + + return {"FINISHED"} + + +class AddDrawingStyle(bpy.types.Operator, Operator): bl_idname = "bim.add_drawing_style" bl_label = "Add Drawing Style" bl_options = {"REGISTER", "UNDO"} def execute(self, context): - new = context.scene.DocProperties.drawing_styles.add() - new.name = "New Drawing Style" + drawing_styles = context.scene.DocProperties.drawing_styles + new = drawing_styles.add() + # drawing style is saved to ifc on rename + new.name = tool.Blender.ensure_unique_name("New Drawing Style", drawing_styles) + context.scene.camera.data.BIMCameraProperties.active_drawing_style_index = len(drawing_styles) - 1 return {"FINISHED"} -class RemoveDrawingStyle(bpy.types.Operator): +class RemoveDrawingStyle(bpy.types.Operator, Operator): bl_idname = "bim.remove_drawing_style" bl_label = "Remove Drawing Style" bl_options = {"REGISTER", "UNDO"} @@ -1424,13 +1495,17 @@ class RemoveDrawingStyle(bpy.types.Operator): def execute(self, context): context.scene.DocProperties.drawing_styles.remove(self.index) + context.scene.camera.data.BIMCameraProperties.active_drawing_style_index = max(self.index - 1, 0) + bpy.ops.bim.save_drawing_styles_data() return {"FINISHED"} -class SaveDrawingStyle(bpy.types.Operator): +class SaveDrawingStyle(bpy.types.Operator, Operator): bl_idname = "bim.save_drawing_style" bl_label = "Save Drawing Style" bl_options = {"REGISTER", "UNDO"} + bl_description = "Save current render setting to currently selected drawing style. Also resaves styles data to IFC" + index: bpy.props.StringProperty() # TODO: check undo redo @@ -1446,11 +1521,14 @@ class SaveDrawingStyle(bpy.types.Operator): except TypeError: pass style[prop.value] = value + if self.index: index = int(self.index) else: index = context.active_object.data.BIMCameraProperties.active_drawing_style_index scene.DocProperties.drawing_styles[index].raster_style = json.dumps(style) + + bpy.ops.bim.save_drawing_styles_data() return {"FINISHED"} def get_view_3d(self, context): @@ -1463,19 +1541,83 @@ class SaveDrawingStyle(bpy.types.Operator): return space -class ActivateDrawingStyle(bpy.types.Operator): +class SaveDrawingStylesData(bpy.types.Operator, Operator): + bl_idname = "bim.save_drawing_styles_data" + bl_label = "Save Drawing Styles Data" + bl_options = {"REGISTER", "UNDO"} + + skip_updating_current_style: bpy.props.BoolProperty(default=False) + rename_style: bpy.props.BoolProperty(default=False) + rename_style_from: bpy.props.StringProperty(default="") + rename_style_to: bpy.props.StringProperty(default="") + + def execute(self, context): + if not DrawingsData.is_loaded: + DrawingsData.load() + drawing_pset_data = DrawingsData.data["active_drawing_pset_data"] + drawing_styles = context.scene.DocProperties.drawing_styles + + rel_path = drawing_pset_data["ShadingStyles"] + current_style = drawing_pset_data.get("CurrentShadingStyle", None) + json_path = Path(tool.Ifc.resolve_uri(rel_path)) + if not json_path.exists(): + self.report({"ERROR"}, "Shading styles file not found: {}".format(json_path)) + return {"CANCELLED"} + + styles_data = {} + for style in drawing_styles: + style_data = {"render_type": style.render_type, "raster_style": json.loads(style.raster_style)} + styles_data[style.name] = style_data + + with open(json_path, "w") as fo: + json.dump(styles_data, fo, indent=4) + + # TODO: currently it doesn't update current style for the other drawings + # handling case when current style is not present in styles saved in ifc + if not self.skip_updating_current_style and current_style not in styles_data and current_style is not None: + # style was renamed + if self.rename_style and current_style == self.rename_style_from: + new_style_name = self.rename_style_to + + # style was removed + else: + new_style_name = None + + ifc_file = tool.Ifc.get() + drawing = ifc_file.by_id(context.scene.DocProperties.active_drawing_id) + pset = tool.Pset.get_element_pset(drawing, "EPset_Drawing") + ifcopenshell.api.run( + "pset.edit_pset", ifc_file, pset=pset, properties={"CurrentShadingStyle": new_style_name} + ) + blenderbim.bim.handler.refresh_ui_data() + + return {"FINISHED"} + + +class ActivateDrawingStyle(bpy.types.Operator, Operator): bl_idname = "bim.activate_drawing_style" bl_label = "Activate Drawing Style" bl_options = {"REGISTER", "UNDO"} def execute(self, context): scene = context.scene - if scene.camera.data.BIMCameraProperties.active_drawing_style_index < len(scene.DocProperties.drawing_styles): - self.drawing_style = scene.DocProperties.drawing_styles[ - scene.camera.data.BIMCameraProperties.active_drawing_style_index - ] - self.set_raster_style(context) - self.set_query(context) + ifc_file = tool.Ifc.get() + active_drawing_style_index = scene.camera.data.BIMCameraProperties.active_drawing_style_index + + if active_drawing_style_index >= len(scene.DocProperties.drawing_styles): + return + + self.drawing_style = scene.DocProperties.drawing_styles[active_drawing_style_index] + + self.set_raster_style(context) + self.set_query(context) + + drawing = ifc_file.by_id(scene.DocProperties.active_drawing_id) + pset = tool.Pset.get_element_pset(drawing, "EPset_Drawing") + ifcopenshell.api.run( + "pset.edit_pset", ifc_file, pset=pset, properties={"CurrentShadingStyle": self.drawing_style.name} + ) + blenderbim.bim.handler.refresh_ui_data() return {"FINISHED"} def set_raster_style(self, context): @@ -1658,6 +1800,7 @@ class AddScheduleToSheet(bpy.types.Operator, Operator): tool.Drawing.import_sheets() +# TODO: dead code - drawing style attributes are never used? class AddDrawingStyleAttribute(bpy.types.Operator): bl_idname = "bim.add_drawing_style_attribute" bl_label = "Add Drawing Style Attribute" @@ -1669,6 +1812,7 @@ class AddDrawingStyleAttribute(bpy.types.Operator): return {"FINISHED"} +# TODO: dead code - drawing style attributes are never used? class RemoveDrawingStyleAttribute(bpy.types.Operator): bl_idname = "bim.remove_drawing_style_attribute" bl_label = "Remove Drawing Style Attribute" diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index fd020915b3..7d75e53d15 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -156,6 +156,21 @@ def update_drawing_name(self, context): core.update_drawing_name(tool.Ifc, tool.Drawing, drawing=drawing, name=self.name) +def get_drawing_style_name(self): + """needed to make `set_drawing_style_name` work""" + return self.get("name", "") + + +def set_drawing_style_name(self, new_value): + """ensure the name is unique""" + scene = bpy.context.scene + drawing_styles = [s.name for s in scene.DocProperties.drawing_styles if s.name != self.name] + new_value = tool.Blender.ensure_unique_name(new_value, drawing_styles) + old_value = self.name + self["name"] = new_value + bpy.ops.bim.save_drawing_styles_data(rename_style=True, rename_style_from=old_value, rename_style_to=new_value) + + def update_schedule_name(self, context): schedule = tool.Ifc.get().by_id(self.ifc_definition_id) core.update_schedule_name(tool.Ifc, tool.Drawing, schedule=schedule, name=self.name) @@ -236,8 +251,8 @@ class Sheet(PropertyGroup): class DrawingStyle(PropertyGroup): - name: StringProperty(name="Name") - raster_style: StringProperty(name="Raster Style") + name: StringProperty(name="Name", get=get_drawing_style_name, set=set_drawing_style_name) + raster_style: StringProperty(name="Raster Style", default="{}") render_type: EnumProperty( items=[ ("NONE", "None", ""), @@ -324,6 +339,10 @@ class DocProperties(PropertyGroup): markers_path: StringProperty(default=os.path.join("drawings", "assets", "markers.svg"), name="Default Markers") symbols_path: StringProperty(default=os.path.join("drawings", "assets", "symbols.svg"), name="Default Symbols") patterns_path: StringProperty(default=os.path.join("drawings", "assets", "patterns.svg"), name="Default Patterns") + shadingstyles_path: StringProperty( + default=os.path.join("drawings", "assets", "shading_styles.json"), name="Default Shading Styles" + ) + shadingstyle_default: StringProperty(default="Blender Default", name="Default Shading Style") class BIMCameraProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index 3573319abc..b4a9ba8723 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -117,38 +117,53 @@ class BIM_PT_drawing_underlay(Panel): layout.use_property_split = True dprops = context.scene.DocProperties props = context.active_object.data.BIMCameraProperties + drawing_index_is_valid = props.active_drawing_style_index < len(dprops.drawing_styles) + + if not DrawingsData.is_loaded: + DrawingsData.load() + drawing_pset_data = DrawingsData.data["active_drawing_pset_data"] row = layout.row(align=True) - row.operator("bim.add_drawing_style") + current_shading_style = drawing_pset_data.get("CurrentShadingStyle", None) + if current_shading_style is None: + row.label(text="Current style is not set.") + else: + row.label(text="Current Shading Style:") + row.label(text=current_shading_style) + row.operator("bim.add_drawing_style", icon="ADD", text="") + if drawing_index_is_valid: + row.operator("bim.remove_drawing_style", icon="X", text="").index = props.active_drawing_style_index + row.operator("bim.reload_drawing_styles", icon="FILE_REFRESH", text="") - if dprops.drawing_styles: - layout.template_list("BIM_UL_generic", "", dprops, "drawing_styles", props, "active_drawing_style_index") + if not dprops.drawing_styles: + return + layout.template_list("BIM_UL_generic", "", dprops, "drawing_styles", props, "active_drawing_style_index") - if props.active_drawing_style_index < len(dprops.drawing_styles): - drawing_style = dprops.drawing_styles[props.active_drawing_style_index] + if not drawing_index_is_valid: + return + drawing_style = dprops.drawing_styles[props.active_drawing_style_index] - row = layout.row(align=True) - row.prop(drawing_style, "name") - row.operator("bim.remove_drawing_style", icon="X", text="").index = props.active_drawing_style_index + row = layout.row(align=True) + row.prop(drawing_style, "name") - row = layout.row() - row.prop(drawing_style, "render_type") - row = layout.row(align=True) - row.prop(drawing_style, "include_query") - row = layout.row(align=True) - row.prop(drawing_style, "exclude_query") + row = layout.row() + row.prop(drawing_style, "render_type") + row = layout.row(align=True) + row.prop(drawing_style, "include_query") + row = layout.row(align=True) + row.prop(drawing_style, "exclude_query") - row = layout.row() - row.operator("bim.add_drawing_style_attribute") + row = layout.row() + row.operator("bim.add_drawing_style_attribute") - for index, attribute in enumerate(drawing_style.attributes): - row = layout.row(align=True) - row.prop(attribute, "name", text="") - row.operator("bim.remove_drawing_style_attribute", icon="X", text="").index = index + for index, attribute in enumerate(drawing_style.attributes): + row = layout.row(align=True) + row.prop(attribute, "name", text="") + row.operator("bim.remove_drawing_style_attribute", icon="X", text="").index = index - row = layout.row(align=True) - row.operator("bim.save_drawing_style") - row.operator("bim.activate_drawing_style") + row = layout.row(align=True) + row.operator("bim.save_drawing_style") + row.operator("bim.activate_drawing_style") class BIM_PT_drawings(Panel): diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index 3a642ed839..2ff02593d8 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -237,6 +237,10 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row.prop(context.scene.DocProperties, "symbols_path") row = self.layout.row(align=True) row.prop(context.scene.DocProperties, "patterns_path") + row = self.layout.row(align=True) + row.prop(context.scene.DocProperties, "shadingstyles_path") + row = self.layout.row(align=True) + row.prop(context.scene.DocProperties, "shadingstyle_default") row = layout.row() row.operator("bim.configure_visibility") diff --git a/src/blenderbim/blenderbim/core/drawing.py b/src/blenderbim/blenderbim/core/drawing.py index 957c1fd1df..e30f60555c 100644 --- a/src/blenderbim/blenderbim/core/drawing.py +++ b/src/blenderbim/blenderbim/core/drawing.py @@ -104,9 +104,7 @@ def remove_sheet(ifc, drawing, sheet=None): def rename_sheet(ifc, drawing, sheet=None, identification=None, name=None): - ifc.run( - "document.edit_information", information=sheet, attributes={"Identification": identification, "Name": name} - ) + ifc.run("document.edit_information", information=sheet, attributes={"Identification": identification, "Name": name}) for reference in drawing.get_document_references(sheet): description = drawing.get_reference_description(reference) if description == "SHEET": @@ -198,7 +196,9 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None): human_scale = "1:100" else: scale = "1/96" - human_scale = "1/8\"=1'-0\"" + human_scale = '1/8"=1\'-0"' + + shading_styles_path = drawing.get_default_drawing_resource_path("ShadingStyles") ifc.run( "pset.edit_pset", pset=pset, @@ -214,8 +214,11 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None): "Markers": drawing.get_default_drawing_resource_path("Markers"), "Symbols": drawing.get_default_drawing_resource_path("Symbols"), "Patterns": drawing.get_default_drawing_resource_path("Patterns"), + "ShadingStyles": (shading_styles_path := drawing.get_default_drawing_resource_path("ShadingStyles")), + "CurrentShadingStyle": drawing.get_default_shading_style(), }, ) + drawing.setup_shading_styles_path(shading_styles_path) information = ifc.run("document.add_information") uri = drawing.get_default_drawing_path(drawing_name) reference = ifc.run("document.add_reference", information=information) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index e24ff4f78e..d52f4ecdd6 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -274,6 +274,8 @@ class Drawing: def get_body_context(cls): pass def get_default_drawing_path(cls, name): pass def get_default_drawing_resource_path(cls, resource): pass + def get_default_shading_style(cls): pass + def setup_shading_styles_path(cls, resource_path): pass def get_default_layout_path(cls, identification, name): pass def get_default_sheet_path(cls, identification, name): pass def get_default_sheet_path(cls, identification, name): pass diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index bd6912c1b7..2a4d208df3 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -115,6 +115,16 @@ class Blender: tool.Blender.get_viewport_context()["area"].tag_redraw() + @classmethod + def ensure_unique_name(cls, name, objects, iteration=0): + """returns a unique name for the given name and dictionary of objects + blender style name with .001, .002, etc. suffix + """ + current_iteration = name if not iteration else f"{name}.{iteration:03d}" + if current_iteration not in objects: + return current_iteration + return cls.ensure_unique_name(name, objects, iteration + 1) + @classmethod def get_default_selection_keypmap(cls): """keymap to replicate default blender selection behaviour with click and box selection""" diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index 64884e7e58..c88db53848 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -877,6 +877,21 @@ class Drawing(blenderbim.core.tool.Drawing): if resource_path: return resource_path.replace("\\", "/") + @classmethod + def get_default_shading_style(cls): + dprops = bpy.context.scene.DocProperties + return dprops.shadingstyle_default + + @classmethod + def setup_shading_styles_path(cls, resource_path): + resource_path = tool.Ifc.resolve_uri(resource_path) + os.makedirs(os.path.dirname(resource_path), exist_ok=True) + if not os.path.exists(resource_path): + resource_basename = os.path.basename(resource_path) + ootb_resource = os.path.join(bpy.context.scene.BIMProperties.data_dir, "assets", resource_basename) + if os.path.exists(ootb_resource): + shutil.copy(ootb_resource, resource_path) + @classmethod def get_potential_reference_elements(cls, drawing): elements = [] @@ -1376,7 +1391,9 @@ class Drawing(blenderbim.core.tool.Drawing): ifc_file = tool.Ifc.get() pset = ifcopenshell.util.element.get_psets(drawing).get("EPset_Drawing", {}) include = pset.get("Include", None) - elements = cls.get_elements_in_camera_view(tool.Ifc.get_object(drawing), [tool.Ifc.get_object(e) for e in ifc_file.by_type("IfcSpace")]) + elements = cls.get_elements_in_camera_view( + tool.Ifc.get_object(drawing), [tool.Ifc.get_object(e) for e in ifc_file.by_type("IfcSpace")] + ) if include: elements = set(ifcopenshell.util.selector.Selector.parse(ifc_file, include, elements=elements)) exclude = pset.get("Exclude", None) @@ -1508,12 +1525,14 @@ class Drawing(blenderbim.core.tool.Drawing): x = (camera.data.BIMCameraProperties.raster_x / camera.data.BIMCameraProperties.raster_y) * y camera_inverse_matrix = camera.matrix_world.inverted() - return set([ - tool.Ifc.get_entity(o) - for o in objs - if cls.is_in_camera_view(o, camera_inverse_matrix, x, y, camera.data.clip_start, camera.data.clip_end) - and tool.Ifc.get_entity(o) - ]) + return set( + [ + tool.Ifc.get_entity(o) + for o in objs + if cls.is_in_camera_view(o, camera_inverse_matrix, x, y, camera.data.clip_start, camera.data.clip_end) + and tool.Ifc.get_entity(o) + ] + ) @classmethod def is_in_camera_view(cls, obj, camera_inverse_matrix, x, y, clip_start, clip_end): diff --git a/src/blenderbim/test/core/test_drawing.py b/src/blenderbim/test/core/test_drawing.py index 8c0dd74cba..55db696d8e 100644 --- a/src/blenderbim/test/core/test_drawing.py +++ b/src/blenderbim/test/core/test_drawing.py @@ -264,6 +264,9 @@ class TestAddDrawing: drawing.get_default_drawing_resource_path("Markers").should_be_called().will_return("markers.svg") drawing.get_default_drawing_resource_path("Symbols").should_be_called().will_return("symbols.svg") drawing.get_default_drawing_resource_path("Patterns").should_be_called().will_return("patterns.svg") + drawing.get_default_drawing_resource_path("ShadingStyles").should_be_called().will_return("shading_styles.json") + drawing.get_default_shading_style().should_be_called().will_return("Blender Default") + drawing.setup_shading_styles_path("shading_styles.json").should_be_called() drawing.get_unit_system().should_be_called().will_return("METRIC") ifc.run( "pset.edit_pset", @@ -280,6 +283,8 @@ class TestAddDrawing: "Markers": "markers.svg", "Symbols": "symbols.svg", "Patterns": "patterns.svg", + "ShadingStyles": "shading_styles.json", + "CurrentShadingStyle": "Blender Default", }, ).should_be_called() drawing.get_default_drawing_path("name").should_be_called().will_return("uri")