feat: snap time operator

feat: snap operators status

It's now possible to snap to others user time's !

Related to #53.
This commit is contained in:
Swann Martinez
2020-01-22 16:17:48 +01:00
parent 44e525aec7
commit 8b7716ac3c
5 changed files with 114 additions and 18 deletions

View File

@ -177,6 +177,12 @@ class SessionProps(bpy.types.PropertyGroup):
description='Show only owned datablocks', description='Show only owned datablocks',
default=True default=True
) )
user_snap_running: bpy.props.BoolProperty(
default=False
)
time_snap_running: bpy.props.BoolProperty(
default=False
)
def load(self): def load(self):
config = environment.load_config() config = environment.load_config()

View File

@ -237,6 +237,7 @@ class ClientUpdate(Timer):
settings.client_color.g, settings.client_color.g,
settings.client_color.b, settings.client_color.b,
1), 1),
'frame_current':bpy.context.scene.frame_current
} }
session.update_user_metadata(metadata) session.update_user_metadata(metadata)
elif current_view_corners != local_user_metadata['view_corners']: elif current_view_corners != local_user_metadata['view_corners']:

View File

@ -36,6 +36,7 @@ modal_executor_queue = None
# OPERATORS # OPERATORS
class SessionStartOperator(bpy.types.Operator): class SessionStartOperator(bpy.types.Operator):
bl_idname = "session.start" bl_idname = "session.start"
bl_label = "start" bl_label = "start"
@ -86,8 +87,6 @@ class SessionStartOperator(bpy.types.Operator):
client = Session(factory=bpy_factory) client = Session(factory=bpy_factory)
if self.host: if self.host:
# Scene setup # Scene setup
if settings.start_empty: if settings.start_empty:
@ -254,6 +253,14 @@ class SessionSnapUserOperator(bpy.types.Operator):
def execute(self, context): def execute(self, context):
wm = context.window_manager wm = context.window_manager
settings = context.window_manager.session
if settings.time_snap_running:
settings.time_snap_running = False
return {'CANCELLED'}
else:
settings.time_snap_running = True
self._timer = wm.event_timer_add(0.1, window=context.window) self._timer = wm.event_timer_add(0.1, window=context.window)
wm.modal_handler_add(self) wm.modal_handler_add(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
@ -263,7 +270,9 @@ class SessionSnapUserOperator(bpy.types.Operator):
wm.event_timer_remove(self._timer) wm.event_timer_remove(self._timer)
def modal(self, context, event): def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}: is_running = context.window_manager.session.time_snap_running
if event.type in {'RIGHTMOUSE', 'ESC'} or not is_running:
self.cancel(context) self.cancel(context)
return {'CANCELLED'} return {'CANCELLED'}
@ -283,6 +292,58 @@ class SessionSnapUserOperator(bpy.types.Operator):
return {'PASS_THROUGH'} return {'PASS_THROUGH'}
class SessionSnapTimeOperator(bpy.types.Operator):
bl_idname = "session.snaptime"
bl_label = "snap to user time"
bl_description = "Snap time to selected user time's"
bl_options = {"REGISTER"}
_timer = None
target_client: bpy.props.StringProperty(default="None")
@classmethod
def poll(cls, context):
return True
def execute(self, context):
settings = context.window_manager.session
if settings.user_snap_running:
settings.user_snap_running = False
return {'CANCELLED'}
else:
settings.user_snap_running = True
wm = context.window_manager
self._timer = wm.event_timer_add(0.1, window=context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
def modal(self, context, event):
is_running = context.window_manager.session.user_snap_running
if event.type in {'RIGHTMOUSE', 'ESC'} or not is_running:
self.cancel(context)
return {'CANCELLED'}
if event.type == 'TIMER':
global client
if client:
target_ref = client.online_users.get(self.target_client)
if target_ref:
context.scene.frame_current = target_ref['metadata']['frame_current']
else:
return {"CANCELLED"}
return {'PASS_THROUGH'}
class SessionApply(bpy.types.Operator): class SessionApply(bpy.types.Operator):
bl_idname = "session.apply" bl_idname = "session.apply"
bl_label = "apply selected block into blender" bl_label = "apply selected block into blender"
@ -372,12 +433,16 @@ classes = (
SessionStopOperator, SessionStopOperator,
SessionPropertyRemoveOperator, SessionPropertyRemoveOperator,
SessionSnapUserOperator, SessionSnapUserOperator,
SessionSnapTimeOperator,
SessionPropertyRightOperator, SessionPropertyRightOperator,
SessionApply, SessionApply,
SessionCommit, SessionCommit,
ApplyArmatureOperator, ApplyArmatureOperator,
) )
@persistent @persistent
def load_pre_handler(dummy): def load_pre_handler(dummy):
global client global client
@ -385,6 +450,7 @@ def load_pre_handler(dummy):
if client and client.state in [STATE_ACTIVE, STATE_SYNCING]: if client and client.state in [STATE_ACTIVE, STATE_SYNCING]:
bpy.ops.session.stop() bpy.ops.session.stop()
@persistent @persistent
def sanitize_deps_graph(dummy): def sanitize_deps_graph(dummy):
"""sanitize deps graph """sanitize deps graph
@ -399,6 +465,15 @@ def sanitize_deps_graph(dummy):
for node_key in client.list(): for node_key in client.list():
client.get(node_key).resolve() client.get(node_key).resolve()
@persistent
def update_client_frame(scene):
if client and client.state == STATE_ACTIVE:
client.update_user_metadata({
'frame_current': scene.frame_current
})
def register(): def register():
from bpy.utils import register_class from bpy.utils import register_class
for cls in classes: for cls in classes:
@ -409,6 +484,9 @@ def register():
bpy.app.handlers.undo_post.append(sanitize_deps_graph) bpy.app.handlers.undo_post.append(sanitize_deps_graph)
bpy.app.handlers.redo_post.append(sanitize_deps_graph) bpy.app.handlers.redo_post.append(sanitize_deps_graph)
bpy.app.handlers.frame_change_pre.append(update_client_frame)
def unregister(): def unregister():
global client global client
@ -425,5 +503,8 @@ def unregister():
bpy.app.handlers.undo_post.remove(sanitize_deps_graph) bpy.app.handlers.undo_post.remove(sanitize_deps_graph)
bpy.app.handlers.redo_post.remove(sanitize_deps_graph) bpy.app.handlers.redo_post.remove(sanitize_deps_graph)
bpy.app.handlers.frame_change_pre.remove(update_client_frame)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@ -198,11 +198,18 @@ class SESSION_PT_user(bpy.types.Panel):
if active_user != 0 and active_user.username != settings.username: if active_user != 0 and active_user.username != settings.username:
row = layout.row() row = layout.row()
user_operations = row.split() user_operations = row.split()
user_operations.alert = context.window_manager.session.time_snap_running
user_operations.operator( user_operations.operator(
"session.snapview", "session.snapview",
text="", text="",
icon='VIEW_CAMERA').target_client = active_user.username icon='VIEW_CAMERA').target_client = active_user.username
user_operations.alert = context.window_manager.session.user_snap_running
user_operations.operator(
"session.snaptime",
text="",
icon='TIME').target_client = active_user.username
class SESSION_UL_users(bpy.types.UIList): class SESSION_UL_users(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
@ -210,17 +217,18 @@ class SESSION_UL_users(bpy.types.UIList):
settings = context.window_manager.session settings = context.window_manager.session
is_local_user = item.username == settings.username is_local_user = item.username == settings.username
ping = '-' ping = '-'
frame_current = '-'
if session: if session:
users = session.online_users user = session.online_users.get(item.username)
for user, user_stat in users.items(): if user:
if item.username in user: ping = str(user['latency'])
ping = str(user_stat['latency']) metadata = user.get('metadata')
break if metadata:
frame_current = str(metadata['frame_current'])
split = layout.split(factor=0.5) split = layout.split(factor=0.5)
split.label(text=item.username) split.label(text=item.username)
split.label(text=str(item.current_frame)) split.label(text=frame_current)
split.label(text=ping) split.label(text=ping)