This commit is contained in:
Swann 2019-02-08 18:34:10 +01:00
parent c86953eb75
commit ead3189b0c
No known key found for this signature in database
GPG Key ID: B02D0B41F8B6D2EE
5 changed files with 190 additions and 60 deletions

70
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,70 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File (Integrated Terminal)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"port": 5678,
"host": "localhost",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "."
}
]
},
{
"name": "Python: Module",
"type": "python",
"request": "launch",
"module": "enter-your-module-name-here",
"console": "integratedTerminal"
},
{
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"console": "integratedTerminal",
"args": [
"runserver",
"--noreload",
"--nothreading"
],
"django": true
},
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app.py"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
],
"jinja": true
},
{
"name": "Python: Current File (External Terminal)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "externalTerminal"
}
]
}

View File

@ -28,6 +28,7 @@ import bpy
def register(): def register():
bpy.types.Scene.message = bpy.props.StringProperty(default="Hi") bpy.types.Scene.message = bpy.props.StringProperty(default="Hi")
bsyncio.register() bsyncio.register()
net_operators.register() net_operators.register()
net_ui.register() net_ui.register()

View File

@ -1,60 +1,81 @@
import zmq import zmq
import asyncio import asyncio
import logging import logging
from .libs import umsgpack
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
class Session(): class Session():
def __init__(self, host='127.0.0.1', port=5555, is_hosting=False): def __init__(self, host='127.0.0.1', port=5555, is_hosting=False):
self.host = host self.host = host
self.port = port self.port = port
self.is_running = False
# init zmq context # init zmq context
self.context = zmq.Context() self.context = zmq.Context()
self.socket = None
# init socket interface
if is_hosting:
self.socket = self.context.socket(zmq.REP)
self.socket.bind("tcp://*:5555")
else:
self.socket = self.context.socket(zmq.REQ)
self.socket.connect("tcp://127.0.0.1:5555")
self.listen = asyncio.ensure_future(self.listen())
self.msg = [] self.msg = []
def is_running(self): #self.listen.add_done_callback(self.close_success())
try:
return not self.listen.done
except:
return False
# TODO: Add a kill signal to destroy clients session # TODO: Add a kill signal to destroy clients session
# TODO: Add a join method # TODO: Add a join method
# TODO: Add a create session method # TODO: Add a create session method
def join(self):
logger.info("joinning {}:{}".format(self.host, self.port))
try:
self.socket = self.context.socket(zmq.REQ)
self.socket.connect("tcp://localhost:5555")
self.listen = asyncio.ensure_future(self.listen())
return True
except zmq.ZMQError:
logger.error("Error while joining {}:{}".format(
self.host, self.port))
return False
# TODO: Find better names
def create(self):
logger.info("Creating session")
try:
self.socket = self.context.socket(zmq.REP)
self.socket.bind("tcp://*:5555")
self.listen = asyncio.ensure_future(self.listen())
return True
except zmq.ZMQError:
logger.error("Error while creating session: ",zmq.ZMQError)
return False
async def listen(self): async def listen(self):
logger.info("Listening on {}:{}".format(self.host, self.port)) logger.info("Listening on {}:{}".format(self.host, self.port))
self.is_running = True
while True: while True:
# Ungly blender workaround to prevent blocking... # Ungly blender workaround to prevent blocking...
await asyncio.sleep(0.016) await asyncio.sleep(0.016)
try: try:
message = self.socket.recv_multipart(zmq.NOBLOCK) msg = self.socket.recv(zmq.NOBLOCK)
self.msg.append(message) # self.msg.append(umsgpack.unpackb(message))
logger.info(message) print(msg)
logger.info(msg)
except zmq.ZMQError: except zmq.ZMQError:
pass pass
def send(self, msg): def send(self, msg):
logger.info("Sending {} to {}:{} ".format(msg, self.host, self.port)) logger.info("Sending {} to {}:{} ".format(msg, self.host, self.port))
bin = umsgpack.packb(msg)
self.socket.send(bin,zmq.NOBLOCK)
self.socket.send(b"msg") async def close_success(self):
self.is_running = False
def close(self): def close(self):
logger.info("Closing session") logger.info("Closing session")
self.socket.close()
self.listen.cancel() self.listen.cancel()
del self.listen
self.is_running = False

