Godot Version
4.7.2 Mono
Question
First time trying to run an EditorScript. I got the error box in the screen shot. As soon as I click the “Ok” button, Godot terminates immediately. What could be the reason for this?
And the script file simply transforms some PNG files in a directory. Gemini wrote it for me. I am sharing it below.
using Embodiment.Types;
using Godot;
using System.Collections.Generic;
namespace Embodiment.EditorScripts
{
[Tool]
public partial class PatternFileConverter : EditorScript
{
public override void _Run()
{
string rootDirectoryPath = "res://Game Data/Patterns";
// 1. Build the Reverse Lookup Dictionary (Natural Color -> Material ID)
Dictionary<Color, byte> colorToMaterialId = new Dictionary<Color, byte>();
for (int i = 0; i < MaterialPresets.MAX_MATERIALS; i++)
{
var mat = MaterialPresets.materialsUnmanaged[i];
if (mat.id != 0 || i == 0) // Skip empty slots, but keep Air (ID 0)
{
byte r = (byte) ( mat.color & 0xFF);
byte g = (byte) ((mat.color >> 8) & 0xFF);
byte b = (byte) ((mat.color >> 16) & 0xFF);
byte a = (byte) ((mat.color >> 24) & 0xFF);
Color godotColor = new Color(r / 255f, g / 255f, b / 255f, a / 255f);
colorToMaterialId[godotColor] = mat.id;
}
}
// 2. Scan recursively to find all _Colored.png files
List<string> filesToProcess = new List<string>();
CollectColoredFiles(rootDirectoryPath, filesToProcess);
// 3. Process every collected file
foreach (string file in filesToProcess)
{
ProcessImage(file, colorToMaterialId);
}
GD.Print($"Batch conversion complete! Processed {filesToProcess.Count} files.");
}
// Recursive method to dig through Cxxx and Byyy directories
private void CollectColoredFiles(string currentPath, List<string> foundFiles)
{
using var dir = DirAccess.Open(currentPath);
if (dir == null) return;
// Find files in the current folder
foreach (string file in dir.GetFiles())
{
if (file.EndsWith("_Colored.png"))
{
foundFiles.Add($"{currentPath}/{file}");
}
}
// Find sub-folders and crawl them
foreach (string subDir in dir.GetDirectories())
{
CollectColoredFiles($"{currentPath}/{subDir}", foundFiles);
}
}
private void ProcessImage(string inputPath, Dictionary<Color, byte> lookup)
{
Image img = Image.LoadFromFile(inputPath);
if (img.GetFormat() != Image.Format.Rgba8)
{
img.Convert(Image.Format.Rgba8);
}
int width = img.GetWidth();
int height = img.GetHeight();
Image dataImage = Image.CreateEmpty(width, height, false, Image.Format.Rgba8);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Color pixelColor = img.GetPixel(x, y);
if (lookup.TryGetValue(pixelColor, out byte materialId))
{
dataImage.SetPixel(x, y, new Color(0, materialId / 255f, 0, 1f));
}
else
{
dataImage.SetPixel(x, y, new Color(0, 0, 0, 1f));
}
}
}
string outputPath = inputPath.Replace("_Colored.png", ".png");
dataImage.SavePng(outputPath);
GD.Print($"Converted: {outputPath}");
}
}
}
