feat: configuration support
This commit is contained in:
parent
34dc4088b5
commit
fa18061687
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,4 +4,5 @@ __pycache__/
|
||||
*$py.classs
|
||||
*.blend1
|
||||
.vscode
|
||||
cache
|
||||
cache
|
||||
config
|
58
__init__.py
58
__init__.py
@ -10,6 +10,7 @@ bl_info = {
|
||||
|
||||
|
||||
import addon_utils
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
@ -24,6 +25,8 @@ DEPENDENCIES = {
|
||||
"PyYAML"
|
||||
}
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# UTILITY FUNCTIONS
|
||||
def client_list_callback(scene, context):
|
||||
@ -59,31 +62,49 @@ def randomColor():
|
||||
b = random.random()
|
||||
return [r, v, b]
|
||||
|
||||
def save_session_config(self,context):
|
||||
config = environment.load_config()
|
||||
|
||||
config["username"] = self.username
|
||||
config["ip"] = self.ip
|
||||
config["port"] = self.port
|
||||
config["start_empty"] = self.start_empty
|
||||
config["enable_presence"] = self.enable_presence
|
||||
|
||||
environment.save_config(config)
|
||||
|
||||
class SessionProps(bpy.types.PropertyGroup):
|
||||
username: bpy.props.StringProperty(
|
||||
name="Username",
|
||||
default="user_{}".format(randomStringDigits())
|
||||
default="user_{}".format(randomStringDigits()),
|
||||
update=save_session_config
|
||||
)
|
||||
ip: bpy.props.StringProperty(
|
||||
name="ip",
|
||||
description='Distant host ip',
|
||||
default="127.0.0.1")
|
||||
default="127.0.0.1",
|
||||
update=save_session_config
|
||||
)
|
||||
port: bpy.props.IntProperty(
|
||||
name="port",
|
||||
description='Distant host port',
|
||||
default=5554)
|
||||
default=5555,
|
||||
update=save_session_config
|
||||
)
|
||||
|
||||
add_property_depth: bpy.props.IntProperty(
|
||||
name="add_property_depth",
|
||||
default=1)
|
||||
default=1
|
||||
)
|
||||
buffer: bpy.props.StringProperty(name="None")
|
||||
is_admin: bpy.props.BoolProperty(name="is_admin", default=False)
|
||||
load_data: bpy.props.BoolProperty(name="load_data", default=True)
|
||||
init_scene: bpy.props.BoolProperty(name="load_data", default=True)
|
||||
clear_scene: bpy.props.BoolProperty(name="clear_scene", default=False)
|
||||
start_empty: bpy.props.BoolProperty(name="start_empty", default=False)
|
||||
update_frequency: bpy.props.FloatProperty(
|
||||
name="update_frequency", default=0.008)
|
||||
name="update_frequency",
|
||||
default=0.008
|
||||
)
|
||||
active_object: bpy.props.PointerProperty(
|
||||
name="active_object", type=bpy.types.Object)
|
||||
session_mode: bpy.props.EnumProperty(
|
||||
@ -102,11 +123,26 @@ class SessionProps(bpy.types.PropertyGroup):
|
||||
description="client enum",
|
||||
items=client_list_callback
|
||||
)
|
||||
enable_draw: bpy.props.BoolProperty(
|
||||
name="enable_draw",
|
||||
enable_presence: bpy.props.BoolProperty(
|
||||
name="enable_presence",
|
||||
description='Enable overlay drawing module',
|
||||
default=True)
|
||||
default=True,
|
||||
update=save_session_config
|
||||
)
|
||||
|
||||
def load(self):
|
||||
config = environment.load_config()
|
||||
logger.info(config)
|
||||
if config:
|
||||
self.username = config["username"]
|
||||
self.ip = config["ip"]
|
||||
self.port = config["port"]
|
||||
self.start_empty = config["start_empty"]
|
||||
self.enable_presence = config["enable_presence"]
|
||||
else:
|
||||
logger.error("Fail to read config")
|
||||
|
||||
|
||||
|
||||
classes = {
|
||||
SessionProps,
|
||||
@ -114,7 +150,7 @@ classes = {
|
||||
|
||||
|
||||
def register():
|
||||
environment.setup(DEPENDENCIES)
|
||||
environment.setup(DEPENDENCIES,bpy.app.binary_path_python)
|
||||
|
||||
from . import operators
|
||||
from . import ui
|
||||
@ -127,6 +163,8 @@ def register():
|
||||
bpy.types.WindowManager.session = bpy.props.PointerProperty(
|
||||
type=SessionProps)
|
||||
|
||||
bpy.context.window_manager.session.load()
|
||||
|
||||
operators.register()
|
||||
ui.register()
|
||||
|
||||
|
@ -12,7 +12,7 @@ from random import randint
|
||||
import zmq
|
||||
import json
|
||||
|
||||
from . import helpers, message
|
||||
from . import environment, helpers, message
|
||||
from .libs import dump_anything, umsgpack
|
||||
|
||||
CONNECT_TIMEOUT = 2
|
||||
@ -23,7 +23,7 @@ DUMP_AGENTS_NUMBER = 1
|
||||
|
||||
lock = threading.Lock()
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.basicConfig(level=environment)
|
||||
instance = None
|
||||
|
||||
|
||||
@ -202,6 +202,7 @@ class Client(object):
|
||||
line = json.dumps(value.body)
|
||||
fp.write(line)
|
||||
|
||||
|
||||
class Server(object):
|
||||
address = None # Server address
|
||||
port = None # Server port
|
||||
|
@ -1,14 +1,32 @@
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
import logging
|
||||
import yaml
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config")
|
||||
CONFIG = os.path.join(CONFIG_DIR, "app.yaml")
|
||||
|
||||
THIRD_PARTY = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libs")
|
||||
PYTHON_PATH = None
|
||||
SUBPROCESS_DIR = None
|
||||
|
||||
|
||||
def load_config():
|
||||
logger.info("loading config")
|
||||
with open(CONFIG, 'r') as config_file:
|
||||
return yaml.safe_load(config_file)
|
||||
|
||||
return None
|
||||
|
||||
def save_config(config):
|
||||
logger.info("saving config")
|
||||
with open(CONFIG, 'w') as outfile:
|
||||
yaml.dump(config, outfile, default_flow_style=False)
|
||||
|
||||
CONFIG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),"config")
|
||||
APP_CONFIG = os.path.join(CONFIG_DIR,"config.yaml")
|
||||
THIRD_PARTY = os.path.join(os.path.dirname(os.path.abspath(__file__)),"libs")
|
||||
PYTHON_PATH = Path(bpy.app.binary_path_python)
|
||||
SUBPROCESS_DIR = PYTHON_PATH.parent
|
||||
|
||||
def module_can_be_imported(name):
|
||||
try:
|
||||
@ -32,11 +50,17 @@ def install_pip():
|
||||
|
||||
def install_package(name):
|
||||
target = get_package_install_directory()
|
||||
|
||||
subprocess.run([str(PYTHON_PATH), "-m", "pip", "install",
|
||||
name, '--target', target], cwd=SUBPROCESS_DIR)
|
||||
|
||||
def setup(dependencies):
|
||||
subprocess.run([str(PYTHON_PATH), "-m", "pip", "install",
|
||||
name, '--target', target], cwd=SUBPROCESS_DIR)
|
||||
|
||||
|
||||
def setup(dependencies, python_path):
|
||||
global PYTHON_PATH, SUBPROCESS_DIR
|
||||
|
||||
PYTHON_PATH = Path(python_path)
|
||||
SUBPROCESS_DIR = PYTHON_PATH.parent
|
||||
|
||||
if not module_can_be_imported("pip"):
|
||||
install_pip()
|
||||
|
||||
|
@ -130,7 +130,7 @@ def load_client(client=None, data=None):
|
||||
net_settings = C.window_manager.session
|
||||
|
||||
if client and data:
|
||||
if net_settings.enable_draw:
|
||||
if net_settings.enable_presence:
|
||||
draw.renderer.draw_client(data)
|
||||
|
||||
draw.renderer.draw_client_selected_objects(data)
|
||||
|
23
operators.py
23
operators.py
@ -88,7 +88,6 @@ def update_client_selected_object(context):
|
||||
|
||||
# TODO: cleanup
|
||||
|
||||
|
||||
def init_datablocks():
|
||||
for datatype in helpers.BPY_TYPES.keys():
|
||||
for item in getattr(bpy.data, helpers.BPY_TYPES[datatype]):
|
||||
@ -134,7 +133,7 @@ class SessionJoinOperator(bpy.types.Operator):
|
||||
global execution_queue
|
||||
net_settings = context.window_manager.session
|
||||
# Scene setup
|
||||
if net_settings.clear_scene:
|
||||
if net_settings.start_empty:
|
||||
clean_scene()
|
||||
|
||||
# Session setup
|
||||
@ -157,7 +156,7 @@ class SessionJoinOperator(bpy.types.Operator):
|
||||
register_ticks()
|
||||
|
||||
# Launch drawing module
|
||||
if net_settings.enable_draw:
|
||||
if net_settings.enable_presence:
|
||||
draw.renderer.run()
|
||||
|
||||
return {"FINISHED"}
|
||||
@ -394,7 +393,22 @@ class SessionDumpDatabase(bpy.types.Operator, ExportHelper):
|
||||
return {"CANCELLED"}
|
||||
|
||||
pass
|
||||
# TODO: Rename to match official blender convention
|
||||
|
||||
|
||||
class SessionSaveConfig(bpy.types.Operator):
|
||||
bl_idname = "session.save"
|
||||
bl_label = "Save session configuration"
|
||||
bl_description = "Save session configuration"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
context.window_manager.session.save()
|
||||
|
||||
|
||||
classes = (
|
||||
SessionJoinOperator,
|
||||
SessionPropertyAddOperator,
|
||||
@ -405,6 +419,7 @@ classes = (
|
||||
SessionSnapUserOperator,
|
||||
SessionPropertyRightOperator,
|
||||
SessionDumpDatabase,
|
||||
SessionSaveConfig,
|
||||
)
|
||||
|
||||
|
||||
|
10
server.py
10
server.py
@ -1,5 +1,6 @@
|
||||
import logging
|
||||
import time
|
||||
import environment
|
||||
from operator import itemgetter
|
||||
|
||||
|
||||
@ -14,7 +15,8 @@ SUPPORTED_TYPES = ['Client','Curve','Material','Texture', 'Light', 'Camera', 'Me
|
||||
class ServerAgent():
|
||||
def __init__(self, context=zmq.Context.instance(), id="admin"):
|
||||
self.context = context
|
||||
|
||||
self.config = environment.load_config()
|
||||
self.port = int(self.config['port'])
|
||||
self.pub_sock = None
|
||||
self.request_sock = None
|
||||
self.collector_sock = None
|
||||
@ -32,19 +34,19 @@ class ServerAgent():
|
||||
# Update all clients
|
||||
self.pub_sock = self.context.socket(zmq.PUB)
|
||||
self.pub_sock.setsockopt(zmq.SNDHWM, 60)
|
||||
self.pub_sock.bind("tcp://*:5555")
|
||||
self.pub_sock.bind("tcp://*:"+str(self.port+1))
|
||||
time.sleep(0.2)
|
||||
|
||||
# Update request
|
||||
self.request_sock = self.context.socket(zmq.ROUTER)
|
||||
self.request_sock.setsockopt(zmq.IDENTITY, b'SERVER')
|
||||
self.request_sock.setsockopt(zmq.RCVHWM, 60)
|
||||
self.request_sock.bind("tcp://*:5554")
|
||||
self.request_sock.bind("tcp://*:"+str(self.port))
|
||||
|
||||
# Update collector
|
||||
self.collector_sock = self.context.socket(zmq.PULL)
|
||||
self.collector_sock.setsockopt(zmq.RCVHWM, 60)
|
||||
self.collector_sock.bind("tcp://*:5556")
|
||||
self.collector_sock.bind("tcp://*:"+str(self.port+2))
|
||||
|
||||
# poller for socket aggregation
|
||||
self.poller = zmq.Poller()
|
||||
|
15
ui.py
15
ui.py
@ -9,11 +9,15 @@ ICONS = {'Curve':'CURVE_DATA', 'Client':'SOLO_ON','Collection': 'FILE_FOLDER', '
|
||||
|
||||
class SESSION_PT_settings(bpy.types.Panel):
|
||||
bl_idname = "MULTIUSER_SETTINGS_PT_panel"
|
||||
bl_label = "Network"
|
||||
bl_label = "Settings"
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Multiuser"
|
||||
|
||||
def draw_header(self, context):
|
||||
self.layout.label(text="", icon='TOOL_SETTINGS')
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@ -41,10 +45,10 @@ class SESSION_PT_settings(bpy.types.Panel):
|
||||
|
||||
row = box.row()
|
||||
row.label(text="draw overlay:")
|
||||
row.prop(net_settings, "enable_draw", text="")
|
||||
row.prop(net_settings, "enable_presence", text="")
|
||||
row = box.row()
|
||||
row.label(text="clear blend:")
|
||||
row.prop(net_settings, "clear_scene", text="")
|
||||
row.prop(net_settings, "start_empty", text="")
|
||||
row = box.row()
|
||||
|
||||
row = box.row()
|
||||
@ -82,7 +86,7 @@ class SESSION_PT_settings(bpy.types.Panel):
|
||||
# row = layout.row(align=True)
|
||||
# row.operator("session.dump", icon='QUIT', text="Dump")
|
||||
# row.operator("session.dump", icon='QUIT', text="Load")
|
||||
# row = layout.row()
|
||||
row = layout.row()
|
||||
|
||||
box = row.box()
|
||||
row = box.row()
|
||||
@ -158,6 +162,9 @@ class SESSION_PT_properties(bpy.types.Panel):
|
||||
def poll(cls, context):
|
||||
return client.instance and client.instance.state() == 3
|
||||
|
||||
def draw_header(self, context):
|
||||
self.layout.label(text="", icon='OUTLINER_OB_GROUP_INSTANCE')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user