diff --git a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py index 396f9a7273..3193a23271 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py @@ -23,7 +23,6 @@ import blenderbim.tool as tool from blenderbim.bim.helper import prop_with_search from bpy.types import WorkSpaceTool -# from blenderbim.bim.module.model.data import AuthoringData, RailingData, RoofData from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA from blenderbim.bim.module.drawing.data import DecoratorData, AnnotationData from blenderbim.bim.ifc import IfcStore @@ -108,7 +107,6 @@ class LaunchAnnotationTypeManager(bpy.types.Operator): op.element = relating_type["id"] - class AnnotationTool(WorkSpaceTool): bl_space_type = "VIEW_3D" bl_context_mode = "OBJECT" diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index 646e6b7cd6..2f8df0f085 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -364,17 +364,27 @@ class RailingData: @classmethod def load(cls): cls.is_loaded = True - cls.data = {"parameters": cls.parameters()} + cls.data = {} + cls.data["parameters"] = cls.pset_data() + cls.data["general_params"] = cls.general_params() @classmethod - def parameters(cls): - element = tool.Ifc.get_entity(bpy.context.active_object) - if element: - psets = ifcopenshell.util.element.get_psets(element) - parameters = psets.get("BBIM_Railing", None) - if parameters: - parameters["data_dict"] = json.loads(parameters.get("Data", "[]") or "[]") - return parameters + def pset_data(cls): + return tool.Model.get_railing_pset_data(bpy.context.active_object) + + @classmethod + def general_params(cls): + props = bpy.context.active_object.BIMRailingProperties + railing_data = cls.data["parameters"]["data_dict"] + general_params = {} + general_props = props.get_general_kwargs(railing_type=railing_data["railing_type"]) + for prop_name in general_props: + prop_value = railing_data[prop_name] + prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value + + prop_readable_name = props.bl_rna.properties[prop_name].name + general_params[prop_readable_name] = prop_value + return general_params class RoofData: diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 76bd1e5960..7f8a2b52d9 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -432,13 +432,13 @@ class BIMDoorProperties(PropertyGroup): name="Transom Thickness", description="Set values > 0 to add a transom.\n" "`0.050 mm` is good as default value", default=0.000, - subtype="DISTANCE" + subtype="DISTANCE", ) transom_offset: bpy.props.FloatProperty( name="Transom Offset", description="Distance from the bottom door opening to the beginning of the transom (unlike windows)", default=1.525, - subtype="DISTANCE" + subtype="DISTANCE", ) casing_thickness: bpy.props.FloatProperty( @@ -547,7 +547,7 @@ class BIMRailingProperties(PropertyGroup): ("NONE", "NONE", ""), ) - is_editing: bpy.props.IntProperty(default=-1) + is_editing: bpy.props.BoolProperty(default=False) is_editing_path: bpy.props.BoolProperty(default=False) railing_type: bpy.props.EnumProperty(name="Railing Type", items=railing_types, default="FRAMELESS_PANEL") @@ -563,29 +563,36 @@ class BIMRailingProperties(PropertyGroup): "If disabled, supports are added automatically based on the support spacing", ) support_spacing: bpy.props.FloatProperty( - name="Support Spacing", - default=1.0, + name="Support Spacing", + default=1.0, min=0.01, description="Distance between supports if automatic supports are used", + subtype="DISTANCE", ) - railing_diameter: bpy.props.FloatProperty(name="Railing Diameter", default=0.050) + railing_diameter: bpy.props.FloatProperty(name="Railing Diameter", default=0.050, subtype="DISTANCE") clear_width: bpy.props.FloatProperty( - name="Clear Width", default=0.040, description="Clear width between the railing and the wall" + name="Clear Width", + default=0.040, + description="Clear width between the railing and the wall", + subtype="DISTANCE", ) terminal_type: bpy.props.EnumProperty(name="Terminal Type", items=cap_types, default="180") - def get_general_kwargs(self, convert_to_project_units=False): + def get_general_kwargs(self, railing_type=None, convert_to_project_units=False): + if railing_type is None: + railing_type = self.railing_type + base_kwargs = { - "railing_type": self.railing_type, + "railing_type": railing_type, "height": self.height, } additional_kwargs = {} - if self.railing_type == "FRAMELESS_PANEL": + if railing_type == "FRAMELESS_PANEL": additional_kwargs = { "thickness": self.thickness, "spacing": self.spacing, } - elif self.railing_type == "WALL_MOUNTED_HANDRAIL": + elif railing_type == "WALL_MOUNTED_HANDRAIL": additional_kwargs = { "railing_diameter": self.railing_diameter, "clear_width": self.clear_width, @@ -606,6 +613,7 @@ class BIMRailingProperties(PropertyGroup): for prop_name in kwargs: setattr(self, prop_name, kwargs[prop_name]) + class BIMRoofProperties(PropertyGroup): non_si_units_props = ( "is_editing", diff --git a/src/blenderbim/blenderbim/bim/module/model/railing.py b/src/blenderbim/blenderbim/bim/module/model/railing.py index 53253884a8..286187471a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/railing.py +++ b/src/blenderbim/blenderbim/bim/module/model/railing.py @@ -23,14 +23,12 @@ import ifcopenshell from ifcopenshell.util.shape_builder import V import blenderbim import blenderbim.tool as tool -from blenderbim.bim.helper import convert_property_group_from_si from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.model.door import bm_sort_out_geom from blenderbim.bim.module.model.data import RailingData, refresh from blenderbim.bim.module.model.decorator import ProfileDecorator -from mathutils import Vector, Matrix -from pprint import pprint +from mathutils import Vector import json # reference: @@ -38,7 +36,6 @@ import json # https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRailingType.htm - def bm_split_edge_at_offset(edge, offset): v0, v1 = edge.verts @@ -83,7 +80,9 @@ def update_railing_modifier_ifc_data(context): if props.railing_type == "WALL_MOUNTED_HANDRAIL": body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW") - railing_path = [Vector(v) for v in RailingData.data["parameters"]["data_dict"]["path_data"]["verts"]] + pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object) + path_data = pset_data["data_dict"]["path_data"] + railing_path = [Vector(v) for v in path_data["verts"]] si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) representation_data = { @@ -121,6 +120,7 @@ def update_railing_modifier_bmesh(context): obj = context.object props = obj.BIMRailingProperties + # NOTE: using Data since bmesh update will hapen very often if not RailingData.is_loaded: RailingData.load() path_data = RailingData.data["parameters"]["data_dict"]["path_data"] @@ -198,7 +198,7 @@ def update_railing_modifier_bmesh(context): bmesh.ops.dissolve_verts(bm, verts=verts_to_dissolve) # to remove unnecessary verts in 0 spacing case bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) - + bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:]) tool.Blender.apply_bmesh(obj.data, bm) @@ -317,7 +317,6 @@ class AddRailing(bpy.types.Operator, tool.Ifc.Operator): self.report({"ERROR"}, "Object has to be IfcRailing/IfcRailingType type to add a railing.") return {"CANCELLED"} - railing_data = props.get_general_kwargs(convert_to_project_units=True) path_data = get_path_data(obj) if not path_data: @@ -353,7 +352,7 @@ class EnableEditingRailing(bpy.types.Operator, tool.Ifc.Operator): # required since we could load pset from .ifc and BIMRailingProperties won't be set props.set_props_kwargs_from_ifc_data(data) - props.is_editing = 1 + props.is_editing = True return {"FINISHED"} @@ -381,7 +380,7 @@ class CancelEditingRailing(bpy.types.Operator, tool.Ifc.Operator): should_sync_changes_first=False, ) - props.is_editing = -1 + props.is_editing = False return {"FINISHED"} @@ -395,13 +394,12 @@ class FinishEditingRailing(bpy.types.Operator, tool.Ifc.Operator): element = tool.Ifc.get_entity(obj) props = obj.BIMRailingProperties - if not RailingData.is_loaded: - RailingData.load() - path_data = RailingData.data["parameters"]["data_dict"]["path_data"] + pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object) + path_data = pset_data["data_dict"]["path_data"] railing_data = props.get_general_kwargs(convert_to_project_units=True) railing_data["path_data"] = path_data - props.is_editing = -1 + props.is_editing = False update_bbim_railing_pset(element, railing_data) update_railing_modifier_ifc_data(context) @@ -419,9 +417,8 @@ class FlipRailingPathOrder(bpy.types.Operator, tool.Ifc.Operator): element = tool.Ifc.get_entity(obj) props = obj.BIMRailingProperties - if not RailingData.is_loaded: - RailingData.load() - path_data = RailingData.data["parameters"]["data_dict"]["path_data"] + pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object) + path_data = pset_data["data_dict"]["path_data"] # flip the vertex order and edges path_data["verts"] = path_data["verts"][::-1] @@ -497,7 +494,9 @@ class FinishEditingRailingPath(bpy.types.Operator, tool.Ifc.Operator): props.is_editing_path = False update_bbim_railing_pset(element, railing_data) - refresh() # RailingData has to be updated before run update_railing_modifier_bmesh + # RailingData has to be updated before run update_railing_modifier_bmesh + # since we know that BBIM_Railing could have changed + refresh() update_railing_modifier_bmesh(context) if bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode="OBJECT") @@ -512,9 +511,8 @@ class RemoveRailing(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): obj = context.active_object - props = obj.BIMRailingProperties element = tool.Ifc.get_entity(obj) - obj.BIMRailingProperties.is_editing = -1 + obj.BIMRailingProperties.is_editing = False pset = tool.Pset.get_element_pset(element, "BBIM_Railing") ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset) diff --git a/src/blenderbim/blenderbim/bim/module/model/ui.py b/src/blenderbim/blenderbim/bim/module/model/ui.py index 37c2695052..fdc7d54d56 100644 --- a/src/blenderbim/blenderbim/bim/module/model/ui.py +++ b/src/blenderbim/blenderbim/bim/module/model/ui.py @@ -552,9 +552,7 @@ class BIM_PT_railing(bpy.types.Panel): row = self.layout.row(align=True) row.label(text="Railing parameters", icon="OUTLINER_OB_LATTICE") - railing_data = RailingData.data["parameters"]["data_dict"] - - if props.is_editing != -1: + if props.is_editing: row = self.layout.row(align=True) row.operator("bim.finish_editing_railing", icon="CHECKMARK", text="Finish Editing") row.operator("bim.cancel_editing_railing", icon="CANCEL", text="") @@ -577,18 +575,15 @@ class BIM_PT_railing(bpy.types.Panel): else: row.operator("bim.enable_editing_railing", icon="GREASEPENCIL", text="") row.operator("bim.enable_editing_railing_path", icon="ANIM", text="") - # TODO: good for preview but probably should move to .is_editing == -1 + # TODO: good for preview but probably should move to .is_editing == True # since it's writing to ifc row.operator("bim.flip_railing_path_order", icon="ARROW_LEFTRIGHT", text="") row.operator("bim.remove_railing", icon="X", text="") box = self.layout.box() - general_props = props.get_general_kwargs() - for prop in general_props: - prop_value = railing_data[prop] - prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value + for prop_name, prop_value in RailingData.data["general_params"].items(): row = box.row(align=True) - row.label(text=f"{props.bl_rna.properties[prop].name}") + row.label(text=prop_name) row.label(text=str(prop_value)) else: row = self.layout.row() diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py index 8cbb24108a..ed8f5b15d1 100644 --- a/src/blenderbim/blenderbim/tool/model.py +++ b/src/blenderbim/blenderbim/tool/model.py @@ -30,6 +30,7 @@ from blenderbim.bim import import_ifc from blenderbim.bim.module.geometry.helper import Helper import collections from blenderbim.bim.module.model.data import AuthoringData +import json class Model(blenderbim.core.tool.Model): @@ -734,3 +735,15 @@ class Model(blenderbim.core.tool.Model): obj.preview.image_pixels_float = pixels AuthoringData.type_thumbnails[element.id()] = obj.preview.icon_id + + @classmethod + def get_railing_pset_data(cls, object): + element = tool.Ifc.get_entity(object) + if not element: + return + psets = ifcopenshell.util.element.get_psets(element) + pset_data = psets.get("BBIM_Railing", None) + if not pset_data: + return + pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]") + return pset_data