添加插件

This commit is contained in:
2025-11-10 00:08:26 +08:00
parent 4059c207c0
commit 76f80db694
2814 changed files with 436400 additions and 178 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 66c9748321f623d458ffaabf2176a2df
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
using System.Threading;
using UnityEngine;
namespace Obvious.Soap
{
/// <summary>
/// Base class for all event listeners
/// </summary>
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/event-listener")]
public abstract class EventListenerBase : MonoBehaviour
{
protected enum Binding
{
UNTIL_DESTROY,
UNTIL_DISABLE
}
[SerializeField] protected Binding _binding = Binding.UNTIL_DESTROY;
[SerializeField] protected bool _disableAfterSubscribing = false;
protected readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
protected abstract void ToggleRegistration(bool toggle);
/// <summary>
/// Returns true if the event listener contains a call to the method with the given name
/// </summary>
public abstract bool ContainsCallToMethod(string methodName);
protected virtual void Awake()
{
if (_binding == Binding.UNTIL_DESTROY)
ToggleRegistration(true);
gameObject.SetActive(!_disableAfterSubscribing);
}
protected virtual void OnEnable()
{
if (_binding == Binding.UNTIL_DISABLE)
ToggleRegistration(true);
}
protected virtual void OnDisable()
{
if (_binding == Binding.UNTIL_DISABLE)
{
ToggleRegistration(false);
_cancellationTokenSource.Cancel();
}
}
protected virtual void OnDestroy()
{
if (_binding == Binding.UNTIL_DESTROY)
{
ToggleRegistration(false);
_cancellationTokenSource.Cancel();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c8f4d2d3fb5e4a33b2cc509626f7313f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventBool
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerBool")]
public class EventListenerBool : EventListenerGeneric<bool>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<bool>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<bool>
{
[SerializeField] private ScriptableEventBool _scriptableEvent = null;
public override ScriptableEvent<bool> ScriptableEvent => _scriptableEvent;
[SerializeField] private BoolUnityEvent _response = null;
public override UnityEvent<bool> Response => _response;
}
[System.Serializable]
public class BoolUnityEvent : UnityEvent<bool>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e64750262007f204b879cd45e18965e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventColor
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerColor")]
public class EventListenerColor : EventListenerGeneric<Color>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Color>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Color>
{
[SerializeField] private ScriptableEventColor _scriptableEvent = null;
public override ScriptableEvent<Color> ScriptableEvent => _scriptableEvent;
[SerializeField] private ColorUnityEvent _response = null;
public override UnityEvent<Color> Response => _response;
}
[System.Serializable]
public class ColorUnityEvent : UnityEvent<Color>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d16da97870a756e4b9063178aca2c848
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
[AddComponentMenu("Soap/EventListeners/EventListenerComponent")]
public class EventListenerComponent : EventListenerGeneric<Component>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Component>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Component>
{
[SerializeField] private ScriptableEventComponent _scriptableEvent = null;
public override ScriptableEvent<Component> ScriptableEvent => _scriptableEvent;
[SerializeField] private ComponentUnityEvent _response = null;
public override UnityEvent<Component> Response => _response;
}
[System.Serializable]
public class ComponentUnityEvent : UnityEvent<Component>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04727cc775fa20d4c821cb3c9f304468
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventFloat
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerFloat")]
public class EventListenerFloat : EventListenerGeneric<float>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<float>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<float>
{
[SerializeField] private ScriptableEventFloat _scriptableEvent = null;
public override ScriptableEvent<float> ScriptableEvent => _scriptableEvent;
[SerializeField] private FloatUnityEvent _response = null;
public override UnityEvent<float> Response => _response;
}
[System.Serializable]
public class FloatUnityEvent : UnityEvent<float>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d0e4e54c3505e9428c41e7621def42c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventGameObject
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerGameObject")]
public class EventListenerGameObject : EventListenerGeneric<GameObject>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<GameObject>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<GameObject>
{
[SerializeField] private ScriptableEventGameObject _scriptableEvent = null;
public override ScriptableEvent<GameObject> ScriptableEvent => _scriptableEvent;
[SerializeField] private GameObjectUnityEvent _response = null;
public override UnityEvent<GameObject> Response => _response;
}
[System.Serializable]
public class GameObjectUnityEvent : UnityEvent<GameObject>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a09b9b4be86d5f4b83fa4de77c033f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
using System;
using UnityEngine.Events;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using System.Collections;
namespace Obvious.Soap
{
public abstract class EventListenerGeneric<T> : EventListenerBase
{
protected virtual EventResponse<T>[] EventResponses { get; }
private readonly Dictionary<ScriptableEvent<T>, EventResponse<T>> _dictionary =
new Dictionary<ScriptableEvent<T>, EventResponse<T>>();
protected override void ToggleRegistration(bool toggle)
{
foreach (var eventResponse in EventResponses)
{
if (toggle)
{
eventResponse.ScriptableEvent.RegisterListener(this);
if (!_dictionary.ContainsKey(eventResponse.ScriptableEvent))
_dictionary.Add(eventResponse.ScriptableEvent, eventResponse);
}
else
{
eventResponse.ScriptableEvent.UnregisterListener(this);
if (_dictionary.ContainsKey(eventResponse.ScriptableEvent))
_dictionary.Remove(eventResponse.ScriptableEvent);
}
}
}
internal void OnEventRaised(ScriptableEvent<T> eventRaised, T param, bool debug = false)
{
var eventResponse = _dictionary[eventRaised];
if (eventResponse.Delay > 0)
{
if (gameObject.activeInHierarchy)
StartCoroutine(Cr_DelayInvokeResponse(eventRaised, eventResponse, param, debug));
else
DelayInvokeResponseAsync(eventRaised, eventResponse, param, debug, _cancellationTokenSource.Token);
}
else
InvokeResponse(eventRaised, eventResponse, param, debug);
}
private IEnumerator Cr_DelayInvokeResponse(ScriptableEvent<T> eventRaised, EventResponse<T> eventResponse, T param,
bool debug)
{
yield return new WaitForSeconds(eventResponse.Delay);
InvokeResponse(eventRaised, eventResponse, param, debug);
}
private async void DelayInvokeResponseAsync(ScriptableEvent<T> eventRaised, EventResponse<T> eventResponse, T param,
bool debug, CancellationToken cancellationToken)
{
try
{
await Task.Delay((int)(eventResponse.Delay * 1000), cancellationToken);
InvokeResponse(eventRaised, eventResponse, param, debug);
}
catch (TaskCanceledException)
{
}
}
private void InvokeResponse(ScriptableEvent<T> eventRaised, EventResponse<T> eventResponse, T param, bool debug)
{
eventResponse.Response?.Invoke(param);
if (debug)
Debug(eventRaised);
}
protected virtual void Debug(ScriptableEvent<T> eventRaised)
{
var response = _dictionary[eventRaised].Response;
var registeredListenerCount = response.GetPersistentEventCount();
for (var i = 0; i < registeredListenerCount; i++)
{
var sb = new StringBuilder();
sb.Append("<color=#f75369>[Event] </color>");
sb.Append(eventRaised.name);
sb.Append(" => ");
sb.Append(response.GetPersistentTarget(i).name);
sb.Append(".");
sb.Append(response.GetPersistentMethodName(i));
sb.Append("()");
UnityEngine.Debug.Log(sb.ToString(), gameObject);
}
}
public override bool ContainsCallToMethod(string methodName)
{
var containsMethod = false;
foreach (var eventResponse in EventResponses)
{
var registeredListenerCount = eventResponse.Response.GetPersistentEventCount();
for (var i = 0; i < registeredListenerCount; i++)
{
if (eventResponse.Response.GetPersistentMethodName(i) == methodName)
{
var sb = new StringBuilder();
sb.Append($"<color=#f75369>{methodName}()</color>");
sb.Append(" is called by: <color=#f75369>[Event] </color>");
sb.Append(eventResponse.ScriptableEvent.name);
UnityEngine.Debug.Log(sb.ToString(), gameObject);
containsMethod = true;
break;
}
}
}
return containsMethod;
}
[Serializable]
public class EventResponse<U> : ISerializationCallbackReceiver
{
public virtual ScriptableEvent<U> ScriptableEvent { get; }
[Tooltip("Delay in seconds before invoking the response.")]
public FloatReference Delay = new FloatReference(0, true);
public virtual UnityEvent<U> Response { get; }
[NonSerialized]
private bool _isInitialized = false;
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
// Set Delay to use local only if it hasn't been initialized yet
if (!_isInitialized && Delay.Variable == null)
{
Delay.UseLocal = true;
_isInitialized = true;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85e92f331570c8543ae177f6ad340292
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventInt.
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerInt")]
public class EventListenerInt : EventListenerGeneric<int>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<int>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<int>
{
[SerializeField] private ScriptableEventInt _scriptableEvent = null;
public override ScriptableEvent<int> ScriptableEvent => _scriptableEvent;
[SerializeField] private IntUnityEvent _response = null;
public override UnityEvent<int> Response => _response;
}
[System.Serializable]
public class IntUnityEvent : UnityEvent<int>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f30bb439e6d7dc94489cd1be18593b0e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,155 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventNoParam.
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerNoParam")]
public class EventListenerNoParam : EventListenerBase
{
[SerializeField] private EventResponse[] _eventResponses = null;
private readonly Dictionary<ScriptableEventNoParam, EventResponse> _dictionary =
new Dictionary<ScriptableEventNoParam, EventResponse>();
protected override void ToggleRegistration(bool toggle)
{
foreach (var eventResponse in _eventResponses)
{
if (toggle)
{
eventResponse.ScriptableEvent.RegisterListener(this);
if (!_dictionary.ContainsKey(eventResponse.ScriptableEvent))
_dictionary.Add(eventResponse.ScriptableEvent, eventResponse);
}
else
{
eventResponse.ScriptableEvent.UnregisterListener(this);
if (_dictionary.ContainsKey(eventResponse.ScriptableEvent))
_dictionary.Remove(eventResponse.ScriptableEvent);
}
}
}
internal void OnEventRaised(ScriptableEventNoParam eventRaised, bool debug = false)
{
var eventResponse = _dictionary[eventRaised];
if (eventResponse.Delay > 0)
{
if (gameObject.activeInHierarchy)
StartCoroutine(Cr_DelayInvokeResponse(eventRaised, eventResponse, debug));
else
DelayInvokeResponseAsync(eventRaised, eventResponse, debug, _cancellationTokenSource.Token);
}
else
InvokeResponse(eventRaised, eventResponse, debug);
}
private IEnumerator Cr_DelayInvokeResponse(ScriptableEventNoParam eventRaised, EventResponse eventResponse,
bool debug)
{
yield return new WaitForSeconds(eventResponse.Delay);
InvokeResponse(eventRaised, eventResponse, debug);
}
private async void DelayInvokeResponseAsync(ScriptableEventNoParam eventRaised, EventResponse eventResponse,
bool debug, CancellationToken cancellationToken)
{
try
{
await Task.Delay((int)(eventResponse.Delay * 1000), cancellationToken);
InvokeResponse(eventRaised, eventResponse, debug);
}
catch (TaskCanceledException)
{
}
}
private void InvokeResponse(ScriptableEventNoParam eventRaised, EventResponse eventResponse, bool debug)
{
eventResponse.Response?.Invoke();
if (debug)
Debug(eventRaised);
}
[System.Serializable]
internal class EventResponse : ISerializationCallbackReceiver
{
[Tooltip("Delay in seconds before invoking the response.")]
public FloatReference Delay = new FloatReference(0,true);
public ScriptableEventNoParam ScriptableEvent;
public UnityEvent Response;
[System.NonSerialized]
private bool _isInitialized = false;
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
// Set Delay to use local only if it hasn't been initialized yet
if (!_isInitialized && Delay.Variable == null)
{
Delay.UseLocal = true;
_isInitialized = true;
}
}
}
#region Debugging
private void Debug(ScriptableEventNoParam eventRaised)
{
var response = _dictionary[eventRaised].Response;
var registeredListenerCount = response.GetPersistentEventCount();
for (var i = 0; i < registeredListenerCount; i++)
{
var debugText = "<color=#f75369>[Event] ";
debugText += eventRaised.name;
debugText += " => </color>";
debugText += response.GetPersistentTarget(i);
debugText += ".";
debugText += response.GetPersistentMethodName(i);
debugText += "()";
UnityEngine.Debug.Log(debugText, gameObject);
}
}
public override bool ContainsCallToMethod(string methodName)
{
var containsMethod = false;
foreach (var eventResponse in _eventResponses)
{
var registeredListenerCount = eventResponse.Response.GetPersistentEventCount();
for (int i = 0; i < registeredListenerCount; i++)
{
if (eventResponse.Response.GetPersistentMethodName(i) == methodName)
{
var debugText = $"<color=#f75369>{methodName}()</color>";
debugText += " is called by the event: <color=#f75369>";
debugText += eventResponse.ScriptableEvent.name;
debugText += "</color>";
UnityEngine.Debug.Log(debugText, gameObject);
containsMethod = true;
break;
}
}
}
return containsMethod;
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d93ba61543949824db31c7cb89b4f009
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using UnityEngine;
using UnityEngine.Events;
using Obvious.Soap;
namespace Obvious.Soap
{
[AddComponentMenu("Soap/EventListeners/EventListenerQuaternion")]
public class EventListenerQuaternion : EventListenerGeneric<Quaternion>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Quaternion>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Quaternion>
{
[SerializeField] private ScriptableEventQuaternion _scriptableEvent = null;
public override ScriptableEvent<Quaternion> ScriptableEvent => _scriptableEvent;
[SerializeField] private QuaternionUnityEvent _response = null;
public override UnityEvent<Quaternion> Response => _response;
}
[System.Serializable]
public class QuaternionUnityEvent : UnityEvent<Quaternion>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9321b24d9dbc1af43a0062ad96d8a2db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
/// <summary>
/// A listener for a ScriptableEventString.
/// </summary>
[AddComponentMenu("Soap/EventListeners/EventListenerString")]
public class EventListenerString : EventListenerGeneric<string>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<string>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<string>
{
[SerializeField] private ScriptableEventString _scriptableEvent = null;
public override ScriptableEvent<string> ScriptableEvent => _scriptableEvent;
[SerializeField] private StringUnityEvent _response = null;
public override UnityEvent<string> Response => _response;
}
[System.Serializable]
public class StringUnityEvent : UnityEvent<string>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2be4161beb6babe428f8453728aa3300
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
[AddComponentMenu("Soap/EventListeners/EventListenerVector2")]
public class EventListenerVector2 : EventListenerGeneric<Vector2>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Vector2>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Vector2>
{
[SerializeField] private ScriptableEventVector2 _scriptableEvent = null;
public override ScriptableEvent<Vector2> ScriptableEvent => _scriptableEvent;
[SerializeField] private Vector2UnityEvent _response = null;
public override UnityEvent<Vector2> Response => _response;
}
[System.Serializable]
public class Vector2UnityEvent : UnityEvent<Vector2>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b46fc160b957184ba7d1ed7716d1fcb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
[AddComponentMenu("Soap/EventListeners/EventListenerVector2Int")]
public class EventListenerVector2Int : EventListenerGeneric<Vector2Int>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Vector2Int>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Vector2Int>
{
[SerializeField] private ScriptableEventVector2Int _scriptableEvent = null;
public override ScriptableEvent<Vector2Int> ScriptableEvent => _scriptableEvent;
[SerializeField] private Vector2IntUnityEvent _response = null;
public override UnityEvent<Vector2Int> Response => _response;
}
[System.Serializable]
public class Vector2IntUnityEvent : UnityEvent<Vector2Int>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e4bf021e1d431447a582cf076d374db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap
{
[AddComponentMenu("Soap/EventListeners/EventListenerVector3")]
public class EventListenerVector3 : EventListenerGeneric<Vector3>
{
[SerializeField] private EventResponse[] _eventResponses = null;
protected override EventResponse<Vector3>[] EventResponses => _eventResponses;
[System.Serializable]
public class EventResponse : EventResponse<Vector3>
{
[SerializeField] private ScriptableEventVector3 _scriptableEvent = null;
public override ScriptableEvent<Vector3> ScriptableEvent => _scriptableEvent;
[SerializeField] private Vector3UnityEvent _response = null;
public override UnityEvent<Vector3> Response => _response;
}
[System.Serializable]
public class Vector3UnityEvent : UnityEvent<Vector3>
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 43f91a7ff6f55e448b69d6d2121dcc06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: f26f39c2872ef84439641da6a91f8b92, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using UnityEngine;
using Object = UnityEngine.Object;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
namespace Obvious.Soap
{
public abstract class ScriptableEvent<T> : ScriptableEventBase, IDrawObjectsInInspector
{
#if ODIN_INSPECTOR
[HideInInspector]
#endif
[Tooltip("Value used when raising the event in editor.")]
[SerializeField] protected T _debugValue = default(T);
private readonly List<EventListenerGeneric<T>> _eventListeners = new List<EventListenerGeneric<T>>();
private readonly List<Object> _listenersObjects = new List<Object>();
protected Action<T> _onRaised = null;
#if ODIN_INSPECTOR
[HideInEditorMode]
[ShowInInspector,EnableGUI]
public IEnumerable<Object> Listeners => EditorListeners;
#endif
/// <summary>
/// Action triggered when this event has been raised.
/// Subscribe to this action if you want to bind methods to this event.
/// </summary>
public event Action<T> OnRaised
{
add
{
_onRaised += value;
#if UNITY_EDITOR
var listener = value.Target as Object;
AddListener(listener);
#endif
}
remove
{
_onRaised -= value;
#if UNITY_EDITOR
var listener = value.Target as Object;
RemoveListener(listener);
#endif
}
}
public override Type GetGenericType => typeof(T);
#if ODIN_INSPECTOR
[Button]
[DisableInEditorMode]
#endif
public virtual void Raise(T param)
{
if (!Application.isPlaying)
return;
for (var i = _eventListeners.Count - 1; i >= 0; i--)
_eventListeners[i].OnEventRaised(this, param, _debugLogEnabled);
_onRaised?.Invoke(param);
#if UNITY_EDITOR
//As this uses reflection, I only allow it to be called in Editor.
//If you want to display debug in builds, delete the #if UNITY_EDITOR
if (_debugLogEnabled)
Debug();
#endif
}
internal void RegisterListener(EventListenerGeneric<T> listener)
{
if (!_eventListeners.Contains(listener))
_eventListeners.Add(listener);
}
internal void UnregisterListener(EventListenerGeneric<T> listener)
{
if (_eventListeners.Contains(listener))
_eventListeners.Remove(listener);
}
public IReadOnlyList<Object> EditorListeners => _listenersObjects.AsReadOnly();
protected virtual void Debug()
{
if (_onRaised == null)
return;
var delegates = _onRaised.GetInvocationList();
foreach (var del in delegates)
{
var sb = new StringBuilder();
sb.Append("<color=#f75369>[Event] </color>");
sb.Append(name);
sb.Append(" => ");
sb.Append(del.GetMethodInfo().Name);
sb.Append("()");
var monoBehaviour = del.Target as MonoBehaviour;
UnityEngine.Debug.Log(sb.ToString(), monoBehaviour?.gameObject);
}
}
internal override void Reset()
{
base.Reset();
_debugLogEnabled = false;
_debugValue = default;
}
#if UNITY_EDITOR
public void AddListener(Object listener)
{
if (listener != null && !_listenersObjects.Contains(listener))
_listenersObjects.Add(listener);
}
public void RemoveListener(Object listener)
{
if (_listenersObjects.Contains(listener))
_listenersObjects.Remove(listener);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6138a28930ffe84090896685ef44334
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace Obvious.Soap
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-event")]
public abstract class ScriptableEventBase : ScriptableBase
{
[Tooltip("Enable console logs when this event is raised.")]
[SerializeField]
protected bool _debugLogEnabled = false;
public bool DebugLogEnabled => _debugLogEnabled;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5042562b9a41436689455a448ce493b9
timeCreated: 1675031077

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_bool.asset", menuName = "Soap/ScriptableEvents/bool")]
public class ScriptableEventBool : ScriptableEvent<bool>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2fb1c8bab02427087aa07a952ef4018
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_color.asset", menuName = "Soap/ScriptableEvents/color")]
public class ScriptableEventColor : ScriptableEvent<Color>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a43c7f7efecc05440a913fce1435b648
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_component.asset", menuName = "Soap/ScriptableEvents/Component")]
public class ScriptableEventComponent: ScriptableEvent<Component>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 567d4db8da90a0748b767129f175ca02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_float.asset", menuName = "Soap/ScriptableEvents/float")]
public class ScriptableEventFloat : ScriptableEvent<float>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 968e031fe5a84c64b770b6a8940c8913
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_gameObject.asset", menuName = "Soap/ScriptableEvents/GameObject")]
public class ScriptableEventGameObject : ScriptableEvent<GameObject>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b4ca911a693eb84c8065b54815ee711
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_int.asset", menuName = "Soap/ScriptableEvents/int")]
public class ScriptableEventInt : ScriptableEvent<int>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed2a53a13d3e4066b3ccfe94e017a207
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
using System;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Object = UnityEngine.Object;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_noParam.asset", menuName = "Soap/ScriptableEvents/No Parameters")]
public class ScriptableEventNoParam : ScriptableEventBase, IDrawObjectsInInspector
{
private readonly List<EventListenerNoParam> _eventListeners = new List<EventListenerNoParam>();
private readonly List<Object> _listenersObjects = new List<Object>();
#if ODIN_INSPECTOR
[HideInEditorMode]
[ShowInInspector,EnableGUI]
public IEnumerable<Object> Listeners => EditorListeners;
#endif
protected Action _onRaised = null;
/// <summary>
/// Action raised when this event is raised.
/// </summary>
public event Action OnRaised
{
add
{
_onRaised += value;
#if UNITY_EDITOR
var listener = value.Target as Object;
AddListener(listener);
#endif
}
remove
{
_onRaised -= value;
#if UNITY_EDITOR
var listener = value.Target as Object;
RemoveListener(listener);
#endif
}
}
#if ODIN_INSPECTOR
[Button]
[DisableInEditorMode]
#endif
public virtual void Raise()
{
if (!Application.isPlaying)
return;
for (var i = _eventListeners.Count - 1; i >= 0; i--)
_eventListeners[i].OnEventRaised(this, _debugLogEnabled);
_onRaised?.Invoke();
#if UNITY_EDITOR
//As this uses reflection, I only allow it to be called in Editor.
//If you want to display debug in builds, delete the #if UNITY_EDITOR
if (_debugLogEnabled)
Debug();
#endif
}
internal void RegisterListener(EventListenerNoParam listener)
{
if (!_eventListeners.Contains(listener))
_eventListeners.Add(listener);
}
internal void UnregisterListener(EventListenerNoParam listener)
{
if (_eventListeners.Contains(listener))
_eventListeners.Remove(listener);
}
public IReadOnlyList<Object> EditorListeners => _listenersObjects.AsReadOnly();
protected virtual void Debug()
{
if (_onRaised == null)
return;
var delegates = _onRaised.GetInvocationList();
foreach (var del in delegates)
{
var sb = new StringBuilder();
sb.Append("<color=#f75369>[Event] </color>");
sb.Append(name);
sb.Append(" => ");
sb.Append(del.GetMethodInfo().Name);
sb.Append("()");
var monoBehaviour = del.Target as MonoBehaviour;
UnityEngine.Debug.Log(sb.ToString(), monoBehaviour?.gameObject);
}
}
internal override void Reset()
{
base.Reset();
_debugLogEnabled = false;
}
public override Type GetGenericType => typeof(void);
#if UNITY_EDITOR
public void AddListener(Object listener)
{
if (listener != null && !_listenersObjects.Contains(listener))
_listenersObjects.Add(listener);
}
public void RemoveListener(Object listener)
{
if (_listenersObjects.Contains(listener))
_listenersObjects.Remove(listener);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a49b7e678b3ebb7418adb84806d24646
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using UnityEngine;
using Obvious.Soap;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_" + nameof(Quaternion), menuName = "Soap/ScriptableEvents/"+ nameof(Quaternion))]
public class ScriptableEventQuaternion : ScriptableEvent<Quaternion>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8bd2c166b1cb80041b394874c35c54c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_string.asset", menuName = "Soap/ScriptableEvents/string")]
public class ScriptableEventString : ScriptableEvent<string>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3f39f579066605409b539400e8d7b94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_vector2.asset", menuName = "Soap/ScriptableEvents/Vector2")]
public class ScriptableEventVector2 : ScriptableEvent<Vector2>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2cfa1f27044fbc4fa2bc609d1f4010d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_vector2Int", menuName = "Soap/ScriptableEvents/Vector2Int")]
public class ScriptableEventVector2Int : ScriptableEvent<Vector2Int>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95458aedb81d064468a15bfe81715111
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_event_vector3.asset", menuName = "Soap/ScriptableEvents/Vector3")]
public class ScriptableEventVector3 : ScriptableEvent<Vector3>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 076e8e1f1417a0b4c8e48e5c8e2057b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c90dc5e2923623d4ea37625d5bc56bd8, type: 3}
userData:
assetBundleName:
assetBundleVariant: