diff --git a/src/blenderbim/blenderbim/bim/module/patch/__init__.py b/src/blenderbim/blenderbim/bim/module/patch/__init__.py index d8a39535d2..bbab2b2396 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/patch/__init__.py @@ -5,6 +5,7 @@ classes = ( operator.SelectIfcPatchInput, operator.SelectIfcPatchOutput, operator.ExecuteIfcPatch, + operator.PopulatePatchArguments, prop.BIMPatchProperties, ui.BIM_PT_patch, ) diff --git a/src/blenderbim/blenderbim/bim/module/patch/operator.py b/src/blenderbim/blenderbim/bim/module/patch/operator.py index 5015942931..fbad98702e 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/operator.py +++ b/src/blenderbim/blenderbim/bim/module/patch/operator.py @@ -1,6 +1,7 @@ import os import bpy import json +from .helper import extract_docs class SelectIfcPatchInput(bpy.types.Operator): @@ -58,3 +59,49 @@ class ExecuteIfcPatch(bpy.types.Operator): } ) return {"FINISHED"} + + +class PopulatePatchArguments(bpy.types.Operator): + bl_idname = "bim.populate_patch_arguments" + bl_label = "Update IFC Patch arguments" + TYPE_BINDINGS = { + "str": "string", + + } + recipe: bpy.props.StringProperty() + + def execute(self, context): + import importlib + import ifcpatch + + patch_args = context.scene.BIMPatchProperties.ifc_patch_args_attr + patch_args.clear() + recipe = self.recipe + spec = importlib.util.spec_from_file_location(recipe, f"{ifcpatch.__path__[0]}/recipes/{recipe}.py") + patcher = importlib.util.module_from_spec(spec) + try: + spec.loader.exec_module(patcher) + try: + docs = extract_docs(patcher.Patcher, boilerplate_args=("src", "file", "logger", "args")) + if "inputs" in docs: + for arg_name in docs["inputs"]: + arg_info = docs["inputs"][arg_name] + new_attr = patch_args.add() + new_attr.data_type = self.TYPE_BINDINGS[arg_info["type"]] + new_attr.name = arg_name + if new_attr.data_type == "string": + new_attr.string_value = arg_info.get("default", "") + elif new_attr.data_type == "float": + new_attr.float_value = arg_info.get("default", 0) + elif new_attr.data_type == "integer": + new_attr.int_value = arg_info.get("default", 0) + elif new_attr.data_type == "boolean": + new_attr.bool_value = arg_info.get("default", False) + + new_attr.description =arg_info.get("description", "") + + except AttributeError as e: + print(e) + except ModuleNotFoundError as e: + print("Error : " + str(e) + "in " + str(patcher)) + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/patch/prop.py b/src/blenderbim/blenderbim/bim/module/patch/prop.py index bfee66f4b0..4214999052 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/prop.py +++ b/src/blenderbim/blenderbim/bim/module/patch/prop.py @@ -41,3 +41,4 @@ class BIMPatchProperties(PropertyGroup): ifc_patch_input: StringProperty(default="", name="IFC Patch Input IFC") ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC") ifc_patch_args: StringProperty(default="", name="Arguments") + ifc_patch_args_attr: CollectionProperty(type=Attribute, name="Arguments") diff --git a/src/blenderbim/blenderbim/bim/module/patch/ui.py b/src/blenderbim/blenderbim/bim/module/patch/ui.py index 49600d2d1c..a4805d88a1 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/ui.py +++ b/src/blenderbim/blenderbim/bim/module/patch/ui.py @@ -1,8 +1,12 @@ import bpy -from bpy.types import Panel +import importlib +import importlib.util +import ifcpatch +from .helper import extract_docs +from .operator import PopulatePatchArguments -class BIM_PT_patch(Panel): +class BIM_PT_patch(bpy.types.Panel): bl_label = "IFC Patch" bl_idname = "BIM_PT_patch" bl_options = {"DEFAULT_CLOSED"} @@ -16,17 +20,48 @@ class BIM_PT_patch(Panel): scene = context.scene props = scene.BIMPatchProperties - row = layout.row() - row.prop(props, "ifc_patch_recipes") + row.prop(props, "ifc_patch_recipes") + + recipe = props.ifc_patch_recipes + + spec = importlib.util.spec_from_file_location(recipe, f"{ifcpatch.__path__[0]}/recipes/{recipe}.py") + patcher = importlib.util.module_from_spec(spec) + try: + spec.loader.exec_module(patcher) + try: + docs = extract_docs(patcher.Patcher, boilerplate_args=("src", "file", "logger", "args")) + if "name" in docs: + layout.label(text=docs["name"]) + if "description" in docs: + for line in docs["description"].split("\n"): + layout.label(text=line) + except AttributeError as e: + print(e) + except ModuleNotFoundError as e: + print("Error : " + str(e) + "in " + str(patcher)) + row = layout.row(align=True) row.prop(props, "ifc_patch_input") row.operator("bim.select_ifc_patch_input", icon="FILE_FOLDER", text="") row = layout.row(align=True) row.prop(props, "ifc_patch_output") row.operator("bim.select_ifc_patch_output", icon="FILE_FOLDER", text="") - row = layout.row() - row.prop(props, "ifc_patch_args") + + op = layout.operator(PopulatePatchArguments.bl_idname) + op.recipe = recipe + if props.ifc_patch_args_attr: + for attr in props.ifc_patch_args_attr: + if attr.data_type == "string": + box = layout.box() + box.row().prop(attr, "string_value", text=attr.name) + if attr.description != "": + row = box.row(align=True) + row.label(text="Description") + row.label(text = attr.description) + else: + row = layout.row() + row.prop(props, "ifc_patch_args") row = layout.row() op = row.operator("bim.execute_ifc_patch")