@@ -9,7 +9,7 @@ import SolarSystemWorld from './SolarSystemWorld.js';
99
1010const VIEW = { width : 960 , height : 720 } ;
1111
12- const COLORS = {
12+ const DEFAULT_COLORS = {
1313 background : '#030712' ,
1414 frame : '#dbeafe' ,
1515 orbit : '#334155' ,
@@ -18,16 +18,38 @@ const COLORS = {
1818 panel : '#07101d' ,
1919} ;
2020
21+ function toObject ( value ) {
22+ return value && typeof value === 'object' ? value : { } ;
23+ }
24+
25+ function sanitizeSolarSceneColors ( skin ) {
26+ const colors = toObject ( skin ?. colors ) ;
27+ return {
28+ background : typeof colors . background === 'string' && colors . background . trim ( ) ? colors . background . trim ( ) : DEFAULT_COLORS . background ,
29+ frame : typeof colors . frame === 'string' && colors . frame . trim ( ) ? colors . frame . trim ( ) : DEFAULT_COLORS . frame ,
30+ orbit : typeof colors . orbit === 'string' && colors . orbit . trim ( ) ? colors . orbit . trim ( ) : DEFAULT_COLORS . orbit ,
31+ text : typeof colors . text === 'string' && colors . text . trim ( ) ? colors . text . trim ( ) : DEFAULT_COLORS . text ,
32+ muted : typeof colors . muted === 'string' && colors . muted . trim ( ) ? colors . muted . trim ( ) : DEFAULT_COLORS . muted ,
33+ panel : typeof colors . panel === 'string' && colors . panel . trim ( ) ? colors . panel . trim ( ) : DEFAULT_COLORS . panel
34+ } ;
35+ }
36+
2137export default class SolarSystemScene extends Scene {
22- constructor ( ) {
38+ constructor ( options = { } ) {
2339 super ( ) ;
24- this . world = new SolarSystemWorld ( VIEW ) ;
40+ this . world = new SolarSystemWorld ( { ...VIEW , skin : options . skin || null } ) ;
41+ this . colors = sanitizeSolarSceneColors ( options . skin ) ;
2542 this . isPaused = false ;
2643 this . lastPausePressed = false ;
2744 this . lastLabelsPressed = false ;
2845 this . lastResetPressed = false ;
2946 }
3047
48+ applySkin ( nextSkin ) {
49+ this . colors = sanitizeSolarSceneColors ( nextSkin ) ;
50+ this . world . applySkin ( nextSkin ) ;
51+ }
52+
3153 update ( dt , engine ) {
3254 const pausePressed = Boolean ( engine . input ?. isDown ?. ( 'KeyP' ) ) ;
3355 const labelsPressed = Boolean ( engine . input ?. isDown ?. ( 'KeyL' ) ) ;
@@ -62,7 +84,7 @@ export default class SolarSystemScene extends Scene {
6284 }
6385
6486 render ( renderer ) {
65- renderer . clear ( COLORS . background ) ;
87+ renderer . clear ( this . colors . background ) ;
6688 this . drawFrame ( renderer ) ;
6789 this . drawOrbits ( renderer ) ;
6890 this . drawBodies ( renderer ) ;
@@ -71,7 +93,7 @@ export default class SolarSystemScene extends Scene {
7193 if ( this . isPaused ) {
7294 renderer . drawRect ( 0 , 0 , VIEW . width , VIEW . height , 'rgba(0, 0, 0, 0.42)' ) ;
7395 renderer . drawText ( 'PAUSED' , VIEW . width / 2 , 324 , {
74- color : COLORS . text ,
96+ color : this . colors . text ,
7597 font : 'bold 30px monospace' ,
7698 textAlign : 'center' ,
7799 } ) ;
@@ -85,11 +107,11 @@ export default class SolarSystemScene extends Scene {
85107
86108 drawFrame ( renderer ) {
87109 const { bounds } = this . world ;
88- renderer . drawRect ( 0 , 0 , VIEW . width , 18 , COLORS . frame ) ;
89- renderer . drawRect ( 0 , VIEW . height - 18 , VIEW . width , 18 , COLORS . frame ) ;
90- renderer . drawRect ( 0 , 0 , 18 , VIEW . height , COLORS . frame ) ;
91- renderer . drawRect ( VIEW . width - 18 , 0 , 18 , VIEW . height , COLORS . frame ) ;
92- renderer . strokeRect ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top , COLORS . frame , 2 ) ;
110+ renderer . drawRect ( 0 , 0 , VIEW . width , 18 , this . colors . frame ) ;
111+ renderer . drawRect ( 0 , VIEW . height - 18 , VIEW . width , 18 , this . colors . frame ) ;
112+ renderer . drawRect ( 0 , 0 , 18 , VIEW . height , this . colors . frame ) ;
113+ renderer . drawRect ( VIEW . width - 18 , 0 , 18 , VIEW . height , this . colors . frame ) ;
114+ renderer . strokeRect ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top , this . colors . frame , 2 ) ;
93115 }
94116
95117 drawOrbits ( renderer ) {
@@ -98,7 +120,7 @@ export default class SolarSystemScene extends Scene {
98120 } ) ;
99121 }
100122
101- drawOrbitRing ( renderer , centerX , centerY , radiusX , radiusY , color = COLORS . orbit , lineWidth = 1 ) {
123+ drawOrbitRing ( renderer , centerX , centerY , radiusX , radiusY , color = this . colors . orbit , lineWidth = 1 ) {
102124 const segments = 48 ;
103125 let previous = null ;
104126
@@ -165,7 +187,7 @@ export default class SolarSystemScene extends Scene {
165187
166188 drawLabel ( renderer , text , x , y , font = '14px monospace' ) {
167189 renderer . drawText ( text , x , y , {
168- color : COLORS . text ,
190+ color : this . colors . text ,
169191 font,
170192 textBaseline : 'top' ,
171193 } ) ;
@@ -174,54 +196,54 @@ export default class SolarSystemScene extends Scene {
174196 drawHud ( renderer ) {
175197 const { bounds } = this . world ;
176198 renderer . drawText ( 'SOLAR SYSTEM' , 28 , 24 , {
177- color : COLORS . text ,
199+ color : this . colors . text ,
178200 font : 'bold 24px monospace' ,
179201 textBaseline : 'top' ,
180202 } ) ;
181203
182- renderer . drawRect ( 642 , 128 , 264 , 168 , COLORS . panel ) ;
183- renderer . strokeRect ( 642 , 128 , 264 , 168 , COLORS . frame , 2 ) ;
204+ renderer . drawRect ( 642 , 128 , 264 , 168 , this . colors . panel ) ;
205+ renderer . strokeRect ( 642 , 128 , 264 , 168 , this . colors . frame , 2 ) ;
184206 renderer . drawText ( 'System View' , 660 , 148 , {
185- color : COLORS . text ,
207+ color : this . colors . text ,
186208 font : 'bold 18px monospace' ,
187209 textBaseline : 'top' ,
188210 } ) ;
189211 renderer . drawText ( `Time: ${ this . world . elapsedDays . toFixed ( 1 ) } days` , 660 , 182 , {
190- color : COLORS . text ,
212+ color : this . colors . text ,
191213 font : '16px monospace' ,
192214 textBaseline : 'top' ,
193215 } ) ;
194216 renderer . drawText ( `Rate: ${ this . world . getTimeScale ( ) . label } ` , 660 , 208 , {
195- color : COLORS . text ,
217+ color : this . colors . text ,
196218 font : '16px monospace' ,
197219 textBaseline : 'top' ,
198220 } ) ;
199221 renderer . drawText ( `Labels: ${ this . world . labelsVisible ? 'ON' : 'OFF' } ` , 660 , 234 , {
200- color : COLORS . text ,
222+ color : this . colors . text ,
201223 font : '16px monospace' ,
202224 textBaseline : 'top' ,
203225 } ) ;
204226 renderer . drawText ( `Bodies: ${ 1 + this . world . planets . length + this . world . moons . length } ` , 660 , 260 , {
205- color : COLORS . text ,
227+ color : this . colors . text ,
206228 font : '16px monospace' ,
207229 textBaseline : 'top' ,
208230 } ) ;
209231
210- renderer . drawRect ( 642 , 314 , 264 , 192 , COLORS . panel ) ;
211- renderer . strokeRect ( 642 , 314 , 264 , 192 , COLORS . frame , 2 ) ;
232+ renderer . drawRect ( 642 , 314 , 264 , 192 , this . colors . panel ) ;
233+ renderer . strokeRect ( 642 , 314 , 264 , 192 , this . colors . frame , 2 ) ;
212234 renderer . drawText ( 'Controls' , 660 , 334 , {
213- color : COLORS . text ,
235+ color : this . colors . text ,
214236 font : 'bold 18px monospace' ,
215237 textBaseline : 'top' ,
216238 } ) ;
217- renderer . drawText ( 'P pause / resume' , 660 , 368 , { color : COLORS . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
218- renderer . drawText ( 'L toggle labels' , 660 , 394 , { color : COLORS . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
219- renderer . drawText ( 'R reset clock' , 660 , 420 , { color : COLORS . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
220- renderer . drawText ( '1 x1 2 x2' , 660 , 446 , { color : COLORS . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
221- renderer . drawText ( '3 x3 4 x4' , 660 , 472 , { color : COLORS . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
239+ renderer . drawText ( 'P pause / resume' , 660 , 368 , { color : this . colors . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
240+ renderer . drawText ( 'L toggle labels' , 660 , 394 , { color : this . colors . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
241+ renderer . drawText ( 'R reset clock' , 660 , 420 , { color : this . colors . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
242+ renderer . drawText ( '1 x1 2 x2' , 660 , 446 , { color : this . colors . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
243+ renderer . drawText ( '3 x3 4 x4' , 660 , 472 , { color : this . colors . muted , font : '16px monospace' , textBaseline : 'top' } ) ;
222244
223245 renderer . drawText ( 'Readable orbital motion, not exact scale.' , bounds . left , 686 , {
224- color : COLORS . muted ,
246+ color : this . colors . muted ,
225247 font : '16px monospace' ,
226248 textBaseline : 'top' ,
227249 } ) ;
0 commit comments