VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.interaction/Editor/OpenXR/OpenXRMigrationWindow.cs
IonutMocanu d7aba243a2 Main
2025-09-08 11:04:02 +03:00

321 lines
12 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if ISDK_OPENXR_HAND
using Oculus.Interaction.HandGrab;
using Oculus.Interaction.PoseDetection;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using static Oculus.Interaction.Editor.AssetListWindow;
namespace Oculus.Interaction.Editor
{
public class OpenXRMigrationWindow
{
private static Type[] _migrableTypes = {
typeof(HandJoint),
typeof(HandJointsPose),
typeof(HandRootOffset),
typeof(HandPinchOffset),
typeof(HandGrabPose),
typeof(HandSphereMap),
typeof(JointVelocityActiveState),
typeof(JointRotationActiveState),
typeof(JointDistanceActiveState),
};
private const string OPENXR_DOCS_LINK = "https://developers.meta.com/horizon/documentation/unity/unity-isdk-openxr-hand";
private static ISDKEditorStyles _styles = new ISDKEditorStyles();
private static Dictionary<AssetListWindow, Dictionary<int, UnityEditor.Editor>> _cachedEditors
= new Dictionary<AssetListWindow, Dictionary<int, UnityEditor.Editor>>();
[MenuItem("Meta/Interaction/OpenXR Migration Tool")]
public static void ShowWindow()
{
//unified entry point for populating the table
Action<AssetListWindow> handleEnabled = (window) =>
{
GetAssets(out List<AssetInfo> assets,
out Dictionary<int, UnityEditor.Editor> editors);
ClearEditors(window);
_cachedEditors.Add(window, editors);
window.SetAssets(assets);
};
//disabled is called also when changing betweewn play/editor mode
Action<AssetListWindow> handleDisabled = (window) =>
{
ClearEditors(window);
};
//teardown references on destroy. Disabled is called always before
Action<AssetListWindow> handleDestroyed = null;
handleDestroyed = (window) =>
{
window.WhenDestroyed -= handleDestroyed;
window.WhenEnabled -= handleEnabled;
window.WhenDisabled -= handleDisabled;
};
AssetListWindow window = Show("OpenXR Migration Tool",
new List<AssetInfo>(), //initialize to empty array
false,
DrawHeader,
DrawFooter,
DrawContent);
//force populate from common callback
handleEnabled(window);
window.WhenEnabled += handleEnabled;
window.WhenDisabled += handleDisabled;
window.WhenDestroyed += handleDestroyed;
}
private static void GetAssets(out List<AssetInfo> assets, out Dictionary<int, UnityEditor.Editor> editors)
{
List<UnityEngine.Object> foundObjects = FindAllObjects();
assets = ToAssetInfos(foundObjects);
editors = CreateEditors(foundObjects);
}
internal static List<UnityEngine.Object> FindAllObjects()
{
List<UnityEngine.Object> foundComponents = new List<UnityEngine.Object>();
foreach (Type migrableType in _migrableTypes)
{
UnityEngine.Object[] objects =
UnityEngine.Object.FindObjectsByType(migrableType, FindObjectsInactive.Include, FindObjectsSortMode.InstanceID);
if (objects != null)
{
foundComponents.AddRange(objects);
}
}
return foundComponents;
}
private static List<AssetInfo> ToAssetInfos(List<UnityEngine.Object> objects)
{
List<AssetInfo> infos = objects.Select(obj =>
{
int instanceID = obj.GetInstanceID();
return new AssetInfo(instanceID.ToString(),
obj.name,
null);
}).ToList();
return infos;
}
private static Dictionary<int, UnityEditor.Editor> CreateEditors(List<UnityEngine.Object> objects)
{
Dictionary<int, UnityEditor.Editor> editors = new Dictionary<int, UnityEditor.Editor>();
foreach (var obj in objects)
{
var editor = UnityEditor.Editor.CreateEditor(obj);
editors.Add(obj.GetInstanceID(), editor);
}
return editors;
}
private static void ClearEditors(AssetListWindow window)
{
if (!_cachedEditors.TryGetValue(window, out var editors))
{
return;
}
foreach (var editorKvp in editors)
{
if (editorKvp.Value is UnityEngine.Object editor)
{
UnityEngine.Object.DestroyImmediate(editor);
}
}
editors.Clear();
_cachedEditors.Remove(window);
}
private static bool TryGetEditor(AssetListWindow window, UnityEngine.Object obj, out UnityEditor.Editor editor)
{
editor = null;
return (_cachedEditors.TryGetValue(window, out var editors)
&& editors.TryGetValue(obj.GetInstanceID(), out editor));
}
private static bool TryGetInstanceId(AssetInfo info, out int instanceId)
{
return int.TryParse(info.AssetPath, out instanceId);
}
private static void DrawContent(AssetListWindow window, int index, AssetInfo assetInfo)
{
using (new EditorGUILayout.HorizontalScope(_styles.ContentArea))
{
bool success = TryNeedsConversion(window, assetInfo, out bool needsConversion);
string color = success ? needsConversion ? "orange" : "lime" : "grey";
string subtitle = success ? needsConversion ? "(needs convertion)"
: "(converted)" : "(can't convert)";
string name = $"<color={color}>{assetInfo.DisplayName}</color> {subtitle}";
EditorGUILayout.LabelField(name, _styles.ContentText);
Rect labelRect = GUILayoutUtility.GetLastRect();
if (GUI.Button(labelRect, string.Empty, GUIStyle.none))
{
SelectAsset(assetInfo);
}
if (GUILayout.Button("Convert to OpenXR"))
{
Convert(window, GetObject(assetInfo));
}
}
}
private static void SelectAsset(AssetInfo info)
{
if (TryGetInstanceId(info, out int instanceID))
{
Selection.activeInstanceID = instanceID;
}
}
private static UnityEngine.Object GetObject(AssetInfo info)
{
if (TryGetInstanceId(info, out int instanceID))
{
return EditorUtility.InstanceIDToObject(instanceID);
}
return null;
}
private static void Convert(AssetListWindow window, UnityEngine.Object obj)
{
if (obj == null)
{
return;
}
if (!TryGetEditor(window, obj, out var editor)
|| editor is not IOpenXRMigrableEditor migrableEditor)
{
return;
}
migrableEditor.Convert(editor.serializedObject);
editor.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(obj);
}
private static bool TryNeedsConversion(AssetListWindow window, AssetInfo info, out bool needsConversion)
{
UnityEngine.Object obj = GetObject(info);
if (obj != null)
{
return TryNeedsConversion(window, obj, out needsConversion);
}
needsConversion = false;
return false;
}
private static bool TryNeedsConversion(AssetListWindow window, UnityEngine.Object obj, out bool needsConversion)
{
if (obj == null)
{
needsConversion = false;
return false;
}
if (!TryGetEditor(window, obj, out var editor)
|| editor is not IOpenXRMigrableEditor migrableEditor)
{
needsConversion = false;
return false;
}
needsConversion = migrableEditor.NeedsConversion(editor.serializedObject);
return true;
}
private static void DrawHeader(AssetListWindow window)
{
string content = "Use this tool to instantly <b>locate and convert</b> the components " +
"in the scene from having <b>OVR</b>-centric parameters to <b>OpenXR</b>-centric parameters. " +
"This includes hand-space offsets, hand joint identifiers and others. Note that you can also convert " +
"the components one by one by using the <b>Convert</b> button in the inspector.\n" +
"\n- Click in any row to highlight the component in the inspector.\n" +
"- Click the row button to convert the component parameters from OVR to OpenXR.\n" +
"- Click the footer button to convert all remaining components from OVR to OpenXR.\n" +
"\nThis tool upgrades only <b>Interaction SDK</b> components, if you have created your " +
"own OVR-centric assets, please refer to the documentation to migrate them manually.";
using (new EditorGUILayout.VerticalScope(_styles.WindowContents))
{
_styles.DrawTitle("Interaction SDK OpenXR Migration tool");
_styles.DrawContent(content, () =>
{
EditorGUILayout.Space();
if (GUILayout.Button(
"For more details please see the <color=#6060ee>Interaction SDK documentation.</color>",
_styles.ContentButton))
{
Application.OpenURL(OPENXR_DOCS_LINK);
}
});
}
}
private static void DrawFooter(AssetListWindow window)
{
using (new EditorGUILayout.VerticalScope(_styles.WindowContents))
{
if (GUILayout.Button("Convert missing to OpenXR", _styles.Button))
{
foreach (AssetInfo asset in window.AssetInfos)
{
UnityEngine.Object obj = GetObject(asset);
if (obj == null)
{
continue;
}
if (TryNeedsConversion(window, obj, out bool needsConversion)
&& needsConversion)
{
Convert(window, obj);
}
}
}
}
}
}
}
#endif