WIP implement material attributes panel. See #1222.

This commit is contained in:
Dion Moult
2021-01-17 21:07:01 +11:00
parent 25fb9be82e
commit 3fe5c88910
8 changed files with 135 additions and 156 deletions
@@ -297,6 +297,7 @@ if bpy is not None:
bpy.types.Scene.MapConversion = bpy.props.PointerProperty(type=prop.MapConversion)
bpy.types.Scene.TargetCRS = bpy.props.PointerProperty(type=prop.TargetCRS)
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) # Check if we need this
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
@@ -321,6 +322,7 @@ if bpy is not None:
del bpy.types.Scene.MapConversion
del bpy.types.Scene.TargetCRS
del bpy.types.Object.BIMObjectProperties
del bpy.types.Material.BIMObjectProperties
del bpy.types.Collection.BIMObjectProperties # Check if we need this
del bpy.types.Material.BIMMaterialProperties
del bpy.types.Mesh.BIMMeshProperties
@@ -204,7 +204,7 @@ class MaterialCreator:
def create_new_single(self, material):
self.materials[material.Name] = obj = bpy.data.materials.new(material.Name)
obj.BIMMaterialProperties.ifc_definition_id = int(material.id())
obj.BIMObjectProperties.ifc_definition_id = int(material.id())
if not material.HasRepresentation or not material.HasRepresentation[0].Representations:
return
for representation in material.HasRepresentation[0].Representations:
@@ -233,7 +233,6 @@ class MaterialCreator:
if not style.is_a("IfcSurfaceStyle"):
continue
material.BIMMaterialProperties.ifc_style_id = int(style.id())
external_style = None
for surface_style in style.Styles:
if surface_style.is_a("IfcSurfaceStyleShading"):
alpha = 1.0
@@ -246,13 +245,6 @@ class MaterialCreator:
surface_style.SurfaceColour.Blue,
alpha,
)
elif surface_style.is_a("IfcExternallyDefinedSurfaceStyle"):
external_style = surface_style
if external_style:
material.BIMMaterialProperties.is_external = True
material.BIMMaterialProperties.location = external_style.Location
material.BIMMaterialProperties.identification = external_style.Identification
material.BIMMaterialProperties.name = external_style.Name
# IfcPresentationStyleAssignment is deprecated as of IFC4
# However it is still widely used thanks to Revit :(
@@ -1,17 +1,21 @@
import bpy
from . import ui, operator
from . import ui, prop, operator
classes = (
operator.EnableEditingAttributes,
operator.DisableEditingAttributes,
operator.EditAttributes,
ui.BIM_PT_attributes,
prop.BIMAttributeProperties,
ui.BIM_PT_object_attributes,
ui.BIM_PT_material_attributes,
)
def register():
pass
bpy.types.Object.BIMAttributeProperties = bpy.props.PointerProperty(type=prop.BIMAttributeProperties)
bpy.types.Material.BIMAttributeProperties = bpy.props.PointerProperty(type=prop.BIMAttributeProperties)
def unregister():
pass
del bpy.types.Object.BIMAttributeProperties
del bpy.types.Material.BIMAttributeProperties
@@ -8,14 +8,20 @@ from blenderbim.bim.module.attribute.data import Data
class EnableEditingAttributes(bpy.types.Operator):
bl_idname = "bim.enable_editing_attributes"
bl_label = "Enable Editing Attributes"
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
obj = bpy.context.active_object
props = obj.BIMObjectProperties
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
oprops = obj.BIMObjectProperties
props = obj.BIMAttributeProperties
while len(props.attributes) > 0:
props.attributes.remove(0)
for attribute in Data.products[props.ifc_definition_id]:
for attribute in Data.products[oprops.ifc_definition_id]:
new = props.attributes.add()
if attribute["type"] == "entity":
continue
@@ -38,10 +44,15 @@ class EnableEditingAttributes(bpy.types.Operator):
class DisableEditingAttributes(bpy.types.Operator):
bl_idname = "bim.disable_editing_attributes"
bl_label = "Disable Editing Attributes"
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
def execute(self, context):
obj = bpy.context.active_object
props = obj.BIMObjectProperties
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
props = obj.BIMAttributeProperties
props.is_editing_attributes = False
return {"FINISHED"}
@@ -49,13 +60,19 @@ class DisableEditingAttributes(bpy.types.Operator):
class EditAttributes(bpy.types.Operator):
bl_idname = "bim.edit_attributes"
bl_label = "Edit Attributes"
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
obj = bpy.context.active_object
props = obj.BIMObjectProperties
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
oprops = obj.BIMObjectProperties
props = obj.BIMAttributeProperties
attributes = {}
for attribute in Data.products[props.ifc_definition_id]:
for attribute in Data.products[oprops.ifc_definition_id]:
blender_attribute = props.attributes.get(attribute["name"])
if not blender_attribute:
continue
@@ -77,9 +94,9 @@ class EditAttributes(bpy.types.Operator):
elif attribute["type"] == "enum":
attributes[attribute["name"]] = blender_attribute.enum_value
edit_attributes.Usecase(self.file, {
"product": self.file.by_id(props.ifc_definition_id),
"product": self.file.by_id(oprops.ifc_definition_id),
"attributes": attributes
}).execute()
Data.load(props.ifc_definition_id)
bpy.ops.bim.disable_editing_attributes()
Data.load(oprops.ifc_definition_id)
bpy.ops.bim.disable_editing_attributes(obj=self.obj, obj_type=self.obj_type)
return {"FINISHED"}
@@ -0,0 +1,20 @@
import bpy
import blenderbim.bim.schema # refactor
from blenderbim.bim.module.material.data import Data
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
class BIMAttributeProperties(PropertyGroup):
attributes: CollectionProperty(name="Attributes", type=Attribute)
is_editing_attributes: BoolProperty(name="Is Editing Attributes")
@@ -2,9 +2,71 @@ from bpy.types import Panel
from blenderbim.bim.module.attribute.data import Data
class BIM_PT_attributes(Panel):
def draw_ui(context, layout, obj_type):
obj = context.active_object if obj_type == "Object" else context.active_object.active_material
oprops = obj.BIMObjectProperties
props = obj.BIMAttributeProperties
if not oprops.ifc_definition_id:
return
if oprops.ifc_definition_id not in Data.products:
Data.load(oprops.ifc_definition_id)
if props.is_editing_attributes:
row = layout.row(align=True)
op = row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
op.obj_type = obj_type
op.obj = obj.name
op = row.operator("bim.disable_editing_attributes", icon="X", text="")
op.obj_type = obj_type
op.obj = obj.name
for attribute in Data.products[oprops.ifc_definition_id]:
if attribute["type"] == "entity":
continue
row = layout.row(align=True)
blender_attribute = props.attributes.get(attribute["name"])
if attribute["type"] == "string" or attribute["type"] == "list":
row.prop(blender_attribute, "string_value", text=attribute["name"])
elif attribute["type"] == "integer":
row.prop(blender_attribute, "int_value", text=attribute["name"])
elif attribute["type"] == "float":
row.prop(blender_attribute, "float_value", text=attribute["name"])
elif attribute["type"] == "enum":
row.prop(blender_attribute, "enum_value", text=attribute["name"])
if attribute["name"] == "GlobalId":
row.operator("bim.generate_global_id", icon="FILE_REFRESH", text="")
if attribute["is_optional"]:
row.prop(
blender_attribute,
"is_null",
icon="RADIOBUT_OFF" if blender_attribute.is_null else "RADIOBUT_ON",
text="",
)
# TODO: reimplement, see #1222
# op = row.operator("bim.copy_attribute_to_selection", icon="COPYDOWN", text="")
# op.attribute_name = attribute.name
# op.attribute_value = attribute.string_value
else:
row = layout.row()
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
op.obj_type = obj_type
op.obj = obj.name
for attribute in Data.products[oprops.ifc_definition_id]:
if attribute["value"] is None or attribute["type"] == "entity":
continue
row = layout.row(align=True)
row.label(text=attribute["name"])
row.label(text=str(attribute["value"]))
# TODO: reimplement, see #1222
# if "IfcSite/" in context.active_object.name or "IfcBuilding/" in context.active_object.name:
# self.draw_addresses_ui()
class BIM_PT_object_attributes(Panel):
bl_label = "IFC Attributes"
bl_idname = "BIM_PT_attributes"
bl_idname = "BIM_PT_object_attributes"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
@@ -14,76 +76,19 @@ class BIM_PT_attributes(Panel):
return bool(context.active_object.BIMObjectProperties.ifc_definition_id)
def draw(self, context):
props = context.active_object.BIMObjectProperties
if not props.ifc_definition_id:
return
if props.ifc_definition_id not in Data.products:
Data.load(props.ifc_definition_id)
draw_ui(context, self.layout, "Object")
if props.is_editing_attributes:
row = self.layout.row(align=True)
row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
row.operator("bim.disable_editing_attributes", icon="X", text="")
for attribute in Data.products[props.ifc_definition_id]:
if attribute["type"] == "entity":
continue
row = self.layout.row(align=True)
blender_attribute = props.attributes.get(attribute["name"])
if attribute["type"] == "string" or attribute["type"] == "list":
row.prop(blender_attribute, "string_value", text=attribute["name"])
elif attribute["type"] == "integer":
row.prop(blender_attribute, "int_value", text=attribute["name"])
elif attribute["type"] == "float":
row.prop(blender_attribute, "float_value", text=attribute["name"])
elif attribute["type"] == "enum":
row.prop(blender_attribute, "enum_value", text=attribute["name"])
class BIM_PT_material_attributes(Panel):
bl_label = "IFC Attributes"
bl_idname = "BIM_PT_material_attributes"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
if attribute["name"] == "GlobalId":
row.operator("bim.generate_global_id", icon="FILE_REFRESH", text="")
if attribute["is_optional"]:
row.prop(blender_attribute, "is_null", icon="RADIOBUT_OFF" if blender_attribute.is_null else "RADIOBUT_ON", text="")
# TODO: reimplement, see #1222
#op = row.operator("bim.copy_attribute_to_selection", icon="COPYDOWN", text="")
#op.attribute_name = attribute.name
#op.attribute_value = attribute.string_value
else:
row = self.layout.row()
row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
for attribute in Data.products[props.ifc_definition_id]:
if attribute["value"] is None or attribute["type"] == "entity":
continue
row = self.layout.row(align=True)
row.label(text=attribute["name"])
row.label(text=str(attribute["value"]))
# TODO: reimplement, see #1222
#if "IfcSite/" in context.active_object.name or "IfcBuilding/" in context.active_object.name:
# self.draw_addresses_ui()
def draw_addresses_ui(self):
self.layout.label(text="Address:")
address = bpy.context.active_object.BIMObjectProperties.address
row = self.layout.row()
row.prop(address, "purpose")
if address.purpose == "USERDEFINED":
row = self.layout.row()
row.prop(address, "user_defined_purpose")
row = self.layout.row()
row.prop(address, "description")
row = self.layout.row()
row.prop(address, "internal_location")
row = self.layout.row()
row.prop(address, "address_lines")
row = self.layout.row()
row.prop(address, "postal_box")
row = self.layout.row()
row.prop(address, "town")
row = self.layout.row()
row.prop(address, "region")
row = self.layout.row()
row.prop(address, "postal_code")
row = self.layout.row()
row.prop(address, "country")
@classmethod
def poll(cls, context):
return bool(context.active_object.active_material.BIMObjectProperties.ifc_definition_id)
def draw(self, context):
draw_ui(context, self.layout, "Material")
@@ -1323,8 +1323,6 @@ class BIMObjectProperties(PropertyGroup):
ifc_definition_id: IntProperty(name="IFC Definition ID")
is_reassigning_class: BoolProperty(name="Is Reassigning Class")
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
attributes: CollectionProperty(name="Attributes", type=Attribute)
is_editing_attributes: BoolProperty(name="Is Editing Attributes")
relating_object: PointerProperty(name="Aggregate", type=bpy.types.Object)
is_editing_aggregate: BoolProperty(name="Is Editing Aggregate")
is_editing_container: BoolProperty(name="Is Editing Container")
@@ -1355,7 +1353,6 @@ class BIMMaterialProperties(PropertyGroup):
psets: CollectionProperty(name="Psets", type=PsetQto)
attributes: CollectionProperty(name="Attributes", type=Attribute)
applicable_attributes: EnumProperty(items=getApplicableMaterialAttributes, name="Attribute Names")
ifc_definition_id: IntProperty(name="IFC Definition ID")
# In Blender, a material object can map to an IFC material, IFC surface style, or both
ifc_style_id: IntProperty(name="IFC Style ID")
-58
View File
@@ -437,64 +437,6 @@ class BIM_PT_presentation_layer_data(Panel):
op.index = scene_props.active_presentation_layer_index
class BIM_PT_material(Panel):
bl_label = "IFC Materials"
bl_idname = "BIM_PT_material"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.active_material is not None
def draw(self, context):
if not bpy.context.active_object.active_material:
return
props = context.active_object.active_material.BIMMaterialProperties
layout = self.layout
row = layout.row()
row.prop(props, "is_external")
row = layout.row(align=True)
row.prop(props, "location")
row.operator("bim.select_external_material_dir", icon="FILE_FOLDER", text="")
row = layout.row()
row.prop(props, "identification")
row = layout.row()
row.prop(props, "name")
row = layout.row()
row.operator("bim.fetch_external_material")
layout.label(text="Attributes:")
row = layout.row(align=True)
row.prop(props, "applicable_attributes", text="")
row.operator("bim.add_material_attribute")
for index, attribute in enumerate(props.attributes):
row = layout.row(align=True)
row.prop(attribute, "name", text="")
row.prop(attribute, "string_value", text="")
row.operator("bim.remove_material_attribute", icon="X", text="").attribute_index = index
row = layout.row()
row.prop(props, "attributes")
layout.label(text="Property Sets:")
row = layout.row(align=True)
row.prop(props, "pset_name", text="")
row.operator("bim.add_material_pset")
for index, pset in enumerate(props.psets):
row = layout.row(align=True)
row.prop(pset, "name", text="")
row.operator("bim.remove_material_pset", icon="X", text="").pset_index = index
for prop in pset.properties:
row = layout.row(align=True)
row.prop(prop, "name", text="")
row.prop(prop, "string_value", text="")
class BIM_PT_gis(Panel):
bl_label = "IFC Georeferencing"
bl_idname = "BIM_PT_gis"