Modeling dimensions now have sensible defaults depending on units and show prior to element creation

This commit is contained in:
Dion Moult
2022-10-15 11:06:09 +11:00
parent 28aab490df
commit b90ab70658
9 changed files with 227 additions and 122 deletions
@@ -1,5 +1,5 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on # BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of BlenderBIM Add-on. # This file is part of BlenderBIM Add-on.
# #
@@ -1,5 +1,5 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on # BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of BlenderBIM Add-on. # This file is part of BlenderBIM Add-on.
# #
@@ -39,6 +39,7 @@ class BimTool(WorkSpaceTool):
bl_keymap = ( bl_keymap = (
# ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}), # ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
# ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}), # ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}),
#("bim.sync_modeling", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
("bim.hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}), ("bim.hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}),
("bim.hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}), ("bim.hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}),
("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}), ("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}),
@@ -56,12 +57,18 @@ class BimTool(WorkSpaceTool):
("bim.hotkey", {"type": "O", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_O")]}), ("bim.hotkey", {"type": "O", "value": "PRESS", "alt": True}, {"properties": [("hotkey", "A_O")]}),
) )
def draw_settings(context, layout, something): def draw_settings(context, layout, ws_tool):
props = context.scene.BIMModelProperties # Unlike operators, Blender doesn't treat workspace tools as a class, so we'll create our own.
is_tool_header = context.region.type == "TOOL_HEADER" BimToolUI.draw(context, layout)
is_sidebar = context.region.type == "UI"
row = layout.row(align=True)
class BimToolUI:
@classmethod
def draw(cls, context, layout):
cls.layout = layout
cls.props = context.scene.BIMModelProperties
row = cls.layout.row(align=True)
if not tool.Ifc.get(): if not tool.Ifc.get():
row.label(text="No IFC Project", icon="ERROR") row.label(text="No IFC Project", icon="ERROR")
return return
@@ -69,121 +76,87 @@ class BimTool(WorkSpaceTool):
if not AuthoringData.is_loaded: if not AuthoringData.is_loaded:
AuthoringData.load() AuthoringData.load()
ifc_classes = AuthoringData.data["ifc_classes"] if "ifc_classes" in AuthoringData.data else False #if ifc_classes and relating_types_ids and not cls.props.icon_id and not is_tool_header:
relating_types_ids = (
AuthoringData.data["relating_types_ids"] if "relating_types_ids" in AuthoringData.data else False
)
#if ifc_classes and relating_types_ids and not props.icon_id and not is_tool_header:
# # hack Dion won't like to show a preview also on the first time the sidebar is shown # # hack Dion won't like to show a preview also on the first time the sidebar is shown
# bpy.app.timers.register(lambda: prop.update_ifc_class(props, "lost_context")) # bpy.app.timers.register(lambda: prop.update_ifc_class(cls.props, "lost_context"))
# bpy.app.timers.register(lambda: prop.update_relating_type(props, "lost_context")) # bpy.app.timers.register(lambda: prop.update_relating_type(cls.props, "lost_context"))
ifc_class = props.ifc_class if context.region.type == "TOOL_HEADER":
relating_type_id = props.relating_type_id cls.draw_header_interface()
elif context.region.type == "UI":
cls.draw_sidebar_interface()
if is_tool_header: if context.active_object:
row = layout.row(align=True) cls.draw_edit_object_interface(context)
if ifc_classes: elif not context.selected_objects:
row.label(text="", icon="FILE_VOLUME") cls.draw_create_object_interface()
row.prop(data=props, property="ifc_class", text="")
else:
row.label(text="No Construction Class", icon="FILE_VOLUME")
row = layout.row(align=True)
if relating_types_ids:
row.label(text="", icon="FILE_3D")
prop_with_search(row, props, "relating_type_id", text="")
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="")
else:
row.label(text="No Construction Type", icon="FILE_3D")
if ifc_classes:
#row = layout.row()
#row.operator("bim.display_constr_types", icon="TRIA_DOWN", text="")
row = layout.row(align=True) @classmethod
row.label(text="", icon="EVENT_SHIFT") def draw_create_object_interface(cls):
row.label(text="", icon="EVENT_A") if not AuthoringData.data["relating_types_ids"]:
op = row.operator("bim.add_constr_type_instance", text="Add") return
op.from_invoke = True if cls.props.ifc_class == "IfcWallType":
op.ifc_class = ifc_class row = cls.layout.row(align=True)
if relating_type_id.isnumeric(): row.prop(data=cls.props, property="extrusion_depth", text="Height")
op.relating_type_id = int(relating_type_id)
elif is_sidebar:
row = layout.row(align=True)
if ifc_classes:
row.label(text="", icon="FILE_VOLUME")
prop_with_search(row, props, "ifc_class", text="")
else:
row.label(text="No Construction Class", icon="FILE_VOLUME")
row = layout.row(align=True)
if relating_types_ids:
row.label(text="", icon="FILE_3D")
prop_with_search(row, props, "relating_type_id", text="")
else:
row.label(text="No Construction Type", icon="FILE_3D")
box = layout.box() row = cls.layout.row(align=True)
if AuthoringData.data["type_thumbnail"]: row.prop(data=cls.props, property="length", text="Length")
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5) elif cls.props.ifc_class in ("IfcColumnType", "IfcBeamType", "IfcMemberType"):
else: row = cls.layout.row(align=True)
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH") row.prop(data=cls.props, property="cardinal_point", text="Axis")
op.ifc_class = props.ifc_class
if ifc_classes: row = cls.layout.row(align=True)
row = layout.row(align=True) label = "Height" if cls.props.ifc_class == "IfcColumn" else "Length"
row.label(text="", icon="EVENT_SHIFT") row.prop(data=cls.props, property="extrusion_depth", text=label)
row.label(text="", icon="EVENT_A") elif cls.props.ifc_class in ("IfcWindowType", "IfcWindowStyle", "IfcDoorType", "IfcDoorStyle"):
op = row.operator("bim.add_constr_type_instance", text="Add") row = cls.layout.row(align=True)
op.from_invoke = True row.prop(data=cls.props, property="rl", text="RL")
op.ifc_class = ifc_class
if relating_type_id.isnumeric():
op.relating_type_id = int(relating_type_id)
@classmethod
def draw_edit_object_interface(cls, context):
if AuthoringData.data["active_class"] in ("IfcWall", "IfcWallStandardCase"): if AuthoringData.data["active_class"] in ("IfcWall", "IfcWallStandardCase"):
row = layout.row(align=True) row = cls.layout.row(align=True)
row.prop(data=props, property="extrusion_depth", text="Height") row.prop(data=cls.props, property="extrusion_depth", text="Height")
op = row.operator("bim.change_extrusion_depth", icon="FILE_REFRESH", text="") op = row.operator("bim.change_extrusion_depth", icon="FILE_REFRESH", text="")
op.depth = props.extrusion_depth op.depth = cls.props.extrusion_depth
row = layout.row(align=True) row = cls.layout.row(align=True)
row.prop(data=props, property="length", text="Length") row.prop(data=cls.props, property="length", text="Length")
op = row.operator("bim.change_layer_length", icon="FILE_REFRESH", text="") op = row.operator("bim.change_layer_length", icon="FILE_REFRESH", text="")
op.length = props.length op.length = cls.props.length
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E") row.label(text="", icon="EVENT_E")
row.operator("bim.hotkey", text="Extend").hotkey = "S_E" row.operator("bim.hotkey", text="Extend").hotkey = "S_E"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_T") row.label(text="", icon="EVENT_T")
row.operator("bim.hotkey", text="Butt").hotkey = "S_T" row.operator("bim.hotkey", text="Butt").hotkey = "S_T"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_Y") row.label(text="", icon="EVENT_Y")
row.operator("bim.hotkey", text="Mitre").hotkey = "S_Y" row.operator("bim.hotkey", text="Mitre").hotkey = "S_Y"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_M") row.label(text="", icon="EVENT_M")
row.operator("bim.hotkey", text="Merge").hotkey = "S_M" row.operator("bim.hotkey", text="Merge").hotkey = "S_M"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_F") row.label(text="", icon="EVENT_F")
row.operator("bim.hotkey", text="Flip").hotkey = "S_F" row.operator("bim.hotkey", text="Flip").hotkey = "S_F"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_S") row.label(text="", icon="EVENT_S")
row.operator("bim.hotkey", text="Split").hotkey = "S_S" row.operator("bim.hotkey", text="Split").hotkey = "S_S"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_G") row.label(text="", icon="EVENT_G")
row.operator("bim.hotkey", text="Regen").hotkey = "S_G" row.operator("bim.hotkey", text="Regen").hotkey = "S_G"
row.operator("bim.join_wall", icon="X", text="").join_type = "" row.operator("bim.join_wall", icon="X", text="").join_type = ""
elif AuthoringData.data["active_class"] in ("IfcSlab", "IfcSlabStandardCase"): elif AuthoringData.data["active_class"] in ("IfcSlab", "IfcSlabStandardCase"):
if not context.active_object: if context.active_object.mode == "OBJECT":
pass row = cls.layout.row(align=True)
elif context.active_object.mode == "OBJECT":
row = layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E") row.label(text="", icon="EVENT_E")
row.operator("bim.hotkey", text="Edit Profile").hotkey = "S_E" row.operator("bim.hotkey", text="Edit Profile").hotkey = "S_E"
@@ -195,34 +168,34 @@ class BimTool(WorkSpaceTool):
"IfcMember", "IfcMember",
"IfcMemberStandardCase", "IfcMemberStandardCase",
): ):
row = layout.row(align=True) row = cls.layout.row(align=True)
row.prop(data=props, property="cardinal_point", text="Axis") row.prop(data=cls.props, property="cardinal_point", text="Axis")
op = row.operator("bim.change_cardinal_point", icon="FILE_REFRESH", text="") op = row.operator("bim.change_cardinal_point", icon="FILE_REFRESH", text="")
op.cardinal_point = int(props.cardinal_point) op.cardinal_point = int(cls.props.cardinal_point)
row = layout.row(align=True) row = cls.layout.row(align=True)
label = "Height" if ifc_class == "IfcColumnType" else "Length" label = "Height" if AuthoringData.data["active_class"] in ("IfcColumn", "IfcColumnStandardCase") else "Length"
row.prop(data=props, property="extrusion_depth", text=label) row.prop(data=cls.props, property="extrusion_depth", text=label)
op = row.operator("bim.change_profile_depth", icon="FILE_REFRESH", text="") op = row.operator("bim.change_profile_depth", icon="FILE_REFRESH", text="")
op.depth = props.extrusion_depth op.depth = cls.props.extrusion_depth
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_E") row.label(text="", icon="EVENT_E")
row.operator("bim.hotkey", text="Extend").hotkey = "S_E" row.operator("bim.hotkey", text="Extend").hotkey = "S_E"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_T") row.label(text="", icon="EVENT_T")
row.operator("bim.hotkey", text="Butt").hotkey = "S_T" row.operator("bim.hotkey", text="Butt").hotkey = "S_T"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_Y") row.label(text="", icon="EVENT_Y")
row.operator("bim.hotkey", text="Mitre").hotkey = "S_Y" row.operator("bim.hotkey", text="Mitre").hotkey = "S_Y"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_R") row.label(text="", icon="EVENT_R")
row.operator("bim.hotkey", text="Rotate 90").hotkey = "S_R" row.operator("bim.hotkey", text="Rotate 90").hotkey = "S_R"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_G") row.label(text="", icon="EVENT_G")
row.operator("bim.hotkey", text="Regen").hotkey = "S_G" row.operator("bim.hotkey", text="Regen").hotkey = "S_G"
@@ -233,25 +206,24 @@ class BimTool(WorkSpaceTool):
"IfcDoor", "IfcDoor",
"IfcDoorStandardCase", "IfcDoorStandardCase",
): ):
row = layout.row(align=True) row = cls.layout.row(align=True)
row.prop(data=props, property="rl", text="RL") row.prop(data=cls.props, property="rl", text="RL")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_G") row.label(text="", icon="EVENT_G")
row.operator("bim.hotkey", text="Regen").hotkey = "S_G" row.operator("bim.hotkey", text="Regen").hotkey = "S_G"
elif AuthoringData.data["active_class"] in (
if props.ifc_class in (
"IfcCableCarrierSegmentType", "IfcCableCarrierSegmentType",
"IfcCableSegmentType", "IfcCableSegmentType",
"IfcDuctSegmentType", "IfcDuctSegmentType",
"IfcPipeSegmentType", "IfcPipeSegmentType",
): ):
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="Extend", icon="EVENT_E") row.label(text="Extend", icon="EVENT_E")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_O") row.label(text="", icon="EVENT_O")
if len(context.selected_objects) == 2: if len(context.selected_objects) == 2:
@@ -265,30 +237,90 @@ class BimTool(WorkSpaceTool):
else: else:
row.operator("bim.show_openings", icon="HIDE_OFF", text="") row.operator("bim.show_openings", icon="HIDE_OFF", text="")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="Align") row.label(text="Align")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="Align Exterior", icon="EVENT_X") row.label(text="Align Exterior", icon="EVENT_X")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="Align Centerline", icon="EVENT_C") row.label(text="Align Centerline", icon="EVENT_C")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT") row.label(text="", icon="EVENT_SHIFT")
row.label(text="Align Interior", icon="EVENT_V") row.label(text="Align Interior", icon="EVENT_V")
row = layout.row(align=True) row = cls.layout.row(align=True)
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="Mode") row.label(text="Mode")
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_ALT") row.label(text="", icon="EVENT_ALT")
row.label(text="", icon="EVENT_O") row.label(text="", icon="EVENT_O")
row.operator("bim.hotkey", text="Void").hotkey = "A_O" row.operator("bim.hotkey", text="Void").hotkey = "A_O"
row = layout.row(align=True) row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_ALT") row.label(text="", icon="EVENT_ALT")
row.label(text="", icon="EVENT_D") row.label(text="", icon="EVENT_D")
row.operator("bim.hotkey", text="Decomposition").hotkey = "A_D" row.operator("bim.hotkey", text="Decomposition").hotkey = "A_D"
@classmethod
def draw_header_interface(cls):
row = cls.layout.row(align=True)
if AuthoringData.data["ifc_classes"]:
row.label(text="", icon="FILE_VOLUME")
row.prop(data=cls.props, property="ifc_class", text="")
else:
row.label(text="No Construction Class", icon="FILE_VOLUME")
row = cls.layout.row(align=True)
if AuthoringData.data["relating_types_ids"]:
row.label(text="", icon="FILE_3D")
prop_with_search(row, cls.props, "relating_type_id", text="")
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="")
else:
row.label(text="No Construction Type", icon="FILE_3D")
if AuthoringData.data["ifc_classes"]:
#row = cls.layout.row()
#row.operator("bim.display_constr_types", icon="TRIA_DOWN", text="")
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_A")
op = row.operator("bim.add_constr_type_instance", text="Add")
op.from_invoke = True
op.ifc_class = cls.props.ifc_class
if cls.props.relating_type_id.isnumeric():
op.relating_type_id = int(cls.props.relating_type_id)
@classmethod
def draw_sidebar_interface(cls):
row = cls.layout.row(align=True)
if AuthoringData.data["ifc_classes"]:
row.label(text="", icon="FILE_VOLUME")
prop_with_search(row, cls.props, "ifc_class", text="")
else:
row.label(text="No Construction Class", icon="FILE_VOLUME")
row = cls.layout.row(align=True)
if AuthoringData.data["relating_types_ids"]:
row.label(text="", icon="FILE_3D")
prop_with_search(row, cls.props, "relating_type_id", text="")
else:
row.label(text="No Construction Type", icon="FILE_3D")
box = cls.layout.box()
if AuthoringData.data["type_thumbnail"]:
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5)
else:
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
op.ifc_class = cls.props.ifc_class
if AuthoringData.data["ifc_classes"]:
row = cls.layout.row(align=True)
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_A")
op = row.operator("bim.add_constr_type_instance", text="Add")
op.from_invoke = True
op.ifc_class = cls.props.ifc_class
if cls.props.relating_type_id.isnumeric():
op.relating_type_id = int(cls.props.relating_type_id)
class Hotkey(bpy.types.Operator, tool.Ifc.Operator): class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.hotkey" bl_idname = "bim.hotkey"
@@ -56,10 +56,6 @@ class CreateProject(bpy.types.Operator):
props = context.scene.BIMProjectProperties props = context.scene.BIMProjectProperties
template = None if props.template_file == "0" else props.template_file template = None if props.template_file == "0" else props.template_file
core.create_project(tool.Ifc, tool.Project, schema=props.export_schema, template=template) core.create_project(tool.Ifc, tool.Project, schema=props.export_schema, template=template)
# Load thumbnails for the first time
if tool.Ifc.get().by_type("IfcElementType"):
ifc_class = sorted(tool.Ifc.get().by_type("IfcElementType"), key=lambda e: e.is_a())[0].is_a()
bpy.ops.bim.load_type_thumbnails(ifc_class=ifc_class)
def rollback(self, data): def rollback(self, data):
IfcStore.file = None IfcStore.file = None
@@ -596,10 +592,9 @@ class LoadProjectElements(bpy.types.Operator):
print("Import finished in {:.2f} seconds".format(time.time() - start)) print("Import finished in {:.2f} seconds".format(time.time() - start))
context.scene.BIMProjectProperties.is_loading = False context.scene.BIMProjectProperties.is_loading = False
# Load thumbnails for the first time tool.Project.load_default_thumbnails()
if tool.Ifc.get().by_type("IfcElementType"): tool.Project.set_default_context()
ifc_class = sorted(tool.Ifc.get().by_type("IfcElementType"), key=lambda e: e.is_a())[0].is_a() tool.Project.set_default_modeling_dimensions()
bpy.ops.bim.load_type_thumbnails(ifc_class=ifc_class)
return {"FINISHED"} return {"FINISHED"}
def get_decomposition_elements(self): def get_decomposition_elements(self):
@@ -74,3 +74,7 @@ def create_project(ifc, project, schema=None, template=None):
if template: if template:
project.append_all_types_from_template(template) project.append_all_types_from_template(template)
project.load_default_thumbnails()
project.set_default_context()
project.set_default_modeling_dimensions()
+3
View File
@@ -379,6 +379,7 @@ class Owner:
class Project: class Project:
def append_all_types_from_template(cls, template): pass def append_all_types_from_template(cls, template): pass
def create_empty(cls, name): pass def create_empty(cls, name): pass
def load_default_thumbnails(cls): pass
def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None): pass def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None): pass
def run_context_add_context(cls, context_type=None, context_identifier=None, target_view=None, parent=None): pass def run_context_add_context(cls, context_type=None, context_identifier=None, target_view=None, parent=None): pass
def run_owner_add_organisation(cls): pass def run_owner_add_organisation(cls): pass
@@ -389,6 +390,8 @@ class Project:
def run_unit_assign_scene_units(cls): pass def run_unit_assign_scene_units(cls): pass
def set_active_spatial_element(cls, obj): pass def set_active_spatial_element(cls, obj): pass
def set_context(cls, context): pass def set_context(cls, context): pass
def set_default_context(cls): pass
def set_default_modeling_dimensions(cls): pass
@interface @interface
+25
View File
@@ -18,6 +18,8 @@
import os import os
import bpy import bpy
import ifcopenshell
import ifcopenshell.util.unit
import blenderbim.core.tool import blenderbim.core.tool
import blenderbim.tool as tool import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
@@ -36,6 +38,12 @@ class Project(blenderbim.core.tool.Project):
def create_empty(cls, name): def create_empty(cls, name):
return bpy.data.objects.new(name, None) return bpy.data.objects.new(name, None)
@classmethod
def load_default_thumbnails(cls):
if tool.Ifc.get().by_type("IfcElementType"):
ifc_class = sorted(tool.Ifc.get().by_type("IfcElementType"), key=lambda e: e.is_a())[0].is_a()
bpy.ops.bim.load_type_thumbnails(ifc_class=ifc_class)
@classmethod @classmethod
def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None): def run_aggregate_assign_object(cls, relating_obj=None, related_obj=None):
return blenderbim.core.aggregate.assign_object( return blenderbim.core.aggregate.assign_object(
@@ -114,3 +122,20 @@ class Project(blenderbim.core.tool.Project):
def set_context(cls, context): def set_context(cls, context):
blenderbim.bim.handler.refresh_ui_data() blenderbim.bim.handler.refresh_ui_data()
bpy.context.scene.BIMRootProperties.contexts = str(context.id()) bpy.context.scene.BIMRootProperties.contexts = str(context.id())
@classmethod
def set_default_context(cls):
context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
if context:
bpy.context.scene.BIMRootProperties.contexts = str(context.id())
@classmethod
def set_default_modeling_dimensions(cls):
props = bpy.context.scene.BIMModelProperties
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
props.extrusion_depth = 3 / unit_scale
props.length = 1 / unit_scale
props.rl = 1 / unit_scale
props.x = 0.5 / unit_scale
props.y = 0.5 / unit_scale
props.z = 0.5 / unit_scale
+12
View File
@@ -77,6 +77,10 @@ class TestCreateProject:
project.set_context("body").should_be_called() project.set_context("body").should_be_called()
project.set_active_spatial_element("storey").should_be_called() project.set_active_spatial_element("storey").should_be_called()
project.load_default_thumbnails().should_be_called()
project.set_default_context().should_be_called()
project.set_default_modeling_dimensions().should_be_called()
subject.create_project(ifc, project, schema="IFC4", template=None) subject.create_project(ifc, project, schema="IFC4", template=None)
def test_appending_project_template_types_if_specified(self, ifc, project): def test_appending_project_template_types_if_specified(self, ifc, project):
@@ -132,6 +136,10 @@ class TestCreateProject:
project.append_all_types_from_template("template").should_be_called() project.append_all_types_from_template("template").should_be_called()
project.load_default_thumbnails().should_be_called()
project.set_default_context().should_be_called()
project.set_default_modeling_dimensions().should_be_called()
subject.create_project(ifc, project, schema="IFC4", template="template") subject.create_project(ifc, project, schema="IFC4", template="template")
def test_create_an_ifc2x3_project_with_owner_defaults(self, ifc, project): def test_create_an_ifc2x3_project_with_owner_defaults(self, ifc, project):
@@ -192,4 +200,8 @@ class TestCreateProject:
project.set_context("body").should_be_called() project.set_context("body").should_be_called()
project.set_active_spatial_element("storey").should_be_called() project.set_active_spatial_element("storey").should_be_called()
project.load_default_thumbnails().should_be_called()
project.set_default_context().should_be_called()
project.set_default_modeling_dimensions().should_be_called()
subject.create_project(ifc, project, schema="IFC2X3", template=None) subject.create_project(ifc, project, schema="IFC2X3", template=None)
+32
View File
@@ -42,6 +42,11 @@ class TestCreateEmpty(NewFile):
assert not bpy.data.objects.get("Foobar").data assert not bpy.data.objects.get("Foobar").data
class TestLoadDefaultThumbnails(NewFile):
def test_nothing(self):
pass # Not possible to test this headlessly
class TestRunAggregateAssignObject(NewFile): class TestRunAggregateAssignObject(NewFile):
def test_nothing(self): def test_nothing(self):
pass pass
@@ -101,3 +106,30 @@ class TestSetContext(NewFile):
context = ifc.createIfcGeometricRepresentationContext() context = ifc.createIfcGeometricRepresentationContext()
subject.set_context(context) subject.set_context(context)
assert bpy.context.scene.BIMRootProperties.contexts == str(context.id()) assert bpy.context.scene.BIMRootProperties.contexts == str(context.id())
class TestSetDefaultContext(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifc.createIfcProject()
model = ifcopenshell.api.run("context.add_context", ifc, context_type="Model")
body = ifcopenshell.api.run("context.add_context", ifc, parent=model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW")
subject.set_default_context()
assert bpy.context.scene.BIMRootProperties.contexts == str(body.id())
class TestSetDefaultModelingDimensions(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifc.createIfcProject()
ifcopenshell.api.run("unit.assign_unit", ifc)
subject.set_default_modeling_dimensions()
props = bpy.context.scene.BIMModelProperties
assert props.extrusion_depth == 3000
assert props.length == 1000
assert props.rl == 1000
assert props.x == 500
assert props.y == 500
assert props.z == 500
@@ -477,6 +477,8 @@ def calculate_unit_scale(file):
:returns: The scale factor :returns: The scale factor
:rtype: float :rtype: float
""" """
if not file.by_type("IfcUnitAssignment"):
return 1
units = file.by_type("IfcUnitAssignment")[0] units = file.by_type("IfcUnitAssignment")[0]
unit_scale = 1 unit_scale = 1
for unit in units.Units: for unit in units.Units: