Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 66 additions & 11 deletions cli/src/editor_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,30 @@ fn unity_install_roots() -> Vec<PathBuf> {
}
}

#[cfg(unix)]
{
if let Some(home) = std::env::var_os("HOME") {
let home = PathBuf::from(home);
roots.push(home.join("Unity").join("Hub").join("Editor"));
roots.push(home.join(".local").join("share").join("Unity").join("Hub").join("Editor"));
roots.push(home.join(".unityhub").join("Editor"));
}
roots.push(PathBuf::from("/opt/Unity").join("Hub").join("Editor"));
roots.push(PathBuf::from("/usr/local/Unity").join("Hub").join("Editor"));

if let Ok(config_dir) = std::env::var("XDG_CONFIG_HOME") {
let hub_dir = PathBuf::from(config_dir).join("unityhub");
if let Some(path) = read_hub_path_string(&hub_dir.join("secondaryInstallPath.json")) {
roots.push(path);
}
} else if let Some(home) = std::env::var_os("HOME") {
let hub_dir = PathBuf::from(home).join(".config").join("unityhub");
if let Some(path) = read_hub_path_string(&hub_dir.join("secondaryInstallPath.json")) {
roots.push(path);
}
}
}

dedupe_paths(roots)
}

Expand All @@ -484,21 +508,52 @@ fn read_hub_path_string(path: &Path) -> Option<PathBuf> {
Some(PathBuf::from(trimmed))
}

fn hub_projects_path() -> Option<PathBuf> {
#[cfg(windows)]
{
let app_data = std::env::var_os("APPDATA")?;
Some(PathBuf::from(app_data).join("UnityHub").join("projects-v1.json"))
}

#[cfg(unix)]
{
let config_dir = std::env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from)
.or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".config")))?;
Some(config_dir.join("unityhub").join("projects-v1.json"))
}
}

fn read_hub_project_version(project: &Path) -> Option<String> {
let app_data = std::env::var_os("APPDATA")?;
let path = PathBuf::from(app_data)
.join("UnityHub")
.join("projects-v1.json");
let path = hub_projects_path()?;
let content = fs::read_to_string(path).ok()?;
let json_start = content.find('{')?;
let value: serde_json::Value = serde_json::from_str(&content[json_start..]).ok()?;
let project_key = project.display().to_string().replace('/', "\\");
value
.get("data")?
.get(&project_key)?
.get("version")?
.as_str()
.map(ToOwned::to_owned)
let project_key = project.display().to_string();

// Try exact match first, then with normalized separators
let data = value.get("data")?;
if let Some(version) = data
.get(&project_key)
.and_then(|entry| entry.get("version"))
.and_then(|v| v.as_str())
{
return Some(version.to_owned());
}

#[cfg(windows)]
{
let alt_key = project_key.replace('/', "\\");
data.get(&alt_key)
.and_then(|entry| entry.get("version"))
.and_then(|v| v.as_str())
.map(ToOwned::to_owned)
}

#[cfg(unix)]
{
None
}
}

fn installed_unity_versions(roots: &[PathBuf]) -> Vec<String> {
Expand Down
3 changes: 3 additions & 0 deletions unity-package/com.ucp.bridge/Editor/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("UCP.Bridge.Editor.Tests")]
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace UCP.Bridge
{
internal static class UnityObjectCompat
{
public static int GetId(this Object obj)
{
#if UNITY_6000_5_OR_NEWER
return unchecked((int)EntityId.ToULong(obj.GetEntityId()));
#else
return obj.GetInstanceID();
#endif
}

public static long GetSceneHandle(Scene scene)
{
#if UNITY_6000_5_OR_NEWER
return unchecked((long)scene.handle.GetRawData());
#else
return scene.handle;
#endif
}

public static Object ResolveByInstanceId(int instanceId)
{
#if UNITY_6000_5_OR_NEWER
return EditorUtility.EntityIdToObject(EntityId.FromULong(unchecked((ulong)instanceId)));
#else
return EditorUtility.InstanceIDToObject(instanceId);
#endif
}

public static T ResolveByInstanceId<T>(int instanceId) where T : Object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private static object HandleInfo(string paramsJson)
["name"] = asset.name,
["type"] = asset.GetType().Name,
["fullType"] = asset.GetType().FullName,
["instanceId"] = asset.GetInstanceID(),
["instanceId"] = asset.GetId(),
["guid"] = AssetDatabase.AssetPathToGUID(assetPath)
};

Expand Down Expand Up @@ -496,7 +496,7 @@ private static object HandleCreateScriptableObject(string paramsJson)
["status"] = "ok",
["path"] = assetPath,
["type"] = soType.Name,
["instanceId"] = instance.GetInstanceID()
["instanceId"] = instance.GetId()
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private static object HandleCreate(string paramsJson)
return new Dictionary<string, object>
{
["status"] = "ok",
["instanceId"] = go.GetInstanceID(),
["instanceId"] = go.GetId(),
["name"] = go.name
};
}
Expand Down Expand Up @@ -192,7 +192,7 @@ private static object HandleInstantiate(string paramsJson)
return new Dictionary<string, object>
{
["status"] = "ok",
["instanceId"] = instance.GetInstanceID(),
["instanceId"] = instance.GetId(),
["name"] = instance.name
};
}
Expand Down Expand Up @@ -314,7 +314,7 @@ private static GameObject FindGameObject(int instanceId)

private static GameObject FindInHierarchy(GameObject go, int instanceId)
{
if (go.GetInstanceID() == instanceId) return go;
if (go.GetId() == instanceId) return go;
for (int i = 0; i < go.transform.childCount; i++)
{
var found = FindInHierarchy(go.transform.GetChild(i).gameObject, instanceId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private static object HandleCreate(string paramsJson)
["path"] = path,
["name"] = material.name,
["shader"] = shader.name,
["instanceId"] = material.GetInstanceID()
["instanceId"] = material.GetId()
};
}

Expand Down Expand Up @@ -278,7 +278,7 @@ private static object ReadMaterialValue(Material mat, string propName, UnityEngi
{
["name"] = tex.name,
["path"] = texPath,
["instanceId"] = tex.GetInstanceID()
["instanceId"] = tex.GetId()
};
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static Dictionary<string, object> Serialize(UnityEngine.Object obj)

var result = new Dictionary<string, object>
{
["instanceId"] = obj.GetInstanceID(),
["instanceId"] = obj.GetId(),
["name"] = obj.name,
["type"] = obj.GetType().Name
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ out success
["status"] = "ok",
["path"] = savePath,
["name"] = prefab.name,
["instanceId"] = prefab.GetInstanceID(),
["sceneInstanceId"] = go.GetInstanceID(),
["instanceId"] = prefab.GetId(),
["sceneInstanceId"] = go.GetId(),
["isPrefabInstance"] = PrefabUtility.IsPartOfPrefabInstance(go)
};
}
Expand Down Expand Up @@ -221,7 +221,7 @@ private static object HandleOverrides(string paramsJson)
added.Add(new Dictionary<string, object>
{
["component"] = ac.instanceComponent.GetType().Name,
["instanceId"] = ac.instanceComponent.GetInstanceID()
["instanceId"] = ac.instanceComponent.GetId()
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ private static GameObject FindGameObject(int instanceId)

private static GameObject FindInHierarchy(GameObject go, int instanceId)
{
if (go.GetInstanceID() == instanceId) return go;
if (go.GetId() == instanceId) return go;
for (int i = 0; i < go.transform.childCount; i++)
{
var found = FindInHierarchy(go.transform.GetChild(i).gameObject, instanceId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private static object HandleSerializationStatus(string paramsJson)
{
{ "serializationMode", mode },
{ "forceText", mode == 2 },
{ "visibleMetaFiles", EditorSettings.externalVersionControl == "Visible Meta Files" }
{ "visibleMetaFiles", VersionControlSettings.mode == "Visible Meta Files" }
};
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ private sealed class TrackedSceneChange
public HashSet<string> Components = new();
}

private static readonly Dictionary<int, Dictionary<string, TrackedSceneChange>> s_changesByScene = new();
private static readonly Dictionary<long, Dictionary<string, TrackedSceneChange>> s_changesByScene = new();

static SceneChangeTracker()
{
Expand All @@ -33,7 +33,7 @@ public static void RecordGameObjectChange(GameObject gameObject, string componen
if (gameObject == null)
return;

RecordSceneChange(gameObject.scene, gameObject.GetInstanceID(), gameObject.name, componentName);
RecordSceneChange(gameObject.scene, gameObject.GetId(), gameObject.name, componentName);
}

public static void RecordDeletedObject(Scene scene, int instanceId, string name, string componentName)
Expand All @@ -56,7 +56,7 @@ public static Dictionary<string, object> DescribeSceneChanges(Scene scene, int m
var modifications = new List<object>();
var omittedCount = 0;

if (scene.IsValid() && s_changesByScene.TryGetValue(scene.handle, out var trackedChanges))
if (scene.IsValid() && s_changesByScene.TryGetValue(UnityObjectCompat.GetSceneHandle(scene), out var trackedChanges))
{
var ordered = trackedChanges.Values
.OrderBy(change => change.InstanceId.HasValue ? 0 : 1)
Expand Down Expand Up @@ -101,7 +101,7 @@ public static void ClearScene(Scene scene)
if (!scene.IsValid())
return;

s_changesByScene.Remove(scene.handle);
s_changesByScene.Remove(UnityObjectCompat.GetSceneHandle(scene));
}

private static UndoPropertyModification[] OnPostprocessModifications(UndoPropertyModification[] modifications)
Expand Down Expand Up @@ -140,10 +140,10 @@ private static void RecordSceneChange(Scene scene, int? instanceId, string name,
if (!scene.IsValid() || !scene.isLoaded)
return;

if (!s_changesByScene.TryGetValue(scene.handle, out var sceneChanges))
if (!s_changesByScene.TryGetValue(UnityObjectCompat.GetSceneHandle(scene), out var sceneChanges))
{
sceneChanges = new Dictionary<string, TrackedSceneChange>();
s_changesByScene[scene.handle] = sceneChanges;
s_changesByScene[UnityObjectCompat.GetSceneHandle(scene)] = sceneChanges;
}

var key = instanceId.HasValue ? instanceId.Value.ToString() : $"scene::{name}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ private static GameObject FindGameObject(int instanceId)

private static GameObject FindInHierarchy(GameObject gameObject, int instanceId)
{
if (gameObject.GetInstanceID() == instanceId)
if (gameObject.GetId() == instanceId)
return gameObject;

foreach (Transform child in gameObject.transform)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private static bool SerializeGameObject(

var entry = new Dictionary<string, object>
{
["instanceId"] = go.GetInstanceID(),
["instanceId"] = go.GetId(),
["name"] = go.name,
["active"] = go.activeSelf,
["tag"] = go.tag,
Expand Down Expand Up @@ -230,7 +230,7 @@ private static void QueryHierarchy(
private static Dictionary<string, object> ProjectGameObject(GameObject go, HashSet<string> fields, int depth)
{
var entry = new Dictionary<string, object>();
AddField(entry, fields, "instanceId", go.GetInstanceID());
AddField(entry, fields, "instanceId", go.GetId());
AddField(entry, fields, "name", go.name);
AddField(entry, fields, "active", go.activeSelf);
AddField(entry, fields, "activeInHierarchy", go.activeInHierarchy);
Expand Down Expand Up @@ -426,7 +426,7 @@ private static GameObject FindByInstanceId(int id)

private static GameObject FindInHierarchy(GameObject go, int instanceId)
{
if (go.GetInstanceID() == instanceId)
if (go.GetId() == instanceId)
return go;

for (int i = 0; i < go.transform.childCount; i++)
Expand Down Expand Up @@ -479,7 +479,7 @@ private static Dictionary<string, object> CreateGameObjectEntry(GameObject go, i
{
return new Dictionary<string, object>
{
["instanceId"] = go.GetInstanceID(),
["instanceId"] = go.GetId(),
["name"] = go.name,
["active"] = go.activeSelf,
["tag"] = go.tag,
Expand Down
Loading