From ee1e401719dca60b8c48ae16434d7a52890160e1 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 15 Mar 2023 18:58:06 +0500 Subject: [PATCH] Ifc Text - drop down menu to switch font size Added drop down menu to Ifc Text section in object properties where you can change text's size and it will automatically change it in `EPset_Annotation.Classes`. You can also preview it in viewport and it will write in IFC only after you finish editing. Still need to investigate `annotation.Annotator.resize_text(context.active_object)` in `refreshFontSize`. --- .../blenderbim/bim/module/drawing/data.py | 37 +++++++------ .../blenderbim/bim/module/drawing/operator.py | 9 ++++ .../blenderbim/bim/module/drawing/prop.py | 16 ++++-- .../blenderbim/bim/module/drawing/ui.py | 3 +- src/blenderbim/blenderbim/core/drawing.py | 1 + src/blenderbim/blenderbim/tool/drawing.py | 52 +++++++++++++++++-- 6 files changed, 90 insertions(+), 28 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/data.py b/src/blenderbim/blenderbim/bim/module/drawing/data.py index f6013fb8ce..d8bf1301ce 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/data.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/data.py @@ -125,6 +125,14 @@ class SchedulesData: return len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "SCHEDULE"]) +FONT_SIZES = { + 'small': 1.8, + 'regular': 2.5, + 'large': 3.5, + 'header': 5.0, + 'title': 7.0, +} + class DecoratorData: # stores 1 type of data per object data = {} @@ -194,24 +202,19 @@ class DecoratorData: if not element: return - classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes") - - font_sizes = { - 'small': 1.8, - 'regular': 2.5, - 'large': 3.5, - 'header': 5, - 'title': 7, - } - - # use `regular` as default - if classes: - tags = classes.split() - # prioritize smaller font sizes just like in svg - font_size_type = next((font_size_type for font_size_type in font_sizes if font_size_type in tags), 'regular') + if obj.BIMTextProperties.is_editing: + font_size = float(obj.BIMTextProperties.font_size) else: - font_size_type = 'regular' + classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes") + + # use `regular` as default + if classes: + classes_split = classes.split() + # prioritize smaller font sizes just like in svg + font_size_type = next((font_size_type for font_size_type in FONT_SIZES if font_size_type in classes_split), 'regular') + else: + font_size_type = 'regular' - font_size = font_sizes[font_size_type] + font_size = FONT_SIZES[font_size_type] cls.data[obj.name] = font_size return font_size diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index a6fe33cd35..97969e6c9a 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -39,6 +39,7 @@ import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.helper as helper +from blenderbim.bim.module.drawing.data import DecoratorData import blenderbim.bim.export_ifc from lxml import etree from mathutils import Vector @@ -1362,6 +1363,14 @@ class DisableEditingText(bpy.types.Operator, Operator): def _execute(self, context): core.disable_editing_text(tool.Drawing, obj=context.active_object) + # force update this object's font size for viewport display + DecoratorData.data.pop(context.object.name, None) + + # TODO: just needed some way to trigger UI update + # probably there is more proper way to do it + props = context.object.BIMTextProperties + props.font_size = props.font_size + class EditAssignedProduct(bpy.types.Operator, Operator): bl_idname = "bim.edit_assigned_product" diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index 5fb60497bd..3b4627da2c 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -25,7 +25,7 @@ import blenderbim.tool as tool import blenderbim.core.drawing as core import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.decoration as decoration -from blenderbim.bim.module.drawing.data import DrawingsData +from blenderbim.bim.module.drawing.data import DrawingsData, DecoratorData from pathlib import Path from blenderbim.bim.prop import Attribute, StrProperty from bpy.types import PropertyGroup @@ -228,10 +228,6 @@ def getVectorStyles(self, context): return vector_styles_enum -def refreshFontSize(self, context): - annotation.Annotator.resize_text(context.active_object) - - class Variable(PropertyGroup): name: StringProperty(name="Name") prop_key: StringProperty(name="Property Key") @@ -408,6 +404,16 @@ class BIMTextProperties(PropertyGroup): def get_box_alignment(self): return self.get("box_alignment", DEFAULT_BOX_ALIGNMENT) + + def refreshFontSize(self, context): + # force update this object's font size for viewport display + DecoratorData.data.pop(context.object.name, None) + + # TODO: line seems outdated and currently is just throwing error. remove? + # File "\blenderbim\bim\module\drawing\annotation.py", line 63, in resize_text + # font_size *= float(text_obj.data.BIMTextProperties.font_size) + # AttributeError: 'NoneType' object has no attribute 'BIMTextProperties' + # annotation.Annotator.resize_text(context.active_object) is_editing: BoolProperty(name="Is Editing", default=False) attributes: CollectionProperty(name="Attributes", type=Attribute) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py index ac46a030c2..58309cad1c 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/ui.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/ui.py @@ -355,8 +355,7 @@ class BIM_PT_text(Panel): row = self.layout.row(align=True) row.prop(props, 'font_size') - # a bit hacky way to align box alignment widget - rows = [self.layout.row(align=True) for i in range(3)] + rows = [] for i in range(9): if i % 3 == 0: split = rows[i//3].split(factor=0.1, align=True) diff --git a/src/blenderbim/blenderbim/core/drawing.py b/src/blenderbim/blenderbim/core/drawing.py index d1d839b974..3c0505d1ef 100644 --- a/src/blenderbim/blenderbim/core/drawing.py +++ b/src/blenderbim/blenderbim/core/drawing.py @@ -33,6 +33,7 @@ def edit_text(ifc, drawing, obj=None): attributes=drawing.export_text_literal_attributes(obj), ) drawing.update_text_value(obj) + drawing.update_text_size_pset(obj) drawing.disable_editing_text(obj) diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index 534bf6815b..5137332c9f 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -34,6 +34,8 @@ import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.helper as helper + +from blenderbim.bim.module.drawing.data import FONT_SIZES, DecoratorData from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT_POSITIONS @@ -463,6 +465,9 @@ class Drawing(blenderbim.core.tool.Drawing): box_alignment_mask[BOX_ALIGNMENT_POSITIONS.index(position_string)] = True props.box_alignment = box_alignment_mask + font_size = DecoratorData.get_ifc_text_font_size(obj) + props.font_size = str(font_size) + @classmethod def import_assigned_product(cls, obj): element = tool.Ifc.get_entity(obj) @@ -525,16 +530,55 @@ class Drawing(blenderbim.core.tool.Drawing): @classmethod def update_text_value(cls, obj): - element = cls.get_text_literal(obj) - if not element: + props = obj.BIMTextProperties + + ifc_literal = cls.get_text_literal(obj) + if not ifc_literal: return - value = element.Literal + value = ifc_literal.Literal product = cls.get_assigned_product(tool.Ifc.get_entity(obj)) if product: variables = {} for variable in re.findall("{{.*?}}", value): value = value.replace(variable, str(ifcopenshell.util.selector.get_element_value(product, variable[2:-2]) or "")) - obj.BIMTextProperties.value = value + props.value = value + + + @classmethod + def update_text_size_pset(cls, obj): + """ updates pset `EPset_Annotation.Classes` value + based on current font size from `obj.BIMTextProperties.font_size` + """ + props = obj.BIMTextProperties + element = tool.Ifc.get_entity(obj) + # updating text font size in EPset_Annotation.Classes + font_size = float(props.font_size) + font_size_str = next((key for key in FONT_SIZES if FONT_SIZES[key] == font_size), None) + classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes") + classes_split = classes.split() if classes else [] + + different_font_sizes = [c for c in classes_split if c in FONT_SIZES and c != font_size_str] + + # if there are different font sizes in classes already + # or if the current font size is not present in classes + # (except regular because it's default) + # then we do need to change pset value in ifc + if different_font_sizes \ + or (font_size_str not in classes_split and font_size_str != 'regular'): + classes_split = [c for c in classes_split if c not in FONT_SIZES] + [font_size_str] + classes = ' '.join(classes_split) + + ifc_file = tool.Ifc.get() + pset = tool.Pset.get_element_pset(element, "EPset_Annotation") + if not pset: + pset = ifcopenshell.api.run("pset.add_pset", ifc_file, product=element, name="EPset_Annotation") + ifcopenshell.api.run( + "pset.edit_pset", + ifc_file, + pset=pset, + properties={"Classes": classes}, + ) + # TODO below this point is highly experimental prototype code with no tests