202 lines
5.5 KiB
C#
202 lines
5.5 KiB
C#
using System.Collections.Generic;
|
|
using BlockSpace.Voxels;
|
|
using Photon.Pun;
|
|
using Photon.VR;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
|
|
namespace BlockSpace.Worlds
|
|
{
|
|
[DisallowMultipleComponent]
|
|
public sealed class CreatorFlightController : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private float flySpeed = 3.5f;
|
|
|
|
[SerializeField]
|
|
private float deadZone = 0.15f;
|
|
|
|
private InputDevice leftHand;
|
|
|
|
private bool flightProvidersDisabled;
|
|
|
|
private readonly Dictionary<Behaviour, bool> cachedProviderStates = new Dictionary<Behaviour, bool>();
|
|
|
|
private CharacterController phasedController;
|
|
|
|
private bool controllerCollisionCached;
|
|
|
|
private bool cachedControllerEnabled;
|
|
|
|
private bool cachedControllerDetectCollisions;
|
|
|
|
private void OnEnable()
|
|
{
|
|
leftHand = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
RestoreProviders();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!PhotonNetwork.InRoom)
|
|
{
|
|
RestoreProviders();
|
|
return;
|
|
}
|
|
VoxelGroupManager instance = VoxelGroupManager.Instance;
|
|
if (instance == null || instance.EditingLocked || !instance.CreatorMode)
|
|
{
|
|
RestoreProviders();
|
|
RestoreCharacterControllerCollisions();
|
|
return;
|
|
}
|
|
DisableNonFlightProviders();
|
|
if (!leftHand.isValid)
|
|
{
|
|
leftHand = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
|
|
}
|
|
Vector2 value = Vector2.zero;
|
|
if (leftHand.isValid)
|
|
{
|
|
leftHand.TryGetFeatureValue(CommonUsages.primary2DAxis, out value);
|
|
}
|
|
if (Mathf.Abs(value.x) < deadZone)
|
|
{
|
|
value.x = 0f;
|
|
}
|
|
if (Mathf.Abs(value.y) < deadZone)
|
|
{
|
|
value.y = 0f;
|
|
}
|
|
Transform transform = ((PhotonVRManager.Manager != null) ? PhotonVRManager.Manager.Head : null);
|
|
Transform localVrTeleportRoot = PlayerTeleportUtil.GetLocalVrTeleportRoot();
|
|
if (!(transform == null) && !(localVrTeleportRoot == null))
|
|
{
|
|
Vector3 obj = ((transform.forward.sqrMagnitude > 0.0001f) ? transform.forward.normalized : Vector3.forward);
|
|
Vector3 vector = ((transform.right.sqrMagnitude > 0.0001f) ? transform.right.normalized : Vector3.right);
|
|
Vector3 vector2 = obj * value.y + vector * value.x;
|
|
if (vector2.sqrMagnitude > 1f)
|
|
{
|
|
vector2.Normalize();
|
|
}
|
|
CharacterController component = localVrTeleportRoot.GetComponent<CharacterController>();
|
|
if (component != null)
|
|
{
|
|
ApplyCharacterControllerPhase(component);
|
|
}
|
|
Vector3 vector3 = vector2 * flySpeed;
|
|
if (!(vector3.sqrMagnitude <= 0.0001f))
|
|
{
|
|
localVrTeleportRoot.position += vector3 * Time.deltaTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DisableNonFlightProviders()
|
|
{
|
|
if (flightProvidersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
PhotonVRManager manager = PhotonVRManager.Manager;
|
|
if (!(manager == null))
|
|
{
|
|
cachedProviderStates.Clear();
|
|
cachedProviderStates.Clear();
|
|
DisableBehavioursUnder(manager.gameObject);
|
|
if (manager.LocalPlayer != null)
|
|
{
|
|
DisableBehavioursUnder(manager.LocalPlayer.gameObject);
|
|
}
|
|
if (manager.transform.root != null)
|
|
{
|
|
DisableBehavioursUnder(manager.transform.root.gameObject);
|
|
}
|
|
flightProvidersDisabled = true;
|
|
}
|
|
}
|
|
|
|
private void DisableBehavioursUnder(GameObject root)
|
|
{
|
|
if (root == null)
|
|
{
|
|
return;
|
|
}
|
|
Behaviour[] componentsInChildren = root.GetComponentsInChildren<Behaviour>(includeInactive: true);
|
|
foreach (Behaviour behaviour in componentsInChildren)
|
|
{
|
|
if (!(behaviour == null) && !(behaviour == this))
|
|
{
|
|
string text = behaviour.GetType().Name;
|
|
if (!string.IsNullOrEmpty(text) && !text.Contains("TurnProvider") && !text.Contains("SmoothTurn") && !text.Contains("SnapTurn") && (text.Contains("GravityProvider") || text.Contains("MoveProvider") || text.Contains("LocomotionProvider") || text.Contains("TeleportationProvider") || text.Contains("ClimbProvider") || text.Contains("ContinuousMove") || text.Contains("DynamicMove")))
|
|
{
|
|
cachedProviderStates[behaviour] = behaviour.enabled;
|
|
behaviour.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RestoreProviders()
|
|
{
|
|
if (!flightProvidersDisabled)
|
|
{
|
|
RestoreCharacterControllerCollisions();
|
|
return;
|
|
}
|
|
foreach (KeyValuePair<Behaviour, bool> cachedProviderState in cachedProviderStates)
|
|
{
|
|
if (cachedProviderState.Key != null)
|
|
{
|
|
cachedProviderState.Key.enabled = cachedProviderState.Value;
|
|
}
|
|
}
|
|
cachedProviderStates.Clear();
|
|
flightProvidersDisabled = false;
|
|
RestoreCharacterControllerCollisions();
|
|
}
|
|
|
|
private void ApplyCharacterControllerPhase(CharacterController controller)
|
|
{
|
|
if (!(controller == null))
|
|
{
|
|
if (phasedController != controller)
|
|
{
|
|
RestoreCharacterControllerCollisions();
|
|
phasedController = controller;
|
|
cachedControllerEnabled = controller.enabled;
|
|
cachedControllerDetectCollisions = controller.detectCollisions;
|
|
controllerCollisionCached = true;
|
|
}
|
|
controller.enabled = false;
|
|
controller.detectCollisions = false;
|
|
}
|
|
}
|
|
|
|
private void RestoreCharacterControllerCollisions()
|
|
{
|
|
if (controllerCollisionCached && phasedController != null)
|
|
{
|
|
phasedController.enabled = cachedControllerEnabled;
|
|
phasedController.detectCollisions = cachedControllerDetectCollisions;
|
|
EnsureControllerUsableAfterEdit(phasedController);
|
|
}
|
|
phasedController = null;
|
|
controllerCollisionCached = false;
|
|
}
|
|
|
|
private static void EnsureControllerUsableAfterEdit(CharacterController controller)
|
|
{
|
|
if (!(controller == null))
|
|
{
|
|
controller.enabled = true;
|
|
controller.detectCollisions = true;
|
|
}
|
|
}
|
|
}
|
|
}
|