Scene Graph manipulation problem

Hi guys,
I’m making a 3d tetris (innovative, I know) I already did the tetroid (tetris piece) generation part and the rotating and moving. I have a problem with freezing the tetroids in place and re-parenting their content. Here’s the architecture background:

Each tetroid object contains a pivot node and an array - lets call it blocks - which holds a set of cubes (i will need to learn to instance sometime later) and an xyz location for each cube relative to the pivot - the pointer and the location are also an array, called vals. When I rotate the tetroid I change stuff in blocks[vals], and then update the each cube’s position according to those values (to keep it all integers for later use).

What I’m trying to do to freeze the tetroid in place is taking all the cubes inside the tetroid, re-parenting them to a floor dummy node, and then put a new tetroid in the global piece variable which held the previous tetroid.

I must tell you that I’m getting shitty results. In more detail:
I’m simulating the ‘freezing’ condition with the enter key press. When I hit it the old piece seems to freeze (change color as expected) and a new piece is created. But when I press the movement buttons neither of them moves, and when I press the rotation button only the supposedly frozen piece rotates and snaps back to 0,0,0 while the new piece won’t react at all.

Source code is here, thanx for the help

bump with updates
Ok, I’ve sort of narrowed down the problem. Here’s the problem (in short this time):

I have a Tetroid class, which holds in it an array of [posx, posy,posz, pointerToBlock] for each block in the tetroid, and a pivot for the whole shape.

When you press enter it reparents all blocks from the current Tetroid object (the var name of it is piece) to the floor node, and after that it is supposed to put a new shape (create a new Tetroid) and put it in the piece variable. The problem is the new shape is actually cerated by it doesn’t react to move, and when i press the rotate buttons it rotates the pieces reparented??

I can’t understand why the newly created Tetroid isn’t treated the same way as the old one.

here’s the code and the relevant maps


When you create the Catcher() object, you called:

self.accept(“arrow_up”, piece.mNode, [0, 0, 1])
self.accept(“arrow_down”, piece.mNode, [0, 0, -1])

piece.mNode is evaluate to the mNode method of the first Tetroid object you created. It is remembered in base.accept. So later even you change the variable “piece” to a new object, the key event handler still reference the first object.

You have to rewrite your logic to fix the bug.

Bah. How can I make it actually reference the new object? Or in which way can I change the logic so it works like I want it to?

Say, for example, make an global object to hold the Tetroid:

class TetroidPool:
    def __init__(self):
       self.tetroids = []

   def add(self):
        t = Tetroid(shape, texPiece)

   def mNode(self, x, y, z):
	t = self.tetrioids[-1] ## the active one is the latest one

pool = TetroidPool()
base.accept("arrow_up", pool.mNode, [0, 0, 1])

So the problem is a (if you’ll excuse me) “python-problem”? I can’t hold a global variable for a single object, I have to remember all the objects I’ve ever had?

No. It is not a python problem.

After you call:
base.accept(“arrow_up”, piece.mNode, [0, 0, 1])

The panda keyboard controller will remember which object’s method to call with the corresponding parameter. Later on you change the piece variable to something else, you can’t expect the handler will follow your changes.

I just suggest one way to this problem. I am sure you can figure out many others without storing these objects.

You lost me man. I’m referring to “piece” as a global variable. I do expect from the event handler to turn to the same variable’s function whenever it is called, but it’s logical to expect it to call the function of the new variable in the global var if I happen to change it. Or am I missing something here?

Yes, I know what you are referring to.

Most computer languages work this way (C, C++, python, …). Lisp, python and some other language can make to work the way you described above in some occasions with some coding technique.

When you call:
base.accept(“arrow_up”, piece.mNode, [0, 0, 1])
The three parameters for base.accept are evaluated immediately. At this moment piece is “pointing” to object1, so object1.mNode is the result of evaluation. In the function of base.accept, it records these variables to a data structure. When “arrow_up” keyboard event comes, base object will called object1.mNode with [0,0,1]

No matter how you change piece, the information inside base object will not be changed and cannot be changed.

This is another way to get around your problem, if you prefer a global variable “piece”

def mymNode(x,y,z):

base.accept("arrow_up", mymNode, [0, 0, 1])

Now the keyboard handler remember the function “mymNode”, which will always called the updated piece variable.