Reference to object as custom property

I’m trying to have a list of objects saved as a custom property within another object. This is what I’ve got so far:

class ContinentProps(bpy.types.PropertyGroup):
    number = bpy.props.IntProperty()
    object = bpy.props.PointerProperty(type = bpy.types.Object)

class ContinentsList(bpy.types.PropertyGroup):
    continentsList = bpy.props.CollectionProperty(type=ContinentProps)

    bpy.types.Object.Continents = bpy.props.PointerProperty(type = ContinentsList)

Then

D.objects[1].Continents.continentsList.add()
D.objects[1].Continents.continentsList[0].number = 10
D.objects[1].Continents.continentsList[0].object = D.objects[2]

For some reason number property works ok, but object property is not, I’m getting this when I try to read it:

>>> D.objects[1].Continents.continentsList[0].object
(<built-in function PointerProperty>, {'attr': 'object', 'type': <class 'bpy_types.Object'>})

What am I missing?

Thanks.

It’s explained here:

Basically, it’s impossible to store references to objects. You can store the object names in StringProperties however.

I had a feeling this is going to be an answer. Is there any event on changing name, deleting objects etc?

Or events on before save/after load of .blend file for that matter?

There are application callbacks in the docs.

I think there are no such callbacks which alert you when names change or properties change. Which is a problem in so many ways… Properties are entirely “polling” by nature. There values are only ever pulled by other pieces of code, and don’t have a signalling mechanism. They have something the Python/C binding refers to as callbacks, but they are just setters and getters. You could theoretically implement your own property, and then have some signalling of your own in setters/getters.

Another way to work around this problem is to use the in-memory addresses. For better or for worse, most blender data objects have an “as_pointer” method, which returns the in-memory address. This address does not change during the lifetime of the loaded blend data, regardless of changing the name. So you could try to keep a cache of pointers and names and thusly notice when a pointer gets a new name. If you want to totally abuse the Blender API, you can even do that check inside the event method of a modal operator…

These lack of modern paradigms is one of the reasons why I call Blender a “living fossil”. Blender is a great, mature piece of software, but some of the paradigms are just awfully dated. And it would be hard or impossible to change that, too.

The problem is, I want the references to persist through saved .blend file, so I guess saving address of the object won’t work.

Oh well, I’ll go with object names and restrict myself to not changing the names after object was created.

Thanks, everyone!

Another solution is to add a custom property “unique id” which is set once and never changed, so that it is saved in the blend file. It’s unfortunate that the Blender API never thought of that.

I have been thinking about how to store arbitrary data in blend files, when the “property system” just isn’t enough. One solution I came up with is to serialize the data to json and store it in either a Text object or a custom property. I haven’t tried it, but it should work.

Perhaps suggest that, unique id per object sounds reasonable and shouldn’t be too hard to implement.

That’s actually not a bad idea, I wasn’t aware python has a built-in json module!

You might find it interesting to store data (possibly JSON-encoded) as a Blender Text datablock. If you prefix the name with a dot, it will be treated as hidden (not show in UI, but still accessible via bpy.data.texts)