mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Fix #1855. Bug where authoring type dropdowns didn't refresh.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# 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 blenderbim.tool as tool
|
||||
|
||||
|
||||
def refresh():
|
||||
AuthoringData.is_loaded = False
|
||||
WorkspaceData.is_loaded = False
|
||||
|
||||
|
||||
class AuthoringData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {
|
||||
"ifc_classes": cls.ifc_classes(),
|
||||
"relating_types": cls.relating_types(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def ifc_classes(cls):
|
||||
results = []
|
||||
classes = set([e.is_a() for e in tool.Ifc.get().by_type("IfcElementType")])
|
||||
results.extend([(c, c, "") for c in sorted(classes)])
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def relating_types(cls):
|
||||
results = []
|
||||
ifc_class = bpy.context.scene.BIMModelProperties.ifc_class
|
||||
if ifc_class:
|
||||
elements = [(str(e.id()), e.Name, "") for e in tool.Ifc.get().by_type(ifc_class)]
|
||||
results.extend(sorted(elements, key=lambda s: s[1]))
|
||||
return results
|
||||
return []
|
||||
|
||||
|
||||
class WorkspaceData(AuthoringData):
|
||||
pass
|
||||
@@ -63,9 +63,9 @@ class AddTypeInstance(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
tprops = context.scene.BIMTypeProperties
|
||||
ifc_class = self.ifc_class or tprops.ifc_class
|
||||
relating_type_id = self.relating_type or tprops.relating_type
|
||||
props = context.scene.BIMModelProperties
|
||||
ifc_class = self.ifc_class or props.ifc_class
|
||||
relating_type_id = self.relating_type or props.relating_type
|
||||
|
||||
if not ifc_class or not relating_type_id:
|
||||
return {"FINISHED"}
|
||||
@@ -118,7 +118,7 @@ class AddTypeInstance(bpy.types.Operator):
|
||||
tool.Ifc,
|
||||
tool.Type,
|
||||
element=tool.Ifc.get_entity(obj),
|
||||
type=tool.Ifc.get().by_id(int(tprops.relating_type)),
|
||||
type=tool.Ifc.get().by_id(int(props.relating_type)),
|
||||
)
|
||||
|
||||
if building_obj:
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.type
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from bpy.types import PropertyGroup
|
||||
@@ -32,21 +33,23 @@ from bpy.props import (
|
||||
CollectionProperty,
|
||||
)
|
||||
|
||||
relating_types_enum = []
|
||||
|
||||
def get_ifc_class(self, context):
|
||||
if not AuthoringData.is_loaded:
|
||||
AuthoringData.load()
|
||||
return AuthoringData.data["ifc_classes"]
|
||||
|
||||
|
||||
def purge():
|
||||
global relating_types_enum
|
||||
relating_types_enum = []
|
||||
def get_relating_type(self, context):
|
||||
if not AuthoringData.is_loaded:
|
||||
AuthoringData.load()
|
||||
return AuthoringData.data["relating_types"]
|
||||
|
||||
|
||||
def getRelatingTypes(self, context):
|
||||
global relating_types_enum
|
||||
if len(relating_types_enum) < 1:
|
||||
elements = IfcStore.get_file().by_type("IfcWallType")
|
||||
relating_types_enum.extend((str(e.id()), e.Name, "") for e in elements)
|
||||
return relating_types_enum
|
||||
def update_ifc_class(self, context):
|
||||
AuthoringData.is_loaded = False
|
||||
|
||||
|
||||
class BIMModelProperties(PropertyGroup):
|
||||
relating_type: EnumProperty(items=getRelatingTypes, name="Relating Type")
|
||||
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="IFC Class", update=update_ifc_class)
|
||||
relating_type: bpy.props.EnumProperty(items=get_relating_type, name="Relating Type")
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import blenderbim.bim.module.type.prop as type_prop
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
|
||||
|
||||
class BIM_PT_authoring(Panel):
|
||||
@@ -33,17 +34,20 @@ class BIM_PT_authoring(Panel):
|
||||
return IfcStore.get_file()
|
||||
|
||||
def draw(self, context):
|
||||
tprops = context.scene.BIMTypeProperties
|
||||
if not AuthoringData.is_loaded:
|
||||
AuthoringData.load()
|
||||
|
||||
props = context.scene.BIMModelProperties
|
||||
col = self.layout.column(align=True)
|
||||
enabled = True
|
||||
|
||||
if type_prop.getIfcTypes(tprops, context):
|
||||
col.prop(tprops, "ifc_class", text="", icon="FILE_VOLUME")
|
||||
if AuthoringData.data["ifc_classes"]:
|
||||
col.prop(props, "ifc_class", text="", icon="FILE_VOLUME")
|
||||
else:
|
||||
col.label(text="No IFC Class", icon="FILE_VOLUME")
|
||||
enabled = False
|
||||
if type_prop.get_relating_type(tprops, context):
|
||||
col.prop(tprops, "relating_type", text="", icon="FILE_3D")
|
||||
if AuthoringData.data["relating_types"]:
|
||||
col.prop(props, "relating_type", text="", icon="FILE_3D")
|
||||
else:
|
||||
col.label(text="No Relating Type", icon="FILE_3D")
|
||||
enabled = False
|
||||
|
||||
@@ -21,6 +21,7 @@ import bpy
|
||||
import blenderbim.bim.module.type.prop as type_prop
|
||||
from bpy.types import WorkSpaceTool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.model.data import WorkspaceData
|
||||
|
||||
|
||||
class BimTool(WorkSpaceTool):
|
||||
@@ -51,17 +52,19 @@ class BimTool(WorkSpaceTool):
|
||||
)
|
||||
|
||||
def draw_settings(context, layout, tool):
|
||||
if not WorkspaceData.is_loaded:
|
||||
WorkspaceData.load()
|
||||
|
||||
row = layout.row(align=True)
|
||||
if not IfcStore.get_file():
|
||||
row.label(text="No IFC Project", icon="ERROR")
|
||||
return
|
||||
props = context.scene.BIMTypeProperties
|
||||
ifc_classes_is_empty = not bool(type_prop.getIfcTypes(props, context))
|
||||
if ifc_classes_is_empty:
|
||||
row.label(text="No IFC Class")
|
||||
else:
|
||||
props = context.scene.BIMModelProperties
|
||||
if WorkspaceData.data["ifc_classes"]:
|
||||
row.prop(props, "ifc_class", text="")
|
||||
if type_prop.get_relating_type(props, context):
|
||||
else:
|
||||
row.label(text="No IFC Class")
|
||||
if WorkspaceData.data["relating_types"]:
|
||||
row.prop(props, "relating_type", text="")
|
||||
else:
|
||||
row.label(text="No Relating Type")
|
||||
@@ -143,8 +146,12 @@ class Hotkey(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
self.props = context.scene.BIMTypeProperties
|
||||
self.ifc_classes_is_empty = not bool(type_prop.getIfcTypes(self.props, context))
|
||||
self.props = context.scene.BIMModelProperties
|
||||
self.ifc_classes_is_empty = True
|
||||
try:
|
||||
self.ifc_classes_is_empty = bool(self.props.ifc_class)
|
||||
except:
|
||||
pass
|
||||
getattr(self, f"hotkey_{self.hotkey}")()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -28,16 +28,13 @@ classes = (
|
||||
operator.SelectTypeObjects,
|
||||
operator.SelectType,
|
||||
prop.BIMTypeProperties,
|
||||
prop.BIMTypeObjectProperties,
|
||||
ui.BIM_PT_type,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMTypeProperties = bpy.props.PointerProperty(type=prop.BIMTypeProperties)
|
||||
bpy.types.Object.BIMTypeProperties = bpy.props.PointerProperty(type=prop.BIMTypeObjectProperties)
|
||||
bpy.types.Object.BIMTypeProperties = bpy.props.PointerProperty(type=prop.BIMTypeProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMTypeProperties
|
||||
del bpy.types.Object.BIMTypeProperties
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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 blenderbim.tool as tool
|
||||
|
||||
|
||||
def refresh():
|
||||
TypeData.is_loaded = False
|
||||
|
||||
|
||||
class TypeData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {
|
||||
"relating_type_classes": cls.relating_type_classes(),
|
||||
"relating_types": cls.relating_types(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def relating_type_classes(cls):
|
||||
results = []
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||
types = ifcopenshell.util.type.get_applicable_types(element.is_a(), schema=tool.Ifc.get_schema())
|
||||
applicable_types_enum.extend((t, t, "") for t in types)
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def relating_types(cls):
|
||||
results = []
|
||||
elements = tool.Ifc.get().by_type(bpy.context.active_object.BIMTypeProperties.relating_type_class)
|
||||
elements = [(str(e.id()), e.Name, "") for e in elements]
|
||||
relating_types_enum.extend(sorted(elements, key=lambda s: s[1]))
|
||||
return results
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.type
|
||||
from blenderbim.bim.module.type.data import TypeData
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from bpy.types import PropertyGroup
|
||||
@@ -32,78 +33,24 @@ from bpy.props import (
|
||||
CollectionProperty,
|
||||
)
|
||||
|
||||
applicable_types_enum = []
|
||||
relating_types_enum = []
|
||||
type_classes_enum = []
|
||||
available_types_enum = []
|
||||
|
||||
|
||||
def purge():
|
||||
global applicable_types_enum
|
||||
global relating_types_enum
|
||||
global type_classes_enum
|
||||
global available_types_enum
|
||||
applicable_types_enum = []
|
||||
relating_types_enum = []
|
||||
type_classes_enum = []
|
||||
available_types_enum = []
|
||||
|
||||
|
||||
def getIfcTypes(self, context):
|
||||
global type_classes_enum
|
||||
file = IfcStore.get_file()
|
||||
if len(type_classes_enum) < 1 and file:
|
||||
classes = set([e.is_a() for e in file.by_type("IfcElementType")])
|
||||
type_classes_enum.extend([(c, c, "") for c in sorted(classes)])
|
||||
return type_classes_enum
|
||||
def get_relating_type_class(self, context):
|
||||
if not TypeData.is_loaded:
|
||||
TypeData.load()
|
||||
return TypeData.data["relating_type_classes"]
|
||||
|
||||
|
||||
def get_relating_type(self, context):
|
||||
global available_types_enum
|
||||
if len(available_types_enum) < 1 and getIfcTypes(self, context):
|
||||
elements = [(str(e.id()), e.Name, "") for e in IfcStore.get_file().by_type(self.ifc_class)]
|
||||
available_types_enum.extend(sorted(elements, key=lambda s: s[1]))
|
||||
return available_types_enum
|
||||
if not TypeData.is_loaded:
|
||||
TypeData.load()
|
||||
return TypeData.data["relating_types"]
|
||||
|
||||
|
||||
def updateTypeInstanceIfcClass(self, context):
|
||||
global type_classes_enum
|
||||
global available_types_enum
|
||||
type_classes_enum.clear()
|
||||
available_types_enum.clear()
|
||||
|
||||
|
||||
def getApplicableTypes(self, context):
|
||||
global applicable_types_enum
|
||||
if len(applicable_types_enum) < 1:
|
||||
element = IfcStore.get_file().by_id(context.active_object.BIMObjectProperties.ifc_definition_id)
|
||||
types = ifcopenshell.util.type.get_applicable_types(element.is_a(), schema=IfcStore.get_file().schema)
|
||||
applicable_types_enum.extend((t, t, "") for t in types)
|
||||
return applicable_types_enum
|
||||
|
||||
|
||||
def get_object_relating_type(self, context):
|
||||
global relating_types_enum
|
||||
if len(relating_types_enum) < 1:
|
||||
elements = IfcStore.get_file().by_type(context.active_object.BIMTypeProperties.relating_type_class)
|
||||
elements = [(str(e.id()), e.Name, "") for e in elements]
|
||||
relating_types_enum.extend(sorted(elements, key=lambda s: s[1]))
|
||||
return relating_types_enum
|
||||
|
||||
|
||||
def updateTypeDropdowns(self, context):
|
||||
global applicable_types_enum
|
||||
global relating_types_enum
|
||||
applicable_types_enum.clear()
|
||||
relating_types_enum.clear()
|
||||
def update_is_editing_type(self, context):
|
||||
TypeData.is_loaded = False
|
||||
|
||||
|
||||
class BIMTypeProperties(PropertyGroup):
|
||||
ifc_class: bpy.props.EnumProperty(items=getIfcTypes, name="IFC Class", update=updateTypeInstanceIfcClass)
|
||||
relating_type: bpy.props.EnumProperty(items=get_relating_type, name="Relating Type")
|
||||
|
||||
|
||||
class BIMTypeObjectProperties(PropertyGroup):
|
||||
is_editing_type: BoolProperty(name="Is Editing Type", update=updateTypeDropdowns)
|
||||
relating_type_class: EnumProperty(items=getApplicableTypes, name="Relating Type Class")
|
||||
relating_type: EnumProperty(items=get_object_relating_type, name="Relating Type")
|
||||
is_editing_type: BoolProperty(name="Is Editing Type", update=update_is_editing_type)
|
||||
relating_type_class: EnumProperty(items=get_relating_type_class, name="Relating Type Class")
|
||||
relating_type: EnumProperty(items=get_relating_type, name="Relating Type")
|
||||
|
||||
@@ -275,9 +275,9 @@ Scenario: Override duplicate move - copying a type instance with a representatio
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I set "scene.BIMTypeProperties.ifc_class" to "IfcWallType"
|
||||
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
|
||||
And the variable "cube" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I set "scene.BIMTypeProperties.relating_type" to "{cube}"
|
||||
And I set "scene.BIMModelProperties.relating_type" to "{cube}"
|
||||
And I press "bim.add_type_instance"
|
||||
And the object "IfcWall/Instance" is selected
|
||||
When I press "object.duplicate_move"
|
||||
|
||||
@@ -8,9 +8,9 @@ Scenario: Add type instance - add from a mesh
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I set "scene.BIMTypeProperties.ifc_class" to "IfcWallType"
|
||||
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
|
||||
And the variable "cube" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I set "scene.BIMTypeProperties.relating_type" to "{cube}"
|
||||
And I set "scene.BIMModelProperties.relating_type" to "{cube}"
|
||||
When I press "bim.add_type_instance"
|
||||
Then the object "IfcWall/Instance" exists
|
||||
|
||||
@@ -21,9 +21,9 @@ Scenario: Add type instance - add from an empty
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I set "scene.BIMTypeProperties.ifc_class" to "IfcWallType"
|
||||
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
|
||||
And the variable "empty" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I set "scene.BIMTypeProperties.relating_type" to "{empty}"
|
||||
And I set "scene.BIMModelProperties.relating_type" to "{empty}"
|
||||
When I press "bim.add_type_instance"
|
||||
Then the object "IfcWall/Instance" exists
|
||||
|
||||
@@ -34,9 +34,9 @@ Scenario: Add type instance - add a mesh where existing instances have changed c
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I set "scene.BIMTypeProperties.ifc_class" to "IfcWallType"
|
||||
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
|
||||
And the variable "cube" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I set "scene.BIMTypeProperties.relating_type" to "{cube}"
|
||||
And I set "scene.BIMModelProperties.relating_type" to "{cube}"
|
||||
And I press "bim.add_type_instance"
|
||||
And the object "IfcWall/Instance" data is a "Tessellation" representation of "Model/Body/MODEL_VIEW"
|
||||
And the object "IfcWall/Instance" is selected
|
||||
|
||||
Reference in New Issue
Block a user