mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 14:02:27 +00:00
Implement undo for non-module operators. See #1475.
This commit is contained in:
@@ -61,9 +61,6 @@ if bpy is not None:
|
|||||||
operator.SelectIfcFile,
|
operator.SelectIfcFile,
|
||||||
operator.ExportIFC,
|
operator.ExportIFC,
|
||||||
operator.ImportIFC,
|
operator.ImportIFC,
|
||||||
operator.SelectExternalMaterialDir,
|
|
||||||
operator.FetchExternalMaterial,
|
|
||||||
operator.FetchObjectPassport,
|
|
||||||
operator.OpenUpstream,
|
operator.OpenUpstream,
|
||||||
operator.AddSectionPlane,
|
operator.AddSectionPlane,
|
||||||
operator.RemoveSectionPlane,
|
operator.RemoveSectionPlane,
|
||||||
@@ -72,8 +69,6 @@ if bpy is not None:
|
|||||||
operator.RemoveIfcFile,
|
operator.RemoveIfcFile,
|
||||||
operator.SetOverrideColour,
|
operator.SetOverrideColour,
|
||||||
operator.SetViewportShadowFromSun,
|
operator.SetViewportShadowFromSun,
|
||||||
operator.CopyPropertyToSelection,
|
|
||||||
operator.CopyAttributeToSelection,
|
|
||||||
operator.LinkIfc,
|
operator.LinkIfc,
|
||||||
operator.SnapSpacesTogether,
|
operator.SnapSpacesTogether,
|
||||||
prop.StrProperty,
|
prop.StrProperty,
|
||||||
|
|||||||
@@ -42,10 +42,6 @@ def draw_ui(context, layout, obj_type):
|
|||||||
icon="RADIOBUT_OFF" if blender_attribute.is_null else "RADIOBUT_ON",
|
icon="RADIOBUT_OFF" if blender_attribute.is_null else "RADIOBUT_ON",
|
||||||
text="",
|
text="",
|
||||||
)
|
)
|
||||||
# TODO: reimplement, see #1222
|
|
||||||
# op = row.operator("bim.copy_attribute_to_selection", icon="COPYDOWN", text="")
|
|
||||||
# op.attribute_name = attribute.name
|
|
||||||
# op.attribute_value = attribute.string_value
|
|
||||||
else:
|
else:
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
|
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from math import radians, degrees, atan, tan, cos, sin
|
|||||||
class ExportIFC(bpy.types.Operator):
|
class ExportIFC(bpy.types.Operator):
|
||||||
bl_idname = "export_ifc.bim"
|
bl_idname = "export_ifc.bim"
|
||||||
bl_label = "Export IFC"
|
bl_label = "Export IFC"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filename_ext = ".ifc"
|
filename_ext = ".ifc"
|
||||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
@@ -40,10 +41,15 @@ class ExportIFC(bpy.types.Operator):
|
|||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
return IfcStore.execute_ifc_operator(self, context)
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
logger = logging.getLogger("ExportIFC")
|
logger = logging.getLogger("ExportIFC")
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
filename=os.path.join(context.scene.BIMProperties.data_dir, "process.log"), filemode="a", level=logging.DEBUG
|
filename=os.path.join(context.scene.BIMProperties.data_dir, "process.log"),
|
||||||
|
filemode="a",
|
||||||
|
level=logging.DEBUG,
|
||||||
)
|
)
|
||||||
extension = self.filepath.split(".")[-1]
|
extension = self.filepath.split(".")[-1]
|
||||||
if extension == "ifczip":
|
if extension == "ifczip":
|
||||||
@@ -75,6 +81,7 @@ class ExportIFC(bpy.types.Operator):
|
|||||||
class ImportIFC(bpy.types.Operator, ImportHelper):
|
class ImportIFC(bpy.types.Operator, ImportHelper):
|
||||||
bl_idname = "import_ifc.bim"
|
bl_idname = "import_ifc.bim"
|
||||||
bl_label = "Import IFC"
|
bl_label = "Import IFC"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filename_ext = ".ifc"
|
filename_ext = ".ifc"
|
||||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||||
|
|
||||||
@@ -102,7 +109,9 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
|||||||
start = time.time()
|
start = time.time()
|
||||||
logger = logging.getLogger("ImportIFC")
|
logger = logging.getLogger("ImportIFC")
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
filename=os.path.join(bpy.context.scene.BIMProperties.data_dir, "process.log"), filemode="a", level=logging.DEBUG
|
filename=os.path.join(bpy.context.scene.BIMProperties.data_dir, "process.log"),
|
||||||
|
filemode="a",
|
||||||
|
level=logging.DEBUG,
|
||||||
)
|
)
|
||||||
|
|
||||||
settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
|
settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
|
||||||
@@ -139,23 +148,10 @@ class OpenUri(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectExternalMaterialDir(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_external_material_dir"
|
|
||||||
bl_label = "Select Material File"
|
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
bpy.context.active_object.active_material.BIMMaterialProperties.location = self.filepath
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
context.window_manager.fileselect_add(self)
|
|
||||||
return {"RUNNING_MODAL"}
|
|
||||||
|
|
||||||
|
|
||||||
class SelectIfcFile(bpy.types.Operator):
|
class SelectIfcFile(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_ifc_file"
|
bl_idname = "bim.select_ifc_file"
|
||||||
bl_label = "Select IFC File"
|
bl_label = "Select IFC File"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||||
|
|
||||||
@@ -171,6 +167,7 @@ class SelectIfcFile(bpy.types.Operator):
|
|||||||
class SelectDataDir(bpy.types.Operator):
|
class SelectDataDir(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_data_dir"
|
bl_idname = "bim.select_data_dir"
|
||||||
bl_label = "Select Data Directory"
|
bl_label = "Select Data Directory"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@@ -185,6 +182,7 @@ class SelectDataDir(bpy.types.Operator):
|
|||||||
class SelectSchemaDir(bpy.types.Operator):
|
class SelectSchemaDir(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_schema_dir"
|
bl_idname = "bim.select_schema_dir"
|
||||||
bl_label = "Select Schema Directory"
|
bl_label = "Select Schema Directory"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@@ -196,52 +194,6 @@ class SelectSchemaDir(bpy.types.Operator):
|
|||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
|
||||||
class FetchExternalMaterial(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.fetch_external_material"
|
|
||||||
bl_label = "Fetch External Material"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
location = bpy.context.active_object.active_material.BIMMaterialProperties.location
|
|
||||||
if location[-6:] != ".mpass":
|
|
||||||
return {"FINISHED"}
|
|
||||||
if not os.path.isabs(location):
|
|
||||||
location = os.path.join(bpy.context.scene.BIMProperties.data_dir, location)
|
|
||||||
with open(location) as f:
|
|
||||||
self.material_pass = json.load(f)
|
|
||||||
if bpy.context.scene.render.engine == "BLENDER_EEVEE" and "eevee" in self.material_pass:
|
|
||||||
self.fetch_eevee_or_cycles("eevee")
|
|
||||||
elif bpy.context.scene.render.engine == "CYCLES" and "cycles" in self.material_pass:
|
|
||||||
self.fetch_eevee_or_cycles("cycles")
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def fetch_eevee_or_cycles(self, name):
|
|
||||||
identification = bpy.context.active_object.active_material.BIMMaterialProperties.identification
|
|
||||||
uri = self.material_pass[name]["uri"]
|
|
||||||
if not os.path.isabs(uri):
|
|
||||||
uri = os.path.join(bpy.context.scene.BIMProperties.data_dir, uri)
|
|
||||||
bpy.ops.wm.link(filename=identification, directory=os.path.join(uri, "Material"))
|
|
||||||
for material in bpy.data.materials:
|
|
||||||
if material.name == identification and material.library:
|
|
||||||
bpy.context.active_object.material_slots[0].material = material
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class FetchObjectPassport(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.fetch_object_passport"
|
|
||||||
bl_label = "Fetch Object Passport"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for reference in bpy.context.active_object.BIMObjectProperties.document_references:
|
|
||||||
reference = bpy.context.scene.BIMProperties.document_references[reference.name]
|
|
||||||
if reference.location[-6:] == ".blend":
|
|
||||||
self.fetch_blender(reference)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def fetch_blender(self, reference):
|
|
||||||
bpy.ops.wm.link(filename=reference.name, directory=os.path.join(reference.location, "Mesh"))
|
|
||||||
bpy.context.active_object.data = bpy.data.meshes[reference.name]
|
|
||||||
|
|
||||||
|
|
||||||
class OpenUpstream(bpy.types.Operator):
|
class OpenUpstream(bpy.types.Operator):
|
||||||
bl_idname = "bim.open_upstream"
|
bl_idname = "bim.open_upstream"
|
||||||
bl_label = "Open Upstream Reference"
|
bl_label = "Open Upstream Reference"
|
||||||
@@ -259,70 +211,10 @@ class OpenUpstream(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class CopyPropertyToSelection(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.copy_property_to_selection"
|
|
||||||
bl_label = "Copy Property To Selection"
|
|
||||||
pset_name: bpy.props.StringProperty()
|
|
||||||
prop_name: bpy.props.StringProperty()
|
|
||||||
prop_value: bpy.props.StringProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for obj in bpy.context.selected_objects:
|
|
||||||
if "/" not in obj.name:
|
|
||||||
continue
|
|
||||||
pset = obj.BIMObjectProperties.psets.get(self.pset_name)
|
|
||||||
if not pset:
|
|
||||||
applicable_psets = schema.ifc.psetqto.get_applicable(obj.name.split("/")[0], pset_only=True)
|
|
||||||
for pset_template in applicable_psets:
|
|
||||||
if pset_template.Name == self.pset_name:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
pset = obj.BIMObjectProperties.psets.add()
|
|
||||||
pset.name = self.pset_name
|
|
||||||
for template_prop_name in (p.Name for p in pset_template.HasPropertyTemplates):
|
|
||||||
prop = pset.properties.add()
|
|
||||||
prop.name = template_prop_name
|
|
||||||
prop = pset.properties.get(self.prop_name)
|
|
||||||
if prop:
|
|
||||||
prop.string_value = self.prop_value
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class CopyAttributeToSelection(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.copy_attribute_to_selection"
|
|
||||||
bl_label = "Copy Attribute To Selection"
|
|
||||||
attribute_name: bpy.props.StringProperty()
|
|
||||||
attribute_value: bpy.props.StringProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
# TODO: reimplement
|
|
||||||
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
|
||||||
self.applicable_attributes_cache = {}
|
|
||||||
for obj in bpy.context.selected_objects:
|
|
||||||
if "/" not in obj.name:
|
|
||||||
continue
|
|
||||||
attribute = obj.BIMObjectProperties.attributes.get(self.attribute_name)
|
|
||||||
if not attribute:
|
|
||||||
applicable_attributes = self.get_applicable_attributes(obj.name.split("/")[0])
|
|
||||||
if self.attribute_name not in applicable_attributes:
|
|
||||||
continue
|
|
||||||
attribute = obj.BIMObjectProperties.attributes.add()
|
|
||||||
attribute.name = self.attribute_name
|
|
||||||
attribute.string_value = self.attribute_value
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
def get_applicable_attributes(self, ifc_class):
|
|
||||||
if ifc_class not in self.applicable_attributes_cache:
|
|
||||||
self.applicable_attributes_cache[ifc_class] = [
|
|
||||||
a.name() for a in self.schema.declaration_by_name(ifc_class).all_attributes()
|
|
||||||
]
|
|
||||||
return self.applicable_attributes_cache[ifc_class]
|
|
||||||
|
|
||||||
|
|
||||||
class AddSectionPlane(bpy.types.Operator):
|
class AddSectionPlane(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_section_plane"
|
bl_idname = "bim.add_section_plane"
|
||||||
bl_label = "Add Temporary Section Cutaway"
|
bl_label = "Add Temporary Section Cutaway"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
obj = self.create_section_obj()
|
obj = self.create_section_obj()
|
||||||
@@ -490,6 +382,7 @@ class AddSectionPlane(bpy.types.Operator):
|
|||||||
class RemoveSectionPlane(bpy.types.Operator):
|
class RemoveSectionPlane(bpy.types.Operator):
|
||||||
bl_idname = "bim.remove_section_plane"
|
bl_idname = "bim.remove_section_plane"
|
||||||
bl_label = "Remove Temporary Section Cutaway"
|
bl_label = "Remove Temporary Section Cutaway"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
name = bpy.context.active_object.name
|
name = bpy.context.active_object.name
|
||||||
@@ -544,6 +437,7 @@ class RemoveSectionPlane(bpy.types.Operator):
|
|||||||
class ReloadIfcFile(bpy.types.Operator):
|
class ReloadIfcFile(bpy.types.Operator):
|
||||||
bl_idname = "bim.reload_ifc_file"
|
bl_idname = "bim.reload_ifc_file"
|
||||||
bl_label = "Reload IFC File"
|
bl_label = "Reload IFC File"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# TODO: reimplement. See #1222.
|
# TODO: reimplement. See #1222.
|
||||||
@@ -553,6 +447,7 @@ class ReloadIfcFile(bpy.types.Operator):
|
|||||||
class AddIfcFile(bpy.types.Operator):
|
class AddIfcFile(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_ifc_file"
|
bl_idname = "bim.add_ifc_file"
|
||||||
bl_label = "Add IFC File"
|
bl_label = "Add IFC File"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
bpy.context.scene.DocProperties.ifc_files.add()
|
bpy.context.scene.DocProperties.ifc_files.add()
|
||||||
@@ -563,6 +458,7 @@ class RemoveIfcFile(bpy.types.Operator):
|
|||||||
bl_idname = "bim.remove_ifc_file"
|
bl_idname = "bim.remove_ifc_file"
|
||||||
bl_label = "Remove IFC File"
|
bl_label = "Remove IFC File"
|
||||||
index: bpy.props.IntProperty()
|
index: bpy.props.IntProperty()
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
bpy.context.scene.DocProperties.ifc_files.remove(self.index)
|
bpy.context.scene.DocProperties.ifc_files.remove(self.index)
|
||||||
@@ -572,6 +468,7 @@ class RemoveIfcFile(bpy.types.Operator):
|
|||||||
class SetOverrideColour(bpy.types.Operator):
|
class SetOverrideColour(bpy.types.Operator):
|
||||||
bl_idname = "bim.set_override_colour"
|
bl_idname = "bim.set_override_colour"
|
||||||
bl_label = "Set Override Colour"
|
bl_label = "Set Override Colour"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
result = 0
|
result = 0
|
||||||
@@ -585,6 +482,7 @@ class SetOverrideColour(bpy.types.Operator):
|
|||||||
class SetViewportShadowFromSun(bpy.types.Operator):
|
class SetViewportShadowFromSun(bpy.types.Operator):
|
||||||
bl_idname = "bim.set_viewport_shadow_from_sun"
|
bl_idname = "bim.set_viewport_shadow_from_sun"
|
||||||
bl_label = "Set Viewport Shadow from Sun"
|
bl_label = "Set Viewport Shadow from Sun"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# The vector used for the light direction is a bit funny
|
# The vector used for the light direction is a bit funny
|
||||||
@@ -598,6 +496,7 @@ class SetViewportShadowFromSun(bpy.types.Operator):
|
|||||||
class LinkIfc(bpy.types.Operator):
|
class LinkIfc(bpy.types.Operator):
|
||||||
bl_idname = "bim.link_ifc"
|
bl_idname = "bim.link_ifc"
|
||||||
bl_label = "Link IFC"
|
bl_label = "Link IFC"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@@ -625,6 +524,7 @@ class LinkIfc(bpy.types.Operator):
|
|||||||
class SnapSpacesTogether(bpy.types.Operator):
|
class SnapSpacesTogether(bpy.types.Operator):
|
||||||
bl_idname = "bim.snap_spaces_together"
|
bl_idname = "bim.snap_spaces_together"
|
||||||
bl_label = "Snap Spaces Together"
|
bl_label = "Snap Spaces Together"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
threshold = 0.5
|
threshold = 0.5
|
||||||
@@ -662,3 +562,128 @@ class SnapSpacesTogether(bpy.types.Operator):
|
|||||||
for v in polygon.vertices:
|
for v in polygon.vertices:
|
||||||
obj.data.vertices[v].co += offset
|
obj.data.vertices[v].co += offset
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectExternalMaterialDir(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_external_material_dir"
|
||||||
|
bl_label = "Select Material File"
|
||||||
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# TODO: this is dead code, awaiting reimplementation. See #1222.
|
||||||
|
bpy.context.active_object.active_material.BIMMaterialProperties.location = self.filepath
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
context.window_manager.fileselect_add(self)
|
||||||
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
|
||||||
|
class FetchExternalMaterial(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.fetch_external_material"
|
||||||
|
bl_label = "Fetch External Material"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# TODO: this is dead code, awaiting reimplementation. See #1222.
|
||||||
|
location = bpy.context.active_object.active_material.BIMMaterialProperties.location
|
||||||
|
if location[-6:] != ".mpass":
|
||||||
|
return {"FINISHED"}
|
||||||
|
if not os.path.isabs(location):
|
||||||
|
location = os.path.join(bpy.context.scene.BIMProperties.data_dir, location)
|
||||||
|
with open(location) as f:
|
||||||
|
self.material_pass = json.load(f)
|
||||||
|
if bpy.context.scene.render.engine == "BLENDER_EEVEE" and "eevee" in self.material_pass:
|
||||||
|
self.fetch_eevee_or_cycles("eevee")
|
||||||
|
elif bpy.context.scene.render.engine == "CYCLES" and "cycles" in self.material_pass:
|
||||||
|
self.fetch_eevee_or_cycles("cycles")
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def fetch_eevee_or_cycles(self, name):
|
||||||
|
identification = bpy.context.active_object.active_material.BIMMaterialProperties.identification
|
||||||
|
uri = self.material_pass[name]["uri"]
|
||||||
|
if not os.path.isabs(uri):
|
||||||
|
uri = os.path.join(bpy.context.scene.BIMProperties.data_dir, uri)
|
||||||
|
bpy.ops.wm.link(filename=identification, directory=os.path.join(uri, "Material"))
|
||||||
|
for material in bpy.data.materials:
|
||||||
|
if material.name == identification and material.library:
|
||||||
|
bpy.context.active_object.material_slots[0].material = material
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class FetchObjectPassport(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.fetch_object_passport"
|
||||||
|
bl_label = "Fetch Object Passport"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# TODO: this is dead code, awaiting reimplementation. See #1222.
|
||||||
|
for reference in bpy.context.active_object.BIMObjectProperties.document_references:
|
||||||
|
reference = bpy.context.scene.BIMProperties.document_references[reference.name]
|
||||||
|
if reference.location[-6:] == ".blend":
|
||||||
|
self.fetch_blender(reference)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def fetch_blender(self, reference):
|
||||||
|
bpy.ops.wm.link(filename=reference.name, directory=os.path.join(reference.location, "Mesh"))
|
||||||
|
bpy.context.active_object.data = bpy.data.meshes[reference.name]
|
||||||
|
|
||||||
|
|
||||||
|
class CopyPropertyToSelection(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.copy_property_to_selection"
|
||||||
|
bl_label = "Copy Property To Selection"
|
||||||
|
pset_name: bpy.props.StringProperty()
|
||||||
|
prop_name: bpy.props.StringProperty()
|
||||||
|
prop_value: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# TODO: this is dead code, awaiting reimplementation. See #1222.
|
||||||
|
for obj in bpy.context.selected_objects:
|
||||||
|
if "/" not in obj.name:
|
||||||
|
continue
|
||||||
|
pset = obj.BIMObjectProperties.psets.get(self.pset_name)
|
||||||
|
if not pset:
|
||||||
|
applicable_psets = schema.ifc.psetqto.get_applicable(obj.name.split("/")[0], pset_only=True)
|
||||||
|
for pset_template in applicable_psets:
|
||||||
|
if pset_template.Name == self.pset_name:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
pset = obj.BIMObjectProperties.psets.add()
|
||||||
|
pset.name = self.pset_name
|
||||||
|
for template_prop_name in (p.Name for p in pset_template.HasPropertyTemplates):
|
||||||
|
prop = pset.properties.add()
|
||||||
|
prop.name = template_prop_name
|
||||||
|
prop = pset.properties.get(self.prop_name)
|
||||||
|
if prop:
|
||||||
|
prop.string_value = self.prop_value
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class CopyAttributeToSelection(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.copy_attribute_to_selection"
|
||||||
|
bl_label = "Copy Attribute To Selection"
|
||||||
|
attribute_name: bpy.props.StringProperty()
|
||||||
|
attribute_value: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# TODO: this is dead code, awaiting reimplementation. See #1222.
|
||||||
|
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
||||||
|
self.applicable_attributes_cache = {}
|
||||||
|
for obj in bpy.context.selected_objects:
|
||||||
|
if "/" not in obj.name:
|
||||||
|
continue
|
||||||
|
attribute = obj.BIMObjectProperties.attributes.get(self.attribute_name)
|
||||||
|
if not attribute:
|
||||||
|
applicable_attributes = self.get_applicable_attributes(obj.name.split("/")[0])
|
||||||
|
if self.attribute_name not in applicable_attributes:
|
||||||
|
continue
|
||||||
|
attribute = obj.BIMObjectProperties.attributes.add()
|
||||||
|
attribute.name = self.attribute_name
|
||||||
|
attribute.string_value = self.attribute_value
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def get_applicable_attributes(self, ifc_class):
|
||||||
|
if ifc_class not in self.applicable_attributes_cache:
|
||||||
|
self.applicable_attributes_cache[ifc_class] = [
|
||||||
|
a.name() for a in self.schema.declaration_by_name(ifc_class).all_attributes()
|
||||||
|
]
|
||||||
|
return self.applicable_attributes_cache[ifc_class]
|
||||||
|
|||||||
@@ -51,10 +51,18 @@ class Transaction:
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
def serialise_value(self, element, value):
|
def serialise_value(self, element, value):
|
||||||
return element.walk(lambda v: isinstance(v, entity_instance), lambda v: {"id": v.id()}, value)
|
return element.walk(
|
||||||
|
lambda v: isinstance(v, entity_instance),
|
||||||
|
lambda v: {"id": v.id()} if v.id() else {"type": v.is_a(), "value": v.wrappedValue},
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
|
||||||
def unserialise_value(self, element, value):
|
def unserialise_value(self, element, value):
|
||||||
return element.walk(lambda v: isinstance(v, dict), lambda v: self.file.by_id(v["id"]), value)
|
return element.walk(
|
||||||
|
lambda v: isinstance(v, dict),
|
||||||
|
lambda v: self.file.by_id(v["id"]) if v.get("id") else self.file.create_entity(v["type"], v["value"]),
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
|
||||||
def batch(self):
|
def batch(self):
|
||||||
self.is_batched = True
|
self.is_batched = True
|
||||||
|
|||||||
Reference in New Issue
Block a user