deltavr multiplayer 2.0

This commit is contained in:
Toomas Tamm
2023-05-08 15:56:10 +03:00
parent 978809a002
commit 07b9b9e2f4
10937 changed files with 2968397 additions and 1521012 deletions

View File

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

View File

@@ -0,0 +1,16 @@
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// Interface to implement for objects that hold a set of <c>Key</c>s
/// </summary>
public interface IKeychain
{
/// <summary>
/// This callback is used to check if this keychain has a specific <c>Key</c>
/// <see cref="Lock"/>
/// </summary>
/// <param name="key">the key to be checked</param>
/// <returns>True if this keychain has the supplied key; false otherwise</returns>
bool Contains(Key key);
}
}

View File

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

View File

@@ -0,0 +1,10 @@
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// An asset that represents a key. Used to check if an object can perform some action
/// (<see cref="XRLockSocketInteractor"/> and <see cref="Keychain"/>)
/// </summary>
[CreateAssetMenuAttribute(menuName = "XR/Key Lock System/Key")]
public class Key : ScriptableObject
{ }
}

View File

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

View File

@@ -0,0 +1,73 @@
using System.Collections.Generic;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// A generic Keychain component that holds the <see cref="Key"/>s to open a <see cref="Lock"/>.
/// Attach a Keychain component to an Interactable and assign to it the same Keys of an <see cref="XRLockSocketInteractor"/>
/// or an <see cref="XRLockGridSocketInteractor"/> to open (or interact with) them.
/// </summary>
[DisallowMultipleComponent]
public class Keychain : MonoBehaviour, IKeychain
{
[SerializeField]
[Tooltip("The keys on this keychain" +
"Create new keys by selecting \"Assets/Create/XR/Key Lock System/Key\"")]
List<Key> m_Keys;
HashSet<int> m_KeysHashSet = new HashSet<int>();
void Awake()
{
RepopulateHashSet();
}
void OnValidate()
{
// A key was added through the inspector while the game was running?
if (Application.isPlaying && m_Keys.Count != m_KeysHashSet.Count)
RepopulateHashSet();
}
void RepopulateHashSet()
{
m_KeysHashSet.Clear();
foreach (var key in m_Keys)
{
if (key != null)
m_KeysHashSet.Add(key.GetInstanceID());
}
}
/// <summary>
/// Adds the supplied key to this keychain
/// </summary>
/// <param name="key">The key to be added to the keychain</param>
public void AddKey(Key key)
{
if (key == null || Contains(key))
return;
m_Keys.Add(key);
m_KeysHashSet.Add(key.GetInstanceID());
}
/// <summary>
/// Adds the supplied key from this keychain
/// </summary>
/// <param name="key">The key to be removed from the keychain</param>
public void RemoveKey(Key key)
{
m_Keys.Remove(key);
if (key != null)
m_KeysHashSet.Remove(key.GetInstanceID());
}
/// <inheritdoc />
public bool Contains(Key key)
{
return key != null && m_KeysHashSet.Contains(key.GetInstanceID());
}
}
}

