Scroll to the end where it says “To put it all together” if you just want the rules.
To begin with, I’ll be using code that looks like this:
tool
extends Node
var backing_field
func _set(property:String, value) -> bool:
if property == "property_name":
backing_field = value
return true
return false
func _get(property:String):
if property == "property_name":
return backing_field
return null
Pretend that code is always there. So we will be specifying this property "property_name"
in _get_property_list
.
For reference, I’ll start by showing how _get_property_list
works in other cases. For example we can make the property an int
:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_INT,
usage = PROPERTY_USAGE_DEFAULT,
}
]
And we can use hint
and hint_string
to further specify how it will behave in the inspector panel. For instance we can narrow the property to a specific range like this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_INT,
usage = PROPERTY_USAGE_DEFAULT,
hint = PROPERTY_HINT_RANGE,
hint_string = "0,10"
}
]
And that would give the property a range from 0
to 10
.
We can of course specify that the property is an Array
instead of an int
:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
}
]
And here is where we get to the question: What hint
and hint_string
can we use with TYPE_ARRAY
.
If we have a look at GDScript exports we find out that we can export an array and also specify the type of the elements, like this:
export(Array, int) var my_array = [1, 2, 3]
So, presumably we will be able to do that with _get_property_list
instead (Without resourcing to Pool*Array
types – we will not be able to specify ranges with those anyway). How do we do that? I’ll show you.
From here on, these are all undocumented. Most of this I figured this out by experimentation. By the way, for Godot 4.0 this will be different.
To specify the type of the elements of the array:
- The
hint
must be24
(This is an undocumented constant I found by experimentation, and I found the name in Godot source:PROPERTY_HINT_TYPE_STRING
however it is not exposed to GDScript). - The
hint_string
must be theTYPE_*
constant converted toString
with":"
appended at the end.
For example, if the type of the elements is int
you put "2:"
in the hint_string
. If the type of the elements is float
you put "3:"
on the hint_string
. Like this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = str(TYPE_INT) + ":"
}
]
For reference str(TYPE_INT)
is "2"
so str(TYPE_INT) + ":"
is "2:"
.
Ok, but what if we want to specify more about the elements? For example what if we want to say that we have an Array
of int
in the range from 0
to 10
using _get_property_list
?
In that case the hint_string
will be:
- The
TYPE_*
constant converted toString
- Followed by
"/"
- Followed by the
PROPERTY_HINT_*
constant converted toString
- Followed by
":"
- Followed by the
hint_string
you would use with thatPROPERTY_HINT_*
constant.
Like this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = str(TYPE_INT) + "/" + str(PROPERTY_HINT_RANGE) + ":0,10"
}
]
Here the hint_string
comes up as "2/1:0,10"
. Notice that the "2"
is now followed by "/"
instead of ":"
.
Alright, that begs the question. What if the elements of the Array
must also be Array
s? Well, we can go back to having an Array
and specifying the type, like this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = str(TYPE_ARRAY) + ":"
}
]
Here the hint_string
comes up as "19:
. That the "19"
came from str(TYPE_ARRAY)
and I’m highlighting that because I’ll start using writing "19"
instead of str(TYPE_ARRAY)
in the code.
Well, let us say we want to specify the type of the elements of the arrays that are elements of the array. For example, let us say that we want an array of arrays of int. That would be like this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = "19:" + str(TYPE_INT) + ":"
}
]
Here the hint_string
comes up as "19:2:
.
And we can put more "19:"
to make an Array
of Array
s of Array
s of whatever and so on. So this is an Array
of Array
s of Array
s of int
s:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = "19:19:" + str(TYPE_INT) + ":"
}
]
Here the hint_string
comes up as "19:19:2:
.
Now, let us say that you want to int
in the range from 0
to 1
as before, we would have to do this:
func _get_property_list() -> Array:
return [
{
name = "property_name",
type = TYPE_ARRAY,
usage = PROPERTY_USAGE_DEFAULT,
hint = 24,
hint_string = "19:19:" + str(TYPE_INT) + "/" + str(PROPERTY_HINT_RANGE) + ":0,10"
}
]
Here the hint_string
comes up as "19:19:2/1:0,10
.
Notice (again) that we don’t have "19:19:" + str(TYPE_INT)
followed by ":"
but by "/"
.
To put it all together:
- The
type
must beTYPE_ARRAY
(Which is19
). - The
hint
must be24
(this is an undocumented constant). - The
hint_string
must be:"19:"
for each level of nestedArray
s we want. None if theArray
is not meant to have otherArray
s inside.- Followed by the
TYPE_*
constant that represents the type of the elements. - Then by either:
- To specify what would be the
hint_string
for the elements:"/"
- Followed by the
PROPERTY_HINT_*
constant converted toString
- Followed by
":"
- Followed by the
hint_string
you would use with thatPROPERTY_HINT_*
constant.
- Otherwise:
- To specify what would be the
The other attributes are not affected by this being an array. You can set them as if you were making a property of the type of the elements of the array.
These are some examples of GDScript exports translated to hint_string
(remember to set type
to TYPE_ARRAY
and hint
to 24
):
export(Array)
:""
export(Array, int)
:"2:"
export(Array, Array, int)
:"19:2:"
export(Array, int, 0, 10)
:"2/1:0,10"
export(Array, Array, int, 0, 10)
:"19:2/1:0,10"
export(Array, int, "Red", "Green", "Blue")
:"2/3:Red,Green,Blue"
export(Array, Array, int, "Red", "Green", "Blue")
:"19:2/3:Red,Green,Blue"
export(Array, float)
:"3:"
export(Array, Array, float)
:"19:3:"
export(Array, float, 0, 100, 10)
:"3/1:0,100,10"
export(Array, Array, float, 0, 100, 10)
:"19:3/1:0,100,10"
export(Array, Texture)
:"17/17:Texture"
export(Array, Array, Texture)
:"19:17/17:Texture"
What kind of experimentation did I do to find this out? I exported some variables and had a look at what was reported by get_property_list
and then tried different combinations in _get_property_list
to see what worked and what didn’t, what was necessary and what wasn’t. Then I looked at Godot source code as sanity check.
By the way, the last documented hint
constant with value 22
is PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS
. We found out about the hint
constant with value 24
which is PROPERTY_HINT_TYPE_STRING
. What happened with 23
? And there are more beyond 24
? There are! See the source code. But that is beyond this answer.