multi-user/multi_user/__init__.py

291 lines
8.6 KiB
Python
Raw Normal View History

2019-02-07 17:41:18 +01:00
bl_info = {
"name": "Multi-User",
2019-10-22 16:37:23 +02:00
"author": "Swann Martinez",
"description": "",
"blender": (2, 80, 0),
"location": "",
"warning": "Unstable addon, use it at your own risks",
"category": "Collaboration"
2019-02-07 17:41:18 +01:00
}
2019-03-14 16:44:18 +01:00
2019-07-01 18:04:35 +02:00
import logging
2019-08-23 12:28:57 +02:00
import os
import random
import sys
2019-08-23 12:28:57 +02:00
import bpy
2019-08-22 10:58:54 +02:00
from bpy.app.handlers import persistent
2019-09-24 18:37:36 +02:00
from . import environment, utils, presence
2019-09-24 14:42:59 +02:00
from .libs.replication.replication.constants import RP_COMMON
2019-08-23 12:28:57 +02:00
# TODO: remove dependency as soon as replication will be installed as a module
DEPENDENCIES = {
2019-08-26 23:14:30 +02:00
("zmq","zmq"),
("msgpack","msgpack"),
("yaml","pyyaml"),
("jsondiff","jsondiff")
}
2019-07-02 16:43:30 +02:00
2019-07-01 18:04:35 +02:00
logger = logging.getLogger(__name__)
logger.setLevel(logging.ERROR)
2019-08-29 14:52:14 +02:00
#TODO: refactor config
# UTILITY FUNCTIONS
def generate_supported_types():
stype_dict = {'supported_types':{}}
for type in bl_types.types_to_register():
_type = getattr(bl_types, type)
props = {}
props['bl_delay_refresh']=_type.bl_delay_refresh
props['bl_delay_apply']=_type.bl_delay_apply
props['use_as_filter'] = False
props['icon'] = _type.bl_icon
2019-09-16 13:43:43 +02:00
props['auto_push']=_type.bl_automatic_push
props['bl_name']=_type.bl_id
stype_dict['supported_types'][_type.bl_rep_class.__name__] = props
return stype_dict
def client_list_callback(scene, context):
2019-08-14 15:57:07 +02:00
from . import operators
from .bl_types.bl_user import BlUser
2019-05-22 17:17:09 +02:00
2019-09-24 14:42:59 +02:00
items = [(RP_COMMON, RP_COMMON, "")]
username = bpy.context.window_manager.session.username
2019-08-14 15:57:07 +02:00
cli = operators.client
if cli:
client_keys = cli.list(filter=BlUser)
for k in client_keys:
2019-10-07 18:31:49 +02:00
name = cli.get(uuid=k).data["name"]
name_desc = name
if name == username:
name_desc += " (self)"
items.append((name, name_desc, ""))
return items
def randomColor():
r = random.random()
v = random.random()
b = random.random()
return [r, v, b]
class ReplicatedDatablock(bpy.types.PropertyGroup):
'''name = StringProperty() '''
2019-07-02 16:43:30 +02:00
type_name: bpy.props.StringProperty()
bl_name: bpy.props.StringProperty()
bl_delay_refresh: bpy.props.FloatProperty()
bl_delay_apply: bpy.props.FloatProperty()
2019-09-13 17:00:15 +02:00
use_as_filter: bpy.props.BoolProperty(default=True)
2019-09-16 13:43:43 +02:00
auto_push: bpy.props.BoolProperty(default=True)
icon: bpy.props.StringProperty()
class SessionProps(bpy.types.PropertyGroup):
2019-05-15 18:37:14 +02:00
username: bpy.props.StringProperty(
name="Username",
2019-09-24 13:26:51 +02:00
default="user_{}".format(utils.random_string_digits())
)
2019-05-15 18:37:14 +02:00
ip: bpy.props.StringProperty(
name="ip",
description='Distant host ip',
2019-09-24 13:26:51 +02:00
default="127.0.0.1"
2019-07-01 18:04:35 +02:00
)
user_uuid: bpy.props.StringProperty(
name="user_uuid",
default="None"
)
2019-05-15 18:37:14 +02:00
port: bpy.props.IntProperty(
name="port",
description='Distant host port',
2019-09-24 13:26:51 +02:00
default=5555
2019-07-01 18:04:35 +02:00
)
2019-05-15 18:37:14 +02:00
add_property_depth: bpy.props.IntProperty(
name="add_property_depth",
2019-07-01 18:04:35 +02:00
default=1
)
outliner_filter: bpy.props.StringProperty(name="None")
2019-09-24 13:26:51 +02:00
is_admin: bpy.props.BoolProperty(
name="is_admin",
default=False
)
init_scene: bpy.props.BoolProperty(
name="init_scene",
default=True
)
2019-07-01 18:14:48 +02:00
start_empty: bpy.props.BoolProperty(
name="start_empty",
2019-09-24 13:26:51 +02:00
default=True
)
2019-05-15 18:37:14 +02:00
active_object: bpy.props.PointerProperty(
name="active_object", type=bpy.types.Object)
2019-05-15 18:37:14 +02:00
session_mode: bpy.props.EnumProperty(
name='session_mode',
description='session mode',
items={
('HOST', 'hosting', 'host a session'),
('CONNECT', 'connexion', 'connect to a session')},
default='HOST')
2019-09-24 18:37:36 +02:00
right_strategy: bpy.props.EnumProperty(
name='right_strategy',
description='right strategy',
items={
('STRICT', 'strict', 'strict right repartition'),
('COMMON', 'common', 'relaxed right repartition')},
default='COMMON')
2019-05-15 18:37:14 +02:00
client_color: bpy.props.FloatVectorProperty(
name="client_instance_color",
subtype='COLOR',
2019-09-24 13:26:51 +02:00
default=randomColor())
2019-05-15 18:37:14 +02:00
clients: bpy.props.EnumProperty(
name="clients",
description="client enum",
items=client_list_callback)
2019-07-01 18:04:35 +02:00
enable_presence: bpy.props.BoolProperty(
2019-09-19 13:02:39 +02:00
name="Presence overlay",
description='Enable overlay drawing module',
2019-09-24 14:42:59 +02:00
default=True,
update=presence.update_presence
)
presence_show_selected: bpy.props.BoolProperty(
name="Show selected objects",
description='Enable selection overlay ',
default=True,
update=presence.update_overlay_settings
2019-09-24 18:37:36 +02:00
)
2019-09-24 14:42:59 +02:00
presence_show_user: bpy.props.BoolProperty(
name="Show users",
description='Enable user overlay ',
default=True,
update=presence.update_overlay_settings
2019-07-01 18:04:35 +02:00
)
supported_datablock: bpy.props.CollectionProperty(
2019-07-02 17:44:59 +02:00
type=ReplicatedDatablock,
)
session_filter: bpy.props.CollectionProperty(
type=ReplicatedDatablock,
)
2019-09-18 23:10:36 +02:00
filter_owned: bpy.props.BoolProperty(
name="filter_owned",
description='Show only owned datablocks',
default=True
)
2019-09-19 13:02:39 +02:00
use_select_right: bpy.props.BoolProperty(
name="Selection right",
description='Change right on selection',
default=True
)
2019-07-01 18:04:35 +02:00
def load(self):
config = environment.load_config()
if "username" in config.keys():
2019-07-01 18:04:35 +02:00
self.username = config["username"]
self.ip = config["ip"]
self.port = config["port"]
self.start_empty = config["start_empty"]
self.enable_presence = config["enable_presence"]
2019-07-02 16:43:30 +02:00
self.client_color = config["client_color"]
2019-07-01 18:04:35 +02:00
else:
logger.error("Fail to read user config")
2019-07-02 16:43:30 +02:00
if len(self.supported_datablock)>0:
self.supported_datablock.clear()
if "supported_types" not in config:
config = generate_supported_types()
for datablock in config["supported_types"].keys():
rep_value = self.supported_datablock.add()
2019-07-03 15:03:37 +02:00
rep_value.name = datablock
2019-07-02 16:43:30 +02:00
rep_value.type_name = datablock
2019-09-24 13:26:51 +02:00
config_block = config["supported_types"][datablock]
rep_value.bl_delay_refresh = config_block['bl_delay_refresh']
rep_value.bl_delay_apply = config_block['bl_delay_apply']
rep_value.icon = config_block['icon']
rep_value.auto_push = config_block['auto_push']
rep_value.bl_name = config_block['bl_name']
2019-09-16 13:43:43 +02:00
2019-07-02 17:44:59 +02:00
def save(self,context):
config = environment.load_config()
if "supported_types" not in config:
config = generate_supported_types()
2019-07-02 17:44:59 +02:00
config["username"] = self.username
config["ip"] = self.ip
config["port"] = self.port
config["start_empty"] = self.start_empty
config["enable_presence"] = self.enable_presence
config["client_color"] = [self.client_color.r,self.client_color.g,self.client_color.b]
2019-07-02 17:44:59 +02:00
for bloc in self.supported_datablock:
2019-09-24 13:26:51 +02:00
config_block = config["supported_types"][bloc.type_name]
config_block['bl_delay_refresh'] = bloc.bl_delay_refresh
config_block['bl_delay_apply'] = bloc.bl_delay_apply
config_block['use_as_filter'] = bloc.use_as_filter
config_block['icon'] = bloc.icon
config_block['auto_push'] = bloc.auto_push
config_block['bl_name'] = bloc.bl_name
2019-07-02 17:44:59 +02:00
environment.save_config(config)
2019-07-02 16:43:30 +02:00
classes = (
ReplicatedDatablock,
2019-08-08 15:35:43 +02:00
SessionProps,
2019-07-02 16:43:30 +02:00
)
2019-08-05 16:48:46 +02:00
libs = os.path.dirname(os.path.abspath(__file__))+"\\libs\\replication"
@persistent
def load_handler(dummy):
import bpy
bpy.context.window_manager.session.load()
2019-05-23 16:49:32 +02:00
def register():
2019-08-05 16:48:46 +02:00
if libs not in sys.path:
sys.path.append(libs)
2019-07-01 18:04:35 +02:00
environment.setup(DEPENDENCIES,bpy.app.binary_path_python)
2019-05-15 18:37:14 +02:00
from . import presence
2019-05-15 18:37:14 +02:00
from . import operators
from . import ui
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.WindowManager.session = bpy.props.PointerProperty(
type=SessionProps)
2019-08-08 18:12:13 +02:00
bpy.types.ID.uuid = bpy.props.StringProperty(default="")
2019-09-24 13:26:51 +02:00
2019-07-01 18:04:35 +02:00
bpy.context.window_manager.session.load()
2019-09-24 13:26:51 +02:00
presence.register()
2019-04-10 17:01:21 +02:00
operators.register()
ui.register()
2019-08-29 14:52:14 +02:00
bpy.app.handlers.load_post.append(load_handler)
2019-02-07 17:41:18 +01:00
def unregister():
from . import presence
2019-05-15 18:37:14 +02:00
from . import operators
from . import ui
presence.unregister()
2019-04-10 17:01:21 +02:00
ui.unregister()
operators.unregister()
del bpy.types.WindowManager.session
2019-07-02 16:43:30 +02:00
for cls in reversed(classes):
bpy.utils.unregister_class(cls)