You can now use the Asset Browser to set a Material Asset as an external style.

To do so Right Click on a material in the Asset Browser then `Set To External Style`. The style editor must be loaded in the properties editor.

Also run black on a file from previous commit and fix a bug soft-locking the style editor when removing a style that is being edited
This commit is contained in:
Gorgious56
2025-01-07 14:55:17 +01:00
parent 3ced6e7bb1
commit 0983f812fd
6 changed files with 70 additions and 25 deletions
@@ -43,6 +43,7 @@ classes = (
operator.SaveUVToStyle,
operator.SelectByStyle,
operator.SelectStyleInStylesUI,
operator.SetAssetMaterialToExternalStyle,
operator.UnlinkStyle,
operator.UpdateCurrentStyle,
operator.UpdateStyleColours,
@@ -61,8 +62,10 @@ classes = (
def register():
bpy.types.Scene.BIMStylesProperties = bpy.props.PointerProperty(type=prop.BIMStylesProperties)
bpy.types.Material.BIMStyleProperties = bpy.props.PointerProperty(type=prop.BIMStyleProperties)
bpy.types.ASSETBROWSER_MT_context_menu.append(ui.draw_asset_browser_context_menu_append)
def unregister():
del bpy.types.Scene.BIMStylesProperties
del bpy.types.Material.BIMStyleProperties
bpy.types.ASSETBROWSER_MT_context_menu.remove(ui.draw_asset_browser_context_menu_append)
@@ -80,6 +80,7 @@ class RemoveStyle(bpy.types.Operator, tool.Ifc.Operator):
style: bpy.props.IntProperty()
def _execute(self, context):
core.disable_editing_style(tool.Style) # So we don't end up soft-locking style edition
core.remove_style(tool.Ifc, tool.Style, style=tool.Ifc.get().by_id(self.style), reload_styles_ui=True)
@@ -236,6 +237,35 @@ class UpdateCurrentStyle(bpy.types.Operator):
return {"FINISHED"}
class SetAssetMaterialToExternalStyle(bpy.types.Operator):
bl_idname = "bim.set_asset_material_to_external_style"
bl_label = "Set To External Style"
bl_options = {"REGISTER", "UNDO"}
def execute_delayed(self, name, filepath, props):
style_id = props.active_style.ifc_definition_id
bpy.ops.bim.enable_editing_surface_style(style=style_id, ifc_class="IfcExternallyDefinedSurfaceStyle")
bpy.ops.bim.browse_external_style(
data_block_type="materials",
data_block=name,
filepath=filepath,
active_surface_style_id=style_id,
use_relative_path=False,
)
bpy.ops.bim.edit_surface_style()
def execute(self, context):
# We delay execution because for some obscure reason we can't use
# the temp override to copy material node tree `right now`
name = context.asset.name
filepath = context.asset.full_library_path
bpy.app.timers.register(
lambda: self.execute_delayed(name, filepath, context.scene.BIMStylesProperties),
first_interval=0.001,
)
return {"FINISHED"}
class BrowseExternalStyle(bpy.types.Operator):
bl_idname = "bim.browse_external_style"
bl_label = "Browse External Style"
@@ -261,6 +261,11 @@ class BIMStylesProperties(PropertyGroup):
styles: CollectionProperty(name="Styles", type=Style)
active_style_index: IntProperty(name="Active Style Index")
@property
def active_style(self):
return self.styles[self.active_style_index] if 0 <= self.active_style_index < len(self.styles) else None
active_style_type: EnumProperty(
name="Active Style Type",
description="Update current blender material to match style type for all objects in the scene",
+12 -3
View File
@@ -52,7 +52,7 @@ class BIM_PT_styles(Panel):
row.operator("bim.load_styles", text="", icon="IMPORT").style_type = style_type
return
active_style = bool(self.props.styles and self.props.active_style_index < len(self.props.styles))
active_style = self.props.active_style
row = self.layout.row(align=True)
row.label(text="{} {}s".format(len(self.props.styles), self.props.style_type), icon="SHADING_RENDERED")
row.operator("bim.disable_editing_styles", text="", icon="CANCEL")
@@ -62,7 +62,7 @@ class BIM_PT_styles(Panel):
if not self.props.is_adding:
row.operator("bim.enable_adding_presentation_style", text="", icon="ADD")
if active_style:
style = self.props.styles[self.props.active_style_index]
style = active_style
row.operator("bim.duplicate_style", text="", icon="DUPLICATE").style = style.ifc_definition_id
row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF").style = style.ifc_definition_id
@@ -237,7 +237,7 @@ class BIM_PT_styles(Panel):
def draw_externally_defined_surface_style(self):
row = self.layout.row()
op = row.operator("bim.browse_external_style", icon="APPEND_BLEND", text="Append From Blend File")
style = self.props.styles[self.props.active_style_index]
style = self.props.active_style
op.active_surface_style_id = style.ifc_definition_id
bonsai.bim.helper.draw_attributes(self.props.external_style_attributes, self.layout)
@@ -327,3 +327,12 @@ class BIM_PT_style(Panel):
row = self.layout.row(align=True)
row.label(text="IFC Style Name:")
row.label(text=BlenderMaterialStyleData.data["linked_style_name"])
def draw_asset_browser_context_menu_append(self, context):
asset = context.asset
if not asset or not asset.id_type == "MATERIAL":
return
if not context.scene.BIMStylesProperties.is_editing:
return
self.layout.operator("bim.set_asset_material_to_external_style")
+19 -19
View File
@@ -943,10 +943,10 @@ class Blender(bonsai.core.tool.Blender):
bpy.ops.bim.finish_editing_door()
elif cls.is_editing_window_parameters(obj):
bpy.ops.bim.finish_editing_window()
else:
else:
return False
return True
@classmethod
def try_canceling_editing_modifier_parameters_or_path(cls, obj: bpy.types.Object) -> bool:
"""Tries to cancel the current BIM modifier parameters or path edition for the active object
@@ -972,45 +972,45 @@ class Blender(bonsai.core.tool.Blender):
return True
@classmethod
def is_eligible_for_railing_modifier(cls, obj: bpy.types.Object)-> bool:
def is_eligible_for_railing_modifier(cls, obj: bpy.types.Object) -> bool:
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRailing", "IfcRailingType"))
@classmethod
def is_eligible_for_stair_modifier(cls, obj: bpy.types.Object)-> bool:
def is_eligible_for_stair_modifier(cls, obj: bpy.types.Object) -> bool:
return tool.Blender.is_object_an_ifc_class(
obj, ("IfcStairFlight", "IfcStairFlightType", "IfcMember", "IfcMemberType", "IfcStair", "IfcStairType")
)
@classmethod
def is_eligible_for_window_modifier(cls, obj: bpy.types.Object)-> bool:
def is_eligible_for_window_modifier(cls, obj: bpy.types.Object) -> bool:
return tool.Blender.is_object_an_ifc_class(obj, ("IfcWindow", "IfcWindowType", "IfcWindowStyle"))
@classmethod
def is_eligible_for_door_modifier(cls, obj: bpy.types.Object)-> bool:
def is_eligible_for_door_modifier(cls, obj: bpy.types.Object) -> bool:
return tool.Blender.is_object_an_ifc_class(obj, ("IfcDoor", "IfcDoorType", "IfcDoorStyle"))
@classmethod
def is_eligible_for_roof_modifier(cls, obj: bpy.types.Object)-> bool:
def is_eligible_for_roof_modifier(cls, obj: bpy.types.Object) -> bool:
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRoof", "IfcRoofType"))
@classmethod
def is_railing(cls, element: entity_instance)-> bool:
def is_railing(cls, element: entity_instance) -> bool:
return tool.Pset.get_element_pset(element, "BBIM_Railing")
@classmethod
def is_roof(cls, element: entity_instance)-> bool:
def is_roof(cls, element: entity_instance) -> bool:
return tool.Pset.get_element_pset(element, "BBIM_Roof")
@classmethod
def is_window(cls, element: entity_instance)-> bool:
def is_window(cls, element: entity_instance) -> bool:
return tool.Pset.get_element_pset(element, "BBIM_Window")
@classmethod
def is_door(cls, element: entity_instance)-> bool:
def is_door(cls, element: entity_instance) -> bool:
return tool.Pset.get_element_pset(element, "BBIM_Door")
@classmethod
def is_stair(cls, element: entity_instance)-> bool:
def is_stair(cls, element: entity_instance) -> bool:
return tool.Pset.get_element_pset(element, "BBIM_Stair")
@classmethod
@@ -1018,31 +1018,31 @@ class Blender(bonsai.core.tool.Blender):
return obj.BIMRailingProperties.is_editing_path
@classmethod
def is_editing_roof_path(cls, obj: bpy.types.Object)-> bool:
def is_editing_roof_path(cls, obj: bpy.types.Object) -> bool:
return obj.BIMRoofProperties.is_editing_path
@classmethod
def is_editing_railing_parameters(cls, obj: bpy.types.Object)-> bool:
def is_editing_railing_parameters(cls, obj: bpy.types.Object) -> bool:
return obj.BIMRailingProperties.is_editing
@classmethod
def is_editing_roof_parameters(cls, obj: bpy.types.Object)-> bool:
def is_editing_roof_parameters(cls, obj: bpy.types.Object) -> bool:
return obj.BIMRoofProperties.is_editing
@classmethod
def is_editing_window_parameters(cls, obj: bpy.types.Object)-> bool:
def is_editing_window_parameters(cls, obj: bpy.types.Object) -> bool:
return obj.BIMWindowProperties.is_editing
@classmethod
def is_editing_door_parameters(cls, obj: bpy.types.Object)-> bool:
def is_editing_door_parameters(cls, obj: bpy.types.Object) -> bool:
return obj.BIMDoorProperties.is_editing
@classmethod
def is_editing_stair_parameters(cls, obj: bpy.types.Object)-> bool:
def is_editing_stair_parameters(cls, obj: bpy.types.Object) -> bool:
return obj.BIMStairProperties.is_editing
@classmethod
def is_modifier_with_non_editable_path(cls, element: entity_instance)-> bool:
def is_modifier_with_non_editable_path(cls, element: entity_instance) -> bool:
return cls.is_stair(element) or cls.is_door(element) or cls.is_window(element)
class Array:
+1 -3
View File
@@ -116,9 +116,7 @@ class Style(bonsai.core.tool.Style):
@classmethod
def get_active_style_in_ui(cls) -> Union[bpy.types.PropertyGroup, None]:
props = bpy.context.scene.BIMStylesProperties
if len(props.styles) > props.active_style_index >= 0:
return props.styles[props.active_style_index]
return None
return props.active_style
@classmethod
def get_active_style_type(cls) -> str: