Custom Properties within PropertyGroups cannot be animated when attached to a PoseBone #48975

Open
opened 2016-07-29 23:08:59 +02:00 by sn0w75-4 · 25 comments

System Information
Ubuntu Linux 14.04 (64-bit)
NVIDIA GTX 960 (NVIDIA Driver Version 367.35)

Blender Version
Broken: 2.77a abf6f08
Worked: N/A

I've found that custom properties stored within PropertyGroups and/or CollectionPropertys cannot actually be animated if they are associated with a PoseBone (Error returned when inserting keyframe is "Failed to resolve path to property, try manually specifying this using a Keying Set instead"). (If the exact same custom properties are associated with an Object, they can be animated by inserting keyframes normally.)

It's possible that I'm mistaken and it is possible to manually specify the property within a CollectionProperty/PropertyGroup using a Keying Set in a more straightforward manner (or at all), but to manually add a Keying Set for every potential instance of a property within a CollectionProperty for every PoseBone that uses the custom properties is an unrealistic for any use case involving a CollectionProperty (and honestly I'm doubtful whether this is even possible, I was unable to successfully create a Keying Set for keyframing a property within a CollectionProperty/PropertyGroup, getting error 'Keying set failed to insert any key frames', although I can't deny the possibility I got the path to the property wrong somehow).

Exact steps for others to reproduce the error

  1. Open the provided .blend file
  2. Install/Enable the provided add-on
  3. Select a bone in the armature in pose mode.
  4. Go to the Bone panel. At the bottom, you'll see a new section called 'Custom Properties Bug'.
  5. Try to insert a keyframe for 'Animatable PropGroup Property'. It will fail.
  6. Click the 'Add Collection Item' button to add an item to a CollectionProperty.
  7. Try to insert a keyframe for 'Animatable Collection Property' (a property within the Item you just added to a collection associated with the PoseBone). It will fail.

bug_report.zip

**System Information** Ubuntu Linux 14.04 (64-bit) NVIDIA GTX 960 (NVIDIA Driver Version 367.35) **Blender Version** Broken: 2.77a abf6f08 Worked: N/A I've found that custom properties stored within PropertyGroups and/or CollectionPropertys cannot actually be animated if they are associated with a PoseBone (Error returned when inserting keyframe is "Failed to resolve path to property, try manually specifying this using a Keying Set instead"). (If the exact same custom properties are associated with an Object, they can be animated by inserting keyframes normally.) It's possible that I'm mistaken and it is possible to manually specify the property within a CollectionProperty/PropertyGroup using a Keying Set in a more straightforward manner (or at all), but to manually add a Keying Set for every potential instance of a property within a CollectionProperty for every PoseBone that uses the custom properties is an unrealistic for any use case involving a CollectionProperty (and honestly I'm doubtful whether this is even possible, I was unable to successfully create a Keying Set for keyframing a property within a CollectionProperty/PropertyGroup, getting error 'Keying set failed to insert any key frames', although I can't deny the possibility I got the path to the property wrong somehow). **Exact steps for others to reproduce the error** 1. Open the provided .blend file 2. Install/Enable the provided add-on 3. Select a bone in the armature in pose mode. 4. Go to the Bone panel. At the bottom, you'll see a new section called 'Custom Properties Bug'. 5. Try to insert a keyframe for 'Animatable PropGroup Property'. It will fail. 6. Click the 'Add Collection Item' button to add an item to a CollectionProperty. 7. Try to insert a keyframe for 'Animatable Collection Property' (a property within the Item you just added to a collection associated with the PoseBone). It will fail. [bug_report.zip](https://archive.blender.org/developer/F329792/bug_report.zip)
Author

Changed status to: 'Open'

Changed status to: 'Open'
Author

Added subscriber: @sn0w75-4

Added subscriber: @sn0w75-4
Author

I've added a second .zip (bug_report_2.zip) that contains a revised version of the add-on used for showcasing the bug that adds a section under the Object panel so you try setting keyframes for custom properties within PropertyGroup/CollectionPropertys of Objects as well as PoseBones (it works for Objects, but not for PoseBones).
bug_report_2.zip

I've added a second .zip (bug_report_2.zip) that contains a revised version of the add-on used for showcasing the bug that adds a section under the Object panel so you try setting keyframes for custom properties within PropertyGroup/CollectionPropertys of Objects as well as PoseBones (it works for Objects, but not for PoseBones). [bug_report_2.zip](https://archive.blender.org/developer/F329847/bug_report_2.zip)

Added subscribers: @JoshuaLeung, @Sergey

Added subscribers: @JoshuaLeung, @Sergey

A bit weird. @JoshuaLeung, mind having a look here? :)

