feat: previous message
This commit is contained in:
@ -130,14 +130,29 @@ def load_pre_handler(dummy):
|
|||||||
if session and session.state in [STATE_ACTIVE, STATE_SYNCING]:
|
if session and session.state in [STATE_ACTIVE, STATE_SYNCING]:
|
||||||
bpy.ops.session.stop()
|
bpy.ops.session.stop()
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def update_client_frame(scene):
|
def update_client_frame(scene):
|
||||||
|
setting = bpy.context.window_manager.session
|
||||||
|
if setting.replay_mode == 'TIMELINE' and \
|
||||||
|
setting.replay_files and \
|
||||||
|
scene.active_replay_file != setting.replay_frame_current :
|
||||||
|
index = bpy.context.scene.active_replay_file
|
||||||
|
bpy.ops.session.load(filepath=bpy.context.window_manager.session.replay_files[index].name,
|
||||||
|
draw_users=True,
|
||||||
|
replay=True)
|
||||||
|
setting.replay_frame_current = index
|
||||||
|
|
||||||
if session and session.state == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
porcelain.update_user_metadata(session.repository, {
|
porcelain.update_user_metadata(session.repository, {
|
||||||
'frame_current': scene.frame_current
|
'frame_current': scene.frame_current
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def post_frame_update(scene):
|
||||||
|
if bpy.context.window_manager.session.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')
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.app.handlers.undo_post.append(resolve_deps_graph)
|
bpy.app.handlers.undo_post.append(resolve_deps_graph)
|
||||||
|
@ -115,15 +115,60 @@ def set_active_replay(self, value):
|
|||||||
else:
|
else:
|
||||||
self.active_replay_file = value
|
self.active_replay_file = value
|
||||||
|
|
||||||
# bpy.ops.session.load( )
|
if bpy.context.window_manager.session.replay_mode == 'MANUAL':
|
||||||
bpy.ops.session.load(
|
bpy.ops.session.load(
|
||||||
filepath=bpy.context.window_manager.session.replay_files[value].name,
|
filepath=bpy.context.window_manager.session.replay_files[value].name,
|
||||||
draw_users=True)
|
draw_users=True,
|
||||||
|
replay=True)
|
||||||
|
|
||||||
def get_active_replay(self):
|
def get_active_replay(self):
|
||||||
return self.get('active_replay_file', 0)
|
return self.get('active_replay_file', 0)
|
||||||
|
|
||||||
|
|
||||||
|
def set_replay_persistent_collection(self, value):
|
||||||
|
if hasattr(self, 'replay_persistent_collection'):
|
||||||
|
self["replay_persistent_collection"] = value
|
||||||
|
else:
|
||||||
|
self.replay_persistent_collection = value
|
||||||
|
|
||||||
|
collection = bpy.data.collections.get("multiuser_timelapse", None)
|
||||||
|
|
||||||
|
if collection is None and value:
|
||||||
|
collection = bpy.data.collections.new('multiuser_timelapse')
|
||||||
|
bpy.context.scene.collection.children.link(collection)
|
||||||
|
elif collection and not value:
|
||||||
|
for o in collection.objects:
|
||||||
|
bpy.data.objects.remove(o)
|
||||||
|
bpy.data.collections.remove(collection)
|
||||||
|
|
||||||
|
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
|
||||||
|
else:
|
||||||
|
self.replay_interval = value
|
||||||
|
|
||||||
|
# Update the animation fcurve
|
||||||
|
replay_action = bpy.data.actions.get('replay_action')
|
||||||
|
replay_fcurve = None
|
||||||
|
|
||||||
|
for fcurve in replay_action.fcurves:
|
||||||
|
if fcurve.data_path == 'active_replay_file':
|
||||||
|
replay_fcurve = fcurve
|
||||||
|
|
||||||
|
if replay_fcurve:
|
||||||
|
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)
|
||||||
|
|
||||||
|
def get_replay_interval(self):
|
||||||
|
return self.get('replay_interval', 10)
|
||||||
|
|
||||||
def get_log_level(self):
|
def get_log_level(self):
|
||||||
return logging.getLogger().level
|
return logging.getLogger().level
|
||||||
|
|
||||||
@ -715,14 +760,28 @@ class SessionProps(bpy.types.PropertyGroup):
|
|||||||
name='File paths',
|
name='File paths',
|
||||||
type=bpy.types.OperatorFileListElement
|
type=bpy.types.OperatorFileListElement
|
||||||
)
|
)
|
||||||
active_replay_file: bpy.props.IntProperty(
|
replay_persistent_collection: bpy.props.BoolProperty(
|
||||||
name="active_replay_file",
|
name="replay_persistent_collection",
|
||||||
default=0,
|
description='Enable a collection that persist accross frames loading',
|
||||||
min=0,
|
get=get_replay_persistent_collection,
|
||||||
description='Active snapshot',
|
set=set_replay_persistent_collection,
|
||||||
set=set_active_replay,
|
)
|
||||||
get=get_active_replay,
|
replay_mode: bpy.props.EnumProperty(
|
||||||
options={'ANIMATABLE'}
|
name='replay method',
|
||||||
|
description='Replay in keyframe (timeline) or manually',
|
||||||
|
items={
|
||||||
|
('TIMELINE', 'TIMELINE', 'Replay from the timeline.'),
|
||||||
|
('MANUAL', 'MANUAL', 'Replay manually, from the replay frame widget.')},
|
||||||
|
default='TIMELINE')
|
||||||
|
replay_interval: bpy.props.IntProperty(
|
||||||
|
name='replay interval',
|
||||||
|
default=10,
|
||||||
|
min=1,
|
||||||
|
set=set_replay_interval,
|
||||||
|
get=get_replay_interval,
|
||||||
|
)
|
||||||
|
replay_frame_current: bpy.props.IntProperty(
|
||||||
|
name='replay_frame_current',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -581,10 +581,16 @@ class SESSION_PT_replay(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
settings = context.window_manager.session
|
||||||
row= layout.row()
|
row= layout.row()
|
||||||
|
row.prop(settings,'replay_mode', toggle=True, expand=True)
|
||||||
row.prop(bpy.context.scene, 'active_replay_file')
|
row= layout.row()
|
||||||
|
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= layout.row()
|
||||||
|
row.prop(settings, 'replay_persistent_collection', text="persistent collection", toggle=True, icon='OUTLINER_COLLECTION')
|
||||||
|
|
||||||
|
|
||||||
class SESSION_PT_repository(bpy.types.Panel):
|
class SESSION_PT_repository(bpy.types.Panel):
|
||||||
|
@ -38,15 +38,6 @@ from replication.constants import (STATE_ACTIVE, STATE_AUTH,
|
|||||||
STATE_LOBBY,
|
STATE_LOBBY,
|
||||||
CONNECTING)
|
CONNECTING)
|
||||||
|
|
||||||
CLEARED_DATABLOCKS = ['actions', 'armatures', 'cache_files', 'cameras',
|
|
||||||
'collections', 'curves', 'filepath', 'fonts',
|
|
||||||
'grease_pencils', 'images', 'lattices', 'libraries',
|
|
||||||
'lightprobes', 'lights', 'linestyles', 'masks',
|
|
||||||
'materials', 'meshes', 'metaballs', 'movieclips',
|
|
||||||
'node_groups', 'objects', 'paint_curves', 'particles',
|
|
||||||
'scenes', 'shape_keys', 'sounds', 'speakers', 'texts',
|
|
||||||
'textures', 'volumes', 'worlds']
|
|
||||||
|
|
||||||
def find_from_attr(attr_name, attr_value, list):
|
def find_from_attr(attr_name, attr_value, list):
|
||||||
for item in list:
|
for item in list:
|
||||||
if getattr(item, attr_name, None) == attr_value:
|
if getattr(item, attr_name, None) == attr_value:
|
||||||
@ -108,26 +99,6 @@ def get_state_str(state):
|
|||||||
return state_str
|
return state_str
|
||||||
|
|
||||||
|
|
||||||
def clean_scene():
|
|
||||||
for type_name in CLEARED_DATABLOCKS:
|
|
||||||
sub_collection_to_avoid = [
|
|
||||||
bpy.data.linestyles.get('LineStyle'),
|
|
||||||
bpy.data.materials.get('Dots Stroke')
|
|
||||||
]
|
|
||||||
|
|
||||||
type_collection = getattr(bpy.data, type_name)
|
|
||||||
items_to_remove = [i for i in type_collection if i not in sub_collection_to_avoid]
|
|
||||||
for item in items_to_remove:
|
|
||||||
try:
|
|
||||||
type_collection.remove(item)
|
|
||||||
logging.info(item.name)
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Clear sequencer
|
|
||||||
bpy.context.scene.sequence_editor_clear()
|
|
||||||
|
|
||||||
|
|
||||||
def get_selected_objects(scene, active_view_layer):
|
def get_selected_objects(scene, active_view_layer):
|
||||||
return [obj.uuid for obj in scene.objects if obj.select_get(view_layer=active_view_layer)]
|
return [obj.uuid for obj in scene.objects if obj.select_get(view_layer=active_view_layer)]
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user