Updating from Multiple Parent NodePaths

Hello All,

If you have the time, please help me with the following:

I would like to bind the attributes of one nodePath to a function of attributes of a collection of nodePaths.

Specifically, I would like to create a nodepath which will inherit the average position of two other “parent” nodepaths and update that average whenever the parents update.

I can do the following:

node1 = render.attachNewNode("1")
node1.setPos(x,y,z)
node2 = render.attachNewNode("2")
node2.setPos(a,b,c)
childNode = render.attachNewNode("child")
childNode.setPos(  (node1.getPos()+node2.getPos())/2  )

but the child node won’t update when node1 & node2 update.

I can bruteforce this by calling childNode.setPos() whenever I call node1.setPos(), but this can become cumbersome, especially if I want to inherent from 100s of “parent” nodes.

Thank you

You could create a task in which you set the position of the child node every frame.

Yes this is the bruteforce method I currently have implemented, but it isn’t as elegant as I’d like: if I’m averaging over 100 nodes, I would have a 100 line codeblock (or a hundred line list of parents) to iterate over.

Anyway, when you do something like

child.reparentTo(parent)

It will update the child’s attributes when the parent’s are updated.
I guess I want something like

child.reparentTo(parent1,parent2)

or

child.instanceFrom(nodeCollection)

Just to complete this thread, I found the simplest solution was to use the panda messenger system.

I define createNode and updateNode methods to send and accept messages via the messenger (this manual page needs some work)

#Create a node and listeners for a list of virtual Parents
def createNode(realParent, virtualParents = [], *args,  **kwargs):
    childNode = realParent.attachNewNode(*args, **kwargs)
    if '_messengerName' in kwargs: 
        setattr(childNode,'_messengerName', kwargs['_messengerName'])
    for parent in virtualParents: 
        self.accept(parent._messengerName+' updated', self.updateNode,[childNode])
        #can accept more calls

#Update a node and send a message (which the children will hear)
def updateNode(node, *args, **kwargs):
    ####Do some updates
    self.messenger.send(node._messengerName + ' updated')