Merge branch 'remove-services' into 'develop'
refactor: differential revision Stage 1 See merge request slumber/multi-user!119
This commit is contained in:
@ -374,15 +374,6 @@ Network
|
|||||||
|
|
||||||
Advanced network settings
|
Advanced network settings
|
||||||
|
|
||||||
**IPC Port** is the port used for Inter Process Communication. This port is used
|
|
||||||
by the multi-user subprocesses to communicate with each other. If different instances
|
|
||||||
of multi-user are using the same IPC port, this will create conflict !
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
You only need to modify this setting if you need to launch multiple clients from the same
|
|
||||||
computer (or if you try to host and join from the same computer). To resolve this, you simply need to enter a different
|
|
||||||
**IPC port** for each blender instance.
|
|
||||||
|
|
||||||
**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.
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Multi-User",
|
"name": "Multi-User",
|
||||||
"author": "Swann Martinez",
|
"author": "Swann Martinez",
|
||||||
"version": (0, 3, 0),
|
"version": (0, 4, 0),
|
||||||
"description": "Enable real-time collaborative workflow inside blender",
|
"description": "Enable real-time collaborative workflow inside blender",
|
||||||
"blender": (2, 82, 0),
|
"blender": (2, 82, 0),
|
||||||
"location": "3D View > Sidebar > Multi-User tab",
|
"location": "3D View > Sidebar > Multi-User tab",
|
||||||
@ -44,7 +44,7 @@ from . import environment
|
|||||||
|
|
||||||
|
|
||||||
DEPENDENCIES = {
|
DEPENDENCIES = {
|
||||||
("replication", '0.1.26'),
|
("replication", '0.1.33'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ if bpy.app.version[1] >= 91:
|
|||||||
__all__.append('bl_volume')
|
__all__.append('bl_volume')
|
||||||
|
|
||||||
from . import *
|
from . import *
|
||||||
from replication.data import ReplicatedDataFactory
|
from replication.data import DataTranslationProtocol
|
||||||
|
|
||||||
def types_to_register():
|
def types_to_register():
|
||||||
return __all__
|
return __all__
|
||||||
|
@ -134,6 +134,8 @@ class BlFile(ReplicatedDatablock):
|
|||||||
if self.preferences.clear_memory_filecache:
|
if self.preferences.clear_memory_filecache:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
if not self.instance:
|
||||||
|
return False
|
||||||
memory_size = sys.getsizeof(self.data['file'])-33
|
memory_size = sys.getsizeof(self.data['file'])-33
|
||||||
disk_size = self.instance.stat().st_size
|
disk_size = self.instance.stat().st_size
|
||||||
return memory_size != disk_size
|
return memory_size != disk_size
|
||||||
|
@ -66,7 +66,7 @@ class BlImage(BlDatablock):
|
|||||||
loader = Loader()
|
loader = Loader()
|
||||||
loader.load(data, target)
|
loader.load(data, target)
|
||||||
|
|
||||||
target.source = data['source']
|
target.source = 'FILE'
|
||||||
target.filepath_raw = get_filepath(data['filename'])
|
target.filepath_raw = get_filepath(data['filename'])
|
||||||
color_space_name = data["colorspace_settings"]["name"]
|
color_space_name = data["colorspace_settings"]["name"]
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ class BlImage(BlDatablock):
|
|||||||
dumper.depth = 2
|
dumper.depth = 2
|
||||||
dumper.include_filter = [
|
dumper.include_filter = [
|
||||||
"name",
|
"name",
|
||||||
'source',
|
# 'source',
|
||||||
'size',
|
'size',
|
||||||
'height',
|
'height',
|
||||||
'alpha',
|
'alpha',
|
||||||
|
@ -368,6 +368,8 @@ def load_sequence(sequence_data: dict, sequence_editor: bpy.types.SequenceEditor
|
|||||||
|
|
||||||
|
|
||||||
class BlScene(BlDatablock):
|
class BlScene(BlDatablock):
|
||||||
|
is_root = True
|
||||||
|
|
||||||
bl_id = "scenes"
|
bl_id = "scenes"
|
||||||
bl_class = bpy.types.Scene
|
bl_class = bpy.types.Scene
|
||||||
bl_check_common = True
|
bl_check_common = True
|
||||||
|
@ -32,6 +32,7 @@ from operator import itemgetter
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from time import gmtime, strftime
|
from time import gmtime, strftime
|
||||||
|
import traceback
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import _pickle as pickle
|
import _pickle as pickle
|
||||||
@ -44,9 +45,11 @@ from bpy.app.handlers import persistent
|
|||||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||||
from replication.constants import (COMMITED, FETCHED, RP_COMMON, STATE_ACTIVE,
|
from replication.constants import (COMMITED, FETCHED, RP_COMMON, STATE_ACTIVE,
|
||||||
STATE_INITIAL, STATE_SYNCING, UP)
|
STATE_INITIAL, STATE_SYNCING, UP)
|
||||||
from replication.data import ReplicatedDataFactory
|
from replication.data import DataTranslationProtocol
|
||||||
from replication.exception import NonAuthorizedOperationError, ContextError
|
from replication.exception import ContextError, NonAuthorizedOperationError
|
||||||
from replication.interface import session
|
from replication.interface import session
|
||||||
|
from replication.porcelain import add, apply
|
||||||
|
from replication.repository import Repository
|
||||||
|
|
||||||
from . import bl_types, environment, timers, ui, utils
|
from . import bl_types, environment, timers, ui, utils
|
||||||
from .presence import SessionStatusWidget, renderer, view3d_find
|
from .presence import SessionStatusWidget, renderer, view3d_find
|
||||||
@ -80,8 +83,8 @@ def initialize_session():
|
|||||||
|
|
||||||
# Step 1: Constrect nodes
|
# Step 1: Constrect nodes
|
||||||
logging.info("Constructing nodes")
|
logging.info("Constructing nodes")
|
||||||
for node in session._graph.list_ordered():
|
for node in session.repository.list_ordered():
|
||||||
node_ref = session.get(uuid=node)
|
node_ref = session.repository.get_node(node)
|
||||||
if node_ref is None:
|
if node_ref is None:
|
||||||
logging.error(f"Can't construct node {node}")
|
logging.error(f"Can't construct node {node}")
|
||||||
elif node_ref.state == FETCHED:
|
elif node_ref.state == FETCHED:
|
||||||
@ -89,8 +92,8 @@ def initialize_session():
|
|||||||
|
|
||||||
# Step 2: Load nodes
|
# Step 2: Load nodes
|
||||||
logging.info("Loading nodes")
|
logging.info("Loading nodes")
|
||||||
for node in session._graph.list_ordered():
|
for node in session.repository.list_ordered():
|
||||||
node_ref = session.get(uuid=node)
|
node_ref = session.repository.get_node(node)
|
||||||
|
|
||||||
if node_ref is None:
|
if node_ref is None:
|
||||||
logging.error(f"Can't load node {node}")
|
logging.error(f"Can't load node {node}")
|
||||||
@ -186,7 +189,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
bpy_factory = ReplicatedDataFactory()
|
bpy_protocol = DataTranslationProtocol()
|
||||||
supported_bl_types = []
|
supported_bl_types = []
|
||||||
|
|
||||||
# init the factory with supported types
|
# init the factory with supported types
|
||||||
@ -205,7 +208,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
type_local_config = settings.supported_datablocks[type_impl_name]
|
type_local_config = settings.supported_datablocks[type_impl_name]
|
||||||
|
|
||||||
bpy_factory.register_type(
|
bpy_protocol.register_type(
|
||||||
type_module_class.bl_class,
|
type_module_class.bl_class,
|
||||||
type_module_class,
|
type_module_class,
|
||||||
check_common=type_module_class.bl_check_common)
|
check_common=type_module_class.bl_check_common)
|
||||||
@ -215,10 +218,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
else:
|
else:
|
||||||
python_binary_path = bpy.app.binary_path_python
|
python_binary_path = bpy.app.binary_path_python
|
||||||
|
|
||||||
session.configure(
|
repo = Repository(data_protocol=bpy_protocol)
|
||||||
factory=bpy_factory,
|
|
||||||
python_path=python_binary_path,
|
|
||||||
external_update_handling=True)
|
|
||||||
|
|
||||||
# Host a session
|
# Host a session
|
||||||
if self.host:
|
if self.host:
|
||||||
@ -229,13 +229,14 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
runtime_settings.internet_ip = environment.get_ip()
|
runtime_settings.internet_ip = environment.get_ip()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Init repository
|
||||||
for scene in bpy.data.scenes:
|
for scene in bpy.data.scenes:
|
||||||
session.add(scene)
|
add(repo, scene)
|
||||||
|
|
||||||
session.host(
|
session.host(
|
||||||
|
repository= repo,
|
||||||
id=settings.username,
|
id=settings.username,
|
||||||
port=settings.port,
|
port=settings.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,
|
cache_directory=settings.cache_directory,
|
||||||
@ -245,7 +246,6 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
logging.error(f"Error: {e}")
|
logging.error(f"Error: {e}")
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
# Join a session
|
# Join a session
|
||||||
else:
|
else:
|
||||||
@ -256,10 +256,10 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
session.connect(
|
session.connect(
|
||||||
|
repository= repo,
|
||||||
id=settings.username,
|
id=settings.username,
|
||||||
address=settings.ip,
|
address=settings.ip,
|
||||||
port=settings.port,
|
port=settings.port,
|
||||||
ipc_port=settings.ipc_port,
|
|
||||||
timeout=settings.connection_timeout,
|
timeout=settings.connection_timeout,
|
||||||
password=admin_pass
|
password=admin_pass
|
||||||
)
|
)
|
||||||
@ -279,7 +279,9 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
session_user_sync = timers.SessionUserSync()
|
session_user_sync = timers.SessionUserSync()
|
||||||
session_background_executor = timers.MainThreadExecutor(
|
session_background_executor = timers.MainThreadExecutor(
|
||||||
execution_queue=background_execution_queue)
|
execution_queue=background_execution_queue)
|
||||||
|
session_listen = timers.SessionListenTimer(timeout=0.001)
|
||||||
|
|
||||||
|
session_listen.register()
|
||||||
session_update.register()
|
session_update.register()
|
||||||
session_user_sync.register()
|
session_user_sync.register()
|
||||||
session_background_executor.register()
|
session_background_executor.register()
|
||||||
@ -287,7 +289,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
deleyables.append(session_background_executor)
|
deleyables.append(session_background_executor)
|
||||||
deleyables.append(session_update)
|
deleyables.append(session_update)
|
||||||
deleyables.append(session_user_sync)
|
deleyables.append(session_user_sync)
|
||||||
|
deleyables.append(session_listen)
|
||||||
|
|
||||||
|
|
||||||
self.report(
|
self.report(
|
||||||
@ -328,7 +330,7 @@ class SessionInitOperator(bpy.types.Operator):
|
|||||||
utils.clean_scene()
|
utils.clean_scene()
|
||||||
|
|
||||||
for scene in bpy.data.scenes:
|
for scene in bpy.data.scenes:
|
||||||
session.add(scene)
|
add(session.repository, scene)
|
||||||
|
|
||||||
session.init()
|
session.init()
|
||||||
|
|
||||||
@ -350,7 +352,7 @@ class SessionStopOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
if session:
|
if session:
|
||||||
try:
|
try:
|
||||||
session.disconnect()
|
session.disconnect(reason='user')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
@ -599,17 +601,22 @@ class SessionApply(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
logging.debug(f"Running apply on {self.target}")
|
logging.debug(f"Running apply on {self.target}")
|
||||||
try:
|
try:
|
||||||
node_ref = session.get(uuid=self.target)
|
node_ref = session.repository.get_node(self.target)
|
||||||
session.apply(self.target,
|
apply(session.repository,
|
||||||
force=True,
|
self.target,
|
||||||
force_dependencies=self.reset_dependencies)
|
force=True,
|
||||||
|
force_dependencies=self.reset_dependencies)
|
||||||
if node_ref.bl_reload_parent:
|
if node_ref.bl_reload_parent:
|
||||||
for parent in session._graph.find_parents(self.target):
|
for parent in session.repository.get_parents(self.target):
|
||||||
logging.debug(f"Refresh parent {parent}")
|
logging.debug(f"Refresh parent {parent}")
|
||||||
session.apply(parent, force=True)
|
|
||||||
|
apply(session.repository,
|
||||||
|
parent.uuid,
|
||||||
|
force=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({'ERROR'}, repr(e))
|
self.report({'ERROR'}, repr(e))
|
||||||
return {"CANCELED"}
|
traceback.print_exc()
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@ -649,15 +656,15 @@ class ApplyArmatureOperator(bpy.types.Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
if event.type == 'TIMER':
|
if event.type == 'TIMER':
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
nodes = session.list(filter=bl_types.bl_armature.BlArmature)
|
nodes = session.list(filter=bl_types.bl_armature.BlArmature)
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node_ref = session.get(uuid=node)
|
node_ref = session.repository.get_node(node)
|
||||||
|
|
||||||
if node_ref.state == FETCHED:
|
if node_ref.state == FETCHED:
|
||||||
try:
|
try:
|
||||||
session.apply(node)
|
apply(session.repository, node)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Fail to apply armature: {e}")
|
logging.error("Fail to apply armature: {e}")
|
||||||
|
|
||||||
@ -794,7 +801,7 @@ class SessionSaveBackupOperator(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return session.state['STATE'] == STATE_ACTIVE
|
return session.state == STATE_ACTIVE
|
||||||
|
|
||||||
class SessionStopAutoSaveOperator(bpy.types.Operator):
|
class SessionStopAutoSaveOperator(bpy.types.Operator):
|
||||||
bl_idname = "session.cancel_autosave"
|
bl_idname = "session.cancel_autosave"
|
||||||
@ -803,7 +810,7 @@ class SessionStopAutoSaveOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (session.state['STATE'] == STATE_ACTIVE and 'SessionBackupTimer' in registry)
|
return (session.state == STATE_ACTIVE and 'SessionBackupTimer' in registry)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
autosave_timer = registry.get('SessionBackupTimer')
|
autosave_timer = registry.get('SessionBackupTimer')
|
||||||
@ -828,7 +835,7 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from replication.graph import ReplicationGraph
|
from replication.repository import Repository
|
||||||
|
|
||||||
# TODO: add filechecks
|
# TODO: add filechecks
|
||||||
|
|
||||||
@ -848,7 +855,7 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
|
|
||||||
|
|
||||||
# init the factory with supported types
|
# init the factory with supported types
|
||||||
bpy_factory = ReplicatedDataFactory()
|
bpy_protocol = DataTranslationProtocol()
|
||||||
for type in bl_types.types_to_register():
|
for type in bl_types.types_to_register():
|
||||||
type_module = getattr(bl_types, type)
|
type_module = getattr(bl_types, type)
|
||||||
name = [e.capitalize() for e in type.split('_')[1:]]
|
name = [e.capitalize() for e in type.split('_')[1:]]
|
||||||
@ -856,16 +863,16 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
type_module_class = getattr(type_module, type_impl_name)
|
type_module_class = getattr(type_module, type_impl_name)
|
||||||
|
|
||||||
|
|
||||||
bpy_factory.register_type(
|
bpy_protocol.register_type(
|
||||||
type_module_class.bl_class,
|
type_module_class.bl_class,
|
||||||
type_module_class)
|
type_module_class)
|
||||||
|
|
||||||
graph = ReplicationGraph()
|
graph = Repository()
|
||||||
|
|
||||||
for node, node_data in nodes:
|
for node, node_data in nodes:
|
||||||
node_type = node_data.get('str_type')
|
node_type = node_data.get('str_type')
|
||||||
|
|
||||||
impl = bpy_factory.get_implementation_from_net(node_type)
|
impl = bpy_protocol.get_implementation_from_net(node_type)
|
||||||
|
|
||||||
if impl:
|
if impl:
|
||||||
logging.info(f"Loading {node}")
|
logging.info(f"Loading {node}")
|
||||||
@ -873,7 +880,7 @@ class SessionLoadSaveOperator(bpy.types.Operator, ImportHelper):
|
|||||||
uuid=node,
|
uuid=node,
|
||||||
dependencies=node_data['dependencies'],
|
dependencies=node_data['dependencies'],
|
||||||
data=node_data['data'])
|
data=node_data['data'])
|
||||||
instance.store(graph)
|
graph.do_commit(instance)
|
||||||
instance.state = FETCHED
|
instance.state = FETCHED
|
||||||
|
|
||||||
logging.info("Graph succefully loaded")
|
logging.info("Graph succefully loaded")
|
||||||
@ -922,7 +929,7 @@ classes = (
|
|||||||
def update_external_dependencies():
|
def update_external_dependencies():
|
||||||
nodes_ids = session.list(filter=bl_types.bl_file.BlFile)
|
nodes_ids = session.list(filter=bl_types.bl_file.BlFile)
|
||||||
for node_id in nodes_ids:
|
for node_id in nodes_ids:
|
||||||
node = session.get(node_id)
|
node = session.repository.get_node(node_id)
|
||||||
if node and node.owner in [session.id, RP_COMMON] \
|
if node and node.owner in [session.id, RP_COMMON] \
|
||||||
and node.has_changed():
|
and node.has_changed():
|
||||||
session.commit(node_id)
|
session.commit(node_id)
|
||||||
@ -931,11 +938,11 @@ def update_external_dependencies():
|
|||||||
def sanitize_deps_graph(remove_nodes: bool = False):
|
def sanitize_deps_graph(remove_nodes: bool = False):
|
||||||
""" Cleanup the replication graph
|
""" Cleanup the replication graph
|
||||||
"""
|
"""
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
start = utils.current_milli_time()
|
start = utils.current_milli_time()
|
||||||
rm_cpt = 0
|
rm_cpt = 0
|
||||||
for node_key in session.list():
|
for node_key in session.list():
|
||||||
node = session.get(node_key)
|
node = session.repository.get_node(node_key)
|
||||||
if node is None \
|
if node is None \
|
||||||
or (node.state == UP and not node.resolve(construct=False)):
|
or (node.state == UP and not node.resolve(construct=False)):
|
||||||
if remove_nodes:
|
if remove_nodes:
|
||||||
@ -956,18 +963,18 @@ def resolve_deps_graph(dummy):
|
|||||||
A future solution should be to avoid storing dataclock reference...
|
A future solution should be to avoid storing dataclock reference...
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
sanitize_deps_graph(remove_nodes=True)
|
sanitize_deps_graph(remove_nodes=True)
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def load_pre_handler(dummy):
|
def load_pre_handler(dummy):
|
||||||
if session and session.state['STATE'] in [STATE_ACTIVE, STATE_SYNCING]:
|
if session and session.state in [STATE_ACTIVE, STATE_SYNCING]:
|
||||||
bpy.ops.session.stop()
|
bpy.ops.session.stop()
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def update_client_frame(scene):
|
def update_client_frame(scene):
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
session.update_user_metadata({
|
session.update_user_metadata({
|
||||||
'frame_current': scene.frame_current
|
'frame_current': scene.frame_current
|
||||||
})
|
})
|
||||||
@ -975,7 +982,7 @@ def update_client_frame(scene):
|
|||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def depsgraph_evaluation(scene):
|
def depsgraph_evaluation(scene):
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
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]
|
||||||
@ -988,7 +995,7 @@ def depsgraph_evaluation(scene):
|
|||||||
# Is the object tracked ?
|
# Is the object tracked ?
|
||||||
if update.id.uuid:
|
if update.id.uuid:
|
||||||
# Retrieve local version
|
# Retrieve local version
|
||||||
node = session.get(uuid=update.id.uuid)
|
node = session.repository.get_node(update.id.uuid)
|
||||||
|
|
||||||
# Check our right on this update:
|
# Check our right on this update:
|
||||||
# - if its ours or ( under common and diff), launch the
|
# - if its ours or ( under common and diff), launch the
|
||||||
@ -1012,11 +1019,11 @@ def depsgraph_evaluation(scene):
|
|||||||
continue
|
continue
|
||||||
# A new scene is created
|
# A new scene is created
|
||||||
elif isinstance(update.id, bpy.types.Scene):
|
elif isinstance(update.id, bpy.types.Scene):
|
||||||
ref = session.get(reference=update.id)
|
ref = session.repository.get_node_by_datablock(update.id)
|
||||||
if ref:
|
if ref:
|
||||||
ref.resolve()
|
ref.resolve()
|
||||||
else:
|
else:
|
||||||
scn_uuid = session.add(update.id)
|
scn_uuid = add(session.repository, update.id)
|
||||||
session.commit(scn_uuid)
|
session.commit(scn_uuid)
|
||||||
session.push(scn_uuid, check_data=False)
|
session.push(scn_uuid, check_data=False)
|
||||||
def register():
|
def register():
|
||||||
@ -1034,7 +1041,7 @@ def register():
|
|||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
session.disconnect()
|
session.disconnect()
|
||||||
|
|
||||||
from bpy.utils import unregister_class
|
from bpy.utils import unregister_class
|
||||||
|
@ -66,14 +66,6 @@ def update_ip(self, context):
|
|||||||
self['ip'] = "127.0.0.1"
|
self['ip'] = "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
def update_port(self, context):
|
|
||||||
max_port = self.port + 3
|
|
||||||
|
|
||||||
if self.ipc_port < max_port and \
|
|
||||||
self['ipc_port'] >= self.port:
|
|
||||||
logging.error(
|
|
||||||
"IPC Port in conflict with the port, assigning a random value")
|
|
||||||
self['ipc_port'] = random.randrange(self.port+4, 10000)
|
|
||||||
|
|
||||||
|
|
||||||
def update_directory(self, context):
|
def update_directory(self, context):
|
||||||
@ -174,12 +166,6 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
supported_datablocks: bpy.props.CollectionProperty(
|
supported_datablocks: bpy.props.CollectionProperty(
|
||||||
type=ReplicatedDatablock,
|
type=ReplicatedDatablock,
|
||||||
)
|
)
|
||||||
ipc_port: bpy.props.IntProperty(
|
|
||||||
name="ipc_port",
|
|
||||||
description='internal ttl port(only useful for multiple local instances)',
|
|
||||||
default=random.randrange(5570, 70000),
|
|
||||||
update=update_port,
|
|
||||||
)
|
|
||||||
init_method: bpy.props.EnumProperty(
|
init_method: bpy.props.EnumProperty(
|
||||||
name='init_method',
|
name='init_method',
|
||||||
description='Init repo',
|
description='Init repo',
|
||||||
|
@ -30,7 +30,7 @@ import mathutils
|
|||||||
from bpy_extras import view3d_utils
|
from bpy_extras import view3d_utils
|
||||||
from gpu_extras.batch import batch_for_shader
|
from gpu_extras.batch import batch_for_shader
|
||||||
from replication.constants import (STATE_ACTIVE, STATE_AUTH, STATE_CONFIG,
|
from replication.constants import (STATE_ACTIVE, STATE_AUTH, STATE_CONFIG,
|
||||||
STATE_INITIAL, STATE_LAUNCHING_SERVICES,
|
STATE_INITIAL, CONNECTING,
|
||||||
STATE_LOBBY, STATE_QUITTING, STATE_SRV_SYNC,
|
STATE_LOBBY, STATE_QUITTING, STATE_SRV_SYNC,
|
||||||
STATE_SYNCING, STATE_WAITING)
|
STATE_SYNCING, STATE_WAITING)
|
||||||
from replication.interface import session
|
from replication.interface import session
|
||||||
@ -399,7 +399,7 @@ class SessionStatusWidget(Widget):
|
|||||||
text_scale = self.preferences.presence_hud_scale
|
text_scale = self.preferences.presence_hud_scale
|
||||||
ui_scale = bpy.context.preferences.view.ui_scale
|
ui_scale = bpy.context.preferences.view.ui_scale
|
||||||
color = [1, 1, 0, 1]
|
color = [1, 1, 0, 1]
|
||||||
state = session.state.get('STATE')
|
state = session.state
|
||||||
state_str = f"{get_state_str(state)}"
|
state_str = f"{get_state_str(state)}"
|
||||||
|
|
||||||
if state == STATE_ACTIVE:
|
if state == STATE_ACTIVE:
|
||||||
|
@ -24,6 +24,7 @@ from replication.constants import (FETCHED, RP_COMMON, STATE_ACTIVE,
|
|||||||
STATE_SRV_SYNC, STATE_SYNCING, UP)
|
STATE_SRV_SYNC, STATE_SYNCING, UP)
|
||||||
from replication.exception import NonAuthorizedOperationError, ContextError
|
from replication.exception import NonAuthorizedOperationError, ContextError
|
||||||
from replication.interface import session
|
from replication.interface import session
|
||||||
|
from replication.porcelain import apply, add
|
||||||
|
|
||||||
from . import operators, utils
|
from . import operators, utils
|
||||||
from .presence import (UserFrustumWidget, UserNameWidget, UserSelectionWidget,
|
from .presence import (UserFrustumWidget, UserNameWidget, UserSelectionWidget,
|
||||||
@ -71,7 +72,7 @@ class Timer(object):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
self.unregister()
|
self.unregister()
|
||||||
session.disconnect()
|
session.disconnect(reason=f"Error during timer {self.id} execution")
|
||||||
else:
|
else:
|
||||||
if self.is_running:
|
if self.is_running:
|
||||||
return self._timeout
|
return self._timeout
|
||||||
@ -100,25 +101,31 @@ class SessionBackupTimer(Timer):
|
|||||||
def execute(self):
|
def execute(self):
|
||||||
session.save(self._filepath)
|
session.save(self._filepath)
|
||||||
|
|
||||||
|
class SessionListenTimer(Timer):
|
||||||
|
def execute(self):
|
||||||
|
session.listen()
|
||||||
|
|
||||||
class ApplyTimer(Timer):
|
class ApplyTimer(Timer):
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
nodes = session.list()
|
nodes = session.list()
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node_ref = session.get(uuid=node)
|
node_ref = session.repository.get_node(node)
|
||||||
|
|
||||||
if node_ref.state == FETCHED:
|
if node_ref.state == FETCHED:
|
||||||
try:
|
try:
|
||||||
session.apply(node)
|
apply(session.repository, node)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Fail to apply {node_ref.uuid}")
|
logging.error(f"Fail to apply {node_ref.uuid}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
else:
|
else:
|
||||||
if node_ref.bl_reload_parent:
|
if node_ref.bl_reload_parent:
|
||||||
for parent in session._graph.find_parents(node):
|
for parent in session.repository.get_parents(node):
|
||||||
logging.debug("Refresh parent {node}")
|
logging.debug("Refresh parent {node}")
|
||||||
session.apply(parent, force=True)
|
apply(session.repository,
|
||||||
|
parent.uuid,
|
||||||
|
force=True)
|
||||||
|
|
||||||
|
|
||||||
class DynamicRightSelectTimer(Timer):
|
class DynamicRightSelectTimer(Timer):
|
||||||
@ -131,7 +138,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
def execute(self):
|
def execute(self):
|
||||||
settings = utils.get_preferences()
|
settings = utils.get_preferences()
|
||||||
|
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state == STATE_ACTIVE:
|
||||||
# Find user
|
# Find user
|
||||||
if self._user is None:
|
if self._user is None:
|
||||||
self._user = session.online_users.get(settings.username)
|
self._user = session.online_users.get(settings.username)
|
||||||
@ -145,7 +152,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
|
|
||||||
# if an annotation exist and is tracked
|
# if an annotation exist and is tracked
|
||||||
if annotation_gp and annotation_gp.uuid:
|
if annotation_gp and annotation_gp.uuid:
|
||||||
registered_gp = session.get(uuid=annotation_gp.uuid)
|
registered_gp = session.repository.get_node(annotation_gp.uuid)
|
||||||
if is_annotating(bpy.context):
|
if is_annotating(bpy.context):
|
||||||
# try to get the right on it
|
# try to get the right on it
|
||||||
if registered_gp.owner == RP_COMMON:
|
if registered_gp.owner == RP_COMMON:
|
||||||
@ -159,7 +166,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
affect_dependencies=False)
|
affect_dependencies=False)
|
||||||
|
|
||||||
if registered_gp.owner == settings.username:
|
if registered_gp.owner == settings.username:
|
||||||
gp_node = session.get(uuid=annotation_gp.uuid)
|
gp_node = session.repository.get_node(annotation_gp.uuid)
|
||||||
if gp_node.has_changed():
|
if gp_node.has_changed():
|
||||||
session.commit(gp_node.uuid)
|
session.commit(gp_node.uuid)
|
||||||
session.push(gp_node.uuid, check_data=False)
|
session.push(gp_node.uuid, check_data=False)
|
||||||
@ -183,7 +190,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
|
|
||||||
# change old selection right to common
|
# change old selection right to common
|
||||||
for obj in obj_common:
|
for obj in obj_common:
|
||||||
node = session.get(uuid=obj)
|
node = session.repository.get_node(obj)
|
||||||
|
|
||||||
if node and (node.owner == settings.username or node.owner == RP_COMMON):
|
if node and (node.owner == settings.username or node.owner == RP_COMMON):
|
||||||
recursive = True
|
recursive = True
|
||||||
@ -201,7 +208,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
|
|
||||||
# change new selection to our
|
# change new selection to our
|
||||||
for obj in obj_ours:
|
for obj in obj_ours:
|
||||||
node = session.get(uuid=obj)
|
node = session.repository.get_node(obj)
|
||||||
|
|
||||||
if node and node.owner == RP_COMMON:
|
if node and node.owner == RP_COMMON:
|
||||||
recursive = True
|
recursive = True
|
||||||
@ -234,7 +241,7 @@ class DynamicRightSelectTimer(Timer):
|
|||||||
owned_keys = session.list(
|
owned_keys = session.list(
|
||||||
filter_owner=settings.username)
|
filter_owner=settings.username)
|
||||||
for key in owned_keys:
|
for key in owned_keys:
|
||||||
node = session.get(uuid=key)
|
node = session.repository.get_node(key)
|
||||||
try:
|
try:
|
||||||
session.change_owner(
|
session.change_owner(
|
||||||
key,
|
key,
|
||||||
@ -263,7 +270,7 @@ class ClientUpdate(Timer):
|
|||||||
settings = utils.get_preferences()
|
settings = utils.get_preferences()
|
||||||
|
|
||||||
if session and renderer:
|
if session and renderer:
|
||||||
if session.state['STATE'] in [STATE_ACTIVE, STATE_LOBBY]:
|
if session.state in [STATE_ACTIVE, STATE_LOBBY]:
|
||||||
local_user = session.online_users.get(
|
local_user = session.online_users.get(
|
||||||
settings.username)
|
settings.username)
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ from replication.constants import (ADDED, ERROR, FETCHED,
|
|||||||
STATE_INITIAL, STATE_SRV_SYNC,
|
STATE_INITIAL, STATE_SRV_SYNC,
|
||||||
STATE_WAITING, STATE_QUITTING,
|
STATE_WAITING, STATE_QUITTING,
|
||||||
STATE_LOBBY,
|
STATE_LOBBY,
|
||||||
STATE_LAUNCHING_SERVICES)
|
CONNECTING)
|
||||||
from replication import __version__
|
from replication import __version__
|
||||||
from replication.interface import session
|
from replication.interface import session
|
||||||
from .timers import registry
|
from .timers import registry
|
||||||
@ -71,9 +71,9 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if session and session.state['STATE'] != STATE_INITIAL:
|
if session and session.state != STATE_INITIAL:
|
||||||
cli_state = session.state
|
cli_state = session.state
|
||||||
state = session.state.get('STATE')
|
state = session.state
|
||||||
connection_icon = "KEYTYPE_MOVING_HOLD_VEC"
|
connection_icon = "KEYTYPE_MOVING_HOLD_VEC"
|
||||||
|
|
||||||
if state == STATE_ACTIVE:
|
if state == STATE_ACTIVE:
|
||||||
@ -81,7 +81,7 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
else:
|
else:
|
||||||
connection_icon = 'PROP_CON'
|
connection_icon = 'PROP_CON'
|
||||||
|
|
||||||
layout.label(text=f"Session - {get_state_str(cli_state['STATE'])}", icon=connection_icon)
|
layout.label(text=f"Session - {get_state_str(cli_state)}", icon=connection_icon)
|
||||||
else:
|
else:
|
||||||
layout.label(text=f"Session - v{__version__}",icon="PROP_OFF")
|
layout.label(text=f"Session - v{__version__}",icon="PROP_OFF")
|
||||||
|
|
||||||
@ -94,13 +94,13 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
if hasattr(context.window_manager, 'session'):
|
if hasattr(context.window_manager, 'session'):
|
||||||
# STATE INITIAL
|
# STATE INITIAL
|
||||||
if not session \
|
if not session \
|
||||||
or (session and session.state['STATE'] == STATE_INITIAL):
|
or (session and session.state == STATE_INITIAL):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
cli_state = session.state
|
progress = session.state_progress
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|
||||||
current_state = cli_state['STATE']
|
current_state = session.state
|
||||||
info_msg = None
|
info_msg = None
|
||||||
|
|
||||||
if current_state in [STATE_ACTIVE]:
|
if current_state in [STATE_ACTIVE]:
|
||||||
@ -124,8 +124,8 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
if current_state in [STATE_SYNCING, STATE_SRV_SYNC, STATE_WAITING]:
|
if current_state in [STATE_SYNCING, STATE_SRV_SYNC, STATE_WAITING]:
|
||||||
info_box = row.box()
|
info_box = row.box()
|
||||||
info_box.row().label(text=printProgressBar(
|
info_box.row().label(text=printProgressBar(
|
||||||
cli_state['CURRENT'],
|
progress['current'],
|
||||||
cli_state['TOTAL'],
|
progress['total'],
|
||||||
length=16
|
length=16
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ class SESSION_PT_settings_network(bpy.types.Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return not session \
|
return not session \
|
||||||
or (session and session.state['STATE'] == 0)
|
or (session and session.state == 0)
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.label(text="", icon='URL')
|
self.layout.label(text="", icon='URL')
|
||||||
@ -199,7 +199,7 @@ class SESSION_PT_settings_user(bpy.types.Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return not session \
|
return not session \
|
||||||
or (session and session.state['STATE'] == 0)
|
or (session and session.state == 0)
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.label(text="", icon='USER')
|
self.layout.label(text="", icon='USER')
|
||||||
@ -230,7 +230,7 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return not session \
|
return not session \
|
||||||
or (session and session.state['STATE'] == 0)
|
or (session and session.state == 0)
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.label(text="", icon='PREFERENCES')
|
self.layout.label(text="", icon='PREFERENCES')
|
||||||
@ -251,9 +251,6 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
|
|||||||
emboss=False)
|
emboss=False)
|
||||||
|
|
||||||
if settings.sidebar_advanced_net_expanded:
|
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 = net_section.row()
|
||||||
net_section_row.label(text="Timeout (ms):")
|
net_section_row.label(text="Timeout (ms):")
|
||||||
net_section_row.prop(settings, "connection_timeout", text="")
|
net_section_row.prop(settings, "connection_timeout", text="")
|
||||||
@ -322,7 +319,7 @@ class SESSION_PT_user(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return session and session.state['STATE'] in [STATE_ACTIVE, STATE_LOBBY]
|
return session and session.state in [STATE_ACTIVE, STATE_LOBBY]
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.label(text="", icon='USER')
|
self.layout.label(text="", icon='USER')
|
||||||
@ -353,7 +350,7 @@ class SESSION_PT_user(bpy.types.Panel):
|
|||||||
if active_user != 0 and active_user.username != settings.username:
|
if active_user != 0 and active_user.username != settings.username:
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
user_operations = row.split()
|
user_operations = row.split()
|
||||||
if session.state['STATE'] == STATE_ACTIVE:
|
if session.state == STATE_ACTIVE:
|
||||||
|
|
||||||
user_operations.alert = context.window_manager.session.time_snap_running
|
user_operations.alert = context.window_manager.session.time_snap_running
|
||||||
user_operations.operator(
|
user_operations.operator(
|
||||||
@ -411,7 +408,7 @@ class SESSION_PT_presence(bpy.types.Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return not session \
|
return not session \
|
||||||
or (session and session.state['STATE'] in [STATE_INITIAL, STATE_ACTIVE])
|
or (session and session.state in [STATE_INITIAL, STATE_ACTIVE])
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.prop(context.window_manager.session,
|
self.layout.prop(context.window_manager.session,
|
||||||
@ -441,7 +438,7 @@ class SESSION_PT_presence(bpy.types.Panel):
|
|||||||
def draw_property(context, parent, property_uuid, level=0):
|
def draw_property(context, parent, property_uuid, level=0):
|
||||||
settings = get_preferences()
|
settings = get_preferences()
|
||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
item = session.get(uuid=property_uuid)
|
item = session.repository.get_node(property_uuid)
|
||||||
|
|
||||||
area_msg = parent.row(align=True)
|
area_msg = parent.row(align=True)
|
||||||
|
|
||||||
@ -519,8 +516,8 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
admin = usr['admin']
|
admin = usr['admin']
|
||||||
return hasattr(context.window_manager, 'session') and \
|
return hasattr(context.window_manager, 'session') and \
|
||||||
session and \
|
session and \
|
||||||
(session.state['STATE'] == STATE_ACTIVE or \
|
(session.state == STATE_ACTIVE or \
|
||||||
session.state['STATE'] == STATE_LOBBY and admin)
|
session.state == STATE_LOBBY and admin)
|
||||||
|
|
||||||
def draw_header(self, context):
|
def draw_header(self, context):
|
||||||
self.layout.label(text="", icon='OUTLINER_OB_GROUP_INSTANCE')
|
self.layout.label(text="", icon='OUTLINER_OB_GROUP_INSTANCE')
|
||||||
@ -536,7 +533,7 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|
||||||
if session.state['STATE'] == STATE_ACTIVE:
|
if session.state == STATE_ACTIVE:
|
||||||
if 'SessionBackupTimer' in registry:
|
if 'SessionBackupTimer' in registry:
|
||||||
row.alert = True
|
row.alert = True
|
||||||
row.operator('session.cancel_autosave', icon="CANCEL")
|
row.operator('session.cancel_autosave', icon="CANCEL")
|
||||||
@ -568,7 +565,7 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
filter_owner=settings.username) if runtime_settings.filter_owned else session.list()
|
filter_owner=settings.username) if runtime_settings.filter_owned else session.list()
|
||||||
|
|
||||||
client_keys = [key for key in key_to_filter
|
client_keys = [key for key in key_to_filter
|
||||||
if session.get(uuid=key).str_type
|
if session.repository.get_node(key).str_type
|
||||||
in types_filter]
|
in types_filter]
|
||||||
|
|
||||||
if client_keys:
|
if client_keys:
|
||||||
@ -579,7 +576,7 @@ class SESSION_PT_repository(bpy.types.Panel):
|
|||||||
else:
|
else:
|
||||||
row.label(text="Empty")
|
row.label(text="Empty")
|
||||||
|
|
||||||
elif session.state['STATE'] == STATE_LOBBY and usr and usr['admin']:
|
elif session.state == STATE_LOBBY and usr and usr['admin']:
|
||||||
row.operator("session.init", icon='TOOL_SETTINGS', text="Init")
|
row.operator("session.init", icon='TOOL_SETTINGS', text="Init")
|
||||||
else:
|
else:
|
||||||
row.label(text="Waiting to start")
|
row.label(text="Waiting to start")
|
||||||
|
@ -36,7 +36,7 @@ from replication.constants import (STATE_ACTIVE, STATE_AUTH,
|
|||||||
STATE_INITIAL, STATE_SRV_SYNC,
|
STATE_INITIAL, STATE_SRV_SYNC,
|
||||||
STATE_WAITING, STATE_QUITTING,
|
STATE_WAITING, STATE_QUITTING,
|
||||||
STATE_LOBBY,
|
STATE_LOBBY,
|
||||||
STATE_LAUNCHING_SERVICES)
|
CONNECTING)
|
||||||
|
|
||||||
|
|
||||||
def find_from_attr(attr_name, attr_value, list):
|
def find_from_attr(attr_name, attr_value, list):
|
||||||
@ -92,7 +92,7 @@ def get_state_str(state):
|
|||||||
state_str = 'OFFLINE'
|
state_str = 'OFFLINE'
|
||||||
elif state == STATE_QUITTING:
|
elif state == STATE_QUITTING:
|
||||||
state_str = 'QUITTING'
|
state_str = 'QUITTING'
|
||||||
elif state == STATE_LAUNCHING_SERVICES:
|
elif state == CONNECTING:
|
||||||
state_str = 'LAUNCHING SERVICES'
|
state_str = 'LAUNCHING SERVICES'
|
||||||
elif state == STATE_LOBBY:
|
elif state == STATE_LOBBY:
|
||||||
state_str = 'LOBBY'
|
state_str = 'LOBBY'
|
||||||
|
Reference in New Issue
Block a user