Search code examples
godotgdscript

Is it possible to add/hide export variables during run time?


I'm trying to add or hide script variables in tool mode like this:

tool

...

export(int) var number_of_appendages=0 setget number_of_appendages_changed

func number_of_appendages_changed(new_val):
    number_of_appendages=new_val;
    _get_property_list()

func _get_property_list():
    
    var variables_list=[]
    for i in number_of_appendages:
        for j in 2:
            variables_list.append({
                    "hint": PROPERTY_HINT_RANGE if j==1 else  PROPERTY_HINT_NONE,
                    "hint_string":"-360, 360,30" if j==1 else "",
                    "usage": PROPERTY_USAGE_DEFAULT,
                    "name": "appendage "+String(i+1)+"/"+("name" if j==0 else "length"),
                    "type": TYPE_REAL if j==1 else TYPE_STRING
                })

    return variables_list

enter image description here

obviously this won't work, but what if I create a max number of appendages and then only toggle the visibility accordingly?

pseudo code:

tool 

...

export(int) var number_of_appendages=0 setget number_of_appendages_changed
const max_appendages=5

func number_of_appendages_changed(new_val):
    number_of_appendages=new_val;
    
    for i in max_appendages:
        if(i>number_of_appendages):
            HIDE_GROUP("Appendage "+String(i+1))

func _get_property_list():
    
    var variables_list=[];
    
    for i in max_appendages:
        for j in 2:
            variables_list.append({
                    "hint": PROPERTY_HINT_RANGE if j==1 else  PROPERTY_HINT_NONE,
                    "hint_string":"-360, 360,30" if j==1 else "",
                    "usage": PROPERTY_USAGE_DEFAULT,
                    "name": "appendage "+String(i+1)+"/"+("name" if j==0 else "length"),
                    "type": TYPE_REAL if j==1 else TYPE_STRING
                })

    return variables_list

is something like this possible? or is there any other way to achieve what I'm trying to accomplish ?


Solution

  • What you have is close to what you have to do. Unlike the pseudo code you came up with.

    As you are aware Godot calls _get_property_list to figure out what to show in the inspector panel.

    However, when you call it like this:

    func number_of_appendages_changed(new_val):
        number_of_appendages=new_val;
        _get_property_list()
    

    It does nothing. Yes, _get_property_list is running, but what happens with its result? It is getting descartad.

    Instead, do this:

    func number_of_appendages_changed(new_val):
        number_of_appendages=new_val;
        property_list_changed_notify()
    

    And with that call property_list_changed_notify you are telling Godot to call _get_property_list and use its result to update the inspector panel.