Godot Version
4.4.1
Question
I am building a custom plugin for my game, in which I am rendering a nested resource structure in a Tree node. All the functionality and rendering is working fine, but every time the plugin is rendered (on selection of a specific type of node) the console is spammed with these “out of bounds” errors:
They seem to be causing slowdown, so I’m guessing they may be a symptom of something else… The error appears to be coming from the batch_row.set[...] lines, which I guess makes sense, but I don’t understand why…
Here is the code in question:
@tool
extends BoxContainer
@onready var editor: PanelContainer = $Editor
@onready var instructions: PanelContainer = $Instructions
@onready var tree: Tree = $Editor/Tree
@export var debug = false:
set(value):
debug = value
update_ui()
@onready var undo_redo = EditorPlugin.new().get_undo_redo()
var editor_selection := EditorInterface.get_selection()
var spawner_config: SpawnerConfig
var spawner_waves: Array[WaveConfig]
var selected_wave: WaveConfig
var selected_wave_batches: Array[WaveBatch]
var tree_root
func _ready() -> void:
undo_redo.version_changed.connect(_on_undo)
tree.columns = 5
tree.column_titles_visible = true
tree.set_column_title(0, "")
tree.set_column_title(1, "Count")
tree.set_column_title(2, "Interval")
tree.set_column_title(3, "Delay")
tree.set_column_title(4, "Asynchronous")
tree.hide_root = true
tree.item_edited.connect(_on_edit)
editor_selection.selection_changed.connect(_on_selection_changed)
update_ui()
func update_ui():
if not editor:
return
var nodes = editor_selection.get_selected_nodes()
if not debug and nodes.size() != 1:
editor.visible = false
instructions.visible = true
return
if not debug and not nodes[0] is SpawnerConfig:
editor.visible = false
instructions.visible = true
return
editor.visible = true
instructions.visible = false
spawner_config = nodes[0]
spawner_waves = spawner_config.waves
if tree:
tree.clear()
tree_root = tree.create_item()
var i = 0
for wave in spawner_waves:
var wave_root = tree.create_item(tree_root)
wave_root.set_text(0, "Wave " + str(i))
var j = 0
for batch in wave.batches:
var batch_row = tree.create_item(wave_root)
batch_row.set_meta("wave_index", i)
batch_row.set_meta("batch_index", j)
var scene = batch.scene.instantiate() as Enemy
# Column 1
batch_row.set_icon(0, scene.sprite.sprite_frames.get_frame_texture("down", 0))
batch_row.set_text(0, scene.name)
batch_row.set_tooltip_text(0, scene.scene_file_path)
# Column 2
batch_row.set_metadata(1, { "key": "count" })
batch_row.set_cell_mode(1, TreeItem.CELL_MODE_RANGE)
batch_row.set_range_config(1, 0, 9999, 1)
batch_row.set_range(1, batch.count)
batch_row.set_editable(1, true)
# Column 3
batch_row.set_metadata(2, { "key": "interval" })
batch_row.set_cell_mode(2, TreeItem.CELL_MODE_RANGE)
batch_row.set_range_config(2, 0.0, 100.0, 0.1)
batch_row.set_range(2, batch.interval)
batch_row.set_editable(2, true)
# Column 4
batch_row.set_metadata(3, { "key": "delay" })
batch_row.set_cell_mode(3, TreeItem.CELL_MODE_RANGE)
batch_row.set_range_config(3, 0.0, 100.0, 0.1)
batch_row.set_range(3, batch.delay)
batch_row.set_editable(3, true)
# Column 5
batch_row.set_metadata(4, { "key": "async" })
batch_row.set_cell_mode(4, TreeItem.CELL_MODE_CHECK)
batch_row.set_checked(4, batch.async)
if j == 0:
batch_row.set_tooltip_text(4, "First batch can't run async")
else:
batch_row.set_editable(4, true)
j += 1
i += 1
func _on_edit():
var edited_column_index = tree.get_edited_column()
var edited_row = tree.get_edited()
var wave_index = edited_row.get_meta("wave_index")
var batch_index = edited_row.get_meta("batch_index")
var column_meta = edited_row.get_metadata(edited_column_index)
var column_key = column_meta.key
var value
match column_key:
"count":
value = edited_row.get_range(edited_column_index)
"interval":
value = edited_row.get_range(edited_column_index)
"delay":
value = edited_row.get_range(edited_column_index)
"async":
value = edited_row.is_checked(edited_column_index)
_: value = edited_row.get_text(edited_column_index)
if spawner_config.waves[wave_index]:
if spawner_config.waves[wave_index].batches[batch_index]:
var object = spawner_config.waves[wave_index].batches[batch_index]
undo_redo.create_action("Change batch value")
undo_redo.add_do_property(object, column_key, value)
undo_redo.add_undo_property(object, column_key, object[column_key])
undo_redo.commit_action()
func _on_undo():
update_ui()
func _on_selection_changed():
if tree:
update_ui()
Any help is greatly appreciated! For now I can just ignore them, annoying as they are they are causing no real actual issues.
