How do I create an export variable that allows adding a list of complex elements like OptionButtons do

Godot Version

4.4.1-stable

Question

I’m trying to implement a system where I could really use some sort of advanced exported array variable, much like the one used by OptionButton nodes, under the “Items” group. How do I write my variable in such a way?
Image higlighting the section I’m talking about

I just read the Godot docs to confirm something. You can use @export_category("category_name") and all exports below it will belong to that category in the Inspector. You can also use @export var Items : Array[Dictionary].

You can export an Array, but you mentioned that, could you be more specific of what you’ve tried and why it failed? You can’t easily create an Array of multiple variables without a Resource type which does not use a similar inspector tool sadly.

It’s not simple and it would be better if you @export an Array of custom resources but if you still want to get the same behavior as that property then you’ll need to use a @tool script and implement the Object._get(), Object._set(), and Object._get_property_list()

Example:

@tool
extends Node


var my_values = []


func _get(property: StringName) -> Variant:
	if property == "item_count":
		return my_values.size()
	if property.begins_with("items/item_"):
		var parts = property.split("/")
		var index = parts[1].split("_")[1]
		var prop = parts[2]
		return my_values[index.to_int()][prop]

	return null


func _set(property: StringName, value: Variant) -> bool:
	if property == "item_count":
		# The property is the special array
		# resize the array
		my_values.resize(value)
		# and fill it with empty values
		# _set() will be called for all entries in the array
		# reloading its contents
		for i in value:
			my_values[i] = {"name": "", "price": 0}
		# notify that the property list changed
		# to update the array
		notify_property_list_changed()
		return true
	if property.begins_with("items/item_"):
		var parts = property.split("/")
		var index = parts[1].split("_")[1]
		var prop = parts[2]
		my_values[index.to_int()][prop] = value
		return true

	return false


func _get_property_list() -> Array:
	var props = []

	# Special Group Array
	props.append({
		"name": "item_count",
		# class_name format <Group Name>,<prefix>
		"class_name": "Items,items/item_",
		"type": TYPE_INT,
		"usage": PROPERTY_USAGE_ARRAY | PROPERTY_USAGE_DEFAULT
	})

	for i in my_values.size():
		# Each array entry needs to have the prefix items/item_
		# followed by the index and the name of the property
		props.append({
			"name": "items/item_%s/name" % i,
			"type": TYPE_STRING,
			"hint": PROPERTY_HINT_NONE,
		})
		props.append({
			"name": "items/item_%s/price" % i,
			"type": TYPE_INT,
			"hint": PROPERTY_HINT_NONE,
		})

	return props

If you need a more specialized inspector editor then you’ll need to make a plugin and implement an inspector plugin

1 Like

I understand. Thanks everybody for the help.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.