< Summary

Line coverage
75%
Covered lines: 112
Uncovered lines: 36
Coverable lines: 148
Total lines: 446
Line coverage: 75.6%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
File 1: OnEnable()0%2.062075%
File 1: OnDisable()0%220100%
File 1: OnPreStart()0%110100%
File 1: OnStart()0%110100%
File 1: OnPreDisabled()0%110100%
File 1: OnDisabled()0%2100%
File 1: OnScriptableObjectPreEnable()0%110100%
File 1: OnScriptableObjectEnable()0%110100%
File 1: OnScriptableObjectPreDisable()0%110100%
File 1: OnScriptableObjectDisable()0%110100%
File 1: OnPlayModeStateChanged(...)0%330100%
File 2: add_PropertyChanging(...)0%110100%
File 2: remove_PropertyChanging(...)0%110100%
File 2: add_PropertyChanged(...)0%110100%
File 2: remove_PropertyChanged(...)0%110100%
File 2: NotifyPropertyChanging(...)0%6200%
File 2: NotifyPropertyChanging(...)0%220100%
File 2: NotifyPropertyChanged(...)0%6200%
File 2: NotifyPropertyChanged(...)0%220100%
File 2: NotifyUnityPropertyChanged(...)0%210100%
File 2: SetField[T](...)0%20400%
File 2: SetField[T](...)0%220100%
File 2: SetFieldInternal[T](...)0%3.023087.5%
File 2: WarnIfLeftOverSubscribers()0%110100%
File 2: add_propertyChanged(...)0%110100%
File 2: remove_propertyChanged(...)0%110100%
File 2: GetViewHashCode()0%110100%
File 2: GetViewHashCode()0%110100%
File 3: AddStackTrace(...)0%550100%
File 3: ResetStackTraces()0%110100%
File 3: get_CollectStackTraces()0%110100%
File 3: set_CollectStackTraces(...)0%110100%
File 3: get_Invocations()0%110100%
File 3: RuntimeScriptableObject()0%110100%
File 3: add_OnStackTraceAdded(...)0%110100%
File 3: remove_OnStackTraceAdded(...)0%2100%

File(s)

./Packages/se.hertzole.scriptable-values/Runtime/Core/RuntimeScriptableObject.cs

