Add ultimate xr
This commit is contained in:
8
Assets/UltimateXR/Editor/Core/Components.meta
Normal file
8
Assets/UltimateXR/Editor/Core/Components.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc45e86f1c364654584db717b44e2f23
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76bd9d6956a81f7479e374e3fd31d679
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/UltimateXR/Editor/Core/Instantiation.meta
Normal file
8
Assets/UltimateXR/Editor/Core/Instantiation.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccb906d54174c324090202dc8456da80
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4c1411e2e9960b4294227f67525ca07
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efee02476eee24a45a611814d56c4410
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/UltimateXR/Editor/Core/Math.meta
Normal file
8
Assets/UltimateXR/Editor/Core/Math.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57a69f04a7c99c6438e8baffecb9481e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
86
Assets/UltimateXR/Editor/Core/Math/UxrAxisPropertyDrawer.cs
Normal file
86
Assets/UltimateXR/Editor/Core/Math/UxrAxisPropertyDrawer.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
8
Assets/UltimateXR/Editor/Core/Settings.meta
Normal file
8
Assets/UltimateXR/Editor/Core/Settings.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5788e34be9db9e14c9ea46ab55af0d4f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d96f219608a592843aa52a749f16f5a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ec9b4c64e5426846b83f134ace8f4af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
177
Assets/UltimateXR/Editor/Core/UxrSdkManagerWindow.cs
Normal file
177
Assets/UltimateXR/Editor/Core/UxrSdkManagerWindow.cs
Normal 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
|
||||
}
|
||||
}
|
||||
11
Assets/UltimateXR/Editor/Core/UxrSdkManagerWindow.cs.meta
Normal file
11
Assets/UltimateXR/Editor/Core/UxrSdkManagerWindow.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9e2598fd14163842989366affd635c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user