diff --git a/src/blenderbim/blenderbim/bim/module/pset/__init__.py b/src/blenderbim/blenderbim/bim/module/pset/__init__.py index fd0bdcda57..905ed3a1d1 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/pset/__init__.py @@ -20,6 +20,7 @@ import bpy from . import ui, prop, operator classes = ( + operator.AddProposedProp, operator.AddPset, operator.AddQto, operator.CopyPropertyToSelection, diff --git a/src/blenderbim/blenderbim/bim/module/pset/data.py b/src/blenderbim/blenderbim/bim/module/pset/data.py index 0c3093f3a5..34c2759e45 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/data.py +++ b/src/blenderbim/blenderbim/bim/module/pset/data.py @@ -101,7 +101,9 @@ class ObjectPsetsData(Data): ) psetnames = cls.format_pset_enum(psets) assigned_names = ifcopenshell.util.element.get_psets(element, psets_only=True, should_inherit=False).keys() - return [p for p in psetnames if p[0] not in assigned_names] + return [("BBIM_CUSTOM_PSET", "Custom Pset", "Create a property set without using a template."), None] + [ + p for p in psetnames if p[0] not in assigned_names + ] @classmethod def qto_name(cls): diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index 0d4037b9f3..30f1ccbe67 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -468,3 +468,17 @@ class BIM_OT_bulk_remove_psets(bpy.types.Operator): self.report({"INFO"}, "Finished applying changes") return {"FINISHED"} + + +class AddProposedProp(bpy.types.Operator): + bl_idname = "bim.add_proposed_prop" + bl_label = "Add Proposed Prop" + bl_options = {"REGISTER", "UNDO"} + obj: bpy.props.StringProperty() + obj_type: bpy.props.StringProperty() + prop_name: bpy.props.StringProperty() + prop_value: bpy.props.StringProperty() + + def execute(self, context): + core.add_proposed_prop(tool.Pset, self.obj, self.obj_type, self.prop_name, self.prop_value) + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py index d88884d7df..c22642057c 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -199,15 +199,19 @@ class IfcProperty(PropertyGroup): class PsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) pset_name: EnumProperty(items=get_pset_name, name="Pset Name") qto_name: EnumProperty(items=get_qto_name, name="Qto Name") + prop_name: StringProperty(name="Property Name", default="MyProperty") + prop_value: StringProperty(name="Property Value", default="Some Value") class MaterialPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -216,6 +220,7 @@ class MaterialPsetProperties(PropertyGroup): class MaterialSetPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -224,6 +229,7 @@ class MaterialSetPsetProperties(PropertyGroup): class MaterialSetItemPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -232,6 +238,7 @@ class MaterialSetItemPsetProperties(PropertyGroup): class TaskPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -240,6 +247,7 @@ class TaskPsetProperties(PropertyGroup): class ResourcePsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -249,6 +257,7 @@ class ResourcePsetProperties(PropertyGroup): class GroupPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -257,6 +266,7 @@ class GroupPsetProperties(PropertyGroup): class ProfilePsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) @@ -265,6 +275,7 @@ class ProfilePsetProperties(PropertyGroup): class WorkSchedulePsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") + active_pset_has_template: BoolProperty(name="Active Pset Has Template") active_pset_name: StringProperty(name="Pset Name") active_pset_type: StringProperty(name="Active Pset Type") properties: CollectionProperty(name="Properties", type=IfcProperty) diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index cb895399ac..16536c5940 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -101,6 +101,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type, allow_remov if props.active_pset_id == pset_id: row.prop(props, "active_pset_name", icon="COPY_ID", text="") op = row.operator("bim.edit_pset", icon="CHECKMARK", text="") + op.pset_id = pset_id op.obj = obj_name op.obj_type = obj_type op = row.operator("bim.disable_pset_editing", icon="CANCEL", text="") @@ -132,6 +133,16 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type, allow_remov if props.active_pset_id == pset_id: for prop in props.properties: draw_psetqto_editable_ui(box, props, prop) + + if not props.active_pset_has_template: + row = box.row(align=True) + row.prop(props, "prop_name", text="") + row.prop(props, "prop_value", text="") + op = row.operator("bim.add_proposed_prop", text="", icon="ADD") + op.obj = obj_name + op.obj_type = obj_type + op.prop_name = props.prop_name + op.prop_value = props.prop_value else: has_props_displayed = False for prop in pset["Properties"]: diff --git a/src/blenderbim/blenderbim/core/pset.py b/src/blenderbim/blenderbim/core/pset.py index cd58736cf2..270eb9993e 100644 --- a/src/blenderbim/blenderbim/core/pset.py +++ b/src/blenderbim/blenderbim/core/pset.py @@ -37,9 +37,10 @@ def add_pset(ifc, pset, blender, obj_name, obj_type): else: elements = [ifc.get().by_id(blender.get_obj_ifc_definition_id(obj_name, obj_type))] for element in elements: + print('checking', element, pset_name) if not element: continue - if not pset.is_pset_applicable(element, pset_name): + if pset_name and not pset.is_pset_applicable(element, pset_name): continue pset.enable_pset_editing(pset_id=0, pset_name=pset_name, pset_type="PSET", obj=obj_name, obj_type=obj_type) @@ -52,9 +53,17 @@ def enable_pset_editing(pset_tool, pset, pset_name, pset_type, obj_name, obj_typ if pset_template: pset_tool.import_pset_from_template(pset_template, pset, props) + has_template = True + else: + has_template = False if pset: pset_tool.import_pset_from_existing(pset, props) - pset_tool.set_active_pset(props, pset) + pset_tool.set_active_pset(props, pset, has_template) else: - pset_tool.enable_proposed_pset(props, pset_name, pset_type) + pset_tool.enable_proposed_pset(props, pset_name, pset_type, has_template) + + +def add_proposed_prop(pset, obj_name, obj_type, name, value): + props = pset.get_pset_props(obj_name, obj_type) + pset.add_proposed_property(name, pset.cast_string_to_primitive(value), props) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 35607cd90e..ae8ce81919 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -618,8 +618,10 @@ class Profile: @interface class Pset: + def add_proposed_property(cls, name, value, props): pass + def cast_string_to_primitive(cls, value: str): pass def clear_blender_pset_properties(cls, props): pass - def enable_proposed_pset(cls, props, pset_name, pset_type): pass + def enable_proposed_pset(cls, props, pset_name, pset_type, has_template): pass def get_element_pset(cls, element, pset_name): pass def get_prop_template_primitive_type(cls, prop_template): pass def get_pset_name(cls, obj, obj_type): pass @@ -629,7 +631,7 @@ class Pset: def import_pset_from_template(cls, pset_template, pset, props): pass def import_single_value_from_template(cls, pset_template, prop_template, data, props): pass def is_pset_applicable(cls,element, pset_name): pass - def set_active_pset(cls, props, pset): pass + def set_active_pset(cls, props, pset, has_template): pass @interface diff --git a/src/blenderbim/blenderbim/tool/pset.py b/src/blenderbim/blenderbim/tool/pset.py index 783931786f..31493ded61 100644 --- a/src/blenderbim/blenderbim/tool/pset.py +++ b/src/blenderbim/blenderbim/tool/pset.py @@ -59,7 +59,9 @@ class Pset(blenderbim.core.tool.Pset): @classmethod def get_pset_name(cls, obj, obj_type): pset = cls.get_pset_props(obj, obj_type) - return pset.pset_name + if (name := pset.pset_name) == "BBIM_CUSTOM_PSET": + return "" + return name @classmethod def is_pset_applicable(cls, element: ifcopenshell.entity_instance, pset_name: str) -> bool: @@ -234,16 +236,51 @@ class Pset(blenderbim.core.tool.Pset): props.properties.clear() @classmethod - def set_active_pset(cls, props, pset): + def set_active_pset(cls, props, pset, has_template): props.active_pset_id = pset.id() props.active_pset_name = pset.Name + props.active_pset_has_template = has_template @classmethod - def enable_proposed_pset(cls, props, pset_name, pset_type): + def enable_proposed_pset(cls, props, pset_name, pset_type, has_template): props.active_pset_id = 0 - props.active_pset_name = pset_name + props.active_pset_name = pset_name or "My_Pset" props.active_pset_type = pset_type + props.active_pset_has_template = has_template @classmethod def get_pset_template(cls, name): return blenderbim.bim.schema.ifc.psetqto.get_by_name(name) + + @classmethod + def add_proposed_property(cls, name, value, props): + if props.properties.get(name): + return + prop = props.properties.add() + prop.name = name + metadata = prop.metadata + metadata.set_value(value) + metadata.name = name + metadata.is_null = value is None + metadata.is_optional = True + metadata.set_value(metadata.get_value_default() if metadata.is_null else value) + + @classmethod + def cast_string_to_primitive(cls, value: str): + value = value.strip() + if value.lower() == "true": + return True + elif value.lower() == "false": + return False + elif value.lower() == "null" or value == "": + return None + try: + value = int(value) + return value + except: + try: + value = float(value) + return value + except: + return value + return value