View File

@ -3,12 +3,32 @@ from . import net_components
session = None session = None
class join(bpy.types.Operator): class join(bpy.types.Operator):
bl_idname = "session.join" bl_idname = "session.join"
bl_label = "connect to net session" bl_label = "join"
bl_description = "Connect to a net session" bl_description = "Connect to a net session"
bl_options = {"REGISTER"} bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return True
def execute(self, context):
# global session
if session.join():
bpy.ops.asyncio.loop()
else:
print('fail to create session, avorting loop')
return {"FINISHED"}
class create(bpy.types.Operator):
bl_idname = "session.create"
bl_label = "create"
bl_description = "create to a net session"
bl_options = {"REGISTER"}
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@ -17,31 +37,17 @@ class join(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global session global session
session = net_components.Session() if session.create():
bpy.ops.asyncio.loop() bpy.ops.asyncio.loop()
else:
print('fail to create session, avorting loop')
return {"FINISHED"} return {"FINISHED"}
class host(bpy.types.Operator):
bl_idname = "session.host"
bl_label = "host a net session"
bl_description = "Connect to a net session"
bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return True
def execute(self, context):
global session
session = net_components.Session(is_hosting=True)
bpy.ops.asyncio.loop()
return {"FINISHED"}
class send(bpy.types.Operator): class send(bpy.types.Operator):
bl_idname = "session.send" bl_idname = "session.send"
bl_label = "Send a message throught the network" bl_label = "Send"
bl_description = "Connect to a net session" bl_description = "Connect to a net session"
bl_options = {"REGISTER"} bl_options = {"REGISTER"}
@ -54,12 +60,13 @@ class send(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global session global session
session.send(b"") session.send(self.message)
return {"FINISHED"} return {"FINISHED"}
class close(bpy.types.Operator): class close(bpy.types.Operator):
bl_idname = "session.close" bl_idname = "session.close"
bl_label = "Send a message throught the network" bl_label = "Close session"
bl_description = "Connect to a net session" bl_description = "Connect to a net session"
bl_options = {"REGISTER"} bl_options = {"REGISTER"}
@ -70,18 +77,33 @@ class close(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global session global session
bpy.ops.asyncio.stop()
session.close() session.close()
bpy.ops.asyncio.stop()
return {"FINISHED"} return {"FINISHED"}
classes = ( classes = (
join, join,
host, create,
send close,
send,
) )
register, unregister = bpy.utils.register_classes_factory(classes)
def register():
global session
session = net_components.Session()
from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@ -15,21 +15,37 @@ class SessionPanel(bpy.types.Panel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
global session
scene = context.scene scene = context.scene
# Create a simple row. # Create a simple row.
row = layout.row() row = layout.row()
if not session: if net_operators.session.is_running:
row.operator("session.join")
row.operator("session.host")
else:
row.operator("session.close") row.operator("session.close")
row = layout.row()
row = layout.row(align=True)
row.prop(scene,"message",text="")
row.operator("session.send").message = scene.message
row = layout.row()
# Debug area
row.label(text="Debug")
row = layout.row()
area_msg = row.box()
if len(net_operators.session.msg) > 0:
for msg in net_operators.session.msg:
area_msg.label(text=str(msg))
else:
area_msg.label(text="Empty")
else:
row.operator("session.join")
row.operator("session.create")
# row.operator("session.send").message = bpy.scene.message
# row.prop(scene,"message")
classes = ( classes = (
SessionPanel, SessionPanel,