2020-03-20 14:56:50 +01:00
|
|
|
# ##### 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 #####
|
|
|
|
|
|
|
|
|
2020-11-02 18:13:31 +01:00
|
|
|
import logging
|
2021-01-28 23:59:19 +01:00
|
|
|
from pathlib import Path
|
2020-11-02 18:13:31 +01:00
|
|
|
|
2019-08-08 23:42:02 +02:00
|
|
|
import bpy
|
|
|
|
import mathutils
|
2020-09-25 11:23:36 +02:00
|
|
|
from deepdiff import DeepDiff
|
2020-11-02 18:13:31 +01:00
|
|
|
from replication.constants import DIFF_JSON, MODIFIED
|
2021-03-26 12:30:15 +01:00
|
|
|
from replication.protocol import ReplicatedDatablock
|
|
|
|
from replication.objects import Node
|
2020-04-02 18:42:41 +02:00
|
|
|
|
2021-01-29 11:39:00 +01:00
|
|
|
from ..utils import flush_history
|
2020-11-02 18:13:31 +01:00
|
|
|
from .bl_collection import (dump_collection_children, dump_collection_objects,
|
|
|
|
load_collection_childrens, load_collection_objects,
|
|
|
|
resolve_collection_dependencies)
|
2021-03-26 12:30:15 +01:00
|
|
|
from .bl_action import (load_animation_data,
|
|
|
|
dump_animation_data,
|
2021-03-26 16:14:27 +01:00
|
|
|
resolve_animation_dependencies)
|
2021-03-26 12:30:15 +01:00
|
|
|
from .bl_datablock import stamp_uuid
|
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
from .bl_file import get_filepath
|
2020-11-02 18:13:31 +01:00
|
|
|
from .dump_anything import Dumper, Loader
|
2021-03-26 12:30:15 +01:00
|
|
|
from ..preferences import get_preferences
|
2020-11-04 22:41:24 +01:00
|
|
|
|
2020-10-14 19:11:32 +02:00
|
|
|
RENDER_SETTINGS = [
|
|
|
|
'dither_intensity',
|
|
|
|
'engine',
|
|
|
|
'film_transparent',
|
|
|
|
'filter_size',
|
|
|
|
'fps',
|
|
|
|
'fps_base',
|
|
|
|
'frame_map_new',
|
|
|
|
'frame_map_old',
|
|
|
|
'hair_subdiv',
|
|
|
|
'hair_type',
|
|
|
|
'line_thickness',
|
|
|
|
'line_thickness_mode',
|
|
|
|
'metadata_input',
|
|
|
|
'motion_blur_shutter',
|
|
|
|
'pixel_aspect_x',
|
|
|
|
'pixel_aspect_y',
|
|
|
|
'preview_pixel_size',
|
|
|
|
'preview_start_resolution',
|
|
|
|
'resolution_percentage',
|
|
|
|
'resolution_x',
|
|
|
|
'resolution_y',
|
|
|
|
'sequencer_gl_preview',
|
|
|
|
'use_bake_clear',
|
|
|
|
'use_bake_lores_mesh',
|
|
|
|
'use_bake_multires',
|
|
|
|
'use_bake_selected_to_active',
|
|
|
|
'use_bake_user_scale',
|
|
|
|
'use_border',
|
|
|
|
'use_compositing',
|
|
|
|
'use_crop_to_border',
|
|
|
|
'use_file_extension',
|
|
|
|
'use_freestyle',
|
|
|
|
'use_full_sample',
|
|
|
|
'use_high_quality_normals',
|
|
|
|
'use_lock_interface',
|
|
|
|
'use_motion_blur',
|
|
|
|
'use_multiview',
|
|
|
|
'use_sequencer',
|
|
|
|
'use_sequencer_override_scene_strip',
|
|
|
|
'use_single_layer',
|
|
|
|
'views_format',
|
|
|
|
]
|
|
|
|
|
|
|
|
EVEE_SETTINGS = [
|
|
|
|
'gi_diffuse_bounces',
|
|
|
|
'gi_cubemap_resolution',
|
|
|
|
'gi_visibility_resolution',
|
|
|
|
'gi_irradiance_smoothing',
|
|
|
|
'gi_glossy_clamp',
|
|
|
|
'gi_filter_quality',
|
|
|
|
'gi_show_irradiance',
|
|
|
|
'gi_show_cubemaps',
|
|
|
|
'gi_irradiance_display_size',
|
|
|
|
'gi_cubemap_display_size',
|
|
|
|
'gi_auto_bake',
|
|
|
|
'taa_samples',
|
|
|
|
'taa_render_samples',
|
|
|
|
'use_taa_reprojection',
|
|
|
|
'sss_samples',
|
|
|
|
'sss_jitter_threshold',
|
|
|
|
'use_ssr',
|
|
|
|
'use_ssr_refraction',
|
|
|
|
'use_ssr_halfres',
|
|
|
|
'ssr_quality',
|
|
|
|
'ssr_max_roughness',
|
|
|
|
'ssr_thickness',
|
|
|
|
'ssr_border_fade',
|
|
|
|
'ssr_firefly_fac',
|
|
|
|
'volumetric_start',
|
|
|
|
'volumetric_end',
|
|
|
|
'volumetric_tile_size',
|
|
|
|
'volumetric_samples',
|
|
|
|
'volumetric_sample_distribution',
|
|
|
|
'use_volumetric_lights',
|
|
|
|
'volumetric_light_clamp',
|
|
|
|
'use_volumetric_shadows',
|
|
|
|
'volumetric_shadow_samples',
|
|
|
|
'use_gtao',
|
|
|
|
'use_gtao_bent_normals',
|
|
|
|
'use_gtao_bounce',
|
|
|
|
'gtao_factor',
|
|
|
|
'gtao_quality',
|
|
|
|
'gtao_distance',
|
|
|
|
'bokeh_max_size',
|
|
|
|
'bokeh_threshold',
|
|
|
|
'use_bloom',
|
|
|
|
'bloom_threshold',
|
|
|
|
'bloom_color',
|
|
|
|
'bloom_knee',
|
|
|
|
'bloom_radius',
|
|
|
|
'bloom_clamp',
|
|
|
|
'bloom_intensity',
|
|
|
|
'use_motion_blur',
|
|
|
|
'motion_blur_shutter',
|
|
|
|
'motion_blur_depth_scale',
|
|
|
|
'motion_blur_max',
|
|
|
|
'motion_blur_steps',
|
|
|
|
'shadow_cube_size',
|
|
|
|
'shadow_cascade_size',
|
|
|
|
'use_shadow_high_bitdepth',
|
|
|
|
'gi_diffuse_bounces',
|
|
|
|
'gi_cubemap_resolution',
|
|
|
|
'gi_visibility_resolution',
|
|
|
|
'gi_irradiance_smoothing',
|
|
|
|
'gi_glossy_clamp',
|
|
|
|
'gi_filter_quality',
|
|
|
|
'gi_show_irradiance',
|
|
|
|
'gi_show_cubemaps',
|
|
|
|
'gi_irradiance_display_size',
|
|
|
|
'gi_cubemap_display_size',
|
|
|
|
'gi_auto_bake',
|
|
|
|
'taa_samples',
|
|
|
|
'taa_render_samples',
|
|
|
|
'use_taa_reprojection',
|
|
|
|
'sss_samples',
|
|
|
|
'sss_jitter_threshold',
|
|
|
|
'use_ssr',
|
|
|
|
'use_ssr_refraction',
|
|
|
|
'use_ssr_halfres',
|
|
|
|
'ssr_quality',
|
|
|
|
'ssr_max_roughness',
|
|
|
|
'ssr_thickness',
|
|
|
|
'ssr_border_fade',
|
|
|
|
'ssr_firefly_fac',
|
|
|
|
'volumetric_start',
|
|
|
|
'volumetric_end',
|
|
|
|
'volumetric_tile_size',
|
|
|
|
'volumetric_samples',
|
|
|
|
'volumetric_sample_distribution',
|
|
|
|
'use_volumetric_lights',
|
|
|
|
'volumetric_light_clamp',
|
|
|
|
'use_volumetric_shadows',
|
|
|
|
'volumetric_shadow_samples',
|
|
|
|
'use_gtao',
|
|
|
|
'use_gtao_bent_normals',
|
|
|
|
'use_gtao_bounce',
|
|
|
|
'gtao_factor',
|
|
|
|
'gtao_quality',
|
|
|
|
'gtao_distance',
|
|
|
|
'bokeh_max_size',
|
|
|
|
'bokeh_threshold',
|
|
|
|
'use_bloom',
|
|
|
|
'bloom_threshold',
|
|
|
|
'bloom_color',
|
|
|
|
'bloom_knee',
|
|
|
|
'bloom_radius',
|
|
|
|
'bloom_clamp',
|
|
|
|
'bloom_intensity',
|
|
|
|
'use_motion_blur',
|
|
|
|
'motion_blur_shutter',
|
|
|
|
'motion_blur_depth_scale',
|
|
|
|
'motion_blur_max',
|
|
|
|
'motion_blur_steps',
|
|
|
|
'shadow_cube_size',
|
|
|
|
'shadow_cascade_size',
|
|
|
|
'use_shadow_high_bitdepth',
|
|
|
|
]
|
|
|
|
|
|
|
|
CYCLES_SETTINGS = [
|
|
|
|
'shading_system',
|
|
|
|
'progressive',
|
|
|
|
'use_denoising',
|
|
|
|
'denoiser',
|
|
|
|
'use_square_samples',
|
|
|
|
'samples',
|
|
|
|
'aa_samples',
|
|
|
|
'diffuse_samples',
|
|
|
|
'glossy_samples',
|
|
|
|
'transmission_samples',
|
|
|
|
'ao_samples',
|
|
|
|
'mesh_light_samples',
|
|
|
|
'subsurface_samples',
|
|
|
|
'volume_samples',
|
|
|
|
'sampling_pattern',
|
|
|
|
'use_layer_samples',
|
|
|
|
'sample_all_lights_direct',
|
|
|
|
'sample_all_lights_indirect',
|
|
|
|
'light_sampling_threshold',
|
|
|
|
'use_adaptive_sampling',
|
|
|
|
'adaptive_threshold',
|
|
|
|
'adaptive_min_samples',
|
|
|
|
'min_light_bounces',
|
|
|
|
'min_transparent_bounces',
|
|
|
|
'caustics_reflective',
|
|
|
|
'caustics_refractive',
|
|
|
|
'blur_glossy',
|
|
|
|
'max_bounces',
|
|
|
|
'diffuse_bounces',
|
|
|
|
'glossy_bounces',
|
|
|
|
'transmission_bounces',
|
|
|
|
'volume_bounces',
|
|
|
|
'transparent_max_bounces',
|
|
|
|
'volume_step_rate',
|
|
|
|
'volume_max_steps',
|
|
|
|
'dicing_rate',
|
|
|
|
'max_subdivisions',
|
|
|
|
'dicing_camera',
|
|
|
|
'offscreen_dicing_scale',
|
|
|
|
'film_exposure',
|
|
|
|
'film_transparent_glass',
|
|
|
|
'film_transparent_roughness',
|
|
|
|
'filter_type',
|
|
|
|
'pixel_filter_type',
|
|
|
|
'filter_width',
|
|
|
|
'seed',
|
|
|
|
'use_animated_seed',
|
|
|
|
'sample_clamp_direct',
|
|
|
|
'sample_clamp_indirect',
|
|
|
|
'tile_order',
|
|
|
|
'use_progressive_refine',
|
|
|
|
'bake_type',
|
|
|
|
'use_camera_cull',
|
|
|
|
'camera_cull_margin',
|
|
|
|
'use_distance_cull',
|
|
|
|
'distance_cull_margin',
|
|
|
|
'motion_blur_position',
|
|
|
|
'rolling_shutter_type',
|
|
|
|
'rolling_shutter_duration',
|
|
|
|
'texture_limit',
|
|
|
|
'texture_limit_render',
|
|
|
|
'ao_bounces',
|
|
|
|
'ao_bounces_render',
|
|
|
|
]
|
|
|
|
|
|
|
|
VIEW_SETTINGS = [
|
|
|
|
'look',
|
|
|
|
'view_transform',
|
|
|
|
'exposure',
|
|
|
|
'gamma',
|
|
|
|
'use_curve_mapping',
|
|
|
|
'white_level',
|
|
|
|
'black_level'
|
|
|
|
]
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2020-11-02 18:13:31 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
def dump_sequence(sequence: bpy.types.Sequence) -> dict:
|
|
|
|
""" Dump a sequence to a dict
|
|
|
|
|
|
|
|
:arg sequence: sequence to dump
|
|
|
|
:type sequence: bpy.types.Sequence
|
|
|
|
:return dict:
|
|
|
|
"""
|
|
|
|
dumper = Dumper()
|
|
|
|
dumper.exclude_filter = [
|
|
|
|
'lock',
|
|
|
|
'select',
|
|
|
|
'select_left_handle',
|
|
|
|
'select_right_handle',
|
|
|
|
'strobe'
|
|
|
|
]
|
|
|
|
dumper.depth = 1
|
|
|
|
data = dumper.dump(sequence)
|
|
|
|
|
|
|
|
# TODO: Support multiple images
|
|
|
|
if sequence.type == 'IMAGE':
|
|
|
|
data['filenames'] = [e.filename for e in sequence.elements]
|
|
|
|
|
|
|
|
# Effect strip inputs
|
|
|
|
input_count = getattr(sequence, 'input_count', None)
|
|
|
|
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):
|
|
|
|
""" Load sequence from dumped data
|
|
|
|
|
|
|
|
:arg sequence_data: sequence to dump
|
|
|
|
:type sequence_data:dict
|
|
|
|
:arg sequence_editor: root sequence editor
|
|
|
|
:type 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,
|
2021-03-26 12:30:15 +01:00
|
|
|
strip_scene,
|
|
|
|
strip_channel,
|
|
|
|
strip_frame_start)
|
2021-01-28 23:59:19 +01:00
|
|
|
elif strip_type == 'MOVIE':
|
|
|
|
filepath = get_filepath(Path(sequence_data['filepath']).name)
|
|
|
|
sequence = sequence_editor.sequences.new_movie(strip_name,
|
2021-03-26 12:30:15 +01:00
|
|
|
filepath,
|
|
|
|
strip_channel,
|
|
|
|
strip_frame_start)
|
2021-01-28 23:59:19 +01:00
|
|
|
elif strip_type == 'SOUND':
|
|
|
|
filepath = bpy.data.sounds[sequence_data['sound']].filepath
|
|
|
|
sequence = sequence_editor.sequences.new_sound(strip_name,
|
2021-03-26 12:30:15 +01:00
|
|
|
filepath,
|
|
|
|
strip_channel,
|
|
|
|
strip_frame_start)
|
2021-01-28 23:59:19 +01:00
|
|
|
elif strip_type == 'IMAGE':
|
|
|
|
images_name = sequence_data.get('filenames')
|
|
|
|
filepath = get_filepath(images_name[0])
|
|
|
|
sequence = sequence_editor.sequences.new_image(strip_name,
|
2021-03-26 12:30:15 +01:00
|
|
|
filepath,
|
|
|
|
strip_channel,
|
|
|
|
strip_frame_start)
|
2021-01-28 23:59:19 +01:00
|
|
|
# load other images
|
2021-03-26 12:30:15 +01:00
|
|
|
if len(images_name) > 1:
|
|
|
|
for img_idx in range(1, len(images_name)):
|
2021-01-28 23:59:19 +01:00
|
|
|
sequence.elements.append((images_name[img_idx]))
|
|
|
|
else:
|
|
|
|
seq = {}
|
2020-11-04 22:41:24 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
for i in range(sequence_data['input_count']):
|
2021-03-26 12:30:15 +01:00
|
|
|
seq[f"seq{i+1}"] = sequence_editor.sequences_all.get(
|
|
|
|
sequence_data.get(f"input_{i+1}", None))
|
2020-11-04 22:41:24 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
sequence = sequence_editor.sequences.new_effect(name=strip_name,
|
2021-03-26 12:30:15 +01:00
|
|
|
type=strip_type,
|
|
|
|
channel=strip_channel,
|
|
|
|
frame_start=strip_frame_start,
|
|
|
|
frame_end=sequence_data['frame_final_end'],
|
|
|
|
**seq)
|
2020-11-04 22:41:24 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
loader = Loader()
|
2021-03-26 12:30:15 +01:00
|
|
|
# TODO: Support filepath updates
|
|
|
|
loader.exclure_filter = ['filepath', 'sound', 'filenames', 'fps']
|
2021-01-28 23:59:19 +01:00
|
|
|
loader.load(sequence, sequence_data)
|
|
|
|
sequence.select = False
|
2020-11-02 18:13:31 +01:00
|
|
|
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
class BlScene(ReplicatedDatablock):
|
2021-03-14 20:58:25 +01:00
|
|
|
is_root = True
|
|
|
|
|
2020-01-13 18:51:31 +01:00
|
|
|
bl_id = "scenes"
|
|
|
|
bl_class = bpy.types.Scene
|
2020-09-17 22:47:11 +02:00
|
|
|
bl_check_common = True
|
2020-01-13 18:51:31 +01:00
|
|
|
bl_icon = 'SCENE_DATA'
|
2020-12-09 14:49:26 +01:00
|
|
|
bl_reload_parent = False
|
2020-01-13 18:51:31 +01:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
@staticmethod
|
|
|
|
def construct(data: dict) -> object:
|
|
|
|
datablock = bpy.data.scenes.new(data["name"])
|
|
|
|
datablock.uuid = data.get("uuid")
|
2021-01-28 23:59:19 +01:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
return datablock
|
2019-08-08 23:42:02 +02:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
@staticmethod
|
|
|
|
def load(data: dict, datablock: object):
|
2019-08-08 23:42:02 +02:00
|
|
|
# Load other meshes metadata
|
2020-04-01 11:34:24 +02:00
|
|
|
loader = Loader()
|
2021-03-26 12:30:15 +01:00
|
|
|
loader.load(datablock, data)
|
2019-08-08 23:42:02 +02:00
|
|
|
|
|
|
|
# Load master collection
|
2020-10-12 20:21:08 +02:00
|
|
|
load_collection_objects(
|
2021-03-26 12:30:15 +01:00
|
|
|
data['collection']['objects'], datablock.collection)
|
2020-10-12 20:21:08 +02:00
|
|
|
load_collection_childrens(
|
2021-03-26 12:30:15 +01:00
|
|
|
data['collection']['children'], datablock.collection)
|
2019-08-08 23:42:02 +02:00
|
|
|
|
2019-09-27 16:55:26 +02:00
|
|
|
if 'world' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.world = bpy.data.worlds[data['world']]
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2019-10-14 14:42:23 +02:00
|
|
|
# Annotation
|
|
|
|
if 'grease_pencil' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.grease_pencil = bpy.data.grease_pencils[data['grease_pencil']]
|
2020-09-25 11:33:35 +02:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
if get_preferences().sync_flags.sync_render_settings:
|
2020-09-25 11:23:36 +02:00
|
|
|
if 'eevee' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
loader.load(datablock.eevee, data['eevee'])
|
2019-09-27 16:55:26 +02:00
|
|
|
|
2020-09-25 11:23:36 +02:00
|
|
|
if 'cycles' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
loader.load(datablock.cycles, data['cycles'])
|
2020-04-02 17:39:14 +02:00
|
|
|
|
2020-09-25 11:23:36 +02:00
|
|
|
if 'render' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
loader.load(datablock.render, data['render'])
|
2020-08-28 14:10:09 +02:00
|
|
|
|
2020-09-25 11:23:36 +02:00
|
|
|
if 'view_settings' in data.keys():
|
2021-03-26 12:30:15 +01:00
|
|
|
loader.load(datablock.view_settings, data['view_settings'])
|
|
|
|
if datablock.view_settings.use_curve_mapping and \
|
2020-11-02 18:13:31 +01:00
|
|
|
'curve_mapping' in data['view_settings']:
|
2020-10-12 20:21:08 +02:00
|
|
|
# TODO: change this ugly fix
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.view_settings.curve_mapping.white_level = data[
|
2020-10-14 19:11:32 +02:00
|
|
|
'view_settings']['curve_mapping']['white_level']
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.view_settings.curve_mapping.black_level = data[
|
2020-10-14 19:11:32 +02:00
|
|
|
'view_settings']['curve_mapping']['black_level']
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.view_settings.curve_mapping.update()
|
2020-04-02 17:39:14 +02:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
# Sequencer
|
|
|
|
sequences = data.get('sequences')
|
2021-03-26 12:30:15 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
if sequences:
|
|
|
|
# Create sequencer data
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.sequence_editor_create()
|
|
|
|
vse = datablock.sequence_editor
|
2021-01-29 11:39:00 +01:00
|
|
|
|
|
|
|
# Clear removed sequences
|
2021-01-28 23:59:19 +01:00
|
|
|
for seq in vse.sequences_all:
|
|
|
|
if seq.name not in sequences:
|
|
|
|
vse.sequences.remove(seq)
|
2021-01-29 11:39:00 +01:00
|
|
|
# Load existing sequences
|
2021-01-28 23:59:19 +01:00
|
|
|
for seq_name, seq_data in sequences.items():
|
|
|
|
load_sequence(seq_data, vse)
|
2021-01-29 11:39:00 +01:00
|
|
|
# If the sequence is no longer used, clear it
|
2021-03-26 12:30:15 +01:00
|
|
|
elif datablock.sequence_editor and not sequences:
|
|
|
|
datablock.sequence_editor_clear()
|
2021-01-28 23:59:19 +01:00
|
|
|
|
2020-12-23 18:46:29 +01:00
|
|
|
# FIXME: Find a better way after the replication big refacotoring
|
|
|
|
# Keep other user from deleting collection object by flushing their history
|
|
|
|
flush_history()
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
@staticmethod
|
|
|
|
def dump(datablock: object) -> dict:
|
|
|
|
stamp_uuid(datablock)
|
2019-09-27 16:55:26 +02:00
|
|
|
|
2020-11-02 18:13:31 +01:00
|
|
|
# Metadata
|
2020-04-01 11:34:24 +02:00
|
|
|
scene_dumper = Dumper()
|
2019-09-27 16:55:26 +02:00
|
|
|
scene_dumper.depth = 1
|
2020-03-26 17:13:59 +01:00
|
|
|
scene_dumper.include_filter = [
|
|
|
|
'name',
|
|
|
|
'world',
|
|
|
|
'id',
|
2020-04-02 17:39:14 +02:00
|
|
|
'grease_pencil',
|
2020-08-28 14:10:09 +02:00
|
|
|
'frame_start',
|
|
|
|
'frame_end',
|
|
|
|
'frame_step',
|
2021-03-26 12:30:15 +01:00
|
|
|
'uuid'
|
2020-03-26 17:13:59 +01:00
|
|
|
]
|
2021-03-26 12:30:15 +01:00
|
|
|
if get_preferences().sync_flags.sync_active_camera:
|
2020-09-25 11:33:35 +02:00
|
|
|
scene_dumper.include_filter.append('camera')
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
data = scene_dumper.dump(datablock)
|
|
|
|
dump_animation_data(datablock, data)
|
2019-09-27 16:55:26 +02:00
|
|
|
|
2020-11-02 18:13:31 +01:00
|
|
|
# Master collection
|
2020-08-28 14:10:09 +02:00
|
|
|
data['collection'] = {}
|
2020-10-12 20:21:08 +02:00
|
|
|
data['collection']['children'] = dump_collection_children(
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.collection)
|
2020-10-12 20:21:08 +02:00
|
|
|
data['collection']['objects'] = dump_collection_objects(
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.collection)
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2020-04-02 17:39:14 +02:00
|
|
|
scene_dumper.depth = 1
|
|
|
|
scene_dumper.include_filter = None
|
2020-04-02 18:42:41 +02:00
|
|
|
|
2020-11-02 18:13:31 +01:00
|
|
|
# Render settings
|
2021-03-26 12:30:15 +01:00
|
|
|
if get_preferences().sync_flags.sync_render_settings:
|
2020-10-14 19:11:32 +02:00
|
|
|
scene_dumper.include_filter = RENDER_SETTINGS
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
data['render'] = scene_dumper.dump(datablock.render)
|
2020-08-28 14:10:09 +02:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
if datablock.render.engine == 'BLENDER_EEVEE':
|
2020-10-14 19:11:32 +02:00
|
|
|
scene_dumper.include_filter = EVEE_SETTINGS
|
2021-03-26 12:30:15 +01:00
|
|
|
data['eevee'] = scene_dumper.dump(datablock.eevee)
|
|
|
|
elif datablock.render.engine == 'CYCLES':
|
2020-10-14 19:11:32 +02:00
|
|
|
scene_dumper.include_filter = CYCLES_SETTINGS
|
2021-03-26 12:30:15 +01:00
|
|
|
data['cycles'] = scene_dumper.dump(datablock.cycles)
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2020-10-14 19:11:32 +02:00
|
|
|
scene_dumper.include_filter = VIEW_SETTINGS
|
2021-03-26 12:30:15 +01:00
|
|
|
data['view_settings'] = scene_dumper.dump(datablock.view_settings)
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
if datablock.view_settings.use_curve_mapping:
|
2020-10-12 20:21:08 +02:00
|
|
|
data['view_settings']['curve_mapping'] = scene_dumper.dump(
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.view_settings.curve_mapping)
|
2020-04-02 18:42:41 +02:00
|
|
|
scene_dumper.depth = 5
|
|
|
|
scene_dumper.include_filter = [
|
|
|
|
'curves',
|
|
|
|
'points',
|
2020-10-14 19:11:32 +02:00
|
|
|
'location',
|
2020-04-02 18:42:41 +02:00
|
|
|
]
|
2020-10-12 20:21:08 +02:00
|
|
|
data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump(
|
2021-03-26 12:30:15 +01:00
|
|
|
datablock.view_settings.curve_mapping.curves)
|
2020-11-11 18:36:00 +01:00
|
|
|
|
2021-01-28 23:59:19 +01:00
|
|
|
# Sequence
|
2021-03-26 12:30:15 +01:00
|
|
|
vse = datablock.sequence_editor
|
2021-01-28 23:59:19 +01:00
|
|
|
if vse:
|
|
|
|
dumped_sequences = {}
|
|
|
|
for seq in vse.sequences_all:
|
|
|
|
dumped_sequences[seq.name] = dump_sequence(seq)
|
|
|
|
data['sequences'] = dumped_sequences
|
|
|
|
|
2019-08-08 23:42:02 +02:00
|
|
|
return data
|
|
|
|
|
2021-03-25 14:55:53 +01:00
|
|
|
@staticmethod
|
2021-03-26 12:30:15 +01:00
|
|
|
def resolve_deps(datablock: object) -> [object]:
|
2019-08-26 17:27:12 +02:00
|
|
|
deps = []
|
2019-09-23 22:13:06 +02:00
|
|
|
|
2020-10-30 16:58:18 +01:00
|
|
|
# Master Collection
|
2021-03-25 14:55:53 +01:00
|
|
|
deps.extend(resolve_collection_dependencies(datablock.collection))
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2019-09-23 22:13:06 +02:00
|
|
|
# world
|
2021-03-25 14:55:53 +01:00
|
|
|
if datablock.world:
|
|
|
|
deps.append(datablock.world)
|
2020-10-12 20:21:08 +02:00
|
|
|
|
2019-10-14 14:42:23 +02:00
|
|
|
# annotations
|
2021-03-25 14:55:53 +01:00
|
|
|
if datablock.grease_pencil:
|
|
|
|
deps.append(datablock.grease_pencil)
|
2019-10-14 14:42:23 +02:00
|
|
|
|
2020-10-30 16:58:18 +01:00
|
|
|
# Sequences
|
2021-03-25 14:55:53 +01:00
|
|
|
vse = datablock.sequence_editor
|
2021-01-28 23:59:19 +01:00
|
|
|
if vse:
|
|
|
|
for sequence in vse.sequences_all:
|
|
|
|
if sequence.type == 'MOVIE' and sequence.filepath:
|
|
|
|
deps.append(Path(bpy.path.abspath(sequence.filepath)))
|
|
|
|
elif sequence.type == 'SOUND' and sequence.sound:
|
|
|
|
deps.append(sequence.sound)
|
|
|
|
elif sequence.type == 'IMAGE':
|
|
|
|
for elem in sequence.elements:
|
|
|
|
sequence.append(
|
|
|
|
Path(bpy.path.abspath(sequence.directory),
|
2021-03-26 12:30:15 +01:00
|
|
|
elem.filename))
|
2020-11-04 22:41:24 +01:00
|
|
|
|
2019-08-26 17:27:12 +02:00
|
|
|
return deps
|
2020-09-25 11:23:36 +02:00
|
|
|
|
|
|
|
def diff(self):
|
|
|
|
exclude_path = []
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
if not get_preferences().sync_flags.sync_render_settings:
|
2020-09-25 11:23:36 +02:00
|
|
|
exclude_path.append("root['eevee']")
|
|
|
|
exclude_path.append("root['cycles']")
|
|
|
|
exclude_path.append("root['view_settings']")
|
|
|
|
exclude_path.append("root['render']")
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
if not get_preferences().sync_flags.sync_active_camera:
|
2020-09-25 11:33:35 +02:00
|
|
|
exclude_path.append("root['camera']")
|
|
|
|
|
2021-03-26 12:30:15 +01:00
|
|
|
return DeepDiff(self.data, self._dump(datablock=self.datablock), exclude_paths=exclude_path)
|