Show ifc specs in file selector (#1980)

* Create simple parser for ifc header specs

* Refactor logic to be usable with other file selectors

* Fix parsing error
This commit is contained in:
Gorgious56
2022-01-12 00:01:49 +01:00
committed by GitHub
parent e81848dfba
commit 65b3960ab3
4 changed files with 74 additions and 34 deletions
+34
View File
@@ -97,3 +97,37 @@ def export_attributes(props, callback=None):
continue # Our job is done continue # Our job is done
attributes[prop.name] = prop.get_value() attributes[prop.name] = prop.get_value()
return attributes return attributes
class IFCHeaderSpecs:
def __init__(self, filepath: str):
# According to https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
self.description = ""
self.implementation_level = ""
self.name = ""
self.time_stamp = ""
self.author = ""
self.organization = ""
self.preprocessor_version = ""
self.originating_system = ""
self.authorization = ""
self.schema_name = ""
with open(filepath) as ifc_file:
max_lines_to_parse = 50
for _ in range(max_lines_to_parse):
line = next(ifc_file)
if line.startswith("FILE_DESCRIPTION"):
for i, part in enumerate(line.split("'")):
if i == 1:
self.description = part
elif i == 3:
self.implementation_level = part
elif line.startswith("FILE_NAME"):
for i, part in enumerate(line.split("'")):
if i == 1:
self.name = part
elif i == 3:
self.time_stamp = part
elif line.startswith("FILE_SCHEMA"):
self.schema_name = line.split("'")[1]
break
@@ -30,6 +30,7 @@ import blenderbim.tool as tool
import blenderbim.core.context import blenderbim.core.context
import blenderbim.core.owner import blenderbim.core.owner
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import IFCFileSelector
from blenderbim.bim import import_ifc from blenderbim.bim import import_ifc
from blenderbim.bim import export_ifc from blenderbim.bim import export_ifc
from ifcopenshell.api.context.data import Data as ContextData from ifcopenshell.api.context.data import Data as ContextData
@@ -126,7 +127,7 @@ class CreateProject(bpy.types.Operator):
IfcStore.file = data["file"] IfcStore.file = data["file"]
class SelectLibraryFile(bpy.types.Operator): class SelectLibraryFile(bpy.types.Operator, IFCFileSelector):
bl_idname = "bim.select_library_file" bl_idname = "bim.select_library_file"
bl_label = "Select Library File" bl_label = "Select Library File"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@@ -539,7 +540,7 @@ class DisableEditingHeader(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class LoadProject(bpy.types.Operator): class LoadProject(bpy.types.Operator, IFCFileSelector):
bl_idname = "bim.load_project" bl_idname = "bim.load_project"
bl_label = "Load Project" bl_label = "Load Project"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@@ -549,7 +550,7 @@ class LoadProject(bpy.types.Operator):
is_advanced: bpy.props.BoolProperty(name="Enable Advanced Mode", default=False) is_advanced: bpy.props.BoolProperty(name="Enable Advanced Mode", default=False)
def execute(self, context): def execute(self, context):
if not os.path.exists(self.filepath) or "ifc" not in os.path.splitext(self.filepath)[1].lower(): if not self.is_existing_ifc_file():
return {"FINISHED"} return {"FINISHED"}
context.scene.BIMProperties.ifc_file = self.filepath context.scene.BIMProperties.ifc_file = self.filepath
context.scene.BIMProjectProperties.is_loading = True context.scene.BIMProjectProperties.is_loading = True
@@ -561,6 +562,10 @@ class LoadProject(bpy.types.Operator):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"} return {"RUNNING_MODAL"}
def draw(self, context):
self.layout.prop(self, "is_advanced")
IFCFileSelector.draw(self, context)
class UnloadProject(bpy.types.Operator): class UnloadProject(bpy.types.Operator):
bl_idname = "bim.unload_project" bl_idname = "bim.unload_project"
+2 -26
View File
@@ -22,9 +22,9 @@ import json
import webbrowser import webbrowser
import ifcopenshell import ifcopenshell
import blenderbim.bim.handler import blenderbim.bim.handler
from pathlib import Path
from . import schema from . import schema
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import IFCFileSelector
from mathutils import Vector, Matrix, Euler from mathutils import Vector, Matrix, Euler
from math import radians from math import radians
@@ -39,7 +39,7 @@ class OpenUri(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class SelectIfcFile(bpy.types.Operator): class SelectIfcFile(bpy.types.Operator, IFCFileSelector):
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"} bl_options = {"REGISTER", "UNDO"}
@@ -47,11 +47,6 @@ class SelectIfcFile(bpy.types.Operator):
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"})
def is_existing_ifc_file(self, filepath=None):
if filepath is None:
filepath = self.filepath
return os.path.exists(filepath) and "ifc" in os.path.splitext(filepath)[1].lower()
def execute(self, context): def execute(self, context):
if self.is_existing_ifc_file(): if self.is_existing_ifc_file():
context.scene.BIMProperties.ifc_file = self.filepath context.scene.BIMProperties.ifc_file = self.filepath
@@ -61,25 +56,6 @@ class SelectIfcFile(bpy.types.Operator):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"} return {"RUNNING_MODAL"}
def draw(self, context):
# Access filepath & Directory https://blender.stackexchange.com/a/207665
params = context.space_data.params
# Decode byte string https://stackoverflow.com/a/47737082/
directory = Path(params.directory.decode("utf-8"))
filepath = os.path.join(directory, params.filename)
if self.is_existing_ifc_file(filepath):
self.draw_ifc_specs(filepath)
def draw_ifc_specs(self, filepath):
with open(filepath) as ifc_file:
max_lines_to_parse = 50
for _ in range(max_lines_to_parse):
line = next(ifc_file)
if line.startswith("FILE_SCHEMA(('") and line.endswith("'));\n"):
schema = line.split("'")[1]
self.layout.label(text=f"File Schema : {schema}")
break
class SelectDataDir(bpy.types.Operator): class SelectDataDir(bpy.types.Operator):
bl_idname = "bim.select_data_dir" bl_idname = "bim.select_data_dir"
+25
View File
@@ -18,9 +18,34 @@
import os import os
import bpy import bpy
from pathlib import Path
from . import ifc from . import ifc
from bpy.types import Panel from bpy.types import Panel
from bpy.props import StringProperty, IntProperty, BoolProperty from bpy.props import StringProperty, IntProperty, BoolProperty
from blenderbim.bim.helper import IFCHeaderSpecs
class IFCFileSelector:
def is_existing_ifc_file(self, filepath=None):
if filepath is None:
filepath = self.filepath
return os.path.exists(filepath) and "ifc" in os.path.splitext(filepath)[1].lower()
def draw(self, context):
# Access filepath & Directory https://blender.stackexchange.com/a/207665
params = context.space_data.params
# Decode byte string https://stackoverflow.com/a/47737082/
directory = Path(params.directory.decode("utf-8"))
filepath = os.path.join(directory, params.filename)
if self.is_existing_ifc_file(filepath):
box = self.layout.box()
box.label(text="IFC Header Specifications", icon="INFO")
ifc_specs = IFCHeaderSpecs(filepath)
for attr_name, attr_value in ifc_specs.__dict__.items():
if attr_value != "":
split = box.split()
split.label(text=attr_name.title().replace("_", " "))
split.label(text=str(attr_value))
class BIM_PT_section_plane(Panel): class BIM_PT_section_plane(Panel):