VSE: Scene Selector & Scene Time Synchronization
Implements the proposed design (with some modifications) in #135058. ## Sequencer Scene This adds a new property called `sequencer_scene` to workspaces. This scene is used by the video sequence editors in the current workspace for their context. This is a first step towards "detaching" the VSE from the active scene in the window. Each sequencer timeline editor shows the sequencer scene that is being used. By default, when no sequencer scene is selected, the timeline and preview are empty. Pressing the "new" button will add a new scene and assign it to the sequencer scene for the current workspace. ## Contextual Playback Pressing `Space` (by default) for starting the animation playback is now contextual: depending on the context (where your mouse cursor is), the scene that is played back might be different. E.g. with a 3D Viewport and a Sequencer open, pressing "play" in the 3D Viewport will play the _active scene_ of the window, while pressing "play" in the sequencer will play the _sequencer scene_. ## Time & Scene Synchronization Additionally, this adds a toggle called "Sync Active Scene". With the property turned on, the active scene & scene time in the window will be synced with the time & scene of the current scene strip in the sequencer. Note that this is _not_ bi-directional. The sequencer can change the active scene and map time, but it's not possible the other way around since it one can have multiple strips using the same scene (+camera, and even time!). Currently this setting is exposed in the footer of the sequencer timeline as well as in the workspace settings. This allows for one of the core concepts that the story tools projects aims at: Working in a scene (e.g. in the 3D viewport) while also working with the edit (in the sequencer timeline). ## Some technical notes * Undoing while playback is running will now cancel playback. This is to avoid the timer, that points to the scene and viewlayer that are playing, to get de-synced after loading the memfile undo step. * When the sequencer scene is not the same as the active scene, we ensure it has a depsgraph. * Normally, when a `NC_SCENE` notifier points to a specific scene, the notifier is dropped if that scene doesn't match the active one in the window. We now also check that it doesn't match the sequencer scene in the active workspace. * When loading older files, we need to make sure that the active workspace in a window uses the active scene as the sequencer scene. This is to make sure that the file opens with the same sequences open. * Tool settings are stored per scene. To make sure the sequencer uses the tool settings for the sequencer scene, the "context.tool_settings" and `CTX_data_tool_settings` members are overridden in the sequence editors. Pull Request: https://projects.blender.org/blender/blender/pulls/140271
This commit is contained in:
@@ -36,6 +36,8 @@ class WORKSPACE_PT_main(WorkSpaceButtonsPanel, Panel):
|
||||
|
||||
layout.prop(workspace, "use_pin_scene")
|
||||
layout.prop(workspace, "object_mode", text="Mode")
|
||||
layout.prop(workspace, "sequencer_scene")
|
||||
layout.prop(workspace, "use_scene_time_sync")
|
||||
|
||||
|
||||
class WORKSPACE_PT_addons(WorkSpaceButtonsPanel, Panel):
|
||||
|
||||
@@ -179,24 +179,29 @@ class SEQUENCER_HT_header(Header):
|
||||
layout.separator_spacer()
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
sequencer_tool_settings = tool_settings.sequencer_tool_settings
|
||||
sequencer_tool_settings = tool_settings.sequencer_tool_settings if tool_settings else None
|
||||
|
||||
if st.view_type == 'PREVIEW':
|
||||
if st.view_type == 'SEQUENCER':
|
||||
row = layout.row(align=True)
|
||||
row.template_ID(context.workspace, "sequencer_scene", new="scene.new_sequencer_scene")
|
||||
|
||||
if sequencer_tool_settings and st.view_type == 'PREVIEW':
|
||||
layout.prop(sequencer_tool_settings, "pivot_point", text="", icon_only=True)
|
||||
|
||||
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
|
||||
if sequencer_tool_settings and st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(sequencer_tool_settings, "overlap_mode", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_snap_sequencer", text="")
|
||||
sub = row.row(align=True)
|
||||
sub.popover(panel="SEQUENCER_PT_snapping")
|
||||
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
|
||||
if tool_settings:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_snap_playhead", text="")
|
||||
row.prop(tool_settings, "use_snap_sequencer", text="")
|
||||
sub = row.row(align=True)
|
||||
sub.popover(panel="SEQUENCER_PT_playhead_snapping", text="")
|
||||
sub.popover(panel="SEQUENCER_PT_snapping")
|
||||
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_snap_playhead", text="")
|
||||
sub = row.row(align=True)
|
||||
sub.popover(panel="SEQUENCER_PT_playhead_snapping", text="")
|
||||
layout.separator_spacer()
|
||||
|
||||
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
|
||||
@@ -243,7 +248,7 @@ class SEQUENCER_MT_editor_menus(Menu):
|
||||
layout.menu("SEQUENCER_MT_view")
|
||||
layout.menu("SEQUENCER_MT_select")
|
||||
|
||||
if has_sequencer:
|
||||
if has_sequencer and context.sequencer_scene:
|
||||
if st.show_markers:
|
||||
layout.menu("SEQUENCER_MT_marker")
|
||||
layout.menu("SEQUENCER_MT_add")
|
||||
@@ -295,10 +300,10 @@ class SEQUENCER_PT_preview_overlay(Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
st = context.space_data
|
||||
return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
|
||||
return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'} and context.sequencer_scene
|
||||
|
||||
def draw(self, context):
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
st = context.space_data
|
||||
overlay_settings = st.preview_overlay
|
||||
layout = self.layout
|
||||
@@ -501,12 +506,12 @@ class SEQUENCER_MT_view(Menu):
|
||||
# See above (#32595)
|
||||
layout.operator_context = 'INVOKE_REGION_PREVIEW'
|
||||
layout.operator("sequencer.view_selected", text="Frame Selected")
|
||||
if is_sequencer_view:
|
||||
if is_sequencer_view and context.sequencer_scene:
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("sequencer.view_all")
|
||||
layout.operator(
|
||||
"anim.scene_range_frame",
|
||||
text="Frame Preview Range" if context.scene.use_preview_range else "Frame Scene Range",
|
||||
text="Frame Preview Range" if context.sequencer_scene.use_preview_range else "Frame Scene Range",
|
||||
)
|
||||
layout.operator("sequencer.view_frame")
|
||||
layout.prop(st, "use_clamp_view")
|
||||
@@ -602,8 +607,9 @@ class SEQUENCER_MT_select(Menu):
|
||||
st = context.space_data
|
||||
has_sequencer, has_preview = _space_view_types(st)
|
||||
is_retiming = (
|
||||
context.scene.sequence_editor is not None and
|
||||
context.scene.sequence_editor.selected_retiming_keys
|
||||
context.sequencer_scene and
|
||||
context.sequencer_scene.sequence_editor is not None and
|
||||
context.sequencer_scene.sequence_editor.selected_retiming_keys
|
||||
)
|
||||
if has_preview:
|
||||
layout.operator_context = 'INVOKE_REGION_PREVIEW'
|
||||
@@ -811,7 +817,7 @@ class SEQUENCER_MT_add_scene(Menu):
|
||||
layout.operator("sequencer.scene_strip_add", text="Scene...", icon='SCENE_DATA')
|
||||
elif bpy_data_scenes_len > 1:
|
||||
layout.label(text="Scenes", icon='NONE')
|
||||
scene = context.scene
|
||||
scene = context.sequencer_scene
|
||||
for sc_item in bpy.data.scenes:
|
||||
if sc_item == scene:
|
||||
continue
|
||||
@@ -1125,8 +1131,9 @@ class SEQUENCER_MT_strip_retiming(Menu):
|
||||
layout = self.layout
|
||||
|
||||
is_retiming = (
|
||||
context.scene.sequence_editor is not None and
|
||||
context.scene.sequence_editor.selected_retiming_keys
|
||||
context.sequencer_scene and
|
||||
context.sequencer_scene.sequence_editor is not None and
|
||||
context.sequencer_scene.sequence_editor.selected_retiming_keys
|
||||
)
|
||||
strip = context.active_strip
|
||||
|
||||
@@ -1440,7 +1447,7 @@ class SEQUENCER_MT_context_menu(Menu):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
if context.scene.sequence_editor.selected_retiming_keys:
|
||||
if context.sequencer_scene.sequence_editor.selected_retiming_keys:
|
||||
layout.operator("sequencer.retiming_add_freeze_frame_slide")
|
||||
layout.operator("sequencer.retiming_add_transition_slide")
|
||||
layout.separator()
|
||||
@@ -1451,7 +1458,7 @@ class SEQUENCER_MT_context_menu(Menu):
|
||||
layout.operator("sequencer.retiming_key_delete", text="Delete Retiming Keys")
|
||||
|
||||
def draw(self, context):
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
if ed.selected_retiming_keys:
|
||||
|
||||
self.draw_retime(context)
|
||||
@@ -1482,12 +1489,13 @@ class SEQUENCER_MT_pivot_pie(Menu):
|
||||
layout = self.layout
|
||||
pie = layout.menu_pie()
|
||||
|
||||
sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
|
||||
if context.tool_settings:
|
||||
sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
|
||||
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CENTER')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CURSOR')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='INDIVIDUAL_ORIGINS')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CENTER')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CURSOR')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='INDIVIDUAL_ORIGINS')
|
||||
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
|
||||
|
||||
|
||||
class SEQUENCER_MT_view_pie(Menu):
|
||||
@@ -1500,7 +1508,7 @@ class SEQUENCER_MT_view_pie(Menu):
|
||||
pie.operator("sequencer.view_all")
|
||||
pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
|
||||
pie.separator()
|
||||
if context.scene.use_preview_range:
|
||||
if context.sequencer_scene.use_preview_range:
|
||||
pie.operator("anim.scene_range_frame", text="Frame Preview Range")
|
||||
else:
|
||||
pie.operator("anim.scene_range_frame", text="Frame Scene Range")
|
||||
@@ -1989,7 +1997,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
scene = context.scene
|
||||
scene = context.sequencer_scene
|
||||
strip = context.active_strip
|
||||
strip_type = strip.type
|
||||
|
||||
@@ -2273,7 +2281,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_split = False
|
||||
layout.use_property_decorate = False
|
||||
|
||||
scene = context.scene
|
||||
scene = context.sequencer_scene
|
||||
frame_current = scene.frame_current
|
||||
strip = context.active_strip
|
||||
|
||||
@@ -2449,7 +2457,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
col = layout.column()
|
||||
|
||||
audio_channels = context.scene.render.ffmpeg.audio_channels
|
||||
audio_channels = context.sequencer_scene.render.ffmpeg.audio_channels
|
||||
pan_enabled = sound.use_mono and audio_channels != 'MONO'
|
||||
pan_text = "{:.2f}°".format(strip.pan * 90.0)
|
||||
|
||||
@@ -2631,14 +2639,14 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return cls.has_sequencer(context) and context.scene.sequence_editor
|
||||
return cls.has_sequencer(context) and context.sequencer_scene and context.sequencer_scene.sequence_editor
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
|
||||
col = layout.column()
|
||||
if ed:
|
||||
@@ -2657,7 +2665,7 @@ class SEQUENCER_PT_cache_view_settings(SequencerButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return cls.has_sequencer(context) and context.scene.sequence_editor
|
||||
return cls.has_sequencer(context) and context.sequencer_scene and context.sequencer_scene.sequence_editor
|
||||
|
||||
def draw_header(self, context):
|
||||
cache_settings = context.space_data.cache_overlay
|
||||
@@ -2670,7 +2678,7 @@ class SEQUENCER_PT_cache_view_settings(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_decorate = False
|
||||
|
||||
cache_settings = context.space_data.cache_overlay
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
layout.active = cache_settings.show_cache
|
||||
|
||||
col = layout.column(heading="Cache", align=True)
|
||||
@@ -2713,14 +2721,14 @@ class SEQUENCER_PT_proxy_settings(SequencerButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return cls.has_sequencer(context) and context.scene.sequence_editor
|
||||
return cls.has_sequencer(context) and context.sequencer_scene and context.sequencer_scene.sequence_editor
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
flow = layout.column_flow()
|
||||
flow.prop(ed, "proxy_storage", text="Storage")
|
||||
|
||||
@@ -2738,7 +2746,7 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not cls.has_sequencer(context) and context.scene.sequence_editor:
|
||||
if not cls.has_sequencer(context) or not context.sequencer_scene or not context.sequencer_scene.sequence_editor:
|
||||
return False
|
||||
|
||||
strip = context.active_strip
|
||||
@@ -2757,7 +2765,7 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
|
||||
strip = context.active_strip
|
||||
|
||||
@@ -2800,12 +2808,16 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_category = "View"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return SequencerButtonsPanel_Output.poll(context) and context.sequencer_scene
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
render = context.scene.render
|
||||
render = context.sequencer_scene.render
|
||||
|
||||
col = layout.column()
|
||||
col.prop(render, "sequencer_gl_preview", text="Shading")
|
||||
@@ -2867,12 +2879,12 @@ class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.scene.sequence_editor:
|
||||
if not context.sequencer_scene or not context.sequencer_scene.sequence_editor:
|
||||
return False
|
||||
return SequencerButtonsPanel_Output.poll(context)
|
||||
|
||||
def draw_header(self, context):
|
||||
scene = context.scene
|
||||
scene = context.sequencer_scene
|
||||
ed = scene.sequence_editor
|
||||
|
||||
self.layout.prop(ed, "show_overlay_frame", text="")
|
||||
@@ -2888,7 +2900,7 @@ class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
|
||||
layout.use_property_decorate = False
|
||||
|
||||
st = context.space_data
|
||||
scene = context.scene
|
||||
scene = context.sequencer_scene
|
||||
ed = scene.sequence_editor
|
||||
|
||||
layout.active = ed.show_overlay_frame
|
||||
@@ -2908,7 +2920,7 @@ class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel):
|
||||
def poll(cls, context):
|
||||
st = context.space_data
|
||||
is_preview = st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
|
||||
return is_preview and (st.display_mode == 'IMAGE')
|
||||
return is_preview and (st.display_mode == 'IMAGE') and context.sequencer_scene
|
||||
|
||||
def draw_header(self, context):
|
||||
overlay_settings = context.space_data.preview_overlay
|
||||
@@ -2918,7 +2930,7 @@ class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
overlay_settings = context.space_data.preview_overlay
|
||||
safe_data = context.scene.safe_areas
|
||||
safe_data = context.sequencer_scene.safe_areas
|
||||
|
||||
layout.active = overlay_settings.show_safe_areas
|
||||
|
||||
@@ -2935,6 +2947,10 @@ class SEQUENCER_PT_view_safe_areas_center_cut(SequencerButtonsPanel_Output, Pane
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_category = "View"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return SequencerButtonsPanel_Output.poll(context) and context.sequencer_scene
|
||||
|
||||
def draw_header(self, context):
|
||||
layout = self.layout
|
||||
overlay_settings = context.space_data.preview_overlay
|
||||
@@ -2944,7 +2960,7 @@ class SEQUENCER_PT_view_safe_areas_center_cut(SequencerButtonsPanel_Output, Pane
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
safe_data = context.scene.safe_areas
|
||||
safe_data = context.sequencer_scene.safe_areas
|
||||
overlay_settings = context.space_data.preview_overlay
|
||||
|
||||
layout.active = overlay_settings.show_safe_areas and overlay_settings.show_safe_center
|
||||
@@ -2963,7 +2979,7 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
|
||||
strip = context.active_strip
|
||||
ed = context.scene.sequence_editor
|
||||
ed = context.sequencer_scene.sequence_editor
|
||||
if strip.type == 'SOUND':
|
||||
sound = strip.sound
|
||||
else:
|
||||
@@ -3154,7 +3170,7 @@ class SEQUENCER_PT_preview_snapping(Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
st = context.space_data
|
||||
return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
|
||||
return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'} and context.tool_settings
|
||||
|
||||
def draw(self, context):
|
||||
tool_settings = context.tool_settings
|
||||
@@ -3179,7 +3195,7 @@ class SEQUENCER_PT_sequencer_snapping(Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
st = context.space_data
|
||||
return st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}
|
||||
return st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'} and context.tool_settings
|
||||
|
||||
def draw(self, context):
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
@@ -8,7 +8,10 @@ from bpy.app.translations import contexts as i18n_contexts
|
||||
|
||||
|
||||
def playback_controls(layout, context):
|
||||
scene = context.scene
|
||||
st = context.space_data
|
||||
is_sequencer = st.type == 'SEQUENCE_EDITOR' and st.view_type == 'SEQUENCER'
|
||||
|
||||
scene = context.scene if not is_sequencer else context.sequencer_scene
|
||||
tool_settings = context.tool_settings
|
||||
screen = context.screen
|
||||
|
||||
@@ -23,16 +26,20 @@ def playback_controls(layout, context):
|
||||
text_ctxt=i18n_contexts.id_windowmanager,
|
||||
)
|
||||
|
||||
if is_sequencer:
|
||||
layout.prop(context.workspace, "use_scene_time_sync", text="Sync Scene Time")
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_keyframe_insert_auto", text="", toggle=True)
|
||||
sub = row.row(align=True)
|
||||
sub.active = tool_settings.use_keyframe_insert_auto
|
||||
sub.popover(
|
||||
panel="TIME_PT_auto_keyframing",
|
||||
text="",
|
||||
)
|
||||
if tool_settings:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_keyframe_insert_auto", text="", toggle=True)
|
||||
sub = row.row(align=True)
|
||||
sub.active = tool_settings.use_keyframe_insert_auto
|
||||
sub.popover(
|
||||
panel="TIME_PT_auto_keyframing",
|
||||
text="",
|
||||
)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("screen.frame_jump", text="", icon='REW').end = False
|
||||
@@ -42,7 +49,7 @@ def playback_controls(layout, context):
|
||||
# if using JACK and A/V sync:
|
||||
# hide the play-reversed button
|
||||
# since JACK transport doesn't support reversed playback
|
||||
if scene.sync_mode == 'AUDIO_SYNC' and context.preferences.system.audio_device == 'JACK':
|
||||
if scene and scene.sync_mode == 'AUDIO_SYNC' and context.preferences.system.audio_device == 'JACK':
|
||||
row.scale_x = 2
|
||||
row.operator("screen.animation_play", text="", icon='PLAY')
|
||||
row.scale_x = 1
|
||||
@@ -59,24 +66,25 @@ def playback_controls(layout, context):
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
row = layout.row()
|
||||
if scene.show_subframe:
|
||||
row.scale_x = 1.15
|
||||
row.prop(scene, "frame_float", text="")
|
||||
else:
|
||||
row.scale_x = 0.95
|
||||
row.prop(scene, "frame_current", text="")
|
||||
if scene:
|
||||
row = layout.row()
|
||||
if scene.show_subframe:
|
||||
row.scale_x = 1.15
|
||||
row.prop(scene, "frame_float", text="")
|
||||
else:
|
||||
row.scale_x = 0.95
|
||||
row.prop(scene, "frame_current", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(scene, "use_preview_range", text="", toggle=True)
|
||||
sub = row.row(align=True)
|
||||
sub.scale_x = 0.8
|
||||
if not scene.use_preview_range:
|
||||
sub.prop(scene, "frame_start", text="Start")
|
||||
sub.prop(scene, "frame_end", text="End")
|
||||
else:
|
||||
sub.prop(scene, "frame_preview_start", text="Start")
|
||||
sub.prop(scene, "frame_preview_end", text="End")
|
||||
row = layout.row(align=True)
|
||||
row.prop(scene, "use_preview_range", text="", toggle=True)
|
||||
sub = row.row(align=True)
|
||||
sub.scale_x = 0.8
|
||||
if not scene.use_preview_range:
|
||||
sub.prop(scene, "frame_start", text="Start")
|
||||
sub.prop(scene, "frame_end", text="End")
|
||||
else:
|
||||
sub.prop(scene, "frame_preview_start", text="Start")
|
||||
sub.prop(scene, "frame_preview_end", text="End")
|
||||
|
||||
|
||||
class TIME_MT_editor_menus(Menu):
|
||||
@@ -206,7 +214,9 @@ class TIME_PT_playback(TimelinePanelButtons, Panel):
|
||||
layout.use_property_decorate = False
|
||||
|
||||
screen = context.screen
|
||||
scene = context.scene
|
||||
st = context.space_data
|
||||
is_sequencer = st.type == 'SEQUENCE_EDITOR' and st.view_type == 'SEQUENCER'
|
||||
scene = context.scene if not is_sequencer else context.sequencer_scene
|
||||
|
||||
layout.prop(scene, "sync_mode", text="Sync")
|
||||
col = layout.column(heading="Audio")
|
||||
@@ -246,7 +256,9 @@ class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
st = context.space_data
|
||||
is_sequencer = st.type == 'SEQUENCE_EDITOR' and st.view_type == 'SEQUENCER'
|
||||
scene = context.scene if not is_sequencer else context.sequencer_scene
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 62
|
||||
#define BLENDER_FILE_SUBVERSION 63
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
||||
@@ -1164,8 +1164,11 @@ Scene *CTX_data_sequencer_scene(const bContext *C)
|
||||
if (ctx_data_pointer_verify(C, "sequencer_scene", (void **)&scene)) {
|
||||
return scene;
|
||||
}
|
||||
/* TODO: Use sequencer scene. */
|
||||
return C->data.scene;
|
||||
WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (workspace) {
|
||||
return workspace->sequencer_scene;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ViewLayer *CTX_data_view_layer(const bContext *C)
|
||||
@@ -1371,8 +1374,12 @@ void CTX_data_scene_set(bContext *C, Scene *scene)
|
||||
|
||||
ToolSettings *CTX_data_tool_settings(const bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ToolSettings *toolsettings;
|
||||
if (ctx_data_pointer_verify(C, "tool_settings", (void **)&toolsettings)) {
|
||||
return toolsettings;
|
||||
}
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
if (scene) {
|
||||
return scene->toolsettings;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
WorkSpace *workspace = (WorkSpace *)id;
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, workspace->pin_scene, IDWALK_CB_NOP);
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, workspace->sequencer_scene, IDWALK_CB_NOP);
|
||||
|
||||
LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, layout->screen, IDWALK_CB_USER);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
@@ -59,6 +61,8 @@
|
||||
#include "SEQ_modifier.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "readfile.hh"
|
||||
|
||||
#include "versioning_common.hh"
|
||||
@@ -1676,6 +1680,16 @@ void do_versions_after_linking_500(FileData *fd, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 63)) {
|
||||
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
|
||||
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
WorkSpace *workspace = WM_window_get_active_workspace(win);
|
||||
workspace->sequencer_scene = scene;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
|
||||
ListBase *ED_scene_markers_get(Scene *scene, ScrArea *area)
|
||||
{
|
||||
if (!scene) {
|
||||
return nullptr;
|
||||
}
|
||||
/* local marker sets... */
|
||||
if (area) {
|
||||
if (area->spacetype == SPACE_ACTION) {
|
||||
@@ -577,7 +580,9 @@ static int markers_frame_sort(const void *a, const void *b)
|
||||
|
||||
void ED_markers_draw(const bContext *C, int flag)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
if (markers == nullptr || BLI_listbase_is_empty(markers)) {
|
||||
return;
|
||||
}
|
||||
@@ -688,7 +693,9 @@ void ED_markers_draw(const bContext *C, int flag)
|
||||
/* special poll() which checks if there are selected markers first */
|
||||
static bool ed_markers_poll_selected_markers(bContext *C)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
|
||||
if (!operator_markers_region_active(C)) {
|
||||
return false;
|
||||
@@ -705,7 +712,9 @@ static bool ed_markers_poll_selected_markers(bContext *C)
|
||||
|
||||
static bool ed_markers_poll_selected_no_locked_markers(bContext *C)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
|
||||
if (!operator_markers_region_active(C)) {
|
||||
@@ -729,7 +738,9 @@ static bool ed_markers_poll_selected_no_locked_markers(bContext *C)
|
||||
/* special poll() which checks if there are any markers at all first */
|
||||
static bool ed_markers_poll_markers_exist(bContext *C)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
|
||||
if (ts->lock_markers || !operator_markers_region_active(C)) {
|
||||
@@ -765,14 +776,17 @@ static bool ed_markers_poll_markers_exist_visible(bContext *C)
|
||||
/* add TimeMarker at current frame */
|
||||
static wmOperatorStatus ed_marker_add_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
TimeMarker *marker;
|
||||
int frame = CTX_data_scene(C)->r.cfra;
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
|
||||
if (markers == nullptr) {
|
||||
if (markers == nullptr || scene == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const int frame = scene->r.cfra;
|
||||
|
||||
/* prefer not having 2 markers at the same place,
|
||||
* though the user can move them to overlap once added */
|
||||
LISTBASE_FOREACH (TimeMarker *, marker, markers) {
|
||||
@@ -786,7 +800,7 @@ static wmOperatorStatus ed_marker_add_exec(bContext *C, wmOperator * /*op*/)
|
||||
marker->flag &= ~SELECT;
|
||||
}
|
||||
|
||||
marker = MEM_callocN<TimeMarker>("TimeMarker");
|
||||
TimeMarker *marker = MEM_callocN<TimeMarker>("TimeMarker");
|
||||
marker->flag = SELECT;
|
||||
marker->frame = frame;
|
||||
SNPRINTF_UTF8(marker->name, "F_%02d", frame);
|
||||
@@ -868,7 +882,8 @@ static bool ed_marker_move_use_time(MarkerMove *mm)
|
||||
|
||||
static void ed_marker_move_update_header(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
MarkerMove *mm = static_cast<MarkerMove *>(op->customdata);
|
||||
TimeMarker *marker, *selmarker = nullptr;
|
||||
const int ofs = RNA_int_get(op->ptr, "frames");
|
||||
@@ -916,8 +931,10 @@ static void ed_marker_move_update_header(bContext *C, wmOperator *op)
|
||||
/* return 0 if not OK */
|
||||
static bool ed_marker_move_init(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
MarkerMove *mm;
|
||||
TimeMarker *marker;
|
||||
int a, totmark;
|
||||
@@ -982,7 +999,9 @@ static wmOperatorStatus ed_marker_move_invoke(bContext *C, wmOperator *op, const
|
||||
if (tweak) {
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
if (!region_position_is_over_marker(v2d, markers, event->xy[0] - region->winrct.xmin)) {
|
||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
@@ -1014,7 +1033,8 @@ static wmOperatorStatus ed_marker_move_invoke(bContext *C, wmOperator *op, const
|
||||
static void ed_marker_move_apply(bContext *C, wmOperator *op)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
Object *camera = scene->camera;
|
||||
MarkerMove *mm = static_cast<MarkerMove *>(op->customdata);
|
||||
TimeMarker *marker;
|
||||
@@ -1052,7 +1072,8 @@ static void ed_marker_move_cancel(bContext *C, wmOperator *op)
|
||||
|
||||
static wmOperatorStatus ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
MarkerMove *mm = static_cast<MarkerMove *>(op->customdata);
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const bool has_numinput = hasNumInput(&mm->num);
|
||||
@@ -1204,7 +1225,9 @@ static void MARKER_OT_move(wmOperatorType *ot)
|
||||
/* duplicate selected TimeMarkers */
|
||||
static void ed_marker_duplicate_apply(bContext *C)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
if (markers == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -1293,7 +1316,8 @@ static void select_marker_camera_switch(
|
||||
using namespace blender::ed;
|
||||
if (camera) {
|
||||
BLI_assert(CTX_data_mode_enum(C) == CTX_MODE_OBJECT);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Base *base;
|
||||
int sel = 0;
|
||||
@@ -1344,7 +1368,9 @@ static wmOperatorStatus ed_marker_select(bContext *C,
|
||||
* The variables (`sel_op` & `deselect_all`) have been included so marker
|
||||
* selection can use identical checks to dope-sheet selection. */
|
||||
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
wmOperatorStatus ret_val = OPERATOR_FINISHED;
|
||||
TimeMarker *nearest_marker = region_position_is_over_marker(v2d, markers, mval[0]);
|
||||
@@ -1496,7 +1522,9 @@ static wmOperatorStatus ed_marker_box_select_invoke(bContext *C,
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
bool over_marker = region_position_is_over_marker(
|
||||
v2d, markers, event->xy[0] - region->winrct.xmin) != nullptr;
|
||||
|
||||
@@ -1511,7 +1539,9 @@ static wmOperatorStatus ed_marker_box_select_invoke(bContext *C,
|
||||
static wmOperatorStatus ed_marker_box_select_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
rctf rect;
|
||||
|
||||
WM_operator_properties_border_to_rctf(op, &rect);
|
||||
@@ -1574,7 +1604,9 @@ static void MARKER_OT_select_box(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus ed_marker_select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
if (markers == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -1696,7 +1728,9 @@ static void MARKER_OT_select_leftright(wmOperatorType *ot)
|
||||
static wmOperatorStatus ed_marker_delete_exec(bContext *C, wmOperator * /*op*/)
|
||||
|
||||
{
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
TimeMarker *marker, *nmarker;
|
||||
bool changed = false;
|
||||
|
||||
@@ -1767,7 +1801,10 @@ static void MARKER_OT_delete(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus ed_marker_rename_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
TimeMarker *marker = ED_markers_get_first_selected(markers);
|
||||
|
||||
if (marker) {
|
||||
RNA_string_get(op->ptr, "name", marker->name);
|
||||
@@ -1783,8 +1820,11 @@ static wmOperatorStatus ed_marker_rename_exec(bContext *C, wmOperator *op)
|
||||
|
||||
static wmOperatorStatus ed_marker_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
/* must initialize the marker name first if there is a marker selected */
|
||||
TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
|
||||
TimeMarker *marker = ED_markers_get_first_selected(markers);
|
||||
if (marker) {
|
||||
RNA_string_set(op->ptr, "name", marker->name);
|
||||
}
|
||||
@@ -1829,7 +1869,9 @@ static void MARKER_OT_rename(wmOperatorType *ot)
|
||||
static wmOperatorStatus ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
Scene *scene_to = static_cast<Scene *>(
|
||||
BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
|
||||
TimeMarker *marker_new;
|
||||
@@ -1895,9 +1937,14 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot)
|
||||
static wmOperatorStatus ed_marker_camera_bind_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
ListBase *markers = is_sequencer ? ED_sequencer_context_get_markers(C) :
|
||||
ED_context_get_markers(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
ListBase *markers = ED_context_get_markers(C);
|
||||
TimeMarker *marker;
|
||||
|
||||
/* Don't do anything if we don't have a camera selected */
|
||||
|
||||
@@ -527,7 +527,11 @@ static float apply_frame_snap(bContext *C, FrameChangeModalData &op_data, const
|
||||
/* Set the new frame number */
|
||||
static void change_frame_apply(bContext *C, wmOperator *op, const bool always_update)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
float frame = RNA_float_get(op->ptr, "frame");
|
||||
bool do_snap = RNA_boolean_get(op->ptr, "snap");
|
||||
|
||||
@@ -550,6 +554,8 @@ static void change_frame_apply(bContext *C, wmOperator *op, const bool always_up
|
||||
}
|
||||
FRAMENUMBER_MIN_CLAMP(scene->r.cfra);
|
||||
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
/* do updates */
|
||||
const bool frame_changed = (old_frame != scene->r.cfra) || (old_subframe != scene->r.subframe);
|
||||
if (frame_changed || always_update) {
|
||||
@@ -574,7 +580,8 @@ static wmOperatorStatus change_frame_exec(bContext *C, wmOperator *op)
|
||||
static float frame_from_event(bContext *C, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
float frame;
|
||||
|
||||
/* convert from region coordinates to View2D 'tot' space */
|
||||
@@ -625,7 +632,7 @@ static bool use_playhead_snapping(bContext *C)
|
||||
|
||||
static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!blender::seq::editing_get(scene)) {
|
||||
return false;
|
||||
}
|
||||
@@ -859,7 +866,8 @@ static bool anim_set_end_frames_poll(bContext *C)
|
||||
|
||||
static wmOperatorStatus anim_set_sfra_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
int frame;
|
||||
|
||||
if (scene == nullptr) {
|
||||
@@ -914,7 +922,8 @@ static void ANIM_OT_start_frame_set(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus anim_set_efra_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
int frame;
|
||||
|
||||
if (scene == nullptr) {
|
||||
@@ -975,7 +984,11 @@ static void ANIM_OT_end_frame_set(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus previewrange_define_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
float sfra, efra;
|
||||
rcti rect;
|
||||
@@ -1039,7 +1052,8 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus previewrange_clear_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
ScrArea *curarea = CTX_wm_area(C);
|
||||
|
||||
/* sanity checks */
|
||||
@@ -1134,10 +1148,13 @@ static void ANIM_OT_debug_channel_list(wmOperatorType *ot)
|
||||
|
||||
static wmOperatorStatus scene_range_frame_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
const Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
BLI_assert(region);
|
||||
BLI_assert(scene);
|
||||
|
||||
View2D &v2d = region->v2d;
|
||||
v2d.cur.xmin = PSFRA;
|
||||
|
||||
@@ -342,7 +342,8 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen);
|
||||
* redraws: uses defines from `stime->redraws`
|
||||
* \param enable: 1 - forward on, -1 - backwards on, 0 - off.
|
||||
*/
|
||||
void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable);
|
||||
void ED_screen_animation_timer(
|
||||
bContext *C, Scene *scene, ViewLayer *view_layer, int redraws, int sync, int enable);
|
||||
void ED_screen_animation_timer_update(bScreen *screen, int redraws);
|
||||
void ED_screen_restore_temp_type(bContext *C, ScrArea *area);
|
||||
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type);
|
||||
@@ -547,6 +548,9 @@ bool ED_operator_regionactive(bContext *C);
|
||||
|
||||
bool ED_operator_scene(bContext *C);
|
||||
bool ED_operator_scene_editable(bContext *C);
|
||||
bool ED_operator_sequencer_scene(bContext *C);
|
||||
bool ED_operator_sequencer_scene_editable(bContext *C);
|
||||
|
||||
bool ED_operator_objectmode(bContext *C);
|
||||
/**
|
||||
* Same as #ED_operator_objectmode() but additionally sets a "disabled hint". That is, a message
|
||||
|
||||
@@ -20,6 +20,13 @@ struct ARegion;
|
||||
struct ScreenAnimData {
|
||||
/** Do not read from this, only for comparing if region exists. */
|
||||
ARegion *region;
|
||||
|
||||
/* The Scene and the View Layer that the animation timer is playing. */
|
||||
Scene *scene;
|
||||
ViewLayer *view_layer;
|
||||
/* For sequencer scenes, account for scene syncing during playback. */
|
||||
bool do_scene_syncing;
|
||||
|
||||
short redraws;
|
||||
/** Flags for playback */
|
||||
short flag;
|
||||
|
||||
@@ -81,4 +81,7 @@ StripSelection pick_strip_and_handle(const struct Scene *scene,
|
||||
bool can_select_handle(const Scene *scene, const Strip *strip, const View2D *v2d);
|
||||
bool handle_is_selected(const Strip *strip, eStripHandle handle);
|
||||
|
||||
bool is_scene_time_sync_needed(const bContext &C);
|
||||
void sync_active_scene_and_time_with_scene_strip(bContext &C);
|
||||
|
||||
} // namespace blender::ed::vse
|
||||
|
||||
@@ -92,7 +92,8 @@ static float view2d_major_step_y__continuous(const View2D *v2d)
|
||||
|
||||
static float view2d_major_step_x__time(const View2D *v2d, const Scene *scene)
|
||||
{
|
||||
const double fps = scene->frames_per_second();
|
||||
/* If we don't have a scene available, pick an arbitrary framerate to show *something*. */
|
||||
const double fps = scene ? scene->frames_per_second() : 25;
|
||||
|
||||
blender::Vector<float, 32> possible_distances;
|
||||
|
||||
|
||||
@@ -710,6 +710,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
||||
const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
|
||||
|
||||
Scene *scene = !is_sequencer ? CTX_data_scene(C) : CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
ScrArea *prev_area = CTX_wm_area(C);
|
||||
ARegion *prev_region = CTX_wm_region(C);
|
||||
GPUOffScreen *ofs;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "SEQ_relations.hh"
|
||||
#include "SEQ_select.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
@@ -112,6 +113,14 @@ bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene)
|
||||
}
|
||||
}
|
||||
|
||||
/* Update scenes used by the sequencer. */
|
||||
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
||||
if (workspace->sequencer_scene == scene) {
|
||||
workspace->sequencer_scene = scene_new;
|
||||
WM_event_add_notifier(C, NC_WINDOW, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_id_delete(bmain, scene);
|
||||
|
||||
return true;
|
||||
@@ -351,6 +360,48 @@ static void SCENE_OT_new_sequencer(wmOperatorType *ot)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name New Sequencer Scene Operator
|
||||
* \{ */
|
||||
|
||||
static wmOperatorStatus new_sequencer_scene_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene_old = WM_window_get_active_scene(win);
|
||||
int type = RNA_enum_get(op->ptr, "type");
|
||||
|
||||
Scene *new_scene = scene_add(bmain, scene_old, eSceneCopyMethod(type));
|
||||
blender::seq::editing_ensure(new_scene);
|
||||
|
||||
WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
workspace->sequencer_scene = new_scene;
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void SCENE_OT_new_sequencer_scene(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "New Sequencer Scene";
|
||||
ot->description = "Add new scene to be used by the sequencer";
|
||||
ot->idname = "SCENE_OT_new_sequencer_scene";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->exec = new_sequencer_scene_exec;
|
||||
ot->invoke = WM_menu_invoke;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
ot->prop = RNA_def_enum(ot->srna, "type", scene_new_items, SCE_COPY_NEW, "Type", "");
|
||||
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_SCENE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Scene Delete Operator
|
||||
* \{ */
|
||||
@@ -444,6 +495,7 @@ void ED_operatortypes_scene()
|
||||
WM_operatortype_append(SCENE_OT_new);
|
||||
WM_operatortype_append(SCENE_OT_delete);
|
||||
WM_operatortype_append(SCENE_OT_new_sequencer);
|
||||
WM_operatortype_append(SCENE_OT_new_sequencer_scene);
|
||||
|
||||
WM_operatortype_append(SCENE_OT_drop_scene_asset);
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ const char *screen_context_dir[] = {
|
||||
"strips",
|
||||
"selected_strips",
|
||||
"selected_editable_strips",
|
||||
"sequencer_scene",
|
||||
nullptr,
|
||||
};
|
||||
|
||||
@@ -673,8 +674,10 @@ static eContextResult screen_ctx_pose_object(const bContext *C, bContextDataResu
|
||||
static eContextResult screen_ctx_active_sequence_strip(const bContext *C,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Strip *strip = blender::seq::select_active_get(scene);
|
||||
if (strip) {
|
||||
CTX_data_pointer_set(result, &scene->id, &RNA_Strip, strip);
|
||||
@@ -684,8 +687,10 @@ static eContextResult screen_ctx_active_sequence_strip(const bContext *C,
|
||||
}
|
||||
static eContextResult screen_ctx_sequences(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed) {
|
||||
LISTBASE_FOREACH (Strip *, strip, ed->current_strips()) {
|
||||
@@ -698,8 +703,10 @@ static eContextResult screen_ctx_sequences(const bContext *C, bContextDataResult
|
||||
}
|
||||
static eContextResult screen_ctx_selected_sequences(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed) {
|
||||
LISTBASE_FOREACH (Strip *, strip, ed->current_strips()) {
|
||||
@@ -715,8 +722,10 @@ static eContextResult screen_ctx_selected_sequences(const bContext *C, bContextD
|
||||
static eContextResult screen_ctx_selected_editable_sequences(const bContext *C,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed == nullptr) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
@@ -1138,8 +1147,10 @@ static eContextResult screen_ctx_ui_list(const bContext *C, bContextDataResult *
|
||||
|
||||
static eContextResult screen_ctx_active_strip(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Strip *strip = blender::seq::select_active_get(scene);
|
||||
if (strip) {
|
||||
CTX_data_pointer_set(result, &scene->id, &RNA_Strip, strip);
|
||||
@@ -1149,8 +1160,10 @@ static eContextResult screen_ctx_active_strip(const bContext *C, bContextDataRes
|
||||
}
|
||||
static eContextResult screen_ctx_strips(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed) {
|
||||
LISTBASE_FOREACH (Strip *, strip, ed->current_strips()) {
|
||||
@@ -1163,8 +1176,10 @@ static eContextResult screen_ctx_strips(const bContext *C, bContextDataResult *r
|
||||
}
|
||||
static eContextResult screen_ctx_selected_strips(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed) {
|
||||
LISTBASE_FOREACH (Strip *, strip, ed->current_strips()) {
|
||||
@@ -1180,8 +1195,10 @@ static eContextResult screen_ctx_selected_strips(const bContext *C, bContextData
|
||||
static eContextResult screen_ctx_selected_editable_strips(const bContext *C,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
Editing *ed = blender::seq::editing_get(scene);
|
||||
if (ed == nullptr) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
@@ -1196,6 +1213,15 @@ static eContextResult screen_ctx_selected_editable_strips(const bContext *C,
|
||||
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
static eContextResult screen_ctx_sequencer_scene(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (scene) {
|
||||
CTX_data_id_pointer_set(result, &scene->id);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
|
||||
/* Registry of context callback functions. */
|
||||
|
||||
@@ -1263,6 +1289,7 @@ ensure_ed_screen_context_functions()
|
||||
map.add("strips", screen_ctx_strips);
|
||||
map.add("selected_strips", screen_ctx_selected_strips);
|
||||
map.add("selected_editable_strips", screen_ctx_selected_editable_strips);
|
||||
map.add("sequencer_scene", screen_ctx_sequencer_scene);
|
||||
return map;
|
||||
}();
|
||||
return screen_context_functions;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "ED_node.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_screen_types.hh"
|
||||
#include "ED_sequencer.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
@@ -1948,12 +1949,12 @@ ScrArea *ED_screen_temp_space_open(bContext *C,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
|
||||
void ED_screen_animation_timer(
|
||||
bContext *C, Scene *scene, ViewLayer *view_layer, int redraws, int sync, int enable)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
bScreen *stopscreen = ED_screen_animation_playing(wm);
|
||||
|
||||
if (stopscreen) {
|
||||
@@ -1967,6 +1968,11 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
|
||||
screen->animtimer = WM_event_timer_add(wm, win, TIMER0, (1.0 / scene->frames_per_second()));
|
||||
|
||||
sad->region = CTX_wm_region(C);
|
||||
sad->scene = scene;
|
||||
sad->view_layer = view_layer;
|
||||
|
||||
sad->do_scene_syncing = blender::ed::vse::is_scene_time_sync_needed(*C);
|
||||
|
||||
sad->sfra = scene->r.cfra;
|
||||
/* Make sure that were are inside the scene or preview frame range. */
|
||||
CLAMP(scene->r.cfra, PSFRA, PEFRA);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_library.hh"
|
||||
#include "BKE_main.hh"
|
||||
@@ -183,6 +184,15 @@ bool ED_operator_scene(bContext *C)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ED_operator_sequencer_scene(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (scene == nullptr || !BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_operator_scene_editable(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -192,6 +202,15 @@ bool ED_operator_scene_editable(bContext *C)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_operator_sequencer_scene_editable(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (scene == nullptr || !BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_operator_objectmode(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -380,12 +399,12 @@ bool ED_operator_graphedit_active(bContext *C)
|
||||
|
||||
bool ED_operator_sequencer_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_SEQ);
|
||||
return ed_spacetype_test(C, SPACE_SEQ) && CTX_data_sequencer_scene(C) != nullptr;
|
||||
}
|
||||
|
||||
bool ED_operator_sequencer_active_editable(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_SEQ) && ED_operator_scene_editable(C);
|
||||
return ed_spacetype_test(C, SPACE_SEQ) && ED_operator_sequencer_scene_editable(C);
|
||||
}
|
||||
|
||||
bool ED_operator_image_active(bContext *C)
|
||||
@@ -3259,7 +3278,11 @@ void ED_areas_do_frame_follow(bContext *C, bool center_view)
|
||||
/* function to be called outside UI context, or for redo */
|
||||
static wmOperatorStatus frame_offset_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int delta = RNA_int_get(op->ptr, "delta");
|
||||
|
||||
@@ -3274,6 +3297,8 @@ static wmOperatorStatus frame_offset_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_areas_do_frame_follow(C, false);
|
||||
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
|
||||
@@ -3306,7 +3331,11 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot)
|
||||
/* function to be called outside UI context, or for redo */
|
||||
static wmOperatorStatus frame_jump_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
|
||||
|
||||
/* Don't change scene->r.cfra directly if animtimer is running as this can cause
|
||||
@@ -3335,6 +3364,8 @@ static wmOperatorStatus frame_jump_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_areas_do_frame_follow(C, true);
|
||||
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
|
||||
@@ -3547,7 +3578,11 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||
/* function to be called outside UI context, or for redo */
|
||||
static wmOperatorStatus marker_jump_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
int closest = scene->r.cfra;
|
||||
const bool next = RNA_boolean_get(op->ptr, "next");
|
||||
bool found = false;
|
||||
@@ -3579,6 +3614,8 @@ static wmOperatorStatus marker_jump_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_areas_do_frame_follow(C, true);
|
||||
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
|
||||
@@ -5613,19 +5650,17 @@ static wmOperatorStatus screen_animation_step_invoke(bContext *C,
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
|
||||
#ifdef PROFILE_AUDIO_SYNC
|
||||
static int old_frame = 0;
|
||||
int newfra_int;
|
||||
#endif
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
|
||||
ScreenAnimData *sad = static_cast<ScreenAnimData *>(wt->customdata);
|
||||
Scene *scene = sad->scene;
|
||||
ViewLayer *view_layer = sad->view_layer;
|
||||
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer);
|
||||
Scene *scene_eval = (depsgraph != nullptr) ? DEG_get_evaluated_scene(depsgraph) : nullptr;
|
||||
ScreenAnimData *sad = static_cast<ScreenAnimData *>(wt->customdata);
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
int sync;
|
||||
double time;
|
||||
@@ -5758,6 +5793,8 @@ static wmOperatorStatus screen_animation_step_invoke(bContext *C,
|
||||
#endif
|
||||
}
|
||||
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
/* Since we follow draw-flags, we can't send notifier but tag regions ourselves. */
|
||||
if (depsgraph != nullptr) {
|
||||
ED_update_for_newframe(bmain, depsgraph);
|
||||
@@ -5894,17 +5931,41 @@ bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
|
||||
wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
|
||||
if (!scene) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ViewLayer *view_layer = is_sequencer ? BKE_view_layer_default_render(scene) :
|
||||
CTX_data_view_layer(C);
|
||||
Depsgraph *depsgraph = is_sequencer ? BKE_scene_ensure_depsgraph(bmain, scene, view_layer) :
|
||||
CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
Main *bmain = DEG_get_bmain(depsgraph);
|
||||
|
||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||
/* stop playback now */
|
||||
ED_screen_animation_timer(C, 0, 0, 0);
|
||||
ED_screen_animation_timer(C, scene, view_layer, 0, 0, 0);
|
||||
ED_scene_fps_average_clear(scene);
|
||||
BKE_sound_stop_scene(scene_eval);
|
||||
|
||||
if (is_sequencer) {
|
||||
/* Stop sound for active scene in window. */
|
||||
BKE_sound_stop_scene(DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C)));
|
||||
}
|
||||
else {
|
||||
/* Stop sound for sequencer scene. */
|
||||
WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (workspace->sequencer_scene) {
|
||||
Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(
|
||||
bmain,
|
||||
workspace->sequencer_scene,
|
||||
BKE_view_layer_default_render(workspace->sequencer_scene));
|
||||
Scene *seq_scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
BKE_sound_stop_scene(seq_scene_eval);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_callback_exec_id_depsgraph(
|
||||
bmain, &scene->id, depsgraph, BKE_CB_EVT_ANIMATION_PLAYBACK_POST);
|
||||
|
||||
@@ -5923,7 +5984,7 @@ wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode)
|
||||
BKE_sound_play_scene(scene_eval);
|
||||
}
|
||||
|
||||
ED_screen_animation_timer(C, screen->redraws_flag, sync, mode);
|
||||
ED_screen_animation_timer(C, scene, view_layer, screen->redraws_flag, sync, mode);
|
||||
ED_scene_fps_average_clear(scene);
|
||||
|
||||
if (screen->animtimer) {
|
||||
|
||||
@@ -244,6 +244,7 @@ WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindo
|
||||
|
||||
workspace_new->flags = workspace_old->flags;
|
||||
workspace_new->pin_scene = workspace_old->pin_scene;
|
||||
workspace_new->sequencer_scene = workspace_old->sequencer_scene;
|
||||
workspace_new->object_mode = workspace_old->object_mode;
|
||||
workspace_new->order = workspace_old->order;
|
||||
BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids);
|
||||
|
||||
@@ -691,7 +691,7 @@ void SEQUENCER_OT_scene_strip_add(wmOperatorType *ot)
|
||||
|
||||
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_MOVE);
|
||||
prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
|
||||
RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
|
||||
RNA_def_enum_funcs(prop, RNA_scene_without_sequencer_scene_itemf);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
|
||||
ot->prop = prop;
|
||||
}
|
||||
|
||||
@@ -327,8 +327,12 @@ void channel_draw_context_init(const bContext *C,
|
||||
void draw_channels(const bContext *C, ARegion *region)
|
||||
{
|
||||
draw_background();
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
Editing *ed = seq::editing_get(CTX_data_sequencer_scene(C));
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (ed == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "ED_numinput.hh"
|
||||
#include "ED_scene.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_screen_types.hh"
|
||||
#include "ED_sequencer.hh"
|
||||
|
||||
#include "UI_interface_layout.hh"
|
||||
@@ -160,7 +161,11 @@ bool has_playback_animation(const Scene *scene)
|
||||
|
||||
bool sequencer_edit_poll(bContext *C)
|
||||
{
|
||||
return (seq::editing_get(CTX_data_sequencer_scene(C)) != nullptr);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
return (seq::editing_get(scene) != nullptr);
|
||||
}
|
||||
|
||||
bool sequencer_edit_with_channel_region_poll(bContext *C)
|
||||
@@ -191,7 +196,7 @@ bool sequencer_strip_poll(bContext *C)
|
||||
bool sequencer_strip_editable_poll(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!ID_IS_EDITABLE(&scene->id)) {
|
||||
if (!scene || !ID_IS_EDITABLE(&scene->id)) {
|
||||
return false;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
@@ -200,19 +205,28 @@ bool sequencer_strip_editable_poll(bContext *C)
|
||||
|
||||
bool sequencer_strip_has_path_poll(bContext *C)
|
||||
{
|
||||
Editing *ed;
|
||||
Strip *strip;
|
||||
return (((ed = seq::editing_get(CTX_data_sequencer_scene(C))) != nullptr) &&
|
||||
((strip = ed->act_strip) != nullptr) && STRIP_HAS_PATH(strip));
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (!ed) {
|
||||
return false;
|
||||
}
|
||||
Strip *strip = ed->act_strip;
|
||||
if (!strip) {
|
||||
return false;
|
||||
}
|
||||
return STRIP_HAS_PATH(strip);
|
||||
}
|
||||
|
||||
bool sequencer_view_has_preview_poll(bContext *C)
|
||||
{
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
if (sseq == nullptr) {
|
||||
if (!sequencer_edit_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
if (seq::editing_get(CTX_data_sequencer_scene(C)) == nullptr) {
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
if (sseq == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!(ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
|
||||
@@ -230,11 +244,16 @@ bool sequencer_view_has_preview_poll(bContext *C)
|
||||
|
||||
bool sequencer_view_preview_only_poll(const bContext *C)
|
||||
{
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
if (sseq == nullptr) {
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
if (seq::editing_get(CTX_data_sequencer_scene(C)) == nullptr) {
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (!ed) {
|
||||
return false;
|
||||
}
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
if (sseq == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!(ELEM(sseq->view, SEQ_VIEW_PREVIEW) && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))) {
|
||||
@@ -266,6 +285,9 @@ bool sequencer_view_strips_poll(bContext *C)
|
||||
|
||||
static bool sequencer_effect_poll(bContext *C)
|
||||
{
|
||||
if (!sequencer_edit_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
|
||||
@@ -281,6 +303,9 @@ static bool sequencer_effect_poll(bContext *C)
|
||||
|
||||
static bool sequencer_swap_inputs_poll(bContext *C)
|
||||
{
|
||||
if (!sequencer_edit_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
Strip *active_strip = seq::select_active_get(scene);
|
||||
|
||||
@@ -293,6 +318,142 @@ static bool sequencer_swap_inputs_poll(bContext *C)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Scene syncing with current scene strip
|
||||
* \{ */
|
||||
|
||||
bool is_scene_time_sync_needed(const bContext &C)
|
||||
{
|
||||
WorkSpace *workspace = CTX_wm_workspace(&C);
|
||||
if (!workspace || !workspace->sequencer_scene) {
|
||||
return false;
|
||||
}
|
||||
if ((workspace->flags & WORKSPACE_SYNC_SCENE_TIME) == 0) {
|
||||
return false;
|
||||
}
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(&C);
|
||||
if (!sseq) {
|
||||
/* We only want to start syncing the time when we're in a sequence editor.
|
||||
* Changing time in any other editor should just affect the active scene. */
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Scene *get_sequencer_scene_for_time_sync(const bContext &C)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(&C);
|
||||
bScreen *screen = ED_screen_animation_playing(wm);
|
||||
if (screen && screen->animtimer) {
|
||||
wmTimer *wt = screen->animtimer;
|
||||
ScreenAnimData *sad = static_cast<ScreenAnimData *>(wt->customdata);
|
||||
if (sad->do_scene_syncing) {
|
||||
return sad->scene;
|
||||
}
|
||||
/* If we're playing a scene that's not a sequence scene, don't try and sync. */
|
||||
return nullptr;
|
||||
}
|
||||
if (is_scene_time_sync_needed(C)) {
|
||||
return CTX_data_sequencer_scene(&C);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void sync_active_scene_and_time_with_scene_strip(bContext &C)
|
||||
{
|
||||
using namespace blender;
|
||||
Scene *sequence_scene = get_sequencer_scene_for_time_sync(C);
|
||||
if (!sequence_scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
wmWindow *win = CTX_wm_window(&C);
|
||||
Scene *active_scene = WM_window_get_active_scene(win);
|
||||
|
||||
Editing *ed = seq::editing_get(sequence_scene);
|
||||
if (!ed) {
|
||||
return;
|
||||
}
|
||||
ListBase *seqbase = seq::active_seqbase_get(ed);
|
||||
const ListBase *channels = seq::channels_displayed_get(ed);
|
||||
VectorSet<Strip *> query_strips = seq::query_strips_recursive_at_frame(
|
||||
sequence_scene, seqbase, sequence_scene->r.cfra);
|
||||
/* Ignore effect strips, sound strips and muted strips. */
|
||||
query_strips.remove_if([&](const Strip *strip) {
|
||||
return (strip->type & STRIP_TYPE_EFFECT) != 0 || strip->type == STRIP_TYPE_SOUND_RAM ||
|
||||
seq::render_is_muted(channels, strip);
|
||||
});
|
||||
Vector<Strip *> strips = query_strips.extract_vector();
|
||||
/* Sort strips by channel. */
|
||||
std::sort(strips.begin(), strips.end(), [](const Strip *a, const Strip *b) {
|
||||
return a->channel > b->channel;
|
||||
});
|
||||
/* Get the top-most scene strip. */
|
||||
const Strip *scene_strip = [&]() -> const Strip * {
|
||||
for (const Strip *strip : strips) {
|
||||
if (strip->type == STRIP_TYPE_SCENE) {
|
||||
return strip;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
if (!scene_strip || !scene_strip->scene) {
|
||||
/* No scene strip with scene found. Switch to pinned scene. */
|
||||
Main *bmain = CTX_data_main(&C);
|
||||
WM_window_set_active_scene(bmain, &C, win, sequence_scene);
|
||||
return;
|
||||
}
|
||||
if (active_scene != scene_strip->scene) {
|
||||
/* Sync active scene in window. */
|
||||
Main *bmain = CTX_data_main(&C);
|
||||
WM_window_set_active_scene(bmain, &C, win, scene_strip->scene);
|
||||
active_scene = scene_strip->scene;
|
||||
}
|
||||
Object *camera = [&]() -> Object * {
|
||||
if (scene_strip->scene_camera) {
|
||||
return scene_strip->scene_camera;
|
||||
}
|
||||
return scene_strip->scene->camera;
|
||||
}();
|
||||
if (camera) {
|
||||
/* Sync camera in any 3D view that uses camera view. */
|
||||
PointerRNA camera_ptr = RNA_id_pointer_create(&camera->id);
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype != SPACE_VIEW3D) {
|
||||
continue;
|
||||
}
|
||||
View3D *view3d = reinterpret_cast<View3D *>(sl);
|
||||
if (view3d->camera == camera) {
|
||||
continue;
|
||||
}
|
||||
PointerRNA view3d_ptr = RNA_pointer_create_discrete(&screen->id, &RNA_SpaceView3D, view3d);
|
||||
RNA_pointer_set(&view3d_ptr, "camera", camera_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the scene time based on the scene strip. */
|
||||
const float frame_index = seq::give_frame_index(
|
||||
sequence_scene, scene_strip, sequence_scene->r.cfra);
|
||||
if (active_scene->r.flag & SCER_SHOW_SUBFRAME) {
|
||||
active_scene->r.cfra = int(frame_index);
|
||||
active_scene->r.subframe = frame_index - int(frame_index);
|
||||
}
|
||||
else {
|
||||
active_scene->r.cfra = round_fl_to_int(frame_index);
|
||||
active_scene->r.subframe = 0.0f;
|
||||
}
|
||||
FRAMENUMBER_MIN_CLAMP(active_scene->r.cfra);
|
||||
|
||||
DEG_id_tag_update(&active_scene->id, ID_RECALC_FRAME_CHANGE);
|
||||
WM_event_add_notifier(&C, NC_WINDOW, nullptr);
|
||||
WM_event_add_notifier(&C, NC_SCENE | ND_FRAME, nullptr);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Remove Gaps Operator
|
||||
* \{ */
|
||||
@@ -685,7 +846,8 @@ static wmOperatorStatus sequencer_slip_invoke(bContext *C, wmOperator *op, const
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static void slip_strips_delta(wmOperator *op, Scene *scene, SlipData *data, const float delta)
|
||||
static void slip_strips_delta(
|
||||
bContext *C, wmOperator *op, Scene *scene, SlipData *data, const float delta)
|
||||
{
|
||||
float new_offset = data->prev_offset + delta;
|
||||
/* Calculate rounded whole frames between offsets, which cannot be determined from `delta` alone.
|
||||
@@ -719,6 +881,8 @@ static void slip_strips_delta(wmOperator *op, Scene *scene, SlipData *data, cons
|
||||
}
|
||||
}
|
||||
|
||||
sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
RNA_float_set(op->ptr, "offset", new_offset);
|
||||
data->prev_offset = new_offset;
|
||||
}
|
||||
@@ -803,13 +967,14 @@ static wmOperatorStatus sequencer_slip_exec(bContext *C, wmOperator *op)
|
||||
float offset = RNA_float_get(op->ptr, "offset");
|
||||
slip_apply_clamp(scene, data, &offset);
|
||||
|
||||
slip_strips_delta(op, scene, data, offset);
|
||||
slip_strips_delta(C, op, scene, data, offset);
|
||||
|
||||
slip_cleanup(C, op, scene);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void slip_handle_num_input(
|
||||
const bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
|
||||
bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
|
||||
{
|
||||
float offset;
|
||||
applyNumInput(&data->num_input, &offset);
|
||||
@@ -818,7 +983,7 @@ static void slip_handle_num_input(
|
||||
slip_update_header(scene, area, data, offset);
|
||||
RNA_float_set(op->ptr, "offset", offset);
|
||||
|
||||
slip_strips_delta(op, scene, data, offset_delta);
|
||||
slip_strips_delta(C, op, scene, data, offset_delta);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
}
|
||||
@@ -843,7 +1008,7 @@ static wmOperatorStatus sequencer_slip_modal(bContext *C, wmOperator *op, const
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
case SLIP_MODAL_CANCEL: {
|
||||
slip_strips_delta(op, scene, data, -data->prev_offset);
|
||||
slip_strips_delta(C, op, scene, data, -data->prev_offset);
|
||||
slip_cleanup(C, op, scene);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -864,7 +1029,7 @@ static wmOperatorStatus sequencer_slip_modal(bContext *C, wmOperator *op, const
|
||||
/* If we exit precision mode, make sure we undo the fractional adjustments and align the
|
||||
* virtual mouse pointer. */
|
||||
float to_nearest_frame = -(data->prev_offset - round_fl_to_int(data->prev_offset));
|
||||
slip_strips_delta(op, scene, data, to_nearest_frame);
|
||||
slip_strips_delta(C, op, scene, data, to_nearest_frame);
|
||||
data->virtual_mval_x += to_nearest_frame * UI_view2d_scale_get_x(v2d);
|
||||
}
|
||||
break;
|
||||
@@ -899,7 +1064,7 @@ static wmOperatorStatus sequencer_slip_modal(bContext *C, wmOperator *op, const
|
||||
/* Also adjust virtual mouse pointer after clamp is applied. */
|
||||
data->virtual_mval_x += (clamped_offset - offset) * UI_view2d_scale_get_x(v2d);
|
||||
|
||||
slip_strips_delta(op, scene, data, clamped_offset_delta);
|
||||
slip_strips_delta(C, op, scene, data, clamped_offset_delta);
|
||||
slip_update_header(scene, area, data, clamped_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
@@ -973,6 +1138,8 @@ static wmOperatorStatus sequencer_mute_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
@@ -1033,6 +1200,8 @@ static wmOperatorStatus sequencer_unmute_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
sync_active_scene_and_time_with_scene_strip(*C);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
@@ -3059,7 +3228,7 @@ void SEQUENCER_OT_change_scene(wmOperatorType *ot)
|
||||
|
||||
/* Properties. */
|
||||
prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
|
||||
RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
|
||||
RNA_def_enum_funcs(prop, RNA_scene_without_sequencer_scene_itemf);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
|
||||
ot->prop = prop;
|
||||
}
|
||||
@@ -3203,10 +3372,19 @@ static wmOperatorStatus sequencer_export_subtitles_exec(bContext *C, wmOperator
|
||||
|
||||
static bool sequencer_strip_is_text_poll(bContext *C)
|
||||
{
|
||||
Editing *ed;
|
||||
Strip *strip;
|
||||
return (((ed = seq::editing_get(CTX_data_sequencer_scene(C))) != nullptr) &&
|
||||
((strip = ed->act_strip) != nullptr) && (strip->type == STRIP_TYPE_TEXT));
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (!ed) {
|
||||
return false;
|
||||
}
|
||||
Strip *strip = ed->act_strip;
|
||||
if (!strip) {
|
||||
return false;
|
||||
}
|
||||
return strip->type == STRIP_TYPE_TEXT;
|
||||
}
|
||||
|
||||
void SEQUENCER_OT_export_subtitles(wmOperatorType *ot)
|
||||
|
||||
@@ -1644,7 +1644,7 @@ void sequencer_preview_region_draw(const bContext *C, ARegion *region)
|
||||
const SpaceSeq &space_sequencer = *static_cast<const SpaceSeq *>(area->spacedata.first);
|
||||
const Scene *scene = CTX_data_sequencer_scene(C);
|
||||
|
||||
if (!scene->ed || space_sequencer.render_size == SEQ_RENDER_SIZE_NONE) {
|
||||
if (!scene || !scene->ed || space_sequencer.render_size == SEQ_RENDER_SIZE_NONE) {
|
||||
sequencer_preview_draw_empty(*region);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,12 @@ namespace blender::ed::vse {
|
||||
|
||||
bool sequencer_retiming_mode_is_active(const bContext *C)
|
||||
{
|
||||
Editing *ed = seq::editing_get(CTX_data_sequencer_scene(C));
|
||||
if (ed == nullptr) {
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (!ed) {
|
||||
return false;
|
||||
}
|
||||
return seq::retiming_selection_get(ed).size() > 0;
|
||||
@@ -129,8 +133,12 @@ void SEQUENCER_OT_retiming_show(wmOperatorType *ot)
|
||||
|
||||
static bool retiming_poll(bContext *C)
|
||||
{
|
||||
const Editing *ed = seq::editing_get(CTX_data_sequencer_scene(C));
|
||||
if (ed == nullptr) {
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
if (!ed) {
|
||||
return false;
|
||||
}
|
||||
Strip *strip = ed->act_strip;
|
||||
|
||||
@@ -42,8 +42,12 @@ static bool sequencer_text_editing_poll(bContext *C)
|
||||
if (!sequencer_editing_initialized_and_active(C)) {
|
||||
return false;
|
||||
}
|
||||
const Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Strip *strip = seq::select_active_get(CTX_data_sequencer_scene(C));
|
||||
const Strip *strip = seq::select_active_get(scene);
|
||||
if (strip == nullptr || strip->type != STRIP_TYPE_TEXT || !seq::effects_can_render_text(strip)) {
|
||||
return false;
|
||||
}
|
||||
@@ -58,7 +62,11 @@ static bool sequencer_text_editing_poll(bContext *C)
|
||||
|
||||
bool sequencer_text_editing_active_poll(bContext *C)
|
||||
{
|
||||
const Strip *strip = seq::select_active_get(CTX_data_sequencer_scene(C));
|
||||
const Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
const Strip *strip = seq::select_active_get(scene);
|
||||
if (strip == nullptr || !sequencer_text_editing_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
@@ -67,8 +75,6 @@ bool sequencer_text_editing_active_poll(bContext *C)
|
||||
return false;
|
||||
}
|
||||
|
||||
const Scene *scene = CTX_data_sequencer_scene(C);
|
||||
|
||||
if (!seq::time_strip_intersects_frame(scene, strip, BKE_scene_frame_get(scene))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ static TimelineDrawContext timeline_draw_context_get(const bContext *C, SeqQuads
|
||||
ctx.sseq = CTX_wm_space_seq(C);
|
||||
ctx.v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
ctx.ed = seq::editing_get(ctx.scene);
|
||||
ctx.ed = ctx.scene ? seq::editing_get(ctx.scene) : nullptr;
|
||||
ctx.channels = ctx.ed ? seq::channels_displayed_get(ctx.ed) : nullptr;
|
||||
|
||||
ctx.viewport = WM_draw_region_get_viewport(ctx.region);
|
||||
@@ -1595,6 +1595,9 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx, StripsDrawBatch &
|
||||
static void draw_timeline_sfra_efra(TimelineDrawContext *ctx)
|
||||
{
|
||||
const Scene *scene = ctx->scene;
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
const View2D *v2d = ctx->v2d;
|
||||
const Editing *ed = seq::editing_get(scene);
|
||||
const int frame_sta = scene->r.sfra;
|
||||
@@ -1834,6 +1837,9 @@ static void draw_timeline_markers(TimelineDrawContext *ctx)
|
||||
if ((ctx->sseq->flag & SEQ_SHOW_MARKERS) == 0) {
|
||||
return;
|
||||
}
|
||||
if (ctx->scene == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
UI_view2d_view_orthoSpecial(ctx->region, ctx->v2d, true);
|
||||
ED_markers_draw(ctx->C, DRAW_MARKERS_MARGIN);
|
||||
@@ -1880,17 +1886,26 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
|
||||
draw_timeline_markers(&ctx);
|
||||
}
|
||||
UI_view2d_view_ortho(ctx.v2d);
|
||||
ANIM_draw_previewrange(ctx.scene, ctx.v2d, 1);
|
||||
if (ctx.scene) {
|
||||
ANIM_draw_previewrange(ctx.scene, ctx.v2d, 1);
|
||||
}
|
||||
draw_timeline_gizmos(&ctx);
|
||||
draw_timeline_post_view_callbacks(&ctx);
|
||||
ED_time_scrub_draw(region, ctx.scene, !(ctx.sseq->flag & SEQ_DRAWFRAMES), true);
|
||||
if (ctx.scene) {
|
||||
ED_time_scrub_draw(region, ctx.scene, !(ctx.sseq->flag & SEQ_DRAWFRAMES), true);
|
||||
}
|
||||
|
||||
seq_prefetch_wm_notify(C, ctx.scene);
|
||||
if (ctx.scene) {
|
||||
seq_prefetch_wm_notify(C, ctx.scene);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_timeline_seq_display(const bContext *C, ARegion *region)
|
||||
{
|
||||
const Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
const SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
@@ -1907,11 +1922,14 @@ void draw_timeline_seq_display(const bContext *C, ARegion *region)
|
||||
region, scene, !(sseq->flag & SEQ_DRAWFRAMES), region->winy >= UI_ANIM_MINY);
|
||||
|
||||
if (region->winy > UI_ANIM_MINY) {
|
||||
const ListBase *seqbase = seq::active_seqbase_get(seq::editing_get(scene));
|
||||
seq::timeline_boundbox(scene, seqbase, &v2d->tot);
|
||||
const rcti scroller_mask = ED_time_scrub_clamp_scroller_mask(v2d->mask);
|
||||
region->v2d.scroll |= V2D_SCROLL_BOTTOM;
|
||||
UI_view2d_scrollers_draw(v2d, &scroller_mask);
|
||||
const Editing *ed = seq::editing_get(scene);
|
||||
if (ed) {
|
||||
const ListBase *seqbase = seq::active_seqbase_get(ed);
|
||||
seq::timeline_boundbox(scene, seqbase, &v2d->tot);
|
||||
const rcti scroller_mask = ED_time_scrub_clamp_scroller_mask(v2d->mask);
|
||||
region->v2d.scroll |= V2D_SCROLL_BOTTOM;
|
||||
UI_view2d_scrollers_draw(v2d, &scroller_mask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
region->v2d.scroll &= ~V2D_SCROLL_BOTTOM;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "BLF_api.hh"
|
||||
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_lib_remap.hh"
|
||||
#include "BKE_screen.hh"
|
||||
@@ -321,7 +322,7 @@ static void sequencer_listener(const wmSpaceTypeListenerParams *params)
|
||||
|
||||
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
|
||||
extern "C" const char *sequencer_context_dir[]; /* Quiet warning. */
|
||||
const char *sequencer_context_dir[] = {"edit_mask", nullptr};
|
||||
const char *sequencer_context_dir[] = {"edit_mask", "tool_settings", nullptr};
|
||||
|
||||
static int /*eContextResult*/ sequencer_context(const bContext *C,
|
||||
const char *member,
|
||||
@@ -334,12 +335,20 @@ static int /*eContextResult*/ sequencer_context(const bContext *C,
|
||||
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
if (CTX_data_equals(member, "edit_mask")) {
|
||||
Mask *mask = seq::active_mask_get(scene);
|
||||
if (mask) {
|
||||
CTX_data_id_pointer_set(result, &mask->id);
|
||||
if (CTX_data_equals(member, "tool_settings")) {
|
||||
if (scene) {
|
||||
CTX_data_pointer_set(result, &scene->id, &RNA_ToolSettings, scene->toolsettings);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
}
|
||||
if (CTX_data_equals(member, "edit_mask")) {
|
||||
if (scene) {
|
||||
Mask *mask = seq::active_mask_get(scene);
|
||||
if (mask) {
|
||||
CTX_data_id_pointer_set(result, &mask->id);
|
||||
}
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
|
||||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
@@ -476,6 +485,9 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transformation uses edge panning to move view. Also if smooth view is running, don't apply
|
||||
* clamping to prevent overriding this functionality. */
|
||||
@@ -687,7 +699,12 @@ static void sequencer_main_cursor(wmWindow *win, ScrArea *area, ARegion *region)
|
||||
UI_view2d_region_to_view(
|
||||
®ion->v2d, mouse_co_region[0], mouse_co_region[1], &mouse_co_view[0], &mouse_co_view[1]);
|
||||
|
||||
const Scene *scene = win->scene;
|
||||
const WorkSpace *workspace = WM_window_get_active_workspace(win);
|
||||
const Scene *scene = workspace->sequencer_scene;
|
||||
if (!scene) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
const Editing *ed = seq::editing_get(scene);
|
||||
|
||||
if (STREQ(tref->idname, "builtin.blade")) {
|
||||
|
||||
@@ -560,9 +560,12 @@ static void create_trans_seq_clamp_data(TransInfo *t, const Scene *scene)
|
||||
}
|
||||
}
|
||||
|
||||
static void createTransSeqData(bContext * /*C*/, TransInfo *t)
|
||||
static void createTransSeqData(bContext *C, TransInfo *t)
|
||||
{
|
||||
Scene *scene = CTX_data_sequencer_scene(t->context);
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
Editing *ed = seq::editing_get(scene);
|
||||
TransData *td = nullptr;
|
||||
TransData2D *td2d = nullptr;
|
||||
|
||||
@@ -128,13 +128,21 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
if (!is_sequencer) {
|
||||
t->scene = sce;
|
||||
t->view_layer = view_layer;
|
||||
}
|
||||
else {
|
||||
t->scene = CTX_data_sequencer_scene(C);
|
||||
t->view_layer = t->scene ? BKE_view_layer_default_render(t->scene) : nullptr;
|
||||
}
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
t->mbus = CTX_wm_message_bus(C);
|
||||
t->depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
t->scene = sce;
|
||||
t->view_layer = view_layer;
|
||||
|
||||
t->area = area;
|
||||
t->region = region;
|
||||
t->settings = ts;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "ED_object.hh"
|
||||
#include "ED_paint.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_screen_types.hh"
|
||||
#include "ED_sculpt.hh"
|
||||
#include "ED_space_api.hh"
|
||||
#include "ED_util.hh"
|
||||
@@ -70,6 +71,15 @@ void ED_editors_init_for_undo(Main *bmain)
|
||||
ED_paint_proj_mesh_data_check(*scene, *ob, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/* Stop animation from playing.
|
||||
* TODO: There might be a way to keep the animation from playing, but sad->scene and
|
||||
* sad->view_layer pointers are outdated and would need to be updated somehow. */
|
||||
bScreen *animscreen = ED_screen_animation_playing(wm);
|
||||
if (animscreen && animscreen->animtimer) {
|
||||
WM_event_timer_remove(wm, win, animscreen->animtimer);
|
||||
animscreen->animtimer = nullptr;
|
||||
}
|
||||
|
||||
/* UI Updates. */
|
||||
/* Flag local View3D's to check and exit if they are empty. */
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
|
||||
@@ -388,6 +388,7 @@
|
||||
.snap_angle_increment_3d_precision = DEG2RADF(1.0f), \
|
||||
.snap_angle_increment_2d_precision = DEG2RADF(1.0f), \
|
||||
\
|
||||
.snap_flag_seq = SCE_SNAP, \
|
||||
/* Weight Paint */ \
|
||||
.weightuser = OB_DRAW_GROUPUSER_ACTIVE, \
|
||||
\
|
||||
|
||||
@@ -166,6 +166,9 @@ typedef struct WorkSpace {
|
||||
* link/append. */
|
||||
struct Scene *pin_scene;
|
||||
|
||||
/* Scene that is used by the sequence editors in this workspace. */
|
||||
struct Scene *sequencer_scene;
|
||||
|
||||
char _pad[4];
|
||||
|
||||
int object_mode;
|
||||
@@ -248,4 +251,6 @@ typedef struct WorkSpaceInstanceHook {
|
||||
typedef enum eWorkSpaceFlags {
|
||||
WORKSPACE_USE_FILTER_BY_ORIGIN = (1 << 1),
|
||||
WORKSPACE_USE_PIN_SCENE = (1 << 2),
|
||||
/* Used for syncing time between sequencer scene strips and the active scene. */
|
||||
WORKSPACE_SYNC_SCENE_TIME = (1 << 3),
|
||||
} eWorkSpaceFlags;
|
||||
|
||||
@@ -97,10 +97,10 @@ const EnumPropertyItem *RNA_scene_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
bool *r_free);
|
||||
const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
bool *r_free);
|
||||
const EnumPropertyItem *RNA_scene_without_sequencer_scene_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
bool *r_free);
|
||||
const EnumPropertyItem *RNA_scene_local_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
|
||||
@@ -192,6 +192,16 @@ static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr)
|
||||
static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr)
|
||||
{
|
||||
bContext *C = (bContext *)ptr->data;
|
||||
const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
|
||||
if (is_sequencer) {
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
if (scene) {
|
||||
ToolSettings *toolsettings = scene->toolsettings;
|
||||
return RNA_pointer_create_id_subdata(
|
||||
*reinterpret_cast<ID *>(scene), &RNA_ToolSettings, toolsettings);
|
||||
}
|
||||
return PointerRNA_NULL;
|
||||
}
|
||||
return RNA_pointer_create_id_subdata(
|
||||
*reinterpret_cast<ID *>(CTX_data_scene(C)), &RNA_ToolSettings, CTX_data_tool_settings(C));
|
||||
}
|
||||
|
||||
@@ -775,6 +775,7 @@ static const EnumPropertyItem eevee_resolution_scale_items[] = {
|
||||
# include "ED_node.hh"
|
||||
# include "ED_render.hh"
|
||||
# include "ED_scene.hh"
|
||||
# include "ED_sequencer.hh"
|
||||
# include "ED_uvedit.hh"
|
||||
# include "ED_view3d.hh"
|
||||
|
||||
@@ -1149,6 +1150,14 @@ static void rna_Scene_show_subframe_update(Main * /*bmain*/,
|
||||
scene->r.subframe = 0.0f;
|
||||
}
|
||||
|
||||
static void rna_Scene_frame_update_context(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = (Scene *)ptr->owner_id;
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
||||
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
|
||||
}
|
||||
|
||||
static void rna_Scene_frame_update(Main * /*bmain*/, Scene * /*current_scene*/, PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = (Scene *)ptr->owner_id;
|
||||
@@ -3599,7 +3608,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY);
|
||||
RNA_def_property_ui_text(prop, "Use Snapping", "Snap strips during transform");
|
||||
RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
|
||||
RNA_def_property_boolean_default(prop, true);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* Publish message-bus. */
|
||||
|
||||
prop = RNA_def_property(srna, "use_snap_uv", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -8657,7 +8665,8 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
prop,
|
||||
"Current Frame",
|
||||
"Current frame, to update animation data from Python frame_set() instead");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update_context");
|
||||
|
||||
prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "r.subframe");
|
||||
|
||||
@@ -135,6 +135,8 @@ const EnumPropertyItem rna_enum_strip_scale_method_items[] = {
|
||||
|
||||
# include "MOV_read.hh"
|
||||
|
||||
# include "ED_sequencer.hh"
|
||||
|
||||
# include "SEQ_add.hh"
|
||||
# include "SEQ_channels.hh"
|
||||
# include "SEQ_edit.hh"
|
||||
@@ -202,6 +204,12 @@ static void rna_Strip_invalidate_preprocessed_update(Main * /*bmain*/,
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Strip_mute_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
rna_Strip_invalidate_raw_update(nullptr, nullptr, ptr);
|
||||
}
|
||||
|
||||
static void UNUSED_FUNCTION(rna_Strip_invalidate_composite_update)(Main * /*bmain*/,
|
||||
Scene * /*scene*/,
|
||||
PointerRNA *ptr)
|
||||
@@ -2234,7 +2242,8 @@ static void rna_def_strip(BlenderRNA *brna)
|
||||
RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Mute", "Disable strip so that it cannot be viewed in the output");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Strip_invalidate_raw_update");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Strip_mute_update");
|
||||
|
||||
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SEQ_LOCK);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
# include "ED_asset.hh"
|
||||
# include "ED_paint.hh"
|
||||
# include "ED_sequencer.hh"
|
||||
|
||||
# include "RNA_access.hh"
|
||||
|
||||
@@ -245,6 +246,11 @@ static int rna_WorkSpaceTool_widget_length(PointerRNA *ptr)
|
||||
return tref->runtime ? strlen(tref->runtime->gizmo_group) : 0;
|
||||
}
|
||||
|
||||
static void rna_workspace_sync_scene_time_update(bContext *C, PointerRNA * /*ptr*/)
|
||||
{
|
||||
blender::ed::vse::sync_active_scene_and_time_with_scene_strip(*C);
|
||||
}
|
||||
|
||||
#else /* RNA_RUNTIME */
|
||||
|
||||
static void rna_def_workspace_owner(BlenderRNA *brna)
|
||||
@@ -485,6 +491,19 @@ static void rna_def_workspace(BlenderRNA *brna)
|
||||
"(which has its own active asset library)");
|
||||
RNA_def_property_update(prop, NC_ASSET | ND_ASSET_LIST_READING, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "sequencer_scene", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "sequencer_scene");
|
||||
RNA_def_property_ui_text(prop, "Sequencer Scene", "");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_PTR_NO_OWNERSHIP);
|
||||
RNA_def_property_update(prop, 0, "rna_window_update_all");
|
||||
|
||||
prop = RNA_def_property(srna, "use_scene_time_sync", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flags", WORKSPACE_SYNC_SCENE_TIME);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Sync Active Scene", "Set the active scene and time based on the current scene strip");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_WINDOW, "rna_workspace_sync_scene_time_update");
|
||||
|
||||
RNA_api_workspace(srna);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,17 @@ blender::VectorSet<Strip *> query_all_strips(ListBase *seqbase);
|
||||
*/
|
||||
blender::VectorSet<Strip *> query_all_strips_recursive(const ListBase *seqbase);
|
||||
|
||||
/**
|
||||
* Query strips at \a timeline_frame in seqbase and nested meta strips.
|
||||
*
|
||||
* \param seqbase: ListBase in which strips are queried
|
||||
* \param timeline_frame: viewed frame
|
||||
* \return set of strips
|
||||
*/
|
||||
blender::VectorSet<Strip *> query_strips_recursive_at_frame(const Scene *scene,
|
||||
const ListBase *seqbase,
|
||||
int timeline_frame);
|
||||
|
||||
/**
|
||||
* Query all effect strips that are directly or indirectly connected to strip_reference.
|
||||
* This includes all effects of strip_reference, strips used by another inputs and their effects,
|
||||
|
||||
@@ -115,6 +115,31 @@ VectorSet<Strip *> query_all_strips_recursive(const ListBase *seqbase)
|
||||
return strips;
|
||||
}
|
||||
|
||||
static void query_strips_recursive_at_frame(const Scene *scene,
|
||||
const ListBase *seqbase,
|
||||
const int timeline_frame,
|
||||
VectorSet<Strip *> &strips)
|
||||
{
|
||||
LISTBASE_FOREACH (Strip *, strip, seqbase) {
|
||||
if (!time_strip_intersects_frame(scene, strip, timeline_frame)) {
|
||||
continue;
|
||||
}
|
||||
if (strip->type == STRIP_TYPE_META) {
|
||||
query_strips_recursive_at_frame(scene, &strip->seqbase, timeline_frame, strips);
|
||||
}
|
||||
strips.add(strip);
|
||||
}
|
||||
}
|
||||
|
||||
VectorSet<Strip *> query_strips_recursive_at_frame(const Scene *scene,
|
||||
const ListBase *seqbase,
|
||||
const int timeline_frame)
|
||||
{
|
||||
VectorSet<Strip *> strips;
|
||||
query_strips_recursive_at_frame(scene, seqbase, timeline_frame, strips);
|
||||
return strips;
|
||||
}
|
||||
|
||||
VectorSet<Strip *> query_all_strips(ListBase *seqbase)
|
||||
{
|
||||
VectorSet<Strip *> strips;
|
||||
|
||||
@@ -354,7 +354,7 @@ SequencerToolSettings *tool_settings_init()
|
||||
tool_settings->snap_mode = SEQ_SNAP_TO_STRIPS | SEQ_SNAP_TO_CURRENT_FRAME |
|
||||
SEQ_SNAP_TO_STRIP_HOLD | SEQ_SNAP_TO_MARKERS | SEQ_SNAP_TO_RETIMING |
|
||||
SEQ_SNAP_TO_PREVIEW_BORDERS | SEQ_SNAP_TO_PREVIEW_CENTER |
|
||||
SEQ_SNAP_TO_STRIPS_PREVIEW;
|
||||
SEQ_SNAP_TO_STRIPS_PREVIEW | SEQ_SNAP_TO_FRAME_RANGE;
|
||||
tool_settings->snap_distance = 15;
|
||||
tool_settings->overlap_mode = SEQ_OVERLAP_SHUFFLE;
|
||||
tool_settings->pivot_point = V3D_AROUND_LOCAL_ORIGINS;
|
||||
|
||||
@@ -990,8 +990,10 @@ static void wm_draw_area_offscreen(bContext *C, wmWindow *win, ScrArea *area, bo
|
||||
if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
|
||||
if (area->spacetype == SPACE_SEQ) {
|
||||
Scene *scene = CTX_data_sequencer_scene(C);
|
||||
WM_toolsystem_update_from_context(
|
||||
C, CTX_wm_workspace(C), scene, BKE_view_layer_default_render(scene), area);
|
||||
if (scene) {
|
||||
WM_toolsystem_update_from_context(
|
||||
C, CTX_wm_workspace(C), scene, BKE_view_layer_default_render(scene), area);
|
||||
}
|
||||
}
|
||||
else {
|
||||
WM_toolsystem_update_from_context(
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "BKE_customdata.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_remap.hh"
|
||||
#include "BKE_library.hh"
|
||||
#include "BKE_main.hh"
|
||||
@@ -510,6 +511,19 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file)
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
/* Update dependency graph of sequencer scene. */
|
||||
Scene *sequencer_scene = CTX_data_sequencer_scene(C);
|
||||
if (sequencer_scene && sequencer_scene != scene) {
|
||||
Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(
|
||||
bmain, sequencer_scene, BKE_view_layer_default_render(sequencer_scene));
|
||||
if (is_after_open_file) {
|
||||
DEG_graph_relations_update(depsgraph);
|
||||
DEG_tag_on_visible_update(bmain, depsgraph);
|
||||
}
|
||||
BKE_scene_graph_update_tagged(depsgraph, bmain);
|
||||
}
|
||||
|
||||
/* Copied to set's in #scene_update_tagged_recursive(). */
|
||||
scene->customdata_mask = win_combine_v3d_datamask;
|
||||
/* XXX, hack so operators can enforce data-masks #26482, GPU render. */
|
||||
@@ -731,7 +745,9 @@ void wm_event_do_notifiers(bContext *C)
|
||||
{
|
||||
/* Pass. */
|
||||
}
|
||||
else if (note->category == NC_SCENE && note->reference && note->reference != scene) {
|
||||
else if (note->category == NC_SCENE && note->reference &&
|
||||
(note->reference != scene && note->reference != workspace->sequencer_scene))
|
||||
{
|
||||
/* Pass. */
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -4578,17 +4578,17 @@ const EnumPropertyItem *RNA_scene_local_itemf(bContext *C,
|
||||
return rna_id_itemf(
|
||||
r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, true, nullptr, nullptr);
|
||||
}
|
||||
const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
bool *r_free)
|
||||
const EnumPropertyItem *RNA_scene_without_sequencer_scene_itemf(bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
bool *r_free)
|
||||
{
|
||||
Scene *scene_active = C ? CTX_data_scene(C) : nullptr;
|
||||
Scene *sequencer_scene = C ? CTX_data_sequencer_scene(C) : nullptr;
|
||||
return rna_id_itemf(r_free,
|
||||
C ? (ID *)CTX_data_main(C)->scenes.first : nullptr,
|
||||
false,
|
||||
rna_id_enum_filter_single,
|
||||
scene_active);
|
||||
sequencer_scene);
|
||||
}
|
||||
const EnumPropertyItem *RNA_movieclip_itemf(bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
|
||||
@@ -46,7 +46,7 @@ class TestBlendUserMap(TestBlendLibLinkHelper):
|
||||
expected_map = {
|
||||
bpy.data.images[0]: {bpy.data.materials[0]},
|
||||
bpy.data.materials[0]: {bpy.data.meshes[0]},
|
||||
bpy.data.scenes[0]: {bpy.data.window_managers[0]},
|
||||
bpy.data.scenes[0]: {bpy.data.window_managers[0], bpy.data.workspaces['Layout']},
|
||||
bpy.data.collections[0]: {bpy.data.scenes[0]},
|
||||
bpy.data.libraries[0]: set(),
|
||||
bpy.data.meshes[0]: {bpy.data.objects[0]},
|
||||
|
||||
Reference in New Issue
Block a user