193 lines
6.2 KiB
C#
193 lines
6.2 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using MCPForUnity.Editor.Data;
|
|
using MCPForUnity.Editor.Services;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace MCPForUnity.Editor.Helpers
|
|
{
|
|
/// <summary>
|
|
/// Automatically syncs Python tools to the MCP server when:
|
|
/// - PythonToolsAsset is modified
|
|
/// - Python files are imported/reimported
|
|
/// - Unity starts up
|
|
/// </summary>
|
|
[InitializeOnLoad]
|
|
public class PythonToolSyncProcessor : AssetPostprocessor
|
|
{
|
|
private const string SyncEnabledKey = "MCPForUnity.AutoSyncEnabled";
|
|
private static bool _isSyncing = false;
|
|
|
|
static PythonToolSyncProcessor()
|
|
{
|
|
// Sync on Unity startup
|
|
EditorApplication.delayCall += () =>
|
|
{
|
|
if (IsAutoSyncEnabled())
|
|
{
|
|
SyncAllTools();
|
|
}
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called after any assets are imported, deleted, or moved
|
|
/// </summary>
|
|
private static void OnPostprocessAllAssets(
|
|
string[] importedAssets,
|
|
string[] deletedAssets,
|
|
string[] movedAssets,
|
|
string[] movedFromAssetPaths)
|
|
{
|
|
// Prevent infinite loop - don't process if we're currently syncing
|
|
if (_isSyncing || !IsAutoSyncEnabled())
|
|
return;
|
|
|
|
bool needsSync = false;
|
|
|
|
// Only check for .py file changes, not PythonToolsAsset changes
|
|
// (PythonToolsAsset changes are internal state updates from syncing)
|
|
foreach (string path in importedAssets.Concat(movedAssets))
|
|
{
|
|
// Check if any .py files were modified
|
|
if (path.EndsWith(".py"))
|
|
{
|
|
needsSync = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check if any .py files were deleted
|
|
if (!needsSync && deletedAssets.Any(path => path.EndsWith(".py")))
|
|
{
|
|
needsSync = true;
|
|
}
|
|
|
|
if (needsSync)
|
|
{
|
|
SyncAllTools();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Syncs all Python tools from all PythonToolsAsset instances to the MCP server
|
|
/// </summary>
|
|
public static void SyncAllTools()
|
|
{
|
|
// Prevent re-entrant calls
|
|
if (_isSyncing)
|
|
{
|
|
McpLog.Warn("Sync already in progress, skipping...");
|
|
return;
|
|
}
|
|
|
|
_isSyncing = true;
|
|
try
|
|
{
|
|
if (!ServerPathResolver.TryFindEmbeddedServerSource(out string srcPath))
|
|
{
|
|
McpLog.Warn("Cannot sync Python tools: MCP server source not found");
|
|
return;
|
|
}
|
|
|
|
string toolsDir = Path.Combine(srcPath, "tools", "custom");
|
|
|
|
var result = MCPServiceLocator.ToolSync.SyncProjectTools(toolsDir);
|
|
|
|
if (result.Success)
|
|
{
|
|
if (result.CopiedCount > 0 || result.SkippedCount > 0)
|
|
{
|
|
McpLog.Info($"Python tools synced: {result.CopiedCount} copied, {result.SkippedCount} skipped");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
McpLog.Error($"Python tool sync failed with {result.ErrorCount} errors");
|
|
foreach (var msg in result.Messages)
|
|
{
|
|
McpLog.Error($" - {msg}");
|
|
}
|
|
}
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
McpLog.Error($"Python tool sync exception: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
_isSyncing = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if auto-sync is enabled (default: true)
|
|
/// </summary>
|
|
public static bool IsAutoSyncEnabled()
|
|
{
|
|
return EditorPrefs.GetBool(SyncEnabledKey, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enables or disables auto-sync
|
|
/// </summary>
|
|
public static void SetAutoSyncEnabled(bool enabled)
|
|
{
|
|
EditorPrefs.SetBool(SyncEnabledKey, enabled);
|
|
McpLog.Info($"Python tool auto-sync {(enabled ? "enabled" : "disabled")}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Menu item to reimport all Python files in the project
|
|
/// </summary>
|
|
[MenuItem("Window/MCP For Unity/Tool Sync/Reimport Python Files", priority = 99)]
|
|
public static void ReimportPythonFiles()
|
|
{
|
|
// Find all Python files (imported as TextAssets by PythonFileImporter)
|
|
var pythonGuids = AssetDatabase.FindAssets("t:TextAsset", new[] { "Assets" })
|
|
.Select(AssetDatabase.GUIDToAssetPath)
|
|
.Where(path => path.EndsWith(".py", System.StringComparison.OrdinalIgnoreCase))
|
|
.ToArray();
|
|
|
|
foreach (string path in pythonGuids)
|
|
{
|
|
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
|
|
}
|
|
|
|
int count = pythonGuids.Length;
|
|
McpLog.Info($"Reimported {count} Python files");
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Menu item to manually trigger sync
|
|
/// </summary>
|
|
[MenuItem("Window/MCP For Unity/Tool Sync/Sync Python Tools", priority = 100)]
|
|
public static void ManualSync()
|
|
{
|
|
McpLog.Info("Manually syncing Python tools...");
|
|
SyncAllTools();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Menu item to toggle auto-sync
|
|
/// </summary>
|
|
[MenuItem("Window/MCP For Unity/Tool Sync/Auto-Sync Python Tools", priority = 101)]
|
|
public static void ToggleAutoSync()
|
|
{
|
|
SetAutoSyncEnabled(!IsAutoSyncEnabled());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validate menu item (shows checkmark when enabled)
|
|
/// </summary>
|
|
[MenuItem("Window/MCP For Unity/Tool Sync/Auto-Sync Python Tools", true, priority = 101)]
|
|
public static bool ToggleAutoSyncValidate()
|
|
{
|
|
Menu.SetChecked("Window/MCP For Unity/Tool Sync/Auto-Sync Python Tools", IsAutoSyncEnabled());
|
|
return true;
|
|
}
|
|
}
|
|
}
|