clean project

This commit is contained in:
Helar Jaadla
2022-03-07 17:52:41 +02:00
parent a174b45bd2
commit cbeb10ec35
5100 changed files with 837159 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
public class ActiveStateUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(IActiveState))]
private MonoBehaviour _activeState;
private IActiveState ActiveState;
[SerializeField]
private UnityEvent _whenActivated;
[SerializeField]
private UnityEvent _whenDeactivated;
public UnityEvent WhenActivated => _whenActivated;
public UnityEvent WhenDeactivated => _whenDeactivated;
[SerializeField]
[Tooltip("If true, the corresponding event will be fired at the beginning of Update")]
private bool _emitOnFirstUpdate = true;
private bool _emittedOnFirstUpdate = false;
private bool _savedState;
protected virtual void Awake()
{
ActiveState = _activeState as IActiveState;
}
protected virtual void Start()
{
Assert.IsNotNull(ActiveState);
_savedState = false;
}
protected virtual void Update()
{
if (_emitOnFirstUpdate && !_emittedOnFirstUpdate)
{
InvokeEvent();
_emittedOnFirstUpdate = true;
}
if (_savedState != ActiveState.Active)
{
_savedState = ActiveState.Active;
InvokeEvent();
}
}
private void InvokeEvent()
{
if (_savedState)
{
_whenActivated.Invoke();
}
else
{
_whenDeactivated.Invoke();
}
}
#region Inject
public void InjectAllActiveStateUnityEventWrapper(IActiveState activeState)
{
InjectActiveState(activeState);
}
public void InjectActiveState(IActiveState activeState)
{
_activeState = activeState as MonoBehaviour;
ActiveState = activeState;
}
public void InjectOptionalEmitOnFirstUpdate(bool emitOnFirstUpdate)
{
_emitOnFirstUpdate = emitOnFirstUpdate;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,100 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System;
using UnityEngine;
using UnityEngine.Assertions;
using Oculus.Interaction.UnityCanvas;
namespace Oculus.Interaction
{
public class CanvasMeshPointable : MonoBehaviour, IPointable
{
[SerializeField]
private CanvasRenderTextureMesh _canvasRenderTextureMesh;
[SerializeField, Interface(typeof(IPointable))]
private MonoBehaviour _pointable;
private IPointable Pointable;
public event Action<PointerArgs> OnPointerEvent = delegate { };
protected bool _started = false;
protected virtual void Awake()
{
Pointable = _pointable as IPointable;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(_canvasRenderTextureMesh);
Assert.IsNotNull(Pointable);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (!_started)
{
return;
}
Pointable.OnPointerEvent += InvokePointerEvent;
}
protected virtual void OnDisable()
{
if (!_started)
{
return;
}
Pointable.OnPointerEvent -= InvokePointerEvent;
}
private void InvokePointerEvent(PointerArgs args)
{
Vector3 transformPosition =
_canvasRenderTextureMesh.ImposterToCanvasTransformPoint(args.Position);
OnPointerEvent(new PointerArgs(args.Identifier,
args.PointerEvent,
transformPosition,
args.Rotation));
}
#region Inject
public void InjectAllCanvasMeshPointable(CanvasRenderTextureMesh canvasRenderTextureMesh,
IPointable pointable)
{
InjectCanvasRenderTextureMesh(canvasRenderTextureMesh);
InjectPointable(pointable);
}
public void InjectPointable(IPointable pointable)
{
_pointable = pointable as MonoBehaviour;
Pointable = pointable;
}
public void InjectCanvasRenderTextureMesh(CanvasRenderTextureMesh canvasRenderTextureMesh)
{
_canvasRenderTextureMesh = canvasRenderTextureMesh;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,147 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
/// <summary>
/// This component makes it possible to connect Interactables in the
/// inspector to Unity Events that are broadcast on state changes.
/// </summary>
public class InteractableUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(IInteractableView))]
private MonoBehaviour _interactableView;
private IInteractableView InteractableView;
[SerializeField]
private UnityEvent _whenHover;
[SerializeField]
private UnityEvent _whenUnhover;
[SerializeField]
private UnityEvent _whenSelect;
[SerializeField]
private UnityEvent _whenUnselect;
[SerializeField]
private UnityEvent _whenInteractorsCountUpdated;
[SerializeField]
private UnityEvent _whenSelectingInteractorsCountUpdated;
#region Properties
public UnityEvent WhenHover => _whenHover;
public UnityEvent WhenUnhover => _whenUnhover;
public UnityEvent WhenSelect => _whenSelect;
public UnityEvent WhenUnselect => _whenUnselect;
public UnityEvent WhenInteractorsCountUpdated => _whenInteractorsCountUpdated;
public UnityEvent WhenSelectingInteractorsCountUpdated => _whenSelectingInteractorsCountUpdated;
#endregion
protected bool _started = false;
protected virtual void Awake()
{
InteractableView = _interactableView as IInteractableView;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(InteractableView);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
InteractableView.WhenStateChanged += HandleStateChanged;
InteractableView.WhenInteractorsCountUpdated += HandleInteractorsCountUpdated;
InteractableView.WhenSelectingInteractorsCountUpdated += HandleSelectingInteractorsCountUpdated;
}
}
protected virtual void OnDisable()
{
if (_started)
{
InteractableView.WhenStateChanged -= HandleStateChanged;
InteractableView.WhenInteractorsCountUpdated -= HandleInteractorsCountUpdated;
InteractableView.WhenSelectingInteractorsCountUpdated -= HandleSelectingInteractorsCountUpdated;
}
}
private void HandleStateChanged(InteractableStateChangeArgs args)
{
switch (args.NewState)
{
case InteractableState.Normal:
if (args.PreviousState == InteractableState.Hover)
{
_whenUnhover.Invoke();
}
break;
case InteractableState.Hover:
if (args.PreviousState == InteractableState.Normal)
{
_whenHover.Invoke();
}
else if (args.PreviousState == InteractableState.Select)
{
_whenUnselect.Invoke();
}
break;
case InteractableState.Select:
if (args.PreviousState == InteractableState.Hover)
{
_whenSelect.Invoke();
}
break;
}
}
private void HandleInteractorsCountUpdated()
{
_whenInteractorsCountUpdated.Invoke();
}
private void HandleSelectingInteractorsCountUpdated()
{
_whenSelectingInteractorsCountUpdated.Invoke();
}
#region Inject
public void InjectAllInteractableUnityEventWrapper(
IInteractableView<IInteractorView> interactableView)
{
InjectInteractableView(interactableView);
}
public void InjectInteractableView(IInteractableView interactableView)
{
_interactableView = interactableView as MonoBehaviour;
InteractableView = interactableView;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,121 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
/// <summary>
/// This component makes it possible to connect Interactors in the
/// inspector to Unity Events that broadcast on state changes
/// </summary>
public class InteractorUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(IInteractorView))]
private MonoBehaviour _interactorView;
private IInteractorView InteractorView;
[SerializeField]
private UnityEvent _whenHover;
[SerializeField]
private UnityEvent _whenUnhover;
[SerializeField]
private UnityEvent _whenSelect;
[SerializeField]
private UnityEvent _whenUnselect;
public UnityEvent WhenHover => _whenHover;
public UnityEvent WhenUnhover => _whenUnhover;
public UnityEvent WhenSelect => _whenSelect;
public UnityEvent WhenUnselect => _whenUnselect;
protected bool _started = false;
protected virtual void Awake()
{
InteractorView = _interactorView as IInteractorView;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(InteractorView);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
InteractorView.WhenStateChanged += HandleStateChanged;
}
}
protected virtual void OnDisable()
{
if (_started)
{
InteractorView.WhenStateChanged -= HandleStateChanged;
}
}
private void HandleStateChanged(InteractorStateChangeArgs args)
{
switch (args.NewState)
{
case InteractorState.Normal:
if (args.PreviousState == InteractorState.Hover)
{
_whenUnhover.Invoke();
}
break;
case InteractorState.Hover:
if (args.PreviousState == InteractorState.Normal)
{
_whenHover.Invoke();
}
else if (args.PreviousState == InteractorState.Select)
{
_whenUnselect.Invoke();
}
break;
case InteractorState.Select:
if (args.PreviousState == InteractorState.Hover)
{
_whenSelect.Invoke();
}
break;
}
}
#region Inject
public void InjectAllInteractorUnityEventWrapper(IInteractorView interactorView)
{
InjectInteractorView(interactorView);
}
public void InjectInteractorView(IInteractorView interactorView)
{
_interactorView = interactorView as MonoBehaviour;
InteractorView = interactorView;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,158 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction
{
public class PhysicsTransformable : MonoBehaviour
{
[SerializeField]
private Transformable _transformable;
[SerializeField]
private Rigidbody _rigidbody;
[SerializeField]
[Tooltip("If enabled, the object's mass will scale appropriately as the scale of the object changes.")]
private bool _scaleMassWithSize = true;
private bool _savedIsKinematicState = false;
private bool _isBeingTransformed = false;
private Vector3 _initialScale;
private bool _hasPendingForce;
private Vector3 _linearVelocity;
private Vector3 _angularVelocity;
protected bool _started = false;
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(_transformable);
Assert.IsNotNull(_rigidbody);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
_transformable.WhenTransformableUpdated += HandleTransformableUpdated;
}
}
protected virtual void OnDisable()
{
if (_started)
{
_transformable.WhenTransformableUpdated -= HandleTransformableUpdated;
}
}
private void HandleTransformableUpdated(TransformableArgs args)
{
switch (args.TransformableEvent)
{
case TransformableEvent.Add:
if (_transformable.GrabPointsCount == 1 && !_isBeingTransformed)
{
DisablePhysics();
}
break;
case TransformableEvent.Remove:
if (_transformable.GrabPointsCount == 0)
{
ReenablePhysics();
}
break;
}
}
private void DisablePhysics()
{
_isBeingTransformed = true;
CachePhysicsState();
_rigidbody.isKinematic = true;
}
private void ReenablePhysics()
{
_isBeingTransformed = false;
// update the mass based on the scale change
if (_scaleMassWithSize)
{
float initialScaledVolume = _initialScale.x * _initialScale.y * _initialScale.z;
Vector3 currentScale = _rigidbody.transform.localScale;
float currentScaledVolume = currentScale.x * currentScale.y * currentScale.z;
float changeInMassFactor = currentScaledVolume / initialScaledVolume;
_rigidbody.mass *= changeInMassFactor;
}
// revert the original kinematic state
_rigidbody.isKinematic = _savedIsKinematicState;
}
public void ApplyVelocities(Vector3 linearVelocity, Vector3 angularVelocity)
{
_hasPendingForce = true;
_linearVelocity = linearVelocity;
_angularVelocity = angularVelocity;
}
private void FixedUpdate()
{
if (_hasPendingForce)
{
_hasPendingForce = false;
_rigidbody.AddForce(_linearVelocity, ForceMode.VelocityChange);
_rigidbody.AddTorque(_angularVelocity, ForceMode.VelocityChange);
}
}
private void CachePhysicsState()
{
_savedIsKinematicState = _rigidbody.isKinematic;
_initialScale = _rigidbody.transform.localScale;
}
#region Inject
public void InjectAllPhysicsTransformable(Transformable transformable, Rigidbody rigidbody)
{
InjectTransformable(transformable);
InjectRigidbody(rigidbody);
}
public void InjectTransformable(Transformable transformable)
{
_transformable = transformable;
}
public void InjectRigidbody(Rigidbody rigidbody)
{
_rigidbody = rigidbody;
}
public void InjectOptionalScaleMassWithSize(bool scaleMassWithSize)
{
_scaleMassWithSize = scaleMassWithSize;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,91 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Assertions;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
/// <summary>
/// PointerCanvas allows any IPointable to forward its
/// events onto an associated Canvas via the IPointableCanvas interface
/// Requires a PointableCanvasModule present in the scene.
/// </summary>
public class PointableCanvas : MonoBehaviour, IPointableCanvas
{
[SerializeField, Interface(typeof(IPointable))]
private MonoBehaviour _pointable;
private IPointable Pointable;
[SerializeField]
private Canvas _canvas;
public Canvas Canvas => _canvas;
public event Action<PointerArgs> OnPointerEvent = delegate { };
private bool _registered = false;
protected bool _started = false;
protected virtual void Awake()
{
Pointable = _pointable as IPointable;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(Pointable);
this.EndStart(ref _started);
}
private void Register()
{
PointableCanvasModule.RegisterPointableCanvas(this);
Pointable.OnPointerEvent += HandlePointerEvent;
_registered = true;
}
private void Unregister()
{
if (!_registered) return;
Pointable.OnPointerEvent -= HandlePointerEvent;
PointableCanvasModule.UnregisterPointableCanvas(this);
_registered = false;
}
private void HandlePointerEvent(PointerArgs args)
{
OnPointerEvent(args);
}
protected virtual void OnEnable()
{
if (_started)
{
Register();
}
}
protected virtual void OnDisable()
{
if (_started)
{
Unregister();
}
}
}
}

View File

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

View File

@@ -0,0 +1,557 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;
using UnityEngine.Assertions;
using System;
namespace Oculus.Interaction
{
public class PointableCanvasEventArgs
{
public readonly Canvas Canvas;
public readonly GameObject Hovered;
public readonly bool Dragging;
public PointableCanvasEventArgs(Canvas canvas, GameObject hovered, bool dragging)
{
Canvas = canvas;
Hovered = hovered;
Dragging = dragging;
}
}
/// <summary>
/// IPointerInteractableModule manages all InteractableCanvas events in
/// the scene and translates them into pointer events for Unity Canvas UIs.
/// </summary>
public class PointableCanvasModule : PointerInputModule
{
public static event Action<PointableCanvasEventArgs> WhenSelected;
public static event Action<PointableCanvasEventArgs> WhenUnselected;
public static event Action<PointableCanvasEventArgs> WhenSelectableHovered;
public static event Action<PointableCanvasEventArgs> WhenSelectableUnhovered;
[SerializeField]
private bool _useInitialPressPositionForDrag = true;
private Camera _pointerEventCamera;
private static PointableCanvasModule _instance = null;
private static PointableCanvasModule Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<PointableCanvasModule>();
}
return _instance;
}
}
public static void RegisterPointableCanvas(IPointableCanvas pointerCanvas)
{
Assert.IsNotNull(Instance, "A PointableCanvasModule is required in the scene.");
Instance.AddPointerCanvas(pointerCanvas);
}
public static void UnregisterPointableCanvas(IPointableCanvas pointerCanvas)
{
Instance?.RemovePointerCanvas(pointerCanvas);
}
private Dictionary<int, Pointer> _pointerMap = new Dictionary<int, Pointer>();
private List<RaycastResult> _raycastResultCache = new List<RaycastResult>();
private List<Pointer> _pointersForDeletion = new List<Pointer>();
private Dictionary<IPointableCanvas, Action<PointerArgs>> _pointerCanvasActionMap =
new Dictionary<IPointableCanvas, Action<PointerArgs>>();
private void AddPointerCanvas(IPointableCanvas pointerCanvas)
{
Action<PointerArgs> pointerCanvasAction = (args) => HandlePointerEvent(pointerCanvas.Canvas, args);
_pointerCanvasActionMap.Add(pointerCanvas, pointerCanvasAction);
pointerCanvas.OnPointerEvent += pointerCanvasAction;
}
private void RemovePointerCanvas(IPointableCanvas pointerCanvas)
{
Action<PointerArgs> pointerCanvasAction = _pointerCanvasActionMap[pointerCanvas];
_pointerCanvasActionMap.Remove(pointerCanvas);
pointerCanvas.OnPointerEvent -= pointerCanvasAction;
List<int> pointerIDs = new List<int>(_pointerMap.Keys);
foreach (int pointerID in pointerIDs)
{
Pointer pointer = _pointerMap[pointerID];
if (pointer.Canvas != pointerCanvas.Canvas)
{
continue;
}
pointer.MarkForDeletion();
_pointersForDeletion.Add(pointer);
_pointerMap.Remove(pointerID);
}
}
private void HandlePointerEvent(Canvas canvas, PointerArgs args)
{
Pointer pointer;
switch (args.PointerEvent)
{
case PointerEvent.Hover:
pointer = new Pointer(canvas);
pointer.PointerEventData = new PointerEventData(eventSystem);
pointer.SetPosition(args.Position);
_pointerMap.Add(args.Identifier, pointer);
break;
case PointerEvent.Unhover:
pointer = _pointerMap[args.Identifier];
_pointerMap.Remove(args.Identifier);
pointer.MarkForDeletion();
_pointersForDeletion.Add(pointer);
break;
case PointerEvent.Select:
pointer = _pointerMap[args.Identifier];
pointer.SetPosition(args.Position);
pointer.Press();
break;
case PointerEvent.Unselect:
pointer = _pointerMap[args.Identifier];
pointer.SetPosition(args.Position);
pointer.Release();
break;
case PointerEvent.Move:
pointer = _pointerMap[args.Identifier];
pointer.SetPosition(args.Position);
break;
}
}
/// <summary>
/// Pointer class that is used for state associated with IPointables that are currently
/// tracked by any IPointableCanvases in the scene.
/// </summary>
private class Pointer
{
public PointerEventData PointerEventData { get; set; }
public bool MarkedForDeletion { get; private set; }
private Canvas _canvas;
public Canvas Canvas => _canvas;
private Vector3 _position;
public Vector3 Position => _position;
private GameObject _hoveredSelectable;
public GameObject HoveredSelectable => _hoveredSelectable;
private bool _pressing = false;
private bool _pressed;
private bool _released;
public Pointer(Canvas canvas)
{
_canvas = canvas;
_pressed = _released = false;
}
public void Press()
{
if (_pressing) return;
_pressing = true;
_pressed = true;
}
public void Release()
{
if (!_pressing) return;
_pressing = false;
_released = true;
}
public void ReadAndResetPressedReleased(out bool pressed, out bool released)
{
pressed = _pressed;
released = _released;
_pressed = _released = false;
}
public void MarkForDeletion()
{
MarkedForDeletion = true;
Release();
}
public void SetPosition(Vector3 position)
{
_position = position;
}
public void SetHoveredSelectable(GameObject hoveredSelectable)
{
_hoveredSelectable = hoveredSelectable;
}
}
protected bool _started = false;
protected override void Start()
{
this.BeginStart(ref _started, base.Start);
this.EndStart(ref _started);
}
protected override void OnEnable()
{
base.OnEnable();
if (_started)
{
_pointerEventCamera = gameObject.AddComponent<Camera>();
_pointerEventCamera.nearClipPlane = 0.1f;
// We do not need this camera to be enabled to serve this module's purposes:
// as a dependency for Canvases and for its WorldToScreenPoint functionality
_pointerEventCamera.enabled = false;
}
}
protected override void OnDisable()
{
if (_started)
{
Destroy(_pointerEventCamera);
_pointerEventCamera = null;
}
base.OnDisable();
}
// Based On FindFirstRaycast
protected static RaycastResult FindFirstRaycastWithinCanvas(List<RaycastResult> candidates, Canvas canvas)
{
GameObject candidateGameObject;
Canvas candidateCanvas;
for (var i = 0; i < candidates.Count; ++i)
{
candidateGameObject = candidates[i].gameObject;
if (candidateGameObject == null) continue;
candidateCanvas = candidateGameObject.GetComponentInParent<Canvas>();
if (candidateCanvas == null) continue;
if (candidateCanvas.rootCanvas != canvas) continue;
return candidates[i];
}
return new RaycastResult();
}
private void UpdateRaycasts(Pointer pointer, out bool pressed, out bool released)
{
PointerEventData pointerEventData = pointer.PointerEventData;
Vector2 prevPosition = pointerEventData.position;
Canvas canvas = pointer.Canvas;
canvas.worldCamera = _pointerEventCamera;
pointerEventData.Reset();
pointer.ReadAndResetPressedReleased(out pressed, out released);
Vector3 position = Vector3.zero;
var plane = new Plane(-1f * canvas.transform.forward, canvas.transform.position);
var ray = new Ray(pointer.Position - canvas.transform.forward, canvas.transform.forward);
float enter;
if (plane.Raycast(ray, out enter))
{
position = ray.GetPoint(enter);
}
// We need to position our camera at an offset from the Pointer position or else
// a graphic raycast may ignore a world canvas that's outside of our regular camera view(s)
_pointerEventCamera.transform.position = pointer.Position - canvas.transform.forward;
_pointerEventCamera.transform.LookAt(pointer.Position, canvas.transform.up);
Vector2 pointerPosition = _pointerEventCamera.WorldToScreenPoint(position);
pointerEventData.position = pointerPosition;
// RaycastAll raycasts against with every GraphicRaycaster in the scene,
// including nested ones like in the case of a dropdown
eventSystem.RaycastAll(pointerEventData, _raycastResultCache);
RaycastResult firstResult = FindFirstRaycastWithinCanvas(_raycastResultCache, canvas);
pointer.PointerEventData.pointerCurrentRaycast = firstResult;
_raycastResultCache.Clear();
// We use a static translation offset from the canvas for 2D position delta tracking
_pointerEventCamera.transform.position = canvas.transform.position - canvas.transform.forward;
_pointerEventCamera.transform.LookAt(canvas.transform.position, canvas.transform.up);
pointerPosition = _pointerEventCamera.WorldToScreenPoint(position);
pointerEventData.position = pointerPosition;
if (pressed)
{
pointerEventData.delta = Vector2.zero;
}
else
{
pointerEventData.delta = pointerEventData.position - prevPosition;
}
pointerEventData.button = PointerEventData.InputButton.Left;
}
public override void Process()
{
foreach (Pointer pointer in _pointersForDeletion)
{
ProcessPointer(pointer, true);
}
_pointersForDeletion.Clear();
foreach (Pointer pointer in _pointerMap.Values)
{
ProcessPointer(pointer);
}
}
private void ProcessPointer(Pointer pointer, bool forceRelease = false)
{
bool pressed = false;
bool released = false;
bool wasDragging = pointer.PointerEventData.dragging;
UpdateRaycasts(pointer, out pressed, out released);
PointerEventData pointerEventData = pointer.PointerEventData;
UpdatePointerEventData(pointerEventData, pressed, released);
released |= forceRelease;
if (!released)
{
ProcessMove(pointerEventData);
ProcessDrag(pointerEventData);
}
else
{
HandlePointerExitAndEnter(pointerEventData, null);
RemovePointerData(pointerEventData);
}
HandleSelectableHover(pointer, wasDragging);
HandleSelectablePress(pointer, pressed, released, wasDragging);
}
private void HandleSelectableHover(Pointer pointer, bool wasDragging)
{
bool dragging = pointer.PointerEventData.dragging || wasDragging;
GameObject currentOverGo = pointer.PointerEventData.pointerCurrentRaycast.gameObject;
GameObject prevHoveredSelectable = pointer.HoveredSelectable;
GameObject newHoveredSelectable = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
pointer.SetHoveredSelectable(newHoveredSelectable);
if (newHoveredSelectable != null && newHoveredSelectable != prevHoveredSelectable)
{
WhenSelectableHovered?.Invoke(new PointableCanvasEventArgs(pointer.Canvas, pointer.HoveredSelectable, dragging));
}
else if (prevHoveredSelectable != null && newHoveredSelectable == null)
{
WhenSelectableUnhovered?.Invoke(new PointableCanvasEventArgs(pointer.Canvas, pointer.HoveredSelectable, dragging));
}
}
private void HandleSelectablePress(Pointer pointer, bool pressed, bool released, bool wasDragging)
{
bool dragging = pointer.PointerEventData.dragging || wasDragging;
if (pressed)
{
WhenSelected?.Invoke(new PointableCanvasEventArgs(pointer.Canvas, pointer.HoveredSelectable, dragging));
}
else if (released && !pointer.MarkedForDeletion)
{
// Unity handles UI selection on release, so we verify the hovered element has been selected
bool hasSelectedHoveredObject = pointer.HoveredSelectable != null &&
pointer.HoveredSelectable == pointer.PointerEventData.selectedObject;
GameObject selectedObject = hasSelectedHoveredObject ? pointer.HoveredSelectable : null;
WhenUnselected?.Invoke(new PointableCanvasEventArgs(pointer.Canvas, selectedObject, dragging));
}
}
/// <summary>
/// This method is based on ProcessTouchPoint in StandaloneInputModule,
/// but is instead used for Pointer events
/// </summary>
protected void UpdatePointerEventData(PointerEventData pointerEvent, bool pressed, bool released)
{
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
// PointerDown notification
if (pressed)
{
pointerEvent.eligibleForClick = true;
pointerEvent.delta = Vector2.zero;
pointerEvent.dragging = false;
pointerEvent.useDragThreshold = true;
pointerEvent.pressPosition = pointerEvent.position;
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
if (pointerEvent.pointerEnter != currentOverGo)
{
// send a pointer enter to the touched element if it isn't the one to select...
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
pointerEvent.pointerEnter = currentOverGo;
}
// search for the control that will receive the press
// if we can't find a press handler set the press
// handler to be what would receive a click.
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
// didnt find a press handler... search for a click handler
if (newPressed == null)
newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
float time = Time.unscaledTime;
if (newPressed == pointerEvent.lastPress)
{
var diffTime = time - pointerEvent.clickTime;
if (diffTime < 0.3f)
++pointerEvent.clickCount;
else
pointerEvent.clickCount = 1;
pointerEvent.clickTime = time;
}
else
{
pointerEvent.clickCount = 1;
}
pointerEvent.pointerPress = newPressed;
pointerEvent.rawPointerPress = currentOverGo;
pointerEvent.clickTime = time;
// Save the drag handler as well
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
if (pointerEvent.pointerDrag != null)
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
}
// PointerUp notification
if (released)
{
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
// see if we mouse up on the same element that we clicked on...
var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
// PointerClick and Drop events
if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
{
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
}
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
{
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
}
pointerEvent.eligibleForClick = false;
pointerEvent.pointerPress = null;
pointerEvent.rawPointerPress = null;
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
pointerEvent.dragging = false;
pointerEvent.pointerDrag = null;
// send exit events as we need to simulate this on touch up on touch device
ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler);
pointerEvent.pointerEnter = null;
}
}
/// <summary>
/// Override of PointerInputModule's ProcessDrag to allow using the initial press position for drag begin.
/// Set _useInitialPressPositionForDrag to false if you prefer the default behaviour of PointerInputModule.
/// </summary>
protected override void ProcessDrag(PointerEventData pointerEvent)
{
if (!pointerEvent.IsPointerMoving() ||
Cursor.lockState == CursorLockMode.Locked ||
pointerEvent.pointerDrag == null)
return;
if (!pointerEvent.dragging
&& ShouldStartDrag(pointerEvent.pressPosition, pointerEvent.position,
eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold))
{
if (_useInitialPressPositionForDrag)
{
pointerEvent.position = pointerEvent.pressPosition;
}
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent,
ExecuteEvents.beginDragHandler);
pointerEvent.dragging = true;
}
// Drag notification
if (pointerEvent.dragging)
{
// Before doing drag we should cancel any pointer down state
// And clear selection!
if (pointerEvent.pointerPress != pointerEvent.pointerDrag)
{
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent,
ExecuteEvents.pointerUpHandler);
pointerEvent.eligibleForClick = false;
pointerEvent.pointerPress = null;
pointerEvent.rawPointerPress = null;
}
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent,
ExecuteEvents.dragHandler);
}
}
/// <summary>
/// Used in PointerInputModule's ProcessDrag implementation. Brought into this subclass with a protected
/// signature (as opposed to the parent's private signature) to be used in this subclass's overridden ProcessDrag.
/// </summary>
protected static bool ShouldStartDrag(Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold)
{
if (!useDragThreshold)
return true;
return (pressPos - currentPos).sqrMagnitude >= threshold * threshold;
}
}
}

