feat: bl_sequencer separate implementation

This commit is contained in:
Swann 2020-11-04 22:41:24 +01:00
parent babecf5ae7
commit 9c83df45fc
No known key found for this signature in database
GPG Key ID: E1D3641A7C43AACB
4 changed files with 185 additions and 107 deletions

View File

@ -37,7 +37,8 @@ __all__ = [
'bl_speaker', 'bl_speaker',
'bl_font', 'bl_font',
'bl_sound', 'bl_sound',
'bl_file' 'bl_file',
'bl_sequencer'
] # Order here defines execution order ] # Order here defines execution order
from . import * from . import *

View File

@ -21,7 +21,7 @@ from collections.abc import Iterable
import bpy import bpy
import mathutils import mathutils
from replication.constants import DIFF_BINARY, UP from replication.constants import DIFF_BINARY, DIFF_JSON, UP
from replication.data import ReplicatedDatablock from replication.data import ReplicatedDatablock
from .. import utils from .. import utils
@ -216,7 +216,7 @@ class BlDatablock(ReplicatedDatablock):
if not self.is_library: if not self.is_library:
dependencies.extend(self._resolve_deps_implementation()) dependencies.extend(self._resolve_deps_implementation())
logging.debug(f"{self.instance.name} dependencies: {dependencies}") logging.debug(f"{self.instance} dependencies: {dependencies}")
return dependencies return dependencies
def _resolve_deps_implementation(self): def _resolve_deps_implementation(self):

View File

@ -17,7 +17,6 @@
import logging import logging
from pathlib import Path
import bpy import bpy
import mathutils import mathutils
@ -29,7 +28,7 @@ from .bl_collection import (dump_collection_children, dump_collection_objects,
resolve_collection_dependencies) resolve_collection_dependencies)
from .bl_datablock import BlDatablock from .bl_datablock import BlDatablock
from .dump_anything import Dumper, Loader from .dump_anything import Dumper, Loader
from .bl_file import get_filepath
RENDER_SETTINGS = [ RENDER_SETTINGS = [
'dither_intensity', 'dither_intensity',
'engine', 'engine',
@ -266,87 +265,9 @@ VIEW_SETTINGS = [
] ]
def dump_sequence(sequence: bpy.types.Sequence) -> dict:
dumper = Dumper()
dumper.exclude_filter = [
'lock',
'select',
'select_left_handle',
'select_right_handle',
]
dumper.depth = 1
data = dumper.dump(sequence)
input_count = getattr(sequence, 'input_count', None)
if sequence.type == 'IMAGE':
data['filename'] = sequence.elements[0].filename
if input_count:
for n in range(input_count):
input_name = f"input_{n+1}"
data[input_name] = getattr(sequence, input_name).name
return data
def load_sequence(sequence_data: dict, sequence_editor: bpy.types.SequenceEditor):
strip_type = sequence_data.get('type')
strip_name = sequence_data.get('name')
strip_channel = sequence_data.get('channel')
strip_frame_start = sequence_data.get('frame_start')
if strip_type == 'SCENE':
strip_scene = bpy.data.scenes.get(sequence_data.get('scene'))
sequence = sequence_editor.sequences.new_scene(strip_name,
strip_scene,
strip_channel,
strip_frame_start)
elif strip_type == 'MOVIE':
filepath = get_filepath(Path(sequence_data['filepath']).name)
sequence = sequence_editor.sequences.new_movie(strip_name,
filepath,
strip_channel,
strip_frame_start)
elif strip_type == 'SOUND':
filepath = bpy.data.sounds[sequence_data['sound']].filepath
sequence = sequence_editor.sequences.new_sound(strip_name,
filepath,
strip_channel,
strip_frame_start)
elif strip_type == 'IMAGE':
filepath = get_filepath(sequence_data['filename'])
sequence = sequence_editor.sequences.new_image(strip_name,
filepath,
strip_channel,
strip_frame_start)
else:
seq1 = sequence_editor.sequences_all.get(sequence_data.get("input_1", None))
seq2 = seq3 = None
if sequence_data['input_count'] == 2:
seq2 = sequence_editor.sequences_all.get(sequence_data.get("input_2", None))
if sequence_data['input_count'] == 3:
seq3 = sequence_editor.sequences_all.get(sequence_data.get("input_3", None))
strip_frame_end = sequence_data.get("strip_frame_end")
sequence = sequence_editor.sequences.new_effect(strip_name,
strip_type,
strip_channel,
strip_frame_start,
seq1=seq1,
seq2=seq2,
seq3=seq3,
)
loader = Loader()
loader.load(sequence, sequence_data)
sequence.select = False
# elif strip_type == 'MOVIE':
def get_sequence_dependency(sequence: bpy.types.Sequence):
if sequence.type == 'MOVIE':
return Path(bpy.path.abspath(sequence.filepath))
elif sequence.type == 'SOUND':
return sequence.sound
elif sequence.type == 'IMAGE':
return Path(bpy.path.abspath(sequence.directory), sequence.elements[0].filename)
class BlScene(BlDatablock): class BlScene(BlDatablock):
@ -406,15 +327,6 @@ class BlScene(BlDatablock):
'view_settings']['curve_mapping']['black_level'] 'view_settings']['curve_mapping']['black_level']
target.view_settings.curve_mapping.update() target.view_settings.curve_mapping.update()
# Sequencer
sequences = data.get('sequences')
if sequences:
target.sequence_editor_clear()
if target.sequence_editor is None:
target.sequence_editor_create()
for seq_name, seq_data in sequences.items():
load_sequence(seq_data, target.sequence_editor)
def _dump_implementation(self, data, instance=None): def _dump_implementation(self, data, instance=None):
assert(instance) assert(instance)
@ -472,16 +384,6 @@ class BlScene(BlDatablock):
] ]
data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump( data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump(
instance.view_settings.curve_mapping.curves) instance.view_settings.curve_mapping.curves)
# Sequencer
if instance.sequence_editor is not None:
sequences = {}
for seq in instance.sequence_editor.sequences_all:
sequences[seq.name] = dump_sequence(seq)
data['sequences'] = sequences
return data return data
def _resolve_deps_implementation(self): def _resolve_deps_implementation(self):
@ -499,12 +401,10 @@ class BlScene(BlDatablock):
deps.append(self.instance.grease_pencil) deps.append(self.instance.grease_pencil)
# Sequences # Sequences
if self.instance.sequence_editor:
for seq in self.instance.sequence_editor.sequences_all:
dep = get_sequence_dependency(seq)
if dep:
deps.append(dep)
# deps.extend(list(self.instance.sequence_editor.sequences_all)) # deps.extend(list(self.instance.sequence_editor.sequences_all))
if self.instance.sequence_editor:
deps.append(self.instance.sequence_editor)
return deps return deps
def diff(self): def diff(self):

