From c8dfbcb87a183f85325ab4e208af6af0b8f5e55d Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Wed, 13 Mar 2019 16:02:54 +0100 Subject: [PATCH] feat(rcf): user representation is now working --- net_operators.py | 292 ++++++++++++++++++++++++----------------------- net_ui.py | 4 +- 2 files changed, 154 insertions(+), 142 deletions(-) diff --git a/net_operators.py b/net_operators.py index be77f46..06a12de 100644 --- a/net_operators.py +++ b/net_operators.py @@ -7,6 +7,8 @@ import logging import mathutils import random import string +import bgl +import blf import gpu from gpu_extras.batch import batch_for_shader @@ -16,6 +18,8 @@ client = None server = None context = None + +COLOR_TABLE = [(1,0,0,1),(0,1,0,1),(0,0,1,1)] NATIVE_TYPES = ( bpy.types.IntProperty, bpy.types.FloatProperty, @@ -93,6 +97,11 @@ def get_client_view_rect(): ) return coords +def get_client_2d(coords): + area, region, rv3d = view3d_find() + + return view3d_utils.location_3d_to_region_2d(region,rv3d,coords) + class UpdateClientView(bpy.types.Operator): bl_idname = "session.update_client" bl_label = "update client" @@ -152,120 +161,6 @@ class UpdateClientView(bpy.types.Operator): self.unregister_handlers() return {"FINISHED"} -class DrawClient(bpy.types.Operator): - bl_idname = "session.draw" - bl_label = "draw clients" - bl_description = "Description that shows in blender tooltips" - bl_options = {"REGISTER"} - - position = bpy.props.FloatVectorProperty(default=(0,0,0)) - def __init__(self): - super().__init__() - - self.shader = None - self.batch = None - self.draw_handle = None - self.draw_event = None - self.coords = None - - - - @classmethod - def poll(cls, context): - return True - - def refresh_view(self, context): - global client - - try: - self.unregister_handlers() - except: - pass - - try: - key = "net/clients/{}".format(client.id.decode()) - client.property_map[key] - current_view = get_client_view_rect() - - client.push_update(key, 'client', current_view) - print(current_view) - except: - pass - #client position update - # area, region, rv3d = view3d_find() - # width = region.width - # height = region.height - # depth = mathutils.Vector((rv3d.view_distance,rv3d.view_distance,rv3d.view_distance)) - # vec = view3d_utils.region_2d_to_vector_3d(region, rv3d, (0,0)) - - # v1 = get_target(region,rv3d,(0,0)) - # v3 = get_target(region,rv3d,(0,height)) - # v2 = get_target(region,rv3d,(width,height)) - # v4 = get_target(region,rv3d,(width,0)) - - self.coords = get_client_view_rect() - - - - - def invoke(self, context,event): - self.refresh_view(context) - self.create_batch() - self.register_handlers(context) - context.window_manager.modal_handler_add(self) - return {"RUNNING_MODAL"} - - def register_handlers(self,context): - self.draw_handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback, (), 'WINDOW', 'POST_VIEW') - self.draw_event = context.window_manager.event_timer_add(0.1, window=context.window) - - def unregister_handlers(self,context): - context.window_manager.event_timer_remove(self.draw_event) - bpy.types.SpaceView3D.draw_handler_remove(self.draw_handle,"WINDOW") - - self.draw_handle = None - self.draw_event = None - - def create_batch(self, coords): - indices = ( - (1, 3), (2, 1), (3, 0),(2,0) - ) - - self.shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') - self.batch = batch_for_shader(self.shader, 'LINES', {"pos": coords}, indices=indices) - - def draw_callback(self): - self.shader.bind() - self.shader.uniform_float("color", (1, 0, 0, 1)) - self.batch.draw(self.shader) - - def modal(self, context, event): - if context.area: - context.area.tag_redraw() - - if event.type in {"TIMER"}: - # Update local view - if get_client_view_rect() != self.coords: - print("update") - self.unregister_handlers(context) - self.refresh_view(context) - self.create_batch() - self.register_handlers(context) - - - - if event.type in {"ESC"}: - self.unregister_handlers(context) - return {"CANCELLED"} - # if self.draw_handle:ยต - # self.finish() - - return {"PASS_THROUGH"} - - def finish(self): - self.unregister_handlers() - return {"FINISHED"} - def on_scene_evalutation(scene): # TODO: viewer representation # TODO: Live update only selected object @@ -354,16 +249,8 @@ def resolve_bpy_path(path): def observer(): global client - - for key, values in client.property_map.items(): - if client.id.decode() in key: - # current_view = get_client_view_rect() - - # client.push_update(key, 'client', current_view) - # print(current_view) - #client position update - pass - else: + if client: + for key, values in client.property_map.items(): try: obj, attr = resolve_bpy_path(key) @@ -375,6 +262,7 @@ def observer(): return bpy.context.scene.session_settings.update_frequency + def refresh_window(): import bpy @@ -387,19 +275,22 @@ def update_scene(msg): global client if msg.id != client.id: - value = None + if msg.mtype == 'client' and msg.id is not client.id: + refresh_window() + else: + value = None - obj, attr = resolve_bpy_path(msg.key) - attr_name = msg.key.split('/')[2] + obj, attr = resolve_bpy_path(msg.key) + attr_name = msg.key.split('/')[2] - value = to_bpy(msg) - # print(msg.get) - logger.debug("Updating scene:\n object: {} attribute: {} , value: {}".format( - obj, attr_name, value)) - try: - setattr(obj, attr_name, value) - except: - pass + value = to_bpy(msg) + # print(msg.get) + logger.debug("Updating scene:\n object: {} attribute: {} , value: {}".format( + obj, attr_name, value)) + try: + setattr(obj, attr_name, value) + except: + pass else: logger.debug('no need to update scene on our own') @@ -446,8 +337,9 @@ class session_join(bpy.types.Operator): bpy.ops.asyncio.loop() bpy.app.timers.register(observer) - net_settings.is_running = True + + bpy.ops.session.draw('INVOKE_DEFAULT') return {"FINISHED"} @@ -539,6 +431,8 @@ class session_stop(bpy.types.Operator): net_settings = context.scene.session_settings + bpy.app.timers.unregister(observer) + if server: server.stop() del server @@ -548,12 +442,11 @@ class session_stop(bpy.types.Operator): del client client = None bpy.ops.asyncio.stop() - - bpy.app.timers.unregister(observer) net_settings.is_running = False else: logger.debug("No server/client running.") + return {"FINISHED"} @@ -568,6 +461,126 @@ class session_settings(bpy.types.PropertyGroup): name="update_frequency", default=0.008) +class session_draw_clients(bpy.types.Operator): + bl_idname = "session.draw" + bl_label = "draw clients" + bl_description = "Description that shows in blender tooltips" + bl_options = {"REGISTER"} + + position = bpy.props.FloatVectorProperty(default=(0,0,0)) + def __init__(self): + super().__init__() + + self.draw_items = [] + self.draw3d_handle = None + self.draw2d_handle = None + self.draw_event = None + self.coords = None + + + @classmethod + def poll(cls, context): + return True + + def invoke(self, context,event): + # + self.coords = get_client_view_rect() + self.create_batch() + self.register_handlers(context) + context.window_manager.modal_handler_add(self) + return {"RUNNING_MODAL"} + + def register_handlers(self,context): + self.draw3d_handle = bpy.types.SpaceView3D.draw_handler_add(self.draw3d_callback, (), 'WINDOW', 'POST_VIEW') + self.draw2d_handle = bpy.types.SpaceView3D.draw_handler_add(self.draw2d_callback, (), 'WINDOW', 'POST_PIXEL') + + self.draw_event = context.window_manager.event_timer_add(0.1, window=context.window) + + def unregister_handlers(self,context): + if self.draw_event and self.draw3d_handle: + context.window_manager.event_timer_remove(self.draw_event) + bpy.types.SpaceView3D.draw_handler_remove(self.draw3d_handle,"WINDOW") + bpy.types.SpaceView3D.draw_handler_remove(self.draw2d_handle,"WINDOW") + + self.draw_items.clear() + self.draw3d_handle = None + self.draw2d_handle = None + self.draw_event = None + + def create_batch(self): + global client + index = 0 + for key, values in client.property_map.items(): + + if values.mtype == "client" and values.id != client.id: + + indices = ( + (1, 3), (2, 1), (3, 0),(2,0) + ) + + shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') + batch = batch_for_shader(shader, 'LINES', {"pos": values.body}, indices=indices) + + + self.draw_items.append((shader,batch, (values.body[1],values.id.decode()),COLOR_TABLE[index])) + + index+=1 + + def draw3d_callback(self): + + bgl.glLineWidth(3) + for shader,batch,font,color in self.draw_items: + shader.bind() + shader.uniform_float("color", color) + batch.draw(shader) + + + + def draw2d_callback(self): + for shader,batch,font,color in self.draw_items: + coords = get_client_2d(font[0]) + + try: + blf.position(0, coords[0], coords[1]+10, 0) + blf.size(0, 10, 72) + blf.color(0,color[0],color[1],color[2],color[3]) + blf.draw(0, font[1]) + + except: + pass + + def modal(self, context, event): + if context.area: + context.area.tag_redraw() + + if not context.scene.session_settings.is_running: + self.finish(context) + + if event.type in {"TIMER"}: + global client + if client: + # Local view update + current_coords = get_client_view_rect() + if current_coords != self.coords: + self.coords= current_coords + key = "net/clients/{}".format(client.id.decode()) + + client.push_update(key, 'client', current_coords) + + # Draw clients + if len(client.property_map) > 0: + self.unregister_handlers(context) + self.create_batch() + + self.register_handlers(context) + + return {"PASS_THROUGH"} + + def finish(self,context): + self.unregister_handlers(context) + return {"FINISHED"} + + # TODO: Rename to match official blender convention classes = ( session_join, @@ -576,8 +589,7 @@ classes = ( session_create, session_settings, session_remove_property, - DrawClient, - UpdateClientView, + session_draw_clients, ) diff --git a/net_ui.py b/net_ui.py index ac2a978..bab0b97 100644 --- a/net_ui.py +++ b/net_ui.py @@ -61,8 +61,8 @@ class SessionPanel(bpy.types.Panel): row.operator("session.create") row = layout.row() - row.operator("session.draw") - row.operator("session.update_client") + # row.operator("session.draw") + # row.operator("session.update_client") classes = ( SessionPanel, )