From 4bde423c50ec5d97ff6b63413251abf8c6a32411 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 21 Nov 2024 18:10:13 +0500 Subject: [PATCH] Date picker UI for IfcDate type attributes Example - https://imgchest.com/p/5xy2bekl3yl set_prop_from_path method got from https://blenderartists.org/t/set-property-using-path-from-path-from-id-prop-path-resolve/1559166 --- src/bonsai/bonsai/bim/helper.py | 6 ++++++ .../bonsai/bim/module/sequence/operator.py | 16 ++++++---------- src/bonsai/bonsai/tool/blender.py | 17 ++++++++++++++++- src/bonsai/bonsai/tool/sequence.py | 7 +------ 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/bonsai/bonsai/bim/helper.py b/src/bonsai/bonsai/bim/helper.py index 6b94bd5335..4d34f271ad 100644 --- a/src/bonsai/bonsai/bim/helper.py +++ b/src/bonsai/bonsai/bim/helper.py @@ -95,6 +95,10 @@ def draw_attribute( if attribute.is_uri: op = layout.operator("bim.select_uri_attribute", text="", icon="FILE_FOLDER") op.data_path = attribute.path_from_id("string_value") + elif attribute.special_type == "DATE": + op = layout.operator("bim.datepicker", text="", icon="TIME") + op.target_prop = attribute.path_from_id("string_value") + if attribute.is_optional: layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") @@ -161,6 +165,8 @@ def import_attribute( new.string_value = "" if new.is_null else str(data[attribute.name()]).replace("\n", "\\n") if attribute.type_of_attribute().declared_type().name() == "IfcURIReference": new.is_uri = True + elif attribute.type_of_attribute()._is("IfcDate"): + new.special_type = "DATE" elif data_type == "boolean": new.bool_value = False if new.is_null else bool(data[attribute.name()]) elif data_type == "integer": diff --git a/src/bonsai/bonsai/bim/module/sequence/operator.py b/src/bonsai/bonsai/bim/module/sequence/operator.py index 3478bddf1a..a855d8d79d 100644 --- a/src/bonsai/bonsai/bim/module/sequence/operator.py +++ b/src/bonsai/bonsai/bim/module/sequence/operator.py @@ -1215,17 +1215,13 @@ class Bonsai_DatePicker(bpy.types.Operator): context.scene.DatePickerProperties.selected_date = self.display_date return context.window_manager.invoke_props_dialog(self) - def get_scene_prop(self, prop_path): - prop = bpy.context.scene.get(prop_path.split(".")[0]) - for part in prop_path.split(".")[1:]: - if part: - prop = prop.get(part) - return prop + def get_scene_prop(self, prop_path: str) -> str: + scene = bpy.context.scene + return scene.path_resolve(prop_path) - def set_scene_prop(self, prop_path, value): - parent = self.get_scene_prop(prop_path[: prop_path.rfind(".")]) - prop = prop_path.split(".")[-1] - parent[prop] = value + def set_scene_prop(self, prop_path: str, value: str) -> None: + scene = bpy.context.scene + tool.Blender.set_prop_from_path(scene, prop_path, value) class Bonsai_DatePickerSetDate(bpy.types.Operator): diff --git a/src/bonsai/bonsai/tool/blender.py b/src/bonsai/bonsai/tool/blender.py index a4a7749c54..993f56ab3f 100644 --- a/src/bonsai/bonsai/tool/blender.py +++ b/src/bonsai/bonsai/tool/blender.py @@ -31,7 +31,7 @@ import importlib from mathutils import Vector from pathlib import Path from bonsai.bim.ifc import IFC_CONNECTED_TYPE -from typing import Any, Optional, Union, Literal, Iterable, Callable +from typing import Any, Optional, Union, Literal, Iterable, Callable, TypeVar from typing_extensions import assert_never @@ -1257,3 +1257,18 @@ class Blender(bonsai.core.tool.Blender): obj.constraints.clear() obj.matrix_world = matrix return True + + @classmethod + def set_prop_from_path(cls, bpy_object: bpy.types.bpy_struct, prop_path: str, value: Any) -> None: + """Set `data_block` property value using path from `path_from_id`.""" + + T = TypeVar("T", bound=bpy.types.bpy_struct) + + def path_resolve(obj: T, prop_path: str) -> tuple[T, str]: + if "." in prop_path: + extra_path, prop_path = prop_path.rsplit(".", 1) + obj = obj.path_resolve(extra_path) + return obj, prop_path + + obj, path = path_resolve(bpy_object, prop_path) + setattr(obj, path, value) diff --git a/src/bonsai/bonsai/tool/sequence.py b/src/bonsai/bonsai/tool/sequence.py index 24e54ffb7f..175e588365 100644 --- a/src/bonsai/bonsai/tool/sequence.py +++ b/src/bonsai/bonsai/tool/sequence.py @@ -506,15 +506,10 @@ class Sequence(bonsai.core.tool.Sequence): @classmethod def load_work_time_attributes(cls, work_time: ifcopenshell.entity_instance) -> None: - def callback(name, prop, data): - if name in ["Start", "Finish"]: - prop.string_value = "" if prop.is_null else data[name] - return True - props = bpy.context.scene.BIMWorkCalendarProperties props.work_time_attributes.clear() - bonsai.bim.helper.import_attributes2(work_time, props.work_time_attributes, callback) + bonsai.bim.helper.import_attributes2(work_time, props.work_time_attributes) @classmethod def enable_editing_work_time(cls, work_time: ifcopenshell.entity_instance) -> None: