292 lines
9.4 KiB
C#
292 lines
9.4 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using VContainer.Internal;
|
|
|
|
namespace VContainer.Unity
|
|
{
|
|
public static class ObjectResolverUnityExtensions
|
|
{
|
|
public readonly struct PrefabDirtyScope : IDisposable
|
|
{
|
|
readonly GameObject _prefab;
|
|
readonly bool _madeDirty;
|
|
|
|
public PrefabDirtyScope(GameObject prefab)
|
|
{
|
|
_prefab = prefab;
|
|
|
|
#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER
|
|
_madeDirty = prefab.activeSelf && !UnityEditor.EditorUtility.IsDirty(_prefab);
|
|
#else
|
|
_madeDirty = false;
|
|
#endif
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER
|
|
if (_madeDirty)
|
|
{
|
|
UnityEditor.EditorUtility.ClearDirty(_prefab);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public static void InjectGameObject(this IObjectResolver resolver, GameObject gameObject)
|
|
{
|
|
void InjectGameObjectRecursive(GameObject current)
|
|
{
|
|
if (current == null) return;
|
|
|
|
using (ListPool<MonoBehaviour>.Get(out var buffer))
|
|
{
|
|
buffer.Clear();
|
|
current.GetComponents(buffer);
|
|
foreach (var monoBehaviour in buffer)
|
|
{
|
|
if (monoBehaviour != null)
|
|
{ // Can be null if the MonoBehaviour's type wasn't found (e.g. if it was stripped)
|
|
resolver.Inject(monoBehaviour);
|
|
}
|
|
}
|
|
}
|
|
|
|
var transform = current.transform;
|
|
for (var i = 0; i < transform.childCount; i++)
|
|
{
|
|
var child = transform.GetChild(i);
|
|
InjectGameObjectRecursive(child.gameObject);
|
|
}
|
|
}
|
|
|
|
InjectGameObjectRecursive(gameObject);
|
|
}
|
|
|
|
public static T Instantiate<T>(this IObjectResolver resolver, T prefab)
|
|
where T : Component
|
|
{
|
|
return resolver.Instantiate(prefab, prefab.transform.position, prefab.transform.rotation);
|
|
}
|
|
|
|
public static T Instantiate<T>(this IObjectResolver resolver, T prefab, Transform parent, bool worldPositionStays = false)
|
|
where T : Component
|
|
{
|
|
var wasActive = prefab.gameObject.activeSelf;
|
|
using (new PrefabDirtyScope(prefab.gameObject))
|
|
{
|
|
prefab.gameObject.SetActive(false);
|
|
|
|
var instance = UnityEngine.Object.Instantiate(prefab, parent, worldPositionStays);
|
|
|
|
SetName(instance, prefab);
|
|
|
|
try
|
|
{
|
|
resolver.InjectGameObject(instance.gameObject);
|
|
}
|
|
finally
|
|
{
|
|
prefab.gameObject.SetActive(wasActive);
|
|
instance.gameObject.SetActive(wasActive);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
public static T Instantiate<T>(
|
|
this IObjectResolver resolver,
|
|
T prefab,
|
|
Vector3 position,
|
|
Quaternion rotation)
|
|
where T : Component
|
|
{
|
|
if (resolver.ApplicationOrigin is LifetimeScope scope)
|
|
{
|
|
return scope.Instantiate(prefab, position, rotation);
|
|
}
|
|
|
|
return resolver.Instantiate(prefab, position, rotation, null);
|
|
}
|
|
|
|
public static T Instantiate<T>(
|
|
this IObjectResolver resolver,
|
|
T prefab,
|
|
Vector3 position,
|
|
Quaternion rotation,
|
|
Transform parent)
|
|
where T : Component
|
|
{
|
|
var wasActive = prefab.gameObject.activeSelf;
|
|
using (new PrefabDirtyScope(prefab.gameObject))
|
|
{
|
|
prefab.gameObject.SetActive(false);
|
|
|
|
var instance = UnityEngine.Object.Instantiate(prefab, position, rotation, parent);
|
|
|
|
SetName(instance, prefab);
|
|
|
|
try
|
|
{
|
|
resolver.InjectGameObject(instance.gameObject);
|
|
}
|
|
finally
|
|
{
|
|
prefab.gameObject.SetActive(wasActive);
|
|
instance.gameObject.SetActive(wasActive);
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
static T Instantiate<T>(this LifetimeScope scope, T prefab, Vector3 position, Quaternion rotation)
|
|
where T : Component
|
|
{
|
|
var wasActive = prefab.gameObject.activeSelf;
|
|
using (new PrefabDirtyScope(prefab.gameObject))
|
|
{
|
|
prefab.gameObject.SetActive(false);
|
|
|
|
T instance;
|
|
if (scope.IsRoot)
|
|
{
|
|
instance = UnityEngine.Object.Instantiate(prefab, position, rotation);
|
|
UnityEngine.Object.DontDestroyOnLoad(instance);
|
|
}
|
|
else
|
|
{
|
|
// Into the same scene as LifetimeScope
|
|
instance = UnityEngine.Object.Instantiate(prefab, position, rotation, scope.transform);
|
|
instance.transform.SetParent(null);
|
|
}
|
|
|
|
SetName(instance, prefab);
|
|
|
|
try
|
|
{
|
|
scope.Container.InjectGameObject(instance.gameObject);
|
|
}
|
|
finally
|
|
{
|
|
prefab.gameObject.SetActive(wasActive);
|
|
instance.gameObject.SetActive(wasActive);
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
static GameObject Instantiate(this LifetimeScope scope, GameObject prefab, Vector3 position, Quaternion rotation)
|
|
{
|
|
var wasActive = prefab.activeSelf;
|
|
using (new PrefabDirtyScope(prefab))
|
|
{
|
|
prefab.SetActive(false);
|
|
|
|
GameObject instance;
|
|
if (scope.IsRoot)
|
|
{
|
|
instance = UnityEngine.Object.Instantiate(prefab, position, rotation);
|
|
UnityEngine.Object.DontDestroyOnLoad(instance);
|
|
}
|
|
else
|
|
{
|
|
// Into the same scene as LifetimeScope
|
|
instance = UnityEngine.Object.Instantiate(prefab, position, rotation, scope.transform);
|
|
instance.transform.SetParent(null);
|
|
}
|
|
|
|
SetName(instance, prefab);
|
|
|
|
try
|
|
{
|
|
scope.Container.InjectGameObject(instance);
|
|
}
|
|
finally
|
|
{
|
|
prefab.SetActive(wasActive);
|
|
instance.SetActive(wasActive);
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
public static GameObject Instantiate(this IObjectResolver resolver, GameObject prefab)
|
|
{
|
|
return resolver.Instantiate(prefab, prefab.transform.position, prefab.transform.rotation);
|
|
}
|
|
|
|
public static GameObject Instantiate(this IObjectResolver resolver, GameObject prefab, Transform parent, bool worldPositionStays = false)
|
|
{
|
|
var wasActive = prefab.activeSelf;
|
|
using (new PrefabDirtyScope(prefab))
|
|
{
|
|
prefab.SetActive(false);
|
|
|
|
GameObject instance = null;
|
|
try
|
|
{
|
|
instance = UnityEngine.Object.Instantiate(prefab, parent, worldPositionStays);
|
|
SetName(instance, prefab);
|
|
resolver.InjectGameObject(instance);
|
|
}
|
|
finally
|
|
{
|
|
prefab.SetActive(wasActive);
|
|
instance?.SetActive(wasActive);
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
public static GameObject Instantiate(
|
|
this IObjectResolver resolver,
|
|
GameObject prefab,
|
|
Vector3 position,
|
|
Quaternion rotation)
|
|
{
|
|
if (resolver.ApplicationOrigin is LifetimeScope scope)
|
|
{
|
|
return scope.Instantiate(prefab, position, rotation);
|
|
}
|
|
|
|
return resolver.Instantiate(prefab, position, rotation, null);
|
|
}
|
|
|
|
public static GameObject Instantiate(
|
|
this IObjectResolver resolver,
|
|
GameObject prefab,
|
|
Vector3 position,
|
|
Quaternion rotation,
|
|
Transform parent)
|
|
{
|
|
var wasActive = prefab.activeSelf;
|
|
using (new PrefabDirtyScope(prefab))
|
|
{
|
|
prefab.SetActive(false);
|
|
|
|
var instance = UnityEngine.Object.Instantiate(prefab, position, rotation, parent);
|
|
|
|
SetName(instance, prefab);
|
|
|
|
try
|
|
{
|
|
resolver.InjectGameObject(instance);
|
|
}
|
|
finally
|
|
{
|
|
prefab.SetActive(wasActive);
|
|
instance.SetActive(wasActive);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
static void SetName(UnityEngine.Object instance, UnityEngine.Object prefab)
|
|
{
|
|
if (VContainerSettings.Instance != null && VContainerSettings.Instance.RemoveClonePostfix)
|
|
instance.name = prefab.name;
|
|
}
|
|
}
|
|
} |