//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace TinyGoose.Tremble.Editor
{
public static class EditorCompileUtil
{
private static readonly EditorPrefsBackedString s_CompileList = new("Tremble_PostCompileActions");
///
/// Compile scripts, then call a static method.
/// Method MUST be static.
/// Method can be private or public.
/// Method must take 0 args, or any number of STRING args only.
///
/// Type containing method
/// Method name (use nameof)
/// Optional list of STRING only args to pass (must not contain ',')
public static void CompileThen(Type type, string staticFunctionName, params string[] stringArgs)
{
foreach (string stringArg in stringArgs)
{
if (stringArg.Contains(','))
{
Debug.LogError($"Cannot schedule call to {type.Name}.{staticFunctionName} - arg contains ',' :(");
return;
}
}
// Add to compile list, backed by editor prefs
string[] existing = s_CompileList.Values;
string[] newList = new string[existing.Length + 1];
if (existing.Length > 0)
{
Array.Copy(existing, newList, existing.Length);
}
newList[^1] = $"{type.FullName}.{staticFunctionName}({String.Join(',', stringArgs)})";
s_CompileList.Values = newList;
// Now recompile
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
}
[UnityEditor.Callbacks.DidReloadScripts]
private static void PostCompile()
{
try
{
// Get list of calls and call each one
string[] calls = s_CompileList.Values;
foreach (string call in calls)
{
RunCall(call);
}
}
finally
{
// Finally clear!
s_CompileList.Values = null;
}
}
private static void RunCall(string call)
{
Match match = Regex.Match(call, @"(.+)\.(.+?)\((.+?)?\)");
if (match.Groups.Count < 4)
{
Debug.LogError($"Call '{call}' was not in the correct format :(");
return;
}
string className = match.Groups[1].Captures[0].Value;
string methodName = match.Groups[2].Captures[0].Value;
string argString = match.Groups[3].Captures.Count > 0 ? match.Groups[3].Captures[0].Value : null;
string[] args = argString.IsNullOrEmpty() ? Array.Empty() : argString.Split(',');
Type finalType = Unsupported.GetTypeFromFullName(className);
if (finalType == null)
{
Debug.LogError($"Couldn't find type {className}!");
return;
}
MethodInfo method = finalType.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
{
Debug.LogError($"Couldn't find static method {finalType.Name}.{methodName}!");
return;
}
int numDeclaringParams = method.GetParameters().Length;
if (numDeclaringParams != args.Length)
{
Debug.LogError($"Couldn't call static method {finalType.Name}.{methodName} with {args.Length} args (expected: {numDeclaringParams}!");
return;
}
method.Invoke(null, args.Select(s => (object)s).ToArray());
}
}
}