feat: store addon config in user preference (except runtime vars)

Related to #20
This commit is contained in:
Swann Martinez
2020-02-28 17:34:30 +01:00
parent a7641d6fc9
commit 8e600778ab
8 changed files with 242 additions and 221 deletions

View File

@ -21,7 +21,7 @@ import sys
import bpy import bpy
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
from . import environment, utils, presence from . import environment, utils, presence, preferences
from .libs.replication.replication.constants import RP_COMMON from .libs.replication.replication.constants import RP_COMMON
@ -37,34 +37,12 @@ DEPENDENCIES = {
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.setLevel(logging.WARNING) logger.setLevel(logging.WARNING)
#TODO: refactor config
# UTILITY FUNCTIONS
def generate_supported_types():
stype_dict = {'supported_types':{}}
for type in bl_types.types_to_register():
type_module = getattr(bl_types, type)
type_impl_name = "Bl{}".format(type.split('_')[1].capitalize())
type_module_class = getattr(type_module, type_impl_name)
props = {}
props['bl_delay_refresh']=type_module_class.bl_delay_refresh
props['bl_delay_apply']=type_module_class.bl_delay_apply
props['use_as_filter'] = False
props['icon'] = type_module_class.bl_icon
props['auto_push']=type_module_class.bl_automatic_push
props['bl_name']=type_module_class.bl_id
stype_dict['supported_types'][type_impl_name] = props
return stype_dict
def client_list_callback(scene, context): def client_list_callback(scene, context):
from . import operators from . import operators
items = [(RP_COMMON, RP_COMMON, "")] items = [(RP_COMMON, RP_COMMON, "")]
username = bpy.context.window_manager.session.username username = bpy.context.preferences.addons[__package__].preferences.username
cli = operators.client cli = operators.client
if cli: if cli:
client_ids = cli.online_users.keys() client_ids = cli.online_users.keys()
@ -77,23 +55,6 @@ def client_list_callback(scene, context):
return items return items
def randomColor():
r = random.random()
v = random.random()
b = random.random()
return [r, v, b]
class ReplicatedDatablock(bpy.types.PropertyGroup):
'''name = StringProperty() '''
type_name: bpy.props.StringProperty()
bl_name: bpy.props.StringProperty()
bl_delay_refresh: bpy.props.FloatProperty()
bl_delay_apply: bpy.props.FloatProperty()
use_as_filter: bpy.props.BoolProperty(default=True)
auto_push: bpy.props.BoolProperty(default=True)
icon: bpy.props.StringProperty()
class SessionUser(bpy.types.PropertyGroup): class SessionUser(bpy.types.PropertyGroup):
"""Session User """Session User
@ -104,37 +65,10 @@ class SessionUser(bpy.types.PropertyGroup):
class SessionProps(bpy.types.PropertyGroup): class SessionProps(bpy.types.PropertyGroup):
username: bpy.props.StringProperty(
name="Username",
default="user_{}".format(utils.random_string_digits())
)
ip: bpy.props.StringProperty(
name="ip",
description='Distant host ip',
default="127.0.0.1"
)
user_uuid: bpy.props.StringProperty(
name="user_uuid",
default="None"
)
port: bpy.props.IntProperty(
name="port",
description='Distant host port',
default=5555
)
ipc_port: bpy.props.IntProperty(
name="ipc_port",
description='internal ttl port(only usefull for multiple local instances)',
default=5561
)
is_admin: bpy.props.BoolProperty( is_admin: bpy.props.BoolProperty(
name="is_admin", name="is_admin",
default=False default=False
) )
start_empty: bpy.props.BoolProperty(
name="start_empty",
default=True
)
session_mode: bpy.props.EnumProperty( session_mode: bpy.props.EnumProperty(
name='session_mode', name='session_mode',
description='session mode', description='session mode',
@ -142,17 +76,6 @@ class SessionProps(bpy.types.PropertyGroup):
('HOST', 'hosting', 'host a session'), ('HOST', 'hosting', 'host a session'),
('CONNECT', 'connexion', 'connect to a session')}, ('CONNECT', 'connexion', 'connect to a session')},
default='HOST') default='HOST')
right_strategy: bpy.props.EnumProperty(
name='right_strategy',
description='right strategy',
items={
('STRICT', 'strict', 'strict right repartition'),
('COMMON', 'common', 'relaxed right repartition')},
default='COMMON')
client_color: bpy.props.FloatVectorProperty(
name="client_instance_color",
subtype='COLOR',
default=randomColor())
clients: bpy.props.EnumProperty( clients: bpy.props.EnumProperty(
name="clients", name="clients",
description="client enum", description="client enum",
@ -175,12 +98,6 @@ class SessionProps(bpy.types.PropertyGroup):
default=True, default=True,
update=presence.update_overlay_settings update=presence.update_overlay_settings
) )
supported_datablock: bpy.props.CollectionProperty(
type=ReplicatedDatablock,
)
session_filter: bpy.props.CollectionProperty(
type=ReplicatedDatablock,
)
filter_owned: bpy.props.BoolProperty( filter_owned: bpy.props.BoolProperty(
name="filter_owned", name="filter_owned",
description='Show only owned datablocks', description='Show only owned datablocks',
@ -193,73 +110,13 @@ class SessionProps(bpy.types.PropertyGroup):
default=False default=False
) )
def load(self):
config = environment.load_config()
if "username" in config.keys():
self.username = config["username"]
self.ip = config["ip"]
self.port = config["port"]
self.start_empty = config["start_empty"]
self.enable_presence = config["enable_presence"]
self.client_color = config["client_color"]
else:
logger.error("Fail to read user config")
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()
rep_value.name = datablock
rep_value.type_name = datablock
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']
def save(self,context):
config = environment.load_config()
if "supported_types" not in config:
config = generate_supported_types()
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]
for bloc in self.supported_datablock:
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
environment.save_config(config)
classes = ( classes = (
SessionUser, SessionUser,
ReplicatedDatablock,
SessionProps, SessionProps,
) )
libs = os.path.dirname(os.path.abspath(__file__))+"\\libs\\replication\\replication" libs = os.path.dirname(os.path.abspath(__file__))+"\\libs\\replication\\replication"
@persistent
def load_handler(dummy):
import bpy
bpy.context.window_manager.session.load()
def register(): def register():
if libs not in sys.path: if libs not in sys.path:
sys.path.append(libs) sys.path.append(libs)
@ -269,6 +126,7 @@ def register():
from . import presence from . import presence
from . import operators from . import operators
from . import ui from . import ui
from . import preferences
for cls in classes: for cls in classes:
bpy.utils.register_class(cls) bpy.utils.register_class(cls)
@ -280,22 +138,22 @@ def register():
type=SessionUser type=SessionUser
) )
bpy.types.WindowManager.user_index = bpy.props.IntProperty() bpy.types.WindowManager.user_index = bpy.props.IntProperty()
bpy.context.window_manager.session.load()
preferences.register()
presence.register() presence.register()
operators.register() operators.register()
ui.register() ui.register()
bpy.app.handlers.load_post.append(load_handler)
def unregister(): def unregister():
from . import presence from . import presence
from . import operators from . import operators
from . import ui from . import ui
from . import preferences
presence.unregister() presence.unregister()
ui.unregister() ui.unregister()
operators.unregister() operators.unregister()
preferences.unregister()
del bpy.types.WindowManager.session del bpy.types.WindowManager.session
for cls in reversed(classes): for cls in reversed(classes):

