using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using NaughtyAttributes.Test; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace Ktyl.Util { [CreateAssetMenu(menuName = "ktyl/Events/Game Event")] public partial class GameEvent : ScriptableObject { [SerializeField] private bool _logRaised; protected readonly List _listeners = new List(); private readonly List _listenerBuffer = new List(); public virtual void Raise() { if (_logRaised) { Debug.Log($"raised {this}", this); } // populate a buffer of listeners, since the original list // may be modified as a consequence of triggering the event _listenerBuffer.Clear(); _listenerBuffer.AddRange(_listeners); foreach (var listener in _listenerBuffer) { listener.OnEventRaised(); } } public void Register(GameEventListener listener) { if (_listeners.Contains(listener)) { Debug.LogError($"{listener} already registered", this); return; } _listeners.Add(listener); } public void Unregister(GameEventListener listener) { if (!_listeners.Contains(listener)) { Debug.LogError($"{listener} not already registered"); return; } _listeners.Remove(listener); } } #region Editor #if UNITY_EDITOR public partial class GameEvent { private int _EDITOR_pingIdx; public void EDITOR_PingNextListener() { Debug.Log($"ping listener {_EDITOR_pingIdx+1}/{_listeners.Count}", this); EditorGUIUtility.PingObject(_listeners[_EDITOR_pingIdx++]); _EDITOR_pingIdx %= _listeners.Count; } } [CustomEditor(typeof(GameEvent), true)] public class GameEventEditor : Editor { private GameEvent _event; private void OnEnable() { _event = target as GameEvent; } public override void OnInspectorGUI() { base.OnInspectorGUI(); if (GUILayout.Button("Raise")) { _event.Raise(); } if (Application.isPlaying && GUILayout.Button("Ping Listeners")) { _event.EDITOR_PingNextListener(); } } } #endif #endregion }