<commit_before>﻿using UnityEngine;
using EventIds = Archon.SwissArmyLib.Events.ManagedUpdate.EventIds;

namespace Archon.SwissArmyLib.Events
{
    /// <summary>
    /// A subclass of MonoBehaviour that uses <see cref="ManagedUpdate"/> for update events.
    /// </summary>
    public abstract class ManagedUpdateBehaviour : MonoBehaviour, IEventListener
    {
        /// <summary>
        /// Affects whether this components' events will be called before or after others'.
        /// 
        /// Basically a reimplementation of Unity's ScriptExecutionOrder.
        /// </summary>
        protected virtual int ExecutionOrder { get { return 0; } }

        /// <summary>
        /// Whether you want to use <see cref="OnUpdate"/>.
        /// </summary>
        protected abstract bool UsesUpdate { get; }

        /// <summary>
        /// Whether you want to use <see cref="OnLateUpdate"/>.
        /// </summary>
        protected abstract bool UsesLateUpdate { get; }

        /// <summary>
        /// Whether you want to use <see cref="OnFixedUpdate"/>.
        /// </summary>
        protected abstract bool UsesFixedUpdate { get; }

        private bool _startWasCalled;

        /// <summary>
        /// Start is called on the frame when a script is enabled just before any of the Update methods is called the first time.
        /// </summary>
        protected virtual void Start()
        {
            _startWasCalled = true;
            StartListening();
        }

        /// <summary>
        /// Called when the component is enabled.
        /// </summary>
        protected virtual void OnEnable()
        {
            // We don't want Update calls before Start has been called.
            if (_startWasCalled)
                StartListening();
        }

        /// <summary>
        /// Called when the component is disabled.
        /// </summary>
        protected virtual void OnDisable()
        {
            if (_startWasCalled)
                StopListening();
        }

        private void StartListening()
        {
            if (UsesUpdate)
                ManagedUpdate.OnUpdate.AddListener(this, ExecutionOrder);
            if (UsesLateUpdate)
                ManagedUpdate.OnLateUpdate.AddListener(this, ExecutionOrder);
            if (UsesFixedUpdate)
                ManagedUpdate.OnFixedUpdate.AddListener(this, ExecutionOrder);
        }

        private void StopListening()
        {
            if (UsesUpdate)
                ManagedUpdate.OnUpdate.RemoveListener(this);
            if (UsesLateUpdate)
                ManagedUpdate.OnLateUpdate.RemoveListener(this);
            if (UsesFixedUpdate)
                ManagedUpdate.OnFixedUpdate.RemoveListener(this);
        }

        /// <inheritdoc />
        public virtual void OnEvent(int eventId)
        {
            switch (eventId)
            {
                case EventIds.Update:
                    OnUpdate();
                    return;
                case EventIds.LateUpdate:
                    OnLateUpdate();
                    return;
                case EventIds.FixedUpdate:
                    OnFixedUpdate();
                    return;
            }
        }

        /// <summary>
        /// Called every frame if <see cref="UsesUpdate"/> is true and the component is enabled.
        /// </summary>
        protected virtual void OnUpdate() { }

        /// <summary>
        /// Called every frame just after <see cref="OnUpdate"/> if <see cref="UsesLateUpdate"/> is true and the component is enabled.
        /// </summary>
        protected virtual void OnLateUpdate() { }

        /// <summary>
        /// This function is called every fixed framerate frame if <see cref="OnFixedUpdate"/> is true and the component is enabled.
        /// </summary>
        protected virtual void OnFixedUpdate() { }
    }
}<commit_msg>Redesigned ManagedUpdateBehaviour as overriding the Uses* properties was tedious.<commit_after>﻿using UnityEngine;
using EventIds = Archon.SwissArmyLib.Events.ManagedUpdate.EventIds;

namespace Archon.SwissArmyLib.Events
{
    /// <summary>
    /// Makes a <see cref="ManagedUpdateBehaviour"/> subclass get notified on an update.
    /// </summary>
    public interface IUpdateable
    {
        /// <summary>
        /// Called every frame.
        /// </summary>
        void OnUpdate();
    }

