Beispiel #1
0
def pre_save_datablock(proxy: DatablockProxy, target: T.ID,
                       context: Context) -> T.ID:
    """Process attributes that must be saved first and return a possibly updated reference to the target"""

    # WARNING this is called from save() and from apply()
    # When called from save, the proxy has  all the synchronized properties
    # WHen called from apply, the proxy only contains the updated properties

    if isinstance(target, T.Mesh) and proxy_requires_clear_geometry(
            proxy, target):
        target.clear_geometry()
    elif isinstance(target, T.Material):
        use_nodes = proxy.data("use_nodes")
        if use_nodes:
            target.use_nodes = True

        is_grease_pencil = proxy.data("is_grease_pencil")
        # will be None for a DeltaUpdate that does not modify "is_grease_pencil"
        if is_grease_pencil is not None:
            # Seems to be write once as no depsgraph update is fired
            if is_grease_pencil and not target.grease_pencil:
                bpy.data.materials.create_gpencil_data(target)
            elif not is_grease_pencil and target.grease_pencil:
                bpy.data.materials.remove_gpencil_data(target)
    elif isinstance(target, T.Scene):
        from mixer.blender_data.misc_proxies import NonePtrProxy

        # Set 'use_node' to True first is the only way I know to be able to set the 'node_tree' attribute
        use_nodes = proxy.data("use_nodes")
        if use_nodes:
            target.use_nodes = True

        sequence_editor = proxy.data("sequence_editor")
        if sequence_editor is not None:
            # NonePtrProxy or StructProxy
            if not isinstance(sequence_editor,
                              NonePtrProxy) and target.sequence_editor is None:
                target.sequence_editor_create()
            elif isinstance(
                    sequence_editor,
                    NonePtrProxy) and target.sequence_editor is not None:
                target.sequence_editor_clear()
    elif isinstance(target, T.Light):
        # required first to have access to new light type attributes
        light_type = proxy.data("type")
        if light_type is not None and light_type != target.type:
            target.type = light_type
            # must reload the reference
            target = proxy.target(context)
    elif isinstance(target, T.World):
        use_nodes = proxy.data("use_nodes")
        if use_nodes:
            target.use_nodes = True

    return target
 def rename_datablock(self, proxy: DatablockProxy, new_name: str, datablock: T.ID):
     """
     Rename a bpy.data collection item and update the proxy state (receiver side)
     """
     logger.info("rename_datablock proxy %s datablock %r into %s", proxy, datablock, new_name)
     datablock.name = new_name
     proxy._data["name"] = new_name
Beispiel #3
0
def pre_save_datablock(proxy: DatablockProxy, target: T.ID,
                       context: Context) -> T.ID:
    """Process attributes that must be saved first and return a possibly updated reference to the target"""

    # WARNING this is called from save() and from apply()
    # When called from save, the proxy has  all the synchronized properties
    # WHen called from apply, the proxy only contains the updated properties

    if target.library:
        return target

    #  animation_data is handled in StructProxy (parent class of DatablockProxy)

    if isinstance(target, T.Mesh):
        from mixer.blender_data.mesh_proxy import MeshProxy

        assert isinstance(proxy, MeshProxy)
        if proxy.requires_clear_geometry(target):
            target.clear_geometry()
    elif isinstance(target, T.Material):
        is_grease_pencil = proxy.data("is_grease_pencil")
        # will be None for a DeltaUpdate that does not modify "is_grease_pencil"
        if is_grease_pencil is not None:
            # Seems to be write once as no depsgraph update is fired
            if is_grease_pencil and not target.grease_pencil:
                bpy.data.materials.create_gpencil_data(target)
            elif not is_grease_pencil and target.grease_pencil:
                bpy.data.materials.remove_gpencil_data(target)
    elif isinstance(target, T.Scene):
        from mixer.blender_data.misc_proxies import NonePtrProxy

        sequence_editor = proxy.data("sequence_editor")
        if sequence_editor is not None:
            # NonePtrProxy or StructProxy
            if not isinstance(sequence_editor,
                              NonePtrProxy) and target.sequence_editor is None:
                target.sequence_editor_create()
            elif isinstance(
                    sequence_editor,
                    NonePtrProxy) and target.sequence_editor is not None:
                target.sequence_editor_clear()
    elif isinstance(target, _morphable_types):
        # required first to have access to new datablock attributes
        type_ = proxy.data("type")
        if type_ is not None and type_ != target.type:
            target.type = type_
            # must reload the reference
            target = target.type_recast()
            uuid = proxy.mixer_uuid
            context.proxy_state.remove_datablock(uuid)
            context.proxy_state.add_datablock(uuid, target)
    elif isinstance(target, T.Action):
        groups = proxy.data("groups")
        if groups:
            groups.save(target.groups, target, "groups", context)

    return target
