pythonursina

Ursina Python - How to correctly reparent an entity?


I am trying to make a Rubik's Cube using Ursina. I am planning on rotating the faces by making all pieces on a face of the cube the parent of the centre of that face, and then rotating the central piece. However, this only seems to work after giving the pieces their first parent, and I cannot successfully change the parent of the pieces.

I tried iterating through the pieces in the face (stored in a list) and using entity.parent = ___ and also entity.parent_setter(___) but neither worked.

from ursina import *

app = Ursina()

cubepiece = Entity(model='cube', color=color.black)
blueplate = Entity(model="cube", scale_x=0.9, scale_y=0.9, scale_z=0.1, z=-0.5, color=color.blue, parent=cubepiece)
yellowplate = Entity(model="cube", scale_x=0.1, scale_y=0.9, scale_z=0.9, x=-0.5, color=color.yellow, parent=cubepiece)
redplate = Entity(model="cube", scale_x=0.9, scale_y=0.1, scale_z=0.9, y=0.5, color=color.red, parent=cubepiece)
whiteplate = Entity(model="cube", scale_x=0.1, scale_y=0.9, scale_z=0.9, x=0.5, color=color.white, parent=cubepiece)
orangeplate = Entity(model="cube", scale_x=0.9, scale_y=0.1, scale_z=0.9, y=-0.5, color=color.orange, parent=cubepiece)
greenplate = Entity(model="cube", scale_x=0.9, scale_y=0.9, scale_z=0.1, z=0.5, color=color.green, parent=cubepiece)

cube = []
for i in range(3):
    layer = []
    for j in range(3):
        line = []
        for k in range(3):
            piece = duplicate(cubepiece)
            piece.set_position((i-1, j-1, k-1))
            line.append(piece)
        layer.append(line)
    cube.append(layer)

destroy(cubepiece)


for layer in cube:
    for line in layer:
        for piece in line:
            if piece != cube[1][1][1]:
                piece.parent = cube[1][1][1]

camera.x = 20
camera.y = 20
camera.fov = 30
camera.look_at((0, 0, 0))

def input(key):
    if key == 'w':
        rotateYellow()
    if key == "up arrow":
        cube[1][1][1].rotation_x += 45
    if key == "down arrow":
        cube[1][1][1].rotation_x -= 45
    if key == "left arrow":
        cube[1][1][1].rotation_y += 45
    if key == "right arrow":
        cube[1][1][1].rotation_y -= 45

def rotateYellow():
    for line in cube[0]:
        for piece in line:
            if piece != cube[0][1][1]:
                piece.parent_setter(cube[0][1][1])
    cube[0][1][1].rotation_x += 45
    for line in cube[0]:
        for piece in line:
            piece.parent_setter(cube[1][1][1])

app.run()

Solution

  • Solution Found:

    I simply used entity.world_parent = ___ in all cases (except when adding the plates to the pieces at the start)

    Working code:

    from ursina import *
    
    app = Ursina()
    
    cubepiece = Entity(model='cube', color=color.black)
    blueplate = Entity(model="cube", scale_x=0.9, scale_y=0.9, scale_z=0.1, z=-0.5, color=color.blue, parent=cubepiece)
    yellowplate = Entity(model="cube", scale_x=0.1, scale_y=0.9, scale_z=0.9, x=-0.5, color=color.yellow, parent=cubepiece)
    redplate = Entity(model="cube", scale_x=0.9, scale_y=0.1, scale_z=0.9, y=0.5, color=color.red, parent=cubepiece)
    whiteplate = Entity(model="cube", scale_x=0.1, scale_y=0.9, scale_z=0.9, x=0.5, color=color.white, parent=cubepiece)
    orangeplate = Entity(model="cube", scale_x=0.9, scale_y=0.1, scale_z=0.9, y=-0.5, color=color.orange, parent=cubepiece)
    greenplate = Entity(model="cube", scale_x=0.9, scale_y=0.9, scale_z=0.1, z=0.5, color=color.green, parent=cubepiece)
    
    cube = []
    for i in range(3):
        layer = []
        for j in range(3):
            line = []
            for k in range(3):
                piece = duplicate(cubepiece)
                piece.set_position((i-1, j-1, k-1))
                line.append(piece)
            layer.append(line)
        cube.append(layer)
    
    destroy(cubepiece)
    
    
    for layer in cube:
        for line in layer:
            for piece in line:
                if piece != cube[1][1][1]:
                    piece.world_parent = cube[1][1][1]
    
    camera.x = 20
    camera.y = 20
    camera.fov = 30
    camera.look_at((0, 0, 0))
    
    def input(key):
        if key == 'w':
            rotateYellow()
        if key == "up arrow":
            cube[1][1][1].rotation_x += 45
        if key == "down arrow":
            cube[1][1][1].rotation_x -= 45
        if key == "left arrow":
            cube[1][1][1].rotation_y += 45
        if key == "right arrow":
            cube[1][1][1].rotation_y -= 45
    
    def rotateYellow():
        for line in cube[0]:
            for piece in line:
                if piece != cube[0][1][1]:
                    piece.world_parent = cube[0][1][1]
        cube[0][1][1].rotation_x += 45
        for line in cube[0]:
            for piece in line:
                piece.world_parent = cube[1][1][1]
    
    app.run()