1 # SPDX-FileCopyrightText: 2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 from typing
import List
, Sequence
, Tuple
7 from bpy
.types
import (
12 def send_sound_strip(s
, dest_scn
):
13 '''recreate sound strip in another scene
14 :dest_scn: scene destination
15 :return: newly create sound strip
20 vse
= dest_scn
.sequence_editor
21 ns
= vse
.sequences
.new_sound(name
=s
.name
, filepath
=s
.sound
.filepath
, channel
=s
.channel
, frame_start
=int(s
.frame_start
))
22 ns
.sound
= s
.sound
# reget the same sound source
31 setattr(ns
, attr
, getattr(s
, attr
))
36 def get_all_overlapping_sound_strip(scn_strip
, skip_mute
=True):
37 """return array of all sound strips for this strip"""
38 if scn_strip
.type != 'SCENE':
41 src_scn
= scn_strip
.id_data
42 vse
= src_scn
.sequence_editor
43 overlapping_sounds
= []
44 for s
in vse
.sequences
:
47 if skip_mute
and s
.mute
:
50 if (s
.frame_final_end
- 1 < scn_strip
.frame_final_start
)\
51 or (s
.frame_final_start
- 1 > scn_strip
.frame_final_end
):
54 overlapping_sounds
.append(s
)
56 return overlapping_sounds
58 def delete_sounds(scene
):
59 for st
in reversed(scene
.sequence_editor
.sequences
):
60 if st
.type == 'SOUND':
61 scene
.sequence_editor
.sequences
.remove(st
)
63 def get_scene_frame_from_sequencer_frame(scn_strip
, sound
) -> float:
64 """return frame in scene referential"""
65 return sound
.frame_start
- scn_strip
.frame_start
+ scn_strip
.scene
.frame_start
67 def send_sound_to_strip_scene(scn_strip
, clear_sequencer
=True, skip_mute
=True):
68 """Add sounds to strip scene"""
69 if scn_strip
.type != 'SCENE':
71 tgt_scene
= scn_strip
.scene
73 sounds
= get_all_overlapping_sound_strip(scn_strip
, skip_mute
=skip_mute
)
77 # Clear sounds if exists in scene vse already
79 delete_sounds(tgt_scene
)
81 print(f
'Duplicating sounds in {tgt_scene.name}:')
83 new_start
= get_scene_frame_from_sequencer_frame(scn_strip
, s
)
84 ns
= send_sound_strip(s
, tgt_scene
)
86 ns
.frame_start
= new_start
87 ns
.frame_offset_start
= s
.frame_offset_start
88 ns
.frame_final_duration
= s
.frame_final_duration
93 def dispatch_sounds_in_scenes(selected_scn_only
=True, skip_mute
=True):
94 """Main function to duplicate sounds in strip scenes"""
95 edit_scene
= bpy
.context
.scene
96 edit
= edit_scene
.sequence_editor
99 for strip
in edit
.sequences
:
100 if strip
.type != 'SCENE':
103 if selected_scn_only
and not strip
.select
:
106 sounds
= send_sound_to_strip_scene(strip
, skip_mute
=skip_mute
)
111 print('INFO', f
'Sound duplicated in {ct} scenes')
113 print('ERROR', f
'No duplication occured')
116 class STORYPENCIL_OT_duplicate_sound_in_edit_scene(Operator
):
117 bl_idname
= "storypencil.duplicate_sound_in_edit_scene"
118 bl_label
= "Sounds To Scenes"
119 bl_description
= "Copy sound strips from VSE to the source scenes"
120 bl_options
= {'REGISTER', 'UNDO'}
123 def poll(cls
, context
):
124 if context
.space_data
.type != 'SEQUENCE_EDITOR':
129 def execute(self
, context
):
130 scene
= context
.scene
131 dispatch_sounds_in_scenes(
132 selected_scn_only
=scene
.storypencil_selected_scn_only
,
133 skip_mute
=scene
.storypencil_skip_sound_mute
)
135 bpy
.ops
.sequencer
.reload()