diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py
index 5a43a63b56..3aecc33fc7 100644
--- a/src/blenderbim/blenderbim/bim/module/model/__init__.py
+++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py
@@ -23,7 +23,8 @@ classes = (
product.AddEmptyType,
product.AddTypeInstance,
product.DisplayIFCTypes,
- product.AddIFCTypeInstance,
+ product.SelectTypeInstance,
+ product.TypeInstanceHelp,
product.AlignProduct,
product.DynamicallyVoidProduct,
workspace.Hotkey,
@@ -36,7 +37,6 @@ classes = (
prop.BIMModelProperties,
prop.IfcTypeInfo,
ui.BIM_PT_authoring,
- ui.BIM_PT_authoring_architectural,
grid.BIM_OT_add_object,
stair.BIM_OT_add_object,
opening.BIM_OT_add_object,
diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py
index 3048360ab6..13dd02d98b 100644
--- a/src/blenderbim/blenderbim/bim/module/model/data.py
+++ b/src/blenderbim/blenderbim/bim/module/model/data.py
@@ -31,6 +31,7 @@ def refresh():
class AuthoringData:
data = {}
is_loaded = False
+ updating = False
@classmethod
def load(cls):
@@ -85,22 +86,33 @@ class AuthoringData:
def relating_types(cls, ifc_class=None):
return [(str(e.id()), e.Name, e.Description or "") for e in cls.ifc_class_entities(ifc_class=ifc_class)]
+ @staticmethod
+ def new_ifc_type_info(ifc_class):
+ ifc_type_info = bpy.context.scene.IfcTypeInfo.add()
+ ifc_type_info.name = ifc_class
+ return ifc_type_info
+
@classmethod
- def assetize_relating_type_from_selection(cls):
- props = bpy.context.scene.BIMModelProperties
- ifc_class = props.ifc_class
- relating_type_id = props.relating_type
- ifc_class_occurrences = cls.ifc_class_entities(ifc_class=ifc_class)
- ifc_class_occurrences = [entity for entity in ifc_class_occurrences if entity.id() == int(relating_type_id)]
- if len(ifc_class_occurrences) == 0:
- return
- ifc_class_entity = ifc_class_occurrences[0]
- obj = tool.Ifc.get_object(ifc_class_entity)
+ def assetize_ifc_class(cls, ifc_class=None):
+ if ifc_class is None:
+ props = bpy.context.scene.BIMModelProperties
+ ifc_class = props.ifc_class
+ ifc_type_info = cls.ifc_type_info(ifc_class)
+ _ = cls.new_ifc_type_info(ifc_class) if ifc_type_info is None else ifc_type_info
+ ifc_class_occurrences = cls.ifc_class_entities(ifc_class)
+ for ifc_class_entity in ifc_class_occurrences:
+ obj = tool.Ifc.get_object(ifc_class_entity)
+ cls.assetize_object(obj, ifc_class, ifc_class_entity)
+ ifc_type_info = cls.ifc_type_info(ifc_class)
+ ifc_type_info.fully_loaded = True
+
+ @classmethod
+ def assetize_object(cls, obj, ifc_class, ifc_class_entity, from_selection=False):
relating_type = ifc_class_entity.Name
to_be_deleted = False
if obj.type == 'EMPTY':
- bpy.ops.bim.add_type_instance()
- new_obj = bpy.context.selected_objects[-1]
+ kwargs = {} if from_selection else {'ifc_class': ifc_class, 'relating_type_id': ifc_class_entity.id()}
+ new_obj = cls.new_ifc_type_instance(**kwargs)
if new_obj is not None:
to_be_deleted = True
obj = new_obj
@@ -114,17 +126,37 @@ class AuthoringData:
for col in obj.users_collection:
col.objects.unlink(obj)
+ @classmethod
+ def assetize_relating_type_from_selection(cls):
+ props = bpy.context.scene.BIMModelProperties
+ ifc_class = props.ifc_class
+ relating_type_id = props.relating_type
+ ifc_class_occurrences = cls.ifc_class_entities(ifc_class=ifc_class)
+ ifc_class_occurrences = [entity for entity in ifc_class_occurrences if entity.id() == int(relating_type_id)]
+ if len(ifc_class_occurrences) == 0:
+ return False
+ ifc_class_entity = ifc_class_occurrences[0]
+ obj = tool.Ifc.get_object(ifc_class_entity)
+ if obj is None:
+ return False
+ cls.assetize_object(obj, ifc_class, ifc_class_entity, from_selection=True)
+ return True
+
@staticmethod
def ifc_type_info(ifc_class):
- ifc_type_infos = [element for element in bpy.context.scene.IfcTypeInfo if element.ifc_class == ifc_class]
+ ifc_type_infos = [element for element in bpy.context.scene.IfcTypeInfo if element.name == ifc_class]
return None if len(ifc_type_infos) == 0 else ifc_type_infos[0]
@classmethod
- def new_ifc_type_instance(cls, ifc_class, relating_type_id):
- props = bpy.context.scene.BIMModelProperties
- props.ifc_class = ifc_class
- props.relating_type = str(relating_type_id)
+ def new_ifc_type_instance(cls, ifc_class=None, relating_type_id=None):
+ if ifc_class is not None:
+ cls.updating = True
+ props = bpy.context.scene.BIMModelProperties
+ props.ifc_class = ifc_class
+ props.relating_type = str(relating_type_id)
+ cls.updating = False
bpy.ops.bim.add_type_instance()
+ return bpy.context.selected_objects[-1]
@staticmethod
def relating_type_name_by_id(ifc_class, relating_type_id):
diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py
index 34a5f665c6..3e8e5c5dd1 100644
--- a/src/blenderbim/blenderbim/bim/module/model/product.py
+++ b/src/blenderbim/blenderbim/bim/module/model/product.py
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see .
import bpy
+import math
import mathutils
import ifcopenshell
import ifcopenshell.api
@@ -30,9 +31,11 @@ import blenderbim.core.geometry
from . import wall, slab, profile, mep
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.model.data import AuthoringData
+from blenderbim.bim.helper import prop_with_search
from ifcopenshell.api.pset.data import Data as PsetData
from mathutils import Vector, Matrix
from bpy_extras.object_utils import AddObjectHelper
+from . import prop
class AddEmptyType(bpy.types.Operator, AddObjectHelper):
@@ -54,13 +57,26 @@ def add_empty_type_button(self, context):
self.layout.operator(AddEmptyType.bl_idname, icon="FILE_3D")
+def close_operator_panel(event):
+ x, y = event.mouse_x, event.mouse_y
+ bpy.context.window.cursor_warp(10, 10)
+ move_back = lambda: bpy.context.window.cursor_warp(x, y)
+ bpy.app.timers.register(move_back, first_interval=0.001)
+
+
class AddTypeInstance(bpy.types.Operator):
bl_idname = "bim.add_type_instance"
- bl_label = "Add Type Instance"
+ bl_label = "Add"
bl_options = {"REGISTER", "UNDO"}
- bl_description = "Add the selected Type Instance to the model"
+ bl_description = "Add Type Instance to the model"
ifc_class: bpy.props.StringProperty()
relating_type: bpy.props.IntProperty()
+ from_invoke: bpy.props.BoolProperty(default=False)
+
+ def invoke(self, context, event):
+ if self.from_invoke:
+ close_operator_panel(event)
+ return self.execute(context)
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
@@ -176,7 +192,7 @@ class AddTypeInstance(bpy.types.Operator):
class DisplayIFCTypes(bpy.types.Operator):
bl_idname = "bim.display_ifc_types"
- bl_label = "Browse IFC Types"
+ bl_label = "Browse IFC Construction Types"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Display all possible IFC types for new instances"
@@ -188,67 +204,232 @@ class DisplayIFCTypes(bpy.types.Operator):
if not AuthoringData.is_loaded:
AuthoringData.load()
props = context.scene.BIMModelProperties
- props.relating_type = props.relating_type
+ if props.unfold_relating_type:
+ ifc_class = props.ifc_class
+ ifc_type_info = AuthoringData.ifc_type_info(ifc_class)
+ if ifc_type_info is None or not ifc_type_info.fully_loaded:
+ AuthoringData.assetize_ifc_class(ifc_class)
+ else:
+ prop.update_relating_type(props, context)
min_width = 250
- width = max([min_width, int(context.region.width / 7)])
+ width_scaling = 6. ** -1
+ width = max([min_width, int(width_scaling * context.region.width)])
return context.window_manager.invoke_popup(self, width=width)
def draw(self, context):
- layout = self.layout
props = context.scene.BIMModelProperties
+ if props.unfold_relating_type:
+ self.draw_by_class(props)
+ else:
+ self.draw_by_class_and_relating_type(props)
+
+ def draw_header(self, props):
+ layout = self.layout
split = layout.split(align=True, factor=0.6)
- col = split.column(align=True)
- row = col.row()
- row.label(text="Select IFC Type to add:")
- col.row().separator(factor=2)
+ col1 = split.column(align=True)
+ row = col1.row()
+ row.prop(data=props, property="unfold_relating_type", text="Preview All Relating Types")
+ col1.row().separator(factor=0.5)
+ row = col1.row()
+ row.label(text="Select IFC Construction Type:")
+ col1.row().separator(factor=2)
enabled = True
if AuthoringData.data["ifc_classes"]:
- row = col.row()
- row.prop(data=props, property="ifc_class", text="", icon="FILE_VOLUME")
- col.row().separator()
+ row = col1.row()
+ row.label(text="", icon="FILE_VOLUME")
+ prop_with_search(row, props, "ifc_class", text="")
+ col1.row().separator()
else:
enabled = False
+ col2 = split.column(align=True)
+ subsplit = col2.split(factor=0.9)
+ subcol = [subsplit.column() for _ in range(2)][-1]
+ subcol.operator("bim.type_instance_help", text="", icon="QUESTION")
+ col2.row().separator(factor=1)
+ return {"enabled": enabled, "layout": layout, "col1": col1, "col2": col2}
+
+ def draw_by_class(self, props):
+ header_data = self.draw_header(props)
+ enabled, layout = [header_data[key] for key in ["enabled", "layout"]]
+ ifc_class = props.ifc_class
+ num_cols = 3
+ layout.row().separator(factor=0.25)
+ flow = layout.grid_flow(row_major=True, columns=num_cols, even_columns=True, even_rows=True, align=True)
+ relating_types = AuthoringData.relating_types()
+ num_types = len(relating_types)
+ for idx, (rt_id, name, desc) in enumerate(relating_types):
+ outer_col = flow.column()
+ box = outer_col.box()
+ row = box.row()
+ row.label(text=name, icon="FILE_3D")
+ row.alignment = "CENTER"
+ row = box.row()
+ if enabled:
+ preview_ifc_types = AuthoringData.data["preview_ifc_types"]
+ if ifc_class in preview_ifc_types:
+ preview_ifc_class = preview_ifc_types[ifc_class]
+ if name in preview_ifc_class:
+ icon_id = preview_ifc_class[name]["icon_id"]
+ row.template_icon(icon_value=icon_id, scale=6.)
+ outer_col.row().separator(factor=0.5)
+ row = outer_col.row()
+ split = row.split(factor=0.5)
+ col = split.column()
+ op = col.operator("bim.select_type_instance", icon="RIGHTARROW_THIN")
+ op.ifc_class = ifc_class
+ op.relating_type_id = rt_id
+ col = split.column()
+ op = col.operator("bim.add_type_instance", icon="ADD")
+ op.from_invoke = True
+ op.ifc_class = ifc_class
+ if rt_id.isnumeric():
+ op.relating_type = int(rt_id)
+ factor = 2 if idx + 1 < math.ceil(num_types / num_cols) else 0.5
+ outer_col.row().separator(factor=factor)
+ last_row_cols = num_types % num_cols
+ if last_row_cols != 0:
+ for _ in range(num_cols - last_row_cols):
+ flow.column()
+
+ def draw_by_class_and_relating_type(self, props):
+ header_data = self.draw_header(props)
+ enabled, col1, col2 = [header_data[key] for key in ["enabled", "col1", "col2"]]
+ ifc_class = props.ifc_class
if AuthoringData.data["relating_types"]:
- row = col.row()
- row.prop(data=props, property="relating_type", text="", icon="FILE_3D")
- col.row().separator()
+ row = col1.row()
+ row.label(text="", icon="FILE_3D")
+ prop_with_search(row, props, "relating_type", text="")
+ col1.row().separator()
else:
enabled = False
- col.row().separator(factor=4)
- row = col.row()
- op = row.operator("bim.add_ifc_type_instance", icon="ADD")
+ col1.row().separator(factor=4.75)
+ row = col1.row()
row.enabled = enabled
- op.ifc_class = props.ifc_class
+ op = row.operator("bim.select_type_instance", icon="RIGHTARROW_THIN")
+ op.ifc_class = ifc_class
op.relating_type_id = props.relating_type
- col = split.column()
- box = col.box()
+ op = row.operator("bim.add_type_instance", icon="ADD")
+ op.from_invoke = True
+ op.ifc_class = ifc_class
+ relating_type = props.relating_type
+ if relating_type.isnumeric():
+ op.relating_type = int(relating_type)
+ box = col2.box()
if enabled:
box.template_icon(icon_value=props.icon_id, scale=6.)
-class AddIFCTypeInstance(bpy.types.Operator):
- bl_idname = "bim.add_ifc_type_instance"
- bl_label = "Add"
+class SelectTypeInstance(bpy.types.Operator):
+ bl_idname = "bim.select_type_instance"
+ bl_label = "Select"
bl_options = {"REGISTER", "UNDO"}
- bl_description = "Add an instance of this IFC type"
+ bl_description = "Pick Type Instance as selection for subsequent operations"
ifc_class: bpy.props.StringProperty()
relating_type_id: bpy.props.StringProperty()
- def close_panel(self, event):
- x, y = event.mouse_x, event.mouse_y
- bpy.context.window.cursor_warp(10, 10)
- move_back = lambda: bpy.context.window.cursor_warp(x, y)
- bpy.app.timers.register(move_back, first_interval=0.001)
-
def invoke(self, context, event):
- self.close_panel(event)
+ close_operator_panel(event)
return self.execute(context)
def execute(self, context):
props = context.scene.BIMModelProperties
- props.ifc_class, props.relating_type = self.ifc_class, self.relating_type_id
- bpy.ops.bim.add_type_instance()
- return {'FINISHED'}
+ if self.ifc_class != "":
+ props.ifc_class = self.ifc_class
+ if self.relating_type_id != "":
+ props.relating_type = self.relating_type_id
+ return {"FINISHED"}
+
+
+class TypeInstanceHelp(bpy.types.Operator):
+ bl_idname = "bim.type_instance_help"
+ bl_label = "IFC Construction Type Help"
+ bl_options = {"REGISTER", "UNDO"}
+ bl_description = "Click to read some contextual help"
+
+ def execute(self, context):
+ return {"FINISHED"}
+
+ def invoke(self, context, event):
+ return context.window_manager.invoke_popup(self, width=525)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.row().separator(factor=0.5)
+ row = layout.row()
+ row.alignment = "CENTER"
+ row.label(text="BlenderBIM Help", icon="BLENDER")
+ row = layout.row()
+ row.alignment = "CENTER"
+ row.label(text="[IFC Construction Type Browser]")
+ layout.row().separator(factor=0.5)
+ row = self.col_with_margins(layout.row()).row()
+ row.label(text="When to use:", icon="KEYTYPE_MOVING_HOLD_VEC")
+ self.draw_lines(layout, self.message_purpose)
+ layout.row().separator()
+ row = self.col_with_margins(layout.row()).row()
+ row.label(text="Overall workflow:", icon="KEYTYPE_MOVING_HOLD_VEC")
+ self.draw_lines(layout, self.message_overall)
+ layout.row().separator()
+ row = self.col_with_margins(layout.row()).row()
+ row.label(text="UI panel hints:", icon="KEYTYPE_MOVING_HOLD_VEC")
+ self.draw_lines(layout, self.message_ui)
+ layout.row().separator(factor=1.5)
+ row = self.col_with_margins(layout.row()).row()
+ row.label(text="Further help:", icon="KEYTYPE_MOVING_HOLD_VEC")
+ layout.row().separator(factor=0.5)
+ row = self.col_with_margins(layout).row()
+ op = row.operator("bim.open_upstream", text="Homepage", icon="HOME")
+ op.page = "home"
+ op = row.operator("bim.open_upstream", text="Docs", icon="DOCUMENTS")
+ op.page = "docs"
+ op = row.operator("bim.open_upstream", text="Wiki", icon="CURRENT_FILE")
+ op.page = "wiki"
+ op = row.operator("bim.open_upstream", text="Community", icon="COMMUNITY")
+ op.page = "community"
+ layout.row().separator()
+
+ @staticmethod
+ def col_with_margins(layout, margin_left=0.025, margin_right=None):
+ margin_right = margin_left if margin_right is None else margin_right
+ split = layout.split(factor=margin_left, align=True)
+ col = [split.column() for _ in range(2)][-1]
+ subsplit = col.split(factor=(1. - margin_right), align=True)
+ subcol = subsplit.column()
+ subsplit.column().label(text="")
+ return subcol
+
+ def draw_lines(self, layout, lines):
+ box = self.col_with_margins(layout).box()
+ for line in lines:
+ row = box.row()
+ row.label(text="", icon="RIGHTARROW_THIN")
+ row.label(text=line)
+
+ @property
+ def message_purpose(self):
+ return [
+ 'Available IFC Construction Types can be previewed and added through the button',
+ '"Browse IFC Construction Types", which appears when an IFC Project Library,',
+ 'containing in turn definitions of construction types, is loaded. In order to ',
+ 'manage loaded IFC Project Libraries, navigate to [Scene Properties] -> [IFC',
+ 'Project Setup] -> [IFC Project Library] under the Properties panel.'
+ ]
+
+ @property
+ def message_overall(self):
+ return [
+ 'Choose an IFC Construction Type by picking 1) an IFC Class and 2) a Relating Type. ',
+ 'Then, click on the "Add" button to directly add one instance of the chosen type to',
+ 'the model, or alternatively click on the "Select" button to be able to later add ',
+ 'several instances with SHIFT + A.'
+ ]
+
+ @property
+ def message_ui(self):
+ return [
+ 'If "Preview All Relating Types" is marked, a preview for every Relating Type will',
+ 'be shown at once. Not advisable on large projects with dozens of types per class.'
+ ]
class AlignProduct(bpy.types.Operator):
diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py
index 5da1e67535..0276c6e13e 100644
--- a/src/blenderbim/blenderbim/bim/module/model/prop.py
+++ b/src/blenderbim/blenderbim/bim/module/model/prop.py
@@ -44,16 +44,25 @@ def update_icon_id(self, context):
if ((ifc_class not in AuthoringData.data["preview_ifc_types"]
or relating_type not in AuthoringData.data["preview_ifc_types"][ifc_class])
and relating_type is not None):
- AuthoringData.assetize_relating_type_from_selection()
+ if not AuthoringData.assetize_relating_type_from_selection():
+ return
props = bpy.context.scene.BIMModelProperties
props.icon_id = AuthoringData.data["preview_ifc_types"][ifc_class][relating_type]["icon_id"]
def update_ifc_class(self, context):
- AuthoringData.load_ifc_classes()
- AuthoringData.load_relating_types()
- self.relating_type = AuthoringData.data["relating_types"][0][0]
- update_icon_id(self, context)
+ if not AuthoringData.updating:
+ AuthoringData.load_ifc_classes()
+ AuthoringData.load_relating_types()
+ props = context.scene.BIMModelProperties
+ if props.unfold_relating_type:
+ ifc_class = props.ifc_class
+ ifc_type_info = AuthoringData.ifc_type_info(ifc_class)
+ if ifc_type_info is None or not ifc_type_info.fully_loaded:
+ AuthoringData.assetize_ifc_class(ifc_class)
+ else:
+ self.relating_type = AuthoringData.data["relating_types"][0][0]
+ update_icon_id(self, context)
def update_relating_type(self, context):
@@ -61,26 +70,45 @@ def update_relating_type(self, context):
update_icon_id(self, context)
+def update_unfold_relating_type(self, context):
+ update_ifc_class(self, context)
+
+ # if self.unfold_relating_type:
+ # props = context.scene.BIMModelProperties
+ # ifc_class = props.ifc_class
+ # ifc_type_info = AuthoringData.ifc_type_info(ifc_class)
+ # if ifc_type_info is None or not ifc_type_info.fully_loaded:
+ # AuthoringData.assetize_ifc_class(ifc_class)
+ # else:
+ # update_ifc_class(self, context)
+
+
class BIMModelProperties(PropertyGroup):
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="IFC Class", update=update_ifc_class)
relating_type: bpy.props.EnumProperty(items=get_relating_type, name="Relating Type", update=update_relating_type)
icon_id: bpy.props.IntProperty()
+ unfold_relating_type: bpy.props.BoolProperty(update=update_unfold_relating_type)
occurrence_name_style: bpy.props.EnumProperty(
items=[("CLASS", "By Class", ""), ("TYPE", "By Type", ""), ("CUSTOM", "Custom", "")],
name="Occurrence Name Style",
)
occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function")
+ getter_enum = {
+ "ifc_class": get_ifc_class,
+ "relating_type": get_relating_type
+ }
def get_ifc_type_info_relating_types(self, context):
- ifc_class = self.ifc_class
+ ifc_class = self.name
return AuthoringData.relating_types(ifc_class=ifc_class)
class IfcTypeInfo(PropertyGroup):
- ifc_class: bpy.props.StringProperty(name="IFC class", description="IFC class")
+ name: bpy.props.StringProperty(name="IFC class", description="IFC class")
relating_type: bpy.props.EnumProperty(
name="Relating type", description="Relating type", items=get_ifc_type_info_relating_types
)
+ fully_loaded: bpy.props.BoolProperty(default=False)
diff --git a/src/blenderbim/blenderbim/bim/module/model/ui.py b/src/blenderbim/blenderbim/bim/module/model/ui.py
index 8a198ce7a1..dcdcf6655d 100644
--- a/src/blenderbim/blenderbim/bim/module/model/ui.py
+++ b/src/blenderbim/blenderbim/bim/module/model/ui.py
@@ -16,54 +16,15 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see .
-import blenderbim.bim.module.type.prop as type_prop
from bpy.types import Panel
-from blenderbim.bim.ifc import IfcStore
-from blenderbim.bim.module.model.data import AuthoringData
class BIM_PT_authoring(Panel):
- bl_idname = "BIM_PT_authoring"
- bl_label = "Authoring"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_category = "BlenderBIM"
-
- @classmethod
- def poll(cls, context):
- return IfcStore.get_file()
-
- def draw(self, context):
- if not AuthoringData.is_loaded:
- AuthoringData.load()
-
- props = context.scene.BIMModelProperties
- col = self.layout.column(align=True)
- enabled = True
-
- if AuthoringData.data["ifc_classes"]:
- col.prop(props, "ifc_class", text="", icon="FILE_VOLUME")
- else:
- col.label(text="No IFC Class", icon="FILE_VOLUME")
- enabled = False
- if AuthoringData.data["relating_types"]:
- col.prop(props, "relating_type", text="", icon="FILE_3D")
- else:
- col.label(text="No Relating Type", icon="FILE_3D")
- enabled = False
- row = col.row()
- row.operator("bim.add_type_instance", icon="ADD")
- row.enabled = enabled
-
-
-class BIM_PT_authoring_architectural(Panel):
bl_label = "Architectural"
- bl_idname = "BIM_PT_authoring_architectural"
- bl_options = {"DEFAULT_CLOSED"}
+ bl_idname = "BIM_PT_authoring"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "BlenderBIM"
- bl_parent_id = "BIM_PT_authoring"
def draw(self, context):
row = self.layout.row(align=True)
diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py
index 1f65486c12..003ea26aa3 100644
--- a/src/blenderbim/blenderbim/bim/module/model/workspace.py
+++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py
@@ -37,6 +37,7 @@ class BimTool(WorkSpaceTool):
bl_keymap = (
# ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
# ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}),
+ ("bim.hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}),
("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}),
("bim.join_wall", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("join_type", "L")]}),
("bim.join_wall", {"type": "Y", "value": "PRESS", "shift": True}, {"properties": [("join_type", "V")]}),
@@ -54,19 +55,52 @@ class BimTool(WorkSpaceTool):
if not AuthoringData.is_loaded and IfcStore.get_file():
AuthoringData.load()
+ props = context.scene.BIMModelProperties
+ is_tool_header = context.region.type == "TOOL_HEADER"
+ ifc_classes = AuthoringData.data["ifc_classes"]
+ relating_types = AuthoringData.data["relating_types"]
+
row = layout.row(align=True)
if not IfcStore.get_file():
row.label(text="No IFC Project", icon="ERROR")
return
- props = context.scene.BIMModelProperties
- if AuthoringData.data["ifc_classes"]:
- row.operator("bim.display_ifc_types", icon="COLLAPSEMENU")
- else:
- row.label(text="No IFC Class")
- if not AuthoringData.data["relating_types"]:
- row.label(text="No Relating Type")
- row.label(text="", icon="BLANK1")
+ if is_tool_header:
+ row.operator("bim.type_instance_help", text="", icon="QUESTION")
+
+ if ifc_classes and is_tool_header:
+ row.label(text="", icon="BLANK1")
+ row.operator("bim.display_ifc_types", icon="COLLAPSEMENU")
+
+ ifc_class = props.ifc_class
+ relating_type = AuthoringData.relating_type_name_by_id(ifc_class, props.relating_type)
+
+ if is_tool_header:
+ row.label(text="", icon="BLANK1")
+ row = layout.row(align=True)
+ row.label(text="", icon="EVENT_SHIFT")
+ row.label(text="", icon="EVENT_A")
+ if ifc_classes:
+ row.label(text=f" Add")
+ row.label(text="", icon="FILE_VOLUME")
+ row.label(text=ifc_class)
+ row.label(text="", icon="FILE_3D")
+ row.label(text=f"{relating_type} ")
+ else:
+ row.label(text=f" Add instance")
+ else:
+ txt_ifc_class = ifc_class if ifc_classes else "No IFC Class"
+ txt_relating_type = relating_type if relating_types else "No Relating Type"
+ row = layout.row(align=True)
+ row.label(text="Selected IFC Type:")
+ row = layout.row(align=True)
+ row.label(text=txt_ifc_class, icon="FILE_VOLUME")
+ row = layout.row(align=True)
+ row.label(text=txt_relating_type, icon="FILE_3D")
+ row = layout.row(align=True)
+ row.label(text="", icon="EVENT_SHIFT")
+ row.label(text="", icon="EVENT_A")
+ row.label(text=f" Add Type Instance")
if AuthoringData.data["ifc_classes"]:
if props.ifc_class == "IfcWallType":
@@ -148,6 +182,9 @@ class Hotkey(bpy.types.Operator):
getattr(self, f"hotkey_{self.hotkey}")()
return {"FINISHED"}
+ def hotkey_S_A(self):
+ bpy.ops.bim.add_type_instance()
+
def hotkey_S_C(self):
if self.has_ifc_class and self.props.ifc_class == "IfcWallType":
bpy.ops.bim.align_wall(align_type="CENTERLINE")