How to add more entries to .tres resource via GDScript?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By alforiumstudios

I’m working on an editor plugin and I want to modify an existing AnimatedSprite via a “tool” script.

The AnimatedSprite’s resource is saved in a separate .tres file, which you can find here, for reference: https://gitlab.com/alforiumstudios/monsterembassy/blob/master/game_source/objects/destructibles/destructible_animations.tres

What should I do if, for example, I wanted to add a new entry to the .tres file with the following content, all using GDScript?

{
"frames": [ ExtResource( 5 ) ],
"loop": true,
"name": "new1_destroy",
"speed": 5.0
}

I can’t find any examples online, so that’s why I’m asking. Thank you!

:bust_in_silhouette: Reply From: Zylann

To modify it, I think you should load the resource with load. This gives you a SpriteFrames resource. If it’s already loaded (which is very likely if your sprite is in an open scene), then Godot will just give you the reference to it.

Then modify the resource normally by using the SpriteFrames API: SpriteFrames — Godot Engine (3.1) documentation in English

Once you’re done, you may want to save the changes. But there is a catch:

You could simply start by saving the resource with ResourceSaver.save(sprite_frames.resource_path, resource). But that will only work if the resource has already been saved as a file before. Remember resources can exist embedded in scenes or even other resources. Also, that’s not undoable, and Godot won’t even know if your project has changed. That might be fine, but in reality, it’s rarely what needs to happen and can lead to annoying usability issues.

So consider this: if your plugin gets to modify a SpriteFrames resource, it very often means the user has a AnimatedSprite using it already in an open scene, or has selected one somehow, which means the resource is already loaded.
When Godot saves a scene, it saves all modified resources with it automatically, and it puts them in correct locations (file, scene, whatever), which means you don’t need to save the resource yourself, or even worry about where it is. You only need to tell Godot it was modified.
How to tell that?
I had the same issue with my plugin before, and I’m not sure if that’s the onlyway, but I came to realize UndoRedo was the key. Whatever you are doing to the resource, try to modify it through the UndoRedo instance of the editor.

This is an excellent and really detailed answer! Thank you so much. I didn’t need to do anything that complicated, really: you gave me all the info I needed and then some. Thanks again.

alforiumstudios | 2019-12-13 17:15

You’re right that the editor has trouble realising that an open Resource has been edited…

I can’t quite figure out the “undo-redo” method you suggested. Do you know of any simple way to close and/or refresh a resource (tileset, SpriteFrames…) that is currently open in the editor, without closing and opening the editor?

alforiumstudios | 2019-12-13 18:09

This seems to be an ongoing issue: Editor doesn't reload changed resources. · Issue #4769 · godotengine/godot · GitHub

alforiumstudios | 2019-12-13 18:10