// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System.Collections.Generic; using UltimateXR.Core; using UltimateXR.Core.Components; using UltimateXR.Extensions.System.Collections; using UnityEngine; namespace UltimateXR.Locomotion { /// /// Component describing the visual representation of a teleport destination. /// public class UxrTeleportTarget : UxrComponent { #region Inspector Properties/Serialized Fields [SerializeField] private GameObject _reorientArrowRoot; [SerializeField] private List _validColorStateIgnoreList; #endregion #region Public Types & Data /// /// Gets whether the component has a separate object that is used to point to where the avatar will be facing towards /// after the teleportation. /// public bool HasReorientArrow => _reorientArrowRoot != null; /// /// Gets the forward vector of the reorient arrow. /// public Vector3 ReorientArrowForward => _reorientArrowRoot != null ? _reorientArrowRoot.transform.forward : Vector3.zero; /// /// Gets or sets the local rotation of the reorient arrow. /// public Quaternion ReorientArrowLocalRotation { get => _reorientArrowRoot != null ? _reorientArrowRoot.transform.localRotation : Quaternion.identity; set { if (_reorientArrowRoot != null) { _reorientArrowRoot.transform.localRotation = value; } } } #endregion #region Public Methods /// /// Enables the reorient arrow. /// /// Whether to enable it public void EnableReorientArrow(bool enable) { if (_reorientArrowRoot != null) { _reorientArrowRoot.SetActive(enable); } } /// /// Orients the direction arrow. /// /// New rotation public void OrientArrow(Quaternion rotation) { if (_reorientArrowRoot != null) { _reorientArrowRoot.transform.rotation = rotation; } } /// /// Sets the material color for objects whose color need to be changed in order to indicate a valid or invalid /// teleport. /// /// New color public void SetMaterialColor(Color color) { foreach (Renderer targetRenderer in _targetRenderers) { if (_object2MaterialID.TryGetValue(targetRenderer.gameObject, out UxrTeleportTargetMaterialID teleportMaterialID)) { Material[] materials = targetRenderer.materials; if (teleportMaterialID.MaterialID >= 0 && teleportMaterialID.MaterialID < materials.Length) { materials[teleportMaterialID.MaterialID].color = color; targetRenderer.materials = materials; } } else { targetRenderer.material.color = color; } } foreach (ParticleSystem pSystem in _particleSystems) { ParticleSystem.ColorOverLifetimeModule colorOverLifetime = pSystem.colorOverLifetime; if (colorOverLifetime.enabled && colorOverLifetime.color.gradient != null) { GradientColorKey[] keys = colorOverLifetime.color.gradient.colorKeys; keys.ForEach(k => k.color = color); colorOverLifetime.color.gradient.colorKeys = keys; } } foreach (ParticleSystemRenderer pSystemRenderer in _particleSystemRenderers) { if (_object2MaterialID.TryGetValue(pSystemRenderer.gameObject, out UxrTeleportTargetMaterialID teleportMaterialID)) { Material[] materials = pSystemRenderer.materials; if (teleportMaterialID.MaterialID >= 0 && teleportMaterialID.MaterialID < materials.Length) { materials[teleportMaterialID.MaterialID].color = color; materials[teleportMaterialID.MaterialID].SetColor(UxrConstants.Shaders.TintColorVarName, color); pSystemRenderer.materials = materials; } } else { pSystemRenderer.material.color = color; pSystemRenderer.material.SetColor(UxrConstants.Shaders.TintColorVarName, color); } } } #endregion #region Unity /// /// Initializes the component. /// protected override void Awake() { base.Awake(); // Register renderers _targetRenderers = new List(GetComponentsInChildren(false)); _particleSystems = new List(GetComponentsInChildren(false)); _particleSystemRenderers = new List(GetComponentsInChildren(false)); _object2MaterialID = new Dictionary(); _targetRenderers.RemoveAll(r => _validColorStateIgnoreList.Contains(r.gameObject)); _particleSystems.RemoveAll(p => _validColorStateIgnoreList.Contains(p.gameObject)); _particleSystemRenderers.RemoveAll(r => _validColorStateIgnoreList.Contains(r.gameObject)); // Register objects that have a UxrTeleportTargetMaterialID component that will tell us which material's color // should be changed if the teleport component uses colors to differentiate between valid and invalid targets. foreach (Renderer targetRenderer in _targetRenderers) { if (targetRenderer.gameObject.TryGetComponent(out var teleportMaterialID)) { _object2MaterialID.Add(teleportMaterialID.gameObject, teleportMaterialID); } } foreach (ParticleSystemRenderer pSystemRenderer in _particleSystemRenderers) { if (pSystemRenderer.gameObject.TryGetComponent(out var teleportMaterialID)) { _object2MaterialID.Add(teleportMaterialID.gameObject, teleportMaterialID); } } } #endregion #region Private Types & Data private List _targetRenderers; private List _particleSystems; private List _particleSystemRenderers; private Dictionary _object2MaterialID; #endregion } }