FittsLaw/Assets/GoogleVR/Scripts/Controller/GvrLaserPointer.cs

124 lines
4.3 KiB
C#
Raw Normal View History

2018-10-08 23:54:11 -04:00
// 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.
// The controller is not available for versions of Unity without the
// GVR native integration.
using UnityEngine;
using UnityEngine.EventSystems;
/// Implementation of GvrBasePointer for a laser pointer visual.
/// This script should be attached to the controller object.
/// The laser visual is important to help users locate their cursor
/// when its not directly in their field of view.
[RequireComponent(typeof(GvrLaserVisual))]
[HelpURL("https://developers.google.com/vr/unity/reference/class/GvrLaserPointer")]
public class GvrLaserPointer : GvrBasePointer {
[Tooltip("Distance from the pointer that raycast hits will be detected.")]
public float maxPointerDistance = 20.0f;
[Tooltip("Distance from the pointer that the reticle will be drawn at when hitting nothing.")]
public float defaultReticleDistance = 20.0f;
[Tooltip("By default, the length of the laser is used as the CameraRayIntersectionDistance. " +
"Set this field to a non-zero value to override it.")]
public float overrideCameraRayIntersectionDistance;
/// The percentage of the reticle mesh that shows the reticle.
/// The rest of the reticle mesh is transparent.
private const float RETICLE_VISUAL_RATIO = 0.1f;
public GvrLaserVisual LaserVisual { get; private set; }
private bool isHittingTarget;
public override float MaxPointerDistance {
get {
return maxPointerDistance;
}
}
public override float CameraRayIntersectionDistance {
get {
if (overrideCameraRayIntersectionDistance != 0.0f) {
return overrideCameraRayIntersectionDistance;
}
return LaserVisual != null ?
LaserVisual.maxLaserDistance : overrideCameraRayIntersectionDistance;
}
}
public override void OnPointerEnter(RaycastResult raycastResult, bool isInteractive) {
LaserVisual.SetDistance(raycastResult.distance);
isHittingTarget = true;
}
public override void OnPointerHover(RaycastResult raycastResult, bool isInteractive) {
LaserVisual.SetDistance(raycastResult.distance);
isHittingTarget = true;
}
public override void OnPointerExit(GameObject previousObject) {
// Don't set the distance immediately.
// If we exit/enter an object on the same frame, then SetDistance
// will be called twice which could cause an issue with lerping the reticle.
// If we don't re-enter a new object, the distance will be set in Update.
isHittingTarget = false;
}
public override void OnPointerClickDown() {
}
public override void OnPointerClickUp() {
}
public override void GetPointerRadius(out float enterRadius, out float exitRadius) {
if (LaserVisual.reticle != null) {
float reticleScale = LaserVisual.reticle.transform.localScale.x;
// Fixed size for enter radius to avoid flickering.
// This will cause some slight variability based on the distance of the object
// from the camera, and is optimized for the average case.
enterRadius = LaserVisual.reticle.sizeMeters * 0.5f * RETICLE_VISUAL_RATIO;
// Dynamic size for exit radius.
// Always correct because we know the intersection point of the object and can
// therefore use the correct radius based on the object's distance from the camera.
exitRadius = reticleScale * LaserVisual.reticle.ReticleMeshSizeMeters * RETICLE_VISUAL_RATIO;
} else {
enterRadius = 0.0f;
exitRadius = 0.0f;
}
}
void Awake() {
LaserVisual = GetComponent<GvrLaserVisual>();
}
protected override void Start() {
base.Start();
LaserVisual.GetPointForDistanceFunction = GetPointAlongPointer;
LaserVisual.SetDistance(defaultReticleDistance, true);
}
void Update() {
if (isHittingTarget) {
return;
}
LaserVisual.SetDistance(defaultReticleDistance);
}
}