diff --git a/multi_user/operators.py b/multi_user/operators.py index 0cccffa..93dd083 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -35,6 +35,7 @@ from operator import itemgetter from pathlib import Path from queue import Queue from time import gmtime, strftime +from numpy import interp from bpy.props import FloatProperty import bmesh @@ -1052,6 +1053,8 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper): def execute(self, context): from replication.repository import Repository + runtime_settings = context.window_manager.session + # init the factory with supported types bpy_protocol = bl_types.get_data_translation_protocol() repo = Repository(bpy_protocol) @@ -1062,7 +1065,7 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper): persistent_collection = bpy.data.collections.get("multiuser_timelapse") if self.replay and \ - context.window_manager.session.replay_persistent_collection and \ + runtime_settings.replay_persistent_collection and \ persistent_collection: collection_repo = Repository( rdp=bpy_protocol, @@ -1088,14 +1091,17 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper): porcelain.apply(repo, node.uuid) if len(self.files) > 1: - context.window_manager.session.replay_files.clear() + runtime_settings.replay_files.clear() context.scene.active_replay_file = len(self.files)-1 directory = Path(self.filepath).parent - for f in self.files: - snap = context.window_manager.session.replay_files.add() - snap.name = str(Path(directory, f['name'])) + file_list = [f['name'] for f in self.files] + file_list.sort() + for f in file_list: + snap = runtime_settings.replay_files.add() + snap.name = str(Path(directory, f)) + print(f) - if context.window_manager.session.replay_mode == 'TIMELINE': + if runtime_settings.replay_mode == 'TIMELINE': replay_action = bpy.data.actions.get('replay_action', bpy.data.actions.new('replay_action')) bpy.context.scene.animation_data_create() @@ -1108,9 +1114,12 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper): for p in reversed(replay_fcurve.keyframe_points): replay_fcurve.keyframe_points.remove(p, fast=True) - intrv = context.window_manager.session.replay_interval - for frame in range(0, len(self.files)-1): - replay_fcurve.keyframe_points.insert(frame * intrv, frame) + duration = runtime_settings.replay_duration + file_count = len(self.files)-1 + for index in range(0, file_count): + frame = interp(index, [0, file_count], [bpy.context.scene.frame_start, duration]) + replay_fcurve.keyframe_points.insert(frame, index) + if self.draw_users: f = gzip.open(self.filepath, "rb") @@ -1124,15 +1133,27 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper): if metadata: draw_user(username, metadata, radius=self.user_skin_radius, intensity=self.user_color_intensity) + # Relink the persistent collection if self.replay and persistent_collection: logging.info(f"Relinking {persistent_collection.name}") bpy.context.scene.collection.children.link(persistent_collection) + # Reasign scene action if self.replay and \ - context.window_manager.session.replay_mode == 'TIMELINE' and \ + runtime_settings.replay_mode == 'TIMELINE' and \ not bpy.context.scene.animation_data : bpy.context.scene.animation_data_create() bpy.context.scene.animation_data.action = bpy.data.actions.get('replay_action') + bpy.context.scene.frame_end = runtime_settings.replay_duration + + # Reasign the scene camera + if self.replay and \ + runtime_settings.replay_persistent_collection and \ + runtime_settings.replay_camera: + bpy.context.scene.camera = runtime_settings.replay_camera + + + return {'FINISHED'} @classmethod diff --git a/multi_user/preferences.py b/multi_user/preferences.py index 4ac14cc..9afef6b 100644 --- a/multi_user/preferences.py +++ b/multi_user/preferences.py @@ -22,6 +22,7 @@ import bpy import string import re import os +from numpy import interp from pathlib import Path @@ -144,11 +145,11 @@ def set_replay_persistent_collection(self, value): def get_replay_persistent_collection(self): return self.get('replay_persistent_collection', False) -def set_replay_interval(self, value): - if hasattr(self, 'replay_interval'): - self["replay_interval"] = value +def set_replay_duration(self, value): + if hasattr(self, 'replay_duration'): + self["replay_duration"] = value else: - self.replay_interval = value + self.replay_duration = value # Update the animation fcurve replay_action = bpy.data.actions.get('replay_action') @@ -162,12 +163,14 @@ def set_replay_interval(self, value): for p in reversed(replay_fcurve.keyframe_points): replay_fcurve.keyframe_points.remove(p, fast=True) - intrv = bpy.context.window_manager.session.replay_interval - for frame in range(0, len(bpy.context.window_manager.session.replay_files)): - replay_fcurve.keyframe_points.insert((frame * intrv), frame) + bpy.context.scene.frame_end = value + files_count = len(bpy.context.window_manager.session.replay_files)-1 + for index in range(0, files_count): + frame = interp(index,[0, files_count],[bpy.context.scene.frame_start, value]) + replay_fcurve.keyframe_points.insert(frame, index) -def get_replay_interval(self): - return self.get('replay_interval', 10) +def get_replay_duration(self): + return self.get('replay_duration', 10) def get_log_level(self): return logging.getLogger().level @@ -773,17 +776,20 @@ class SessionProps(bpy.types.PropertyGroup): ('TIMELINE', 'TIMELINE', 'Replay from the timeline.'), ('MANUAL', 'MANUAL', 'Replay manually, from the replay frame widget.')}, default='TIMELINE') - replay_interval: bpy.props.IntProperty( + replay_duration: bpy.props.IntProperty( name='replay interval', - default=10, - min=1, - set=set_replay_interval, - get=get_replay_interval, + default=250, + min=10, + set=set_replay_duration, + get=get_replay_duration, ) replay_frame_current: bpy.props.IntProperty( name='replay_frame_current', ) - + replay_camera: bpy.props.PointerProperty( + name='Replay camera', + type=bpy.types.Object + ) classes = ( diff --git a/multi_user/ui.py b/multi_user/ui.py index a78ad3f..603520f 100644 --- a/multi_user/ui.py +++ b/multi_user/ui.py @@ -588,10 +588,13 @@ class SESSION_PT_replay(bpy.types.Panel): if settings.replay_mode == 'MANUAL': row.prop(bpy.context.scene, 'active_replay_file', text="Snapshot index") else: - row.prop(settings, 'replay_interval', text="interval (frame)") + row.prop(settings, 'replay_duration', text="Replay Duration") row= layout.row() row.prop(settings, 'replay_persistent_collection', text="persistent collection", toggle=True, icon='OUTLINER_COLLECTION') + if settings.replay_persistent_collection: + row= layout.row() + row.prop(settings, 'replay_camera', text="", icon='VIEW_CAMERA') class SESSION_PT_repository(bpy.types.Panel): bl_idname = "MULTIUSER_PROPERTIES_PT_panel"