#if UNITY_5 || UNITY_5_3_OR_NEWER
using System;
using Svelto.ECS.Hybrid;
using UnityEngine;
namespace Svelto.ECS.Extensions.Unity
{
public static class SveltoGUIHelper
{
///
/// This is the suggested way to create GUIs from prefabs now.
///
///
///
///
///
///
///
///
///
public static T CreateFromPrefab(ref uint startIndex, Transform contextHolder, IEntityFactory factory,
ExclusiveGroup group, bool searchImplementorsInChildren = false, string groupNamePostfix = null) where T : MonoBehaviour, IEntityDescriptorHolder
{
Create(new EGID(startIndex++, group), contextHolder, factory, out var holder);
var children = contextHolder.GetComponentsInChildren(true);
foreach (var child in children)
{
if (child.GetType() != typeof(T))
{
var monoBehaviour = child as MonoBehaviour;
IImplementor[] childImplementors;
if (searchImplementorsInChildren == false)
childImplementors = monoBehaviour.GetComponents();
else
childImplementors = monoBehaviour.GetComponentsInChildren(true);
startIndex = InternalBuildAll(startIndex, child, factory, group, childImplementors,
groupNamePostfix);
}
}
return holder;
}
///
/// Creates all the entities in a hierarchy. This was commonly used to create entities from gameobjects
/// already present in the scene
///
///
///
///
///
///
///
///
public static uint CreateAll(uint startIndex, ExclusiveGroup group,
Transform contextHolder, IEntityFactory factory, string groupNamePostfix = null) where T : MonoBehaviour, IEntityDescriptorHolder
{
var holders = contextHolder.GetComponentsInChildren(true);
foreach (var holder in holders)
{
var implementors = holder.GetComponents();
try
{
startIndex = InternalBuildAll(startIndex, holder, factory, group, implementors, groupNamePostfix);
}
catch (Exception ex)
{
throw new Exception($"When building entity from game object {Path(holder.transform)}", ex);
}
}
return startIndex;
}
static string Path(Transform go)
{
string s = go.name;
while (go.parent != null)
{
go = go.parent;
s = go.name + "/" + s;
}
return s;
}
public static EntityInitializer Create(EGID ID, Transform contextHolder, IEntityFactory factory,
out T holder, bool searchImplementorsInChildren = false)
where T : MonoBehaviour, IEntityDescriptorHolder
{
holder = contextHolder.GetComponentInChildren(true);
if (holder == null)
{
throw new Exception($"Could not find holder {typeof(T).Name} in {contextHolder.name}");
}
var implementors = searchImplementorsInChildren == false ? holder.GetComponents() : holder.GetComponentsInChildren(true) ;
return factory.BuildEntity(ID, holder.GetDescriptor(), implementors);
}
public static EntityInitializer Create(EGID ID, Transform contextHolder,
IEntityFactory factory, bool searchImplementorsInChildren = false)
where T : MonoBehaviour, IEntityDescriptorHolder
{
var holder = contextHolder.GetComponentInChildren(true);
if (holder == null)
{
throw new Exception($"Could not find holder {typeof(T).Name} in {contextHolder.name}");
}
var implementors = searchImplementorsInChildren == false ? holder.GetComponents() : holder.GetComponentsInChildren(true) ;
return factory.BuildEntity(ID, holder.GetDescriptor(), implementors);
}
static uint InternalBuildAll(uint startIndex, IEntityDescriptorHolder descriptorHolder,
IEntityFactory factory, ExclusiveGroup group, IImplementor[] implementors, string groupNamePostfix)
{
ExclusiveGroupStruct realGroup = group;
if (string.IsNullOrEmpty(descriptorHolder.groupName) == false)
{
realGroup = ExclusiveGroup.Search(!string.IsNullOrEmpty(groupNamePostfix)
? $"{descriptorHolder.groupName}{groupNamePostfix}"
: descriptorHolder.groupName);
}
EGID egid;
var holderId = descriptorHolder.id;
if (holderId == 0)
egid = new EGID(startIndex++, realGroup);
else
egid = new EGID(holderId, realGroup);
var init = factory.BuildEntity(egid, descriptorHolder.GetDescriptor(), implementors);
init.Init(new EntityHierarchyComponent(group));
return startIndex;
}
///
/// Works like CreateAll but only builds entities with holders that have the same group specified
/// This is a very specific case, basically used only by ControlsScreenRowFactory. Not sure what the real
/// use case is.
///
///
/// The group to match
///
///
/// EntityDescriptorHolder type
/// Next available ID
public static uint CreateAllInMatchingGroup(uint startId, ExclusiveGroup exclusiveGroup,
Transform contextHolder, IEntityFactory factory) where T : MonoBehaviour, IEntityDescriptorHolder
{
var holders = contextHolder.GetComponentsInChildren(true);
foreach (var holder in holders)
{
if (string.IsNullOrEmpty(holder.groupName) == false)
{
var realGroup = ExclusiveGroup.Search(holder.groupName);
if (realGroup != exclusiveGroup)
continue;
}
else
{
continue;
}
var implementors = holder.GetComponents();
startId = InternalBuildAll(startId, holder, factory, exclusiveGroup, implementors, null);
}
return startId;
}
}
}
#endif