124 lines
4.3 KiB
C#
124 lines
4.3 KiB
C#
|
// 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);
|
||
|
}
|
||
|
}
|