How to add data to an Object(ID) type

hi,
I am trying to create an object to serve as a manager that operates on other objects.
an analogy will be something a particle emitter, that has an array of particles, and each tick update positions. This is my class

class NewtonWorld(bpy.types.Object):
    """create an interface to the newton workd"""

    def __init__(self, object):
        #print ("create manager one once")
        self.name = 'newton_world'
        self.world = newton.ndWorld()

    def SetIterations (self, iterations):
        self.world.SetSolverIterations(iterations)

ndWorld is a cpp class. and I tested in plain vanilla python.
So far it works until I am trying to call a function from a subclass of a blender object.
here is the operator that try that

class NewtonWorldSetProperty(bpy.types.Operator):
    """newton world set engine properties"""
    bl_label = 'newton world set property'
    bl_idname = 'view3d.newton_world_set_property'
    bl_description = "newton world set property"

    def findWorld(self):
        col = bpy.data.collections.get("Collection")
        if col:
            for obj in col.objects:
                if obj.name == 'newton_world':
                    print ("esta es una pura mierda 0")
                    return obj
        return None


    def execute(self, context):
        scene = context.scene
        world = self.findWorld()
        propertyGroup = scene.newton_world_properties
        world.SetIterations(propertyGroup.solverIterations)
        return {'FINISHED'}

but I get this error.

location: <unknown location>:-1
Error: Python: Traceback (most recent call last):
  File "C:\Program Files\Blender Foundation\Blender 2.93\2.93/scripts/addons/newtonPy\newtonWorld.py", line 107, in execute
    world.SetIterations(propertyGroup.solverIterations)
AttributeError: 'Object' object has no attribute 'SetIterations'

location: <unknown location>:-1

normally in Cpp I would have to do a cast to teh subclass but in python that is no part of the language .
the object is part of the scene so it is of Type Object(ID),
however that object is a subclass of type Object(ID) class NewtonWorld(bpy.types.Object):

so how do people subclass from an Object and add extra information?

notice that the error has nothing to do with the CPP class, the erro is that the class does no recognize any member of any variable

another way to go around this is by adding a custom data to the superclass Object(ID),
but it seems this is not possible since the are only few types allowed (int, float, string and that sort of things)
is there any way to store a pointer to a cpp class generated by swig with and Object(ID)?

also notice that Python is a dynamically cast language, what I am doing works out of the box in vanilla python, but somehow it does not in Blender python.

Ok, I just veryfy that what I am doing is 100% legal in python, so somehow in blender Blender when I add the sub classed object to the scene, what is does is that it make a copy of the most base super class, in thsi case I am what goes to teh scene is a cube, not a sub class for cube
if I call a member of the class afte I just created, is does works.

tshi code below works.

class NewtonWorldCreate(bpy.types.Operator):
    """Creates a newton world"""
    bl_label = 'create newton world'
    bl_idname = 'view3d.newton_world_create'
    bl_description = "create a newton world"

    def execute(self, context):
        scene = context.scene

        # this does not works.
        #scene.newton_world = bpy.data.objects.new('newton_world', None) 
        world = NewtonWorld(context.active_object)
        world.SetIterations(10)

        scene.newton_world = world
        return {'FINISHED'}

but of I find the object from the scene and try to call a class member is simply fail.

so my question is still the very first I ask last week, how can I make a blender add on that need to store a class created in Cpp .

This has been way more difficult that I expected.

ok to make very vert clear, this is teh problem

class NewtonWorldCreateHomeObject(bpy.types.Operator):
    """Creates a newton world home"""
    bl_label = 'create newton world'
    bl_idname = 'view3d.newton_world_create_home'
    bl_description = "create newton world"

    def execute(self, context):
        scene = context.scene
        selectedObjec = context.active_object
        bpy.ops.mesh.primitive_cube_add(size=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
        if selectedObjec == context.active_object:
            print ('change to [object mode] operator canceled')
            return {'CANCELLED'}

        context.active_object.name = 'newtonHome'
        world = NewtonWorld(context.active_object)
        scene.newton_world = world
        print ("test calss NewtonWorld")

        # this line works
        world.SetIterations(10)

        # this line fail in blender but not in python
        scene.newton_world.SetIterations(10)

        return {'FINISHED'}

how could that be?

well never mind.
I decided that I will simple use a global variable, to hold the world, It seem blender has done something to their buidl in python that when adding a subclass to of a build types, blender make a copy of the type, and ignore the subclass.
this seems to defeat the object oriented nature of Python and Blender, but let it be as it made I have not other choice.
thsi can be closed now.

you need to do like this.

bpy.types.Object.world  = newton.ndWorld()

Once you do this then every object in blender will have world property and you can access it
i.e, access world property for active object in scene via context.object.world

Well, I wish I knew before

I decided to make the object a singleton.
I think in the long run this setup if far simpler.
I made some good progress now.

By hooking a hander callback, I now get my update each animation tick.
All in all, it is not bad.

I am now ready to populate the world with blender object that has custom properties that made them proxis of ndRigidBodies.

Hopelly this phase will be less painfull.

This time I am not going to even try saving the python cpp object with the Blender mesh object, I will simply saved as an integer index that look them up from a vector.

This way only blender custom will be stored in blender objects.

My hope is that this eliminate sterilization problems later on.

Thank you very much for the tip, it is always good to know.

1 Like