1- import { QualityMode } from '@/utils/constants ' ;
1+ import { QualityMode } from '@/utils/quality ' ;
22import { type World } from '@dimforge/rapier3d-compat' ;
33import {
44 THREE ,
@@ -18,10 +18,12 @@ import {
1818 UILoadingScreen ,
1919 VolumetricClouds ,
2020 generateSetupData ,
21+ UIMainMenu ,
2122 } from '@opengolfsim/fuse' ;
2223
2324
2425const gameContext : {
26+ isReady : boolean ,
2527 startPoint : THREE . Vector3 ,
2628 aimPoint : THREE . Vector3 ,
2729 qualityLevel : QualityMode ,
@@ -50,6 +52,7 @@ const gameContext: {
5052 shotData ?: UIShotData ,
5153 courseMap ?: UICourseMap ,
5254 playerMenu ?: UIPlayerMenu ,
55+ mainMenu ?: UIMainMenu ,
5356 loadingScreen ?: UILoadingScreen ,
5457 rangeFinder ?: UIRangeFinder ,
5558 stats ?: UIStats ,
@@ -58,6 +61,7 @@ const gameContext: {
5861 distanceToAim : number ,
5962 heightToAim : number ,
6063} = {
64+ isReady : false ,
6165 timer : new THREE . Timer ( ) ,
6266 startPoint : new THREE . Vector3 ( 0 , 0 , 0 ) ,
6367 aimPoint : new THREE . Vector3 ( 0 , 0 , 0 ) ,
@@ -97,11 +101,14 @@ function setupNextShot() {
97101 gameContext . golfBall ?. reset ( gameContext . aimPoint , gameContext . startPoint ) ;
98102
99103 aimPointUpdated ( true ) ;
100-
104+
105+ gameContext . clouds ?. update ( ) ;
106+
101107 gameContext . courseMap ?. updatePosition ( gameContext . startPoint , gameContext . game . pinPoint ( ) ) ;
102108 gameContext . courseMap ?. updateHole ( gameContext . game . activeHole ) ;
103109
104110 gameContext . playerMenu ?. update ( gameContext . game . activePlayer ) ;
111+
105112}
106113
107114function setupRenderer ( ) {
@@ -110,19 +117,29 @@ function setupRenderer() {
110117
111118 THREE . ColorManagement . enabled = true ;
112119
113- gameContext . renderer = new THREE . WebGLRenderer ( { canvas, antialias : true } ) ;
120+ app . sendMessage ( { type : 'log' , message : `qualityLevel: ${ gameContext . qualityLevel } ` } ) ;
121+
122+ gameContext . renderer = new THREE . WebGLRenderer ( {
123+ canvas,
124+ antialias : true // gameContext.qualityLevel >= QualityMode.Medium
125+ } ) ;
114126 gameContext . renderer . setSize ( window . innerWidth , window . innerHeight ) ;
115- console . log ( 'window.devicePixelRatio' , Math . min ( window . devicePixelRatio , 1 ) ) ;
116-
117- let maxPixelRatio = 1 ;
127+
128+ let maxPixelRatio = Math . min ( window . devicePixelRatio , 1 ) ;
118129 if ( gameContext . qualityLevel >= QualityMode . High ) {
119- maxPixelRatio = 2 ;
130+ maxPixelRatio = Math . min ( window . devicePixelRatio , 2 ) ;
120131 }
121- gameContext . renderer . setPixelRatio ( Math . min ( window . devicePixelRatio , maxPixelRatio ) ) ;
122- gameContext . renderer . shadowMap . enabled = true ;
132+
133+ app . sendMessage ( { type : 'log' , message : `maxPixelRatio: ${ maxPixelRatio } ` } ) ;
134+
135+ gameContext . renderer . setPixelRatio ( maxPixelRatio ) ;
136+ gameContext . renderer . shadowMap . enabled = gameContext . qualityLevel >= QualityMode . Medium ;
123137 gameContext . renderer . shadowMap . type = THREE . PCFShadowMap ;
124- gameContext . renderer . toneMapping = THREE . ACESFilmicToneMapping ; // or whatever you pick
125- gameContext . renderer . toneMappingExposure = 1.0 ;
138+
139+ if ( gameContext . qualityLevel >= QualityMode . Medium ) {
140+ gameContext . renderer . toneMapping = THREE . ACESFilmicToneMapping ; // or whatever you pick
141+ gameContext . renderer . toneMappingExposure = 1.0 ;
142+ }
126143
127144}
128145
@@ -227,7 +244,8 @@ function adjustAimPoint(newPosition: THREE.Vector3) {
227244 newPosition . y = ground . y ;
228245 }
229246 gameContext . aimPoint . copy ( newPosition ) ;
230- gameContext . camera ?. setPositions ( gameContext . game . startPoint ( ) , gameContext . aimPoint ) ;
247+ gameContext . camera ?. setPositions ( gameContext . game . startPoint ( ) , gameContext . aimPoint ) ;
248+
231249 aimPointUpdated ( true ) ;
232250}
233251
@@ -258,18 +276,25 @@ async function setupCourse() {
258276 if ( ! app . world ) {
259277 throw new Error ( 'Physics world does not exist' ) ;
260278 }
279+
261280 if ( ! gameContext ?. setupData ) {
262281 throw new Error ( 'Missing setupData!' ) ;
263282 }
264283 if ( ! gameContext ?. gameData ?. courseUrl ) {
265284 throw new Error ( 'Missing a courseUrl to a GLB in the gameData object' ) ;
266285 }
286+ if ( typeof gameContext . setupData ?. qualityLevel !== 'undefined' ) {
287+ gameContext . qualityLevel = gameContext . setupData . qualityLevel ;
288+ }
267289 setupRenderer ( ) ;
268-
290+ if ( ! gameContext . renderer ) {
291+ throw new Error ( 'Missing renderer!' ) ;
292+ }
269293 // load course details and meshes
270294 gameContext . course = new CourseLoader (
271295 app . world ,
272296 app . rapier ,
297+ gameContext . renderer ,
273298 {
274299 setupData : gameContext . setupData ,
275300 manager : gameContext . loadingScreen ?. manager
@@ -305,6 +330,9 @@ async function setupCourse() {
305330
306331 gameContext . shotData = new UIShotData ( '#shot-data' , { units : gameContext . setupData ?. units } ) ;
307332 gameContext . rangeFinder = new UIRangeFinder ( '#top-center' , { units : gameContext . setupData ?. units } ) ;
333+ gameContext . mainMenu = new UIMainMenu ( '#top-left' ) ;
334+ gameContext . mainMenu . on ( 'exit' , ( ) => app . exit ( ) )
335+
308336 gameContext . playerMenu = new UIPlayerMenu ( '#top-left' , { players : gameContext . game ?. players || [ ] } ) ;
309337 gameContext . playerMenu . on ( 'selectPlayer' , player => {
310338 // handle player changed
@@ -339,8 +367,8 @@ function preLoad() {
339367 // }
340368 // allow override with query param
341369 const qualityParam = ( new URLSearchParams ( window . location . search ) ) . get ( 'quality' ) ;
342- if ( gameContext . setupData && qualityParam ) {
343- gameContext . setupData . qualityLevel = parseInt ( qualityParam , 10 ) ;
370+ if ( qualityParam ) {
371+ gameContext . qualityLevel = parseInt ( qualityParam , 10 ) ;
344372 }
345373
346374 console . log ( '[debug] Setup Data' , gameContext . setupData ) ;
@@ -349,10 +377,11 @@ function preLoad() {
349377 gameContext . stats = new UIStats ( '#render-stats' , { hidden : false , renderer : gameContext . renderer } ) ; // start hidden (press S to toggle)
350378 if ( ! error ) {
351379 requestAnimationFrame ( animate ) ;
380+ gameContext . isReady = true ;
352381 }
353382 } ) ;
354383 gameContext . loadingScreen . load ( setupCourse ) ;
355-
384+ document . body . style . opacity = '1' ;
356385 gameContext . timer . connect ( document ) ;
357386}
358387
@@ -372,7 +401,9 @@ function animate(animDelta: number) {
372401 gameContext . controls ?. update ( delta ) ;
373402 gameContext . clouds ?. update ( delta ) ;
374403
375- if ( gameContext . camera ) gameContext . course ?. update ( delta , gameContext . camera ) ;
404+ if ( gameContext . camera && gameContext . isReady ) {
405+ gameContext . course ?. update ( delta , gameContext . camera , gameContext . golfBall ?. isShotActive ) ;
406+ }
376407
377408 gameContext . game ?. update ( delta ) ;
378409
0 commit comments