P.S. It's not required to install the addon, script can be run from text editor in Blender.

A bit weird. @JoshuaLeung, mind having a look here? :) P.S. It's not required to install the addon, script can be run from text editor in Blender.

Added subscriber: @GrahamHeld

Added subscriber: @GrahamHeld

This "bug" is still present in the official 2.78 RC as of 9/11/2016. I just ran in to this while working on my own addon involving PoseBones.

The conditions in my scene file and property setup are virtually identical to the ones described above.

This "bug" is still present in the official 2.78 RC as of 9/11/2016. I just ran in to this while working on my own addon involving PoseBones. The conditions in my scene file and property setup are virtually identical to the ones described above.
Author

@GrahamHeld

FYI, I did a workaround for this by, instead of storing the properties within a PropertyGroup or CollectionProperty, to just associate a set of custom properties directly with the PoseBone that use a naming scheme you can use to 'emulate' an array/CollectionProperty. (Since custom properties associated directly with the PoseBone that aren't inside of any PropertyGroup/CollectionProperty can still be animated.)

So, for example, if you wanted an array of a particular type of custom property, you'd make a set of variables that look like this:
num_things
thing0_propA
thing0_propB
thing0_propC
thing1_propA
thing1_propB
thing1_propC

etc...

It's a very dirty workaround imo, but it'll get the job done if you don't have time to wait for a fix.
This worked for my use case since I knew I wouldn't need an array size of more than a few items,
But for a use case that involves tens or hundreds of array items, this may not be a great workaround.

@GrahamHeld FYI, I did a workaround for this by, instead of storing the properties within a PropertyGroup or CollectionProperty, to just associate a set of custom properties directly with the PoseBone that use a naming scheme you can use to 'emulate' an array/CollectionProperty. (Since custom properties associated directly with the PoseBone that aren't inside of any PropertyGroup/CollectionProperty can still be animated.) So, for example, if you wanted an array of a particular type of custom property, you'd make a set of variables that look like this: num_things thing0_propA thing0_propB thing0_propC thing1_propA thing1_propB thing1_propC etc... It's a very dirty workaround imo, but it'll get the job done if you don't have time to wait for a fix. This worked for my use case since I knew I wouldn't need an array size of more than a few items, But for a use case that involves tens or hundreds of array items, this may not be a great workaround.

Added subscriber: @dr.sybren

Added subscriber: @dr.sybren

This is apparently a known limitation, it's documented as TODO in rna_path_from_ID_to_idpgroup() (the TODO was added in 19efa4301a in 2010). As such this isn't considered a bug. It's still clearly useful functionality, though, so I'll mark it as a To Do.

This is apparently a known limitation, it's documented as TODO in `rna_path_from_ID_to_idpgroup()` (the TODO was added in 19efa4301a in 2010). As such this isn't considered a bug. It's still clearly useful functionality, though, so I'll mark it as a To Do.

Added subscriber: @tylerfurby

Added subscriber: @tylerfurby

Any status on this becoming implemented? Have quite a few properties written in collection properties in an add-on of mine -- none of which are related to rigging or bones.

Any status on this becoming implemented? Have quite a few properties written in collection properties in an add-on of mine -- none of which are related to rigging or bones.

At this time there is no concrete plan to implement this.

At this time there is no concrete plan to implement this.

Added subscriber: @pauanyu_blender

Added subscriber: @pauanyu_blender

Added subscriber: @geloescht

Added subscriber: @geloescht

Added subscriber: @Solstice245

Added subscriber: @Solstice245

Here to second this...this limitation also affects pointer properties. Fortunately for me though that is much easier to work around.

Here to second this...this limitation also affects pointer properties. Fortunately for me though that is much easier to work around.

I am willing to tackle this, as it hinders my add-on development greatly. However I don't have much experience with the blender C source, so some advice from the veterans is appreciated. Scanning the code and stepping through the involved functions I came up with two possible solutions.

  • The first one sounds cleaner to me but involves expanding the structure PointerRNA by one more pointer. It would look like this:
typedef struct PointerRNA {
  struct ID *owner_id;
  struct StructRNA *type;
  void *data;
  struct StructRNA *idp_owner;
} PointerRNA;

idp_owner would point to the object that holds the ID property being pointed to or NULL if it isn't an ID property. Thus is would be equal to owner_id if it is held by an actual ID type or point to a PoseBone, Sequence, etc. otherwise. We should be able to figure out the path of idp_owner in the same way as with any other plain RNA property and tack on the path of the ID property. Hopefully the increased size of the struct won't matter too much because afaict PointerRNA isn't used by value very often. If this doesn't make any sense or this tradeoff is unacceptable, please let me know.

  • The other possibility would be to add some kind of virtual function on the same level as StructRNA.idproperties that allows us to iterate over all nested properties of an ID datablock that can possibly hold ID properties. The function doesn't necessarily need to be defined on StructRNA as it is only needed for ID types, but I am not sure where would be the best place to put it. We then search all of those in rna_path_from_ID_to_idpgroup() instead of just those of the ID type. That would keep PointerRNA the same but the performance could be worse, especially when there are many ID properties defined, and custom methods would have to be written and maintained for every ID type.

  • Lastly it might be possible to iterate over all RNA properties of the owner ID datablock recursively and find those that can hold ID properties. Python knows all properties, so it should be doable somehow, although I am not sure how it works. The performance would probably be abysmal, so I haven't looked into this.

Can you advise me if any of these plans sound reasonable, @dr.sybren?

I am willing to tackle this, as it hinders my add-on development greatly. However I don't have much experience with the blender C source, so some advice from the veterans is appreciated. Scanning the code and stepping through the involved functions I came up with two possible solutions. - The first one sounds cleaner to me but involves expanding the structure PointerRNA by one more pointer. It would look like this: ``` typedef struct PointerRNA { struct ID *owner_id; struct StructRNA *type; void *data; struct StructRNA *idp_owner; } PointerRNA; ``` idp_owner would point to the object that holds the ID property being pointed to or NULL if it isn't an ID property. Thus is would be equal to owner_id if it is held by an actual ID type or point to a PoseBone, Sequence, etc. otherwise. We should be able to figure out the path of idp_owner in the same way as with any other plain RNA property and tack on the path of the ID property. Hopefully the increased size of the struct won't matter too much because afaict PointerRNA isn't used by value very often. If this doesn't make any sense or this tradeoff is unacceptable, please let me know. - The other possibility would be to add some kind of virtual function on the same level as StructRNA.idproperties that allows us to iterate over all nested properties of an ID datablock that can possibly hold ID properties. The function doesn't necessarily need to be defined on StructRNA as it is only needed for ID types, but I am not sure where would be the best place to put it. We then search all of those in `rna_path_from_ID_to_idpgroup()` instead of just those of the ID type. That would keep PointerRNA the same but the performance could be worse, especially when there are many ID properties defined, and custom methods would have to be written and maintained for every ID type. - Lastly it might be possible to iterate over all RNA properties of the owner ID datablock recursively and find those that can hold ID properties. Python knows all properties, so it should be doable somehow, although I am not sure how it works. The performance would probably be abysmal, so I haven't looked into this. Can you advise me if any of these plans sound reasonable, @dr.sybren?

Added subscriber: @mont29

Added subscriber: @mont29

For this I would actually appreciate @mont29 's feedback :)

For this I would actually appreciate @mont29 's feedback :)

After spending more time with the code I decided that the alternatives I proposed require changes in too many places to be practical. Instead I came up with a hack of sorts where a reference to the struct that owns the ID property group and its type is stored in unused fields of IDProperty::data. It is propagated to any property that is added to an IDP_GROUP or IDP_IDPARRAY. rna_path_from_ID_to_idpgroup() uses this ownership reference if it exists to search for the ID property in the right place and builds a path.
Creating and updating the reference after loading a file happens in the idprops() function for each type. It was the easiest place to do add that, otherwise RNA stuff would have to be added in places that doesn't deal with RNA. I can see how something might go wrong here but so far haven't encountered any problems.
The attached patch is a proof of concept and shouldn't be seen as a patch to be committed immediately. My question is if this is acceptable as an approach since it is kind of a hack (but on the other hand the way ID properties are stored already looks like a hack to me).
T48975_poc.diff test_animate_sequence_props.blend1
In the attached example, run the script in the text editor and navigate to the sequence editor. In the test tab, try to insert keyframes on the nested ID properties of the sequence. With the patch applied, this should work.

After spending more time with the code I decided that the alternatives I proposed require changes in too many places to be practical. Instead I came up with a hack of sorts where a reference to the struct that owns the ID property group and its type is stored in unused fields of `IDProperty::data`. It is propagated to any property that is added to an IDP_GROUP or IDP_IDPARRAY. `rna_path_from_ID_to_idpgroup()` uses this ownership reference if it exists to search for the ID property in the right place and builds a path. Creating and updating the reference after loading a file happens in the `idprops()` function for each type. It was the easiest place to do add that, otherwise RNA stuff would have to be added in places that doesn't deal with RNA. I can see how something might go wrong here but so far haven't encountered any problems. The attached patch is a proof of concept and shouldn't be seen as a patch to be committed immediately. My question is if this is acceptable as an approach since it is kind of a hack (but on the other hand the way ID properties are stored already looks like a hack to me). [T48975_poc.diff](https://archive.blender.org/developer/F10180126/T48975_poc.diff) [test_animate_sequence_props.blend1](https://archive.blender.org/developer/F10180192/test_animate_sequence_props.blend1) In the attached example, run the script in the text editor and navigate to the sequence editor. In the test tab, try to insert keyframes on the nested ID properties of the sequence. With the patch applied, this should work.

I realized that attaching a diff as a comment is not the right way. Sorry for this, see D11652

I realized that attaching a diff as a comment is not the right way. Sorry for this, see [D11652](https://archive.blender.org/developer/D11652)
Member

Added subscriber: @Mets

Added subscriber: @Mets

I'm curious if any progress has been made here? I'm very much looking forward to it.

I'm curious if any progress has been made here? I'm very much looking forward to it.

My diff seems to work for me (though limited to sequences and pose bones atm) but I haven't gotten any feedback from more experienced developers. I wouldn't want to spend more time on it without knowing whether it could possibly be accepted, especially since it is kind of a hack.

My diff seems to work for me (though limited to sequences and pose bones atm) but I haven't gotten any feedback from more experienced developers. I wouldn't want to spend more time on it without knowing whether it could possibly be accepted, especially since it is kind of a hack.
Philipp Oeser removed the
Interest
Animation & Rigging
label 2023-02-09 14:36:45 +01:00
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
9 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#48975
No description provided.