Heroes_of_Hiis/Assets/Oculus/Interaction/Runtime/Scripts/Input/DataSource.cs

203 lines
6.1 KiB
C#

/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities 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 UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Serialization;
namespace Oculus.Interaction.Input
{
public interface IDataSource
{
int CurrentDataVersion { get; }
void MarkInputDataRequiresUpdate();
event Action InputDataAvailable;
}
public interface IDataSource<TData, TConfig> : IDataSource
{
TData GetData();
TConfig Config { get; }
}
public abstract class DataSource<TData, TConfig> : MonoBehaviour, IDataSource<TData, TConfig>
where TData : class, ICopyFrom<TData>, new()
{
public bool Started { get; private set; }
protected bool _started = false;
private bool _requiresUpdate = true;
[Flags]
public enum UpdateModeFlags
{
Manual = 0,
UnityUpdate = 1 << 0,
UnityFixedUpdate = 1 << 1,
UnityLateUpdate = 1 << 2,
AfterPreviousStep = 1 << 3
}
[Header("Update")]
[SerializeField]
private UpdateModeFlags _updateMode;
public UpdateModeFlags UpdateMode => _updateMode;
[SerializeField, Interface(typeof(IDataSource)), Optional]
private MonoBehaviour _updateAfter;
private IDataSource UpdateAfter;
private int _currentDataVersion;
protected bool UpdateModeAfterPrevious => (_updateMode & UpdateModeFlags.AfterPreviousStep) != 0;
// Notifies that new data is available for query via GetData() method.
// Do not use this event if you are reading data from a `Oculus.Interaction.Input.Hand` object,
// instead, use the `Updated` event on that class.
public event Action InputDataAvailable = delegate { };
public virtual int CurrentDataVersion => _currentDataVersion;
#region Unity Lifecycle
protected virtual void Start()
{
this.BeginStart(ref _started);
if (_updateAfter != null)
{
UpdateAfter = _updateAfter as IDataSource;
Assert.IsNotNull(UpdateAfter);
}
Started = true;
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
if (Started && UpdateModeAfterPrevious && UpdateAfter != null)
{
UpdateAfter.InputDataAvailable += MarkInputDataRequiresUpdate;
}
}
}
protected virtual void OnDisable()
{
if (_started)
{
if (UpdateAfter != null)
{
UpdateAfter.InputDataAvailable -= MarkInputDataRequiresUpdate;
}
}
}
protected virtual void Update()
{
if ((_updateMode & UpdateModeFlags.UnityUpdate) != 0)
{
MarkInputDataRequiresUpdate();
}
}
protected virtual void FixedUpdate()
{
if ((_updateMode & UpdateModeFlags.UnityFixedUpdate) != 0)
{
MarkInputDataRequiresUpdate();
}
}
protected virtual void LateUpdate()
{
if ((_updateMode & UpdateModeFlags.UnityLateUpdate) != 0)
{
MarkInputDataRequiresUpdate();
}
}
#endregion
protected void ResetUpdateAfter(IDataSource updateAfter, UpdateModeFlags updateMode)
{
bool wasActive = isActiveAndEnabled;
if (isActiveAndEnabled) { OnDisable(); }
_updateMode = updateMode;
UpdateAfter = updateAfter;
_requiresUpdate = true;
_currentDataVersion += 1;
if (wasActive) { OnEnable(); }
}
public TData GetData()
{
if (RequiresUpdate())
{
UpdateData();
_requiresUpdate = false;
}
return DataAsset;
}
protected bool RequiresUpdate()
{
return Started && _requiresUpdate && isActiveAndEnabled;
}
/// <summary>
/// Marks the DataAsset stored as outdated, which means it will be
/// re-processed JIT during the next call to GetData.
/// </summary>
public virtual void MarkInputDataRequiresUpdate()
{
_requiresUpdate = true;
_currentDataVersion += 1;
InputDataAvailable();
}
protected abstract void UpdateData();
/// <summary>
/// Returns the current DataAsset, without performing any updates.
/// </summary>
/// <returns>
/// Null if no call to GetData has been made since this data source was initialized.
/// </returns>
protected abstract TData DataAsset { get; }
public abstract TConfig Config { get; }
#region Inject
public void InjectAllDataSource(UpdateModeFlags updateMode, IDataSource updateAfter)
{
InjectUpdateMode(updateMode);
InjectUpdateAfter(updateAfter);
}
public void InjectUpdateMode(UpdateModeFlags updateMode)
{
_updateMode = updateMode;
}
public void InjectUpdateAfter(IDataSource updateAfter)
{
_updateAfter = updateAfter as MonoBehaviour;
UpdateAfter = updateAfter;
}
#endregion
}
}