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); } } } }