refactor: use client metadata

This commit is contained in:
Swann Martinez
2020-01-22 14:33:34 +01:00
parent da5406952c
commit e253ccd52d
9 changed files with 66 additions and 158 deletions

View File

@ -57,22 +57,19 @@ def generate_supported_types():
def client_list_callback(scene, context): def client_list_callback(scene, context):
from . import operators from . import operators
from .bl_types.bl_user import BlUser
items = [(RP_COMMON, RP_COMMON, "")] items = [(RP_COMMON, RP_COMMON, "")]
username = bpy.context.window_manager.session.username username = bpy.context.window_manager.session.username
cli = operators.client cli = operators.client
if cli: if cli:
client_keys = cli.list(filter=BlUser) client_ids = cli.online_users.keys()
for k in client_keys: for id in client_ids:
name = cli.get(uuid=k).data["name"] name_desc = id
if id == username:
name_desc = name
if name == username:
name_desc += " (self)" name_desc += " (self)"
items.append((name, name_desc, "")) items.append((id, name_desc, ""))
return items return items

View File

@ -1,5 +1,4 @@
__all__ = [ __all__ = [
'bl_user',
'bl_object', 'bl_object',
'bl_mesh', 'bl_mesh',
'bl_camera', 'bl_camera',

View File

@ -1,64 +0,0 @@
import bpy
import mathutils
import jsondiff
from .. import utils
from .. import presence
from .bl_datablock import BlDatablock
from ..libs.replication.replication.constants import UP
class BlUser(BlDatablock):
bl_id = "users"
bl_class = presence.User
bl_delay_refresh = .1
bl_delay_apply = .1
bl_automatic_push = True
bl_icon = 'CON_ARMATURE'
def construct(self, data):
user = bpy.data.window_managers['WinMan'].online_users.add()
user.name = data['name']
user.username = data['name']
user.current_frame = data['current_frame']
def apply(self):
if self.pointer is None:
self.set_pointer()
self.load(self.data,self.pointer)
for obj in bpy.data.objects:
if obj.hide_select and obj.uuid not in self.data['selected_objects']:
obj.hide_select = False
elif not obj.hide_select and obj.uuid in self.data['selected_objects']:
obj.hide_select = True
presence.refresh_3d_view()
self.state = UP
def load(self, data, target):
target.current_frame = data['current_frame']
def dump(self, pointer=None):
data = utils.dump_anything.dump(pointer)
data['location'] = pointer.location
data['color'] = pointer.color
data['selected_objects'] = pointer.selected_objects
data['view_matrix'] = pointer.view_matrix
data['current_frame'] = bpy.context.scene.frame_current
return data
def update(self):
self.pointer.is_dirty = True
def resolve(self):
self.pointer = bpy.data.window_managers['WinMan'].online_users.get(self.data['name'])
def is_valid(self):
return True

View File

@ -3,10 +3,10 @@ import logging
import bpy import bpy
from . import operators, presence, utils from . import operators, presence, utils
from .bl_types.bl_user import BlUser
from .libs.replication.replication.constants import FETCHED, RP_COMMON from .libs.replication.replication.constants import FETCHED, RP_COMMON
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class Delayable(): class Delayable():
@ -83,7 +83,6 @@ class DynamicRightSelectTimer(Timer):
super().__init__(timout) super().__init__(timout)
self._last_selection = [] self._last_selection = []
self._user = None self._user = None
self._user_metadata = None
self._right_strategy = RP_COMMON self._right_strategy = RP_COMMON
def execute(self): def execute(self):
@ -94,7 +93,6 @@ class DynamicRightSelectTimer(Timer):
# Find user # Find user
if self._user is None: if self._user is None:
self._user = session.online_users.get(settings.username) self._user = session.online_users.get(settings.username)
self._user_metadata = self._user.get('metadata')
if self._right_strategy is None: if self._right_strategy is None:
self._right_strategy = session.get_config()[ self._right_strategy = session.get_config()[
@ -140,21 +138,25 @@ class DynamicRightSelectTimer(Timer):
return return
self._last_selection = current_selection self._last_selection = current_selection
self._user_metadata['selected_objects'] = current_selection
session.update_user_metadata(self._user_metadata) user_metadata = {
'selected_objects': current_selection
}
session.update_user_metadata(user_metadata)
logger.info("Update selection") logger.info("Update selection")
# Fix deselection until right managment refactoring (with Roles concepts) # Fix deselection until right managment refactoring (with Roles concepts)
if len(current_selection) == 0 and self._right_strategy == RP_COMMON: if len(current_selection) == 0 and self._right_strategy == RP_COMMON:
owned_keys = session.list( owned_keys = session.list(
filter_owner=settings.username) filter_owner=settings.username)
for key in owned_keys: for key in owned_keys:
node = session.get(uuid=key) node = session.get(uuid=key)
if not isinstance(node, BlUser):
session.change_owner( session.change_owner(
key, key,
RP_COMMON, RP_COMMON,
recursive=recursive) recursive=recursive)
for user, user_info in session.online_users.items(): for user, user_info in session.online_users.items():
if user != settings.username: if user != settings.username:
@ -190,8 +192,9 @@ class Draw(Delayable):
class DrawClient(Draw): class DrawClient(Draw):
def execute(self): def execute(self):
session = operators.client session = getattr(operators, 'client')
if session and presence.renderer: renderer = getattr(presence, 'renderer')
if session and renderer:
settings = bpy.context.window_manager.session settings = bpy.context.window_manager.session
users = session.online_users users = session.online_users
@ -199,10 +202,10 @@ class DrawClient(Draw):
metadata = user.get('metadata') metadata = user.get('metadata')
if settings.presence_show_selected and 'selected_objects' in metadata.keys(): if settings.presence_show_selected and 'selected_objects' in metadata.keys():
presence.renderer.draw_client_selection( renderer.draw_client_selection(
user['id'], metadata['color'], metadata['selected_objects']) user['id'], metadata['color'], metadata['selected_objects'])
if settings.presence_show_user and 'view_corners' in metadata: if settings.presence_show_user and 'view_corners' in metadata:
presence.renderer.draw_client_camera( renderer.draw_client_camera(
user['id'], metadata['view_corners'], metadata['color']) user['id'], metadata['view_corners'], metadata['color'])
@ -213,23 +216,31 @@ class ClientUpdate(Timer):
def execute(self): def execute(self):
settings = bpy.context.window_manager.session settings = bpy.context.window_manager.session
session_info = bpy.context.window_manager.session session_info = bpy.context.window_manager.session
session = operators.client session = getattr(operators, 'client')
if session: if session:
local_user = operators.client.online_users.get( local_user = operators.client.online_users.get(
session_info.username) session_info.username)
if not local_user:
return
metadata = { local_user_metadata = local_user.get('metadata')
'view_corners': presence.get_view_corners(), current_view_corners = presence.get_view_corners()
'view_matrix': presence.get_view_matrix(),
'color': (settings.client_color.r,
settings.client_color.g,
settings.client_color.b,
1),
}
session.update_user_metadata(metadata) if not local_user_metadata:
logger.info("init user metadata")
logger.info("{}".format(local_user)) metadata = {
'view_corners': current_view_corners,
'view_matrix': presence.get_view_matrix(),
'color': (settings.client_color.r,
settings.client_color.g,
settings.client_color.b,
1),
}
session.update_user_metadata(metadata)
elif current_view_corners != local_user_metadata['view_corners']:
logger.info('update user metadata')
local_user_metadata['view_corners'] = current_view_corners
session.update_user_metadata(local_user_metadata)
# sync online users # sync online users
session_users = operators.client.online_users session_users = operators.client.online_users
@ -240,7 +251,7 @@ class ClientUpdate(Timer):
ui_users.remove(index) ui_users.remove(index)
bpy.context.window_manager.session.presence_show_user = False bpy.context.window_manager.session.presence_show_user = False
bpy.context.window_manager.session.presence_show_user = True bpy.context.window_manager.session.presence_show_user = True
presence.refresh_3d_view()
break break
for user in session_users: for user in session_users:
@ -248,3 +259,6 @@ class ClientUpdate(Timer):
new_key = ui_users.add() new_key = ui_users.add()
new_key.name = user new_key.name = user
new_key.username = user new_key.username = user
# TODO: event drivent 3d view refresh
presence.refresh_3d_view()

View File

@ -36,7 +36,6 @@ 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"
@ -54,16 +53,15 @@ class SessionStartOperator(bpy.types.Operator):
users = bpy.data.window_managers['WinMan'].online_users users = bpy.data.window_managers['WinMan'].online_users
# TODO: Sync server clients # TODO: Sync server clients
users.clear() users.clear()
# save config # save config
settings.save(context) settings.save(context)
bpy_factory = ReplicatedDataFactory() bpy_factory = ReplicatedDataFactory()
supported_bl_types = [] supported_bl_types = []
ui_context = context.copy() ui_context = context.copy()
# init the factory with supported types # init the factory with supported types
for type in bl_types.types_to_register(): for type in bl_types.types_to_register():
type_module = getattr(bl_types, type) type_module = getattr(bl_types, type)
@ -88,6 +86,8 @@ 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:
@ -118,18 +118,6 @@ class SessionStartOperator(bpy.types.Operator):
"A session is already hosted on this address") "A session is already hosted on this address")
return {"CANCELLED"} return {"CANCELLED"}
# Init user settings
usr = presence.User(
username=settings.username,
color=(settings.client_color.r,
settings.client_color.g,
settings.client_color.b,
1),
)
settings.user_uuid = client.add(usr, owner=settings.username)
client.commit(settings.user_uuid)
if self.host: if self.host:
for scene in bpy.data.scenes: for scene in bpy.data.scenes:
scene_uuid = client.add(scene) scene_uuid = client.add(scene)

View File

@ -122,33 +122,6 @@ def get_view_matrix():
return matrix_dumper.dump(rv3d.view_matrix) return matrix_dumper.dump(rv3d.view_matrix)
class User():
def __init__(self, username=None, color=(0, 0, 0, 1)):
self.is_dirty = False
self.name = username
self.color = color
self.location = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
self.selected_objects = []
self.last_select_objects = []
self.view_matrix = None
def update_location(self):
current_coords = get_view_corners()
area, region, rv3d = view3d_find()
if area and region and rv3d:
current_coords = list(get_view_corners())
if current_coords and self.location != current_coords:
self.location = current_coords
matrix_dumper = utils.dump_anything.Dumper()
current_vm = matrix_dumper.dump(rv3d.view_matrix)
if self.view_matrix != current_vm:
self.view_matrix = current_vm
def update_selected_objects(self, context):
self.selected_objects = utils.get_selected_objects(context.scene)
def update_presence(self, context): def update_presence(self, context):
global renderer global renderer
@ -226,14 +199,14 @@ class DrawFactory(object):
self.d2d_items.clear() self.d2d_items.clear()
def draw_client_selection(self, client_uuid, client_color, client_selection): def draw_client_selection(self, client_id, client_color, client_selection):
local_user = bpy.context.window_manager.session.user_uuid local_user = bpy.context.window_manager.session.username
if local_user != client_uuid: if local_user != client_id:
self.flush_selection(client_uuid) self.flush_selection(client_id)
for select_ob in client_selection: for select_ob in client_selection:
drawable_key = "{}_select_{}".format(client_uuid, select_ob) drawable_key = "{}_select_{}".format(client_id, select_ob)
ob = utils.find_from_attr("uuid", select_ob, bpy.data.objects) ob = utils.find_from_attr("uuid", select_ob, bpy.data.objects)
if not ob: if not ob:
@ -282,11 +255,11 @@ class DrawFactory(object):
self.d3d_items[key] = (shader, batch, color) self.d3d_items[key] = (shader, batch, color)
def draw_client_camera(self, client_uuid, client_location, client_color): def draw_client_camera(self, client_id, client_location, client_color):
if client_location: if client_location:
local_user = bpy.context.window_manager.session.user_uuid local_user = bpy.context.window_manager.session.username
if local_user != client_uuid: if local_user != client_id:
try: try:
indices = ( indices = (
(1, 3), (2, 1), (3, 0), (1, 3), (2, 1), (3, 0),
@ -301,8 +274,8 @@ class DrawFactory(object):
batch = batch_for_shader( batch = batch_for_shader(
shader, 'LINES', {"pos": position}, indices=indices) shader, 'LINES', {"pos": position}, indices=indices)
self.d3d_items[client_uuid] = (shader, batch, color) self.d3d_items[client_id] = (shader, batch, color)
self.d2d_items[client_uuid] = (position[1], client_uuid, color) self.d2d_items[client_id] = (position[1], client_id, color)
except Exception as e: except Exception as e:
logger.error("Draw client exception {}".format(e)) logger.error("Draw client exception {}".format(e))

View File

@ -1,7 +1,6 @@
import bpy import bpy
from . import operators from . import operators
from .bl_types.bl_user import BlUser
from .libs.replication.replication.constants import (ADDED, ERROR, FETCHED, from .libs.replication.replication.constants import (ADDED, ERROR, FETCHED,
MODIFIED, RP_COMMON, UP) MODIFIED, RP_COMMON, UP)
@ -188,7 +187,7 @@ class SESSION_PT_user(bpy.types.Panel):
# Create a simple row. # Create a simple row.
row = layout.row() row = layout.row()
box = row.box() box = row.box()
split = box.split(factor=0.3) split = box.split(factor=0.5)
split.label(text="user") split.label(text="user")
split.label(text="frame") split.label(text="frame")
split.label(text="ping") split.label(text="ping")
@ -219,7 +218,7 @@ class SESSION_UL_users(bpy.types.UIList):
ping = str(user_stat['latency']) ping = str(user_stat['latency'])
break break
split = layout.split(factor=0.3) 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=str(item.current_frame))
split.label(text=ping) split.label(text=ping)
@ -256,7 +255,7 @@ def draw_property(context, parent, property_uuid, level=0):
settings = context.window_manager.session settings = context.window_manager.session
item = operators.client.get(uuid=property_uuid) item = operators.client.get(uuid=property_uuid)
if item.str_type == 'BlUser' or item.state == ERROR: if item.state == ERROR:
return return
area_msg = parent.row(align=True) area_msg = parent.row(align=True)

View File

@ -27,6 +27,7 @@ def has_driver(target):
and target.animation_data and target.animation_data
and target.animation_data.drivers) and target.animation_data.drivers)
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:
@ -56,7 +57,7 @@ def get_datablock_users(datablock):
def random_string_digits(stringLength=6): def random_string_digits(stringLength=6):
"""Generate a random string of letters and digits """ """Generate a random string of letters and digits """
lettersAndDigits = string.ascii_letters + string.digits lettersAndDigits = string.ascii_letters + string.digits
return ''.join(random.choice(lettersAndDigits) for i in range(stringLength)) return ''.join(random.choices(lettersAndDigits, k=stringLength))
def clean_scene(): def clean_scene():
@ -151,6 +152,7 @@ def dump_datablock_attibutes(datablock=None, attributes=[], depth=1, dickt=None)
return data return data
def resolve_from_id(id, optionnal_type=None): def resolve_from_id(id, optionnal_type=None):
for category in dir(bpy.data): for category in dir(bpy.data):
root = getattr(bpy.data, category) root = getattr(bpy.data, category)