[Bf-extensions-cvs] [6fcd157f] master: Storypencil: Support Audio files and UI refactor
Antonio Vazquez
noreply at git.blender.org
Thu Jan 19 15:48:24 CET 2023
Commit: 6fcd157f2497d9ba4ba82191cb2abf3de11a0394
Author: Antonio Vazquez
Date: Tue Jan 17 12:02:23 2023 +0100
Branches: master
https://developer.blender.org/rBA6fcd157f2497d9ba4ba82191cb2abf3de11a0394
Storypencil: Support Audio files and UI refactor
* Now Edit scenes support audio files included in VSE scene.
The audio file is copied to edit scene and allows to keep audio synch.
* Refactor UI to make easier to understand swithing modes.
* Fix some bugs founds during testing.
Thanks to Samuel Bernou for provinding base code for audio handling.
===================================================================
M storypencil/__init__.py
M storypencil/dopesheet_overlay.py
M storypencil/render.py
A storypencil/sound.py
M storypencil/synchro.py
M storypencil/ui.py
===================================================================
diff --git a/storypencil/__init__.py b/storypencil/__init__.py
index d1e6bd09..05b929f1 100644
--- a/storypencil/__init__.py
+++ b/storypencil/__init__.py
@@ -6,8 +6,8 @@
bl_info = {
"name": "Storypencil - Storyboard Tools",
"description": "Storyboard tools",
- "author": "Antonio Vazquez, Matias Mendiola, Daniel Martinez Lara, Rodrigo Blaas",
- "version": (1, 1, 1),
+ "author": "Antonio Vazquez, Matias Mendiola, Daniel Martinez Lara, Rodrigo Blaas, Samuel Bernou",
+ "version": (1, 1, 3),
"blender": (3, 3, 0),
"location": "",
"warning": "",
@@ -24,6 +24,7 @@ if "bpy" in locals():
importlib.reload(synchro)
importlib.reload(dopesheet_overlay)
importlib.reload(scene_tools)
+ importlib.reload(sound)
importlib.reload(render)
importlib.reload(ui)
else:
@@ -31,6 +32,7 @@ else:
from . import synchro
from . import dopesheet_overlay
from . import scene_tools
+ from . import sound
from . import render
from . import ui
@@ -62,17 +64,23 @@ classes = (
synchro.STORYPENCIL_OT_AddSecondaryWindowOperator,
synchro.STORYPENCIL_OT_Switch,
synchro.STORYPENCIL_OT_TabSwitch,
+ sound.STORYPENCIL_OT_duplicate_sound_in_edit_scene,
render.STORYPENCIL_OT_RenderAction,
ui.STORYPENCIL_PT_Settings,
+ ui.STORYPENCIL_PT_ModePanel,
ui.STORYPENCIL_PT_SettingsNew,
ui.STORYPENCIL_PT_RenderPanel,
ui.STORYPENCIL_PT_General,
- ui.STORYPENCIL_MT_extra_options,
)
def save_mode(self, context):
wm = context.window_manager
+ if context.scene.storypencil_mode == 'WINDOW':
+ context.scene.storypencil_use_new_window = True
+ else:
+ context.scene.storypencil_use_new_window = False
+
wm['storypencil_use_new_window'] = context.scene.storypencil_use_new_window
# Close all secondary windows
if context.scene.storypencil_use_new_window is False:
@@ -121,8 +129,7 @@ def register():
Scene.storypencil_use_new_window = BoolProperty(name="Open in new window",
description="Use secondary main window to edit scenes",
- default=False,
- update=save_mode)
+ default=False)
Scene.storypencil_main_workspace = PointerProperty(type=WorkSpace,
description="Main Workspace used for editing Storyboard")
@@ -159,8 +166,8 @@ def register():
Scene.storypencil_render_numbering = EnumProperty(name="Image Numbering",
items=(
- ('1', "Frame", "Use real frame number"),
- ('2', "Consecutive", "Use sequential numbering"),
+ ('FRAME', "Frame", "Use real frame number"),
+ ('CONSECUTIVE', "Consecutive", "Use sequential numbering"),
),
description="Defines how frame is named")
@@ -168,6 +175,24 @@ def register():
description="Create a separated folder for each strip",
default=True)
+ Scene.storypencil_copy_sounds = BoolProperty(name="Copy Sounds",
+ description="Copy automatically the sounds from VSE to edit scene",
+ default=True)
+
+ Scene.storypencil_mode = EnumProperty(name="Mode",
+ items=(
+ ('SWITCH', "Switch", "Use same window and switch scene"),
+ ('WINDOW', "New Window", "Use a new window for editing"),
+ ),
+ update=save_mode,
+ description="Defines how frame is named")
+ Scene.storypencil_selected_scn_only = BoolProperty(name='Selected Scene Only',
+ default=False,
+ description='Selected Scenes only')
+ Scene.storypencil_skip_sound_mute = BoolProperty(name='Ignore Muted Sound',
+ default=True,
+ description='Skip muted sound')
+
WindowManager.storypencil_settings = PointerProperty(
type=synchro.STORYPENCIL_PG_Settings,
name="Storypencil settings",
@@ -232,6 +257,10 @@ def unregister():
del Scene.storypencil_add_render_strip
del Scene.storypencil_render_numbering
del Scene.storypencil_add_render_byfolder
+ del Scene.storypencil_copy_sounds
+ del Scene.storypencil_mode
+ del Scene.storypencil_selected_scn_only
+ del Scene.storypencil_skip_sound_mute
if __name__ == '__main__':
register()
diff --git a/storypencil/dopesheet_overlay.py b/storypencil/dopesheet_overlay.py
index 2c00d8e9..26aeedfe 100644
--- a/storypencil/dopesheet_overlay.py
+++ b/storypencil/dopesheet_overlay.py
@@ -58,13 +58,18 @@ def get_scene_strip_in_out(strip):
def draw_callback_px(line_drawer: LineDrawer):
context = bpy.context
region = context.region
+ main_scene = context.scene.storypencil_main_scene
+ if main_scene is None:
+ return
+ use_win = main_scene.storypencil_use_new_window
wm = context.window_manager
if (
- not wm.storypencil_settings.active
+ (use_win and not wm.storypencil_settings.active)
or not wm.storypencil_settings.show_main_strip_range
- or not is_secondary_window(wm, window_id(context.window))
+ or (use_win and not is_secondary_window(wm, window_id(context.window)))
+ or (not use_win and context.scene == main_scene)
):
return
diff --git a/storypencil/render.py b/storypencil/render.py
index 357209df..31d07e2f 100644
--- a/storypencil/render.py
+++ b/storypencil/render.py
@@ -177,7 +177,7 @@ class STORYPENCIL_OT_RenderAction(Operator):
if keyframe > scene.frame_end:
break
# For frame name use only the number
- if scene.storypencil_render_numbering == '1':
+ if scene.storypencil_render_numbering == 'FRAME':
# Real
framename = strip_name + '.' + self.format_to4(key)
else:
diff --git a/storypencil/sound.py b/storypencil/sound.py
new file mode 100644
index 00000000..d3f43f1b
--- /dev/null
+++ b/storypencil/sound.py
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import bpy
+from typing import List, Sequence, Tuple
+from bpy.types import (
+ Operator,
+)
+
+
+def send_sound_strip(s, dest_scn):
+ '''recreate sound strip in another scene
+ :dest_scn: scene destination
+ :return: newly create sound strip
+ '''
+
+ if s.type != 'SOUND':
+ return
+ vse = dest_scn.sequence_editor
+ ns = vse.sequences.new_sound(name=s.name, filepath=s.sound.filepath, channel=s.channel, frame_start=int(s.frame_start))
+ ns.sound = s.sound # reget the same sound source
+
+ for attr in ('pitch',
+ 'pan',
+ 'show_waveform',
+ 'speed_factor',
+ 'volume',
+ 'mute'):
+ if hasattr(s, attr):
+ setattr(ns, attr, getattr(s, attr))
+ if ns.volume == 0:
+ ns.volume = 1
+ return ns
+
+def get_all_overlapping_sound_strip(scn_strip, skip_mute=True):
+ """return array of all sound strips for this strip"""
+ if scn_strip.type != 'SCENE':
+ return
+
+ src_scn = scn_strip.id_data
+ vse = src_scn.sequence_editor
+ overlapping_sounds = []
+ for s in vse.sequences:
+ if s.type != 'SOUND':
+ continue
+ if skip_mute and s.mute:
+ continue
+
+ if (s.frame_final_end - 1 < scn_strip.frame_final_start)\
+ or (s.frame_final_start - 1 > scn_strip.frame_final_end):
+ continue
+
+ overlapping_sounds.append(s)
+
+ return overlapping_sounds
+
+def delete_sounds(scene):
+ for st in reversed(scene.sequence_editor.sequences):
+ if st.type == 'SOUND':
+ scene.sequence_editor.sequences.remove(st)
+
+def get_scene_frame_from_sequencer_frame(scn_strip, sound) -> float:
+ """return frame in scene referential"""
+ return sound.frame_start - scn_strip.frame_start + scn_strip.scene.frame_start
+
+def send_sound_to_strip_scene(scn_strip, clear_sequencer=True, skip_mute=True):
+ """Add sounds to strip scene"""
+ if scn_strip.type != 'SCENE':
+ return
+ tgt_scene = scn_strip.scene
+
+ sounds = get_all_overlapping_sound_strip(scn_strip, skip_mute=skip_mute)
+ if not sounds:
+ return
+
+ # Clear sounds if exists in scene vse already
+ if clear_sequencer:
+ delete_sounds(tgt_scene)
+
+ print(f'Duplicating sounds in {tgt_scene.name}:')
+ for s in sounds:
+ new_start = get_scene_frame_from_sequencer_frame(scn_strip, s)
+ ns = send_sound_strip(s, tgt_scene)
+ if ns:
+ ns.frame_start = new_start
+ ns.frame_offset_start = s.frame_offset_start
+ ns.frame_final_duration = s.frame_final_duration
+
+ return sounds
+
+
+def dispatch_sounds_in_scenes(selected_scn_only=True, skip_mute=True):
+ """Main function to duplicate sounds in strip scenes"""
+ edit_scene = bpy.context.scene
+ edit = edit_scene.sequence_editor
+
+ ct = 0
+ for strip in edit.sequences:
+ if strip.type != 'SCENE':
+ continue
+
+ if selected_scn_only and not strip.select:
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list