View File

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

View File

@@ -0,0 +1,138 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
namespace Oculus.Interaction
{
/// <summary>
/// This component makes it possible to connect PointableCanvases in the
/// inspector to Unity Events that are broadcast from PointableCanvasModule.
/// Useful for hooking into uGUI navigation.
/// </summary>
public class PointableCanvasUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(IPointableCanvas))]
private MonoBehaviour _pointableCanvas;
private IPointableCanvas PointableCanvas;
[SerializeField, Tooltip("Selection and hover events will not be fired while dragging.")]
private bool _suppressWhileDragging = true;
[SerializeField, Tooltip("Raised when beginning hover of a uGUI selectable")]
private UnityEvent _whenBeginHighlight;
[SerializeField, Tooltip("Raised when ending hover of a uGUI selectable")]
private UnityEvent _whenEndHighlight;
[SerializeField, Tooltip("Raised when selecting a hovered uGUI selectable")]
private UnityEvent _whenSelectedHovered;
[SerializeField, Tooltip("Raised when selecting with no uGUI selectable hovered")]
private UnityEvent _whenSelectedEmpty;
[SerializeField, Tooltip("Raised when deselecting a hovered uGUI selectable")]
private UnityEvent _whenUnselectedHovered;
[SerializeField, Tooltip("Raised when deselecting with no uGUI selectable hovered")]
private UnityEvent _whenUnselectedEmpty;
protected bool _started = false;
private bool ShouldFireEvent(PointableCanvasEventArgs args)
{
if (args.Canvas != PointableCanvas.Canvas)
{
return false;
}
if (_suppressWhileDragging && args.Dragging)
{
return false;
}
return true;
}
private void PointableCanvasModule_WhenSelectableHoverEnter(PointableCanvasEventArgs args)
{
if (ShouldFireEvent(args))
{
_whenBeginHighlight.Invoke();
}
}
private void PointableCanvasModule_WhenSelectableHoverExit(PointableCanvasEventArgs args)
{
if (ShouldFireEvent(args))
{
_whenEndHighlight.Invoke();
}
}
private void PointableCanvasModule_WhenSelectableSelected(PointableCanvasEventArgs args)
{
if (ShouldFireEvent(args))
{
if (args.Hovered == null)
_whenSelectedEmpty.Invoke();
else
_whenSelectedHovered.Invoke();
}
}
private void PointableCanvasModule_WhenSelectableUnselected(PointableCanvasEventArgs args)
{
if (ShouldFireEvent(args))
{
if (args.Hovered == null)
_whenUnselectedEmpty.Invoke();
else
_whenUnselectedHovered.Invoke();
}
}
protected virtual void Awake()
{
PointableCanvas = _pointableCanvas as IPointableCanvas;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(PointableCanvas);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
PointableCanvasModule.WhenSelectableHovered += PointableCanvasModule_WhenSelectableHoverEnter;
PointableCanvasModule.WhenSelectableUnhovered += PointableCanvasModule_WhenSelectableHoverExit;
PointableCanvasModule.WhenSelected += PointableCanvasModule_WhenSelectableSelected;
PointableCanvasModule.WhenUnselected += PointableCanvasModule_WhenSelectableUnselected;
}
}
protected virtual void OnDisable()
{
if (_started)
{
PointableCanvasModule.WhenSelectableHovered -= PointableCanvasModule_WhenSelectableHoverEnter;
PointableCanvasModule.WhenSelectableUnhovered -= PointableCanvasModule_WhenSelectableHoverExit;
PointableCanvasModule.WhenSelected -= PointableCanvasModule_WhenSelectableSelected;
PointableCanvasModule.WhenUnselected -= PointableCanvasModule_WhenSelectableUnselected;
}
}
}
}