#LineLine coverage
 1using System;
 2using System.Diagnostics.CodeAnalysis;
 3using UnityEngine;
 4#if UNITY_EDITOR
 5using UnityEditor;
 6#endif
 7
 8namespace Hertzole.ScriptableValues
 9{
 10    /// <summary>
 11    ///     Base class for <see cref="ScriptableObject" /> that have values that should be resettable.
 12    /// </summary>
 13#if UNITY_EDITOR
 14    [HelpURL(Documentation.CREATING_CUSTOM_TYPES_URL)]
 15#endif
 16    public abstract partial class RuntimeScriptableObject : ScriptableObject, IScriptableValueCallbacks
 17    {
 18        /// <summary>
 19        ///     Subscribes to play mode state changed to listen for play mode events.
 20        ///     <para>When the game is built, it calls the <see cref="OnStart" /> method.</para>
 21        /// </summary>
 22        private void OnEnable()
 2770223        {
 24#if UNITY_EDITOR
 2770225            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
 26
 27            // This could be loaded in the editor, but we only want to call OnStart when entering play mode.
 28            // If it's loaded during play mode, we want to call OnStart right away.
 2770229            if (!Application.isPlaying)
 64230            {
 64231                return;
 32            }
 33#endif
 2706034            OnPreStart();
 2706035            OnStart();
 2770236        }
 37
 38        /// <summary>
 39        ///     Unsubscribes from play mode state changed to stop listening for play mode events.
 40        ///     <para>When the game is built, it calls the <see cref="OnDisabled" /> method.</para>
 41        /// </summary>
 42        private void OnDisable()
 2753443        {
 44#if UNITY_EDITOR
 2753445            EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
 46
 47            // This could be loaded in the editor, but we only want to call OnDisabled when entering play mode.
 48            // If it's loaded during play mode, we want to call OnDisabled right away.
 2753449            if (!Application.isPlaying)
 55850            {
 55851                return;
 52            }
 53#endif
 2697654            OnPreDisabled();
 2697655            OnDisabled();
 2753456        }
 57
 58        /// <summary>
 59        ///     Called when the game starts, before <see cref="OnStart" />.
 60        ///     <para>
 61        ///         You should not subscribe to events in this method! Use <see cref="OnStart" /> instead.
 62        ///         <see cref="OnPreStart" /> should be used for preparing the scriptable object.
 63        ///     </para>
 64        /// </summary>
 65        /// <remarks>If this isn't called when the game starts, it's called once this scriptable object is loaded and in
 2466        protected virtual void OnPreStart() { }
 67
 68        /// <summary>
 69        ///     Called when the game starts, after <see cref="OnPreStart" />.
 70        ///     <para>You should not prepare the object in this method! Use <see cref="OnPreStart" /> instead.</para>
 71        /// </summary>
 72        /// <remarks>If this isn't called when the game starts, it's called once this scriptable object is loaded and in
 5476873        protected virtual void OnStart() { }
 74
 75        /// <summary>
 76        ///     Called when the game is ending, before <see cref="OnDisabled" />.
 77        ///     <para>You should not clean up the object in this method! Use <see cref="OnDisabled" /> instead.</para>
 78        /// </summary>
 79        /// <remarks>This can also be called during the game is the scriptable object is destroyed and/or unloaded.</rem
 5448080        protected virtual void OnPreDisabled() { }
 81
 82        /// <summary>
 83        ///     Called when the game is ending, after <see cref="OnPreDisabled" />.
 84        ///     <para>
 85        ///         You should not unsubscribe from events in this method! Use <see cref="OnPreDisabled" /> instead.
 86        ///         <see cref="OnDisabled" /> should be used for cleaning up the scriptable object.
 87        ///     </para>
 88        /// </summary>
 89        /// <remarks>This can also be called during the game is the scriptable object is destroyed and/or unloaded.</rem
 090        protected virtual void OnDisabled() { }
 91
 92        /// <inheritdoc />
 93        void IScriptableValueCallbacks.OnScriptableObjectPreEnable()
 34894        {
 34895            ResetStackTraces();
 34896            OnPreStart();
 34897        }
 98
 99        /// <inheritdoc />
 100        void IScriptableValueCallbacks.OnScriptableObjectEnable()
 348101        {
 348102            OnStart();
 348103        }
 104
 105        /// <inheritdoc />
 106        void IScriptableValueCallbacks.OnScriptableObjectPreDisable()
 288107        {
 288108            OnPreDisabled();
 288109        }
 110
 111        /// <inheritdoc />
 112        void IScriptableValueCallbacks.OnScriptableObjectDisable()
 288113        {
 288114            OnDisabled();
 288115        }
 116
 117#if UNITY_EDITOR
 118        /// <summary>
 119        ///     Called when the play mode state changes.
 120        /// </summary>
 121        /// <param name="state">The new play mode state.</param>
 122        private void OnPlayModeStateChanged(PlayModeStateChange state)
 270123        {
 270124            if (state == PlayModeStateChange.ExitingEditMode)
 90125            {
 90126                ResetStackTraces();
 90127                ScriptableValuesInitialization.RegisterForEnable(this);
 90128            }
 180129            else if (state == PlayModeStateChange.ExitingPlayMode)
 84130            {
 84131                ScriptableValuesInitialization.RegisterForDisable(this);
 132#pragma warning disable CS0618 // Type or member is obsolete
 84133                OnExitPlayMode();
 134#pragma warning restore CS0618 // Type or member is obsolete
 84135            }
 270136        }
 137
 138        /// <summary>
 139        ///     Called when the game exits play mode.
 140        /// </summary>
 141        [Obsolete("Use either 'OnPreDisabled' or 'OnDisabled' instead.")]
 142        [ExcludeFromCodeCoverage]
 143        protected virtual void OnExitPlayMode() { }
 144#endif
 145    }
 146}

