diff --git a/__init__.py b/__init__.py index 94df6a0..cb0e6da 100644 --- a/__init__.py +++ b/__init__.py @@ -96,6 +96,10 @@ class SessionProps(bpy.types.PropertyGroup): default="127.0.0.1", update=save_session_config ) + user_uuid: bpy.props.StringProperty( + name="user_uuid", + default="None" + ) port: bpy.props.IntProperty( name="port", description='Distant host port', diff --git a/bl_types/bl_user.py b/bl_types/bl_user.py index f04d8b3..3432e50 100644 --- a/bl_types/bl_user.py +++ b/bl_types/bl_user.py @@ -19,16 +19,24 @@ class BlUser(ReplicatedDatablock): return User() def load(self, data, target): - target.name = data['name'] - + # target.name = data['name'] + utils.dump_anything.load(target, data) def dump(self,pointer=None): - return utils.dump_anything.dump(pointer) + data = utils.dump_anything.dump(pointer) + data['location'] = pointer.location + data['color'] = pointer.color + return data + def diff(self): - pass + for i,coord in enumerate(self.pointer.location): + if coord != self.buffer['location'][i]: + print("user location update") + return True + return False -bl_id = "user" +bl_id = "users" bl_class = User bl_rep_class = BlUser diff --git a/delayable.py b/delayable.py new file mode 100644 index 0000000..0d754ae --- /dev/null +++ b/delayable.py @@ -0,0 +1,79 @@ +import bpy +from .libs.replication.constants import * +from . import operators + +class Delayable(): + def register(self): + raise NotImplementedError + + def execute(self): + raise NotImplementedError + + def unregister(self): + raise NotImplementedError + +class Timer(Delayable): + """Timer binder interface for blender + + Run a bpy.app.Timer in the background looping at the given rate + """ + def __init__(self, duration=1): + self._timeout = duration + + def register(self): + """Register the timer into the blender timer system + """ + bpy.app.timers.register(self.execute) + + def execute(self): + """Main timer loop + """ + return self._timeout + + def unregister(self): + """Unnegister the timer of the blender timer system + """ + bpy.app.timers.unregister(self.execute) + +class ApplyTimer(Timer): + def __init__(self, timout=1,target_type=None): + self._type = target_type + super().__init__(timout) + + def execute(self): + if operators.client: + nodes = operators.client.list(filter=self._type) + + for node in nodes: + node_ref = operators.client.get(node) + + if node_ref.state == FETCHED: + operators.client.apply(uuid=node) + + return self._timeout + +class Draw(Delayable): + def __init__(self): + self._handler = None + + def register(self): + self._handler = bpy.types.SpaceView3D.draw_handler_add( + self.execute,(), 'WINDOW', 'POST_VIEW') + + def execute(self): + raise NotImplementedError() + + def unregister(self): + bpy.types.SpaceView3D.draw_handler_remove( + self._handler, "WINDOW") + +class ClientUpdate(Draw): + def __init__(self, client_uuid=None): + assert(client_uuid) + self._client_uuid = client_uuid + super().__init__() + + def execute(self): + if hasattr(operators,"client"): + operators.client.get(self._client_uuid).pointer.update_location() + print("update! ") \ No newline at end of file diff --git a/operators.py b/operators.py index ed00628..403540a 100644 --- a/operators.py +++ b/operators.py @@ -13,7 +13,7 @@ import bpy import mathutils from bpy_extras.io_utils import ExportHelper -from . import environment, presence, ui, utils, timer +from . import environment, presence, ui, utils, delayable from .libs import umsgpack from .libs.replication.data import ReplicatedDataFactory from .libs.replication.interface import Client @@ -22,43 +22,9 @@ from . import bl_types logger = logging.getLogger(__name__) client = None - +delayables = [] context = None -# def upload_client_instance_position(): -# username = bpy.context.window_manager.session.username -# if client: - -# key = "Client/{}".format(username) - -# current_coords = presence.get_client_view_rect() -# client_list = client.get(key) - -# if current_coords and client_list: -# if current_coords != client_list[0][1]['location']: -# client_list[0][1]['location'] = current_coords -# client.set(key, client_list[0][1]) - - -# def update_client_selected_object(context): -# session = bpy.context.window_manager.session -# username = bpy.context.window_manager.session.username -# client_key = "Client/{}".format(username) -# client_data = client.get(client_key) - -# selected_objects = utils.get_selected_objects(context.scene) -# if len(selected_objects) > 0 and len(client_data) > 0: - -# for obj in selected_objects: -# # if obj not in client_data[0][1]['active_objects']: -# client_data[0][1]['active_objects'] = selected_objects - -# client.set(client_key, client_data[0][1]) -# break - -# elif client_data and client_data[0][1]['active_objects']: -# client_data[0][1]['active_objects'] = [] -# client.set(client_key, client_data[0][1]) def add_datablock(datablock): global client @@ -96,26 +62,6 @@ def init_supported_datablocks(supported_types_id): add_datablock(item) -# def default_tick(): -# upload_client_instance_position() - -# return .1 - - -# def register_ticks(): -# # REGISTER Updaters -# bpy.app.timers.register(default_tick) -# bpy.app.timers.register(execute_queued_functions) - - -# def unregister_ticks(): - # REGISTER Updaters - # try: - # bpy.app.timers.unregister(default_tick) - # bpy.app.timers.unregister(execute_queued_functions) - # except: - # pass - # OPERATORS class SessionStartOperator(bpy.types.Operator): @@ -131,7 +77,7 @@ class SessionStartOperator(bpy.types.Operator): return True def execute(self, context): - global client + global client, delayables settings = context.window_manager.session # save config settings.save(context) @@ -148,10 +94,9 @@ class SessionStartOperator(bpy.types.Operator): _type = getattr(bl_types, type) supported_bl_types.append(_type.bl_id) - if _type.bl_id == 'objects':#For testing - bpy_factory.register_type(_type.bl_class, _type.bl_rep_class, timer=0.16,automatic=True) - obj_timer = timer.ApplyTimer(timout=0.16,target_type=_type.bl_rep_class) - obj_timer.start() + if _type.bl_id == 'users':#For testing + bpy_factory.register_type(_type.bl_class, _type.bl_rep_class, timer=0.1,automatic=True) + # delayables.append(delayable.ApplyTimer(timout=0.16,target_type=_type.bl_rep_class)) else: bpy_factory.register_type(_type.bl_class, _type.bl_rep_class) @@ -177,17 +122,24 @@ class SessionStartOperator(bpy.types.Operator): username=settings.username, color=list(settings.client_color), ) - client.add(usr) + + settings.user_uuid = client.add(usr) + + delayables.append(delayable.ClientUpdate(client_uuid=settings.user_uuid)) + # Push all added values client.push() + # settings.is_running = True # bpy.ops.session.refresh() # register_ticks() # Launch drawing module - if settings.enable_presence: - presence.renderer.run() - + # if settings.enable_presence: + # presence.renderer.run() + + for d in delayables: + d.register() return {"FINISHED"} @@ -202,12 +154,14 @@ class SessionStopOperator(bpy.types.Operator): return True def execute(self, context): - global client + global client, delayables assert(client) client.disconnect() + for d in delayables: + d.unregister() # del client_instance # unregister_ticks() diff --git a/presence.py b/presence.py index a640d91..52f1c89 100644 --- a/presence.py +++ b/presence.py @@ -66,7 +66,7 @@ def get_client_view_rect(): v5 = get_target(region, rv3d, (width/2, height/2)) v6 = get_target_far(region, rv3d, (width/2, height/2), 10) - coords = [v1, v2, v3, v4,v5,v6] + coords = v5 indices = ( (1, 3), (2, 1), (3, 0), (2, 0) ) @@ -85,9 +85,36 @@ class User(): def __init__(self, username=None, color=(0,0,0,1)): self.name = username self.color = color - self.location = (0,0,0) + self.location = [0,0,0] self.active_object = "" - + + def update_location(self): + current_coords = get_client_view_rect() + + if current_coords: + self.location = current_coords + + + + def update_client_selected_object(self,context): + session = bpy.context.window_manager.session + username = bpy.context.window_manager.session.username + # client_data = client.get(client_key) + + selected_objects = utils.get_selected_objects(context.scene) + if len(selected_objects) > 0 and len(client_data) > 0: + + for obj in selected_objects: + # if obj not in client_data[0][1]['active_objects']: + client_data[0][1]['active_objects'] = selected_objects + + client.set(client_key, client_data[0][1]) + break + + elif client_data and client_data[0][1]['active_objects']: + client_data[0][1]['active_objects'] = [] + client.set(client_key, client_data[0][1]) + diff --git a/timer.py b/timer.py deleted file mode 100644 index fe12159..0000000 --- a/timer.py +++ /dev/null @@ -1,33 +0,0 @@ -import bpy -from .libs.replication.constants import * -from . import operators - -class Timer(): - def __init__(self, duration=1): - self._timeout = duration - - def start(self): - bpy.app.timers.register(self.execute) - - def execute(self): - return self._timeout - - def stop(self): - bpy.app.timers.unregister(self.execute) - -class ApplyTimer(Timer): - def __init__(self, timout=1,target_type=None): - self._type = target_type - super().__init__(timout) - - def execute(self): - if operators.client: - nodes = operators.client.list(filter=self._type) - - for node in nodes: - node_ref = operators.client.get(node) - - if node_ref.state == FETCHED: - operators.client.apply(uuid=node) - - return self._timeout \ No newline at end of file