View File

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

View File

@@ -0,0 +1,115 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
/// <summary>
/// This componenet makes it possible to connect IPointables in the
/// inspector to Unity Events that are broadcast on IPointable events.
/// </summary>
public class PointableUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(IPointable))]
private MonoBehaviour _pointable;
private IPointable Pointable;
[SerializeField]
private UnityEvent _whenHover;
[SerializeField]
private UnityEvent _whenUnhover;
[SerializeField]
private UnityEvent _whenSelect;
[SerializeField]
private UnityEvent _whenUnselect;
[SerializeField]
private UnityEvent _whenMove;
public UnityEvent WhenHover => _whenHover;
public UnityEvent WhenUnhover => _whenUnhover;
public UnityEvent WhenSelect => _whenSelect;
public UnityEvent WhenUnselect => _whenUnselect;
public UnityEvent WhenMove => _whenMove;
protected bool _started = false;
protected virtual void Awake()
{
Pointable = _pointable as IPointable;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(Pointable);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
Pointable.OnPointerEvent += HandlePointerEvent;
}
}
protected virtual void OnDisable()
{
if (_started)
{
Pointable.OnPointerEvent -= HandlePointerEvent;
}
}
private void HandlePointerEvent(PointerArgs args)
{
switch (args.PointerEvent)
{
case PointerEvent.Hover:
_whenHover.Invoke();
break;
case PointerEvent.Unhover:
_whenUnhover.Invoke();
break;
case PointerEvent.Select:
_whenSelect.Invoke();
break;
case PointerEvent.Unselect:
_whenUnselect.Invoke();
break;
case PointerEvent.Move:
_whenMove.Invoke();
break;
}
}
#region Inject
public void InjectAllPointableUnityEventWrapper(IPointable pointable)
{
InjectPointable(pointable);
}
public void InjectPointable(IPointable pointable)
{
_pointable = pointable as MonoBehaviour;
Pointable = pointable;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,92 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Oculus.Interaction
{
public class SelectorUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(ISelector))]
private MonoBehaviour _selector;
private ISelector Selector;
[SerializeField]
private UnityEvent _whenSelected;
[SerializeField]
private UnityEvent _whenUnselected;
public UnityEvent WhenSelected => _whenSelected;
public UnityEvent WhenUnselected => _whenUnselected;
protected bool _started = false;
protected virtual void Awake()
{
Selector = _selector as ISelector;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(Selector);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
Selector.WhenSelected += HandleSelected;
Selector.WhenUnselected += HandleUnselected;
}
}
protected virtual void OnDisable()
{
if (_started)
{
Selector.WhenSelected -= HandleSelected;
Selector.WhenUnselected -= HandleUnselected;
}
}
private void HandleSelected()
{
_whenSelected.Invoke();
}
private void HandleUnselected()
{
_whenUnselected.Invoke();
}
#region Inject
public void InjectAllSelectorUnityEventWrapper(ISelector selector)
{
InjectSelector(selector);
}
public void InjectSelector(ISelector selector)
{
_selector = selector as MonoBehaviour;
Selector = selector;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,57 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace Oculus.Interaction
{
/// <summary>
/// Override Toggle to clear state on drag while still bubbling events up through
/// the hierarchy. Particularly useful for buttons inside of scroll views.
/// </summary>
public class ToggleDeselect : Toggle
{
[SerializeField]
private bool _clearStateOnDrag = false;
public bool ClearStateOnDrag
{
get
{
return _clearStateOnDrag;
}
set
{
_clearStateOnDrag = value;
}
}
public void OnBeginDrag(PointerEventData pointerEventData)
{
if (!_clearStateOnDrag)
{
return;
}
InstantClearState();
DoStateTransition(SelectionState.Normal, true);
ExecuteEvents.ExecuteHierarchy(
transform.parent.gameObject,
pointerEventData,
ExecuteEvents.beginDragHandler
);
}
}
}

View File

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

View File

@@ -0,0 +1,109 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
namespace Oculus.Interaction
{
/// <summary>
/// This component makes it possible to connect Transformables in the
/// inspector to Unity Events that are invoked on Transformable Updates
/// </summary>
public class TransformableUnityEventWrapper : MonoBehaviour
{
[SerializeField, Interface(typeof(ITransformable))]
private MonoBehaviour _transformable;
private ITransformable Transformable { get; set; }
[SerializeField]
private UnityEvent _onAdd;
[SerializeField]
private UnityEvent _onRemove;
[SerializeField]
private UnityEvent _onTransfer;
[SerializeField]
private UnityEvent _onUpdate;
public UnityEvent OnAdd => _onAdd;
public UnityEvent OnRemove => _onRemove;
public UnityEvent OnTransfer => _onTransfer;
public UnityEvent OnUpdate => _onUpdate;
protected bool _started = false;
protected virtual void Awake()
{
Transformable = _transformable as ITransformable;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(Transformable);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
Transformable.WhenTransformableUpdated += HandleWhenTransformableUpdated;
}
}
protected virtual void OnDisable()
{
if (_started)
{
Transformable.WhenTransformableUpdated -= HandleWhenTransformableUpdated;
}
}
private void HandleWhenTransformableUpdated(TransformableArgs args)
{
switch (args.TransformableEvent)
{
case TransformableEvent.Add:
_onAdd.Invoke();
break;
case TransformableEvent.Update:
break;
case TransformableEvent.Remove:
_onRemove.Invoke();
break;
case TransformableEvent.Transfer:
_onTransfer.Invoke();
break;
default:
break;
}
}
#region Inject
public void InjectAllTransformableUnityEventWrapper(ITransformable transformable)
{
InjectTransformable(transformable);
}
public void InjectTransformable(ITransformable transformable)
{
_transformable = transformable as MonoBehaviour;
Transformable = transformable;
}
#endregion
}
}

