Doing math and formatting on machine variables before displaying on a widget

75 views
Skip to first unread message

kaydeeH

unread,
Nov 8, 2025, 5:29:20 PMNov 8
to MPF Users
Hi all,

I've been beating my head against this for a while, so it's time to reach out again. I feel like this has been asked in one form or another multiple times but I haven't found an answer that works in this specific case.

Context: this is MPF 0.57.3.dev2 with MC (not Godot).

Simply put, I'm trying to add a widget (to an already on-screen slide) that shows the master volume level. Because this can happen in either the attract loop or during the game and because it relates to the service buttons, I have this in my service mode for now (open to other suggestions there). I can get it to show the machine variable "master_volume" but it's a float and I want to format it as a percentage, and I cannot get it to do that. Here's what does work:

widgets:
  # volume up or down
  volume_display:
    - type: text
      x: center
      y: bottom+29%
      anchor_x: middle
      anchor_y: middle
      z: 10003
      color: black
      text: "Volume: (machine|master_volume)"
      expire: 2s

widget_player:
  # volume
  machine_var_master_volume:
    volume_display:
      action: add

When that runs, it shows on the slide just fine and expires after 2s as it should, but it says Volume: 0.35, for example (master_volume is a float from 0 to 1 that moves in 0.05 increments). How do I rework this to show Volume: 35%? I have been through just about everything I can think of. I'm sure it's something simple using a string formatter or something, but I've tried about everything I can find and nothing has worked. It either stops pulling the variable and formats the whole string as literal text, or MPF throws various errors.

I was originally trying to dynamically format the width of a rectangle as a sort of volume meter, scaled from 0 to a max width based on the master_volume machine variable, but that was an even tougher fight and I gave up and tried the simple text approach, as above.

Any help in either direction would be much appreciated!

Thanks,
Kaydee

Dan - aka BorgDog

unread,
Nov 9, 2025, 3:20:35 PMNov 9
to MPF Users
according to the docs https://missionpinball.org/latest/config/instructions/text_templates/  any python formatting should work, and the link on that page to python docs shows the % symbol should do what you want, by using as {variable:format_string}

I have not tried it, but something like this is what I would try first.   text: "Volume: (machine|master_volume:%)"

kaydeeH

unread,
Nov 10, 2025, 7:34:11 PMNov 10
to MPF Users
Thanks for the attempt! I wish I could say it worked. When I tried that, it just took the whole string as a literal and prints everything in the quotation marks exactly as written.

Dan - aka BorgDog

unread,
Nov 10, 2025, 9:50:43 PMNov 10
to MPF Users
yeah, getting those format strings in the correct way seems to always be an adventure every time I do it.  here is an example that works on my machine that may lead to a solution. quotes and brackets and parentheses oh my!

text: "{(players[0].score):0>2,d}"

Brad Myers

unread,
Nov 11, 2025, 2:38:11 AMNov 11
to mpf-...@googlegroups.com
https://chatgpt.com/s/t_6912e7030ef481919552d8d7d58d5da7

Hi all,

You’re super close — the trick is that formatting only kicks in when the placeholder is inside {}. Wrap your (machine|master_volume) token in braces and use Python’s percent format specifier:

# widget definition
widgets:
  volume_display:
    - type: text
      x: center
      y: bottom+29%
      anchor_x: middle
      anchor_y: middle
      z: 10003
      color: black
      text: "Volume: {(machine|master_volume):.0%}" # 0.35 -> "35%"
      expire: 2s

# show it whenever the machine var changes
widget_player:
  machine_var_master_volume:
    volume_display:
      action: add

:.0% multiplies by 100, appends %, and shows 0 decimals (e.g., 0.35 → 35%).
Use :.1% if you want one decimal place (e.g., 35.0%).

This is straight from MPF’s Text Templates behavior: variables go in {}, and the part after the colon is standard Python’s format mini-language. 

And yes, (machine|my_var) is the right token form for slide/text content; MPF documents that syntax specifically for slide widgets. 


(Optional) If you want a skinny “volume bar”

MPF’s rectangle width: is in pixels, so a quick pattern is to create a fixed-height rectangle and animate its width on machine_var_master_volume using the event’s (value):

# put a bar on the slide (start at width 0)
slides:
  service_overlay:
    widgets:
      - type: rectangle
        key: volume_bar
        x: left+5%
        y: bottom+25%
        anchor_x: left
        anchor_y: middle
        height: 14
        width: 0
        corner_radius: 3
        color: "00FF00"

# increase width whenever master_volume changes
widgets:
  volume_bar:
    - type: rectangle
      animations:
        machine_var_master_volume:
          - property: width
            value: (value) # see note below

Then scale it to your desired max width by feeding the event a pixel value (e.g., post a companion event or compute a machine var to pixels). The animation/how-to shows using value: (value) directly from the event; rectangle width itself is documented as pixel-based. 

But if all you needed was “35%” instead of “0.35”, the first snippet with:

text: "Volume: {(machine|master_volume):.0%}"

is the minimal, reliable fix. ✅

Hope that helps! —Kaydee helpers on MPF 😊

--
You received this message because you are subscribed to the Google Groups "MPF Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mpf-users+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/mpf-users/d1e62807-5e66-4038-b81c-843849cdf5e7n%40googlegroups.com.

kaydeeH

unread,
Nov 12, 2025, 4:30:31 PMNov 12
to MPF Users
@Brad: Your format string produces this result: Volume: {0.15:.0%} So that's closer, it's at least showing the float volume now instead of treating it like a literal string, but the formatting instruction is shown as a literal string. In this case, my text: entry looks identical to yours.

@Dan: Your format string produces this result: Volume: {0.15>2,D} So it's about the same as Brad's. The float shows here as well, but it's still ignoring the formatting and displaying it as a literal string. In this case, I'm using the following: text: "Volume: {(machine|master_volume):0>2,d}"

I also tried removing the "Volume: " part to see if that was tripping it up, but it produced identical results, just without the "Volume: " text in front of it. I then also tried removing the quotation marks entirely, but then the game won't start due to a yaml validation error.

"yeah, getting those format strings in the correct way seems to always be an adventure every time I do it" - Truer words have never been spoken!
Reply all
Reply to author
Forward
0 new messages