2
$\begingroup$

This is hard to explain but I will try.

I have a panel UI that I use to generate a geometry but lets call it a parent group object.

I have a PropertyGroup List with a PropertyGroup for the Items so each generated object is stored in the list, so where you select the item in the list the UI in the same panel updates with the different objects properties and name that it's given. This name is the Geo's name in the Scene Property viewer as well as the name in the item in the list, which is the only thing I display there in the list.

When I rename the actual object not in my panel I have a complex solution where a watcher is monitoring for name changes and looking to update the panel. I can simply update the item.name from the list to the new name and it is visually seen to update, but when it comes to the field that represents the name in the properties panel I can in theory update it but it doesn't change visually no update. This is StringProperty that does not have an update function or anything like it but probably should I just don't know how to trigger it.

If I try to create a 'name' StringProperty in the List PropertyGroup it won't let me so I'm unable to assign an 'update' function.

If I create an extra property called geoName and assign an update function, then I can set it's value to the StringProperty via myProp = self.name. I guess I'm looking for a way to assign an update function to the 'name' property that is part of a list via

listGroup = props.PointerProperty(type=ListGroup)

So the UI shows it this way

ro.template_list("ListGroup", "Group_List", listGroup, "items", listGroup, "idx")

That is a UIList that has a draw_item function

class ListGroup(bpy.types.PropertyGroup):
    idx = bpy.props.IntProperty(name="Index", description="Index for ListGroup", default=0, update=listItemSelected)
    items = bpy.props.CollectionProperty(type=ListGroupItem)
and this 


class GenSourceItem(bpy.types.PropertyGroup):
    #items like StringProperty are here

is the set of properties where you can not seem to add the update function to the name property because it already exists so I can't set the field in the UI that is for creating them. The name field is also a way to edit it (which works and renames the geo and the list's name), but again if I edit the name of the object and the list updates it can't update the StringProperty in the panel without having an extra go between value I've assigned an update function to.

Said another way for clarity: since the UIList item has a 'name' and I can change/update it but I can't be notified it updated and reflect the change in the panel. How might I assign an update function to the List Items name property? or tell a StringProperty in a Panel to update. That parts wierd because I can update it somewhere in this watcher watching (continuously for what should be a geo name update event), and it seems to change it there, but I guess it must be out of the display context somehow (I guess because that geoObj name change is happening in the official Scene tree viewer)?

$\endgroup$

1 Answer 1

1
$\begingroup$

When defining a PropertyGroup one can define a StringProperty 'name', overwriting the internal name property. Any interaction with the name will use this new Property. This can be used in conjunction with a second StringProperty to create an update-hook like this:

import bpy

class Test(bpy.types.PropertyGroup):
    # there's allways "name" as a StringProperty.
    # we may overwrite it though, to add callbacks
    def _upd_name(self, context): # this will handle our update
        if self.name == self.old_name: return # abort: no change, no update
        print("changed name from '%s' to '%s'" % (self.old_name, self.name))
        for item in context.scene.test_collection:
            if item.ref == self.old_name:
                print("...updating ref in element:",item.name)
                item.ref = self.name
        self.old_name = self.name # update our old name
    # the _upd_name function must handle all callbacks.
    name : bpy.props.StringProperty(update=_upd_name) # our public name
    old_name : bpy.props.StringProperty() # helps us with our update
    # lets get a property to update
    ref : bpy.props.StringProperty()

def register():
    bpy.utils.register_class(Test) # register it and assign it
    bpy.types.Scene.test_collection = bpy.props.CollectionProperty(type=Test)
    # lets give it a test
    scn = bpy.context.scene
    A = scn.test_collection.add()
    A.old_name = A.name = "A" # setting both at the same time suppresses update.
    for n in "BCDEFGHI":
        item = scn.test_collection.add()
        item.old_name = item.name = n
        item.ref = A.name
    A.name = "A" # no real update
    A.name = "my-chosen-name" # update

if __name__=="__main__": register()

Note that this will lead to a second entry inside the rna_type.properties collection:

print(list(bpy.context.scene.test_collection[0].rna_type.properties.keys()))

Ideally we'd like to add the update function to the original item, but that seems to be impossible. Notice that you can not patch a hook to the name of objects either, as they are done internally. You'd only loose the ability to change the real name as your interface starts using the new name.

$\endgroup$

You must log in to answer this question.

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