def test_exact_class(self): filter_stack = FilterStack() filter_set = {T.Scene: [TypeFilterOut(T.SceneEEVEE)]} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties(filter_stack, property_order) props = synchronized_properties.properties(T.Mesh) self.assertFalse(any([matches_type(p, T.SceneEEVEE) for _, p in props]))
def test_exact_class(self): filter_stack = FilterStack() filter_set = {T.BlendData: [TypeFilterIn(T.CollectionProperty)]} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties(filter_stack, property_order) props = list(synchronized_properties.properties(T.BlendData)) self.assertTrue(any([matches_type(p, T.BlendDataCameras) for _, p in props])) self.assertFalse(any([matches_type(p, T.StringProperty) for _, p in props]))
def test_exact_class(self): filter_stack = FilterStack() filter_set = {T.Mesh: CollectionFilterOut(T.MeshVertices)} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties(filter_stack) props = synchronized_properties.properties(T.Mesh) self.assertFalse( any([matches_type(p, T.MeshVertices) for _, p in props])) self.assertTrue(any([matches_type(p, T.MeshLoops) for _, p in props]))
def test_unrelated_class(self): filter_stack = FilterStack() # Exclude on unrelated class : does nothing filter_set = {T.Collection: CollectionFilterOut(T.MeshVertices)} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties(filter_stack) props = synchronized_properties.properties(T.Mesh) self.assertTrue( any([matches_type(p, T.MeshVertices) for _, p in props])) self.assertTrue(any([matches_type(p, T.MeshLoops) for _, p in props]))
def test_base_class(self): filter_stack = FilterStack() # Exclude on ID, applies to derived classes filter_set = {T.ID: CollectionFilterOut(T.MeshVertices)} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties(filter_stack) props = synchronized_properties.properties(T.Mesh) self.assertFalse( any([matches_type(p, T.MeshVertices) for _, p in props])) self.assertTrue(any([matches_type(p, T.MeshLoops) for _, p in props]))
def test_root_class(self): filter_stack = FilterStack() # Exclude on all classes filter_set = {None: [CollectionFilterOut(T.MeshVertices)]} filter_stack.append(filter_set) synchronized_properties = SynchronizedProperties( filter_stack, property_order) props = synchronized_properties.properties(T.Mesh) self.assertFalse( any([matches_type(p, T.MeshVertices) for _, p in props])) self.assertTrue(any([matches_type(p, T.MeshLoops) for _, p in props]))
def test_blenddata_filtered(self): blend_data = self.proxy._data scene = blend_data["scenes"].search_one("Scene_0")._data self.assertTrue("eevee" in scene) filter_stack = copy.copy(test_filter) filter_stack.append({T.Scene: [TypeFilterOut(T.SceneEEVEE)]}) proxy = BpyDataProxy() proxy.load(SynchronizedProperties(filter_stack, property_order)) blend_data_ = proxy._data scene_ = blend_data_["scenes"].search_one("Scene_0")._data self.assertFalse("eevee" in scene_)
def load(self, synchronized_properties: SynchronizedProperties): """Load the current scene into this proxy Only used for test. The initial load is performed by update() """ self.initialize_ref_targets(synchronized_properties) context = self.context(synchronized_properties) for name, _ in synchronized_properties.properties( bpy_type=T.BlendData): collection = getattr(bpy.data, name) self._data[name] = DatablockCollectionProxy(name).load( collection, name, context) return self
def diff(self, blend_proxy: BpyDataProxy, synchronized_properties: SynchronizedProperties): self.collection_deltas.clear() self.id_deltas.clear() for collection_name, _ in synchronized_properties.properties(bpy_type=T.BlendData): if collection_name not in blend_proxy._data: continue delta = BpyPropCollectionDiff() delta.diff(blend_proxy._data[collection_name], collection_name, synchronized_properties) if not delta.empty(): self.collection_deltas.append((collection_name, delta)) # Before this change: # Only datablocks handled by the generic synchronization system get a uuid, either from # BpyDataProxy.initialize_ref_targets() during room creation, or later during diff processing. # Datablocks of unhandled types get no uuid and DatablockRefProxy references to them are incorrect. # What is more, this means trouble for tests since datablocks of unhandled types are assigned # a uuid during the message grabbing, which means that they get different uuids on both ends. for collection_name in synchronized_properties.unhandled_bpy_data_collection_names: collection = getattr(bpy.data, collection_name) for datablock in collection.values(): ensure_uuid(datablock)
def initialize_ref_targets( self, synchronized_properties: SynchronizedProperties): """Keep track of all bpy.data items so that loading recognizes references to them Call this before updating the proxy from send_scene_content. It is not needed on the receiver side. TODO check is this is actually required or if we can rely upon is_embedded_data being False """ # Normal operation no more involve BpyDataProxy.load() ad initial synchronization behaves # like a creation. The current load_as_what() implementation relies on root_ids to determine if # a T.ID must ne loaded as an IDRef (pointer to bpy.data) or an IDDef (pointer to an "owned" ID). # so we need to load all the root_ids before loading anything into the proxy. # However, root_ids may no more be required if we can load all the proxies inside out (deepmost first, i.e # (Mesh, Metaball, ..), then Object, the Scene). This should be possible as as we sort # the updates inside out in update() to the receiver gets them in order for name, _ in synchronized_properties.properties( bpy_type=T.BlendData): if name in collection_name_to_type: # TODO use BlendData bl_collection = getattr(bpy.data, name) for _id_name, item in bl_collection.items(): uuid = ensure_uuid(item) self.state.datablocks[uuid] = item