1+ #if UNITY_EDITOR
2+ using System ;
13using System . Collections . Generic ;
4+ using UnityEditor ;
25using UnityEngine ;
3- using UnityEngine . LowLevel ;
4- using UnityEngine . PlayerLoop ;
56
67namespace Hertzole . ScriptableValues
78{
8- internal sealed class ScriptableValuesUpdate { }
9-
109 internal static class ScriptableValuesPlayerLoop
1110 {
1211 private static readonly List < IScriptableValueCallbacks > objectsToEnable = new List < IScriptableValueCallbacks > ( ) ;
1312 private static readonly List < IScriptableValueCallbacks > objectsToDisable = new List < IScriptableValueCallbacks > ( ) ;
1413
15- [ RuntimeInitializeOnLoadMethod ( RuntimeInitializeLoadType . SubsystemRegistration ) ]
16- private static void Init ( )
14+ [ InitializeOnLoadMethod ]
15+ private static void InitInEditor ( )
1716 {
18- PlayerLoopSystem defaultLoop = PlayerLoop . GetCurrentPlayerLoop ( ) ;
19-
20- PlayerLoopSystem customUpdate = new PlayerLoopSystem
21- {
22- updateDelegate = OnUpdate ,
23- type = typeof ( ScriptableValuesUpdate ) ,
24- subSystemList = null
25- } ;
26-
27- PlayerLoopSystem loopWithUpdate = InsertSystemAfter < EarlyUpdate > ( in defaultLoop , in customUpdate ) ;
28- PlayerLoop . SetPlayerLoop ( loopWithUpdate ) ;
17+ EditorApplication . playModeStateChanged += OnPlayModeStateChanged ;
2918 }
3019
31- public static void RegisterForEnable ( IScriptableValueCallbacks obj )
20+ private static void OnPlayModeStateChanged ( PlayModeStateChange state )
3221 {
33- if ( ! objectsToEnable . Contains ( obj ) )
22+ // When exiting play mode, we want to call OnScriptableObjectPreDisable and OnScriptableObjectDisable on all registered objects.
23+ if ( state == PlayModeStateChange . EnteredEditMode )
3424 {
35- objectsToEnable . Add ( obj ) ;
36- }
37- }
25+ for ( int i = 0 ; i < objectsToDisable . Count ; i ++ )
26+ {
27+ objectsToDisable [ i ] . OnScriptableObjectPreDisable ( ) ;
28+ }
3829
39- public static void RegisterForDisable ( IScriptableValueCallbacks obj )
40- {
41- if ( ! objectsToDisable . Contains ( obj ) )
42- {
43- objectsToDisable . Add ( obj ) ;
30+ for ( int i = 0 ; i < objectsToDisable . Count ; i ++ )
31+ {
32+ objectsToDisable [ i ] . OnScriptableObjectDisable ( ) ;
33+ }
34+
35+ objectsToDisable . Clear ( ) ;
4436 }
4537 }
4638
47- private static void OnUpdate ( )
39+ [ RuntimeInitializeOnLoadMethod ( RuntimeInitializeLoadType . SubsystemRegistration ) ]
40+ private static void Init ( )
4841 {
49- #if UNITY_EDITOR
50- if ( ! Application . isPlaying )
51- {
52- return ;
53- }
54- #endif
55-
42+ // When the game starts, call OnScriptableObjectPreEnable and OnScriptableObjectEnable on all registered objects.
5643 for ( int i = 0 ; i < objectsToEnable . Count ; i ++ )
5744 {
5845 objectsToEnable [ i ] . OnScriptableObjectPreEnable ( ) ;
@@ -63,50 +50,35 @@ private static void OnUpdate()
6350 objectsToEnable [ i ] . OnScriptableObjectEnable ( ) ;
6451 }
6552
66- for ( int i = 0 ; i < objectsToDisable . Count ; i ++ )
53+ objectsToEnable . Clear ( ) ;
54+ }
55+
56+ public static void RegisterForEnable ( IScriptableValueCallbacks obj )
57+ {
58+ // This is a bootstrapper, we can't register for enable if the application is already playing. The object should call those methods directly.
59+ if ( Application . isPlaying )
6760 {
68- objectsToDisable [ i ] . OnScriptableObjectPreDisable ( ) ;
61+ throw new InvalidOperationException ( "Cannot register for enable when the application is already playing." ) ;
6962 }
7063
71- for ( int i = 0 ; i < objectsToDisable . Count ; i ++ )
64+ if ( ! objectsToEnable . Contains ( obj ) )
7265 {
73- objectsToDisable [ i ] . OnScriptableObjectDisable ( ) ;
66+ objectsToEnable . Add ( obj ) ;
7467 }
75-
76- objectsToEnable . Clear ( ) ;
77- objectsToDisable . Clear ( ) ;
7868 }
7969
80- private static PlayerLoopSystem InsertSystemAfter < T > ( in PlayerLoopSystem loopSystem , in PlayerLoopSystem newSystem ) where T : struct
70+ public static void RegisterForDisable ( IScriptableValueCallbacks obj )
8171 {
82- // Create a new root PlayerLoopSystem
83- PlayerLoopSystem newPlayerLoop = new PlayerLoopSystem
72+ if ( ! Application . isPlaying )
8473 {
85- loopConditionFunction = loopSystem . loopConditionFunction ,
86- type = loopSystem . type ,
87- updateDelegate = loopSystem . updateDelegate ,
88- updateFunction = loopSystem . updateFunction
89- } ;
90-
91- // Create a new list to populate with subsystems, including the custom system
92- List < PlayerLoopSystem > newSubSystemList = new List < PlayerLoopSystem > ( ) ;
74+ throw new InvalidOperationException ( "Cannot register for disable when the application is not playing." ) ;
75+ }
9376
94- //Iterate through the subsystems in the existing loop we passed in and add them to the new list
95- if ( loopSystem . subSystemList != null )
77+ if ( ! objectsToDisable . Contains ( obj ) )
9678 {
97- for ( int i = 0 ; i < loopSystem . subSystemList . Length ; i ++ )
98- {
99- newSubSystemList . Add ( loopSystem . subSystemList [ i ] ) ;
100- // If the previously added subsystem is of the type to add after, add the custom system
101- if ( loopSystem . subSystemList [ i ] . type == typeof ( T ) )
102- {
103- newSubSystemList . Add ( newSystem ) ;
104- }
105- }
79+ objectsToDisable . Add ( obj ) ;
10680 }
107-
108- newPlayerLoop . subSystemList = newSubSystemList . ToArray ( ) ;
109- return newPlayerLoop ;
11081 }
11182 }
112- }
83+ }
84+ #endif
0 commit comments