Added VR libraries
This commit is contained in:
@@ -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