feat(rcf): cleanup

feat(rcf): append client color
feat(rcf): load selected object from mg loader
This commit is contained in:
Swann Martinez
2019-03-29 17:15:22 +01:00
parent 6abc900f86
commit 736a409db2
3 changed files with 173 additions and 124 deletions

View File

@ -243,9 +243,9 @@ class RCFClient():
logger.info("{} client running".format(id)) logger.info("{} client running".format(id))
self.push_update( self.push_update(
"net/clients/{}".format(self.id.decode()), "client", [(0,0,0),(0,0,0),(0,0,0),(0,0,0)]) "net/clients/{}".format(self.id.decode()), "client", None)
self.push_update( self.push_update(
"net/objects/{}".format(self.id.decode()), "client_object", None) "net/objects/{}".format(self.id.decode()), "clientObject", None)
self.tick_task = asyncio.ensure_future(self.tick()) self.tick_task = asyncio.ensure_future(self.tick())

View File

@ -44,7 +44,7 @@ def clean_scene(elements=SUPPORTED_DATABLOCKS):
def view3d_find(): def view3d_find():
for area in bpy.context.window.screen.areas: for area in bpy.data.window_managers[0].windows[0].screen.areas:
if area.type == 'VIEW_3D': if area.type == 'VIEW_3D':
v3d = area.spaces[0] v3d = area.spaces[0]
rv3d = v3d.region_3d rv3d = v3d.region_3d
@ -52,15 +52,17 @@ def view3d_find():
if region.type == 'WINDOW': if region.type == 'WINDOW':
return area, region, rv3d return area, region, rv3d
break
return None, None, None return None, None, None
def get_target(region, rv3d, coord): def get_target(region, rv3d, coord):
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) target = [0,0,0]
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
target = ray_origin + view_vector if coord and region and rv3d:
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
target = ray_origin + view_vector
return [target.x, target.y, target.z] return [target.x, target.y, target.z]
@ -72,48 +74,29 @@ def get_client_view_rect():
v3 = [0, 0, 0] v3 = [0, 0, 0]
v4 = [0, 0, 0] v4 = [0, 0, 0]
width = region.width if area and region and rv3d:
height = region.height width = region.width
height = region.height
v1 = get_target(region, rv3d, (0, 0)) v1 = get_target(region, rv3d, (0, 0))
v3 = get_target(region, rv3d, (0, height)) v3 = get_target(region, rv3d, (0, height))
v2 = get_target(region, rv3d, (width, height)) v2 = get_target(region, rv3d, (width, height))
v4 = get_target(region, rv3d, (width, 0)) v4 = get_target(region, rv3d, (width, 0))
coords = (v1, v2, v3, v4) coords = (v1, v2, v3, v4)
indices = ( indices = (
(1, 3), (2, 1), (3, 0), (2, 0) (1, 3), (2, 1), (3, 0), (2, 0)
) )
return coords return coords
def get_client_view_rect():
area, region, rv3d = view3d_find()
v1 = [0, 0, 0]
v2 = [0, 0, 0]
v3 = [0, 0, 0]
v4 = [0, 0, 0]
width = region.width
height = region.height
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))
coords = (v1, v2, v3, v4)
indices = (
(1, 3), (2, 1), (3, 0), (2, 0)
)
return coords
def get_client_2d(coords): def get_client_2d(coords):
area, region, rv3d = view3d_find() area, region, rv3d = view3d_find()
if area and region and rv3d:
return view3d_utils.location_3d_to_region_2d(region, rv3d, coords) return view3d_utils.location_3d_to_region_2d(region, rv3d, coords)
else:
return None
def randomStringDigits(stringLength=6): def randomStringDigits(stringLength=6):
@ -121,6 +104,12 @@ def randomStringDigits(stringLength=6):
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.choice(lettersAndDigits) for i in range(stringLength))
def randomColor():
r = random.random()
v = random.random()
b = random.random()
return [r,v,b]
def resolve_bpy_path(path): def resolve_bpy_path(path):
""" """
@ -158,8 +147,6 @@ def dump_datablock(datablock,depth):
def dump_datablock_attibute(datablock,attributes,depth=1): def dump_datablock_attibute(datablock,attributes,depth=1):
if datablock: if datablock:
print("sending {}".format(datablock.name))
dumper = dump_anything.Dumper() dumper = dump_anything.Dumper()
dumper.type_subset = dumper.match_subset_all dumper.type_subset = dumper.match_subset_all
dumper.depth = depth dumper.depth = depth
@ -180,6 +167,31 @@ def upload_mesh(mesh):
if mesh.bl_rna.name == 'Mesh': if mesh.bl_rna.name == 'Mesh':
dump_datablock_attibute(mesh,['name','polygons','edges','vertices'],6) dump_datablock_attibute(mesh,['name','polygons','edges','vertices'],6)
def upload_material(mesh):
if mesh.bl_rna.name == 'Material':
dump_datablock_attibute(mesh,['name','node_tree'],7)
def upload_client_position():
global client
if client:
key = "net/clients/{}".format(client.id.decode())
try:
current_coords = get_client_view_rect()
data = client.property_map[key].body
if data is None:
data = {}
data['location'] = current_coords
color = bpy.context.scene.session_settings.client_color
data['color'] = (color.r,color.g,color.b,1)
client.push_update(key, 'client', data)
elif current_coords[0] != data['location'][0]:
data['location'] = current_coords
client.push_update(key, 'client', data)
except:
pass
def init_scene(): def init_scene():
for cam in bpy.data.cameras: for cam in bpy.data.cameras:
dump_datablock(cam,1) dump_datablock(cam,1)
@ -196,6 +208,7 @@ def init_scene():
for scene in bpy.data.scenes: for scene in bpy.data.scenes:
dump_datablock(scene,4) dump_datablock(scene,4)
def load_mesh(target=None, data=None, create=False): def load_mesh(target=None, data=None, create=False):
import bmesh import bmesh
@ -383,18 +396,13 @@ def update_scene(msg):
if msg.id != client.id: if msg.id != client.id:
net_vars = bpy.context.scene.session_settings net_vars = bpy.context.scene.session_settings
if net_vars.active_object: # if net_vars.active_object:
if net_vars.active_object.name in msg.key: # if net_vars.active_object.name in msg.key:
raise ValueError() # raise ValueError()
if 'net' not in msg.key: if 'net' not in msg.key:
target = resolve_bpy_path(msg.key) target = resolve_bpy_path(msg.key)
try:
if msg.body["name"] in TASKS:
TASKS.remove(msg.body["name"])
except:
pass
if msg.mtype == 'Object': if msg.mtype == 'Object':
load_object(target=target, data=msg.body, load_object(target=target, data=msg.body,
create=net_vars.load_data) create=net_vars.load_data)
@ -416,9 +424,27 @@ def update_scene(msg):
elif 'Light' in msg.mtype: elif 'Light' in msg.mtype:
load_light(target=target, data=msg.body, load_light(target=target, data=msg.body,
create=net_vars.load_data) create=net_vars.load_data)
else: elif msg.mtype == 'Camera' :
load_default(target=target, data=msg.body, load_default(target=target, data=msg.body,
create=net_vars.load_data, type=msg.mtype) create=net_vars.load_data, type=msg.mtype)
else:
if msg.mtype == 'client':
refresh_window()
elif msg.mtype == 'clientObject':
selected_objects = []
for k, v in client.property_map.items():
if v.mtype == 'clientObject':
if client.id != v.id:
selected_objects.append(v.body['object'])
for obj in bpy.data.objects:
if obj.name in selected_objects:
obj.hide_select = True
else:
obj.hide_select = False
refresh_window()
recv_callbacks = [update_scene] recv_callbacks = [update_scene]
@ -465,6 +491,9 @@ class session_join(bpy.types.Operator):
net_settings.is_running = True net_settings.is_running = True
# REGISTER Updaters
bpy.app.timers.register(tick)
bpy.ops.session.draw('INVOKE_DEFAULT') bpy.ops.session.draw('INVOKE_DEFAULT')
return {"FINISHED"} return {"FINISHED"}
@ -578,6 +607,7 @@ class session_stop(bpy.types.Operator):
client = None client = None
bpy.ops.asyncio.stop() bpy.ops.asyncio.stop()
net_settings.is_running = False net_settings.is_running = False
bpy.app.timers.unregister(tick)
else: else:
logger.debug("No server/client running.") logger.debug("No server/client running.")
@ -608,7 +638,9 @@ class session_settings(bpy.types.PropertyGroup):
('HOST', 'hosting', 'host a session'), ('HOST', 'hosting', 'host a session'),
('CONNECT', 'connexion', 'connect to a session')}, ('CONNECT', 'connexion', 'connect to a session')},
default='HOST') default='HOST')
client_color = bpy.props.FloatVectorProperty(name="client_color",
subtype='COLOR',
default=randomColor())
class session_draw_clients(bpy.types.Operator): class session_draw_clients(bpy.types.Operator):
bl_idname = "session.draw" bl_idname = "session.draw"
@ -650,67 +682,79 @@ class session_draw_clients(bpy.types.Operator):
0.008, window=context.window) 0.008, window=context.window)
def unregister_handlers(self, context): def unregister_handlers(self, context):
if self.draw_event and self.draw3d_handle and self.draw2d_handle: if self.draw_event:
context.window_manager.event_timer_remove(self.draw_event) context.window_manager.event_timer_remove(self.draw_event)
bpy.types.SpaceView3D.draw_handler_remove( self.draw_event = None
self.draw3d_handle, "WINDOW")
if self.draw2d_handle:
bpy.types.SpaceView3D.draw_handler_remove( bpy.types.SpaceView3D.draw_handler_remove(
self.draw2d_handle, "WINDOW") self.draw2d_handle, "WINDOW")
self.draw_items.clear()
self.draw3d_handle = None
self.draw2d_handle = None self.draw2d_handle = None
self.draw_event = None
if self.draw3d_handle:
bpy.types.SpaceView3D.draw_handler_remove(
self.draw3d_handle, "WINDOW")
self.draw3d_handle = None
self.draw_items.clear()
# TODO: refactor this ugly things # TODO: refactor this ugly things
def create_batch(self): def create_batch(self):
global client global client
index = 0 index = 0
index_object = 0 index_object = 0
self.draw_items.clear()
for key, values in client.property_map.items(): for key, values in client.property_map.items():
if values.body is not None: if 'net' in key and values.body is not None and values.id != client.id:
if values.mtype == "client_object": if values.mtype == "clientObject":
if values.id != client.id and values.body is not None: indices = (
indices = ( (0, 1), (1, 2), (2, 3), (0, 3),
(0, 1), (1, 2), (2, 3), (0, 3), (4, 5), (5, 6), (6, 7), (4, 7),
(4, 5), (5, 6), (6, 7), (4, 7), (0, 4), (1, 5), (2, 6), (3, 7)
(0, 4), (1, 5), (2, 6), (3, 7) )
)
if values.body in bpy.data.objects.keys(): if values.body['object'] in bpy.data.objects.keys():
ob = bpy.data.objects[values.body] ob = bpy.data.objects[values.body['object']]
else: else:
return return
bbox_corners = [ob.matrix_world @ mathutils.Vector(corner) for corner in ob.bound_box] bbox_corners = [ob.matrix_world @ mathutils.Vector(corner) for corner in ob.bound_box]
coords = [(point.x, point.y, point.z) coords = [(point.x, point.y, point.z)
for point in bbox_corners] for point in bbox_corners]
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
batch = batch_for_shader(
shader, 'LINES', {"pos": coords}, indices=indices)
self.draw_items.append( color = values.body['color']
(shader, batch, (None, None), COLOR_TABLE[index-1])) batch = batch_for_shader(
shader, 'LINES', {"pos": coords}, indices=indices)
self.draw_items.append(
(shader, batch, (None, None), color))
# index_object += 1 # index_object += 1
if values.mtype == "client": if values.mtype == "client":
if values.id != client.id: indices = (
indices = ( (1, 3), (2, 1), (3, 0), (2, 0)
(1, 3), (2, 1), (3, 0), (2, 0) )
)
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
batch = batch_for_shader( position = values.body['location']
shader, 'LINES', {"pos": values.body}, indices=indices) color = values.body['color']
batch = batch_for_shader(
shader, 'LINES', {"pos":position}, indices=indices)
self.draw_items.append( self.draw_items.append(
(shader, batch, (values.body[1], values.id.decode()), COLOR_TABLE[index])) (shader, batch, (position[1], values.id.decode()), color))
index += 1 index += 1
def draw3d_callback(self): def draw3d_callback(self):
bgl.glLineWidth(3) bgl.glLineWidth(3)
for shader, batch, font, color in self.draw_items: for shader, batch, font, color in self.draw_items:
shader.bind() shader.bind()
@ -735,7 +779,7 @@ class session_draw_clients(bpy.types.Operator):
global client global client
for k, v in client.property_map.items(): for k, v in client.property_map.items():
if v.mtype == 'client_object': if v.mtype == 'clientObject':
if client.id != v.id: if client.id != v.id:
if obj.name in v.body: if obj.name in v.body:
return True return True
@ -748,52 +792,50 @@ class session_draw_clients(bpy.types.Operator):
if not context.scene.session_settings.is_running: if not context.scene.session_settings.is_running:
self.finish(context) self.finish(context)
return {"FINISHED"}
if event.type in {"TIMER"}: if event.type in {"TIMER"}:
global client global client
session = context.scene.session_settings session = context.scene.session_settings
if 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)
# Hide selected objects # Hide selected objects
for object in context.scene.objects: # for object in context.scene.objects:
if self.is_object_selected(object): # if self.is_object_selected(object):
object.hide_select = True # object.hide_select = True
else: # else:
object.hide_select = False # object.hide_select = False
# Active object bounding box # Active object bounding box
if len(context.selected_objects) > 0: if len(context.selected_objects) > 0:
if session.active_object is not context.selected_objects[0] or session.active_object.is_evaluated: if session.active_object is not context.selected_objects[0] or session.active_object.is_evaluated:
session.active_object = context.selected_objects[0] session.active_object = context.selected_objects[0]
key = "net/objects/{}".format(client.id.decode()) key = "net/objects/{}".format(client.id.decode())
data = {}
data['color'] = [session.client_color.r,session.client_color.g,session.client_color.b]
data['object'] = session.active_object.name
client.push_update( client.push_update(
key, 'client_object', session.active_object.name) key, 'clientObject', data)
elif len(context.selected_objects) == 0 and session.active_object: elif len(context.selected_objects) == 0 and session.active_object:
session.active_object = None session.active_object = None
data = {}
data['object'] = None
key = "net/objects/{}".format(client.id.decode()) key = "net/objects/{}".format(client.id.decode())
client.push_update(key, 'client_object', None) client.push_update(key, 'clientObject', data)
# Draw clients # Draw clients
if len(client.property_map) > 0: if len(client.property_map) > 1:
self.unregister_handlers(context) # self.unregister_handlers(context)
self.create_batch() self.create_batch()
self.register_handlers(context) # self.register_handlers(context)
return {"PASS_THROUGH"} return {"PASS_THROUGH"}
def finish(self, context): def finish(self, context):
self.unregister_handlers(context) self.unregister_handlers(context)
return {"FINISHED"}
class session_snapview(bpy.types.Operator): class session_snapview(bpy.types.Operator):
@ -815,7 +857,7 @@ class session_snapview(bpy.types.Operator):
for k, v in client.property_map.items(): for k, v in client.property_map.items():
if v.mtype == 'client' and v.id.decode() == self.target_client: if v.mtype == 'client' and v.id.decode() == self.target_client:
rv3d.view_location = v.body[1] rv3d.view_location = v.body['location'][1]
rv3d.view_distance = 30.0 rv3d.view_distance = 30.0
return {"FINISHED"} return {"FINISHED"}
@ -836,26 +878,27 @@ classes = (
session_snapview, session_snapview,
) )
def update_loop():
for t in TASKS:
dump_datablock(bpy.data.objects[t].data,4)
dump_datablock(bpy.data.objects[t],1)
dump_datablock(bpy.data.scenes[0],4)
return 0.5 def tick():
upload_client_position()
return 0.1
# TODO: Enqueu tqsks
def depsgraph_update(scene): def depsgraph_update(scene):
for c in bpy.context.depsgraph.updates.items(): for c in bpy.context.depsgraph.updates.items():
print(c[1].id)
global client global client
if client: if client:
if client.status == net_components.RCFStatus.CONNECTED: if client.status == net_components.RCFStatus.CONNECTED:
print(c[1].id)
if c[1].is_updated_geometry: if c[1].is_updated_geometry:
print("GEOMETRY UPDATE") pass
elif c[1].is_updated_transform: elif c[1].is_updated_transform:
print("TRANFORM UPDATE")
dump_datablock_attibute(bpy.data.objects[c[1].id.name],['matrix_world']) dump_datablock_attibute(bpy.data.objects[c[1].id.name],['matrix_world'])
else: else:
if c[1].id.bl_rna.name == 'Material' or c[1].id.bl_rna.name == 'Shader Nodetree':
print(c[1].id.bl_rna.name)
data_name = c[1].id.name data_name = c[1].id.name
if data_name in bpy.data.objects.keys(): if data_name in bpy.data.objects.keys():
found = False found = False
@ -881,7 +924,6 @@ def register():
bpy.types.Scene.session_settings = bpy.props.PointerProperty( bpy.types.Scene.session_settings = bpy.props.PointerProperty(
type=session_settings) type=session_settings)
bpy.app.handlers.depsgraph_update_post.append(depsgraph_update) bpy.app.handlers.depsgraph_update_post.append(depsgraph_update)
bpy.app.timers.register(update_loop)
def unregister(): def unregister():
global server global server
@ -889,7 +931,7 @@ def unregister():
try: try:
bpy.app.handlers.depsgraph_update_post.remove(depsgraph_update) bpy.app.handlers.depsgraph_update_post.remove(depsgraph_update)
bpy.app.timers.unregister(update_loop)
except: except:
pass pass

View File

@ -19,8 +19,15 @@ class SessionSettingsPanel(bpy.types.Panel):
row = layout.row() row = layout.row()
if net_operators.client is None: if net_operators.client is None:
row = layout.row() row = layout.row()
row.prop(scene.session_settings, "username", text="username:") box = row.box()
row = box.row()
row.label(text="User infos")
row = box.row()
row.prop(scene.session_settings, "username", text="id")
row = box.row()
row.prop(scene.session_settings, "client_color", text="color")
row = layout.row() row = layout.row()
row.prop(scene.session_settings, "session_mode", expand=True) row.prop(scene.session_settings, "session_mode", expand=True)