View File

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

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// Use this object as a generic way to validate if an object can perform some action.
/// The check is done in the <see cref="CanUnlock"/> method.
/// This class is used in combination with a <see cref="Keychain"/> component.
/// </summary>
/// <seealso cref="XRLockSocketInteractor"/>
/// <seealso cref="XRLockGridSocketInteractor"/>
[Serializable]
public class Lock
{
[SerializeField]
[Tooltip("The required keys to unlock this lock" +
"Create new keys by selecting \"Assets/Create/XR/Key Lock System/Key\"")]
List<Key> m_RequiredKeys;
/// <summary>
/// Returns the required keys to unlock this lock.
/// </summary>
public List<Key> requiredKeys => m_RequiredKeys;
/// <summary>
/// Checks if the supplied keychain has all the required keys to open this lock.
/// </summary>
/// <param name="keychain">The keychain to be checked.</param>
/// <returns>True if the supplied keychain has all the required keys; false otherwise.</returns>
public bool CanUnlock(IKeychain keychain)
{
if (keychain == null)
return m_RequiredKeys.Count == 0;
foreach (var requiredKey in m_RequiredKeys)
{
if (requiredKey == null)
continue;
if (!keychain.Contains(requiredKey))
return false;
}
return true;
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,59 @@
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// This class is responsible for creating the perler sockets grid and turning on/off the machine.
/// </summary>
public class PerlerMachineController : MonoBehaviour
{
static readonly string k_EmissionKeyword = "_EMISSION";
[SerializeField]
[Tooltip("The emissive materials that will change state whenever the machine is turned on/off")]
Material[] m_EmissiveMaterials;
bool m_MachineActive;
void Awake()
{
DisableEmissiveMaterials();
}
#if UNITY_EDITOR
void OnDestroy()
{
EnableEmissiveMaterials();
}
#endif
void DisableEmissiveMaterials()
{
foreach (var material in m_EmissiveMaterials)
material.DisableKeyword(k_EmissionKeyword);
}
void EnableEmissiveMaterials()
{
foreach (var material in m_EmissiveMaterials)
material.EnableKeyword(k_EmissionKeyword);
}
/// <summary>
/// Call this method to activate or deactivate the machine. This will also turn on/off its lights.
/// Used by the BatterySlot GameObject socket.
/// </summary>
/// <param name="active">Value of <see langword="true"/> to activate the machine; <see langword="false"/> otherwise.</param>
public void SetMachineActive(bool active)
{
// It's the same state?
if (active == m_MachineActive)
return;
// Change the machine light state
m_MachineActive = active;
if (m_MachineActive)
EnableEmissiveMaterials();
else
DisableEmissiveMaterials();
}
}
}

View File

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

View File

@@ -0,0 +1,176 @@
using System.Collections.Generic;
using UnityEngine.XR.Interaction.Toolkit;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// Socket Interactor for holding a group of Interactables in a 2D grid.
/// </summary>
/// <remarks>
/// The grid starts at the position of the Attach Transform.
/// During Awake, a Grid Socket instantiates one GameObject (as child of its Attach Transform) for each grid cell.
/// The Transform component of these instantiated objects are used as the actual attach point for the Interactables.
/// </remarks>
public class XRGridSocketInteractor : XRSocketInteractor
{
[Space]
[SerializeField]
[Tooltip("The grid width. The grid width is along the Attach Transform's local X axis.")]
int m_GridWidth = 2;
/// <summary>
/// The grid width. The grid width is along the Attach Transform's local X axis.
/// </summary>
public int gridWidth
{
get => m_GridWidth;
set => m_GridWidth = Mathf.Max(1, value);
}
[SerializeField]
[Tooltip("The grid height. The grid height is along the Attach Transform's local Y axis.")]
int m_GridHeight = 2;
/// <summary>
/// The grid height. The grid height is along the Attach Transform's local Y axis.
/// </summary>
public int gridHeight
{
get => m_GridHeight;
set => m_GridHeight = Mathf.Max(1, value);
}
/// <summary>
/// (Read Only) The grid size. The maximum number of Interactables that this Interactor can hold.
/// </summary>
public int gridSize => m_GridWidth * m_GridHeight;
[SerializeField]
[Tooltip("The distance (in local space) between cells in the grid.")]
Vector2 m_CellOffset = new Vector2(0.1f, 0.1f);
/// <summary>
/// The distance (in local space) between cells in the grid.
/// </summary>
public Vector2 cellOffset
{
get => m_CellOffset;
set => m_CellOffset = value;
}
readonly HashSet<Transform> m_UnorderedUsedAttachedTransform = new HashSet<Transform>();
readonly Dictionary<IXRInteractable, Transform> m_UsedAttachTransformByInteractable =
new Dictionary<IXRInteractable, Transform>();
Transform[,] m_Grid;
bool hasEmptyAttachTransform => m_UnorderedUsedAttachedTransform.Count < gridSize;
/// <summary>
/// Creates the grid.
/// </summary>
void CreateGrid()
{
m_Grid = new Transform[m_GridHeight, m_GridWidth];
for (var i = 0; i < m_GridHeight; i++)
{
for (var j = 0; j < m_GridWidth; j++)
{
var attachTransformInstance = new GameObject($"[{gameObject.name}] Attach ({i},{j})").transform;
attachTransformInstance.SetParent(attachTransform, false);
var offset = new Vector3(j * m_CellOffset.x, i * m_CellOffset.y, 0f);
attachTransformInstance.localPosition = offset;
m_Grid[i, j] = attachTransformInstance;
}
}
}
/// <inheritdoc />
protected override void Awake()
{
base.Awake();
CreateGrid();
// The same material is used on both situations
interactableCantHoverMeshMaterial = interactableHoverMeshMaterial;
}
/// <summary>
/// See <see cref="MonoBehaviour"/>.
/// </summary>
protected virtual void OnValidate()
{
m_GridWidth = Mathf.Max(1, m_GridWidth);
m_GridHeight = Mathf.Max(1, m_GridHeight);
}
/// <summary>
/// See <see cref="MonoBehaviour"/>.
/// </summary>
protected virtual void OnDrawGizmosSelected()
{
Gizmos.color = Color.green;
Gizmos.matrix = attachTransform != null ? attachTransform.localToWorldMatrix : transform.localToWorldMatrix;
for (var i = 0; i < m_GridHeight; i++)
{
for (var j = 0; j < m_GridWidth; j++)
{
var currentPosition = new Vector3(j * m_CellOffset.x, i * m_CellOffset.y, 0f);
Gizmos.DrawLine(currentPosition + (Vector3.left * m_CellOffset.x * 0.5f), currentPosition + (Vector3.right * m_CellOffset.y * 0.5f));
Gizmos.DrawLine(currentPosition + (Vector3.down * m_CellOffset.x * 0.5f), currentPosition + (Vector3.up * m_CellOffset.y * 0.5f));
}
}
}
/// <inheritdoc />
protected override void OnSelectEntering(SelectEnterEventArgs args)
{
base.OnSelectEntering(args);
var closestAttachTransform = GetAttachTransform(args.interactableObject);
m_UnorderedUsedAttachedTransform.Add(closestAttachTransform);
m_UsedAttachTransformByInteractable.Add(args.interactableObject, closestAttachTransform);
}
/// <inheritdoc />
protected override void OnSelectExiting(SelectExitEventArgs args)
{
var closestAttachTransform = m_UsedAttachTransformByInteractable[args.interactableObject];
m_UnorderedUsedAttachedTransform.Remove(closestAttachTransform);
m_UsedAttachTransformByInteractable.Remove(args.interactableObject);
base.OnSelectExiting(args);
}
/// <inheritdoc />
public override bool CanSelect(IXRSelectInteractable interactable)
{
return IsSelecting(interactable)
|| (hasEmptyAttachTransform && !interactable.isSelected && !m_UnorderedUsedAttachedTransform.Contains(GetAttachTransform(interactable)));
}
/// <inheritdoc />
public override bool CanHover(IXRHoverInteractable interactable)
{
return base.CanHover(interactable)
&& !m_UnorderedUsedAttachedTransform.Contains(GetAttachTransform(interactable));
}
/// <inheritdoc />
public override Transform GetAttachTransform(IXRInteractable interactable)
{
if (m_UsedAttachTransformByInteractable.TryGetValue(interactable, out var interactableAttachTransform))
return interactableAttachTransform;
var interactableLocalPosition = attachTransform.InverseTransformPoint(interactable.GetAttachTransform(this).position);
var i = Mathf.RoundToInt(interactableLocalPosition.y / m_CellOffset.y);
var j = Mathf.RoundToInt(interactableLocalPosition.x / m_CellOffset.x);
i = Mathf.Clamp(i, 0, m_GridHeight - 1);
j = Mathf.Clamp(j, 0, m_GridWidth - 1);
return m_Grid[i, j];
}
}
}

