2019-02-08 00:41:18 +08:00
|
|
|
bl_info = {
|
2019-07-01 21:39:01 +08:00
|
|
|
"name": "Multi-User",
|
|
|
|
"author": "CUBE CREATIVE",
|
2019-05-21 22:53:55 +08:00
|
|
|
"description": "",
|
|
|
|
"blender": (2, 80, 0),
|
|
|
|
"location": "",
|
|
|
|
"warning": "",
|
|
|
|
"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-07-01 21:39:01 +08:00
|
|
|
import random
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import bpy
|
2019-07-02 21:55:57 +08:00
|
|
|
from . import environment
|
2019-08-08 21:35:43 +08:00
|
|
|
from . import utils
|
2019-08-22 16:58:54 +08:00
|
|
|
from bpy.app.handlers import persistent
|
2019-07-01 21:39:01 +08:00
|
|
|
|
|
|
|
DEPENDENCIES = {
|
|
|
|
"zmq",
|
|
|
|
"umsgpack",
|
2019-07-17 04:50:34 +08:00
|
|
|
"pyyaml"
|
2019-07-01 21:39:01 +08:00
|
|
|
}
|
2019-05-23 00:19:11 +08:00
|
|
|
|
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-05-15 20:52:45 +08:00
|
|
|
|
|
|
|
# UTILITY FUNCTIONS
|
|
|
|
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-05-15 20:52:45 +08:00
|
|
|
items = [("Common", "Common", "")]
|
|
|
|
|
2019-05-21 22:53:55 +08:00
|
|
|
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)
|
2019-06-14 00:09:16 +08:00
|
|
|
for k in client_keys:
|
2019-08-14 21:57:07 +08:00
|
|
|
name = cli.get(k).buffer["name"]
|
2019-05-21 22:53:55 +08:00
|
|
|
|
2019-07-11 21:45:56 +08:00
|
|
|
name_desc = name
|
2019-05-15 20:52:45 +08:00
|
|
|
if name == username:
|
2019-07-11 21:45:56 +08:00
|
|
|
name_desc += " (self)"
|
2019-05-15 20:52:45 +08:00
|
|
|
|
2019-07-11 21:45:56 +08:00
|
|
|
items.append((name, name_desc, ""))
|
2019-05-15 20:52:45 +08:00
|
|
|
|
|
|
|
return items
|
|
|
|
|
|
|
|
|
|
|
|
def randomColor():
|
|
|
|
r = random.random()
|
|
|
|
v = random.random()
|
|
|
|
b = random.random()
|
|
|
|
return [r, v, b]
|
|
|
|
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-07-02 00:04:35 +08:00
|
|
|
def save_session_config(self,context):
|
|
|
|
config = environment.load_config()
|
|
|
|
|
2019-07-02 21:55:57 +08:00
|
|
|
config["username"] = self.username
|
2019-07-02 00:04:35 +08:00
|
|
|
config["ip"] = self.ip
|
2019-07-02 21:55:57 +08:00
|
|
|
config["port"] = self.port
|
|
|
|
config["start_empty"] = self.start_empty
|
|
|
|
config["enable_presence"] = self.enable_presence
|
2019-07-02 00:14:48 +08:00
|
|
|
config["client_color"] = [self.client_color.r,self.client_color.g,self.client_color.b]
|
2019-07-20 00:22:02 +08:00
|
|
|
|
2019-07-02 21:55:57 +08:00
|
|
|
rep_type = {}
|
|
|
|
for bloc in self.supported_datablock:
|
2019-07-02 23:44:59 +08:00
|
|
|
config["replicated_types"][bloc.type_name] = bloc.is_replicated
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-07-03 21:32:00 +08:00
|
|
|
# Generate ordered replicate types
|
2019-07-16 04:25:20 +08:00
|
|
|
environment.genererate_replicated_types()
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-07-03 21:32:00 +08:00
|
|
|
# Save out the configuration file
|
2019-07-02 00:04:35 +08:00
|
|
|
environment.save_config(config)
|
2019-05-15 20:52:45 +08:00
|
|
|
|
2019-07-03 21:32:00 +08:00
|
|
|
|
2019-07-02 21:55:57 +08:00
|
|
|
class ReplicatedDatablock(bpy.types.PropertyGroup):
|
|
|
|
'''name = StringProperty() '''
|
2019-07-02 22:43:30 +08:00
|
|
|
type_name: bpy.props.StringProperty()
|
|
|
|
is_replicated: bpy.props.BoolProperty()
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-07-03 21:32:00 +08:00
|
|
|
|
2019-05-21 22:53:55 +08:00
|
|
|
class SessionProps(bpy.types.PropertyGroup):
|
2019-05-16 00:37:14 +08:00
|
|
|
username: bpy.props.StringProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="Username",
|
2019-08-05 23:58:56 +08:00
|
|
|
default="user_{}".format(utils.random_string_digits()),
|
2019-07-02 00:04:35 +08:00
|
|
|
update=save_session_config
|
2019-05-21 22:53:55 +08:00
|
|
|
)
|
2019-05-16 00:37:14 +08:00
|
|
|
ip: bpy.props.StringProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="ip",
|
|
|
|
description='Distant host ip',
|
2019-07-02 00:04:35 +08:00
|
|
|
default="127.0.0.1",
|
|
|
|
update=save_session_config
|
|
|
|
)
|
2019-08-14 00:00:54 +08:00
|
|
|
user_uuid: bpy.props.StringProperty(
|
|
|
|
name="user_uuid",
|
|
|
|
default="None"
|
|
|
|
)
|
2019-05-16 00:37:14 +08:00
|
|
|
port: bpy.props.IntProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="port",
|
|
|
|
description='Distant host port',
|
2019-07-02 00:04:35 +08:00
|
|
|
default=5555,
|
|
|
|
update=save_session_config
|
|
|
|
)
|
2019-05-16 00:37:14 +08:00
|
|
|
add_property_depth: bpy.props.IntProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="add_property_depth",
|
2019-07-02 00:04:35 +08:00
|
|
|
default=1
|
|
|
|
)
|
2019-08-09 16:58:47 +08:00
|
|
|
outliner_filter: bpy.props.StringProperty(name="None")
|
2019-05-16 00:37:14 +08:00
|
|
|
is_admin: bpy.props.BoolProperty(name="is_admin", default=False)
|
2019-08-08 17:43:12 +08:00
|
|
|
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",
|
|
|
|
default=False,
|
2019-08-09 16:58:47 +08:00
|
|
|
update=save_session_config)
|
2019-05-16 00:37:14 +08:00
|
|
|
active_object: bpy.props.PointerProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="active_object", type=bpy.types.Object)
|
2019-05-16 00:37:14 +08:00
|
|
|
session_mode: bpy.props.EnumProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name='session_mode',
|
|
|
|
description='session mode',
|
|
|
|
items={
|
|
|
|
('HOST', 'hosting', 'host a session'),
|
|
|
|
('CONNECT', 'connexion', 'connect to a session')},
|
|
|
|
default='HOST')
|
2019-05-16 00:37:14 +08:00
|
|
|
client_color: bpy.props.FloatVectorProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="client_instance_color",
|
|
|
|
subtype='COLOR',
|
2019-07-02 21:55:57 +08:00
|
|
|
default=randomColor(),
|
|
|
|
update=save_session_config)
|
2019-05-16 00:37:14 +08:00
|
|
|
clients: bpy.props.EnumProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="clients",
|
|
|
|
description="client enum",
|
2019-08-09 16:58:47 +08:00
|
|
|
items=client_list_callback)
|
2019-07-02 00:04:35 +08:00
|
|
|
enable_presence: bpy.props.BoolProperty(
|
|
|
|
name="enable_presence",
|
2019-05-15 20:52:45 +08:00
|
|
|
description='Enable overlay drawing module',
|
2019-07-02 00:04:35 +08:00
|
|
|
default=True,
|
|
|
|
update=save_session_config
|
|
|
|
)
|
2019-07-02 21:55:57 +08:00
|
|
|
supported_datablock: bpy.props.CollectionProperty(
|
2019-07-02 23:44:59 +08:00
|
|
|
type=ReplicatedDatablock,
|
2019-07-02 21:55:57 +08:00
|
|
|
)
|
2019-07-02 00:04:35 +08:00
|
|
|
|
|
|
|
def load(self):
|
|
|
|
config = environment.load_config()
|
|
|
|
logger.info(config)
|
2019-07-02 21:55:57 +08:00
|
|
|
if "username" in config:
|
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:
|
2019-07-02 21:55:57 +08:00
|
|
|
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()
|
2019-07-03 21:03:37 +08:00
|
|
|
|
2019-07-02 23:44:59 +08:00
|
|
|
for datablock,enabled in config["replicated_types"].items():
|
2019-07-02 21:55:57 +08:00
|
|
|
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-07-02 21:55:57 +08:00
|
|
|
rep_value.is_replicated = enabled
|
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-02 21:55:57 +08:00
|
|
|
|
2019-07-03 21:03:37 +08:00
|
|
|
|
2019-07-02 23:44:59 +08:00
|
|
|
for bloc in self.supported_datablock:
|
|
|
|
config["replicated_types"][bloc.type_name] = bloc.is_replicated
|
|
|
|
|
|
|
|
environment.save_config(config)
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-05-15 20:52:45 +08:00
|
|
|
|
2019-07-02 22:43:30 +08:00
|
|
|
classes = (
|
2019-07-02 21:55:57 +08:00
|
|
|
ReplicatedDatablock,
|
2019-08-08 21:35:43 +08:00
|
|
|
SessionProps,
|
2019-07-02 21:55:57 +08:00
|
|
|
|
2019-07-02 22:43:30 +08:00
|
|
|
)
|
2019-05-15 20:52:45 +08:00
|
|
|
|
2019-08-05 22:48:46 +08:00
|
|
|
libs = os.path.dirname(os.path.abspath(__file__))+"\\libs\\replication"
|
2019-05-21 22:53:55 +08:00
|
|
|
|
2019-07-09 04:39:11 +08:00
|
|
|
@persistent
|
|
|
|
def load_handler(dummy):
|
|
|
|
import bpy
|
|
|
|
bpy.context.window_manager.session.load()
|
2019-07-12 00:03:00 +08:00
|
|
|
# Generate ordered replicate types
|
|
|
|
|
2019-07-09 05:24:08 +08:00
|
|
|
save_session_config(bpy.context.window_manager.session,bpy.context)
|
2019-07-09 04:39:11 +08:00
|
|
|
|
|
|
|
|
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)
|
|
|
|
print(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
|
|
|
|
|
2019-05-15 20:52:45 +08:00
|
|
|
for cls in classes:
|
|
|
|
bpy.utils.register_class(cls)
|
|
|
|
|
|
|
|
bpy.types.WindowManager.session = bpy.props.PointerProperty(
|
2019-05-21 22:53:55 +08:00
|
|
|
type=SessionProps)
|
2019-08-09 00:12:13 +08:00
|
|
|
bpy.types.ID.uuid = bpy.props.StringProperty(default="")
|
2019-07-02 00:04:35 +08:00
|
|
|
bpy.context.window_manager.session.load()
|
2019-07-02 23:44:59 +08:00
|
|
|
save_session_config(bpy.context.window_manager.session,bpy.context)
|
2019-04-10 23:01:21 +08:00
|
|
|
operators.register()
|
|
|
|
ui.register()
|
|
|
|
|
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-05-21 22:53:55 +08:00
|
|
|
|
2019-04-10 23:01:21 +08:00
|
|
|
ui.unregister()
|
|
|
|
operators.unregister()
|
|
|
|
|
2019-05-15 20:52:45 +08:00
|
|
|
del bpy.types.WindowManager.session
|
|
|
|
|
2019-07-02 22:43:30 +08:00
|
|
|
for cls in reversed(classes):
|
2019-05-15 20:52:45 +08:00
|
|
|
bpy.utils.unregister_class(cls)
|