refactor: porcail api
This commit is contained in:
parent
0e73af4d49
commit
93d50ac56b
@ -59,6 +59,7 @@ background_execution_queue = Queue()
|
|||||||
deleyables = []
|
deleyables = []
|
||||||
stop_modal_executor = False
|
stop_modal_executor = False
|
||||||
|
|
||||||
|
|
||||||
def session_callback(name):
|
def session_callback(name):
|
||||||
""" Session callback wrapper
|
""" Session callback wrapper
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ def initialize_session():
|
|||||||
logging.error(f"Can't construct node {node}")
|
logging.error(f"Can't construct node {node}")
|
||||||
elif node_ref.state == FETCHED:
|
elif node_ref.state == FETCHED:
|
||||||
node_ref.resolve()
|
node_ref.resolve()
|
||||||
|
|
||||||
# Step 2: Load nodes
|
# Step 2: Load nodes
|
||||||
logging.info("Loading nodes")
|
logging.info("Loading nodes")
|
||||||
for node in session.repository.list_ordered():
|
for node in session.repository.list_ordered():
|
||||||
@ -140,7 +141,8 @@ def on_connection_end(reason="none"):
|
|||||||
if isinstance(handler, logging.FileHandler):
|
if isinstance(handler, logging.FileHandler):
|
||||||
logger.removeHandler(handler)
|
logger.removeHandler(handler)
|
||||||
if reason != "user":
|
if reason != "user":
|
||||||
bpy.ops.session.notify('INVOKE_DEFAULT', message=f"Disconnected from session. Reason: {reason}. ")
|
bpy.ops.session.notify(
|
||||||
|
'INVOKE_DEFAULT', message=f"Disconnected from session. Reason: {reason}. ")
|
||||||
|
|
||||||
|
|
||||||
# OPERATORS
|
# OPERATORS
|
||||||
@ -190,8 +192,8 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
bpy_protocol = io_bpy.get_data_translation_protocol()
|
bpy_protocol = io_bpy.get_data_translation_protocol()
|
||||||
|
|
||||||
# Check if supported_datablocks are up to date before starting the
|
# Check if supported_datablocks are up to date before starting the
|
||||||
# the session
|
# the session
|
||||||
for impl in bpy_protocol.implementations.values():
|
for impl in bpy_protocol.implementations.values():
|
||||||
if impl.__name__ not in settings.supported_datablocks:
|
if impl.__name__ not in settings.supported_datablocks:
|
||||||
@ -205,78 +207,61 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
else:
|
else:
|
||||||
python_binary_path = bpy.app.binary_path_python
|
python_binary_path = bpy.app.binary_path_python
|
||||||
|
|
||||||
# Host a session
|
# HOST
|
||||||
if self.host:
|
if self.host:
|
||||||
if settings.init_method == 'EMPTY':
|
if settings.init_method == 'EMPTY':
|
||||||
utils.clean_scene()
|
utils.clean_scene()
|
||||||
|
|
||||||
try:
|
# Start the server locally
|
||||||
# Init repository
|
server = porcelain.serve(port=settings.port,
|
||||||
for scene in bpy.data.scenes:
|
timeout=settings.connection_timeout,
|
||||||
porcelain.add(repo, scene)
|
admin_password=admin_pass,
|
||||||
|
log_directory=settings.cache_directory)
|
||||||
# Create an empty repository
|
|
||||||
repo = Repository(
|
|
||||||
data_protocol=bpy_protocol)
|
|
||||||
|
|
||||||
session.host(
|
# Init repository
|
||||||
repository= repo,
|
repo = porcelain.init(bare=False,
|
||||||
id=settings.username,
|
data_protocol=bpy_protocol)
|
||||||
port=settings.port,
|
|
||||||
timeout=settings.connection_timeout,
|
# Add the existing scenes
|
||||||
password=admin_pass,
|
for scene in bpy.data.scenes:
|
||||||
cache_directory=settings.cache_directory,
|
porcelain.add(repo, scene)
|
||||||
server_log_level=logging.getLevelName(
|
|
||||||
logging.getLogger().level),
|
porcelain.remote_add(repo,
|
||||||
)
|
'server',
|
||||||
except Exception as e:
|
'127.0.0.1',
|
||||||
self.report({'ERROR'}, repr(e))
|
settings.port)
|
||||||
logging.error(f"Error: {e}")
|
porcelain.sync(repo, 'server')
|
||||||
traceback.print_exc()
|
porcelain.push(repo, 'server')
|
||||||
# Join a session
|
# JOIN
|
||||||
else:
|
else:
|
||||||
if not runtime_settings.admin:
|
utils.clean_scene()
|
||||||
utils.clean_scene()
|
|
||||||
# regular session, no password needed
|
|
||||||
admin_pass = None
|
|
||||||
|
|
||||||
try:
|
repo = porcelain.clone(settings.ip, settings.ip)
|
||||||
session.connect(
|
|
||||||
repository= repo,
|
|
||||||
id=settings.username,
|
|
||||||
address=settings.ip,
|
|
||||||
port=settings.port,
|
|
||||||
timeout=settings.connection_timeout,
|
|
||||||
password=admin_pass
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self.report({'ERROR'}, str(e))
|
|
||||||
logging.error(str(e))
|
|
||||||
|
|
||||||
# Background client updates service
|
# Background client updates service
|
||||||
deleyables.append(timers.ClientUpdate())
|
# deleyables.append(timers.ClientUpdate())
|
||||||
deleyables.append(timers.DynamicRightSelectTimer())
|
# deleyables.append(timers.DynamicRightSelectTimer())
|
||||||
deleyables.append(timers.ApplyTimer(timeout=settings.depsgraph_update_rate))
|
# deleyables.append(timers.ApplyTimer(
|
||||||
|
# timeout=settings.depsgraph_update_rate))
|
||||||
# deleyables.append(timers.PushTimer(
|
# deleyables.append(timers.PushTimer(
|
||||||
# queue=stagging,
|
# queue=stagging,
|
||||||
# timeout=settings.depsgraph_update_rate
|
# timeout=settings.depsgraph_update_rate
|
||||||
# ))
|
# ))
|
||||||
session_update = timers.SessionStatusUpdate()
|
# session_update = timers.SessionStatusUpdate()
|
||||||
session_user_sync = timers.SessionUserSync()
|
# session_user_sync = timers.SessionUserSync()
|
||||||
session_background_executor = timers.MainThreadExecutor(
|
# session_background_executor = timers.MainThreadExecutor(
|
||||||
execution_queue=background_execution_queue)
|
# execution_queue=background_execution_queue)
|
||||||
session_listen = timers.SessionListenTimer(timeout=0.001)
|
# session_listen = timers.SessionListenTimer(timeout=0.001)
|
||||||
|
|
||||||
session_listen.register()
|
# session_listen.register()
|
||||||
session_update.register()
|
# session_update.register()
|
||||||
session_user_sync.register()
|
# session_user_sync.register()
|
||||||
session_background_executor.register()
|
# session_background_executor.register()
|
||||||
|
|
||||||
deleyables.append(session_background_executor)
|
# deleyables.append(session_background_executor)
|
||||||
deleyables.append(session_update)
|
# deleyables.append(session_update)
|
||||||
deleyables.append(session_user_sync)
|
# deleyables.append(session_user_sync)
|
||||||
deleyables.append(session_listen)
|
# deleyables.append(session_listen)
|
||||||
|
|
||||||
|
|
||||||
self.report(
|
self.report(
|
||||||
{'INFO'},
|
{'INFO'},
|
||||||
@ -589,20 +574,20 @@ class SessionApply(bpy.types.Operator):
|
|||||||
try:
|
try:
|
||||||
node_ref = session.repository.get_node(self.target)
|
node_ref = session.repository.get_node(self.target)
|
||||||
porcelain.apply(session.repository,
|
porcelain.apply(session.repository,
|
||||||
self.target,
|
self.target,
|
||||||
force=True,
|
force=True,
|
||||||
force_dependencies=self.reset_dependencies)
|
force_dependencies=self.reset_dependencies)
|
||||||
if node_ref.bl_reload_parent:
|
if node_ref.bl_reload_parent:
|
||||||
for parent in session.repository.get_parents(self.target):
|
for parent in session.repository.get_parents(self.target):
|
||||||
logging.debug(f"Refresh parent {parent}")
|
logging.debug(f"Refresh parent {parent}")
|
||||||
|
|
||||||
porcelain.apply(session.repository,
|
porcelain.apply(session.repository,
|
||||||
parent.uuid,
|
parent.uuid,
|
||||||
force=True)
|
force=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@ -628,6 +613,7 @@ class SessionCommit(bpy.types.Operator):
|
|||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
return {"CANCELED"}
|
return {"CANCELED"}
|
||||||
|
|
||||||
|
|
||||||
class ApplyArmatureOperator(bpy.types.Operator):
|
class ApplyArmatureOperator(bpy.types.Operator):
|
||||||
"""Operator which runs its self from a timer"""
|
"""Operator which runs its self from a timer"""
|
||||||
bl_idname = "session.apply_armature_operator"
|
bl_idname = "session.apply_armature_operator"
|
||||||
@ -699,6 +685,7 @@ class SessionClearCache(bpy.types.Operator):
|
|||||||
row = self.layout
|
row = self.layout
|
||||||
row.label(text=f" Do you really want to remove local cache ? ")
|
row.label(text=f" Do you really want to remove local cache ? ")
|
||||||
|
|
||||||
|
|
||||||
class SessionPurgeOperator(bpy.types.Operator):
|
class SessionPurgeOperator(bpy.types.Operator):
|
||||||
"Remove node with lost references"
|
"Remove node with lost references"
|
||||||
bl_idname = "session.purge"
|
bl_idname = "session.purge"
|
||||||
@ -743,7 +730,6 @@ class SessionNotifyOperator(bpy.types.Operator):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.row().label(text=self.message)
|
layout.row().label(text=self.message)
|
||||||
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
@ -789,6 +775,7 @@ class SessionSaveBackupOperator(bpy.types.Operator, ExportHelper):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return session.state == STATE_ACTIVE
|
return session.state == STATE_ACTIVE
|
||||||
|
|
||||||
|
|
||||||
class SessionStopAutoSaveOperator(bpy.types.Operator):
|
class SessionStopAutoSaveOperator(bpy.types.Operator):
|
||||||
bl_idname = "session.cancel_autosave"
|
bl_idname = "session.cancel_autosave"
|
||||||
bl_label = "Cancel auto-save"
|
bl_label = "Cancel auto-save"
|
||||||
@ -829,15 +816,13 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
except OSError as e:
|
except OSError as e:
|
||||||
f = open(self.filepath, "rb")
|
f = open(self.filepath, "rb")
|
||||||
db = pickle.load(f)
|
db = pickle.load(f)
|
||||||
|
|
||||||
if db:
|
if db:
|
||||||
logging.info(f"Reading {self.filepath}")
|
logging.info(f"Reading {self.filepath}")
|
||||||
nodes = db.get("nodes")
|
nodes = db.get("nodes")
|
||||||
|
|
||||||
logging.info(f"{len(nodes)} Nodes to load")
|
logging.info(f"{len(nodes)} Nodes to load")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# init the factory with supported types
|
# init the factory with supported types
|
||||||
bpy_protocol = DataTranslationProtocol()
|
bpy_protocol = DataTranslationProtocol()
|
||||||
for type in io_bpy.types_to_register():
|
for type in io_bpy.types_to_register():
|
||||||
@ -846,11 +831,10 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
type_impl_name = 'Bl'+''.join(name)
|
type_impl_name = 'Bl'+''.join(name)
|
||||||
type_module_class = getattr(type_module, type_impl_name)
|
type_module_class = getattr(type_module, type_impl_name)
|
||||||
|
|
||||||
|
|
||||||
bpy_protocol.register_type(
|
bpy_protocol.register_type(
|
||||||
type_module_class.bl_class,
|
type_module_class.bl_class,
|
||||||
type_module_class)
|
type_module_class)
|
||||||
|
|
||||||
graph = Repository()
|
graph = Repository()
|
||||||
|
|
||||||
for node, node_data in nodes:
|
for node, node_data in nodes:
|
||||||
@ -866,7 +850,7 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
data=node_data['data'])
|
data=node_data['data'])
|
||||||
graph.do_commit(instance)
|
graph.do_commit(instance)
|
||||||
instance.state = FETCHED
|
instance.state = FETCHED
|
||||||
|
|
||||||
logging.info("Graph succefully loaded")
|
logging.info("Graph succefully loaded")
|
||||||
|
|
||||||
utils.clean_scene()
|
utils.clean_scene()
|
||||||
@ -879,15 +863,16 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
for node in graph.list_ordered():
|
for node in graph.list_ordered():
|
||||||
graph[node].apply()
|
graph[node].apply()
|
||||||
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def menu_func_import(self, context):
|
def menu_func_import(self, context):
|
||||||
self.layout.operator(SessionLoadSaveOperator.bl_idname, text='Multi-user session snapshot (.db)')
|
self.layout.operator(SessionLoadSaveOperator.bl_idname,
|
||||||
|
text='Multi-user session snapshot (.db)')
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
@ -910,6 +895,7 @@ classes = (
|
|||||||
SessionPurgeOperator,
|
SessionPurgeOperator,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_external_dependencies():
|
def update_external_dependencies():
|
||||||
nodes_ids = session.list(filter=io_bpy.bl_file.BlFile)
|
nodes_ids = session.list(filter=io_bpy.bl_file.BlFile)
|
||||||
for node_id in nodes_ids:
|
for node_id in nodes_ids:
|
||||||
@ -919,6 +905,7 @@ def update_external_dependencies():
|
|||||||
porcelain.commit(session.repository, node_id)
|
porcelain.commit(session.repository, node_id)
|
||||||
session.push(node_id, check_data=False)
|
session.push(node_id, check_data=False)
|
||||||
|
|
||||||
|
|
||||||
def sanitize_deps_graph(remove_nodes: bool = False):
|
def sanitize_deps_graph(remove_nodes: bool = False):
|
||||||
""" Cleanup the replication graph
|
""" Cleanup the replication graph
|
||||||
"""
|
"""
|
||||||
@ -950,6 +937,7 @@ def resolve_deps_graph(dummy):
|
|||||||
if session and session.state == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
sanitize_deps_graph(remove_nodes=True)
|
sanitize_deps_graph(remove_nodes=True)
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def load_pre_handler(dummy):
|
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]:
|
||||||
@ -980,7 +968,7 @@ def depsgraph_evaluation(scene):
|
|||||||
if update.id.uuid:
|
if update.id.uuid:
|
||||||
# Retrieve local version
|
# Retrieve local version
|
||||||
node = session.repository.get_node(update.id.uuid)
|
node = session.repository.get_node(update.id.uuid)
|
||||||
|
|
||||||
# Check our right on this update:
|
# Check our right on this update:
|
||||||
# - if its ours or ( under common and diff), launch the
|
# - if its ours or ( under common and diff), launch the
|
||||||
# update process
|
# update process
|
||||||
@ -994,12 +982,12 @@ def depsgraph_evaluation(scene):
|
|||||||
except ReferenceError:
|
except ReferenceError:
|
||||||
logging.debug(f"Reference error {node.uuid}")
|
logging.debug(f"Reference error {node.uuid}")
|
||||||
except ContextError as e:
|
except ContextError as e:
|
||||||
logging.debug(e)
|
logging.debug(e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
# A new scene is created
|
# A new scene is created
|
||||||
elif isinstance(update.id, bpy.types.Scene):
|
elif isinstance(update.id, bpy.types.Scene):
|
||||||
ref = session.repository.get_node_by_datablock(update.id)
|
ref = session.repository.get_node_by_datablock(update.id)
|
||||||
if ref:
|
if ref:
|
||||||
@ -1008,13 +996,14 @@ def depsgraph_evaluation(scene):
|
|||||||
scn_uuid = porcelain.add(session.repository, update.id)
|
scn_uuid = porcelain.add(session.repository, update.id)
|
||||||
porcelain.commit(session.repository, scn_uuid)
|
porcelain.commit(session.repository, scn_uuid)
|
||||||
porcelain.push(session.repository)
|
porcelain.push(session.repository)
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
from bpy.utils import register_class
|
from bpy.utils import register_class
|
||||||
|
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
register_class(cls)
|
register_class(cls)
|
||||||
|
|
||||||
|
|
||||||
bpy.app.handlers.undo_post.append(resolve_deps_graph)
|
bpy.app.handlers.undo_post.append(resolve_deps_graph)
|
||||||
bpy.app.handlers.redo_post.append(resolve_deps_graph)
|
bpy.app.handlers.redo_post.append(resolve_deps_graph)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user