Add ultimate xr

This commit is contained in:
2024-08-06 21:58:35 +02:00
parent 864033bf10
commit 7165bacd9d
3952 changed files with 2162037 additions and 35 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dc45e86f1c364654584db717b44e2f23
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrSyncObjectEditor.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Linq;
using UltimateXR.Core.Components;
using UltimateXR.Core.StateSave;
using UnityEditor;
using UnityEngine;
namespace UltimateXR.Editor.Core.Components
{
[CustomEditor(typeof(UxrSyncObject))]
[CanEditMultipleObjects]
public class UxrSyncObjectEditor : UnityEditor.Editor
{
#region Unity
/// <summary>
/// Creates references to the serialized properties.
/// </summary>
private void OnEnable()
{
_propertySyncTransform = serializedObject.FindProperty(PropertyNameSyncTransform);
_propertyTransformSpace = serializedObject.FindProperty(PropertyNameTransformSpace);
_propertySyncActiveAndEnabled = serializedObject.FindProperty(PropertyNameSyncActiveAndEnabled);
_propertySyncWhileDisabled = serializedObject.FindProperty(PropertyNameSyncWhileDisabled);
}
/// <inheritdoc />
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(_propertySyncTransform, ContentSyncTransform);
if (_propertySyncTransform.boolValue)
{
EditorGUILayout.PropertyField(_propertyTransformSpace, ContentTransformSpace);
}
foreach (Object selectedObject in targets)
{
UxrSyncObject syncObject = selectedObject as UxrSyncObject;
IUxrStateSave stateSaveTransform = syncObject.GetComponents<IUxrStateSave>().FirstOrDefault(c => c != syncObject && c.RequiresTransformSerialization(UxrStateSaveLevel.ChangesSinceBeginning));
if (syncObject.SyncTransform && stateSaveTransform != null)
{
if (targets.Length > 1)
{
EditorGUILayout.HelpBox($"The transform in {syncObject.name} is already synced by a {stateSaveTransform.Component.GetType().Name} component on the same GameObject. Consider disabling transform syncing.", MessageType.Error);
}
else
{
EditorGUILayout.HelpBox($"The transform is already synced by a {stateSaveTransform.Component.GetType().Name} component on the same GameObject. Consider disabling transform syncing.", MessageType.Error);
}
}
}
EditorGUILayout.PropertyField(_propertySyncActiveAndEnabled, ContentSyncActiveAndEnabled);
EditorGUILayout.PropertyField(_propertySyncWhileDisabled, ContentSyncWhileDisabled);
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Private Types & Data
private static GUIContent ContentSyncTransform { get; } = new GUIContent("Sync Transform", "Synchronizes the transform in multiplayer and save stats.");
private static GUIContent ContentTransformSpace { get; } = new GUIContent("Space", "Space that the transform is saved in.");
private static GUIContent ContentSyncActiveAndEnabled { get; } = new GUIContent("Sync Active/Enabled", "Synchronizes the GameObject's active state and the component's enabled state.");
private static GUIContent ContentSyncWhileDisabled { get; } = new GUIContent("Sync While Disabled", "Synchronizes even while the Component/GameObject is disabled.");
private const string PropertyNameSyncTransform = "_syncTransform";
private const string PropertyNameTransformSpace = "_transformSpace";
private const string PropertyNameSyncActiveAndEnabled = "_syncActiveAndEnabled";
private const string PropertyNameSyncWhileDisabled = "_syncWhileDisabled";
private SerializedProperty _propertySyncTransform;
private SerializedProperty _propertyTransformSpace;
private SerializedProperty _propertySyncActiveAndEnabled;
private SerializedProperty _propertySyncWhileDisabled;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76bd9d6956a81f7479e374e3fd31d679
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ccb906d54174c324090202dc8456da80
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,209 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrInstanceManagerEditor.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UltimateXR.Core;
using UltimateXR.Core.Components;
using UltimateXR.Core.Instantiation;
using UltimateXR.Core.Settings;
using UltimateXR.Core.Unique;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace UltimateXR.Editor.Core.Instantiation
{
/// <summary>
/// Custom inspector for <see cref="UxrInstanceManager" />.
/// </summary>
[CustomEditor(typeof(UxrInstanceManager))]
public class UxrInstanceManagerEditor : UnityEditor.Editor
{
#region Public Methods
/// <summary>
/// Checks if the prefab list contains only elements with a IUxrUnique component in the root. If not, it will return
/// false, keep the serialized property elements to null and return a message to show.
/// </summary>
/// <param name="propertyPrefabList">SerializedProperty with a list of prefabs (GameObject)</param>
/// <param name="message">If the method return false, the message will contain a string to show on screen</param>
/// <returns>Whether the prefab list was valid (true) or contained one or more invalid elements (false)</returns>
public static bool ValidatePrefabsWithUniqueId(SerializedProperty propertyPrefabList, out string message)
{
List<string> invalidPrefabNames = null;
message = null;
for (int i = 0; i < propertyPrefabList.arraySize; ++i)
{
GameObject prefab = propertyPrefabList.GetArrayElementAtIndex(i).objectReferenceValue as GameObject;
if (prefab != null && prefab.GetComponent<IUxrUniqueId>() == null)
{
if (invalidPrefabNames == null)
{
invalidPrefabNames = new List<string>();
}
invalidPrefabNames.Add(prefab.name);
propertyPrefabList.GetArrayElementAtIndex(i).objectReferenceValue = null;
}
}
if (invalidPrefabNames != null)
{
int maxEntries = 10;
if (invalidPrefabNames.Count <= maxEntries)
{
message = $"One or more prefabs don't have a component to track it. Consider adding a {nameof(UxrSyncObject)} to the root of the following prefab(s):\n\n{string.Join("\n", invalidPrefabNames)}";
}
else
{
message = $"The list of prefabs contains many elements without a component to track it. Consider adding a {nameof(UxrSyncObject)} on the root to be able to instantiate the prefab using the {nameof(UxrInstanceManager)}.\nInvalid prefabs have been removed from the list.";
}
}
return invalidPrefabNames == null;
}
#endregion
#region Unity
/// <summary>
/// Creates references to the serialized properties.
/// </summary>
private void OnEnable()
{
_propertyRegisterAutomatically = serializedObject.FindProperty(PropertyNameRegisterAutomatically);
_propertyIncludeFrameworkPrefabs = serializedObject.FindProperty(PropertyNameIncludeFrameworkPrefabs);
_propertyAutomaticPrefabs = serializedObject.FindProperty(PropertyNameAutomaticPrefabs);
_propertyUserDefinedPrefabs = serializedObject.FindProperty(PropertyNameUserDefinedPrefabs);
if (_propertyAutomaticPrefabs.arraySize == 0 && _propertyRegisterAutomatically.boolValue)
{
FindPrefabsAutomatically();
serializedObject.ApplyModifiedProperties();
}
_propertyAutomaticPrefabs.isExpanded = false;
}
/// <inheritdoc />
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.HelpBox($"Use {nameof(UxrInstanceManager)} to instantiate objects at runtime that need to be synchronized on all devices in multiplayer, save-files or replays.\nTo be able to track instantiation, prefabs need at least one component with the {nameof(IUxrUniqueId)} interface on the root, such as any component derived from {nameof(UxrComponent)}. A {nameof(UxrSyncObject)} component can be used when there is no other present.",
MessageType.Info);
EditorGUILayout.PropertyField(_propertyRegisterAutomatically, ContentRegisterAutomatically);
if (_propertyRegisterAutomatically.boolValue)
{
EditorGUILayout.PropertyField(_propertyIncludeFrameworkPrefabs, ContentIncludeFrameworkPrefabs);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(EditorGUIUtility.labelWidth);
if (GUILayout.Button(ContentFindPrefabs, GUILayout.ExpandWidth(true)))
{
FindPrefabsAutomatically();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(_propertyAutomaticPrefabs, ContentAutomaticPrefabs);
if (!ValidatePrefabsWithUniqueId(_propertyAutomaticPrefabs, out string message))
{
EditorUtility.DisplayDialog(UxrConstants.Editor.Error, message, UxrConstants.Editor.Ok);
}
}
else
{
EditorGUILayout.HelpBox($"Use prefab lists to keep big projects well organized and to avoid long generation times of the automatic list. To create a new prefab list use the Create->UltimateXR menu in the Project Window.", MessageType.Info);
EditorGUILayout.PropertyField(_propertyUserDefinedPrefabs, ContentUserDefinedPrefabs);
}
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Private Methods
/// <summary>
/// Tries to populate the prefab list with all instantiable prefabs in the project.
/// </summary>
private void FindPrefabsAutomatically()
{
List<GameObject> prefabs = new List<GameObject>();
Stopwatch sw = Stopwatch.StartNew();
EditorUtility.DisplayCancelableProgressBar("Finding Prefabs", "Building asset list", 0.0f);
List<string> paths = AssetDatabase.GetAllAssetPaths().Where(p => p.EndsWith(".prefab")).OrderBy(p => p).ToList();
for (var i = 0; i < paths.Count; i++)
{
string path = paths[i];
if (!_propertyIncludeFrameworkPrefabs.boolValue && UxrEditorUtils.PathIsInUltimateXR(path))
{
continue;
}
GameObject prefab = AssetDatabase.LoadMainAssetAtPath(path) as GameObject;
if (prefab != null)
{
EditorUtility.DisplayCancelableProgressBar("Finding Prefabs", prefab.name, paths.Count == 1 ? 1.0f : i / (paths.Count - 1));
IUxrUniqueId component = prefab.GetComponent<IUxrUniqueId>();
if (component != null)
{
prefabs.Add(prefab);
}
}
}
UxrEditorUtils.AssignSerializedPropertyArray(_propertyAutomaticPrefabs, prefabs);
EditorUtility.ClearProgressBar();
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Relevant)
{
Debug.Log($"{UxrConstants.CoreModule} Found {prefabs.Count} instantiable prefabs with Unique ID in {sw.ElapsedMilliseconds}ms.");
}
}
#endregion
#region Private Types & Data
private static GUIContent ContentRegisterAutomatically { get; } = new GUIContent("Create List Automatically", "Create a list automatically of all instantiable prefabs in the project. Use manual lists in big projects to avoid long refresh times.");
private static GUIContent ContentIncludeFrameworkPrefabs { get; } = new GUIContent($"Include {nameof(UltimateXR)} Prefabs", "Include all instantiable prefabs from the framework in the list too.");
private static GUIContent ContentFindPrefabs { get; } = new GUIContent("Regenerate List", "Finds all instantiable prefabs in the project.");
private static GUIContent ContentAutomaticPrefabs { get; } = new GUIContent("Registered Prefabs", "List of prefabs");
private static GUIContent ContentUserDefinedPrefabs { get; } = new GUIContent("User Defined Prefab Lists", "List of prefabs");
private const string PropertyNameRegisterAutomatically = "_registerAutomatically";
private const string PropertyNameIncludeFrameworkPrefabs = "_includeFrameworkPrefabs";
private const string PropertyNameAutomaticPrefabs = "_automaticPrefabs";
private const string PropertyNameUserDefinedPrefabs = "_userDefinedPrefabs";
private SerializedProperty _propertyRegisterAutomatically;
private SerializedProperty _propertyIncludeFrameworkPrefabs;
private SerializedProperty _propertyAutomaticPrefabs;
private SerializedProperty _propertyUserDefinedPrefabs;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4c1411e2e9960b4294227f67525ca07
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrPrefabListEditor.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core;
using UltimateXR.Core.Instantiation;
using UnityEditor;
using UnityEngine;
namespace UltimateXR.Editor.Core.Instantiation
{
/// <summary>
/// Custom inspector for <see cref="UxrPrefabList" />.
/// </summary>
[CustomEditor(typeof(UxrPrefabList))]
public class UxrGlobalSettingsEditor : UnityEditor.Editor
{
#region Unity
/// <summary>
/// Creates references to the serialized properties.
/// </summary>
private void OnEnable()
{
_propPrefabList = serializedObject.FindProperty(PropertyPrefabList);
}
/// <inheritdoc />
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(_propPrefabList, ContentPrefabList);
if (!UxrInstanceManagerEditor.ValidatePrefabsWithUniqueId(_propPrefabList, out string message))
{
EditorUtility.DisplayDialog(UxrConstants.Editor.Error, message, UxrConstants.Editor.Ok);
}
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Private Types & Data
private GUIContent ContentPrefabList { get; } = new GUIContent("Prefab List", "List of prefabs");
private const string PropertyPrefabList = "_prefabList";
private SerializedProperty _propPrefabList;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: efee02476eee24a45a611814d56c4410
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57a69f04a7c99c6438e8baffecb9481e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAxisPropertyDrawer.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core.Math;
using UnityEditor;
using UnityEngine;
namespace UltimateXR.Editor.Core.Math
{
/// <summary>
/// Custom property drawer for <see cref="UxrAxis" />.
/// </summary>
[CustomPropertyDrawer(typeof(UxrAxis))]
public class UxrAxisPropertyDrawer : PropertyDrawer
{
#region Public Types & Data
public const string PropertyAxis = "_axis";
#endregion
#region Public Overrides PropertyDrawer
/// <inheritdoc />
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight;
}
#endregion
#region Public Methods
/// <summary>
/// Draws an axis popup selector using <see cref="EditorGUILayout" />.
/// </summary>
/// <param name="content">Label and tooltip</param>
/// <param name="axis">Axis value</param>
/// <returns>New axis value</returns>
public static UxrAxis EditorGuiLayout(GUIContent content, UxrAxis axis)
{
return EditorGUILayout.Popup(content, (int)axis, AxesAsStrings);
}
#endregion
#region Unity
/// <inheritdoc />
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
SerializedProperty propertyAxis = property.FindPropertyRelative(PropertyAxis);
if (property.serializedObject.isEditingMultipleObjects)
{
// Multi-selection doesn't work correctly with PropertyDrawers when not using PropertyFields. Disable UI.
// https://answers.unity.com/questions/1214493/custompropertydrawer-cant-restrict-multi-editing.html
bool isGuiEnabled = GUI.enabled;
GUI.enabled = false;
EditorGUI.PropertyField(UxrEditorUtils.GetRect(position, 0), propertyAxis, label);
GUI.enabled = isGuiEnabled;
}
else
{
propertyAxis.intValue = EditorGUI.Popup(UxrEditorUtils.GetRect(position, 0), label, propertyAxis.intValue, UxrEditorUtils.ToGUIContentArray(AxesAsStrings));
}
EditorGUI.EndProperty();
}
#endregion
#region Private Types & Data
/// <summary>
/// Gets the possible axis values as strings.
/// </summary>
private static string[] AxesAsStrings { get; } = { "X", "Y", "Z" };
#endregion
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: ab8dfed24d683ba44b4415fef957f698
timeCreated: 1538564324
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5788e34be9db9e14c9ea46ab55af0d4f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrGlobalSettingsEditor.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core;
using UltimateXR.Core.Settings;
using UnityEditor;
using UnityEngine;
namespace UltimateXR.Editor.Core.Settings
{
/// <summary>
/// Custom inspector for <see cref="UxrGlobalSettings" />.
/// </summary>
[CustomEditor(typeof(UxrGlobalSettings))]
public class UxrGlobalSettingsEditor : UnityEditor.Editor
{
#region Unity
/// <summary>
/// Creates references to the serialized properties.
/// </summary>
private void OnEnable()
{
_propLogLevelAnimation = serializedObject.FindProperty(PropertyLogLevelAnimation);
_propLogLevelAvatar = serializedObject.FindProperty(PropertyLogLevelAvatar);
_propLogLevelCore = serializedObject.FindProperty(PropertyLogLevelCore);
_propLogLevelDevices = serializedObject.FindProperty(PropertyLogLevelDevices);
_propLogLevelLocomotion = serializedObject.FindProperty(PropertyLogLevelLocomotion);
_propLogLevelManipulation = serializedObject.FindProperty(PropertyLogLevelManipulation);
_propLogLevelNetworking = serializedObject.FindProperty(PropertyLogLevelNetworking);
_propLogLevelRendering = serializedObject.FindProperty(PropertyLogLevelRendering);
_propLogLevelUI = serializedObject.FindProperty(PropertyLogLevelUI);
_propLogLevelWeapons = serializedObject.FindProperty(PropertyLogLevelWeapons);
_propNetFormatInitialState = serializedObject.FindProperty(PropertyNetFormatInitialState);
_propNetFormatStateSync = serializedObject.FindProperty(PropertyNetFormatStateSync);
_propNetSyncGrabbablePhysics = serializedObject.FindProperty(PropertyNetSyncGrabbablePhysics);
_propNetGrabbableSyncIntervalSeconds = serializedObject.FindProperty(PropertyNetGrabbableSyncIntervalSeconds);
}
/// <inheritdoc />
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.TextArea($"{UxrConstants.UltimateXR} version: {UxrConstants.Version}");
// Log level configuration
_showLogLevels = UxrEditorUtils.FoldoutStylish("Log Levels", _showLogLevels);
if (_showLogLevels)
{
EditorGUILayout.PropertyField(_propLogLevelAnimation, ContentLogLevelAnimation);
EditorGUILayout.PropertyField(_propLogLevelAvatar, ContentLogLevelAvatar);
EditorGUILayout.PropertyField(_propLogLevelCore, ContentLogLevelCore);
EditorGUILayout.PropertyField(_propLogLevelDevices, ContentLogLevelDevices);
EditorGUILayout.PropertyField(_propLogLevelLocomotion, ContentLogLevelLocomotion);
EditorGUILayout.PropertyField(_propLogLevelManipulation, ContentLogLevelManipulation);
EditorGUILayout.PropertyField(_propLogLevelNetworking, ContentLogLevelNetworking);
EditorGUILayout.PropertyField(_propLogLevelRendering, ContentLogLevelRendering);
EditorGUILayout.PropertyField(_propLogLevelUI, ContentLogLevelUI);
EditorGUILayout.PropertyField(_propLogLevelWeapons, ContentLogLevelWeapons);
}
// Networking config
_showNetworking = UxrEditorUtils.FoldoutStylish("Networking", _showNetworking);
if (_showNetworking)
{
EditorGUILayout.PropertyField(_propNetFormatInitialState, ContentNetFormatInitialState);
EditorGUILayout.PropertyField(_propNetFormatStateSync, ContentNetFormatStateSync);
EditorGUILayout.PropertyField(_propNetSyncGrabbablePhysics, ContentNetSyncGrabbablePhysics);
if (_propNetSyncGrabbablePhysics.boolValue)
{
EditorGUILayout.Slider(_propNetGrabbableSyncIntervalSeconds, 0.1f, 10.0f, ContentNetGrabbableSyncIntervalSeconds);
}
}
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Private Types & Data
private GUIContent ContentLogLevelAnimation { get; } = new GUIContent("Animation", "Selects the console log level for animation events");
private GUIContent ContentLogLevelAvatar { get; } = new GUIContent("Avatar", "Selects the console log level for avatar events");
private GUIContent ContentLogLevelCore { get; } = new GUIContent("Core", "Selects the console log level for core events");
private GUIContent ContentLogLevelDevices { get; } = new GUIContent("Devices", "Selects the console log level for device events");
private GUIContent ContentLogLevelLocomotion { get; } = new GUIContent("Locomotion", "Selects the console log level for locomotion events");
private GUIContent ContentLogLevelManipulation { get; } = new GUIContent("Manipulation", "Selects the console log level for manipulation events");
private GUIContent ContentLogLevelNetworking { get; } = new GUIContent("Networking", "Selects the console log level for networking events");
private GUIContent ContentLogLevelRendering { get; } = new GUIContent("Rendering", "Selects the console log level for rendering events");
private GUIContent ContentLogLevelUI { get; } = new GUIContent("UI", "Selects the console log level for UI events");
private GUIContent ContentLogLevelWeapons { get; } = new GUIContent("Weapons", "Selects the console log level for weapon events");
private GUIContent ContentNetFormatInitialState { get; } = new GUIContent("Initial State Msg Format", "Selects the message format to use when the host sends the initial state of the session upon joining. Compression has a little CPU overhead but will use less bandwidth.");
private GUIContent ContentNetFormatStateSync { get; } = new GUIContent("State Sync Msg Format", "Selects the message format to use when exchanging state synchronization updates. Compression has a little CPU overhead but will use less bandwidth.");
private GUIContent ContentNetSyncGrabbablePhysics { get; } = new GUIContent("Sync Grabbable Physics", "Selects whether to sync grabbable objects with rigidbodies that have no NetworkTransform/NetworkRidibody set up. This keeps position/rotation and speeds manually in sync by sending periodic messages.");
private GUIContent ContentNetGrabbableSyncIntervalSeconds { get; } = new GUIContent("Grabbable Sync Interval (Seconds)", "Selects the interval in seconds grabbable objects with rigidbodies are kept in sync when there are no NetworkTransform/NetworkRidibody set up. Lower values will send RPC messages more frequently but will increase bandwidth.");
private const string PropertyLogLevelAnimation = "_logLevelAnimation";
private const string PropertyLogLevelAvatar = "_logLevelAvatar";
private const string PropertyLogLevelCore = "_logLevelCore";
private const string PropertyLogLevelDevices = "_logLevelDevices";
private const string PropertyLogLevelLocomotion = "_logLevelLocomotion";
private const string PropertyLogLevelManipulation = "_logLevelManipulation";
private const string PropertyLogLevelNetworking = "_logLevelNetworking";
private const string PropertyLogLevelRendering = "_logLevelRendering";
private const string PropertyLogLevelUI = "_logLevelUI";
private const string PropertyLogLevelWeapons = "_logLevelWeapons";
private const string PropertyNetFormatInitialState = "_netFormatInitialState";
private const string PropertyNetFormatStateSync = "_netFormatStateSync";
private const string PropertyNetSyncGrabbablePhysics = "_syncGrabbablePhysics";
private const string PropertyNetGrabbableSyncIntervalSeconds = "_grabbableSyncIntervalSeconds";
private SerializedProperty _propLogLevelAnimation;
private SerializedProperty _propLogLevelAvatar;
private SerializedProperty _propLogLevelCore;
private SerializedProperty _propLogLevelDevices;
private SerializedProperty _propLogLevelLocomotion;
private SerializedProperty _propLogLevelManipulation;
private SerializedProperty _propLogLevelNetworking;
private SerializedProperty _propLogLevelRendering;
private SerializedProperty _propLogLevelUI;
private SerializedProperty _propLogLevelWeapons;
private SerializedProperty _propNetFormatInitialState;
private SerializedProperty _propNetFormatStateSync;
private SerializedProperty _propNetSyncGrabbablePhysics;
private SerializedProperty _propNetGrabbableSyncIntervalSeconds;
private bool _showLogLevels = true;
private bool _showNetworking = true;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d96f219608a592843aa52a749f16f5a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrComponentIntegrityChecker.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using UltimateXR.Core;
using UltimateXR.Core.Unique;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace UltimateXR.Editor.Core
{
/// <summary>
/// Class that hooks to Unity scene saving to detect inconsistencies in unique IDs of <see cref="IUxrUniqueId" />
/// components.
/// </summary>
public static class UxrComponentIntegrityChecker
{
#region Public Methods
/// <summary>
/// Method called when Unity loads. It will hook to the scene saving event.
/// </summary>
[InitializeOnLoadMethod]
public static void HookToSceneSave()
{
EditorSceneManager.sceneSaving -= EditorSceneManager_sceneSaving;
EditorSceneManager.sceneSaving += EditorSceneManager_sceneSaving;
}
#endregion
#region Event Handling Methods
/// <summary>
/// Called by Unity when the scene is saved.
/// </summary>
/// <param name="scene">Scene to be saved</param>
/// <param name="path">Path to save to</param>
private static void EditorSceneManager_sceneSaving(Scene scene, string path)
{
// Momentarily don't perform automatic ID generation, since changes might call OnValidate() which is where automatic ID generation is done.
EditorPrefs.SetBool(UxrConstants.Editor.AutomaticIdGenerationPrefs, false);
Dictionary<Guid, IUxrUniqueId> sceneUxrComponents = new Dictionary<Guid, IUxrUniqueId>();
foreach (GameObject rootGameObject in scene.GetRootGameObjects())
{
IUxrUniqueId[] components = rootGameObject.GetComponentsInChildren<IUxrUniqueId>(true);
foreach (IUxrUniqueId component in components)
{
int attemptCount = 0;
while (component.UniqueId == default || sceneUxrComponents.ContainsKey(component.UniqueId))
{
// ID is either missing (shouldn't happen) or duplicated (by duplicating a GameObject in the scene). Generate new ID.
component.ChangeUniqueId(UxrUniqueIdImplementer.GetNewUniqueId());
attemptCount++;
if (attemptCount > MaxAttempts)
{
break;
}
}
if (component.UniqueId != default)
{
sceneUxrComponents.TryAdd(component.UniqueId, component);
}
}
}
// Re-enable automatic ID generation.
EditorPrefs.SetBool(UxrConstants.Editor.AutomaticIdGenerationPrefs, true);
}
#endregion
#region Private Types & Data
private const int MaxAttempts = 100;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ec9b4c64e5426846b83f134ace8f4af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,177 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrSdkManagerWindow.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using UltimateXR.Core;
using UltimateXR.Editor.Sdks;
using UltimateXR.Extensions.System;
using UnityEditor;
using UnityEngine;
namespace UltimateXR.Editor.Core
{
/// <summary>
/// Editor class that allows to create/modify/delete hand poses that can be used for interaction or manipulation in
/// avatars.
/// </summary>
public class UxrSdkManagerWindow : EditorWindow
{
#region Public Methods
/// <summary>
/// Shows the SDK Manager window.
/// </summary>
[MenuItem(UxrConstants.Editor.MenuPathSdks + "SDK Manager", priority = UxrConstants.Editor.PriorityMenuPathSdks + 100)]
public static void ShowWindow()
{
ShowWindow(UxrSdkLocator.SupportType.InputTracking);
}
/// <summary>
/// Shows the SDK Manager window.
/// </summary>
/// <param name="supportType">SDK type tab to show</param>
public static void ShowWindow(UxrSdkLocator.SupportType supportType)
{
UxrSdkManagerWindow managerWindow = GetWindow(typeof(UxrSdkManagerWindow), true, "UltimateXR SDK Manager") as UxrSdkManagerWindow;
if (GetRegisteredSdkSupportTypes().Contains(supportType))
{
managerWindow._selectedType = (int)supportType;
}
}
#endregion
#region Unity
/// <summary>
/// Initializes the window.
/// </summary>
private void OnEnable()
{
_foldouts = new Dictionary<UxrSdkLocator, bool>();
_registeredTypes = GetRegisteredSdkSupportTypes();
}
/// <summary>
/// Draws the UI and handles input events.
/// </summary>
private void OnGUI()
{
if (EditorApplication.isCompiling)
{
EditorGUILayout.LabelField("Compiling...");
return;
}
if (_registeredTypes.Count == 0)
{
EditorGUILayout.LabelField("No SDK locators have been registered");
return;
}
// SDK type tabs
if (_registeredTypes.Count > 1)
{
EditorGUILayout.Space();
EditorGUILayout.Space();
_selectedType = GUILayout.Toolbar(_selectedType, _registeredTypes.Select(t => t.ToString().SplitCamelCase()).ToArray());
}
// SDK list
IEnumerable<UxrSdkLocator> locatorsOfCurrentType = UxrSdkManager.SDKLocators.Where(l => l.Support == _registeredTypes[_selectedType]);
if (!locatorsOfCurrentType.Any())
{
EditorGUILayout.LabelField("Support coming in next versions. Stay tuned!");
return;
}
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Supported SDKs:", EditorStyles.boldLabel);
EditorGUILayout.Space();
foreach (UxrSdkLocator sdkLocator in locatorsOfCurrentType)
{
if (!_foldouts.ContainsKey(sdkLocator))
{
_foldouts.Add(sdkLocator, true);
}
_foldouts[sdkLocator] = UxrEditorUtils.FoldoutStylish(sdkLocator.Name, _foldouts[sdkLocator]);
if (_foldouts[sdkLocator])
{
EditorGUI.indentLevel += 1;
EditorGUILayout.LabelField("Status: " + sdkLocator.CurrentStateString);
if (sdkLocator.CurrentState == UxrSdkLocator.State.NotInstalled)
{
if (UxrEditorUtils.CenteredButton(new GUIContent("Get SDK")))
{
sdkLocator.TryGet();
}
}
else if (sdkLocator.CurrentState == UxrSdkLocator.State.Available && sdkLocator.CanBeUpdated)
{
if (UxrEditorUtils.CenteredButton(new GUIContent("SDK Update Check")))
{
sdkLocator.TryUpdate();
}
}
GUI.enabled = UxrSdkManager.HasAnySymbols(sdkLocator);
if (UxrEditorUtils.CenteredButton(new GUIContent("Remove Symbols")))
{
UxrSdkManager.RemoveSymbols(sdkLocator);
}
GUI.enabled = true;
if (sdkLocator.CurrentState == UxrSdkLocator.State.Available)
{
sdkLocator.OnInspectorGUI();
}
EditorGUI.indentLevel -= 1;
}
}
EditorGUILayout.Space();
}
#endregion
#region Private Methods
/// <summary>
/// Gets the different SDK types that have been registered
/// </summary>
/// <returns>SDK types</returns>
private static List<UxrSdkLocator.SupportType> GetRegisteredSdkSupportTypes()
{
return Enum.GetValues(typeof(UxrSdkLocator.SupportType)).OfType<UxrSdkLocator.SupportType>().ToList();
}
#endregion
#region Private Types & Data
private List<UxrSdkLocator.SupportType> _registeredTypes = new List<UxrSdkLocator.SupportType>();
private int _selectedType;
private Dictionary<UxrSdkLocator, bool> _foldouts;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e9e2598fd14163842989366affd635c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: