feat(rcf): attempt to bring back the drawing module
This commit is contained in:
37
client.py
37
client.py
@ -59,7 +59,6 @@ class State(Enum):
|
|||||||
ACTIVE = 3
|
ACTIVE = 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RCFClient(object):
|
class RCFClient(object):
|
||||||
ctx = None
|
ctx = None
|
||||||
pipe = None
|
pipe = None
|
||||||
@ -70,7 +69,7 @@ class RCFClient(object):
|
|||||||
self.pipe, peer = zpipe(self.ctx)
|
self.pipe, peer = zpipe(self.ctx)
|
||||||
self.queue = queue.Queue()
|
self.queue = queue.Queue()
|
||||||
self.agent = threading.Thread(
|
self.agent = threading.Thread(
|
||||||
target=rcf_client_agent, args=(self.ctx, peer,self.queue))
|
target=rcf_client_agent, args=(self.ctx, peer,self.queue),name="net-agent")
|
||||||
self.agent.daemon = True
|
self.agent.daemon = True
|
||||||
self.agent.start()
|
self.agent.start()
|
||||||
|
|
||||||
@ -79,12 +78,12 @@ class RCFClient(object):
|
|||||||
id, str) else id), (address.encode() if isinstance(
|
id, str) else id), (address.encode() if isinstance(
|
||||||
address, str) else address), b'%d' % port])
|
address, str) else address), b'%d' % port])
|
||||||
|
|
||||||
def set(self, key):
|
def set(self, key, value=None):
|
||||||
"""Set new value in distributed hash table
|
"""Set new value in distributed hash table
|
||||||
Sends [SET][key][value] to the agent
|
Sends [SET][key][value] to the agent
|
||||||
"""
|
"""
|
||||||
self.pipe.send_multipart(
|
self.pipe.send_multipart(
|
||||||
[b"SET", umsgpack.packb(key)])
|
[b"SET", umsgpack.packb(key),( umsgpack.packb(value) if value else umsgpack.packb('None') )])
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
"""Lookup value in distributed hash table
|
"""Lookup value in distributed hash table
|
||||||
@ -114,6 +113,7 @@ class RCFClient(object):
|
|||||||
else:
|
else:
|
||||||
return umsgpack.unpackb(reply[0])
|
return umsgpack.unpackb(reply[0])
|
||||||
|
|
||||||
|
|
||||||
class RCFServer(object):
|
class RCFServer(object):
|
||||||
address = None # Server address
|
address = None # Server address
|
||||||
port = None # Server port
|
port = None # Server port
|
||||||
@ -125,8 +125,8 @@ class RCFServer(object):
|
|||||||
self.port = port
|
self.port = port
|
||||||
self.snapshot = ctx.socket(zmq.DEALER)
|
self.snapshot = ctx.socket(zmq.DEALER)
|
||||||
self.snapshot.linger = 0
|
self.snapshot.linger = 0
|
||||||
self.snapshot.connect("tcp://{}:{}".format(address.decode(), port))
|
|
||||||
self.snapshot.setsockopt(zmq.IDENTITY, id)
|
self.snapshot.setsockopt(zmq.IDENTITY, id)
|
||||||
|
self.snapshot.connect("tcp://{}:{}".format(address.decode(), port))
|
||||||
self.subscriber = ctx.socket(zmq.SUB)
|
self.subscriber = ctx.socket(zmq.SUB)
|
||||||
self.subscriber.setsockopt_string(zmq.SUBSCRIBE, '')
|
self.subscriber.setsockopt_string(zmq.SUBSCRIBE, '')
|
||||||
self.subscriber.connect("tcp://{}:{}".format(address.decode(), port+1))
|
self.subscriber.connect("tcp://{}:{}".format(address.decode(), port+1))
|
||||||
@ -158,7 +158,7 @@ class RCFClientAgent(object):
|
|||||||
self.publisher.linger = 0
|
self.publisher.linger = 0
|
||||||
self.serial, peer = zpipe(self.ctx)
|
self.serial, peer = zpipe(self.ctx)
|
||||||
self.serial_agent = threading.Thread(
|
self.serial_agent = threading.Thread(
|
||||||
target=serialization_agent, args=(self.ctx, peer))
|
target=serialization_agent, args=(self.ctx, peer), name="serial-agent")
|
||||||
self.serial_agent.daemon = True
|
self.serial_agent.daemon = True
|
||||||
self.serial_agent.start()
|
self.serial_agent.start()
|
||||||
|
|
||||||
@ -182,7 +182,11 @@ class RCFClientAgent(object):
|
|||||||
elif command == b"SET":
|
elif command == b"SET":
|
||||||
key = umsgpack.unpackb(msg[0])
|
key = umsgpack.unpackb(msg[0])
|
||||||
value = None
|
value = None
|
||||||
value = helpers.dump(key)
|
|
||||||
|
value = umsgpack.unpackb(msg[1])
|
||||||
|
|
||||||
|
if value == 'None':
|
||||||
|
value = helpers.dump(key)
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
logger.info("{} dumped".format(key))
|
logger.info("{} dumped".format(key))
|
||||||
@ -195,9 +199,15 @@ class RCFClientAgent(object):
|
|||||||
logger.error("Fail to dump ")
|
logger.error("Fail to dump ")
|
||||||
|
|
||||||
elif command == b"GET":
|
elif command == b"GET":
|
||||||
|
value = []
|
||||||
key = umsgpack.unpackb(msg[0])
|
key = umsgpack.unpackb(msg[0])
|
||||||
value = self.property_map.get(key)
|
for k in self.property_map.keys():
|
||||||
self.pipe.send(umsgpack.packb(value.body) if value else b'')
|
if key in k:
|
||||||
|
value.append([k,self.property_map.get(k).body])
|
||||||
|
|
||||||
|
# value = [self.property_map.get(key) for key in keys]
|
||||||
|
# value = self.property_map.get(key)
|
||||||
|
self.pipe.send(umsgpack.packb(value) if value else b'')
|
||||||
|
|
||||||
elif command == b"LIST":
|
elif command == b"LIST":
|
||||||
self.pipe.send(umsgpack.packb(list(self.property_map)))
|
self.pipe.send(umsgpack.packb(list(self.property_map)))
|
||||||
@ -246,7 +256,7 @@ def rcf_client_agent(ctx, pipe,queue):
|
|||||||
if agent.state == State.SYNCING:
|
if agent.state == State.SYNCING:
|
||||||
# Store snapshot
|
# Store snapshot
|
||||||
if rcfmsg.key == "SNAPSHOT_END":
|
if rcfmsg.key == "SNAPSHOT_END":
|
||||||
# logger.info("snapshot complete")
|
logger.info("snapshot complete")
|
||||||
agent.state = State.ACTIVE
|
agent.state = State.ACTIVE
|
||||||
else:
|
else:
|
||||||
helpers.load(rcfmsg.key,rcfmsg.body)
|
helpers.load(rcfmsg.key,rcfmsg.body)
|
||||||
@ -254,7 +264,8 @@ def rcf_client_agent(ctx, pipe,queue):
|
|||||||
elif agent.state == State.ACTIVE:
|
elif agent.state == State.ACTIVE:
|
||||||
if rcfmsg.id != agent.id:
|
if rcfmsg.id != agent.id:
|
||||||
# update_queue.put((rcfmsg.key,rcfmsg.body))
|
# update_queue.put((rcfmsg.key,rcfmsg.body))
|
||||||
helpers.load(rcfmsg.key,rcfmsg.body)
|
with lock:
|
||||||
|
helpers.load(rcfmsg.key,rcfmsg.body)
|
||||||
# logger.info("load")
|
# logger.info("load")
|
||||||
# agent.serial.send_multipart([b"LOAD", umsgpack.packb(rcfmsg.key), umsgpack.packb(rcfmsg.body)])
|
# agent.serial.send_multipart([b"LOAD", umsgpack.packb(rcfmsg.key), umsgpack.packb(rcfmsg.body)])
|
||||||
|
|
||||||
@ -298,6 +309,7 @@ class SerializationAgent(object):
|
|||||||
|
|
||||||
key = umsgpack.unpackb(msg[0])
|
key = umsgpack.unpackb(msg[0])
|
||||||
value = umsgpack.unpackb(msg[1])
|
value = umsgpack.unpackb(msg[1])
|
||||||
|
|
||||||
|
|
||||||
helpers.load(key,value)
|
helpers.load(key,value)
|
||||||
|
|
||||||
@ -307,7 +319,6 @@ class SerializationAgent(object):
|
|||||||
def serialization_agent(ctx, pipe):
|
def serialization_agent(ctx, pipe):
|
||||||
agent = SerializationAgent(ctx, pipe)
|
agent = SerializationAgent(ctx, pipe)
|
||||||
|
|
||||||
|
|
||||||
global stop
|
global stop
|
||||||
while True:
|
while True:
|
||||||
if stop:
|
if stop:
|
||||||
@ -325,3 +336,5 @@ def serialization_agent(ctx, pipe):
|
|||||||
if agent.pipe in items:
|
if agent.pipe in items:
|
||||||
agent.control_message()
|
agent.control_message()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
draw.py
4
draw.py
@ -47,7 +47,7 @@ def get_client_view_rect():
|
|||||||
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)
|
||||||
)
|
)
|
||||||
@ -105,6 +105,8 @@ class HUD(object):
|
|||||||
|
|
||||||
self.draw_items.clear()
|
self.draw_items.clear()
|
||||||
|
|
||||||
|
clients = self.client.get("Client")
|
||||||
|
|
||||||
for key, values in self.client.property_map.items():
|
for key, values in self.client.property_map.items():
|
||||||
if 'net' in key and values.body is not None and values.id != self.client.id:
|
if 'net' in key and values.body is not None and values.id != self.client.id:
|
||||||
if values.mtype == "clientObject":
|
if values.mtype == "clientObject":
|
||||||
|
@ -41,7 +41,9 @@ def load(key, value):
|
|||||||
elif target_type == 'Camera':
|
elif target_type == 'Camera':
|
||||||
load_default(target=target, data=value,
|
load_default(target=target, data=value,
|
||||||
create=True, type=target_type)
|
create=True, type=target_type)
|
||||||
|
elif target_type == 'Client':
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def resolve_bpy_path(path):
|
def resolve_bpy_path(path):
|
||||||
"""
|
"""
|
||||||
|
10
message.py
10
message.py
@ -48,25 +48,23 @@ class RCFMessage(object):
|
|||||||
def send(self, socket):
|
def send(self, socket):
|
||||||
"""Send key-value message to socket; any empty frames are sent as such."""
|
"""Send key-value message to socket; any empty frames are sent as such."""
|
||||||
key = ''.encode() if self.key is None else self.key.encode()
|
key = ''.encode() if self.key is None else self.key.encode()
|
||||||
mtype = ''.encode() if self.mtype is None else self.mtype.encode()
|
|
||||||
body = ''.encode() if self.body is None else umsgpack.packb(self.body)
|
body = ''.encode() if self.body is None else umsgpack.packb(self.body)
|
||||||
id = ''.encode() if self.id is None else self.id
|
id = ''.encode() if self.id is None else self.id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
socket.send_multipart([key, id, mtype, body])
|
socket.send_multipart([key, id, body])
|
||||||
except:
|
except:
|
||||||
logger.info("Fail to send {} {}".format(key, id))
|
print("Fail to send {} {}".format(key, id))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def recv(cls, socket):
|
def recv(cls, socket):
|
||||||
"""Reads key-value message from socket, returns new kvmsg instance."""
|
"""Reads key-value message from socket, returns new kvmsg instance."""
|
||||||
key, id, mtype, body = socket.recv_multipart(zmq.DONTWAIT)
|
key, id, body = socket.recv_multipart(zmq.DONTWAIT)
|
||||||
key = key.decode() if key else None
|
key = key.decode() if key else None
|
||||||
id = id if id else None
|
id = id if id else None
|
||||||
mtype = mtype.decode() if body else None
|
|
||||||
body = umsgpack.unpackb(body) if body else None
|
body = umsgpack.unpackb(body) if body else None
|
||||||
|
|
||||||
return cls(key=key, id=id, mtype=mtype, body=body)
|
return cls(key=key, id=id, body=body)
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
if self.body is None:
|
if self.body is None:
|
||||||
|
76
operators.py
76
operators.py
@ -17,7 +17,7 @@ from bpy_extras import view3d_utils
|
|||||||
from gpu_extras.batch import batch_for_shader
|
from gpu_extras.batch import batch_for_shader
|
||||||
|
|
||||||
from . import client, ui, draw, helpers
|
from . import client, ui, draw, helpers
|
||||||
|
from .libs import umsgpack
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -85,21 +85,29 @@ def refresh_window():
|
|||||||
def upload_client_instance_position():
|
def upload_client_instance_position():
|
||||||
global client_instance
|
global client_instance
|
||||||
|
|
||||||
|
username = bpy.context.scene.session_settings.username
|
||||||
if client_instance:
|
if client_instance:
|
||||||
key = "net/client_instances/{}".format(client_instance.id.decode())
|
|
||||||
|
key = "Client/{}".format(username)
|
||||||
|
# key = "Object/Cube"
|
||||||
|
print(key)
|
||||||
try:
|
try:
|
||||||
current_coords = net_draw.get_client_instance_view_rect()
|
current_coords = draw.get_client_view_rect()
|
||||||
data = client_instance.property_map[key].body
|
client = client_instance.get(key)
|
||||||
if data is None:
|
# print((client[0][1][b'location']))
|
||||||
data = {}
|
|
||||||
data['location'] = current_coords
|
|
||||||
color = bpy.context.scene.session_settings.client_instance_color
|
# if data is None:
|
||||||
data['color'] = (color.r, color.g, color.b, 1)
|
# data = {}
|
||||||
client_instance.push_update(key, 'client_instance', data)
|
# data['location'] = current_coords
|
||||||
elif current_coords[0] != data['location'][0]:
|
# color = bpy.context.scene.session_settings.client_instance_color
|
||||||
data['location'] = current_coords
|
# data['color'] = (color.r, color.g, color.b, 1)
|
||||||
client_instance.push_update(key, 'client_instance', data)
|
# client_instance.push_update(key, 'client_instance', data)
|
||||||
|
if current_coords != client[0][1][b'location']:
|
||||||
|
print(current_coords)
|
||||||
|
print(client[0][1][b'location'])
|
||||||
|
client[0][1][b'location'] = current_coords
|
||||||
|
client_instance.set(key, client[0][1])
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -305,11 +313,11 @@ def default_tick():
|
|||||||
# print("pull error: {}".format(e))
|
# print("pull error: {}".format(e))
|
||||||
|
|
||||||
# bpy.ops.session.refresh()
|
# bpy.ops.session.refresh()
|
||||||
global client_instance
|
# global client_instance
|
||||||
|
|
||||||
if not client_instance.queue.empty():
|
# if not client_instance.queue.empty():
|
||||||
update = client_instance.queue.get()
|
# update = client_instance.queue.get()
|
||||||
helpers.load(update[0],update[1])
|
# helpers.load(update[0],update[1])
|
||||||
|
|
||||||
return 0.001
|
return 0.001
|
||||||
|
|
||||||
@ -342,18 +350,18 @@ def material_tick():
|
|||||||
|
|
||||||
def draw_tick():
|
def draw_tick():
|
||||||
# drawing
|
# drawing
|
||||||
global drawer
|
# global drawer
|
||||||
|
|
||||||
drawer.draw()
|
# drawer.draw()
|
||||||
|
|
||||||
# Upload
|
# Upload
|
||||||
upload_client_instance_position()
|
upload_client_instance_position()
|
||||||
return 0.2
|
return 1
|
||||||
|
|
||||||
|
|
||||||
def register_ticks():
|
def register_ticks():
|
||||||
# REGISTER Updaters
|
# REGISTER Updaters
|
||||||
# bpy.app.timers.register(draw_tick)
|
bpy.app.timers.register(draw_tick)
|
||||||
# bpy.app.timers.register(mesh_tick)
|
# bpy.app.timers.register(mesh_tick)
|
||||||
# bpy.app.timers.register(object_tick)
|
# bpy.app.timers.register(object_tick)
|
||||||
bpy.app.timers.register(default_tick)
|
bpy.app.timers.register(default_tick)
|
||||||
@ -363,7 +371,7 @@ def unregister_ticks():
|
|||||||
# REGISTER Updaters
|
# REGISTER Updaters
|
||||||
# global drawer
|
# global drawer
|
||||||
# drawer.unregister_handlers()
|
# drawer.unregister_handlers()
|
||||||
# bpy.app.timers.unregister(draw_tick)
|
bpy.app.timers.unregister(draw_tick)
|
||||||
# bpy.app.timers.unregister(mesh_tick)
|
# bpy.app.timers.unregister(mesh_tick)
|
||||||
# bpy.app.timers.unregister(object_tick)
|
# bpy.app.timers.unregister(object_tick)
|
||||||
bpy.app.timers.unregister(default_tick)
|
bpy.app.timers.unregister(default_tick)
|
||||||
@ -446,6 +454,24 @@ class session_add_property(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class session_get_property(bpy.types.Operator):
|
||||||
|
bl_idname = "session.get_prop"
|
||||||
|
bl_label = "get"
|
||||||
|
bl_description = "broadcast a property to connected client_instances"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
global client_instance
|
||||||
|
|
||||||
|
client_instance.get("client")
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class session_remove_property(bpy.types.Operator):
|
class session_remove_property(bpy.types.Operator):
|
||||||
bl_idname = "session.remove_prop"
|
bl_idname = "session.remove_prop"
|
||||||
bl_label = "remove"
|
bl_label = "remove"
|
||||||
@ -592,6 +618,7 @@ classes = (
|
|||||||
session_join,
|
session_join,
|
||||||
session_refresh,
|
session_refresh,
|
||||||
session_add_property,
|
session_add_property,
|
||||||
|
session_get_property,
|
||||||
session_stop,
|
session_stop,
|
||||||
session_create,
|
session_create,
|
||||||
session_settings,
|
session_settings,
|
||||||
@ -642,6 +669,7 @@ def depsgraph_update(scene):
|
|||||||
# if updated_data.is_updated_transform:
|
# if updated_data.is_updated_transform:
|
||||||
# add_update(updated_data.id.bl_rna.name, updated_data.id.name)
|
# add_update(updated_data.id.bl_rna.name, updated_data.id.name)
|
||||||
# else:
|
# else:
|
||||||
|
|
||||||
if is_dirty(updates):
|
if is_dirty(updates):
|
||||||
for update in ordered(updates):
|
for update in ordered(updates):
|
||||||
if update[2] == "Master Collection":
|
if update[2] == "Master Collection":
|
||||||
@ -650,7 +678,7 @@ def depsgraph_update(scene):
|
|||||||
client_instance.set("{}/{}".format(update[1], update[2]))
|
client_instance.set("{}/{}".format(update[1], update[2]))
|
||||||
|
|
||||||
|
|
||||||
if len(updates) is 1 and len(bpy.context.selected_objects)>0:
|
if len(bpy.context.selected_objects)>0:
|
||||||
updated_data = updates[0]
|
updated_data = updates[0]
|
||||||
if updated_data.id.name == bpy.context.selected_objects[0].name:
|
if updated_data.id.name == bpy.context.selected_objects[0].name:
|
||||||
if updated_data.is_updated_transform or updated_data.is_updated_geometry:
|
if updated_data.is_updated_transform or updated_data.is_updated_geometry:
|
||||||
|
13
server.py
13
server.py
@ -8,7 +8,7 @@ import message
|
|||||||
logger = logging.getLogger("Server")
|
logger = logging.getLogger("Server")
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
SUPPORTED_TYPES = [ 'Material',
|
SUPPORTED_TYPES = [ 'Client', 'Material',
|
||||||
'Texture', 'Light', 'Camera','Mesh', 'Grease Pencil', 'Object', 'Action', 'Armature','Collection', 'Scene']
|
'Texture', 'Light', 'Camera','Mesh', 'Grease Pencil', 'Object', 'Action', 'Armature','Collection', 'Scene']
|
||||||
|
|
||||||
class RCFServerAgent():
|
class RCFServerAgent():
|
||||||
@ -66,6 +66,17 @@ class RCFServerAgent():
|
|||||||
request = msg[1]
|
request = msg[1]
|
||||||
|
|
||||||
if request == b"SNAPSHOT_REQUEST":
|
if request == b"SNAPSHOT_REQUEST":
|
||||||
|
client_key = "Client/{}".format(identity.decode())
|
||||||
|
|
||||||
|
if client_key not in self.property_map.keys():
|
||||||
|
logger.info("New user:{}".format(identity.decode()))
|
||||||
|
|
||||||
|
client_dict = {}
|
||||||
|
client_dict['location'] = [0,0,0]
|
||||||
|
client_dict['active_object'] = ''
|
||||||
|
client_store = message.RCFMessage(key=client_key, id=identity,body=client_dict)
|
||||||
|
logger.info(client_store)
|
||||||
|
client_store.store(self.property_map)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.info("Bad snapshot request")
|
logger.info("Bad snapshot request")
|
||||||
|
Reference in New Issue
Block a user