using System.Collections.Generic;
using System.Threading;
using Unity.Entities;
namespace UnityEngine.Perception.GroundTruth
{
struct IdAssignmentParameters : IComponentData
{
public uint idStart;
public uint idStep;
}
///
/// System which notifies the registered about additions.
///
public class GroundTruthLabelSetupSystem : ComponentSystem
{
List m_ActiveGenerators = new List();
ThreadLocal m_MaterialPropertyBlocks = new ThreadLocal();
int m_CurrentObjectIndex = -1;
///
protected override void OnCreate()
{
//These are here to inform the system runner the queries we are interested in. Without these calls, OnUpdate() might not be called
GetEntityQuery(ComponentType.Exclude(), ComponentType.ReadOnly());
GetEntityQuery(ComponentType.ReadOnly(), ComponentType.ReadOnly());
}
///
protected override void OnUpdate()
{
var entityQuery = Entities.WithAll().ToEntityQuery();
IdAssignmentParameters idAssignmentParameters;
if (entityQuery.CalculateEntityCount() == 1)
idAssignmentParameters = entityQuery.GetSingleton();
else
idAssignmentParameters = new IdAssignmentParameters {idStart = 1, idStep = 1};
var entityCount = Entities.WithAll().ToEntityQuery().CalculateEntityCount();
if (entityCount == 0)
m_CurrentObjectIndex = -1;
Entities.WithNone().ForEach((Entity e, Labeling labeling) =>
{
var objectIndex = (uint)Interlocked.Increment(ref m_CurrentObjectIndex);
var instanceId = idAssignmentParameters.idStart + objectIndex * idAssignmentParameters.idStep;
var gameObject = labeling.gameObject;
if (!m_MaterialPropertyBlocks.IsValueCreated)
m_MaterialPropertyBlocks.Value = new MaterialPropertyBlock();
InitGameObjectRecursive(gameObject, m_MaterialPropertyBlocks.Value, labeling, instanceId);
EntityManager.AddComponentData(e, new GroundTruthInfo
{
instanceId = instanceId
});
labeling.SetInstanceId(instanceId);
});
}
void InitGameObjectRecursive(GameObject gameObject, MaterialPropertyBlock mpb, Labeling labeling, uint instanceId)
{
var renderer = (Renderer)gameObject.GetComponent();
if (renderer == null)
renderer = gameObject.GetComponent();
if (renderer != null)
{
renderer.GetPropertyBlock(mpb);
foreach (var pass in m_ActiveGenerators)
pass.SetupMaterialProperties(mpb, renderer, labeling, instanceId);
renderer.SetPropertyBlock(mpb);
}
for (var i = 0; i < gameObject.transform.childCount; i++)
{
var child = gameObject.transform.GetChild(i).gameObject;
if (child.GetComponent() != null)
continue;
InitGameObjectRecursive(child, mpb, labeling, instanceId);
}
}
///
/// 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);
Entities.ForEach((Labeling labeling, ref GroundTruthInfo info) =>
{
var gameObject = labeling.gameObject;
InitGameObjectRecursive(gameObject, m_MaterialPropertyBlocks.Value, labeling, info.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);
}
}
}