mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
External Styles
Added support for external blender styles that will be saved to ifc. What it basically means that you can append material from external .blend file as a style that can be loaded in your blender material anytime. 1) External style can be added in Material Tab https://i.imgur.com/BYfesi5.png Note that you select material name at the right side of file selecting panel: https://i.imgur.com/mvqaaod.png 2) After adding external style you can switch between external and other surface styles: https://i.imgur.com/YtCz8an.png 3) There is also option to switch styles to External for all objects in the scene: https://i.imgur.com/u3zTcX9.png Some other changes: - some ui adjustments - moved functions that create blender shaders to tool.Loader (they also reset shader graph now so it's possible to use them on non-default blender materials) - some new tools for copying node graph from one material to another, appending data blocks - new operator for browsing external styles can be reused later to append other data blocks
This commit is contained in:
@@ -1490,173 +1490,18 @@ class IfcImporter:
|
||||
|
||||
for surface_style in style.Styles:
|
||||
if surface_style.is_a() == "IfcSurfaceStyleShading":
|
||||
self.create_surface_style_shading(blender_material, surface_style)
|
||||
tool.Loader.create_surface_style_shading(blender_material, surface_style)
|
||||
elif surface_style.is_a("IfcSurfaceStyleRendering"):
|
||||
rendering_style = surface_style
|
||||
self.create_surface_style_rendering(blender_material, surface_style)
|
||||
tool.Loader.create_surface_style_rendering(blender_material, surface_style)
|
||||
elif surface_style.is_a("IfcSurfaceStyleWithTextures"):
|
||||
texture_style = surface_style
|
||||
|
||||
if rendering_style and texture_style:
|
||||
self.create_surface_style_with_textures(blender_material, rendering_style, texture_style)
|
||||
tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style)
|
||||
|
||||
tool.Style.record_shading(blender_material)
|
||||
|
||||
def create_surface_style_shading(self, blender_material, surface_style):
|
||||
alpha = 1.0
|
||||
# Transparency was added in IFC4
|
||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
||||
alpha = 1 - surface_style.Transparency
|
||||
blender_material.diffuse_color = (
|
||||
surface_style.SurfaceColour.Red,
|
||||
surface_style.SurfaceColour.Green,
|
||||
surface_style.SurfaceColour.Blue,
|
||||
alpha,
|
||||
)
|
||||
|
||||
def create_surface_style_rendering(self, blender_material, surface_style):
|
||||
self.create_surface_style_shading(blender_material, surface_style)
|
||||
if surface_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
||||
blender_material.use_nodes = True
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
if surface_style.DiffuseColour:
|
||||
if surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
||||
bsdf.inputs["Base Color"].default_value = (
|
||||
surface_style.DiffuseColour.Red,
|
||||
surface_style.DiffuseColour.Green,
|
||||
surface_style.DiffuseColour.Blue,
|
||||
1,
|
||||
)
|
||||
elif surface_style.DiffuseColour.is_a("IfcNormalisedRatioMeasure"):
|
||||
bsdf.inputs["Base Color"].default_value = (
|
||||
surface_style.SurfaceColour.Red * surface_style.DiffuseColour.wrappedValue,
|
||||
surface_style.SurfaceColour.Green * surface_style.DiffuseColour.wrappedValue,
|
||||
surface_style.SurfaceColour.Blue * surface_style.DiffuseColour.wrappedValue,
|
||||
1,
|
||||
)
|
||||
if surface_style.SpecularColour and surface_style.SpecularColour.is_a("IfcNormalisedRatioMeasure"):
|
||||
bsdf.inputs["Metallic"].default_value = surface_style.SpecularColour.wrappedValue
|
||||
if surface_style.SpecularHighlight and surface_style.SpecularHighlight.is_a("IfcSpecularRoughness"):
|
||||
bsdf.inputs["Roughness"].default_value = surface_style.SpecularHighlight.wrappedValue
|
||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
||||
bsdf.inputs["Alpha"].default_value = 1 - surface_style.Transparency
|
||||
blender_material.blend_method = "BLEND"
|
||||
elif surface_style.ReflectanceMethod == "FLAT":
|
||||
blender_material.use_nodes = True
|
||||
|
||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
|
||||
mix = blender_material.node_tree.nodes.new(type="ShaderNodeMixShader")
|
||||
mix.location = bsdf.location
|
||||
blender_material.node_tree.links.new(mix.outputs[0], output.inputs["Surface"])
|
||||
|
||||
blender_material.node_tree.nodes.remove(bsdf)
|
||||
|
||||
lightpath = blender_material.node_tree.nodes.new(type="ShaderNodeLightPath")
|
||||
lightpath.location = mix.location - mathutils.Vector((200, -200))
|
||||
blender_material.node_tree.links.new(lightpath.outputs[0], mix.inputs[0])
|
||||
|
||||
bsdf = blender_material.node_tree.nodes.new(type="ShaderNodeBsdfTransparent")
|
||||
bsdf.location = mix.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(bsdf.outputs[0], mix.inputs[1])
|
||||
|
||||
rgb = blender_material.node_tree.nodes.new(type="ShaderNodeRGB")
|
||||
rgb.location = mix.location - mathutils.Vector((200, 200))
|
||||
blender_material.node_tree.links.new(rgb.outputs[0], mix.inputs[2])
|
||||
|
||||
if surface_style.DiffuseColour and surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
||||
rgb.outputs[0].default_value = (
|
||||
surface_style.DiffuseColour.Red,
|
||||
surface_style.DiffuseColour.Green,
|
||||
surface_style.DiffuseColour.Blue,
|
||||
1,
|
||||
)
|
||||
|
||||
def create_surface_style_with_textures(self, blender_material, rendering_style, texture_style):
|
||||
for texture in texture_style.Textures:
|
||||
mode = getattr(texture, "Mode", None)
|
||||
node = None
|
||||
|
||||
if texture.is_a("IfcImageTexture"):
|
||||
image_url = texture.URLReference
|
||||
if not os.path.abspath(texture.URLReference) and tool.Ifc.get_path():
|
||||
image_url = os.path.join(os.path.dirname(tool.Ifc.get_path()), texture.URLReference)
|
||||
|
||||
if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
if mode == "NORMAL":
|
||||
normalmap = blender_material.node_tree.nodes.new(type="ShaderNodeNormalMap")
|
||||
normalmap.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(normalmap.outputs[0], bsdf.inputs["Normal"])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = normalmap.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
image.colorspace_settings.name = "Non-Color"
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], normalmap.inputs["Color"])
|
||||
elif mode == "EMISSIVE":
|
||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
||||
|
||||
add = blender_material.node_tree.nodes.new(type="ShaderNodeAddShader")
|
||||
add.location = bsdf.location + mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(bsdf.outputs[0], add.inputs[1])
|
||||
blender_material.node_tree.links.new(add.outputs[0], output.inputs[0])
|
||||
|
||||
emission = blender_material.node_tree.nodes.new(type="ShaderNodeEmission")
|
||||
emission.location = add.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(emission.outputs[0], add.inputs[0])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = emission.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], emission.inputs[0])
|
||||
elif mode == "METALLICROUGHNESS":
|
||||
separate = blender_material.node_tree.nodes.new(type="ShaderNodeSeparateRGB")
|
||||
separate.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(separate.outputs[1], bsdf.inputs["Roughness"])
|
||||
blender_material.node_tree.links.new(separate.outputs[2], bsdf.inputs["Metallic"])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = separate.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
image.colorspace_settings.name = "Non-Color"
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], separate.inputs[0])
|
||||
elif mode == "OCCLUSION":
|
||||
# TODO work out how to implement glTF settings here
|
||||
# https://docs.blender.org/manual/en/dev/addons/import_export/scene_gltf2.html
|
||||
pass
|
||||
elif mode == "DIFFUSE":
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = bsdf.location - mathutils.Vector((400, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs["Base Color"])
|
||||
blender_material.node_tree.links.new(node.outputs[1], bsdf.inputs["Alpha"])
|
||||
blender_material.blend_method = "BLEND"
|
||||
elif rendering_style.ReflectanceMethod == "FLAT":
|
||||
bsdf = blender_material.node_tree.nodes["Mix Shader"]
|
||||
if mode == "EMISSIVE":
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs[2])
|
||||
|
||||
if node and getattr(texture, "IsMappedBy", None):
|
||||
coordinates = texture.IsMappedBy[0]
|
||||
coord = blender_material.node_tree.nodes.new(type="ShaderNodeTexCoord")
|
||||
coord.location = node.location - mathutils.Vector((200, 0))
|
||||
if coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD":
|
||||
blender_material.node_tree.links.new(coord.outputs["Generated"], node.inputs["Vector"])
|
||||
elif coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD-EYE":
|
||||
blender_material.node_tree.links.new(coord.outputs["Camera"], node.inputs["Vector"])
|
||||
else:
|
||||
blender_material.node_tree.links.new(coord.outputs["UV"], node.inputs["Vector"])
|
||||
|
||||
def place_objects_in_collections(self):
|
||||
for ifc_definition_id, obj in self.added_data.items():
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
|
||||
@@ -30,7 +30,8 @@ class BIM_PT_misc_utilities(bpy.types.Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMMiscProperties
|
||||
|
||||
row = layout.row()
|
||||
row.prop(context.scene.BIMStylesProperties, "active_style_type", icon="SHADING_RENDERED", text="")
|
||||
row = layout.split(factor=0.2, align=True)
|
||||
row.prop(props, "override_colour", text="")
|
||||
row.operator("bim.set_override_colour")
|
||||
|
||||
@@ -21,10 +21,15 @@ from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AddStyle,
|
||||
operator.DisableEditingStyle,
|
||||
operator.DisableEditingStyles,
|
||||
operator.EditStyle,
|
||||
operator.EnableEditingStyle,
|
||||
operator.DisableEditingStyle,
|
||||
operator.EditStyle,
|
||||
operator.EnableEditingExternalStyle,
|
||||
operator.DisableEditingExternalStyle,
|
||||
operator.EditExternalStyle,
|
||||
operator.DisableEditingStyles,
|
||||
operator.BrowseExternalStyle,
|
||||
operator.ActivateExternalStyle,
|
||||
operator.LoadStyles,
|
||||
operator.RemoveStyle,
|
||||
operator.SelectByStyle,
|
||||
@@ -37,6 +42,7 @@ classes = (
|
||||
ui.BIM_PT_styles,
|
||||
ui.BIM_PT_style,
|
||||
ui.BIM_PT_style_attributes,
|
||||
ui.BIM_PT_external_style_attributes,
|
||||
ui.BIM_UL_styles,
|
||||
)
|
||||
|
||||
|
||||
@@ -56,7 +56,12 @@ class StyleAttributesData:
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"ifc_style_id": cls.ifc_style_id(), "attributes": cls.get_attributes()}
|
||||
cls.data = {
|
||||
"ifc_style_id": cls.ifc_style_id(),
|
||||
"attributes": cls.get_attributes(),
|
||||
"style_elements": cls.get_style_elements(),
|
||||
}
|
||||
cls.data["external_style_attributes"] = cls.get_external_style_attributes()
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
@@ -72,3 +77,19 @@ class StyleAttributesData:
|
||||
continue
|
||||
results.append({"name": name, "value": str(value)})
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def get_style_elements(cls):
|
||||
return tool.Style.get_style_elements(bpy.context.active_object.active_material)
|
||||
|
||||
@classmethod
|
||||
def get_external_style_attributes(cls):
|
||||
external_style = cls.data["style_elements"].get("IfcExternallyDefinedSurfaceStyle", None)
|
||||
if not external_style:
|
||||
return None
|
||||
results = []
|
||||
for name, value in external_style.get_info().items():
|
||||
if name in ["id", "type"]:
|
||||
continue
|
||||
results.append({"name": name, "value": str(value)})
|
||||
return results
|
||||
|
||||
@@ -22,11 +22,15 @@ import blenderbim.tool as tool
|
||||
import blenderbim.core.style as core
|
||||
import ifcopenshell.util.representation
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.style.data import StylesData, StyleAttributesData
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
|
||||
class UpdateStyleColours(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.update_style_colours"
|
||||
bl_label = "Update Style Colours"
|
||||
bl_label = "Save Current Shading Style"
|
||||
bl_description = "Save current style values to IfcSurfaceStyleShading"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
@@ -103,6 +107,200 @@ class EditStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
core.edit_style(tool.Ifc, tool.Style, obj=context.active_object.active_material)
|
||||
|
||||
|
||||
class BrowseExternalStyle(bpy.types.Operator):
|
||||
bl_idname = "bim.browse_external_style"
|
||||
bl_label = "Browse External Style"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
filepath: bpy.props.StringProperty(
|
||||
name="File Path", description="Filepath used to import from", maxlen=1024, default="", subtype="FILE_PATH"
|
||||
)
|
||||
|
||||
filter_glob: bpy.props.StringProperty(
|
||||
default="*.blend",
|
||||
options={"HIDDEN"},
|
||||
)
|
||||
|
||||
def get_data_block_types(self, context):
|
||||
return [("materials", "materials", "materials")]
|
||||
# NOTE: the code below can be used later when we'll be adding other data-blocks besides materials
|
||||
l = [("0", "", "")]
|
||||
SUPPORTED_DATA_BLOCKS = ("materials", "textures", "brushes")
|
||||
if os.path.exists(self.filepath) and self.filepath.endswith(".blend"):
|
||||
with bpy.data.libraries.load(self.filepath) as (data_from, data_to):
|
||||
for data_block_type in dir(data_from):
|
||||
if data_block_type not in SUPPORTED_DATA_BLOCKS:
|
||||
continue
|
||||
data = getattr(data_from, data_block_type)
|
||||
if data:
|
||||
item = (data_block_type,) * 3
|
||||
l.append(item)
|
||||
return l
|
||||
|
||||
def get_data_blocks(self, context):
|
||||
l = [("", "", "")]
|
||||
if self.data_block_type != "0" and os.path.exists(self.filepath) and self.filepath.endswith(".blend"):
|
||||
with bpy.data.libraries.load(self.filepath) as (data_from, data_to):
|
||||
objects = getattr(data_from, self.data_block_type)
|
||||
for o in objects:
|
||||
l.append((o, o, o))
|
||||
return l
|
||||
|
||||
data_block_type: bpy.props.EnumProperty(
|
||||
name="Data Block Type",
|
||||
description="List of data blocks in the .blend file",
|
||||
items=get_data_block_types,
|
||||
)
|
||||
|
||||
data_block: bpy.props.EnumProperty(
|
||||
name="List of objects in the .blend file",
|
||||
description="List of objects in the .blend file",
|
||||
items=get_data_blocks,
|
||||
)
|
||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||
directory: bpy.props.StringProperty(
|
||||
name="Directory",
|
||||
description="Start file browsing directory",
|
||||
default="",
|
||||
)
|
||||
|
||||
def invoke(self, context, event):
|
||||
mat = context.active_object.active_material
|
||||
external_style = tool.Style.get_style_elements(mat).get("IfcExternallyDefinedSurfaceStyle", None)
|
||||
# automatically select previously selected external style in file browser
|
||||
if external_style and self.filepath == "":
|
||||
style_path = Path(tool.Ifc.resolve_uri(external_style.Location))
|
||||
self.directory = str(style_path.parent)
|
||||
self.filepath = str(style_path)
|
||||
self.data_block_type, self.data_block = external_style.Identification.split("/")
|
||||
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text="Data Block Type")
|
||||
layout.prop(self, "data_block_type", text="", icon="GROUP")
|
||||
layout.label(text="Data Block")
|
||||
layout.prop(self, "data_block", text="")
|
||||
if bpy.data.is_saved:
|
||||
layout.prop(self, "use_relative_path")
|
||||
else:
|
||||
self.use_relative_path = False
|
||||
layout.label(text="Save the .blend file first ")
|
||||
layout.label(text="to use relative paths for .ifc.")
|
||||
|
||||
def execute(self, context):
|
||||
if self.data_block_type == "0":
|
||||
self.report({"ERROR"}, "Select a data block type")
|
||||
return {"CANCELLED"}
|
||||
|
||||
if self.data_block == "":
|
||||
self.report({"ERROR"}, "Select a data block")
|
||||
return {"CANCELLED"}
|
||||
|
||||
if not os.path.exists(self.filepath):
|
||||
self.report({"ERROR"}, f"File not found:\n'{self.filepath}'")
|
||||
return {"CANCELLED"}
|
||||
|
||||
db = tool.Blender.append_data_block(self.filepath, self.data_block_type, self.data_block)
|
||||
if not db["data_block"]:
|
||||
self.report({"ERROR"}, db["msg"])
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.data.materials.remove(db["data_block"])
|
||||
|
||||
if not StyleAttributesData.is_loaded:
|
||||
StyleAttributesData.load()
|
||||
external_style = StyleAttributesData.data["style_elements"].get("IfcExternallyDefinedSurfaceStyle", None)
|
||||
|
||||
if self.use_relative_path:
|
||||
filepath = os.path.relpath(self.filepath, bpy.path.abspath("//"))
|
||||
else:
|
||||
filepath = self.filepath
|
||||
|
||||
attributes = {
|
||||
"Location": filepath,
|
||||
"Identification": f"{self.data_block_type}/{self.data_block}",
|
||||
"Name": self.data_block,
|
||||
}
|
||||
if not external_style:
|
||||
core.add_external_style(
|
||||
tool.Ifc, tool.Style, obj=context.active_object.active_material, attributes=attributes
|
||||
)
|
||||
else:
|
||||
core.update_external_style(tool.Ifc, tool.Style, external_style=external_style, attributes=attributes)
|
||||
|
||||
StyleAttributesData.is_loaded = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingExternalStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_external_style"
|
||||
bl_label = "Enable Editing External Style"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
core.enable_editing_external_style(tool.Style, obj=context.active_object.active_material)
|
||||
|
||||
|
||||
class DisableEditingExternalStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.disable_editing_external_style"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_label = "Disable Editing External Style"
|
||||
|
||||
def _execute(self, context):
|
||||
core.disable_editing_external_style(tool.Style, obj=context.active_object.active_material)
|
||||
|
||||
|
||||
class EditExternalStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_external_style"
|
||||
bl_label = "Edit External Style"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
core.edit_external_style(tool.Ifc, tool.Style, obj=context.active_object.active_material)
|
||||
|
||||
|
||||
class ActivateExternalStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.activate_external_style"
|
||||
bl_label = "Activate External Style"
|
||||
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
||||
|
||||
def _execute(self, context):
|
||||
material = context.active_object.active_material
|
||||
external_style = tool.Style.get_style_elements(material)["IfcExternallyDefinedSurfaceStyle"]
|
||||
data_block_type, data_block = external_style.Identification.split("/")
|
||||
style_path = Path(tool.Ifc.resolve_uri(external_style.Location))
|
||||
|
||||
if style_path.suffix != ".blend":
|
||||
self.report({"ERROR"}, f"Only Blender external styles are supported")
|
||||
return {"CANCELLED"}
|
||||
|
||||
if not style_path.exists():
|
||||
self.report({"ERROR"}, f"File not found:\n'{style_path}'")
|
||||
return {"CANCELLED"}
|
||||
|
||||
db = tool.Blender.append_data_block(str(style_path), data_block_type, data_block)
|
||||
if not db["data_block"]:
|
||||
self.report({"ERROR"}, db["msg"])
|
||||
return {"CANCELLED"}
|
||||
|
||||
props_to_copy = [
|
||||
"diffuse_color",
|
||||
"metallic",
|
||||
"roughness",
|
||||
"specular_intensity",
|
||||
"use_nodes",
|
||||
]
|
||||
for prop_name in props_to_copy:
|
||||
setattr(material, prop_name, getattr(db["data_block"], prop_name))
|
||||
|
||||
if material.use_nodes:
|
||||
tool.Blender.copy_node_graph_to_active_object(context, db["data_block"])
|
||||
bpy.data.materials.remove(db["data_block"])
|
||||
|
||||
|
||||
class DisableEditingStyles(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.disable_editing_styles"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@@ -31,6 +31,7 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
def get_style_types(self, context):
|
||||
@@ -45,13 +46,74 @@ class Style(PropertyGroup):
|
||||
total_elements: IntProperty(name="Total Elements")
|
||||
|
||||
|
||||
STYLE_TYPES = [
|
||||
("Shading", "Shading", ""),
|
||||
("External", "External", ""),
|
||||
]
|
||||
|
||||
|
||||
def update_shading_styles(self, context):
|
||||
materials_to_objects = dict()
|
||||
|
||||
for obj in bpy.data.objects:
|
||||
blender_material = obj.active_material
|
||||
if blender_material and blender_material.BIMMaterialProperties.ifc_style_id != 0:
|
||||
materials_to_objects[blender_material] = obj
|
||||
|
||||
for mat, obj in materials_to_objects.items():
|
||||
tool.Style.change_current_style_type(context, obj, mat, self.active_style_type)
|
||||
|
||||
|
||||
class BIMStylesProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Editing")
|
||||
style_type: EnumProperty(items=get_style_types, name="Style Type")
|
||||
styles: CollectionProperty(name="Styles", type=Style)
|
||||
active_style_index: IntProperty(name="Active Style Index")
|
||||
active_style_type: EnumProperty(
|
||||
name="Active Style Type",
|
||||
description="Update current blender material to match style type for all objects in the scene",
|
||||
items=STYLE_TYPES,
|
||||
default="Shading",
|
||||
update=update_shading_styles,
|
||||
)
|
||||
|
||||
|
||||
def update_shading_style(self, context):
|
||||
blender_material = context.active_object.active_material
|
||||
style_elements = tool.Style.get_style_elements(blender_material)
|
||||
if self.active_style_type == "External":
|
||||
if "IfcExternallyDefinedSurfaceStyle" in style_elements:
|
||||
bpy.ops.bim.activate_external_style()
|
||||
|
||||
elif self.active_style_type == "Shading":
|
||||
style_elements = tool.Style.get_style_elements(blender_material)
|
||||
rendering_style = None
|
||||
texture_style = None
|
||||
|
||||
for surface_style in style_elements.values():
|
||||
if surface_style.is_a() == "IfcSurfaceStyleShading":
|
||||
tool.Loader.create_surface_style_shading(blender_material, surface_style)
|
||||
elif surface_style.is_a("IfcSurfaceStyleRendering"):
|
||||
rendering_style = surface_style
|
||||
tool.Loader.create_surface_style_rendering(blender_material, surface_style)
|
||||
elif surface_style.is_a("IfcSurfaceStyleWithTextures"):
|
||||
texture_style = surface_style
|
||||
|
||||
if rendering_style and texture_style:
|
||||
tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style)
|
||||
|
||||
|
||||
class BIMStyleProperties(PropertyGroup):
|
||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||
is_editing: BoolProperty(name="Is Editing")
|
||||
|
||||
external_style_attributes: CollectionProperty(name="External Style Attributes", type=Attribute)
|
||||
is_editing_external_style: BoolProperty(name="Is Editing External Style")
|
||||
|
||||
active_style_type: EnumProperty(
|
||||
name="Active Style Type",
|
||||
description="Update current blender material to match style type",
|
||||
items=STYLE_TYPES,
|
||||
default="Shading",
|
||||
update=update_shading_style,
|
||||
)
|
||||
|
||||
@@ -82,18 +82,22 @@ class BIM_PT_style(MaterialButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
props = context.active_object.active_material.BIMMaterialProperties
|
||||
style_props = context.active_object.active_material.BIMStyleProperties
|
||||
mat = context.material
|
||||
row = self.layout.row(align=True)
|
||||
if props.ifc_style_id:
|
||||
row.operator("bim.update_style_colours", icon="GREASEPENCIL")
|
||||
row.operator("bim.update_style_textures", icon="TEXTURE", text="")
|
||||
row.operator("bim.unlink_style", icon="UNLINKED", text="")
|
||||
row.operator("bim.remove_style", icon="X", text="").style = props.ifc_style_id
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(mat, "diffuse_color", text="Color")
|
||||
|
||||
else:
|
||||
if not props.ifc_style_id:
|
||||
row.operator("bim.add_style", icon="ADD")
|
||||
return
|
||||
|
||||
row.prop(style_props, "active_style_type", icon="SHADING_RENDERED", text="")
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.update_style_colours", icon="GREASEPENCIL")
|
||||
row.operator("bim.update_style_textures", icon="TEXTURE", text="")
|
||||
row.operator("bim.unlink_style", icon="UNLINKED", text="")
|
||||
row.operator("bim.remove_style", icon="X", text="").style = props.ifc_style_id
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(mat, "diffuse_color", text="Viewport Color" if mat.use_nodes else "Render Color")
|
||||
|
||||
|
||||
class BIM_PT_style_attributes(Panel):
|
||||
@@ -102,6 +106,7 @@ class BIM_PT_style_attributes(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "material"
|
||||
bl_parent_id = "BIM_PT_style"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -143,6 +148,61 @@ class BIM_PT_style_attributes(Panel):
|
||||
row.label(text=attribute["value"])
|
||||
|
||||
|
||||
class BIM_PT_external_style_attributes(Panel):
|
||||
bl_label = "IFC External Surface Style"
|
||||
bl_idname = "BIM_PT_external_style_attributes"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "material"
|
||||
bl_parent_id = "BIM_PT_style"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not IfcStore.get_file():
|
||||
return False
|
||||
try:
|
||||
return bool(context.active_object.active_material.BIMMaterialProperties.ifc_style_id)
|
||||
except:
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
if not StyleAttributesData.is_loaded or (
|
||||
context.active_object.active_material.BIMMaterialProperties.ifc_style_id
|
||||
!= StyleAttributesData.data["ifc_style_id"]
|
||||
):
|
||||
StyleAttributesData.load()
|
||||
|
||||
mat = context.active_object.active_material
|
||||
mprops = mat.BIMMaterialProperties
|
||||
props = mat.BIMStyleProperties
|
||||
|
||||
external_style = StyleAttributesData.data["style_elements"].get("IfcExternallyDefinedSurfaceStyle", None)
|
||||
if not external_style:
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.browse_external_style", text="Add External Style", icon="ADD")
|
||||
return
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Parameters:")
|
||||
|
||||
if props.is_editing_external_style:
|
||||
row.operator("bim.edit_external_style", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_external_style", icon="CANCEL", text="")
|
||||
blenderbim.bim.helper.draw_attributes(props.external_style_attributes, self.layout)
|
||||
else:
|
||||
row.operator("bim.browse_external_style", icon="APPEND_BLEND", text="")
|
||||
row.operator("bim.enable_editing_external_style", icon="GREASEPENCIL", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="STEP ID")
|
||||
row.label(text=str(external_style.id()))
|
||||
|
||||
for attribute in StyleAttributesData.data["external_style_attributes"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=attribute["name"])
|
||||
row.label(text=attribute["value"])
|
||||
|
||||
|
||||
class BIM_UL_styles(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
|
||||
@@ -33,6 +33,17 @@ def add_style(ifc, style, obj=None):
|
||||
return element
|
||||
|
||||
|
||||
def add_external_style(ifc, style, obj, attributes):
|
||||
element = style.get_style(obj)
|
||||
ifc.run(
|
||||
"style.add_surface_style", style=element, ifc_class="IfcExternallyDefinedSurfaceStyle", attributes=attributes
|
||||
)
|
||||
|
||||
|
||||
def update_external_style(ifc, style, external_style, attributes):
|
||||
ifc.run("style.edit_surface_style", style=external_style, attributes=attributes)
|
||||
|
||||
|
||||
def remove_style(ifc, material, style_tool, style=None):
|
||||
obj = ifc.get_object(style)
|
||||
ifc.unlink(obj=obj, element=style)
|
||||
@@ -95,16 +106,33 @@ def enable_editing_style(style, obj=None):
|
||||
style.import_surface_attributes(style.get_style(obj), obj)
|
||||
|
||||
|
||||
def enable_editing_external_style(style, obj=None):
|
||||
external_style = style.get_style_elements(obj)["IfcExternallyDefinedSurfaceStyle"]
|
||||
style.enable_editing_external_style(obj)
|
||||
style.import_external_style_attributes(external_style, obj)
|
||||
|
||||
|
||||
def disable_editing_style(style, obj=None):
|
||||
style.disable_editing(obj)
|
||||
|
||||
|
||||
def disable_editing_external_style(style, obj=None):
|
||||
style.disable_editing_external_style(obj)
|
||||
|
||||
|
||||
def edit_style(ifc, style, obj=None):
|
||||
attributes = style.export_surface_attributes(obj)
|
||||
ifc.run("style.edit_presentation_style", style=style.get_style(obj), attributes=attributes)
|
||||
style.disable_editing(obj)
|
||||
|
||||
|
||||
def edit_external_style(ifc, style, obj=None):
|
||||
attributes = style.export_external_style_attributes(obj)
|
||||
external_style = style.get_style_elements(obj)["IfcExternallyDefinedSurfaceStyle"]
|
||||
update_external_style(ifc, style, external_style, attributes)
|
||||
style.disable_editing_external_style(obj)
|
||||
|
||||
|
||||
def load_styles(style, style_type=None):
|
||||
style.import_presentation_styles(style_type)
|
||||
style.enable_editing_styles()
|
||||
|
||||
@@ -108,11 +108,48 @@ class Blender:
|
||||
return context_override
|
||||
|
||||
@classmethod
|
||||
def update_viewport(cls):
|
||||
# if it stops working in future Blender versions
|
||||
# there is an alternative:
|
||||
# bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
||||
def get_shader_editor_context(cls):
|
||||
for screen in bpy.data.screens:
|
||||
for area in screen.areas:
|
||||
if area.type == "NODE_EDITOR":
|
||||
for space in area.spaces:
|
||||
if space.tree_type == "ShaderNodeTree":
|
||||
context_override = {"area": area, "space": space, "screen": screen}
|
||||
return context_override
|
||||
|
||||
@classmethod
|
||||
def copy_node_graph_to_active_object(cls, context, material):
|
||||
"""make sure to override `context.active_object`
|
||||
to you want change node graph for the object that's not actually active
|
||||
"""
|
||||
temp_override = cls.get_shader_editor_context()
|
||||
old_material = context.active_object.active_material
|
||||
new_material = material
|
||||
|
||||
# remove all nodes from the current material
|
||||
for n in old_material.node_tree.nodes[:]:
|
||||
old_material.node_tree.nodes.remove(n)
|
||||
|
||||
# change current material and make other window's shader editor is updated
|
||||
context.active_object.active_material = new_material
|
||||
temp_override["space"].node_tree = new_material.node_tree
|
||||
|
||||
# select all nodes and copy them to clipboard
|
||||
for node in new_material.node_tree.nodes:
|
||||
node.select = True
|
||||
bpy.ops.node.clipboard_copy(temp_override)
|
||||
|
||||
# back to original material
|
||||
context.active_object.active_material = old_material
|
||||
temp_override["space"].node_tree = old_material.node_tree
|
||||
bpy.ops.node.clipboard_paste(temp_override, offset=(0, 0))
|
||||
|
||||
@classmethod
|
||||
def update_screen(cls):
|
||||
bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1)
|
||||
|
||||
@classmethod
|
||||
def update_viewport(cls):
|
||||
tool.Blender.get_viewport_context()["area"].tag_redraw()
|
||||
|
||||
@classmethod
|
||||
@@ -215,6 +252,14 @@ class Blender:
|
||||
context.view_layer.objects.active = active_object
|
||||
active_object.select_set(True)
|
||||
|
||||
@classmethod
|
||||
def append_data_block(cls, filepath, data_block_type, name, link=False, relative=False):
|
||||
with bpy.data.libraries.load(filepath, link=link, relative=relative) as (data_from, data_to):
|
||||
if name not in getattr(data_from, data_block_type):
|
||||
return {"data_block": None, "msg": f"Data-block {data_block_type}/{name} not found in {filepath}"}
|
||||
getattr(data_to, data_block_type).append(name)
|
||||
return {"data_block": getattr(data_to, data_block_type)[0], "msg": ""}
|
||||
|
||||
## BMESH UTILS ##
|
||||
@classmethod
|
||||
def apply_bmesh(cls, mesh, bm, obj=None):
|
||||
|
||||
@@ -21,6 +21,8 @@ import bpy
|
||||
import ifcopenshell.util.element
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
import os
|
||||
import mathutils
|
||||
|
||||
|
||||
# Progressively we'll refactor loading elements into Blender objects into this
|
||||
@@ -28,6 +30,7 @@ import blenderbim.tool as tool
|
||||
# partially load and unload objects for huge models, partial model editing, and
|
||||
# supplementary objects (e.g. drawings, structural analysis models, etc).
|
||||
|
||||
|
||||
class Loader(blenderbim.core.tool.Loader):
|
||||
@classmethod
|
||||
def get_mesh_name(cls, geometry):
|
||||
@@ -52,3 +55,174 @@ class Loader(blenderbim.core.tool.Loader):
|
||||
else:
|
||||
# TODO: See #2002
|
||||
mesh.BIMMeshProperties.ifc_definition_id = int(geometry.id.replace(",", ""))
|
||||
|
||||
@classmethod
|
||||
def create_surface_style_shading(cls, blender_material, surface_style):
|
||||
alpha = 1.0
|
||||
# Transparency was added in IFC4
|
||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
||||
alpha = 1 - surface_style.Transparency
|
||||
blender_material.diffuse_color = (
|
||||
surface_style.SurfaceColour.Red,
|
||||
surface_style.SurfaceColour.Green,
|
||||
surface_style.SurfaceColour.Blue,
|
||||
alpha,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def restart_material_node_tree(cls, blender_material):
|
||||
nodes = blender_material.node_tree.nodes
|
||||
links = blender_material.node_tree.links
|
||||
for n in nodes[:]:
|
||||
nodes.remove(n)
|
||||
output = nodes.new("ShaderNodeOutputMaterial")
|
||||
bsdf = nodes.new("ShaderNodeBsdfPrincipled")
|
||||
links.new(bsdf.outputs["BSDF"], output.inputs["Surface"])
|
||||
|
||||
@classmethod
|
||||
def create_surface_style_rendering(cls, blender_material, surface_style):
|
||||
cls.create_surface_style_shading(blender_material, surface_style)
|
||||
if surface_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
||||
blender_material.use_nodes = True
|
||||
cls.restart_material_node_tree(blender_material)
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
if surface_style.DiffuseColour:
|
||||
if surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
||||
bsdf.inputs["Base Color"].default_value = (
|
||||
surface_style.DiffuseColour.Red,
|
||||
surface_style.DiffuseColour.Green,
|
||||
surface_style.DiffuseColour.Blue,
|
||||
1,
|
||||
)
|
||||
elif surface_style.DiffuseColour.is_a("IfcNormalisedRatioMeasure"):
|
||||
bsdf.inputs["Base Color"].default_value = (
|
||||
surface_style.SurfaceColour.Red * surface_style.DiffuseColour.wrappedValue,
|
||||
surface_style.SurfaceColour.Green * surface_style.DiffuseColour.wrappedValue,
|
||||
surface_style.SurfaceColour.Blue * surface_style.DiffuseColour.wrappedValue,
|
||||
1,
|
||||
)
|
||||
if surface_style.SpecularColour and surface_style.SpecularColour.is_a("IfcNormalisedRatioMeasure"):
|
||||
bsdf.inputs["Metallic"].default_value = surface_style.SpecularColour.wrappedValue
|
||||
if surface_style.SpecularHighlight and surface_style.SpecularHighlight.is_a("IfcSpecularRoughness"):
|
||||
bsdf.inputs["Roughness"].default_value = surface_style.SpecularHighlight.wrappedValue
|
||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
||||
bsdf.inputs["Alpha"].default_value = 1 - surface_style.Transparency
|
||||
blender_material.blend_method = "BLEND"
|
||||
|
||||
elif surface_style.ReflectanceMethod == "FLAT":
|
||||
blender_material.use_nodes = True
|
||||
cls.restart_material_node_tree(blender_material)
|
||||
|
||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
|
||||
mix = blender_material.node_tree.nodes.new(type="ShaderNodeMixShader")
|
||||
mix.location = bsdf.location
|
||||
blender_material.node_tree.links.new(mix.outputs[0], output.inputs["Surface"])
|
||||
|
||||
blender_material.node_tree.nodes.remove(bsdf)
|
||||
|
||||
lightpath = blender_material.node_tree.nodes.new(type="ShaderNodeLightPath")
|
||||
lightpath.location = mix.location - mathutils.Vector((200, -200))
|
||||
blender_material.node_tree.links.new(lightpath.outputs[0], mix.inputs[0])
|
||||
|
||||
bsdf = blender_material.node_tree.nodes.new(type="ShaderNodeBsdfTransparent")
|
||||
bsdf.location = mix.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(bsdf.outputs[0], mix.inputs[1])
|
||||
|
||||
rgb = blender_material.node_tree.nodes.new(type="ShaderNodeRGB")
|
||||
rgb.location = mix.location - mathutils.Vector((200, 200))
|
||||
blender_material.node_tree.links.new(rgb.outputs[0], mix.inputs[2])
|
||||
|
||||
if surface_style.DiffuseColour and surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
||||
rgb.outputs[0].default_value = (
|
||||
surface_style.DiffuseColour.Red,
|
||||
surface_style.DiffuseColour.Green,
|
||||
surface_style.DiffuseColour.Blue,
|
||||
1,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def create_surface_style_with_textures(cls, blender_material, rendering_style, texture_style):
|
||||
for texture in texture_style.Textures:
|
||||
mode = getattr(texture, "Mode", None)
|
||||
node = None
|
||||
|
||||
if texture.is_a("IfcImageTexture"):
|
||||
image_url = texture.URLReference
|
||||
if not os.path.abspath(texture.URLReference) and tool.Ifc.get_path():
|
||||
image_url = os.path.join(os.path.dirname(tool.Ifc.get_path()), texture.URLReference)
|
||||
|
||||
if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
||||
bsdf = blender_material.node_tree.nodes["Principled BSDF"]
|
||||
if mode == "NORMAL":
|
||||
normalmap = blender_material.node_tree.nodes.new(type="ShaderNodeNormalMap")
|
||||
normalmap.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(normalmap.outputs[0], bsdf.inputs["Normal"])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = normalmap.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
image.colorspace_settings.name = "Non-Color"
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], normalmap.inputs["Color"])
|
||||
elif mode == "EMISSIVE":
|
||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
||||
|
||||
add = blender_material.node_tree.nodes.new(type="ShaderNodeAddShader")
|
||||
add.location = bsdf.location + mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(bsdf.outputs[0], add.inputs[1])
|
||||
blender_material.node_tree.links.new(add.outputs[0], output.inputs[0])
|
||||
|
||||
emission = blender_material.node_tree.nodes.new(type="ShaderNodeEmission")
|
||||
emission.location = add.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(emission.outputs[0], add.inputs[0])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = emission.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], emission.inputs[0])
|
||||
elif mode == "METALLICROUGHNESS":
|
||||
separate = blender_material.node_tree.nodes.new(type="ShaderNodeSeparateRGB")
|
||||
separate.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
blender_material.node_tree.links.new(separate.outputs[1], bsdf.inputs["Roughness"])
|
||||
blender_material.node_tree.links.new(separate.outputs[2], bsdf.inputs["Metallic"])
|
||||
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = separate.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
image.colorspace_settings.name = "Non-Color"
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], separate.inputs[0])
|
||||
elif mode == "OCCLUSION":
|
||||
# TODO work out how to implement glTF settings here
|
||||
# https://docs.blender.org/manual/en/dev/addons/import_export/scene_gltf2.html
|
||||
pass
|
||||
elif mode == "DIFFUSE":
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = bsdf.location - mathutils.Vector((400, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs["Base Color"])
|
||||
blender_material.node_tree.links.new(node.outputs[1], bsdf.inputs["Alpha"])
|
||||
blender_material.blend_method = "BLEND"
|
||||
elif rendering_style.ReflectanceMethod == "FLAT":
|
||||
bsdf = blender_material.node_tree.nodes["Mix Shader"]
|
||||
if mode == "EMISSIVE":
|
||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
node.location = bsdf.location - mathutils.Vector((200, 0))
|
||||
image = bpy.data.images.load(image_url)
|
||||
node.image = image
|
||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs[2])
|
||||
|
||||
if node and getattr(texture, "IsMappedBy", None):
|
||||
coordinates = texture.IsMappedBy[0]
|
||||
coord = blender_material.node_tree.nodes.new(type="ShaderNodeTexCoord")
|
||||
coord.location = node.location - mathutils.Vector((200, 0))
|
||||
if coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD":
|
||||
blender_material.node_tree.links.new(coord.outputs["Generated"], node.inputs["Vector"])
|
||||
elif coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD-EYE":
|
||||
blender_material.node_tree.links.new(coord.outputs["Camera"], node.inputs["Vector"])
|
||||
else:
|
||||
blender_material.node_tree.links.new(coord.outputs["UV"], node.inputs["Vector"])
|
||||
|
||||
@@ -33,6 +33,10 @@ class Style(blenderbim.core.tool.Style):
|
||||
def disable_editing(cls, obj):
|
||||
obj.BIMStyleProperties.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def disable_editing_external_style(cls, obj):
|
||||
obj.BIMStyleProperties.is_editing_external_style = False
|
||||
|
||||
@classmethod
|
||||
def disable_editing_styles(cls):
|
||||
bpy.context.scene.BIMStylesProperties.is_editing = False
|
||||
@@ -41,6 +45,10 @@ class Style(blenderbim.core.tool.Style):
|
||||
def enable_editing(cls, obj):
|
||||
obj.BIMStyleProperties.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def enable_editing_external_style(cls, obj):
|
||||
obj.BIMStyleProperties.is_editing_external_style = True
|
||||
|
||||
@classmethod
|
||||
def enable_editing_styles(cls):
|
||||
bpy.context.scene.BIMStylesProperties.is_editing = True
|
||||
@@ -49,6 +57,10 @@ class Style(blenderbim.core.tool.Style):
|
||||
def export_surface_attributes(cls, obj):
|
||||
return blenderbim.bim.helper.export_attributes(obj.BIMStyleProperties.attributes)
|
||||
|
||||
@classmethod
|
||||
def export_external_style_attributes(cls, obj):
|
||||
return blenderbim.bim.helper.export_attributes(obj.BIMStyleProperties.external_style_attributes)
|
||||
|
||||
@classmethod
|
||||
def get_active_style_type(cls):
|
||||
return bpy.context.scene.BIMStylesProperties.style_type
|
||||
@@ -73,6 +85,14 @@ class Style(blenderbim.core.tool.Style):
|
||||
except:
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def get_style_elements(cls, blender_material):
|
||||
style = tool.Ifc.get().by_id(blender_material.BIMMaterialProperties.ifc_style_id)
|
||||
style_elements = {}
|
||||
for style in style.Styles:
|
||||
style_elements[style.is_a()] = style
|
||||
return style_elements
|
||||
|
||||
@classmethod
|
||||
def get_surface_rendering_attributes(cls, obj):
|
||||
transparency = 1 - obj.diffuse_color[3]
|
||||
@@ -197,8 +217,15 @@ class Style(blenderbim.core.tool.Style):
|
||||
|
||||
@classmethod
|
||||
def import_surface_attributes(cls, style, obj):
|
||||
obj.BIMStyleProperties.attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(style, obj.BIMStyleProperties.attributes)
|
||||
attributes = obj.BIMStyleProperties.attributes
|
||||
attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(style, attributes)
|
||||
|
||||
@classmethod
|
||||
def import_external_style_attributes(cls, style, obj):
|
||||
attributes = obj.BIMStyleProperties.external_style_attributes
|
||||
attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(style, attributes)
|
||||
|
||||
@classmethod
|
||||
def is_editing_styles(cls):
|
||||
@@ -214,3 +241,8 @@ class Style(blenderbim.core.tool.Style):
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
|
||||
@classmethod
|
||||
def change_current_style_type(cls, context, obj, blender_material, style_type):
|
||||
with context.temp_override(active_object=obj):
|
||||
blender_material.BIMStyleProperties.active_style_type = style_type
|
||||
|
||||
Reference in New Issue
Block a user