chore(bridge): 删除桥接包的提交记录和Git属性配置

删除了 .codely-bridge-commit 文件中存储的提交哈希值
移除了 .gitattributes 文件中的行结束符配置规则
```
This commit is contained in:
huadexuan committed 2026-09-24 21:41:14 +08:00
1 parent d26d323912
commit 13d0c80335
392 files changed
+1813 -1894

No files matched your search

@@ -0,0 +1 @@
47f3110000c95eee5cd83c827e0f1f11585f7ae1
@@ -30,6 +30,8 @@ namespace UnityTcp.Editor.Helpers
static BridgeUpdateRestartPrompt()
{
if (EditorAutomationGuard.ShouldSkipBridgeAutoStart()) return;
EditorApplication.delayCall += TryShowPendingPrompt;
}
@@ -113,6 +113,8 @@ namespace UnityTcp.Editor.Helpers
static DialogWatcher()
{
if (EditorAutomationGuard.ShouldSkipBridgeAutoStart()) return;
// Force main-thread-only static init NOW, on this ([InitializeOnLoad]) thread,
// before any watcher thread exists: the Windows watcher thread reads
// UnityTcpBridge.IsRunning in Notify, and if that were the bridge's first touch its
@@ -0,0 +1,34 @@
using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityTcp.Editor.Helpers
{
/// <summary>
/// Restricts bridge auto-start to the main Editor process and supported automation runs.
/// Set <see cref="AllowBridgeInBatchEnvVar"/> to opt in when integration tests need the bridge.
/// </summary>
internal static class EditorAutomationGuard
{
internal const string AllowBridgeInBatchEnvVar = "UNITY_TCP_ALLOW_BATCH";
internal static bool IsAutomatedEditorRun()
=> Application.isBatchMode
|| SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null;
internal static bool ShouldSkipBridgeAutoStart()
=> EditorProcessGuard.ShouldSkipEditorAutoStart()
|| (IsAutomatedEditorRun()
&& string.IsNullOrWhiteSpace(
Environment.GetEnvironmentVariable(AllowBridgeInBatchEnvVar)));
internal static bool ShouldSkipBridgeAutoStart(
bool isAssetImportWorker,
bool isSecondaryEditor,
bool isAutomatedEditorRun,
bool allowBridgeInBatch)
=> isAssetImportWorker
|| isSecondaryEditor
|| (isAutomatedEditorRun && !allowBridgeInBatch);
}
}
@@ -0,0 +1,135 @@
using System.Linq;
using Codely.Newtonsoft.Json.Linq;
using UnityEditor;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#else
using UnityEditor.Experimental.SceneManagement;
#endif
using UnityEngine;
namespace UnityTcp.Editor.Helpers
{
/// <summary>
/// Builds the standard Unity selection payload shared by
/// <see cref="UnityTcp.Editor.Notifier.SelectionChangedNotifier"/> and
/// <see cref="UnityTcp.Editor.Tools.ManageEditor"/>'s get_selection action,
/// keeping the two callers in sync without duplicating logic.
/// </summary>
public static class SelectionPayloadBuilder
{
/// <summary>
/// Constructs a <see cref="JObject"/> describing the current Unity Editor selection.
/// The caller is responsible for wrapping the result (e.g. in
/// <see cref="Response.Success"/> or directly broadcasting it as a notification).
/// </summary>
public static JObject Build()
{
var assetGUIDs = Selection.assetGUIDs;
var assetPaths = assetGUIDs?.Select(AssetDatabase.GUIDToAssetPath).ToArray();
string activeAssetPath = Selection.activeObject != null
? AssetDatabase.GetAssetPath(Selection.activeObject)
: null;
string activeAsset = string.IsNullOrEmpty(activeAssetPath)
? null
: activeAssetPath.Replace('\\', '/');
bool isSubAsset = Selection.activeObject != null
&& AssetDatabase.IsSubAsset(Selection.activeObject);
string activeAssetFileId = string.IsNullOrEmpty(activeAsset)
? null
: Selection.activeObject.FormatLocalFileId();
string activeAssetGuid = string.IsNullOrEmpty(activeAsset)
? null
: Selection.activeObject.GetAssetGuid();
var activeGo = Selection.activeGameObject;
var goSource = activeGo != null && activeGo.scene.IsValid()
? PrefabUtility.GetCorrespondingObjectFromSource(activeGo)
: null;
string sourcePrefabGuid = goSource != null
? AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(goSource))
: null;
var payload = new
{
activeObject = Selection.activeObject?.name,
activeObjectKind = Selection.activeObject.GetKind(),
activeAsset = activeAsset,
// Decimal string: Tuanjie fileIDs can exceed JS Number / Int32.
activeAssetLocalId = activeAssetFileId,
activeAssetGuid = activeAssetGuid,
activeSelectedSubAsset = isSubAsset && !string.IsNullOrEmpty(activeAssetFileId)
? (object)new
{
type = Selection.activeObject.GetType().Name,
name = Selection.activeObject.name,
fileId = activeAssetFileId,
}
: null,
activeGameObject = activeGo?.name,
activeGameObjectScenePath = GetSceneOrPrefabPath(activeGo),
// instanceID always refers to the GameObject, never Transform/component.
// Decimal string: Unity 6.5 EntityId can exceed JS Number / 2^53.
activeInstanceID = activeGo.FormatStableInstanceId() ?? "0",
activeGameObjectFileId = activeGo.FormatLocalFileId(),
activeGameObjectGuid = activeGo.FormatGlobalObjectGuid(),
// Prefab instance children: fileId is the source-prefab local id,
// not a scene YAML id. Pair with these to grep the prefab file.
activeGameObjectIsPrefabInstanceChild = goSource != null,
activeGameObjectSourcePrefabGuid = string.IsNullOrEmpty(sourcePrefabGuid) ? null : sourcePrefabGuid,
activeGameObjectSourcePrefabFileId = goSource.FormatLocalFileId(),
activeTransform = Selection.activeTransform?.name,
#if UNITY_2020_1_OR_NEWER
count = Selection.count,
#else
count = Selection.objects?.Length ?? 0,
#endif
objects = Selection.objects
.Where(obj => obj != null)
.Select(obj => new
{
name = obj.name,
type = obj.GetType().FullName,
instanceID = obj.FormatStableInstanceId(),
})
.ToList(),
gameObjects = Selection.gameObjects
.Where(go => go != null)
.Select(go => new
{
name = go.name,
path = go.GetHierarchyPathWithIndex(),
instanceID = go.FormatStableInstanceId(),
kind = go.GetKind(),
fileId = go.FormatLocalFileId(),
guid = go.FormatGlobalObjectGuid(),
componentNames = go.GetComponentTypeNames(),
})
.ToList(),
assetGUIDs = assetGUIDs,
assetPaths = assetPaths,
};
return JObject.FromObject(payload);
}
/// <summary>
/// Returns the scene or prefab asset path that owns <paramref name="go"/>,
/// normalised to forward-slashes. Returns <c>null</c> for null input.
/// </summary>
public static string GetSceneOrPrefabPath(GameObject go)
{
if (go == null) return null;
if (go.scene.IsValid() && !string.IsNullOrEmpty(go.scene.path))
return go.scene.path.Replace('\\', '/');
string stagePath = InstanceIdExtensions.GetPrefabStageAssetPath(
PrefabStageUtility.GetPrefabStage(go));
if (!string.IsNullOrEmpty(stagePath))
return stagePath.Replace('\\', '/');
string assetPath = AssetDatabase.GetAssetPath(go);
return string.IsNullOrEmpty(assetPath) ? null : assetPath.Replace('\\', '/');
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 00ca19b90d0118744b3dae38cfcd149f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -143,9 +143,22 @@ namespace UnityTcp.Editor.Helpers
// Set from any thread when state changed outside the tick (a cross-thread detach);
// consumed by Tick on the main thread, which owns persistence.
private static volatile bool _saveRequested;
private static bool _initialized;
static StepJobRunner()
{
if (EditorAutomationGuard.ShouldSkipBridgeAutoStart()) return;
EnsureInitialized();
}
// Main-thread only. Explicit bridge/job starts need restoration too, even
// when InitializeOnLoad deliberately skipped auto-start in this domain.
internal static void EnsureInitialized()
{
if (_initialized) return;
// Set before Load: a restored job's OnRestored may enroll another job.
_initialized = true;
Load();
// Pending markers persist but only step jobs survive the reload; retire the rest so no
// client is left polling a job that no longer exists.
@@ -171,6 +184,7 @@ namespace UnityTcp.Editor.Helpers
bool detached = false)
{
if (job == null) throw new ArgumentNullException(nameof(job));
EnsureInitialized();
var ctx = new JobContext(requestId, name, detached);
var entry = new Entry
@@ -490,9 +504,8 @@ namespace UnityTcp.Editor.Helpers
{
Save();
_entries.Clear();
Load();
DetachedJobs.ReconcilePending(
_entries.Where(e => e.Detached).Select(e => e.JobId).ToList());
_initialized = false;
EnsureInitialized();
}
private static void Load()
@@ -55,24 +55,17 @@ namespace UnityTcp.Editor.Helpers
"create",
"modify",
"delete",
"add_component",
"remove_component",
"set_component_property"
},
["manage_asset"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"import",
"ensure_prefab_variant",
"create",
"modify",
"delete",
"duplicate",
"move"
"modify"
},
["manage_scene"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"ensure_scene_open",
"ensure_scene_saved",
"create",
"load",
"save"
@@ -0,0 +1,16 @@
namespace UnityTcp.Editor.Native
{
// Managed code only enables the feature; native window probes decide when to show.
internal static class EditorBusyProxy
{
internal const bool BusyWindowEnabled = true;
internal static void Refresh()
{
#if UNITY_EDITOR_WIN
try { NativeUnityTcpBridgeAPI.NTB_SetEditorBusyProxyEnabled?.Invoke(BusyWindowEnabled ? 1 : 0); }
catch { /* Optional UI must not interrupt bridge startup. */ }
#endif
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ff8b1598a9bb4fbd8067e7245bc1f68d
@@ -169,6 +169,13 @@ namespace UnityTcp.Editor.Native
static NativeDllLoader()
{
if (EditorAutomationGuard.ShouldSkipBridgeAutoStart()) return;
RegisterCleanupHandlers();
}
private static void RegisterCleanupHandlers()
{
#if UNITY_2020_1_OR_NEWER
UnityEditor.PackageManager.Events.registeringPackages -= OnPackagesRegistering;
UnityEditor.PackageManager.Events.registeringPackages += OnPackagesRegistering;
@@ -264,6 +271,8 @@ namespace UnityTcp.Editor.Native
private static void RegisterLogCallback()
{
if (!IsLoaded) return;
// Explicit starts need cleanup too, even when bridge auto-start is disabled.
RegisterCleanupHandlers();
try
{
_logCallback = (level, message) =>
@@ -351,6 +360,8 @@ namespace UnityTcp.Editor.Native
{
if (_handle == IntPtr.Zero) return;
OnUnload?.Invoke(reason);
// Stop/join native workers even when no managed bridge subscribed to OnUnload.
NativeUnityTcpBridgeHost.StopServer(reason);
UnregisterLogCallback();
PlatformFree(_handle);
_handle = IntPtr.Zero;
@@ -369,6 +380,7 @@ namespace UnityTcp.Editor.Native
NativeUnityTcpBridgeAPI.NTB_ResumeManagedCommandProcessing = null;
NativeUnityTcpBridgeAPI.NTB_NotifyAll = null;
NativeUnityTcpBridgeAPI.NTB_SetStreamPort = null;
NativeUnityTcpBridgeAPI.NTB_SetEditorBusyProxyEnabled = null;
SetLogCallback = null;
SessionState.EraseString(HandleKey);
}
@@ -405,7 +417,7 @@ namespace UnityTcp.Editor.Native
{
if (!CheckAbiVersion()) return false;
return
bool resolved =
Resolve("NTB_StartBridge", ref NativeUnityTcpBridgeAPI.NTB_StartBridge) &&
Resolve("NTB_StopWithReason", ref NativeUnityTcpBridgeAPI.NTB_StopWithReason) &&
Resolve("NTB_Stop", ref NativeUnityTcpBridgeAPI.NTB_Stop) &&
@@ -421,6 +433,13 @@ namespace UnityTcp.Editor.Native
Resolve("NTB_NotifyAll", ref NativeUnityTcpBridgeAPI.NTB_NotifyAll) &&
Resolve("NTB_SetStreamPort", ref NativeUnityTcpBridgeAPI.NTB_SetStreamPort) &&
Resolve("Log_SetCallback", ref SetLogCallback);
if (!resolved) return false;
#if UNITY_EDITOR_WIN
// The busy-Editor proxy is optional; failure to bind it must not disable commands.
ResolveOptional("NTB_SetEditorBusyProxyEnabled", ref NativeUnityTcpBridgeAPI.NTB_SetEditorBusyProxyEnabled);
#endif
return true;
}
private static bool CheckAbiVersion()
@@ -464,6 +483,14 @@ namespace UnityTcp.Editor.Native
return true;
}
#if UNITY_EDITOR_WIN
private static void ResolveOptional<T>(string symbol, ref T del) where T : Delegate
{
IntPtr ptr = GetProcAddress(_handle, symbol);
del = ptr == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer<T>(ptr);
}
#endif
private static string PluginPathUnder(string packageRoot)
{
if (string.IsNullOrEmpty(packageRoot)) return null;
@@ -61,6 +61,9 @@ namespace UnityTcp.Editor.Native
// NTB_StartBridge — safe to call at any time.
internal delegate void SetStreamPortDelegate(int streamPort);
// Optional Windows busy-Editor proxy; unavailable UI must not block commands.
internal delegate void SetEditorBusyProxyEnabledDelegate(int enabled);
internal static GetAbiVersionDelegate NTB_GetAbiVersion;
internal static StartBridgeDelegate NTB_StartBridge;
internal static StopDelegate NTB_Stop;
@@ -76,6 +79,7 @@ namespace UnityTcp.Editor.Native
internal static ResumeManagedCommandProcessingDelegate NTB_ResumeManagedCommandProcessing;
internal static NotifyAllDelegate NTB_NotifyAll;
internal static SetStreamPortDelegate NTB_SetStreamPort;
internal static SetEditorBusyProxyEnabledDelegate NTB_SetEditorBusyProxyEnabled;
#endif
}
}
@@ -52,6 +52,7 @@ namespace UnityTcp.Editor.Native
try
{
#if UNITY_EDITOR_WIN || UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
EditorBusyProxy.Refresh();
// After a domain reload the managed side restarts but the native server
// remains bound to its existing port. Probe first so we attach to the
// existing listener instead of relying solely on NTB_StartBridge's idempotency.
Loaded 100 of 392 files, more files were not shown because too many files have changed in this diff. Show more