Skip to content

Commit 0b1933f

Browse files
Merge pull request #96 from Antoshidza/main
Make scene building editable
2 parents 4593b54 + 0b7ddd5 commit 0b1933f

14 files changed

+42
-179
lines changed

.github/README.md

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,24 @@ public class Loader : MonoBehaviour
160160
{
161161
private void Start()
162162
{
163-
var extraInstallerScope = new ExtraInstallerScope(greetSceneScopeBuilder =>
163+
void InstallExtra(Scene scene, ContainerBuilder builder)
164164
{
165-
greetSceneScopeBuilder.AddSingleton("of Developers");
166-
});
165+
builder.AddSingleton("of Developers");
166+
}
167+
168+
// This way you can access ContainerBuilder of the scene that is currently building
169+
SceneScope.OnSceneContainerBuilding += InstallExtra;
167170

168171
// If you are loading scenes without addressables
169172
UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("Greet").completed += operation =>
170173
{
171-
extraInstallerScope.Dispose();
174+
SceneScope.OnSceneContainerBuilding -= InstallExtra;
172175
};
173176

174177
// If you are loading scenes with addressables
175178
UnityEngine.AddressableAssets.Addressables.LoadSceneAsync("Greet").Completed += operation =>
176179
{
177-
extraInstallerScope.Dispose();
180+
SceneScope.OnSceneContainerBuilding -= InstallExtra;
178181
};
179182
}
180183
}
@@ -214,26 +217,31 @@ ProjectContainer --> GameScene
214217
ProjectContainer --> GameModeTwoScene
215218
```
216219

217-
### Parent Override Scope
218-
The `ParentOverrideScope` class allows you to temporarily override the default parent container for all containers created via `ContainerBuilder`. Once an instance of this scope is created, it remains active until explicitly disposed, during which time all newly built containers will inherit from the overridden parent instead of the default one.
219-
This is particularly useful for instance when you want one scene to inherit services from another scene, enabling a more granular control over which parent container is used for each newly loaded scene.
220-
220+
### Override scene container parent
221+
To do this or whatever else you want with scene `ContainerBuilder` you can access it with `SceneScope.OnSceneContainerBuilding` like we show in `Loader.cs` in "Getting Started" section.
221222
```csharp
223+
// here we take boot scene container just for an example, you can use any container you need
222224
var bootSceneContainer = gameObject.scene.GetSceneContainer();
223-
var parentOverrideScope = new ParentOverrideScope(bootSceneContainer);
225+
226+
void OverrideParent(Scene scene, ContainerBuilder builder)
227+
{
228+
builder.SetParent(bootSceneContainer);
229+
}
230+
231+
SceneScope.OnSceneContainerBuilding += OverrideParent;
224232

225233
// If you are loading scenes without addressables
226234
SceneManager.LoadSceneAsync("Lobby", LoadSceneMode.Additive).completed += operation =>
227235
{
228-
parentOverrideScope.Dispose();
236+
SceneScope.OnSceneContainerBuilding -= OverrideParent;
229237
};
230238

231239
// If you are loading scenes with addressables
232240
Addressables.LoadSceneAsync("Lobby", LoadSceneMode.Additive).Completed += operation =>
233241
{
234-
parentOverrideScope.Dispose();
242+
SceneScope.OnSceneContainerBuilding -= OverrideParent;
235243
};
236-
```
244+
```
237245

238246
By utilizing this API, you can create hierarchical structures such as the one shown below:
239247

