Merge pull request #126 from xsodus/feature/vscode-ghcs-support
Feature: VSCode GitHub Copilot Supportmain
commit
8211d85563
|
|
@ -31,3 +31,4 @@ CONTRIBUTING.md.meta
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
.aider*
|
.aider*
|
||||||
|
.DS_Store*
|
||||||
|
|
@ -43,6 +43,26 @@ namespace UnityMcpBridge.Editor.Data
|
||||||
mcpType = McpTypes.Cursor,
|
mcpType = McpTypes.Cursor,
|
||||||
configStatus = "Not Configured",
|
configStatus = "Not Configured",
|
||||||
},
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "VSCode GitHub Copilot",
|
||||||
|
windowsConfigPath = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
"Code",
|
||||||
|
"User",
|
||||||
|
"settings.json"
|
||||||
|
),
|
||||||
|
linuxConfigPath = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||||
|
"Library",
|
||||||
|
"Application Support",
|
||||||
|
"Code",
|
||||||
|
"User",
|
||||||
|
"settings.json"
|
||||||
|
),
|
||||||
|
mcpType = McpTypes.VSCode,
|
||||||
|
configStatus = "Not Configured",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize status enums after construction
|
// Initialize status enums after construction
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace UnityMcpBridge.Editor.Models
|
||||||
{
|
{
|
||||||
ClaudeDesktop,
|
ClaudeDesktop,
|
||||||
Cursor,
|
Cursor,
|
||||||
|
VSCode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
// Editor window to display manual configuration instructions
|
// Editor window to display manual configuration instructions
|
||||||
public class ManualConfigEditorWindow : EditorWindow
|
public class ManualConfigEditorWindow : EditorWindow
|
||||||
{
|
{
|
||||||
private string configPath;
|
protected string configPath;
|
||||||
private string configJson;
|
protected string configJson;
|
||||||
private Vector2 scrollPos;
|
protected Vector2 scrollPos;
|
||||||
private bool pathCopied = false;
|
protected bool pathCopied = false;
|
||||||
private bool jsonCopied = false;
|
protected bool jsonCopied = false;
|
||||||
private float copyFeedbackTimer = 0;
|
protected float copyFeedbackTimer = 0;
|
||||||
private McpClient mcpClient;
|
protected McpClient mcpClient;
|
||||||
|
|
||||||
public static void ShowWindow(string configPath, string configJson, McpClient mcpClient)
|
public static void ShowWindow(string configPath, string configJson, McpClient mcpClient)
|
||||||
{
|
{
|
||||||
|
|
@ -26,7 +26,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
window.Show();
|
window.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGUI()
|
protected virtual void OnGUI()
|
||||||
{
|
{
|
||||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
||||||
|
|
||||||
|
|
@ -245,7 +245,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
EditorGUILayout.EndScrollView();
|
EditorGUILayout.EndScrollView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
protected virtual void Update()
|
||||||
{
|
{
|
||||||
// Handle the feedback message timer
|
// Handle the feedback message timer
|
||||||
if (copyFeedbackTimer > 0)
|
if (copyFeedbackTimer > 0)
|
||||||
|
|
|
||||||
|
|
@ -137,24 +137,75 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
// Create muted button style for Manual Setup
|
// Create muted button style for Manual Setup
|
||||||
GUIStyle mutedButtonStyle = new(buttonStyle);
|
GUIStyle mutedButtonStyle = new(buttonStyle);
|
||||||
|
|
||||||
if (
|
if (mcpClient.mcpType == McpTypes.VSCode)
|
||||||
GUILayout.Button(
|
{
|
||||||
$"Auto Configure {mcpClient.name}",
|
// Special handling for VSCode GitHub Copilot
|
||||||
buttonStyle,
|
if (
|
||||||
GUILayout.Height(28)
|
GUILayout.Button(
|
||||||
|
"Auto Configure VSCode with GitHub Copilot",
|
||||||
|
buttonStyle,
|
||||||
|
GUILayout.Height(28)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
{
|
||||||
{
|
ConfigureMcpClient(mcpClient);
|
||||||
ConfigureMcpClient(mcpClient);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("Manual Setup", mutedButtonStyle, GUILayout.Height(28)))
|
if (GUILayout.Button("Manual Setup", mutedButtonStyle, GUILayout.Height(28)))
|
||||||
|
{
|
||||||
|
// Show VSCode specific manual setup window
|
||||||
|
string configPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? mcpClient.windowsConfigPath
|
||||||
|
: mcpClient.linuxConfigPath;
|
||||||
|
|
||||||
|
// Get the Python directory path
|
||||||
|
string pythonDir = FindPackagePythonDirectory();
|
||||||
|
|
||||||
|
// Create VSCode-specific configuration
|
||||||
|
var vscodeConfig = new
|
||||||
|
{
|
||||||
|
mcp = new
|
||||||
|
{
|
||||||
|
servers = new
|
||||||
|
{
|
||||||
|
unityMCP = new
|
||||||
|
{
|
||||||
|
command = "uv",
|
||||||
|
args = new[] { "--directory", pythonDir, "run", "server.py" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
|
||||||
|
string manualConfigJson = JsonConvert.SerializeObject(vscodeConfig, jsonSettings);
|
||||||
|
|
||||||
|
// Use the VSCodeManualSetupWindow directly since we're in the same namespace
|
||||||
|
VSCodeManualSetupWindow.ShowWindow(configPath, manualConfigJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Get the appropriate config path based on OS
|
// Standard client buttons
|
||||||
string configPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
if (
|
||||||
? mcpClient.windowsConfigPath
|
GUILayout.Button(
|
||||||
: mcpClient.linuxConfigPath;
|
$"Auto Configure {mcpClient.name}",
|
||||||
ShowManualInstructionsWindow(configPath, mcpClient);
|
buttonStyle,
|
||||||
|
GUILayout.Height(28)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ConfigureMcpClient(mcpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Manual Setup", mutedButtonStyle, GUILayout.Height(28)))
|
||||||
|
{
|
||||||
|
// Get the appropriate config path based on OS
|
||||||
|
string configPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? mcpClient.windowsConfigPath
|
||||||
|
: mcpClient.linuxConfigPath;
|
||||||
|
ShowManualInstructionsWindow(configPath, mcpClient);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EditorGUILayout.Space(5);
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
|
@ -274,7 +325,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
isUnityBridgeRunning = !isUnityBridgeRunning;
|
isUnityBridgeRunning = !isUnityBridgeRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string WriteToConfig(string pythonDir, string configPath)
|
private string WriteToConfig(string pythonDir, string configPath, McpClient mcpClient = null)
|
||||||
{
|
{
|
||||||
// Create configuration object for unityMCP
|
// Create configuration object for unityMCP
|
||||||
McpConfigServer unityMCPConfig = new()
|
McpConfigServer unityMCPConfig = new()
|
||||||
|
|
@ -303,14 +354,36 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
dynamic existingConfig = JsonConvert.DeserializeObject(existingJson);
|
dynamic existingConfig = JsonConvert.DeserializeObject(existingJson);
|
||||||
existingConfig ??= new Newtonsoft.Json.Linq.JObject();
|
existingConfig ??= new Newtonsoft.Json.Linq.JObject();
|
||||||
|
|
||||||
// Ensure mcpServers object exists
|
// Handle different client types with a switch statement
|
||||||
if (existingConfig.mcpServers == null)
|
switch (mcpClient?.mcpType)
|
||||||
{
|
{
|
||||||
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
|
case McpTypes.VSCode:
|
||||||
|
// VSCode specific configuration
|
||||||
|
// Ensure mcp object exists
|
||||||
|
if (existingConfig.mcp == null)
|
||||||
|
{
|
||||||
|
existingConfig.mcp = new Newtonsoft.Json.Linq.JObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure mcp.servers object exists
|
||||||
|
if (existingConfig.mcp.servers == null)
|
||||||
|
{
|
||||||
|
existingConfig.mcp.servers = new Newtonsoft.Json.Linq.JObject();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Standard MCP configuration (Claude Desktop, Cursor, etc.)
|
||||||
|
// Ensure mcpServers object exists
|
||||||
|
if (existingConfig.mcpServers == null)
|
||||||
|
{
|
||||||
|
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add/update unityMCP while preserving other servers
|
// Add/update UnityMCP server in VSCode settings
|
||||||
existingConfig.mcpServers.unityMCP =
|
existingConfig.mcp.servers.unityMCP =
|
||||||
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
||||||
JsonConvert.SerializeObject(unityMCPConfig)
|
JsonConvert.SerializeObject(unityMCPConfig)
|
||||||
);
|
);
|
||||||
|
|
@ -334,22 +407,49 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
{
|
{
|
||||||
// Get the Python directory path using Package Manager API
|
// Get the Python directory path using Package Manager API
|
||||||
string pythonDir = FindPackagePythonDirectory();
|
string pythonDir = FindPackagePythonDirectory();
|
||||||
|
string manualConfigJson;
|
||||||
// Create the manual configuration message
|
|
||||||
McpConfig jsonConfig = new()
|
// Create common JsonSerializerSettings
|
||||||
{
|
|
||||||
mcpServers = new McpConfigServers
|
|
||||||
{
|
|
||||||
unityMCP = new McpConfigServer
|
|
||||||
{
|
|
||||||
command = "uv",
|
|
||||||
args = new[] { "--directory", pythonDir, "run", "server.py" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
|
JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
|
||||||
string manualConfigJson = JsonConvert.SerializeObject(jsonConfig, jsonSettings);
|
|
||||||
|
// Use switch statement to handle different client types
|
||||||
|
switch (mcpClient.mcpType)
|
||||||
|
{
|
||||||
|
case McpTypes.VSCode:
|
||||||
|
// Create VSCode-specific configuration with proper format
|
||||||
|
var vscodeConfig = new
|
||||||
|
{
|
||||||
|
mcp = new
|
||||||
|
{
|
||||||
|
servers = new
|
||||||
|
{
|
||||||
|
unityMCP = new
|
||||||
|
{
|
||||||
|
command = "uv",
|
||||||
|
args = new[] { "--directory", pythonDir, "run", "server.py" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
manualConfigJson = JsonConvert.SerializeObject(vscodeConfig, jsonSettings);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Create standard MCP configuration for other clients
|
||||||
|
McpConfig jsonConfig = new()
|
||||||
|
{
|
||||||
|
mcpServers = new McpConfigServers
|
||||||
|
{
|
||||||
|
unityMCP = new McpConfigServer
|
||||||
|
{
|
||||||
|
command = "uv",
|
||||||
|
args = new[] { "--directory", pythonDir, "run", "server.py" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
manualConfigJson = JsonConvert.SerializeObject(jsonConfig, jsonSettings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient);
|
ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient);
|
||||||
}
|
}
|
||||||
|
|
@ -450,7 +550,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
return "Manual Configuration Required";
|
return "Manual Configuration Required";
|
||||||
}
|
}
|
||||||
|
|
||||||
string result = WriteToConfig(pythonDir, configPath);
|
string result = WriteToConfig(pythonDir, configPath, mcpClient);
|
||||||
|
|
||||||
// Update the client status after successful configuration
|
// Update the client status after successful configuration
|
||||||
if (result == "Configured successfully")
|
if (result == "Configured successfully")
|
||||||
|
|
@ -542,18 +642,42 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
string configJson = File.ReadAllText(configPath);
|
string configJson = File.ReadAllText(configPath);
|
||||||
McpConfig config = JsonConvert.DeserializeObject<McpConfig>(configJson);
|
string pythonDir = ServerInstaller.GetServerPath();
|
||||||
|
|
||||||
if (config?.mcpServers?.unityMCP != null)
|
// Use switch statement to handle different client types, extracting common logic
|
||||||
|
string[] args = null;
|
||||||
|
bool configExists = false;
|
||||||
|
|
||||||
|
switch (mcpClient.mcpType)
|
||||||
{
|
{
|
||||||
string pythonDir = ServerInstaller.GetServerPath();
|
case McpTypes.VSCode:
|
||||||
if (
|
dynamic config = JsonConvert.DeserializeObject(configJson);
|
||||||
pythonDir != null
|
|
||||||
&& Array.Exists(
|
if (config?.mcp?.servers?.unityMCP != null)
|
||||||
config.mcpServers.unityMCP.args,
|
{
|
||||||
arg => arg.Contains(pythonDir, StringComparison.Ordinal)
|
// Extract args from VSCode config format
|
||||||
)
|
args = config.mcp.servers.unityMCP.args.ToObject<string[]>();
|
||||||
)
|
configExists = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Standard MCP configuration check for Claude Desktop, Cursor, etc.
|
||||||
|
McpConfig standardConfig = JsonConvert.DeserializeObject<McpConfig>(configJson);
|
||||||
|
|
||||||
|
if (standardConfig?.mcpServers?.unityMCP != null)
|
||||||
|
{
|
||||||
|
args = standardConfig.mcpServers.unityMCP.args;
|
||||||
|
configExists = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common logic for checking configuration status
|
||||||
|
if (configExists)
|
||||||
|
{
|
||||||
|
if (pythonDir != null &&
|
||||||
|
Array.Exists(args, arg => arg.Contains(pythonDir, StringComparison.Ordinal)))
|
||||||
{
|
{
|
||||||
mcpClient.SetStatus(McpStatus.Configured);
|
mcpClient.SetStatus(McpStatus.Configured);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,295 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityMcpBridge.Editor.Models;
|
||||||
|
|
||||||
|
namespace UnityMcpBridge.Editor.Windows
|
||||||
|
{
|
||||||
|
public class VSCodeManualSetupWindow : ManualConfigEditorWindow
|
||||||
|
{
|
||||||
|
public static new void ShowWindow(string configPath, string configJson)
|
||||||
|
{
|
||||||
|
var window = GetWindow<VSCodeManualSetupWindow>("VSCode GitHub Copilot Setup");
|
||||||
|
window.configPath = configPath;
|
||||||
|
window.configJson = configJson;
|
||||||
|
window.minSize = new Vector2(550, 500);
|
||||||
|
|
||||||
|
// Create a McpClient for VSCode
|
||||||
|
window.mcpClient = new McpClient
|
||||||
|
{
|
||||||
|
name = "VSCode GitHub Copilot",
|
||||||
|
mcpType = McpTypes.VSCode
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnGUI()
|
||||||
|
{
|
||||||
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
||||||
|
|
||||||
|
// Header with improved styling
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
Rect titleRect = EditorGUILayout.GetControlRect(false, 30);
|
||||||
|
EditorGUI.DrawRect(
|
||||||
|
new Rect(titleRect.x, titleRect.y, titleRect.width, titleRect.height),
|
||||||
|
new Color(0.2f, 0.2f, 0.2f, 0.1f)
|
||||||
|
);
|
||||||
|
GUI.Label(
|
||||||
|
new Rect(titleRect.x + 10, titleRect.y + 6, titleRect.width - 20, titleRect.height),
|
||||||
|
"VSCode GitHub Copilot MCP Setup",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
// Instructions with improved styling
|
||||||
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||||
|
|
||||||
|
Rect headerRect = EditorGUILayout.GetControlRect(false, 24);
|
||||||
|
EditorGUI.DrawRect(
|
||||||
|
new Rect(headerRect.x, headerRect.y, headerRect.width, headerRect.height),
|
||||||
|
new Color(0.1f, 0.1f, 0.1f, 0.2f)
|
||||||
|
);
|
||||||
|
GUI.Label(
|
||||||
|
new Rect(
|
||||||
|
headerRect.x + 8,
|
||||||
|
headerRect.y + 4,
|
||||||
|
headerRect.width - 16,
|
||||||
|
headerRect.height
|
||||||
|
),
|
||||||
|
"Setting up GitHub Copilot in VSCode with Unity MCP",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
GUIStyle instructionStyle = new(EditorStyles.wordWrappedLabel)
|
||||||
|
{
|
||||||
|
margin = new RectOffset(10, 10, 5, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"1. Prerequisites",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• Ensure you have VSCode installed",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• Ensure you have GitHub Copilot extension installed in VSCode",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• Ensure you have a valid GitHub Copilot subscription",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"2. Steps to Configure",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"a) Open VSCode Settings (File > Preferences > Settings)",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"b) Click on the 'Open Settings (JSON)' button in the top right",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"c) Add the MCP configuration shown below to your settings.json file",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"d) Save the file and restart VSCode",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"3. VSCode settings.json location:",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
|
||||||
|
// Path section with improved styling
|
||||||
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||||
|
string displayPath;
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
displayPath = System.IO.Path.Combine(
|
||||||
|
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData),
|
||||||
|
"Code",
|
||||||
|
"User",
|
||||||
|
"settings.json"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
displayPath = System.IO.Path.Combine(
|
||||||
|
System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile),
|
||||||
|
"Library",
|
||||||
|
"Application Support",
|
||||||
|
"Code",
|
||||||
|
"User",
|
||||||
|
"settings.json"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the path in the base class config path
|
||||||
|
if (string.IsNullOrEmpty(configPath))
|
||||||
|
{
|
||||||
|
configPath = displayPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent text overflow by allowing the text field to wrap
|
||||||
|
GUIStyle pathStyle = new(EditorStyles.textField) { wordWrap = true };
|
||||||
|
|
||||||
|
EditorGUILayout.TextField(
|
||||||
|
displayPath,
|
||||||
|
pathStyle,
|
||||||
|
GUILayout.Height(EditorGUIUtility.singleLineHeight)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Copy button with improved styling
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUIStyle copyButtonStyle = new(GUI.skin.button)
|
||||||
|
{
|
||||||
|
padding = new RectOffset(15, 15, 5, 5),
|
||||||
|
margin = new RectOffset(10, 10, 5, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
GUILayout.Button(
|
||||||
|
"Copy Path",
|
||||||
|
copyButtonStyle,
|
||||||
|
GUILayout.Height(25),
|
||||||
|
GUILayout.Width(100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EditorGUIUtility.systemCopyBuffer = displayPath;
|
||||||
|
pathCopied = true;
|
||||||
|
copyFeedbackTimer = 2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
GUILayout.Button(
|
||||||
|
"Open File",
|
||||||
|
copyButtonStyle,
|
||||||
|
GUILayout.Height(25),
|
||||||
|
GUILayout.Width(100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Open the file using the system's default application
|
||||||
|
System.Diagnostics.Process.Start(
|
||||||
|
new System.Diagnostics.ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = displayPath,
|
||||||
|
UseShellExecute = true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathCopied)
|
||||||
|
{
|
||||||
|
GUIStyle feedbackStyle = new(EditorStyles.label);
|
||||||
|
feedbackStyle.normal.textColor = Color.green;
|
||||||
|
EditorGUILayout.LabelField("Copied!", feedbackStyle, GUILayout.Width(60));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"4. Add this configuration to your settings.json:",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
|
||||||
|
// JSON section with improved styling
|
||||||
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||||
|
|
||||||
|
// Improved text area for JSON with syntax highlighting colors
|
||||||
|
GUIStyle jsonStyle = new(EditorStyles.textArea)
|
||||||
|
{
|
||||||
|
font = EditorStyles.boldFont,
|
||||||
|
wordWrap = true,
|
||||||
|
};
|
||||||
|
jsonStyle.normal.textColor = new Color(0.3f, 0.6f, 0.9f); // Syntax highlighting blue
|
||||||
|
|
||||||
|
// Draw the JSON in a text area with a taller height for better readability
|
||||||
|
EditorGUILayout.TextArea(configJson, jsonStyle, GUILayout.Height(200));
|
||||||
|
|
||||||
|
// Copy JSON button with improved styling
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
|
||||||
|
if (
|
||||||
|
GUILayout.Button(
|
||||||
|
"Copy JSON",
|
||||||
|
copyButtonStyle,
|
||||||
|
GUILayout.Height(25),
|
||||||
|
GUILayout.Width(100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EditorGUIUtility.systemCopyBuffer = configJson;
|
||||||
|
jsonCopied = true;
|
||||||
|
copyFeedbackTimer = 2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonCopied)
|
||||||
|
{
|
||||||
|
GUIStyle feedbackStyle = new(EditorStyles.label);
|
||||||
|
feedbackStyle.normal.textColor = Color.green;
|
||||||
|
EditorGUILayout.LabelField("Copied!", feedbackStyle, GUILayout.Width(60));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"5. After configuration:",
|
||||||
|
EditorStyles.boldLabel
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• Restart VSCode",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• GitHub Copilot will now be able to interact with your Unity project through the MCP protocol",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
EditorGUILayout.LabelField(
|
||||||
|
"• Remember to have the Unity MCP Bridge running in Unity Editor",
|
||||||
|
instructionStyle
|
||||||
|
);
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
|
||||||
|
EditorGUILayout.Space(10);
|
||||||
|
|
||||||
|
// Close button at the bottom
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
if (GUILayout.Button("Close", GUILayout.Height(30), GUILayout.Width(100)))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
// Call the base implementation which handles the copy feedback timer
|
||||||
|
base.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 377fe73d52cf0435fabead5f50a0d204
|
||||||
Loading…
Reference in New Issue