Merge branch '111-improve-the-logging-process' into 'develop'
Resolve "Improve the logging process" See merge request slumber/multi-user!42
This commit is contained in:
BIN
docs/getting_started/img/quickstart_advanced_logging.png
Normal file
BIN
docs/getting_started/img/quickstart_advanced_logging.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
docs/getting_started/img/quickstart_advanced_network.png
Normal file
BIN
docs/getting_started/img/quickstart_advanced_network.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
BIN
docs/getting_started/img/quickstart_advanced_replication.png
Normal file
BIN
docs/getting_started/img/quickstart_advanced_replication.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -299,8 +299,8 @@ Here is a quick list of available actions:
|
|||||||
|
|
||||||
.. _advanced:
|
.. _advanced:
|
||||||
|
|
||||||
Advanced configuration
|
Advanced settings
|
||||||
======================
|
=================
|
||||||
|
|
||||||
This section contains optional settings to configure the session behavior.
|
This section contains optional settings to configure the session behavior.
|
||||||
|
|
||||||
@ -309,7 +309,14 @@ This section contains optional settings to configure the session behavior.
|
|||||||
|
|
||||||
Advanced configuration panel
|
Advanced configuration panel
|
||||||
|
|
||||||
.. rubric:: Network panel
|
-------
|
||||||
|
Network
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. figure:: img/quickstart_advanced_network.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
Advanced network settings
|
||||||
|
|
||||||
**IPC Port** is the port used for Inter Process Communication. This port is used
|
**IPC Port** is the port used for Inter Process Communication. This port is used
|
||||||
by the multi-users subprocesses to communicate with each others. If different instances
|
by the multi-users subprocesses to communicate with each others. If different instances
|
||||||
@ -323,7 +330,14 @@ of the multi-user are using the same IPC port it will create conflict !
|
|||||||
**Timeout (in milliseconds)** is the maximum ping authorized before auto-disconnecting.
|
**Timeout (in milliseconds)** is the maximum ping authorized before auto-disconnecting.
|
||||||
You should only increase it if you have a bad connection.
|
You should only increase it if you have a bad connection.
|
||||||
|
|
||||||
.. rubric:: Replication panel
|
-----------
|
||||||
|
Replication
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. figure:: img/quickstart_advanced_replication.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
Advanced replication settings
|
||||||
|
|
||||||
**Synchronize render settings** (only host) enable replication of EEVEE and CYCLES render settings to match render between clients.
|
**Synchronize render settings** (only host) enable replication of EEVEE and CYCLES render settings to match render between clients.
|
||||||
|
|
||||||
@ -341,4 +355,25 @@ You should only increase it if you have a bad connection.
|
|||||||
- **Refresh**: pushed data update rate (in second)
|
- **Refresh**: pushed data update rate (in second)
|
||||||
- **Apply**: pulled data update rate (in second)
|
- **Apply**: pulled data update rate (in second)
|
||||||
|
|
||||||
|
---
|
||||||
|
Log
|
||||||
|
---
|
||||||
|
|
||||||
|
.. figure:: img/quickstart_advanced_logging.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
Advanced log settings
|
||||||
|
|
||||||
|
**log level** allow to set the logging level of detail. Here is the detail for each values:
|
||||||
|
|
||||||
|
+-----------+-----------------------------------------------+
|
||||||
|
| Log level | Description |
|
||||||
|
+===========+===============================================+
|
||||||
|
| ERROR | Shows only critical error |
|
||||||
|
+-----------+-----------------------------------------------+
|
||||||
|
| WARNING | Shows only errors (all kind) |
|
||||||
|
+-----------+-----------------------------------------------+
|
||||||
|
| INFO | Shows only status related messages and errors |
|
||||||
|
+-----------+-----------------------------------------------+
|
||||||
|
| DEBUG | Shows every possible information. |
|
||||||
|
+-----------+-----------------------------------------------+
|
@ -199,11 +199,11 @@ You can run the dedicated server on any platform by following those steps:
|
|||||||
replication.serve
|
replication.serve
|
||||||
|
|
||||||
.. hint::
|
.. hint::
|
||||||
You can also specify a custom **port** (-p), **timeout** (-t) and **admin password** (-pwd) with the following optionnal argument
|
You can also specify a custom **port** (-p), **timeout** (-t), **admin password** (-pwd), **log level(ERROR, WARNING, INFO or DEBUG)** (-l) and **log file** (-lf) with the following optionnal argument
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
replication.serve -p 5555 -pwd toto -t 1000
|
replication.serve -p 5555 -pwd toto -t 1000 -l INFO -lf server.log
|
||||||
|
|
||||||
As soon as the dedicated server is running, you can connect to it from blender (follow :ref:`how-to-join`).
|
As soon as the dedicated server is running, you can connect to it from blender (follow :ref:`how-to-join`).
|
||||||
|
|
||||||
|
@ -44,13 +44,16 @@ from . import environment, utils
|
|||||||
|
|
||||||
|
|
||||||
DEPENDENCIES = {
|
DEPENDENCIES = {
|
||||||
("replication", '0.0.21a5'),
|
("replication", '0.0.21a6'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
# Setup logging policy
|
# Setup logging policy
|
||||||
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
|
logging.basicConfig(
|
||||||
|
format='%(asctime)s CLIENT %(levelname)-8s %(message)s',
|
||||||
|
datefmt='%H:%M:%S',
|
||||||
|
level=logging.INFO)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
environment.setup(DEPENDENCIES, bpy.app.binary_path_python)
|
environment.setup(DEPENDENCIES, bpy.app.binary_path_python)
|
||||||
|
@ -25,7 +25,7 @@ from pathlib import Path
|
|||||||
import socket
|
import socket
|
||||||
import re
|
import re
|
||||||
|
|
||||||
VERSION_EXPR = re.compile('\d+\.\d+\.\d+')
|
VERSION_EXPR = re.compile('\d+\.\d+\.\d+\w\d+')
|
||||||
|
|
||||||
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")
|
||||||
DEFAULT_CACHE_DIR = os.path.join(
|
DEFAULT_CACHE_DIR = os.path.join(
|
||||||
@ -67,7 +67,6 @@ def check_package_version(name, required_version):
|
|||||||
out = subprocess.run(f"{str(PYTHON_PATH)} -m pip show {name}", capture_output=True)
|
out = subprocess.run(f"{str(PYTHON_PATH)} -m pip show {name}", capture_output=True)
|
||||||
|
|
||||||
version = VERSION_EXPR.search(out.stdout.decode())
|
version = VERSION_EXPR.search(out.stdout.decode())
|
||||||
|
|
||||||
if version and version.group() == required_version:
|
if version and version.group() == required_version:
|
||||||
logging.info(f"{name} is up to date")
|
logging.info(f"{name} is up to date")
|
||||||
return True
|
return True
|
||||||
|
@ -34,8 +34,8 @@ from bpy.app.handlers import persistent
|
|||||||
|
|
||||||
from . import bl_types, delayable, environment, presence, ui, utils
|
from . import bl_types, delayable, environment, presence, ui, utils
|
||||||
from replication.constants import (FETCHED, STATE_ACTIVE,
|
from replication.constants import (FETCHED, STATE_ACTIVE,
|
||||||
STATE_INITIAL,
|
STATE_INITIAL,
|
||||||
STATE_SYNCING, RP_COMMON, UP)
|
STATE_SYNCING, RP_COMMON, UP)
|
||||||
from replication.data import ReplicatedDataFactory
|
from replication.data import ReplicatedDataFactory
|
||||||
from replication.exception import NonAuthorizedOperationError
|
from replication.exception import NonAuthorizedOperationError
|
||||||
from replication.interface import Session
|
from replication.interface import Session
|
||||||
@ -71,6 +71,29 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
users.clear()
|
users.clear()
|
||||||
delayables.clear()
|
delayables.clear()
|
||||||
|
|
||||||
|
logging.getLogger().handlers.clear()
|
||||||
|
# logging.basicConfig(level=settings.logging_level)
|
||||||
|
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
fmt='%(asctime)s CLIENT %(levelname)-8s %(message)s',
|
||||||
|
datefmt='%H:%M:%S'
|
||||||
|
)
|
||||||
|
|
||||||
|
log_directory = os.path.join(
|
||||||
|
settings.cache_directory,
|
||||||
|
"multiuser_client.log")
|
||||||
|
|
||||||
|
os.makedirs(settings.cache_directory, exist_ok=True)
|
||||||
|
logger = logging.getLogger()
|
||||||
|
handler = logging.FileHandler(log_directory, mode='w')
|
||||||
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
for handler in logger.handlers:
|
||||||
|
if isinstance(handler, logging.NullHandler):
|
||||||
|
continue
|
||||||
|
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
bpy_factory = ReplicatedDataFactory()
|
bpy_factory = ReplicatedDataFactory()
|
||||||
supported_bl_types = []
|
supported_bl_types = []
|
||||||
|
|
||||||
@ -104,7 +127,8 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
external_update_handling=use_extern_update)
|
external_update_handling=use_extern_update)
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
if settings.update_method == 'DEPSGRAPH':
|
||||||
delayables.append(delayable.ApplyTimer(settings.depsgraph_update_rate/1000))
|
delayables.append(delayable.ApplyTimer(
|
||||||
|
settings.depsgraph_update_rate/1000))
|
||||||
|
|
||||||
# Host a session
|
# Host a session
|
||||||
if self.host:
|
if self.host:
|
||||||
@ -123,7 +147,10 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
port=settings.port,
|
port=settings.port,
|
||||||
ipc_port=settings.ipc_port,
|
ipc_port=settings.ipc_port,
|
||||||
timeout=settings.connection_timeout,
|
timeout=settings.connection_timeout,
|
||||||
password=admin_pass
|
password=admin_pass,
|
||||||
|
cache_directory=settings.cache_directory,
|
||||||
|
server_log_level=logging.getLevelName(
|
||||||
|
logging.getLogger().level),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
@ -162,7 +189,6 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
delayables.append(session_update)
|
delayables.append(session_update)
|
||||||
delayables.append(session_user_sync)
|
delayables.append(session_user_sync)
|
||||||
|
|
||||||
|
|
||||||
@client.register('on_connection')
|
@client.register('on_connection')
|
||||||
def initialize_session():
|
def initialize_session():
|
||||||
settings = utils.get_preferences()
|
settings = utils.get_preferences()
|
||||||
@ -177,7 +203,6 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
if node_ref.state == FETCHED:
|
if node_ref.state == FETCHED:
|
||||||
node_ref.apply()
|
node_ref.apply()
|
||||||
|
|
||||||
|
|
||||||
# Launch drawing module
|
# Launch drawing module
|
||||||
if runtime_settings.enable_presence:
|
if runtime_settings.enable_presence:
|
||||||
presence.renderer.run()
|
presence.renderer.run()
|
||||||
@ -187,7 +212,8 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
d.register()
|
d.register()
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
if settings.update_method == 'DEPSGRAPH':
|
||||||
bpy.app.handlers.depsgraph_update_post.append(depsgraph_evaluation)
|
bpy.app.handlers.depsgraph_update_post.append(
|
||||||
|
depsgraph_evaluation)
|
||||||
|
|
||||||
@client.register('on_exit')
|
@client.register('on_exit')
|
||||||
def desinitialize_session():
|
def desinitialize_session():
|
||||||
@ -204,7 +230,8 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
presence.renderer.stop()
|
presence.renderer.stop()
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
if settings.update_method == 'DEPSGRAPH':
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(depsgraph_evaluation)
|
bpy.app.handlers.depsgraph_update_post.remove(
|
||||||
|
depsgraph_evaluation)
|
||||||
|
|
||||||
bpy.ops.session.apply_armature_operator()
|
bpy.ops.session.apply_armature_operator()
|
||||||
|
|
||||||
@ -422,14 +449,16 @@ class SessionSnapUserOperator(bpy.types.Operator):
|
|||||||
if target_scene != context.scene.name:
|
if target_scene != context.scene.name:
|
||||||
blender_scene = bpy.data.scenes.get(target_scene, None)
|
blender_scene = bpy.data.scenes.get(target_scene, None)
|
||||||
if blender_scene is None:
|
if blender_scene is None:
|
||||||
self.report({'ERROR'}, f"Scene {target_scene} doesn't exist on the local client.")
|
self.report(
|
||||||
|
{'ERROR'}, f"Scene {target_scene} doesn't exist on the local client.")
|
||||||
session_sessings.time_snap_running = False
|
session_sessings.time_snap_running = False
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
bpy.context.window.scene = blender_scene
|
bpy.context.window.scene = blender_scene
|
||||||
|
|
||||||
# Update client viewmatrix
|
# Update client viewmatrix
|
||||||
client_vmatrix = target_ref['metadata'].get('view_matrix', None)
|
client_vmatrix = target_ref['metadata'].get(
|
||||||
|
'view_matrix', None)
|
||||||
|
|
||||||
if client_vmatrix:
|
if client_vmatrix:
|
||||||
rv3d.view_matrix = mathutils.Matrix(client_vmatrix)
|
rv3d.view_matrix = mathutils.Matrix(client_vmatrix)
|
||||||
@ -625,6 +654,7 @@ def update_client_frame(scene):
|
|||||||
'frame_current': scene.frame_current
|
'frame_current': scene.frame_current
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def depsgraph_evaluation(scene):
|
def depsgraph_evaluation(scene):
|
||||||
if client and client.state['STATE'] == STATE_ACTIVE:
|
if client and client.state['STATE'] == STATE_ACTIVE:
|
||||||
@ -648,7 +678,7 @@ def depsgraph_evaluation(scene):
|
|||||||
if node and node.owner in [client.id, RP_COMMON] and node.state == UP:
|
if node and node.owner in [client.id, RP_COMMON] and node.state == UP:
|
||||||
# Avoid slow geometry update
|
# Avoid slow geometry update
|
||||||
if 'EDIT' in context.mode and \
|
if 'EDIT' in context.mode and \
|
||||||
not settings.enable_editmode_updates:
|
not settings.enable_editmode_updates:
|
||||||
break
|
break
|
||||||
|
|
||||||
client.stash(node.uuid)
|
client.stash(node.uuid)
|
||||||
@ -672,8 +702,6 @@ def register():
|
|||||||
bpy.app.handlers.frame_change_pre.append(update_client_frame)
|
bpy.app.handlers.frame_change_pre.append(update_client_frame)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
global client
|
global client
|
||||||
|
|
||||||
@ -690,4 +718,3 @@ def unregister():
|
|||||||
|
|
||||||
bpy.app.handlers.load_pre.remove(load_pre_handler)
|
bpy.app.handlers.load_pre.remove(load_pre_handler)
|
||||||
bpy.app.handlers.frame_change_pre.remove(update_client_frame)
|
bpy.app.handlers.frame_change_pre.remove(update_client_frame)
|
||||||
|
|
@ -21,7 +21,8 @@ import bpy
|
|||||||
import string
|
import string
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from . import utils, bl_types, environment, addon_updater_ops, presence, ui
|
from . import bl_types, environment, addon_updater_ops, presence, ui
|
||||||
|
from .utils import get_preferences, get_expanded_icon
|
||||||
from replication.constants import RP_COMMON
|
from replication.constants import RP_COMMON
|
||||||
|
|
||||||
IP_EXPR = re.compile('\d+\.\d+\.\d+\.\d+')
|
IP_EXPR = re.compile('\d+\.\d+\.\d+\.\d+')
|
||||||
@ -46,6 +47,7 @@ def update_panel_category(self, context):
|
|||||||
ui.SESSION_PT_settings.bl_category = self.panel_category
|
ui.SESSION_PT_settings.bl_category = self.panel_category
|
||||||
ui.register()
|
ui.register()
|
||||||
|
|
||||||
|
|
||||||
def update_ip(self, context):
|
def update_ip(self, context):
|
||||||
ip = IP_EXPR.search(self.ip)
|
ip = IP_EXPR.search(self.ip)
|
||||||
|
|
||||||
@ -55,14 +57,25 @@ def update_ip(self, context):
|
|||||||
logging.error("Wrong IP format")
|
logging.error("Wrong IP format")
|
||||||
self['ip'] = "127.0.0.1"
|
self['ip'] = "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
def update_port(self, context):
|
def update_port(self, context):
|
||||||
max_port = self.port + 3
|
max_port = self.port + 3
|
||||||
|
|
||||||
if self.ipc_port < max_port and \
|
if self.ipc_port < max_port and \
|
||||||
self['ipc_port'] >= self.port:
|
self['ipc_port'] >= self.port:
|
||||||
logging.error("IPC Port in conflic with the port, assigning a random value")
|
logging.error(
|
||||||
|
"IPC Port in conflic with the port, assigning a random value")
|
||||||
self['ipc_port'] = random.randrange(self.port+4, 10000)
|
self['ipc_port'] = random.randrange(self.port+4, 10000)
|
||||||
|
|
||||||
|
|
||||||
|
def set_log_level(self, value):
|
||||||
|
logging.getLogger().setLevel(value)
|
||||||
|
|
||||||
|
|
||||||
|
def get_log_level(self):
|
||||||
|
return logging.getLogger().level
|
||||||
|
|
||||||
|
|
||||||
class ReplicatedDatablock(bpy.types.PropertyGroup):
|
class ReplicatedDatablock(bpy.types.PropertyGroup):
|
||||||
type_name: bpy.props.StringProperty()
|
type_name: bpy.props.StringProperty()
|
||||||
bl_name: bpy.props.StringProperty()
|
bl_name: bpy.props.StringProperty()
|
||||||
@ -134,7 +147,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
description='replication update method',
|
description='replication update method',
|
||||||
items=[
|
items=[
|
||||||
('DEFAULT', "Default", "Default: Use threads to monitor databloc changes"),
|
('DEFAULT', "Default", "Default: Use threads to monitor databloc changes"),
|
||||||
('DEPSGRAPH', "Depsgraph", "Experimental: Use the blender dependency graph to trigger updates"),
|
('DEPSGRAPH', "Depsgraph",
|
||||||
|
"Experimental: Use the blender dependency graph to trigger updates"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
# Replication update settings
|
# Replication update settings
|
||||||
@ -158,17 +172,18 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
],
|
],
|
||||||
default='CONFIG'
|
default='CONFIG'
|
||||||
)
|
)
|
||||||
# WIP
|
|
||||||
logging_level: bpy.props.EnumProperty(
|
logging_level: bpy.props.EnumProperty(
|
||||||
name="Log level",
|
name="Log level",
|
||||||
description="Log verbosity level",
|
description="Log verbosity level",
|
||||||
items=[
|
items=[
|
||||||
('ERROR', "error", "show only errors"),
|
('ERROR', "error", "show only errors", logging.ERROR),
|
||||||
('WARNING', "warning", "only show warnings and errors"),
|
('WARNING', "warning", "only show warnings and errors", logging.WARNING),
|
||||||
('INFO', "info", "default level"),
|
('INFO', "info", "default level", logging.INFO),
|
||||||
('DEBUG', "debug", "show all logs"),
|
('DEBUG', "debug", "show all logs", logging.DEBUG),
|
||||||
],
|
],
|
||||||
default='INFO'
|
default='INFO',
|
||||||
|
set=set_log_level,
|
||||||
|
get=get_log_level
|
||||||
)
|
)
|
||||||
conf_session_identity_expanded: bpy.props.BoolProperty(
|
conf_session_identity_expanded: bpy.props.BoolProperty(
|
||||||
name="Identity",
|
name="Identity",
|
||||||
@ -200,7 +215,21 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
description="Interface",
|
description="Interface",
|
||||||
default=False
|
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_net_expanded: bpy.props.BoolProperty(
|
||||||
|
name="sidebar_advanced_net_expanded",
|
||||||
|
description="sidebar_advanced_net_expanded",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
auto_check_update: bpy.props.BoolProperty(
|
auto_check_update: bpy.props.BoolProperty(
|
||||||
name="Auto-check for Update",
|
name="Auto-check for Update",
|
||||||
description="If enabled, auto-check for updates using an interval",
|
description="If enabled, auto-check for updates using an interval",
|
||||||
@ -252,8 +281,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
box = grid.box()
|
box = grid.box()
|
||||||
box.prop(
|
box.prop(
|
||||||
self, "conf_session_identity_expanded", text="User informations",
|
self, "conf_session_identity_expanded", text="User informations",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_identity_expanded
|
icon=get_expanded_icon(self.conf_session_identity_expanded),
|
||||||
else 'DISCLOSURE_TRI_RIGHT', emboss=False)
|
emboss=False)
|
||||||
if self.conf_session_identity_expanded:
|
if self.conf_session_identity_expanded:
|
||||||
box.row().prop(self, "username", text="name")
|
box.row().prop(self, "username", text="name")
|
||||||
box.row().prop(self, "client_color", text="color")
|
box.row().prop(self, "client_color", text="color")
|
||||||
@ -262,8 +291,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
box = grid.box()
|
box = grid.box()
|
||||||
box.prop(
|
box.prop(
|
||||||
self, "conf_session_net_expanded", text="Netorking",
|
self, "conf_session_net_expanded", text="Netorking",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_net_expanded
|
icon=get_expanded_icon(self.conf_session_net_expanded),
|
||||||
else 'DISCLOSURE_TRI_RIGHT', emboss=False)
|
emboss=False)
|
||||||
|
|
||||||
if self.conf_session_net_expanded:
|
if self.conf_session_net_expanded:
|
||||||
box.row().prop(self, "ip", text="Address")
|
box.row().prop(self, "ip", text="Address")
|
||||||
@ -280,8 +309,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
table = box.box()
|
table = box.box()
|
||||||
table.row().prop(
|
table.row().prop(
|
||||||
self, "conf_session_timing_expanded", text="Refresh rates",
|
self, "conf_session_timing_expanded", text="Refresh rates",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_timing_expanded
|
icon=get_expanded_icon(self.conf_session_timing_expanded),
|
||||||
else 'DISCLOSURE_TRI_RIGHT', emboss=False)
|
emboss=False)
|
||||||
|
|
||||||
if self.conf_session_timing_expanded:
|
if self.conf_session_timing_expanded:
|
||||||
line = table.row()
|
line = table.row()
|
||||||
@ -299,8 +328,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
box = grid.box()
|
box = grid.box()
|
||||||
box.prop(
|
box.prop(
|
||||||
self, "conf_session_hosting_expanded", text="Hosting",
|
self, "conf_session_hosting_expanded", text="Hosting",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_hosting_expanded
|
icon=get_expanded_icon(self.conf_session_hosting_expanded),
|
||||||
else 'DISCLOSURE_TRI_RIGHT', emboss=False)
|
emboss=False)
|
||||||
if self.conf_session_hosting_expanded:
|
if self.conf_session_hosting_expanded:
|
||||||
row = box.row()
|
row = box.row()
|
||||||
row.label(text="Init the session from:")
|
row.label(text="Init the session from:")
|
||||||
@ -310,8 +339,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
box = grid.box()
|
box = grid.box()
|
||||||
box.prop(
|
box.prop(
|
||||||
self, "conf_session_cache_expanded", text="Cache",
|
self, "conf_session_cache_expanded", text="Cache",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_cache_expanded
|
icon=get_expanded_icon(self.conf_session_cache_expanded),
|
||||||
else 'DISCLOSURE_TRI_RIGHT', emboss=False)
|
emboss=False)
|
||||||
if self.conf_session_cache_expanded:
|
if self.conf_session_cache_expanded:
|
||||||
box.row().prop(self, "cache_directory", text="Cache directory")
|
box.row().prop(self, "cache_directory", text="Cache directory")
|
||||||
|
|
||||||
@ -319,7 +348,7 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
box = grid.box()
|
box = grid.box()
|
||||||
box.prop(
|
box.prop(
|
||||||
self, "conf_session_ui_expanded", text="Interface",
|
self, "conf_session_ui_expanded", text="Interface",
|
||||||
icon='DISCLOSURE_TRI_DOWN' if self.conf_session_ui_expanded else 'DISCLOSURE_TRI_RIGHT',
|
icon=get_expanded_icon(self.conf_session_ui_expanded),
|
||||||
emboss=False)
|
emboss=False)
|
||||||
if self.conf_session_ui_expanded:
|
if self.conf_session_ui_expanded:
|
||||||
box.row().prop(self, "panel_category", text="Panel category", expand=True)
|
box.row().prop(self, "panel_category", text="Panel category", expand=True)
|
||||||
@ -353,7 +382,7 @@ def client_list_callback(scene, context):
|
|||||||
|
|
||||||
items = [(RP_COMMON, RP_COMMON, "")]
|
items = [(RP_COMMON, RP_COMMON, "")]
|
||||||
|
|
||||||
username = utils.get_preferences().username
|
username = get_preferences().username
|
||||||
cli = operators.client
|
cli = operators.client
|
||||||
if cli:
|
if cli:
|
||||||
client_ids = cli.online_users.keys()
|
client_ids = cli.online_users.keys()
|
||||||
|
135
multi_user/ui.py
135
multi_user/ui.py
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from . import operators, utils
|
from . import operators
|
||||||
|
from .utils import get_preferences, get_expanded_icon
|
||||||
from replication.constants import (ADDED, ERROR, FETCHED,
|
from replication.constants import (ADDED, ERROR, FETCHED,
|
||||||
MODIFIED, RP_COMMON, UP,
|
MODIFIED, RP_COMMON, UP,
|
||||||
STATE_ACTIVE, STATE_AUTH,
|
STATE_ACTIVE, STATE_AUTH,
|
||||||
@ -112,7 +113,7 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
layout.use_property_split = True
|
layout.use_property_split = True
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
|
|
||||||
if hasattr(context.window_manager, 'session'):
|
if hasattr(context.window_manager, 'session'):
|
||||||
# STATE INITIAL
|
# STATE INITIAL
|
||||||
@ -195,7 +196,7 @@ class SESSION_PT_settings_network(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
|
|
||||||
# USER SETTINGS
|
# USER SETTINGS
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
@ -253,7 +254,7 @@ class SESSION_PT_settings_user(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
# USER SETTINGS
|
# USER SETTINGS
|
||||||
@ -284,60 +285,88 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
|
|
||||||
|
|
||||||
net_section = layout.row().box()
|
net_section = layout.row().box()
|
||||||
net_section.label(text="Network ", icon='TRIA_DOWN')
|
net_section.prop(
|
||||||
net_section_row = net_section.row()
|
settings,
|
||||||
net_section_row.label(text="IPC Port:")
|
"sidebar_advanced_net_expanded",
|
||||||
net_section_row.prop(settings, "ipc_port", text="")
|
text="Network",
|
||||||
net_section_row = net_section.row()
|
icon=get_expanded_icon(settings.sidebar_advanced_net_expanded),
|
||||||
net_section_row.label(text="Timeout (ms):")
|
emboss=False)
|
||||||
net_section_row.prop(settings, "connection_timeout", text="")
|
|
||||||
|
if settings.sidebar_advanced_net_expanded:
|
||||||
|
net_section_row = net_section.row()
|
||||||
|
net_section_row.label(text="IPC Port:")
|
||||||
|
net_section_row.prop(settings, "ipc_port", text="")
|
||||||
|
net_section_row = net_section.row()
|
||||||
|
net_section_row.label(text="Timeout (ms):")
|
||||||
|
net_section_row.prop(settings, "connection_timeout", text="")
|
||||||
|
|
||||||
replication_section = layout.row().box()
|
replication_section = layout.row().box()
|
||||||
replication_section.label(text="Replication ", icon='TRIA_DOWN')
|
replication_section.prop(
|
||||||
replication_section_row = replication_section.row()
|
settings,
|
||||||
replication_section_row.label(text="Sync flags", icon='COLLECTION_NEW')
|
"sidebar_advanced_rep_expanded",
|
||||||
replication_section_row = replication_section.row()
|
text="Replication",
|
||||||
replication_section_row.prop(settings.sync_flags, "sync_render_settings")
|
icon=get_expanded_icon(settings.sidebar_advanced_rep_expanded),
|
||||||
replication_section_row = replication_section.row()
|
emboss=False)
|
||||||
# replication_section_row.label(text=":", icon='EDITMODE_HLT')
|
|
||||||
replication_section_row.prop(settings, "enable_editmode_updates")
|
if settings.sidebar_advanced_rep_expanded:
|
||||||
replication_section_row = replication_section.row()
|
|
||||||
if settings.enable_editmode_updates:
|
|
||||||
warning = replication_section_row.box()
|
|
||||||
warning.label(text="Don't use this with heavy meshes !", icon='ERROR')
|
|
||||||
replication_section_row = replication_section.row()
|
replication_section_row = replication_section.row()
|
||||||
replication_section_row.label(text="Update method", icon='RECOVER_LAST')
|
|
||||||
replication_section_row = replication_section.row()
|
|
||||||
replication_section_row.prop(settings, "update_method", expand=True)
|
|
||||||
replication_section_row = replication_section.row()
|
|
||||||
replication_timers = replication_section_row.box()
|
|
||||||
replication_timers.label(text="Replication timers", icon='TIME')
|
|
||||||
if settings.update_method == "DEFAULT":
|
|
||||||
replication_timers = replication_timers.row()
|
|
||||||
# Replication frequencies
|
|
||||||
flow = replication_timers.grid_flow(
|
|
||||||
row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
|
||||||
line = flow.row(align=True)
|
|
||||||
line.label(text=" ")
|
|
||||||
line.separator()
|
|
||||||
line.label(text="refresh (sec)")
|
|
||||||
line.label(text="apply (sec)")
|
|
||||||
|
|
||||||
for item in settings.supported_datablocks:
|
replication_section_row.label(text="Sync flags", icon='COLLECTION_NEW')
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
replication_section_row.prop(settings.sync_flags, "sync_render_settings")
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
|
||||||
|
replication_section_row.prop(settings, "enable_editmode_updates")
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
if settings.enable_editmode_updates:
|
||||||
|
warning = replication_section_row.box()
|
||||||
|
warning.label(text="Don't use this with heavy meshes !", icon='ERROR')
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
|
||||||
|
replication_section_row.label(text="Update method", icon='RECOVER_LAST')
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
replication_section_row.prop(settings, "update_method", expand=True)
|
||||||
|
replication_section_row = replication_section.row()
|
||||||
|
replication_timers = replication_section_row.box()
|
||||||
|
replication_timers.label(text="Replication timers", icon='TIME')
|
||||||
|
if settings.update_method == "DEFAULT":
|
||||||
|
replication_timers = replication_timers.row()
|
||||||
|
# Replication frequencies
|
||||||
|
flow = replication_timers.grid_flow(
|
||||||
|
row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
||||||
line = flow.row(align=True)
|
line = flow.row(align=True)
|
||||||
line.prop(item, "auto_push", text="", icon=item.icon)
|
line.label(text=" ")
|
||||||
line.separator()
|
line.separator()
|
||||||
line.prop(item, "bl_delay_refresh", text="")
|
line.label(text="refresh (sec)")
|
||||||
line.prop(item, "bl_delay_apply", text="")
|
line.label(text="apply (sec)")
|
||||||
else:
|
|
||||||
replication_timers = replication_timers.row()
|
|
||||||
replication_timers.label(text="Update rate (ms):")
|
|
||||||
replication_timers.prop(settings, "depsgraph_update_rate", text="")
|
|
||||||
|
|
||||||
|
for item in settings.supported_datablocks:
|
||||||
|
line = flow.row(align=True)
|
||||||
|
line.prop(item, "auto_push", text="", icon=item.icon)
|
||||||
|
line.separator()
|
||||||
|
line.prop(item, "bl_delay_refresh", text="")
|
||||||
|
line.prop(item, "bl_delay_apply", text="")
|
||||||
|
else:
|
||||||
|
replication_timers = replication_timers.row()
|
||||||
|
replication_timers.label(text="Update rate (ms):")
|
||||||
|
replication_timers.prop(settings, "depsgraph_update_rate", text="")
|
||||||
|
|
||||||
|
log_section = layout.row().box()
|
||||||
|
log_section.prop(
|
||||||
|
settings,
|
||||||
|
"sidebar_advanced_log_expanded",
|
||||||
|
text="Logging",
|
||||||
|
icon=get_expanded_icon(settings.sidebar_advanced_log_expanded),
|
||||||
|
emboss=False)
|
||||||
|
|
||||||
|
if settings.sidebar_advanced_log_expanded:
|
||||||
|
log_section_row = log_section.row()
|
||||||
|
log_section_row.label(text="Log level:")
|
||||||
|
log_section_row.prop(settings, 'logging_level', text="")
|
||||||
class SESSION_PT_user(bpy.types.Panel):
|
class SESSION_PT_user(bpy.types.Panel):
|
||||||
bl_idname = "MULTIUSER_USER_PT_panel"
|
bl_idname = "MULTIUSER_USER_PT_panel"
|
||||||
bl_label = "Online users"
|
bl_label = "Online users"
|
||||||
@ -356,7 +385,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 = utils.get_preferences()
|
settings = get_preferences()
|
||||||
active_user = online_users[selected_user] if len(
|
active_user = online_users[selected_user] if len(
|
||||||
online_users)-1 >= selected_user else 0
|
online_users)-1 >= selected_user else 0
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
@ -402,7 +431,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 = utils.get_preferences()
|
settings = get_preferences()
|
||||||
is_local_user = item.username == settings.username
|
is_local_user = item.username == settings.username
|
||||||
ping = '-'
|
ping = '-'
|
||||||
frame_current = '-'
|
frame_current = '-'
|
||||||
@ -486,7 +515,7 @@ 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 = utils.get_preferences()
|
settings = get_preferences()
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
item = operators.client.get(uuid=property_uuid)
|
item = operators.client.get(uuid=property_uuid)
|
||||||
|
|
||||||
@ -557,7 +586,7 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
session = operators.client
|
session = operators.client
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
admin = False
|
admin = False
|
||||||
|
|
||||||
if session and hasattr(session,'online_users'):
|
if session and hasattr(session,'online_users'):
|
||||||
@ -576,7 +605,7 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
settings = utils.get_preferences()
|
settings = get_preferences()
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
|
|
||||||
session = operators.client
|
session = operators.client
|
||||||
|
@ -39,7 +39,7 @@ def find_from_attr(attr_name, attr_value, list):
|
|||||||
|
|
||||||
def get_datablock_users(datablock):
|
def get_datablock_users(datablock):
|
||||||
users = []
|
users = []
|
||||||
supported_types = get_preferences().supported_datablocks
|
supported_types = get_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:
|
||||||
@ -82,5 +82,13 @@ def resolve_from_id(id, optionnal_type=None):
|
|||||||
def get_preferences():
|
def get_preferences():
|
||||||
return bpy.context.preferences.addons[__package__].preferences
|
return bpy.context.preferences.addons[__package__].preferences
|
||||||
|
|
||||||
|
|
||||||
def current_milli_time():
|
def current_milli_time():
|
||||||
return int(round(time.time() * 1000))
|
return int(round(time.time() * 1000))
|
||||||
|
|
||||||
|
|
||||||
|
def get_expanded_icon(prop: bpy.types.BoolProperty) -> str:
|
||||||
|
if prop:
|
||||||
|
return 'DISCLOSURE_TRI_DOWN'
|
||||||
|
else:
|
||||||
|
return 'DISCLOSURE_TRI_RIGHT'
|
||||||
|
Reference in New Issue
Block a user