Added VR libraries
This commit is contained in:
514
Assets/GoogleVR/Scripts/EventSystem/GvrBasePointer.cs
Normal file
514
Assets/GoogleVR/Scripts/EventSystem/GvrBasePointer.cs
Normal file
@@ -0,0 +1,514 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
/// This abstract class should be implemented for pointer based input, and used with
|
||||
/// the GvrPointerInputModule script.
|
||||
///
|
||||
/// It provides methods called on pointer interaction with in-game objects and UI,
|
||||
/// trigger events, and 'BaseInputModule' class state changes.
|
||||
///
|
||||
/// To have the methods called, an instance of this (implemented) class must be
|
||||
/// registered with the **GvrPointerManager** script in 'Start' by calling
|
||||
/// GvrPointerInputModule.OnPointerCreated.
|
||||
///
|
||||
/// This abstract class should be implemented by pointers doing 1 of 2 things:
|
||||
/// 1. Responding to movement of the users head (Cardboard gaze-based-pointer).
|
||||
/// 2. Responding to the movement of the daydream controller (Daydream 3D pointer).
|
||||
public abstract class GvrBasePointer : MonoBehaviour, IGvrControllerInputDeviceReceiver {
|
||||
public enum RaycastMode {
|
||||
/// Casts a ray from the camera through the target of the pointer.
|
||||
/// This is ideal for reticles that are always rendered on top.
|
||||
/// The object that is selected will always be the object that appears
|
||||
/// underneath the reticle from the perspective of the camera.
|
||||
/// This also prevents the reticle from appearing to "jump" when it starts/stops hitting an object.
|
||||
///
|
||||
/// Recommended for reticles that are always rendered on top such as the GvrReticlePointer
|
||||
/// prefab which is used for cardboard apps.
|
||||
///
|
||||
/// Note: This will prevent the user from pointing around an object to hit something that is out of sight.
|
||||
/// This isn't a problem in a typical use case.
|
||||
///
|
||||
/// When used with the standard daydream controller,
|
||||
/// the hit detection will not account for the laser correctly for objects that are closer to the
|
||||
/// camera than the end of the laser.
|
||||
/// In that case, it is recommended to do one of the following things:
|
||||
///
|
||||
/// 1. Hide the laser.
|
||||
/// 2. Use a full-length laser pointer in Direct mode.
|
||||
/// 3. Use the Hybrid raycast mode.
|
||||
Camera,
|
||||
/// Cast a ray directly from the pointer origin.
|
||||
///
|
||||
/// Recommended for full-length laser pointers.
|
||||
Direct,
|
||||
/// Default method for casting ray.
|
||||
///
|
||||
/// Combines the Camera and Direct raycast modes.
|
||||
/// Uses a Direct ray up until the CameraRayIntersectionDistance, and then switches to use
|
||||
/// a Camera ray starting from the point where the two rays intersect.
|
||||
///
|
||||
/// Recommended for use with the standard settings of the GvrControllerPointer prefab.
|
||||
/// This is the most versatile raycast mode. Like Camera mode, this prevents the reticle
|
||||
/// appearing jumpy. Additionally, it still allows the user to target objects that are close
|
||||
/// to them by using the laser as a visual reference.
|
||||
Hybrid,
|
||||
}
|
||||
|
||||
/// Represents a ray segment for a series of intersecting rays.
|
||||
/// This is useful for Hybrid raycast mode, which uses two sequential rays.
|
||||
public struct PointerRay {
|
||||
/// The ray for this segment of the pointer.
|
||||
public Ray ray;
|
||||
|
||||
/// The distance along the pointer from the origin of the first ray to this ray.
|
||||
public float distanceFromStart;
|
||||
|
||||
/// Distance that this ray extends to.
|
||||
public float distance;
|
||||
}
|
||||
|
||||
/// Determines which raycast mode to use for this raycaster.
|
||||
/// • Camera - Ray is cast from the camera through the pointer.
|
||||
/// • Direct - Ray is cast forward from the pointer.
|
||||
/// • Hybrid - Begins with a Direct ray and transitions to a Camera ray.
|
||||
[Tooltip("Determines which raycast mode to use for this raycaster.\n" +
|
||||
" • Camera - Ray is cast from camera.\n" +
|
||||
" • Direct - Ray is cast from pointer.\n" +
|
||||
" • Hybrid - Transitions from Direct ray to Camera ray.")]
|
||||
public RaycastMode raycastMode = RaycastMode.Hybrid;
|
||||
|
||||
/// Determines the eventCamera for _GvrPointerPhysicsRaycaster_ and _GvrPointerGraphicRaycaster_.
|
||||
/// Additionaly, this is used to control what camera to use when calculating the Camera ray for
|
||||
/// the Hybrid and Camera raycast modes.
|
||||
[Tooltip("Optional: Use a camera other than Camera.main.")]
|
||||
public Camera overridePointerCamera;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// Determines if the rays used for raycasting will be drawn in the editor.
|
||||
[Tooltip("Determines if the rays used for raycasting will be drawn in the editor.")]
|
||||
public bool drawDebugRays = false;
|
||||
#endif // UNITY_EDITOR
|
||||
|
||||
/// Convenience function to access what the pointer is currently hitting.
|
||||
public RaycastResult CurrentRaycastResult {
|
||||
get {
|
||||
return GvrPointerInputModule.CurrentRaycastResult;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Obsolete("Replaced by CurrentRaycastResult.worldPosition")]
|
||||
public Vector3 PointerIntersection {
|
||||
get {
|
||||
RaycastResult raycastResult = CurrentRaycastResult;
|
||||
return raycastResult.worldPosition;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Obsolete("Replaced by CurrentRaycastResult.gameObject != null")]
|
||||
public bool IsPointerIntersecting {
|
||||
get {
|
||||
RaycastResult raycastResult = CurrentRaycastResult;
|
||||
return raycastResult.gameObject != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// This is used to determine if the enterRadius or the exitRadius should be used for the raycast.
|
||||
/// It is set by GvrPointerInputModule and doesn't need to be controlled manually.
|
||||
public bool ShouldUseExitRadiusForRaycast { get; set; }
|
||||
|
||||
/// If ShouldUseExitRadiusForRaycast is true, returns the exitRadius.
|
||||
/// Otherwise, returns the enterRadius.
|
||||
public float CurrentPointerRadius {
|
||||
get {
|
||||
float enterRadius, exitRadius;
|
||||
GetPointerRadius(out enterRadius, out exitRadius);
|
||||
if (ShouldUseExitRadiusForRaycast) {
|
||||
return exitRadius;
|
||||
} else {
|
||||
return enterRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the transform that represents this pointer.
|
||||
/// It is used by GvrBasePointerRaycaster as the origin of the ray.
|
||||
public virtual Transform PointerTransform {
|
||||
get {
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
|
||||
public GvrControllerInputDevice ControllerInputDevice { get; set; }
|
||||
|
||||
/// If true, the trigger was just pressed. This is an event flag:
|
||||
/// it will be true for only one frame after the event happens.
|
||||
/// Defaults to mouse button 0 down on Cardboard or
|
||||
/// ControllerInputDevice.GetButtonDown(TouchPadButton) on Daydream.
|
||||
/// Can be overridden to change the trigger.
|
||||
public virtual bool TriggerDown {
|
||||
get {
|
||||
bool isTriggerDown = Input.GetMouseButtonDown(0);
|
||||
if (ControllerInputDevice != null) {
|
||||
isTriggerDown |=
|
||||
ControllerInputDevice.GetButtonDown(GvrControllerButton.TouchPadButton);
|
||||
}
|
||||
return isTriggerDown;
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the trigger is currently being pressed. This is not
|
||||
/// an event: it represents the trigger's state (it remains true while the trigger is being
|
||||
/// pressed).
|
||||
/// Defaults to mouse button 0 state on Cardboard or
|
||||
/// ControllerInputDevice.GetButton(TouchPadButton) on Daydream.
|
||||
/// Can be overridden to change the trigger.
|
||||
public virtual bool Triggering {
|
||||
get {
|
||||
bool isTriggering = Input.GetMouseButton(0);
|
||||
if (ControllerInputDevice != null) {
|
||||
isTriggering |=
|
||||
ControllerInputDevice.GetButton(GvrControllerButton.TouchPadButton);
|
||||
}
|
||||
return isTriggering;
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the trigger was just released. This is an event flag:
|
||||
/// it will be true for only one frame after the event happens.
|
||||
/// Defaults to mouse button 0 up on Cardboard or
|
||||
/// ControllerInputDevice.GetButtonUp(TouchPadButton) on Daydream.
|
||||
/// Can be overridden to change the trigger.
|
||||
public virtual bool TriggerUp {
|
||||
get {
|
||||
bool isTriggerUp = Input.GetMouseButtonUp(0);
|
||||
if (ControllerInputDevice == null) {
|
||||
isTriggerUp |=
|
||||
ControllerInputDevice.GetButtonUp(GvrControllerButton.TouchPadButton);
|
||||
}
|
||||
return isTriggerUp;
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the user just started touching the touchpad. This is an event flag (it is true
|
||||
/// for only one frame after the event happens, then reverts to false).
|
||||
/// Used by _GvrPointerScrollInput_ to generate OnScroll events using Unity's Event System.
|
||||
/// Defaults to ControllerInputDevice.GetButtonDown(TouchPadTouch), can be overridden to change
|
||||
/// the input source.
|
||||
public virtual bool TouchDown {
|
||||
get {
|
||||
if (ControllerInputDevice == null) {
|
||||
return false;
|
||||
} else {
|
||||
return ControllerInputDevice.GetButtonDown(GvrControllerButton.TouchPadTouch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the user is currently touching the touchpad.
|
||||
/// Used by _GvrPointerScrollInput_ to generate OnScroll events using Unity's Event System.
|
||||
/// Defaults to ControllerInputDevice.GetButton(TouchPadTouch), can be overridden to change
|
||||
/// the input source.
|
||||
public virtual bool IsTouching {
|
||||
get {
|
||||
if (ControllerInputDevice == null) {
|
||||
return false;
|
||||
} else {
|
||||
return ControllerInputDevice.GetButton(GvrControllerButton.TouchPadTouch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the user just stopped touching the touchpad. This is an event flag (it is true
|
||||
/// for only one frame after the event happens, then reverts to false).
|
||||
/// Used by _GvrPointerScrollInput_ to generate OnScroll events using Unity's Event System.
|
||||
/// Defaults to ControllerInputDevice.GetButtonUp(TouchPadTouch), can be overridden to change
|
||||
/// the input source.
|
||||
public virtual bool TouchUp {
|
||||
get {
|
||||
if (ControllerInputDevice == null) {
|
||||
return false;
|
||||
} else {
|
||||
return ControllerInputDevice.GetButtonUp(GvrControllerButton.TouchPadTouch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Position of the current touch, if touching the touchpad.
|
||||
/// If not touching, this is the position of the last touch (when the finger left the touchpad).
|
||||
/// The X and Y range is from 0 to 1.
|
||||
/// (0, 0) is the top left of the touchpad and (1, 1) is the bottom right of the touchpad.
|
||||
/// Used by `GvrPointerScrollInput` to generate OnScroll events using Unity's Event System.
|
||||
/// Defaults to `ControllerInputDevice.TouchPos` but translated to top-left-relative coordinates
|
||||
/// for backwards compatibility. Can be overridden to change the input source.
|
||||
public virtual Vector2 TouchPos {
|
||||
get {
|
||||
if (ControllerInputDevice == null) {
|
||||
return Vector2.zero;
|
||||
} else {
|
||||
Vector2 touchPos = ControllerInputDevice.TouchPos;
|
||||
touchPos.x = (touchPos.x / 2.0f) + 0.5f;
|
||||
touchPos.y = (-touchPos.y / 2.0f) + 0.5f;
|
||||
return touchPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the end point of the pointer when it is MaxPointerDistance away from the origin.
|
||||
public virtual Vector3 MaxPointerEndPoint {
|
||||
get {
|
||||
Transform pointerTransform = PointerTransform;
|
||||
if (pointerTransform == null) {
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
Vector3 maxEndPoint = GetPointAlongPointer(MaxPointerDistance);
|
||||
return maxEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, the pointer will be used for generating input events by _GvrPointerInputModule_.
|
||||
public virtual bool IsAvailable {
|
||||
get {
|
||||
Transform pointerTransform = PointerTransform;
|
||||
if (pointerTransform == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pointerTransform.gameObject.activeInHierarchy;
|
||||
}
|
||||
}
|
||||
|
||||
/// When using the Camera raycast mode, this is used to calculate
|
||||
/// where the ray from the pointer will intersect with the ray from the camera.
|
||||
public virtual float CameraRayIntersectionDistance {
|
||||
get {
|
||||
return MaxPointerDistance;
|
||||
}
|
||||
}
|
||||
|
||||
public Camera PointerCamera {
|
||||
get {
|
||||
if (overridePointerCamera != null) {
|
||||
return overridePointerCamera;
|
||||
}
|
||||
|
||||
return Camera.main;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the max distance from the pointer that raycast hits will be detected.
|
||||
public abstract float MaxPointerDistance { get; }
|
||||
|
||||
/// Called when the pointer is facing a valid GameObject. This can be a 3D
|
||||
/// or UI element.
|
||||
///
|
||||
/// **raycastResult** is the hit detection result for the object being pointed at.
|
||||
/// **isInteractive** is true if the object being pointed at is interactive.
|
||||
public abstract void OnPointerEnter(RaycastResult raycastResult, bool isInteractive);
|
||||
|
||||
/// Called every frame the user is still pointing at a valid GameObject. This
|
||||
/// can be a 3D or UI element.
|
||||
///
|
||||
/// **raycastResult** is the hit detection result for the object being pointed at.
|
||||
/// **isInteractive** is true if the object being pointed at is interactive.
|
||||
public abstract void OnPointerHover(RaycastResult raycastResultResult, bool isInteractive);
|
||||
|
||||
/// Called when the pointer no longer faces an object previously
|
||||
/// intersected with a ray projected from the camera.
|
||||
/// This is also called just before **OnInputModuleDisabled**
|
||||
/// previousObject will be null in this case.
|
||||
///
|
||||
/// **previousObject** is the object that was being pointed at the previous frame.
|
||||
public abstract void OnPointerExit(GameObject previousObject);
|
||||
|
||||
/// Called when a click is initiated.
|
||||
public abstract void OnPointerClickDown();
|
||||
|
||||
/// Called when click is finished.
|
||||
public abstract void OnPointerClickUp();
|
||||
|
||||
/// Return the radius of the pointer. It is used by GvrPointerPhysicsRaycaster when
|
||||
/// searching for valid pointer targets. If a radius is 0, then a ray is used to find
|
||||
/// a valid pointer target. Otherwise it will use a SphereCast.
|
||||
/// The *enterRadius* is used for finding new targets while the *exitRadius*
|
||||
/// is used to see if you are still nearby the object currently pointed at
|
||||
/// to avoid a flickering effect when just at the border of the intersection.
|
||||
///
|
||||
/// NOTE: This is only works with GvrPointerPhysicsRaycaster. To use it with uGUI,
|
||||
/// add 3D colliders to your canvas elements.
|
||||
public abstract void GetPointerRadius(out float enterRadius, out float exitRadius);
|
||||
|
||||
/// Returns a point in worldspace a specified distance along the pointer.
|
||||
/// What this point will be is different depending on the raycastMode.
|
||||
///
|
||||
/// Because raycast modes differ, use this function instead of manually calculating a point
|
||||
/// projected from the pointer.
|
||||
public Vector3 GetPointAlongPointer(float distance) {
|
||||
PointerRay pointerRay = GetRayForDistance(distance);
|
||||
return pointerRay.ray.GetPoint(distance - pointerRay.distanceFromStart);
|
||||
}
|
||||
|
||||
/// Returns the ray used for projecting points out of the pointer for the given distance.
|
||||
/// In Hybrid raycast mode, the ray will be different depending upon the distance.
|
||||
/// In Camera or Direct raycast mode, the ray will always be the same.
|
||||
public PointerRay GetRayForDistance(float distance) {
|
||||
PointerRay result = new PointerRay();
|
||||
|
||||
if (raycastMode == RaycastMode.Hybrid) {
|
||||
float directDistance = CameraRayIntersectionDistance;
|
||||
if (distance < directDistance) {
|
||||
result = CalculateHybridRay(this, RaycastMode.Direct);
|
||||
} else {
|
||||
result = CalculateHybridRay(this, RaycastMode.Camera);
|
||||
}
|
||||
} else {
|
||||
result = CalculateRay(this, raycastMode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Calculates the ray for a given Raycast mode.
|
||||
/// Will throw an exception if the raycast mode Hybrid is passed in.
|
||||
/// If you need to calculate the ray for the direct or camera segment of the Hybrid raycast,
|
||||
/// use CalculateHybridRay instead.
|
||||
public static PointerRay CalculateRay(GvrBasePointer pointer, RaycastMode mode) {
|
||||
PointerRay result = new PointerRay();
|
||||
|
||||
if (pointer == null || !pointer.IsAvailable) {
|
||||
Debug.LogError("Cannot calculate ray when the pointer isn't available.");
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform pointerTransform = pointer.PointerTransform;
|
||||
|
||||
if (pointerTransform == null) {
|
||||
Debug.LogError("Cannot calculate ray when pointerTransform is null.");
|
||||
return result;
|
||||
}
|
||||
|
||||
result.distance = pointer.MaxPointerDistance;
|
||||
|
||||
switch (mode) {
|
||||
case RaycastMode.Camera:
|
||||
Camera camera = pointer.PointerCamera;
|
||||
if (camera == null) {
|
||||
Debug.LogError("Cannot calculate ray because pointer.PointerCamera is null." +
|
||||
"To fix this, either tag a Camera as \"MainCamera\" or set overridePointerCamera.");
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 rayPointerStart = pointerTransform.position;
|
||||
Vector3 rayPointerEnd = rayPointerStart +
|
||||
(pointerTransform.forward * pointer.CameraRayIntersectionDistance);
|
||||
|
||||
Vector3 cameraLocation = camera.transform.position;
|
||||
Vector3 finalRayDirection = rayPointerEnd - cameraLocation;
|
||||
finalRayDirection.Normalize();
|
||||
|
||||
Vector3 finalRayStart = cameraLocation + (finalRayDirection * camera.nearClipPlane);
|
||||
|
||||
result.ray = new Ray(finalRayStart, finalRayDirection);
|
||||
break;
|
||||
case RaycastMode.Direct:
|
||||
result.ray = new Ray(pointerTransform.position, pointerTransform.forward);
|
||||
break;
|
||||
default:
|
||||
throw new UnityException("Invalid RaycastMode " + mode + " passed into CalculateRay.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Calculates the ray for the segment of the Hybrid raycast determined by the raycast mode
|
||||
/// passed in. Throws an exception if Hybrid is passed in.
|
||||
public static PointerRay CalculateHybridRay(GvrBasePointer pointer, RaycastMode hybridMode) {
|
||||
PointerRay result;
|
||||
|
||||
switch (hybridMode) {
|
||||
case RaycastMode.Direct:
|
||||
result = CalculateRay(pointer, hybridMode);
|
||||
result.distance = pointer.CameraRayIntersectionDistance;
|
||||
break;
|
||||
case RaycastMode.Camera:
|
||||
result = CalculateRay(pointer, hybridMode);
|
||||
PointerRay directRay = CalculateHybridRay(pointer, RaycastMode.Direct);
|
||||
result.ray.origin = directRay.ray.GetPoint(directRay.distance);
|
||||
result.distanceFromStart = directRay.distance;
|
||||
result.distance = pointer.MaxPointerDistance - directRay.distance;
|
||||
break;
|
||||
default:
|
||||
throw new UnityException("Invalid RaycastMode " + hybridMode + " passed into CalculateHybridRay.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual void Start() {
|
||||
GvrPointerInputModule.OnPointerCreated(this);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected virtual void OnDrawGizmos() {
|
||||
if (drawDebugRays && Application.isPlaying && isActiveAndEnabled) {
|
||||
switch (raycastMode) {
|
||||
case RaycastMode.Camera:
|
||||
// Camera line.
|
||||
Gizmos.color = Color.green;
|
||||
PointerRay pointerRay = CalculateRay(this, RaycastMode.Camera);
|
||||
Gizmos.DrawLine(pointerRay.ray.origin, pointerRay.ray.GetPoint(pointerRay.distance));
|
||||
Camera camera = PointerCamera;
|
||||
|
||||
// Pointer to intersection dotted line.
|
||||
Vector3 intersection =
|
||||
PointerTransform.position + (PointerTransform.forward * CameraRayIntersectionDistance);
|
||||
UnityEditor.Handles.DrawDottedLine(PointerTransform.position, intersection, 1.0f);
|
||||
break;
|
||||
case RaycastMode.Direct:
|
||||
// Direct line.
|
||||
Gizmos.color = Color.blue;
|
||||
pointerRay = CalculateRay(this, RaycastMode.Direct);
|
||||
Gizmos.DrawLine(pointerRay.ray.origin, pointerRay.ray.GetPoint(pointerRay.distance));
|
||||
break;
|
||||
case RaycastMode.Hybrid:
|
||||
// Direct line.
|
||||
Gizmos.color = Color.blue;
|
||||
pointerRay = CalculateHybridRay(this, RaycastMode.Direct);
|
||||
Gizmos.DrawLine(pointerRay.ray.origin, pointerRay.ray.GetPoint(pointerRay.distance));
|
||||
|
||||
// Camera line.
|
||||
Gizmos.color = Color.green;
|
||||
pointerRay = CalculateHybridRay(this, RaycastMode.Camera);
|
||||
Gizmos.DrawLine(pointerRay.ray.origin, pointerRay.ray.GetPoint(pointerRay.distance));
|
||||
|
||||
// Camera to intersection dotted line.
|
||||
camera = PointerCamera;
|
||||
if (camera != null) {
|
||||
UnityEditor.Handles.DrawDottedLine(camera.transform.position, pointerRay.ray.origin, 1.0f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR
|
||||
}
|
||||
12
Assets/GoogleVR/Scripts/EventSystem/GvrBasePointer.cs.meta
Normal file
12
Assets/GoogleVR/Scripts/EventSystem/GvrBasePointer.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41c83891d500f43ca90ce70315712c84
|
||||
timeCreated: 1472600806
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// This script provides shared functionality used by all Gvr raycasters.
|
||||
public abstract class GvrBasePointerRaycaster : BaseRaycaster {
|
||||
private GvrBasePointer.PointerRay lastRay;
|
||||
|
||||
protected GvrBasePointer.RaycastMode CurrentRaycastModeForHybrid { get; private set; }
|
||||
|
||||
protected GvrBasePointerRaycaster() {
|
||||
}
|
||||
|
||||
public GvrBasePointer.PointerRay GetLastRay() {
|
||||
return lastRay;
|
||||
}
|
||||
|
||||
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList) {
|
||||
GvrBasePointer pointer = GvrPointerInputModule.Pointer;
|
||||
if (pointer == null || !pointer.IsAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pointer.raycastMode == GvrBasePointer.RaycastMode.Hybrid) {
|
||||
RaycastHybrid(pointer, eventData, resultAppendList);
|
||||
} else {
|
||||
RaycastDefault(pointer, eventData, resultAppendList);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract bool PerformRaycast(GvrBasePointer.PointerRay pointerRay, float radius,
|
||||
PointerEventData eventData, List<RaycastResult> resultAppendList);
|
||||
|
||||
private void RaycastHybrid(GvrBasePointer pointer, PointerEventData eventData, List<RaycastResult> resultAppendList) {
|
||||
CurrentRaycastModeForHybrid = GvrBasePointer.RaycastMode.Direct;
|
||||
lastRay = GvrBasePointer.CalculateHybridRay(pointer, CurrentRaycastModeForHybrid);
|
||||
float radius = pointer.CurrentPointerRadius;
|
||||
bool foundHit = PerformRaycast(lastRay, radius, eventData, resultAppendList);
|
||||
|
||||
if (!foundHit) {
|
||||
CurrentRaycastModeForHybrid = GvrBasePointer.RaycastMode.Camera;
|
||||
lastRay = GvrBasePointer.CalculateHybridRay(pointer, CurrentRaycastModeForHybrid);
|
||||
PerformRaycast(lastRay, radius, eventData, resultAppendList);
|
||||
}
|
||||
}
|
||||
|
||||
private void RaycastDefault(GvrBasePointer pointer, PointerEventData eventData, List<RaycastResult> resultAppendList) {
|
||||
lastRay = GvrBasePointer.CalculateRay(pointer, pointer.raycastMode);
|
||||
float radius = pointer.CurrentPointerRadius;
|
||||
PerformRaycast(lastRay, radius, eventData, resultAppendList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b05767d6e8b854cd0987b344898cc15d
|
||||
timeCreated: 1478543740
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
/// Interface to implement if you wish to receive OnGvrPointerHover callbacks.
|
||||
public interface IGvrPointerHoverHandler : IEventSystemHandler {
|
||||
|
||||
/// Called when pointer is hovering over GameObject.
|
||||
void OnGvrPointerHover(PointerEventData eventData);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7441953e05443d4fa517d1ce7382b0c
|
||||
timeCreated: 1475082809
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
using System.Collections;
|
||||
|
||||
/// This script extends the standard Unity EventSystem events with Gvr specific events.
|
||||
public static class GvrExecuteEventsExtension {
|
||||
private static readonly ExecuteEvents.EventFunction<IGvrPointerHoverHandler> s_HoverHandler = Execute;
|
||||
|
||||
private static void Execute(IGvrPointerHoverHandler handler, BaseEventData eventData) {
|
||||
handler.OnGvrPointerHover(ExecuteEvents.ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
public static ExecuteEvents.EventFunction<IGvrPointerHoverHandler> pointerHoverHandler {
|
||||
get { return s_HoverHandler; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a443597ee157fe49a30c4310f1fb2eb
|
||||
timeCreated: 1475082615
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,234 @@
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// This script provides a raycaster for use with the GvrPointerInputModule.
|
||||
/// It behaves similarly to the standards Graphic raycaster, except that it utilize raycast
|
||||
/// modes specifically for Gvr.
|
||||
///
|
||||
/// View GvrBasePointerRaycaster.cs and GvrPointerInputModule.cs for more details.
|
||||
[AddComponentMenu("GoogleVR/GvrPointerGraphicRaycaster")]
|
||||
[RequireComponent(typeof(Canvas))]
|
||||
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrPointerGraphicRaycaster")]
|
||||
public class GvrPointerGraphicRaycaster : GvrBasePointerRaycaster {
|
||||
public enum BlockingObjects {
|
||||
None = 0,
|
||||
TwoD = 1,
|
||||
ThreeD = 2,
|
||||
All = 3,
|
||||
}
|
||||
|
||||
private const int NO_EVENT_MASK_SET = -1;
|
||||
|
||||
public bool ignoreReversedGraphics = true;
|
||||
public BlockingObjects blockingObjects = BlockingObjects.ThreeD;
|
||||
public LayerMask blockingMask = NO_EVENT_MASK_SET;
|
||||
|
||||
private Canvas targetCanvas;
|
||||
private List<Graphic> raycastResults = new List<Graphic>();
|
||||
private Camera cachedPointerEventCamera;
|
||||
|
||||
private static readonly List<Graphic> sortedGraphics = new List<Graphic>();
|
||||
|
||||
public override Camera eventCamera {
|
||||
get {
|
||||
GvrBasePointer pointer = GvrPointerInputModule.Pointer;
|
||||
if (pointer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pointer.raycastMode == GvrBasePointer.RaycastMode.Hybrid) {
|
||||
return GetCameraForRaycastMode(pointer, CurrentRaycastModeForHybrid);
|
||||
} else {
|
||||
return GetCameraForRaycastMode(pointer, pointer.raycastMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Canvas canvas {
|
||||
get {
|
||||
if (targetCanvas != null)
|
||||
return targetCanvas;
|
||||
|
||||
targetCanvas = GetComponent<Canvas>();
|
||||
return targetCanvas;
|
||||
}
|
||||
}
|
||||
|
||||
protected GvrPointerGraphicRaycaster() {
|
||||
}
|
||||
|
||||
protected override bool PerformRaycast(GvrBasePointer.PointerRay pointerRay, float radius,
|
||||
PointerEventData eventData, List<RaycastResult> resultAppendList) {
|
||||
if (canvas == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eventCamera == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (canvas.renderMode != RenderMode.WorldSpace) {
|
||||
Debug.LogError("GvrPointerGraphicRaycaster requires that the canvas renderMode is set to WorldSpace.");
|
||||
return false;
|
||||
}
|
||||
|
||||
float hitDistance = float.MaxValue;
|
||||
|
||||
if (blockingObjects != BlockingObjects.None) {
|
||||
float dist = pointerRay.distance;
|
||||
|
||||
if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All) {
|
||||
RaycastHit hit;
|
||||
if (Physics.Raycast(pointerRay.ray, out hit, dist, blockingMask)) {
|
||||
hitDistance = hit.distance;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All) {
|
||||
RaycastHit2D hit = Physics2D.Raycast(pointerRay.ray.origin, pointerRay.ray.direction, dist, blockingMask);
|
||||
|
||||
if (hit.collider != null) {
|
||||
hitDistance = hit.fraction * dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
raycastResults.Clear();
|
||||
Ray finalRay;
|
||||
Raycast(canvas, pointerRay.ray, eventCamera, pointerRay.distance, raycastResults, out finalRay);
|
||||
|
||||
bool foundHit = false;
|
||||
|
||||
for (int index = 0; index < raycastResults.Count; index++) {
|
||||
GameObject go = raycastResults[index].gameObject;
|
||||
bool appendGraphic = true;
|
||||
|
||||
if (ignoreReversedGraphics) {
|
||||
// If we have a camera compare the direction against the cameras forward.
|
||||
Vector3 cameraFoward = eventCamera.transform.rotation * Vector3.forward;
|
||||
Vector3 dir = go.transform.rotation * Vector3.forward;
|
||||
appendGraphic = Vector3.Dot(cameraFoward, dir) > 0;
|
||||
}
|
||||
|
||||
if (appendGraphic) {
|
||||
float resultDistance = 0;
|
||||
|
||||
Transform trans = go.transform;
|
||||
Vector3 transForward = trans.forward;
|
||||
// http://geomalgorithms.com/a06-_intersect-2.html
|
||||
float transDot = Vector3.Dot(transForward, trans.position - pointerRay.ray.origin);
|
||||
float rayDot = Vector3.Dot(transForward, pointerRay.ray.direction);
|
||||
resultDistance = transDot / rayDot;
|
||||
Vector3 hitPosition = pointerRay.ray.origin + (pointerRay.ray.direction * resultDistance);
|
||||
|
||||
// Check to see if the go is behind the camera.
|
||||
if (resultDistance < 0 || resultDistance >= hitDistance || resultDistance > pointerRay.distance) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resultDistance = resultDistance + pointerRay.distanceFromStart;
|
||||
Transform pointerTransform =
|
||||
GvrPointerInputModule.Pointer.PointerTransform;
|
||||
float delta = (hitPosition - pointerTransform.position).magnitude;
|
||||
if (delta < pointerRay.distanceFromStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RaycastResult castResult = new RaycastResult
|
||||
{
|
||||
gameObject = go,
|
||||
module = this,
|
||||
distance = resultDistance,
|
||||
worldPosition = hitPosition,
|
||||
screenPosition = eventCamera.WorldToScreenPoint(hitPosition),
|
||||
index = resultAppendList.Count,
|
||||
depth = raycastResults[index].depth,
|
||||
sortingLayer = canvas.sortingLayerID,
|
||||
sortingOrder = canvas.sortingOrder
|
||||
};
|
||||
|
||||
resultAppendList.Add(castResult);
|
||||
foundHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return foundHit;
|
||||
}
|
||||
|
||||
private Camera GetCameraForRaycastMode(GvrBasePointer pointer, GvrBasePointer.RaycastMode mode) {
|
||||
switch (mode) {
|
||||
case GvrBasePointer.RaycastMode.Direct:
|
||||
if (cachedPointerEventCamera == null) {
|
||||
Transform pointerTransform = GvrPointerInputModule.Pointer.PointerTransform;
|
||||
cachedPointerEventCamera = pointerTransform.GetComponent<Camera>();
|
||||
}
|
||||
|
||||
if (cachedPointerEventCamera == null) {
|
||||
cachedPointerEventCamera = AddDummyCameraToPointer(pointer);
|
||||
return null;
|
||||
}
|
||||
|
||||
return cachedPointerEventCamera;
|
||||
case GvrBasePointer.RaycastMode.Camera:
|
||||
default:
|
||||
return pointer.PointerCamera;
|
||||
}
|
||||
}
|
||||
|
||||
private Camera AddDummyCameraToPointer(GvrBasePointer pointer) {
|
||||
Camera camera = pointer.PointerTransform.gameObject.AddComponent<Camera>();
|
||||
camera.enabled = false;
|
||||
camera.nearClipPlane = 0.01f; // Minimum Near Clip Plane.
|
||||
return camera;
|
||||
}
|
||||
|
||||
/// Perform a raycast into the screen and collect all graphics underneath it.
|
||||
private static void Raycast(Canvas canvas, Ray ray, Camera cam, float distance,
|
||||
List<Graphic> results, out Ray finalRay) {
|
||||
Vector3 screenPoint = cam.WorldToScreenPoint(ray.GetPoint(distance));
|
||||
finalRay = cam.ScreenPointToRay(screenPoint);
|
||||
|
||||
// Necessary for the event system
|
||||
IList<Graphic> foundGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);
|
||||
for (int i = 0; i < foundGraphics.Count; ++i) {
|
||||
Graphic graphic = foundGraphics[i];
|
||||
|
||||
// -1 means it hasn't been processed by the canvas, which means it isn't actually drawn
|
||||
if (graphic.depth == -1 || !graphic.raycastTarget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, screenPoint, cam)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (graphic.Raycast(screenPoint, cam)) {
|
||||
sortedGraphics.Add(graphic);
|
||||
}
|
||||
}
|
||||
|
||||
sortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
|
||||
|
||||
for (int i = 0; i < sortedGraphics.Count; ++i) {
|
||||
results.Add(sortedGraphics[i]);
|
||||
}
|
||||
|
||||
sortedGraphics.Clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 739800cd36aba44e9b04ce977e5784bd
|
||||
timeCreated: 1478217778
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,181 @@
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
/// This script provides a raycaster for use with the GvrPointerInputModule.
|
||||
/// It behaves similarly to the standards Physics raycaster, except that it utilize raycast
|
||||
/// modes specifically for Gvr.
|
||||
///
|
||||
/// View GvrBasePointerRaycaster.cs and GvrPointerInputModule.cs for more details.
|
||||
[AddComponentMenu("GoogleVR/GvrPointerPhysicsRaycaster")]
|
||||
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrPointerPhysicsRaycaster")]
|
||||
public class GvrPointerPhysicsRaycaster : GvrBasePointerRaycaster {
|
||||
/// Used to sort the raycast hits by distance.
|
||||
private class HitComparer: IComparer<RaycastHit> {
|
||||
public int Compare(RaycastHit lhs, RaycastHit rhs) {
|
||||
return lhs.distance.CompareTo(rhs.distance);
|
||||
}
|
||||
}
|
||||
|
||||
/// Const to use for clarity when no event mask is set
|
||||
protected const int NO_EVENT_MASK_SET = -1;
|
||||
|
||||
/// The maximum allowed value for the field maxRaycastHits.
|
||||
private const int MAX_RAYCAST_HITS_MAX = 512;
|
||||
|
||||
/// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
|
||||
[SerializeField]
|
||||
protected LayerMask raycasterEventMask = NO_EVENT_MASK_SET;
|
||||
|
||||
[SerializeField]
|
||||
[Range(1, MAX_RAYCAST_HITS_MAX)]
|
||||
/// The max number of hits that the raycaster can detect at once.
|
||||
/// They are NOT guaranteed to be ordered by distance. This value should be set to a higher number
|
||||
/// than the number of objects the pointer is expected to intersect with in a single frame.
|
||||
///
|
||||
/// This functionality is used to prevent unnecessary memory allocation to improve performance.
|
||||
/// https://docs.unity3d.com/ScriptReference/Physics.SphereCastNonAlloc.html
|
||||
private int maxRaycastHits = 64;
|
||||
|
||||
/// Buffer of raycast hits re-used each time PerformRaycast is called.
|
||||
private RaycastHit[] hits;
|
||||
|
||||
/// Used to sort the hits by distance.
|
||||
private HitComparer hitComparer = new HitComparer();
|
||||
|
||||
public int MaxRaycastHits {
|
||||
get {
|
||||
return maxRaycastHits;
|
||||
}
|
||||
set {
|
||||
maxRaycastHits = Mathf.Min(value, MAX_RAYCAST_HITS_MAX);
|
||||
|
||||
if (Application.isPlaying && hits != null && hits.Length != maxRaycastHits) {
|
||||
hits = new RaycastHit[maxRaycastHits];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Camera used for masking layers and determining the screen position of the raycast result.
|
||||
public override Camera eventCamera {
|
||||
get {
|
||||
GvrBasePointer pointer = GvrPointerInputModule.Pointer;
|
||||
if (pointer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return pointer.PointerCamera;
|
||||
}
|
||||
}
|
||||
|
||||
/// Event mask used to determine which objects will receive events.
|
||||
public int finalEventMask {
|
||||
get {
|
||||
return (eventCamera != null) ? eventCamera.cullingMask & eventMask : NO_EVENT_MASK_SET;
|
||||
}
|
||||
}
|
||||
|
||||
/// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
|
||||
public LayerMask eventMask {
|
||||
get {
|
||||
return raycasterEventMask;
|
||||
}
|
||||
set {
|
||||
raycasterEventMask = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected GvrPointerPhysicsRaycaster() {
|
||||
}
|
||||
|
||||
protected override void Awake() {
|
||||
base.Awake();
|
||||
hits = new RaycastHit[maxRaycastHits];
|
||||
}
|
||||
|
||||
protected override bool PerformRaycast(GvrBasePointer.PointerRay pointerRay, float radius,
|
||||
PointerEventData eventData, List<RaycastResult> resultAppendList) {
|
||||
|
||||
if (eventCamera == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHits;
|
||||
if (radius > 0.0f) {
|
||||
numHits = Physics.SphereCastNonAlloc(pointerRay.ray, radius, hits, pointerRay.distance, finalEventMask);
|
||||
} else {
|
||||
numHits = Physics.RaycastNonAlloc(pointerRay.ray, hits, pointerRay.distance, finalEventMask);
|
||||
}
|
||||
|
||||
if (numHits == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numHits == MaxRaycastHits) {
|
||||
MaxRaycastHits *= 2;
|
||||
Debug.LogWarningFormat("Physics Raycast/Spherecast returned {0} hits, which is the current " +
|
||||
"maximum and means that some hits may have been lost. Setting maxRaycastHits to {1}. " +
|
||||
"Please set maxRaycastHits to a sufficiently high value for your scene.",
|
||||
numHits, MaxRaycastHits);
|
||||
}
|
||||
|
||||
Array.Sort(hits, 0, numHits, hitComparer);
|
||||
|
||||
for (int i = 0; i < numHits; ++i) {
|
||||
Vector3 projection = Vector3.Project(hits[i].point - pointerRay.ray.origin, pointerRay.ray.direction);
|
||||
Vector3 hitPosition = projection + pointerRay.ray.origin;
|
||||
float resultDistance = hits[i].distance + pointerRay.distanceFromStart;
|
||||
|
||||
Transform pointerTransform =
|
||||
GvrPointerInputModule.Pointer.PointerTransform;
|
||||
float delta = (hitPosition - pointerTransform.position).magnitude;
|
||||
if (delta < pointerRay.distanceFromStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RaycastResult result = new RaycastResult
|
||||
{
|
||||
gameObject = hits[i].collider.gameObject,
|
||||
module = this,
|
||||
distance = resultDistance,
|
||||
worldPosition = hitPosition,
|
||||
worldNormal = hits[i].normal,
|
||||
screenPosition = eventCamera.WorldToScreenPoint(hitPosition),
|
||||
index = resultAppendList.Count,
|
||||
sortingLayer = 0,
|
||||
sortingOrder = 0
|
||||
};
|
||||
|
||||
resultAppendList.Add(result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate() {
|
||||
base.OnValidate();
|
||||
|
||||
// Makes sure that the hits buffer is updated if maxRaycastHits is changed in the inspector
|
||||
// while testing in the editor.
|
||||
if (Application.isPlaying) {
|
||||
MaxRaycastHits = maxRaycastHits;
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb5dd43baba2d4dc1bab789615567e3d
|
||||
timeCreated: 1478196044
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
283
Assets/GoogleVR/Scripts/EventSystem/GvrPointerScrollInput.cs
Normal file
283
Assets/GoogleVR/Scripts/EventSystem/GvrPointerScrollInput.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
/// This class is used by _GvrPointerInputModule_ to route scroll events through Unity's Event System.
|
||||
/// It maintains indepedent velocities for each instance of _IScrollHandler_ that is currently being scrolled.
|
||||
/// Inertia can optionally be toggled off.
|
||||
[System.Serializable]
|
||||
public class GvrPointerScrollInput {
|
||||
public const string PROPERTY_NAME_INERTIA = "inertia";
|
||||
public const string PROPERTY_NAME_DECELERATION_RATE = "decelerationRate";
|
||||
|
||||
private class ScrollInfo {
|
||||
public bool isScrollingX = false;
|
||||
public bool isScrollingY = false;
|
||||
public Vector2 initScroll = Vector2.zero;
|
||||
public Vector2 lastScroll = Vector2.zero;
|
||||
public Vector2 scrollVelocity = Vector2.zero;
|
||||
public IGvrScrollSettings scrollSettings = null;
|
||||
|
||||
public bool IsScrolling {
|
||||
get {
|
||||
return isScrollingX || isScrollingY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Inertia means that scroll events will continue for a while after the user stops
|
||||
/// touching the touchpad. It gradually slows down according to the decelerationRate.
|
||||
[Tooltip("Determines if movement inertia is enabled.")]
|
||||
public bool inertia = true;
|
||||
|
||||
/// The deceleration rate is the speed reduction per second.
|
||||
/// A value of 0.5 halves the speed each second. The default is 0.05.
|
||||
/// The deceleration rate is only used when inertia is enabled.
|
||||
[Tooltip("The rate at which movement slows down.")]
|
||||
public float decelerationRate = 0.05f;
|
||||
|
||||
/// Multiplier for calculating the scroll delta so that the scroll delta is
|
||||
/// within the order of magnitude that the UI system expects.
|
||||
public const float SCROLL_DELTA_MULTIPLIER = 1000.0f;
|
||||
|
||||
private const float CUTOFF_HZ = 10.0f;
|
||||
private const float RC = (float) (1.0 / (2.0 * Mathf.PI * CUTOFF_HZ));
|
||||
private const float SPEED_CLAMP_RATIO = 0.05f;
|
||||
private const float SPEED_CLAMP = (SPEED_CLAMP_RATIO * SCROLL_DELTA_MULTIPLIER);
|
||||
private const float SPEED_CLAMP_SQUARED = SPEED_CLAMP * SPEED_CLAMP;
|
||||
private const float INERTIA_THRESHOLD_RATIO = 0.2f;
|
||||
private const float INERTIA_THRESHOLD = (INERTIA_THRESHOLD_RATIO * SCROLL_DELTA_MULTIPLIER);
|
||||
private const float INERTIA_THRESHOLD_SQUARED = INERTIA_THRESHOLD * INERTIA_THRESHOLD;
|
||||
private const float SLOP_VERTICAL = 0.165f * SCROLL_DELTA_MULTIPLIER;
|
||||
private const float SLOP_HORIZONTAL = 0.15f * SCROLL_DELTA_MULTIPLIER;
|
||||
|
||||
private Dictionary<GameObject, ScrollInfo> scrollHandlers = new Dictionary<GameObject, ScrollInfo>();
|
||||
private List<GameObject> scrollingObjects = new List<GameObject>();
|
||||
|
||||
public void HandleScroll(GameObject currentGameObject, PointerEventData pointerData,
|
||||
GvrBasePointer pointer, IGvrEventExecutor eventExecutor) {
|
||||
bool touchDown = false;
|
||||
bool touching = false;
|
||||
bool touchUp = false;
|
||||
Vector2 currentScroll = Vector2.zero;
|
||||
|
||||
if (pointer != null && pointer.IsAvailable) {
|
||||
touchDown = pointer.TouchDown;
|
||||
touching = pointer.IsTouching;
|
||||
touchUp = pointer.TouchUp;
|
||||
currentScroll = pointer.TouchPos * SCROLL_DELTA_MULTIPLIER;
|
||||
}
|
||||
|
||||
GameObject currentScrollHandler = eventExecutor.GetEventHandler<IScrollHandler>(currentGameObject);
|
||||
|
||||
if (touchDown) {
|
||||
RemoveScrollHandler(currentScrollHandler);
|
||||
}
|
||||
|
||||
if (currentScrollHandler != null && (touchDown || touching)) {
|
||||
OnTouchingScrollHandler(currentScrollHandler, pointerData, currentScroll, eventExecutor);
|
||||
} else if (touchUp && currentScrollHandler != null) {
|
||||
OnReleaseScrollHandler(currentScrollHandler);
|
||||
}
|
||||
|
||||
StopScrollingIfNecessary(touching, currentScrollHandler);
|
||||
UpdateInertiaScrollHandlers(touching, currentScrollHandler, pointerData, eventExecutor);
|
||||
}
|
||||
|
||||
private void OnTouchingScrollHandler(GameObject currentScrollHandler, PointerEventData pointerData,
|
||||
Vector2 currentScroll, IGvrEventExecutor eventExecutor) {
|
||||
ScrollInfo scrollInfo = null;
|
||||
if (!scrollHandlers.ContainsKey(currentScrollHandler)) {
|
||||
scrollInfo = AddScrollHandler(currentScrollHandler, currentScroll);
|
||||
} else {
|
||||
scrollInfo = scrollHandlers[currentScrollHandler];
|
||||
}
|
||||
|
||||
// Detect if we should start scrolling along the x-axis based on the horizontal slop threshold.
|
||||
if (CanScrollStartX(scrollInfo, currentScroll)) {
|
||||
scrollInfo.isScrollingX = true;
|
||||
}
|
||||
|
||||
// Detect if we should start scrolling along the y-axis based on the vertical slop threshold.
|
||||
if (CanScrollStartY(scrollInfo, currentScroll)) {
|
||||
scrollInfo.isScrollingY = true;
|
||||
}
|
||||
|
||||
if (scrollInfo.IsScrolling) {
|
||||
Vector2 clampedScroll = currentScroll;
|
||||
Vector2 clampedLastScroll = scrollInfo.lastScroll;
|
||||
if (!scrollInfo.isScrollingX) {
|
||||
clampedScroll.x = 0.0f;
|
||||
clampedLastScroll.x = 0.0f;
|
||||
}
|
||||
|
||||
if (!scrollInfo.isScrollingY) {
|
||||
clampedScroll.y = 0.0f;
|
||||
clampedLastScroll.y = 0.0f;
|
||||
}
|
||||
|
||||
Vector2 scrollDisplacement = clampedScroll - clampedLastScroll;
|
||||
UpdateVelocity(scrollInfo, scrollDisplacement);
|
||||
|
||||
if (!ShouldUseInertia(scrollInfo)) {
|
||||
// If inertia is disabled, then we send scroll events immediately.
|
||||
pointerData.scrollDelta = scrollDisplacement;
|
||||
eventExecutor.ExecuteHierarchy(currentScrollHandler, pointerData, ExecuteEvents.scrollHandler);
|
||||
pointerData.scrollDelta = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
scrollInfo.lastScroll = currentScroll;
|
||||
}
|
||||
|
||||
private void OnReleaseScrollHandler(GameObject currentScrollHandler) {
|
||||
// When we touch up, immediately stop scrolling the currentScrollHandler if it's velocity is low.
|
||||
ScrollInfo scrollInfo;
|
||||
if (scrollHandlers.TryGetValue(currentScrollHandler, out scrollInfo)) {
|
||||
if (!scrollInfo.IsScrolling || scrollInfo.scrollVelocity.sqrMagnitude <= INERTIA_THRESHOLD_SQUARED) {
|
||||
RemoveScrollHandler(currentScrollHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVelocity(ScrollInfo scrollInfo, Vector2 scrollDisplacement) {
|
||||
Vector2 newVelocity = scrollDisplacement / Time.deltaTime;
|
||||
float weight = Time.deltaTime / (RC + Time.deltaTime);
|
||||
scrollInfo.scrollVelocity = Vector2.Lerp(scrollInfo.scrollVelocity, newVelocity, weight);
|
||||
}
|
||||
|
||||
private void StopScrollingIfNecessary(bool touching, GameObject currentScrollHandler) {
|
||||
if (scrollHandlers.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If inertia is disabled, stop scrolling any scrollHandler that isn't currently being touched.
|
||||
for (int i = scrollingObjects.Count - 1; i >= 0; i--) {
|
||||
GameObject scrollHandler = scrollingObjects[i];
|
||||
ScrollInfo scrollInfo = scrollHandlers[scrollHandler];
|
||||
|
||||
bool isScrollling = scrollInfo.IsScrolling;
|
||||
|
||||
bool isVelocityBelowThreshold =
|
||||
isScrollling && scrollInfo.scrollVelocity.sqrMagnitude <= SPEED_CLAMP_SQUARED;
|
||||
|
||||
bool isCurrentlyTouching = touching && scrollHandler == currentScrollHandler;
|
||||
|
||||
bool shouldUseInertia = ShouldUseInertia(scrollInfo);
|
||||
|
||||
bool shouldStopScrolling = isVelocityBelowThreshold
|
||||
|| ((!shouldUseInertia || !isScrollling) && !isCurrentlyTouching);
|
||||
|
||||
if (shouldStopScrolling) {
|
||||
RemoveScrollHandler(scrollHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInertiaScrollHandlers(bool touching, GameObject currentScrollHandler,
|
||||
PointerEventData pointerData, IGvrEventExecutor eventExecutor) {
|
||||
if (pointerData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the currentScrollHandler is null, then the currently scrolling scrollHandlers
|
||||
// must still be decelerated so the function does not return early.
|
||||
|
||||
for (int i = 0; i < scrollingObjects.Count; i++) {
|
||||
GameObject scrollHandler = scrollingObjects[i];
|
||||
ScrollInfo scrollInfo = scrollHandlers[scrollHandler];
|
||||
|
||||
if (!ShouldUseInertia(scrollInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (scrollInfo.IsScrolling) {
|
||||
// Decelerate the scrollHandler if necessary.
|
||||
if (!touching || scrollHandler != currentScrollHandler) {
|
||||
float finalDecelerationRate = GetDecelerationRate(scrollInfo);
|
||||
scrollInfo.scrollVelocity *= Mathf.Pow(finalDecelerationRate, Time.deltaTime);
|
||||
}
|
||||
|
||||
// Send the scroll events.
|
||||
pointerData.scrollDelta = scrollInfo.scrollVelocity * Time.deltaTime;
|
||||
eventExecutor.ExecuteHierarchy(scrollHandler, pointerData, ExecuteEvents.scrollHandler);
|
||||
}
|
||||
}
|
||||
pointerData.scrollDelta = Vector2.zero;
|
||||
}
|
||||
|
||||
private ScrollInfo AddScrollHandler(GameObject scrollHandler, Vector2 currentScroll) {
|
||||
ScrollInfo scrollInfo = new ScrollInfo();
|
||||
scrollInfo.initScroll = currentScroll;
|
||||
scrollInfo.lastScroll = currentScroll;
|
||||
scrollInfo.scrollSettings = scrollHandler.GetComponent<IGvrScrollSettings>();
|
||||
scrollHandlers[scrollHandler] = scrollInfo;
|
||||
scrollingObjects.Add(scrollHandler);
|
||||
return scrollInfo;
|
||||
}
|
||||
|
||||
private void RemoveScrollHandler(GameObject scrollHandler) {
|
||||
// Check if it's null via object.Equals instead of doing a direct comparison
|
||||
// to avoid using Unity's equality check override for UnityEngine.Objects.
|
||||
// This is so that we can remove Unity objects that have been Destroyed from the dictionary,
|
||||
// but will still return early when an object is actually null.
|
||||
if (object.Equals(scrollHandler, null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scrollHandlers.ContainsKey(scrollHandler)) {
|
||||
return;
|
||||
}
|
||||
|
||||
scrollHandlers.Remove(scrollHandler);
|
||||
scrollingObjects.Remove(scrollHandler);
|
||||
}
|
||||
|
||||
private bool ShouldUseInertia(ScrollInfo scrollInfo) {
|
||||
if (scrollInfo != null && scrollInfo.scrollSettings != null) {
|
||||
return scrollInfo.scrollSettings.InertiaOverride;
|
||||
}
|
||||
|
||||
return inertia;
|
||||
}
|
||||
|
||||
private float GetDecelerationRate(ScrollInfo scrollInfo) {
|
||||
if (scrollInfo != null && scrollInfo.scrollSettings != null) {
|
||||
return scrollInfo.scrollSettings.DecelerationRateOverride;
|
||||
}
|
||||
|
||||
return decelerationRate;
|
||||
}
|
||||
|
||||
private static bool CanScrollStartX(ScrollInfo scrollInfo, Vector2 currentScroll) {
|
||||
if (scrollInfo == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Mathf.Abs(currentScroll.x - scrollInfo.initScroll.x) >= SLOP_HORIZONTAL;
|
||||
}
|
||||
|
||||
private static bool CanScrollStartY(ScrollInfo scrollInfo, Vector2 currentScroll) {
|
||||
if (scrollInfo == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Mathf.Abs(currentScroll.y - scrollInfo.initScroll.y) >= SLOP_VERTICAL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23744ffc3b678488e858089d1a2973d9
|
||||
timeCreated: 1487096177
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
46
Assets/GoogleVR/Scripts/EventSystem/GvrScrollSettings.cs
Normal file
46
Assets/GoogleVR/Scripts/EventSystem/GvrScrollSettings.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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 System.Collections;
|
||||
|
||||
/// Used to override the global scroll settings in _GvrPointerScrollInput_
|
||||
/// for the GameObject that this script is attached to.
|
||||
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrScrollSettings")]
|
||||
public class GvrScrollSettings : MonoBehaviour, IGvrScrollSettings {
|
||||
/// Override the Inertia property in _GvrPointerScrollInput_ for this object.
|
||||
///
|
||||
/// Inertia means that scroll events will continue for a while after the user stops
|
||||
/// touching the touchpad. It gradually slows down according to the decelerationRate.
|
||||
[Tooltip("Determines if movement inertia is enabled.")]
|
||||
public bool inertiaOverride = true;
|
||||
|
||||
/// The deceleration rate is the speed reduction per second.
|
||||
/// A value of 0.5 halves the speed each second. The default is 0.05.
|
||||
/// The deceleration rate is only used when inertia is enabled.
|
||||
[Tooltip("The rate at which movement slows down.")]
|
||||
public float decelerationRateOverride = 0.05f;
|
||||
|
||||
public bool InertiaOverride {
|
||||
get {
|
||||
return inertiaOverride;
|
||||
}
|
||||
}
|
||||
|
||||
public float DecelerationRateOverride {
|
||||
get {
|
||||
return decelerationRateOverride;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5db1ab7348db34ecbac8c834c5d3425f
|
||||
timeCreated: 1496793989
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
57
Assets/GoogleVR/Scripts/EventSystem/GvrXREventsSubscriber.cs
Normal file
57
Assets/GoogleVR/Scripts/EventSystem/GvrXREventsSubscriber.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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 System.Collections;
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
using UnityEngine.XR;
|
||||
#else
|
||||
using XRDevice = UnityEngine.VR.VRDevice;
|
||||
using XRSettings = UnityEngine.VR.VRSettings;
|
||||
#endif // UNITY_2017_2_OR_NEWER
|
||||
|
||||
// Handler for subscribing XR Unity actions to GVR Actions.
|
||||
public class GvrXREventsSubscriber : MonoBehaviour {
|
||||
private static GvrXREventsSubscriber instance;
|
||||
private string _loadedDeviceName;
|
||||
public static string loadedDeviceName {
|
||||
get {
|
||||
return GetInstance()._loadedDeviceName;
|
||||
}
|
||||
set {
|
||||
GetInstance()._loadedDeviceName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnDeviceLoadAction(string newLoadedDeviceName) {
|
||||
loadedDeviceName = newLoadedDeviceName;
|
||||
}
|
||||
|
||||
void Awake() {
|
||||
instance = this;
|
||||
_loadedDeviceName = XRSettings.loadedDeviceName;
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
XRDevice.deviceLoaded += OnDeviceLoadAction;
|
||||
#endif // UNITY_2018_3_OR_NEWER
|
||||
}
|
||||
|
||||
private static GvrXREventsSubscriber GetInstance() {
|
||||
if (instance == null) {
|
||||
GameObject gvrXREventsSubscriber = new GameObject("GvrXREventsSubscriber");
|
||||
gvrXREventsSubscriber.AddComponent<GvrXREventsSubscriber>();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12a8088f6fe474f31bffbd957940f5fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Assets/GoogleVR/Scripts/EventSystem/IGvrScrollSettings.cs
Normal file
40
Assets/GoogleVR/Scripts/EventSystem/IGvrScrollSettings.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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 System.Collections;
|
||||
|
||||
/// Interface to implement to override the global scroll settings
|
||||
/// in _GvrPointerScrollInput_ for an object.
|
||||
///
|
||||
/// Must be implmented by a component. It will override the scroll settings for the
|
||||
/// GameObject that the component is attached to.
|
||||
///
|
||||
/// Can use _GvrScrollSettings_ To override scroll settings for any existing UI type,
|
||||
/// or a custom UI component can implement this directly to override the scroll settings
|
||||
/// for the UI component's use case.
|
||||
public interface IGvrScrollSettings {
|
||||
/// Override the Inertia property in _GvrPointerScrollInput_ for this object.
|
||||
///
|
||||
/// Inertia means that scroll events will continue for a while after the user stops
|
||||
/// touching the touchpad. It gradually slows down according to the decelerationRate.
|
||||
bool InertiaOverride { get; }
|
||||
|
||||
/// Override the DecelerationRate property in _GvrPointerScrollInput_ for this object.
|
||||
///
|
||||
/// The deceleration rate is the speed reduction per second.
|
||||
/// A value of 0.5 halves the speed each second.
|
||||
/// The deceleration rate is only used when inertia is enabled.
|
||||
float DecelerationRateOverride { get; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4a605c315b944e7f84ed1dbe9ff6921
|
||||
timeCreated: 1496856692
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/GoogleVR/Scripts/EventSystem/InputModule.meta
Normal file
8
Assets/GoogleVR/Scripts/EventSystem/InputModule.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd315516f5723a340ad63cc669faf852
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// Exposes events from _GvrEventExecutor_ that are fired by _GvrPointerInputModule_ to the editor.
|
||||
/// Makes it possible to handle EventSystem events globally.
|
||||
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrAllEventsTrigger")]
|
||||
public class GvrAllEventsTrigger : MonoBehaviour {
|
||||
|
||||
[Serializable]
|
||||
public class TriggerEvent : UnityEvent<GameObject, PointerEventData>
|
||||
{}
|
||||
|
||||
public TriggerEvent OnPointerClick;
|
||||
public TriggerEvent OnPointerDown;
|
||||
public TriggerEvent OnPointerUp;
|
||||
public TriggerEvent OnPointerEnter;
|
||||
public TriggerEvent OnPointerExit;
|
||||
public TriggerEvent OnScroll;
|
||||
|
||||
private bool listenersAdded;
|
||||
|
||||
void OnEnable() {
|
||||
AddListeners();
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
RemoveListeners();
|
||||
}
|
||||
|
||||
void Start() {
|
||||
// The eventExecutor may not be available during OnEnable when the script is first created.
|
||||
AddListeners();
|
||||
}
|
||||
|
||||
private void AddListeners() {
|
||||
GvrEventExecutor eventExecutor = GvrPointerInputModule.FindEventExecutor();
|
||||
if (eventExecutor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenersAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventExecutor.OnPointerClick += OnPointerClickHandler;
|
||||
eventExecutor.OnPointerDown += OnPointerDownHandler;
|
||||
eventExecutor.OnPointerUp += OnPointerUpHandler;
|
||||
eventExecutor.OnPointerEnter += OnPointerEnterHandler;
|
||||
eventExecutor.OnPointerExit += OnPointerExitHandler;
|
||||
eventExecutor.OnScroll += OnScrollHandler;
|
||||
|
||||
listenersAdded = true;
|
||||
}
|
||||
|
||||
private void RemoveListeners() {
|
||||
GvrEventExecutor eventExecutor = GvrPointerInputModule.FindEventExecutor();
|
||||
if (eventExecutor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!listenersAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventExecutor.OnPointerClick -= OnPointerClickHandler;
|
||||
eventExecutor.OnPointerDown -= OnPointerDownHandler;
|
||||
eventExecutor.OnPointerUp -= OnPointerUpHandler;
|
||||
eventExecutor.OnPointerEnter -= OnPointerEnterHandler;
|
||||
eventExecutor.OnPointerExit -= OnPointerExitHandler;
|
||||
eventExecutor.OnScroll -= OnScrollHandler;
|
||||
|
||||
listenersAdded = false;
|
||||
}
|
||||
|
||||
private void OnPointerClickHandler(GameObject target, PointerEventData eventData) {
|
||||
OnPointerClick.Invoke(target, eventData);
|
||||
}
|
||||
|
||||
private void OnPointerDownHandler(GameObject target, PointerEventData eventData) {
|
||||
OnPointerDown.Invoke(target, eventData);
|
||||
}
|
||||
|
||||
private void OnPointerUpHandler(GameObject target, PointerEventData eventData) {
|
||||
OnPointerUp.Invoke(target, eventData);
|
||||
}
|
||||
|
||||
private void OnPointerEnterHandler(GameObject target, PointerEventData eventData) {
|
||||
OnPointerEnter.Invoke(target, eventData);
|
||||
}
|
||||
|
||||
private void OnPointerExitHandler(GameObject target, PointerEventData eventData) {
|
||||
OnPointerExit.Invoke(target, eventData);
|
||||
}
|
||||
|
||||
private void OnScrollHandler(GameObject target, PointerEventData eventData) {
|
||||
OnScroll.Invoke(target, eventData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca0157c63fb794df89c6735fc602eca2
|
||||
timeCreated: 1493228030
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,159 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
/// Wraps UnityEngine.EventSystems.ExecuteEvents.
|
||||
/// Also, exposes event delegates to allow global handling of events.
|
||||
public class GvrEventExecutor : IGvrEventExecutor {
|
||||
public delegate void EventDelegate(GameObject target, PointerEventData eventData);
|
||||
|
||||
/// Fired when a Click occurs on any object.
|
||||
public event EventDelegate OnPointerClick {
|
||||
add {
|
||||
AddEventDelegate<IPointerClickHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IPointerClickHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when a Down event occurs on any object.
|
||||
public event EventDelegate OnPointerDown {
|
||||
add {
|
||||
AddEventDelegate<IPointerDownHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IPointerDownHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when an Up event occurs on any object.
|
||||
public event EventDelegate OnPointerUp {
|
||||
add {
|
||||
AddEventDelegate<IPointerUpHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IPointerUpHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when an Enter event occurs on any object.
|
||||
public event EventDelegate OnPointerEnter {
|
||||
add {
|
||||
AddEventDelegate<IPointerEnterHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IPointerEnterHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when an Exit event occurs on any object.
|
||||
public event EventDelegate OnPointerExit {
|
||||
add {
|
||||
AddEventDelegate<IPointerExitHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IPointerExitHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when a Scroll event occurs on any object.
|
||||
public event EventDelegate OnScroll {
|
||||
add {
|
||||
AddEventDelegate<IScrollHandler>(value);
|
||||
}
|
||||
remove {
|
||||
RemoveEventDelegate<IScrollHandler>(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores delegates for events.
|
||||
private Dictionary<Type, EventDelegate> eventTable;
|
||||
|
||||
public GvrEventExecutor() {
|
||||
eventTable = new Dictionary<Type, EventDelegate>();
|
||||
}
|
||||
|
||||
public bool Execute<T>(GameObject target,
|
||||
BaseEventData eventData,
|
||||
ExecuteEvents.EventFunction<T> functor)
|
||||
where T : IEventSystemHandler {
|
||||
bool result = ExecuteEvents.Execute<T>(target, eventData, functor);
|
||||
CallEventDelegate<T>(target, eventData);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public GameObject ExecuteHierarchy<T>(GameObject root,
|
||||
BaseEventData eventData,
|
||||
ExecuteEvents.EventFunction<T> callbackFunction)
|
||||
where T : IEventSystemHandler {
|
||||
GameObject result = ExecuteEvents.ExecuteHierarchy<T>(root, eventData, callbackFunction);
|
||||
CallEventDelegate<T>(root, eventData);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public GameObject GetEventHandler<T>(GameObject root)
|
||||
where T : IEventSystemHandler {
|
||||
return ExecuteEvents.GetEventHandler<T>(root);
|
||||
}
|
||||
|
||||
private void CallEventDelegate<T>(GameObject target, BaseEventData eventData)
|
||||
where T : IEventSystemHandler {
|
||||
Type type = typeof(T);
|
||||
|
||||
EventDelegate eventDelegate;
|
||||
if (eventTable.TryGetValue(type, out eventDelegate)) {
|
||||
PointerEventData pointerEventData = eventData as PointerEventData;
|
||||
if (pointerEventData == null) {
|
||||
Debug.LogError("Event data must be PointerEventData.");
|
||||
return;
|
||||
}
|
||||
|
||||
eventDelegate(target, pointerEventData);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEventDelegate<T>(EventDelegate eventDelegate) {
|
||||
Type type = typeof(T);
|
||||
|
||||
EventDelegate existingDelegate;
|
||||
if (eventTable.TryGetValue(type, out existingDelegate)) {
|
||||
eventTable[type] = existingDelegate + eventDelegate;
|
||||
} else {
|
||||
eventTable[type] = eventDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveEventDelegate<T>(EventDelegate eventDelegate) {
|
||||
Type type = typeof(T);
|
||||
|
||||
EventDelegate existingDelegate;
|
||||
if (!eventTable.TryGetValue(type, out existingDelegate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventDelegate = existingDelegate - eventDelegate;
|
||||
if (eventDelegate != null) {
|
||||
eventTable[type] = eventDelegate;
|
||||
} else {
|
||||
eventTable.Remove(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a93ebe04d36b49c388adce4ac442226
|
||||
timeCreated: 1493142648
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License, you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// This script provides an implemention of Unity's `BaseInputModule` class, so
|
||||
/// that Canvas-based (_uGUI_) UI elements and 3D scene objects can be
|
||||
/// interacted with in a Gvr Application.
|
||||
///
|
||||
/// This script is intended for use with either a
|
||||
/// 3D Pointer with the Daydream Controller (Recommended for Daydream),
|
||||
/// or a Gaze-based-Pointer (Recommended for Cardboard).
|
||||
///
|
||||
/// To use, attach to the scene's **EventSystem** object. Be sure to move it above the
|
||||
/// other modules, such as _TouchInputModule_ and _StandaloneInputModule_, in order
|
||||
/// for the Pointer to take priority in the event system.
|
||||
///
|
||||
/// If you are using a **Canvas**, set the _Render Mode_ to **World Space**,
|
||||
/// and add the _GvrPointerGraphicRaycaster_ script to the object.
|
||||
///
|
||||
/// If you'd like pointers to work with 3D scene objects, add a _GvrPointerPhysicsRaycaster_ to the main camera,
|
||||
/// and add a component that implements one of the _Event_ interfaces (_EventTrigger_ will work nicely) to
|
||||
/// an object with a collider.
|
||||
///
|
||||
/// GvrPointerInputModule emits the following events: _Enter_, _Exit_, _Down_, _Up_, _Click_, _Select_,
|
||||
/// _Deselect_, _UpdateSelected_, and _GvrPointerHover_. Scroll, move, and submit/cancel events are not emitted.
|
||||
///
|
||||
/// To use a 3D Pointer with the Daydream Controller:
|
||||
/// - Add the prefab GoogleVR/Prefabs/UI/GvrControllerPointer to your scene.
|
||||
/// - Set the parent of GvrControllerPointer to the same parent as the main camera
|
||||
/// (With a local position of 0,0,0).
|
||||
///
|
||||
/// To use a Gaze-based-pointer:
|
||||
/// - Add the prefab GoogleVR/Prefabs/UI/GvrReticlePointer to your scene.
|
||||
/// - Set the parent of GvrReticlePointer to the main camera.
|
||||
///
|
||||
[AddComponentMenu("GoogleVR/GvrPointerInputModule")]
|
||||
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrPointerInputModule")]
|
||||
public class GvrPointerInputModule : BaseInputModule, IGvrInputModuleController {
|
||||
/// Determines whether Pointer input is active in VR Mode only (`true`), or all of the
|
||||
/// time (`false`). Set to false if you plan to use direct screen taps or other
|
||||
/// input when not in VR Mode.
|
||||
[Tooltip("Whether Pointer input is active in VR Mode only (true), or all the time (false).")]
|
||||
public bool vrModeOnly = false;
|
||||
|
||||
[Tooltip("Manages scroll events for the input module.")]
|
||||
public GvrPointerScrollInput scrollInput = new GvrPointerScrollInput();
|
||||
|
||||
public GvrPointerInputModuleImpl Impl { get; private set; }
|
||||
|
||||
public GvrEventExecutor EventExecutor { get; private set; }
|
||||
|
||||
public new EventSystem eventSystem {
|
||||
get {
|
||||
return base.eventSystem;
|
||||
}
|
||||
}
|
||||
|
||||
public List<RaycastResult> RaycastResultCache {
|
||||
get {
|
||||
return m_RaycastResultCache;
|
||||
}
|
||||
}
|
||||
|
||||
public static GvrBasePointer Pointer {
|
||||
get {
|
||||
GvrPointerInputModule module = FindInputModule();
|
||||
if (module == null || module.Impl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return module.Impl.Pointer;
|
||||
}
|
||||
set {
|
||||
GvrPointerInputModule module = FindInputModule();
|
||||
if (module == null || module.Impl == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
module.Impl.Pointer = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// GvrBasePointer calls this when it is created.
|
||||
/// If a pointer hasn't already been assigned, it
|
||||
/// will assign the newly created one by default.
|
||||
///
|
||||
/// This simplifies the common case of having only one
|
||||
/// GvrBasePointer so is can be automatically hooked up
|
||||
/// to the manager. If multiple GvrBasePointers are in
|
||||
/// the scene, the app has to take responsibility for
|
||||
/// setting which one is active.
|
||||
public static void OnPointerCreated(GvrBasePointer createdPointer) {
|
||||
GvrPointerInputModule module = FindInputModule();
|
||||
if (module == null || module.Impl == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (module.Impl.Pointer == null) {
|
||||
module.Impl.Pointer = createdPointer;
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to find the Event Executor that is part of
|
||||
/// the input module if one exists in the scene.
|
||||
public static GvrEventExecutor FindEventExecutor() {
|
||||
GvrPointerInputModule gvrInputModule = FindInputModule();
|
||||
if (gvrInputModule == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return gvrInputModule.EventExecutor;
|
||||
}
|
||||
|
||||
/// Helper function to find the input module if one exists in the
|
||||
/// scene and it is the active module.
|
||||
public static GvrPointerInputModule FindInputModule() {
|
||||
if (EventSystem.current == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EventSystem eventSystem = EventSystem.current;
|
||||
if (eventSystem == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GvrPointerInputModule gvrInputModule =
|
||||
eventSystem.GetComponent<GvrPointerInputModule>();
|
||||
|
||||
return gvrInputModule;
|
||||
}
|
||||
|
||||
/// Convenience function to access what the current RaycastResult.
|
||||
public static RaycastResult CurrentRaycastResult {
|
||||
get {
|
||||
GvrPointerInputModule inputModule = GvrPointerInputModule.FindInputModule();
|
||||
if (inputModule == null) {
|
||||
return new RaycastResult();
|
||||
}
|
||||
|
||||
if (inputModule.Impl == null) {
|
||||
return new RaycastResult();
|
||||
}
|
||||
|
||||
if (inputModule.Impl.CurrentEventData == null) {
|
||||
return new RaycastResult();
|
||||
}
|
||||
|
||||
return inputModule.Impl.CurrentEventData.pointerCurrentRaycast;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldActivateModule() {
|
||||
return Impl.ShouldActivateModule();
|
||||
}
|
||||
|
||||
public override void DeactivateModule() {
|
||||
Impl.DeactivateModule();
|
||||
}
|
||||
|
||||
public override bool IsPointerOverGameObject(int pointerId) {
|
||||
return Impl.IsPointerOverGameObject(pointerId);
|
||||
}
|
||||
|
||||
public override void Process() {
|
||||
UpdateImplProperties();
|
||||
Impl.Process();
|
||||
}
|
||||
|
||||
protected override void Awake() {
|
||||
base.Awake();
|
||||
Impl = new GvrPointerInputModuleImpl();
|
||||
EventExecutor = new GvrEventExecutor();
|
||||
UpdateImplProperties();
|
||||
}
|
||||
|
||||
public bool ShouldActivate() {
|
||||
return base.ShouldActivateModule();
|
||||
}
|
||||
|
||||
public void Deactivate() {
|
||||
base.DeactivateModule();
|
||||
}
|
||||
|
||||
public new GameObject FindCommonRoot(GameObject g1, GameObject g2) {
|
||||
return BaseInputModule.FindCommonRoot(g1, g2);
|
||||
}
|
||||
|
||||
public new BaseEventData GetBaseEventData() {
|
||||
return base.GetBaseEventData();
|
||||
}
|
||||
|
||||
public new RaycastResult FindFirstRaycast(List<RaycastResult> candidates) {
|
||||
return BaseInputModule.FindFirstRaycast(candidates);
|
||||
}
|
||||
|
||||
private void UpdateImplProperties() {
|
||||
if (Impl == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Impl.ScrollInput = scrollInput;
|
||||
Impl.VrModeOnly = vrModeOnly;
|
||||
Impl.ModuleController = this;
|
||||
Impl.EventExecutor = EventExecutor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcd4baceb58cc40c98e500572bede6a6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,458 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License, you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
using UnityEngine.XR;
|
||||
#else
|
||||
using XRSettings = UnityEngine.VR.VRSettings;
|
||||
#endif // UNITY_2017_2_OR_NEWER
|
||||
|
||||
/// Implementation of _GvrPointerInputModule_
|
||||
public class GvrPointerInputModuleImpl {
|
||||
/// Interface for controlling the actual InputModule.
|
||||
public IGvrInputModuleController ModuleController { get; set; }
|
||||
|
||||
/// Interface for executing events.
|
||||
public IGvrEventExecutor EventExecutor { get; set; }
|
||||
|
||||
/// Determines whether pointer input is active in VR Mode only (`true`), or all of the
|
||||
/// time (`false`). Set to false if you plan to use direct screen taps or other
|
||||
/// input when not in VR Mode.
|
||||
public bool VrModeOnly { get; set; }
|
||||
|
||||
/// The GvrPointerScrollInput used to route Scroll Events through _EventSystem_
|
||||
public GvrPointerScrollInput ScrollInput { get; set; }
|
||||
|
||||
/// PointerEventData from the most recent frame.
|
||||
public PointerEventData CurrentEventData { get; private set; }
|
||||
|
||||
/// The GvrBasePointer which will be responding to pointer events.
|
||||
public GvrBasePointer Pointer {
|
||||
get {
|
||||
return pointer;
|
||||
}
|
||||
set {
|
||||
if (pointer == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
TryExitPointer();
|
||||
|
||||
pointer = value;
|
||||
}
|
||||
}
|
||||
|
||||
private GvrBasePointer pointer;
|
||||
private Vector2 lastPose;
|
||||
private bool isPointerHovering = false;
|
||||
|
||||
// Active state
|
||||
private bool isActive = false;
|
||||
|
||||
public bool ShouldActivateModule() {
|
||||
bool isVrModeEnabled = !VrModeOnly;
|
||||
isVrModeEnabled |= XRSettings.enabled;
|
||||
|
||||
bool activeState = ModuleController.ShouldActivate() && isVrModeEnabled;
|
||||
|
||||
if (activeState != isActive) {
|
||||
isActive = activeState;
|
||||
}
|
||||
|
||||
return activeState;
|
||||
}
|
||||
|
||||
public void DeactivateModule() {
|
||||
TryExitPointer();
|
||||
ModuleController.Deactivate();
|
||||
if (CurrentEventData != null) {
|
||||
HandlePendingClick();
|
||||
HandlePointerExitAndEnter(CurrentEventData, null);
|
||||
CurrentEventData = null;
|
||||
}
|
||||
ModuleController.eventSystem.SetSelectedGameObject(null, ModuleController.GetBaseEventData());
|
||||
}
|
||||
|
||||
public bool IsPointerOverGameObject(int pointerId) {
|
||||
return CurrentEventData != null && CurrentEventData.pointerEnter != null;
|
||||
}
|
||||
|
||||
public void Process() {
|
||||
// If the pointer is inactive, make sure it is exited if necessary.
|
||||
if (!IsPointerActiveAndAvailable()) {
|
||||
TryExitPointer();
|
||||
}
|
||||
|
||||
// Save the previous Game Object
|
||||
GameObject previousObject = GetCurrentGameObject();
|
||||
|
||||
CastRay();
|
||||
UpdateCurrentObject(previousObject);
|
||||
UpdatePointer(previousObject);
|
||||
|
||||
// True during the frame that the trigger has been pressed.
|
||||
bool triggerDown = false;
|
||||
// True if the trigger is held down.
|
||||
bool triggering = false;
|
||||
|
||||
if (IsPointerActiveAndAvailable()) {
|
||||
triggerDown = Pointer.TriggerDown;
|
||||
triggering = Pointer.Triggering;
|
||||
}
|
||||
|
||||
bool handlePendingClickRequired = !triggering;
|
||||
|
||||
// Handle input
|
||||
if (!triggerDown && triggering) {
|
||||
HandleDrag();
|
||||
} else if (triggerDown && !CurrentEventData.eligibleForClick) {
|
||||
// New trigger action.
|
||||
HandleTriggerDown();
|
||||
} else if (handlePendingClickRequired) {
|
||||
// Check if there is a pending click to handle.
|
||||
HandlePendingClick();
|
||||
}
|
||||
|
||||
ScrollInput.HandleScroll(GetCurrentGameObject(), CurrentEventData, Pointer, EventExecutor);
|
||||
}
|
||||
|
||||
private void CastRay() {
|
||||
Vector2 currentPose = lastPose;
|
||||
if (IsPointerActiveAndAvailable()) {
|
||||
currentPose = GvrMathHelpers.NormalizedCartesianToSpherical(Pointer.PointerTransform.forward);
|
||||
}
|
||||
|
||||
if (CurrentEventData == null) {
|
||||
CurrentEventData = new PointerEventData(ModuleController.eventSystem);
|
||||
lastPose = currentPose;
|
||||
}
|
||||
|
||||
// Store the previous raycast result.
|
||||
RaycastResult previousRaycastResult = CurrentEventData.pointerCurrentRaycast;
|
||||
|
||||
// The initial cast must use the enter radius.
|
||||
if (IsPointerActiveAndAvailable()) {
|
||||
Pointer.ShouldUseExitRadiusForRaycast = false;
|
||||
}
|
||||
|
||||
// Cast a ray into the scene
|
||||
CurrentEventData.Reset();
|
||||
// Set the position to the center of the camera.
|
||||
// This is only necessary if using the built-in Unity raycasters.
|
||||
RaycastResult raycastResult;
|
||||
CurrentEventData.position = GvrVRHelpers.GetViewportCenter();
|
||||
bool isPointerActiveAndAvailable = IsPointerActiveAndAvailable();
|
||||
if (isPointerActiveAndAvailable) {
|
||||
RaycastAll();
|
||||
raycastResult = ModuleController.FindFirstRaycast(ModuleController.RaycastResultCache);
|
||||
if (Pointer.ControllerInputDevice == null || Pointer.ControllerInputDevice.IsDominantHand) {
|
||||
CurrentEventData.pointerId = (int)GvrControllerHand.Dominant;
|
||||
} else {
|
||||
CurrentEventData.pointerId = (int)GvrControllerHand.NonDominant;
|
||||
}
|
||||
} else {
|
||||
raycastResult = new RaycastResult();
|
||||
raycastResult.Clear();
|
||||
}
|
||||
|
||||
// If we were already pointing at an object we must check that object against the exit radius
|
||||
// to make sure we are no longer pointing at it to prevent flicker.
|
||||
if (previousRaycastResult.gameObject != null
|
||||
&& raycastResult.gameObject != previousRaycastResult.gameObject
|
||||
&& isPointerActiveAndAvailable) {
|
||||
Pointer.ShouldUseExitRadiusForRaycast = true;
|
||||
RaycastAll();
|
||||
RaycastResult firstResult = ModuleController.FindFirstRaycast(ModuleController.RaycastResultCache);
|
||||
if (firstResult.gameObject == previousRaycastResult.gameObject) {
|
||||
raycastResult = firstResult;
|
||||
}
|
||||
}
|
||||
|
||||
if (raycastResult.gameObject != null && raycastResult.worldPosition == Vector3.zero) {
|
||||
raycastResult.worldPosition =
|
||||
GvrMathHelpers.GetIntersectionPosition(CurrentEventData.enterEventCamera, raycastResult);
|
||||
}
|
||||
|
||||
CurrentEventData.pointerCurrentRaycast = raycastResult;
|
||||
|
||||
// Find the real screen position associated with the raycast
|
||||
// Based on the results of the hit and the state of the pointerData.
|
||||
if (raycastResult.gameObject != null) {
|
||||
CurrentEventData.position = raycastResult.screenPosition;
|
||||
} else if (IsPointerActiveAndAvailable() && CurrentEventData.enterEventCamera != null) {
|
||||
Vector3 pointerPos = Pointer.MaxPointerEndPoint;
|
||||
CurrentEventData.position = CurrentEventData.enterEventCamera.WorldToScreenPoint(pointerPos);
|
||||
}
|
||||
|
||||
ModuleController.RaycastResultCache.Clear();
|
||||
CurrentEventData.delta = currentPose - lastPose;
|
||||
lastPose = currentPose;
|
||||
|
||||
// Check to make sure the Raycaster being used is a GvrRaycaster.
|
||||
if (raycastResult.module != null
|
||||
&& !(raycastResult.module is GvrPointerGraphicRaycaster)
|
||||
&& !(raycastResult.module is GvrPointerPhysicsRaycaster)) {
|
||||
Debug.LogWarning("Using Raycaster (Raycaster: " + raycastResult.module.GetType() +
|
||||
", Object: " + raycastResult.module.name + "). It is recommended to use " +
|
||||
"GvrPointerPhysicsRaycaster or GvrPointerGrahpicRaycaster with GvrPointerInputModule.");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCurrentObject(GameObject previousObject) {
|
||||
if (CurrentEventData == null) {
|
||||
return;
|
||||
}
|
||||
// Send enter events and update the highlight.
|
||||
GameObject currentObject = GetCurrentGameObject(); // Get the pointer target
|
||||
HandlePointerExitAndEnter(CurrentEventData, currentObject);
|
||||
|
||||
// Update the current selection, or clear if it is no longer the current object.
|
||||
var selected = EventExecutor.GetEventHandler<ISelectHandler>(currentObject);
|
||||
if (selected == ModuleController.eventSystem.currentSelectedGameObject) {
|
||||
EventExecutor.Execute(ModuleController.eventSystem.currentSelectedGameObject, ModuleController.GetBaseEventData(),
|
||||
ExecuteEvents.updateSelectedHandler);
|
||||
} else {
|
||||
ModuleController.eventSystem.SetSelectedGameObject(null, CurrentEventData);
|
||||
}
|
||||
|
||||
// Execute hover event.
|
||||
if (currentObject != null && currentObject == previousObject) {
|
||||
EventExecutor.ExecuteHierarchy(currentObject, CurrentEventData, GvrExecuteEventsExtension.pointerHoverHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePointer(GameObject previousObject) {
|
||||
if (CurrentEventData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject currentObject = GetCurrentGameObject(); // Get the pointer target
|
||||
bool isPointerActiveAndAvailable = IsPointerActiveAndAvailable();
|
||||
|
||||
bool isInteractive = CurrentEventData.pointerPress != null ||
|
||||
EventExecutor.GetEventHandler<IPointerClickHandler>(currentObject) != null ||
|
||||
EventExecutor.GetEventHandler<IDragHandler>(currentObject) != null;
|
||||
|
||||
if (isPointerHovering && currentObject != null && currentObject == previousObject) {
|
||||
if (isPointerActiveAndAvailable) {
|
||||
Pointer.OnPointerHover(CurrentEventData.pointerCurrentRaycast, isInteractive);
|
||||
}
|
||||
} else {
|
||||
// If the object's don't match or the hovering object has been destroyed
|
||||
// then the pointer has exited.
|
||||
if (previousObject != null || (currentObject == null && isPointerHovering)) {
|
||||
if (isPointerActiveAndAvailable) {
|
||||
Pointer.OnPointerExit(previousObject);
|
||||
}
|
||||
isPointerHovering = false;
|
||||
}
|
||||
|
||||
if (currentObject != null) {
|
||||
if (isPointerActiveAndAvailable) {
|
||||
Pointer.OnPointerEnter(CurrentEventData.pointerCurrentRaycast, isInteractive);
|
||||
}
|
||||
isPointerHovering = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ShouldStartDrag(Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold) {
|
||||
if (!useDragThreshold)
|
||||
return true;
|
||||
|
||||
return (pressPos - currentPos).sqrMagnitude >= threshold * threshold;
|
||||
}
|
||||
|
||||
private void HandleDrag() {
|
||||
bool moving = CurrentEventData.IsPointerMoving();
|
||||
bool shouldStartDrag = ShouldStartDrag(CurrentEventData.pressPosition,
|
||||
CurrentEventData.position,
|
||||
ModuleController.eventSystem.pixelDragThreshold,
|
||||
CurrentEventData.useDragThreshold);
|
||||
|
||||
if (moving && shouldStartDrag && CurrentEventData.pointerDrag != null && !CurrentEventData.dragging) {
|
||||
EventExecutor.Execute(CurrentEventData.pointerDrag, CurrentEventData,
|
||||
ExecuteEvents.beginDragHandler);
|
||||
CurrentEventData.dragging = true;
|
||||
}
|
||||
|
||||
// Drag notification
|
||||
if (CurrentEventData.dragging && moving && CurrentEventData.pointerDrag != null) {
|
||||
// Before doing drag we should cancel any pointer down state
|
||||
// And clear selection!
|
||||
if (CurrentEventData.pointerPress != CurrentEventData.pointerDrag) {
|
||||
EventExecutor.Execute(CurrentEventData.pointerPress, CurrentEventData, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
CurrentEventData.eligibleForClick = false;
|
||||
CurrentEventData.pointerPress = null;
|
||||
CurrentEventData.rawPointerPress = null;
|
||||
}
|
||||
|
||||
EventExecutor.Execute(CurrentEventData.pointerDrag, CurrentEventData, ExecuteEvents.dragHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePendingClick() {
|
||||
if (CurrentEventData == null || (!CurrentEventData.eligibleForClick && !CurrentEventData.dragging)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPointerActiveAndAvailable()) {
|
||||
Pointer.OnPointerClickUp();
|
||||
}
|
||||
|
||||
var go = CurrentEventData.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// Send pointer up and click events.
|
||||
EventExecutor.Execute(CurrentEventData.pointerPress, CurrentEventData, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
GameObject pointerClickHandler = EventExecutor.GetEventHandler<IPointerClickHandler>(go);
|
||||
if (CurrentEventData.pointerPress == pointerClickHandler && CurrentEventData.eligibleForClick) {
|
||||
EventExecutor.Execute(CurrentEventData.pointerPress, CurrentEventData, ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
|
||||
if (CurrentEventData != null && CurrentEventData.pointerDrag != null && CurrentEventData.dragging) {
|
||||
EventExecutor.ExecuteHierarchy(go, CurrentEventData, ExecuteEvents.dropHandler);
|
||||
EventExecutor.Execute(CurrentEventData.pointerDrag, CurrentEventData, ExecuteEvents.endDragHandler);
|
||||
}
|
||||
|
||||
if (CurrentEventData != null) {
|
||||
// Clear the click state.
|
||||
CurrentEventData.pointerPress = null;
|
||||
CurrentEventData.rawPointerPress = null;
|
||||
CurrentEventData.eligibleForClick = false;
|
||||
CurrentEventData.clickCount = 0;
|
||||
CurrentEventData.clickTime = 0;
|
||||
CurrentEventData.pointerDrag = null;
|
||||
CurrentEventData.dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleTriggerDown() {
|
||||
var go = CurrentEventData.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// Send pointer down event.
|
||||
CurrentEventData.pressPosition = CurrentEventData.position;
|
||||
CurrentEventData.pointerPressRaycast = CurrentEventData.pointerCurrentRaycast;
|
||||
CurrentEventData.pointerPress =
|
||||
EventExecutor.ExecuteHierarchy(go, CurrentEventData, ExecuteEvents.pointerDownHandler) ??
|
||||
EventExecutor.GetEventHandler<IPointerClickHandler>(go);
|
||||
|
||||
// Save the pending click state.
|
||||
CurrentEventData.rawPointerPress = go;
|
||||
CurrentEventData.eligibleForClick = true;
|
||||
CurrentEventData.delta = Vector2.zero;
|
||||
CurrentEventData.dragging = false;
|
||||
CurrentEventData.useDragThreshold = true;
|
||||
CurrentEventData.clickCount = 1;
|
||||
CurrentEventData.clickTime = Time.unscaledTime;
|
||||
|
||||
// Save the drag handler as well
|
||||
CurrentEventData.pointerDrag = EventExecutor.GetEventHandler<IDragHandler>(go);
|
||||
if (CurrentEventData.pointerDrag != null) {
|
||||
EventExecutor.Execute(CurrentEventData.pointerDrag, CurrentEventData, ExecuteEvents.initializePotentialDrag);
|
||||
}
|
||||
|
||||
if (IsPointerActiveAndAvailable()) {
|
||||
Pointer.OnPointerClickDown();
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject GetCurrentGameObject() {
|
||||
if (CurrentEventData != null) {
|
||||
return CurrentEventData.pointerCurrentRaycast.gameObject;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Modified version of BaseInputModule.HandlePointerExitAndEnter that calls EventExecutor instead of
|
||||
// UnityEngine.EventSystems.ExecuteEvents.
|
||||
private void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget) {
|
||||
// If we have no target or pointerEnter has been deleted then
|
||||
// just send exit events to anything we are tracking.
|
||||
// Afterwards, exit.
|
||||
if (newEnterTarget == null || currentPointerData.pointerEnter == null) {
|
||||
for (var i = 0; i < currentPointerData.hovered.Count; ++i) {
|
||||
EventExecutor.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler);
|
||||
}
|
||||
|
||||
currentPointerData.hovered.Clear();
|
||||
|
||||
if (newEnterTarget == null) {
|
||||
currentPointerData.pointerEnter = newEnterTarget;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have not changed hover target.
|
||||
if (newEnterTarget && currentPointerData.pointerEnter == newEnterTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject commonRoot = ModuleController.FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget);
|
||||
|
||||
// We already an entered object from last time.
|
||||
if (currentPointerData.pointerEnter != null) {
|
||||
// Send exit handler call to all elements in the chain
|
||||
// until we reach the new target, or null!
|
||||
Transform t = currentPointerData.pointerEnter.transform;
|
||||
|
||||
while (t != null) {
|
||||
// If we reach the common root break out!
|
||||
if (commonRoot != null && commonRoot.transform == t)
|
||||
break;
|
||||
|
||||
EventExecutor.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler);
|
||||
currentPointerData.hovered.Remove(t.gameObject);
|
||||
t = t.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Now issue the enter call up to but not including the common root.
|
||||
currentPointerData.pointerEnter = newEnterTarget;
|
||||
if (newEnterTarget != null) {
|
||||
Transform t = newEnterTarget.transform;
|
||||
|
||||
while (t != null && t.gameObject != commonRoot) {
|
||||
EventExecutor.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler);
|
||||
currentPointerData.hovered.Add(t.gameObject);
|
||||
t = t.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TryExitPointer() {
|
||||
if (Pointer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject currentGameObject = GetCurrentGameObject();
|
||||
if (currentGameObject) {
|
||||
Pointer.OnPointerExit(currentGameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsPointerActiveAndAvailable() {
|
||||
return pointer != null && pointer.IsAvailable;
|
||||
}
|
||||
|
||||
private void RaycastAll() {
|
||||
ModuleController.RaycastResultCache.Clear();
|
||||
ModuleController.eventSystem.RaycastAll(CurrentEventData, ModuleController.RaycastResultCache);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2e5fe232b3b94de2a12eb364ebc371e
|
||||
timeCreated: 1492661146
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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.EventSystems;
|
||||
|
||||
/// Provides an interface for executing events for _IEventSystemHandler_.
|
||||
public interface IGvrEventExecutor {
|
||||
bool Execute<T>(GameObject target,
|
||||
BaseEventData eventData,
|
||||
ExecuteEvents.EventFunction<T> functor)
|
||||
where T : IEventSystemHandler;
|
||||
|
||||
GameObject ExecuteHierarchy<T>(GameObject root,
|
||||
BaseEventData eventData,
|
||||
ExecuteEvents.EventFunction<T> callbackFunction)
|
||||
where T : IEventSystemHandler;
|
||||
|
||||
GameObject GetEventHandler<T>(GameObject root)
|
||||
where T : IEventSystemHandler;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 171f0a30d9ead4516a8fa319cfebe270
|
||||
timeCreated: 1493142648
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// Interface for manipulating an InputModule used by _GvrPointerInputModuleImpl_
|
||||
public interface IGvrInputModuleController {
|
||||
EventSystem eventSystem { get; }
|
||||
List<RaycastResult> RaycastResultCache { get; }
|
||||
|
||||
bool ShouldActivate();
|
||||
void Deactivate();
|
||||
GameObject FindCommonRoot(GameObject g1, GameObject g2);
|
||||
BaseEventData GetBaseEventData();
|
||||
RaycastResult FindFirstRaycast(List<RaycastResult> candidates);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 118ed627eb676472d803284d1a988bbd
|
||||
timeCreated: 1492665020
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user