View File

@ -0,0 +1,177 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
import bpy
import mathutils
from pathlib import Path
import logging
from .bl_file import get_filepath
from .dump_anything import Loader, Dumper
from .bl_datablock import BlDatablock, get_datablock_from_uuid
def dump_sequence(sequence: bpy.types.Sequence) -> dict:
dumper = Dumper()
dumper.exclude_filter = [
'lock',
'select',
'select_left_handle',
'select_right_handle',
]
dumper.depth = 1
data = dumper.dump(sequence)
input_count = getattr(sequence, 'input_count', None)
if sequence.type == 'IMAGE':
data['filename'] = sequence.elements[0].filename
if input_count:
for n in range(input_count):
input_name = f"input_{n+1}"
data[input_name] = getattr(sequence, input_name).name
return data
def load_sequence(sequence_data: dict, sequence_editor: bpy.types.SequenceEditor):
strip_type = sequence_data.get('type')
strip_name = sequence_data.get('name')
strip_channel = sequence_data.get('channel')
strip_frame_start = sequence_data.get('frame_start')
sequence = sequence_editor.sequences_all.get(strip_name, None)
if sequence is None:
if strip_type == 'SCENE':
strip_scene = bpy.data.scenes.get(sequence_data.get('scene'))
sequence = sequence_editor.sequences.new_scene(strip_name,
strip_scene,
strip_channel,
strip_frame_start)
elif strip_type == 'MOVIE':
filepath = get_filepath(Path(sequence_data['filepath']).name)
sequence = sequence_editor.sequences.new_movie(strip_name,
filepath,
strip_channel,
strip_frame_start)
elif strip_type == 'SOUND':
filepath = bpy.data.sounds[sequence_data['sound']].filepath
sequence = sequence_editor.sequences.new_sound(strip_name,
filepath,
strip_channel,
strip_frame_start)
elif strip_type == 'IMAGE':
filepath = get_filepath(sequence_data['filename'])
sequence = sequence_editor.sequences.new_image(strip_name,
filepath,
strip_channel,
strip_frame_start)
else:
seq = {}
for i in range(sequence_data['input_count']):
seq[f"seq{i}"] = sequence_editor.sequences_all.get(sequence_data.get("input_{i}", None))
sequence = sequence_editor.sequences.new_effect(name=strip_name,
type=strip_type,
channel=strip_channel,
frame_start=strip_frame_start,
frame_end=sequence_data['frame_final_end'],
**seq)
loader = Loader()
loader.load(sequence, sequence_data)
sequence.select = False
def get_sequence_dependency(sequence: bpy.types.Sequence):
if sequence.type == 'MOVIE':
return Path(bpy.path.abspath(sequence.filepath))
elif sequence.type == 'SOUND':
return sequence.sound
elif sequence.type == 'IMAGE':
return Path(bpy.path.abspath(sequence.directory), sequence.elements[0].filename)
class BlSequencer(BlDatablock):
bl_id = "scenes"
bl_class = bpy.types.SequenceEditor
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_check_common = True
bl_icon = 'SEQUENCE'
def _construct(self, data):
# Get the scene
scene_id = data.get('name')
scene = bpy.data.scenes.get(scene_id, None)
# Create sequencer data
scene.sequence_editor_clear()
scene.sequence_editor_create()
return scene.sequence_editor
def resolve(self):
scene = bpy.data.scenes.get(self.data['name'], None)
if scene:
if scene.sequence_editor is None:
self.instance = self._construct(self.data)
else:
self.instance = scene.sequence_editor
else:
logging.warning("Sequencer editor scene not found")
def _load_implementation(self, data, target):
loader = Loader()
# Sequencer
sequences = data.get('sequences')
if sequences:
# target.sequence_editor_clear()
# if target.sequence_editor is None:
# target.sequence_editor_create()
for seq_name, seq_data in sequences.items():
load_sequence(seq_data, target)
pass
def _dump_implementation(self, data, instance=None):
assert(instance)
sequence_dumper = Dumper()
sequence_dumper.depth = 1
sequence_dumper.include_filter = [
'proxy_storage',
]
data = {}#sequence_dumper.dump(instance)
# Sequencer
sequences = {}
for seq in instance.sequences_all:
sequences[seq.name] = dump_sequence(seq)
data['sequences'] = sequences
data['name'] = instance.id_data.name
return data
def _resolve_deps_implementation(self):
deps = []
for seq in self.instance.sequences_all:
dep = get_sequence_dependency(seq)
if dep:
deps.append(dep)
return deps