View File

@ -88,7 +88,7 @@ class DynamicRightSelectTimer(Timer):
def execute(self): def execute(self):
session = operators.client session = operators.client
settings = bpy.context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
if session and session.state['STATE'] == STATE_ACTIVE: if session and session.state['STATE'] == STATE_ACTIVE:
# Find user # Find user
@ -220,8 +220,7 @@ class ClientUpdate(Timer):
self.handle_quit = False self.handle_quit = False
def execute(self): def execute(self):
settings = bpy.context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
session_info = bpy.context.window_manager.session
session = getattr(operators, 'client', None) session = getattr(operators, 'client', None)
renderer = getattr(presence, 'renderer', None) renderer = getattr(presence, 'renderer', None)
@ -231,7 +230,7 @@ class ClientUpdate(Timer):
bpy.ops.session.stop() bpy.ops.session.stop()
local_user = operators.client.online_users.get( local_user = operators.client.online_users.get(
session_info.username) settings.username)
if not local_user: if not local_user:
return return

View File

@ -8,9 +8,6 @@ from pathlib import Path
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.setLevel(logging.WARNING) logger.setLevel(logging.WARNING)
CONFIG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config")
CONFIG = os.path.join(CONFIG_DIR, "app.yaml")
THIRD_PARTY = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libs") THIRD_PARTY = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libs")
CACHE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cache") CACHE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cache")
PYTHON_PATH = None PYTHON_PATH = None
@ -19,27 +16,6 @@ SUBPROCESS_DIR = None
rtypes = [] rtypes = []
def load_config():
import yaml
try:
with open(CONFIG, 'r') as config_file:
return yaml.safe_load(config_file)
except FileNotFoundError:
logger.info("no config")
return {}
def save_config(config):
import yaml
logger.info("saving config")
with open(CONFIG, 'w') as outfile:
yaml.dump(config, outfile, default_flow_style=False)
def module_can_be_imported(name): def module_can_be_imported(name):
try: try:
__import__(name) __import__(name)
@ -68,9 +44,6 @@ def setup(dependencies, python_path):
PYTHON_PATH = Path(python_path) PYTHON_PATH = Path(python_path)
SUBPROCESS_DIR = PYTHON_PATH.parent SUBPROCESS_DIR = PYTHON_PATH.parent
check_dir(CACHE_DIR)
check_dir(CONFIG_DIR)
if not module_can_be_imported("pip"): if not module_can_be_imported("pip"):
install_pip() install_pip()