Beispiel #4
0
    def load(
        self,
        bl_instance: T.ID,
        key: str,
        context: Context,
        bpy_data_collection_name: str = None,
    ):
        """
        Load a datablock into this proxy
        """
        if bl_instance.is_embedded_data and bpy_data_collection_name is not None:
            logger.error(
                f"DatablockProxy.load() for {bl_instance} : is_embedded_data is True and bpy_prop_collection is {bpy_data_collection_name}. Item ignored"
            )
            return

        if bl_instance.is_embedded_data:
            self._bpy_data_collection = None

        if bpy_data_collection_name is not None:
            self._bpy_data_collection = bpy_data_collection_name

        self._class_name = bl_instance.__class__.__name__
        self._data.clear()
        properties = context.synchronized_properties.properties(bl_instance)
        # this assumes that specifics.py apply only to ID, not Struct
        properties = specifics.conditional_properties(bl_instance, properties)
        try:
            context.visit_state.datablock_proxy = self
            for name, bl_rna_property in properties:
                attr = getattr(bl_instance, name)
                attr_value = read_attribute(attr, name, bl_rna_property,
                                            context)
                # Also write None values to reset attributes like Camera.dof.focus_object
                # TODO for scene, test difference, only send update if dirty as continuous updates to scene
                # master collection will conflicting writes with Master Collection
                self._data[name] = attr_value
        finally:
            context.visit_state.datablock_proxy = None

        specifics.post_save_id(self, bl_instance)

        uuid = bl_instance.get("mixer_uuid")
        if uuid:
            # It is a bpy.data ID, not an ID "embedded" inside another ID, like scene.collection
            id_ = context.proxy_state.datablocks.get(uuid)
            if id_ is not bl_instance:
                # this occurs when
                # - when we find a reference to a BlendData ID that was not loaded
                # - the ID are not properly ordred at creation time, for instance (objects, meshes)
                # instead of (meshes, objects) : a bug
                logger.debug(
                    "DatablockProxy.load(): %s not in context.proxy_state.datablocks[uuid]",
                    bl_instance)
            self._datablock_uuid = bl_instance.mixer_uuid
            context.proxy_state.proxies[uuid] = self

        self.attach_media_descriptor(bl_instance)
        return self
Beispiel #5
0
 def rename_datablock(self, proxy: DatablockProxy, new_name: str,
                      datablock: T.ID):
     """
     Rename a bpy.data collection item and update the proxy state
     """
     logger.info("rename_datablock proxy %s datablock %s into %s", proxy,
                 datablock, new_name)
     proxy.rename(new_name)
     datablock.name = new_name
Beispiel #6
0
    def load(self, datablock: T.ID):
        """Load the custom properties of datablock, skipping API defined properties"""
        keys, rna_ui = self._user_keys(datablock)
        # This only load custom properties with a UI
        if rna_ui is None:
            self._dict.clear()
            self._rna_ui.clear()
            return self

        self._rna_ui = rna_ui.to_dict()
        self._dict = {name: datablock.get(name) for name in keys}
Beispiel #7
0
def pre_save_id(proxy: Proxy, target: T.ID) -> T.ID:
    """Process attributes that must be saved first and return a possibly updated reference to the target

    Args:
        bpy_struct: The collection that contgains the ID
        attr_name: Its key

    Returns:
        [bpy.types.ID]: a possibly new ID
    """
    if isinstance(target, T.Scene):
        # Set 'use_node' to True first is the only way I know to be able to set the 'node_tree' attribute
        use_nodes = proxy.data("use_nodes")
        if use_nodes:
            target.use_nodes = True
        sequence_editor = proxy.data("sequence_editor")
        if sequence_editor is not None and target.sequence_editor is None:
            target.sequence_editor_create()
    elif isinstance(target, T.Light):
        # required first to have access to new light type attributes
        light_type = proxy.data("type")
        if light_type is not None and light_type != target.type:
            target.type = light_type
            # must reload the reference
            target = proxy.target()
    elif isinstance(target, T.ColorManagedViewSettings):
        use_curve_mapping = proxy.data("use_curve_mapping")
        if use_curve_mapping:
            target.use_curve_mapping = True
    elif isinstance(target, bpy.types.World):
        use_nodes = proxy.data("use_nodes")
        if use_nodes:
            target.use_nodes = True
    return target
Beispiel #8
0
 def _user_keys(self, datablock: T.ID):
     keys = set(datablock.keys())
     rna_ui = datablock.get("_RNA_UI", None)
     keys -= {"_RNA_UI"}
     keys -= set(datablock.bl_rna.properties.keys())
     return keys, rna_ui