I’ve been working on a script that can automatically execute scripts attached to imported assets (while respecting and enforcing Blender’s script & security policy).
The goal is an add-on / extension that patches the drudgery and insecurity of Blender’s current import system when dealing with assets rigged with scripted powers.
I want it to work with Blender 3.0+. Most of my work has been using 4.5 (for nothing more than convenience) but I have been testing regularly against 3.0, 3.5, 5.0, and 5.2 as well.
There is a weirdness I need help understanding, though.
Attached TEXT data-blocks, when first imported, have two users in 5.0+, not one!
The following script can be used to see this yourself.
❶ Open Blender with the System Console available (not the Python Console in Blender)
❷ Paste and run the following script in the Text Editor:
import bpy
from bpy.app.handlers import persistent
@persistent
def import_handler(import_context):
for item in import_context.import_items:
if item.id_type in ('COLLECTION', 'ARMATURE', 'TEXT'):
print("{:2d} {}".format(item.id.users, item.id.name_full))
def register():
bpy.app.handlers.blend_import_post.append(import_handler)
if __name__ == "__main__":
register()
❸ Open your Asset Browser and drop in any asset with an attached script (commonly found on character rigs — anything you’ve set up with Rigify will do).
I assume I am talking to the choir here, but just in case: If you do not have your Asset Browser set-up then any other import method will also do: File > Append, File > Link, drag & drop, etc.
❹ Check your System Console output. The collection and the armature (and most everything else that I’ve filtered out) will have a user count of 1.
But the rig_ui.py (or whatever text block attached to your data) will have:
- (Blender < 5.0) user count ==
1(which is expected) - (Blender ≥ 5.0) user count ==
2(like, wut!?)
The result holds regardless of the Import Method.
❺ What is this extra user?
(Now in the Python Console in Blender) we find that in 5.0+ the data-block is used twice by the same object:
>>> bpy.data.user_map()[bpy.data.texts["rig_ui.py"]]
{bpy.data.objects['Armature'], bpy.data.objects['Armature']}
>>> |
Further exploration in the Outliner shows that the library links to a magic copy of the source blendfile in the asset library. Here I used the Flick model as an asset.
What is magic about it is that “Flick 2.1-asset.blend.001” does not exist anywhere I can find it, and I do not know why it exists at all.
Please explain this to me
I cannot find anything about it online, and I am really hoping I won’t have to try to chase this down in Blender’s source code.
Secondary question (for the tl;dr response)
Is it reasonable that I continue checking the number of users at import to see if this is the first import, only now just checking for users ≤ 2 when bpy.app.version ≥ (5,0,0)?
Or do I need to start handling blend_import_pre and cataloguing everything that exists prior to import so that I can perform a diff after?
