@@ -72,33 +72,21 @@ export async function exportNode(editor: Editor, node: Node): Promise<void> {
7272 // Store original doNotSerialize values
7373 const originalDoNotSerialize = new Map < Node , boolean > ( ) ;
7474
75- // Temporarily set doNotSerialize = true for all nodes except the ones we want to include
76- scene . meshes . forEach ( ( mesh ) => {
77- originalDoNotSerialize . set ( mesh , mesh . doNotSerialize ) ;
78- mesh . doNotSerialize = ! nodesToInclude . has ( mesh ) ;
79- } ) ;
80-
81- scene . lights . forEach ( ( light ) => {
82- originalDoNotSerialize . set ( light , light . doNotSerialize ) ;
83- light . doNotSerialize = ! nodesToInclude . has ( light ) ;
84- } ) ;
75+ exportMeshes ( scene , nodesToInclude , originalDoNotSerialize ) ;
76+ exportLights ( scene , nodesToInclude , originalDoNotSerialize ) ;
77+ exportCameras ( scene , nodesToInclude , originalDoNotSerialize ) ;
78+ exportTransformNodes ( scene , nodesToInclude , originalDoNotSerialize ) ;
8579
86- scene . cameras . forEach ( ( camera ) => {
87- originalDoNotSerialize . set ( camera , camera . doNotSerialize ) ;
88- camera . doNotSerialize = ! nodesToInclude . has ( camera ) ;
89- } ) ;
90-
91- scene . transformNodes . forEach ( ( transformNode ) => {
92- originalDoNotSerialize . set ( transformNode , transformNode . doNotSerialize ) ;
93- transformNode . doNotSerialize = ! nodesToInclude . has ( transformNode ) ;
94- } ) ;
80+ const originalParticleSystems = exportParticleSystems ( scene , nodesToInclude ) ;
81+ const originalSoundTracks = exportSounds ( scene , nodesToInclude ) ;
9582
9683 // Serialize the filtered scene
9784 const data = await SceneSerializer . SerializeAsync ( scene ) ;
9885
99- // Restore original doNotSerialize values
100- originalDoNotSerialize . forEach ( ( value , node ) => {
101- node . doNotSerialize = value ;
86+ // Restore original scene state
87+ restoreSceneState ( scene , originalDoNotSerialize , {
88+ originalParticleSystems,
89+ originalSoundTracks
10290 } ) ;
10391
10492 await writeJSON ( filePath , data , JSON_CONFIG ) ;
@@ -112,3 +100,161 @@ export async function exportNode(editor: Editor, node: Node): Promise<void> {
112100 }
113101 }
114102}
103+
104+ /**
105+ * Restores the original scene state after export.
106+ * @param scene The scene to restore
107+ * @param originalDoNotSerialize Map containing original serialization states
108+ * @param exportData Data needed for restoration
109+ */
110+ function restoreSceneState (
111+ scene : any ,
112+ originalDoNotSerialize : Map < Node , boolean > ,
113+ exportData : { originalParticleSystems : any [ ] ; originalSoundTracks : any [ ] }
114+ ) : void {
115+ // Restore original doNotSerialize values
116+ originalDoNotSerialize . forEach ( ( value , node ) => {
117+ node . doNotSerialize = value ;
118+ } ) ;
119+
120+ // Restore particle systems
121+ scene . particleSystems . length = 0 ;
122+ exportData . originalParticleSystems . forEach ( ( ps : any ) =>
123+ scene . particleSystems . push ( ps )
124+ ) ;
125+
126+ // Restore soundtracks
127+ scene . soundTracks = exportData . originalSoundTracks ;
128+ }
129+
130+ /**
131+ * Configures mesh nodes for export.
132+ * @param scene The scene containing the meshes
133+ * @param nodesToInclude Set of nodes to include in the export
134+ * @param originalDoNotSerialize Map to store original serialization state
135+ */
136+ function exportMeshes (
137+ scene : any ,
138+ nodesToInclude : Set < Node > ,
139+ originalDoNotSerialize : Map < Node , boolean >
140+ ) : void {
141+ scene . meshes . forEach ( ( mesh : Node ) => {
142+ originalDoNotSerialize . set ( mesh , mesh . doNotSerialize ) ;
143+ mesh . doNotSerialize = ! nodesToInclude . has ( mesh ) ;
144+ } ) ;
145+ }
146+
147+ /**
148+ * Configures light nodes for export.
149+ * @param scene The scene containing the lights
150+ * @param nodesToInclude Set of nodes to include in the export
151+ * @param originalDoNotSerialize Map to store original serialization state
152+ */
153+ function exportLights (
154+ scene : any ,
155+ nodesToInclude : Set < Node > ,
156+ originalDoNotSerialize : Map < Node , boolean >
157+ ) : void {
158+ scene . lights . forEach ( ( light : Node ) => {
159+ originalDoNotSerialize . set ( light , light . doNotSerialize ) ;
160+ light . doNotSerialize = ! nodesToInclude . has ( light ) ;
161+ } ) ;
162+ }
163+
164+ /**
165+ * Configures camera nodes for export.
166+ * @param scene The scene containing the cameras
167+ * @param nodesToInclude Set of nodes to include in the export
168+ * @param originalDoNotSerialize Map to store original serialization state
169+ */
170+ function exportCameras (
171+ scene : any ,
172+ nodesToInclude : Set < Node > ,
173+ originalDoNotSerialize : Map < Node , boolean >
174+ ) : void {
175+ scene . cameras . forEach ( ( camera : Node ) => {
176+ originalDoNotSerialize . set ( camera , camera . doNotSerialize ) ;
177+ camera . doNotSerialize = ! nodesToInclude . has ( camera ) ;
178+ } ) ;
179+ }
180+
181+ /**
182+ * Configures transform nodes for export.
183+ * @param scene The scene containing the transform nodes
184+ * @param nodesToInclude Set of nodes to include in the export
185+ * @param originalDoNotSerialize Map to store original serialization state
186+ */
187+ function exportTransformNodes (
188+ scene : any ,
189+ nodesToInclude : Set < Node > ,
190+ originalDoNotSerialize : Map < Node , boolean >
191+ ) : void {
192+ scene . transformNodes . forEach ( ( transformNode : Node ) => {
193+ originalDoNotSerialize . set ( transformNode , transformNode . doNotSerialize ) ;
194+ transformNode . doNotSerialize = ! nodesToInclude . has ( transformNode ) ;
195+ } ) ;
196+ }
197+
198+ /**
199+ * Filters particle systems for export based on their attached nodes.
200+ * @param scene The scene containing the particle systems
201+ * @param nodesToInclude Set of nodes to include in the export
202+ * @returns The original array of particle systems (for restoration)
203+ */
204+ function exportParticleSystems ( scene : any , nodesToInclude : Set < Node > ) : Array < any > {
205+ // Save original particle systems
206+ const originalParticleSystems = scene . particleSystems . slice ( ) ;
207+
208+ // Filter particle systems to only include those attached to our nodes
209+ const particlesToKeep = originalParticleSystems . filter ( ( ps : any ) => {
210+ const emitter = ps . emitter ;
211+ return emitter && nodesToInclude . has ( emitter as Node ) ;
212+ } ) ;
213+
214+ // Replace the scene's particle systems with only those we want to include
215+ scene . particleSystems . length = 0 ;
216+ particlesToKeep . forEach ( ( ps : any ) => scene . particleSystems . push ( ps ) ) ;
217+
218+ return originalParticleSystems ;
219+ }
220+
221+ /**
222+ * Filters sounds for export based on their attached nodes.
223+ * @param scene The scene containing the sounds
224+ * @param nodesToInclude Set of nodes to include in the export
225+ * @returns The original array of soundtracks (for restoration)
226+ */
227+ function exportSounds ( scene : any , nodesToInclude : Set < Node > ) : Array < any > {
228+ // Handle sounds - filter out sounds not attached to our nodes
229+ let originalSoundTracks : any [ ] = [ ] ;
230+
231+ if ( scene . soundTracks ) {
232+ // Store original soundtracks to restore later
233+ originalSoundTracks = scene . soundTracks . slice ( ) ;
234+
235+ // Filter each soundtrack to only include sounds attached to our nodes
236+ const filteredSoundTracks = scene . soundTracks . map ( ( soundtrack : any ) => {
237+ // Create a new sound collection with only the sounds attached to our nodes
238+ const filteredSoundCollection = soundtrack . soundCollection . filter ( ( sound : any ) => {
239+ if ( sound . spatialSound && sound . metadata && sound . metadata . connectedMeshName ) {
240+ // Check if the connected mesh name matches any of our nodes
241+ for ( const meshNode of nodesToInclude ) {
242+ if ( meshNode . name === sound . metadata . connectedMeshName ) {
243+ return true ;
244+ }
245+ }
246+ }
247+ return false ;
248+ } ) ;
249+
250+ // Replace the original sound collection with our filtered one
251+ soundtrack . soundCollection = filteredSoundCollection ;
252+ return soundtrack ;
253+ } ) . filter ( ( st : any ) => st . soundCollection . length > 0 ) ; // Remove empty soundtracks
254+
255+ // Replace scene soundtracks with our filtered ones
256+ scene . soundTracks = filteredSoundTracks ;
257+ }
258+
259+ return originalSoundTracks ;
260+ }
0 commit comments