mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 10:33:44 +00:00
Type manager can now browse to type classes that don't have any types yet
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
import functools
|
import functools
|
||||||
|
import ifcopenshell
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
||||||
@@ -41,6 +42,8 @@ class AuthoringData:
|
|||||||
cls.load_ifc_classes()
|
cls.load_ifc_classes()
|
||||||
cls.load_relating_types()
|
cls.load_relating_types()
|
||||||
cls.load_relating_types_browser()
|
cls.load_relating_types_browser()
|
||||||
|
cls.data["type_class"] = cls.type_class()
|
||||||
|
cls.data["type_predefined_type"] = cls.type_predefined_type()
|
||||||
cls.data["total_types"] = cls.total_types()
|
cls.data["total_types"] = cls.total_types()
|
||||||
cls.data["total_pages"] = cls.total_pages()
|
cls.data["total_pages"] = cls.total_pages()
|
||||||
cls.data["next_page"] = cls.next_page()
|
cls.data["next_page"] = cls.next_page()
|
||||||
@@ -51,6 +54,24 @@ class AuthoringData:
|
|||||||
cls.data["has_visible_openings"] = cls.has_visible_openings()
|
cls.data["has_visible_openings"] = cls.has_visible_openings()
|
||||||
cls.data["active_class"] = cls.active_class()
|
cls.data["active_class"] = cls.active_class()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def type_class(cls):
|
||||||
|
declaration = tool.Ifc.schema().declaration_by_name("IfcElementType")
|
||||||
|
declarations = ifcopenshell.util.schema.get_subtypes(declaration)
|
||||||
|
names = [d.name() for d in declarations]
|
||||||
|
names.extend(("IfcDoorStyle", "IfcWindowStyle"))
|
||||||
|
return [(c, c, "") for c in sorted(names)]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def type_predefined_type(cls):
|
||||||
|
results = []
|
||||||
|
declaration = tool.Ifc().schema().declaration_by_name(cls.props.type_class)
|
||||||
|
for attribute in declaration.attributes():
|
||||||
|
if attribute.name() == "PredefinedType":
|
||||||
|
results.extend([(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()])
|
||||||
|
break
|
||||||
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def type_thumbnail(cls):
|
def type_thumbnail(cls):
|
||||||
if not cls.props.relating_type_id:
|
if not cls.props.relating_type_id:
|
||||||
@@ -72,13 +93,13 @@ class AuthoringData:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def total_types(cls):
|
def total_types(cls):
|
||||||
ifc_class = cls.props.ifc_class
|
type_class = cls.props.type_class
|
||||||
return len(tool.Ifc.get().by_type(ifc_class)) if ifc_class else 0
|
return len(tool.Ifc.get().by_type(type_class)) if type_class else 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def total_pages(cls):
|
def total_pages(cls):
|
||||||
ifc_class = cls.props.ifc_class
|
type_class = cls.props.type_class
|
||||||
total_types = len(tool.Ifc.get().by_type(ifc_class)) if ifc_class else 0
|
total_types = len(tool.Ifc.get().by_type(type_class)) if type_class else 0
|
||||||
return math.ceil(total_types / cls.types_per_page)
|
return math.ceil(total_types / cls.types_per_page)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -93,20 +114,26 @@ class AuthoringData:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def paginated_relating_types(cls):
|
def paginated_relating_types(cls):
|
||||||
ifc_class = cls.props.ifc_class
|
type_class = cls.props.type_class
|
||||||
if not ifc_class:
|
if not type_class:
|
||||||
return []
|
return []
|
||||||
results = []
|
results = []
|
||||||
elements = sorted(tool.Ifc.get().by_type(ifc_class), key=lambda e: e.Name or "Unnamed")
|
elements = sorted(tool.Ifc.get().by_type(type_class), key=lambda e: e.Name or "Unnamed")
|
||||||
elements = elements[(cls.props.type_page - 1) * cls.types_per_page:cls.props.type_page * cls.types_per_page]
|
elements = elements[(cls.props.type_page - 1) * cls.types_per_page : cls.props.type_page * cls.types_per_page]
|
||||||
for element in elements:
|
for element in elements:
|
||||||
results.append({
|
predefined_type = ifcopenshell.util.element.get_predefined_type(element)
|
||||||
"id": element.id(),
|
if predefined_type == "NOTDEFINED":
|
||||||
"ifc_class": element.is_a(),
|
predefined_type = None
|
||||||
"name": element.Name or "Unnamed",
|
results.append(
|
||||||
"description": element.Description or "No Description",
|
{
|
||||||
"icon_id": cls.type_thumbnails.get(element.id(), None) or 0,
|
"id": element.id(),
|
||||||
})
|
"ifc_class": element.is_a(),
|
||||||
|
"name": element.Name or "Unnamed",
|
||||||
|
"description": element.Description or "No Description",
|
||||||
|
"predefined_type": predefined_type,
|
||||||
|
"icon_id": cls.type_thumbnails.get(element.id(), None) or 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ def get_ifc_class(self, context):
|
|||||||
return AuthoringData.data["ifc_classes"]
|
return AuthoringData.data["ifc_classes"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_type_class(self, context):
|
||||||
|
if not AuthoringData.is_loaded:
|
||||||
|
AuthoringData.load()
|
||||||
|
return AuthoringData.data["type_class"]
|
||||||
|
|
||||||
|
|
||||||
def get_relating_type(self, context):
|
def get_relating_type(self, context):
|
||||||
if not AuthoringData.is_loaded:
|
if not AuthoringData.is_loaded:
|
||||||
AuthoringData.load()
|
AuthoringData.load()
|
||||||
@@ -41,6 +47,12 @@ def get_relating_type_browser(self, context):
|
|||||||
return AuthoringData.data["relating_types_ids_browser"]
|
return AuthoringData.data["relating_types_ids_browser"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_type_predefined_type(self, context):
|
||||||
|
if not AuthoringData.is_loaded:
|
||||||
|
AuthoringData.load()
|
||||||
|
return AuthoringData.data["type_predefined_type"]
|
||||||
|
|
||||||
|
|
||||||
def store_cursor_position(context, event, cursor=True, window=True):
|
def store_cursor_position(context, event, cursor=True, window=True):
|
||||||
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
||||||
if cursor:
|
if cursor:
|
||||||
@@ -62,8 +74,10 @@ def update_icon_id(self, context, browser=False):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def set_icon(update_interval_seconds=1e-4):
|
def set_icon(update_interval_seconds=1e-4):
|
||||||
if (ifc_class not in self.constr_classes
|
if (
|
||||||
or relating_type_id not in self.constr_classes[ifc_class].constr_types):
|
ifc_class not in self.constr_classes
|
||||||
|
or relating_type_id not in self.constr_classes[ifc_class].constr_types
|
||||||
|
):
|
||||||
return update_interval_seconds
|
return update_interval_seconds
|
||||||
else:
|
else:
|
||||||
self.icon_id = self.constr_classes[ifc_class].constr_types[relating_type_id].icon_id
|
self.icon_id = self.constr_classes[ifc_class].constr_types[relating_type_id].icon_id
|
||||||
@@ -76,6 +90,15 @@ def update_ifc_class(self, context):
|
|||||||
AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail()
|
AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail()
|
||||||
|
|
||||||
|
|
||||||
|
def update_type_class(self, context):
|
||||||
|
AuthoringData.data["total_types"] = AuthoringData.total_types()
|
||||||
|
AuthoringData.data["total_pages"] = AuthoringData.total_pages()
|
||||||
|
AuthoringData.data["prev_page"] = AuthoringData.prev_page()
|
||||||
|
AuthoringData.data["next_page"] = AuthoringData.next_page()
|
||||||
|
AuthoringData.data["paginated_relating_types"] = AuthoringData.paginated_relating_types()
|
||||||
|
AuthoringData.data["type_predefined_type"] = AuthoringData.type_predefined_type()
|
||||||
|
|
||||||
|
|
||||||
def update_ifc_class_browser(self, context):
|
def update_ifc_class_browser(self, context):
|
||||||
if context.region is not None and context.region.type != "TOOL_HEADER":
|
if context.region is not None and context.region.type != "TOOL_HEADER":
|
||||||
AuthoringData.load_ifc_classes()
|
AuthoringData.load_ifc_classes()
|
||||||
@@ -206,3 +229,16 @@ class BIMModelProperties(PropertyGroup):
|
|||||||
z: bpy.props.FloatProperty(name="Z", default=0.5)
|
z: bpy.props.FloatProperty(name="Z", default=0.5)
|
||||||
rl: bpy.props.FloatProperty(name="RL", default=1)
|
rl: bpy.props.FloatProperty(name="RL", default=1)
|
||||||
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
||||||
|
type_template: bpy.props.EnumProperty(
|
||||||
|
items=(
|
||||||
|
("1", "Custom Mesh", ""),
|
||||||
|
("2", "Vertical Layers", ""),
|
||||||
|
("2", "Horizontal Layers", ""),
|
||||||
|
("3", "Extruded Profile", ""),
|
||||||
|
("4", "Non-Geometric Type", ""),
|
||||||
|
),
|
||||||
|
name="Type Template",
|
||||||
|
default="1",
|
||||||
|
)
|
||||||
|
type_class: bpy.props.EnumProperty(items=get_type_class, name="IFC Class", update=update_type_class)
|
||||||
|
type_predefined_type: bpy.props.EnumProperty(items=get_type_predefined_type, name="Predefined Type", default=None)
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class LaunchTypeManager(bpy.types.Operator):
|
|||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
props.type_page = 1
|
props.type_page = 1
|
||||||
|
if props.ifc_class:
|
||||||
|
props.type_class = props.ifc_class
|
||||||
bpy.ops.bim.load_type_thumbnails(ifc_class=props.ifc_class)
|
bpy.ops.bim.load_type_thumbnails(ifc_class=props.ifc_class)
|
||||||
if not AuthoringData.is_loaded:
|
if not AuthoringData.is_loaded:
|
||||||
AuthoringData.load()
|
AuthoringData.load()
|
||||||
@@ -43,15 +45,24 @@ class LaunchTypeManager(bpy.types.Operator):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row()
|
||||||
|
row.prop(props, "type_class", text="")
|
||||||
|
|
||||||
|
columns = self.layout.column_flow(columns=3)
|
||||||
|
row = columns.row()
|
||||||
|
row.alignment = "LEFT"
|
||||||
|
row.label(text=f"{AuthoringData.data['total_types']} Types", icon="FILE_VOLUME")
|
||||||
|
|
||||||
|
row = columns.row(align=True)
|
||||||
|
row.alignment = "CENTER"
|
||||||
|
row.prop(props, "type_predefined_type", text="")
|
||||||
|
row.prop(props, "type_template", text="")
|
||||||
|
op = row.operator("bim.change_type_page", icon="ADD", text="")
|
||||||
|
|
||||||
|
row = columns.row(align=True)
|
||||||
row.alignment = "RIGHT"
|
row.alignment = "RIGHT"
|
||||||
#row.label(text=f"", icon="FILE_VOLUME")
|
|
||||||
|
|
||||||
text = f"{AuthoringData.data['total_types']} types"
|
|
||||||
if AuthoringData.data["total_pages"] > 1:
|
if AuthoringData.data["total_pages"] > 1:
|
||||||
text += f" ({props.type_page}/{AuthoringData.data['total_pages']}) "
|
row.label(text=f"Page {props.type_page}/{AuthoringData.data['total_pages']} ")
|
||||||
row.label(text=text)
|
|
||||||
|
|
||||||
if AuthoringData.data["prev_page"]:
|
if AuthoringData.data["prev_page"]:
|
||||||
op = row.operator("bim.change_type_page", icon="TRIA_LEFT", text="")
|
op = row.operator("bim.change_type_page", icon="TRIA_LEFT", text="")
|
||||||
op.page = AuthoringData.data["prev_page"]
|
op.page = AuthoringData.data["prev_page"]
|
||||||
@@ -74,11 +85,16 @@ class LaunchTypeManager(bpy.types.Operator):
|
|||||||
row.label(text=relating_type["description"])
|
row.label(text=relating_type["description"])
|
||||||
|
|
||||||
row = box.row()
|
row = box.row()
|
||||||
row.template_icon(icon_value=relating_type["icon_id"], scale=4)
|
if relating_type["icon_id"]:
|
||||||
|
row.template_icon(icon_value=relating_type["icon_id"], scale=4)
|
||||||
|
else:
|
||||||
|
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
|
||||||
|
op.ifc_class = props.type_class
|
||||||
|
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
|
|
||||||
op = row.operator("bim.add_constr_type_instance", icon="ADD")
|
text = f"Add {relating_type['predefined_type']}" if relating_type["predefined_type"] else "Add"
|
||||||
|
op = row.operator("bim.add_constr_type_instance", icon="ADD", text=text)
|
||||||
op.from_invoke = True
|
op.from_invoke = True
|
||||||
op.ifc_class = relating_type["ifc_class"]
|
op.ifc_class = relating_type["ifc_class"]
|
||||||
op.relating_type_id = relating_type["id"]
|
op.relating_type_id = relating_type["id"]
|
||||||
|
|||||||
Reference in New Issue
Block a user