diff --git a/src/bonsai/bonsai/bim/module/drawing/__init__.py b/src/bonsai/bonsai/bim/module/drawing/__init__.py index 67a9ed0853..9f172ce2bb 100644 --- a/src/bonsai/bonsai/bim/module/drawing/__init__.py +++ b/src/bonsai/bonsai/bim/module/drawing/__init__.py @@ -45,6 +45,7 @@ classes = ( operator.CleanWireframes, operator.ContractSheet, operator.ConvertSVGToDXF, + operator.CopyTextToSelection, operator.CreateDrawing, operator.CreateSheets, operator.DisableAddAnnotationType, @@ -115,7 +116,6 @@ classes = ( prop.BIMCameraProperties, prop.ElementValueRow, prop.LiteralProps, - prop.LiteralApplySettings, prop.BIMTextProperties, prop.BIMAssignedProductProperties, prop.BIMAnnotationProperties, diff --git a/src/bonsai/bonsai/bim/module/drawing/data.py b/src/bonsai/bonsai/bim/module/drawing/data.py index ed457a7bbf..a4396d84c5 100644 --- a/src/bonsai/bonsai/bim/module/drawing/data.py +++ b/src/bonsai/bonsai/bim/module/drawing/data.py @@ -355,8 +355,6 @@ class DecoratorData: font_size = FONT_SIZES[font_size_type] symbol = tool.Drawing.get_annotation_symbol(element) newline_at = pset_data.get("Newline_At", 0) - reverse_list = pset_data.get("Reverse_List", False) - list_separator = pset_data.get("List_Separator") or ", " # other attributes literals = tool.Drawing.get_text_literal(obj, return_list=True) @@ -384,8 +382,6 @@ class DecoratorData: "FontSize": font_size, "Symbol": symbol, "Newline_At": newline_at, - "Reverse_List": reverse_list, - "List_Separator": list_separator, } @classmethod diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 4c52993aa0..d02e4c6c76 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -3181,9 +3181,20 @@ class EditText(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.edit_text" bl_label = "Edit Text" bl_description = "Save changes to the text annotation and\ndisable the text editing options" - bl_options = {"REGISTER", "UNDO"} + def _execute(self, context): + core.edit_text(tool.Drawing, obj=tool.Blender.get_active_object()) + tool.Blender.update_viewport() + + +class CopyTextToSelection(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.copy_text_to_selection" + bl_label = "Copy Text To Selection" + bl_description = "Copy text formatting or literals to selected objects" + bl_options = {"REGISTER", "UNDO"} + attribute: bpy.props.StringProperty() + def _execute(self, context): apply_objs = [ obj @@ -3191,7 +3202,12 @@ class EditText(bpy.types.Operator, tool.Ifc.Operator): if (element := tool.Ifc.get_entity(obj)) and tool.Drawing.is_annotation_object_type(element, ["TEXT", "TEXT_LEADER"]) ] - core.edit_text(tool.Drawing, attribute_obj=tool.Blender.get_active_object(), apply_objs=apply_objs) + core.copy_text_to_selection( + tool.Drawing, + attribute=self.attribute, + attribute_obj=tool.Blender.get_active_object(), + apply_objs=apply_objs, + ) tool.Blender.update_viewport() @@ -3207,8 +3223,6 @@ class EnableEditingText(bpy.types.Operator, tool.Ifc.Operator): props = tool.Drawing.get_text_props(obj) core.enable_editing_text(tool.Drawing, obj=obj) - props.ensure_literal_apply_settings(len(props.literals)) - text_element = tool.Ifc.get_entity(obj) assigned_product_entity = tool.Drawing.get_assigned_product(text_element) if text_element else None assigned_product_obj = tool.Ifc.get_object(assigned_product_entity) if assigned_product_entity else None @@ -3297,9 +3311,6 @@ class AddTextLiteral(bpy.types.Operator): box_alignment_mask = [False] * 9 box_alignment_mask[6] = True # bottom_left box_alignment literal_props.box_alignment = box_alignment_mask - - props.ensure_literal_apply_settings(len(props.literals)) - return {"FINISHED"} @@ -3318,9 +3329,6 @@ class RemoveTextLiteral(bpy.types.Operator): props = tool.Drawing.get_text_props(obj) props.literals.remove(self.literal_prop_id) tool.Blender.update_viewport() - - props.ensure_literal_apply_settings(len(props.literals)) - return {"FINISHED"} diff --git a/src/bonsai/bonsai/bim/module/drawing/prop.py b/src/bonsai/bonsai/bim/module/drawing/prop.py index 3b7040bc02..b323b8d41e 100644 --- a/src/bonsai/bonsai/bim/module/drawing/prop.py +++ b/src/bonsai/bonsai/bim/module/drawing/prop.py @@ -872,22 +872,20 @@ class LiteralProps(PropertyGroup): category_for_adding: str -class LiteralApplySettings(PropertyGroup): - literal_index: IntProperty(name="Literal Index") - apply_text_to_all: BoolProperty(name="Apply Text to All", default=False) - apply_path_to_all: BoolProperty(name="Apply Path to All", default=False) - apply_box_alignment_to_all: BoolProperty(name="Apply Box Alignment to All", default=False) - - if TYPE_CHECKING: - literal_index: int - apply_text_to_all: bool - apply_path_to_all: bool - apply_box_alignment_to_all: bool - - class BIMTextProperties(PropertyGroup): is_editing: BoolProperty(name="Is Editing", default=False) literals: CollectionProperty(name="Literals", type=LiteralProps) + newline_at: IntProperty(name="Newline At") + symbol: EnumProperty( # pyright: ignore[reportRedeclaration] + name="Symbol", + description="Symbol from symbols.svg to use for this text.", + items=[(s, s, "") for s in ["NO SYMBOL", "CUSTOM SYMBOL"] + tool.Drawing.DEFAULT_SYMBOLS], + default="NO SYMBOL", + ) + custom_symbol: StringProperty( # pyright: ignore[reportRedeclaration] + name="Custom Symbol", + description="Non-default symbol to use for this text.", + ) font_size: EnumProperty( items=[ ("1.8", "1.8 - Small", ""), @@ -899,52 +897,34 @@ class BIMTextProperties(PropertyGroup): default="2.5", name="Font Size", ) - newline_at: IntProperty(name="Newline At") - reverse_list: BoolProperty(name="Reverse List", description="Reverses the order of any list.", default=False) - list_separator: StringProperty( # pyright: ignore[reportRedeclaration] - name="List Separator", - description="Text used to separate lists. Uses a comma (, ) if empty.", + align_horizontal: EnumProperty( + items=[ + ("left", "Left", "", "ALIGN_LEFT", 0), + ("middle", "Middle", "", "ALIGN_CENTER", 1), + ("right", "Right", "", "ALIGN_RIGHT", 2), + ], + default="left", + name="Horizontal Alignment", ) - symbol: EnumProperty( # pyright: ignore[reportRedeclaration] - name="Symbol", - description="Symbol from symbols.svg to use for this text.", - items=[(s, s, "") for s in ["NO SYMBOL", "CUSTOM SYMBOL"] + tool.Drawing.DEFAULT_SYMBOLS], - default="NO SYMBOL", + align_vertical: EnumProperty( + items=[ + ("top", "Top", "", "ALIGN_TOP", 0), + ("middle", "Middle", "", "ALIGN_MIDDLE", 1), + ("bottom", "Bottom", "", "ALIGN_BOTTOM", 2), + ], + default="middle", + name="Vertical Alignment", ) - custom_symbol: StringProperty( # pyright: ignore[reportRedeclaration] - name="Custom Symbol", - description="Non-default symbol to use for this text.", - ) - - apply_font_size_to_all: BoolProperty( - name="Apply Font Size to All", description="Apply font size changes to all selected text objects", default=False - ) - apply_newline_to_all: BoolProperty( - name="Apply Newline to All", description="Apply newline changes to all selected text objects", default=False - ) - - literal_apply_settings: CollectionProperty(name="Literal Apply Settings", type=LiteralApplySettings) - - def ensure_literal_apply_settings(self, literal_count: int): - """Ensure we have apply settings for all literals""" - while len(self.literal_apply_settings) > literal_count: - self.literal_apply_settings.remove(len(self.literal_apply_settings) - 1) - - while len(self.literal_apply_settings) < literal_count: - setting = self.literal_apply_settings.add() - setting.literal_index = len(self.literal_apply_settings) - 1 if TYPE_CHECKING: is_editing: bool literals: bpy.types.bpy_prop_collection_idprop[LiteralProps] - font_size: str newline_at: int - reverse_list: bool - list_separator: str symbol: Union[str, Literal["NO SYMBOL", "CUSTOM SYMBOL"]] custom_symbol: str - apply_font_size_to_all: bool - apply_newline_to_all: bool + font_size: str + align_horizontal: str + align_vertical: str def get_symbol(self) -> Union[str, None]: if self.symbol == "NO SYMBOL": @@ -979,8 +959,6 @@ class BIMTextProperties(PropertyGroup): "FontSize": float(self.font_size), "Newline_At": int(self.newline_at), "Symbol": self.get_symbol(), - "Reverse_List": self.reverse_list, - "List_Separator": self.list_separator or ", ", } return text_data diff --git a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py index dac8e54a61..ef64fdefc6 100644 --- a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py +++ b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py @@ -989,11 +989,6 @@ class SvgWriter: symbol = tool.Drawing.get_annotation_symbol(element) newline_at = tool.Drawing.get_newline_at(element) - # Get reverse_list and list_separator from EPset_Annotation - pset_data = ifcopenshell.util.element.get_pset(element, "EPset_Annotation") or {} - reverse_list = pset_data.get("Reverse_List", False) - list_separator = pset_data.get("List_Separator") or ", " - template_text_fields = [] if symbol: symbol_transform = self.get_symbol_transform(text_position_svg_str, angle, text_obj) @@ -1010,7 +1005,7 @@ class SvgWriter: # NOTE: zip makes sure that we iterate over the shortest list for field, text_literal in zip(template_text_fields, text_literals): field.text = tool.Drawing.replace_text_literal_variables( - text_literal.Literal, product or element, reverse_list, list_separator + text_literal.Literal, product or element ) field.attrib["class"] = classes_str @@ -1030,9 +1025,7 @@ class SvgWriter: line_number = 0 for text_literal in text_literals: - text = tool.Drawing.replace_text_literal_variables( - text_literal.Literal, product or element, reverse_list, list_separator - ) + text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element) text_segments = parse_markdown_it(text) diff --git a/src/bonsai/bonsai/bim/module/drawing/ui.py b/src/bonsai/bonsai/bim/module/drawing/ui.py index 45ae50beb4..556459b8b6 100644 --- a/src/bonsai/bonsai/bim/module/drawing/ui.py +++ b/src/bonsai/bonsai/bim/module/drawing/ui.py @@ -644,58 +644,56 @@ class BIM_PT_text(Panel): row.operator("bim.add_text_literal", icon="ADD", text="Add Literal") else: row.operator("bim.edit_text", icon="CHECKMARK") - row.operator("bim.add_text_literal", icon="ADD", text="") row.operator("bim.disable_editing_text", icon="CANCEL", text="") row = self.layout.row(align=True) row.prop(props, "font_size") - row.prop(props, "apply_font_size_to_all", text="", icon="COPYDOWN") + row.operator("bim.copy_text_to_selection", text="", icon="COPYDOWN").attribute = "FONT_SIZE" + row = self.layout.row() + row.label(text="Alignment") + row.prop(props, "align_horizontal", text="", expand=True) + row.prop(props, "align_vertical", text="", expand=True) + row.operator("bim.copy_text_to_selection", text="", icon="COPYDOWN").attribute = "ALIGNMENT" row = self.layout.row(align=True) row.prop(props, "newline_at") - row = self.layout.row(align=True) - row.prop(props, "reverse_list") - row = self.layout.row(align=True) - row.prop(props, "list_separator") + row.operator("bim.copy_text_to_selection", text="", icon="COPYDOWN").attribute = "WRAP_LENGTH" row = self.layout.row(align=True) row.prop(props, "symbol") if props.symbol == "CUSTOM SYMBOL": row = self.layout.row(align=True) row.prop(props, "custom_symbol", text="") - row.prop(props, "apply_newline_to_all", text="", icon="COPYDOWN") select_op = row.operator("bim.select_similar_text_literal_value", text="", icon="RESTRICT_SELECT_OFF") select_op.literal_value = str(props.newline_at) select_op.attribute_type = "newline" + row.operator("bim.copy_text_to_selection", text="", icon="COPYDOWN").attribute = "SYMBOL" + + row = self.layout.row(align=True) + row.label(text="Literals:") + row.operator("bim.copy_text_to_selection", text="", icon="COPYDOWN").attribute = "LITERALS" + row.operator("bim.add_text_literal", icon="ADD", text="") for i, literal_props in enumerate(props.literals): box = self.layout.box() - - row = box.row(align=True) - row.label(text=f"Literal[{i}]:") - if i > 0: - row.operator("bim.order_text_literal_up", icon="TRIA_UP", text="").literal_prop_id = i - if i < len(props.literals) - 1: - row.operator("bim.order_text_literal_down", icon="TRIA_DOWN", text="").literal_prop_id = i - row.operator("bim.remove_text_literal", icon="X", text="").literal_prop_id = i - - if len(literal_props.attributes) > 0 and i < len(props.literal_apply_settings): + if len(literal_props.attributes): row = box.row(align=True) bonsai.bim.helper.draw_attribute(literal_props.attributes[0], row, enable_search=True) + if i > 0: + row.operator("bim.order_text_literal_up", icon="TRIA_UP", text="").literal_prop_id = i + if i < len(props.literals) - 1: + row.operator("bim.order_text_literal_down", icon="TRIA_DOWN", text="").literal_prop_id = i + row.operator("bim.remove_text_literal", icon="X", text="").literal_prop_id = i expand_icon = "DOWNARROW_HLT" if getattr(literal_props, "show_element_values", False) else "RIGHTARROW" op = row.operator("bim.toggle_element_values_panel", icon=expand_icon, text="") op.literal_prop_id = i - row.prop(props.literal_apply_settings[i], "apply_text_to_all", text="", icon="COPYDOWN") - element = tool.Ifc.get_entity(obj) assigned_element = tool.Drawing.get_assigned_product(element) or element resolved_value = tool.Drawing.replace_text_literal_variables( literal_props.attributes[0].string_value, assigned_element, - props.reverse_list, - props.list_separator, ) row = box.row(align=True) row.label(text="CurrentValue:") @@ -779,8 +777,6 @@ class BIM_PT_text(Panel): else: row.prop(attr, "string_value", text="Path") select_value = attr.string_value - if i < len(props.literal_apply_settings): - row.prop(props.literal_apply_settings[i], "apply_path_to_all", text="", icon="COPYDOWN") other_attributes = [a for a in literal_props.attributes[2:] if a.name != "BoxAlignment"] if other_attributes: @@ -800,10 +796,6 @@ class BIM_PT_text(Panel): col = row.column(align=True) alignment_label_row = col.row(align=True) alignment_label_row.label(text=" Text box alignment:") - if i < len(props.literal_apply_settings): - alignment_label_row.prop( - props.literal_apply_settings[i], "apply_box_alignment_to_all", text="", icon="COPYDOWN" - ) box_alignment_value = ( literal_props.attributes[ @@ -824,61 +816,52 @@ class BIM_PT_text(Panel): props = tool.Drawing.get_text_props(obj) if props.is_editing: - self.draw_text_editing_ui(context) - else: - text_data = DecoratorData.get_text_data(obj) + return self.draw_text_editing_ui(context) + text_data = DecoratorData.get_text_data(obj) - row = self.layout.row() - row.operator("bim.enable_editing_text", icon="GREASEPENCIL") + row = self.layout.row() + row.operator("bim.enable_editing_text", icon="GREASEPENCIL") - row = self.layout.row(align=True) - row.label(text="FontSize") - click_op = row.operator( - "bim.select_similar_text_literal_value", text=str(text_data["FontSize"]), emboss=False - ) - click_op.literal_value = str(text_data["FontSize"]) - click_op.attribute_type = "font_size" - click_op.display_text = str(text_data["FontSize"]) + row = self.layout.row(align=True) + row.label(text="FontSize") + click_op = row.operator("bim.select_similar_text_literal_value", text=str(text_data["FontSize"]), emboss=False) + click_op.literal_value = str(text_data["FontSize"]) + click_op.attribute_type = "font_size" + click_op.display_text = str(text_data["FontSize"]) - row = self.layout.row(align=True) - row.label(text="Newline_At") - click_op = row.operator( - "bim.select_similar_text_literal_value", text=str(text_data["Newline_At"]), emboss=False - ) - click_op.literal_value = str(text_data["Newline_At"]) - click_op.attribute_type = "newline" - click_op.display_text = str(text_data["Newline_At"]) - row = self.layout.row(align=True) - row.label(text="Reverse_List") - row.label(text=str(text_data["Reverse_List"])) - row = self.layout.row(align=True) - row.label(text="List_Separator") - row.label(text=str(text_data["List_Separator"])) + row = self.layout.row(align=True) + row.label(text="Newline_At") + click_op = row.operator( + "bim.select_similar_text_literal_value", text=str(text_data["Newline_At"]), emboss=False + ) + click_op.literal_value = str(text_data["Newline_At"]) + click_op.attribute_type = "newline" + click_op.display_text = str(text_data["Newline_At"]) - for i, literal_data in enumerate(text_data["Literals"]): - box = self.layout.box() - box.label(text=f"Literal[{i}]:") + for i, literal_data in enumerate(text_data["Literals"]): + box = self.layout.box() + box.label(text=f"Literal[{i}]:") - # Combine both approaches: clickable attributes from PR #7292 and display from PR #7106 - for attribute in literal_data: - row = box.row(align=True) - row.label(text=attribute) - click_op = row.operator( - "bim.select_similar_text_literal_value", - text=str(literal_data[attribute]), - emboss=False, - ) - click_op.literal_value = str(literal_data[attribute]) - click_op.literal_index = i - if attribute == "Literal": - click_op.attribute_type = "literal" - elif attribute == "Path": - click_op.attribute_type = "path" - elif attribute == "BoxAlignment": - click_op.attribute_type = "box_alignment" - else: - click_op.attribute_type = "text" - click_op.display_text = str(literal_data[attribute]) + # Combine both approaches: clickable attributes from PR #7292 and display from PR #7106 + for attribute in literal_data: + row = box.row(align=True) + row.label(text=attribute) + click_op = row.operator( + "bim.select_similar_text_literal_value", + text=str(literal_data[attribute]), + emboss=False, + ) + click_op.literal_value = str(literal_data[attribute]) + click_op.literal_index = i + if attribute == "Literal": + click_op.attribute_type = "literal" + elif attribute == "Path": + click_op.attribute_type = "path" + elif attribute == "BoxAlignment": + click_op.attribute_type = "box_alignment" + else: + click_op.attribute_type = "text" + click_op.display_text = str(literal_data[attribute]) class BIM_UL_drawinglist(bpy.types.UIList): diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index eb2c47f1dc..42b0f77fbb 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -38,13 +38,42 @@ def disable_editing_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> drawing.disable_editing_text(obj) -def edit_text(drawing: type[tool.Drawing], attribute_obj: bpy.types.Object, apply_objs: list[bpy.types.Object]) -> None: - literal_attributes = drawing.export_text_literal_attributes(attribute_obj) +def edit_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None: + literal_attributes = drawing.export_text_literal_attributes(obj) + drawing.edit_text_font_size(obj, drawing.export_font_size(obj)) + drawing.edit_text_wrap_length(obj, drawing.export_wrap_length(obj)) + drawing.edit_text_symbol(obj, drawing.export_symbol(obj)) + drawing.edit_text_literals(obj, literal_attributes) + drawing.disable_editing_text(obj) + + +def copy_text_to_selection( + drawing: type[tool.Drawing], + attribute: Literal["FONT_SIZE", "ALIGNMENT", "WRAP_LENGTH", "SYMBOL", "LITERALS"], + attribute_obj: bpy.types.Object, + apply_objs: list[bpy.types.Object], +) -> None: + if attribute == "FONT_SIZE": + data = drawing.export_font_size(attribute_obj) + elif attribute == "ALIGNMENT": + data = drawing.export_alignment(attribute_obj) + elif attribute == "WRAP_LENGTH": + data = drawing.export_wrap_length(attribute_obj) + elif attribute == "SYMBOL": + data = drawing.export_symbol(attribute_obj) + elif attribute == "LITERALS": + data = drawing.export_text_literal_attributes(attribute_obj) for obj in apply_objs: - drawing.edit_text_literals(obj, literal_attributes) - # TODO: font size should be part of a separate set of formatting controls, not part of text editing - drawing.update_text_size_pset(obj) - drawing.update_text_annotation_properties(obj) + if attribute == "FONT_SIZE": + drawing.edit_text_font_size(obj, data) + elif attribute == "ALIGNMENT": + drawing.edit_text_alignment(obj, data) + elif attribute == "WRAP_LENGTH": + drawing.edit_text_wrap_length(obj, data) + elif attribute == "SYMBOL": + drawing.edit_text_symbol(obj, data) + elif attribute == "LITERALS": + drawing.edit_text_literals(obj, data) drawing.disable_editing_text(obj) diff --git a/src/bonsai/bonsai/core/tool.py b/src/bonsai/bonsai/core/tool.py index a34de4d4fe..a0b6290b12 100644 --- a/src/bonsai/bonsai/core/tool.py +++ b/src/bonsai/bonsai/core/tool.py @@ -334,6 +334,11 @@ class Drawing: def disable_editing_sheets(cls): pass def disable_editing_text(cls, obj): pass def does_file_exist(cls, uri): pass + def edit_text_alignment(cls, obj, alignment): pass + def edit_text_font_size(cls, obj, size): pass + def edit_text_literals(cls, obj, literals): pass + def edit_text_symbol(cls, obj, symbol): pass + def edit_text_wrap_length(cls, obj, wrap_length): pass def enable_editing(cls, obj): pass def enable_editing_assigned_product(cls, obj): pass def enable_editing_drawings(cls): pass @@ -403,8 +408,6 @@ class Drawing: def show_decorations(cls): pass def sync_object_placement(cls, obj): pass def update_embedded_svg_location(cls, uri, old_location, new_location): pass - def update_text_annotation_properties(cls, obj): pass - def update_text_size_pset(cls, obj): pass @interface diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index a0a45b403a..3b98b92611 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -608,6 +608,25 @@ class Drawing(bonsai.core.tool.Drawing): literals.append(literal_data) return literals + @classmethod + def export_font_size(cls, obj: bpy.types.Object) -> str: + return float(cls.get_text_props(obj).font_size) + + @classmethod + def export_alignment(cls, obj: bpy.types.Object) -> str: + props = cls.get_text_props(obj) + if (alignment := props.align_vertical + "-" + props.align_horizontal) == "middle-middle": + return "center" + return alignment + + @classmethod + def export_wrap_length(cls, obj: bpy.types.Object) -> str: + return cls.get_text_props(obj).newline_at + + @classmethod + def export_symbol(cls, obj: bpy.types.Object) -> str: + return cls.get_text_props(obj).get_symbol() + @classmethod def create_annotation_context( cls, target_view: str, object_type: Optional[str] = None @@ -1181,8 +1200,6 @@ class Drawing(bonsai.core.tool.Drawing): props.font_size = str(text_data["FontSize"]) props.newline_at = text_data["Newline_At"] props.set_symbol(text_data["Symbol"]) - props.reverse_list = text_data["Reverse_List"] - props.list_separator = text_data["List_Separator"] @classmethod def import_assigned_product(cls, obj: bpy.types.Object) -> None: @@ -1279,7 +1296,7 @@ class Drawing(bonsai.core.tool.Drawing): props.should_draw_decorations = True @classmethod - def update_text_size_pset(cls, obj: bpy.types.Object) -> None: + def edit_text_font_size(cls, obj: bpy.types.Object, font_size: float) -> None: """updates pset `EPset_Annotation.Classes` value based on current font size from `obj.BIMTextProperties.font_size` """ @@ -1289,8 +1306,9 @@ class Drawing(bonsai.core.tool.Drawing): element = tool.Ifc.get_entity(obj) assert element # updating text font size in EPset_Annotation.Classes - font_size = float(props.font_size) + print("we got", font_size, repr(font_size)) font_size_str = next((key for key in FONT_SIZES if FONT_SIZES[key] == font_size), None) + print("so", font_size_str) classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes") assert isinstance(classes, Union[str, None]) classes_split = classes.split() if classes else [] @@ -1310,34 +1328,32 @@ class Drawing(bonsai.core.tool.Drawing): pset = tool.Pset.get_element_pset(element, "EPset_Annotation") if not pset: pset = ifcopenshell.api.pset.add_pset(ifc_file, product=element, name="EPset_Annotation") - ifcopenshell.api.pset.edit_pset( - ifc_file, - pset=pset, - properties={"Classes": classes}, - ) + ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={"Classes": classes}) @classmethod - def update_text_annotation_properties(cls, obj: bpy.types.Object) -> None: - """Update all EPset_Annotation properties from the text props""" - props = cls.get_text_props(obj) + def edit_text_wrap_length(cls, obj: bpy.types.Object, wrap_length: int) -> None: element = tool.Ifc.get_entity(obj) - assert element - ifc_file = tool.Ifc.get() pset = tool.Pset.get_element_pset(element, "EPset_Annotation") if not pset: pset = ifcopenshell.api.pset.add_pset(ifc_file, product=element, name="EPset_Annotation") + ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={"Newline_At": wrap_length}) - ifcopenshell.api.pset.edit_pset( - ifc_file, - pset=pset, - properties={ - "Newline_At": int(props.newline_at), - "Symbol": props.get_symbol(), - "Reverse_List": props.reverse_list, - "List_Separator": props.list_separator or "", - }, - ) + @classmethod + def edit_text_symbol(cls, obj: bpy.types.Object, symbol: str) -> None: + element = tool.Ifc.get_entity(obj) + ifc_file = tool.Ifc.get() + pset = tool.Pset.get_element_pset(element, "EPset_Annotation") + if not pset: + pset = ifcopenshell.api.pset.add_pset(ifc_file, product=element, name="EPset_Annotation") + ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={"Symbol": symbol}) + + @classmethod + def edit_text_alignment(cls, obj: bpy.types.Object, alignment: str) -> None: + ifc_literals = cls.get_text_literal(obj, return_list=True) + for ifc_literal in ifc_literals or []: + if ifc_literal.is_a("IfcTextLiteralWithExtent"): + ifc_literal.BoxAlignment = alignment # TODO below this point is highly experimental prototype code with no tests @@ -2081,13 +2097,9 @@ class Drawing(bonsai.core.tool.Drawing): cls, text: str, product: Optional[ifcopenshell.entity_instance] = None, - reverse_list: bool = False, - list_separator: str = ", ", ) -> str: if not product: return text - if list_separator: - list_separator = list_separator.encode().decode("unicode_escape") for command in re.findall("``.*?``", text): original_command = command @@ -2102,10 +2114,7 @@ class Drawing(bonsai.core.tool.Drawing): for variable in re.findall("{{.*?}}", text): value = ifcopenshell.util.selector.get_element_value(product, variable[2:-2]) if isinstance(value, (list, tuple)): - if reverse_list: - value = list_separator.join(str(v) for v in reversed(value)) - else: - value = list_separator.join(str(v) for v in value) + value = ", ".join(str(v) for v in value) text = text.replace(variable, str(value)) return text