/*
* 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 UnityEngine;
namespace Oculus.Interaction.Input
{
///
/// A specialization of which consumes data from another ,
/// modifies that data in some way, then makes the modified data available to downstream consumers. Examples of this include
/// (which applies smoothing to hand tracking data) and (which
/// can change the position and shape of hand tracking data based on conditions in the scene).
///
public abstract class
DataModifier : DataSource
where TData : class, ICopyFrom, new()
{
[Header("Data Modifier")]
[SerializeField, Interface(nameof(_modifyDataFromSource))]
protected UnityEngine.Object _iModifyDataFromSourceMono;
private IDataSource _modifyDataFromSource;
[SerializeField]
[Tooltip("If this is false, then this modifier will simply pass through " +
"data without performing any modification. This saves on memory " +
"and computation")]
protected bool _applyModifier = true;
private static TData InvalidAsset { get; } = new TData();
private TData _thisDataAsset;
private TData _currentDataAsset = InvalidAsset;
protected override TData DataAsset => _currentDataAsset;
///
/// Returns the from which this DataModifier retrieves the it
/// modifies. This source is typically set through the Unity Editor, but it can also be set programmatically using
/// .
///
public virtual IDataSource ModifyDataFromSource => _modifyDataFromSource == null
? (_modifyDataFromSource = _iModifyDataFromSourceMono as IDataSource)
: _modifyDataFromSource;
///
/// Implementation of ; for details, please refer to the related
/// documentation provided for that interface.
///
public override int CurrentDataVersion
{
get
{
return _applyModifier
? base.CurrentDataVersion
: ModifyDataFromSource.CurrentDataVersion;
}
}
///
/// Changes the source from which this modifier retrieves the data it modifies, the source for updates, and the
/// .
///
/// The source from which this modifier retrieves the data it modifies
/// The after which this modifier should be updated
/// The to use from now on
///
/// Typically, the same value is passed as both and
/// so that the modifier is updated whenever and immediately after the source from which it retrieves the unmodified data
/// acquires new data to modify.
///
public void ResetSources(IDataSource modifyDataFromSource, IDataSource updateAfter, UpdateModeFlags updateMode)
{
ResetUpdateAfter(updateAfter, updateMode);
_modifyDataFromSource = modifyDataFromSource;
_currentDataAsset = InvalidAsset;
}
protected override void UpdateData()
{
if (_applyModifier)
{
if (_thisDataAsset == null)
{
_thisDataAsset = new TData();
}
_thisDataAsset.CopyFrom(ModifyDataFromSource.GetData());
_currentDataAsset = _thisDataAsset;
Apply(_currentDataAsset);
}
else
{
_currentDataAsset = ModifyDataFromSource.GetData();
}
}
protected abstract void Apply(TData data);
protected override void Start()
{
this.BeginStart(ref _started, () => base.Start());
this.AssertField(ModifyDataFromSource, nameof(ModifyDataFromSource));
this.EndStart(ref _started);
}
#region Inject
///
/// Injects all required dependencies for a dynamically instantiated DataModifier; effectively wraps
/// ,
/// , and .
/// This method exists to support Interaction SDK's dependency injection pattern and is not needed for typical Unity
/// Editor-based usage.
///
public void InjectAllDataModifier(UpdateModeFlags updateMode, IDataSource updateAfter, IDataSource modifyDataFromSource, bool applyModifier)
{
base.InjectAllDataSource(updateMode, updateAfter);
InjectModifyDataFromSource(modifyDataFromSource);
InjectApplyModifier(applyModifier);
}
///
/// Sets the for unmodified data on a dynamically instantiated DataModifier. This method exists
/// to support Interaction SDK's dependency injection pattern and is not needed for typical Unity Editor-based usage.
///
///
public void InjectModifyDataFromSource(IDataSource modifyDataFromSource)
{
_modifyDataFromSource = modifyDataFromSource;
_iModifyDataFromSourceMono = modifyDataFromSource as Object;
}
///
/// Sets whether or not to apply modification on a dynamically instantiated DataSource. This method exists to support
/// Interaction SDK's dependency injection pattern and is not needed for typical Unity Editor-based usage.
///
///
public void InjectApplyModifier(bool applyModifier)
{
_applyModifier = applyModifier;
}
#endregion
}
}