View File

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

View File

@@ -0,0 +1,95 @@
using UnityEngine.XR.Interaction.Toolkit;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// This component makes sure that the attached <c>Interactor</c> always have an interactable selected.
/// This is accomplished by forcing the <c>Interactor</c> to select a new <c>Interactable Prefab</c> instance whenever
/// it loses the current selected interactable.
/// </summary>
[DisallowMultipleComponent]
[RequireComponent(typeof(XRBaseInteractor))]
public class XRInfiniteInteractable : MonoBehaviour
{
[SerializeField]
[Tooltip("Whether infinite spawning is active.")]
bool m_Active = true;
[SerializeField]
[Tooltip("If true then during Awake the Interactor \"Starting Selected Interactable\" will be overriden by an " +
"instance of the \"Interactable Prefab\".")]
bool m_OverrideStartingSelectedInteractable;
[SerializeField]
[Tooltip("The Prefab or GameObject to be instantiated and selected.")]
XRBaseInteractable m_InteractablePrefab;
XRBaseInteractor m_Interactor;
/// <summary>
/// Whether infinite spawning is enabled.
/// </summary>
public bool active
{
get => m_Active;
set
{
m_Active = value;
if (enabled && value && !m_Interactor.hasSelection)
InstantiateAndSelectInteractable();
}
}
void Awake()
{
m_Interactor = GetComponent<XRBaseInteractor>();
if (m_OverrideStartingSelectedInteractable)
OverrideStartingSelectedInteractable();
}
void OnEnable()
{
if (m_InteractablePrefab == null)
{
Debug.LogWarning("No interactable prefab set - nothing to spawn!");
enabled = false;
return;
}
m_Interactor.selectExited.AddListener(OnSelectExited);
}
void OnDisable()
{
m_Interactor.selectExited.RemoveListener(OnSelectExited);
}
void OnSelectExited(SelectExitEventArgs selectExitEventArgs)
{
if (selectExitEventArgs.isCanceled || !active)
return;
InstantiateAndSelectInteractable();
}
XRBaseInteractable InstantiateInteractable()
{
var socketTransform = m_Interactor.transform;
return Instantiate(m_InteractablePrefab, socketTransform.position, socketTransform.rotation);
}
void OverrideStartingSelectedInteractable()
{
m_Interactor.startingSelectedInteractable = InstantiateInteractable();
}
void InstantiateAndSelectInteractable()
{
if (!gameObject.activeInHierarchy || m_Interactor.interactionManager == null)
return;
m_Interactor.interactionManager.SelectEnter((IXRSelectInteractor)m_Interactor, InstantiateInteractable());
}
}
}

