11using CinematicShaders . Native ;
22using CinematicShaders . Shaders . GTAO ;
3+ using CinematicShaders . Shaders . Starfield ;
34using CinematicShaders . UI ;
45using KSP . UI . Screens ;
56using UnityEngine ;
7+ using UnityEngine . SceneManagement ;
68
79namespace CinematicShaders . Core
810{
@@ -29,14 +31,32 @@ void Awake()
2931 void Start ( )
3032 {
3133 GTAOSettings . Load ( ) ;
34+ StarfieldSettings . Load ( ) ;
35+ // If we're already in a game session, re-apply per-save settings to override
36+ // the global settings we just loaded. This happens on scene changes within
37+ // the same save (e.g., Flight -> Tracking Station -> Flight).
38+ // OnGameStateLoad only fires when first loading a save, not on scene changes.
39+ if ( HighLogic . LoadedScene != GameScenes . MAINMENU &&
40+ HighLogic . LoadedScene != GameScenes . LOADING &&
41+ StarfieldPerSaveSettings . Instance != null )
42+ {
43+ Debug . Log ( "[CinematicShaders] Re-applying per-save settings after scene change" ) ;
44+ StarfieldPerSaveSettings . Instance . ApplyToSettings ( ) ;
45+ }
46+ StarCatalogManager . Initialize ( ) ; // Ensure catalog folder exists
3247
33- if ( HighLogic . LoadedScene != GameScenes . MAINMENU && GTAOSettings . EnableGTAO )
48+ // Only auto-enable if in a playable scene (not LOADING, MAINMENU, or EDITOR)
49+ if ( IsPlayableScene ( ) && ( GTAOSettings . EnableGTAO || StarfieldSettings . EnableStarfield ) )
3450 {
3551 Invoke ( nameof ( DelayedInit ) , 0.5f ) ;
3652 }
3753
3854 GameEvents . onGUIApplicationLauncherReady . Add ( OnGUIApplicationLauncherReady ) ;
3955 GameEvents . onLevelWasLoadedGUIReady . Add ( OnLevelWasLoadedGUIReady ) ;
56+
57+ // Listen for game load/save events for per-save settings
58+ GameEvents . onGameStateLoad . Add ( OnGameStateLoad ) ;
59+ GameEvents . onGameStateSave . Add ( OnGameStateSave ) ;
4060
4161 if ( _toolbarIcon == null )
4262 {
@@ -56,12 +76,36 @@ private void DelayedInit()
5676 {
5777 if ( GTAOSettings . EnableGTAO )
5878 GTAOManager . Initialize ( ) ;
79+ if ( StarfieldSettings . EnableStarfield )
80+ StarfieldManager . Initialize ( ) ;
81+ }
82+
83+ /// <summary>
84+ /// Check if current scene is a playable scene (not LOADING, MAINMENU, or EDITOR)
85+ /// Starfield needs a sky camera which only exists in these scenes
86+ /// </summary>
87+ private bool IsPlayableScene ( )
88+ {
89+ return HighLogic . LoadedScene == GameScenes . SPACECENTER ||
90+ HighLogic . LoadedScene == GameScenes . FLIGHT ||
91+ HighLogic . LoadedScene == GameScenes . TRACKSTATION ;
5992 }
6093
6194 private void OnLevelWasLoadedGUIReady ( GameScenes scene )
6295 {
6396 if ( scene == GameScenes . MAINMENU ) return ;
6497
98+ // If coming from MAINMENU to a playable scene, reset the starfield compositor
99+ // It may be in a bad state from failed initialization during game startup
100+ if ( StarfieldManager . IsActive )
101+ {
102+ Debug . Log ( "[CinematicShaders] Scene change from menu - resetting starfield compositor..." ) ;
103+ StarfieldManager . DisableStarfield ( ) ;
104+ }
105+
106+ // Mark catalog for reload on scene change (device may have reset)
107+ StarfieldSettings . InvalidateCatalogForReload ( ) ;
108+
65109 if ( GTAOSettings . EnableGTAO )
66110 {
67111 if ( scene == GameScenes . EDITOR && GTAOManager . IsActive )
@@ -84,6 +128,12 @@ private void OnLevelWasLoadedGUIReady(GameScenes scene)
84128 Invoke ( nameof ( RetryInit ) , 3.0f ) ;
85129 }
86130 }
131+
132+ // Initialize Starfield completely independently of GTAO
133+ if ( StarfieldSettings . EnableStarfield && IsPlayableScene ( ) )
134+ {
135+ StarfieldManager . Initialize ( ) ;
136+ }
87137 }
88138
89139 private void RetryInit ( )
@@ -102,6 +152,8 @@ void OnDestroy()
102152
103153 GameEvents . onGUIApplicationLauncherReady . Remove ( OnGUIApplicationLauncherReady ) ;
104154 GameEvents . onLevelWasLoadedGUIReady . Remove ( OnLevelWasLoadedGUIReady ) ;
155+ GameEvents . onGameStateLoad . Remove ( OnGameStateLoad ) ;
156+ GameEvents . onGameStateSave . Remove ( OnGameStateSave ) ;
105157
106158 if ( _toolbarButton != null && ApplicationLauncher . Instance != null )
107159 {
@@ -112,6 +164,7 @@ void OnDestroy()
112164 if ( _mainWindow != null && _mainWindow . gameObject != null )
113165 Destroy ( _mainWindow . gameObject ) ;
114166
167+ // Shutdown GTAO
115168 try
116169 {
117170 if ( GTAONative . IsLoaded )
@@ -122,9 +175,53 @@ void OnDestroy()
122175 /* DLL already unloaded, ignore */
123176 }
124177
178+ // Shutdown Starfield
179+ try
180+ {
181+ if ( StarfieldNative . IsLoaded )
182+ StarfieldNative . CR_StarfieldShutdown ( ) ;
183+ }
184+ catch ( System . Exception )
185+ {
186+ /* DLL already unloaded, ignore */
187+ }
188+
125189 Instance = null ;
126190 }
127191
192+ private void OnGameStateLoad ( ConfigNode node )
193+ {
194+ Debug . Log ( "[CinematicShaders] Game state loaded - applying per-save settings" ) ;
195+
196+ // Apply per-save settings from ScenarioModule if available
197+ if ( StarfieldPerSaveSettings . Instance != null )
198+ {
199+ Debug . Log ( "[CinematicShaders] Found StarfieldPerSaveSettings, applying..." ) ;
200+ StarfieldPerSaveSettings . Instance . ApplyToSettings ( ) ;
201+ }
202+ else
203+ {
204+ Debug . LogWarning ( "[CinematicShaders] StarfieldPerSaveSettings.Instance is null!" ) ;
205+ }
206+
207+ Debug . Log ( $ "[CinematicShaders] After per-save settings: EnableStarfield={ StarfieldSettings . EnableStarfield } , Catalog={ StarfieldSettings . ActiveCatalogPath } ") ;
208+
209+ // Initialize starfield if enabled and we're in a playable scene
210+ if ( StarfieldSettings . EnableStarfield && IsPlayableScene ( ) )
211+ {
212+ Debug . Log ( "[CinematicShaders] Initializing Starfield..." ) ;
213+ StarfieldManager . Initialize ( ) ;
214+ }
215+ }
216+
217+ private void OnGameStateSave ( ConfigNode node )
218+ {
219+ Debug . Log ( "[CinematicShaders] Game state saving - capturing per-save settings" ) ;
220+ // Per-save settings are automatically saved by KSP from StarfieldPerSaveSettings.Instance
221+ }
222+
223+
224+
128225 private void OnGUIApplicationLauncherReady ( )
129226 {
130227 if ( _toolbarButton != null || Instance != this ) return ;
0 commit comments