I’m currently writing a class that has use for a property that falls in the category of “integer but only if a boolean is set”, much like the UI overrides. I’ve done enough with editor plugins to know roughly how I might go about crafting an inspector bit like this that way, but I’m curious, is there a way to do it via _get_property_list()?
I’m specifically looking to create something like the highlighted section below:
To be clear, I know how to create the property mechanics of two dependent variables. I’m specifically looking for the path of least resistance for the UI bit, which I have a few uses of already.
Thank you, that flag did not jump out as what I was looking for when I reviewed that documentation.
It does seem finnicky but I’m not sure why. If I use the example above and use no type hint, I can’t toggle the checkbox on manually, but if I set the integer, it turns on. If I add an : int = 0 annotation and default to the test variable, I can check the box manually but not uncheck it.
I’m assuming this is because of how it’s implemented under the hood? Basically int can’t be null, but PROPERTY_USAGE_CHECKABLE uses the null as the unset state?
Is the behavior I’m seeing of not being able to check the box manually expected? That’s not how the inspector element I screenshotted above works.
Wow, you really know this thing in and out. Thank you so, so much. The extra code in _get_property_list() makes sense to me. The need to add _get() and _set(), not so much. That said, it does seem necessary to get things to work the way I expect them to.
I see the documentation for _get() alludes to this, but what’s missing is why either a normal variable or a property with get and set don’t seem to work.
In short: you’ve gotten me where I need to go, but if you don’t mind, I’d love to understand a little bit better why this is necessary. Thank you again so much!
Edit: Is it because the properties simply don’t exist at the time _get_property_list is called? That makes it clear to me why we might need the _test variable above, but not why a normal setget wouldn’t work.
Script variables are also added when getting the property list with get_property_list().
With _get_property_list() you are adding new properties, not overriding old ones. The inspector parses the properties with get_property_list() it finds the variable one and skips it, then it finds the new property and creates the inspector property.
if it’s marked as an int (var test:int = 0) it can’t be unchecked because an int can’t be null. int has no constructor that accepts a null.
if it’s marked as a Variant (var test = 0) it can’t be checked because there’s no default Variant constructor which makes it be null which automatically unchecks the check.
I’m not sure if this can be considered a bug or not. If you think it’s one feel free to open an issue here Issues · godotengine/godot · GitHub
You can use Object._validate_property() insead if you don’t want to use _get()/_set()/_get_property_list(). You can modify the script variable usage flags in it.
@tool
extends Node
var test = null
func _ready() -> void:
print(test)
func _validate_property(property: Dictionary) -> void:
if property.name == "test":
property.type = TYPE_INT
property.usage |= PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_EDITOR
if test != null:
property.usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED
You can’t type your variable as an int though, it will have the same issue (no constructor with null).
Thank you. I have a lot more to learn, and I’ll think about whether or not I want to submit that as a bug. At the very least I think there’s an enhancement request about this behavior, I just have to figure out what it should be.
This solution with _validate_property() seems more elegant and more concise, as I don’t have to define the entire property dictionary (I can just modify what’s there), and I don’t have to create additional _set() and _get() functions.
I appreciate how there’s multiple ways to go about this, but at the same time wish it was a little more straightforward. I suppose a request asking for an @export annotation for the CHECKED behavior wouldn’t be unreasonable!