[Bf-committers] Getting the associated Blender object name from a uiBut object

The Simple Carnival jeff at simplecarnival.com
Sun Aug 6 17:04:06 CEST 2017

Hello --

I recently discovered that it's possible to automate the render or view 
capability of an object via the Outliner: 

This is a fantastic feature, but I need a way to select multiple objects 
and automate their render or view capability simultaneously, 
particularly in a parent/child scenario. For example, let's say I have a 
parent object with 100 child objects. If I want all of those objects to 
not be rendered, it's very tedious to right click on the render icon of 
each of those objects in the Outliner and and choose "Insert Keyframe" 
from the popup menu.

In my custom Blender fork, I've added a right-click menu option for the 
Outliner called "Insert Recursive Keyframes" and have implemented the 
following code. Right now, I'm able to set the keyframe for the initial 
object that I right-clicked on. I can also iterate through all of the 
other buttons in the outliner and set a keyframe for the same type (i.e. 
if you right-click on a render icon to set a keyframe, this code will 
set render icon keyframes for *all* of the objects in the scene).

Now for my question. I cannot figure out how to determine what a uiBut 
object *is* in relation to the actual Blender object in the scene. In 
other words, I can see all of the properties of the uiBut objects that 
I'm iterating through...except for the actual Blender object name that 
is somehow tied to it. Since I can't figure out the Blender object name, 
I can't determine if the uiBut object that I'm looking at is a child of 
the uiBut object where I just inserted a keyframe.Or maybe I'm going 
about this all wrong and there's some other way to determine if one 
uiBut object is the child of another uiBut object. I've been looking at 
this for hours and I haven't been able to figure out how to do it.

Any help would be greatly appreciated!

Jeff Boller

static int insert_recursive_key_button_exec(bContext *C, wmOperator *op)
     Scene *scene = CTX_data_scene(C);
     PointerRNA ptr = { { NULL } };
     PropertyRNA *prop = NULL;
     uiBut *but;
     short success = 0;
     int index;
     const bool all = RNA_boolean_get(op->ptr, "all");
     short flag = 0;

     flag = ANIM_get_keyframing_flags(scene, 1);
     but = UI_context_active_but_get(C);
     UI_context_active_but_prop_get(C, &ptr, &prop, &index);

     // Set the keyframe that we actually clicked on.
     success = set_custom_keyframe(C, op, ptr, prop, but, all, index, flag);
     if (!success) return OPERATOR_CANCELLED;

     // Now look around for child objects where we need to set 
additional keyframes.
     uiBut *but_found = NULL;
     ARegion *ar = CTX_wm_region(C);
     if (ar) {
         uiBlock *block;
         uiBut *but2, *otherbut = NULL;
         for (block = ar->uiblocks.first; block; block = block->next) {
             for (but2 = block->buttons.first; but2; but2 = but2->next) {
                 if (!but2->active) {
                     // OK, so we know this isn't the main button we 
just picked.
                     // Can we pull some properties out of this and 
determine exactly what it is?
                     otherbut = but2;
                     if (otherbut && otherbut->rnapoin.data) {
                         PointerRNA otherptr = otherbut->rnapoin;
                         PropertyRNA *otherprop = otherbut->rnaprop;
                         int otherindex = otherbut->rnaindex;

                         // Make sure we're dealing with the same sort 
of keyframe (hide, hide_select, hide_render)
                         if (!memcmp(otherprop->identifier, 
prop->identifier, 11)) {

                             // HOW CAN WE CHECK THAT THIS IS A CHILD OF 

                             // Assuming that this is a child of the 
original thing we clicked on, set this keyframe too.
                             success = set_custom_keyframe(C, op, 
otherptr, otherprop, otherbut, all, otherindex, flag);
                             if (!success) return OPERATOR_CANCELLED;

     if (success) {
         /* send updates */

         /* send notifiers that keyframes have been changed */
         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, 


More information about the Bf-committers mailing list