mainsail-crew / mainsail

Mainsail is the popular web interface for managing and controlling 3D printers with Klipper.
https://docs.mainsail.xyz
GNU General Public License v3.0
1.68k stars 351 forks source link

[FR] UI Controls for gcode macro attributes #484

Open bcbuckles opened 2 years ago

bcbuckles commented 2 years ago

Ability to add UI controls mapped to variables. For example, toggle switches that toggle Booleans, Slider Controls to adjust float variables, SpinBoxes for lists, etc.

This would drastically increase the capability of the GCODE macro features

meteyou commented 2 years ago

Thx for your request! This would only be possible with a custom naming or something similar of the variable names to sort these variable types and and and... I thought about something like this many times, but have no time for testing. Maybe we can add this in the future...

zellneralex commented 2 years ago

The problem is the a gcode_macro variable can be anything from a simple bool or number to an complex dictionary structure. It would be imposable to build them all without a klipper object definition. As these is not existing we can not do that.

But there is a simple workaround to get an slider or switch: You can define an output pin that will be shown as switch or slider depending if you configure pwm or not. Following is a small example:

## dummy output to get an switch in Mainsail
## any unused mcu pin can be defined you will not connect anything
## as I use the rPi as mcu I will use a pin from it
## Off -> M106 will update fan
## On -> M106 can not uodate fan
[output_pin lock_M106]
pin: rpi: gpio16
value:0

#####################################################################
#  Macros
#####################################################################
# M106 with lock and manual set feature
# M106 S128 M1 will update the fan in any case
[gcode_macro M106]
description: set fan with manual override and lock option
rename_existing: M106.1
gcode:
  {% if printer['output_pin lock_M106'].value|int == 0 or params.M|default(0) == '1' %}
    M106.1 {rawparams}
  {% else %}
    {action_respond_info("M106 update is locked")}
  {% endif %}

They ability to enter parameter direct at the macro button and the workaround to generate a slider or switch is all we can provide with the current klipper implementation

airato commented 2 years ago

maybe we could get away with a solution limited to booleans and floats? Or even just floats. I think that would still provide great value for macro customizations. Maybe something simple with macro name convention, like mainsail_variables_<panel_name>. What do you think?

Example:

[gcode_macro mainsail_variables_my_custom_panel]
variable_my_var: 0.04
variable_is_something_enabled: True

gcode:
zellneralex commented 2 years ago

Personally I do not believe in this kind of convention as most user will never find out about it. The right way would be to add a definition for e.g global variables with types to Klipper so that the definition is commonly known. In the example your my_val has no min and max so to what should a slider be limited. Also stuff like stepping is not defined that way.

airato commented 2 years ago

Good points! For super simple cases like in my example above, we can define a macro that saves new values, something like this

[gcode_macro SET_VAR]
gcode:
    {% set my_var_new = params.MY_VAR|default(0)|float %}
    SET_GCODE_VARIABLE MACRO=Vars VARIABLE=my_var VALUE=my_var_new

And then the macro button for this one will have a dropdown to enter the param values, which basically a UI I was talking about 👍

zellneralex commented 2 years ago

@airato that is part of V2.1 anyhow and can be done with any beta today

bcbuckles commented 2 years ago

@airato Personally, I think I would use booleans most, and then floats. Booleans would be great to add toggles for various logic such as "Heat Soak" which might enable a heat soak routine as part of your print_start". Would be nice to alter your start GCODE or other logic based on some UI controls.

bcbuckles commented 2 years ago

Admititdly, I am not an expert on the current variables implementation, or what features are in the Mainsail Beta, but with my limited knowledge I had the following thought for implementation. It appears that parameters passed to GCODE macros are always strings, so it might be possible to implement this functionality as a few different classes of macro buttons/shortcuts. Maybe you create a new macro button, for example a toggle switch, and it is linked to a particular gcode macro and passes the string "True" or "False" to the macro. The same could be done for a slider, passing the value as a string to the macro. It would then be on the user to typecast or handle the string within their macro, and could set it to a var themselves inside the macro. This would mean adding new UI element/class for datatypes, but that could be reasonable, I wouldn't imagine we would need many. Just expanding to a few predefined like button, toggle, slider could be a huge capability

This could be similar to what @zellneralex has mentioned above, but like I said I have some homework to do on the current implementations before I can be truly helpful to the conversation.

TypQxQ commented 6 months ago

Want to bump this up and add: Poll the GCODE_VARIABLE regularly to update the buttons display.

Having them grouped could allow for one file to contain a "plugin" that can be distributed and maintained through the update manager or being part of another component. Would be possible to enable the group with one click in settings and ordered as a panel.

Examples of implementations:

Could have a plugin store to showcase different plugins and if each is contained in it's own file it is easy to manage. Could all be placed inside a ./mainsail_plugins/ folder of the config folder.

This are just a few of the possibilities.