mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
IFC text - box alignment in viewport
This commit is contained in:
@@ -193,7 +193,7 @@ class DecoratorData:
|
||||
return display_data
|
||||
|
||||
@classmethod
|
||||
def get_ifc_text_font_size(cls, obj):
|
||||
def get_ifc_text_data(cls, obj):
|
||||
"""returns font size in mm for current ifc text object"""
|
||||
result = cls.data.get(obj.name, None)
|
||||
if result is not None:
|
||||
@@ -203,21 +203,25 @@ class DecoratorData:
|
||||
if not element:
|
||||
return
|
||||
|
||||
if obj.BIMTextProperties.is_editing:
|
||||
font_size = float(obj.BIMTextProperties.font_size)
|
||||
props = obj.BIMTextProperties
|
||||
# getting font size
|
||||
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:
|
||||
classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes")
|
||||
font_size_type = "regular"
|
||||
font_size = FONT_SIZES[font_size_type]
|
||||
|
||||
# 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"
|
||||
# other attributes
|
||||
literal = tool.Drawing.get_text_literal(obj)
|
||||
box_alignment = literal.BoxAlignment
|
||||
text = props.value
|
||||
|
||||
font_size = FONT_SIZES[font_size_type]
|
||||
cls.data[obj.name] = font_size
|
||||
return font_size
|
||||
text_data = {"text": text, "font_size": font_size, "box_alignment": box_alignment}
|
||||
cls.data[obj.name] = text_data
|
||||
return text_data
|
||||
|
||||
@@ -379,7 +379,19 @@ class BaseDecorator:
|
||||
|
||||
batch.draw(self.shader)
|
||||
|
||||
def draw_label(self, context, text, pos, dir, gap=4, center=True, vcenter=False, font_size=2.5, line_no=0):
|
||||
def draw_label(
|
||||
self,
|
||||
context,
|
||||
text,
|
||||
pos,
|
||||
dir,
|
||||
gap=4,
|
||||
center=True,
|
||||
vcenter=False,
|
||||
font_size_mm=2.5,
|
||||
line_no=0,
|
||||
box_alignment=None,
|
||||
):
|
||||
"""Draw text label
|
||||
|
||||
Args:
|
||||
@@ -409,26 +421,42 @@ class BaseDecorator:
|
||||
# In particular it works only for the OpenGOST font and produces a 2.5mm font size.
|
||||
# It probably should be dynamically calculated using system.dpi or something.
|
||||
# font_size = 16 <-- this is a good default
|
||||
font_size = int(0.004118616 * mm_to_px) * font_size / 2.5
|
||||
pos = pos - Vector((0, line_no * font_size))
|
||||
# TODO: need to synchronize it better with svg
|
||||
font_size_px = int(0.004118616 * mm_to_px) * font_size_mm / 2.5
|
||||
pos = pos - Vector((0, line_no * font_size_px))
|
||||
|
||||
blf.size(font_id, font_size, dpi)
|
||||
blf.size(font_id, font_size_px, dpi)
|
||||
|
||||
w, h = 0, 0
|
||||
if center or vcenter:
|
||||
if box_alignment or center or vcenter:
|
||||
w, h = blf.dimensions(font_id, text)
|
||||
|
||||
if center:
|
||||
# horizontal centering
|
||||
pos -= Vector((cos, sin)) * w * 0.5
|
||||
if box_alignment:
|
||||
# TODO: need to work out the rotation too
|
||||
if "bottom" in box_alignment:
|
||||
pass
|
||||
elif "top" in box_alignment:
|
||||
pos -= Vector((0, h))
|
||||
else:
|
||||
pos -= Vector((0, h / 2)) # middle / center
|
||||
|
||||
if vcenter:
|
||||
# vertical centering
|
||||
pos -= Vector((-sin, cos)) * h * 0.5
|
||||
if "left" in box_alignment:
|
||||
pass
|
||||
elif "right" in box_alignment:
|
||||
pos -= Vector((w, 0))
|
||||
else:
|
||||
pos -= Vector((w / 2, 0))
|
||||
else:
|
||||
if center:
|
||||
# horizontal centering
|
||||
pos -= Vector((cos, sin)) * w * 0.5
|
||||
|
||||
if gap:
|
||||
# side-shifting
|
||||
pos += Vector((-sin, cos)) * gap
|
||||
if vcenter:
|
||||
# vertical centering
|
||||
pos -= Vector((-sin, cos)) * h * 0.5
|
||||
|
||||
if gap:
|
||||
# side-shifting
|
||||
pos += Vector((-sin, cos)) * gap
|
||||
|
||||
blf.enable(font_id, blf.ROTATION)
|
||||
blf.position(font_id, pos.x, pos.y, 0) if hasattr(pos, "x") else blf.position(font_id, 0, 0, 0)
|
||||
@@ -2072,13 +2100,21 @@ class TextDecorator(BaseDecorator):
|
||||
# TODO: support text rotation
|
||||
dir = Vector((1, 0))
|
||||
pos = location_3d_to_region_2d(region, region3d, obj.matrix_world.translation)
|
||||
font_size = DecoratorData.get_ifc_text_font_size(obj)
|
||||
props = obj.BIMTextProperties
|
||||
text = props.get_text() if props.is_editing else props.value
|
||||
|
||||
for line_i, line in enumerate(text.split("\\n")):
|
||||
text_data = props.get_text_edited_data() if props.is_editing else DecoratorData.get_ifc_text_data(obj)
|
||||
box_alignment = text_data["box_alignment"]
|
||||
for line_i, line in enumerate(text_data["text"].split("\\n")):
|
||||
self.draw_label(
|
||||
context, line, pos, dir, gap=0, center=False, vcenter=False, font_size=font_size, line_no=line_i
|
||||
context,
|
||||
line,
|
||||
pos,
|
||||
dir,
|
||||
gap=0,
|
||||
center=False,
|
||||
vcenter=False,
|
||||
font_size_mm=text_data["font_size"],
|
||||
line_no=line_i,
|
||||
box_alignment=box_alignment,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -416,10 +416,6 @@ class BIMTextProperties(PropertyGroup):
|
||||
def get_box_alignment(self):
|
||||
return self.get("box_alignment", DEFAULT_BOX_ALIGNMENT)
|
||||
|
||||
def refresh_font_size(self, context):
|
||||
# force update this object's font size for viewport display
|
||||
DecoratorData.data.pop(context.object.name, None)
|
||||
|
||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||
test_prop: StringProperty(name="test_prop", default="TEXT")
|
||||
@@ -436,16 +432,23 @@ class BIMTextProperties(PropertyGroup):
|
||||
("7.0", "7.0 - Title", ""),
|
||||
],
|
||||
default="2.5",
|
||||
update=refresh_font_size,
|
||||
name="Font Size",
|
||||
)
|
||||
box_alignment: BoolVectorProperty(
|
||||
name="Box alignment", size=9, set=set_box_alignment, get=get_box_alignment, default=DEFAULT_BOX_ALIGNMENT
|
||||
)
|
||||
|
||||
def get_text(self):
|
||||
text_attribute = self.attributes.get("Literal", None)
|
||||
return text_attribute.string_value if text_attribute else self.text
|
||||
def get_text_edited_data(self):
|
||||
"""should be called only if `is_editing`
|
||||
etherwise should use `DecoratorData.get_ifc_text_data(obj)` instead
|
||||
because this data could be out of date
|
||||
"""
|
||||
text_data = {
|
||||
"text": self.attributes["Literal"].string_value,
|
||||
"font_size": float(self.font_size),
|
||||
"box_alignment": self.attributes["BoxAlignment"].string_value,
|
||||
}
|
||||
return text_data
|
||||
|
||||
|
||||
class BIMAssignedProductProperties(PropertyGroup):
|
||||
|
||||
@@ -465,8 +465,8 @@ 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)
|
||||
text_data = DecoratorData.get_ifc_text_data(obj)
|
||||
props.font_size = str(text_data["font_size"])
|
||||
|
||||
@classmethod
|
||||
def import_assigned_product(cls, obj):
|
||||
|
||||
Reference in New Issue
Block a user