using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Perception.Randomization.Parameters;
namespace UnityEngine.Experimental.Perception.Randomization.Configuration
{
///
/// Creates parameter interfaces for randomizing simulations
///
[ExecuteInEditMode]
[AddComponentMenu("Perception/Randomization/ParameterConfiguration")]
public class ParameterConfiguration : MonoBehaviour
{
internal static HashSet configurations = new HashSet();
[SerializeReference] internal List parameters = new List();
///
/// Find a parameter in this configuration by name
///
/// The name of the parameter to lookup
/// The type of parameter to lookup
/// The parameter if found, null otherwise
///
public Parameter GetParameter(string parameterName, Type parameterType)
{
foreach (var parameter in parameters)
{
if (parameter.name == parameterName && parameter.GetType() == parameterType)
return parameter;
}
return null;
}
///
/// Find a parameter in this configuration by name and type
///
///
/// The type of parameter to look for
/// The parameter if found, null otherwise
public T GetParameter(string parameterName) where T : Parameter
{
foreach (var parameter in parameters)
{
if (parameter.name == parameterName && parameter is T typedParameter)
return typedParameter;
}
return null;
}
string PlaceholderParameterName() => $"Parameter{parameters.Count}";
internal T AddParameter() where T : Parameter, new()
{
var parameter = new T();
parameter.name = PlaceholderParameterName();
parameters.Add(parameter);
return parameter;
}
internal Parameter AddParameter(Type parameterType)
{
if (!parameterType.IsSubclassOf(typeof(Parameter)))
throw new ParameterConfigurationException($"Cannot add non-parameter types ({parameterType})");
var parameter = (Parameter)Activator.CreateInstance(parameterType);
parameter.name = PlaceholderParameterName();
parameters.Add(parameter);
return parameter;
}
internal void ApplyParameters(int seedOffset, ParameterApplicationFrequency frequency)
{
foreach (var parameter in parameters)
if (parameter.target.applicationFrequency == frequency)
parameter.ApplyToTarget(seedOffset);
}
internal void ResetParameterStates(int scenarioIteration)
{
foreach (var parameter in parameters)
parameter.ResetState(scenarioIteration);
}
internal void ValidateParameters()
{
var parameterNames = new HashSet();
foreach (var parameter in parameters)
{
if (parameterNames.Contains(parameter.name))
throw new ParameterConfigurationException(
$"Two or more parameters cannot share the same name (\"{parameter.name}\")");
parameterNames.Add(parameter.name);
parameter.Validate();
}
}
void OnEnable()
{
configurations.Add(this);
}
void OnDisable()
{
configurations.Remove(this);
}
}
}