From 9c83df45fcce6e795df160be2ccac8d9d22ad67a Mon Sep 17 00:00:00 2001 From: Swann Date: Wed, 4 Nov 2020 22:41:24 +0100 Subject: [PATCH] feat: bl_sequencer separate implementation --- multi_user/bl_types/__init__.py | 3 +- multi_user/bl_types/bl_datablock.py | 4 +- multi_user/bl_types/bl_scene.py | 108 +---------------- multi_user/bl_types/bl_sequencer.py | 177 ++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 107 deletions(-) create mode 100644 multi_user/bl_types/bl_sequencer.py diff --git a/multi_user/bl_types/__init__.py b/multi_user/bl_types/__init__.py index add7058..fca195f 100644 --- a/multi_user/bl_types/__init__.py +++ b/multi_user/bl_types/__init__.py @@ -37,7 +37,8 @@ __all__ = [ 'bl_speaker', 'bl_font', 'bl_sound', - 'bl_file' + 'bl_file', + 'bl_sequencer' ] # Order here defines execution order from . import * diff --git a/multi_user/bl_types/bl_datablock.py b/multi_user/bl_types/bl_datablock.py index aa9eab0..8f6344c 100644 --- a/multi_user/bl_types/bl_datablock.py +++ b/multi_user/bl_types/bl_datablock.py @@ -21,7 +21,7 @@ from collections.abc import Iterable import bpy import mathutils -from replication.constants import DIFF_BINARY, UP +from replication.constants import DIFF_BINARY, DIFF_JSON, UP from replication.data import ReplicatedDatablock from .. import utils @@ -216,7 +216,7 @@ class BlDatablock(ReplicatedDatablock): if not self.is_library: dependencies.extend(self._resolve_deps_implementation()) - logging.debug(f"{self.instance.name} dependencies: {dependencies}") + logging.debug(f"{self.instance} dependencies: {dependencies}") return dependencies def _resolve_deps_implementation(self): diff --git a/multi_user/bl_types/bl_scene.py b/multi_user/bl_types/bl_scene.py index f06ee88..0c485f4 100644 --- a/multi_user/bl_types/bl_scene.py +++ b/multi_user/bl_types/bl_scene.py @@ -17,7 +17,6 @@ import logging -from pathlib import Path import bpy import mathutils @@ -29,7 +28,7 @@ from .bl_collection import (dump_collection_children, dump_collection_objects, resolve_collection_dependencies) from .bl_datablock import BlDatablock from .dump_anything import Dumper, Loader -from .bl_file import get_filepath + RENDER_SETTINGS = [ 'dither_intensity', '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): @@ -406,15 +327,6 @@ class BlScene(BlDatablock): 'view_settings']['curve_mapping']['black_level'] 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): assert(instance) @@ -472,16 +384,6 @@ class BlScene(BlDatablock): ] data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump( 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 def _resolve_deps_implementation(self): @@ -499,12 +401,10 @@ class BlScene(BlDatablock): deps.append(self.instance.grease_pencil) # 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)) + if self.instance.sequence_editor: + deps.append(self.instance.sequence_editor) + return deps def diff(self): diff --git a/multi_user/bl_types/bl_sequencer.py b/multi_user/bl_types/bl_sequencer.py new file mode 100644 index 0000000..f55d282 --- /dev/null +++ b/multi_user/bl_types/bl_sequencer.py @@ -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 . +# +# ##### 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