Update Project

This commit is contained in:
2026-03-20 13:04:43 +02:00
parent 9b587e6cba
commit beae2dea89
2295 changed files with 251259 additions and 33 deletions
@@ -0,0 +1,450 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ModestTree;
#if ZEN_SIGNALS_ADD_UNIRX
using UniRx;
#endif
namespace Zenject
{
public class SignalBus : ILateDisposable
{
readonly SignalSubscription.Pool _subscriptionPool;
readonly Dictionary<BindingId, SignalDeclaration> _localDeclarationMap = new Dictionary<BindingId, SignalDeclaration>();
readonly SignalBus _parentBus;
readonly Dictionary<SignalSubscriptionId, SignalSubscription> _subscriptionMap = new Dictionary<SignalSubscriptionId, SignalSubscription>();
readonly ZenjectSettings.SignalSettings _settings;
readonly SignalDeclaration.Factory _signalDeclarationFactory;
readonly DiContainer _container;
public SignalBus(
[Inject(Source = InjectSources.Local)]
List<SignalDeclaration> signalDeclarations,
[Inject(Source = InjectSources.Parent, Optional = true)]
SignalBus parentBus,
[InjectOptional]
ZenjectSettings zenjectSettings,
SignalSubscription.Pool subscriptionPool,
SignalDeclaration.Factory signalDeclarationFactory,
DiContainer container)
{
_subscriptionPool = subscriptionPool;
zenjectSettings = zenjectSettings ?? ZenjectSettings.Default;
_settings = zenjectSettings.Signals ?? ZenjectSettings.SignalSettings.Default;
_signalDeclarationFactory = signalDeclarationFactory;
_container = container;
signalDeclarations.ForEach(x =>
{
if (!_localDeclarationMap.ContainsKey(x.BindingId))
{
_localDeclarationMap.Add(x.BindingId, x);
}
else _localDeclarationMap[x.BindingId].Subscriptions.AllocFreeAddRange(x.Subscriptions);
});
_parentBus = parentBus;
}
public SignalBus ParentBus
{
get { return _parentBus; }
}
public int NumSubscribers
{
get { return _subscriptionMap.Count; }
}
//Fires Signals with their interfaces
public void AbstractFire<TSignal>() where TSignal : new() => AbstractFire(new TSignal());
public void AbstractFire<TSignal>(TSignal signal) => AbstractFireId(null, signal);
public void AbstractFireId<TSignal>(object identifier, TSignal signal)
{
// Do this before creating the signal so that it throws if the signal was not declared
Type signalType = typeof(TSignal);
InternalFire(signalType, signal, identifier, true);
Type[] interfaces = signalType.GetInterfaces();
int numOfInterfaces = interfaces.Length;
for (int i = 0; i < numOfInterfaces; i++)
{
InternalFire(interfaces[i], signal, identifier, true);
}
}
public void LateDispose()
{
if (_settings.RequireStrictUnsubscribe)
{
if (!_subscriptionMap.IsEmpty())
{
throw Assert.CreateException(
"Found subscriptions for signals '{0}' in SignalBus.LateDispose! Either add the explicit Unsubscribe or set SignalSettings.AutoUnsubscribeInDispose to true",
_subscriptionMap.Values.Select(x => x.SignalId.ToString()).Join(", "));
}
}
else
{
foreach (var subscription in _subscriptionMap.Values)
{
subscription.Dispose();
}
}
foreach (var declaration in _localDeclarationMap.Values)
{
declaration.Dispose();
}
}
public void FireId<TSignal>(object identifier, TSignal signal)
{
InternalFire(typeof(TSignal), signal, identifier, true);
}
public void Fire<TSignal>(TSignal signal)
{
FireId<TSignal>(null, signal);
}
public void FireId<TSignal>(object identifier)
{
InternalFire(typeof(TSignal), null, identifier, true);
}
public void Fire<TSignal>()
{
FireId<TSignal>(null);
}
public void FireId(object identifier, object signal)
{
InternalFire(signal.GetType(), signal, identifier, true);
}
public void Fire(object signal)
{
FireId(null, signal);
}
public bool IsSignalDeclared<TSignal>()
{
return IsSignalDeclared(typeof(TSignal), null);
}
public bool IsSignalDeclared<TSignal>(object identifier)
{
return IsSignalDeclared(typeof(TSignal), identifier);
}
public bool IsSignalDeclared(Type signalType)
{
return IsSignalDeclared(signalType, null);
}
public bool IsSignalDeclared(Type signalType, object identifier)
{
var signalId = new BindingId(signalType, identifier);
return GetDeclaration(signalId) != null;
}
public void TryFireId<TSignal>(object identifier, TSignal signal)
{
InternalFire(typeof(TSignal), signal, identifier, false);
}
public void TryFire<TSignal>(TSignal signal)
{
TryFireId<TSignal>(null, signal);
}
public void TryFireId<TSignal>(object identifier)
{
InternalFire(typeof(TSignal), null, identifier, false);
}
public void TryFire<TSignal>()
{
TryFireId<TSignal>(null);
}
public void TryFireId(object identifier, object signal)
{
InternalFire(signal.GetType(), signal, identifier, false);
}
public void TryFire(object signal)
{
TryFireId(null, signal);
}
private void InternalFire(Type signalType, object signal, object identifier, bool requireDeclaration)
{
var signalId = new BindingId(signalType, identifier);
// Do this before creating the signal so that it throws if the signal was not declared
var declaration = GetDeclaration(signalId);
if (declaration == null)
{
if (requireDeclaration)
{
throw Assert.CreateException("Fired undeclared signal '{0}'!", signalId);
}
}
else
{
if (signal == null)
{
signal = Activator.CreateInstance(signalType);
}
declaration.Fire(signal);
}
}
#if ZEN_SIGNALS_ADD_UNIRX
public IObservable<TSignal> GetStreamId<TSignal>(object identifier)
{
return GetStreamId(typeof(TSignal), identifier).Select(x => (TSignal)x);
}
public IObservable<TSignal> GetStream<TSignal>()
{
return GetStreamId<TSignal>(null);
}
public IObservable<object> GetStreamId(Type signalType, object identifier)
{
return GetDeclaration(new BindingId(signalType, identifier)).Stream;
}
public IObservable<object> GetStream(Type signalType)
{
return GetStreamId(signalType, null);
}
#endif
public void SubscribeId<TSignal>(object identifier, Action callback)
{
Action<object> wrapperCallback = args => callback();
SubscribeInternal(typeof(TSignal), identifier, callback, wrapperCallback);
}
public void Subscribe<TSignal>(Action callback)
{
SubscribeId<TSignal>(null, callback);
}
public void SubscribeId<TSignal>(object identifier, Action<TSignal> callback)
{
Action<object> wrapperCallback = args => callback((TSignal)args);
SubscribeInternal(typeof(TSignal), identifier, callback, wrapperCallback);
}
public void Subscribe<TSignal>(Action<TSignal> callback)
{
SubscribeId<TSignal>(null, callback);
}
public void SubscribeId(Type signalType, object identifier, Action<object> callback)
{
SubscribeInternal(signalType, identifier, callback, callback);
}
public void Subscribe(Type signalType, Action<object> callback)
{
SubscribeId(signalType, null, callback);
}
public void UnsubscribeId<TSignal>(object identifier, Action callback)
{
UnsubscribeId(typeof(TSignal), identifier, callback);
}
public void Unsubscribe<TSignal>(Action callback)
{
UnsubscribeId<TSignal>(null, callback);
}
public void UnsubscribeId(Type signalType, object identifier, Action callback)
{
UnsubscribeInternal(signalType, identifier, callback, true);
}
public void Unsubscribe(Type signalType, Action callback)
{
UnsubscribeId(signalType, null, callback);
}
public void UnsubscribeId(Type signalType, object identifier, Action<object> callback)
{
UnsubscribeInternal(signalType, identifier, callback, true);
}
public void Unsubscribe(Type signalType, Action<object> callback)
{
UnsubscribeId(signalType, null, callback);
}
public void UnsubscribeId<TSignal>(object identifier, Action<TSignal> callback)
{
UnsubscribeInternal(typeof(TSignal), identifier, callback, true);
}
public void Unsubscribe<TSignal>(Action<TSignal> callback)
{
UnsubscribeId<TSignal>(null, callback);
}
public void TryUnsubscribeId<TSignal>(object identifier, Action callback)
{
UnsubscribeInternal(typeof(TSignal), identifier, callback, false);
}
public void TryUnsubscribe<TSignal>(Action callback)
{
TryUnsubscribeId<TSignal>(null, callback);
}
public void TryUnsubscribeId(Type signalType, object identifier, Action callback)
{
UnsubscribeInternal(signalType, identifier, callback, false);
}
public void TryUnsubscribe(Type signalType, Action callback)
{
TryUnsubscribeId(signalType, null, callback);
}
public void TryUnsubscribeId(Type signalType, object identifier, Action<object> callback)
{
UnsubscribeInternal(signalType, identifier, callback, false);
}
public void TryUnsubscribe(Type signalType, Action<object> callback)
{
TryUnsubscribeId(signalType, null, callback);
}
public void TryUnsubscribeId<TSignal>(object identifier, Action<TSignal> callback)
{
UnsubscribeInternal(typeof(TSignal), identifier, callback, false);
}
public void TryUnsubscribe<TSignal>(Action<TSignal> callback)
{
TryUnsubscribeId<TSignal>(null, callback);
}
void UnsubscribeInternal(Type signalType, object identifier, object token, bool throwIfMissing)
{
UnsubscribeInternal(new BindingId(signalType, identifier), token, throwIfMissing);
}
void UnsubscribeInternal(BindingId signalId, object token, bool throwIfMissing)
{
UnsubscribeInternal(
new SignalSubscriptionId(signalId, token), throwIfMissing);
}
void UnsubscribeInternal(SignalSubscriptionId id, bool throwIfMissing)
{
SignalSubscription subscription;
if (_subscriptionMap.TryGetValue(id, out subscription))
{
_subscriptionMap.RemoveWithConfirm(id);
subscription.Dispose();
}
else
{
if (throwIfMissing)
{
throw Assert.CreateException(
"Called unsubscribe for signal '{0}' but could not find corresponding subscribe. If this is intentional, call TryUnsubscribe instead.");
}
}
}
void SubscribeInternal(Type signalType, object identifier, object token, Action<object> callback)
{
SubscribeInternal(new BindingId(signalType, identifier), token, callback);
}
void SubscribeInternal(BindingId signalId, object token, Action<object> callback)
{
SubscribeInternal(
new SignalSubscriptionId(signalId, token), callback);
}
void SubscribeInternal(SignalSubscriptionId id, Action<object> callback)
{
Assert.That(!_subscriptionMap.ContainsKey(id),
"Tried subscribing to the same signal with the same callback on Zenject.SignalBus");
var declaration = GetDeclaration(id.SignalId);
if (declaration == null)
{
throw Assert.CreateException("Tried subscribing to undeclared signal '{0}'!", id.SignalId);
}
var subscription = _subscriptionPool.Spawn(callback, declaration);
_subscriptionMap.Add(id, subscription);
}
public void DeclareSignal<T>(
object identifier = null, SignalMissingHandlerResponses? missingHandlerResponse = null, bool? forceAsync = null, int? asyncTickPriority = null)
{
DeclareSignal(typeof(T), identifier, missingHandlerResponse, forceAsync, asyncTickPriority);
}
public void DeclareSignal(
Type signalType, object identifier = null, SignalMissingHandlerResponses? missingHandlerResponse = null, bool? forceAsync = null, int? asyncTickPriority = null)
{
var bindInfo = SignalExtensions.CreateDefaultSignalDeclarationBindInfo(_container, signalType);
bindInfo.Identifier = identifier;
if (missingHandlerResponse.HasValue)
{
bindInfo.Identifier = missingHandlerResponse.Value;
}
if (forceAsync.HasValue)
{
bindInfo.RunAsync = forceAsync.Value;
}
if (asyncTickPriority.HasValue)
{
bindInfo.TickPriority = asyncTickPriority.Value;
}
var declaration = _signalDeclarationFactory.Create(bindInfo);
_localDeclarationMap.Add(declaration.BindingId, declaration);
}
SignalDeclaration GetDeclaration(BindingId signalId)
{
SignalDeclaration handler;
if (_localDeclarationMap.TryGetValue(signalId, out handler))
{
return handler;
}
if (_parentBus != null)
{
return _parentBus.GetDeclaration(signalId);
}
return null;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d457d0e45e1d3c54f9bc2bc3aece1760
timeCreated: 1521266917
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
using ModestTree;
namespace Zenject
{
// Note that you only need to install this once
public class SignalBusInstaller : Installer<SignalBusInstaller>
{
public override void InstallBindings()
{
Assert.That(!Container.HasBinding<SignalBus>(), "Detected multiple SignalBus bindings. SignalBusInstaller should only be installed once");
Container.BindInterfacesAndSelfTo<SignalBus>().AsSingle().CopyIntoAllSubContainers();
Container.BindInterfacesTo<SignalDeclarationAsyncInitializer>().AsSingle().CopyIntoAllSubContainers();
Container.BindMemoryPool<SignalSubscription, SignalSubscription.Pool>();
// Dispose last to ensure that we don't remove SignalSubscription before the user does
Container.BindLateDisposableExecutionOrder<SignalBus>(-999);
Container.BindFactory<SignalDeclarationBindInfo, SignalDeclaration, SignalDeclaration.Factory>();
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 2afd112e630107f458140fbe19d4e31c
timeCreated: 1528988907
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,40 @@
using System.Collections.Generic;
using ModestTree;
namespace Zenject
{
// This class just exists to solve a circular dependency that would otherwise happen if we
// attempted to inject TickableManager into either SignalDeclaration or SignalBus
// And we need to directly depend on TickableManager because we need each SignalDeclaration
// to have a unique tick priority
public class SignalDeclarationAsyncInitializer : IInitializable
{
readonly LazyInject<TickableManager> _tickManager;
readonly List<SignalDeclaration> _declarations;
public SignalDeclarationAsyncInitializer(
[Inject(Source = InjectSources.Local)]
List<SignalDeclaration> declarations,
[Inject(Optional = true, Source = InjectSources.Local)]
LazyInject<TickableManager> tickManager)
{
_declarations = declarations;
_tickManager = tickManager;
}
public void Initialize()
{
for (int i = 0; i < _declarations.Count; i++)
{
var declaration = _declarations[i];
if (declaration.IsAsync)
{
Assert.IsNotNull(_tickManager.Value, "TickableManager is required when using asynchronous signals");
_tickManager.Value.Add(declaration, declaration.TickPriority);
}
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e8d0040c0a3734b49b26f7cdaa86c5e8
timeCreated: 1529153251
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: