or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdapplication-framework.mdasset-loading.mdaudio.mdindex.mdinput.mdmathematics.mdscene-graph.mdtask-event.mduser-interface.md

input.mddocs/

0

# Input and Controls

1

2

Panda3D provides comprehensive input handling for keyboard, mouse, and gamepad devices through an event-driven system that integrates seamlessly with the task and messaging systems.

3

4

## Capabilities

5

6

### Keyboard Input

7

8

Keyboard input is handled through events generated for key press and release actions.

9

10

```python { .api }

11

# Key event patterns

12

# Press events: key name (e.g., "a", "space", "escape")

13

# Release events: key name + "-up" (e.g., "a-up", "space-up")

14

15

# Common key events

16

"escape" # Escape key

17

"space" # Space bar

18

"enter" # Enter/Return key

19

"tab" # Tab key

20

"backspace" # Backspace key

21

"delete" # Delete key

22

23

# Letter keys

24

"a", "a-up" # A key press/release

25

"b", "b-up" # B key press/release

26

# ... (all letters a-z)

27

28

# Number keys

29

"1", "1-up" # Number 1 key

30

"2", "2-up" # Number 2 key

31

# ... (numbers 0-9)

32

33

# Arrow keys

34

"arrow_up", "arrow_up-up"

35

"arrow_down", "arrow_down-up"

36

"arrow_left", "arrow_left-up"

37

"arrow_right", "arrow_right-up"

38

39

# Function keys

40

"f1", "f1-up" # Function keys F1-F12

41

"f2", "f2-up"

42

# ... (f1 through f12)

43

44

# Modifier keys

45

"shift", "shift-up" # Shift keys

46

"control", "control-up" # Control keys

47

"alt", "alt-up" # Alt keys

48

49

# Special keys

50

"home", "home-up"

51

"end", "end-up"

52

"page_up", "page_up-up"

53

"page_down", "page_down-up"

54

"insert", "insert-up"

55

```

56

57

### Mouse Input

58

59

Mouse input includes button clicks, movement, and wheel events.

60

61

```python { .api }

62

# Mouse button events

63

"mouse1" # Left mouse button press

64

"mouse1-up" # Left mouse button release

65

"mouse2" # Middle mouse button press

66

"mouse2-up" # Middle mouse button release

67

"mouse3" # Right mouse button press

68

"mouse3-up" # Right mouse button release

69

70

# Mouse wheel events

71

"wheel_up" # Mouse wheel scroll up

72

"wheel_down" # Mouse wheel scroll down

73

74

# Mouse movement tracking through MouseWatcher

75

class MouseWatcher:

76

def hasMouse(self) -> bool:

77

"""Check if mouse is within window."""

78

79

def getMouseX(self) -> float:

80

"""Get mouse X coordinate (-1 to 1)."""

81

82

def getMouseY(self) -> float:

83

"""Get mouse Y coordinate (-1 to 1)."""

84

85

def getMouse(self) -> Vec2:

86

"""Get mouse position as Vec2."""

87

88

def isButtonDown(self, button: int) -> bool:

89

"""Check if mouse button is currently down."""

90

```

91

92

### Input State Tracking

93

94

Track the current state of input devices for continuous input handling.

95

96

```python { .api }

97

# Access through base.mouseWatcherNode

98

mouseWatcher = base.mouseWatcherNode

99

100

# Check current input states

101

def isKeyDown(key: str) -> bool:

102

"""Check if key is currently pressed."""

103

return base.mouseWatcherNode.isButtonDown(key)

104

105

# Common input state checks

106

def getMousePos() -> tuple:

107

"""Get current mouse position."""

108

if base.mouseWatcherNode.hasMouse():

109

x = base.mouseWatcherNode.getMouseX()

110

y = base.mouseWatcherNode.getMouseY()

111

return (x, y)

112

return None

113

114

def getMouseDelta() -> tuple:

115

"""Get mouse movement since last frame."""

116

# Implementation depends on tracking previous position

117

pass

118

```

119

120

### Input Event Handling

121

122

Bind input events to functions using the event system.

123

124

