@@ -47,7 +47,20 @@ function activeSoundFromToolState(toolState) {
4747}
4848
4949export class AudioSfxPlaygroundV2App {
50- constructor ( { accordions, actionNav, audioEngine, controls, inspector, preview, serializer, shell, statusLog, tileList, windowRef = window } ) {
50+ constructor ( {
51+ accordions,
52+ actionNav,
53+ audioEngine,
54+ controls,
55+ inspector,
56+ preview,
57+ serializer,
58+ shell,
59+ statusLog,
60+ tileList,
61+ windowRef = window ,
62+ workspaceDirtyBridge = null
63+ } ) {
5164 this . accordions = accordions ;
5265 this . actionNav = actionNav ;
5366 this . activeSoundId = "" ;
@@ -62,6 +75,7 @@ export class AudioSfxPlaygroundV2App {
6275 this . statusLog = statusLog ;
6376 this . tileList = tileList ;
6477 this . window = windowRef ;
78+ this . workspaceDirtyBridge = workspaceDirtyBridge ;
6579 }
6680
6781 start ( ) {
@@ -94,11 +108,35 @@ export class AudioSfxPlaygroundV2App {
94108 }
95109 } ) ;
96110 this . statusLog . mount ( ) ;
111+ this . loadWorkspacePayload ( ) ;
97112 this . renderSoundList ( ) ;
98113 this . refreshPreview ( ) ;
99114 this . statusLog . write ( "Audio / SFX Playground V2 ready." ) ;
100115 }
101116
117+ loadWorkspacePayload ( ) {
118+ if ( ! this . workspaceDirtyBridge ) {
119+ return ;
120+ }
121+ const result = this . workspaceDirtyBridge . readPayload ( ) ;
122+ if ( result . skipped ) {
123+ return ;
124+ }
125+ if ( ! result . ok ) {
126+ this . statusLog . error ( `Workspace payload load failed: ${ result . message } ` ) ;
127+ return ;
128+ }
129+ const nextSoundEntries = result . value . soundEntries . map ( ( entry ) => ( {
130+ id : entry . id ,
131+ sound : cloneSound ( entry . sound )
132+ } ) ) ;
133+ this . activeSoundId = result . value . activeSoundId ;
134+ this . soundEntries = nextSoundEntries ;
135+ this . nextSoundNumber = nextSoundNumberAfter ( nextSoundEntries ) ;
136+ this . controls . loadSound ( result . value . sound ) ;
137+ this . statusLog . write ( `Loaded ${ result . value . sound . name } from Workspace V2.` ) ;
138+ }
139+
102140 currentToolState ( ) {
103141 const validation = this . controls . validate ( { nameOverride : this . activeSoundName ( ) } ) ;
104142 if ( ! validation . valid ) {
@@ -130,10 +168,33 @@ export class AudioSfxPlaygroundV2App {
130168 const validation = this . controls . validate ( { nameOverride : this . activeSoundName ( ) } ) ;
131169 if ( validation . valid && this . updateActiveSound ( this . soundForActiveEditorValue ( validation . value ) ) ) {
132170 this . renderSoundList ( ) ;
171+ this . syncWorkspaceDirty ( "audio-sfx-editor-change" , [ "data.sounds" ] ) ;
133172 }
134173 this . refreshPreview ( ) ;
135174 }
136175
176+ syncWorkspaceDirty ( reason , changedKeys ) {
177+ if ( ! this . workspaceDirtyBridge ) {
178+ return ;
179+ }
180+ const { toolState, validation } = this . currentToolState ( ) ;
181+ if ( ! validation . valid || ! toolState ) {
182+ this . statusLog . error ( `Workspace dirty sync skipped: ${ validation . message } ` ) ;
183+ return ;
184+ }
185+ const result = this . workspaceDirtyBridge . syncToolState ( toolState , { reason, changedKeys } ) ;
186+ if ( result . skipped ) {
187+ return ;
188+ }
189+ if ( ! result . ok ) {
190+ this . statusLog . error ( `Workspace dirty sync failed: ${ result . message } ` ) ;
191+ return ;
192+ }
193+ if ( result . changed ) {
194+ this . statusLog . write ( `Workspace dirty state updated: ${ result . reason } .` ) ;
195+ }
196+ }
197+
137198 hasDuplicateSoundName ( name , excludedSoundId = "" ) {
138199 const normalizedName = normalizeSoundName ( name ) ;
139200 return this . soundEntries . some ( ( entry ) => entry . id !== excludedSoundId && normalizeSoundName ( entry . sound . name ) === normalizedName ) ;
@@ -205,6 +266,7 @@ export class AudioSfxPlaygroundV2App {
205266 const entry = this . createSoundEntry ( validation . value ) ;
206267 this . renderSoundList ( ) ;
207268 this . refreshPreview ( ) ;
269+ this . syncWorkspaceDirty ( "audio-sfx-sound-added" , [ "data.sounds" , "data.activeSoundId" ] ) ;
208270 this . statusLog . write ( `Added ${ entry . sound . name } .` ) ;
209271 }
210272
@@ -229,6 +291,7 @@ export class AudioSfxPlaygroundV2App {
229291 entry . sound . name = nextName ;
230292 this . renderSoundList ( ) ;
231293 this . refreshPreview ( ) ;
294+ this . syncWorkspaceDirty ( "audio-sfx-sound-renamed" , [ "data.sounds" ] ) ;
232295 this . statusLog . write ( `Renamed SFX to ${ entry . sound . name } .` ) ;
233296 }
234297
@@ -292,6 +355,7 @@ export class AudioSfxPlaygroundV2App {
292355 }
293356 this . renderSoundList ( ) ;
294357 this . refreshPreview ( ) ;
358+ this . syncWorkspaceDirty ( "audio-sfx-sound-deleted" , [ "data.sounds" , "data.activeSoundId" ] ) ;
295359 this . statusLog . write ( `Deleted ${ entry . sound . name } .` ) ;
296360 }
297361
@@ -358,6 +422,7 @@ export class AudioSfxPlaygroundV2App {
358422 this . controls . loadSound ( result . value . sound ) ;
359423 this . renderSoundList ( ) ;
360424 this . refreshPreview ( ) ;
425+ this . syncWorkspaceDirty ( "audio-sfx-json-imported" , [ "data.sounds" , "data.activeSoundId" ] ) ;
361426 this . statusLog . write ( `Imported JSON from ${ file . name } .` ) ;
362427 } catch ( error ) {
363428 this . statusLog . error ( `Import JSON failed: ${ error . message } ` ) ;
0 commit comments