import scene3d
scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
scene.set_ground(length=10, width=10)
sphere = scene3d.Shapes.Sphere(diameter=1.5, segments=16)
sphere.set_color('#4488ff')
sphere.set_position(0, 1, 0)
sphere.on_click(lambda: sphere.set_color('#e94560'))
scene.add(sphere)
scene.run()On Click — Event Handling
So far your scenes have run the same way every time — code runs top to bottom and that’s it. But real programs respond to what the user does.
An event is something that happens — a mouse click, a key press, a timer firing. You write a function that should run when that event occurs, and you connect it to the event. That connected function is called an event handler.
In scene3d, every mesh supports on_click(handler) — pass it a function and that function runs every time the user clicks the mesh.
A Simple Click Handler
The simplest way to handle a click is with a lambda — a tiny one-line function with no name.
sphere.on_click(lambda: sphere.set_color('#e94560'))Read this as: “When the sphere is clicked, run this: sphere.set_color('#e94560')”
Run the cell, then click the sphere in the scene to change its color.
How on_click Works
sphere.on_click(lambda: sphere.set_color('#e94560'))| Part | What it does |
|---|---|
sphere.on_click(...) |
Registers a handler for click events on this mesh |
lambda: |
Creates a small anonymous function with no name |
sphere.set_color(...) |
The code that runs when the click happens |
The handler must be registered before the mesh is added to the scene with scene.add(). The handler is registered when you call on_click, but it doesn’t run until a click occurs. You can think of it as leaving a note: “If this is ever clicked, do this.”
Lambda is great for simple single-line actions. For anything more complex, use a named function.
{ “question_type”: “multiple_choice”, “question”: “When does the function passed to on_click actually run?”, “options”: [ { “key”: “a”, “text”: “Immediately when on_click is called” }, { “key”: “b”, “text”: “When scene.run() is called” }, { “key”: “c”, “text”: “Every frame, just like on_frame” }, { “key”: “d”, “text”: “When the user clicks the mesh” } ], “answer”: “d”, “submitted_answer”: “” }
Named Functions for More Complex Handlers
A lambda can only hold one expression. When the handler needs multiple steps — like updating a counter, choosing a new color, and updating a HUD — use a regular named function instead.
The scene below counts how many times the sphere has been clicked and cycles through colors. Click the sphere several times to watch it change!
import scene3d
scene = scene3d.Scene()
scene.set_sky('#0f3460')
scene.set_ground(length=10, width=10)
ctx = scene.get_context('2d')
colors = ['#4488ff', '#e94560', '#f5a623', '#44cc88', '#cc44ff']
click_count = 0
def on_sphere_click():
global click_count
click_count += 1
sphere.set_color(colors[click_count % len(colors)])
ctx.clear()
ctx.fill_style = '#ffffff'
ctx.font = '22px sans-serif'
ctx.fill_text(f'Clicks: {click_count}', 10, 30)
sphere = scene3d.Shapes.Sphere(diameter=1.5, segments=16)
sphere.set_color('#4488ff')
sphere.set_position(0, 1, 0)
sphere.on_click(on_sphere_click)
scene.add(sphere)
ctx.fill_style = '#ffffff'
ctx.font = '22px sans-serif'
ctx.fill_text('Click the sphere!', 10, 30)
scene.run(){ “question_type”: “true_false”, “question”: “A lambda is the only way to pass a handler to on_click — named functions cannot be used.”, “answer”: “False”, “submitted_answer”: “” }
Multiple Objects, Multiple Handlers
Every mesh can have its own click handler — they don’t interfere with each other. The scene below has three shapes. Each one responds to clicks independently. Try clicking each shape and reading the message on screen.
import scene3d
scene = scene3d.Scene()
scene.set_sky('#0f3460')
scene.set_ground(length=14, width=10)
ctx = scene.get_context('2d')
message = 'Click any shape!'
def show(text):
global message
message = text
ctx.clear()
ctx.fill_style = '#ffffff'
ctx.font = '22px sans-serif'
ctx.fill_text(message, 10, 30)
box = scene3d.Shapes.Box(width=1.2, height=1.2, depth=1.2)
box.set_color('#e94560')
box.set_position(-4, 0.6, 0)
box.on_click(lambda: show('You clicked the box!'))
scene.add(box)
sphere = scene3d.Shapes.Sphere(diameter=1.2, segments=16)
sphere.set_color('#f5a623')
sphere.set_position(0, 0.6, 0)
sphere.on_click(lambda: show('You clicked the sphere!'))
scene.add(sphere)
cylinder = scene3d.Shapes.Cylinder(diameter=1.0, height=1.5, tessellation=16)
cylinder.set_color('#44cc88')
cylinder.set_position(4, 0.75, 0)
cylinder.on_click(lambda: show('You clicked the cylinder!'))
scene.add(cylinder)
show('Click any shape!')
scene.run(){ “question_type”: “multiple_choice”, “question”: “If you call on_click on three different meshes, what happens when the user clicks one of them?”, “options”: [ { “key”: “a”, “text”: “All three handlers run” }, { “key”: “b”, “text”: “Only the handler for the clicked mesh runs” }, { “key”: “c”, “text”: “The first handler registered always runs” }, { “key”: “d”, “text”: “on_click only works for one mesh at a time” } ], “answer”: “b”, “submitted_answer”: “” }
{ “question_type”: “freeform”, “question”: “In one sentence, describe what an ‘event handler’ is.”, “answer”: “a function that runs when an event occurs”, “submitted_answer”: “” }
Try It Yourself
The scene below has a row of five spheres. Each one tracks how many times it’s been clicked and changes to a random new color with every click. Click them as fast as you can!
import scene3d
import random
scene = scene3d.Scene()
scene.set_sky('#0f3460')
scene.set_ground(length=16, width=8)
palette = ['#e94560', '#f5a623', '#4488ff', '#44cc88', '#cc44ff', '#ff8844', '#44ffcc']
spheres = []
clicks = [0, 0, 0, 0, 0]
ctx = scene.get_context('2d')
def update_hud():
ctx.clear()
ctx.fill_style = '#ffffff'
ctx.font = '20px sans-serif'
ctx.fill_text('Clicks: ' + ' | '.join(str(c) for c in clicks), 10, 28)
def make_handler(idx):
def handler():
clicks[idx] += 1
spheres[idx].set_color(random.choice(palette))
update_hud()
return handler
for i in range(5):
s = scene3d.Shapes.Sphere(diameter=1.2, segments=16)
s.set_color(palette[i])
s.set_position(i * 3 - 6, 0.7, 0)
s.on_click(make_handler(i))
scene.add(s)
spheres.append(s)
update_hud()
scene.run()Think about an interactive game or experience you’d like to build — a puzzle, a quiz, an instrument you play with clicks.
Which objects would be clickable? What would each click do? Would clicks change just one object, or would clicking one thing affect others too? Describe the experience you have in mind.