2019-05-21 22:53:55 +08:00
|
|
|
from pathlib import Path
|
|
|
|
import addon_utils
|
|
|
|
import random
|
|
|
|
import string
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import bpy
|
2019-05-23 00:19:11 +08:00
|
|
|
|
2019-02-08 00:41:18 +08:00
|
|
|
bl_info = {
|
2019-05-21 22:53:55 +08:00
|
|
|
"name": "Multi-User ",
|
|
|
|
"author": "CUBE",
|
|
|
|
"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-05-23 00:19:11 +08:00
|
|
|
|
2019-05-23 22:49:32 +08:00
|
|
|
def module_can_be_imported(name):
|
|
|
|
try:
|
|
|
|
__import__(name)
|
|
|
|
return True
|
|
|
|
except ModuleNotFoundError:
|
|
|
|
return False
|
2019-05-15 20:52:45 +08:00
|
|
|
|
|
|
|
# UTILITY FUNCTIONS
|
|
|
|
def client_list_callback(scene, context):
|
2019-05-22 23:17:09 +08:00
|
|
|
from . import operators
|
|
|
|
|
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-05-15 20:52:45 +08:00
|
|
|
|
2019-05-22 23:17:09 +08:00
|
|
|
if operators.client_keys:
|
|
|
|
for k in operators.client_keys:
|
2019-05-15 20:52:45 +08:00
|
|
|
if 'Client' in k[0]:
|
|
|
|
name = k[1]
|
2019-05-21 22:53:55 +08:00
|
|
|
|
2019-05-15 20:52:45 +08:00
|
|
|
if name == username:
|
|
|
|
name += " (self)"
|
|
|
|
|
|
|
|
items.append((name, name, ""))
|
|
|
|
|
|
|
|
return items
|
|
|
|
|
|
|
|
|
|
|
|
def randomStringDigits(stringLength=6):
|
|
|
|
"""Generate a random string of letters and digits """
|
|
|
|
lettersAndDigits = string.ascii_letters + string.digits
|
|
|
|
return ''.join(random.choice(lettersAndDigits) for i in range(stringLength))
|
|
|
|
|
|
|
|
|
|
|
|
def randomColor():
|
|
|
|
r = random.random()
|
|
|
|
v = random.random()
|
|
|
|
b = random.random()
|
|
|
|
return [r, v, b]
|
|
|
|
|
|
|
|
|
2019-05-09 20:20:42 +08:00
|
|
|
def get_package_install_directory():
|
|
|
|
for path in sys.path:
|
|
|
|
if os.path.basename(path) in ("dist-packages", "site-packages"):
|
|
|
|
return path
|
|
|
|
|
2019-02-08 00:57:03 +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",
|
|
|
|
default="user_{}".format(randomStringDigits())
|
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',
|
|
|
|
default="127.0.0.1")
|
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',
|
|
|
|
default=5555)
|
|
|
|
|
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",
|
|
|
|
default=1)
|
2019-05-16 00:37:14 +08:00
|
|
|
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)
|
2019-06-12 22:44:48 +08:00
|
|
|
clear_scene: bpy.props.BoolProperty(name="clear_scene", default=False)
|
2019-05-16 00:37:14 +08:00
|
|
|
update_frequency: bpy.props.FloatProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="update_frequency", default=0.008)
|
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',
|
|
|
|
default=randomColor())
|
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",
|
|
|
|
items=client_list_callback
|
|
|
|
)
|
2019-05-16 00:37:14 +08:00
|
|
|
enable_draw: bpy.props.BoolProperty(
|
2019-05-15 20:52:45 +08:00
|
|
|
name="enable_draw",
|
|
|
|
description='Enable overlay drawing module',
|
|
|
|
default=True)
|
|
|
|
|
2019-05-21 22:53:55 +08:00
|
|
|
|
2019-05-15 20:52:45 +08:00
|
|
|
classes = {
|
2019-05-21 22:53:55 +08:00
|
|
|
SessionProps,
|
2019-05-15 20:52:45 +08:00
|
|
|
}
|
|
|
|
|
2019-05-21 22:53:55 +08:00
|
|
|
|
2019-05-23 22:49:32 +08:00
|
|
|
python_path = Path(bpy.app.binary_path_python)
|
|
|
|
cwd_for_subprocesses = python_path.parent
|
|
|
|
target = get_package_install_directory()
|
|
|
|
|
2019-05-23 00:19:11 +08:00
|
|
|
|
2019-05-23 22:49:32 +08:00
|
|
|
def install_pip():
|
|
|
|
# pip can not necessarily be imported into Blender after this
|
|
|
|
get_pip_path = Path(__file__).parent / "libs" / "get-pip.py"
|
|
|
|
subprocess.run([str(python_path), str(get_pip_path)], cwd=cwd_for_subprocesses)
|
|
|
|
|
|
|
|
|
|
|
|
def install_package(name):
|
|
|
|
target = get_package_install_directory()
|
|
|
|
subprocess.run([str(python_path), "-m", "pip", "install", name, '--target', target], cwd=cwd_for_subprocesses)
|
|
|
|
|
|
|
|
|
|
|
|
def register():
|
|
|
|
if not module_can_be_imported("pip"):
|
|
|
|
install_pip()
|
|
|
|
|
|
|
|
if not module_can_be_imported("zmq"):
|
2019-05-21 22:53:55 +08:00
|
|
|
subprocess.run([str(python_path), "-m", "pip", "install",
|
|
|
|
"zmq", '--target', target], cwd=cwd_for_subprocesses)
|
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.ID.id = bpy.props.StringProperty(default="None")
|
|
|
|
bpy.types.ID.is_dirty = bpy.props.BoolProperty(default=False)
|
|
|
|
bpy.types.WindowManager.session = bpy.props.PointerProperty(
|
2019-05-21 22:53:55 +08:00
|
|
|
type=SessionProps)
|
2019-05-15 20:52:45 +08:00
|
|
|
|
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
|
|
|
|
del bpy.types.ID.id
|
|
|
|
del bpy.types.ID.is_dirty
|
|
|
|
|
|
|
|
for cls in classes:
|
|
|
|
bpy.utils.unregister_class(cls)
|