@@ -31,6 +31,7 @@ import { buildProjectPackage, summarizeProjectPackaging } from "../shared/projec
3131import { buildEditorExperienceLayer , summarizeEditorExperienceLayer } from "../shared/editorExperienceLayer.js" ;
3232import { buildDebugVisualizationLayer , summarizeDebugVisualizationLayer } from "../shared/debugVisualizationLayer.js" ;
3333import { registerToolBootContract } from "../shared/toolBootContract.js" ;
34+ import { createLivePreviewSyncBridge } from "../shared/livePreviewSyncChannel.js" ;
3435
3536const SAMPLE_DIRECTORY_PATH = "./samples/" ;
3637const SAMPLE_MANIFEST_PATH = "./samples/sample-manifest.json" ;
@@ -390,6 +391,9 @@ class ParallaxEditorApp {
390391 this . lastRuntimeResult = null ;
391392 this . editorExperienceResult = null ;
392393 this . debugVisualizationResult = null ;
394+ this . livePreviewSync = createLivePreviewSyncBridge ( { sourceId : "parallax-editor" } ) ;
395+ this . livePreviewSyncFrame = 0 ;
396+ this . pendingLivePreviewReason = "init" ;
393397 }
394398
395399 invalidateImageCache ( ) {
@@ -402,6 +406,7 @@ class ParallaxEditorApp {
402406 this . attachEvents ( ) ;
403407 this . syncInputsFromDocument ( ) ;
404408 this . renderAll ( ) ;
409+ this . queueLivePreviewSync ( "init" ) ;
405410 this . loadSampleManifest ( ) ;
406411 }
407412
@@ -539,6 +544,32 @@ class ParallaxEditorApp {
539544
540545 touchDocument ( ) {
541546 this . documentModel . metadata . updatedAt = new Date ( ) . toISOString ( ) ;
547+ this . queueLivePreviewSync ( "document-update" ) ;
548+ }
549+
550+ publishLivePreviewSync ( reason = "update" ) {
551+ this . livePreviewSync . publish (
552+ {
553+ toolId : "parallax-editor" ,
554+ reason,
555+ parallaxDocument : cloneDeep ( this . documentModel )
556+ } ,
557+ "tool-live-preview-sync"
558+ ) ;
559+ }
560+
561+ queueLivePreviewSync ( reason = "update" ) {
562+ this . pendingLivePreviewReason = reason ;
563+ if ( this . livePreviewSyncFrame ) {
564+ return ;
565+ }
566+ const schedule = typeof requestAnimationFrame === "function"
567+ ? requestAnimationFrame
568+ : ( callback ) => setTimeout ( callback , 16 ) ;
569+ this . livePreviewSyncFrame = schedule ( ( ) => {
570+ this . livePreviewSyncFrame = 0 ;
571+ this . publishLivePreviewSync ( this . pendingLivePreviewReason ) ;
572+ } ) ;
542573 }
543574
544575 updateStatus ( message ) {
@@ -933,6 +964,7 @@ class ParallaxEditorApp {
933964 this . cameraY = 0 ;
934965 this . syncInputsFromDocument ( ) ;
935966 this . renderAll ( ) ;
967+ this . queueLivePreviewSync ( "load-sample" ) ;
936968 this . updateStatus ( `Loaded sample ${ selectedPath } .` ) ;
937969 } catch ( error ) {
938970 this . updateStatus ( `Sample load failed: ${ error instanceof Error ? error . message : "unknown error" } ` ) ;
@@ -948,6 +980,7 @@ class ParallaxEditorApp {
948980 this . cameraY = 0 ;
949981 this . syncInputsFromDocument ( ) ;
950982 this . renderAll ( ) ;
983+ this . queueLivePreviewSync ( "new-project" ) ;
951984 this . updateStatus ( "Created new parallax document." ) ;
952985 }
953986
@@ -1151,6 +1184,7 @@ class ParallaxEditorApp {
11511184 this . cameraY = 0 ;
11521185 this . syncInputsFromDocument ( ) ;
11531186 this . renderAll ( ) ;
1187+ this . queueLivePreviewSync ( "load-project" ) ;
11541188 const validation = this . validateProjectAssets ( ) ;
11551189 if ( resolution . resolvedCount > 0 ) {
11561190 this . updateStatus ( `Loaded ${ file . name } (${ resolution . resolvedCount } layer image refs restored from asset registry, validation: ${ summarizeAssetValidation ( validation ) } ).` ) ;
0 commit comments