Merge branch '158-exception-access-violation-during-undo-redo' into '132-fix-undo-edit-last-operation-redo-handling-2'
Resolve "Exception access violation during Undo/Redo" See merge request slumber/multi-user!92
This commit is contained in:
@ -44,7 +44,7 @@ from . import environment
|
|||||||
|
|
||||||
|
|
||||||
DEPENDENCIES = {
|
DEPENDENCIES = {
|
||||||
("replication", '0.1.19'),
|
("replication", '0.1.20'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,16 +137,19 @@ class BlDatablock(ReplicatedDatablock):
|
|||||||
def resolve(self, construct = True):
|
def resolve(self, construct = True):
|
||||||
datablock_ref = None
|
datablock_ref = None
|
||||||
datablock_root = getattr(bpy.data, self.bl_id)
|
datablock_root = getattr(bpy.data, self.bl_id)
|
||||||
datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root)
|
|
||||||
|
try:
|
||||||
|
datablock_ref = datablock_root[self.data['name']]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if not datablock_ref:
|
if not datablock_ref:
|
||||||
try:
|
datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root)
|
||||||
datablock_ref = datablock_root[self.data['name']]
|
|
||||||
except Exception:
|
if construct and not datablock_ref:
|
||||||
if construct:
|
name = self.data.get('name')
|
||||||
name = self.data.get('name')
|
logging.debug(f"Constructing {name}")
|
||||||
logging.debug(f"Constructing {name}")
|
datablock_ref = self._construct(data=self.data)
|
||||||
datablock_ref = self._construct(data=self.data)
|
|
||||||
|
|
||||||
if datablock_ref is not None:
|
if datablock_ref is not None:
|
||||||
setattr(datablock_ref, 'uuid', self.uuid)
|
setattr(datablock_ref, 'uuid', self.uuid)
|
||||||
|
@ -45,7 +45,7 @@ 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 ReplicatedDataFactory
|
||||||
from replication.exception import NonAuthorizedOperationError
|
from replication.exception import NonAuthorizedOperationError, ContextError
|
||||||
from replication.interface import session
|
from replication.interface import session
|
||||||
|
|
||||||
from . import bl_types, environment, timers, ui, utils
|
from . import bl_types, environment, timers, ui, utils
|
||||||
@ -93,8 +93,7 @@ def initialize_session():
|
|||||||
for d in deleyables:
|
for d in deleyables:
|
||||||
d.register()
|
d.register()
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
bpy.app.handlers.depsgraph_update_post.append(depsgraph_evaluation)
|
||||||
bpy.app.handlers.depsgraph_update_post.append(depsgraph_evaluation)
|
|
||||||
|
|
||||||
bpy.ops.session.apply_armature_operator('INVOKE_DEFAULT')
|
bpy.ops.session.apply_armature_operator('INVOKE_DEFAULT')
|
||||||
|
|
||||||
@ -119,9 +118,7 @@ def on_connection_end(reason="none"):
|
|||||||
|
|
||||||
stop_modal_executor = True
|
stop_modal_executor = True
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
bpy.app.handlers.depsgraph_update_post.remove(depsgraph_evaluation)
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(
|
|
||||||
depsgraph_evaluation)
|
|
||||||
|
|
||||||
# Step 3: remove file handled
|
# Step 3: remove file handled
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
@ -151,7 +148,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
runtime_settings = context.window_manager.session
|
runtime_settings = context.window_manager.session
|
||||||
users = bpy.data.window_managers['WinMan'].online_users
|
users = bpy.data.window_managers['WinMan'].online_users
|
||||||
admin_pass = runtime_settings.password
|
admin_pass = runtime_settings.password
|
||||||
use_extern_update = settings.update_method == 'DEPSGRAPH'
|
|
||||||
users.clear()
|
users.clear()
|
||||||
deleyables.clear()
|
deleyables.clear()
|
||||||
|
|
||||||
@ -203,12 +200,11 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
automatic=type_local_config.auto_push,
|
automatic=type_local_config.auto_push,
|
||||||
check_common=type_module_class.bl_check_common)
|
check_common=type_module_class.bl_check_common)
|
||||||
|
|
||||||
if settings.update_method == 'DEFAULT':
|
if type_local_config.bl_delay_apply > 0:
|
||||||
if type_local_config.bl_delay_apply > 0:
|
deleyables.append(
|
||||||
deleyables.append(
|
timers.ApplyTimer(
|
||||||
timers.ApplyTimer(
|
timeout=type_local_config.bl_delay_apply,
|
||||||
timeout=type_local_config.bl_delay_apply,
|
target_type=type_module_class))
|
||||||
target_type=type_module_class))
|
|
||||||
|
|
||||||
if bpy.app.version[1] >= 91:
|
if bpy.app.version[1] >= 91:
|
||||||
python_binary_path = sys.executable
|
python_binary_path = sys.executable
|
||||||
@ -218,11 +214,7 @@ class SessionStartOperator(bpy.types.Operator):
|
|||||||
session.configure(
|
session.configure(
|
||||||
factory=bpy_factory,
|
factory=bpy_factory,
|
||||||
python_path=python_binary_path,
|
python_path=python_binary_path,
|
||||||
external_update_handling=use_extern_update)
|
external_update_handling=True)
|
||||||
|
|
||||||
if settings.update_method == 'DEPSGRAPH':
|
|
||||||
deleyables.append(timers.ApplyTimer(
|
|
||||||
settings.depsgraph_update_rate/1000))
|
|
||||||
|
|
||||||
# Host a session
|
# Host a session
|
||||||
if self.host:
|
if self.host:
|
||||||
@ -929,13 +921,14 @@ def sanitize_deps_graph(dummy):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
if session and session.state['STATE'] == STATE_ACTIVE:
|
if session and session.state['STATE'] == STATE_ACTIVE:
|
||||||
session.lock_operations()
|
# pass
|
||||||
|
# session.lock_operations()
|
||||||
|
start = utils.current_milli_time()
|
||||||
for node_key in session.list():
|
for node_key in session.list():
|
||||||
node = session.get(node_key)
|
node = session.get(node_key)
|
||||||
node.resolve(construct=False)
|
node.resolve(construct=False)
|
||||||
|
logging.debug(f"Sanitize took { utils.current_milli_time()-start}ms")
|
||||||
session.unlock_operations()
|
# session.unlock_operations()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -979,7 +972,19 @@ def depsgraph_evaluation(scene):
|
|||||||
not settings.sync_flags.sync_during_editmode:
|
not settings.sync_flags.sync_during_editmode:
|
||||||
break
|
break
|
||||||
|
|
||||||
session.stash(node.uuid)
|
# session.stash(node.uuid)
|
||||||
|
if node.has_changed():
|
||||||
|
try:
|
||||||
|
session.commit(node.uuid)
|
||||||
|
session.push(node.uuid)
|
||||||
|
except ReferenceError:
|
||||||
|
logging.debug(f"Reference error {node.uuid}")
|
||||||
|
if not node.is_valid():
|
||||||
|
session.remove(node.uuid)
|
||||||
|
except ContextError as e:
|
||||||
|
logging.debug(e)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
else:
|
else:
|
||||||
# Distant update
|
# Distant update
|
||||||
continue
|
continue
|
||||||
|
@ -199,15 +199,6 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
description='connection timeout before disconnection',
|
description='connection timeout before disconnection',
|
||||||
default=1000
|
default=1000
|
||||||
)
|
)
|
||||||
update_method: bpy.props.EnumProperty(
|
|
||||||
name='update method',
|
|
||||||
description='replication update method',
|
|
||||||
items=[
|
|
||||||
('DEFAULT', "Default", "Default: Use threads to monitor databloc changes"),
|
|
||||||
('DEPSGRAPH', "Depsgraph",
|
|
||||||
"Experimental: Use the blender dependency graph to trigger updates"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
# Replication update settings
|
# Replication update settings
|
||||||
depsgraph_update_rate: bpy.props.IntProperty(
|
depsgraph_update_rate: bpy.props.IntProperty(
|
||||||
name='depsgraph update rate',
|
name='depsgraph update rate',
|
||||||
@ -390,9 +381,6 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
|||||||
row = box.row()
|
row = box.row()
|
||||||
row.label(text="Init the session from:")
|
row.label(text="Init the session from:")
|
||||||
row.prop(self, "init_method", text="")
|
row.prop(self, "init_method", text="")
|
||||||
row = box.row()
|
|
||||||
row.label(text="Update method:")
|
|
||||||
row.prop(self, "update_method", text="")
|
|
||||||
|
|
||||||
table = box.box()
|
table = box.box()
|
||||||
table.row().prop(
|
table.row().prop(
|
||||||
|
@ -269,7 +269,6 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
|
|||||||
if settings.sidebar_advanced_rep_expanded:
|
if settings.sidebar_advanced_rep_expanded:
|
||||||
replication_section_row = replication_section.row()
|
replication_section_row = replication_section.row()
|
||||||
|
|
||||||
replication_section_row.label(text="Sync flags", icon='COLLECTION_NEW')
|
|
||||||
replication_section_row = replication_section.row()
|
replication_section_row = replication_section.row()
|
||||||
replication_section_row.prop(settings.sync_flags, "sync_render_settings")
|
replication_section_row.prop(settings.sync_flags, "sync_render_settings")
|
||||||
replication_section_row = replication_section.row()
|
replication_section_row = replication_section.row()
|
||||||
@ -283,33 +282,6 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
|
|||||||
warning.label(text="Don't use this with heavy meshes !", icon='ERROR')
|
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:
|
|
||||||
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="")
|
|
||||||
|
|
||||||
cache_section = layout.row().box()
|
cache_section = layout.row().box()
|
||||||
cache_section.prop(
|
cache_section.prop(
|
||||||
|
Reference in New Issue
Block a user