chore(unity): 固定Unity CLI Loop本地包并移除UnitySkills依赖
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
using Unity.Profiling;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace io.github.hatayama.uLoopMCP
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler for McpEditorWindow - Manages Unity and server events
|
||||
/// Helper class for Presenter layer in MVP architecture
|
||||
/// Related classes:
|
||||
/// - McpEditorWindow: Main presenter that owns this handler
|
||||
/// - McpEditorModel: Model layer for state management
|
||||
/// - McpBridgeServer: Server that provides events
|
||||
/// - McpServerController: Server lifecycle management
|
||||
/// </summary>
|
||||
internal class McpEditorWindowEventHandler
|
||||
{
|
||||
private static readonly ProfilerMarker s_onEditorUpdateMarker =
|
||||
new ProfilerMarker("McpEditorWindow.OnEditorUpdate");
|
||||
private static readonly ProfilerMarker s_refreshUiMarker =
|
||||
new ProfilerMarker("McpEditorWindow.RefreshUI");
|
||||
|
||||
private readonly McpEditorModel _model;
|
||||
private readonly McpEditorWindow _window;
|
||||
|
||||
public McpEditorWindowEventHandler(McpEditorModel model, McpEditorWindow window)
|
||||
{
|
||||
_model = model;
|
||||
_window = window;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all event subscriptions
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
SubscribeToUnityEvents();
|
||||
SubscribeToServerEvents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup all event subscriptions
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
UnsubscribeFromUnityEvents();
|
||||
UnsubscribeFromServerEvents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to Unity Editor events
|
||||
/// </summary>
|
||||
private void SubscribeToUnityEvents()
|
||||
{
|
||||
EditorApplication.update += OnEditorUpdate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribe from Unity Editor events
|
||||
/// </summary>
|
||||
private void UnsubscribeFromUnityEvents()
|
||||
{
|
||||
EditorApplication.update -= OnEditorUpdate;
|
||||
}
|
||||
|
||||
private void SubscribeToServerEvents()
|
||||
{
|
||||
UnsubscribeFromServerEvents();
|
||||
|
||||
McpBridgeServer.OnServerStarted += OnServerStateChanged;
|
||||
McpBridgeServer.OnServerStopping += OnServerStateChanged;
|
||||
ConnectedToolsMonitoringService.OnConnectedToolsChanged += OnConnectedToolsChanged;
|
||||
CustomToolManager.OnToolsChanged += OnToolsChanged;
|
||||
|
||||
McpBridgeServer currentServer = McpServerController.CurrentServer;
|
||||
if (currentServer != null)
|
||||
{
|
||||
currentServer.OnClientConnected += OnClientConnected;
|
||||
currentServer.OnClientDisconnected += OnClientDisconnected;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromServerEvents()
|
||||
{
|
||||
McpBridgeServer.OnServerStarted -= OnServerStateChanged;
|
||||
McpBridgeServer.OnServerStopping -= OnServerStateChanged;
|
||||
ConnectedToolsMonitoringService.OnConnectedToolsChanged -= OnConnectedToolsChanged;
|
||||
CustomToolManager.OnToolsChanged -= OnToolsChanged;
|
||||
|
||||
McpBridgeServer currentServer = McpServerController.CurrentServer;
|
||||
if (currentServer != null)
|
||||
{
|
||||
currentServer.OnClientConnected -= OnClientConnected;
|
||||
currentServer.OnClientDisconnected -= OnClientDisconnected;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnServerStateChanged()
|
||||
{
|
||||
_window.InvalidateToolSettingsCatalog();
|
||||
_model.RequestRepaint();
|
||||
}
|
||||
|
||||
private void OnConnectedToolsChanged()
|
||||
{
|
||||
_model.RequestRepaint();
|
||||
}
|
||||
|
||||
private void OnToolsChanged()
|
||||
{
|
||||
_window.InvalidateToolSettingsCatalog();
|
||||
_model.RequestRepaint();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle client connection event - force UI repaint for immediate update
|
||||
/// </summary>
|
||||
private void OnClientConnected(string clientEndpoint)
|
||||
{
|
||||
// Enhanced logging for debugging client connection
|
||||
// Count check for debugging purposes only
|
||||
|
||||
// Clear reconnecting flags when client connects
|
||||
McpServerController.ClearReconnectingFlag();
|
||||
|
||||
// Mark that repaint is needed since events are called from background thread
|
||||
_model.RequestRepaint();
|
||||
|
||||
// Exit post-compile mode when client connects
|
||||
if (_model.Runtime.IsPostCompileMode)
|
||||
{
|
||||
_model.DisablePostCompileMode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle client disconnection event - force UI repaint for immediate update
|
||||
/// </summary>
|
||||
private void OnClientDisconnected(string clientEndpoint)
|
||||
{
|
||||
// Enhanced logging for debugging client disconnection issues
|
||||
// Count check for debugging purposes only
|
||||
|
||||
|
||||
// Mark that repaint is needed since events are called from background thread
|
||||
_model.RequestRepaint();
|
||||
}
|
||||
|
||||
private void OnEditorUpdate()
|
||||
{
|
||||
using (s_onEditorUpdateMarker.Auto())
|
||||
{
|
||||
if (!McpEditorWindowRefreshPolicy.ShouldRefreshOnEditorUpdate(_model.Runtime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_model.ClearRepaintRequest();
|
||||
using (s_refreshUiMarker.Auto())
|
||||
{
|
||||
_window.RefreshAllSections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-subscribe to server events (called after server start)
|
||||
/// </summary>
|
||||
public void RefreshServerEventSubscriptions()
|
||||
{
|
||||
SubscribeToServerEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// Post-compile recovery can stay active while UI data is unchanged, so explicit repaint
|
||||
// requests gate expensive full-section refreshes.
|
||||
internal static class McpEditorWindowRefreshPolicy
|
||||
{
|
||||
public static bool ShouldRefreshOnEditorUpdate(RuntimeState runtimeState)
|
||||
{
|
||||
Debug.Assert(runtimeState != null, "runtimeState must not be null");
|
||||
|
||||
return runtimeState.NeedsRepaint;
|
||||
}
|
||||
|
||||
public static bool ShouldRunExpensiveChecks(McpEditorWindowRefreshMode refreshMode)
|
||||
{
|
||||
return refreshMode == McpEditorWindowRefreshMode.Full;
|
||||
}
|
||||
|
||||
public static bool ShouldRefreshSkillInstallState(
|
||||
McpEditorWindowRefreshMode refreshMode,
|
||||
bool refreshRequested)
|
||||
{
|
||||
return refreshRequested && ShouldRunExpensiveChecks(refreshMode);
|
||||
}
|
||||
|
||||
public static bool ShouldKeepToolSettingsCatalogDirty(ToolSettingsSectionData toolSettingsData)
|
||||
{
|
||||
Debug.Assert(toolSettingsData != null, "toolSettingsData must not be null");
|
||||
|
||||
return toolSettingsData.ShowToolSettings && !toolSettingsData.IsRegistryAvailable;
|
||||
}
|
||||
|
||||
public static bool ShouldStartToolSettingsRegistryWarmup(
|
||||
bool isAlreadyScheduled,
|
||||
int attemptCount,
|
||||
int maxAttempts)
|
||||
{
|
||||
Debug.Assert(attemptCount >= 0, "attemptCount must not be negative");
|
||||
Debug.Assert(maxAttempts > 0, "maxAttempts must be positive");
|
||||
|
||||
return !isAlreadyScheduled && attemptCount < maxAttempts;
|
||||
}
|
||||
|
||||
public static double CalculateToolSettingsRegistryWarmupDelaySeconds(
|
||||
double initialDelaySeconds,
|
||||
double maxDelaySeconds,
|
||||
int attemptCount)
|
||||
{
|
||||
Debug.Assert(initialDelaySeconds > 0.0, "initialDelaySeconds must be positive");
|
||||
Debug.Assert(maxDelaySeconds >= initialDelaySeconds, "maxDelaySeconds must not be smaller than initialDelaySeconds");
|
||||
Debug.Assert(attemptCount >= 0, "attemptCount must not be negative");
|
||||
|
||||
double delaySeconds = initialDelaySeconds;
|
||||
for (int i = 0; i < attemptCount; i++)
|
||||
{
|
||||
delaySeconds *= 2.0;
|
||||
}
|
||||
|
||||
return System.Math.Min(delaySeconds, maxDelaySeconds);
|
||||
}
|
||||
}
|
||||
|
||||
internal enum McpEditorWindowRefreshMode
|
||||
{
|
||||
InitialPaint,
|
||||
Full
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user