using Godot; [Tool] public partial class CsvResourceImporter : EditorPlugin { private const string MenuName = "Import CSV Resources..."; private EditorFileDialog _configDialog; public override void _EnterTree() { AddToolMenuItem(MenuName, Callable.From(OnImportMenu)); _configDialog = new EditorFileDialog { Access = EditorFileDialog.AccessEnum.Resources, FileMode = EditorFileDialog.FileModeEnum.OpenFile, Title = "Select CsvImportConfig" }; _configDialog.AddFilter("*.tres,*.res ; Csv Import Config"); _configDialog.FileSelected += OnConfigSelected; EditorInterface.Singleton.GetBaseControl().AddChild(_configDialog); } public override void _ExitTree() { RemoveToolMenuItem(MenuName); if (_configDialog != null && IsInstanceValid(_configDialog)) { _configDialog.FileSelected -= OnConfigSelected; _configDialog.QueueFree(); } } private void OnImportMenu() { if (_configDialog == null) { return; } _configDialog.PopupCentered(new Vector2I(900, 600)); } private void OnConfigSelected(string path) { var config = ResourceLoader.Load(path); if (config == null) { GD.PushError($"CSV importer: failed to load config: {path}"); return; } var result = CsvImporter.Import(config); if (result.ErrorCount > 0) { GD.PushWarning($"CSV importer: completed with {result.ErrorCount} errors, {result.CreatedCount} created, {result.SkippedCount} skipped."); foreach (var error in result.Errors) { GD.PushWarning(error); } } else { GD.Print($"CSV importer: created {result.CreatedCount} resources, skipped {result.SkippedCount}."); } var fileSystem = EditorInterface.Singleton.GetResourceFilesystem(); fileSystem?.Scan(); } }