View File

@ -58,14 +58,13 @@ class SessionStartOperator(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global client, delayables, ui_context, server_process global client, delayables, ui_context, server_process
settings = context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
runtime_settings = context.window_manager.session
users = bpy.data.window_managers['WinMan'].online_users users = bpy.data.window_managers['WinMan'].online_users
# TODO: Sync server clients # TODO: Sync server clients
users.clear() users.clear()
delayables.clear() delayables.clear()
# save config
settings.save(context)
bpy_factory = ReplicatedDataFactory() bpy_factory = ReplicatedDataFactory()
supported_bl_types = [] supported_bl_types = []
@ -80,7 +79,7 @@ class SessionStartOperator(bpy.types.Operator):
supported_bl_types.append(type_module_class.bl_id) supported_bl_types.append(type_module_class.bl_id)
# Retreive local replicated types settings # Retreive local replicated types settings
type_local_config = settings.supported_datablock[type_impl_name] type_local_config = settings.supported_datablocks[type_impl_name]
bpy_factory.register_type( bpy_factory.register_type(
type_module_class.bl_class, type_module_class.bl_class,
@ -118,7 +117,7 @@ class SessionStartOperator(bpy.types.Operator):
self.report({'ERROR'}, repr(e)) self.report({'ERROR'}, repr(e))
logger.error(f"Error: {e}") logger.error(f"Error: {e}")
finally: finally:
settings.is_admin = True runtime_settings.is_admin = True
# Join a session # Join a session
else: else:
@ -135,7 +134,7 @@ class SessionStartOperator(bpy.types.Operator):
self.report({'ERROR'}, repr(e)) self.report({'ERROR'}, repr(e))
logger.error(f"Error: {e}") logger.error(f"Error: {e}")
finally: finally:
settings.is_admin = False runtime_settings.is_admin = False
# Background client updates service # Background client updates service
#TODO: Refactoring #TODO: Refactoring
@ -144,7 +143,7 @@ class SessionStartOperator(bpy.types.Operator):
delayables.append(delayable.DynamicRightSelectTimer()) delayables.append(delayable.DynamicRightSelectTimer())
# Launch drawing module # Launch drawing module
if settings.enable_presence: if runtime_settings.enable_presence:
presence.renderer.run() presence.renderer.run()
# Register blender main thread tools # Register blender main thread tools
@ -226,17 +225,17 @@ class SessionPropertyRightOperator(bpy.types.Operator):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
settings = context.window_manager.session runtime_settings = context.window_manager.session
col = layout.column() col = layout.column()
col.prop(settings, "clients") col.prop(runtime_settings, "clients")
def execute(self, context): def execute(self, context):
settings = context.window_manager.session runtime_settings = context.window_manager.session
global client global client
if client: if client:
client.change_owner(self.key, settings.clients) client.change_owner(self.key, runtime_settings.clients)
return {"FINISHED"} return {"FINISHED"}
@ -257,13 +256,13 @@ class SessionSnapUserOperator(bpy.types.Operator):
def execute(self, context): def execute(self, context):
wm = context.window_manager wm = context.window_manager
settings = context.window_manager.session runtime_settings = context.window_manager.session
if settings.time_snap_running: if runtime_settings.time_snap_running:
settings.time_snap_running = False runtime_settings.time_snap_running = False
return {'CANCELLED'} return {'CANCELLED'}
else: else:
settings.time_snap_running = True runtime_settings.time_snap_running = True
self._timer = wm.event_timer_add(0.1, window=context.window) self._timer = wm.event_timer_add(0.1, window=context.window)
wm.modal_handler_add(self) wm.modal_handler_add(self)
@ -311,13 +310,13 @@ class SessionSnapTimeOperator(bpy.types.Operator):
return True return True
def execute(self, context): def execute(self, context):
settings = context.window_manager.session runtime_settings = context.window_manager.session
if settings.user_snap_running: if runtime_settings.user_snap_running:
settings.user_snap_running = False runtime_settings.user_snap_running = False
return {'CANCELLED'} return {'CANCELLED'}
else: else:
settings.user_snap_running = True runtime_settings.user_snap_running = True
wm = context.window_manager wm = context.window_manager
self._timer = wm.event_timer_add(0.05, window=context.window) self._timer = wm.event_timer_add(0.05, window=context.window)
@ -483,7 +482,7 @@ def depsgraph_evaluation(scene):
context = bpy.context context = bpy.context
blender_depsgraph = bpy.context.view_layer.depsgraph blender_depsgraph = bpy.context.view_layer.depsgraph
dependency_updates = [u for u in blender_depsgraph.updates] dependency_updates = [u for u in blender_depsgraph.updates]
session_infos = bpy.context.window_manager.session session_infos = bpy.context.preferences.addons[__package__].preferences
# NOTE: maybe we don't need to check each update but only the first # NOTE: maybe we don't need to check each update but only the first

181
multi_user/preferences.py Normal file
View File

@ -0,0 +1,181 @@
import logging
import bpy
from . import utils, bl_types
logger = logging.getLogger(__name__)
class ReplicatedDatablock(bpy.types.PropertyGroup):
type_name: bpy.props.StringProperty()
bl_name: bpy.props.StringProperty()
bl_delay_refresh: bpy.props.FloatProperty()
bl_delay_apply: bpy.props.FloatProperty()
use_as_filter: bpy.props.BoolProperty(default=True)
auto_push: bpy.props.BoolProperty(default=True)
icon: bpy.props.StringProperty()
class SessionPrefs(bpy.types.AddonPreferences):
bl_idname = __package__
ip: bpy.props.StringProperty(
name="ip",
description='Distant host ip',
default="127.0.0.1")
username: bpy.props.StringProperty(
name="Username",
default="user_{}".format(utils.random_string_digits())
)
client_color: bpy.props.FloatVectorProperty(
name="client_instance_color",
subtype='COLOR',
default=utils.randomColor())
port: bpy.props.IntProperty(
name="port",
description='Distant host port',
default=5555
)
supported_datablocks: bpy.props.CollectionProperty(
type=ReplicatedDatablock,
)
ipc_port: bpy.props.IntProperty(
name="ipc_port",
description='internal ttl port(only usefull for multiple local instances)',
default=5561
)
start_empty: bpy.props.BoolProperty(
name="start_empty",
default=False
)
right_strategy: bpy.props.EnumProperty(
name='right_strategy',
description='right strategy',
items={
('STRICT', 'strict', 'strict right repartition'),
('COMMON', 'common', 'relaxed right repartition')},
default='COMMON')
# for UI
category: bpy.props.EnumProperty(
name="Category",
description="Preferences Category",
items=[
('INFO', "Information", "Information about this add-on"),
('CONFIG', "Configuration", "Configuration about this add-on"),
# ('UPDATE', "Update", "Update this add-on"),
],
default='INFO'
)
conf_session_identity_expanded: bpy.props.BoolProperty(
name="Identity",
description="Identity",
default=True
)
conf_session_rights_expanded: bpy.props.BoolProperty(
name="Rights",
description="Rights",
default=True
)
conf_session_net_expanded: bpy.props.BoolProperty(
name="Net",
description="net",
default=True
)
def draw(self, context):
layout = self.layout
layout.row().prop(self, "category", expand=True)
if self.category == 'INFO':
layout.separator()
layout.label(text="WIP")
if self.category == 'CONFIG':
grid = layout.column()
# USER INFORMATIONS
box = grid.box()
box.prop(
self, "conf_session_identity_expanded", text="User informations",
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_identity_expanded
else 'DISCLOSURE_TRI_RIGHT')
if self.conf_session_identity_expanded:
box.row().prop(self, "username", text="name")
box.row().prop(self, "client_color", text="color")
# NETWORK SETTINGS
box = grid.box()
box.prop(
self, "conf_session_net_expanded", text="Netorking",
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_net_expanded
else 'DISCLOSURE_TRI_RIGHT')
if self.conf_session_net_expanded:
box.row().prop(self, "ip", text="Address")
row = box.row()
row.label(text="Port:")
row.prop(self, "port", text="Address")
row = box.row()
row.label(text="Start with an empty scene:")
row.prop(self, "start_empty", text="")
line = box.row(align=True)
line.label(text=" ")
line.separator()
line.label(text="refresh (sec)")
line.label(text="apply (sec)")
for item in self.supported_datablocks:
line = box.row(align=True)
line.label(text="", icon=item.icon)
line.prop(item, "bl_delay_refresh", text="")
line.prop(item, "bl_delay_apply", text="")
# HOST SETTINGS
box = grid.box()
box.prop(
self, "conf_session_rights_expanded", text="Hosting",
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_rights_expanded
else 'DISCLOSURE_TRI_RIGHT')
if self.conf_session_rights_expanded:
box.row().prop(self, "right_strategy", text="Right model")
row = box.row()
row.label(text="Start with an empty scene:")
row.prop(self, "start_empty", text="")
def generate_supported_types(self):
self.supported_datablocks.clear()
for type in bl_types.types_to_register():
new_db = self.supported_datablocks.add()
type_module = getattr(bl_types, type)
type_impl_name = "Bl{}".format(type.split('_')[1].capitalize())
type_module_class = getattr(type_module, type_impl_name)
new_db.name = type_impl_name
new_db.type_name = type_impl_name
new_db.bl_delay_refresh = type_module_class.bl_delay_refresh
new_db.bl_delay_apply =type_module_class.bl_delay_apply
new_db.use_as_filter = True
new_db.icon = type_module_class.bl_icon
new_db.auto_push =type_module_class.bl_automatic_push
new_db.bl_name=type_module_class.bl_id
classes = (
ReplicatedDatablock,
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:
logger.info('Generating bl_types preferences')
prefs.generate_supported_types()
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)

View File

@ -204,7 +204,7 @@ class DrawFactory(object):
self.d2d_items.clear() self.d2d_items.clear()
def draw_client_selection(self, client_id, client_color, client_selection): def draw_client_selection(self, client_id, client_color, client_selection):
local_user = bpy.context.window_manager.session.username local_user = bpy.context.preferences.addons[__package__].preferences.username
if local_user != client_id: if local_user != client_id:
self.flush_selection(client_id) self.flush_selection(client_id)
@ -261,7 +261,7 @@ class DrawFactory(object):
def draw_client_camera(self, client_id, client_location, client_color): def draw_client_camera(self, client_id, client_location, client_color):
if client_location: if client_location:
local_user = bpy.context.window_manager.session.username local_user = bpy.context.preferences.addons[__package__].preferences.username
if local_user != client_id: if local_user != client_id:
try: try:

View File

@ -139,11 +139,12 @@ class SESSION_PT_settings_network(bpy.types.Panel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
settings = context.window_manager.session runtime_settings = context.window_manager.session
settings = bpy.context.preferences.addons[__package__].preferences
# USER SETTINGS # USER SETTINGS
row = layout.row() row = layout.row()
row.prop(settings, "session_mode", expand=True) row.prop(runtime_settings, "session_mode", expand=True)
row = layout.row() row = layout.row()
box = row.box() box = row.box()
@ -157,7 +158,7 @@ class SESSION_PT_settings_network(bpy.types.Panel):
row.label(text="IPC Port:") row.label(text="IPC Port:")
row.prop(settings, "ipc_port", text="") row.prop(settings, "ipc_port", text="")
if settings.session_mode == 'HOST': if runtime_settings.session_mode == 'HOST':
row = box.row() row = box.row()
row.label(text="Start empty:") row.label(text="Start empty:")
row.prop(settings, "start_empty", text="") row.prop(settings, "start_empty", text="")
@ -184,7 +185,8 @@ class SESSION_PT_settings_user(bpy.types.Panel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
settings = context.window_manager.session runtime_settings = context.window_manager.session
settings = bpy.context.preferences.addons[__package__].preferences
row = layout.row() row = layout.row()
# USER SETTINGS # USER SETTINGS
@ -212,9 +214,11 @@ class SESSION_PT_settings_replication(bpy.types.Panel):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
settings = context.window_manager.session runtime_settings = context.window_manager.session
settings = bpy.context.preferences.addons[__package__].preferences
# Right managment # Right managment
if settings.session_mode == 'HOST': if runtime_settings.session_mode == 'HOST':
row = layout.row(align=True) row = layout.row(align=True)
row.label(text="Right strategy:") row.label(text="Right strategy:")
row.prop(settings,"right_strategy",text="") row.prop(settings,"right_strategy",text="")
@ -231,7 +235,7 @@ class SESSION_PT_settings_replication(bpy.types.Panel):
line.label(text="refresh (sec)") line.label(text="refresh (sec)")
line.label(text="apply (sec)") line.label(text="apply (sec)")
for item in settings.supported_datablock: for item in settings.supported_datablocks:
line = flow.row(align=True) line = flow.row(align=True)
line.prop(item, "auto_push", text="", icon=item.icon) line.prop(item, "auto_push", text="", icon=item.icon)
line.separator() line.separator()
@ -255,7 +259,7 @@ class SESSION_PT_user(bpy.types.Panel):
layout = self.layout layout = self.layout
online_users = context.window_manager.online_users online_users = context.window_manager.online_users
selected_user = context.window_manager.user_index selected_user = context.window_manager.user_index
settings = context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
active_user = online_users[selected_user] if len(online_users)-1>=selected_user else 0 active_user = online_users[selected_user] if len(online_users)-1>=selected_user else 0
@ -289,7 +293,7 @@ class SESSION_PT_user(bpy.types.Panel):
class SESSION_UL_users(bpy.types.UIList): class SESSION_UL_users(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
session = operators.client session = operators.client
settings = context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
is_local_user = item.username == settings.username is_local_user = item.username == settings.username
ping = '-' ping = '-'
frame_current = '-' frame_current = '-'
@ -364,7 +368,8 @@ class SESSION_PT_services(bpy.types.Panel):
def draw_property(context, parent, property_uuid, level=0): def draw_property(context, parent, property_uuid, level=0):
settings = context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
runtime_settings = context.window_manager.session
item = operators.client.get(uuid=property_uuid) item = operators.client.get(uuid=property_uuid)
if item.state == ERROR: if item.state == ERROR:
@ -381,12 +386,12 @@ def draw_property(context, parent, property_uuid, level=0):
detail_item_box = line.row(align=True) detail_item_box = line.row(align=True)
detail_item_box.label(text="", detail_item_box.label(text="",
icon=settings.supported_datablock[item.str_type].icon) icon=settings.supported_datablocks[item.str_type].icon)
detail_item_box.label(text="{} ".format(name)) detail_item_box.label(text="{} ".format(name))
# Operations # Operations
have_right_to_modify = settings.is_admin or \ have_right_to_modify = runtime_settings.is_admin or \
item.owner == settings.username or \ item.owner == settings.username or \
item.owner == RP_COMMON item.owner == RP_COMMON
@ -444,7 +449,8 @@ class SESSION_PT_outliner(bpy.types.Panel):
if hasattr(context.window_manager, 'session'): if hasattr(context.window_manager, 'session'):
# Filters # Filters
settings = context.window_manager.session settings = bpy.context.preferences.addons[__package__].preferences
runtime_settings = context.window_manager.session
flow = layout.grid_flow( flow = layout.grid_flow(
row_major=True, row_major=True,
columns=0, columns=0,
@ -452,21 +458,21 @@ class SESSION_PT_outliner(bpy.types.Panel):
even_rows=False, even_rows=False,
align=True) align=True)
for item in settings.supported_datablock: for item in settings.supported_datablocks:
col = flow.column(align=True) col = flow.column(align=True)
col.prop(item, "use_as_filter", text="", icon=item.icon) col.prop(item, "use_as_filter", text="", icon=item.icon)
row = layout.row(align=True) row = layout.row(align=True)
row.prop(settings, "filter_owned", text="Show only owned") row.prop(runtime_settings, "filter_owned", text="Show only owned")
row = layout.row(align=True) row = layout.row(align=True)
# Properties # Properties
types_filter = [t.type_name for t in settings.supported_datablock types_filter = [t.type_name for t in settings.supported_datablocks
if t.use_as_filter] if t.use_as_filter]
key_to_filter = operators.client.list( key_to_filter = operators.client.list(
filter_owner=settings.username) if settings.filter_owned else operators.client.list() filter_owner=settings.username) if runtime_settings.filter_owned else operators.client.list()
client_keys = [key for key in key_to_filter client_keys = [key for key in key_to_filter
if operators.client.get(uuid=key).str_type if operators.client.get(uuid=key).str_type

View File

@ -37,7 +37,7 @@ def find_from_attr(attr_name, attr_value, list):
def get_datablock_users(datablock): def get_datablock_users(datablock):
users = [] users = []
supported_types = bpy.context.window_manager.session.supported_datablock supported_types = bpy.context.preferences.addons[__package__].preferences.supported_datablocks
if hasattr(datablock, 'users_collection') and datablock.users_collection: if hasattr(datablock, 'users_collection') and datablock.users_collection:
users.extend(list(datablock.users_collection)) users.extend(list(datablock.users_collection))
if hasattr(datablock, 'users_scene') and datablock.users_scene: if hasattr(datablock, 'users_scene') and datablock.users_scene:
@ -59,6 +59,11 @@ def random_string_digits(stringLength=6):
lettersAndDigits = string.ascii_letters + string.digits lettersAndDigits = string.ascii_letters + string.digits
return ''.join(random.choices(lettersAndDigits, k=stringLength)) return ''.join(random.choices(lettersAndDigits, k=stringLength))
def randomColor():
r = random.random()
v = random.random()
b = random.random()
return [r, v, b]
def clean_scene(): def clean_scene():
for type_name in dir(bpy.data): for type_name in dir(bpy.data):