// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using UnityEngine;
using UnityEngine.Events;
namespace Doozy.Runtime.Signals
{
/// Specialized class that connects to a signal stream to receive signals
[Serializable]
public class SignalReceiver : ISignalReceiver
{
/// Stream connection mode
[SerializeField] private StreamConnection ConnectionMode;
/// Signal provider id
[SerializeField] private ProviderId SignalProviderId;
/// Signal provider reference
[SerializeField] private SignalProvider ProviderReference;
/// Stream id
[SerializeField] private StreamId StreamId;
/// UnityAction triggered whenever a signal is sent though the stream this receiver is connected to
public UnityAction onSignal { get; set; }
/// Stream connection mode
public StreamConnection streamConnection { get => ConnectionMode; protected internal set => ConnectionMode = value; }
/// Signal provider id
public ProviderId providerId { get => SignalProviderId; protected internal set => SignalProviderId = value; }
/// Signal provider reference
public SignalProvider providerReference { get => ProviderReference; protected internal set => ProviderReference = value; }
/// Stream id
public StreamId streamId { get => StreamId; protected internal set => StreamId = value; }
/// Stream id
public GameObject signalSource { get; protected internal set; }
public SignalStream stream { get; private set; }
public bool isConnected { get; private set; }
public bool isDisconnecting { get; private set; }
public SignalReceiver()
{
Reset();
}
public ISignalReceiver Reset()
{
ConnectionMode = StreamConnection.None;
SignalProviderId = new ProviderId();
ProviderReference = null;
StreamId = new StreamId();
signalSource = null;
stream = null;
isConnected = false;
isDisconnecting = false;
return this;
}
public virtual void OnSignal(Signal signal) =>
onSignal?.Invoke(signal);
public void Connect()
{
if (!Application.isPlaying)
{
Disconnect();
return;
}
if (isConnected)
return;
switch (streamConnection)
{
case StreamConnection.None: return;
case StreamConnection.ProviderId:
providerReference = (SignalProvider)SignalsService.GetProvider(providerId, signalSource);
if (providerReference == null)
{
Debug.Log("Provider not found!");
return;
}
if (!providerReference.isConnected) providerReference.OpenStream();
stream = providerReference.stream;
break;
case StreamConnection.ProviderReference:
if (providerReference == null)
{
Debug.Log("Provider not referenced!");
return;
}
if (!providerReference.isConnected) providerReference.OpenStream();
stream = providerReference.stream;
break;
case StreamConnection.StreamId:
if (streamId.Category.Equals(SignalStream.k_DefaultCategory) ||
streamId.Name.Equals(SignalStream.k_DefaultName))
{
Debug.Log($"Will not connect to {streamId.Category} > {streamId.Name}");
return;
}
stream = SignalsService.GetStream(streamId.Category, streamId.Name);
break;
default:
throw new ArgumentOutOfRangeException();
}
if (stream == null) //ToDo: check this particular case when the stream is null
{
return;
}
stream.ConnectReceiver(this);
streamId.SetStream(stream);
isConnected = true;
}
public void Disconnect()
{
if (!isConnected)
return;
SignalStream streamReference = stream;
stream = null;
isConnected = false;
streamReference.DisconnectReceiver(this);
}
}
public static class SignalReceiverExtensions
{
public static T SetStreamConnection(this T target, StreamConnection streamConnection) where T : SignalReceiver
{
target.streamConnection = streamConnection;
return target;
}
public static T SetProviderId(this T target, ProviderId providerId, bool updateStreamConnection = true) where T : SignalReceiver
{
target.providerId = providerId;
return updateStreamConnection ? target.SetStreamConnection(StreamConnection.ProviderId) : target;
}
public static T SetProviderReference(this T target, SignalProvider providerReference, bool updateStreamConnection = true) where T : SignalReceiver
{
target.providerReference = providerReference;
return updateStreamConnection ? target.SetStreamConnection(StreamConnection.ProviderReference) : target;
}
public static T SetStreamId(this T target, StreamId streamId, bool updateStreamConnection = true) where T : SignalReceiver
{
target.streamId = streamId;
return updateStreamConnection ? target.SetStreamConnection(StreamConnection.StreamId) : target;
}
public static T SetStreamId(this T target, string category, string name, bool updateStreamConnection = true) where T : SignalReceiver
{
target.streamId = new StreamId(category, name);
return updateStreamConnection ? target.SetStreamConnection(StreamConnection.StreamId) : target;
}
public static T SetSignalSource(this T target, GameObject signalSource) where T : SignalReceiver
{
if (target.isConnected) return target;
target.signalSource = signalSource;
return target;
}
public static T SetOnSignalCallback(this T target, UnityAction callback) where T : SignalReceiver
{
target.onSignal = callback;
return target;
}
public static T AddOnSignalCallback(this T target, UnityAction callback) where T : SignalReceiver
{
target.onSignal += callback;
return target;
}
public static T RemoveOnSignalCallback(this T target, UnityAction callback) where T : SignalReceiver
{
target.onSignal -= callback;
return target;
}
public static T ClearOnSignalCallback(this T target) where T : SignalReceiver
{
target.onSignal = null;
return target;
}
}
}