```python { .api }

125

# Basic event binding (from ShowBase or DirectObject)

126

def accept(event: str, method: callable, extraArgs: list = []) -> None:

127

"""Bind input event to method."""

128

129

def ignore(event: str) -> None:

130

"""Stop handling input event."""

131

132

def ignoreAll() -> None:

133

"""Stop handling all events."""

134

135

# Example event handlers

136

def handleKeyPress(self):

137

"""Handle key press event."""

138

pass

139

140

def handleMouseClick(self):

141

"""Handle mouse click event."""

142

pass

143

144

def handleMouseDrag(self):

145

"""Handle mouse drag event."""

146

pass

147

```

148

149

### Advanced Input Patterns

150

151

Common input handling patterns for games and applications.

152

153

```python { .api }

154

# Movement input handling

155

MOVEMENT_KEYS = {

156

"w": Vec3(0, 1, 0), # Forward

157

"s": Vec3(0, -1, 0), # Backward

158

"a": Vec3(-1, 0, 0), # Left

159

"d": Vec3(1, 0, 0), # Right

160

"q": Vec3(0, 0, 1), # Up

161

"e": Vec3(0, 0, -1) # Down

162

}

163

164

# Input combinations

165

def isShiftPressed() -> bool:

166

"""Check if shift modifier is active."""

167

return base.mouseWatcherNode.isButtonDown("shift")

168

169

def isCtrlPressed() -> bool:

170

"""Check if control modifier is active."""

171

return base.mouseWatcherNode.isButtonDown("control")

172

```

173

174

## Usage Examples

175

176

### Basic Input Handling

177

178

```python

179

from direct.showbase.ShowBase import ShowBase

180

from panda3d.core import Vec3

181

182

class InputDemo(ShowBase):

183

def __init__(self):

184

ShowBase.__init__(self)

185

186

# Create player object

187

self.player = self.loader.loadModel("models/player")

188

self.player.reparentTo(self.render)

189

self.player.setPos(0, 10, 0)

190

191

# Setup input handling

192

self.setupInput()

193

194

# Movement state

195

self.keys_pressed = set()

196

self.mouse_pressed = set()

197

198

# Start input update task

199

self.taskMgr.add(self.updateInput, "update-input")

200

201

def setupInput(self):

202

"""Setup all input event handlers."""

203

# Movement keys

204

movement_keys = ["w", "a", "s", "d", "q", "e"]

205

for key in movement_keys:

206

self.accept(key, self.onKeyPress, [key])

207

self.accept(f"{key}-up", self.onKeyRelease, [key])

208

209

# Action keys

210

self.accept("space", self.jump)

211

self.accept("shift", self.run)

212

self.accept("shift-up", self.walk)

213

214

# Mouse input

215

self.accept("mouse1", self.onMousePress, [1])

216

self.accept("mouse1-up", self.onMouseRelease, [1])

217

self.accept("mouse3", self.onMousePress, [3])

218

self.accept("mouse3-up", self.onMouseRelease, [3])

219

220

# Special keys

221

self.accept("escape", self.exitGame)

222

self.accept("f1", self.showHelp)

223

224

# Mouse wheel

225

self.accept("wheel_up", self.zoomIn)

226

self.accept("wheel_down", self.zoomOut)

227

228

def onKeyPress(self, key):

229

"""Handle key press."""

230

self.keys_pressed.add(key)

231

print(f"Key pressed: {key}")

232

233

def onKeyRelease(self, key):

234

"""Handle key release."""

235

self.keys_pressed.discard(key)

236

print(f"Key released: {key}")

237

238

def onMousePress(self, button):

239

"""Handle mouse button press."""

240

self.mouse_pressed.add(button)

241

242

# Get mouse position

243

if self.mouseWatcherNode.hasMouse():

244

x = self.mouseWatcherNode.getMouseX()

245

y = self.mouseWatcherNode.getMouseY()

246

print(f"Mouse {button} pressed at ({x:.2f}, {y:.2f})")

247

248

def onMouseRelease(self, button):

249

"""Handle mouse button release."""

250

self.mouse_pressed.discard(button)

251

print(f"Mouse {button} released")

252

253

def updateInput(self, task):

254

"""Update input-based movement."""

255

dt = globalClock.getDt()

256

257

# Calculate movement vector

258

movement = Vec3(0, 0, 0)

259

speed = 10.0 # Base speed

260

261

# Apply movement keys

262

if "w" in self.keys_pressed:

263

movement += Vec3(0, 1, 0)

264

if "s" in self.keys_pressed:

265

movement += Vec3(0, -1, 0)

266

if "a" in self.keys_pressed:

267

movement += Vec3(-1, 0, 0)

268

if "d" in self.keys_pressed:

269

movement += Vec3(1, 0, 0)

270

if "q" in self.keys_pressed:

271

movement += Vec3(0, 0, 1)

272

if "e" in self.keys_pressed:

273

movement += Vec3(0, 0, -1)

274

275

# Apply speed modifiers

276

if self.isShiftPressed():

277

speed *= 2.0 # Run speed

278

279

# Normalize and apply movement

280

if movement.length() > 0:

281

movement.normalize()

282

movement *= speed * dt

283

284

current_pos = self.player.getPos()

285

self.player.setPos(current_pos + movement)

286

287

return task.cont

288

289

def isShiftPressed(self):

290

"""Check if shift is currently pressed."""

291

return self.mouseWatcherNode.isButtonDown("shift")

292

293

def jump(self):

294

"""Handle jump action."""

295

print("Jump!")

296

# Add jump logic here

297

298

def run(self):

299

"""Start running."""

300

print("Running...")

301

302

def walk(self):

303

"""Stop running."""

304

print("Walking...")

305

306

def zoomIn(self):

307

"""Zoom camera in."""

308

pos = self.camera.getPos()

309

self.camera.setPos(pos * 0.9)

310

311

def zoomOut(self):

312

"""Zoom camera out."""

313

pos = self.camera.getPos()

314

self.camera.setPos(pos * 1.1)

315

316

def showHelp(self):

317

"""Show help information."""

318

print("Help: WASD to move, Shift to run, Space to jump, ESC to exit")

319

320

def exitGame(self):

321

"""Exit the game."""

322

print("Exiting...")

323

self.userExit()

324

325

app = InputDemo()

326

app.run()

327

```