@@ -287,35 +295,6 @@ using var scopedContainer = parentContainer.Scope(builder =>
287295
});
288296
```
289297

290-
### Extra Installer Scope
291-
The `ExtraInstallerScope` provides a mechanism for injecting additional bindings into containers after their initial setup. Once an instance of this scope is created, it remains active until explicitly disposed, it acts as a post-installation hook for all containers built through `ContainerBuilder`.
292-
This is especially useful in dynamic scenarios—for example, if you have fetched asynchronous dependencies in a boot scene and want to ensure they are available when transitioning into a gameplay scene. It supports use cases resembling a state machine, where the application moves from an "initializing" state to a "ready" state, injecting the required dependencies at the appropriate time.
293-
294-
Below is an example of a Boot scene that retrieves a remote configuration before transitioning to the Game scene. By the time the Game scene is loaded, the remote configuration is already registered within the Game scene's scope container.
295-
296-
```csharp
297-
public class Boot : MonoBehaviour
298-
{
299-
private async void Start()
300-
{
301-
var remoteConfig = await FetchRemoteConfigAsync();
302-
303-
var extraInstallerScope = new ExtraInstallerScope(gameSceneScopeContainerBuilder =>
304-
{
305-
gameSceneScopeContainerBuilder.AddSingleton(remoteConfig);
306-
});
307-
308-
SceneManager.LoadSceneAsync("Game").completed += operation => extraInstallerScope.Dispose();
309-
}
310-
311-
private async Task<string> FetchRemoteConfigAsync()
312-
{
313-
await Task.Delay(1000); // Simulate network delay
314-
return "remote config data";
315-
}
316-
}
317-
```
318-
319298
## 🔩 Bindings
320299

321300
### AddSingleton (From Type)

Assets/Reflex.EditModeTests/ExtraInstallerScopeTests.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

Assets/Reflex.EditModeTests/ExtraInstallerScopeTests.cs.meta

Lines changed: 0 additions & 3 deletions
This file was deleted.

Assets/Reflex.EditModeTests/ParentOverrideScopeTests.cs

Lines changed: 0 additions & 32 deletions
This file was deleted.

Assets/Reflex.EditModeTests/ParentOverrideScopeTests.cs.meta

Lines changed: 0 additions & 3 deletions
This file was deleted.

Assets/Reflex/Core/Container.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public sealed class Container : IDisposable
1818
internal List<Container> Children { get; } = new();
1919
internal Dictionary<Type, List<IResolver>> ResolversByContract { get; }
2020
internal DisposableCollection Disposables { get; }
21+
#if UNITY_EDITOR
22+
internal static readonly List<Container> RootContainers = new();
23+
#endif
2124

2225
internal Container(string name, Container parent, Dictionary<Type, List<IResolver>> resolversByContract, DisposableCollection disposables)
2326
{
@@ -28,6 +31,13 @@ internal Container(string name, Container parent, Dictionary<Type, List<IResolve
2831
ResolversByContract = resolversByContract;
2932
Disposables = disposables;
3033
OverrideSelfInjection();
34+
35+
#if UNITY_EDITOR
36+
if (parent == null)
37+
{
38+
RootContainers.Add(this);
39+
}
40+
#endif
3141
}
3242

3343
public bool HasBinding<T>()

Assets/Reflex/Core/ContainerBuilder.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using Reflex.Extensions;
54
using Reflex.Generics;
6-
using Reflex.Injectors;
75
using Reflex.Resolvers;
86

97
namespace Reflex.Core
@@ -19,15 +17,6 @@ public Container Build()
1917
{
2018
var disposables = new DisposableCollection();
2119
var resolversByContract = new Dictionary<Type, List<IResolver>>();
22-
23-
// Extra installers
24-
UnityInjector.ExtraInstallers?.Invoke(this);
25-
26-
// Parent override
27-
if (UnityInjector.ContainerParentOverride.TryPeek(out var parentOverride))
28-
{
29-
Parent = parentOverride;
30-
}
3120

3221
// Inherited resolvers
3322
if (Parent != null)

Assets/Reflex/Core/ExtraInstallerScope.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

Assets/Reflex/Core/ExtraInstallerScope.cs.meta

Lines changed: 0 additions & 3 deletions
This file was deleted.

Assets/Reflex/Core/ParentOverrideScope.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)