In [ ]:
import ipywidgets as wd
from vpython import *
scene.width = 600
scene.height = 600
show = 'box'
last_show = show

R = 0.4 # radius of sphere
D = 0.7 # size of box

texs = [textures.flower, textures.granite, textures.gravel, textures.metal, textures.rock, textures.rough,
        textures.rug, textures.stones, textures.stucco, textures.wood, textures.wood_old, textures.earth]
bumps = [None, None, bumpmaps.gravel, None, bumpmaps.rock, None, None,
         bumpmaps.stones, bumpmaps.stucco, None, bumpmaps.wood_old]
texnames = ['flower', 'granite', 'gravel', 'metal', 'rock', 'rough', 'rug', 'stones', 'stucco', 'wood', 'wood_old', 'earth']
bumpnames = [ None, None, 'gravel', None, 'rock', None, None, 'stones', 'stucco', None, 'wood_old']

labels = []

def erase():
    objects = scene.objects
    for obj in objects:
        obj.visible = False

def show_object(index, x, y):
    T = texs[index]
    B = None
    # Bump maps aren't very salient unless one moves the light or rotates the object,
    # so don't bother with bump maps unless there's an option to move the light or object.
    #if (bumps[index] !== null) B = bumpmaps[bumps[index]]
    if show == 'box':
        c = box(pos=vec(x,y,0), size=D*vec(1,1,1))
    elif show == 'sphere':
        c = sphere(pos=vec(x,y,0), size=D*vec(1,1,1))
    elif show == 'cylinder': 
        c = cylinder(pos=vec(x-D/2,y,0), size=D*vec(1,1,1))
    elif show == 'cone': 
        c = cone(pos=vec(x-D/2,y,0), size=D*vec(1,1,1))
    elif show == 'pyramid': 
        c = pyramid(pos=vec(x-D/2,y,0), size=D*vec(1,1,1))
    c.index = index
    c.shininess = 0
    c.texture = dict(file=T, bumpmap=B)
    labels.append(label(pos=vec(x,y-.5,0), box=0, text='textures.'+texnames[index]))

def start_setup():
    scene.range = 2.2
    scene.fov = 0.2
    scene.center = vec(1.5,2,0)
    scene.forward = vec(0,0,-1)
    erase()
    #scene.visible = False
    index = 0
    y = 3.3
    while y > 0:
        for x in range(4):
            if index >= len(texs): break; 
            show_object(index, x, y)
            index += 1
        y -= 1.3

def end_setup():
    #scene.visible = True
    scene.title = 'Click an object to enlarge it.'

def setup():
    start_setup()
    end_setup()

start_setup()
#scene.caption = "Loading textures..."
#scene.waitfor("textures") # not yet implemented in Jupyter VPython

m = wd.Dropdown(options=['box', 'sphere', 'cylinder', 'cone', 'pyramid'], value='box',
                           description="Change the type of object: ")
container = wd.HBox(children=[m])
display(container)

def m_handler(s):
    global show
    show = s['new']
m.observe(m_handler, names='value')

end_setup()

hit = None
clicked = False
def click(ev):
    global hit, clicked
    hit = scene.mouse.pick
    clicked = True
scene.bind("click", click)

def single_object(index):
    erase()
    scene.center = vec(0,-.1*R,0)
    scene.range = 1.5*R
    show_object(index, 0, 0)
    scene.title = 'Click anywhere to see all textures.'

picked = None
    
while True:
    rate(30)
    if show != last_show:
        last_show = show
        if picked != None:
            single_object(picked.index)
        else:
            setup()
    if clicked:
        clicked = False
        if picked != None:
            picked = None
            setup()
        elif picked == None and hit != None:
            picked = hit
            hit = None
            single_object(picked.index)



In [1]:
scene.range


Out[1]:
2.2

In [ ]: