|
|
- /************************************************************************************
-
- Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
-
- See SampleFramework license.txt for license terms. Unless required by applicable law
- or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied. See the license for specific
- language governing permissions and limitations under the license.
-
- ************************************************************************************/
-
- using System.Collections;
- using UnityEngine;
- using UnityEngine.Assertions;
-
- namespace OculusSampleFramework
- {
- /// <summary>
- /// An example visual controller for a button intended for the train sample scene.
- /// </summary>
- public class TrainButtonVisualController : MonoBehaviour
- {
- private const float LERP_TO_OLD_POS_DURATION = 1.0f;
- private const float LOCAL_SIZE_HALVED = 0.5f;
-
- [SerializeField] private MeshRenderer _meshRenderer = null;
- [SerializeField] private MeshRenderer _glowRenderer = null;
- [SerializeField] private ButtonController _buttonController = null;
- [SerializeField] private Color _buttonContactColor = new Color(0.51f, 0.78f, 0.92f, 1.0f);
- [SerializeField] private Color _buttonActionColor = new Color(0.24f, 0.72f, 0.98f, 1.0f);
-
- [SerializeField] private AudioSource _audioSource = null;
- [SerializeField] private AudioClip _actionSoundEffect = null;
-
- [SerializeField] private Transform _buttonContactTransform = null;
- [SerializeField] private float _contactMaxDisplacementDistance = 0.0141f;
-
- private Material _buttonMaterial;
- private Color _buttonDefaultColor;
- private int _materialColorId;
-
- private bool _buttonInContactOrActionStates = false;
-
- private Coroutine _lerpToOldPositionCr = null;
- private Vector3 _oldPosition;
-
- private void Awake()
- {
- Assert.IsNotNull(_meshRenderer);
- Assert.IsNotNull(_glowRenderer);
- Assert.IsNotNull(_buttonController);
- Assert.IsNotNull(_audioSource);
- Assert.IsNotNull(_actionSoundEffect);
-
- Assert.IsNotNull(_buttonContactTransform);
- _materialColorId = Shader.PropertyToID("_Color");
- _buttonMaterial = _meshRenderer.material;
- _buttonDefaultColor = _buttonMaterial.GetColor(_materialColorId);
-
- _oldPosition = transform.localPosition;
- }
-
- private void OnDestroy()
- {
- if (_buttonMaterial != null)
- {
- Destroy(_buttonMaterial);
- }
- }
-
- private void OnEnable()
- {
- _buttonController.InteractableStateChanged.AddListener(InteractableStateChanged);
- _buttonController.ContactZoneEvent += ActionOrInContactZoneStayEvent;
- _buttonController.ActionZoneEvent += ActionOrInContactZoneStayEvent;
- _buttonInContactOrActionStates = false;
- }
-
- private void OnDisable()
- {
- if (_buttonController != null)
- {
- _buttonController.InteractableStateChanged.RemoveListener(InteractableStateChanged);
- _buttonController.ContactZoneEvent -= ActionOrInContactZoneStayEvent;
- _buttonController.ActionZoneEvent -= ActionOrInContactZoneStayEvent;
- }
- }
-
- private void ActionOrInContactZoneStayEvent(ColliderZoneArgs collisionArgs)
- {
- if (!_buttonInContactOrActionStates || collisionArgs.CollidingTool.IsFarFieldTool)
- {
- return;
- }
-
- // calculate how much the button should be pushed inwards. based on contact zone.
- // assume collider is uniform 1x1x1 cube, and all scaling, etc is done on transform component
- // another way to test distances is to measure distance to plane that represents where
- // button translation must stop
- Vector3 buttonScale = _buttonContactTransform.localScale;
- Vector3 interactionPosition = collisionArgs.CollidingTool.InteractionPosition;
- Vector3 localSpacePosition = _buttonContactTransform.InverseTransformPoint(
- interactionPosition);
- // calculate offset in local space. so bias coordinates from 0.5,-0.5 to 0, -1.
- // 0 is no offset, 1.0 in local space is max offset pushing inwards
- Vector3 offsetVector = localSpacePosition - LOCAL_SIZE_HALVED * Vector3.one;
- // affect offset by button scale. only care about y (since y goes inwards)
- float scaledLocalSpaceOffset = offsetVector.y * buttonScale.y;
-
- // restrict button movement. can only go so far in negative direction, and cannot
- // be positive (which would cause the button to "stick out")
- if (scaledLocalSpaceOffset > -_contactMaxDisplacementDistance && scaledLocalSpaceOffset
- <= 0.0f)
- {
- transform.localPosition = new Vector3(_oldPosition.x, _oldPosition.y +
- scaledLocalSpaceOffset, _oldPosition.z);
- }
- }
-
- private void InteractableStateChanged(InteractableStateArgs obj)
- {
- _buttonInContactOrActionStates = false;
- _glowRenderer.gameObject.SetActive(obj.NewInteractableState >
- InteractableState.Default);
- switch (obj.NewInteractableState)
- {
- case InteractableState.ContactState:
- StopResetLerping();
- _buttonMaterial.SetColor(_materialColorId, _buttonContactColor);
- _buttonInContactOrActionStates = true;
- break;
- case InteractableState.ProximityState:
- _buttonMaterial.SetColor(_materialColorId, _buttonDefaultColor);
- LerpToOldPosition();
- break;
- case InteractableState.ActionState:
- StopResetLerping();
- _buttonMaterial.SetColor(_materialColorId, _buttonActionColor);
- PlaySound(_actionSoundEffect);
- _buttonInContactOrActionStates = true;
- break;
- default:
- _buttonMaterial.SetColor(_materialColorId, _buttonDefaultColor);
- LerpToOldPosition();
- break;
- }
- }
-
- private void PlaySound(AudioClip clip)
- {
- _audioSource.timeSamples = 0;
- _audioSource.clip = clip;
- _audioSource.Play();
- }
-
- private void StopResetLerping()
- {
- if (_lerpToOldPositionCr != null)
- {
- StopCoroutine(_lerpToOldPositionCr);
- }
- }
-
- private void LerpToOldPosition()
- {
- if ((transform.localPosition - _oldPosition).sqrMagnitude < Mathf.Epsilon)
- {
- return;
- }
-
- StopResetLerping();
- _lerpToOldPositionCr = StartCoroutine(ResetPosition());
- }
-
- private IEnumerator ResetPosition()
- {
- var startTime = Time.time;
- var endTime = Time.time + LERP_TO_OLD_POS_DURATION;
-
- while (Time.time < endTime)
- {
- transform.localPosition = Vector3.Lerp(transform.localPosition, _oldPosition,
- (Time.time - startTime) / LERP_TO_OLD_POS_DURATION);
- yield return null;
- }
-
- transform.localPosition = _oldPosition;
- _lerpToOldPositionCr = null;
- }
- }
- }
|