328

329

### Advanced Input Controller

330

331

```python

332

from direct.showbase.DirectObject import DirectObject

333

from panda3d.core import Vec3

334

335

class InputController(DirectObject):

336

"""Advanced input handling controller."""

337

338

def __init__(self, controlled_object):

339

DirectObject.__init__(self)

340

341

self.controlled_object = controlled_object

342

343

# Input state

344

self.keys_down = set()

345

self.mouse_buttons_down = set()

346

self.previous_mouse_pos = None

347

self.mouse_sensitivity = 1.0

348

349

# Input settings

350

self.move_speed = 10.0

351

self.run_multiplier = 2.0

352

self.mouse_look_enabled = False

353

354

# Setup input bindings

355

self.setupInputBindings()

356

357

# Start update task

358

self.addTask(self.updateInput, "input-controller")

359

360

def setupInputBindings(self):

361

"""Setup all input event handlers."""

362

# Movement keys

363

movement_keys = ["w", "a", "s", "d", "space", "shift"]

364

for key in movement_keys:

365

self.accept(key, self.onKeyDown, [key])

366

self.accept(f"{key}-up", self.onKeyUp, [key])

367

368

# Mouse look

369

self.accept("mouse2", self.enableMouseLook)

370

self.accept("mouse2-up", self.disableMouseLook)

371

372

# Mouse sensitivity

373

self.accept("=", self.adjustMouseSensitivity, [0.1])

374

self.accept("-", self.adjustMouseSensitivity, [-0.1])

375

376

def onKeyDown(self, key):

377

"""Handle key press."""

378

self.keys_down.add(key)

379

380

def onKeyUp(self, key):

381

"""Handle key release."""

382

self.keys_down.discard(key)

383

384

def enableMouseLook(self):

385

"""Enable mouse look mode."""

386

self.mouse_look_enabled = True

387

self.previous_mouse_pos = self.getMousePos()

388

389

# Hide cursor

390

props = WindowProperties()

391

props.setCursorHidden(True)

392

base.win.requestProperties(props)

393

394

def disableMouseLook(self):

395

"""Disable mouse look mode."""

396

self.mouse_look_enabled = False

397

398

# Show cursor

399

props = WindowProperties()

400

props.setCursorHidden(False)

401

base.win.requestProperties(props)

402

403

def getMousePos(self):

404

"""Get current mouse position."""

405

if base.mouseWatcherNode.hasMouse():

406

return (

407

base.mouseWatcherNode.getMouseX(),

408

base.mouseWatcherNode.getMouseY()

409

)

410

return None

411

412

def updateInput(self, task):

413

"""Update input processing."""

414

dt = globalClock.getDt()

415

416

# Handle movement

417

self.updateMovement(dt)

418

419

# Handle mouse look

420

if self.mouse_look_enabled:

421

self.updateMouseLook()

422

423

return task.cont

424

425

def updateMovement(self, dt):

426

"""Update object movement based on input."""

427

movement = Vec3(0, 0, 0)

428

429

# Calculate movement direction

430

if "w" in self.keys_down:

431

movement += Vec3(0, 1, 0)

432

if "s" in self.keys_down:

433

movement += Vec3(0, -1, 0)

434

if "a" in self.keys_down:

435

movement += Vec3(-1, 0, 0)

436

if "d" in self.keys_down:

437

movement += Vec3(1, 0, 0)

438

if "space" in self.keys_down:

439

movement += Vec3(0, 0, 1)

440

441

# Apply speed

442

speed = self.move_speed

443

if "shift" in self.keys_down:

444

speed *= self.run_multiplier

445

446

# Apply movement

447

if movement.length() > 0:

448

movement.normalize()

449

movement *= speed * dt

450

451

# Transform movement relative to object orientation

452

movement = self.controlled_object.getRelativeVector(

453

render, movement

454

)

455

456

current_pos = self.controlled_object.getPos()

457

self.controlled_object.setPos(current_pos + movement)

458

459

def updateMouseLook(self):

460

"""Update mouse look rotation."""

461

current_mouse = self.getMousePos()

462

463

if current_mouse and self.previous_mouse_pos:

464

# Calculate mouse delta

465

dx = current_mouse[0] - self.previous_mouse_pos[0]

466

dy = current_mouse[1] - self.previous_mouse_pos[1]

467

468

# Apply mouse sensitivity

469

dx *= self.mouse_sensitivity * 100

470

dy *= self.mouse_sensitivity * 100

471

472

# Update object rotation

473

current_hpr = self.controlled_object.getHpr()

474

new_h = current_hpr.getX() - dx # Horizontal rotation

475

new_p = current_hpr.getY() + dy # Vertical rotation

476

477

# Clamp vertical rotation

478

new_p = max(-90, min(90, new_p))

479

480

self.controlled_object.setHpr(new_h, new_p, 0)

481

482

self.previous_mouse_pos = current_mouse

483

484

def adjustMouseSensitivity(self, change):

485

"""Adjust mouse sensitivity."""

486

self.mouse_sensitivity = max(0.1, min(5.0,

487

self.mouse_sensitivity + change))

488

print(f"Mouse sensitivity: {self.mouse_sensitivity:.1f}")

489

490

def cleanup(self):

491

"""Clean up input controller."""

492

self.disableMouseLook()

493

self.removeAllTasks()

494

self.ignoreAll()

495

```

496

497

## Types

498

499

```python { .api }

500

from panda3d.core import Vec2

501

502

# Mouse coordinates are normalized to -1.0 to 1.0 range

503

# (0, 0) is center of window

504

# (-1, -1) is bottom-left corner

505

# (1, 1) is top-right corner

506

507

# Key names follow specific conventions:

508

# - Letters: "a" through "z"

509

# - Numbers: "0" through "9"

510

# - Special: "space", "enter", "escape", "tab", etc.

511

# - Arrows: "arrow_up", "arrow_down", "arrow_left", "arrow_right"

512

# - Function: "f1" through "f12"

513

# - Modifiers: "shift", "control", "alt"

514

515

# Mouse button numbers:

516

MOUSE_LEFT = 1 # Left mouse button

517

MOUSE_MIDDLE = 2 # Middle mouse button

518

MOUSE_RIGHT = 3 # Right mouse button

519

```