View File

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

View File

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

View File

@@ -0,0 +1,203 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Oculus.Interaction.UnityCanvas
{
public class CanvasCylinder : CanvasRenderTextureMesh
{
[Serializable]
public struct MeshGenerationSettings
{
[Delayed]
public float VerticesPerDegree;
[Delayed]
public int MaxHorizontalResolution;
[Delayed]
public int MaxVerticalResolution;
}
public const int MIN_RESOLUTION = 2;
[Tooltip("The radius of the cylinder that the Canvas texture is projected onto.")]
[Delayed]
[SerializeField]
private float _curveRadius = 1;
[SerializeField]
private MeshGenerationSettings _meshGeneration = new MeshGenerationSettings()
{
VerticesPerDegree = 1.4f,
MaxHorizontalResolution = 128,
MaxVerticalResolution = 32
};
protected override OVROverlay.OverlayShape OverlayShape => OVROverlay.OverlayShape.Cylinder;
#if UNITY_EDITOR
protected virtual void OnValidate()
{
_curveRadius = Mathf.Max(0.01f, _curveRadius);
_meshGeneration.MaxHorizontalResolution = Mathf.Max(MIN_RESOLUTION,
_meshGeneration.MaxHorizontalResolution);
_meshGeneration.MaxVerticalResolution = Mathf.Max(MIN_RESOLUTION,
_meshGeneration.MaxVerticalResolution);
_meshGeneration.VerticesPerDegree = Mathf.Max(0, _meshGeneration.VerticesPerDegree);
if (Application.isPlaying && _started)
{
EditorApplication.delayCall += () =>
{
UpdateImposter();
};
}
}
#endif
public float CurveRadius
{
get
{
return _curveRadius;
}
set
{
if (_curveRadius == value)
{
return;
}
_curveRadius = value;
if (isActiveAndEnabled && Application.isPlaying)
{
UpdateImposter();
}
}
}
protected override void UpdateOverlayPositionAndScale()
{
if (_overlay == null)
{
return;
}
var resolution = _canvasRenderTexture.GetBaseResolutionToUse();
_overlay.transform.localPosition = new Vector3(0, 0, -_curveRadius) - _runtimeOffset;
_overlay.transform.localScale = new Vector3(_canvasRenderTexture.PixelsToUnits(resolution.x),
_canvasRenderTexture.PixelsToUnits(resolution.y),
_curveRadius);
}
protected override Vector3 MeshInverseTransform(Vector3 localPosition)
{
float angle = Mathf.Atan2(localPosition.x, localPosition.z + _curveRadius);
float x = angle * _curveRadius;
float y = localPosition.y;
return new Vector3(x, y);
}
protected override void GenerateMesh(out List<Vector3> verts,
out List<int> tris,
out List<Vector2> uvs)
{
verts = new List<Vector3>();
tris = new List<int>();
uvs = new List<Vector2>();
var resolution = _canvasRenderTexture.GetBaseResolutionToUse();
float xPos = _canvasRenderTexture.PixelsToUnits(Mathf.RoundToInt(resolution.x)) * 0.5f;
float xNeg = -xPos;
float yPos = _canvasRenderTexture.PixelsToUnits(Mathf.RoundToInt(resolution.y)) * 0.5f;
float yNeg = -yPos;
int horizontalResolution = Mathf.Max(2,
Mathf.RoundToInt(_meshGeneration.VerticesPerDegree * Mathf.Rad2Deg * xPos /
_curveRadius));
int verticalResolution =
Mathf.Max(2, Mathf.RoundToInt(horizontalResolution * yPos / xPos));
horizontalResolution = Mathf.Clamp(horizontalResolution, 2,
_meshGeneration.MaxHorizontalResolution);
verticalResolution = Mathf.Clamp(verticalResolution, 2,
_meshGeneration.MaxVerticalResolution);
Vector3 getCurvedPoint(float u, float v)
{
float x = Mathf.Lerp(xNeg, xPos, u);
float y = Mathf.Lerp(yNeg, yPos, v);
float angle = x / _curveRadius;
Vector3 point;
point.x = Mathf.Sin(angle) * _curveRadius;
point.y = y;
point.z = Mathf.Cos(angle) * _curveRadius - _curveRadius;
return point;
}
for (int y = 0; y < verticalResolution; y++)
{
for (int x = 0; x < horizontalResolution; x++)
{
float u = x / (horizontalResolution - 1.0f);
float v = y / (verticalResolution - 1.0f);
verts.Add(getCurvedPoint(u, v));
uvs.Add(new Vector2(u, v));
}
}
for (int y = 0; y < verticalResolution - 1; y++)
{
for (int x = 0; x < horizontalResolution - 1; x++)
{
int v00 = x + y * horizontalResolution;
int v10 = v00 + 1;
int v01 = v00 + horizontalResolution;
int v11 = v00 + 1 + horizontalResolution;
tris.Add(v00);
tris.Add(v11);
tris.Add(v10);
tris.Add(v00);
tris.Add(v01);
tris.Add(v11);
}
}
}
#region Inject
public void InjectAllCanvasCylinder(CanvasRenderTexture canvasRenderTexture,
float curveRadius)
{
InjectAllCanvasRenderTextureMesh(canvasRenderTexture);
InjectCurveRadius(curveRadius);
}
public void InjectCurveRadius(float curveRadius)
{
_curveRadius = curveRadius;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,85 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace Oculus.Interaction.UnityCanvas
{
public class CanvasRect : CanvasRenderTextureMesh
{
protected override OVROverlay.OverlayShape OverlayShape => OVROverlay.OverlayShape.Quad;
protected override void UpdateOverlayPositionAndScale()
{
if (_overlay == null)
{
return;
}
var resolution = _canvasRenderTexture.GetBaseResolutionToUse();
_overlay.transform.localPosition = -_runtimeOffset;
_overlay.transform.localScale = new Vector3(_canvasRenderTexture.PixelsToUnits(resolution.x),
_canvasRenderTexture.PixelsToUnits(resolution.y),
1);
}
protected override Vector3 MeshInverseTransform(Vector3 localPosition)
{
return localPosition;
}
protected override void GenerateMesh(out List<Vector3> verts,
out List<int> tris,
out List<Vector2> uvs)
{
verts = new List<Vector3>();
tris = new List<int>();
uvs = new List<Vector2>();
var resolution = _canvasRenderTexture.GetBaseResolutionToUse();
float xPos = _canvasRenderTexture.PixelsToUnits(Mathf.RoundToInt(resolution.x)) * 0.5f;
float xNeg = -xPos;
float yPos = _canvasRenderTexture.PixelsToUnits(Mathf.RoundToInt(resolution.y)) * 0.5f;
float yNeg = -yPos;
verts.Add(new Vector3(xNeg, yNeg, 0));
verts.Add(new Vector3(xNeg, yPos, 0));
verts.Add(new Vector3(xPos, yPos, 0));
verts.Add(new Vector3(xPos, yNeg, 0));
tris.Add(0);
tris.Add(1);
tris.Add(2);
tris.Add(0);
tris.Add(2);
tris.Add(3);
uvs.Add(new Vector2(0, 0));
uvs.Add(new Vector2(0, 1));
uvs.Add(new Vector2(1, 1));
uvs.Add(new Vector2(1, 0));
}
#region Inject
public void InjectAllCanvasRect(CanvasRenderTexture canvasRenderTexture)
{
InjectAllCanvasRenderTextureMesh(canvasRenderTexture);
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,448 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.EventSystems;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Oculus.Interaction.UnityCanvas
{
[RequireComponent(typeof(Canvas))]
[DisallowMultipleComponent]
public class CanvasRenderTexture : UIBehaviour
{
public enum DriveMode
{
Auto,
Manual
}
public const int DEFAULT_UI_LAYERMASK = 1 << 5; //Hardcoded as the UI layer in Unity.
private static readonly Vector2Int DEFAULT_TEXTURE_RES = new Vector2Int(128, 128);
[Tooltip("If you need extra resolution, you can use this as a whole-integer multiplier of the final resolution used to render the texture.")]
[Range(1, 3)]
[Delayed]
[SerializeField]
private int _renderScale = 1;
[SerializeField]
private DriveMode _dimensionsDriveMode = DriveMode.Auto;
[Tooltip("The exact pixel resolution of the texture used for interface rendering. If set to auto this will take the size of the attached " +
"RectTransform into consideration, in addition to the configured pixel-to-meter ratio.")]
[Delayed]
[SerializeField]
private Vector2Int _resolution = DEFAULT_TEXTURE_RES;
[SerializeField]
private int _pixelsPerUnit = 100;
[SerializeField]
private RenderingMode _renderingMode = RenderingMode.AlphaCutout;
[Tooltip("Whether or not mip-maps should be auto-generated for the texture. Can help aliasing if the texture can be " +
"viewed from many difference distances.")]
[SerializeField]
private bool _generateMipMaps = false;
[Tooltip(
"Requires MSAA. Provides limited transparency useful for anti-aliasing soft edges of UI elements.")]
[SerializeField]
private bool _useAlphaToMask = true;
[Range(0, 1)]
[SerializeField]
private float _alphaCutoutThreshold = 0.5f;
[Tooltip(
"Uses a more expensive image sampling technique for improved quality at the cost of performance.")]
[SerializeField]
protected bool _enableSuperSampling = true;
[Tooltip(
"Attempts to anti-alias the edges of the underlay by using alpha blending. Can cause borders of " +
"darkness around partially transparent objects.")]
[SerializeField]
private bool _doUnderlayAntiAliasing = false;
[Tooltip(
"OVR Layers can provide a buggy or less ideal workflow while in the editor. This option allows you " +
"emulate the layer rendering while in the editor, while still using the OVR Layer rendering in a build.")]
[SerializeField]
private bool _emulateWhileInEditor = true;
[Header("Rendering Settings")]
[Tooltip("The layers to render when the rendering texture is created. All child renderers should be part of this mask.")]
[SerializeField]
private LayerMask _renderingLayers = DEFAULT_UI_LAYERMASK;
[SerializeField, Optional]
private Material _defaultUIMaterial = null;
public RenderingMode RenderingMode => _renderingMode;
public LayerMask RenderingLayers => _renderingLayers;
public bool UseAlphaToMask => _useAlphaToMask;
public bool DoUnderlayAntiAliasing => _doUnderlayAntiAliasing;
public bool EnableSuperSampling => _enableSuperSampling;
public float AlphaCutoutThreshold => _alphaCutoutThreshold;
public Action<Texture> OnUpdateRenderTexture = delegate { };
public bool UseEditorEmulation()
{
return Application.isEditor ? _emulateWhileInEditor : false;
}
public int RenderScale
{
get
{
return _renderScale;
}
set
{
if (_renderScale < 1 || _renderScale > 3)
{
throw new ArgumentException($"Render scale must be between 1 and 3, but was {value}");
}
if (_renderScale == value)
{
return;
}
_renderScale = value;
if (isActiveAndEnabled && Application.isPlaying)
{
UpdateCamera();
}
}
}
public Material DefaultUIMaterial => _defaultUIMaterial;
public Camera OverlayCamera => _camera;
public Texture Texture => _tex;
private RenderTexture _tex;
private Camera _camera;
protected bool _started = false;
public Vector2Int CalcAutoResolution()
{
var rectTransform = GetComponent<RectTransform>();
if (rectTransform == null)
{
return DEFAULT_TEXTURE_RES;
}
Vector2 size = rectTransform.sizeDelta;
size.x *= rectTransform.lossyScale.x;
size.y *= rectTransform.lossyScale.y;
int x = Mathf.RoundToInt(UnitsToPixels(size.x));
int y = Mathf.RoundToInt(UnitsToPixels(size.y));
return new Vector2Int(Mathf.Max(x, 1), Mathf.Max(y, 1));
}
public Vector2Int GetBaseResolutionToUse()
{
if (_dimensionsDriveMode == DriveMode.Auto)
{
return CalcAutoResolution();
}
else
{
return _resolution;
}
}
public Vector2Int GetScaledResolutionToUse()
{
return new Vector2Int(
Mathf.RoundToInt(GetBaseResolutionToUse().x * (float)_renderScale),
Mathf.RoundToInt(GetBaseResolutionToUse().y * (float)_renderScale)
);
}
public float PixelsToUnits(float pixels)
{
return (1f / _pixelsPerUnit) * pixels;
}
public float UnitsToPixels(float units)
{
return _pixelsPerUnit * units;
}
public bool ShouldUseOVROverlay
{
get
{
switch (_renderingMode)
{
case RenderingMode.OVR_Underlay:
case RenderingMode.OVR_Overlay:
return !UseEditorEmulation();
default:
return false;
}
}
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (Application.isPlaying && _started)
{
EditorApplication.delayCall += () =>
{
UpdateCamera();
};
}
}
#endif
protected override void OnRectTransformDimensionsChange()
{
base.OnRectTransformDimensionsChange();
if (_started)
{
UpdateCamera();
}
}
protected override void Start()
{
this.BeginStart(ref _started, base.Start);
this.EndStart(ref _started);
}
protected override void OnEnable()
{
base.OnEnable();
if (_started)
{
if (_defaultUIMaterial == null)
{
_defaultUIMaterial = new Material(Shader.Find("UI/Default (Overlay)"));
}
UpdateCamera();
}
}
protected override void OnDisable()
{
if (_started)
{
if (_camera?.gameObject != null)
{
Destroy(_camera.gameObject);
}
if (_tex != null)
{
DestroyImmediate(_tex);
}
}
base.OnDisable();
}
protected void UpdateCamera()
{
Profiler.BeginSample("InterfaceRenderer.UpdateCamera");
try
{
if (_camera == null)
{
GameObject cameraObj = CreateChildObject("__Camera");
_camera = cameraObj.AddComponent<Camera>();
_camera.orthographic = true;
_camera.nearClipPlane = -0.1f;
_camera.farClipPlane = 0.1f;
_camera.backgroundColor = new Color(0, 0, 0, 0);
_camera.clearFlags = CameraClearFlags.SolidColor;
}
UpdateRenderTexture();
UpdateOrthoSize();
UpdateCameraCullingMask();
}
finally
{
Profiler.EndSample();
}
}
protected void UpdateRenderTexture()
{
Profiler.BeginSample("InterfaceRenderer.UpdateRenderTexture");
try
{
var resolutionToUse = GetScaledResolutionToUse();
//Never generate mips when using OVROverlay, they are not used
bool desiredMipsSetting = ShouldUseOVROverlay ? false : _generateMipMaps;
if (_tex == null ||
_tex.width != resolutionToUse.x ||
_tex.height != resolutionToUse.y ||
_tex.autoGenerateMips != desiredMipsSetting)
{
if (_tex != null)
{
_camera.targetTexture = null;
DestroyImmediate(_tex);
}
_tex = new RenderTexture(resolutionToUse.x, resolutionToUse.y, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
_tex.filterMode = FilterMode.Bilinear;
_tex.autoGenerateMips = desiredMipsSetting;
_camera.targetTexture = _tex;
OnUpdateRenderTexture(_tex);
}
}
finally
{
Profiler.EndSample();
}
}
private void UpdateOrthoSize()
{
if (_camera != null)
{
_camera.orthographicSize = PixelsToUnits(GetBaseResolutionToUse().y) * 0.5f;
}
}
private void UpdateCameraCullingMask()
{
if (_camera != null)
{
_camera.cullingMask = _renderingLayers.value;
}
}
protected GameObject CreateChildObject(string name)
{
GameObject obj = new GameObject(name);
obj.transform.SetParent(transform);
obj.transform.localPosition = Vector3.zero;
obj.transform.localRotation = Quaternion.identity;
obj.transform.localScale = Vector3.one;
return obj;
}
public static class Properties
{
public static readonly string DimensionDriveMode = nameof(_dimensionsDriveMode);
public static readonly string Resolution = nameof(_resolution);
public static readonly string RenderScale = nameof(_renderScale);
public static readonly string PixelsPerUnit = nameof(_pixelsPerUnit);
public static readonly string RenderLayers = nameof(_renderingLayers);
public static readonly string RenderingMode = nameof(_renderingMode);
public static readonly string GenerateMips = nameof(_generateMipMaps);
public static readonly string UseAlphaToMask = nameof(_useAlphaToMask);
public static readonly string AlphaCutoutThreshold = nameof(_alphaCutoutThreshold);
public static readonly string UseExpensiveSuperSample = nameof(_enableSuperSampling);
public static readonly string DoUnderlayAA = nameof(_doUnderlayAntiAliasing);
public static readonly string EmulateWhileInEditor = nameof(_emulateWhileInEditor);
public static readonly string DefaultUIMaterial = nameof(_defaultUIMaterial);
}
#region Inject
public void InjectAllCanvasRenderTexture(int pixelsPerUnit,
int renderScale,
LayerMask renderingLayers,
RenderingMode renderingMode,
bool doUnderlayAntiAliasing,
float alphaCutoutThreshold,
bool useAlphaToMask)
{
InjectPixelsPerUnit(pixelsPerUnit);
InjectRenderScale(renderScale);
InjectRenderingLayers(renderingLayers);
InjectRenderingMode(renderingMode);
InjectDoUnderlayAntiAliasing(doUnderlayAntiAliasing);
InjectAlphaCutoutThreshold(alphaCutoutThreshold);
InjectUseAlphaToMask(useAlphaToMask);
}
public void InjectPixelsPerUnit(int pixelsPerUnit)
{
_pixelsPerUnit = pixelsPerUnit;
}
public void InjectRenderScale(int renderScale)
{
_renderScale = renderScale;
}
public void InjectRenderingMode(RenderingMode renderingMode)
{
_renderingMode = renderingMode;
}
public void InjectRenderingLayers(LayerMask renderingLayers)
{
_renderingLayers = renderingLayers;
}
public void InjectDoUnderlayAntiAliasing(bool doUnderlayAntiAliasing)
{
_doUnderlayAntiAliasing = doUnderlayAntiAliasing;
}
public void InjectUseAlphaToMask(bool useAlphaToMask)
{
_useAlphaToMask = useAlphaToMask;
}
public void InjectAlphaCutoutThreshold(float alphaCutoutThreshold)
{
_alphaCutoutThreshold = alphaCutoutThreshold;
}
public void InjectOptionalDefaultUIMaterial(Material defaultUIMaterial)
{
_defaultUIMaterial = defaultUIMaterial;
}
public void InjectOptionalGenerateMipMaps(bool generateMipMaps)
{
_generateMipMaps = generateMipMaps;
}
#endregion
}
}

View File

@@ -0,0 +1,16 @@
fileFormatVersion: 2
guid: b7ecff74e52843a41ab3a441ac81379e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- _defaultUIMaterial: {fileID: 2100000, guid: bc9f80a2ae0e0a24d870176e48ab1b93,
type: 2}
- _imposterMaterial: {fileID: 2100000, guid: 5c093e4058df12042a75bcb967ca1554, type: 2}
- _depthQuadMaterial: {fileID: 2100000, guid: c7cda63c3ebb50847950fc3a925d784f,
type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,295 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Profiling;
namespace Oculus.Interaction.UnityCanvas
{
[DisallowMultipleComponent]
public abstract class CanvasRenderTextureMesh : MonoBehaviour
{
private static readonly int MainTexShaderID = Shader.PropertyToID("_MainTex");
[SerializeField]
protected CanvasRenderTexture _canvasRenderTexture;
[SerializeField, Optional]
private MeshCollider _meshCollider = null;
[Tooltip("If non-zero it will cause the position of the canvas to be offset by this amount at runtime, while " +
"the renderer will remain where it was at edit time. This can be used to prevent the two representations from overlapping.")]
[SerializeField]
protected Vector3 _runtimeOffset = new Vector3(0, 0, 0);
protected OVROverlay _overlay;
private Material _material = null;
private MeshFilter _imposterFilter;
private MeshRenderer _imposterRenderer;
protected bool _started = false;
protected abstract Vector3 MeshInverseTransform(Vector3 localPosition);
protected abstract void GenerateMesh(out List<Vector3> verts, out List<int> tris, out List<Vector2> uvs);
protected abstract void UpdateOverlayPositionAndScale();
protected abstract OVROverlay.OverlayShape OverlayShape { get; }
/// <summary>
/// Transform a position in world space relative to the imposter to an associated position relative
/// to the original canvas in world space.
/// </summary>
public Vector3 ImposterToCanvasTransformPoint(Vector3 worldPosition)
{
Vector3 localToImposter =
_imposterFilter.transform.InverseTransformPoint(worldPosition);
Vector3 canvasLocalPosition = MeshInverseTransform(localToImposter);
Vector3 transformedWorldPosition = _canvasRenderTexture.transform.TransformPoint(canvasLocalPosition / _canvasRenderTexture.transform.lossyScale.x);
return transformedWorldPosition;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(_canvasRenderTexture);
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
CreateMaterial();
UpdateImposter();
_canvasRenderTexture.OnUpdateRenderTexture += HandleUpdateRenderTexture;
if (_canvasRenderTexture.Texture != null)
{
HandleUpdateRenderTexture(_canvasRenderTexture.Texture);
}
}
}
protected virtual void OnDisable()
{
if (_started)
{
_canvasRenderTexture.OnUpdateRenderTexture -= HandleUpdateRenderTexture;
if (_material != null)
{
Destroy(_material);
_material = null;
}
}
}
protected virtual void HandleUpdateRenderTexture(Texture texture)
{
if (_imposterRenderer != null)
{
_imposterRenderer.material = _material;
var block = new MaterialPropertyBlock();
_imposterRenderer.GetPropertyBlock(block);
block.SetTexture(MainTexShaderID, _canvasRenderTexture.Texture);
if (_canvasRenderTexture.RenderingMode == RenderingMode.AlphaCutout &&
!_canvasRenderTexture.UseAlphaToMask)
{
block.SetFloat("_Cutoff", _canvasRenderTexture.AlphaCutoutThreshold);
}
if (_canvasRenderTexture.RenderingMode == RenderingMode.OVR_Underlay &&
_canvasRenderTexture.UseEditorEmulation())
{
block.SetFloat("_Cutoff", 0.5f);
}
_imposterRenderer.SetPropertyBlock(block);
}
UpdateOverlay();
UpdateImposter();
}
protected void UpdateImposter()
{
Profiler.BeginSample("InterfaceRenderer.UpdateImposter");
try
{
if (_imposterFilter == null || _imposterRenderer == null)
{
_imposterFilter = gameObject.AddComponent<MeshFilter>();
_imposterRenderer = gameObject.AddComponent<MeshRenderer>();
}
else
{
_imposterRenderer.gameObject.SetActive(true);
}
if (_material != null)
{
_imposterRenderer.material = _material;
}
GenerateMesh(out List<Vector3> verts, out List<int> tris, out List<Vector2> uvs);
Mesh mesh = new Mesh();
mesh.SetVertices(verts);
mesh.SetUVs(0, uvs);
mesh.SetTriangles(tris, 0);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
_imposterFilter.mesh = mesh;
if (_meshCollider != null)
{
_meshCollider.sharedMesh = _imposterFilter.sharedMesh;
}
}
finally
{
Profiler.EndSample();
}
}
protected void CreateMaterial()
{
Profiler.BeginSample("InterfaceRenderer.UpdateMaterial");
try
{
string shaderName;
switch (_canvasRenderTexture.RenderingMode)
{
case RenderingMode.AlphaBlended:
shaderName = "Hidden/Imposter_AlphaBlended";
break;
case RenderingMode.AlphaCutout:
if (_canvasRenderTexture.UseAlphaToMask)
{
shaderName = "Hidden/Imposter_AlphaToMask";
}
else
{
shaderName = "Hidden/Imposter_AlphaCutout";
}
break;
case RenderingMode.Opaque:
shaderName = "Hidden/Imposter_Opaque";
break;
case RenderingMode.OVR_Underlay:
if (_canvasRenderTexture.UseEditorEmulation())
{
shaderName = "Hidden/Imposter_AlphaCutout";
}
else if (_canvasRenderTexture.DoUnderlayAntiAliasing)
{
shaderName = "Hidden/Imposter_Underlay_AA";
}
else
{
shaderName = "Hidden/Imposter_Underlay";
}
break;
case RenderingMode.OVR_Overlay:
shaderName = "Hidden/Imposter_AlphaCutout";
break;
default:
throw new Exception();
}
_material = new Material(Shader.Find(shaderName));
}
finally
{
Profiler.EndSample();
}
}
protected void UpdateOverlay()
{
Profiler.BeginSample("InterfaceRenderer.UpdateOverlay");
try
{
if (!_canvasRenderTexture.ShouldUseOVROverlay)
{
_overlay?.gameObject?.SetActive(false);
return;
}
if (_overlay == null)
{
GameObject overlayObj = CreateChildObject("__Overlay");
_overlay = overlayObj.AddComponent<OVROverlay>();
_overlay.isAlphaPremultiplied = !Application.isMobilePlatform;
}
else
{
_overlay.gameObject.SetActive(true);
}
bool useUnderlayRendering = _canvasRenderTexture.RenderingMode == RenderingMode.OVR_Underlay;
_overlay.textures = new Texture[1] { _canvasRenderTexture.Texture };
_overlay.noDepthBufferTesting = useUnderlayRendering;
_overlay.currentOverlayType = useUnderlayRendering ? OVROverlay.OverlayType.Underlay : OVROverlay.OverlayType.Overlay;
_overlay.currentOverlayShape = OverlayShape;
_overlay.useExpensiveSuperSample = _canvasRenderTexture.EnableSuperSampling;
UpdateOverlayPositionAndScale();
}
finally
{
Profiler.EndSample();
}
}
protected GameObject CreateChildObject(string name)
{
GameObject obj = new GameObject(name);
obj.transform.SetParent(transform);
obj.transform.localPosition = Vector3.zero;
obj.transform.localRotation = Quaternion.identity;
obj.transform.localScale = Vector3.one;
return obj;
}
#region Inject
public void InjectAllCanvasRenderTextureMesh(CanvasRenderTexture canvasRenderTexture)
{
InjectCanvasRenderTexture(canvasRenderTexture);
}
public void InjectCanvasRenderTexture(CanvasRenderTexture canvasRenderTexture)
{
_canvasRenderTexture = canvasRenderTexture;
}
public void InjectOptionalMeshCollider(MeshCollider meshCollider)
{
_meshCollider = meshCollider;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,31 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
namespace Oculus.Interaction.UnityCanvas
{
public enum RenderingMode
{
[InspectorName("Alpha-Blended")]
AlphaBlended = 0,
[InspectorName("Alpha-Cutout")]
AlphaCutout,
[InspectorName("Opaque")]
Opaque,
[InspectorName("OVR/Overlay")]
OVR_Overlay = 100,
[InspectorName("OVR/Underlay")]
OVR_Underlay
}
}

View File

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

View File

@@ -0,0 +1,35 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using UnityEngine;
namespace Oculus.Interaction.UnityCanvas
{
/// <summary>
/// Dropdowns menus in Unity are automatically set to sorting order 30000, which
/// does not play nicely with world space UIs.
/// Meant to be used in conjunction with an EventTrigger on a given Dropdown, this component
/// can be used to set a different sorting order on this and any child canvas.
/// </summary>
public class UpdateCanvasSortingOrder : MonoBehaviour
{
public void SetCanvasSortingOrder(int sortingOrder)
{
Canvas[] canvases = transform.parent.gameObject.GetComponentsInChildren<Canvas>();
if (canvases == null) return;
foreach (Canvas canvas in canvases)
{
canvas.sortingOrder = sortingOrder;
}
}
}
}

View File

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

View File

@@ -0,0 +1,35 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
namespace Oculus.Interaction
{
public static class UnityInfo
{
public static bool IsEditor()
{
#if UNITY_EDITOR
return true;
#else
return false;
#endif
}
public static bool Version_2020_3_Or_Newer()
{
#if UNITY_2020_3_OR_NEWER
return true;
#else
return false;
#endif
}
}
}

View File

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