multi-user/__init__.py

285 lines
8.4 KiB
Python
Raw Normal View History

2019-02-08 00:41:18 +08:00
bl_info = {
"name": "Multi-User",
"author": "CUBE CREATIVE",
"description": "",
"blender": (2, 80, 0),
"location": "",
"warning": "Unstable addon, use it at your own risks",
"category": "Collaboration"
2019-02-08 00:41:18 +08:00
}
2019-03-14 23:44:18 +08:00
2019-07-02 00:04:35 +08:00
import logging
2019-08-23 18:28:57 +08:00
import os
import random
import sys
2019-08-23 18:28:57 +08:00
import bpy
2019-08-22 16:58:54 +08:00
from bpy.app.handlers import persistent
2019-09-25 00:37:36 +08:00
from . import environment, utils, presence
2019-09-24 20:42:59 +08:00
from .libs.replication.replication.constants import RP_COMMON
2019-08-23 18:28:57 +08:00
# TODO: remove dependency as soon as replication will be installed as a module
DEPENDENCIES = {
2019-08-27 05:14:30 +08:00
("zmq","zmq"),
("msgpack","msgpack"),
("yaml","pyyaml"),
("jsondiff","jsondiff")
}
2019-07-02 22:43:30 +08:00
2019-07-02 00:04:35 +08:00
logger = logging.getLogger(__name__)
2019-07-20 00:37:57 +08:00
logger.setLevel(logging.DEBUG)
2019-08-29 20:52:14 +08: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 19:43:43 +08: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 21:57:07 +08:00
from . import operators
from .bl_types.bl_user import BlUser
2019-05-22 23:17:09 +08:00
2019-09-24 20:42:59 +08:00
items = [(RP_COMMON, RP_COMMON, "")]
username = bpy.context.window_manager.session.username
2019-08-14 21:57:07 +08:00
cli = operators.client
if cli:
client_keys = cli.list(filter=BlUser)
for k in client_keys:
name = cli.get(uuid=k).buffer["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 22:43:30 +08: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 23:00:15 +08:00
use_as_filter: bpy.props.BoolProperty(default=True)
2019-09-16 19:43:43 +08:00
auto_push: bpy.props.BoolProperty(default=True)
icon: bpy.props.StringProperty()
class SessionProps(bpy.types.PropertyGroup):
2019-05-16 00:37:14 +08:00
username: bpy.props.StringProperty(
name="Username",
2019-09-24 19:26:51 +08:00
default="user_{}".format(utils.random_string_digits())
)
2019-05-16 00:37:14 +08:00
ip: bpy.props.StringProperty(
name="ip",
description='Distant host ip',
2019-09-24 19:26:51 +08:00
default="127.0.0.1"
2019-07-02 00:04:35 +08:00
)
user_uuid: bpy.props.StringProperty(
name="user_uuid",
default="None"
)
2019-05-16 00:37:14 +08:00
port: bpy.props.IntProperty(
name="port",
description='Distant host port',
2019-09-24 19:26:51 +08:00
default=5555
2019-07-02 00:04:35 +08:00
)
2019-05-16 00:37:14 +08:00
add_property_depth: bpy.props.IntProperty(
name="add_property_depth",
2019-07-02 00:04:35 +08:00
default=1
)
outliner_filter: bpy.props.StringProperty(name="None")
2019-09-24 19:26:51 +08:00
is_admin: bpy.props.BoolProperty(
name="is_admin",
default=False
)
init_scene: bpy.props.BoolProperty(
name="init_scene",
default=True
)
2019-07-02 00:14:48 +08:00
start_empty: bpy.props.BoolProperty(
name="start_empty",
2019-09-24 19:26:51 +08:00
default=True
)
2019-05-16 00:37:14 +08:00
active_object: bpy.props.PointerProperty(
name="active_object", type=bpy.types.Object)
2019-05-16 00:37:14 +08: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-25 00:37:36 +08: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-16 00:37:14 +08:00
client_color: bpy.props.FloatVectorProperty(
name="client_instance_color",
subtype='COLOR',
2019-09-24 19:26:51 +08:00
default=randomColor())
2019-05-16 00:37:14 +08:00
clients: bpy.props.EnumProperty(
name="clients",
description="client enum",
items=client_list_callback)
2019-07-02 00:04:35 +08:00
enable_presence: bpy.props.BoolProperty(
2019-09-19 19:02:39 +08:00
name="Presence overlay",
description='Enable overlay drawing module',
2019-09-24 20:42:59 +08: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-25 00:37:36 +08:00
)
2019-09-24 20:42:59 +08:00
presence_show_user: bpy.props.BoolProperty(
name="Show users",
description='Enable user overlay ',
default=True,
update=presence.update_overlay_settings
2019-07-02 00:04:35 +08:00
)
supported_datablock: bpy.props.CollectionProperty(
2019-07-02 23:44:59 +08:00
type=ReplicatedDatablock,
)
session_filter: bpy.props.CollectionProperty(
type=ReplicatedDatablock,
)
2019-09-19 05:10:36 +08:00
filter_owned: bpy.props.BoolProperty(
name="filter_owned",
description='Show only owned datablocks',
default=True
)
2019-09-19 19:02:39 +08:00
use_select_right: bpy.props.BoolProperty(
name="Selection right",
description='Change right on selection',
default=True
)
2019-07-02 00:04:35 +08:00
def load(self):
config = environment.load_config()
logger.info(config)
if "username" in config.keys():
2019-07-02 00:04:35 +08: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 22:43:30 +08:00
self.client_color = config["client_color"]
2019-07-02 00:04:35 +08:00
else:
logger.error("Fail to read user config")
2019-07-02 22:43:30 +08: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 21:03:37 +08:00
rep_value.name = datablock
2019-07-02 22:43:30 +08:00
rep_value.type_name = datablock
2019-09-24 19:26:51 +08: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 19:43:43 +08:00
2019-07-02 23:44:59 +08:00
def save(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
config["client_color"] = [self.client_color.r,self.client_color.g,self.client_color.b]
2019-07-03 21:03:37 +08:00
2019-07-02 23:44:59 +08:00
for bloc in self.supported_datablock:
2019-09-24 19:26:51 +08: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 23:44:59 +08:00
environment.save_config(config)
2019-07-02 22:43:30 +08:00
classes = (
ReplicatedDatablock,
2019-08-08 21:35:43 +08:00
SessionProps,
2019-07-02 22:43:30 +08:00
)
2019-08-05 22:48:46 +08: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 22:49:32 +08:00
def register():
2019-08-05 22:48:46 +08:00
if libs not in sys.path:
sys.path.append(libs)
2019-07-02 00:04:35 +08:00
environment.setup(DEPENDENCIES,bpy.app.binary_path_python)
2019-05-16 00:37:14 +08: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-09 00:12:13 +08:00
bpy.types.ID.uuid = bpy.props.StringProperty(default="")
2019-09-24 19:26:51 +08:00
2019-07-02 00:04:35 +08:00
bpy.context.window_manager.session.load()
2019-09-24 19:26:51 +08:00
2019-04-10 23:01:21 +08:00
operators.register()
ui.register()
2019-08-29 20:52:14 +08:00
bpy.app.handlers.load_post.append(load_handler)
2019-02-08 00:41:18 +08:00
def unregister():
2019-05-16 00:37:14 +08:00
from . import operators
from . import ui
2019-04-10 23:01:21 +08:00
ui.unregister()
operators.unregister()
del bpy.types.WindowManager.session
2019-07-02 22:43:30 +08:00
for cls in reversed(classes):
bpy.utils.unregister_class(cls)