mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Add support for null attributes for people, roles, and addresses. New prototoype testable architecture. See #1711.
This commit is contained in:
@@ -436,6 +436,7 @@ endif
|
||||
.PHONY: test
|
||||
test:
|
||||
make test-core
|
||||
make test-tool
|
||||
make test-bim
|
||||
|
||||
.PHONY: test-core
|
||||
@@ -446,6 +447,10 @@ test-core:
|
||||
test-bim:
|
||||
pytest test/bim
|
||||
|
||||
.PHONY: test-tool
|
||||
test-tool:
|
||||
pytest test/tool
|
||||
|
||||
.PHONY: qa
|
||||
qa:
|
||||
black .
|
||||
|
||||
@@ -26,6 +26,8 @@ classes = (
|
||||
operator.AddPerson,
|
||||
operator.EditPerson,
|
||||
operator.RemovePerson,
|
||||
operator.AddPersonAttribute,
|
||||
operator.RemovePersonAttribute,
|
||||
operator.EnableEditingOrganisation,
|
||||
operator.DisableEditingOrganisation,
|
||||
operator.AddOrganisation,
|
||||
@@ -39,10 +41,10 @@ classes = (
|
||||
operator.EnableEditingAddress,
|
||||
operator.DisableEditingAddress,
|
||||
operator.AddAddress,
|
||||
operator.AddAddressAttribute,
|
||||
operator.RemoveAddressAttribute,
|
||||
operator.EditAddress,
|
||||
operator.RemoveAddress,
|
||||
prop.Role,
|
||||
prop.Address,
|
||||
prop.Person,
|
||||
prop.Organisation,
|
||||
prop.BIMOwnerProperties,
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# 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
|
||||
|
||||
|
||||
class PeopleData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"people": cls.get_people()}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def get_people(cls):
|
||||
people = []
|
||||
for person in tool.Ifc().get().by_type("IfcPerson"):
|
||||
people.append(
|
||||
{
|
||||
"id": person.id(),
|
||||
"props": bpy.context.scene.BIMOwnerProperties.person_attributes,
|
||||
"name": cls.get_person_name(person),
|
||||
"is_editing": cls.get_person_is_editing(person),
|
||||
"is_engaged": bool(person.EngagedIn),
|
||||
"list_attributes": cls.get_person_list_attributes(person),
|
||||
"roles": cls.get_person_roles(person),
|
||||
"addresses": cls.get_person_addresses(person),
|
||||
}
|
||||
)
|
||||
return people
|
||||
|
||||
@classmethod
|
||||
def get_person_name(cls, person):
|
||||
if tool.Ifc().get_schema() == "IFC2X3":
|
||||
name = person.Id
|
||||
else:
|
||||
name = person.Identification
|
||||
name = name or "*"
|
||||
if person.GivenName or person.FamilyName:
|
||||
full_name = "{} {}".format(person.GivenName or "", person.FamilyName or "").strip()
|
||||
name += f" ({full_name})"
|
||||
return name
|
||||
|
||||
@classmethod
|
||||
def get_person_is_editing(cls, person):
|
||||
return bpy.context.scene.BIMOwnerProperties.active_person_id == person.id()
|
||||
|
||||
@classmethod
|
||||
def get_person_list_attributes(cls, person):
|
||||
results = []
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
for name in ["MiddleNames", "PrefixTitles", "SuffixTitles"]:
|
||||
if name == "MiddleNames":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.middle_names)]
|
||||
elif name == "PrefixTitles":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.prefix_titles)]
|
||||
elif name == "SuffixTitles":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.suffix_titles)]
|
||||
results.append({"name": name, "items": items})
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def get_person_roles(cls, person):
|
||||
results = []
|
||||
for role in person.Roles or []:
|
||||
results.append(
|
||||
{
|
||||
"id": role.id(),
|
||||
"is_editing": bpy.context.scene.BIMOwnerProperties.active_role_id == role.id(),
|
||||
"label": role.UserDefinedRole or role.Role,
|
||||
"props": bpy.context.scene.BIMOwnerProperties.role_attributes,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def get_person_addresses(cls, person):
|
||||
results = []
|
||||
for address in person.Addresses or []:
|
||||
results.append(
|
||||
{
|
||||
"id": address.id(),
|
||||
"is_editing": bpy.context.scene.BIMOwnerProperties.active_address_id == address.id(),
|
||||
"label": address.is_a(),
|
||||
"props": bpy.context.scene.BIMOwnerProperties.address_attributes,
|
||||
"list_attributes": cls.get_address_list_attributes(address),
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def get_address_list_attributes(cls, address):
|
||||
results = []
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
if address.is_a("IfcPostalAddress"):
|
||||
names = ["AddressLines"]
|
||||
elif address.is_a("IfcTelecomAddress"):
|
||||
names = ["TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs"]
|
||||
for name in names:
|
||||
if name == "AddressLines":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.address_lines)]
|
||||
elif name == "TelephoneNumbers":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.telephone_numbers)]
|
||||
elif name == "FacsimileNumbers":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.facsimile_numbers)]
|
||||
elif name == "ElectronicMailAddresses":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.electronic_mail_addresses)]
|
||||
elif name == "MessagingIDs":
|
||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.messaging_ids)]
|
||||
results.append({"name": name, "items": items})
|
||||
return results
|
||||
@@ -18,10 +18,21 @@
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.api
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.owner as core
|
||||
import blenderbim.bim.module.owner.data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from ifcopenshell.api.owner.data import Data
|
||||
|
||||
|
||||
# TODO: Just testing
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.module.owner.data.PeopleData.is_loaded = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def flatten_collection(collection):
|
||||
return [v.name for v in collection] if collection else None
|
||||
|
||||
@@ -59,317 +70,190 @@ class AddOrRemoveElementFromCollection(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingPerson(bpy.types.Operator):
|
||||
class EnableEditingPerson(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.enable_editing_person"
|
||||
bl_label = "Enable Editing Person"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
person_id: bpy.props.IntProperty()
|
||||
person: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
props.active_person_id = self.person_id
|
||||
data = Data.people[self.person_id]
|
||||
name = data["Id"] if self.file.schema == "IFC2X3" else data["Identification"]
|
||||
person = props.person
|
||||
person.name = name or ""
|
||||
person.family_name = data["FamilyName"] or ""
|
||||
person.given_name = data["GivenName"] or ""
|
||||
populate_collection(person.middle_names, data.get("MiddleNames", None))
|
||||
populate_collection(person.prefix_titles, data.get("PrefixTitles", None))
|
||||
populate_collection(person.suffix_titles, data.get("SuffixTitles", None))
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.enable_editing_person(tool.PersonEditor(), person=tool.Ifc().get().by_id(self.person))
|
||||
|
||||
|
||||
class DisableEditingPerson(bpy.types.Operator):
|
||||
class DisableEditingPerson(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.disable_editing_person"
|
||||
bl_label = "Disable Editing Person"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMOwnerProperties.active_person_id = 0
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.disable_editing_person(tool.PersonEditor())
|
||||
|
||||
|
||||
class AddPerson(bpy.types.Operator):
|
||||
class AddPerson(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_person"
|
||||
bl_label = "Add Person"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
ifcopenshell.api.run("owner.add_person", IfcStore.get_file())
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.add_person(tool.Ifc())
|
||||
|
||||
|
||||
class EditPerson(bpy.types.Operator):
|
||||
class EditPerson(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.edit_person"
|
||||
bl_label = "Edit Person"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
person = props.person
|
||||
attributes = {
|
||||
"Identification": person.name or None,
|
||||
"FamilyName": person.family_name or None,
|
||||
"GivenName": person.given_name or None,
|
||||
"MiddleNames": flatten_collection(person.middle_names),
|
||||
"PrefixTitles": flatten_collection(person.prefix_titles),
|
||||
"SuffixTitles": flatten_collection(person.suffix_titles),
|
||||
}
|
||||
if self.file.schema == "IFC2X3":
|
||||
attributes["Id"] = attributes["Identification"]
|
||||
del attributes["Identification"]
|
||||
ifcopenshell.api.run(
|
||||
"owner.edit_person",
|
||||
self.file,
|
||||
**{"person": self.file.by_id(props.active_person_id), "attributes": attributes}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
bpy.ops.bim.disable_editing_person()
|
||||
return {"FINISHED"}
|
||||
core.edit_person(tool.Ifc(), tool.PersonEditor())
|
||||
|
||||
|
||||
class RemovePerson(bpy.types.Operator):
|
||||
class RemovePerson(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_person"
|
||||
bl_label = "Remove Person"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
person_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
person: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run("owner.remove_person", self.file, **{"person": self.file.by_id(self.person_id)})
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.remove_person(tool.Ifc(), person=tool.Ifc().get().by_id(self.person))
|
||||
|
||||
|
||||
class EnableEditingRole(bpy.types.Operator):
|
||||
class AddPersonAttribute(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_person_attribute"
|
||||
bl_label = "Add Person Attribute"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.add_person_attribute(tool.PersonEditor(), name=self.name)
|
||||
|
||||
|
||||
class RemovePersonAttribute(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_person_attribute"
|
||||
bl_label = "Remove Person Attribute"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
id: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.remove_person_attribute(tool.PersonEditor(), name=self.name, id=self.id)
|
||||
|
||||
|
||||
class EnableEditingRole(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.enable_editing_role"
|
||||
bl_label = "Enable Editing Role"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
role_id: bpy.props.IntProperty()
|
||||
role: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
props.active_role_id = self.role_id
|
||||
data = Data.roles[self.role_id]
|
||||
props.role.name = data["Role"]
|
||||
props.role.user_defined_role = data["UserDefinedRole"] or ""
|
||||
props.role.description = data["Description"] or ""
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.enable_editing_role(tool.RoleEditor(), role=tool.Ifc().get().by_id(self.role))
|
||||
|
||||
|
||||
class DisableEditingRole(bpy.types.Operator):
|
||||
class DisableEditingRole(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.disable_editing_role"
|
||||
bl_label = "Disable Editing Role"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMOwnerProperties.active_role_id = 0
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.disable_editing_role(tool.RoleEditor())
|
||||
|
||||
|
||||
class AddRole(bpy.types.Operator):
|
||||
class AddRole(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_role"
|
||||
bl_label = "Add Role"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
assigned_object_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
parent: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"owner.add_role", self.file, **{"assigned_object": self.file.by_id(self.assigned_object_id)}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.add_role(tool.Ifc(), parent=tool.Ifc().get().by_id(self.parent))
|
||||
|
||||
|
||||
class EditRole(bpy.types.Operator):
|
||||
class EditRole(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.edit_role"
|
||||
bl_label = "Edit Role"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
attributes = {
|
||||
"Role": props.role.name,
|
||||
"UserDefinedRole": props.role.user_defined_role if props.role.name == "USERDEFINED" else None,
|
||||
"Description": props.role.description or None,
|
||||
}
|
||||
ifcopenshell.api.run(
|
||||
"owner.edit_role", self.file, **{"role": self.file.by_id(props.active_role_id), "attributes": attributes}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
bpy.ops.bim.disable_editing_role()
|
||||
return {"FINISHED"}
|
||||
core.edit_role(tool.Ifc(), tool.RoleEditor())
|
||||
|
||||
|
||||
class RemoveRole(bpy.types.Operator):
|
||||
class RemoveRole(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_role"
|
||||
bl_label = "Remove Role"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
role_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
role: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run("owner.remove_role", self.file, **{"role": self.file.by_id(self.role_id)})
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.remove_role(tool.Ifc(), role=tool.Ifc().get().by_id(self.role))
|
||||
|
||||
|
||||
class AddAddress(bpy.types.Operator):
|
||||
class AddAddress(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_address"
|
||||
bl_label = "Add Address"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
assigned_object_id: bpy.props.IntProperty()
|
||||
parent: bpy.props.IntProperty()
|
||||
ifc_class: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
def _execute(self, context):
|
||||
core.add_address(tool.Ifc(), parent=tool.Ifc().get().by_id(self.parent), ifc_class=self.ifc_class)
|
||||
|
||||
|
||||
class AddAddressAttribute(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_address_attribute"
|
||||
bl_label = "Add Address Attribute"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"owner.add_address",
|
||||
self.file,
|
||||
**{"assigned_object": self.file.by_id(self.assigned_object_id), "ifc_class": self.ifc_class}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.add_address_attribute(tool.AddressEditor, name=self.name)
|
||||
|
||||
|
||||
class EnableEditingAddress(bpy.types.Operator):
|
||||
class RemoveAddressAttribute(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_address_attribute"
|
||||
bl_label = "Remove Address Attribute"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
id: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.remove_address_attribute(tool.AddressEditor, name=self.name, id=self.id)
|
||||
|
||||
|
||||
class EnableEditingAddress(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.enable_editing_address"
|
||||
bl_label = "Enable Editing Address"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
address_id: bpy.props.IntProperty()
|
||||
address: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
props.active_address_id = self.address_id
|
||||
data = Data.addresses[self.address_id]
|
||||
address = props.address
|
||||
address.name = data["type"]
|
||||
address.purpose = data["Purpose"] or "None"
|
||||
address.description = data["Description"] or ""
|
||||
address.user_defined_purpose = data["UserDefinedPurpose"] or ""
|
||||
|
||||
if data["type"] == "IfcTelecomAddress":
|
||||
populate_collection(address.telephone_numbers, data.get("TelephoneNumbers", None))
|
||||
populate_collection(address.facsimile_numbers, data.get("FacsimileNumbers", None))
|
||||
address.pager_number = data["PagerNumber"] or ""
|
||||
populate_collection(address.electronic_mail_addresses, data.get("ElectronicMailAddresses", None))
|
||||
address.www_home_page_url = data["WWWHomePageURL"] or ""
|
||||
if self.file.schema != "IFC2X3":
|
||||
populate_collection(address.messaging_ids, data.get("MessagingIDs", None))
|
||||
elif data["type"] == "IfcPostalAddress":
|
||||
address.internal_location = data["InternalLocation"] or ""
|
||||
populate_collection(address.address_lines, data.get("AddressLines", None))
|
||||
address.postal_box = data["PostalBox"] or ""
|
||||
address.town = data["Town"] or ""
|
||||
address.region = data["Region"] or ""
|
||||
address.postal_code = data["PostalCode"] or ""
|
||||
address.country = data["Country"] or ""
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.enable_editing_address(tool.AddressEditor(), address=tool.Ifc().get().by_id(self.address))
|
||||
|
||||
|
||||
class DisableEditingAddress(bpy.types.Operator):
|
||||
class DisableEditingAddress(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.disable_editing_address"
|
||||
bl_label = "Disable Editing Address"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMOwnerProperties.active_address_id = 0
|
||||
return {"FINISHED"}
|
||||
def _execute(self, context):
|
||||
core.disable_editing_address(tool.AddressEditor())
|
||||
|
||||
|
||||
class EditAddress(bpy.types.Operator):
|
||||
class EditAddress(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.edit_address"
|
||||
bl_label = "Edit Address"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMOwnerProperties
|
||||
attributes = {
|
||||
"Purpose": props.address.purpose,
|
||||
"UserDefinedPurpose": props.address.user_defined_purpose
|
||||
if props.address.purpose == "USERDEFINED"
|
||||
else None,
|
||||
"Description": props.address.description or None,
|
||||
}
|
||||
address = self.file.by_id(props.active_address_id)
|
||||
if address.is_a("IfcTelecomAddress"):
|
||||
attributes.update(
|
||||
{
|
||||
"TelephoneNumbers": flatten_collection(props.address.telephone_numbers),
|
||||
"FacsimileNumbers": flatten_collection(props.address.facsimile_numbers),
|
||||
"PagerNumber": props.address.pager_number or None,
|
||||
"ElectronicMailAddresses": flatten_collection(props.address.electronic_mail_addresses),
|
||||
"WWWHomePageURL": props.address.www_home_page_url or None,
|
||||
"MessagingIDs": flatten_collection(props.address.messaging_ids),
|
||||
}
|
||||
)
|
||||
if self.file.schema == "IFC2X3":
|
||||
del attributes["MessagingIDs"]
|
||||
elif address.is_a("IfcPostalAddress"):
|
||||
attributes.update(
|
||||
{
|
||||
"InternalLocation": props.address.internal_location or None,
|
||||
"AddressLines": flatten_collection(props.address.address_lines),
|
||||
"PostalBox": props.address.postal_box or None,
|
||||
"Town": props.address.town or None,
|
||||
"Region": props.address.region or None,
|
||||
"PostalCode": props.address.postal_code or None,
|
||||
"Country": props.address.country or None,
|
||||
}
|
||||
)
|
||||
ifcopenshell.api.run("owner.edit_address", self.file, **{"address": address, "attributes": attributes})
|
||||
Data.load(IfcStore.get_file())
|
||||
bpy.ops.bim.disable_editing_address()
|
||||
return {"FINISHED"}
|
||||
core.edit_address(tool.Ifc, tool.AddressEditor)
|
||||
|
||||
|
||||
class RemoveAddress(bpy.types.Operator):
|
||||
class RemoveAddress(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_address"
|
||||
bl_label = "Remove Address"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
address_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
address: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run("owner.remove_address", self.file, **{"address": self.file.by_id(self.address_id)})
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
core.remove_address(tool.Ifc(), address=tool.Ifc().get().by_id(self.address))
|
||||
|
||||
|
||||
class EnableEditingOrganisation(bpy.types.Operator):
|
||||
|
||||
@@ -67,71 +67,6 @@ def getOrganisations(self, context):
|
||||
return _organisations_enum
|
||||
|
||||
|
||||
class Address(PropertyGroup):
|
||||
name: StringProperty(name="Name", default="IfcPostalAddress") # Stores IfcPostalAddress or IfcTelecomAddress
|
||||
purpose: EnumProperty(
|
||||
items=[
|
||||
("None", "None", ""),
|
||||
("OFFICE", "OFFICE", "An office address."),
|
||||
("SITE", "SITE", "A site address."),
|
||||
("HOME", "HOME", "A home address."),
|
||||
("DISTRIBUTIONPOINT", "DISTRIBUTIONPOINT", "A postal distribution point address."),
|
||||
("USERDEFINED", "USERDEFINED", "A user defined address type to be provided."),
|
||||
],
|
||||
name="Purpose",
|
||||
)
|
||||
description: StringProperty(name="Description")
|
||||
user_defined_purpose: StringProperty(name="Custom Purpose")
|
||||
|
||||
internal_location: StringProperty(name="Internal Location")
|
||||
address_lines: CollectionProperty(type=StrProperty, name="Address")
|
||||
postal_box: StringProperty(name="Postal Box")
|
||||
town: StringProperty(name="Town")
|
||||
region: StringProperty(name="Region")
|
||||
postal_code: StringProperty(name="Postal Code")
|
||||
country: StringProperty(name="Country")
|
||||
|
||||
telephone_numbers: CollectionProperty(type=StrProperty, name="Telephone Numbers")
|
||||
facsimile_numbers: CollectionProperty(type=StrProperty, name="Facsimile Numbers")
|
||||
pager_number: StringProperty(name="Pager Number")
|
||||
electronic_mail_addresses: CollectionProperty(type=StrProperty, name="Emails")
|
||||
www_home_page_url: StringProperty(name="Website")
|
||||
messaging_ids: CollectionProperty(type=StrProperty, name="IMs")
|
||||
|
||||
|
||||
class Role(PropertyGroup):
|
||||
name: EnumProperty(
|
||||
items=[
|
||||
("SUPPLIER", "SUPPLIER", ""),
|
||||
("MANUFACTURER", "MANUFACTURER", ""),
|
||||
("CONTRACTOR", "CONTRACTOR", ""),
|
||||
("SUBCONTRACTOR", "SUBCONTRACTOR", ""),
|
||||
("ARCHITECT", "ARCHITECT", ""),
|
||||
("STRUCTURALENGINEER", "STRUCTURALENGINEER", ""),
|
||||
("COSTENGINEER", "COSTENGINEER", ""),
|
||||
("CLIENT", "CLIENT", ""),
|
||||
("BUILDINGOWNER", "BUILDINGOWNER", ""),
|
||||
("BUILDINGOPERATOR", "BUILDINGOPERATOR", ""),
|
||||
("MECHANICALENGINEER", "MECHANICALENGINEER", ""),
|
||||
("ELECTRICALENGINEER", "ELECTRICALENGINEER", ""),
|
||||
("PROJECTMANAGER", "PROJECTMANAGER", ""),
|
||||
("FACILITIESMANAGER", "FACILITIESMANAGER", ""),
|
||||
("CIVILENGINEER", "CIVILENGINEER", ""),
|
||||
("COMMISSIONINGENGINEER", "COMMISSIONINGENGINEER", ""),
|
||||
("ENGINEER", "ENGINEER", ""),
|
||||
("OWNER", "OWNER", ""),
|
||||
("CONSULTANT", "CONSULTANT", ""),
|
||||
("CONSTRUCTIONMANAGER", "CONSTRUCTIONMANAGER", ""),
|
||||
("FIELDCONSTRUCTIONMANAGER", "FIELDCONSTRUCTIONMANAGER", ""),
|
||||
("RESELLER", "RESELLER", ""),
|
||||
("USERDEFINED", "USERDEFINED", ""),
|
||||
],
|
||||
name="Name",
|
||||
)
|
||||
user_defined_role: StringProperty(name="Custom Role")
|
||||
description: StringProperty(name="Description")
|
||||
|
||||
|
||||
class Organisation(PropertyGroup):
|
||||
identification: StringProperty(name="Identification")
|
||||
name: StringProperty(name="Name")
|
||||
@@ -149,12 +84,21 @@ class Person(PropertyGroup):
|
||||
|
||||
class BIMOwnerProperties(PropertyGroup):
|
||||
person: PointerProperty(type=Person)
|
||||
person_attributes: CollectionProperty(name="Person Attributes", type=Attribute)
|
||||
middle_names: CollectionProperty(type=StrProperty, name="Middle Names")
|
||||
prefix_titles: CollectionProperty(type=StrProperty, name="Prefixes")
|
||||
suffix_titles: CollectionProperty(type=StrProperty, name="Suffixes")
|
||||
active_person_id: IntProperty(name="Active Person Id")
|
||||
organisation: PointerProperty(type=Organisation)
|
||||
active_organisation_id: IntProperty(name="Active Organisation Id")
|
||||
role: PointerProperty(type=Role)
|
||||
active_role_id: IntProperty(name="Active Role Id")
|
||||
address: PointerProperty(type=Address)
|
||||
role_attributes: CollectionProperty(name="Role Attributes", type=Attribute)
|
||||
active_address_id: IntProperty(name="Active Address Id")
|
||||
address_attributes: CollectionProperty(name="Address Attributes", type=Attribute)
|
||||
address_lines: CollectionProperty(type=StrProperty, name="Address")
|
||||
telephone_numbers: CollectionProperty(type=StrProperty, name="Telephone Numbers")
|
||||
facsimile_numbers: CollectionProperty(type=StrProperty, name="Facsimile Numbers")
|
||||
electronic_mail_addresses: CollectionProperty(type=StrProperty, name="Emails")
|
||||
messaging_ids: CollectionProperty(type=StrProperty, name="IMs")
|
||||
user_person: EnumProperty(items=getPersons, name="Person")
|
||||
user_organisation: EnumProperty(items=getOrganisations, name="Organisation")
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.module.owner.data import PeopleData
|
||||
from bpy.types import Panel
|
||||
from ifcopenshell.api.owner.data import Data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from .operator import AddOrRemoveElementFromCollection
|
||||
|
||||
|
||||
def draw_string_collection(layout, owner, collection_name):
|
||||
@@ -31,12 +33,12 @@ def draw_string_collection(layout, owner, collection_name):
|
||||
row = draw_prop_on_new_row(
|
||||
column, collection[i], "name", align=True, text=f"{owner.bl_rna.properties[collection_name].name}"
|
||||
)
|
||||
add_op = row.operator(AddOrRemoveElementFromCollection.bl_idname, icon="ADD", text="")
|
||||
add_op = row.operator("bim.add_or_remove_element_from_collection", icon="ADD", text="")
|
||||
add_op.operation = "+"
|
||||
add_op.collection_path = collection.path_from_id()
|
||||
else:
|
||||
row = draw_prop_on_new_row(column, collection[i], "name", align=True, text=f"#{i + 1}")
|
||||
rem_op = row.operator(AddOrRemoveElementFromCollection.bl_idname, icon="REMOVE", text="")
|
||||
rem_op = row.operator("bim.add_or_remove_element_from_collection", icon="REMOVE", text="")
|
||||
rem_op.operation = "-"
|
||||
rem_op.collection_path = collection.path_from_id()
|
||||
rem_op.selected_item_idx = i
|
||||
@@ -116,7 +118,7 @@ def draw_addresses_ui(box, assigned_object_id, addresses, file, context):
|
||||
row.operator("bim.remove_address", icon="X", text="").address_id = address_id
|
||||
|
||||
|
||||
class BIM_PT_people(Panel):
|
||||
class BIM_PT_people(bpy.types.Panel):
|
||||
bl_label = "IFC People"
|
||||
bl_idname = "BIM_PT_people"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
@@ -126,47 +128,102 @@ class BIM_PT_people(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file()
|
||||
return tool.Ifc().get()
|
||||
|
||||
def draw(self, context):
|
||||
if not Data.is_loaded:
|
||||
Data.load(IfcStore.get_file())
|
||||
if not PeopleData.is_loaded:
|
||||
PeopleData.load()
|
||||
|
||||
self.file = IfcStore.get_file()
|
||||
self.layout.use_property_split = True
|
||||
self.layout.use_property_decorate = False
|
||||
props = context.scene.BIMOwnerProperties
|
||||
|
||||
row = self.layout.row()
|
||||
row.operator("bim.add_person", icon="ADD")
|
||||
|
||||
for person_id, person in Data.people.items():
|
||||
if props.active_person_id == person_id:
|
||||
blender_person = props.person
|
||||
box = self.layout.box()
|
||||
row = draw_prop_on_new_row(box, blender_person, "name", align=True, icon="USER", text="")
|
||||
row.operator("bim.edit_person", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_person", icon="CANCEL", text="")
|
||||
draw_prop_on_new_row(box, blender_person, "family_name")
|
||||
draw_prop_on_new_row(box, blender_person, "given_name")
|
||||
draw_string_collection(box, blender_person, "middle_names")
|
||||
draw_string_collection(box, blender_person, "prefix_titles")
|
||||
draw_string_collection(box, blender_person, "suffix_titles")
|
||||
draw_roles_ui(box, person_id, person["Roles"], context)
|
||||
draw_addresses_ui(box, person_id, person["Addresses"], self.file, context)
|
||||
for person in PeopleData.data["people"]:
|
||||
self.draw_person(person)
|
||||
|
||||
def draw_person(self, person):
|
||||
if person["is_editing"]:
|
||||
box = self.layout.box()
|
||||
row = box.row(align=True)
|
||||
row.operator("bim.edit_person", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_person", icon="CANCEL", text="")
|
||||
blenderbim.bim.helper.draw_attributes(person["props"], box)
|
||||
|
||||
for attribute in person["list_attributes"]:
|
||||
row = box.row(align=True)
|
||||
row.label(text=attribute["name"])
|
||||
op = row.operator("bim.add_person_attribute", icon="ADD", text="")
|
||||
op.name = attribute["name"]
|
||||
|
||||
for item in attribute["items"]:
|
||||
row = box.row(align=True)
|
||||
row.prop(item["prop"], "name", text="")
|
||||
op = row.operator("bim.remove_person_attribute", icon="REMOVE", text="")
|
||||
op.name = attribute["name"]
|
||||
op.id = item["id"]
|
||||
|
||||
self.draw_roles(box, person)
|
||||
self.draw_addresses(box, person)
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=person["name"])
|
||||
row.operator("bim.enable_editing_person", icon="GREASEPENCIL", text="").person = person["id"]
|
||||
if not person["is_engaged"]:
|
||||
row.operator("bim.remove_person", icon="X", text="").person = person["id"]
|
||||
|
||||
def draw_roles(self, box, person):
|
||||
row = box.row(align=True)
|
||||
row.label(text="Roles")
|
||||
op = row.operator("bim.add_role", icon="ADD", text="")
|
||||
op.parent = person["id"]
|
||||
|
||||
for role in person["roles"]:
|
||||
if role["is_editing"]:
|
||||
row = box.row(align=True)
|
||||
row.operator("bim.edit_role", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_role", icon="CANCEL", text="")
|
||||
blenderbim.bim.helper.draw_attributes(role["props"], box)
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
name = person["Id"] if self.file.schema == "IFC2X3" else person["Identification"]
|
||||
name = name or "*"
|
||||
if person["GivenName"] or person["FamilyName"]:
|
||||
full_name = "{} {}".format(person["GivenName"] or "", person["FamilyName"] or "").strip()
|
||||
name += f" ({full_name})"
|
||||
row.label(text=name)
|
||||
if person["Roles"]:
|
||||
row.label(text=", ".join([Data.roles[r]["Role"] for r in person["Roles"]]))
|
||||
row.operator("bim.enable_editing_person", icon="GREASEPENCIL", text="").person_id = person_id
|
||||
if not person["is_engaged"]:
|
||||
row.operator("bim.remove_person", icon="X", text="").person_id = person_id
|
||||
row = box.row(align=True)
|
||||
row.label(text=role["label"])
|
||||
row.operator("bim.enable_editing_role", icon="GREASEPENCIL", text="").role = role["id"]
|
||||
row.operator("bim.remove_role", icon="X", text="").role = role["id"]
|
||||
|
||||
def draw_addresses(self, box, person):
|
||||
row = box.row(align=True)
|
||||
row.label(text="Addresses")
|
||||
op = row.operator("bim.add_address", icon="LINK_BLEND", text="")
|
||||
op.parent = person["id"]
|
||||
op.ifc_class = "IfcTelecomAddress"
|
||||
op = row.operator("bim.add_address", icon="APPEND_BLEND", text="")
|
||||
op.parent = person["id"]
|
||||
op.ifc_class = "IfcPostalAddress"
|
||||
|
||||
for address in person["addresses"]:
|
||||
if address["is_editing"]:
|
||||
row = box.row(align=True)
|
||||
row.operator("bim.edit_address", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_address", icon="CANCEL", text="")
|
||||
blenderbim.bim.helper.draw_attributes(address["props"], box)
|
||||
for attribute in address["list_attributes"]:
|
||||
row = box.row(align=True)
|
||||
row.label(text=attribute["name"])
|
||||
op = row.operator("bim.add_address_attribute", icon="ADD", text="")
|
||||
op.name = attribute["name"]
|
||||
|
||||
for item in attribute["items"]:
|
||||
row = box.row(align=True)
|
||||
row.prop(item["prop"], "name", text="")
|
||||
op = row.operator("bim.remove_address_attribute", icon="REMOVE", text="")
|
||||
op.name = attribute["name"]
|
||||
op.id = item["id"]
|
||||
else:
|
||||
row = box.row(align=True)
|
||||
row.label(text=address["label"])
|
||||
row.operator("bim.enable_editing_address", icon="GREASEPENCIL", text="").address = address["id"]
|
||||
row.operator("bim.remove_address", icon="X", text="").address = address["id"]
|
||||
|
||||
|
||||
class BIM_PT_organisations(Panel):
|
||||
|
||||
@@ -21,11 +21,7 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import blenderbim.bim.schema
|
||||
import blenderbim.bim.handler
|
||||
from blenderbim.bim.module.pset_template.prop import (
|
||||
updatePsetTemplateFiles,
|
||||
updatePsetTemplates,
|
||||
getPsetTemplates
|
||||
)
|
||||
from blenderbim.bim.module.pset_template.prop import updatePsetTemplateFiles, updatePsetTemplates, getPsetTemplates
|
||||
from ifcopenshell.api.pset_template.data import Data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# 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/>.
|
||||
|
||||
|
||||
def add_person(ifc):
|
||||
return ifc.run("owner.add_person")
|
||||
|
||||
|
||||
def remove_person(ifc, person=None):
|
||||
ifc.run("owner.remove_person", person=person)
|
||||
|
||||
|
||||
def enable_editing_person(person_editor, person=None):
|
||||
person_editor.set_person(person)
|
||||
person_editor.import_attributes()
|
||||
|
||||
|
||||
def disable_editing_person(person_editor):
|
||||
person_editor.clear_person()
|
||||
|
||||
|
||||
def edit_person(ifc, person_editor):
|
||||
ifc.run("owner.edit_person", person=person_editor.get_person(), attributes=person_editor.export_attributes())
|
||||
disable_editing_person(person_editor)
|
||||
|
||||
|
||||
def add_person_attribute(person_editor, name=None):
|
||||
person_editor.add_attribute(name)
|
||||
|
||||
|
||||
def remove_person_attribute(person_editor, name=None, id=None):
|
||||
person_editor.remove_attribute(name, id)
|
||||
|
||||
|
||||
def add_role(ifc, parent=None):
|
||||
return ifc.run("owner.add_role", assigned_object=parent)
|
||||
|
||||
|
||||
def remove_role(ifc, role=None):
|
||||
ifc.run("owner.remove_role", role=role)
|
||||
|
||||
|
||||
def enable_editing_role(role_editor, role=None):
|
||||
role_editor.set_role(role)
|
||||
role_editor.import_attributes()
|
||||
|
||||
|
||||
def disable_editing_role(role_editor):
|
||||
role_editor.clear_role()
|
||||
|
||||
|
||||
def edit_role(ifc, role_editor):
|
||||
ifc.run("owner.edit_role", role=role_editor.get_role(), attributes=role_editor.export_attributes())
|
||||
role_editor.clear_role()
|
||||
|
||||
|
||||
def add_address(ifc, parent=None, ifc_class="IfcPostalAddress"):
|
||||
return ifc.run("owner.add_address", assigned_object=parent, ifc_class=ifc_class)
|
||||
|
||||
|
||||
def remove_address(ifc, address=None):
|
||||
ifc.run("owner.remove_address", address=address)
|
||||
|
||||
|
||||
def enable_editing_address(address_editor, address=None):
|
||||
address_editor.set_address(address)
|
||||
address_editor.import_attributes()
|
||||
|
||||
|
||||
def disable_editing_address(address_editor):
|
||||
address_editor.clear_address()
|
||||
|
||||
|
||||
def edit_address(ifc, address_editor):
|
||||
address = address_editor.get_address()
|
||||
ifc.run("owner.edit_address", address=address, attributes=address_editor.export_attributes())
|
||||
address_editor.clear_address()
|
||||
|
||||
|
||||
def add_address_attribute(address_editor, name=None):
|
||||
address_editor.add_attribute(name)
|
||||
|
||||
|
||||
def remove_address_attribute(address_editor, name=None, id=None):
|
||||
address_editor.remove_attribute(name, id)
|
||||
@@ -0,0 +1,23 @@
|
||||
# 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/>.
|
||||
|
||||
from blenderbim.core.tool.ifc import Ifc
|
||||
from blenderbim.core.tool.blender import Blender
|
||||
from blenderbim.core.tool.person_editor import PersonEditor
|
||||
from blenderbim.core.tool.role_editor import RoleEditor
|
||||
from blenderbim.core.tool.address_editor import AddressEditor
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 abc
|
||||
|
||||
|
||||
class AddressEditor(abc.ABC):
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def set_address(cls, address):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def import_attributes(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def clear_address(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def get_address(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def export_attributes(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def add_attribute(cls, name):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def remove_attribute(cls, name, id):
|
||||
pass
|
||||
@@ -0,0 +1,23 @@
|
||||
# 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 abc
|
||||
|
||||
|
||||
class Blender(abc.ABC):
|
||||
pass
|
||||
@@ -16,15 +16,11 @@
|
||||
# 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 abc
|
||||
|
||||
class Ifc:
|
||||
|
||||
class Ifc(abc.ABC):
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def run(cls, command, **kwargs):
|
||||
"""Runs an operation on the active IFC dataset"""
|
||||
pass
|
||||
|
||||
|
||||
class Blender:
|
||||
@classmethod
|
||||
def get_ifc(cls):
|
||||
pass
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 abc
|
||||
|
||||
|
||||
class PersonEditor(abc.ABC):
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def set_person(cls, person):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def import_attributes(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def clear_person(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def export_attributes(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def get_person(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def add_attribute(cls, name):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def remove_attribute(cls, name, id):
|
||||
pass
|
||||
@@ -0,0 +1,46 @@
|
||||
# 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 abc
|
||||
|
||||
|
||||
class RoleEditor(abc.ABC):
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def set_role(cls, role):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def import_attributes(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def clear_role(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def get_role(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def export_attributes(cls):
|
||||
pass
|
||||
@@ -0,0 +1,23 @@
|
||||
# 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/>.
|
||||
|
||||
from blenderbim.tool.ifc import Ifc
|
||||
from blenderbim.tool.blender import Blender
|
||||
from blenderbim.tool.person_editor import PersonEditor
|
||||
from blenderbim.tool.role_editor import RoleEditor
|
||||
from blenderbim.tool.address_editor import AddressEditor
|
||||
@@ -0,0 +1,108 @@
|
||||
# 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.core.tool
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
class AddressEditor(blenderbim.core.tool.AddressEditor):
|
||||
@classmethod
|
||||
def set_address(cls, address):
|
||||
bpy.context.scene.BIMOwnerProperties.active_address_id = address.id()
|
||||
|
||||
@classmethod
|
||||
def import_attributes(cls):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
props.address_attributes.clear()
|
||||
props.address_lines.clear()
|
||||
props.telephone_numbers.clear()
|
||||
props.facsimile_numbers.clear()
|
||||
props.electronic_mail_addresses.clear()
|
||||
props.messaging_ids.clear()
|
||||
|
||||
address = cls.get_address()
|
||||
|
||||
def callback(name, prop, data):
|
||||
if name == "AddressLines":
|
||||
for line in data[name] or []:
|
||||
props.address_lines.add().name = line
|
||||
elif name == "TelephoneNumbers":
|
||||
for line in data[name] or []:
|
||||
props.telephone_numbers.add().name = line
|
||||
elif name == "FacsimileNumbers":
|
||||
for line in data[name] or []:
|
||||
props.facsimile_numbers.add().name = line
|
||||
elif name == "ElectronicMailAddresses":
|
||||
for line in data[name] or []:
|
||||
props.electronic_mail_addresses.add().name = line
|
||||
elif name == "MessagingIDs":
|
||||
for line in data[name] or []:
|
||||
props.messaging_ids.add().name = line
|
||||
|
||||
blenderbim.bim.helper.import_attributes(address.is_a(), props.address_attributes, address.get_info(), callback)
|
||||
|
||||
@classmethod
|
||||
def clear_address(cls):
|
||||
bpy.context.scene.BIMOwnerProperties.active_address_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_address(cls):
|
||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_address_id)
|
||||
|
||||
@classmethod
|
||||
def export_attributes(cls):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.address_attributes)
|
||||
if cls.get_address().is_a("IfcPostalAddress"):
|
||||
attributes["AddressLines"] = [l.name for l in props.address_lines] or None
|
||||
elif cls.get_address().is_a("IfcTelecomAddress"):
|
||||
attributes["TelephoneNumbers"] = [l.name for l in props.telephone_numbers] or None
|
||||
attributes["FacsimileNumbers"] = [l.name for l in props.facsimile_numbers] or None
|
||||
attributes["ElectronicMailAddresses"] = [l.name for l in props.electronic_mail_addresses] or None
|
||||
attributes["MessagingIDs"] = [l.name for l in props.messaging_ids] or None
|
||||
return attributes
|
||||
|
||||
@classmethod
|
||||
def add_attribute(cls, name):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
if name == "AddressLines":
|
||||
props.address_lines.add()
|
||||
elif name == "TelephoneNumbers":
|
||||
props.telephone_numbers.add()
|
||||
elif name == "FacsimileNumbers":
|
||||
props.facsimile_numbers.add()
|
||||
elif name == "ElectronicMailAddresses":
|
||||
props.electronic_mail_addresses.add()
|
||||
elif name == "MessagingIDs":
|
||||
props.messaging_ids.add()
|
||||
|
||||
@classmethod
|
||||
def remove_attribute(cls, name, id):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
if name == "AddressLines":
|
||||
props.address_lines.remove(id)
|
||||
elif name == "TelephoneNumbers":
|
||||
props.telephone_numbers.remove(id)
|
||||
elif name == "FacsimileNumbers":
|
||||
props.facsimile_numbers.remove(id)
|
||||
elif name == "ElectronicMailAddresses":
|
||||
props.electronic_mail_addresses.remove(id)
|
||||
elif name == "MessagingIDs":
|
||||
props.messaging_ids.remove(id)
|
||||
@@ -16,17 +16,11 @@
|
||||
# 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.api
|
||||
import blenderbim.core.tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Ifc:
|
||||
@classmethod
|
||||
def run(cls, command, **kwargs):
|
||||
return ifcopenshell.api.run(command, IfcStore.get_file(), **kwargs)
|
||||
|
||||
|
||||
class Blender:
|
||||
@classmethod
|
||||
def get_ifc(cls):
|
||||
return "ifc"
|
||||
pass
|
||||
@@ -0,0 +1,40 @@
|
||||
# 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.api
|
||||
import blenderbim.core.tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Ifc:
|
||||
@classmethod
|
||||
def run(cls, command, **kwargs):
|
||||
return ifcopenshell.api.run(command, IfcStore.get_file(), **kwargs)
|
||||
|
||||
@classmethod
|
||||
def set(cls, ifc):
|
||||
IfcStore.file = ifc
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
return IfcStore.get_file()
|
||||
|
||||
@classmethod
|
||||
def get_schema(cls):
|
||||
return IfcStore.get_file().schema
|
||||
@@ -0,0 +1,86 @@
|
||||
# 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.api
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
class PersonEditor(blenderbim.core.tool.person_editor.PersonEditor):
|
||||
@classmethod
|
||||
def set_person(cls, person):
|
||||
bpy.context.scene.BIMOwnerProperties.active_person_id = person.id()
|
||||
|
||||
@classmethod
|
||||
def import_attributes(cls):
|
||||
person = tool.Ifc.get().by_id(bpy.context.scene.BIMOwnerProperties.active_person_id)
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
props.person_attributes.clear()
|
||||
props.middle_names.clear()
|
||||
props.prefix_titles.clear()
|
||||
props.suffix_titles.clear()
|
||||
|
||||
def callback(name, prop, data):
|
||||
if name == "MiddleNames":
|
||||
for name in data["MiddleNames"] or []:
|
||||
props.middle_names.add().name = name or ""
|
||||
if name == "PrefixTitles":
|
||||
for name in data["PrefixTitles"] or []:
|
||||
props.prefix_titles.add().name = name or ""
|
||||
if name == "SuffixTitles":
|
||||
for name in data["SuffixTitles"] or []:
|
||||
props.suffix_titles.add().name = name or ""
|
||||
|
||||
blenderbim.bim.helper.import_attributes("IfcPerson", props.person_attributes, person.get_info(), callback)
|
||||
|
||||
@classmethod
|
||||
def clear_person(cls):
|
||||
bpy.context.scene.BIMOwnerProperties.active_person_id = 0
|
||||
|
||||
@classmethod
|
||||
def export_attributes(cls):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.person_attributes)
|
||||
attributes["MiddleNames"] = [v.name for v in props.middle_names] if props.middle_names else None
|
||||
attributes["PrefixTitles"] = [v.name for v in props.prefix_titles] if props.prefix_titles else None
|
||||
attributes["SuffixTitles"] = [v.name for v in props.suffix_titles] if props.suffix_titles else None
|
||||
return attributes
|
||||
|
||||
@classmethod
|
||||
def get_person(cls):
|
||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_person_id)
|
||||
|
||||
@classmethod
|
||||
def add_attribute(cls, name):
|
||||
if name == "MiddleNames":
|
||||
bpy.context.scene.BIMOwnerProperties.middle_names.add()
|
||||
elif name == "PrefixTitles":
|
||||
bpy.context.scene.BIMOwnerProperties.prefix_titles.add()
|
||||
elif name == "SuffixTitles":
|
||||
bpy.context.scene.BIMOwnerProperties.suffix_titles.add()
|
||||
|
||||
@classmethod
|
||||
def remove_attribute(cls, name, id):
|
||||
if name == "MiddleNames":
|
||||
bpy.context.scene.BIMOwnerProperties.middle_names.remove(id)
|
||||
elif name == "PrefixTitles":
|
||||
bpy.context.scene.BIMOwnerProperties.prefix_titles.remove(id)
|
||||
elif name == "SuffixTitles":
|
||||
bpy.context.scene.BIMOwnerProperties.suffix_titles.remove(id)
|
||||
@@ -0,0 +1,47 @@
|
||||
# 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.core.tool
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.helper
|
||||
|
||||
|
||||
class RoleEditor(blenderbim.core.tool.role_editor.RoleEditor):
|
||||
@classmethod
|
||||
def set_role(cls, role):
|
||||
bpy.context.scene.BIMOwnerProperties.active_role_id = role.id()
|
||||
|
||||
@classmethod
|
||||
def import_attributes(cls):
|
||||
role = cls.get_role()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
props.role_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes("IfcActorRole", props.role_attributes, role.get_info())
|
||||
|
||||
@classmethod
|
||||
def clear_role(cls):
|
||||
bpy.context.scene.BIMOwnerProperties.active_role_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_role(cls):
|
||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_role_id)
|
||||
|
||||
@classmethod
|
||||
def export_attributes(cls):
|
||||
return blenderbim.bim.helper.export_attributes(bpy.context.scene.BIMOwnerProperties.role_attributes)
|
||||
@@ -32,7 +32,7 @@ from mathutils import Vector
|
||||
webbrowser.open = lambda x: True
|
||||
|
||||
|
||||
variables = {"cwd": os.getcwd()}
|
||||
variables = {"cwd": os.getcwd(), "ifc": "IfcStore.get_file()"}
|
||||
|
||||
|
||||
class NewFile:
|
||||
@@ -45,6 +45,17 @@ class NewFile:
|
||||
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|
||||
|
||||
|
||||
class NewIfc:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self):
|
||||
IfcStore.purge()
|
||||
bpy.ops.wm.read_homefile(app_template="")
|
||||
while bpy.data.objects:
|
||||
bpy.data.objects.remove(bpy.data.objects[0])
|
||||
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|
||||
bpy.ops.bim.create_project()
|
||||
|
||||
|
||||
def scenario(function):
|
||||
def subfunction(self):
|
||||
run(function(self))
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# 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/>.
|
||||
@@ -0,0 +1,279 @@
|
||||
# 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 test.bim.bootstrap
|
||||
|
||||
|
||||
class TestAddPerson(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
When I press "bim.add_person"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestRemovePerson(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
When I press "bim.remove_person(person={person})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestAddPersonAttribute(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
When I press "bim.add_person_attribute(name='MiddleNames')"
|
||||
And I press "bim.add_person_attribute(name='PrefixTitles')"
|
||||
And I press "bim.add_person_attribute(name='SuffixTitles')"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestRemovePersonAttribute(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
When I press "bim.add_person_attribute(name='MiddleNames')"
|
||||
And I press "bim.remove_person_attribute(name='MiddleNames', id=0)"
|
||||
And I press "bim.add_person_attribute(name='PrefixTitles')"
|
||||
And I press "bim.remove_person_attribute(name='PrefixTitles', id=0)"
|
||||
And I press "bim.add_person_attribute(name='SuffixTitles')"
|
||||
And I press "bim.remove_person_attribute(name='SuffixTitles', id=0)"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestEnableEditingPerson(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
When I press "bim.enable_editing_person(person={person})"
|
||||
Then "scene.BIMOwnerProperties.active_person_id" is "{person}"
|
||||
"""
|
||||
|
||||
|
||||
class TestDisableEditingPerson(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.enable_editing_person(person={person})"
|
||||
When I press "bim.disable_editing_person"
|
||||
Then "scene.BIMOwnerProperties.active_person_id" is "0"
|
||||
"""
|
||||
|
||||
|
||||
class TestEditPerson(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.enable_editing_person(person={person})"
|
||||
When I press "bim.edit_person"
|
||||
Then "scene.BIMOwnerProperties.active_person_id" is "0"
|
||||
"""
|
||||
|
||||
|
||||
class TestAddRole(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
When I press "bim.add_role(parent={person})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestRemoveRole(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_role(parent={person})"
|
||||
And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()"
|
||||
When I press "bim.remove_role(role={role})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestEnableEditingRole(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_role(parent={person})"
|
||||
And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()"
|
||||
When I press "bim.enable_editing_role(role={role})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestDisableEditingRole(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_role(parent={person})"
|
||||
And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()"
|
||||
And I press "bim.enable_editing_role(role={role})"
|
||||
When I press "bim.disable_editing_role()"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestEditRole(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_role(parent={person})"
|
||||
And the variable "role" is "{ifc}.by_type('IfcActorRole')[0].id()"
|
||||
And I press "bim.enable_editing_role(role={role})"
|
||||
When I press "bim.edit_role()"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestAddAddress(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
When I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestAddAddressAttribute(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
And I press "bim.enable_editing_address(address={address})"
|
||||
When I press "bim.add_address_attribute(name='AddressLines')"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestRemoveAddressAttribute(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
And I press "bim.enable_editing_address(address={address})"
|
||||
And I press "bim.add_address_attribute(name='AddressLines')"
|
||||
When I press "bim.remove_address_attribute(name='AddressLines', id=0)"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestRemoveAddress(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
When I press "bim.remove_address(address={address})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestEnableEditingAddress(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
When I press "bim.enable_editing_address(address={address})"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestDisableEditingAddress(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
And I press "bim.enable_editing_address(address={address})"
|
||||
When I press "bim.disable_editing_address()"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
|
||||
|
||||
class TestEditAddress(test.bim.bootstrap.NewFile):
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_run(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_person"
|
||||
And the variable "person" is "{ifc}.by_type('IfcPerson')[0].id()"
|
||||
And I press "bim.add_address(parent={person}, ifc_class='IfcPostalAddress')"
|
||||
And the variable "address" is "{ifc}.by_type('IfcPostalAddress')[0].id()"
|
||||
And I press "bim.enable_editing_address(address={address})"
|
||||
When I press "bim.edit_address()"
|
||||
Then nothing interesting happens
|
||||
"""
|
||||
@@ -35,25 +35,25 @@ def blender():
|
||||
prophet.verify()
|
||||
|
||||
|
||||
def subject(sus):
|
||||
def decorate(cls):
|
||||
cls.sus = sus
|
||||
return cls
|
||||
|
||||
return decorate
|
||||
@pytest.fixture
|
||||
def person_editor():
|
||||
prophet = Prophecy(blenderbim.core.tool.PersonEditor)
|
||||
yield prophet
|
||||
prophet.verify()
|
||||
|
||||
|
||||
class Spec:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self):
|
||||
self.subject = None
|
||||
@pytest.fixture
|
||||
def role_editor():
|
||||
prophet = Prophecy(blenderbim.core.tool.RoleEditor)
|
||||
yield prophet
|
||||
prophet.verify()
|
||||
|
||||
def construct_with(self, *args, **kwargs):
|
||||
self.subject = self.sus(*args, **kwargs)
|
||||
return self.subject
|
||||
|
||||
def predict(self, cls):
|
||||
return Prophecy(cls)
|
||||
@pytest.fixture
|
||||
def address_editor():
|
||||
prophet = Prophecy(blenderbim.core.tool.AddressEditor)
|
||||
yield prophet
|
||||
prophet.verify()
|
||||
|
||||
|
||||
class Prophecy:
|
||||
@@ -66,10 +66,12 @@ class Prophecy:
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if not hasattr(self.subject, attr):
|
||||
raise AttributeError(f"Prophecy has no attribute {attr}")
|
||||
raise AttributeError(f"Prophecy {self.subject} has no attribute {attr}")
|
||||
|
||||
def decorate(*args, **kwargs):
|
||||
call = {"name": attr, "args": args, "kwargs": kwargs}
|
||||
# Ensure that signature is valid
|
||||
getattr(self.subject, attr)(*args, **kwargs)
|
||||
try:
|
||||
key = json.dumps(call, sort_keys=True)
|
||||
self.calls.append(call)
|
||||
@@ -81,23 +83,25 @@ class Prophecy:
|
||||
|
||||
return decorate
|
||||
|
||||
def should(self):
|
||||
def should_be_called(self, number=None):
|
||||
self.should_call = self.calls.pop()
|
||||
return self
|
||||
|
||||
def be_called(self, number=None):
|
||||
self.predictions.append({"type": "SHOULD_BE_CALLED", "number": number, "call": self.should_call})
|
||||
return self
|
||||
|
||||
def return_with(self, value):
|
||||
def will_return(self, value):
|
||||
key = json.dumps(self.should_call, sort_keys=True)
|
||||
self.return_values[key] = value
|
||||
return self
|
||||
|
||||
def verify(self):
|
||||
predicted_calls = []
|
||||
for prediction in self.predictions:
|
||||
predicted_calls.append(prediction["call"])
|
||||
if prediction["type"] == "SHOULD_BE_CALLED":
|
||||
self.verify_should_be_called(prediction)
|
||||
for call in self.calls:
|
||||
if call not in predicted_calls:
|
||||
raise Exception(f"Unpredicted call: {call}")
|
||||
|
||||
def verify_should_be_called(self, prediction):
|
||||
if prediction["number"]:
|
||||
@@ -106,4 +110,4 @@ class Prophecy:
|
||||
raise Exception(f"Called {count}: {prediction}")
|
||||
else:
|
||||
if prediction["call"] not in self.calls:
|
||||
raise Exception("Not called", prediction)
|
||||
raise Exception(f"{self.subject} was not called with {prediction['call']['name']}: {prediction}")
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# 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 blenderbim.core.owner as subject
|
||||
from test.core.bootstrap import ifc, blender, person_editor, role_editor, address_editor
|
||||
|
||||
|
||||
class TestAddPerson:
|
||||
def test_run(self, ifc):
|
||||
ifc.run("owner.add_person").should_be_called().will_return("person")
|
||||
assert subject.add_person(ifc) == "person"
|
||||
|
||||
|
||||
class TestRemovePerson:
|
||||
def test_run(self, ifc):
|
||||
ifc.run("owner.remove_person", person="person").should_be_called()
|
||||
subject.remove_person(ifc, person="person")
|
||||
|
||||
|
||||
class TestEnableEditingPerson:
|
||||
def test_run(self, person_editor):
|
||||
person_editor.set_person("person").should_be_called()
|
||||
person_editor.import_attributes().should_be_called()
|
||||
subject.enable_editing_person(person_editor, person="person")
|
||||
|
||||
|
||||
class TestDisableEditingPerson:
|
||||
def test_run(self, person_editor):
|
||||
person_editor.clear_person().should_be_called()
|
||||
subject.disable_editing_person(person_editor)
|
||||
|
||||
|
||||
class TestEditPerson:
|
||||
def test_run(self, ifc, person_editor):
|
||||
person_editor.get_person().should_be_called().will_return("person")
|
||||
person_editor.export_attributes().should_be_called().will_return("attributes")
|
||||
ifc.run("owner.edit_person", person="person", attributes="attributes").should_be_called()
|
||||
person_editor.clear_person().should_be_called()
|
||||
subject.edit_person(ifc, person_editor)
|
||||
|
||||
|
||||
class TestAddPersonAttribute:
|
||||
def test_run(self, person_editor):
|
||||
person_editor.add_attribute("name").should_be_called()
|
||||
subject.add_person_attribute(person_editor, name="name")
|
||||
|
||||
|
||||
class TestRemovePersonAttribute:
|
||||
def test_run(self, person_editor):
|
||||
person_editor.remove_attribute("name", "id").should_be_called()
|
||||
subject.remove_person_attribute(person_editor, name="name", id="id")
|
||||
|
||||
|
||||
class TestAddRole:
|
||||
def test_run(self, ifc):
|
||||
ifc.run("owner.add_role", assigned_object="parent").should_be_called().will_return("role")
|
||||
assert subject.add_role(ifc, parent="parent") == "role"
|
||||
|
||||
|
||||
class TestRemoveRole:
|
||||
def test_run(self, ifc):
|
||||
ifc.run("owner.remove_role", role="role").should_be_called()
|
||||
subject.remove_role(ifc, role="role")
|
||||
|
||||
|
||||
class TestEnableEditingRole:
|
||||
def test_run(self, role_editor):
|
||||
role_editor.set_role("role").should_be_called()
|
||||
role_editor.import_attributes().should_be_called()
|
||||
subject.enable_editing_role(role_editor, role="role")
|
||||
|
||||
|
||||
class TestDisableEditingRole:
|
||||
def test_run(self, role_editor):
|
||||
role_editor.clear_role().should_be_called()
|
||||
subject.disable_editing_role(role_editor)
|
||||
|
||||
|
||||
class TestEditRole:
|
||||
def test_run(self, ifc, role_editor):
|
||||
role_editor.export_attributes().should_be_called().will_return("attributes")
|
||||
role_editor.get_role().should_be_called().will_return("role")
|
||||
ifc.run("owner.edit_role", role="role", attributes="attributes").should_be_called()
|
||||
role_editor.clear_role().should_be_called()
|
||||
subject.edit_role(ifc, role_editor)
|
||||
|
||||
|
||||
class TestAddAddress:
|
||||
def test_run(self, ifc):
|
||||
ifc.run(
|
||||
"owner.add_address", assigned_object="parent", ifc_class="IfcPostalAddress"
|
||||
).should_be_called().will_return("address")
|
||||
assert subject.add_address(ifc, parent="parent", ifc_class="IfcPostalAddress") == "address"
|
||||
|
||||
|
||||
class TestRemoveAddress:
|
||||
def test_run(self, ifc):
|
||||
ifc.run("owner.remove_address", address="address").should_be_called()
|
||||
subject.remove_address(ifc, address="address")
|
||||
|
||||
|
||||
class TestEnableEditingAddress:
|
||||
def test_run(self, address_editor):
|
||||
address_editor.set_address("address").should_be_called()
|
||||
address_editor.import_attributes().should_be_called()
|
||||
subject.enable_editing_address(address_editor, address="address")
|
||||
|
||||
|
||||
class TestDisableEditingAddress:
|
||||
def test_run(self, address_editor):
|
||||
address_editor.clear_address().should_be_called()
|
||||
subject.disable_editing_address(address_editor)
|
||||
|
||||
|
||||
class TestEditAddress:
|
||||
def test_run(self, ifc, address_editor):
|
||||
address_editor.get_address().should_be_called().will_return("address")
|
||||
address_editor.export_attributes().should_be_called().will_return("attributes")
|
||||
ifc.run("owner.edit_address", address="address", attributes="attributes").should_be_called()
|
||||
address_editor.clear_address().should_be_called()
|
||||
subject.edit_address(ifc, address_editor)
|
||||
|
||||
|
||||
class TestAddAddressAttribute:
|
||||
def test_run(self, address_editor):
|
||||
address_editor.add_attribute("name").should_be_called()
|
||||
subject.add_address_attribute(address_editor, name="name")
|
||||
|
||||
|
||||
class TestRemoveAddressAttribute:
|
||||
def test_run(self, address_editor):
|
||||
address_editor.remove_attribute("name", "id").should_be_called()
|
||||
subject.remove_address_attribute(address_editor, name="name", id="id")
|
||||
@@ -0,0 +1,17 @@
|
||||
# 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/>.
|
||||
@@ -0,0 +1,197 @@
|
||||
# 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 test.bim.bootstrap
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.tool.address_editor import AddressEditor as subject
|
||||
|
||||
|
||||
class TestImplementsTool(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
assert isinstance(subject(), blenderbim.core.tool.AddressEditor)
|
||||
|
||||
|
||||
class TestSetAddress(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
address = ifc.createIfcPostalAddress()
|
||||
subject().set_address(address)
|
||||
assert bpy.context.scene.BIMOwnerProperties.active_address_id == address.id()
|
||||
|
||||
|
||||
class TestImportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_importing_a_postal_address(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
address = ifc.createIfcPostalAddress()
|
||||
address.Purpose = "USERDEFINED"
|
||||
address.Description = "Description"
|
||||
address.UserDefinedPurpose = "UserDefinedPurpose"
|
||||
address.InternalLocation = "InternalLocation"
|
||||
address.AddressLines = ["Address", "Lines"]
|
||||
address.PostalBox = "PostalBox"
|
||||
address.Town = "Town"
|
||||
address.Region = "Region"
|
||||
address.PostalCode = "PostalCode"
|
||||
address.Country = "Country"
|
||||
subject().set_address(address)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.address_attributes.get("Purpose").enum_value == "USERDEFINED"
|
||||
assert props.address_attributes.get("Description").string_value == "Description"
|
||||
assert props.address_attributes.get("UserDefinedPurpose").string_value == "UserDefinedPurpose"
|
||||
assert props.address_attributes.get("InternalLocation").string_value == "InternalLocation"
|
||||
assert props.address_attributes.get("PostalBox").string_value == "PostalBox"
|
||||
assert props.address_attributes.get("Town").string_value == "Town"
|
||||
assert props.address_attributes.get("Region").string_value == "Region"
|
||||
assert props.address_attributes.get("PostalCode").string_value == "PostalCode"
|
||||
assert props.address_attributes.get("Country").string_value == "Country"
|
||||
assert len(props.address_lines) == 2
|
||||
assert props.address_lines[0].name == "Address"
|
||||
assert props.address_lines[1].name == "Lines"
|
||||
|
||||
def test_importing_a_postal_address_twice(self):
|
||||
self.test_importing_a_postal_address()
|
||||
ifc = tool.Ifc().get()
|
||||
address = ifc.createIfcPostalAddress()
|
||||
address.Purpose = "OFFICE"
|
||||
subject().set_address(address)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.address_attributes.get("Purpose").enum_value == "OFFICE"
|
||||
assert len(props.address_lines) == 0
|
||||
|
||||
def test_importing_a_telecom_address(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
address = ifc.createIfcTelecomAddress()
|
||||
address.Purpose = "USERDEFINED"
|
||||
address.Description = "Description"
|
||||
address.UserDefinedPurpose = "UserDefinedPurpose"
|
||||
address.TelephoneNumbers = ["Telephone", "Numbers"]
|
||||
address.FacsimileNumbers = ["Facsimile", "Numbers"]
|
||||
address.PagerNumber = "PagerNumber"
|
||||
address.ElectronicMailAddresses = ["Electronic", "Mail", "Addresses"]
|
||||
address.WWWHomePageURL = "WWWHomePageURL"
|
||||
address.MessagingIDs = ["Messaging", "IDs"]
|
||||
subject().set_address(address)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.address_attributes.get("Purpose").enum_value == "USERDEFINED"
|
||||
assert props.address_attributes.get("Description").string_value == "Description"
|
||||
assert props.address_attributes.get("UserDefinedPurpose").string_value == "UserDefinedPurpose"
|
||||
assert [a.name for a in props.telephone_numbers] == ["Telephone", "Numbers"]
|
||||
assert [a.name for a in props.facsimile_numbers] == ["Facsimile", "Numbers"]
|
||||
assert [a.name for a in props.electronic_mail_addresses] == ["Electronic", "Mail", "Addresses"]
|
||||
assert [a.name for a in props.messaging_ids] == ["Messaging", "IDs"]
|
||||
|
||||
def test_importing_a_telecom_address_twice(self):
|
||||
self.test_importing_a_telecom_address()
|
||||
ifc = tool.Ifc().get()
|
||||
address = ifc.createIfcTelecomAddress()
|
||||
address.Purpose = "OFFICE"
|
||||
subject().set_address(address)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.address_attributes.get("Purpose").enum_value == "OFFICE"
|
||||
assert len(props.telephone_numbers) == 0
|
||||
assert len(props.facsimile_numbers) == 0
|
||||
assert len(props.electronic_mail_addresses) == 0
|
||||
assert len(props.messaging_ids) == 0
|
||||
|
||||
|
||||
class TestClearAddress(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
address = ifc.createIfcPostalAddress()
|
||||
subject().set_address(address)
|
||||
subject().clear_address()
|
||||
assert bpy.context.scene.BIMOwnerProperties.active_address_id == 0
|
||||
|
||||
|
||||
class TestGetAddress(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
address = ifc.createIfcPostalAddress()
|
||||
subject().set_address(address)
|
||||
assert subject().get_address() == address
|
||||
|
||||
|
||||
class TestExportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_exporting_a_postal_address(self):
|
||||
TestImportAttributes().test_importing_a_postal_address()
|
||||
assert subject().export_attributes() == {
|
||||
"Purpose": "USERDEFINED",
|
||||
"Description": "Description",
|
||||
"UserDefinedPurpose": "UserDefinedPurpose",
|
||||
"InternalLocation": "InternalLocation",
|
||||
"AddressLines": ["Address", "Lines"],
|
||||
"PostalBox": "PostalBox",
|
||||
"Town": "Town",
|
||||
"Region": "Region",
|
||||
"PostalCode": "PostalCode",
|
||||
"Country": "Country",
|
||||
}
|
||||
|
||||
def test_exporting_a_telecom_address(self):
|
||||
TestImportAttributes().test_importing_a_telecom_address()
|
||||
assert subject().export_attributes() == {
|
||||
"Purpose": "USERDEFINED",
|
||||
"Description": "Description",
|
||||
"UserDefinedPurpose": "UserDefinedPurpose",
|
||||
"TelephoneNumbers": ["Telephone", "Numbers"],
|
||||
"FacsimileNumbers": ["Facsimile", "Numbers"],
|
||||
"PagerNumber": "PagerNumber",
|
||||
"ElectronicMailAddresses": ["Electronic", "Mail", "Addresses"],
|
||||
"WWWHomePageURL": "WWWHomePageURL",
|
||||
"MessagingIDs": ["Messaging", "IDs"],
|
||||
}
|
||||
|
||||
|
||||
class TestAddAttribute(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
subject().add_attribute("AddressLines")
|
||||
subject().add_attribute("TelephoneNumbers")
|
||||
subject().add_attribute("FacsimileNumbers")
|
||||
subject().add_attribute("ElectronicMailAddresses")
|
||||
subject().add_attribute("MessagingIDs")
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert len(props.address_lines) == 1
|
||||
assert len(props.telephone_numbers) == 1
|
||||
assert len(props.facsimile_numbers) == 1
|
||||
assert len(props.electronic_mail_addresses) == 1
|
||||
assert len(props.messaging_ids) == 1
|
||||
|
||||
|
||||
class TestRemoveAddress(test.bim.bootstrap.NewFile):
|
||||
TestAddAttribute().test_run()
|
||||
subject().remove_attribute("AddressLines", 0)
|
||||
subject().remove_attribute("TelephoneNumbers", 0)
|
||||
subject().remove_attribute("FacsimileNumbers", 0)
|
||||
subject().remove_attribute("ElectronicMailAddresses", 0)
|
||||
subject().remove_attribute("MessagingIDs", 0)
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert len(props.address_lines) == 0
|
||||
assert len(props.telephone_numbers) == 0
|
||||
assert len(props.facsimile_numbers) == 0
|
||||
assert len(props.electronic_mail_addresses) == 0
|
||||
assert len(props.messaging_ids) == 0
|
||||
@@ -0,0 +1,17 @@
|
||||
# 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/>.
|
||||
@@ -0,0 +1,58 @@
|
||||
# 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 test.bim.bootstrap
|
||||
from blenderbim.tool import Ifc as subject
|
||||
|
||||
|
||||
class TestSet(test.bim.bootstrap.NewFile):
|
||||
def test_setting_an_ifc_data(self):
|
||||
ifc = ifcopenshell.file()
|
||||
subject().set(ifc)
|
||||
assert subject().get() == ifc
|
||||
|
||||
|
||||
class TestGet(test.bim.bootstrap.NewFile):
|
||||
def test_getting_an_ifc_dataset_from_a_ifc_spf_filepath(self):
|
||||
assert subject().get() is None
|
||||
bpy.context.scene.BIMProperties.ifc_file = "test/files/basic.ifc"
|
||||
result = subject().get()
|
||||
assert isinstance(result, ifcopenshell.file)
|
||||
|
||||
def test_getting_the_active_ifc_dataset_regardless_of_ifc_path(self):
|
||||
bpy.context.scene.BIMProperties.ifc_file = "test/files/basic.ifc"
|
||||
ifc = ifcopenshell.file()
|
||||
subject().set(ifc)
|
||||
assert subject().get() == ifc
|
||||
|
||||
|
||||
class TestRun(test.bim.bootstrap.NewFile):
|
||||
def test_running_a_command_on_the_active_ifc_dataset(self):
|
||||
ifc = ifcopenshell.file()
|
||||
subject().set(ifc)
|
||||
wall = subject().run("root.create_entity", ifc_class="IfcWall")
|
||||
assert subject().get().by_type("IfcWall")[0] == wall
|
||||
|
||||
|
||||
class TestGetSchema(test.bim.bootstrap.NewFile):
|
||||
def test_getting_the_schema_version_identifier(self):
|
||||
ifc = ifcopenshell.file(schema="IFC4")
|
||||
subject().set(ifc)
|
||||
assert subject().get_schema() == "IFC4"
|
||||
@@ -0,0 +1,152 @@
|
||||
# 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 test.bim.bootstrap
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.tool.person_editor import PersonEditor as subject
|
||||
|
||||
|
||||
class TestImplementsTool(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
assert isinstance(subject(), blenderbim.core.tool.person_editor.PersonEditor)
|
||||
|
||||
|
||||
class TestSetPerson(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
person = ifcopenshell.file().createIfcPerson()
|
||||
subject().set_person(person)
|
||||
assert bpy.context.scene.BIMOwnerProperties.active_person_id == person.id()
|
||||
|
||||
|
||||
class TestImportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
person = ifc.createIfcPerson()
|
||||
person.Identification = "identification"
|
||||
person.GivenName = "given_name"
|
||||
person.FamilyName = "family_name"
|
||||
person.MiddleNames = ("middle", "names")
|
||||
person.PrefixTitles = ("prefix", "titles")
|
||||
person.SuffixTitles = ("suffix", "titles")
|
||||
subject().set_person(person)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.person_attributes.get("Identification").string_value == "identification"
|
||||
assert props.person_attributes.get("GivenName").string_value == "given_name"
|
||||
assert props.person_attributes.get("FamilyName").string_value == "family_name"
|
||||
assert len(props.middle_names) == 2
|
||||
assert props.middle_names[0].name == "middle"
|
||||
assert props.middle_names[1].name == "names"
|
||||
assert len(props.prefix_titles) == 2
|
||||
assert props.prefix_titles[0].name == "prefix"
|
||||
assert props.prefix_titles[1].name == "titles"
|
||||
assert len(props.suffix_titles) == 2
|
||||
assert props.suffix_titles[0].name == "suffix"
|
||||
assert props.suffix_titles[1].name == "titles"
|
||||
|
||||
def test_overwriting_a_previous_import(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
person = ifc.createIfcPerson()
|
||||
person.Identification = "identification"
|
||||
person.GivenName = "given_name"
|
||||
subject().set_person(person)
|
||||
subject().import_attributes()
|
||||
person.Identification = "identification2"
|
||||
person.GivenName = None
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.person_attributes.get("Identification").string_value == "identification2"
|
||||
assert props.person_attributes.get("GivenName").string_value == ""
|
||||
|
||||
|
||||
class TestClearPerson(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
props.active_person_id = 1
|
||||
subject().clear_person()
|
||||
assert props.active_person_id == 0
|
||||
|
||||
|
||||
class TestExportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
person = ifc.createIfcPerson()
|
||||
person.Identification = "identification"
|
||||
person.GivenName = "given_name"
|
||||
person.FamilyName = "family_name"
|
||||
person.MiddleNames = ("middle", "names")
|
||||
person.PrefixTitles = ("prefix", "titles")
|
||||
person.SuffixTitles = ("suffix", "titles")
|
||||
subject().set_person(person)
|
||||
subject().import_attributes()
|
||||
assert subject().export_attributes() == {
|
||||
"Identification": "identification",
|
||||
"GivenName": "given_name",
|
||||
"FamilyName": "family_name",
|
||||
"MiddleNames": ["middle", "names"],
|
||||
"PrefixTitles": ["prefix", "titles"],
|
||||
"SuffixTitles": ["suffix", "titles"],
|
||||
}
|
||||
|
||||
def test_getting_empty_list_attributes_as_none(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
result = subject().export_attributes()
|
||||
assert result["MiddleNames"] is None
|
||||
assert result["PrefixTitles"] is None
|
||||
assert result["SuffixTitles"] is None
|
||||
|
||||
|
||||
class TestGetPerson(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
person = ifc.createIfcPerson()
|
||||
subject().set_person(person)
|
||||
assert subject().get_person() == person
|
||||
|
||||
|
||||
class TestAddAttribute(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
subject().add_attribute("MiddleNames")
|
||||
subject().add_attribute("PrefixTitles")
|
||||
subject().add_attribute("SuffixTitles")
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert len(props.middle_names) == 1
|
||||
assert len(props.prefix_titles) == 1
|
||||
assert len(props.suffix_titles) == 1
|
||||
|
||||
|
||||
class TestRemoveAttribute(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
subject().add_attribute("MiddleNames")
|
||||
subject().remove_attribute("MiddleNames", 0)
|
||||
subject().add_attribute("PrefixTitles")
|
||||
subject().remove_attribute("PrefixTitles", 0)
|
||||
subject().add_attribute("SuffixTitles")
|
||||
subject().remove_attribute("SuffixTitles", 0)
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert len(props.middle_names) == 0
|
||||
assert len(props.prefix_titles) == 0
|
||||
assert len(props.suffix_titles) == 0
|
||||
@@ -0,0 +1,98 @@
|
||||
# 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 test.bim.bootstrap
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.tool.role_editor import RoleEditor as subject
|
||||
|
||||
|
||||
class TestImplementsTool(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
assert isinstance(subject(), blenderbim.core.tool.role_editor.RoleEditor)
|
||||
|
||||
|
||||
class TestSetRole(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
role = ifcopenshell.file().createIfcActorRole()
|
||||
subject().set_role(role)
|
||||
assert bpy.context.scene.BIMOwnerProperties.active_role_id == role.id()
|
||||
|
||||
|
||||
class TestImportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
role = ifc.createIfcActorRole()
|
||||
role.Role = "USERDEFINED"
|
||||
role.UserDefinedRole = "UserDefinedRole"
|
||||
role.Description = "Description"
|
||||
subject().set_role(role)
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.role_attributes.get("Role").enum_value == "USERDEFINED"
|
||||
assert props.role_attributes.get("UserDefinedRole").string_value == "UserDefinedRole"
|
||||
assert props.role_attributes.get("Description").string_value == "Description"
|
||||
|
||||
def test_importing_twice(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
role = ifc.createIfcActorRole()
|
||||
role.Role = "USERDEFINED"
|
||||
subject().set_role(role)
|
||||
subject().import_attributes()
|
||||
role.Role = "ARCHITECT"
|
||||
subject().import_attributes()
|
||||
props = bpy.context.scene.BIMOwnerProperties
|
||||
assert props.role_attributes.get("Role").enum_value == "ARCHITECT"
|
||||
|
||||
|
||||
class TestClearRole(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
role = ifcopenshell.file().createIfcActorRole()
|
||||
subject().set_role(role)
|
||||
subject().clear_role()
|
||||
assert bpy.context.scene.BIMOwnerProperties.active_role_id == 0
|
||||
|
||||
|
||||
class TestGetRole(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
role = ifc.createIfcActorRole()
|
||||
subject().set_role(role)
|
||||
assert subject().get_role() == role
|
||||
|
||||
|
||||
class TestExportAttributes(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc().set(ifc)
|
||||
role = ifc.createIfcActorRole()
|
||||
role.Role = "USERDEFINED"
|
||||
role.UserDefinedRole = "UserDefinedRole"
|
||||
role.Description = "Description"
|
||||
subject().set_role(role)
|
||||
subject().import_attributes()
|
||||
assert subject().export_attributes() == {
|
||||
"Role": "USERDEFINED",
|
||||
"UserDefinedRole": "UserDefinedRole",
|
||||
"Description": "Description",
|
||||
}
|
||||
Reference in New Issue
Block a user