core/util/Spawn.cs
[AttributeUsage(AttributeTargets.Property)]
public class SpawnAttribute(string parent = null) : Attribute {
public string Parent {get; set;} = parent;
}
public class Spawn {
private static Component CurrentOwner {get; set;}
public static void SetOwner(Component caller) {CurrentOwner = caller;}
public static void GameObject(string property, string name, GameObject parent = null) {GameObject(CurrentOwner, property, name, parent);}
public static void GameObject(Component owner, string property, string name, GameObject parent = null) {
var propdesc = GetPropertyDescription(owner, property);
if (propdesc == null) {
Log.Error("Spawn.GameObject couldnt find property "+property);
return;
}
ClearExisting(owner, propdesc);
propdesc.SetValue(owner, SpawnObject(owner, name, parent));
}
public static void Component(string property, GameObject parent = null) {Component(CurrentOwner, property, null, parent);}
public static void Component(Component caller, string property, Component owner = null, GameObject parent = null) {
var propdesc = GetPropertyDescription(caller, property);
if (propdesc == null) {
Log.Error("Spawn.GameObject couldnt find property "+property);
return;
}
ClearExisting(caller, propdesc);
owner ??= caller;
propdesc.SetValue(caller, SpawnComponent(TypeLibrary.GetType(propdesc.PropertyType), owner, caller, parent));
}
public static void Spawnables() {Spawnables(CurrentOwner, null);}
public static void Spawnables(Component caller, Component owner = null) {
var type = TypeLibrary.GetType(caller.GetType());
foreach (var property in type.DeclaredMembers) {
if (!property.IsProperty)
continue;
var attribute = property.GetCustomAttribute<SpawnAttribute>();
if (attribute == null)
continue;
GameObject parent = null;
if (!string.IsNullOrEmpty(attribute.Parent))
parent = (GameObject)type.GetValue(caller, attribute.Parent);
Component(caller, property.Name, owner, parent);
}
}
private static PropertyDescription GetPropertyDescription(Component owner, string property) {
foreach (var propdesc in TypeLibrary.GetPropertyDescriptions(owner)) {
if (propdesc.Name == property)
return propdesc;
}
return null;
}
private static void ClearExisting(Component owner, PropertyDescription propdesc) {
var component = propdesc.GetValue(owner);
if (component == null)
return;
if (component is GameObject obj)
obj.Destroy();
if (component is Component cmp)
cmp.Destroy();
}
private static GameObject SpawnObject(Component owner, string name, GameObject parent) {
var obj = owner.Scene.CreateObject();
if (name[0] == '_')
obj.Name = owner.GameObject.Name + name;
else
obj.Name = name;
if (parent != null)
obj.SetParent(parent, false);
else
obj.SetParent(owner.GameObject, false);
return obj;
}
private static Component SpawnComponent(TypeDescription type, Component owner, Component caller, GameObject parent) {
Component comp;
if (parent != null)
comp = parent.Components.Create(type);
else
comp = caller.Components.Create(type);
GetPropertyDescription(comp, "Owner")?.SetValue(comp, owner);
return comp;
}
}