clean project
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d2705674196dfc4da9c25fbacda72d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b78f8e52fe10fd9499c5e5c8b3f953fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1464721f2283eb14e94a33e812b47be4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cf00a93483fd1b4ba357bf6f764d6e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bedaac29a943f844a7074b53c8bdf9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ffe41fe81087fa41a2062cc69b99615
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2518c50cb3fc6a6458d4b743c2f69c7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5626a0b1dc955a43be59ce7ea116678
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2f8f6e9e6f3e114b9bf9a57c2160615
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de76f7169412b8f4896235a1585d8939
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af559e57b81a946479f0ad978a1a3763
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f5531e0e19dff046a5b9f58ee68fe2e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86ce14e80f612a041be6385c43fed586
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85ef10d17088b3c4cad9a5d13887b157
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2025423b67857c349bf8cf435762b5cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e17f00312f4fea429367cb5b305689d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e5de7ab187e8dc47a0f654ad1e1107a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f40996cdf2361b8478af26d6e2630d42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
35
Assets/Oculus/Interaction/Runtime/Scripts/Unity/UnityInfo.cs
Normal file
35
Assets/Oculus/Interaction/Runtime/Scripts/Unity/UnityInfo.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59709ed6d58f88541a420b6ef3165513
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user