rokojori_action_library/Tools/gd-only-generator/GDLibraryGenerator.cs

171 lines
4.2 KiB
C#

using Godot;
using Rokojori;
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Linq;
using System.IO;
namespace Rokojori.GDLibraryGeneration
{
[Tool][GlobalClass]
public partial class GDLibraryGenerator:Node
{
[Export]
public string path = "rokojori_action_library_gd";
[Export]
public bool scanForGDExport = true;
[Export]
public string[] files = [];
[ExportToolButton( "Generate" )]
public Callable generateButton => Callable.From(
()=>
{
GenerateGDLibrary();
}
);
HashSet<string> defines = new HashSet<string>();
void GenerateGDLibrary()
{
defines = new HashSet<string>();
defines.Add( GDScriptGenerator.GD_SCRIPT_TRANSPILING );
var codeFilePaths = GetCodeFilePaths();
var rokojoriProPath = FilePath.Absolute( ProjectSettings.GlobalizePath( RokojoriPlugin.path ) );
var rokojoriGDPath = FilePath.Absolute( ProjectSettings.GlobalizePath( "res://addons/" + path ) );
codeFilePaths.ForEach(
( c )=>
{
var parser = new CSParser( c.absolutePath, defines );
var root = parser.root as CSFileRoot;
var originalPath = FilePath.Absolute( root.GetFilePath() );
var relativePath = rokojoriProPath.MakeAbsolutePathRelative( originalPath.parentAbsolutePath );
var gdPath = rokojoriGDPath.MakeRelative( relativePath.path );
var converter = new GDScriptFromCSAST();
converter.Convert( root );
var gdclass = converter.gdClass;
var gdgenerator = new GDScriptGenerator();
gdgenerator.gdClasses = [ gdclass ];
FilesSync.EnsureDirectoryExists( gdPath.absolutePath );
gdgenerator.Generate( gdPath.absolutePath );
}
);
}
List<FilePath> GetCodeFilePaths()
{
var codeFilePaths = new List<FilePath>();
var map = new HashSet<string>();
var combinedFiles = new List<string>();
combinedFiles.AddRange( files );
if ( scanForGDExport )
{
var absPath = ProjectSettings.GlobalizePath( RokojoriPlugin.path );
var scannedExportfiles = FilesSync.GetFilesRecursive( absPath, f => f.HasFileExtension( ".cs" ) );
scannedExportfiles = scannedExportfiles.Filter(
( f, i ) =>
{
var text = f.LoadUTF8();
if ( ! text.Contains( "GDExport" ) )
{
return false;
}
var parser = new CSParser( f.absolutePath, defines );
var csRoot = parser.root as CSFileRoot;
var cd = csRoot.GetObjectDeclarations().Find( c => c.objectName.match == f.fileName );
return cd?.GetMemberAttributes().Contains( "GDExport" ) ?? false;
}
);
var scannedPaths = scannedExportfiles.Map( f => f.absolutePath );
RJLog.Log( "Found paths:", scannedPaths );
combinedFiles.AddRange( scannedPaths );
}
combinedFiles.ForEach(
( fileString )=>
{
FilePath filePath;
if ( fileString.StartsWith( "res://" ) )
{
filePath = FilePath.Absolute( ProjectSettings.GlobalizePath( fileString ) );
}
else if ( ! fileString.EndsWith( ".cs" ) )
{
filePath = FindFilePathOf( fileString );
}
else
{
filePath = FilePath.Absolute( fileString );
}
if ( filePath == null || ! filePath.Exists() )
{
return;
}
var absolutePath = filePath.absolutePath;
if ( map.Contains( absolutePath ) )
{
return;
}
codeFilePaths.Add( filePath );
map.Add( absolutePath );
}
);
return codeFilePaths;
}
List<FilePath> filePaths;
FilePath FindFilePathOf( string type )
{
if ( filePaths == null )
{
var rokojoriPath = ProjectSettings.GlobalizePath( RokojoriPlugin.path );
filePaths = FilesSync.GetFilesRecursive( rokojoriPath, fp => fp.HasFileExtension( ".cs" ) );
}
return filePaths.Find( fp => fp.fileName == type );
}
}
}