2a88c3e5ac
fix: _bool numpy not found
721 lines
24 KiB
Python
721 lines
24 KiB
Python
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
import random
|
|
import logging
|
|
from uuid import uuid4
|
|
import bpy
|
|
import string
|
|
import re
|
|
import os
|
|
|
|
from pathlib import Path
|
|
|
|
from . import bl_types, environment, addon_updater_ops, presence, ui
|
|
from .utils import get_preferences, get_expanded_icon, get_folder_size
|
|
from replication.constants import RP_COMMON
|
|
from replication.interface import session
|
|
|
|
# From https://stackoverflow.com/a/106223
|
|
IP_REGEX = re.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
|
HOSTNAME_REGEX = re.compile("^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$")
|
|
|
|
#SERVER PRESETS AT LAUNCH
|
|
DEFAULT_PRESETS = {
|
|
"localhost" : {
|
|
"server_name": "localhost",
|
|
"ip": "localhost",
|
|
"port": 5555,
|
|
"use_admin_password": True,
|
|
"admin_password": "admin",
|
|
"server_password": ""
|
|
},
|
|
}
|
|
|
|
def randomColor():
|
|
"""Generate a random color """
|
|
r = random.random()
|
|
v = random.random()
|
|
b = random.random()
|
|
return [r, v, b]
|
|
|
|
|
|
def random_string_digits(stringLength=6):
|
|
"""Generate a random string of letters and digits"""
|
|
lettersAndDigits = string.ascii_letters + string.digits
|
|
return ''.join(random.choices(lettersAndDigits, k=stringLength))
|
|
|
|
|
|
def update_panel_category(self, context):
|
|
ui.unregister()
|
|
ui.SESSION_PT_settings.bl_category = self.panel_category
|
|
ui.register()
|
|
|
|
|
|
def update_ip(self, context):
|
|
ip = IP_REGEX.search(self.ip)
|
|
dns = HOSTNAME_REGEX.search(self.ip)
|
|
|
|
if ip:
|
|
self['ip'] = ip.group()
|
|
elif dns:
|
|
self['ip'] = dns.group()
|
|
else:
|
|
logging.error("Wrong IP format")
|
|
self['ip'] = "127.0.0.1"
|
|
|
|
|
|
def update_directory(self, context):
|
|
new_dir = Path(self.cache_directory)
|
|
if new_dir.exists() and any(Path(self.cache_directory).iterdir()):
|
|
logging.error("The folder is not empty, choose another one.")
|
|
self['cache_directory'] = environment.DEFAULT_CACHE_DIR
|
|
elif not new_dir.exists():
|
|
logging.info("Target cache folder doesn't exist, creating it.")
|
|
os.makedirs(self.cache_directory, exist_ok=True)
|
|
|
|
|
|
def set_log_level(self, value):
|
|
logging.getLogger().setLevel(value)
|
|
|
|
|
|
def get_log_level(self):
|
|
return logging.getLogger().level
|
|
|
|
|
|
class ReplicatedDatablock(bpy.types.PropertyGroup):
|
|
type_name: bpy.props.StringProperty()
|
|
bl_name: bpy.props.StringProperty()
|
|
use_as_filter: bpy.props.BoolProperty(default=True)
|
|
auto_push: bpy.props.BoolProperty(default=True)
|
|
icon: bpy.props.StringProperty()
|
|
|
|
class ServerPreset(bpy.types.PropertyGroup):
|
|
server_name: bpy.props.StringProperty(default="")
|
|
ip: bpy.props.StringProperty(default="127.0.0.1", update=update_ip)
|
|
port: bpy.props.IntProperty(default=5555)
|
|
use_server_password: bpy.props.BoolProperty(default=False)
|
|
server_password: bpy.props.StringProperty(default="", subtype = "PASSWORD")
|
|
use_admin_password: bpy.props.BoolProperty(default=False)
|
|
admin_password: bpy.props.StringProperty(default="", subtype = "PASSWORD")
|
|
is_online: bpy.props.BoolProperty(default=False)
|
|
is_private: bpy.props.BoolProperty(default=False)
|
|
|
|
def set_sync_render_settings(self, value):
|
|
self['sync_render_settings'] = value
|
|
if session and bpy.context.scene.uuid and value:
|
|
bpy.ops.session.apply('INVOKE_DEFAULT',
|
|
target=bpy.context.scene.uuid,
|
|
reset_dependencies=False)
|
|
|
|
|
|
def set_sync_active_camera(self, value):
|
|
self['sync_active_camera'] = value
|
|
|
|
if session and bpy.context.scene.uuid and value:
|
|
bpy.ops.session.apply('INVOKE_DEFAULT',
|
|
target=bpy.context.scene.uuid,
|
|
reset_dependencies=False)
|
|
|
|
|
|
class ReplicationFlags(bpy.types.PropertyGroup):
|
|
def get_sync_render_settings(self):
|
|
return self.get('sync_render_settings', True)
|
|
|
|
def get_sync_active_camera(self):
|
|
return self.get('sync_active_camera', True)
|
|
|
|
sync_render_settings: bpy.props.BoolProperty(
|
|
name="Synchronize render settings",
|
|
description="Synchronize render settings (eevee and cycles only)",
|
|
default=False,
|
|
set=set_sync_render_settings,
|
|
get=get_sync_render_settings
|
|
)
|
|
sync_during_editmode: bpy.props.BoolProperty(
|
|
name="Edit mode updates",
|
|
description="Enable objects update in edit mode (! Impact performances !)",
|
|
default=False
|
|
)
|
|
sync_active_camera: bpy.props.BoolProperty(
|
|
name="Synchronize active camera",
|
|
description="Synchronize the active camera",
|
|
default=True,
|
|
get=get_sync_active_camera,
|
|
set=set_sync_active_camera
|
|
)
|
|
|
|
|
|
class SessionPrefs(bpy.types.AddonPreferences):
|
|
bl_idname = __package__
|
|
|
|
# User settings
|
|
username: bpy.props.StringProperty(
|
|
name="Username",
|
|
default=f"user_{random_string_digits()}"
|
|
)
|
|
client_color: bpy.props.FloatVectorProperty(
|
|
name="client_instance_color",
|
|
description='User color',
|
|
subtype='COLOR',
|
|
default=randomColor()
|
|
)
|
|
# Current server settings
|
|
server_name: bpy.props.StringProperty(
|
|
name="server_name",
|
|
description="Custom name of the server",
|
|
default='localhost',
|
|
)
|
|
server_index: bpy.props.IntProperty(
|
|
name="server_index",
|
|
description="index of the server",
|
|
)
|
|
# User host session settings
|
|
host_port: bpy.props.IntProperty(
|
|
name="host_port",
|
|
description='Distant host port',
|
|
default=5555
|
|
)
|
|
host_use_server_password: bpy.props.BoolProperty(
|
|
name="use_server_password",
|
|
description='Use session password',
|
|
default=False
|
|
)
|
|
host_server_password: bpy.props.StringProperty(
|
|
name="server_password",
|
|
description='Session password',
|
|
subtype='PASSWORD'
|
|
)
|
|
host_use_admin_password: bpy.props.BoolProperty(
|
|
name="use_admin_password",
|
|
description='Use admin password',
|
|
default=True
|
|
)
|
|
host_admin_password: bpy.props.StringProperty(
|
|
name="admin_password",
|
|
description='Admin password',
|
|
subtype='PASSWORD',
|
|
default='admin'
|
|
)
|
|
# Other
|
|
is_first_launch: bpy.props.BoolProperty(
|
|
name="is_fnirst_launch",
|
|
description="First time lauching the addon",
|
|
default=True
|
|
)
|
|
sync_flags: bpy.props.PointerProperty(
|
|
type=ReplicationFlags
|
|
)
|
|
supported_datablocks: bpy.props.CollectionProperty(
|
|
type=ReplicatedDatablock,
|
|
)
|
|
init_method: bpy.props.EnumProperty(
|
|
name='init_method',
|
|
description='Init repo',
|
|
items={
|
|
('EMPTY', 'an empty scene', 'start empty'),
|
|
('BLEND', 'current scenes', 'use current scenes')},
|
|
default='BLEND')
|
|
cache_directory: bpy.props.StringProperty(
|
|
name="cache directory",
|
|
subtype="DIR_PATH",
|
|
default=environment.DEFAULT_CACHE_DIR,
|
|
update=update_directory)
|
|
connection_timeout: bpy.props.IntProperty(
|
|
name='connection timeout',
|
|
description='connection timeout before disconnection',
|
|
default=5000
|
|
)
|
|
ping_timeout: bpy.props.IntProperty(
|
|
name='ping timeout',
|
|
description='check if servers are online',
|
|
default=500
|
|
)
|
|
# Replication update settings
|
|
depsgraph_update_rate: bpy.props.FloatProperty(
|
|
name='depsgraph update rate (s)',
|
|
description='Dependency graph uppdate rate (s)',
|
|
default=1
|
|
)
|
|
clear_memory_filecache: bpy.props.BoolProperty(
|
|
name="Clear memory filecache",
|
|
description="Remove filecache from memory",
|
|
default=False
|
|
)
|
|
# For UI
|
|
category: bpy.props.EnumProperty(
|
|
name="Category",
|
|
description="Preferences Category",
|
|
items=[
|
|
('PREF', "Preferences", "Preferences of this add-on"),
|
|
('CONFIG', "Configuration", "Configuration of this add-on"),
|
|
('UPDATE', "Update", "Update this add-on"),
|
|
],
|
|
default='CONFIG'
|
|
)
|
|
logging_level: bpy.props.EnumProperty(
|
|
name="Log level",
|
|
description="Log verbosity level",
|
|
items=[
|
|
('ERROR', "error", "show only errors", logging.ERROR),
|
|
('WARNING', "warning", "only show warnings and errors", logging.WARNING),
|
|
('INFO', "info", "default level", logging.INFO),
|
|
('DEBUG', "debug", "show all logs", logging.DEBUG),
|
|
],
|
|
default='INFO',
|
|
set=set_log_level,
|
|
get=get_log_level
|
|
)
|
|
presence_hud_scale: bpy.props.FloatProperty(
|
|
name="Text scale",
|
|
description="Adjust the session widget text scale",
|
|
min=7,
|
|
max=90,
|
|
default=25,
|
|
)
|
|
presence_hud_hpos: bpy.props.FloatProperty(
|
|
name="Horizontal position",
|
|
description="Adjust the session widget horizontal position",
|
|
min=1,
|
|
max=90,
|
|
default=1,
|
|
step=1,
|
|
subtype='PERCENTAGE',
|
|
)
|
|
presence_hud_vpos: bpy.props.FloatProperty(
|
|
name="Vertical position",
|
|
description="Adjust the session widget vertical position",
|
|
min=1,
|
|
max=94,
|
|
default=1,
|
|
step=1,
|
|
subtype='PERCENTAGE',
|
|
)
|
|
presence_text_distance: bpy.props.FloatProperty(
|
|
name="Distance text visibilty",
|
|
description="Adjust the distance visibilty of user's mode/name",
|
|
min=0.1,
|
|
max=10000,
|
|
default=100,
|
|
)
|
|
conf_session_identity_expanded: bpy.props.BoolProperty(
|
|
name="Identity",
|
|
description="Identity",
|
|
default=False
|
|
)
|
|
conf_session_net_expanded: bpy.props.BoolProperty(
|
|
name="Net",
|
|
description="net",
|
|
default=False
|
|
)
|
|
conf_session_hosting_expanded: bpy.props.BoolProperty(
|
|
name="Rights",
|
|
description="Rights",
|
|
default=False
|
|
)
|
|
conf_session_rep_expanded: bpy.props.BoolProperty(
|
|
name="Replication",
|
|
description="Replication",
|
|
default=False
|
|
)
|
|
conf_session_cache_expanded: bpy.props.BoolProperty(
|
|
name="Cache",
|
|
description="cache",
|
|
default=False
|
|
)
|
|
conf_session_log_expanded: bpy.props.BoolProperty(
|
|
name="conf_session_log_expanded",
|
|
description="conf_session_log_expanded",
|
|
default=False
|
|
)
|
|
conf_session_ui_expanded: bpy.props.BoolProperty(
|
|
name="Interface",
|
|
description="Interface",
|
|
default=False
|
|
)
|
|
sidebar_repository_shown: bpy.props.BoolProperty(
|
|
name="sidebar_repository_shown",
|
|
description="sidebar_repository_shown",
|
|
default=False
|
|
)
|
|
sidebar_advanced_shown: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_shown",
|
|
description="sidebar_advanced_shown",
|
|
default=False
|
|
)
|
|
sidebar_advanced_rep_expanded: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_rep_expanded",
|
|
description="sidebar_advanced_rep_expanded",
|
|
default=False
|
|
)
|
|
sidebar_advanced_log_expanded: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_log_expanded",
|
|
description="sidebar_advanced_log_expanded",
|
|
default=False
|
|
)
|
|
sidebar_advanced_uinfo_expanded: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_uinfo_expanded",
|
|
description="sidebar_advanced_uinfo_expanded",
|
|
default=False
|
|
)
|
|
sidebar_advanced_net_expanded: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_net_expanded",
|
|
description="sidebar_advanced_net_expanded",
|
|
default=False
|
|
)
|
|
sidebar_advanced_cache_expanded: bpy.props.BoolProperty(
|
|
name="sidebar_advanced_cache_expanded",
|
|
description="sidebar_advanced_cache_expanded",
|
|
default=False
|
|
)
|
|
|
|
auto_check_update: bpy.props.BoolProperty(
|
|
name="Auto-check for Update",
|
|
description="If enabled, auto-check for updates using an interval",
|
|
default=False,
|
|
)
|
|
updater_intrval_months: bpy.props.IntProperty(
|
|
name='Months',
|
|
description="Number of months between checking for updates",
|
|
default=0,
|
|
min=0
|
|
)
|
|
updater_intrval_days: bpy.props.IntProperty(
|
|
name='Days',
|
|
description="Number of days between checking for updates",
|
|
default=7,
|
|
min=0,
|
|
max=31
|
|
)
|
|
updater_intrval_hours: bpy.props.IntProperty(
|
|
name='Hours',
|
|
description="Number of hours between checking for updates",
|
|
default=0,
|
|
min=0,
|
|
max=23
|
|
)
|
|
updater_intrval_minutes: bpy.props.IntProperty(
|
|
name='Minutes',
|
|
description="Number of minutes between checking for updates",
|
|
default=0,
|
|
min=0,
|
|
max=59
|
|
)
|
|
|
|
# Server preset
|
|
def server_list_callback(scene, context):
|
|
settings = get_preferences()
|
|
enum = []
|
|
for i in settings.server_preset:
|
|
enum.append((i.name, i.name, ""))
|
|
return enum
|
|
|
|
server_preset: bpy.props.CollectionProperty(
|
|
name="server preset",
|
|
type=ServerPreset,
|
|
)
|
|
|
|
# Custom panel
|
|
panel_category: bpy.props.StringProperty(
|
|
description="Choose a name for the category of the panel",
|
|
default="Multiuser",
|
|
update=update_panel_category)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.row().prop(self, "category", expand=True)
|
|
|
|
if self.category == 'PREF':
|
|
grid = layout.column()
|
|
|
|
box = grid.box()
|
|
row = box.row()
|
|
# USER SETTINGS
|
|
split = row.split(factor=0.7, align=True)
|
|
split.prop(self, "username", text="User")
|
|
split.prop(self, "client_color", text="")
|
|
|
|
row = box.row()
|
|
row.label(text="Hide settings:")
|
|
row = box.row()
|
|
row.prop(self, "sidebar_advanced_shown", text="Hide “Advanced” settings in side pannel (Not in session)")
|
|
row = box.row()
|
|
row.prop(self, "sidebar_repository_shown", text="Hide “Repository” settings in side pannel (In session)")
|
|
|
|
if self.category == 'CONFIG':
|
|
grid = layout.column()
|
|
|
|
# HOST SETTINGS
|
|
box = grid.box()
|
|
box.prop(
|
|
self, "conf_session_hosting_expanded", text="Hosting",
|
|
icon=get_expanded_icon(self.conf_session_hosting_expanded),
|
|
emboss=False)
|
|
if self.conf_session_hosting_expanded:
|
|
row = box.row()
|
|
row.prop(self, "host_port", text="Port: ")
|
|
row = box.row()
|
|
row.label(text="Init the session from:")
|
|
row.prop(self, "init_method", text="")
|
|
row = box.row()
|
|
col = row.column()
|
|
col.prop(self, "host_use_server_password", text="Server password:")
|
|
col = row.column()
|
|
col.enabled = True if self.host_use_server_password else False
|
|
col.prop(self, "host_server_password", text="")
|
|
row = box.row()
|
|
col = row.column()
|
|
col.prop(self, "host_use_admin_password", text="Admin password:")
|
|
col = row.column()
|
|
col.enabled = True if self.host_use_admin_password else False
|
|
col.prop(self, "host_admin_password", text="")
|
|
|
|
# NETWORKING
|
|
box = grid.box()
|
|
box.prop(
|
|
self, "conf_session_net_expanded", text="Network",
|
|
icon=get_expanded_icon(self.conf_session_net_expanded),
|
|
emboss=False)
|
|
if self.conf_session_net_expanded:
|
|
row = box.row()
|
|
row.label(text="Timeout (ms):")
|
|
row.prop(self, "connection_timeout", text="")
|
|
row = box.row()
|
|
row.label(text="Server ping (ms):")
|
|
row.prop(self, "ping_timeout", text="")
|
|
|
|
# REPLICATION
|
|
box = grid.box()
|
|
box.prop(
|
|
self, "conf_session_rep_expanded", text="Replication",
|
|
icon=get_expanded_icon(self.conf_session_rep_expanded),
|
|
emboss=False)
|
|
if self.conf_session_rep_expanded:
|
|
row = box.row()
|
|
row.prop(self.sync_flags, "sync_render_settings")
|
|
row = box.row()
|
|
row.prop(self.sync_flags, "sync_active_camera")
|
|
row = box.row()
|
|
row.prop(self.sync_flags, "sync_during_editmode")
|
|
row = box.row()
|
|
if self.sync_flags.sync_during_editmode:
|
|
warning = row.box()
|
|
warning.label(text="Don't use this with heavy meshes !", icon='ERROR')
|
|
row = box.row()
|
|
row.prop(self, "depsgraph_update_rate", text="Apply delay")
|
|
|
|
# CACHE SETTINGS
|
|
box = grid.box()
|
|
box.prop(
|
|
self, "conf_session_cache_expanded", text="Cache",
|
|
icon=get_expanded_icon(self.conf_session_cache_expanded),
|
|
emboss=False)
|
|
if self.conf_session_cache_expanded:
|
|
box.row().prop(self, "cache_directory", text="Cache directory")
|
|
box.row().prop(self, "clear_memory_filecache", text="Clear memory filecache")
|
|
box.row().operator('session.clear_cache', text=f"Clear cache ({get_folder_size(self.cache_directory)})")
|
|
|
|
# LOGGING
|
|
box = grid.box()
|
|
box.prop(
|
|
self, "conf_session_log_expanded", text="Logging",
|
|
icon=get_expanded_icon(self.conf_session_log_expanded),
|
|
emboss=False)
|
|
if self.conf_session_log_expanded:
|
|
row = box.row()
|
|
row.label(text="Log level:")
|
|
row.prop(self, 'logging_level', text="")
|
|
|
|
if self.category == 'UPDATE':
|
|
from . import addon_updater_ops
|
|
addon_updater_ops.update_settings_ui(self, context)
|
|
|
|
def generate_supported_types(self):
|
|
self.supported_datablocks.clear()
|
|
|
|
bpy_protocol = bl_types.get_data_translation_protocol()
|
|
|
|
# init the factory with supported types
|
|
for dcc_type_id, impl in bpy_protocol.implementations.items():
|
|
new_db = self.supported_datablocks.add()
|
|
|
|
new_db.name = dcc_type_id
|
|
new_db.type_name = dcc_type_id
|
|
new_db.use_as_filter = True
|
|
new_db.icon = impl.bl_icon
|
|
new_db.bl_name = impl.bl_id
|
|
|
|
# Get a server preset through its name
|
|
def get_server_preset(self, name):
|
|
existing_preset = None
|
|
|
|
for server_preset in self.server_preset :
|
|
if server_preset.server_name == name :
|
|
existing_preset = server_preset
|
|
|
|
return existing_preset
|
|
|
|
# Custom at launch server preset
|
|
def generate_default_presets(self):
|
|
for preset_name, preset_data in DEFAULT_PRESETS.items():
|
|
existing_preset = self.get_server_preset(preset_name)
|
|
if existing_preset :
|
|
continue
|
|
new_server = self.server_preset.add()
|
|
new_server.name = str(uuid4())
|
|
new_server.server_name = preset_data.get('server_name')
|
|
new_server.ip = preset_data.get('ip')
|
|
new_server.port = preset_data.get('port')
|
|
new_server.use_server_password = preset_data.get('use_server_password',False)
|
|
new_server.server_password = preset_data.get('server_password',None)
|
|
new_server.use_admin_password = preset_data.get('use_admin_password',False)
|
|
new_server.admin_password = preset_data.get('admin_password',None)
|
|
|
|
|
|
def client_list_callback(scene, context):
|
|
from . import operators
|
|
|
|
items = [(RP_COMMON, RP_COMMON, "")]
|
|
|
|
username = get_preferences().username
|
|
|
|
if session:
|
|
client_ids = session.online_users.keys()
|
|
for id in client_ids:
|
|
name_desc = id
|
|
if id == username:
|
|
name_desc += " (self)"
|
|
|
|
items.append((id, name_desc, ""))
|
|
|
|
return items
|
|
|
|
|
|
class SessionUser(bpy.types.PropertyGroup):
|
|
"""Session User
|
|
|
|
Blender user information property
|
|
"""
|
|
username: bpy.props.StringProperty(name="username")
|
|
current_frame: bpy.props.IntProperty(name="current_frame")
|
|
color: bpy.props.FloatVectorProperty(name="color", subtype="COLOR",
|
|
min=0.0,
|
|
max=1.0,
|
|
size=4,
|
|
default=(1.0, 1.0, 1.0, 1.0))
|
|
|
|
|
|
class SessionProps(bpy.types.PropertyGroup):
|
|
session_mode: bpy.props.EnumProperty(
|
|
name='session_mode',
|
|
description='session mode',
|
|
items={
|
|
('HOST', 'HOST', 'host a session'),
|
|
('CONNECT', 'JOIN', 'connect to a session')},
|
|
default='CONNECT')
|
|
clients: bpy.props.EnumProperty(
|
|
name="clients",
|
|
description="client enum",
|
|
items=client_list_callback)
|
|
enable_presence: bpy.props.BoolProperty(
|
|
name="Presence overlay",
|
|
description='Enable overlay drawing module',
|
|
default=True,
|
|
)
|
|
presence_show_selected: bpy.props.BoolProperty(
|
|
name="Show selected objects",
|
|
description='Enable selection overlay ',
|
|
default=True,
|
|
)
|
|
presence_show_user: bpy.props.BoolProperty(
|
|
name="Show users",
|
|
description='Enable user overlay ',
|
|
default=True,
|
|
)
|
|
presence_show_mode: bpy.props.BoolProperty(
|
|
name="Show users current mode",
|
|
description='Enable user mode overlay ',
|
|
default=False,
|
|
)
|
|
presence_show_far_user: bpy.props.BoolProperty(
|
|
name="Show users on different scenes",
|
|
description="Show user on different scenes",
|
|
default=False,
|
|
)
|
|
presence_show_session_status: bpy.props.BoolProperty(
|
|
name="Show session status ",
|
|
description="Show session status on the viewport",
|
|
default=True,
|
|
)
|
|
filter_owned: bpy.props.BoolProperty(
|
|
name="filter_owned",
|
|
description='Show only owned datablocks',
|
|
default=True
|
|
)
|
|
filter_name: bpy.props.StringProperty(
|
|
name="filter_name",
|
|
default="",
|
|
description='Node name filter',
|
|
)
|
|
admin: bpy.props.BoolProperty(
|
|
name="admin",
|
|
description='Connect as admin',
|
|
default=False
|
|
)
|
|
user_snap_running: bpy.props.BoolProperty(
|
|
default=False
|
|
)
|
|
time_snap_running: bpy.props.BoolProperty(
|
|
default=False
|
|
)
|
|
is_host: bpy.props.BoolProperty(
|
|
default=False
|
|
)
|
|
|
|
|
|
classes = (
|
|
SessionUser,
|
|
SessionProps,
|
|
ReplicationFlags,
|
|
ReplicatedDatablock,
|
|
ServerPreset,
|
|
SessionPrefs,
|
|
)
|
|
|
|
|
|
def register():
|
|
from bpy.utils import register_class
|
|
|
|
for cls in classes:
|
|
register_class(cls)
|
|
|
|
prefs = bpy.context.preferences.addons[__package__].preferences
|
|
if len(prefs.supported_datablocks) == 0:
|
|
logging.debug('Generating bl_types preferences')
|
|
prefs.generate_supported_types()
|
|
|
|
# at launch server presets
|
|
prefs.generate_default_presets()
|
|
|
|
|
|
|
|
def unregister():
|
|
from bpy.utils import unregister_class
|
|
|
|
for cls in reversed(classes):
|
|
unregister_class(cls)
|