using System.Collections.Generic;
using UnityEngine.Perception.Randomization.Randomizers;
namespace UnityEngine.Perception.GroundTruth
{
///
/// Manages the registration of components
///
[DefaultExecutionOrder(1)]
public class LabelManager
{
///
/// Returns the active LabeledObjectsManager instance
///
public static LabelManager singleton { get; } = new LabelManager();
const uint k_StartingIndex = 1;
uint m_NextObjectIndex = k_StartingIndex;
List m_ActiveGenerators = new List();
LinkedHashSet m_LabelsPendingRegistration = new LinkedHashSet();
LinkedHashSet m_RegisteredLabels = new LinkedHashSet();
///
/// Returns the set of registered Labeling components
///
public IEnumerable registeredLabels => m_RegisteredLabels;
///
/// Registers all pending labels.
/// Called once per frame during LateUpdate by the .
///
public void RegisterPendingLabels()
{
if (m_RegisteredLabels.Count == 0)
m_NextObjectIndex = k_StartingIndex;
foreach (var unregisteredLabel in m_LabelsPendingRegistration)
{
if (m_RegisteredLabels.Contains(unregisteredLabel))
continue;
var instanceId = m_NextObjectIndex++;
RecursivelyInitializeGameObjects(
unregisteredLabel.gameObject,
new MaterialPropertyBlock(),
unregisteredLabel,
instanceId);
unregisteredLabel.SetInstanceId(instanceId);
m_RegisteredLabels.Add(unregisteredLabel);
}
m_LabelsPendingRegistration.Clear();
}
///
/// Activates the given .
/// will be called for all
/// instances under each object containing a component.
///
/// The generator to register
public void Activate(IGroundTruthGenerator generator)
{
m_ActiveGenerators.Add(generator);
foreach (var label in m_RegisteredLabels)
RecursivelyInitializeGameObjects(label.gameObject, new MaterialPropertyBlock(), label, label.instanceId);
}
///
/// Deactivates the given .
/// It will no longer receive calls when instances are created.
///
/// The generator to deactivate
///
/// True if the was successfully removed.
/// False if was not active.
///
public bool Deactivate(IGroundTruthGenerator generator)
{
return m_ActiveGenerators.Remove(generator);
}
///
/// Unregisters a labeling component
///
/// the component to unregister
internal void Unregister(Labeling labeling)
{
m_LabelsPendingRegistration.Remove(labeling);
m_RegisteredLabels.Remove(labeling);
}
///
/// Refresh ground truth generation for the labeling of a particular GameObject. This is necessary when the
/// list of labels changes or when renderers or materials change on objects in the hierarchy.
///
/// the component to refresh
internal void RefreshLabeling(Labeling labeling)
{
m_RegisteredLabels.Remove(labeling);
m_LabelsPendingRegistration.Add(labeling);
}
///
/// Recursively initializes Renderer components on GameObjects with Labeling components
///
/// The parent GameObject being initialized
/// A reusable material property block
/// The labeling component attached to the current gameObject
/// The perception specific instanceId assigned to the current gameObject
void RecursivelyInitializeGameObjects(
GameObject gameObject, MaterialPropertyBlock mpb, Labeling labeling, uint instanceId)
{
var terrain = gameObject.GetComponent();
if (terrain != null)
{
terrain.GetSplatMaterialPropertyBlock(mpb);
foreach (var pass in m_ActiveGenerators)
{
if (labeling.enabled)
{
pass.SetupMaterialProperties(mpb, null, labeling, instanceId);
}
else
{
pass.ClearMaterialProperties(mpb, null, labeling, instanceId);
}
}
terrain.SetSplatMaterialPropertyBlock(mpb);
}
var renderer = gameObject.GetComponent();
if (renderer != null)
{
renderer.GetPropertyBlock(mpb);
foreach (var pass in m_ActiveGenerators)
{
if (labeling.enabled)
{
pass.SetupMaterialProperties(mpb, renderer, labeling, instanceId);
}
else
{
pass.ClearMaterialProperties(mpb, renderer, labeling, instanceId);
}
}
renderer.SetPropertyBlock(mpb);
var materialCount = renderer.materials.Length;
for (var i = 0; i < materialCount; i++)
{
renderer.GetPropertyBlock(mpb, i);
//Only apply to individual materials if there is already a MaterialPropertyBlock on it
if (!mpb.isEmpty)
{
foreach (var pass in m_ActiveGenerators)
{
if (labeling.enabled)
{
pass.SetupMaterialProperties(mpb, renderer, labeling, instanceId);
}
else
{
pass.ClearMaterialProperties(mpb, renderer, labeling, instanceId);
}
}
renderer.SetPropertyBlock(mpb, i);
}
}
}
for (var i = 0; i < gameObject.transform.childCount; i++)
{
var child = gameObject.transform.GetChild(i).gameObject;
if (child.GetComponent() != null)
continue;
RecursivelyInitializeGameObjects(child, mpb, labeling, instanceId);
}
}
}
}