diff --git a/apps/www/components/LaunchWeek/14/TicketCanvas.tsx b/apps/www/components/LaunchWeek/14/TicketCanvas.tsx index c556c1d00dd..c54c61e4f3a 100644 --- a/apps/www/components/LaunchWeek/14/TicketCanvas.tsx +++ b/apps/www/components/LaunchWeek/14/TicketCanvas.tsx @@ -32,12 +32,16 @@ const TicketCanvas = ({ }: TicketCanvasProps) => { const sceneRef = useRef(null) const tunnelRef = useRef(null) + const initQueue = useRef<{ init: Promise; renderer: SceneRenderer }[]>([]) const setup = useCallback( (container: HTMLElement) => { - const sceneRenderer = new SceneRenderer(container) + const uuid = Math.random().toString(36).substring(7) - void sceneRenderer.init(async () => { - sceneRef.current = new TicketScene({ + const sceneRenderer = new SceneRenderer(container, initQueue.current, uuid) + + const initPromise = sceneRenderer.init(async () => { + const scene = new TicketScene({ + defaultVisible: sceneRef.current?.state.visible, defaultSecret: secret, defaultPlatinum: platinum, user, @@ -51,13 +55,17 @@ const TicketCanvas = ({ }, }) - tunnelRef.current = new TunnelScene({ + const tunnel = new TunnelScene({ defaultVisible: true, }) - await sceneRenderer.activateScene(sceneRef.current, true) - await sceneRenderer.activateScene(tunnelRef.current) + await sceneRenderer.activateScene(scene, true) + await sceneRenderer.activateScene(tunnel) + sceneRef.current = scene + tunnelRef.current = tunnel }) + initQueue.current.push({ init: initPromise, renderer: sceneRenderer }) + return sceneRenderer }, [platinum, secret, startDate, user] diff --git a/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts b/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts index 4ae89485805..53a35c3eb02 100644 --- a/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts +++ b/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts @@ -163,12 +163,7 @@ class TicketScene implements BaseScene { 688.43 / 2000, 788.63 / 2000, ], - y: [ - 0 / 1400, - 71.61 / 1400, - 163.5 / 1400, - 235.54 / 1400 - ], + y: [0 / 1400, 71.61 / 1400, 163.5 / 1400, 235.54 / 1400], }, } @@ -386,7 +381,6 @@ class TicketScene implements BaseScene { for (const intersect of intersects) { const clickedMesh = intersect.object as THREE.Mesh - console.log((clickedMesh.material as THREE.Material).name) // Handle click based on which mesh was clicked if (clickedMesh === this._namedMeshes.TicketFrontWebsiteButton) { this.options.onWebsiteButtonClicked?.() @@ -577,13 +571,9 @@ class TicketScene implements BaseScene { private _updateTicketSize(time?: number) { if (this.state.visible) { - // console.log("Setting ticket visible") - // this._ticket?.scale.set(1, 1, 1) this._ticket?.scale.lerp(new Vector3(1, 1, 1), 0.01) } else { - // console.log("Setting ticket invisible") this._ticket?.scale.lerp(new Vector3(0, 0, 0), 0.01) - // this._ticket?.scale.set(0, 0, 0) } // Update world matrices after scaling to ensure raycaster works correctly @@ -666,17 +656,15 @@ class TicketScene implements BaseScene { for (const part of mesh.children) { if (!(part instanceof THREE.Mesh)) { - console.warn(`Part is not a THREE.Mesh. Got:`, part) continue } if (!(part.material instanceof THREE.Material)) { - console.log(`Material is not an instance of THREE.Material. Got:`, part.material) + console.warn(`Material is not an instance of THREE.Material. Got:`, part.material) continue } if ((TicketScene.TEXTURE_NAMES as readonly string[]).includes(part.material.name)) { - console.log(`Found named mesh:`, part.material.name) this._namedMeshes[part.material.name as AvailableTextures] = part } else { console.warn(`Mesh ${part.material.name} is not a named texture`) @@ -694,10 +682,7 @@ class TicketScene implements BaseScene { if (!force) { if (this._internalState.loadedTextureType === textureSetKey) { - console.log('Textures already loaded. Active set:', textureSetKey) return - } else { - console.log('Loading textures for set:', textureSetKey) } } @@ -721,7 +706,6 @@ class TicketScene implements BaseScene { const allMeshes = Object.entries(this._namedMeshes) // Preload all textures and prepare canvases for (const [name, mesh] of allMeshes) { - console.log('Drawind texture', name) if (!mesh || !(mesh instanceof THREE.Mesh)) { console.warn(`Mesh ${name} is not a THREE.Mesh`) continue @@ -743,7 +727,6 @@ class TicketScene implements BaseScene { // If we have an image for this texture const textureDescriptor = textureImageMap[textureKey] if (!textureDescriptor) { - console.warn(`No texture descriptor found for texture ${textureKey}`) continue } @@ -785,7 +768,6 @@ class TicketScene implements BaseScene { texture.colorSpace = THREE.SRGBColorSpace texture.needsUpdate = true - console.log('Drawing texture on', textureKey, mesh) // Fix: Preserve the original material properties const originalMaterial = mesh.material const originalColor = mesh.material.color.clone() @@ -905,7 +887,6 @@ class TicketScene implements BaseScene { const seatCoord = this.state.ticketNumber % 32 const seatCol = seatCoord % 8 const seatRow = Math.floor(seatCoord / 8) - console.log('Seat coord:', seatCoord, seatCol, seatRow) context.fillStyle = colorObjToRgb(colors.textNeonColor) @@ -914,8 +895,10 @@ class TicketScene implements BaseScene { // Translate the context based on seat coordinates // Adjust these multipliers to control spacing between seats context.translate( - this.texts.seatStart.x * canvas.width + (this.texts.seatPositions.x[seatCol] ?? 0) * canvas.width, - this.texts.seatStart.y * canvas.height + (this.texts.seatPositions.y[seatRow] ?? 0) * canvas.height + this.texts.seatStart.x * canvas.width + + (this.texts.seatPositions.x[seatCol] ?? 0) * canvas.width, + this.texts.seatStart.y * canvas.height + + (this.texts.seatPositions.y[seatRow] ?? 0) * canvas.height ) // Fill the path at the new position context.fill(this.textureImages.secret.seatPath) diff --git a/apps/www/components/LaunchWeek/14/utils/SceneRenderer.ts b/apps/www/components/LaunchWeek/14/utils/SceneRenderer.ts index f8dfea9792d..fb3798970ea 100644 --- a/apps/www/components/LaunchWeek/14/utils/SceneRenderer.ts +++ b/apps/www/components/LaunchWeek/14/utils/SceneRenderer.ts @@ -46,7 +46,11 @@ class SceneRenderer { private _isDisposed = false private _isInitialized = false - constructor(public container: HTMLElement) { + constructor( + public container: HTMLElement, + private waitFor?: { init: Promise; renderer: SceneRenderer }[], + private uuid?: string + ) { this.renderer = new WebGLRenderer({ antialias: true, alpha: true }) this.composer = new EffectComposer(this.renderer) @@ -70,13 +74,22 @@ class SceneRenderer { } async init(sceneInitializer: () => Promise) { - if (this._isDisposed) { + console.log('SCENE RENDERER: Init call', this.waitFor?.length, this.uuid) + await Promise.allSettled( + this.waitFor?.filter((t) => t.renderer !== this).map((t) => t.init) || [] + ) + + if(this._isDisposed) { + console.log('SCENE RENDERER: Already disposed before sceneInitializer', this.uuid) return } + console.log('SCENE RENDERER: Waited for all pending inits', this.waitFor?.length, this.uuid) + await sceneInitializer() - if (this._isDisposed) { + if(this._isDisposed) { + console.log('SCENE RENDERER: Already disposed after sceneInitializer', this.uuid) return } @@ -101,7 +114,18 @@ class SceneRenderer { } async activateScene(scene: BaseScene, main?: boolean) { + if(this._isDisposed) { + console.log('SCENE RENDERER: Already disposed before activateScene', this.uuid) + return + } + const threeScene = await scene.setup(this) + + if(this._isDisposed) { + console.log('SCENE RENDERER: Already disposed after activateScene', this.uuid) + return + } + if (main && threeScene) { this.mainThreeJsScene = threeScene } @@ -130,6 +154,8 @@ class SceneRenderer { } cleanup() { + console.log('SCENE RENDERER: Cleanup', this.uuid) + this._isDisposed = true this.composer.dispose() this.renderer.dispose() @@ -144,6 +170,15 @@ class SceneRenderer { window.removeEventListener('resize', this._resizeHandler) this._resizeHandler = null } + + if (this.waitFor) { + // Mutate array in place instead of replacing reference + this.waitFor.splice( + 0, + this.waitFor.length, + ...this.waitFor.filter((t) => t.renderer === this) + ) + } } private _resize(ev: UIEvent) { diff --git a/apps/www/pages/launch-week/14/index.tsx b/apps/www/pages/launch-week/14/index.tsx index a1424f45acc..068dc6af064 100644 --- a/apps/www/pages/launch-week/14/index.tsx +++ b/apps/www/pages/launch-week/14/index.tsx @@ -1,6 +1,6 @@ import { NextSeo } from 'next-seo' import { useRouter } from 'next/router' -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { Session } from '@supabase/supabase-js' import TicketCanvas from '~/components/LaunchWeek/14/TicketCanvas' import DefaultLayout from '~/components/Layouts/Default'