refactor: move clean to operator.py

feat: timeline action mapping for replay
feat: persistent  collection
fix: draw users in the right scene according to the snapshot
This commit is contained in:
Swann 2021-12-08 16:30:40 +01:00
parent 8d15e69b50
commit 0e20d35e7d

View File

@ -67,10 +67,49 @@ deleyables = []
stop_modal_executor = False
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']
PERSISTENT_DATABLOCKS = ['LineStyle', 'Dots Stroke', 'replay_action']
def clean_scene(ignored_datablocks: list = None):
"""
Delete all datablock of the scene except PERSISTENT_DATABLOCKS and ignored
ones in ignored_datablocks.
"""
PERSISTENT_DATABLOCKS.extend(ignored_datablocks)
# Avoid to trigger a runtime error by keeping the last scene
PERSISTENT_DATABLOCKS.append(bpy.data.scenes[0].name)
for type_name in CLEARED_DATABLOCKS:
type_collection = getattr(bpy.data, type_name)
for datablock in type_collection:
if datablock.name in PERSISTENT_DATABLOCKS:
logging.debug(f"Skipping {datablock.name}")
continue
else:
logging.debug(f"Removing {datablock.name}")
type_collection.remove(datablock)
# Clear sequencer
bpy.context.scene.sequence_editor_clear()
def draw_user(username, metadata, radius=0.01, intensity=10.0):
"""
Generate a mesh representation of a given user frustum and
sight of view.
"""
view_corners = metadata.get('view_corners')
color = metadata.get('color', (1,1,1,0))
objects = metadata.get('selected_objects', None)
scene = metadata.get('scene_current', bpy.context.scene.name)
user_collection = bpy.data.collections.new(username)
@ -176,7 +215,7 @@ def draw_user(username, metadata, radius=0.01, intensity=10.0):
bbox_mesh.materials.append(user_mat)
bpy.context.scene.collection.children.link(user_collection)
bpy.data.scenes[scene].collection.children.link(user_collection)
def session_callback(name):
@ -363,7 +402,7 @@ class SessionConnectOperator(bpy.types.Operator):
# Join a session
if not active_server.use_admin_password:
utils.clean_scene()
clean_scene()
try:
porcelain.remote_add(
@ -434,7 +473,7 @@ class SessionHostOperator(bpy.types.Operator):
# Host a session
if settings.init_method == 'EMPTY':
utils.clean_scene()
clean_scene()
try:
# Init repository
@ -498,7 +537,7 @@ class SessionInitOperator(bpy.types.Operator):
def execute(self, context):
if self.init_method == 'EMPTY':
utils.clean_scene()
clean_scene()
for scene in bpy.data.scenes:
porcelain.add(session.repository, scene)
@ -982,6 +1021,13 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
description="Draw users in the scene",
default=False,
)
replay: bpy.props.BoolProperty(
name="Replay mode",
description="Enable replay functions",
default=False,
)
user_skin_radius: bpy.props.FloatProperty(
name="Wireframe radius",
description="Wireframe radius",
@ -995,19 +1041,38 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
files: bpy.props.CollectionProperty(
name='File paths',
type=bpy.types.OperatorFileListElement)
type=bpy.types.OperatorFileListElement
)
def draw(self, context):
pass
def execute(self, context):
from replication.repository import Repository
# init the factory with supported types
bpy_protocol = bl_types.get_data_translation_protocol()
repo = Repository(bpy_protocol)
repo.loads(self.filepath)
utils.clean_scene()
# Persitstent collection
ignored_datablocks = []
persistent_collection = bpy.data.collections.get("multiuser_timelapse")
if self.replay and \
context.window_manager.session.replay_persistent_collection and \
persistent_collection:
collection_repo = Repository(
rdp=bpy_protocol,
username="None")
porcelain.add(collection_repo, persistent_collection)
porcelain.commit(collection_repo, persistent_collection.uuid)
for node in collection_repo.graph.values():
ignored_datablocks.append(node.data.get('name'))
clean_scene(ignored_datablocks=ignored_datablocks)
nodes = [repo.graph.get(n) for n in repo.index_sorted]
@ -1029,7 +1094,24 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
for f in self.files:
snap = context.window_manager.session.replay_files.add()
snap.name = str(Path(directory, f['name']))
if context.window_manager.session.replay_mode == 'TIMELINE':
replay_action = bpy.data.actions.get('replay_action', bpy.data.actions.new('replay_action'))
bpy.context.scene.animation_data_create()
bpy.context.scene.animation_data.action = replay_action
if len(replay_action.fcurves) > 0 and replay_action.fcurves[0].data_path == 'active_replay_file':
replay_fcurve = replay_action.fcurves[0]
else:
replay_fcurve = replay_action.fcurves.new('active_replay_file')
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)
if self.draw_users:
f = gzip.open(self.filepath, "rb")
db = pickle.load(f)
@ -1042,6 +1124,15 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
if metadata:
draw_user(username, metadata, radius=self.user_skin_radius, intensity=self.user_color_intensity)
if self.replay and persistent_collection:
logging.info(f"Relinking {persistent_collection.name}")
bpy.context.scene.collection.children.link(persistent_collection)
if self.replay and \
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')
return {'FINISHED'}
@classmethod