godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 92 forks source link

Specific node type checking #9535

Open cashew-olddew opened 5 months ago

cashew-olddew commented 5 months ago

Describe the project you are working on

A project which tries to apply different sounds to UI elements, depending on their node type. For example, one sound for a Button and another sound for a CheckButton.

Describe the problem or limitation you are having in your project

Currently, checking for type can be done with is. Example: if button is Button:.

Obviously, since CheckButton is a subset of Button, the check for it will also return true. For example:

if button is Button:
    print("Button is button")
if check_button is Button:
    print("CheckButton is button")

prints:

Button is button
CheckButton is button

Since both fall under Button, it is hard to make a separation and take different actions depending on which type of node I have. The same happens if I check the type of a check_button: typeof(button) returns the same thing as typeof(check_button)

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a stricter type check (e.g. specific_is). With this:

if button specific_is Button:
    print("Button is button")
if check_button specific_is Button:
    print("CheckButton is button")

the message printed is:

Button is button

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

specific_is (or any other better fitting keyword name) returns the exact type of a node, disregarding any extended, implemented or parent type.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This can be worked around by checking the more specific types first and breaking after a match.

Is there a reason why this should be core and not an add-on in the asset library?

Other languages seem to treat this gracefully. For example, in Java, you could check if an object is an instance of something with obj instanceof Class. This has the same functionality as Godot is.

However, if we want to get the precise class of an object, there is getClass() in Java. I didn't manage to find something similar in Godot.

KoBeWi commented 5 months ago

Another workaround is using get_class() and doing String comparison. It's slower and less safe than is, but it won't matter for UI.

timothyqiu commented 5 months ago

Since we have is_instance_of(value, type), it could be is_same_type(a, b).

dalexeev commented 5 months ago

You can check subtypes first:

if control is CheckButton:
    print("CheckButton")
elif control is Button:
    print("Button except CheckButton")
else:
    print("Non-Button")

Since we have is_instance_of(value, type), it could be is_same_type(a, b).

We could solve this if we added first-class types. is_same_type(value_a, value_b) would be equivalent to gdtypeof(value_a) == gdtypeof(value_b).

cashew-olddew commented 5 months ago

Another workaround is using get_class() and doing String comparison. It's slower and less safe than is, but it won't matter for UI.

This is a great workaround and works! However, this comes with the disadvantages you also noted.

You can check subtypes first:

if control is CheckButton:
    print("CheckButton")
elif control is Button:
    print("Button except CheckButton")
else:
    print("Non-Button")

You're right in saying that subtypes can be checked first. I also noticed that and added it to the workaround section:

This can be worked around by checking the more specific types first

However, this workaround does not help in the case in which the types we want to check for are stored in an unordered array or a dictionary only known at run-time.