Option to change text symbol from general text editing UI

Example - https://files.catbox.moe/kxyepa.mp4
This commit is contained in:
Andrej730
2025-09-09 10:09:56 +05:00
parent 876c5ac2e6
commit 679fa6d876
8 changed files with 77 additions and 9 deletions
@@ -601,8 +601,7 @@ class BaseDecorator:
props = tool.Drawing.get_text_props(obj)
text_data = DecoratorData.data["text"].get(obj.name, None)
if props.is_editing:
# Still use original `text_data`, because of the "Symbol".
text_data = text_data | props.get_text_edited_data()
text_data = props.get_text_edited_data()
literals_data = text_data["Literals"]
symbol = text_data["Symbol"]
newline_at = text_data["Newline_At"]
@@ -738,12 +738,43 @@ class BIMTextProperties(PropertyGroup):
name="Font Size",
)
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.",
)
if TYPE_CHECKING:
is_editing: bool
literals: bpy.types.bpy_prop_collection_idprop[LiteralProps]
font_size: str
newline_at: int
symbol: Union[str, Literal["NO SYMBOL", "CUSTOM SYMBOL"]]
custom_symbol: str
def get_symbol(self) -> Union[str, None]:
if self.symbol == "NO SYMBOL":
return None
elif self.symbol == "CUSTOM SYMBOL":
return self.custom_symbol or None
else:
return self.symbol
def set_symbol(self, symbol: Union[str, None]):
if not symbol:
self.property_unset("symbol")
self.property_unset("custom_symbol")
elif symbol in tool.Drawing.DEFAULT_SYMBOLS:
self.symbol = symbol
self.property_unset("custom_symbol")
else:
self.symbol = "CUSTOM SYMBOL"
self.custom_symbol = symbol
def get_text_edited_data(self) -> dict[str, Any]:
"""should be called only if `is_editing`
@@ -758,6 +789,7 @@ class BIMTextProperties(PropertyGroup):
"Literals": literals_data,
"FontSize": float(self.font_size),
"Newline_At": int(self.newline_at),
"Symbol": self.get_symbol(),
}
return text_data
@@ -591,6 +591,12 @@ class BIM_PT_text(Panel):
row = self.layout.row(align=True)
row.prop(props, "newline_at")
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="")
for i, literal_props in enumerate(props.literals):
box = self.layout.box()
row = self.layout.row(align=True)
+1 -1
View File
@@ -39,7 +39,7 @@ def disable_editing_text(drawing: type[tool.Drawing], obj: bpy.types.Object) ->
def edit_text(drawing: type[tool.Drawing], obj: bpy.types.Object) -> None:
drawing.synchronise_ifc_and_text_attributes(obj)
drawing.update_text_size_pset(obj)
drawing.update_newline_at(obj)
drawing.update_newline_at_and_symbol(obj)
drawing.disable_editing_text(obj)
+1 -1
View File
@@ -394,7 +394,7 @@ class Drawing:
def sync_object_placement(cls, obj): pass
def synchronise_ifc_and_text_attributes(cls, obj): pass
def update_embedded_svg_location(cls, uri, old_location, new_location): pass
def update_newline_at(cls, obj): pass
def update_newline_at_and_symbol(cls, obj): pass
def update_text_size_pset(cls, obj): pass
+5
View File
@@ -1581,6 +1581,11 @@ class Blender(bonsai.core.tool.Blender):
return repr(bpy_prop)
return repr(bpy_struct)
@classmethod
def get_props_attribute_name(cls, props: bpy.types.PropertyGroup) -> str:
"""E.g. `bpy.data.objects['IfcAnnotation/TEXT'].BIMTextProperties` -> `BIMTextProperties`"""
return repr(props).rpartition(".")[-1]
@classmethod
def resolve_data_path_to_data_attr(cls, data_path: str) -> tuple[bpy.types.bpy_struct, str]:
"""
+30 -4
View File
@@ -110,6 +110,27 @@ class Drawing(bonsai.core.tool.Drawing):
}
# fmt: on
DEFAULT_SYMBOLS = [
"rectangle-tag",
"triangle-tag",
"hexagon-tag",
"capsule-tag",
"circle-tag",
"door-tag",
"window-tag",
"space-tag",
"elevation-arrow",
"elevation-tag",
"section-arrow",
"section-tag",
"dot",
"setout-tag",
"setout-point",
"control-point",
"traverse-point",
"spot-elevation",
]
@classmethod
def get_document_props(cls) -> DocProperties:
assert (scene := bpy.context.scene)
@@ -434,8 +455,7 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def disable_editing_text(cls, obj: bpy.types.Object) -> None:
props = tool.Drawing.get_text_props(obj)
props.is_editing = False
props.literals.clear()
obj.property_unset(tool.Blender.get_props_attribute_name(props))
@classmethod
def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
@@ -1077,6 +1097,7 @@ class Drawing(bonsai.core.tool.Drawing):
text_data = DecoratorData.get_text_data(obj)
props.font_size = str(text_data["FontSize"])
props.newline_at = text_data["Newline_At"]
props.set_symbol(text_data["Symbol"])
@classmethod
def import_assigned_product(cls, obj: bpy.types.Object) -> None:
@@ -1214,10 +1235,12 @@ class Drawing(bonsai.core.tool.Drawing):
)
@classmethod
def update_newline_at(cls, obj: bpy.types.Object) -> None:
def update_newline_at_and_symbol(cls, obj: bpy.types.Object) -> None:
props = cls.get_text_props(obj)
element = tool.Ifc.get_entity(obj)
assert element
newline_at = int(props.newline_at)
symbol = props.get_symbol()
ifc_file = tool.Ifc.get()
pset = tool.Pset.get_element_pset(element, "EPset_Annotation")
if not pset:
@@ -1225,7 +1248,10 @@ class Drawing(bonsai.core.tool.Drawing):
ifcopenshell.api.pset.edit_pset(
ifc_file,
pset=pset,
properties={"Newline_At": newline_at},
properties={
"Newline_At": newline_at,
"Symbol": symbol,
},
)
# TODO below this point is highly experimental prototype code with no tests
+1 -1
View File
@@ -37,7 +37,7 @@ class TestEditText:
def test_run(self, drawing):
drawing.synchronise_ifc_and_text_attributes("obj").should_be_called()
drawing.update_text_size_pset("obj").should_be_called()
drawing.update_newline_at("obj").should_be_called()
drawing.update_newline_at_and_symbol("obj").should_be_called()
drawing.disable_editing_text("obj").should_be_called()
subject.edit_text(drawing, obj="obj")