4
$\begingroup$

I'm trying to create an operator run from a button with text inside it, for adding bees. But the text is long and it's not clearly visible.

enter image description here

Resizing the button is no help.

enter image description here

The text can be broken in multiple lines and ideally it would have to be centered... something like:

enter image description here

Is there a way to do that?

Thank you

EDIT: @Strike Digital

Yes! that works. I just have problems centering it:

enter image description here

The operator:

multi_line_operator(
    layout,
    "wm.context_set_string",
    lines=[
        "Bee what yo wanna bee", 
        "Bee what yo wanna bee, Bee what yo wanna bee",
        "yo wanna bee",
        "bee"],      
)

Am I missing something?

$\endgroup$
2
  • $\begingroup$ I'm not sure what you mean by centring it? If you mean that the text is still being cut off when it's too long, then you might want to look into using a text wrapping function like is shown here: b3d.interplanety.org/en/… $\endgroup$ Commented Oct 26, 2022 at 15:23
  • $\begingroup$ Bee thanks! [15 character filler] $\endgroup$
    – Kabu
    Commented Oct 26, 2022 at 17:02

1 Answer 1

7
+50
$\begingroup$

Is there an officially supported to do this?

Unfortunately, no.

Is there a very hacky way to do this?

Absolutely!

I wrote a function that draws multi line operators like this:

Multi line operator buttons

Here's the code:

def multi_line_operator(
    layout: bpy.types.UILayout,
    operator: str,
    lines: list[str],
    line_spacing: float = .85,
    padding=.4,
    icon: str = "NONE",
):
    """Draw an operator with a multi line label"""
    # Draw the text over multiple rows in a column
    col = layout.column(align=True)
    col.scale_y = line_spacing
    for line in lines:
        row = col.row()
        row.alignment = "CENTER"
        row.label(text=line)

    # The scale needed to cover all of the text with the button
    scale = len(lines) * col.scale_y + padding
    col = layout.column(align=True)

    # This is the magic: drawing a property with a negative y scale will push everything drawn below it up.
    # It's very hacky, but it works...
    # The only reason not to use it is that it might be broken in future updates.
    propcol = col.column(align=True)
    propcol.scale_y = -scale  # give this column a negative scale
    # This can be any property, it doesn't matter which as it won't be editable.
    propcol.prop(bpy.context.scene.unit_settings, "scale_length")

    # Draw an operator below the prop so that it will be moved up.
    row = col.row(align=True)
    row.scale_y = scale
    op = row.operator(operator, text=" ", icon=icon)
    return op


How does it work?

It works by abusing a bug/unintended feature where if you draw a property on a row with a negative scale, it will start to move all elements drawn afterwards upwards, meaning that you can essentially draw two UI elements in the same place.

That means that in this case, we can first simply draw the text we want over multiple labels, and the afterwards, draw a property in a row with a negative scale (in this case -1 multiplied by the number of lines), and after that draw an operator with the same scale but positive, which essentially draws the button behind the labels.

How do I use it?

Just drop the function into your project, and then call it like so:

multi_line_operator(
    layout,
    "wm.context_set_string",
    lines=["ooh, cool text", "more text!", "woah!"],
    line_spacing=.85,
)

Are there any differences compared to drawing a normal operator?

Yes, but they're pretty minor. Here are the ones I've found so far:

  • Text is generally darker than on a normal operator (unless it is drawn in a box), and it also doesn't light up when hovered over with the mouse.
  • Drawing an icon on the operator won't cause the text to go off-centre (this could be implemented, though).

Hope that helps!

$\endgroup$
1
  • $\begingroup$ Please check my edit $\endgroup$
    – Kabu
    Commented Oct 26, 2022 at 10:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .