Update Project
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
using Zenject.Internal;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public class ProjectContext : Context
|
||||
{
|
||||
public static event Action PreInstall;
|
||||
public static event Action PostInstall;
|
||||
public static event Action PreResolve;
|
||||
public static event Action PostResolve;
|
||||
|
||||
public const string ProjectContextResourcePath = "ProjectContext";
|
||||
public const string ProjectContextResourcePathOld = "ProjectCompositionRoot";
|
||||
|
||||
static ProjectContext _instance;
|
||||
|
||||
// TODO: Set this to false the next time major version is incremented
|
||||
[Tooltip("When true, objects that are created at runtime will be parented to the ProjectContext")]
|
||||
[SerializeField]
|
||||
bool _parentNewObjectsUnderContext = true;
|
||||
|
||||
[SerializeField]
|
||||
ReflectionBakingCoverageModes _editorReflectionBakingCoverageMode = ReflectionBakingCoverageModes.FallbackToDirectReflection;
|
||||
|
||||
[SerializeField]
|
||||
ReflectionBakingCoverageModes _buildsReflectionBakingCoverageMode = ReflectionBakingCoverageModes.FallbackToDirectReflection;
|
||||
|
||||
[SerializeField]
|
||||
ZenjectSettings _settings = null;
|
||||
|
||||
DiContainer _container;
|
||||
|
||||
public override DiContainer Container
|
||||
{
|
||||
get { return _container; }
|
||||
}
|
||||
|
||||
public static bool HasInstance
|
||||
{
|
||||
get { return _instance != null; }
|
||||
}
|
||||
|
||||
public static ProjectContext Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
InstantiateAndInitialize();
|
||||
Assert.IsNotNull(_instance);
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ValidateOnNextRun
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override IEnumerable<GameObject> GetRootGameObjects()
|
||||
{
|
||||
return new[] { gameObject };
|
||||
}
|
||||
|
||||
public static GameObject TryGetPrefab()
|
||||
{
|
||||
var prefabs = Resources.LoadAll(ProjectContextResourcePath, typeof(GameObject));
|
||||
|
||||
if (prefabs.Length > 0)
|
||||
{
|
||||
Assert.That(prefabs.Length == 1,
|
||||
"Found multiple project context prefabs at resource path '{0}'", ProjectContextResourcePath);
|
||||
return (GameObject)prefabs[0];
|
||||
}
|
||||
|
||||
prefabs = Resources.LoadAll(ProjectContextResourcePathOld, typeof(GameObject));
|
||||
|
||||
if (prefabs.Length > 0)
|
||||
{
|
||||
Assert.That(prefabs.Length == 1,
|
||||
"Found multiple project context prefabs at resource path '{0}'", ProjectContextResourcePathOld);
|
||||
return (GameObject)prefabs[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static void InstantiateAndInitialize()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
ProfileBlock.UnityMainThread = Thread.CurrentThread;
|
||||
#endif
|
||||
|
||||
Assert.That(FindObjectsOfType<ProjectContext>().IsEmpty(),
|
||||
"Tried to create multiple instances of ProjectContext!");
|
||||
|
||||
var prefab = TryGetPrefab();
|
||||
|
||||
var prefabWasActive = false;
|
||||
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("GameObject.Instantiate"))
|
||||
#endif
|
||||
{
|
||||
if (prefab == null)
|
||||
{
|
||||
_instance = new GameObject("ProjectContext")
|
||||
.AddComponent<ProjectContext>();
|
||||
}
|
||||
else
|
||||
{
|
||||
prefabWasActive = prefab.activeSelf;
|
||||
|
||||
GameObject gameObjectInstance;
|
||||
#if UNITY_EDITOR
|
||||
if(prefabWasActive)
|
||||
{
|
||||
// This ensures the prefab's Awake() methods don't fire (and, if in the editor, that the prefab file doesn't get modified)
|
||||
gameObjectInstance = GameObject.Instantiate(prefab, ZenUtilInternal.GetOrCreateInactivePrefabParent());
|
||||
gameObjectInstance.SetActive(false);
|
||||
gameObjectInstance.transform.SetParent(null, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
gameObjectInstance = GameObject.Instantiate(prefab);
|
||||
}
|
||||
#else
|
||||
if(prefabWasActive)
|
||||
{
|
||||
prefab.SetActive(false);
|
||||
gameObjectInstance = GameObject.Instantiate(prefab);
|
||||
prefab.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
gameObjectInstance = GameObject.Instantiate(prefab);
|
||||
}
|
||||
#endif
|
||||
|
||||
_instance = gameObjectInstance.GetComponent<ProjectContext>();
|
||||
|
||||
Assert.IsNotNull(_instance,
|
||||
"Could not find ProjectContext component on prefab 'Resources/{0}.prefab'", ProjectContextResourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We use Initialize instead of awake here in case someone calls
|
||||
// ProjectContext.Instance while ProjectContext is initializing
|
||||
_instance.Initialize();
|
||||
|
||||
if (prefabWasActive)
|
||||
{
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("User Code"))
|
||||
#endif
|
||||
{
|
||||
// We always instantiate it as disabled so that Awake and Start events are triggered after inject
|
||||
_instance.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ParentNewObjectsUnderContext
|
||||
{
|
||||
get { return _parentNewObjectsUnderContext; }
|
||||
set { _parentNewObjectsUnderContext = value; }
|
||||
}
|
||||
|
||||
public void EnsureIsInitialized()
|
||||
{
|
||||
// Do nothing - Initialize occurs in Instance property
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
// DontDestroyOnLoad can only be called when in play mode and otherwise produces errors
|
||||
// ProjectContext is created during design time (in an empty scene) when running validation
|
||||
// and also when running unit tests
|
||||
// In these cases we don't need DontDestroyOnLoad so just skip it
|
||||
{
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Assert.IsNull(_container);
|
||||
|
||||
if (Application.isEditor)
|
||||
{
|
||||
TypeAnalyzer.ReflectionBakingCoverageMode = _editorReflectionBakingCoverageMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeAnalyzer.ReflectionBakingCoverageMode = _buildsReflectionBakingCoverageMode;
|
||||
}
|
||||
|
||||
var isValidating = ValidateOnNextRun;
|
||||
|
||||
// Reset immediately to ensure it doesn't get used in another run
|
||||
ValidateOnNextRun = false;
|
||||
|
||||
_container = new DiContainer(
|
||||
new[] { StaticContext.Container }, isValidating);
|
||||
|
||||
// Do this after creating DiContainer in case it's needed by the pre install logic
|
||||
if (PreInstall != null)
|
||||
{
|
||||
PreInstall();
|
||||
}
|
||||
|
||||
var injectableMonoBehaviours = new List<MonoBehaviour>();
|
||||
GetInjectableMonoBehaviours(injectableMonoBehaviours);
|
||||
|
||||
foreach (var instance in injectableMonoBehaviours)
|
||||
{
|
||||
_container.QueueForInject(instance);
|
||||
}
|
||||
|
||||
_container.IsInstalling = true;
|
||||
|
||||
try
|
||||
{
|
||||
InstallBindings(injectableMonoBehaviours);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_container.IsInstalling = false;
|
||||
}
|
||||
|
||||
if (PostInstall != null)
|
||||
{
|
||||
PostInstall();
|
||||
}
|
||||
|
||||
if (PreResolve != null)
|
||||
{
|
||||
PreResolve();
|
||||
}
|
||||
|
||||
_container.ResolveRoots();
|
||||
|
||||
if (PostResolve != null)
|
||||
{
|
||||
PostResolve();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetInjectableMonoBehaviours(List<MonoBehaviour> monoBehaviours)
|
||||
{
|
||||
ZenUtilInternal.AddStateMachineBehaviourAutoInjectersUnderGameObject(gameObject);
|
||||
ZenUtilInternal.GetInjectableMonoBehavioursUnderGameObject(gameObject, monoBehaviours);
|
||||
}
|
||||
|
||||
void InstallBindings(List<MonoBehaviour> injectableMonoBehaviours)
|
||||
{
|
||||
if (_parentNewObjectsUnderContext)
|
||||
{
|
||||
_container.DefaultParent = transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
_container.DefaultParent = null;
|
||||
}
|
||||
|
||||
_container.Settings = _settings ?? ZenjectSettings.Default;
|
||||
|
||||
_container.Bind<ZenjectSceneLoader>().AsSingle();
|
||||
|
||||
ZenjectManagersInstaller.Install(_container);
|
||||
|
||||
_container.Bind<Context>().FromInstance(this);
|
||||
|
||||
_container.Bind(typeof(ProjectKernel), typeof(MonoKernel))
|
||||
.To<ProjectKernel>().FromNewComponentOn(gameObject).AsSingle().NonLazy();
|
||||
|
||||
_container.Bind<SceneContextRegistry>().AsSingle();
|
||||
|
||||
InstallSceneBindings(injectableMonoBehaviours);
|
||||
|
||||
InstallInstallers();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user