2
$\begingroup$

I'm going to keep this one more focused than my last question:

Appending scripts and materials from a .blend file in an addon used to look like this:

USER  = pathlib.Path(bpy.utils.resource_path('USER'))
ADDONS = USER / 'addons'
MYADDON = ADDONS / 'DIPSS'
SKIN = "Skin.blend"
srcPath = USER / "scripts/addons" / ADDONS / "assets" / SKIN
srcFile = str(MYADDON)

class WM_OT_Main(Operator):
    bl_label = "Load Procedural Systems"
    bl_idname = "wm.load_main"

    def execute(self, context):
        if not bpy.data.materials.get("Skin"): 
            bpy.ops.wm.append(
            filepath="Skin.blend",
            directory= srcFile / skinmat,
            filename="Skin",
            set_fake=True)

And now I'm trying to make it work in Blender 4, and I'm not sure why the following:

import bpy
import sys
import pathlib

from bpy.utils import resource_path
from pathlib import Path

#Assorted functions for other parts of the script#

from bpy import context


USER = pathlib.Path(bpy.utils.resource_path('USER'))
srcFile = (USER/"scripts/addons/DIPSS/assets/Skin.blend")

skinmat = "\\Material\\"
skinscript = "\\Text\\"

class WM_OT_Main(Operator):
    bl_label = "Load Procedural Systems"
    bl_idname = "wm.load_main"

with bpy.data.libraries.load(srcFile) as (data_from, data_to):
            for attr in dir(data_to):
                setattr(data_to, attr, getattr(data_from, attr))
            
        if not bpy.data.materials.get("Fingernails"):
            with bpy.data.libraries.load(srcFile) as (data_from, data_to):
                data_to.material = data_from.material

Gets this error message: TypeError: bad argument type for built-in operation

I've been trying different approaches from these pages:

Regarding data libraries

regarding materials and appending

Not having much luck, hoping somebody can make sense of it for me.

Update

I found this answer to a similar question, and tried the following:

if not bpy.data.materials.get("Fingernails"):
            with bpy.data.libraries.load(srcFile, link=False) as (data_src, data_dst):
                data_dst.materials = ["Fingernails"]
                mat = data_dst.materials[0]
                mat.name = "Fingernails"

Same error, so the problem must be in how I'm trying to lay out the path right?

Update again

Following tangentially related questions I have come up with a new thing to try, and a new error, which is exciting.

USER = pathlib.Path(bpy.utils.resource_path('USER'))
ADDONS = USER / 'addons'
srcFile = ADDONS / 'DIPSS'
skinmat = "\\Material\\"
skinscript = "\\Text\\"

class WM_OT_Main(Operator):
    bl_label = "Load Procedural Systems"
    bl_idname = "wm.load_main"
    
    
    def execute(self, context):            
            
        if not bpy.data.materials.get("Fingernails"): 
            bpy.ops.wm.append (str(
            srcFile / skinmat / "Fingernails"))
            set_fake=True

Gives me this error: TypeError: Calling operator "bpy.ops.wm.append" error, expected a string enum in ('INVOKE_DEFAULT', 'INVOKE_REGION_WIN', 'INVOKE_REGION_CHANNELS', 'INVOKE_REGION_PREVIEW', 'INVOKE_AREA', 'INVOKE_SCREEN', 'EXEC_DEFAULT', 'EXEC_REGION_WIN', 'EXEC_REGION_CHANNELS', 'EXEC_REGION_PREVIEW', 'EXEC_AREA', 'EXEC_SCREEN')

If I try it without str is just goes back to raise ValueError("1-2 args execution context is supported") again.

Trying more new things, compressing the code section and now I'm getting this:

__init__.py", line 92
    bpy.ops.wm.append(filepath = "Skin.blend", srcFile / skinmat/ "Fingernails")
                                                                               ^
SyntaxError: positional argument follows keyword argument

If I do it without the () it just does nothing and skips to the next section, which I haven't been working on because there are several I'll have to change.

$\endgroup$

1 Answer 1

1
$\begingroup$

I finally figured it out, though the solution wasn't obvious and I had to draw it from several sources.

USER = pathlib.Path(bpy.utils.resource_path('USER'))
ADDONS = USER / 'addons'
srcPath = ADDONS / 'DIPSS' / 'assets' / 'Skin.blend'
srcFile = str(srcPath)
skinmat = "\\Material\\"
skinscript = "\\Text\\"

# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class WM_OT_Main(Operator):
    bl_label = "Load Procedural Systems"
    bl_idname = "wm.load_main"
    
    
    def execute(self, context):
        if not bpy.data.materials.get("Skin"): 
            with bpy.data.libraries.load(srcFile) as (data_from, data_to):
                for attr in dir(data_to):
                    setattr(data_to, attr, getattr(data_from, attr))
            
        override = context.copy()
        override["edit_text"] =  bpy.data.texts['menu_script.py']
        with context.temp_override(**override):
            bpy.ops.text.run_script()
            
        return {'FINISHED'}

Not only does this work, it appends all the materials and scripts at once, which is very efficient.

There are some functions missing: The old script used to check for the presence of the files before appending them, to avoid duplicates, and it used to assign a fake user to all the materials to prevent them being lost.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .