165 lines
4.6 KiB
C#
165 lines
4.6 KiB
C#
namespace Mapbox.Examples
|
|
{
|
|
using Mapbox.Unity.Location;
|
|
using UnityEngine;
|
|
|
|
public class RotateWithLocationProvider : MonoBehaviour
|
|
{
|
|
/// <summary>
|
|
/// Location property used for rotation: false=Heading (default), true=Orientation
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Per default 'UserHeading' (direction the device is moving) is used for rotation. Check to use 'DeviceOrientation' (where the device is facing)")]
|
|
bool _useDeviceOrientation;
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Only evaluated when 'Use Device Orientation' is checked. Subtracts UserHeading from DeviceOrientation. Useful if map is rotated by UserHeading and DeviceOrientation should be displayed relative to the heading.")]
|
|
bool _subtractUserHeading;
|
|
|
|
/// <summary>
|
|
/// The rate at which the transform's rotation tries catch up to the provided heading.
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("The rate at which the transform's rotation tries catch up to the provided heading. ")]
|
|
float _rotationFollowFactor = 1;
|
|
|
|
/// <summary>
|
|
/// Set this to true if you'd like to adjust the rotation of a RectTransform (in a UI canvas) with the heading.
|
|
/// </summary>
|
|
[SerializeField]
|
|
bool _rotateZ;
|
|
|
|
/// <summary>
|
|
/// <para>Set this to true if you'd like to adjust the sign of the rotation angle.</para>
|
|
/// <para>eg angle passed in 63.5, angle that should be used for rotation: -63.5.</para>
|
|
/// <para>This might be needed when rotating the map and not objects on the map.</para>
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Set this to true if you'd like to adjust the sign of the rotation angle. eg angle passed in 63.5, angle that should be used for rotation: -63.5.")]
|
|
bool _useNegativeAngle;
|
|
|
|
/// <summary>
|
|
/// Use a mock <see cref="T:Mapbox.Unity.Location.TransformLocationProvider"/>,
|
|
/// rather than a <see cref="T:Mapbox.Unity.Location.EditorLocationProvider"/>.
|
|
/// </summary>
|
|
[SerializeField]
|
|
bool _useTransformLocationProvider;
|
|
|
|
Quaternion _targetRotation;
|
|
|
|
/// <summary>
|
|
/// The location provider.
|
|
/// This is public so you change which concrete <see cref="ILocationProvider"/> to use at runtime.
|
|
/// </summary>
|
|
ILocationProvider _locationProvider;
|
|
public ILocationProvider LocationProvider
|
|
{
|
|
private get
|
|
{
|
|
if (_locationProvider == null)
|
|
{
|
|
_locationProvider = _useTransformLocationProvider ?
|
|
LocationProviderFactory.Instance.TransformLocationProvider : LocationProviderFactory.Instance.DefaultLocationProvider;
|
|
}
|
|
|
|
return _locationProvider;
|
|
}
|
|
set
|
|
{
|
|
if (_locationProvider != null)
|
|
{
|
|
_locationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
|
|
|
|
}
|
|
_locationProvider = value;
|
|
_locationProvider.OnLocationUpdated += LocationProvider_OnLocationUpdated;
|
|
}
|
|
}
|
|
|
|
Vector3 _targetPosition;
|
|
|
|
void Start()
|
|
{
|
|
LocationProvider.OnLocationUpdated += LocationProvider_OnLocationUpdated;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
if (LocationProvider != null)
|
|
{
|
|
LocationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
|
|
}
|
|
}
|
|
|
|
void LocationProvider_OnLocationUpdated(Location location)
|
|
{
|
|
|
|
float rotationAngle = _useDeviceOrientation ? location.DeviceOrientation : location.UserHeading;
|
|
|
|
if (_useNegativeAngle) { rotationAngle *= -1f; }
|
|
|
|
// 'Orientation' changes all the time, pass through immediately
|
|
if (_useDeviceOrientation)
|
|
{
|
|
if (_subtractUserHeading)
|
|
{
|
|
if (rotationAngle > location.UserHeading)
|
|
{
|
|
rotationAngle = 360 - (rotationAngle - location.UserHeading);
|
|
}
|
|
else
|
|
{
|
|
rotationAngle = location.UserHeading - rotationAngle + 360;
|
|
}
|
|
|
|
if (rotationAngle < 0) { rotationAngle += 360; }
|
|
if (rotationAngle >= 360) { rotationAngle -= 360; }
|
|
}
|
|
_targetRotation = Quaternion.Euler(getNewEulerAngles(rotationAngle));
|
|
}
|
|
else
|
|
{
|
|
// if rotating by 'Heading' only do it if heading has a new value
|
|
if (location.IsUserHeadingUpdated)
|
|
{
|
|
_targetRotation = Quaternion.Euler(getNewEulerAngles(rotationAngle));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private Vector3 getNewEulerAngles(float newAngle)
|
|
{
|
|
var localRotation = transform.localRotation;
|
|
var currentEuler = localRotation.eulerAngles;
|
|
var euler = Mapbox.Unity.Constants.Math.Vector3Zero;
|
|
|
|
if (_rotateZ)
|
|
{
|
|
euler.z = -newAngle;
|
|
|
|
euler.x = currentEuler.x;
|
|
euler.y = currentEuler.y;
|
|
}
|
|
else
|
|
{
|
|
euler.y = -newAngle;
|
|
|
|
euler.x = currentEuler.x;
|
|
euler.z = currentEuler.z;
|
|
}
|
|
|
|
return euler;
|
|
}
|
|
|
|
|
|
void Update()
|
|
{
|
|
transform.localRotation = Quaternion.Lerp(transform.localRotation, _targetRotation, Time.deltaTime * _rotationFollowFactor);
|
|
}
|
|
}
|
|
}
|