2
$\begingroup$

I would like to assign a unique Immutable index of the objects that are added in the scene. I want this unique index to be stored in an object type property (Relative to the object)

Obviously the object can be deleted and I would like the index to always grow regardless of whether the object is deleted (keeping it stored somewhere)

So assuming you have 10 objects in the scene, they will have an index, from 1 to 10

Assuming deleting all 10 objects, I would like that by adding a new object, the index continues to grow, i.e. in this case the index should be 11, Obviously the index could be very high even if there are few objects in the scene, but it is very important that it remains so, and that it is always growing.

I suppose I should create a list that contains all the previous indexes or something similar.

This situation is making me difficult.

This is how we declare an object-type property: I don't really know how to build a function that assigns correctly only when the len(bpy.data.objects[:]) changes, I can also think of a function called by bpy.app.handlers.depsgraph_update_post(), but I'm not sure

class ObjectProperties(bpy.types.PropertyGroup):
    obj_index = bpy.props.IntProperty()

def register():
    bpy.types.Object.obj_prop = bpy.props.PointerProperty(type=ObjectProperties)

My question is inherent in this answer , I was thinking of indexing all the objects present in the bpy.data.objects with a unique index. I want to try replacing the "Object Info" node with a driver, which is driven by the object's IntProperty Like this: enter image description here

An additional problem is when copying the object (Without instance)

I have done various tests, but there seems to be some problem with updating the integer value in the Driver.

Based on @batFINGER 's answer, the indexing method seems to be right for me. But I can't understand where I am wrong with the driver, when I assign sefl.scene_object_index to the driver, the driver never changes and always remains on 0 Although in this case C.object.scene_object_index is 6 (As seen in the console)

enter image description here

I had already noticed this problem, when I tried to make an index in my own way, I noticed that the driver was assuming wrong values

$\endgroup$
3
  • $\begingroup$ Could you provide some context? Why do you need this? $\endgroup$ Commented Jul 27, 2020 at 14:02
  • $\begingroup$ I need to drive a material driver, but I need the indexing never to change. $\endgroup$
    – Noob Cat
    Commented Jul 28, 2020 at 7:32
  • 2
    $\begingroup$ I think it would make sense for you to edit the question and provide more context, tell more about what you want to do and why. It would help to avoid miscommunication and would also probably encourage people to provide some answers. See xyproblem.info . I think some people might hesitate answering such a question without more context because of that issue. $\endgroup$ Commented Jul 28, 2020 at 8:04

1 Answer 1

6
+100
$\begingroup$

A collection of pointers

Can set up a collection on the scene with pointers to objects.

On an object set up a property to populate the collection and return the objects index in that collection.

Feel it's a little hacky to use context to get the scene within the getter method.

Example of setting up the props.

import bpy
from bpy.props import PointerProperty, CollectionProperty, IntProperty
from bpy.types import PropertyGroup, Object

class SceneObject(PropertyGroup):
    object : PointerProperty(type=Object)

def get_scene_object_index(self):
    from bpy import context
    scene = context.scene
    obs = [o.object for o in scene.scene_objects]
    for ob in set(scene.objects) - set(obs):
        o = scene.scene_objects.add()
        o.name = ob.name
        o.object = ob
        obs.append(ob)
        ob["scene_object_index"] = len(obs)
    
    return self["scene_object_index"]   


bpy.utils.register_class(SceneObject)

bpy.types.Scene.scene_objects = CollectionProperty(type=SceneObject)
Object.scene_object_index = IntProperty(get=get_scene_object_index)

def draw(self, context):
    layout = self.layout
    scene = context.scene
    ob = context.object
    self.layout.prop(ob, "scene_object_index")
    for o in context.scene.scene_objects:
        layout.label(text=f"{o.object.name}")    

bpy.types.OBJECT_PT_context_object.prepend(draw)

Added a little draw method to object props panel

Drive the pass_index

A driver using this prop can be added to the pass index of an object. Adding a value input driver to a material node will require targeting a different object per material.

EDIT

Have edited to give each object a custom property. Needs a rethink re property name to have a unique value per scene. It appears the driver "auto updates" better from the custom property rather than the read (getter) only property.

Will revisit and clean up if I have time, thinking a prop on scene with an update method.

enter image description here

Note at issue here is the collection property of the scene is giving the object a user. Deleting objects using operator will only unlink them from the scene, not remove them from the data. Requires an edit to remove objects if they are only used by the collection.

If an object that is assigned to a pointer is removed from data the pointer will return None

$\endgroup$
5
  • $\begingroup$ I admit that I was amazed at how few lines it is possible to do this, the index seems to remain intact as I asked. It looks amazing. Aside from the fact that the driver (in my case) doesn't seem to update with the self.scene_object_index, it always returns 0, even if the object is actually correctly indexed $\endgroup$
    – Noob Cat
    Commented Aug 4, 2020 at 19:33
  • $\begingroup$ I tried to insert self.scene_object_index in the driver, but the driver always remains 0, then I tried to insert bpy.data.objects['My Object'].scene_object_index and it works (The driver obviously reports many warnings) I can't understand why this happens $\endgroup$
    – Noob Cat
    Commented Aug 5, 2020 at 12:20
  • $\begingroup$ Have indexed from zero, so for one scene object the value will be zero. Add one in the getter method return to index from 1. If there are further error messages edit them into the question. $\endgroup$
    – batFINGER
    Commented Aug 5, 2020 at 13:08
  • $\begingroup$ Great answer, everything works correctly now. One question: Why did you choose set(context.scene.objects) and not set(bpy.data.objects) $\endgroup$
    – Noob Cat
    Commented Aug 6, 2020 at 14:08
  • 1
    $\begingroup$ One is all objects linked to the scene, the other is all objects in the blend file. As mentioned in answer, will find deleting objects will only unlink from scene, but will still exist in bpy.data.objects. For the most part we are interested in scene objects not all, that may or may not be linked to any all or no scenes in the blend file. $\endgroup$
    – batFINGER
    Commented Aug 6, 2020 at 14:14

You must log in to answer this question.

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