Fix regression bug where you couldn't add a grid.

This commit is contained in:
Dion Moult
2021-10-23 21:19:10 +11:00
parent 918915aeae
commit 7bccf10fec
8 changed files with 121 additions and 49 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ def draw_attribute(attribute, layout, copy_operator=None):
layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
if copy_operator:
op = layout.operator(f"{copy_operator}", text="", icon="COPYDOWN")
op.data = json.dumps({"name": attribute.name, "value": attribute.get_value(), "is_null": attribute.is_null})
op.attribute_name = attribute.name
def import_attributes(ifc_class, props, data, callback=None):
@@ -0,0 +1,74 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import blenderbim.tool as tool
def refresh():
AttributesData.is_loaded = False
MaterialAttributesData.is_loaded = False
class AttributesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"attributes": cls.attributes()}
cls.is_loaded = True
@classmethod
def attributes(cls):
results = []
element = tool.Ifc.get_entity(bpy.context.active_object)
data = element.get_info()
if hasattr(element, "GlobalId"):
excluded_keys = ["id", "type"]
else:
excluded_keys = ["type"]
for key, value in data.items():
if value is None or isinstance(value, ifcopenshell.entity_instance) or key in excluded_keys:
continue
if key == "id":
key = "STEP ID"
results.append({"name": key, "value": str(value)})
return results
class MaterialAttributesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"attributes": cls.attributes()}
cls.is_loaded = True
@classmethod
def attributes(cls):
results = []
element = tool.Ifc.get_entity(bpy.context.active_object.active_material)
data = element.get_info()
for key, value in data.items():
if value is None or isinstance(value, ifcopenshell.entity_instance) or key in ["id", "type"]:
continue
results.append({"name": key, "value": str(value)})
return results
@@ -75,16 +75,13 @@ class DisableEditingAttributes(bpy.types.Operator):
return {"FINISHED"}
class EditAttributes(bpy.types.Operator):
class EditAttributes(bpy.types.Operator, Operator):
bl_idname = "bim.edit_attributes"
bl_label = "Edit Attributes"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
if self.obj_type == "Object":
@@ -16,17 +16,16 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import blenderbim.bim.helper
from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.attribute.data import Data
from blenderbim.bim.module.attribute.data import AttributesData, MaterialAttributesData
def draw_ui(context, layout, obj_type):
def draw_ui(context, layout, obj_type, attributes):
obj = context.active_object if obj_type == "Object" else context.active_object.active_material
oprops = obj.BIMObjectProperties
props = obj.BIMAttributeProperties
if oprops.ifc_definition_id not in Data.products:
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
if props.is_editing_attributes:
row = layout.row(align=True)
@@ -37,49 +36,17 @@ def draw_ui(context, layout, obj_type):
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="",
)
if attribute["name"] != "GlobalId":
op = row.operator("bim.copy_attribute_to_selection", icon="COPYDOWN", text="")
op.attribute_name = attribute["name"]
blenderbim.bim.helper.draw_attributes(props.attributes, layout, copy_operator="bim.copy_attribute_to_selection")
else:
row = layout.row()
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
op.obj_type = obj_type
op.obj = obj.name
if "GlobalId" not in [a["name"] for a in Data.products[oprops.ifc_definition_id]]:
row = layout.row(align=True)
row.label(text="STEP ID")
row.label(text=str(oprops.ifc_definition_id))
for attribute in Data.products[oprops.ifc_definition_id]:
if attribute["value"] is None or attribute["type"] == "entity":
continue
for attribute in attributes:
row = layout.row(align=True)
row.label(text=attribute["name"])
row.label(text=str(attribute["value"]))
row.label(text=attribute["value"])
# TODO: reimplement, see #1222
# if "IfcSite/" in context.active_object.name or "IfcBuilding/" in context.active_object.name:
@@ -102,7 +69,9 @@ class BIM_PT_object_attributes(Panel):
return bool(context.active_object.BIMObjectProperties.ifc_definition_id)
def draw(self, context):
draw_ui(context, self.layout, "Object")
if not AttributesData.is_loaded:
AttributesData.load()
draw_ui(context, self.layout, "Object", AttributesData.data["attributes"])
class BIM_PT_material_attributes(Panel):
@@ -122,4 +91,6 @@ class BIM_PT_material_attributes(Panel):
return False
def draw(self, context):
draw_ui(context, self.layout, "Material")
if not MaterialAttributesData.is_loaded:
MaterialAttributesData.load()
draw_ui(context, self.layout, "Material", MaterialAttributesData.data["attributes"])
@@ -18,6 +18,8 @@
import bpy
import ifcopenshell.api
import blenderbim.core.spatial
import blenderbim.tool as tool
from bpy.types import Operator
from bpy.props import FloatProperty, IntProperty
from mathutils import Vector
@@ -51,8 +53,8 @@ def add_object(self, context):
if has_site_collection:
site_obj = bpy.data.objects.get(grandchild.name)
if site_obj and site_obj.BIMObjectProperties.ifc_definition_id:
bpy.ops.bim.assign_container(
relating_structure=site_obj.BIMObjectProperties.ifc_definition_id, related_element=obj.name
blenderbim.core.spatial.assign_container(
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=site_obj, element_obj=obj
)
axes_collection = bpy.data.collections.new("UAxes")
@@ -26,3 +26,14 @@ Scenario: Add type instance - add from an empty
And I set "scene.BIMTypeProperties.relating_type" to "{empty}"
When I press "bim.add_type_instance"
Then the object "IfcWall/Instance" exists
Scenario: Add grid
Given an empty IFC project
When I press "mesh.add_grid"
Then the object "IfcGrid/Grid" is an "IfcGrid"
And the object "IfcGridAxis/A" is an "IfcGridAxis"
And the object "IfcGridAxis/B" is an "IfcGridAxis"
And the object "IfcGridAxis/C" is an "IfcGridAxis"
And the object "IfcGridAxis/01" is an "IfcGridAxis"
And the object "IfcGridAxis/02" is an "IfcGridAxis"
And the object "IfcGridAxis/03" is an "IfcGridAxis"
@@ -12,7 +12,7 @@ class Usecase:
def execute(self):
element = self.file.create_entity(
"IfcGridAxis", **{"axis_tag": self.settings["axis_tag"], "SameSense": self.settings["same_sense"]}
"IfcGridAxis", **{"AxisTag": self.settings["axis_tag"], "SameSense": self.settings["same_sense"]}
)
axes = list(getattr(self.settings["grid"], self.settings["uvw_axes"]) or [])
axes.append(element)
@@ -0,0 +1,17 @@
import test.bootstrap
import ifcopenshell.api
class TestCreateGridAxis(test.bootstrap.IFC4):
def test_run(self):
grid = self.file.createIfcGrid()
axis = ifcopenshell.api.run(
"grid.create_grid_axis", self.file, axis_tag="axis_tag", same_sense=True, uvw_axes="UAxes", grid=grid
)
assert axis.AxisTag == "axis_tag"
assert axis.SameSense is True
assert grid.UAxes == (axis,)
axis2 = ifcopenshell.api.run(
"grid.create_grid_axis", self.file, axis_tag="axis_tag", same_sense=True, uvw_axes="UAxes", grid=grid
)
assert grid.UAxes == (axis,axis2)