Tool: access variables from autoload?

Godot Version

v4.2.1.stable.official [b09f793f5]

Question

In my project I have a “tool” scene that does some stuff while I’m in IDE. That works great. So now I want to use it to change something in a global array which is part of an autoloading script… but I’m getting an error:
Invalid get index ‘data_fragment_collected’ (on base: ‘Node (sys.gd)’).
which looks like it’s caused by failing to load the data from the array in question to begin with (this all works great in the launched project, just not in the IDE).

Is there a way to access this autoload script’s array from the tool or should I try to set it all up in some different way?

To reply to myself… I found the same question from 6 years ago:
https://www.reddit.com/r/godot/comments/7axc0i/referencing_autoload_scripts_from_tool_scripts/

But when I try to define the autoload,

onready var MySingleton = get_node("/root/MySingleton")

(or using res://) it fails (in my case the autoload is a script).

Since you provided no code, I am not sure about your intent or requirements, but if you need some global state that autoload is not enough for, you can always use static functions.
A static function on a class can be called by any script at any time and a static variable on a class will hold the data during the entire lifetime of the process.
This may be a problem in a @tool script in not handled carefully. You could be holding objects that need to be freed, or that have been freed.
As long as you are careful with what data you are holding, a static var can take the place of an autoload. Now, this means the static var exists before any autoload scripts are even added. _static_init() happens, I believe, even before the graphics context exists during a run of a process.
So instead of static init call a custom static initializer function from the _ready() of some node you control, is my best advice.
Again, without your intent clear, this is hard to assess, but that’s my best guess.

Here is what I started with, I tried other things too but just to clarify what I’m trying to achieve.

In Autoload:

extends Node

var stuff : Array[bool]

func _ready():
	stuff.resize(200)
	
	for S in stuff.size():
		stuff[S] = false

In the button that I’m trying to use for changing the “stuff” array (only to be used within IDE):

@tool
extends Button

enum modify_actions {none, change_stuff}
@export var modification : modify_actions = modify_actions.none :
	set(M):
		match M:
			modify_actions.change_stuff:
				change_stuff()
			_: pass
		# modification = M


func change_stuff():
	for S in MyAutoload.stuff.size():
		MyAutoload.stuff[S] = false
		print(MyAutoload.stuff[S])

Things I tried (on their own or combinations, not included just to keep the intent clear) but didn’t work: turning the autoload to tool, initializing the array in the button, preloading the Autoload…

add a class_name to your autoload

class_name MyAutoload extends Node

make stuff static

static var stuff: Array[bool]

you may or may not need to remove it from the autoload list
I think that should be enough, but im not 100% on wether that will persist your changes.

1 Like

I’m not totally sure about autoload nodes in editor time, but editor will refuse to run any code that doesn’t define @tool keyword; this means if, theoretically, your autoload exist in editor, editor is refusing to use its script due it not having @tool

I removed the “MyAutoload” from the project’s autoloads and applied the modifications.

This way I can access variables and related from the “MyAutoload”, but not the array (since the array is resized in MyAutoload’s _ready(), which is not called in the IDE). I tried turning the MyAutoload (which is not an autoload anymore) to @tool but this still doesn’t initialize the array.

I tried that too, but didn’t manage to make it work.

Maybe autoloads doesn’t exist in editor then (which could make sense, since autoloads are created right before the scene is added in the game instance)

Maybe… here is what the project looks like in its current state:
https://archive.org/download/ShowFlowFleetingWorld/engage%20access%20an%20array%20from%20autoload.zip

(Edit: to test it, select the “Assign stuff” button and then in the Inspector select the “Modification / Chnage stuff” entry.)
image

Which doesn’t crash, but the problem is that the @ tool has no idea the array is meant to contain 200 slots. At this point I could just make it do what it has to do by resizing the array within the @ tool’s function for array manipulation… but then I’d have to do that for every array I’d like to use like this in the future, which I’m trying to avoid.

Why do you need it to be an autoload anyway? What are you trying to do?

In the code sample I linked to, there is no reason for the script to be an autoload. But in my main project, this is where I keep all things that have to be accessed from different parts of the project.

This particular array that I’m trying to modify is used to keep track of various secrets that the player discovered (or not) in game. So when I’m testing the project, I often want to test specific configurations of these discovered / undiscovered secrets (for example, “discovered first 20 but not last 100 with anything in between random”, or “discovered first 5 and then every second” etc).

So since there are quite a few of these secrets, it doesn’t make sense to modify it all manually every time I want to set a specific configuration and I am trying to set it all up with a @ tool.

In the end, I didn’t manage to make it work in this particular way.

What I did instead, is just save / load the array to / from drive every time I want to modify it. This is not as nice as using a @ tool (downside is that I’m not able to see updates in real time on screen and have to actually launch the project, which is what I was hoping to avoid by using a @ tool) but it works and is still reasonably fast so I’ll go with it for now.

I would recommend then investigating about resources, it can serve your purpose of data handling while being able to be shared between your objects as if it were an autoload. In any case, glad that you managed a solution

1 Like

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