mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 13:38:05 +00:00
WIP port search module with new features! See #1222.
* New IFC class search * Slicker UI * Colour by class and reset colours now available in search panel
This commit is contained in:
@@ -29,6 +29,7 @@ if bpy is not None:
|
|||||||
"owner": None,
|
"owner": None,
|
||||||
"project": None,
|
"project": None,
|
||||||
"pset": None,
|
"pset": None,
|
||||||
|
"search": None,
|
||||||
"spatial": None,
|
"spatial": None,
|
||||||
"style": None,
|
"style": None,
|
||||||
"type": None,
|
"type": None,
|
||||||
@@ -40,16 +41,12 @@ if bpy is not None:
|
|||||||
modules[name] = importlib.import_module(f"blenderbim.bim.module.{name}")
|
modules[name] = importlib.import_module(f"blenderbim.bim.module.{name}")
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
operator.SelectClass,
|
|
||||||
operator.SelectType,
|
|
||||||
operator.OpenUri,
|
operator.OpenUri,
|
||||||
operator.SelectDataDir,
|
operator.SelectDataDir,
|
||||||
operator.SelectSchemaDir,
|
operator.SelectSchemaDir,
|
||||||
operator.SelectIfcFile,
|
operator.SelectIfcFile,
|
||||||
operator.ExportIFC,
|
operator.ExportIFC,
|
||||||
operator.ImportIFC,
|
operator.ImportIFC,
|
||||||
operator.ColourByAttribute,
|
|
||||||
operator.ColourByPset,
|
|
||||||
operator.SelectExternalMaterialDir,
|
operator.SelectExternalMaterialDir,
|
||||||
operator.AddSweptSolid,
|
operator.AddSweptSolid,
|
||||||
operator.RemoveSweptSolid,
|
operator.RemoveSweptSolid,
|
||||||
@@ -75,12 +72,8 @@ if bpy is not None:
|
|||||||
operator.AssignConstraint,
|
operator.AssignConstraint,
|
||||||
operator.UnassignConstraint,
|
operator.UnassignConstraint,
|
||||||
operator.RemoveObjectConstraint,
|
operator.RemoveObjectConstraint,
|
||||||
operator.GenerateGlobalId,
|
|
||||||
operator.AddMaterialAttribute,
|
operator.AddMaterialAttribute,
|
||||||
operator.RemoveMaterialAttribute,
|
operator.RemoveMaterialAttribute,
|
||||||
operator.SelectGlobalId,
|
|
||||||
operator.SelectAttribute,
|
|
||||||
operator.SelectPset,
|
|
||||||
operator.FetchLibraryInformation,
|
operator.FetchLibraryInformation,
|
||||||
operator.FetchExternalMaterial,
|
operator.FetchExternalMaterial,
|
||||||
operator.FetchObjectPassport,
|
operator.FetchObjectPassport,
|
||||||
@@ -200,7 +193,6 @@ if bpy is not None:
|
|||||||
ui.BIM_PT_sheets,
|
ui.BIM_PT_sheets,
|
||||||
ui.BIM_PT_psets,
|
ui.BIM_PT_psets,
|
||||||
ui.BIM_PT_constraints,
|
ui.BIM_PT_constraints,
|
||||||
ui.BIM_PT_search,
|
|
||||||
ui.BIM_PT_ifcclash,
|
ui.BIM_PT_ifcclash,
|
||||||
ui.BIM_PT_library,
|
ui.BIM_PT_library,
|
||||||
ui.BIM_PT_presentation_layers,
|
ui.BIM_PT_presentation_layers,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ classes = (
|
|||||||
operator.EnableEditingAttributes,
|
operator.EnableEditingAttributes,
|
||||||
operator.DisableEditingAttributes,
|
operator.DisableEditingAttributes,
|
||||||
operator.EditAttributes,
|
operator.EditAttributes,
|
||||||
|
operator.GenerateGlobalId,
|
||||||
prop.BIMAttributeProperties,
|
prop.BIMAttributeProperties,
|
||||||
ui.BIM_PT_object_attributes,
|
ui.BIM_PT_object_attributes,
|
||||||
ui.BIM_PT_material_attributes,
|
ui.BIM_PT_material_attributes,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import json
|
import json
|
||||||
|
import ifcopenshell
|
||||||
import blenderbim.bim.module.attribute.edit_attributes as edit_attributes
|
import blenderbim.bim.module.attribute.edit_attributes as edit_attributes
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.attribute.data import Data
|
from blenderbim.bim.module.attribute.data import Data
|
||||||
@@ -100,3 +101,19 @@ class EditAttributes(bpy.types.Operator):
|
|||||||
Data.load(oprops.ifc_definition_id)
|
Data.load(oprops.ifc_definition_id)
|
||||||
bpy.ops.bim.disable_editing_attributes(obj=self.obj, obj_type=self.obj_type)
|
bpy.ops.bim.disable_editing_attributes(obj=self.obj, obj_type=self.obj_type)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class GenerateGlobalId(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.generate_global_id"
|
||||||
|
bl_label = "Regenerate GlobalId"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
index = bpy.context.active_object.BIMAttributeProperties.attributes.find("GlobalId")
|
||||||
|
if index >= 0:
|
||||||
|
global_id = bpy.context.active_object.BIMAttributeProperties.attributes[index]
|
||||||
|
else:
|
||||||
|
global_id = bpy.context.active_object.BIMAttributeProperties.attributes.add()
|
||||||
|
global_id.name = "GlobalId"
|
||||||
|
global_id.data_type = "string"
|
||||||
|
global_id.string_value = ifcopenshell.guid.new()
|
||||||
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ classes = (
|
|||||||
operator.BIMTesterPurge,
|
operator.BIMTesterPurge,
|
||||||
operator.SelectFeaturesDir,
|
operator.SelectFeaturesDir,
|
||||||
operator.RejectElement,
|
operator.RejectElement,
|
||||||
operator.ColourByClass,
|
|
||||||
operator.ResetObjectColours,
|
|
||||||
operator.ApproveClass,
|
operator.ApproveClass,
|
||||||
operator.RejectClass,
|
operator.RejectClass,
|
||||||
operator.SelectAudited,
|
operator.SelectAudited,
|
||||||
@@ -22,4 +20,3 @@ def register():
|
|||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
del bpy.types.Scene.BimTesterProperties
|
del bpy.types.Scene.BimTesterProperties
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ class ExecuteBIMTester(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
|
||||||
filename = os.path.join(
|
filename = os.path.join(
|
||||||
bpy.context.scene.BimTesterProperties.features_dir, bpy.context.scene.BimTesterProperties.features_file + ".feature"
|
bpy.context.scene.BimTesterProperties.features_dir,
|
||||||
|
bpy.context.scene.BimTesterProperties.features_file + ".feature",
|
||||||
)
|
)
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(bpy.context.scene.BimTesterProperties.features_dir)
|
os.chdir(bpy.context.scene.BimTesterProperties.features_dir)
|
||||||
@@ -32,6 +33,7 @@ class ExecuteBIMTester(bpy.types.Operator):
|
|||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class BIMTesterPurge(bpy.types.Operator):
|
class BIMTesterPurge(bpy.types.Operator):
|
||||||
bl_idname = "bim.bim_tester_purge"
|
bl_idname = "bim.bim_tester_purge"
|
||||||
bl_label = "Purge Tests"
|
bl_label = "Purge Tests"
|
||||||
@@ -39,7 +41,8 @@ class BIMTesterPurge(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
|
||||||
filename = os.path.join(
|
filename = os.path.join(
|
||||||
bpy.context.scene.BimTesterProperties.features_dir, bpy.context.scene.BimTesterProperties.features_file + ".feature"
|
bpy.context.scene.BimTesterProperties.features_dir,
|
||||||
|
bpy.context.scene.BimTesterProperties.features_file + ".feature",
|
||||||
)
|
)
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(bpy.context.scene.BimTesterProperties.features_dir)
|
os.chdir(bpy.context.scene.BimTesterProperties.features_dir)
|
||||||
@@ -47,6 +50,7 @@ class BIMTesterPurge(bpy.types.Operator):
|
|||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectFeaturesDir(bpy.types.Operator):
|
class SelectFeaturesDir(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_features_dir"
|
bl_idname = "bim.select_features_dir"
|
||||||
bl_label = "Select Features Directory"
|
bl_label = "Select Features Directory"
|
||||||
@@ -62,6 +66,7 @@ class SelectFeaturesDir(bpy.types.Operator):
|
|||||||
context.window_manager.fileselect_add(self)
|
context.window_manager.fileselect_add(self)
|
||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
|
||||||
class RejectElement(bpy.types.Operator):
|
class RejectElement(bpy.types.Operator):
|
||||||
bl_idname = "bim.reject_element"
|
bl_idname = "bim.reject_element"
|
||||||
bl_label = "Reject Element"
|
bl_label = "Reject Element"
|
||||||
@@ -79,32 +84,6 @@ class RejectElement(bpy.types.Operator):
|
|||||||
QAHelper.append_to_scenario(lines)
|
QAHelper.append_to_scenario(lines)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
class ColourByClass(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.colour_by_class"
|
|
||||||
bl_label = "Colour by Class"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
colours = cycle(colour_list)
|
|
||||||
ifc_classes = {}
|
|
||||||
for obj in bpy.context.visible_objects:
|
|
||||||
if "/" not in obj.name:
|
|
||||||
continue
|
|
||||||
ifc_class = obj.name.split("/")[0]
|
|
||||||
if ifc_class not in ifc_classes:
|
|
||||||
ifc_classes[ifc_class] = next(colours)
|
|
||||||
obj.color = ifc_classes[ifc_class]
|
|
||||||
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
|
|
||||||
area.spaces[0].shading.color_type = "OBJECT"
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
class ResetObjectColours(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.reset_object_colours"
|
|
||||||
bl_label = "Reset Colours"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for object in bpy.context.selected_objects:
|
|
||||||
object.color = (1, 1, 1, 1)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
class ApproveClass(bpy.types.Operator):
|
class ApproveClass(bpy.types.Operator):
|
||||||
bl_idname = "bim.approve_class"
|
bl_idname = "bim.approve_class"
|
||||||
@@ -117,14 +96,11 @@ class ApproveClass(bpy.types.Operator):
|
|||||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
continue
|
continue
|
||||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
lines.append(
|
lines.append(" * The element {} is an {}".format(element.GlobalId, element.is_a()))
|
||||||
" * The element {} is an {}".format(
|
|
||||||
element.GlobalId, element.is_a()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
QAHelper.append_to_scenario(lines)
|
QAHelper.append_to_scenario(lines)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class RejectClass(bpy.types.Operator):
|
class RejectClass(bpy.types.Operator):
|
||||||
bl_idname = "bim.reject_class"
|
bl_idname = "bim.reject_class"
|
||||||
bl_label = "Reject Class"
|
bl_label = "Reject Class"
|
||||||
@@ -144,6 +120,7 @@ class RejectClass(bpy.types.Operator):
|
|||||||
QAHelper.append_to_scenario(lines)
|
QAHelper.append_to_scenario(lines)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectAudited(bpy.types.Operator):
|
class SelectAudited(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_audited"
|
bl_idname = "bim.select_audited"
|
||||||
bl_label = "Select Audited"
|
bl_label = "Select Audited"
|
||||||
@@ -169,11 +146,13 @@ class SelectAudited(bpy.types.Operator):
|
|||||||
def is_a_global_id(self, word):
|
def is_a_global_id(self, word):
|
||||||
return word[0] in ["0", "1", "2", "3"] and len(word) == 22
|
return word[0] in ["0", "1", "2", "3"] and len(word) == 22
|
||||||
|
|
||||||
|
|
||||||
class QAHelper:
|
class QAHelper:
|
||||||
@classmethod
|
@classmethod
|
||||||
def append_to_scenario(cls, lines):
|
def append_to_scenario(cls, lines):
|
||||||
filename = os.path.join(
|
filename = os.path.join(
|
||||||
bpy.context.scene.BimTesterProperties.features_dir, bpy.context.scene.BimTesterProperties.features_file + ".feature"
|
bpy.context.scene.BimTesterProperties.features_dir,
|
||||||
|
bpy.context.scene.BimTesterProperties.features_file + ".feature",
|
||||||
)
|
)
|
||||||
if os.path.exists(filename + "~"):
|
if os.path.exists(filename + "~"):
|
||||||
os.remove(filename + "~")
|
os.remove(filename + "~")
|
||||||
@@ -194,6 +173,7 @@ class QAHelper:
|
|||||||
destination.write(source_line)
|
destination.write(source_line)
|
||||||
os.remove(filename + "~")
|
os.remove(filename + "~")
|
||||||
|
|
||||||
|
|
||||||
colour_list = [
|
colour_list = [
|
||||||
(0.651, 0.81, 0.892, 1),
|
(0.651, 0.81, 0.892, 1),
|
||||||
(0.121, 0.471, 0.706, 1),
|
(0.121, 0.471, 0.706, 1),
|
||||||
|
|||||||
@@ -46,10 +46,6 @@ class BIM_PT_qa(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.operator("bim.reject_element")
|
row.operator("bim.reject_element")
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator("bim.colour_by_class")
|
|
||||||
row.operator("bim.reset_object_colours")
|
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(bimtester_properties, "audit_ifc_class")
|
row.prop(bimtester_properties, "audit_ifc_class")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import bpy
|
||||||
|
from . import ui, prop, operator
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
operator.SelectGlobalId,
|
||||||
|
operator.SelectIfcClass,
|
||||||
|
operator.SelectAttribute,
|
||||||
|
operator.SelectPset,
|
||||||
|
operator.ColourByAttribute,
|
||||||
|
operator.ColourByPset,
|
||||||
|
operator.ColourByClass,
|
||||||
|
operator.ResetObjectColours,
|
||||||
|
prop.BIMSearchProperties,
|
||||||
|
ui.BIM_PT_search,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.types.Scene.BIMSearchProperties = bpy.props.PointerProperty(type=prop.BIMSearchProperties)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
del bpy.types.Scene.BIMSearchProperties
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
import re
|
||||||
|
import bpy
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.element
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
from itertools import cycle
|
||||||
|
|
||||||
|
|
||||||
|
colour_list = [
|
||||||
|
(0.651, 0.81, 0.892, 1),
|
||||||
|
(0.121, 0.471, 0.706, 1),
|
||||||
|
(0.699, 0.876, 0.54, 1),
|
||||||
|
(0.199, 0.629, 0.174, 1),
|
||||||
|
(0.983, 0.605, 0.602, 1),
|
||||||
|
(0.89, 0.101, 0.112, 1),
|
||||||
|
(0.989, 0.751, 0.427, 1),
|
||||||
|
(0.986, 0.497, 0.1, 1),
|
||||||
|
(0.792, 0.699, 0.839, 1),
|
||||||
|
(0.414, 0.239, 0.603, 1),
|
||||||
|
(0.993, 0.999, 0.6, 1),
|
||||||
|
(0.693, 0.349, 0.157, 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def does_keyword_exist(pattern, string):
|
||||||
|
string = str(string)
|
||||||
|
if (
|
||||||
|
bpy.context.scene.BIMSearchProperties.should_use_regex
|
||||||
|
and bpy.context.scene.BIMSearchProperties.should_ignorecase
|
||||||
|
and re.search(pattern, string, flags=re.IGNORECASE)
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
elif bpy.context.scene.BIMSearchProperties.should_use_regex and re.search(pattern, string):
|
||||||
|
return True
|
||||||
|
elif bpy.context.scene.BIMSearchProperties.should_ignorecase and string.lower() == pattern.lower():
|
||||||
|
return True
|
||||||
|
elif string == pattern:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class SelectGlobalId(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_global_id"
|
||||||
|
bl_label = "Select GlobalId"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
props = context.scene.BIMSearchProperties
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
if element.GlobalId == props.global_id:
|
||||||
|
obj.select_set(True)
|
||||||
|
break
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectIfcClass(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_ifc_class"
|
||||||
|
bl_label = "Select IFC Class"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
props = context.scene.BIMSearchProperties
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
if does_keyword_exist(props.ifc_class, element.is_a()):
|
||||||
|
obj.select_set(True)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectAttribute(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_attribute"
|
||||||
|
bl_label = "Select Attribute"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
props = context.scene.BIMSearchProperties
|
||||||
|
pattern = props.search_attribute_value
|
||||||
|
attribute_name = props.search_attribute_name
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
if does_keyword_exist(pattern, getattr(element, attribute_name, None)):
|
||||||
|
obj.select_set(True)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectPset(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_pset"
|
||||||
|
bl_label = "Select Pset"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
props = context.scene.BIMSearchProperties
|
||||||
|
search_pset_name = props.search_pset_name
|
||||||
|
search_prop_name = props.search_prop_name
|
||||||
|
pattern = props.search_pset_value
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
props = psets.get(search_pset_name, {})
|
||||||
|
if does_keyword_exist(pattern, props.get(search_prop_name, None)):
|
||||||
|
obj.select_set(True)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class ColourByAttribute(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.colour_by_attribute"
|
||||||
|
bl_label = "Colour by Attribute"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
colours = cycle(colour_list)
|
||||||
|
values = {}
|
||||||
|
attribute_name = context.scene.BIMSearchProperties.search_attribute_name
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
value = getattr(element, attribute_name, None)
|
||||||
|
if value not in values:
|
||||||
|
values[value] = next(colours)
|
||||||
|
obj.color = values[value]
|
||||||
|
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
|
||||||
|
area.spaces[0].shading.color_type = "OBJECT"
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class ColourByPset(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.colour_by_pset"
|
||||||
|
bl_label = "Colour by Pset"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
colours = cycle(colour_list)
|
||||||
|
values = {}
|
||||||
|
search_pset_name = context.scene.BIMSearchProperties.search_pset_name
|
||||||
|
search_prop_name = context.scene.BIMSearchProperties.search_prop_name
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
props = psets.get(search_pset_name, {})
|
||||||
|
value = str(props.get(search_prop_name, None))
|
||||||
|
if value not in values:
|
||||||
|
values[value] = next(colours)
|
||||||
|
obj.color = values[value]
|
||||||
|
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
|
||||||
|
area.spaces[0].shading.color_type = "OBJECT"
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class ColourByClass(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.colour_by_class"
|
||||||
|
bl_label = "Colour by Class"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
|
colours = cycle(colour_list)
|
||||||
|
ifc_classes = {}
|
||||||
|
for obj in bpy.context.visible_objects:
|
||||||
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
|
continue
|
||||||
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
ifc_class = element.is_a()
|
||||||
|
if ifc_class not in ifc_classes:
|
||||||
|
ifc_classes[ifc_class] = next(colours)
|
||||||
|
obj.color = ifc_classes[ifc_class]
|
||||||
|
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
|
||||||
|
area.spaces[0].shading.color_type = "OBJECT"
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class ResetObjectColours(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.reset_object_colours"
|
||||||
|
bl_label = "Reset Colours"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
for obj in bpy.context.selected_objects:
|
||||||
|
obj.color = (1, 1, 1, 1)
|
||||||
|
return {"FINISHED"}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import bpy
|
||||||
|
from bpy.types import PropertyGroup
|
||||||
|
from bpy.props import (
|
||||||
|
PointerProperty,
|
||||||
|
StringProperty,
|
||||||
|
EnumProperty,
|
||||||
|
BoolProperty,
|
||||||
|
IntProperty,
|
||||||
|
FloatProperty,
|
||||||
|
FloatVectorProperty,
|
||||||
|
CollectionProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
class BIMSearchProperties(PropertyGroup):
|
||||||
|
should_use_regex: BoolProperty(name="Search With Regex", default=False)
|
||||||
|
should_ignorecase: BoolProperty(name="Search Ignoring Case", default=True)
|
||||||
|
global_id: StringProperty(name="GlobalId")
|
||||||
|
ifc_class: StringProperty(name="IFC Class")
|
||||||
|
search_attribute_name: StringProperty(name="Search Attribute Name")
|
||||||
|
search_attribute_value: StringProperty(name="Search Attribute Value")
|
||||||
|
search_pset_name: StringProperty(name="Search Pset Name")
|
||||||
|
search_prop_name: StringProperty(name="Search Prop Name")
|
||||||
|
search_pset_value: StringProperty(name="Search Pset Value")
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import bpy
|
||||||
|
from bpy.types import Panel
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_search(Panel):
|
||||||
|
bl_label = "IFC Search"
|
||||||
|
bl_idname = "BIM_PT_search"
|
||||||
|
bl_options = {"DEFAULT_CLOSED"}
|
||||||
|
bl_space_type = "PROPERTIES"
|
||||||
|
bl_region_type = "WINDOW"
|
||||||
|
bl_context = "scene"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
props = context.scene.BIMSearchProperties
|
||||||
|
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(props, "should_use_regex")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(props, "should_ignorecase")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.reset_object_colours", icon="BRUSH_DATA")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "global_id", text="", icon="TRACKER")
|
||||||
|
row.operator("bim.select_global_id", text="", icon="VIEWZOOM")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "ifc_class", text="", icon="OBJECT_DATA")
|
||||||
|
row.operator("bim.select_ifc_class", text="", icon="VIEWZOOM")
|
||||||
|
row.operator("bim.colour_by_class", text="", icon="BRUSH_DATA")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "search_attribute_name", text="", icon="PROPERTIES")
|
||||||
|
row.prop(props, "search_attribute_value", text="")
|
||||||
|
row.operator("bim.select_attribute", text="", icon="VIEWZOOM")
|
||||||
|
row.operator("bim.colour_by_attribute", text="", icon="BRUSH_DATA")
|
||||||
|
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(props, "search_pset_name", text="", icon="COPY_ID")
|
||||||
|
row.prop(props, "search_prop_name", text="")
|
||||||
|
row.prop(props, "search_pset_value", text="")
|
||||||
|
row.operator("bim.select_pset", text="", icon="VIEWZOOM")
|
||||||
|
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
|
||||||
@@ -25,28 +25,12 @@ from . import ifc
|
|||||||
from . import annotation
|
from . import annotation
|
||||||
from . import helper
|
from . import helper
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
from itertools import cycle
|
|
||||||
from mathutils import Vector, Matrix, Euler, geometry
|
from mathutils import Vector, Matrix, Euler, geometry
|
||||||
import bmesh
|
import bmesh
|
||||||
from math import radians, degrees, atan, tan, cos, sin
|
from math import radians, degrees, atan, tan, cos, sin
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
|
|
||||||
colour_list = [
|
|
||||||
(0.651, 0.81, 0.892, 1),
|
|
||||||
(0.121, 0.471, 0.706, 1),
|
|
||||||
(0.699, 0.876, 0.54, 1),
|
|
||||||
(0.199, 0.629, 0.174, 1),
|
|
||||||
(0.983, 0.605, 0.602, 1),
|
|
||||||
(0.89, 0.101, 0.112, 1),
|
|
||||||
(0.989, 0.751, 0.427, 1),
|
|
||||||
(0.986, 0.497, 0.1, 1),
|
|
||||||
(0.792, 0.699, 0.839, 1),
|
|
||||||
(0.414, 0.239, 0.603, 1),
|
|
||||||
(0.993, 0.999, 0.6, 1),
|
|
||||||
(0.693, 0.349, 0.157, 1),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def depsgraph_update_pre_handler(scene):
|
def depsgraph_update_pre_handler(scene):
|
||||||
@@ -139,169 +123,6 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SelectGlobalId(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_global_id"
|
|
||||||
bl_label = "Select GlobalId"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for obj in bpy.context.visible_objects:
|
|
||||||
index = obj.BIMObjectProperties.attributes.find("GlobalId")
|
|
||||||
if (
|
|
||||||
index != -1
|
|
||||||
and obj.BIMObjectProperties.attributes[index].string_value == bpy.context.scene.BIMProperties.global_id
|
|
||||||
):
|
|
||||||
obj.select_set(True)
|
|
||||||
break
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class SelectAttribute(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_attribute"
|
|
||||||
bl_label = "Select Attribute"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
import re
|
|
||||||
|
|
||||||
search_value = bpy.context.scene.BIMProperties.search_attribute_value
|
|
||||||
for object in bpy.context.visible_objects:
|
|
||||||
index = object.BIMObjectProperties.attributes.find(bpy.context.scene.BIMProperties.search_attribute_name)
|
|
||||||
if index == -1:
|
|
||||||
continue
|
|
||||||
value = object.BIMObjectProperties.attributes[index].string_value
|
|
||||||
if (
|
|
||||||
bpy.context.scene.BIMProperties.search_regex
|
|
||||||
and bpy.context.scene.BIMProperties.search_ignorecase
|
|
||||||
and re.search(search_value, value, flags=re.IGNORECASE)
|
|
||||||
):
|
|
||||||
object.select_set(True)
|
|
||||||
elif bpy.context.scene.BIMProperties.search_regex and re.search(search_value, value):
|
|
||||||
object.select_set(True)
|
|
||||||
elif bpy.context.scene.BIMProperties.search_ignorecase and value.lower() == search_value.lower():
|
|
||||||
object.select_set(True)
|
|
||||||
elif value == search_value:
|
|
||||||
object.select_set(True)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class SelectPset(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_pset"
|
|
||||||
bl_label = "Select Pset"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
import re
|
|
||||||
|
|
||||||
search_pset_name = bpy.context.scene.BIMProperties.search_pset_name
|
|
||||||
search_prop_name = bpy.context.scene.BIMProperties.search_prop_name
|
|
||||||
search_value = bpy.context.scene.BIMProperties.search_pset_value
|
|
||||||
for object in bpy.context.visible_objects:
|
|
||||||
pset_index = object.BIMObjectProperties.psets.find(search_pset_name)
|
|
||||||
if pset_index == -1:
|
|
||||||
continue
|
|
||||||
prop_index = object.BIMObjectProperties.psets[pset_index].properties.find(search_prop_name)
|
|
||||||
if prop_index == -1:
|
|
||||||
continue
|
|
||||||
value = object.BIMObjectProperties.psets[pset_index].properties[prop_index].string_value
|
|
||||||
if (
|
|
||||||
bpy.context.scene.BIMProperties.search_regex
|
|
||||||
and bpy.context.scene.BIMProperties.search_ignorecase
|
|
||||||
and re.search(search_value, value, flags=re.IGNORECASE)
|
|
||||||
):
|
|
||||||
object.select_set(True)
|
|
||||||
elif bpy.context.scene.BIMProperties.search_regex and re.search(search_value, value):
|
|
||||||
object.select_set(True)
|
|
||||||
elif bpy.context.scene.BIMProperties.search_ignorecase and value.lower() == search_value.lower():
|
|
||||||
object.select_set(True)
|
|
||||||
elif value == search_value:
|
|
||||||
object.select_set(True)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class SelectClass(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_class"
|
|
||||||
bl_label = "Select IFC Class"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for object in bpy.context.visible_objects:
|
|
||||||
if (
|
|
||||||
"/" in object.name
|
|
||||||
and object.name[0:3] == "Ifc"
|
|
||||||
and object.name.split("/")[0] == bpy.context.scene.BIMProperties.ifc_class
|
|
||||||
):
|
|
||||||
object.select_set(True)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class SelectType(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.select_type"
|
|
||||||
bl_label = "Select IFC Type"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
for object in bpy.context.visible_objects:
|
|
||||||
if (
|
|
||||||
"/" in object.name
|
|
||||||
and object.name[0:3] == "Ifc"
|
|
||||||
and object.name.split("/")[0] == bpy.context.scene.BIMProperties.ifc_class
|
|
||||||
and "PredefinedType" in object.BIMObjectProperties.attributes
|
|
||||||
and object.BIMObjectProperties.attributes["PredefinedType"].string_value
|
|
||||||
== bpy.context.scene.BIMProperties.ifc_predefined_type
|
|
||||||
):
|
|
||||||
if bpy.context.scene.BIMProperties.ifc_predefined_type != "USERDEFINED":
|
|
||||||
object.select_set(True)
|
|
||||||
elif (
|
|
||||||
"ObjectType" in object.BIMObjectProperties.attributes
|
|
||||||
and object.BIMObjectProperties.attributes["ObjectType"].string_value
|
|
||||||
== bpy.context.scene.BIMProperties.ifc_userdefined_type
|
|
||||||
):
|
|
||||||
object.select_set(True)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ColourByAttribute(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.colour_by_attribute"
|
|
||||||
bl_label = "Colour by Attribute"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
colours = cycle(colour_list)
|
|
||||||
values = {}
|
|
||||||
attribute_name = bpy.context.scene.BIMProperties.search_attribute_name
|
|
||||||
for obj in bpy.context.visible_objects:
|
|
||||||
index = obj.BIMObjectProperties.attributes.find(attribute_name)
|
|
||||||
if index == -1:
|
|
||||||
continue
|
|
||||||
value = obj.BIMObjectProperties.attributes[index].string_value
|
|
||||||
if value not in values:
|
|
||||||
values[value] = next(colours)
|
|
||||||
obj.color = values[value]
|
|
||||||
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
|
|
||||||
area.spaces[0].shading.color_type = "OBJECT"
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ColourByPset(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.colour_by_pset"
|
|
||||||
bl_label = "Colour by Pset"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
colours = cycle(colour_list)
|
|
||||||
values = {}
|
|
||||||
search_pset_name = bpy.context.scene.BIMProperties.search_pset_name
|
|
||||||
search_prop_name = bpy.context.scene.BIMProperties.search_prop_name
|
|
||||||
for obj in bpy.context.visible_objects:
|
|
||||||
pset_index = obj.BIMObjectProperties.psets.find(search_pset_name)
|
|
||||||
if pset_index == -1:
|
|
||||||
continue
|
|
||||||
prop_index = obj.BIMObjectProperties.psets[pset_index].properties.find(search_prop_name)
|
|
||||||
if prop_index == -1:
|
|
||||||
continue
|
|
||||||
value = obj.BIMObjectProperties.psets[pset_index].properties[prop_index].string_value
|
|
||||||
if value not in values:
|
|
||||||
values[value] = next(colours)
|
|
||||||
obj.color = values[value]
|
|
||||||
area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D")
|
|
||||||
area.spaces[0].shading.color_type = "OBJECT"
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class OpenUri(bpy.types.Operator):
|
class OpenUri(bpy.types.Operator):
|
||||||
bl_idname = "bim.open_uri"
|
bl_idname = "bim.open_uri"
|
||||||
bl_label = "Open URI"
|
bl_label = "Open URI"
|
||||||
@@ -442,22 +263,6 @@ class RemoveObjectConstraint(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class GenerateGlobalId(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.generate_global_id"
|
|
||||||
bl_label = "Regenerate GlobalId"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
index = bpy.context.active_object.BIMObjectProperties.attributes.find("GlobalId")
|
|
||||||
if index >= 0:
|
|
||||||
global_id = bpy.context.active_object.BIMObjectProperties.attributes[index]
|
|
||||||
else:
|
|
||||||
global_id = bpy.context.active_object.BIMObjectProperties.attributes.add()
|
|
||||||
global_id.name = "GlobalId"
|
|
||||||
global_id.data_type = "string"
|
|
||||||
global_id.string_value = ifcopenshell.guid.new()
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class AddMaterialAttribute(bpy.types.Operator):
|
class AddMaterialAttribute(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_material_attribute"
|
bl_idname = "bim.add_material_attribute"
|
||||||
bl_label = "Add Material Attribute"
|
bl_label = "Add Material Attribute"
|
||||||
|
|||||||
@@ -823,14 +823,6 @@ class BIMProperties(PropertyGroup):
|
|||||||
|
|
||||||
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
|
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
|
||||||
has_library: BoolProperty(name="Has Project Library", default=False)
|
has_library: BoolProperty(name="Has Project Library", default=False)
|
||||||
search_regex: BoolProperty(name="Search With Regex", default=False)
|
|
||||||
search_ignorecase: BoolProperty(name="Search Ignoring Case", default=True)
|
|
||||||
global_id: StringProperty(name="GlobalId")
|
|
||||||
search_attribute_name: StringProperty(name="Search Attribute Name")
|
|
||||||
search_attribute_value: StringProperty(name="Search Attribute Value")
|
|
||||||
search_pset_name: StringProperty(name="Search Pset Name")
|
|
||||||
search_prop_name: StringProperty(name="Search Prop Name")
|
|
||||||
search_pset_value: StringProperty(name="Search Pset Value")
|
|
||||||
contexts: EnumProperty(items=getContexts, name="Contexts")
|
contexts: EnumProperty(items=getContexts, name="Contexts")
|
||||||
available_contexts: EnumProperty(items=[("Model", "Model", ""), ("Plan", "Plan", "")], name="Available Contexts")
|
available_contexts: EnumProperty(items=[("Model", "Model", ""), ("Plan", "Plan", "")], name="Available Contexts")
|
||||||
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
|
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
|
||||||
|
|||||||
@@ -511,50 +511,6 @@ class BIM_PT_text(Panel):
|
|||||||
row.prop(variable, "prop_key")
|
row.prop(variable, "prop_key")
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_search(Panel):
|
|
||||||
bl_label = "IFC Search"
|
|
||||||
bl_idname = "BIM_PT_search"
|
|
||||||
bl_options = {"DEFAULT_CLOSED"}
|
|
||||||
bl_space_type = "PROPERTIES"
|
|
||||||
bl_region_type = "WINDOW"
|
|
||||||
bl_context = "scene"
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
scene = context.scene
|
|
||||||
props = scene.BIMProperties
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(props, "search_regex")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(props, "search_ignorecase")
|
|
||||||
|
|
||||||
layout.label(text="Global ID:")
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "global_id", text="")
|
|
||||||
row.operator("bim.select_global_id", text="", icon="VIEWZOOM")
|
|
||||||
|
|
||||||
layout.label(text="Attribute:")
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "search_attribute_name", text="")
|
|
||||||
row.prop(props, "search_attribute_value", text="")
|
|
||||||
row.operator("bim.select_attribute", text="", icon="VIEWZOOM")
|
|
||||||
row.operator("bim.colour_by_attribute", text="", icon="BRUSH_DATA")
|
|
||||||
|
|
||||||
layout.label(text="Pset:")
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "search_pset_name", text="")
|
|
||||||
row.prop(props, "search_prop_name", text="")
|
|
||||||
row.prop(props, "search_pset_value", text="")
|
|
||||||
row.operator("bim.select_pset", text="", icon="VIEWZOOM")
|
|
||||||
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator("bim.select_class")
|
|
||||||
row.operator("bim.select_type")
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_library(Panel):
|
class BIM_PT_library(Panel):
|
||||||
bl_label = "IFC BIM Server Library"
|
bl_label = "IFC BIM Server Library"
|
||||||
bl_idname = "BIM_PT_library"
|
bl_idname = "BIM_PT_library"
|
||||||
|
|||||||
Reference in New Issue
Block a user