Re-implementing C++ RNA PointerProperty in Python causes orphans

TL;DR: When implementing the removed Object.pose_library RNA property as a Python PointerProperty, why do .blends saved with the C++ version (2.93) of the property require re-linking actions when opened with the Python definition (4.x)?


Full context, the legacy Pose Library was removed in Blender 3.x to force users to migrate to the Asset Browser. The Asset system is not a suitable replacement for pose/animation workflows, it’s apples and oranges. Not enough people care or spoke up in time, I suppose.

I have years of old files and hundreds of poses keyed for the old system, converting them to Assets is not viable nor appealing for several reasons (several features/operators still missing, default Pose Asset thumbnail is hardcoded workbench render, no list view).

This year I ported each of the removed pose operators to Python, and set up a modern panel in the N menu. This works as intended, and should work for the foreseeable future (as long as Blender devs do not remove the bpy.types.ActionPoseMarkers data type). I very much intend to publish it on Github once finished.


The last issue I’m running into is one of the most crucial parts: the Object.pose_library PointerProperty used to reference the linked poselib Actions.

This registration is fine for new data/scenes saved with the new property, but old scenes drop their Actions to orphans when opened, and they must be re-linked (this can be dozens in one .blend across several separate scenes).

def register():
    bpy.types.Object.pose_library = bpy.props.PointerProperty(
        type=bpy.types.Action, 
        override={'LIBRARY_OVERRIDABLE'}, 
        )

Documentation and preceding examples are scarce here. I’m suspecting the issue is due to the C++ definition of pose_library possessing properties that do not to translate to Python, such as RNA_def_property_pointer_sdna and values like PROP_ID_REFCOUNT, or that I am missing another required parameter:


  prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
  RNA_def_property_pointer_sdna(prop, NULL, "poselib");
  RNA_def_property_struct_type(prop, "Action");
  RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
  RNA_def_property_ui_text(prop,
                           "Pose Library",
                           "Deprecated, will be removed in Blender 3.3. "
                           "Action used as a pose library for armatures");

To prevent data loss while I figure this out, i’ve set an operator to run on startup that will protect any orphaned Actions that have pose markers, but this is after it’s too late and the Actions are already orphaned. I don’t know if it can be caught early enough on startup, so the goal is to prevent this from happening.

It’s more an annoyance at the moment, but the add-on will not be complete without the ability to open files saved prior to 3.x with no manual re-linking. Does anyone have knowledge on these data structures in this context?

You might be lucky and someone can help you here.
Just in case you are not aware of it, there is Blender Chat (chat.blender.org). Many rooms are specifically for development, but there is also a “python” room where questions can be asked. As this is a fairly low level question, you might get lucky and one of the developers might see it and might be able to help.

Hello, why not open the files with version 2.93 and corresponding script, link the custom props there, then open the files in 4.0 ?

Hey hello!

Manually opening and saving the files with the custom property works (likely not in 2.93 though due to the RNA property present in same namespace), but the goal is to avoid remediating old files. With this route, I could use a script to iterate over my archive of .blends in order to convert this value offline rather than by hand, then the immediate problem is solved.

However, I wish to publish the add-on to the general public, without the need for manual linking or conversions to bring up old poses.


EDIT: The RNA docs are the only place I can see reference to the relation between core and plugin properties, and it seems like this will just not work, as Python props are not registered at runtime. I’d love to be proven wrong, but this may be the answer:

The RNA definitions are generated in a way similar to DNA preprocessing, in advance as part of the build system. Such a preprocessing step avoids manually writing much API code, taking advantage of the available information from the DNA system. Also it should avoid startup overhead since the result of the definitions would be baked into the source code. For python/plugin ID properties however this would still need to be done at runtime, though the code currently those not support that.

You can adapt your script for the API of 2.93, all the releases docs are archived. And then run your script headless on a 2.93 version doing a batch processing so you don’t have to manually open each file, update your proxy properties that you would define on a different namespace, then open it back on 4.0+ script and transfer these properties back to your actual re-created props.

Converting the property would indeed work, but again it’s not the intention. End users should ideally be able to enable this add-on and access their legacy poses in a new panel without any further steps or pre-conversions.

In my case, I will often open an old file to retrieve and copy an existing pose to clipboard buffer for another file, then close the older blend without saving. Many of these .blends are opened directly from a network archive (which extracts .blend to 7z temp location).

I also do not want to change the modified dates on these files as I reference these dates when looking for old data from certain time periods. This is least concern though as the attribute can be easily set back.

If manual remediation is required, then I would ditch the removed property and define a new property for the add-on to use. This could be as simple as:

  1. Iterate over range of .blends using headless operation with 2.93 (or up to 3.4).
  2. For any data in Object.pose_library, set new custom property using the linked poselib reference
  3. Wrap this in a routine to retain the file modified date.

However, I wonder if it’s not the “runtime” factor that I’m missing to properly re-implement the RNA property. I’m digging through anything I can to find how to set this attribute via Python, but I can only find people’s work in C:

RNA_def_property_pointer_sdna(prop, NULL, "poselib");