using System;
using System.Linq;
using MCPForUnity.Editor.Data;
using MCPForUnity.Editor.Dependencies;
using MCPForUnity.Editor.Dependencies.Models;
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Models;
using UnityEditor;
using UnityEngine;
namespace MCPForUnity.Editor.Setup
{
/// <summary>
/// Setup wizard window for guiding users through dependency installation
/// </summary>
public class SetupWizardWindow : EditorWindow
{
private DependencyCheckResult _dependencyResult;
private Vector2 _scrollPosition;
private int _currentStep = 0;
private readonly string[] _stepTitles = {
"Setup",
"Complete"
};
public static void ShowWindow(DependencyCheckResult dependencyResult = null)
{
var window = GetWindow<SetupWizardWindow>("MCP for Unity Setup");
window.minSize = new Vector2(500, 400);
window.maxSize = new Vector2(800, 600);
window._dependencyResult = dependencyResult ?? DependencyManager.CheckAllDependencies();
window.Show();
}
private void OnEnable()
{
if (_dependencyResult == null)
{
_dependencyResult = DependencyManager.CheckAllDependencies();
}
}
private void OnGUI()
{
DrawHeader();
DrawProgressBar();
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
switch (_currentStep)
{
case 0: DrawSetupStep(); break;
case 1: DrawCompleteStep(); break;
}
EditorGUILayout.EndScrollView();
DrawFooter();
}
private void DrawHeader()
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.Label("MCP for Unity Setup Wizard", EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
GUILayout.Label($"Step {_currentStep + 1} of {_stepTitles.Length}");
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Step title
var titleStyle = new GUIStyle(EditorStyles.largeLabel)
{
fontSize = 16,
fontStyle = FontStyle.Bold
};
EditorGUILayout.LabelField(_stepTitles[_currentStep], titleStyle);
EditorGUILayout.Space();
}
private void DrawProgressBar()
{
var rect = EditorGUILayout.GetControlRect(false, 4);
var progress = (_currentStep + 1) / (float)_stepTitles.Length;
EditorGUI.ProgressBar(rect, progress, "");
EditorGUILayout.Space();
}
private void DrawSetupStep()
{
// Welcome section
DrawSectionTitle("MCP for Unity Setup");
EditorGUILayout.LabelField(
"This wizard will help you set up MCP for Unity to connect AI assistants with your Unity Editor.",
EditorStyles.wordWrappedLabel
);
EditorGUILayout.Space();
// Dependency check section
EditorGUILayout.BeginHorizontal();
DrawSectionTitle("System Check", 14);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh", GUILayout.Width(60), GUILayout.Height(20)))
{
_dependencyResult = DependencyManager.CheckAllDependencies();
}
EditorGUILayout.EndHorizontal();
// Show simplified dependency status
foreach (var dep in _dependencyResult.Dependencies)
{
DrawSimpleDependencyStatus(dep);
}
// Overall status and installation guidance
EditorGUILayout.Space();
if (!_dependencyResult.IsSystemReady)
{
// Only show critical warnings when dependencies are actually missing
EditorGUILayout.HelpBox(
"\u26A0 Missing Dependencies: MCP for Unity requires Python 3.10+ and UV package manager to function properly.",
MessageType.Warning
);
EditorGUILayout.Space();
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
DrawErrorStatus("Installation Required");
var recommendations = DependencyManager.GetInstallationRecommendations();
EditorGUILayout.LabelField(recommendations, EditorStyles.wordWrappedLabel);
EditorGUILayout.Space();
if (GUILayout.Button("Open Installation Links", GUILayout.Height(25)))
{
OpenInstallationUrls();
}
EditorGUILayout.EndVertical();
}
else
{
DrawSuccessStatus("System Ready");
EditorGUILayout.LabelField("All requirements are met. You can proceed to configure your AI clients.", EditorStyles.wordWrappedLabel);
}
}
private void DrawCompleteStep()
{
DrawSectionTitle("Setup Complete");
// Refresh dependency check with caching to avoid heavy operations on every repaint
if (_dependencyResult == null || (DateTime.UtcNow - _dependencyResult.CheckedAt).TotalSeconds > 2)
{
_dependencyResult = DependencyManager.CheckAllDependencies();
}
if (_dependencyResult.IsSystemReady)
{
DrawSuccessStatus("MCP for Unity Ready!");
EditorGUILayout.HelpBox(
"π MCP for Unity is now set up and ready to use!\n\n" +
"β’ Dependencies verified\n" +
"β’ MCP server ready\n" +
"β’ Client configuration accessible",
MessageType.Info
);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Documentation", GUILayout.Height(30)))
{
Application.OpenURL("https://github.com/CoplayDev/unity-mcp");
}
if (GUILayout.Button("Client Settings", GUILayout.Height(30)))
{
Windows.MCPForUnityEditorWindow.ShowWindow();
}
EditorGUILayout.EndHorizontal();
}
else
{
DrawErrorStatus("Setup Incomplete - Package Non-Functional");
EditorGUILayout.HelpBox(
"π¨ MCP for Unity CANNOT work - dependencies still missing!\n\n" +
"Install ALL required dependencies before the package will function.",
MessageType.Error
);
var missingDeps = _dependencyResult.GetMissingRequired();
if (missingDeps.Count > 0)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Still Missing:", EditorStyles.boldLabel);
foreach (var dep in missingDeps)
{
EditorGUILayout.LabelField($"β {dep.Name}", EditorStyles.label);
}
}
EditorGUILayout.Space();
if (GUILayout.Button("Go Back to Setup", GUILayout.Height(30)))
{
_currentStep = 0;
}
}
}
// Helper methods for consistent UI components
private void DrawSectionTitle(string title, int fontSize = 16)
{
var titleStyle = new GUIStyle(EditorStyles.boldLabel)
{
fontSize = fontSize,
fontStyle = FontStyle.Bold
};
EditorGUILayout.LabelField(title, titleStyle);
EditorGUILayout.Space();
}
private void DrawSuccessStatus(string message)
{
var originalColor = GUI.color;
GUI.color = Color.green;
EditorGUILayout.LabelField($"β {message}", EditorStyles.boldLabel);
GUI.color = originalColor;
EditorGUILayout.Space();
}
private void DrawErrorStatus(string message)
{
var originalColor = GUI.color;
GUI.color = Color.red;
EditorGUILayout.LabelField($"β {message}", EditorStyles.boldLabel);
GUI.color = originalColor;
EditorGUILayout.Space();
}
private void DrawSimpleDependencyStatus(DependencyStatus dep)
{
EditorGUILayout.BeginHorizontal();
var statusIcon = dep.IsAvailable ? "β" : "β";
var statusColor = dep.IsAvailable ? Color.green : Color.red;
var originalColor = GUI.color;
GUI.color = statusColor;
GUILayout.Label(statusIcon, GUILayout.Width(20));
EditorGUILayout.LabelField(dep.Name, EditorStyles.boldLabel);
GUI.color = originalColor;
if (!dep.IsAvailable && !string.IsNullOrEmpty(dep.ErrorMessage))
{
EditorGUILayout.LabelField($"({dep.ErrorMessage})", EditorStyles.miniLabel);
}
EditorGUILayout.EndHorizontal();
}
private void DrawFooter()
{
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
// Back button
GUI.enabled = _currentStep > 0;
if (GUILayout.Button("Back", GUILayout.Width(60)))
{
_currentStep--;
}
GUILayout.FlexibleSpace();
// Skip button
if (GUILayout.Button("Skip", GUILayout.Width(60)))
{
bool dismiss = EditorUtility.DisplayDialog(
"Skip Setup",
"\u26A0 Skipping setup will leave MCP for Unity non-functional!\n\n" +
"You can restart setup from: Window > MCP for Unity > Setup Wizard (Required)",
"Skip Anyway",
"Cancel"
);
if (dismiss)
{
SetupWizard.MarkSetupDismissed();
Close();
}
}
// Next/Done button
GUI.enabled = true;
string buttonText = _currentStep == _stepTitles.Length - 1 ? "Done" : "Next";
if (GUILayout.Button(buttonText, GUILayout.Width(80)))
{
if (_currentStep == _stepTitles.Length - 1)
{
SetupWizard.MarkSetupCompleted();
Close();
}
else
{
_currentStep++;
}
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
}
private void OpenInstallationUrls()
{
var (pythonUrl, uvUrl) = DependencyManager.GetInstallationUrls();
bool openPython = EditorUtility.DisplayDialog(
"Open Installation URLs",
"Open Python installation page?",
"Yes",
"No"
);
if (openPython)
{
Application.OpenURL(pythonUrl);
}
bool openUV = EditorUtility.DisplayDialog(
"Open Installation URLs",
"Open UV installation page?",
"Yes",
"No"
);
if (openUV)
{
Application.OpenURL(uvUrl);
}
}
}
}