From dd286f93eb896b60ceeac556c7524b2e982aa207 Mon Sep 17 00:00:00 2001 From: Philippe Crassous Date: Wed, 28 Apr 2021 20:31:49 +0200 Subject: [PATCH] fix: tag for update after updating an array - after receiving a strokes update, the receiver display was not updated until edit mode was entered --- mixer/blender_client/data.py | 16 ++++++++++++++-- mixer/blender_data/bpy_data_proxy.py | 11 ++++++++--- mixer/blender_data/datablock_proxy.py | 13 ++++++++++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/mixer/blender_client/data.py b/mixer/blender_client/data.py index ff1d546a..fbd34597 100644 --- a/mixer/blender_client/data.py +++ b/mixer/blender_client/data.py @@ -25,6 +25,8 @@ import traceback from typing import List, TYPE_CHECKING +import bpy + from mixer.blender_data.json_codec import Codec, DecodeError, EncodeError from mixer.blender_data.messages import ( BlenderDataMessage, @@ -145,14 +147,24 @@ def build_data_create(buffer): def _build_soas(uuid: Uuid, soas: List[Soa]): + update = False try: for soa in soas: - share_data.bpy_data_proxy.update_soa(uuid, soa.path, soa.members) + update |= share_data.bpy_data_proxy.update_soa(uuid, soa.path, soa.members) except Exception: + # Partial update of arrays may cause data length mismatch between array elements (co, normals, ...) logger.error(f"Exception during update_soa for {uuid} {soa.path}") + logger.error(" ------- This may cause a Blender crash ---------") for line in traceback.format_exc().splitlines(): logger.error(line) - logger.error("ignored") + + if update: + # TODO this is skipped if the proxy update call is retained until returning into OBJECT mode + try: + # needed for Grease Pencil. + bpy.context.view_layer.update() + except Exception: + pass def build_data_update(buffer: bytes): diff --git a/mixer/blender_data/bpy_data_proxy.py b/mixer/blender_data/bpy_data_proxy.py index 90034054..be15f290 100644 --- a/mixer/blender_data/bpy_data_proxy.py +++ b/mixer/blender_data/bpy_data_proxy.py @@ -630,11 +630,16 @@ def diff(self, synchronized_properties: SynchronizedProperties) -> Optional[BpyD return diff return None - @retain(None) - def update_soa(self, uuid: Uuid, path: Path, soa_members: List[SoaMember]): + @retain(False) + def update_soa(self, uuid: Uuid, path: Path, soa_members: List[SoaMember]) -> bool: + """Update the arrays if the proxy identified by uuid. + + Returns: + True if the view layer should be updated + """ datablock_proxy = self.state.proxies[uuid] datablock = self.state.datablock(uuid) - datablock_proxy.update_soa(datablock, path, soa_members) + return datablock_proxy.update_soa(datablock, path, soa_members) def append_delayed_updates(self, delayed_updates: Set[T.ID]): self._delayed_local_updates |= {update.mixer_uuid for update in delayed_updates} diff --git a/mixer/blender_data/datablock_proxy.py b/mixer/blender_data/datablock_proxy.py index 232cd39b..6b1bf536 100644 --- a/mixer/blender_data/datablock_proxy.py +++ b/mixer/blender_data/datablock_proxy.py @@ -519,22 +519,29 @@ def apply_to_proxy( collection = getattr(bpy.data, self.collection_name) self.apply(attribute, collection, attribute.name, delta, context, to_blender=False) - def update_soa(self, bl_item, path: Path, soa_members: List[SoaMember]): + def update_soa(self, bl_item, path: Path, soa_members: List[SoaMember]) -> bool: r = self.find_by_path(bl_item, path) if r is None: logger.error(f"update_soa: {path} not found in {bl_item}") - return + return False container, container_proxy = r for soa_member in soa_members: soa_proxy = container_proxy.data(soa_member[0]) soa_proxy.save_array(container, soa_member[0], soa_member[1]) - # HACK force updates : + # HACK force updates : unsure what is strictly required + # specifying refresh is not compatible with Grease Pencil and causes a crash + update = False if isinstance(bl_item, T.Mesh): bl_item.update() elif isinstance(bl_item, T.Curve): bl_item.twist_mode = bl_item.twist_mode + elif isinstance(bl_item, T.GreasePencil): + bl_item.update_tag() + update = True + + return update def diff(self, attribute: T.ID, key: Union[int, str], prop: T.Property, context: Context) -> Optional[Delta]: """