def diff(self, proxy: BpyPropDataCollectionProxy, collection_name: str, context: Context): self.items_added.clear() self.items_removed.clear() self.items_renamed.clear() proxy_items = {id_proxy.mixer_uuid(): id_proxy for id_proxy in proxy._data.values()} bl_collection = getattr(bpy.data, collection_name) blender_items = {} for name, item in bl_collection.items(): if skip_bpy_data_item(collection_name, item): continue uuid = item.mixer_uuid if uuid in blender_items.keys(): # duplicate uuid, from an object duplication original_item = blender_items[uuid] logger.info(f"Duplicate uuid {uuid} for {original_item[1]} and {item.name}...") logger.info("... assuming object was duplicated. Resetting (not an error)") # reset the uuid, ensure will regenerate item.mixer_uuid = "" ensure_uuid(item) if item.mixer_uuid in blender_items.keys(): logger.error(f"Duplicate uuid found for {item}") continue blender_items[item.mixer_uuid] = (name, collection_name) self.items_added, self.items_removed, self.items_renamed = find_renamed(proxy_items, blender_items) if not self.empty(): BlendData.instance().collection(collection_name).set_dirty()
def diff( self, proxy: DatablockCollectionProxy, collection_name: str, synchronized_properties: SynchronizedProperties ): self.items_added.clear() self.items_removed.clear() self.items_renamed.clear() proxy_items = {id_proxy.mixer_uuid(): id_proxy for id_proxy in proxy._data.values()} bl_collection = getattr(bpy.data, collection_name) blender_items = {} for name, item in bl_collection.items(): if skip_bpy_data_item(collection_name, item): continue uuid = item.mixer_uuid if uuid in blender_items.keys(): # duplicate uuid, from an object duplication duplicate_name, duplicate_collection_name = blender_items[uuid] logger.info( f"Duplicate uuid {uuid} in bpy.data.{duplicate_collection_name} for {duplicate_name} and bpy.data.{collection_name} for {name}..." ) logger.info("... assuming object was duplicated. Resetting (not an error)") # reset the uuid, ensure will regenerate item.mixer_uuid = "" ensure_uuid(item) if item.mixer_uuid in blender_items.keys(): logger.error(f"Duplicate uuid found for {item}") continue blender_items[item.mixer_uuid] = (name, collection_name) self.items_added, self.items_removed, self.items_renamed = find_renamed(proxy_items, blender_items)
def load(self, bl_collection: bpy.types.bpy_prop_collection, key: str, context: Context): # noqa N802 """ Load bl_collection elements as standalone datablocks. """ for name, item in bl_collection.items(): collection_name = BlendData.instance().bl_collection_name_from_ID( item) if skip_bpy_data_item(collection_name, item): continue uuid = ensure_uuid(item) self._data[uuid] = DatablockProxy().load( item, name, context, bpy_data_collection_name=collection_name) return self
def diff(self, proxy: DatablockCollectionProxy, collection_name: str, synchronized_properties: SynchronizedProperties): self._items_added.clear() self._items_removed.clear() self._items_renamed.clear() # Proxies for received image datablocks that failed to load because of a locally misconfigured shared folders do # not have a datablock (they have one when loading the .blend file). Do not consider the proxies without # datablock otherwise they would be found as deleted and removals would be sent to peers that may have # them. proxies = { datablock_proxy.mixer_uuid: datablock_proxy for datablock_proxy in proxy._data.values() if datablock_proxy.has_datablock } bl_collection = getattr(bpy.data, collection_name) # (item name, collection name) blender_items: Dict[Uuid, Tuple[T.ID, str]] = {} conflicts: List[T.ID] = [] for datablock in bl_collection.values(): if skip_bpy_data_item(collection_name, datablock): continue uuid = datablock.mixer_uuid if uuid in blender_items.keys(): conflicts.append(datablock) else: ensure_uuid(datablock) if datablock.mixer_uuid in blender_items.keys(): logger.error(f"Duplicate uuid found for {datablock}") continue blender_items[datablock.mixer_uuid] = (datablock, collection_name) for second_datablock in conflicts: first_datablock = blender_items[second_datablock.mixer_uuid][0] if first_datablock.library is None: if second_datablock.library is None: # local/local : assume second is the new conflicting, from a copy paste second_datablock.mixer_uuid = "" ensure_uuid(second_datablock) blender_items[second_datablock.mixer_uuid] = ( second_datablock, collection_name) else: # local/linked: first is made_local from linked second first_datablock.mixer_uuid = "" ensure_uuid(first_datablock) blender_items[first_datablock.mixer_uuid] = ( first_datablock, collection_name) else: if second_datablock.library is not None: # linked/local: breaks the assumption that local are listed before linked. Strange. # could do as local.linked if we were sure that is doe"s not have another weird cause logger.error( f"Unexpected link datablock {first_datablock} listed before local {second_datablock} ..." ) logger.error(f"... {second_datablock} ignored") else: # linked/linked: Conflicts between two linked. One of: # - a library contains uuids and is indirectly linked more than once # - a self link # Probably need to locally reset both uuids, keeping the link target uuid for direct link datablock logger.error( f"Linked datablock with duplicate uuids {first_datablock} {second_datablock}..." ) logger.error("... unsupported") proxy_uuids = set(proxies.keys()) blender_uuids = set(blender_items.keys()) # Ignore linked datablocks to find renamed datablocks, as they cannot be renamed locally renamed_uuids = { uuid for uuid in blender_uuids & proxy_uuids if not isinstance(proxies[uuid], DatablockLinkProxy) and proxies[uuid].data("name") != blender_items[uuid][0].name } added_uuids = blender_uuids - proxy_uuids - renamed_uuids removed_uuids = proxy_uuids - blender_uuids - renamed_uuids # this finds standalone datablock, link datablocks and override datablocks self._items_added = [(blender_items[uuid][0], blender_items[uuid][1]) for uuid in added_uuids] self._items_removed = [proxies[uuid] for uuid in removed_uuids] # TODO LIB self._items_renamed = [(proxies[uuid], blender_items[uuid][0].name) for uuid in renamed_uuids]
def diff(self, proxy: DatablockCollectionProxy, collection_name: str, synchronized_properties: SynchronizedProperties): self._items_added.clear() self._items_removed.clear() self._items_renamed.clear() # Proxies for received image datablocks that failed to load because of a locally misconfigured shared folders do # not have a datablock (they have one when loading the .blend file). Do not consider the proxies without # datablock otherwise they would be found as deleted and removals would be sent to peers that may have # them. proxies = { datablock_proxy.mixer_uuid: datablock_proxy for datablock_proxy in proxy._data.values() if datablock_proxy.has_datablock } bl_collection = getattr(bpy.data, collection_name) # (item name, collection name) blender_items: Dict[Uuid, Tuple[T.ID, str]] = {} for datablock in bl_collection.values(): if skip_bpy_data_item(collection_name, datablock): continue uuid = datablock.mixer_uuid if uuid in blender_items.keys(): # duplicate uuid, from an object duplication duplicate_name, duplicate_collection_name = blender_items[uuid] logger.info( f"Duplicate uuid {uuid} in bpy.data.{duplicate_collection_name} for {duplicate_name} and bpy.data.{collection_name} for {datablock.name_full!r}..." ) logger.info( f"... assuming object was duplicated. Resetting {datablock.name_full!r} (not an error)" ) # reset the uuid, ensure will regenerate datablock.mixer_uuid = "" ensure_uuid(datablock) if datablock.mixer_uuid in blender_items.keys(): logger.error(f"Duplicate uuid found for {datablock}") continue blender_items[datablock.mixer_uuid] = (datablock, collection_name) proxy_uuids = set(proxies.keys()) blender_uuids = set(blender_items.keys()) # Ignore linked datablocks to find renamed datablocks, as they cannot be renamed locally renamed_uuids = { uuid for uuid in blender_uuids & proxy_uuids if not isinstance(proxies[uuid], DatablockLinkProxy) and proxies[uuid].data("name") != blender_items[uuid][0].name } added_uuids = blender_uuids - proxy_uuids - renamed_uuids removed_uuids = proxy_uuids - blender_uuids - renamed_uuids # this finds standalone datablock, link datablocks and override datablocks self._items_added = [(blender_items[uuid][0], blender_items[uuid][1]) for uuid in added_uuids] self._items_removed = [proxies[uuid] for uuid in removed_uuids] # TODO LIB self._items_renamed = [(proxies[uuid], blender_items[uuid][0].name) for uuid in renamed_uuids]