diff --git a/src/bonsai/bonsai/bim/module/model/data.py b/src/bonsai/bonsai/bim/module/model/data.py index 9a37bc55fa..c19e21a6dc 100644 --- a/src/bonsai/bonsai/bim/module/model/data.py +++ b/src/bonsai/bonsai/bim/module/model/data.py @@ -58,14 +58,15 @@ class AuthoringData: cls.data["ifc_classes"] = cls.ifc_classes() cls.data["ifc_class_current"] = cls.ifc_class_current() # Make sure .ifc_classes() was run before next lines - cls.data["filtered_type_elements"] = cls.filtered_type_elements() - # Make sure .filtered_type_elements() was run before next lines + cls.data["type_elements"] = cls.type_elements() + cls.data["type_elements_filtered"] = cls.type_elements_filtered() cls.data["relating_type_id"] = cls.relating_type_id() # Make sure .relating_type_id() was run before next lines cls.data["relating_type_id_current"] = cls.relating_type_id_current() cls.data["relating_type_name"] = cls.relating_type_name() cls.data["relating_type_description"] = cls.relating_type_description() cls.data["predefined_type"] = cls.predefined_type() + # Make sure .type_elements_filtered() was run before next lines cls.data["total_types"] = cls.total_types() cls.data["total_pages"] = cls.total_pages() # Only after .total_types() cls.data["next_page"] = cls.next_page() @@ -116,7 +117,7 @@ class AuthoringData: @classmethod def total_types(cls): - return len(cls.data["filtered_type_elements"]) + return len(cls.data["type_elements_filtered"]) @classmethod def total_pages(cls): @@ -134,19 +135,24 @@ class AuthoringData: return cls.props.type_page - 1 @classmethod - def filtered_type_elements(cls): + def type_elements(cls): ifc_class = cls.data["ifc_class_current"] if not ifc_class: return [] elements = list(tool.Ifc.get().by_type(ifc_class)) - if cls.props.search_name: - elements = [e for e in elements if cls.props.search_name.lower() in (e.Name or "Unnamed").lower()] return natsorted(elements, key=lambda s: (s.Name or "Unnamed").lower()) + @classmethod + def type_elements_filtered(cls): + elements = cls.data["type_elements"] + if cls.props.search_name: + return [e for e in elements if cls.props.search_name.lower() in (e.Name or "Unnamed").lower()] + return elements + @classmethod def paginated_relating_types(cls): results = [] - elements = cls.data["filtered_type_elements"] + elements = cls.data["type_elements_filtered"] elements = elements[(cls.props.type_page - 1) * cls.types_per_page : cls.props.type_page * cls.types_per_page] for element in elements: predefined_type = ifcopenshell.util.element.get_predefined_type(element) @@ -273,7 +279,7 @@ class AuthoringData: @classmethod def relating_type_id(cls): - elements = cls.data["filtered_type_elements"] + elements = cls.data["type_elements"] return [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in elements] @classmethod diff --git a/src/bonsai/bonsai/bim/module/model/product.py b/src/bonsai/bonsai/bim/module/model/product.py index 9e9bafcaba..7d76e47d4a 100644 --- a/src/bonsai/bonsai/bim/module/model/product.py +++ b/src/bonsai/bonsai/bim/module/model/product.py @@ -568,7 +568,7 @@ class LoadTypeThumbnails(bpy.types.Operator, tool.Ifc.Operator): # Large projects have hundreds of types which can lead to unnecessary lag. if not AuthoringData.is_loaded: AuthoringData.load() - queue = AuthoringData.data["filtered_type_elements"] + queue = AuthoringData.data["type_elements_filtered"] if self.limit: queue = queue[self.offset : self.offset + self.limit] else: diff --git a/src/bonsai/bonsai/bim/module/model/prop.py b/src/bonsai/bonsai/bim/module/model/prop.py index c9f1de899c..3a164477d6 100644 --- a/src/bonsai/bonsai/bim/module/model/prop.py +++ b/src/bonsai/bonsai/bim/module/model/prop.py @@ -65,10 +65,14 @@ def update_relating_type_id(self, context): AuthoringData.data["relating_type_name"] = AuthoringData.relating_type_name() AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail() AuthoringData.data["predefined_type"] = AuthoringData.predefined_type() + self.type_page = [e[0] for e in AuthoringData.data["relating_type_id"]].index(self.relating_type_id) // 9 + 1 def update_type_page(self, context): AuthoringData.data["paginated_relating_types"] = AuthoringData.paginated_relating_types() + bpy.ops.bim.load_type_thumbnails(ifc_class=self.ifc_class, offset=9 * (self.type_page - 1), limit=9) + self["type_page"] = min(self["type_page"], AuthoringData.data["total_pages"]) + self["type_page"] = max(self["type_page"], 1) def update_relating_array_from_object(self, context): @@ -101,7 +105,7 @@ def update_search_name(self, context): AuthoringData.load() # Total number of pages may decrease when using the search bar : if self.type_page > AuthoringData.data["total_pages"]: - self.type_page = AuthoringData.data["total_pages"] + self.type_page = max(1, AuthoringData.data["total_pages"]) bpy.ops.bim.load_type_thumbnails(ifc_class=self.ifc_class) @@ -177,7 +181,7 @@ class BIMModelProperties(PropertyGroup): # Used for plan calculation points such as in room generation rl3: bpy.props.FloatProperty(name="RL", default=1, subtype="DISTANCE", description="Z offset for space calculation") x_angle: bpy.props.FloatProperty(name="X Angle", default=0, subtype="ANGLE", min=-pi / 180 * 89, max=pi / 180 * 89) - type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page) + type_page: bpy.props.IntProperty(name="Type Page", default=1, min=1,update=update_type_page) type_name: bpy.props.StringProperty(name="Name", default="TYPEX") boundary_class: bpy.props.EnumProperty(items=get_boundary_class, name="Boundary Class") direction_sense: bpy.props.EnumProperty( diff --git a/src/bonsai/bonsai/bim/module/model/ui.py b/src/bonsai/bonsai/bim/module/model/ui.py index 08fc46cb6f..0534aa6b55 100644 --- a/src/bonsai/bonsai/bim/module/model/ui.py +++ b/src/bonsai/bonsai/bim/module/model/ui.py @@ -87,7 +87,6 @@ class LaunchTypeManager(bpy.types.Operator): bl_description = "Display all available Construction Types to add new occurrences" def execute(self, context): - bpy.ops.bim.hotkey("INVOKE_DEFAULT", hotkey="S_A") return {"FINISHED"} def invoke(self, context, event): @@ -101,9 +100,7 @@ class LaunchTypeManager(bpy.types.Operator): # will be None if project has no types if ifc_class is not None: bpy.ops.bim.load_type_thumbnails(ifc_class=ifc_class, offset=0, limit=9) - return context.window_manager.invoke_props_dialog( - self, width=550, title="Type Manager", confirm_text="Add Occurrence" - ) + return context.window_manager.invoke_props_dialog(self, width=550, title="Type Manager", confirm_text="Close") def draw(self, context): props = context.scene.BIMModelProperties @@ -113,25 +110,33 @@ class LaunchTypeManager(bpy.types.Operator): text += "s" row.label(text=text, icon="FILE_VOLUME") row.menu("BIM_MT_type_manager_menu", text="", icon="PREFERENCES") + row = self.layout.row(align=True) row.operator("bim.launch_add_element", text=f"Create New {AuthoringData.data['ifc_element_type']}", icon="ADD") + row = self.layout.row(align=True) + row.prop(props, "relating_type_id", text="") + # prop_with_search(row, props, "relating_type_id", text="", should_click_ok_to_validate=True) + row.prop(props, "search_name", icon="FILTER", text="") + columns = self.layout.column_flow(columns=3) - row = columns.row(align=True) - row.alignment = "CENTER" + if AuthoringData.data["total_pages"] > 0: + row = columns.row(align=True) + row.alignment = "RIGHT" + row2 = row.row(align=True) + row2.label(text="Page") + row2.prop(props, "type_page", text="", emboss=False) + row2.label(text=f"/{AuthoringData.data['total_pages']} ") - row = columns.row(align=True) - row.alignment = "RIGHT" - if AuthoringData.data["total_pages"] > 1: - row.label(text=f"Page {props.type_page}/{AuthoringData.data['total_pages']} ") - if AuthoringData.data["prev_page"]: - op = row.operator("bim.change_type_page", icon="TRIA_LEFT", text="") - op.page = AuthoringData.data["prev_page"] - if AuthoringData.data["next_page"]: - op = row.operator("bim.change_type_page", icon="TRIA_RIGHT", text="") - op.page = AuthoringData.data["next_page"] + prev_page_op = row.row(align=True) + op = prev_page_op.operator("bim.change_type_page", icon="TRIA_LEFT", text="") + op.page = AuthoringData.data["prev_page"] or 0 + prev_page_op.enabled = op.page > 0 - self.layout.prop(props, "search_name", icon="VIEWZOOM", text="") + next_page_op = row.row(align=True) + op = next_page_op.operator("bim.change_type_page", icon="TRIA_RIGHT", text="") + op.page = AuthoringData.data["next_page"] or 0 + next_page_op.enabled = op.page > 0 flow = self.layout.grid_flow(row_major=True, columns=3, even_columns=True, even_rows=True, align=True) @@ -139,11 +144,11 @@ class LaunchTypeManager(bpy.types.Operator): outer_col = flow.column() box = outer_col.box() - row = box.row(align=True) + row = box.row() op = row.operator("bim.set_active_type", text=relating_type["name"], icon="BLANK1", emboss=False) op.relating_type = relating_type["id"] - op = row.operator("bim.launch_type_menu", icon="PREFERENCES", text="", emboss=False) + op = row.operator("bim.launch_type_menu", icon="PREFERENCES", text="", emboss=True) op.relating_type_id = relating_type["id"] row = box.row() diff --git a/src/bonsai/bonsai/bim/module/model/workspace.py b/src/bonsai/bonsai/bim/module/model/workspace.py index ecdf6d6044..0e6e3bf4e9 100644 --- a/src/bonsai/bonsai/bim/module/model/workspace.py +++ b/src/bonsai/bonsai/bim/module/model/workspace.py @@ -509,13 +509,9 @@ class CreateObjectUI: if ifc_class: box = cls.layout.box() row = box.row(align=True) - prop_with_search(row, cls.props, "relating_type_id", text="") - if AuthoringData.data["type_thumbnail"] and ui_context == "TOOL_HEADER": - row.template_icon(icon_value=AuthoringData.data["type_thumbnail"]) - row.operator("bim.launch_type_manager", text="Type Manager", emboss=False) - else: - row.operator("bim.launch_type_manager", icon="BLANK1", text="Type Manager", emboss=False) - + if ui_context == "TOOL_HEADER": + row.template_icon(icon_value=AuthoringData.data.get("type_thumbnail", 0)) + row.operator("bim.launch_type_manager", text=AuthoringData.data["relating_type_name"], emboss=False) row.operator( "bim.launch_type_manager", icon=tool.Blender.TYPE_MANAGER_ICON,