./Packages/se.hertzole.scriptable-values/Runtime/Core/RuntimeScriptableObject.Notify.cs

#LineLine coverage
 1#nullable enable
 2#if SCRIPTABLE_VALUES_RUNTIME_BINDING && SCRIPTABLE_VALUES_UITOOLKIT
 3#define SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 4#endif // SCRIPTABLE_VALUES_RUNTIME_BINDING
 5
 6using System.ComponentModel;
 7using System.Diagnostics;
 8using System.Runtime.CompilerServices;
 9using Hertzole.ScriptableValues.Helpers;
 10using UnityEngine.Assertions;
 11#if SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 12using System;
 13using Unity.Properties;
 14using UnityEngine.UIElements;
 15#endif // SCRIPTABLE_VALUES_RUNTIME_BINDING
 16
 17namespace Hertzole.ScriptableValues
 18{
 19    partial class RuntimeScriptableObject :
 20#if SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 21        IDataSourceViewHashProvider,
 22        INotifyBindablePropertyChanged,
 23#endif // SCRIPTABLE_VALUES_RUNTIME_BINDING
 24        INotifyPropertyChanging,
 25        INotifyPropertyChanged
 26    {
 27        private event PropertyChangingEventHandler? OnNotifyPropertyChanging;
 28        private event PropertyChangedEventHandler? OnNotifyPropertyChanged;
 29
 30        event PropertyChangingEventHandler INotifyPropertyChanging.PropertyChanging
 31        {
 975632            add { OnNotifyPropertyChanging += value; }
 975633            remove { OnNotifyPropertyChanging -= value; }
 34        }
 35        event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
 36        {
 975637            add { OnNotifyPropertyChanged += value; }
 975638            remove { OnNotifyPropertyChanged -= value; }
 39        }
 40
 41        /// <summary>
 42        ///     Invoke the <see cref="INotifyPropertyChanging.PropertyChanging" /> event with the given property name.
 43        /// </summary>
 44        /// <param name="propertyName">The name of the property that is changing.</param>
 45        protected void NotifyPropertyChanging([CallerMemberName] string propertyName = "")
 046        {
 47            // Check first if the event is null to avoid creating a new PropertyChangingEventArgs
 048            if (OnNotifyPropertyChanging != null)
 049            {
 050                NotifyPropertyChanging(new PropertyChangingEventArgs(propertyName));
 051            }
 052        }
 53
 54        /// <summary>
 55        ///     Invokes the <see cref="INotifyPropertyChanging.PropertyChanging" /> event with the given
 56        ///     <see cref="PropertyChangingEventArgs" />.
 57        /// </summary>
 58        /// <param name="args">The <see cref="PropertyChangingEventArgs" /> to use.</param>
 59        protected void NotifyPropertyChanging(PropertyChangingEventArgs args)
 4989060        {
 4989061            Assert.IsNotNull(args);
 62
 4989063            OnNotifyPropertyChanging?.Invoke(this, args);
 4989064        }
 65
 66        /// <summary>
 67        ///     Invoke the <see cref="INotifyPropertyChanged.PropertyChanged" /> event and the
 68        ///     <see cref="INotifyBindablePropertyChanged.propertyChanged" /> event with the given property name.
 69        /// </summary>
 70        /// <param name="propertyName">The name of the property that has changed.</param>
 71        protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
 072        {
 73            // Check first if the event is null to avoid creating a new PropertyChangedEventArgs
 074            if (OnNotifyPropertyChanged != null)
 075            {
 076                NotifyPropertyChanged(new PropertyChangedEventArgs(propertyName));
 077            }
 78            else
 079            {
 80                // If the event is null, we can still notify Unity about the property change.
 81                // NotifyPropertyChanged would call this otherwise...
 082                NotifyUnityPropertyChanged(propertyName);
 083            }
 084        }
 85
 86        /// <summary>
 87        ///     Invoke the <see cref="INotifyPropertyChanged.PropertyChanged" /> event and the
 88        ///     <see cref="INotifyBindablePropertyChanged.propertyChanged" /> event with the given
 89        ///     <see cref="PropertyChangedEventArgs" />.
 90        /// </summary>
 91        /// <param name="args">The <see cref="PropertyChangedEventArgs" /> to use.</param>
 92        protected void NotifyPropertyChanged(PropertyChangedEventArgs args)
 4989093        {
 4989094            Assert.IsNotNull(args);
 95
 3326096            NotifyUnityPropertyChanged(args.PropertyName);
 4989097            OnNotifyPropertyChanged?.Invoke(this, args);
 4989098        }
 99
 100        [Conditional("SCRIPTABLE_VALUES_DO_UI_TOOLKIT")]
 101        private void NotifyUnityPropertyChanged(string propertyName)
 33260102        {
 103#if SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 33260104            OnPropertyChanged?.Invoke(this, new BindablePropertyChangedEventArgs(new BindingId(new PropertyPath(property
 105#endif // SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 33260106        }
 107
 108        /// <summary>
 109        ///     Sets a field to a new value and notifies the property changed event.
 110        /// </summary>
 111        /// <remarks>Calling this will not notify any property changes if the new value is the same as the current field
 112        /// <param name="field">The field to set.</param>
 113        /// <param name="newValue">The new value to set.</param>
 114        /// <param name="propertyName">The name of the property that is changing.</param>
 115        /// <typeparam name="T">The type of the field.</typeparam>
 116        /// <returns><c>true</c> if the field was changed; otherwise, <c>false</c>.</returns>
 117        protected bool SetField<T>(ref T field, T newValue, [CallerMemberName] string propertyName = "")
 0118        {
 0119            if (EqualityHelper.Equals(field, newValue))
 0120            {
 0121                return false;
 122            }
 123
 0124            PropertyChangingEventArgs? changingEventArgs = null;
 0125            PropertyChangedEventArgs? changedEventArgs = null;
 126
 127            // Only create the event args if the event is not null
 0128            if (OnNotifyPropertyChanging != null)
 0129            {
 0130                changingEventArgs = new PropertyChangingEventArgs(propertyName);
 0131            }
 132
 0133            if (OnNotifyPropertyChanged != null)
 0134            {
 0135                changedEventArgs = new PropertyChangedEventArgs(propertyName);
 0136            }
 137
 0138            return SetFieldInternal(ref field, newValue, changingEventArgs, changedEventArgs, propertyName);
 0139        }
 140
 141        /// <summary>
 142        ///     Sets a field to a new value and notifies the property changed event.
 143        /// </summary>
 144        /// <param name="field">The field to set.</param>
 145        /// <param name="newValue">The new value to set.</param>
 146        /// <param name="changingArgs">The <see cref="PropertyChangingEventArgs" /> to use.</param>
 147        /// <param name="changedArgs">The <see cref="PropertyChangedEventArgs" /> to use.</param>
 148        /// <typeparam name="T">The type of the field.</typeparam>
 149        /// <returns><c>true</c> if the field was changed; otherwise, <c>false</c>.</returns>
 150        protected bool SetField<T>(ref T field, T newValue, PropertyChangingEventArgs changingArgs, PropertyChangedEvent
 104466151        {
 104466152            if (EqualityHelper.Equals(field, newValue))
 70068153            {
 70068154                return false;
 155            }
 156
 34398157            return SetFieldInternal(ref field, newValue, changingArgs, changedArgs, changedArgs.PropertyName);
 104466158        }
 159
 160        private bool SetFieldInternal<T>(ref T field,
 161            T newValue,
 162            PropertyChangingEventArgs? changingArgs,
 163            PropertyChangedEventArgs? changedArgs,
 164            string propertyName)
 34398165        {
 34398166            Assert.IsNotNull(changingArgs);
 34398167            Assert.IsNotNull(changedArgs);
 168
 34398169            if (changingArgs != null)
 34398170            {
 34398171                NotifyPropertyChanging(changingArgs);
 34398172            }
 173
 34398174            field = newValue;
 175
 34398176            if (changedArgs != null)
 34398177            {
 34398178                NotifyPropertyChanged(changedArgs);
 34398179            }
 180            else
 0181            {
 0182                NotifyUnityPropertyChanged(propertyName);
 0183            }
 184
 34398185            return true;
 34398186        }
 187
 188        /// <summary>
 189        ///     Warns if there are any left-over subscribers to the events.
 190        /// </summary>
 191        /// <remarks>This will only be called in the Unity editor and builds with the DEBUG flag.</remarks>
 192        [Conditional("DEBUG")]
 193        protected virtual void WarnIfLeftOverSubscribers()
 27276194        {
 27276195            EventHelper.WarnIfLeftOverSubscribers(OnNotifyPropertyChanging, "INotifyPropertyChanging.PropertyChanging", 
 27276196            EventHelper.WarnIfLeftOverSubscribers(OnNotifyPropertyChanged, "INotifyPropertyChanged.PropertyChanged", thi
 197#if SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 18692198            EventHelper.WarnIfLeftOverSubscribers(OnPropertyChanged, "INotifyBindablePropertyChanged.propertyChanged", t
 199#endif // SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 27276200        }
 201
 202#if SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 203        private event EventHandler<BindablePropertyChangedEventArgs>? OnPropertyChanged;
 204
 205        event EventHandler<BindablePropertyChangedEventArgs> INotifyBindablePropertyChanged.propertyChanged
 206        {
 2940207            add { OnPropertyChanged += value; }
 2940208            remove { OnPropertyChanged -= value; }
 209        }
 210
 211        /// <summary>
 212        ///     Computes a hash code for the view of the data source.
 213        /// </summary>
 214        /// <returns>A hash code for the current object.</returns>
 215        protected virtual long GetViewHashCode()
 1960216        {
 1960217            return GetHashCode();
 1960218        }
 219
 220        long IDataSourceViewHashProvider.GetViewHashCode()
 1960221        {
 1960222            return GetViewHashCode();
 1960223        }
 224#endif // SCRIPTABLE_VALUES_DO_UI_TOOLKIT
 225    }
 226}

./Packages/se.hertzole.scriptable-values/Runtime/Core/RuntimeScriptableObject.StackTraces.cs

#LineLine coverage
 1#nullable enable
 2
 3using System.Diagnostics;
 4#if UNITY_EDITOR
 5using System;
 6using System.Collections.Generic;
 7using Hertzole.ScriptableValues.Debugging;
 8#endif
 9
 10namespace Hertzole.ScriptableValues
 11{
 12    public partial class RuntimeScriptableObject
 13#if UNITY_EDITOR
 14        : IStackTraceProvider
 15#endif
 16    {
 17        /// <summary>
 18        ///     Adds a stack trace.
 19        /// </summary>
 20        /// <remarks>This only does something in the Unity editor. This method is completely blank in builds.</remarks>
 21        /// <param name="skipFrames">How many frames/calls to skip.</param>
 22        [Conditional("UNITY_EDITOR")]
 23        protected void AddStackTrace(int skipFrames = 0)
 4403124        {
 25#if UNITY_EDITOR
 4403126            if (!((IStackTraceProvider) this).CollectStackTraces || !UserSettings.CollectStackTraces)
 4118127            {
 4118128                return;
 29            }
 30
 31            // Always skip one frame because we don't want to include this current method.
 285032            StackTrace trace = new StackTrace(1 + skipFrames, true);
 33
 34            // Insert first so the most recent invocation is at the top.
 285035            ((IStackTraceProvider) this).Invocations.Insert(0, new StackTraceEntry(trace));
 36
 285037            if (((IStackTraceProvider) this).Invocations.Count > IStackTraceProvider.MAX_STACK_TRACE_ENTRIES)
 4838            {
 4839                ((IStackTraceProvider) this).Invocations.RemoveAt(((IStackTraceProvider) this).Invocations.Count - 1);
 4840            }
 41
 285042            OnStackTraceAddedInternal?.Invoke();
 43#endif
 4403144        }
 45
 46        /// <summary>
 47        ///     Removes all stack traces.
 48        /// </summary>
 49        /// <remarks>This only does something in the Unity editor. This method is completely blank in builds.</remarks>
 50        [Conditional("UNITY_EDITOR")]
 51        protected void ResetStackTraces()
 43852        {
 53#if UNITY_EDITOR
 43854            ((IStackTraceProvider) this).Invocations.Clear();
 55#endif
 43856        }
 57#if UNITY_EDITOR
 58        bool IStackTraceProvider.CollectStackTraces
 59        {
 13209360            get { return UserSettings.GetCollectStackTraces(this); }
 57661            set { UserSettings.SetCollectStackTraces(this, value); }
 62        }
 63
 3504664        IList<StackTraceEntry> IStackTraceProvider.Invocations { get; } = new List<StackTraceEntry>();
 65        event Action IStackTraceProvider.OnStackTraceAdded
 66        {
 43267            add { OnStackTraceAddedInternal += value; }
 068            remove { OnStackTraceAddedInternal -= value; }
 69        }
 70
 71        private event Action? OnStackTraceAddedInternal;
 72#endif
 73    }
 74}

Methods/Properties

OnEnable()
OnDisable()
OnPreStart()
OnStart()
OnPreDisabled()
OnDisabled()
OnScriptableObjectPreEnable()
OnScriptableObjectEnable()
OnScriptableObjectPreDisable()
OnScriptableObjectDisable()
OnPlayModeStateChanged(UnityEditor.PlayModeStateChange)
add_PropertyChanging(System.ComponentModel.PropertyChangingEventHandler)
remove_PropertyChanging(System.ComponentModel.PropertyChangingEventHandler)
add_PropertyChanged(System.ComponentModel.PropertyChangedEventHandler)
remove_PropertyChanged(System.ComponentModel.PropertyChangedEventHandler)
NotifyPropertyChanging(System.String)
NotifyPropertyChanging(System.ComponentModel.PropertyChangingEventArgs)
NotifyPropertyChanged(System.String)
NotifyPropertyChanged(System.ComponentModel.PropertyChangedEventArgs)
NotifyUnityPropertyChanged(System.String)
SetField[T](, T, System.String)
SetField[T](, T, System.ComponentModel.PropertyChangingEventArgs, System.ComponentModel.PropertyChangedEventArgs)
SetFieldInternal[T](, T, System.ComponentModel.PropertyChangingEventArgs, System.ComponentModel.PropertyChangedEventArgs, System.String)
WarnIfLeftOverSubscribers()
add_propertyChanged(System.EventHandler[BindablePropertyChangedEventArgs])
remove_propertyChanged(System.EventHandler[BindablePropertyChangedEventArgs])
GetViewHashCode()
GetViewHashCode()
AddStackTrace(System.Int32)
ResetStackTraces()
get_CollectStackTraces()
set_CollectStackTraces(System.Boolean)
get_Invocations()
RuntimeScriptableObject()
add_OnStackTraceAdded(System.Action)
remove_OnStackTraceAdded(System.Action)