Initial Commit
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc41c06067fc1d4479c3b85aa2707cfb
|
||||
folderAsset: yes
|
||||
timeCreated: 1461708046
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,334 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public abstract class Context : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
List<ScriptableObjectInstaller> _scriptableObjectInstallers = new List<ScriptableObjectInstaller>();
|
||||
|
||||
[FormerlySerializedAs("Installers")]
|
||||
[FormerlySerializedAs("_installers")]
|
||||
[SerializeField]
|
||||
List<MonoInstaller> _monoInstallers = new List<MonoInstaller>();
|
||||
|
||||
[SerializeField]
|
||||
List<MonoInstaller> _installerPrefabs = new List<MonoInstaller>();
|
||||
|
||||
List<InstallerBase> _normalInstallers = new List<InstallerBase>();
|
||||
List<Type> _normalInstallerTypes = new List<Type>();
|
||||
|
||||
public IEnumerable<MonoInstaller> Installers
|
||||
{
|
||||
get { return _monoInstallers; }
|
||||
set
|
||||
{
|
||||
_monoInstallers.Clear();
|
||||
_monoInstallers.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<MonoInstaller> InstallerPrefabs
|
||||
{
|
||||
get { return _installerPrefabs; }
|
||||
set
|
||||
{
|
||||
_installerPrefabs.Clear();
|
||||
_installerPrefabs.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ScriptableObjectInstaller> ScriptableObjectInstallers
|
||||
{
|
||||
get { return _scriptableObjectInstallers; }
|
||||
set
|
||||
{
|
||||
_scriptableObjectInstallers.Clear();
|
||||
_scriptableObjectInstallers.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike other installer types this has to be set through code
|
||||
public IEnumerable<Type> NormalInstallerTypes
|
||||
{
|
||||
get { return _normalInstallerTypes; }
|
||||
set
|
||||
{
|
||||
Assert.That(value.All(x => x != null && x.DerivesFrom<InstallerBase>()));
|
||||
|
||||
_normalInstallerTypes.Clear();
|
||||
_normalInstallerTypes.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike other installer types this has to be set through code
|
||||
public IEnumerable<InstallerBase> NormalInstallers
|
||||
{
|
||||
get { return _normalInstallers; }
|
||||
set
|
||||
{
|
||||
_normalInstallers.Clear();
|
||||
_normalInstallers.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract DiContainer Container
|
||||
{
|
||||
get;
|
||||
}
|
||||
public abstract IEnumerable<GameObject> GetRootGameObjects();
|
||||
|
||||
|
||||
public void AddNormalInstallerType(Type installerType)
|
||||
{
|
||||
Assert.IsNotNull(installerType);
|
||||
Assert.That(installerType.DerivesFrom<InstallerBase>());
|
||||
|
||||
_normalInstallerTypes.Add(installerType);
|
||||
}
|
||||
|
||||
public void AddNormalInstaller(InstallerBase installer)
|
||||
{
|
||||
_normalInstallers.Add(installer);
|
||||
}
|
||||
|
||||
void CheckInstallerPrefabTypes(List<MonoInstaller> installers, List<MonoInstaller> installerPrefabs)
|
||||
{
|
||||
foreach (var installer in installers)
|
||||
{
|
||||
Assert.IsNotNull(installer, "Found null installer in Context '{0}'", name);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
Assert.That(!PrefabUtility.IsPartOfPrefabAsset(installer.gameObject),
|
||||
#else
|
||||
Assert.That(PrefabUtility.GetPrefabType(installer.gameObject) != PrefabType.Prefab,
|
||||
#endif
|
||||
"Found prefab with name '{0}' in the Installer property of Context '{1}'. You should use the property 'InstallerPrefabs' for this instead.", installer.name, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
foreach (var installerPrefab in installerPrefabs)
|
||||
{
|
||||
Assert.IsNotNull(installerPrefab, "Found null prefab in Context");
|
||||
|
||||
// We'd like to do this but this is actually a valid case sometimes
|
||||
// (eg. loading an asset bundle with a scene containing a scene context when inside unity editor)
|
||||
//#if UNITY_EDITOR
|
||||
//Assert.That(PrefabUtility.GetPrefabType(installerPrefab.gameObject) == PrefabType.Prefab,
|
||||
//"Found non-prefab with name '{0}' in the InstallerPrefabs property of Context '{1}'. You should use the property 'Installer' for this instead",
|
||||
//installerPrefab.name, this.name);
|
||||
//#endif
|
||||
Assert.That(installerPrefab.GetComponent<MonoInstaller>() != null,
|
||||
"Expected to find component with type 'MonoInstaller' on given installer prefab '{0}'", installerPrefab.name);
|
||||
}
|
||||
}
|
||||
|
||||
protected void InstallInstallers()
|
||||
{
|
||||
InstallInstallers(
|
||||
_normalInstallers, _normalInstallerTypes, _scriptableObjectInstallers, _monoInstallers, _installerPrefabs);
|
||||
}
|
||||
|
||||
protected void InstallInstallers(
|
||||
List<InstallerBase> normalInstallers,
|
||||
List<Type> normalInstallerTypes,
|
||||
List<ScriptableObjectInstaller> scriptableObjectInstallers,
|
||||
List<MonoInstaller> installers,
|
||||
List<MonoInstaller> installerPrefabs)
|
||||
{
|
||||
CheckInstallerPrefabTypes(installers, installerPrefabs);
|
||||
|
||||
// Ideally we would just have one flat list of all the installers
|
||||
// since that way the user has complete control over the order, but
|
||||
// that's not possible since Unity does not allow serializing lists of interfaces
|
||||
// (and it has to be an inteface since the scriptable object installers only share
|
||||
// the interface)
|
||||
//
|
||||
// So the best we can do is have a hard-coded order in terms of the installer type
|
||||
//
|
||||
// The order is:
|
||||
// - Normal installers given directly via code
|
||||
// - ScriptableObject installers
|
||||
// - MonoInstallers in the scene
|
||||
// - Prefab Installers
|
||||
//
|
||||
// We put ScriptableObject installers before the MonoInstallers because
|
||||
// ScriptableObjectInstallers are often used for settings (including settings
|
||||
// that are injected into other installers like MonoInstallers)
|
||||
|
||||
var allInstallers = normalInstallers.Cast<IInstaller>()
|
||||
.Concat(scriptableObjectInstallers.Cast<IInstaller>())
|
||||
.Concat(installers.Cast<IInstaller>()).ToList();
|
||||
|
||||
foreach (var installerPrefab in installerPrefabs)
|
||||
{
|
||||
Assert.IsNotNull(installerPrefab, "Found null installer prefab in '{0}'", GetType());
|
||||
|
||||
GameObject installerGameObject;
|
||||
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("GameObject.Instantiate"))
|
||||
#endif
|
||||
{
|
||||
installerGameObject = GameObject.Instantiate(installerPrefab.gameObject);
|
||||
}
|
||||
|
||||
installerGameObject.transform.SetParent(transform, false);
|
||||
var installer = installerGameObject.GetComponent<MonoInstaller>();
|
||||
|
||||
Assert.IsNotNull(installer, "Could not find installer component on prefab '{0}'", installerPrefab.name);
|
||||
|
||||
allInstallers.Add(installer);
|
||||
}
|
||||
|
||||
foreach (var installerType in normalInstallerTypes)
|
||||
{
|
||||
var installer = (InstallerBase)Container.Instantiate(installerType);
|
||||
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("User Code"))
|
||||
#endif
|
||||
{
|
||||
installer.InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var installer in allInstallers)
|
||||
{
|
||||
Assert.IsNotNull(installer,
|
||||
"Found null installer in '{0}'", GetType());
|
||||
|
||||
Container.Inject(installer);
|
||||
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("User Code"))
|
||||
#endif
|
||||
{
|
||||
installer.InstallBindings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void InstallSceneBindings(List<MonoBehaviour> injectableMonoBehaviours)
|
||||
{
|
||||
foreach (var binding in injectableMonoBehaviours.OfType<ZenjectBinding>())
|
||||
{
|
||||
if (binding == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (binding.Context == null || (binding.UseSceneContext && this is SceneContext))
|
||||
{
|
||||
binding.Context = this;
|
||||
}
|
||||
}
|
||||
|
||||
// We'd prefer to use GameObject.FindObjectsOfType<ZenjectBinding>() here
|
||||
// instead but that doesn't find inactive gameobjects
|
||||
// TODO: Consider changing this
|
||||
// Maybe ZenjectBinding could add itself to a registry class on Awake/OnEnable
|
||||
// then we could avoid calling the slow Resources.FindObjectsOfTypeAll here
|
||||
foreach (var binding in Resources.FindObjectsOfTypeAll<ZenjectBinding>())
|
||||
{
|
||||
if (binding == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is necessary for cases where the ZenjectBinding is inside a GameObjectContext
|
||||
// since it won't be caught in the other loop above
|
||||
if (this is SceneContext)
|
||||
{
|
||||
if (binding.Context == null && binding.UseSceneContext
|
||||
&& binding.gameObject.scene == gameObject.scene)
|
||||
{
|
||||
binding.Context = this;
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.Context == this)
|
||||
{
|
||||
InstallZenjectBinding(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InstallZenjectBinding(ZenjectBinding binding)
|
||||
{
|
||||
if (!binding.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (binding.Components == null || binding.Components.IsEmpty())
|
||||
{
|
||||
Log.Warn("Found empty list of components on ZenjectBinding on object '{0}'", binding.name);
|
||||
return;
|
||||
}
|
||||
|
||||
string identifier = null;
|
||||
|
||||
if (binding.Identifier.Trim().Length > 0)
|
||||
{
|
||||
identifier = binding.Identifier;
|
||||
}
|
||||
|
||||
foreach (var component in binding.Components)
|
||||
{
|
||||
var bindType = binding.BindType;
|
||||
|
||||
if (component == null)
|
||||
{
|
||||
Log.Warn("Found null component in ZenjectBinding on object '{0}'", binding.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
var componentType = component.GetType();
|
||||
|
||||
switch (bindType)
|
||||
{
|
||||
case ZenjectBinding.BindTypes.Self:
|
||||
{
|
||||
Container.Bind(componentType).WithId(identifier).FromInstance(component);
|
||||
break;
|
||||
}
|
||||
case ZenjectBinding.BindTypes.BaseType:
|
||||
{
|
||||
Container.Bind(componentType.BaseType()).WithId(identifier).FromInstance(component);
|
||||
break;
|
||||
}
|
||||
case ZenjectBinding.BindTypes.AllInterfaces:
|
||||
{
|
||||
Container.Bind(componentType.Interfaces()).WithId(identifier).FromInstance(component);
|
||||
break;
|
||||
}
|
||||
case ZenjectBinding.BindTypes.AllInterfacesAndSelf:
|
||||
{
|
||||
Container.Bind(componentType.Interfaces().Concat(new[] { componentType }).ToArray()).WithId(identifier).FromInstance(component);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw Assert.CreateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void GetInjectableMonoBehaviours(List<MonoBehaviour> components);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be0cf56827265f44bbdeba09329d66ab
|
||||
timeCreated: 1461708053
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,205 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Zenject.Internal;
|
||||
|
||||
#pragma warning disable 649
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public class GameObjectContext : RunnableContext
|
||||
{
|
||||
public event Action PreInstall;
|
||||
public event Action PostInstall;
|
||||
public event Action PreResolve;
|
||||
public event Action PostResolve;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Note that this field is optional and can be ignored in most cases. This is really only needed if you want to control the 'Script Execution Order' of your subcontainer. In this case, define a new class that derives from MonoKernel, add it to this game object, then drag it into this field. Then you can set a value for 'Script Execution Order' for this new class and this will control when all ITickable/IInitializable classes bound within this subcontainer get called.")]
|
||||
[FormerlySerializedAs("_facade")]
|
||||
MonoKernel _kernel;
|
||||
|
||||
DiContainer _container;
|
||||
|
||||
// Need to cache this when auto run is false
|
||||
DiContainer _parentContainer;
|
||||
|
||||
bool _hasInstalled;
|
||||
|
||||
public override DiContainer Container
|
||||
{
|
||||
get { return _container; }
|
||||
}
|
||||
|
||||
public override IEnumerable<GameObject> GetRootGameObjects()
|
||||
{
|
||||
return new[] { gameObject };
|
||||
}
|
||||
|
||||
[Inject]
|
||||
public void Construct(
|
||||
DiContainer parentContainer)
|
||||
{
|
||||
Assert.IsNull(_parentContainer);
|
||||
_parentContainer = parentContainer;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
protected override void RunInternal()
|
||||
{
|
||||
Install(_parentContainer);
|
||||
ResolveAndStart();
|
||||
}
|
||||
|
||||
public void Install(DiContainer parentContainer)
|
||||
{
|
||||
Assert.That(_parentContainer == null || _parentContainer == parentContainer);
|
||||
|
||||
// We allow calling this explicitly instead of relying on the [Inject] event above
|
||||
// so that we can follow the two-pass construction-injection pattern in the providers
|
||||
if (_hasInstalled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_hasInstalled = true;
|
||||
|
||||
Assert.IsNull(_container);
|
||||
_container = parentContainer.CreateSubContainer();
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (instance is MonoKernel)
|
||||
{
|
||||
Assert.That(ReferenceEquals(instance, _kernel),
|
||||
"Found MonoKernel derived class that is not hooked up to GameObjectContext. If you use MonoKernel, you must indicate this to GameObjectContext by dragging and dropping it to the Kernel field in the inspector");
|
||||
}
|
||||
|
||||
_container.QueueForInject(instance);
|
||||
}
|
||||
|
||||
_container.IsInstalling = true;
|
||||
|
||||
try
|
||||
{
|
||||
InstallBindings(injectableMonoBehaviours);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_container.IsInstalling = false;
|
||||
}
|
||||
|
||||
if (PostInstall != null)
|
||||
{
|
||||
PostInstall();
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveAndStart()
|
||||
{
|
||||
if (PreResolve != null)
|
||||
{
|
||||
PreResolve();
|
||||
}
|
||||
|
||||
_container.ResolveRoots();
|
||||
|
||||
if (PostResolve != null)
|
||||
{
|
||||
PostResolve();
|
||||
}
|
||||
|
||||
// Normally, the IInitializable.Initialize method would be called during MonoKernel.Start
|
||||
// However, this behaviour is undesirable for dynamically created objects, since Unity
|
||||
// has the strange behaviour of waiting until the end of the frame to call Start() on
|
||||
// dynamically created objects, which means that any GameObjectContext that is created
|
||||
// dynamically via a factory cannot be used immediately after calling Create(), since
|
||||
// it will not have been initialized
|
||||
// So we have chosen to diverge from Unity behaviour here and trigger IInitializable.Initialize
|
||||
// immediately - but only when the GameObjectContext is created dynamically. For any
|
||||
// GameObjectContext's that are placed in the scene, we still want to execute
|
||||
// IInitializable.Initialize during Start()
|
||||
if (gameObject.scene.isLoaded && !_container.IsValidating)
|
||||
{
|
||||
_kernel = _container.Resolve<MonoKernel>();
|
||||
_kernel.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetInjectableMonoBehaviours(List<MonoBehaviour> monoBehaviours)
|
||||
{
|
||||
ZenUtilInternal.AddStateMachineBehaviourAutoInjectersUnderGameObject(gameObject);
|
||||
|
||||
// We inject on all components on the root except ourself
|
||||
foreach (var monoBehaviour in GetComponents<MonoBehaviour>())
|
||||
{
|
||||
if (monoBehaviour == null)
|
||||
{
|
||||
// Missing script
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ZenUtilInternal.IsInjectableMonoBehaviourType(monoBehaviour.GetType()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (monoBehaviour == this)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
monoBehaviours.Add(monoBehaviour);
|
||||
}
|
||||
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
{
|
||||
var child = transform.GetChild(i);
|
||||
|
||||
if (child != null)
|
||||
{
|
||||
ZenUtilInternal.GetInjectableMonoBehavioursUnderGameObject(
|
||||
child.gameObject, monoBehaviours);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InstallBindings(List<MonoBehaviour> injectableMonoBehaviours)
|
||||
{
|
||||
_container.DefaultParent = transform;
|
||||
|
||||
_container.Bind<Context>().FromInstance(this);
|
||||
_container.Bind<GameObjectContext>().FromInstance(this);
|
||||
|
||||
if (_kernel == null)
|
||||
{
|
||||
_container.Bind<MonoKernel>()
|
||||
.To<DefaultGameObjectKernel>().FromNewComponentOn(gameObject).AsSingle().NonLazy();
|
||||
}
|
||||
else
|
||||
{
|
||||
_container.Bind<MonoKernel>().FromInstance(_kernel).AsSingle().NonLazy();
|
||||
}
|
||||
|
||||
InstallSceneBindings(injectableMonoBehaviours);
|
||||
InstallInstallers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08eca9f7688a0a24685b89133b020c8e
|
||||
timeCreated: 1456086415
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4e6589720da476459dc6dd71624b071
|
||||
timeCreated: 1487808999
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public abstract class RunnableContext : Context
|
||||
{
|
||||
[Tooltip("When false, wait until run method is explicitly called. Otherwise run on initialize")]
|
||||
[SerializeField]
|
||||
bool _autoRun = true;
|
||||
|
||||
static bool _staticAutoRun = true;
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
protected void Initialize()
|
||||
{
|
||||
if (_staticAutoRun && _autoRun)
|
||||
{
|
||||
Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
// True should always be default
|
||||
_staticAutoRun = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
Assert.That(!Initialized,
|
||||
"The context already has been initialized!");
|
||||
|
||||
RunInternal();
|
||||
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
protected abstract void RunInternal();
|
||||
|
||||
public static T CreateComponent<T>(GameObject gameObject) where T : RunnableContext
|
||||
{
|
||||
_staticAutoRun = false;
|
||||
|
||||
var result = gameObject.AddComponent<T>();
|
||||
Assert.That(_staticAutoRun); // Should be reset
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13e9b26d23f6422cb282cc27631fc9e2
|
||||
timeCreated: 1494725784
|
||||
@@ -0,0 +1,381 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ModestTree;
|
||||
using ModestTree.Util;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Zenject.Internal;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public class SceneContext : RunnableContext
|
||||
{
|
||||
public event Action PreInstall;
|
||||
public event Action PostInstall;
|
||||
public event Action PreResolve;
|
||||
public event Action PostResolve;
|
||||
|
||||
public UnityEvent OnPreInstall;
|
||||
public UnityEvent OnPostInstall;
|
||||
public UnityEvent OnPreResolve;
|
||||
public UnityEvent OnPostResolve;
|
||||
|
||||
public static Action<DiContainer> ExtraBindingsInstallMethod;
|
||||
public static Action<DiContainer> ExtraBindingsLateInstallMethod;
|
||||
|
||||
public static IEnumerable<DiContainer> ParentContainers;
|
||||
|
||||
[FormerlySerializedAs("ParentNewObjectsUnderRoot")]
|
||||
[FormerlySerializedAs("_parentNewObjectsUnderRoot")]
|
||||
[Tooltip("When true, objects that are created at runtime will be parented to the SceneContext")]
|
||||
[SerializeField]
|
||||
bool _parentNewObjectsUnderSceneContext;
|
||||
|
||||
[Tooltip("Optional contract names for this SceneContext, allowing contexts in subsequently loaded scenes to depend on it and be parented to it, and also for previously loaded decorators to be included")]
|
||||
[SerializeField]
|
||||
List<string> _contractNames = new List<string>();
|
||||
|
||||
[Tooltip("Optional contract names of SceneContexts in previously loaded scenes that this context depends on and to which it should be parented")]
|
||||
[SerializeField]
|
||||
List<string> _parentContractNames = new List<string>();
|
||||
|
||||
DiContainer _container;
|
||||
|
||||
readonly List<SceneDecoratorContext> _decoratorContexts = new List<SceneDecoratorContext>();
|
||||
|
||||
bool _hasInstalled;
|
||||
bool _hasResolved;
|
||||
|
||||
public override DiContainer Container
|
||||
{
|
||||
get { return _container; }
|
||||
}
|
||||
|
||||
public bool HasResolved
|
||||
{
|
||||
get { return _hasResolved; }
|
||||
}
|
||||
|
||||
public bool HasInstalled
|
||||
{
|
||||
get { return _hasInstalled; }
|
||||
}
|
||||
|
||||
public bool IsValidating
|
||||
{
|
||||
get
|
||||
{
|
||||
return ProjectContext.Instance.Container.IsValidating;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> ContractNames
|
||||
{
|
||||
get { return _contractNames; }
|
||||
set
|
||||
{
|
||||
_contractNames.Clear();
|
||||
_contractNames.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> ParentContractNames
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new List<string>();
|
||||
result.AddRange(_parentContractNames);
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
_parentContractNames = value.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ParentNewObjectsUnderSceneContext
|
||||
{
|
||||
get { return _parentNewObjectsUnderSceneContext; }
|
||||
set { _parentNewObjectsUnderSceneContext = value; }
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
ProfileTimers.ResetAll();
|
||||
using (ProfileTimers.CreateTimedBlock("Other"))
|
||||
#endif
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
Assert.That(IsValidating);
|
||||
|
||||
Install();
|
||||
Resolve();
|
||||
}
|
||||
|
||||
protected override void RunInternal()
|
||||
{
|
||||
// We always want to initialize ProjectContext as early as possible
|
||||
ProjectContext.Instance.EnsureIsInitialized();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using (ProfileBlock.Start("Zenject.SceneContext.Install"))
|
||||
#endif
|
||||
{
|
||||
Install();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using (ProfileBlock.Start("Zenject.SceneContext.Resolve"))
|
||||
#endif
|
||||
{
|
||||
Resolve();
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<GameObject> GetRootGameObjects()
|
||||
{
|
||||
return ZenUtilInternal.GetRootGameObjects(gameObject.scene);
|
||||
}
|
||||
|
||||
IEnumerable<DiContainer> GetParentContainers()
|
||||
{
|
||||
var parentContractNames = ParentContractNames;
|
||||
|
||||
if (parentContractNames.IsEmpty())
|
||||
{
|
||||
if (ParentContainers != null)
|
||||
{
|
||||
var tempParentContainer = ParentContainers;
|
||||
|
||||
// Always reset after using it - it is only used to pass the reference
|
||||
// between scenes via ZenjectSceneLoader
|
||||
ParentContainers = null;
|
||||
|
||||
return tempParentContainer;
|
||||
}
|
||||
|
||||
return new[] { ProjectContext.Instance.Container };
|
||||
}
|
||||
|
||||
Assert.IsNull(ParentContainers,
|
||||
"Scene cannot have both a parent scene context name set and also an explicit parent container given");
|
||||
|
||||
var parentContainers = UnityUtil.AllLoadedScenes
|
||||
.Except(gameObject.scene)
|
||||
.SelectMany(scene => scene.GetRootGameObjects())
|
||||
.SelectMany(root => root.GetComponentsInChildren<SceneContext>())
|
||||
.Where(sceneContext => sceneContext.ContractNames.Where(x => parentContractNames.Contains(x)).Any())
|
||||
.Select(x => x.Container)
|
||||
.ToList();
|
||||
|
||||
if (!parentContainers.Any())
|
||||
{
|
||||
throw Assert.CreateException(
|
||||
"SceneContext on object {0} of scene {1} requires at least one of contracts '{2}', but none of the loaded SceneContexts implements that contract.",
|
||||
gameObject.name,
|
||||
gameObject.scene.name,
|
||||
parentContractNames.Join(", "));
|
||||
}
|
||||
|
||||
return parentContainers;
|
||||
}
|
||||
|
||||
List<SceneDecoratorContext> LookupDecoratorContexts()
|
||||
{
|
||||
if (_contractNames.IsEmpty())
|
||||
{
|
||||
return new List<SceneDecoratorContext>();
|
||||
}
|
||||
|
||||
return UnityUtil.AllLoadedScenes
|
||||
.Except(gameObject.scene)
|
||||
.SelectMany(scene => scene.GetRootGameObjects())
|
||||
.SelectMany(root => root.GetComponentsInChildren<SceneDecoratorContext>())
|
||||
.Where(decoratorContext => _contractNames.Contains(decoratorContext.DecoratedContractName))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void Install()
|
||||
{
|
||||
Assert.That(!_hasInstalled);
|
||||
_hasInstalled = true;
|
||||
|
||||
Assert.IsNull(_container);
|
||||
|
||||
var parents = GetParentContainers();
|
||||
Assert.That(!parents.IsEmpty());
|
||||
Assert.That(parents.All(x => x.IsValidating == parents.First().IsValidating));
|
||||
|
||||
_container = new DiContainer(parents, parents.First().IsValidating);
|
||||
|
||||
// Do this after creating DiContainer in case it's needed by the pre install logic
|
||||
if (PreInstall != null)
|
||||
{
|
||||
PreInstall();
|
||||
}
|
||||
|
||||
if (OnPreInstall != null)
|
||||
{
|
||||
OnPreInstall.Invoke();
|
||||
}
|
||||
|
||||
Assert.That(_decoratorContexts.IsEmpty());
|
||||
_decoratorContexts.AddRange(LookupDecoratorContexts());
|
||||
|
||||
if (_parentNewObjectsUnderSceneContext)
|
||||
{
|
||||
_container.DefaultParent = transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
_container.DefaultParent = null;
|
||||
}
|
||||
|
||||
// Record all the injectable components in the scene BEFORE installing the installers
|
||||
// This is nice for cases where the user calls InstantiatePrefab<>, etc. in their installer
|
||||
// so that it doesn't inject on the game object twice
|
||||
// InitialComponentsInjecter will also guarantee that any component that is injected into
|
||||
// another component has itself been injected
|
||||
var injectableMonoBehaviours = new List<MonoBehaviour>();
|
||||
GetInjectableMonoBehaviours(injectableMonoBehaviours);
|
||||
foreach (var instance in injectableMonoBehaviours)
|
||||
{
|
||||
_container.QueueForInject(instance);
|
||||
}
|
||||
|
||||
foreach (var decoratorContext in _decoratorContexts)
|
||||
{
|
||||
decoratorContext.Initialize(_container);
|
||||
}
|
||||
|
||||
_container.IsInstalling = true;
|
||||
|
||||
try
|
||||
{
|
||||
InstallBindings(injectableMonoBehaviours);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_container.IsInstalling = false;
|
||||
}
|
||||
|
||||
if (PostInstall != null)
|
||||
{
|
||||
PostInstall();
|
||||
}
|
||||
|
||||
if (OnPostInstall != null)
|
||||
{
|
||||
OnPostInstall.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void Resolve()
|
||||
{
|
||||
if (PreResolve != null)
|
||||
{
|
||||
PreResolve();
|
||||
}
|
||||
|
||||
if (OnPreResolve != null)
|
||||
{
|
||||
OnPreResolve.Invoke();
|
||||
}
|
||||
|
||||
Assert.That(_hasInstalled);
|
||||
Assert.That(!_hasResolved);
|
||||
_hasResolved = true;
|
||||
|
||||
_container.ResolveRoots();
|
||||
|
||||
if (PostResolve != null)
|
||||
{
|
||||
PostResolve();
|
||||
}
|
||||
|
||||
if (OnPostResolve != null)
|
||||
{
|
||||
OnPostResolve.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
void InstallBindings(List<MonoBehaviour> injectableMonoBehaviours)
|
||||
{
|
||||
_container.Bind(typeof(Context), typeof(SceneContext)).To<SceneContext>().FromInstance(this);
|
||||
_container.BindInterfacesTo<SceneContextRegistryAdderAndRemover>().AsSingle();
|
||||
|
||||
// Add to registry first and remove from registry last
|
||||
_container.BindExecutionOrder<SceneContextRegistryAdderAndRemover>(-1);
|
||||
|
||||
foreach (var decoratorContext in _decoratorContexts)
|
||||
{
|
||||
decoratorContext.InstallDecoratorSceneBindings();
|
||||
}
|
||||
|
||||
InstallSceneBindings(injectableMonoBehaviours);
|
||||
|
||||
_container.Bind(typeof(SceneKernel), typeof(MonoKernel))
|
||||
.To<SceneKernel>().FromNewComponentOn(gameObject).AsSingle().NonLazy();
|
||||
|
||||
_container.Bind<ZenjectSceneLoader>().AsSingle();
|
||||
|
||||
if (ExtraBindingsInstallMethod != null)
|
||||
{
|
||||
ExtraBindingsInstallMethod(_container);
|
||||
// Reset extra bindings for next time we change scenes
|
||||
ExtraBindingsInstallMethod = null;
|
||||
}
|
||||
|
||||
// Always install the installers last so they can be injected with
|
||||
// everything above
|
||||
foreach (var decoratorContext in _decoratorContexts)
|
||||
{
|
||||
decoratorContext.InstallDecoratorInstallers();
|
||||
}
|
||||
|
||||
InstallInstallers();
|
||||
|
||||
foreach (var decoratorContext in _decoratorContexts)
|
||||
{
|
||||
decoratorContext.InstallLateDecoratorInstallers();
|
||||
}
|
||||
|
||||
if (ExtraBindingsLateInstallMethod != null)
|
||||
{
|
||||
ExtraBindingsLateInstallMethod(_container);
|
||||
// Reset extra bindings for next time we change scenes
|
||||
ExtraBindingsLateInstallMethod = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetInjectableMonoBehaviours(List<MonoBehaviour> monoBehaviours)
|
||||
{
|
||||
var scene = gameObject.scene;
|
||||
|
||||
ZenUtilInternal.AddStateMachineBehaviourAutoInjectersInScene(scene);
|
||||
ZenUtilInternal.GetInjectableMonoBehavioursInScene(scene, monoBehaviours);
|
||||
}
|
||||
|
||||
// These methods can be used for cases where you need to create the SceneContext entirely in code
|
||||
// Note that if you use these methods that you have to call Run() yourself
|
||||
// This is useful because it allows you to create a SceneContext and configure it how you want
|
||||
// and add what installers you want before kicking off the Install/Resolve
|
||||
public static SceneContext Create()
|
||||
{
|
||||
return CreateComponent<SceneContext>(
|
||||
new GameObject("SceneContext"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89715ad69b973a14899afa2c6730b30b
|
||||
timeCreated: 1435941958
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -9999
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Zenject.Internal;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public class SceneDecoratorContext : Context
|
||||
{
|
||||
[SerializeField]
|
||||
List<MonoInstaller> _lateInstallers = new List<MonoInstaller>();
|
||||
|
||||
[SerializeField]
|
||||
List<MonoInstaller> _lateInstallerPrefabs = new List<MonoInstaller>();
|
||||
|
||||
[SerializeField]
|
||||
List<ScriptableObjectInstaller> _lateScriptableObjectInstallers = new List<ScriptableObjectInstaller>();
|
||||
|
||||
public IEnumerable<MonoInstaller> LateInstallers
|
||||
{
|
||||
get { return _lateInstallers; }
|
||||
set
|
||||
{
|
||||
_lateInstallers.Clear();
|
||||
_lateInstallers.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<MonoInstaller> LateInstallerPrefabs
|
||||
{
|
||||
get { return _lateInstallerPrefabs; }
|
||||
set
|
||||
{
|
||||
_lateInstallerPrefabs.Clear();
|
||||
_lateInstallerPrefabs.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ScriptableObjectInstaller> LateScriptableObjectInstallers
|
||||
{
|
||||
get { return _lateScriptableObjectInstallers; }
|
||||
set
|
||||
{
|
||||
_lateScriptableObjectInstallers.Clear();
|
||||
_lateScriptableObjectInstallers.AddRange(value);
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("SceneName")]
|
||||
[SerializeField]
|
||||
string _decoratedContractName = null;
|
||||
|
||||
DiContainer _container;
|
||||
readonly List<MonoBehaviour> _injectableMonoBehaviours = new List<MonoBehaviour>();
|
||||
|
||||
public string DecoratedContractName
|
||||
{
|
||||
get { return _decoratedContractName; }
|
||||
}
|
||||
|
||||
public override DiContainer Container
|
||||
{
|
||||
get
|
||||
{
|
||||
Assert.IsNotNull(_container);
|
||||
return _container;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<GameObject> GetRootGameObjects()
|
||||
{
|
||||
// This method should never be called because SceneDecoratorContext's are not bound
|
||||
// to the container
|
||||
throw Assert.CreateException();
|
||||
}
|
||||
|
||||
public void Initialize(DiContainer container)
|
||||
{
|
||||
Assert.IsNull(_container);
|
||||
Assert.That(_injectableMonoBehaviours.IsEmpty());
|
||||
|
||||
_container = container;
|
||||
|
||||
GetInjectableMonoBehaviours(_injectableMonoBehaviours);
|
||||
|
||||
foreach (var instance in _injectableMonoBehaviours)
|
||||
{
|
||||
container.QueueForInject(instance);
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallDecoratorSceneBindings()
|
||||
{
|
||||
_container.Bind<SceneDecoratorContext>().FromInstance(this);
|
||||
InstallSceneBindings(_injectableMonoBehaviours);
|
||||
}
|
||||
|
||||
public void InstallDecoratorInstallers()
|
||||
{
|
||||
InstallInstallers();
|
||||
}
|
||||
|
||||
protected override void GetInjectableMonoBehaviours(List<MonoBehaviour> monoBehaviours)
|
||||
{
|
||||
var scene = gameObject.scene;
|
||||
|
||||
ZenUtilInternal.AddStateMachineBehaviourAutoInjectersInScene(scene);
|
||||
ZenUtilInternal.GetInjectableMonoBehavioursInScene(scene, monoBehaviours);
|
||||
}
|
||||
|
||||
public void InstallLateDecoratorInstallers()
|
||||
{
|
||||
InstallInstallers(new List<InstallerBase>(), new List<Type>(), _lateScriptableObjectInstallers, _lateInstallers, _lateInstallerPrefabs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed7323e8fdd8c26438c6485f2060dad0
|
||||
timeCreated: 1487808999
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// For some platforms, it's desirable to be able to add dependencies to Zenject before
|
||||
// Unity even starts up (eg. WSA as described here https://github.com/svermeulen/Zenject/issues/118)
|
||||
// In those cases you can call StaticContext.Container.BindX to add dependencies
|
||||
// Anything you add there will then be injected everywhere, since all other contexts
|
||||
// should be children of StaticContext
|
||||
public static class StaticContext
|
||||
{
|
||||
static DiContainer _container;
|
||||
|
||||
// Useful sometimes to call from play mode tests
|
||||
public static void Clear()
|
||||
{
|
||||
_container = null;
|
||||
}
|
||||
|
||||
public static bool HasContainer
|
||||
{
|
||||
get { return _container != null; }
|
||||
}
|
||||
|
||||
public static DiContainer Container
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_container == null)
|
||||
{
|
||||
_container = new DiContainer();
|
||||
}
|
||||
|
||||
return _container;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 668a9feb769954340b35901a0c829397
|
||||
timeCreated: 1462834162
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Zenject
|
||||
{
|
||||
// We extract the interface so that monobehaviours can be installers
|
||||
public interface IInstaller
|
||||
{
|
||||
void InstallBindings();
|
||||
|
||||
bool IsEnabled
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65a9d43edcbe33640989f12f980de5d1
|
||||
timeCreated: 1461708051
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace Zenject
|
||||
{
|
||||
//
|
||||
// I'd recommmend using Installer<> instead, and then always use the approach
|
||||
// of calling `MyInstaller.Install(Container)`
|
||||
// This way, if you want to add strongly typed parameters later you can do this
|
||||
// by deriving from a different Installer<> base class
|
||||
//
|
||||
public abstract class Installer : InstallerBase
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Derive from this class then install like this:
|
||||
// FooInstaller.Install(Container);
|
||||
//
|
||||
public abstract class Installer<TDerived> : InstallerBase
|
||||
where TDerived : Installer<TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container)
|
||||
{
|
||||
container.Instantiate<TDerived>().InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
// Use these versions to pass parameters to your installer
|
||||
|
||||
public abstract class Installer<TParam1, TDerived> : InstallerBase
|
||||
where TDerived : Installer<TParam1, TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container, TParam1 p1)
|
||||
{
|
||||
container.InstantiateExplicit<TDerived>(
|
||||
InjectUtil.CreateArgListExplicit(p1)).InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Installer<TParam1, TParam2, TDerived> : InstallerBase
|
||||
where TDerived : Installer<TParam1, TParam2, TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container, TParam1 p1, TParam2 p2)
|
||||
{
|
||||
container.InstantiateExplicit<TDerived>(
|
||||
InjectUtil.CreateArgListExplicit(p1, p2)).InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Installer<TParam1, TParam2, TParam3, TDerived> : InstallerBase
|
||||
where TDerived : Installer<TParam1, TParam2, TParam3, TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3)
|
||||
{
|
||||
container.InstantiateExplicit<TDerived>(
|
||||
InjectUtil.CreateArgListExplicit(p1, p2, p3)).InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Installer<TParam1, TParam2, TParam3, TParam4, TDerived> : InstallerBase
|
||||
where TDerived : Installer<TParam1, TParam2, TParam3, TParam4, TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4)
|
||||
{
|
||||
container.InstantiateExplicit<TDerived>(
|
||||
InjectUtil.CreateArgListExplicit(p1, p2, p3, p4)).InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Installer<TParam1, TParam2, TParam3, TParam4, TParam5, TDerived> : InstallerBase
|
||||
where TDerived : Installer<TParam1, TParam2, TParam3, TParam4, TParam5, TDerived>
|
||||
{
|
||||
public static void Install(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4, TParam5 p5)
|
||||
{
|
||||
container.InstantiateExplicit<TDerived>(
|
||||
InjectUtil.CreateArgListExplicit(p1, p2, p3, p4, p5)).InstallBindings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 743eef94d86c79e4189b311a7c7528ce
|
||||
timeCreated: 1461708051
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Zenject
|
||||
{
|
||||
public abstract class InstallerBase : IInstaller
|
||||
{
|
||||
[Inject]
|
||||
DiContainer _container = null;
|
||||
|
||||
protected DiContainer Container
|
||||
{
|
||||
get { return _container; }
|
||||
}
|
||||
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public abstract void InstallBindings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d908209e11d07744483c5fea3b406f33
|
||||
timeCreated: 1465520282
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,171 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using ModestTree;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// We'd prefer to make this abstract but Unity 5.3.5 has a bug where references
|
||||
// can get lost during compile errors for classes that are abstract
|
||||
public class MonoInstaller : MonoInstallerBase
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Derive from this class instead to install like this:
|
||||
// FooInstaller.InstallFromResource(Container);
|
||||
// Or
|
||||
// FooInstaller.InstallFromResource("My/Path/ToPrefab", Container);
|
||||
//
|
||||
// (Instead of needing to add the MonoInstaller via inspector)
|
||||
//
|
||||
// This approach is needed if you want to pass in strongly parameters to it from
|
||||
// another installer
|
||||
public class MonoInstaller<TDerived> : MonoInstaller
|
||||
where TDerived : MonoInstaller<TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container)
|
||||
{
|
||||
return InstallFromResource(resourcePath, container, new object[0]);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(DiContainer container, object[] extraArgs)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, extraArgs);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, object[] extraArgs)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.Inject(installer, extraArgs);
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class MonoInstaller<TParam1, TDerived> : MonoInstallerBase
|
||||
where TDerived : MonoInstaller<TParam1, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class MonoInstaller<TParam1, TParam2, TDerived> : MonoInstallerBase
|
||||
where TDerived : MonoInstaller<TParam1, TParam2, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class MonoInstaller<TParam1, TParam2, TParam3, TDerived> : MonoInstallerBase
|
||||
where TDerived : MonoInstaller<TParam1, TParam2, TParam3, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2, p3);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2, p3));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class MonoInstaller<TParam1, TParam2, TParam3, TParam4, TDerived> : MonoInstallerBase
|
||||
where TDerived : MonoInstaller<TParam1, TParam2, TParam3, TParam4, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2, p3, p4));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class MonoInstaller<TParam1, TParam2, TParam3, TParam4, TParam5, TDerived> : MonoInstallerBase
|
||||
where TDerived : MonoInstaller<TParam1, TParam2, TParam3, TParam4, TParam5, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4, TParam5 p5)
|
||||
{
|
||||
return InstallFromResource(MonoInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2, p3, p4, p5);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4, TParam5 p5)
|
||||
{
|
||||
var installer = MonoInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2, p3, p4, p5));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MonoInstallerUtil
|
||||
{
|
||||
public static string GetDefaultResourcePath<TInstaller>()
|
||||
where TInstaller : MonoInstallerBase
|
||||
{
|
||||
return "Installers/" + typeof(TInstaller).PrettyName();
|
||||
}
|
||||
|
||||
public static TInstaller CreateInstaller<TInstaller>(
|
||||
string resourcePath, DiContainer container)
|
||||
where TInstaller : MonoInstallerBase
|
||||
{
|
||||
bool shouldMakeActive;
|
||||
var gameObj = container.CreateAndParentPrefabResource(
|
||||
resourcePath, GameObjectCreationParameters.Default, null, out shouldMakeActive);
|
||||
|
||||
if (shouldMakeActive && !container.IsValidating)
|
||||
{
|
||||
#if ZEN_INTERNAL_PROFILING
|
||||
using (ProfileTimers.CreateTimedBlock("User Code"))
|
||||
#endif
|
||||
{
|
||||
gameObj.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
var installers = gameObj.GetComponentsInChildren<TInstaller>();
|
||||
|
||||
Assert.That(installers.Length == 1,
|
||||
"Could not find unique MonoInstaller with type '{0}' on prefab '{1}'", typeof(TInstaller), gameObj.name);
|
||||
|
||||
return installers[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 724ff9f6c80e0b044b7db58730dc6075
|
||||
timeCreated: 1461708051
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// We'd prefer to make this abstract but Unity 5.3.5 has a bug where references
|
||||
// can get lost during compile errors for classes that are abstract
|
||||
[DebuggerStepThrough]
|
||||
public class MonoInstallerBase : MonoBehaviour, IInstaller
|
||||
{
|
||||
[Inject]
|
||||
protected DiContainer Container
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get { return enabled; }
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
// Define this method so we expose the enabled check box
|
||||
}
|
||||
|
||||
public virtual void InstallBindings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93d53e91e1ef3484a99feb7aa58f2b63
|
||||
timeCreated: 1465520769
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,141 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using ModestTree;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// We'd prefer to make this abstract but Unity 5.3.5 has a bug where references
|
||||
// can get lost during compile errors for classes that are abstract
|
||||
public class ScriptableObjectInstaller : ScriptableObjectInstallerBase
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Derive from this class instead to install like this:
|
||||
// FooInstaller.InstallFromResource(Container);
|
||||
// Or
|
||||
// FooInstaller.InstallFromResource("My/Path/ToScriptableObjectInstance", Container);
|
||||
//
|
||||
// (Instead of needing to add the ScriptableObjectInstaller directly via inspector)
|
||||
//
|
||||
// This approach is needed if you want to pass in strongly typed runtime parameters too it
|
||||
//
|
||||
public class ScriptableObjectInstaller<TDerived> : ScriptableObjectInstaller
|
||||
where TDerived : ScriptableObjectInstaller<TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container)
|
||||
{
|
||||
return InstallFromResource(
|
||||
ScriptableObjectInstallerUtil.GetDefaultResourcePath<TDerived>(), container);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container)
|
||||
{
|
||||
var installer = ScriptableObjectInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.Inject(installer);
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptableObjectInstaller<TParam1, TDerived> : ScriptableObjectInstallerBase
|
||||
where TDerived : ScriptableObjectInstaller<TParam1, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1)
|
||||
{
|
||||
return InstallFromResource(
|
||||
ScriptableObjectInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1)
|
||||
{
|
||||
var installer = ScriptableObjectInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptableObjectInstaller<TParam1, TParam2, TDerived> : ScriptableObjectInstallerBase
|
||||
where TDerived : ScriptableObjectInstaller<TParam1, TParam2, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2)
|
||||
{
|
||||
return InstallFromResource(
|
||||
ScriptableObjectInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2)
|
||||
{
|
||||
var installer = ScriptableObjectInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptableObjectInstaller<TParam1, TParam2, TParam3, TDerived> : ScriptableObjectInstallerBase
|
||||
where TDerived : ScriptableObjectInstaller<TParam1, TParam2, TParam3, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3)
|
||||
{
|
||||
return InstallFromResource(
|
||||
ScriptableObjectInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2, p3);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3)
|
||||
{
|
||||
var installer = ScriptableObjectInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2, p3));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptableObjectInstaller<TParam1, TParam2, TParam3, TParam4, TDerived> : ScriptableObjectInstallerBase
|
||||
where TDerived : ScriptableObjectInstaller<TParam1, TParam2, TParam3, TParam4, TDerived>
|
||||
{
|
||||
public static TDerived InstallFromResource(DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4)
|
||||
{
|
||||
return InstallFromResource(
|
||||
ScriptableObjectInstallerUtil.GetDefaultResourcePath<TDerived>(), container, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
public static TDerived InstallFromResource(string resourcePath, DiContainer container, TParam1 p1, TParam2 p2, TParam3 p3, TParam4 p4)
|
||||
{
|
||||
var installer = ScriptableObjectInstallerUtil.CreateInstaller<TDerived>(resourcePath, container);
|
||||
container.InjectExplicit(installer, InjectUtil.CreateArgListExplicit(p1, p2, p3, p4));
|
||||
installer.InstallBindings();
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScriptableObjectInstallerUtil
|
||||
{
|
||||
public static string GetDefaultResourcePath<TInstaller>()
|
||||
where TInstaller : ScriptableObjectInstallerBase
|
||||
{
|
||||
return "Installers/" + typeof(TInstaller).PrettyName();
|
||||
}
|
||||
|
||||
public static TInstaller CreateInstaller<TInstaller>(
|
||||
string resourcePath, DiContainer container)
|
||||
where TInstaller : ScriptableObjectInstallerBase
|
||||
{
|
||||
var installers = Resources.LoadAll(resourcePath);
|
||||
|
||||
Assert.That(installers.Length == 1,
|
||||
"Could not find unique ScriptableObjectInstaller with type '{0}' at resource path '{1}'", typeof(TInstaller), resourcePath);
|
||||
|
||||
var installer = installers[0];
|
||||
|
||||
Assert.That(installer is TInstaller,
|
||||
"Expected to find installer with type '{0}' at resource path '{1}'", typeof(TInstaller), resourcePath);
|
||||
|
||||
return (TInstaller)installer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00b9d7602aaf02748aa93779bbf29799
|
||||
timeCreated: 1461708048
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// We'd prefer to make this abstract but Unity 5.3.5 has a bug where references
|
||||
// can get lost during compile errors for classes that are abstract
|
||||
public class ScriptableObjectInstallerBase : ScriptableObject, IInstaller
|
||||
{
|
||||
[Inject]
|
||||
DiContainer _container = null;
|
||||
|
||||
protected DiContainer Container
|
||||
{
|
||||
get { return _container; }
|
||||
}
|
||||
|
||||
bool IInstaller.IsEnabled
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public virtual void InstallBindings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97c39aeade32bd54c8754bc9d6da25ab
|
||||
timeCreated: 1465523215
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
#if !NOT_UNITY3D
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
public class ZenjectBinding : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The component to add to the Zenject container")]
|
||||
[SerializeField]
|
||||
Component[] _components = null;
|
||||
|
||||
[Tooltip("Note: This value is optional and can be ignored in most cases. This can be useful to differentiate multiple bindings of the same type. For example, if you have multiple cameras in your scene, you can 'name' them by giving each one a different identifier. For your main camera you might call it 'Main' then any class can refer to it by using an attribute like [Inject(Id = 'Main')]")]
|
||||
[SerializeField]
|
||||
string _identifier = string.Empty;
|
||||
|
||||
[Tooltip("When set, this will bind the given components to the SceneContext. It can be used as a shortcut to explicitly dragging the SceneContext into the Context field. This is useful when using ZenjectBinding inside GameObjectContext. If your ZenjectBinding is for a component that is not underneath GameObjectContext then it is not necessary to check this")]
|
||||
[SerializeField]
|
||||
bool _useSceneContext = false;
|
||||
|
||||
[Tooltip("Note: This value is optional and can be ignored in most cases. This value will determine what container the component gets added to. If unset, the component will be bound on the most 'local' context. In most cases this will be the SceneContext, unless this component is underneath a GameObjectContext, or ProjectContext, in which case it will bind to that instead by default. You can also override this default by providing the Context directly. This can be useful if you want to bind something that is inside a GameObjectContext to the SceneContext container.")]
|
||||
[SerializeField]
|
||||
[FormerlySerializedAs("_compositionRoot")]
|
||||
Context _context = null;
|
||||
|
||||
[Tooltip("This value is used to determine how to bind this component. When set to 'Self' is equivalent to calling Container.FromInstance inside an installer. When set to 'AllInterfaces' this is equivalent to calling 'Container.BindInterfaces<MyMonoBehaviour>().ToInstance', and similarly for InterfacesAndSelf")]
|
||||
[SerializeField]
|
||||
BindTypes _bindType = BindTypes.Self;
|
||||
|
||||
public bool UseSceneContext
|
||||
{
|
||||
get { return _useSceneContext; }
|
||||
}
|
||||
|
||||
public Context Context
|
||||
{
|
||||
get { return _context; }
|
||||
set { _context = value; }
|
||||
}
|
||||
|
||||
public Component[] Components
|
||||
{
|
||||
get { return _components; }
|
||||
}
|
||||
|
||||
public string Identifier
|
||||
{
|
||||
get { return _identifier; }
|
||||
}
|
||||
|
||||
public BindTypes BindType
|
||||
{
|
||||
get { return _bindType; }
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// Define this method so we expose the enabled check box
|
||||
}
|
||||
|
||||
public enum BindTypes
|
||||
{
|
||||
Self,
|
||||
AllInterfaces,
|
||||
AllInterfacesAndSelf,
|
||||
BaseType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0166d8ff8d905b048b2448179e1f5d11
|
||||
timeCreated: 1454288321
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
namespace Zenject
|
||||
{
|
||||
// This is installed by default in ProjectContext, however, if you are using Zenject outside
|
||||
// of Unity then you might want to call this
|
||||
//
|
||||
// In this case though, you will have to manually call InitializableManager.Initialize,
|
||||
// DisposableManager.Dispose, TickableManager.Tick, etc. when appropriate for the environment
|
||||
// you are working in
|
||||
//
|
||||
// You might also want to use this installer in a ZenjectUnitTestFixture
|
||||
public class ZenjectManagersInstaller : Installer<ZenjectManagersInstaller>
|
||||
{
|
||||
public override void InstallBindings()
|
||||
{
|
||||
Container.Bind(typeof(TickableManager), typeof(InitializableManager), typeof(DisposableManager))
|
||||
.ToSelf().AsSingle().CopyIntoAllSubContainers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b05e95f8fed82b244b78a5e2df541713
|
||||
timeCreated: 1529046908
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user