View File

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

View File

@@ -0,0 +1,44 @@
using UnityEngine.XR.Interaction.Toolkit;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// Grid Socket interactor that only selects and hovers interactables with a <see cref="Keychain"/> component containing specific keys.
/// </summary>
public class XRLockGridSocketInteractor : XRGridSocketInteractor
{
[Space]
[SerializeField]
[Tooltip("The required keys to interact with this socket.")]
Lock m_Lock;
/// <summary>
/// The required keys to interact with this socket.
/// </summary>
public Lock keychainLock
{
get => m_Lock;
set => m_Lock = value;
}
/// <inheritdoc />
public override bool CanHover(IXRHoverInteractable interactable)
{
if (!base.CanHover(interactable))
return false;
var keyChain = interactable.transform.GetComponent<IKeychain>();
return m_Lock.CanUnlock(keyChain);
}
/// <inheritdoc />
public override bool CanSelect(IXRSelectInteractable interactable)
{
if (!base.CanSelect(interactable))
return false;
var keyChain = interactable.transform.GetComponent<IKeychain>();
return m_Lock.CanUnlock(keyChain);
}
}
}

View File

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

View File

@@ -0,0 +1,44 @@
using UnityEngine.XR.Interaction.Toolkit;
namespace UnityEngine.XR.Content.Interaction
{
/// <summary>
/// Socket interactor that only selects and hovers interactables with a keychain component containing specific keys.
/// </summary>
public class XRLockSocketInteractor : XRSocketInteractor
{
[Space]
[SerializeField]
[Tooltip("The required keys to interact with this socket.")]
Lock m_Lock;
/// <summary>
/// The required keys to interact with this socket.
/// </summary>
public Lock keychainLock
{
get => m_Lock;
set => m_Lock = value;
}
/// <inheritdoc />
public override bool CanHover(IXRHoverInteractable interactable)
{
if (!base.CanHover(interactable))
return false;
var keyChain = interactable.transform.GetComponent<IKeychain>();
return m_Lock.CanUnlock(keyChain);
}
/// <inheritdoc />
public override bool CanSelect(IXRSelectInteractable interactable)
{
if (!base.CanSelect(interactable))
return false;
var keyChain = interactable.transform.GetComponent<IKeychain>();
return m_Lock.CanUnlock(keyChain);
}
}
}

View File

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