using System;
namespace UnityEngine.Experimental.Perception.Randomization.Parameters
{
///
/// Used to apply sampled parameter values to a particular GameObject, Component, and property.
/// Typically managed by a parameter configuration.
///
[Serializable]
public class ParameterTarget
{
[SerializeField] internal GameObject gameObject;
[SerializeField] internal Component component;
[SerializeField] internal string propertyName = string.Empty;
[SerializeField] internal FieldOrProperty fieldOrProperty = FieldOrProperty.Field;
[SerializeField] internal ParameterApplicationFrequency applicationFrequency = ParameterApplicationFrequency.OnIterationSetup;
///
/// Assigns a new target
///
/// The target GameObject
/// The target component on the target GameObject
/// The name of the property to apply the parameter to
/// How often to apply the parameter to its target
public void AssignNewTarget(
GameObject targetObject,
Component targetComponent,
string fieldOrPropertyName,
ParameterApplicationFrequency frequency)
{
gameObject = targetObject;
component = targetComponent;
propertyName = fieldOrPropertyName;
applicationFrequency = frequency;
var componentType = component.GetType();
fieldOrProperty = componentType.GetField(fieldOrPropertyName) != null
? FieldOrProperty.Field
: FieldOrProperty.Property;
}
internal void Clear()
{
gameObject = null;
component = null;
propertyName = string.Empty;
}
internal void ApplyValueToTarget(object value)
{
var componentType = component.GetType();
if (fieldOrProperty == FieldOrProperty.Field)
{
var field = componentType.GetField(propertyName);
if (field == null)
throw new ParameterValidationException(
$"Component type {componentType.Name} does not have a field named {propertyName}");
field.SetValue(component, value);
}
else
{
var property = componentType.GetProperty(propertyName);
if (property == null)
throw new ParameterValidationException(
$"Component type {componentType.Name} does not have a property named {propertyName}");
property.SetValue(component, value);
}
}
}
///
/// How often to apply a new sample to a parameter's target
///
public enum ParameterApplicationFrequency
{
///
/// Applies a parameter once every iteration
///
OnIterationSetup,
///
/// Applies a parameter once every frame
///
EveryFrame
}
enum FieldOrProperty
{
Field, Property
}
}