// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System.Collections.Generic; using System.Linq; using UltimateXR.Core; using UltimateXR.Core.Components; using UltimateXR.Core.Settings; using UltimateXR.Extensions.System.Collections; using UltimateXR.Extensions.Unity; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace UltimateXR.Networking { /// /// Component that stores added network components from different SDKs so that they can be tracked more easily. /// They are mainly used by the UxrNetworkManagerEditor to delete added components. /// public partial class UxrNetworkComponentReferences : UxrComponent { #region Inspector Properties/Serialized Fields [SerializeField] private Origin _origin; [SerializeField] private List _addedGameObjects; [SerializeField] private List _addedComponents; #endregion #region Public Types & Data /// /// Gets the origin of the components. /// public Origin ComponentOrigin => _origin; /// /// Gets or sets the networking GameObjects that were registered by this component so that they can be deleted later /// using . /// public List AddedGameObjects { get => _addedGameObjects; set => _addedGameObjects = value; } /// /// Gets or sets the networking components that were registered by this component so that they can be deleted later /// using . /// public List AddedComponents { get => _addedComponents; set => _addedComponents = value; } #endregion #region Public Methods /// /// Creates a on a given GameObject that will keep track of all added /// network components. /// /// Object to process /// Network GameObjects that were added /// Network components that were added /// The origin of the components /// The created public static UxrNetworkComponentReferences RegisterNetworkComponents(GameObject gameObject, IEnumerable addedGameObjects, IEnumerable addedComponents, Origin origin) { #if UNITY_EDITOR UxrNetworkComponentReferences networkComponents = Undo.AddComponent(gameObject); SerializedObject serializedObject = new SerializedObject(networkComponents); serializedObject.FindProperty(UxrConstants.Editor.PropertyObjectHideFlags).enumValueFlag = (int)ComponentHideFlags; serializedObject.FindProperty(nameof(_origin)).enumValueIndex = (int)origin; SerializedProperty propAddedGameObjects = serializedObject.FindProperty(nameof(_addedGameObjects)); SerializedProperty propAddedComponents = serializedObject.FindProperty(nameof(_addedComponents)); propAddedGameObjects.arraySize = addedGameObjects.Count(); propAddedComponents.arraySize = addedComponents.Count(); int i = 0; foreach (GameObject go in addedGameObjects) { propAddedGameObjects.GetArrayElementAtIndex(i++).objectReferenceValue = go; } i = 0; foreach (Component component in addedComponents) { propAddedComponents.GetArrayElementAtIndex(i++).objectReferenceValue = component; } serializedObject.ApplyModifiedProperties(); return networkComponents; #else return null; #endif } /// /// Destroys all added network components in a GameObject and any of its children. /// /// GameObject to process public static void DestroyNetworkComponentsRecursively(GameObject gameObject, Origin origin) { gameObject.GetComponentsInChildren(true).Where(c => c._origin == origin).ForEach(c => c.DestroyWithAddedComponents()); } /// /// Destroys this component together with all the networking components that were added to this same GameObject. /// public void DestroyWithAddedComponents() { if (Application.isPlaying) { if (_addedComponents != null) { foreach (Component c in _addedComponents.Where(c => c != null)) { Destroy(c); } _addedComponents.Clear(); } if (_addedGameObjects != null) { foreach (GameObject g in _addedGameObjects.Where(g => g != null)) { Destroy(g); } _addedGameObjects.Clear(); } Destroy(this); return; } #if UNITY_EDITOR for (int i = 0; i < _addedComponents.Count; ++i) { if (_addedComponents[i] != null) { if (UxrGlobalSettings.Instance.LogLevelNetworking >= UxrLogLevel.Relevant) { Debug.Log($"{UxrConstants.NetworkingModule} Destroying component {_addedComponents[i].GetType().Name} in {_addedComponents[i].GetPathUnderScene()}"); } Undo.DestroyObjectImmediate(_addedComponents[i]); } else { if (UxrGlobalSettings.Instance.LogLevelNetworking >= UxrLogLevel.Relevant) { Debug.Log($"{UxrConstants.NetworkingModule} component {i} is null"); } } } for (int i = 0; i < _addedGameObjects.Count; ++i) { if (_addedGameObjects[i] != null) { if (UxrGlobalSettings.Instance.LogLevelNetworking >= UxrLogLevel.Relevant) { Debug.Log($"{UxrConstants.NetworkingModule} Destroying GameObject {_addedGameObjects[i].GetPathUnderScene()}"); } Undo.DestroyObjectImmediate(_addedGameObjects[i]); } else { if (UxrGlobalSettings.Instance.LogLevelNetworking >= UxrLogLevel.Relevant) { Debug.Log($"{UxrConstants.NetworkingModule} GameObject {i} is null"); } } } _addedGameObjects.Clear(); _addedComponents.Clear(); Undo.DestroyObjectImmediate(this); #endif } #endregion #region Unity /// /// Initializes the visibility. /// protected override void Awake() { base.Awake(); hideFlags = ComponentHideFlags; } /// /// This is a workaround to make hideFlags work on prefabs. Maybe related: /// https://forum.unity.com/threads/is-it-impossible-to-save-component-hideflags-in-a-prefab.976974/ /// protected override void OnValidate() { base.OnValidate(); hideFlags = ComponentHideFlags; } #endregion #region Private Types & Data /// /// Gets the required hide flags for this component. /// private static HideFlags ComponentHideFlags => HideFlags.HideInInspector | HideFlags.HideInHierarchy | HideFlags.NotEditable; #endregion } }