    /// <summary>
    /// Makes a <see cref="ManagedUpdateBehaviour"/> subclass get notified on a late update.
    /// </summary>
    public interface ILateUpdateable
    {
        /// <summary>
        /// Called every frame, after the regular update loop.
        /// </summary>
        void OnLateUpdate();
    }

    /// <summary>
    /// Makes a <see cref="ManagedUpdateBehaviour"/> subclass get notified on a fixed update.
    /// </summary>
    public interface IFixedUpdateable
    {
        /// <summary>
        /// Called every fixed update.
        /// </summary>
        void OnFixedUpdate();
    }

    /// <summary>
    /// A subclass of MonoBehaviour that uses <see cref="ManagedUpdate"/> for update events.
    /// </summary>
    public abstract class ManagedUpdateBehaviour : MonoBehaviour, IEventListener
    {
        /// <summary>
        /// Affects whether this components' events will be called before or after others'.
        /// 
        /// Basically a reimplementation of Unity's ScriptExecutionOrder.
        /// </summary>
        protected virtual int ExecutionOrder { get { return 0; } }

        private bool _startWasCalled;
        private bool _isListening;
        private IUpdateable _updateable;
        private ILateUpdateable _lateUpdateable;
        private IFixedUpdateable _fixedUpdateable;

        /// <summary>
        /// Start is called on the frame when a script is enabled just before any of the Update methods is called the first time.
        /// </summary>
        protected virtual void Start()
        {
            // ReSharper disable SuspiciousTypeConversion.Global
            _updateable = this as IUpdateable;
            _lateUpdateable = this as ILateUpdateable;
            _fixedUpdateable = this as IFixedUpdateable;
            // ReSharper restore SuspiciousTypeConversion.Global

            if (_updateable == null
                && _lateUpdateable == null
                && _fixedUpdateable == null)
            {
                Debug.LogWarning("This component doesn't implement any update interfaces.");
            }

            _startWasCalled = true;
            StartListening();
        }

        /// <summary>
        /// Called when the component is enabled.
        /// </summary>
        protected virtual void OnEnable()
        {
            // We don't want Update calls before Start has been called.
            if (_startWasCalled)
                StartListening();
        }

        /// <summary>
        /// Called when the component is disabled.
        /// </summary>
        protected virtual void OnDisable()
        {
            if (_startWasCalled)
                StopListening();
        }

        private void StartListening()
        {
            if (_isListening)
            {
                Debug.LogError("Attempt at starting to listen for updates, while already listening. Did you forget to call base.OnDisable()?");
                return;
            }

            if (_updateable != null)
                ManagedUpdate.OnUpdate.AddListener(this, ExecutionOrder);
            if (_lateUpdateable != null)
                ManagedUpdate.OnLateUpdate.AddListener(this, ExecutionOrder);
            if (_fixedUpdateable != null)
                ManagedUpdate.OnFixedUpdate.AddListener(this, ExecutionOrder);

            _isListening = true;
        }

        private void StopListening()
        {
            if (!_isListening)
            {
                Debug.LogError("Attempted to stop listening for updates while not listening. Did you forget to call base.Start() or base.OnEnable()?");
                return;
            }

            if (_updateable != null)
                ManagedUpdate.OnUpdate.RemoveListener(this);
            if (_lateUpdateable != null)
                ManagedUpdate.OnLateUpdate.RemoveListener(this);
            if (_fixedUpdateable != null)
                ManagedUpdate.OnFixedUpdate.RemoveListener(this);

            _isListening = false;
        }

        /// <inheritdoc />
        public virtual void OnEvent(int eventId)
        {
            switch (eventId)
            {
                case EventIds.Update:
                    _updateable.OnUpdate();
                    return;
                case EventIds.LateUpdate:
                    _lateUpdateable.OnLateUpdate();
                    return;
                case EventIds.FixedUpdate:
                    _fixedUpdateable.OnFixedUpdate();
                    return;
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.09415073115860517, 'fraction_numerical': 0.0002249718785151856, 'mean_word_length': 1.6088615023474178, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5521463', 'n_tokens_mistral': 2235, 'n_tokens_neox': 2093, 'n_words': 633}