I have a tool script that generates a bunch of image files. I need these images to be imported by Godot as Image resources, which are then linked up to nodes.
This mostly works, however, I don’t see any way to automate the process of changing the image’s import preset from the default Texture2D to Image.
The goal is to have a tool script that generates an image file (In this case it’s a distance field texture). That image file is then loaded as an Image resource and used by nodes (in this case other nodes can now query positions and get the exact distance to the nearest location).
I worked around the issue for now by using Image.load_from_file explicitly. This doesn’t work at runtime, which I don’t currently need, but if I did need it to work at runtime I’d be stuck.
Another workaround is to save the image as a .res file on image creation, but this has a number of downsides, the main one being that we no longer get image compression so the files are huge.
Ok, so I had to look up what a distance field texture was. Based on my admittedly quick research, an SDF texture contains data from 0 to 1 to store the distance and is typically a black and white texture.
Based on this what I would do is create a translation to and from the texture using an array of arrays. So a 16x16 texture would be an array containing 16 array, each containing 16 floats. Since an image, even a black and white one, has to store rgba for each pixel (plus header data) your array would be roughly 1/4 the size.
The easiest way is just to use ResourceSaver.save(my_image, "res://my_image.res") if you don’t plan to do anything with the image afterwards like editing it externally.
I’ve not found an easy way of changing the preset of a resource but you can manually do it by editing the .import file with the desired configuration and force a re-import on it. In this case is easy because the Image preset has no configuration.
@tool
extends EditorScript
const REMAP_CONTENT = """
[remap]
importer="image"
"""
func _run() -> void:
# Get the resource filesystem
var fs = EditorInterface.get_resource_filesystem()
# Connect once to the filesystem_changed signal to manually edit the .import file
fs.filesystem_changed.connect(func():
var remap = FileAccess.open("res://my_image.png.import", FileAccess.WRITE)
remap.store_string(REMAP_CONTENT)
remap.close()
fs.reimport_files(["res://my_image.png"])
, CONNECT_ONE_SHOT)
# Generate the image and save it
var tex = load("res://icon.svg") as Texture2D
var img = tex.get_image()
img.save_png("res://my_image.png")
# Force a scan in the filesystem so the filesystem_changed signal is triggered
fs.scan()
This is just a quick example, I’m not sure if it will work fine if you create multiple files at once. You could probably tweak it further for that.