215 lines
6.5 KiB
C#
215 lines
6.5 KiB
C#
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
* All rights reserved.
|
|
*
|
|
* Licensed under the Oculus SDK License Agreement (the "License");
|
|
* you may not use the Oculus SDK except in compliance with the License,
|
|
* which is provided at the time of installation or download, or which
|
|
* otherwise accompanies this software in either electronic or hard copy form.
|
|
*
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://developer.oculus.com/licenses/oculussdk/
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
|
* 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;
|
|
|
|
namespace Oculus.Interaction
|
|
{
|
|
/// <summary>
|
|
/// Gradually pulls the selected interactable towards your interactor.
|
|
/// </summary>
|
|
public class AutoMoveTowardsTargetProvider : MonoBehaviour, IMovementProvider
|
|
{
|
|
[SerializeField]
|
|
private PoseTravelData _travellingData = PoseTravelData.DEFAULT;
|
|
public PoseTravelData TravellingData
|
|
{
|
|
get
|
|
{
|
|
return _travellingData;
|
|
}
|
|
set
|
|
{
|
|
_travellingData = value;
|
|
}
|
|
}
|
|
|
|
[SerializeField, Interface(typeof(IPointableElement))]
|
|
private UnityEngine.Object _pointableElement;
|
|
public IPointableElement PointableElement { get; private set; }
|
|
|
|
private bool _started;
|
|
|
|
public List<AutoMoveTowardsTarget> _movers = new List<AutoMoveTowardsTarget>();
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
PointableElement = _pointableElement as IPointableElement;
|
|
}
|
|
|
|
protected virtual void Start()
|
|
{
|
|
this.BeginStart(ref _started);
|
|
this.AssertField(_pointableElement, nameof(_pointableElement));
|
|
this.EndStart(ref _started);
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
for (int i = _movers.Count - 1; i >= 0; i--)
|
|
{
|
|
AutoMoveTowardsTarget mover = _movers[i];
|
|
if (mover.Aborting)
|
|
{
|
|
mover.Tick();
|
|
if (mover.Stopped)
|
|
{
|
|
_movers.Remove(mover);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public IMovement CreateMovement()
|
|
{
|
|
AutoMoveTowardsTarget mover = new AutoMoveTowardsTarget(_travellingData, PointableElement);
|
|
mover.WhenAborted += HandleAborted;
|
|
return mover;
|
|
}
|
|
|
|
private void HandleAborted(AutoMoveTowardsTarget mover)
|
|
{
|
|
mover.WhenAborted -= HandleAborted;
|
|
_movers.Add(mover);
|
|
}
|
|
|
|
#region Inject
|
|
|
|
public void InjectAllAutoMoveTowardsTargetProvider(IPointableElement pointableElement)
|
|
{
|
|
InjectPointableElement(pointableElement);
|
|
}
|
|
|
|
public void InjectPointableElement(IPointableElement pointableElement)
|
|
{
|
|
PointableElement = pointableElement;
|
|
_pointableElement = pointableElement as UnityEngine.Object;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// This IMovement stores the initial Pose, and in case
|
|
/// of an aborted movement it will finish it itself.
|
|
/// </summary>
|
|
public class AutoMoveTowardsTarget : IMovement
|
|
{
|
|
private PoseTravelData _travellingData;
|
|
private IPointableElement _pointableElement;
|
|
|
|
public Pose Pose => _tween.Pose;
|
|
public bool Stopped => _tween == null || _tween.Stopped;
|
|
public bool Aborting { get; private set; }
|
|
|
|
public Action<AutoMoveTowardsTarget> WhenAborted = delegate { };
|
|
|
|
private UniqueIdentifier _identifier;
|
|
public int Identifier => _identifier.ID;
|
|
|
|
private Tween _tween;
|
|
private Pose _target;
|
|
private Pose _source;
|
|
private bool _eventRegistered;
|
|
|
|
public AutoMoveTowardsTarget(PoseTravelData travellingData, IPointableElement pointableElement)
|
|
{
|
|
_identifier = UniqueIdentifier.Generate(Context.Global.GetInstance(), this);
|
|
_travellingData = travellingData;
|
|
_pointableElement = pointableElement;
|
|
}
|
|
|
|
public void MoveTo(Pose target)
|
|
{
|
|
AbortSelfAligment();
|
|
_target = target;
|
|
_tween = _travellingData.CreateTween(_source, target);
|
|
if (!_eventRegistered)
|
|
{
|
|
_pointableElement.WhenPointerEventRaised += HandlePointerEventRaised;
|
|
_eventRegistered = true;
|
|
}
|
|
}
|
|
|
|
public void UpdateTarget(Pose target)
|
|
{
|
|
_target = target;
|
|
_tween.UpdateTarget(_target);
|
|
}
|
|
|
|
public void StopAndSetPose(Pose pose)
|
|
{
|
|
if (_eventRegistered)
|
|
{
|
|
_pointableElement.WhenPointerEventRaised -= HandlePointerEventRaised;
|
|
_eventRegistered = false;
|
|
}
|
|
|
|
_source = pose;
|
|
if (_tween != null && !_tween.Stopped)
|
|
{
|
|
GeneratePointerEvent(PointerEventType.Hover);
|
|
GeneratePointerEvent(PointerEventType.Select);
|
|
Aborting = true;
|
|
WhenAborted.Invoke(this);
|
|
}
|
|
}
|
|
|
|
public void Tick()
|
|
{
|
|
_tween.Tick();
|
|
if (Aborting)
|
|
{
|
|
GeneratePointerEvent(PointerEventType.Move);
|
|
if (_tween.Stopped)
|
|
{
|
|
AbortSelfAligment();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void HandlePointerEventRaised(PointerEvent evt)
|
|
{
|
|
if (evt.Type == PointerEventType.Select || evt.Type == PointerEventType.Unselect)
|
|
{
|
|
AbortSelfAligment();
|
|
}
|
|
}
|
|
|
|
private void AbortSelfAligment()
|
|
{
|
|
if (Aborting)
|
|
{
|
|
Aborting = false;
|
|
|
|
GeneratePointerEvent(PointerEventType.Unselect);
|
|
GeneratePointerEvent(PointerEventType.Unhover);
|
|
}
|
|
}
|
|
|
|
private void GeneratePointerEvent(PointerEventType pointerEventType)
|
|
{
|
|
PointerEvent evt = new PointerEvent(Identifier, pointerEventType, Pose);
|
|
_pointableElement.ProcessPointerEvent(evt);
|
|
}
|
|
}
|
|
}
|