3
$\begingroup$

I would like to set some rules before loading a date object, into the current project. But I don't really know how to do it and if it is possible to do it.

So I give an example:

I would like to import (Then load) an object, only if it has a material in at least bpy.data.objects['object_name'].data.materials[:]

Unfortunately I realized that the bpy.data.libraries.load() method may not do what I have in mind.

Below, I report what I tried to do (which obviously does not work) but forste explains better what I would like to do:

with bpy.data.libraries.load(my_path, link=False) as (data_from, data_to):
    objs_to_load=[]
    for obj in data_from.objects:
        if obj.data.materials[:]: # <--Incorrect example on purpose
            objs_to_load.append(obj)
        
    data_to.objects = objs_to_load

Clearly in the example above there is an error, I cannot read obj.data.materials, as it results in a string. The problem is that I don't want to import the object, as I don't want to fill the memory with useless objects for my purpose.

Anyone have any idea how to do it if it is possible?

$\endgroup$
4
  • 1
    $\begingroup$ Unfortunately it seems blendfile.py is the only option (reading the binary file directly). blender.stackexchange.com/a/109704/86891 I hope you're ready to learn a new language :) $\endgroup$
    – Gorgious
    May 30, 2022 at 19:01
  • $\begingroup$ The module is interesting, but there seems to be no documentation about it. So it turns out unusable, without in-depth knowledge $\endgroup$
    – Noob Cat
    Jun 1, 2022 at 12:45
  • $\begingroup$ Yeah that's what I meant in the last sentence... $\endgroup$
    – Gorgious
    Jun 1, 2022 at 13:17
  • $\begingroup$ I think the best option would be to "ask blender to run its garbage collection now", but searching around I don't see an obvious way to do that, the defecto option is to save-loading the project :( blender.stackexchange.com/a/75608/3038 $\endgroup$ Jun 5, 2022 at 23:37

1 Answer 1

4
+25
$\begingroup$

One obvious but inefficient way is to run a new Blender process in the background that opens the file and grabs whatever data you need. The data will need to be serialized by the background process, passed back to your script, then deserialized.

Afterwards you can use the data with libraries.load.

Here's a simple example:

import bpy
import subprocess

my_script = """
import bpy
print("$ BEGIN")
for ob in bpy.data.objects:
    if ob.material_slots:
        print("+", ob.name)
print("$ END")
"""

my_path = "Test.blend"

result = subprocess.run(
    [
        bpy.app.binary_path,
        "-b",
        my_path,
        "--python-exit-code", "1",
        "--python-expr",
        "exec(%s)" % repr(my_script),
    ],
    capture_output=True,
    check=True,
    text=True,
)

# Deserialize object names
lines = result.stdout.splitlines()
lines = lines[lines.index("$ BEGIN") + 1:lines.index("$ END")]
ob_names = [line.removeprefix("+ ") for line in lines]

print(ob_names)
$\endgroup$
3
  • $\begingroup$ Interesting, does it work on all operating systems? $\endgroup$
    – Noob Cat
    Jun 1, 2022 at 20:03
  • 1
    $\begingroup$ I don't know why it wouldn't (maybe text encoding?), but you'd have to try it. Tested on Linux here. $\endgroup$
    – scurest
    Jun 1, 2022 at 20:18
  • 1
    $\begingroup$ I've tested it on Windows 10, Everything seems to be fine, and it works great. It only remains to be tested on the Macintosh Which unfortunately I don't have on hand $\endgroup$
    – Noob Cat
    Jun 2, 2022 at 18:18

You must log in to answer this question.

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