修改提交
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# TCP Bridge UI Windows
|
||||
|
||||
This folder contains Unity Editor windows for managing the TCP Bridge server.
|
||||
|
||||
## Windows Overview
|
||||
|
||||
### TcpBridgeControlWindow
|
||||
|
||||
**Access**: `Tools > Codely Bridge > Control Window`
|
||||
|
||||
The main control panel for managing the TCP Bridge server. Features:
|
||||
|
||||
- **Server Status**: Real-time status display with visual indicators
|
||||
- **Server Controls**: Start, Stop, and Restart buttons
|
||||
- **Configuration**: Debug logging toggle
|
||||
- **Port Management**: View current port, discover new ports, check availability
|
||||
- **Debug Information**: System info and console access
|
||||
|
||||
### TcpBridgeStatusWindow
|
||||
|
||||
**Access**: `Tools > Codely Bridge > Status Window`
|
||||
|
||||
A compact status window that can be docked anywhere in Unity for quick monitoring:
|
||||
|
||||
- **Status Indicator**: Running/Stopped with port information
|
||||
- **Quick Controls**: Start/Stop buttons
|
||||
- **Control Window Access**: Quick link to full control window
|
||||
|
||||
### TcpBridgeMenuItems
|
||||
|
||||
**Access**: `Tools > Codely Bridge > [various options]`
|
||||
|
||||
Menu items for quick operations:
|
||||
|
||||
- **Start Server** - Start the TCP bridge
|
||||
- **Stop Server** - Stop the TCP bridge
|
||||
- **Restart Server** - Restart the TCP bridge
|
||||
- **Show Server Status** - Display status dialog
|
||||
- **Discover New Port** - Find and optionally switch to new port
|
||||
- **Enable/Disable Debug Logging** - Toggle debug output
|
||||
|
||||
## Usage Tips
|
||||
|
||||
1. **First Time Setup**: The TCP bridge starts automatically when Unity loads
|
||||
2. **Status Monitoring**: Keep the Status Window docked for quick monitoring
|
||||
3. **Port Issues**: Use "Discover New Port" if you encounter port conflicts
|
||||
4. **Debugging**: Enable debug logging when troubleshooting connection issues
|
||||
5. **Menu Access**: Use keyboard shortcuts or menu items for quick operations
|
||||
|
||||
## Integration
|
||||
|
||||
All windows are designed to work together:
|
||||
|
||||
- Status Window → Control Window (full features)
|
||||
- Menu Items → Quick operations without opening windows
|
||||
- Control Window → Comprehensive management interface
|
||||
|
||||
The UI automatically updates to reflect the current server state and provides consistent feedback across all interfaces.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d6a0fe967b8fd64f94895d914f34608
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,470 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityTcp.Editor.Helpers;
|
||||
|
||||
namespace UnityTcp.Editor.Windows
|
||||
{
|
||||
public class TcpBridgeControlWindow : EditorWindow
|
||||
{
|
||||
private enum BridgeState { NotStarted, Starting, Started }
|
||||
|
||||
private double lastStatusUpdate;
|
||||
private const double StatusUpdateInterval = 0.5;
|
||||
private BridgeState currentState = BridgeState.NotStarted;
|
||||
private bool isStarting = false;
|
||||
private double startingTime = 0;
|
||||
private const double StartingTimeout = 3.0;
|
||||
|
||||
// Window title icon
|
||||
private Texture2D titleIcon;
|
||||
|
||||
// Client icons
|
||||
private Texture2D codelyIcon;
|
||||
private Texture2D vscodeIcon;
|
||||
private Texture2D visualStudioIcon;
|
||||
private Texture2D jetbrainsIcon;
|
||||
private Texture2D cliIcon;
|
||||
private Texture2D unityEditorIcon;
|
||||
private Texture2D tuanjieIcon;
|
||||
|
||||
// Fonts
|
||||
private Font firaMono;
|
||||
private Font inter;
|
||||
|
||||
// Button textures
|
||||
private Texture2D connectTex;
|
||||
private Texture2D connectHoverTex;
|
||||
private Texture2D connectPressedTex;
|
||||
private Texture2D connectingTex;
|
||||
private Texture2D disconnectTex;
|
||||
private Texture2D disconnectHoverTex;
|
||||
private Texture2D disconnectPressedTex;
|
||||
|
||||
// Connection tracking
|
||||
private bool connectedToCLI;
|
||||
private bool connectedToVSCode;
|
||||
private bool connectedToVisualStudio;
|
||||
private bool connectedToJetBrains;
|
||||
private bool connectedToUnityEditor;
|
||||
private bool connectedToTuanjie;
|
||||
|
||||
private static readonly Color GreenColor = new Color(0x01 / 255f, 0xA7 / 255f, 0x7F / 255f);
|
||||
private static readonly Color GrayColor = new Color(0.5f, 0.5f, 0.5f);
|
||||
private static readonly Color SubtextColor = new Color(0x9C / 255f, 0xA3 / 255f, 0xAF / 255f);
|
||||
|
||||
// ── Scale ────────────────────────────────────────────────────────────────
|
||||
private const float ScaleFactor = 2 / 1.5f;
|
||||
|
||||
// ── Base sizes (ScaleFactor = 1) ─────────────────────────────────────────
|
||||
private const float BaseWindowWidth = 430f;
|
||||
private const float BaseLeftMargin = 25f;
|
||||
private const float BaseTopPadding = 40f;
|
||||
private const float BaseBottomPadding = 40f;
|
||||
private const float BaseCodelyIconSize = 40f;
|
||||
private const float BaseSpaceAfterIcon = 25f;
|
||||
private const int BaseTitleFontSize = 20;
|
||||
private const float BaseSpaceAfterTitle = 15f;
|
||||
private const int BaseBodyFontSize = 17;
|
||||
private const float BaseSpaceAfterBody = 30f;
|
||||
private const int BaseStatusFontSize = 12;
|
||||
private const float BaseSpaceBeforeStatus = 30f;
|
||||
private const float BaseMinWindowHeight = 80f;
|
||||
private const int BaseConnectedFontSize = 16;
|
||||
private const float BaseConnectedItemSpacing = 6f;
|
||||
private const float BaseClientIconSize = 24f;
|
||||
private const float BaseClientIconLabelGap = 6f;
|
||||
private const int BaseClientLabelFontSize = 13;
|
||||
private const float BaseClientLabelHeight = 18f;
|
||||
private const float BaseClientItemSpacing = 12f;
|
||||
private const float BaseConnectBtnW = 159f;
|
||||
private const float BaseConnectBtnH = 40f;
|
||||
|
||||
// ── Scaled values ─────────────────────────────────────────────────────────
|
||||
private static float WindowWidth => BaseWindowWidth * ScaleFactor;
|
||||
private static float LeftMargin => BaseLeftMargin * ScaleFactor;
|
||||
private static float TopPadding => BaseTopPadding * ScaleFactor;
|
||||
private static float BottomPadding => BaseBottomPadding * ScaleFactor;
|
||||
private static float CodelyIconSize => BaseCodelyIconSize * ScaleFactor;
|
||||
private static float SpaceAfterIcon => BaseSpaceAfterIcon * ScaleFactor;
|
||||
private static int TitleFontSize => Mathf.RoundToInt(BaseTitleFontSize * ScaleFactor);
|
||||
private static float SpaceAfterTitle => BaseSpaceAfterTitle * ScaleFactor;
|
||||
private static int BodyFontSize => Mathf.RoundToInt(BaseBodyFontSize * ScaleFactor);
|
||||
private static float SpaceAfterBody => BaseSpaceAfterBody * ScaleFactor;
|
||||
private static int StatusFontSize => Mathf.RoundToInt(BaseStatusFontSize * ScaleFactor);
|
||||
private static float SpaceBeforeStatus => BaseSpaceBeforeStatus * ScaleFactor;
|
||||
private static float MinWindowHeight => BaseMinWindowHeight * ScaleFactor;
|
||||
private static int ConnectedFontSize => Mathf.RoundToInt(BaseConnectedFontSize * ScaleFactor);
|
||||
private static float ConnectedItemSpacing => BaseConnectedItemSpacing * ScaleFactor;
|
||||
private static float ClientIconSize => BaseClientIconSize * ScaleFactor;
|
||||
private static float ClientIconLabelGap => BaseClientIconLabelGap * ScaleFactor;
|
||||
private static int ClientLabelFontSize => Mathf.RoundToInt(BaseClientLabelFontSize * ScaleFactor);
|
||||
private static float ClientLabelHeight => BaseClientLabelHeight * ScaleFactor;
|
||||
private static float ClientItemSpacing => BaseClientItemSpacing * ScaleFactor;
|
||||
private static float ConnectBtnW => BaseConnectBtnW * ScaleFactor;
|
||||
private static float ConnectBtnH => BaseConnectBtnH * ScaleFactor;
|
||||
|
||||
[MenuItem("Window/Codely Bridge", priority = 1001)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<TcpBridgeControlWindow>("Codely Bridge");
|
||||
window.minSize = new Vector2(WindowWidth, MinWindowHeight);
|
||||
window.maxSize = new Vector2(WindowWidth, 2000f);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
EditorPrefs.SetBool("UnityTcp.DebugLogs", false);
|
||||
LoadIcons();
|
||||
UpdateStatus();
|
||||
UnityTcpBridge.OnClientPlatformsChanged += OnClientPlatformsChanged;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UnityTcpBridge.OnClientPlatformsChanged -= OnClientPlatformsChanged;
|
||||
}
|
||||
|
||||
private void OnClientPlatformsChanged() => UpdateConnectionStatus();
|
||||
|
||||
private static Texture2D Load(string path) =>
|
||||
AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
|
||||
private void LoadIcons()
|
||||
{
|
||||
const string b = "Packages/cn.tuanjie.codely.bridge/Editor/Icons/";
|
||||
titleIcon = Load(b + "title_icon.png");
|
||||
codelyIcon = Load(b + "codely.png");
|
||||
vscodeIcon = Load(b + "vscode.png");
|
||||
visualStudioIcon = Load(b + "visualstudio.png");
|
||||
jetbrainsIcon = Load(b + "jetbrains.png");
|
||||
cliIcon = Load(b + "cli.png");
|
||||
unityEditorIcon = Load(b + "unity_editor.png");
|
||||
tuanjieIcon = Load(b + "tuanjie.png");
|
||||
connectTex = Load(b + "connect.png");
|
||||
connectHoverTex = Load(b + "connect_hover.png");
|
||||
connectPressedTex = Load(b + "connect_pressed.png");
|
||||
connectingTex = Load(b + "connecting.png");
|
||||
disconnectTex = Load(b + "disconnect.png");
|
||||
disconnectHoverTex = Load(b + "disconnect_hover.png");
|
||||
disconnectPressedTex = Load(b + "disconnect_pressed.png");
|
||||
|
||||
firaMono = AssetDatabase.LoadAssetAtPath<Font>("Packages/cn.tuanjie.codely.bridge/Editor/fonts/FiraMono-Regular.ttf");
|
||||
inter = AssetDatabase.LoadAssetAtPath<Font>("Packages/cn.tuanjie.codely.bridge/Editor/fonts/Inter.ttc");
|
||||
|
||||
if (titleIcon != null)
|
||||
titleContent = new GUIContent(" Codely Bridge", titleIcon);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (EditorApplication.timeSinceStartup - lastStatusUpdate > StatusUpdateInterval)
|
||||
{
|
||||
UpdateStatus();
|
||||
lastStatusUpdate = EditorApplication.timeSinceStartup;
|
||||
}
|
||||
|
||||
DrawUI();
|
||||
}
|
||||
|
||||
private static readonly Color BgColor = new Color(0.18f, 0.18f, 0.18f);
|
||||
|
||||
private void DrawUI()
|
||||
{
|
||||
EditorGUI.DrawRect(new Rect(0, 0, position.width, position.height), BgColor);
|
||||
|
||||
bool started = currentState == BridgeState.Started;
|
||||
|
||||
// ── Top padding ──────────────────────────────────────────────────────
|
||||
GUILayout.Space(TopPadding);
|
||||
|
||||
// ── Codely icon ──────────────────────────────────────────────────────
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(LeftMargin);
|
||||
if (codelyIcon != null)
|
||||
GUILayout.Box(codelyIcon, GUIStyle.none, GUILayout.Width(CodelyIconSize), GUILayout.Height(CodelyIconSize));
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(SpaceAfterIcon);
|
||||
|
||||
// ── Title ────────────────────────────────────────────────────────────
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(LeftMargin);
|
||||
var titleStyle = new GUIStyle(EditorStyles.boldLabel) { fontSize = TitleFontSize, wordWrap = false, font = inter };
|
||||
if (started) {
|
||||
titleStyle.normal.textColor = GreenColor;
|
||||
titleStyle.hover.textColor = GreenColor;
|
||||
}
|
||||
else {
|
||||
titleStyle.normal.textColor = Color.white;
|
||||
titleStyle.hover.textColor = Color.white;
|
||||
}
|
||||
GUILayout.Label(
|
||||
started ? "Codely bridge is ready \u2713" : "Connect to Codely Agent",
|
||||
titleStyle);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(SpaceAfterTitle);
|
||||
|
||||
// ── Body (Form 1: client list | Form 2: text + status) ───────────────
|
||||
bool hasClients = started && (connectedToCLI || connectedToVSCode || connectedToVisualStudio
|
||||
|| connectedToJetBrains || connectedToUnityEditor || connectedToTuanjie);
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(LeftMargin);
|
||||
GUILayout.BeginVertical();
|
||||
if (hasClients)
|
||||
DrawClientListBody();
|
||||
else
|
||||
DrawNoClientBody();
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(SpaceAfterBody);
|
||||
|
||||
// ── Action button ────────────────────────────────────────────────────
|
||||
Texture2D btnNormal = null, btnPressed = null, btnHover = null;
|
||||
bool btnEnabled = true;
|
||||
System.Action btnAction = null;
|
||||
|
||||
switch (currentState)
|
||||
{
|
||||
case BridgeState.NotStarted:
|
||||
btnNormal = connectTex;
|
||||
btnPressed = connectPressedTex;
|
||||
btnHover = connectHoverTex;
|
||||
btnAction = StartBridge;
|
||||
break;
|
||||
case BridgeState.Starting:
|
||||
btnNormal = connectingTex;
|
||||
btnPressed = connectingTex;
|
||||
btnHover = connectingTex;
|
||||
btnEnabled = false;
|
||||
break;
|
||||
case BridgeState.Started:
|
||||
btnNormal = disconnectTex;
|
||||
btnPressed = disconnectPressedTex;
|
||||
btnHover = disconnectHoverTex;
|
||||
btnAction = StopBridge;
|
||||
break;
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(LeftMargin);
|
||||
|
||||
if (btnNormal != null)
|
||||
{
|
||||
float btnW = ConnectBtnW;
|
||||
float btnH = ConnectBtnH;
|
||||
|
||||
var style = new GUIStyle(GUIStyle.none);
|
||||
style.normal.background = btnNormal;
|
||||
style.active.background = btnPressed ?? btnNormal;
|
||||
style.hover.background = btnHover ?? btnNormal;
|
||||
|
||||
if (!btnEnabled) GUI.enabled = false;
|
||||
if (GUILayout.Button(GUIContent.none, style, GUILayout.Width(btnW), GUILayout.Height(btnH))
|
||||
&& btnAction != null)
|
||||
btnAction();
|
||||
if (!btnEnabled) GUI.enabled = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string fallback = currentState == BridgeState.NotStarted ? "Connect \u2192"
|
||||
: currentState == BridgeState.Starting ? "Connecting..."
|
||||
: "Disconnect";
|
||||
if (!btnEnabled) GUI.enabled = false;
|
||||
if (GUILayout.Button(fallback, GUILayout.Width(ConnectBtnW), GUILayout.Height(ConnectBtnH))
|
||||
&& btnAction != null)
|
||||
btnAction();
|
||||
if (!btnEnabled) GUI.enabled = true;
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// ── Bottom padding ───────────────────────────────────────────────────
|
||||
GUILayout.Space(BottomPadding);
|
||||
|
||||
// ── Auto-resize height to fit content ────────────────────────────────
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
float targetH = Mathf.Max(MinWindowHeight, GUILayoutUtility.GetLastRect().yMax);
|
||||
if (Mathf.Abs(position.height - targetH) > 1f)
|
||||
{
|
||||
minSize = new Vector2(WindowWidth, targetH);
|
||||
maxSize = new Vector2(WindowWidth, targetH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Form 1 – bridge started and at least one client is connected
|
||||
private void DrawClientListBody()
|
||||
{
|
||||
var labelStyle = new GUIStyle(EditorStyles.label) { fontSize = ConnectedFontSize, font = inter };
|
||||
labelStyle.normal.textColor = SubtextColor;
|
||||
labelStyle.hover.textColor = SubtextColor;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
// Left column: "Connected to :" label, top-aligned
|
||||
float labelW = labelStyle.CalcSize(new GUIContent("Connected to :")).x + 4f;
|
||||
GUILayout.Label("Connected to :", labelStyle, GUILayout.Width(labelW));
|
||||
|
||||
// Right column: all clients stacked vertically
|
||||
GUILayout.BeginVertical();
|
||||
if (connectedToVSCode) DrawClient(vscodeIcon, "VS Code");
|
||||
if (connectedToVisualStudio) DrawClient(visualStudioIcon, "Visual Studio");
|
||||
if (connectedToJetBrains) DrawClient(jetbrainsIcon, "JetBrains");
|
||||
if (connectedToCLI) DrawClient(cliIcon, "CLI");
|
||||
if (connectedToUnityEditor) DrawClient(unityEditorIcon, "Unity Editor");
|
||||
if (connectedToTuanjie) DrawClient(tuanjieIcon, "Tuanjie");
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
// Form 2 – not started, starting, or started but no clients yet
|
||||
private void DrawNoClientBody()
|
||||
{
|
||||
string bodyText = currentState == BridgeState.Started
|
||||
? "Waiting for clients..."
|
||||
: "Start Codely Bridge to connect to Codely Agents.";
|
||||
|
||||
var bodyStyle = new GUIStyle(EditorStyles.label) { fontSize = BodyFontSize, wordWrap = true, font = inter };
|
||||
bodyStyle.normal.textColor = SubtextColor;
|
||||
bodyStyle.hover.textColor = SubtextColor;
|
||||
GUILayout.Label(bodyText, bodyStyle);
|
||||
|
||||
GUILayout.Space(SpaceBeforeStatus);
|
||||
|
||||
string dots = new string('.', (int)(EditorApplication.timeSinceStartup * 2) % 3 + 1);
|
||||
string statusText = currentState == BridgeState.Starting ? $"\u2022 Status: Connecting{dots}"
|
||||
: currentState == BridgeState.Started ? "\u2022 Status: Waiting for clients..."
|
||||
: "\u2022 Status: Disconnected";
|
||||
|
||||
GUILayout.Label(
|
||||
statusText,
|
||||
new GUIStyle(EditorStyles.label)
|
||||
{
|
||||
fontSize = StatusFontSize,
|
||||
font = firaMono,
|
||||
normal = { textColor = GrayColor },
|
||||
hover = { textColor = GrayColor }
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawClient(Texture2D icon, string label)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
if (icon != null)
|
||||
GUILayout.Box(icon, GUIStyle.none, GUILayout.Width(ClientIconSize), GUILayout.Height(ClientIconSize));
|
||||
else
|
||||
GUILayout.Space(ClientIconSize);
|
||||
GUILayout.Space(ClientIconLabelGap);
|
||||
GUILayout.Label(
|
||||
label,
|
||||
new GUIStyle(EditorStyles.label) { fontSize = ClientLabelFontSize, font = inter, alignment = TextAnchor.MiddleLeft, normal = { textColor = Color.white }, hover = { textColor = Color.white } },
|
||||
GUILayout.Height(ClientLabelHeight));
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(ClientItemSpacing);
|
||||
}
|
||||
|
||||
private void StartBridge()
|
||||
{
|
||||
try
|
||||
{
|
||||
UnityTcpBridge.Start();
|
||||
isStarting = true;
|
||||
startingTime = EditorApplication.timeSinceStartup;
|
||||
currentState = BridgeState.Starting;
|
||||
TcpLog.Info("Codely Bridge started via Control Window");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
TcpLog.Error($"Failed to start Codely Bridge: {ex.Message}");
|
||||
currentState = BridgeState.NotStarted;
|
||||
isStarting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void StopBridge()
|
||||
{
|
||||
try
|
||||
{
|
||||
UnityTcpBridge.Stop(true);
|
||||
TcpLog.Info("Codely Bridge manually stopped via Control Window");
|
||||
currentState = BridgeState.NotStarted;
|
||||
isStarting = false;
|
||||
ResetConnections();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
TcpLog.Error($"Failed to stop Codely Bridge: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetConnections()
|
||||
{
|
||||
connectedToCLI = connectedToVSCode = connectedToVisualStudio =
|
||||
connectedToJetBrains = connectedToUnityEditor = connectedToTuanjie = false;
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
bool isRunning = UnityTcpBridge.IsRunning;
|
||||
|
||||
if (isStarting && isRunning)
|
||||
{
|
||||
currentState = BridgeState.Started;
|
||||
isStarting = false;
|
||||
}
|
||||
else if (isStarting && !isRunning)
|
||||
{
|
||||
if (EditorApplication.timeSinceStartup - startingTime > StartingTimeout)
|
||||
{
|
||||
currentState = BridgeState.NotStarted;
|
||||
isStarting = false;
|
||||
}
|
||||
}
|
||||
else if (!isStarting && isRunning && currentState != BridgeState.Started)
|
||||
{
|
||||
currentState = BridgeState.Started;
|
||||
}
|
||||
else if (!isRunning && currentState == BridgeState.Started)
|
||||
{
|
||||
currentState = BridgeState.NotStarted;
|
||||
ResetConnections();
|
||||
}
|
||||
|
||||
if (currentState == BridgeState.Started)
|
||||
UpdateConnectionStatus();
|
||||
}
|
||||
|
||||
private void UpdateConnectionStatus()
|
||||
{
|
||||
var clients = UnityTcpBridge.GetConnectedClients();
|
||||
ResetConnections();
|
||||
|
||||
foreach (var platform in clients.Values)
|
||||
{
|
||||
var p = platform.ToLower();
|
||||
if (p.Contains("cli"))
|
||||
connectedToCLI = true;
|
||||
else if (p.Contains("vscode") || p.Contains("vs code"))
|
||||
connectedToVSCode = true;
|
||||
else if (p.Contains("visualstudio") || p.Contains("visual studio"))
|
||||
connectedToVisualStudio = true;
|
||||
else if (p.Contains("jetbrains") || p.Contains("intellij") || p.Contains("rider"))
|
||||
connectedToJetBrains = true;
|
||||
else if (p.Contains("tuanjie") || p.Contains("codely") || p.Contains("agent"))
|
||||
connectedToTuanjie = true;
|
||||
else if (p.Contains("unity"))
|
||||
connectedToUnityEditor = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInspectorUpdate() => Repaint();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88296ad49ad2c6a4287fe46c718d0e88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,114 @@
|
||||
using UnityEditor;
|
||||
using UnityTcp.Editor.Helpers;
|
||||
|
||||
namespace UnityTcp.Editor.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Menu items for quick Codely bridge operations
|
||||
/// </summary>
|
||||
public static class TcpBridgeMenuItems
|
||||
{
|
||||
public static void StartServer()
|
||||
{
|
||||
if (!UnityTcpBridge.IsRunning)
|
||||
{
|
||||
UnityTcpBridge.Start();
|
||||
TcpLog.Info("Codely Bridge started via menu");
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpLog.Info("Codely Bridge is already running");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool StartServerValidate()
|
||||
{
|
||||
return !UnityTcpBridge.IsRunning;
|
||||
}
|
||||
|
||||
public static void StopServer()
|
||||
{
|
||||
if (UnityTcpBridge.IsRunning)
|
||||
{
|
||||
UnityTcpBridge.Stop(true); // Pass true to indicate manual stop
|
||||
TcpLog.Info("Codely Bridge manually stopped via menu");
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpLog.Info("Codely Bridge is not running");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool StopServerValidate()
|
||||
{
|
||||
return UnityTcpBridge.IsRunning;
|
||||
}
|
||||
|
||||
public static void RestartServer()
|
||||
{
|
||||
UnityTcpBridge.Stop();
|
||||
System.Threading.Thread.Sleep(100);
|
||||
UnityTcpBridge.Start();
|
||||
TcpLog.Info("Codely Bridge restarted via menu");
|
||||
}
|
||||
|
||||
public static void ShowServerStatus()
|
||||
{
|
||||
bool isRunning = UnityTcpBridge.IsRunning;
|
||||
int port = UnityTcpBridge.GetCurrentPort();
|
||||
|
||||
string message = isRunning
|
||||
? $"Codely Bridge is RUNNING on port {port}\nConnect to: localhost:{port}"
|
||||
: "Codely Bridge is STOPPED";
|
||||
|
||||
EditorUtility.DisplayDialog("Codely Bridge Status", message, "OK");
|
||||
}
|
||||
|
||||
public static void DiscoverNewPort()
|
||||
{
|
||||
try
|
||||
{
|
||||
int newPort = PortManager.DiscoverNewPort();
|
||||
string message = $"New port discovered: {newPort}\n\nRestart the Codely Bridge to use the new port.";
|
||||
|
||||
bool restart = EditorUtility.DisplayDialog(
|
||||
"New Port Discovered",
|
||||
message,
|
||||
"Restart Now",
|
||||
"Later"
|
||||
);
|
||||
|
||||
if (restart)
|
||||
{
|
||||
RestartServer();
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Port Discovery Failed", ex.Message, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableDebugLogging()
|
||||
{
|
||||
EditorPrefs.SetBool("UnityTcp.DebugLogs", true);
|
||||
TcpLog.Info("Debug logging enabled");
|
||||
}
|
||||
|
||||
public static bool EnableDebugLoggingValidate()
|
||||
{
|
||||
return !EditorPrefs.GetBool("UnityTcp.DebugLogs", false);
|
||||
}
|
||||
|
||||
public static void DisableDebugLogging()
|
||||
{
|
||||
EditorPrefs.SetBool("UnityTcp.DebugLogs", false);
|
||||
TcpLog.Info("Debug logging disabled");
|
||||
}
|
||||
|
||||
public static bool DisableDebugLoggingValidate()
|
||||
{
|
||||
return EditorPrefs.GetBool("UnityTcp.DebugLogs", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f4b4cc7c6f3a374483cd55efa7a4d5c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityTcp.Editor.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple status window that can be docked for quick Codely bridge status viewing
|
||||
/// </summary>
|
||||
public class TcpBridgeStatusWindow : EditorWindow
|
||||
{
|
||||
private double lastUpdate;
|
||||
private const double UpdateInterval = 1.0; // Update every second
|
||||
private GUIStyle statusStyle;
|
||||
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<TcpBridgeStatusWindow>("Codely Status");
|
||||
window.minSize = new Vector2(200, 100);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (statusStyle == null)
|
||||
{
|
||||
statusStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 14,
|
||||
alignment = TextAnchor.MiddleCenter
|
||||
};
|
||||
}
|
||||
|
||||
// Update periodically
|
||||
if (EditorApplication.timeSinceStartup - lastUpdate > UpdateInterval)
|
||||
{
|
||||
lastUpdate = EditorApplication.timeSinceStartup;
|
||||
Repaint();
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
bool isRunning = UnityTcpBridge.IsRunning;
|
||||
int currentPort = UnityTcpBridge.GetCurrentPort();
|
||||
|
||||
// Status indicator
|
||||
Color statusColor = isRunning ? Color.green : Color.red;
|
||||
string statusText = isRunning ? "RUNNING" : "STOPPED";
|
||||
|
||||
GUI.color = statusColor;
|
||||
EditorGUILayout.LabelField($"● {statusText}", statusStyle);
|
||||
GUI.color = Color.white;
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
EditorGUILayout.LabelField($"Port: {currentPort}", EditorStyles.centeredGreyMiniLabel);
|
||||
EditorGUILayout.LabelField($"localhost:{currentPort}", EditorStyles.centeredGreyMiniLabel);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Quick action buttons
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUI.enabled = !isRunning;
|
||||
if (GUILayout.Button("Start"))
|
||||
{
|
||||
UnityTcpBridge.Start();
|
||||
}
|
||||
|
||||
GUI.enabled = isRunning;
|
||||
if (GUILayout.Button("Stop"))
|
||||
{
|
||||
UnityTcpBridge.Stop(true); // Pass true to indicate manual stop
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
if (GUILayout.Button("Open Control Window"))
|
||||
{
|
||||
TcpBridgeControlWindow.ShowWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInspectorUpdate()
|
||||
{
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a43028cc630b1ef4684ca6cd5ac758ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user