mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
bim.save_uv_to_style - support saving uv to objects without a style
There was a problem with assigning uv workflow if object wasn't originally from IFC - saving uv requires object to have IfcSurfaceStyle but assigning IfcSurfaceStyle would reload representation discarding UV. So, the current workflow for saving non-ifc objects uv to ifc: 1) Assign class to ifc object 2) Create IfcSurfaceStyle with a texture (currently also requires a rendering style) 3) Use "Save UV To Style" Example - https://imgur.com/a/GZqo38M
This commit is contained in:
@@ -882,7 +882,11 @@ class AddSurfaceTexture(bpy.types.Operator):
|
|||||||
class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.save_uv_to_style"
|
bl_idname = "bim.save_uv_to_style"
|
||||||
bl_label = "Save UV To Style"
|
bl_label = "Save UV To Style"
|
||||||
bl_description = "Save active object UV to it's IfcSurfaceStyle's IfcSurfaceTexture"
|
bl_description = (
|
||||||
|
"Save active object UV to the IfcSurfaceStyle's IfcSurfaceTexture.\n\n"
|
||||||
|
"If object already has IfcSurfaceStyleWithTextures, then it will be used.\n"
|
||||||
|
"Otherwise operator will use currently selected surface style (style will be autoassigned)"
|
||||||
|
)
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -890,9 +894,6 @@ class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
if not (obj := context.active_object) or not tool.Ifc.get_entity(obj):
|
if not (obj := context.active_object) or not tool.Ifc.get_entity(obj):
|
||||||
cls.poll_message_set("No IFC object selected")
|
cls.poll_message_set("No IFC object selected")
|
||||||
return False
|
return False
|
||||||
if not obj.active_material or not tool.Ifc.get_entity(obj.active_material):
|
|
||||||
cls.poll_message_set("Object has no IFC style.")
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
@@ -903,12 +904,25 @@ class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
# We need IFC material with a texture style since in IFC
|
# We need IFC material with a texture style since in IFC
|
||||||
# UV indexing (IfcTextureCoordinate) requires some IfcSurfaceTexture.
|
# UV indexing (IfcTextureCoordinate) requires some IfcSurfaceTexture.
|
||||||
|
material, style = None, None
|
||||||
|
style_is_assigned = False
|
||||||
material = obj.active_material
|
material = obj.active_material
|
||||||
assert material
|
if material:
|
||||||
|
style = tool.Ifc.get_entity(material)
|
||||||
|
|
||||||
# find active style item
|
if style:
|
||||||
style = tool.Ifc.get_entity(material)
|
style_is_assigned = True
|
||||||
assert style
|
else:
|
||||||
|
style_item = tool.Style.get_active_style_in_ui()
|
||||||
|
if not style_item:
|
||||||
|
self.report({"ERROR"}, "Object has no style and no style is selected.")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
style = ifc_file.by_id(style_item.ifc_definition_id)
|
||||||
|
|
||||||
|
texture_style = tool.Style.get_texture_style(style)
|
||||||
|
if not texture_style:
|
||||||
|
self.report({"ERROR"}, "IfcSurfaceStyle has no texture style.")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
def get_active_representation_items() -> list[ifcopenshell.entity_instance]:
|
def get_active_representation_items() -> list[ifcopenshell.entity_instance]:
|
||||||
representation = tool.Geometry.get_active_representation(obj)
|
representation = tool.Geometry.get_active_representation(obj)
|
||||||
@@ -923,7 +937,7 @@ class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
all_styled_items = set(tool.Style.get_styled_items(style))
|
all_styled_items = set(tool.Style.get_styled_items(style))
|
||||||
active_representation_items = set(get_active_representation_items())
|
active_representation_items = set(get_active_representation_items())
|
||||||
|
|
||||||
if not active_representation_items.issubset(all_styled_items):
|
if style_is_assigned and not active_representation_items.issubset(all_styled_items):
|
||||||
self.report(
|
self.report(
|
||||||
{"ERROR"},
|
{"ERROR"},
|
||||||
"Not all items of the current representation are styled by the active style, not yet supported",
|
"Not all items of the current representation are styled by the active style, not yet supported",
|
||||||
@@ -943,11 +957,6 @@ class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
self.report({"ERROR"}, "Only 1 faceset item is supported.")
|
self.report({"ERROR"}, "Only 1 faceset item is supported.")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
texture_style = tool.Style.get_texture_style(material)
|
|
||||||
if not texture_style:
|
|
||||||
self.report({"ERROR"}, "No texture style found, not yet supported.")
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
mesh = obj.data
|
mesh = obj.data
|
||||||
assert isinstance(mesh, bpy.types.Mesh)
|
assert isinstance(mesh, bpy.types.Mesh)
|
||||||
uv_layer = mesh.uv_layers.active
|
uv_layer = mesh.uv_layers.active
|
||||||
@@ -1016,6 +1025,10 @@ class SaveUVToStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
uv_verts_list.TexCoordsList = uv_verts
|
uv_verts_list.TexCoordsList = uv_verts
|
||||||
texture_coord.TexCoords = uv_verts_list
|
texture_coord.TexCoords = uv_verts_list
|
||||||
|
|
||||||
|
if not style_is_assigned:
|
||||||
|
with context.temp_override(selected_objects=[obj]):
|
||||||
|
bpy.ops.bim.assign_style_to_selected(style_id=style.id())
|
||||||
|
|
||||||
self.report({"INFO"}, f"UV saved to the style '{style.Name}'.")
|
self.report({"INFO"}, f"UV saved to the style '{style.Name}'.")
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -103,6 +103,13 @@ class Style(bonsai.core.tool.Style):
|
|||||||
props = bpy.context.scene.BIMStylesProperties
|
props = bpy.context.scene.BIMStylesProperties
|
||||||
return bonsai.bim.helper.export_attributes(props.attributes)
|
return bonsai.bim.helper.export_attributes(props.attributes)
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_active_style_type(cls) -> str:
|
def get_active_style_type(cls) -> str:
|
||||||
return bpy.context.scene.BIMStylesProperties.style_type
|
return bpy.context.scene.BIMStylesProperties.style_type
|
||||||
@@ -432,22 +439,30 @@ class Style(bonsai.core.tool.Style):
|
|||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_surface_rendering_style(cls, obj: bpy.types.Material) -> Union[ifcopenshell.entity_instance, None]:
|
def get_surface_rendering_style(
|
||||||
style_elements = cls.get_style_elements(obj)
|
cls, blender_material_or_style: Union[bpy.types.Material, ifcopenshell.entity_instance]
|
||||||
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
|
style_elements = cls.get_style_elements(blender_material_or_style)
|
||||||
return style_elements.get("IfcSurfaceStyleRendering", None)
|
return style_elements.get("IfcSurfaceStyleRendering", None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_texture_style(cls, obj: bpy.types.Material) -> Union[ifcopenshell.entity_instance, None]:
|
def get_texture_style(
|
||||||
style_elements = cls.get_style_elements(obj)
|
cls, blender_material_or_style: Union[bpy.types.Material, ifcopenshell.entity_instance]
|
||||||
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
|
style_elements = cls.get_style_elements(blender_material_or_style)
|
||||||
return style_elements.get("IfcSurfaceStyleWithTextures", None)
|
return style_elements.get("IfcSurfaceStyleWithTextures", None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_external_style(cls, obj: bpy.types.Material) -> Union[ifcopenshell.entity_instance, None]:
|
def get_external_style(
|
||||||
style_elements = cls.get_style_elements(obj)
|
cls, blender_material_or_style: Union[bpy.types.Material, ifcopenshell.entity_instance]
|
||||||
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
|
style_elements = cls.get_style_elements(blender_material_or_style)
|
||||||
return style_elements.get("IfcExternallyDefinedSurfaceStyle", None)
|
return style_elements.get("IfcExternallyDefinedSurfaceStyle", None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_surface_shading_attributes(cls, obj: bpy.types.Material) -> dict[str, Any]:
|
def get_surface_shading_attributes(
|
||||||
|
cls, blender_material_or_style: Union[bpy.types.Material, ifcopenshell.entity_instance]
|
||||||
|
) -> dict[str, Any]:
|
||||||
data = {
|
data = {
|
||||||
"SurfaceColour": {
|
"SurfaceColour": {
|
||||||
"Name": None,
|
"Name": None,
|
||||||
|
|||||||
Reference in New Issue
Block a user